ΠΠ»ΠΈΠ·Π°Π½Π΅
ΠΠΎΠ±ΡΡ Π΄Π΅Π½. ΠΠ΅ΡΠ΅ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½ Π³ΠΎΠ΄ΠΈΠ½Π° ΡΠ°Π±ΠΎΡΠΈΠΌ ΡΡΡ ΡΠΊΡΠΈΠΏΡ (ΠΈΠ»ΠΈ ΠΏΠΎ-ΡΠΊΠΎΡΠΎ Π½Π°Π±ΠΎΡ ΠΎΡ ΡΠΊΡΠΈΠΏΡΠΎΠ²Π΅), ΠΊΠΎΠΉΡΠΎ Π³Π΅Π½Π΅ΡΠΈΡΠ° ΠΎΡΡΠ΅ΡΠΈ Π·Π° ΡΡΡΡΠΎΡΠ½ΠΈΠ΅ΡΠΎ Π½Π° Π²ΠΈΡΡΡΠ°Π»Π½ΠΈΡΠ΅ ΠΌΠ°ΡΠΈΠ½ΠΈ (ΠΈ Π½Π΅ ΡΠ°ΠΌΠΎ). Π Π΅ΡΠΈΡ Π΄Π° ΡΠΏΠΎΠ΄Π΅Π»Ρ ΠΌΠΎΡ ΠΎΠΏΠΈΡ Π² ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ΡΠΎ ΠΈ ΡΠ°ΠΌΠΈΡ ΠΊΠΎΠ΄. ΠΠ°Π΄ΡΠ²Π°ΠΌ ΡΠ΅ Π½Π° ΠΊΡΠΈΡΠΈΠΊΠ° ΠΈ ΡΠΎΠ·ΠΈ ΠΌΠ°ΡΠ΅ΡΠΈΠ°Π» Π΄Π° Π΅ ΠΏΠΎΠ»Π΅Π·Π΅Π½ Π½Π° Π½ΡΠΊΠΎΠ³ΠΎ.
Π€ΠΎΡΠΌΠΈΡΠ°Π½Π΅ Π½Π° ΠΏΠΎΡΡΠ΅Π±Π½ΠΎΡΡ
ΠΠΌΠ°ΠΌΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ (ΠΎΠΊΠΎΠ»ΠΎ 1500 Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ, ΡΠ°Π·ΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈ Π² 3 vCenters). Π‘ΡΠ·Π΄Π°Π²Π°Ρ ΡΠ΅ Π½ΠΎΠ²ΠΈ ΠΈ ΡΠ΅ ΠΈΠ·ΡΡΠΈΠ²Π°Ρ Π΄ΠΎΡΡΠ° ΡΠ΅ΡΡΠΎ ΡΡΠ°ΡΠΈ. ΠΠ° Π΄Π° ΡΠ΅ ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ° ΡΠ΅Π΄, ΠΊΡΠΌ vCenter Π±ΡΡ
Π° Π΄ΠΎΠ±Π°Π²Π΅Π½ΠΈ Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΡΠΊΠΈ ΠΏΠΎΠ»Π΅ΡΠ°, Π·Π° Π΄Π° ΡΠ΅ ΡΠ°Π·Π΄Π΅Π»ΡΡ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈΡΠ΅ ΠΌΠ°ΡΠΈΠ½ΠΈ Π½Π° ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΠΈ, Π΄Π° ΡΠ΅ ΠΏΠΎΡΠΎΡΠΈ Π΄Π°Π»ΠΈ ΡΠ° ΡΠ΅ΡΡΠΎΠ²ΠΈ ΠΈ ΠΎΡ ΠΊΠΎΠ³ΠΎ ΠΈ ΠΊΠΎΠ³Π° ΡΠ° ΡΡΠ·Π΄Π°Π΄Π΅Π½ΠΈ. Π§ΠΎΠ²Π΅ΡΠΊΠΈΡΡ ΡΠ°ΠΊΡΠΎΡ Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ ΡΠ°ΠΊΡΠ°, ΡΠ΅ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΎΡ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°ΡΠ° ΠΌΠ°ΡΠΈΠ½ΠΈ ΠΎΡΡΠ°Π½Π°Ρ
Π° Ρ ΠΏΡΠ°Π·Π½ΠΈ ΠΏΠΎΠ»Π΅ΡΠ°, ΠΊΠΎΠ΅ΡΠΎ ΡΡΠ»ΠΎΠΆΠ½ΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΠ°. ΠΠ΅Π΄Π½ΡΠΆ Π½Π° Π²ΡΠ΅ΠΊΠΈ ΡΠ΅ΡΡ ΠΌΠ΅ΡΠ΅ΡΠ° Π½ΡΠΊΠΎΠΉ ΡΠ΅ ΠΈΠ·ΠΏΠ»Π°ΡΠΈ ΠΈ Π·Π°ΠΏΠΎΡΠ½Π° Π΄Π° ΡΠ°Π±ΠΎΡΠΈ Π²ΡΡΡ
Ρ Π°ΠΊΡΡΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅ΡΠΎ Π½Π° ΡΠ΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ, Π½ΠΎ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΡΡ ΠΏΡΠ΅ΡΡΠ°Π½Π° Π΄Π° Π±ΡΠ΄Π΅ ΡΠ΅Π»Π΅Π²Π°Π½ΡΠ΅Π½ ΡΠ»Π΅Π΄ ΡΠ΅Π΄ΠΌΠΈΡΠ° ΠΈ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°.
ΠΠ΅Π΄Π½Π°Π³Π° Π΄Π° ΡΡΠΎΡΠ½Ρ, ΡΠ΅ Π²ΡΠ΅ΠΊΠΈ ΡΠ°Π·Π±ΠΈΡΠ°, ΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° ΠΈΠΌΠ° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π·Π° ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° ΠΌΠ°ΡΠΈΠ½ΠΈ, ΠΏΡΠΎΡΠ΅Ρ Π·Π° ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ΡΠΎ ΠΈΠΌ ΠΈ Ρ.Π½. ΠΈ ΡΠ°ΠΊΠ° Π½Π°ΡΠ°ΡΡΠΊ. Π Π² ΡΡΡΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ Π²ΡΠΈΡΠΊΠΈ ΡΡΡΠΈΠΊΡΠ½ΠΎ ΡΠ»Π΅Π΄Π²Π°Ρ ΡΠΎΠ·ΠΈ ΠΏΡΠΎΡΠ΅Ρ ΠΈ Π²ΡΠΈΡΠΊΠΎ Π΅ Π½Π°ΡΠ΅Π΄. ΠΠ° ΡΡΠΆΠ°Π»Π΅Π½ΠΈΠ΅ ΡΡΠΊ Π½Π΅ Π΅ ΡΠ°ΠΊΠ°, Π½ΠΎ Π½Π΅ ΡΠΎΠ²Π° Π΅ ΡΠ΅ΠΌΠ°ΡΠ° Π½Π° ΡΡΠ°ΡΠΈΡΡΠ° :)
ΠΠ°ΡΠΎ ΡΡΠ»ΠΎ Π±Π΅ΡΠ΅ Π²Π·Π΅ΡΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π΄Π° ΡΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠ° ΠΏΡΠΎΠ²Π΅ΡΠΊΠ°ΡΠ° Π½Π° ΠΊΠΎΡΠ΅ΠΊΡΠ½ΠΎΡΡΡΠ° Π½Π° ΠΏΠΎΠΏΡΠ»Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΏΠΎΠ»Π΅ΡΠ°ΡΠ°.
Π Π΅ΡΠΈΡ
ΠΌΠ΅, ΡΠ΅ Π΅Π΄Π½ΠΎ Π΅ΠΆΠ΅Π΄Π½Π΅Π²Π½ΠΎ ΠΏΠΈΡΠΌΠΎ ΡΡΡ ΡΠΏΠΈΡΡΠΊ Π½Π° Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Π΄ΠΎ Π²ΡΠΈΡΠΊΠΈ ΠΎΡΠ³ΠΎΠ²ΠΎΡΠ½ΠΈ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΠΈ ΠΈ ΡΠ΅Ρ
Π½ΠΈΡΠ΅ ΡΠ΅ΡΠΎΠ²Π΅ Π±ΠΈ Π±ΠΈΠ»ΠΎ Π΄ΠΎΠ±ΡΠΎ Π½Π°ΡΠ°Π»ΠΎ.
Π ΡΠΎΠ·ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ Π΅Π΄ΠΈΠ½ ΠΎΡ ΠΊΠΎΠ»Π΅Π³ΠΈΡΠ΅ ΠΌΠΈ Π²Π΅ΡΠ΅ Π±Π΅ΡΠ΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ°Π» ΡΠΊΡΠΈΠΏΡ Π² PowerShell, ΠΊΠΎΠΉΡΠΎ Π²ΡΠ΅ΠΊΠΈ Π΄Π΅Π½ ΠΏΠΎ Π³ΡΠ°ΡΠΈΠΊ ΡΡΠ±ΠΈΡΠ°ΡΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° Π²ΡΠΈΡΠΊΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Π½Π° Π²ΡΠΈΡΠΊΠΈ vCenters ΠΈ Π³Π΅Π½Π΅ΡΠΈΡΠ°ΡΠ΅ 3 csv Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ° (Π²ΡΠ΅ΠΊΠΈ Π·Π° ΡΠ²ΠΎΡ vCenter), ΠΊΠΎΠΈΡΠΎ ΡΠ΅ ΠΊΠ°ΡΠ²Π°Ρ Π° Π² ΠΎΠ±Ρ Π΄ΠΈΡΠΊ. ΠΠ΅ΡΠ΅ ΡΠ΅ΡΠ΅Π½ΠΎ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΠΌ ΡΠΎΠ·ΠΈ ΡΠΊΡΠΈΠΏΡ ΠΊΠ°ΡΠΎ ΠΎΡΠ½ΠΎΠ²Π° ΠΈ Π΄Π° Π³ΠΎ Π΄ΠΎΠΏΡΠ»Π½ΠΈΠΌ Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° Π΅Π·ΠΈΠΊΠ° R, Ρ ΠΊΠΎΠΉΡΠΎ ΠΈΠΌΠ°Ρ ΠΌΠ΅ ΠΈΠ·Π²Π΅ΡΡΠ΅Π½ ΠΎΠΏΠΈΡ.
Π ΠΏΡΠΎΡΠ΅ΡΠ° Π½Π° ΡΠΈΠ½Π°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ ΠΏΠΎΠ»ΡΡΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΏΠΎ ΠΏΠΎΡΠ°ΡΠ°, Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ Ρ ΠΎΡΠ½ΠΎΠ²Π½Π° ΠΈ ΠΈΡΡΠΎΡΠΈΡΠ΅ΡΠΊΠ° ΡΠ°Π±Π»ΠΈΡΠ° (ΠΏΠΎΠ²Π΅ΡΠ΅ Π·Π° ΡΠΎΠ²Π° ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ), ΠΊΠ°ΠΊΡΠΎ ΠΈ Π°Π½Π°Π»ΠΈΠ· Π½Π° vSphere ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΎΠ½Π½ΠΈ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅, Π·Π° Π΄Π° Π½Π°ΠΌΠ΅ΡΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»Π½ΠΈΡΠ΅ ΡΡΠ·Π΄Π°ΡΠ΅Π»ΠΈ Π½Π° vm ΠΈ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π½Π° ΡΡΡ Π½ΠΎΡΠΎ ΡΡΠ·Π΄Π°Π²Π°Π½Π΅.
ΠΠ° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ°ΡΠ° ΡΠ° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ IDE RStudio Desktop ΠΈ PowerShell ISE.
Π‘ΠΊΡΠΈΠΏΡΡΡ ΡΠ΅ ΡΡΠ°ΡΡΠΈΡΠ° ΠΎΡ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½Π° Π²ΠΈΡΡΡΠ°Π»Π½Π° ΠΌΠ°ΡΠΈΠ½Π° Π½Π° Windows.
ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π½Π° ΠΎΠ±ΡΠ°ΡΠ° Π»ΠΎΠ³ΠΈΠΊΠ°.
ΠΠ±ΡΠ°ΡΠ° Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π° ΡΠΊΡΠΈΠΏΡΠΎΠ²Π΅ΡΠ΅ Π΅ ΡΠ»Π΅Π΄Π½Π°ΡΠ°.
- ΠΠΈΠ΅ ΡΡΠ±ΠΈΡΠ°ΠΌΠ΅ Π΄Π°Π½Π½ΠΈ Π·Π° Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° PowerShell ΡΠΊΡΠΈΠΏΡ, ΠΊΠΎΠΉΡΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°ΠΌΠ΅ ΡΡΠ΅Π· R, ΠΈ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡΠ°ΠΌΠ΅ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠ° Π² Π΅Π΄ΠΈΠ½ csv. ΠΠ±ΡΠ°ΡΠ½ΠΎΡΠΎ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ Π΅Π·ΠΈΡΠΈΡΠ΅ ΡΠ΅ ΠΈΠ·Π²ΡΡΡΠ²Π° ΠΏΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π΅Π½ Π½Π°ΡΠΈΠ½. (Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΡΠΏΡΠ°Π²Π»ΡΠ²Π°Ρ Π΄Π°Π½Π½ΠΈ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ ΠΎΡ R ΠΊΡΠΌ PowerShell ΠΏΠΎΠ΄ ΡΠΎΡΠΌΠ°ΡΠ° Π½Π° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ, Π½ΠΎ ΡΠΎΠ²Π° Π΅ ΡΡΡΠ΄Π½ΠΎ ΠΈ Π½Π°Π»ΠΈΡΠΈΠ΅ΡΠΎ Π½Π° ΠΌΠ΅ΠΆΠ΄ΠΈΠ½Π½ΠΈ csv ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ ΡΠ»Π΅ΡΠ½ΡΠ²Π° ΠΎΡΡΡΡΠ°Π½ΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° Π³ΡΠ΅ΡΠΊΠΈ ΠΈ ΡΠΏΠΎΠ΄Π΅Π»ΡΠ½Π΅ΡΠΎ Π½Π° ΠΌΠ΅ΠΆΠ΄ΠΈΠ½Π½ΠΈ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠΈ Ρ Π½ΡΠΊΠΎΠ³ΠΎ).
- ΠΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ R, Π½ΠΈΠ΅ ΡΠΎΡΠΌΠΈΡΠ°ΠΌΠ΅ Π²Π°Π»ΠΈΠ΄Π½ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈ Π·Π° ΠΏΠΎΠ»Π΅ΡΠ°ΡΠ°, ΡΠΈΠΈΡΠΎ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ ΠΏΡΠΎΠ²Π΅ΡΡΠ²Π°ΠΌΠ΅. β Π‘ΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ Word Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ, ΠΊΠΎΠΉΡΠΎ ΡΠ΅ ΡΡΠ΄ΡΡΠΆΠ° ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈΡΠ΅ Π½Π° ΡΠ΅Π·ΠΈ ΠΏΠΎΠ»Π΅ΡΠ° Π·Π° Π²ΠΌΡΠΊΠ²Π°Π½Π΅ Π² ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΎΠ½Π½ΠΎΡΠΎ ΠΏΠΈΡΠΌΠΎ, ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ Π±ΡΠ΄Π΅ ΠΎΡΠ³ΠΎΠ²ΠΎΡΡΡ Π½Π° Π²ΡΠΏΡΠΎΡΠΈΡΠ΅ Π½Π° ΠΊΠΎΠ»Π΅Π³ΠΈΡΠ΅ βΠΠ΅, Π½ΠΎ ΠΊΠ°ΠΊ Π΄Π° ΠΏΠΎΠΏΡΠ»Π½Ρ ΡΠΎΠ²Π°?β
- ΠΠ°ΡΠ΅ΠΆΠ΄Π°ΠΌΠ΅ Π΄Π°Π½Π½ΠΈ Π·Π° Π²ΡΠΈΡΠΊΠΈ VM ΠΎΡ csv Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° R, ΡΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ ΡΠ°ΠΌΠΊΠ° Ρ Π΄Π°Π½Π½ΠΈ, ΠΏΡΠ΅ΠΌΠ°Ρ Π²Π°ΠΌΠ΅ Π½Π΅Π½ΡΠΆΠ½ΠΈΡΠ΅ ΠΏΠΎΠ»Π΅ΡΠ° ΠΈ ΡΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΎΠ½Π΅Π½ xlsx Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ, ΠΊΠΎΠΉΡΠΎ ΡΠ΅ ΡΡΠ΄ΡΡΠΆΠ° ΠΎΠ±ΠΎΠ±ΡΠ΅Π½Π° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° Π²ΡΠΈΡΠΊΠΈ VM, ΠΊΠΎΡΡΠΎ ΠΊΠ°ΡΠ²Π°ΠΌΠ΅ Π² ΡΠΏΠΎΠ΄Π΅Π»Π΅Π½ ΡΠ΅ΡΡΡΡ.
- ΠΡΠΈΠ»Π°Π³Π°ΠΌΠ΅ Π²ΡΠΈΡΠΊΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π·Π° ΠΊΠΎΡΠ΅ΠΊΡΠ½ΠΎΡΡΡΠ° Π½Π° ΠΏΠΎΠΏΡΠ»Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΏΠΎΠ»Π΅ΡΠ°ΡΠ° ΠΊΡΠΌ ΡΠ°ΠΌΠΊΠ°ΡΠ° Ρ Π΄Π°Π½Π½ΠΈ Π·Π° Π²ΡΠΈΡΠΊΠΈ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ ΠΈ ΡΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ ΡΠ°Π±Π»ΠΈΡΠ°, ΡΡΠ΄ΡΡΠΆΠ°ΡΠ° ΡΠ°ΠΌΠΎ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Ρ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈ ΠΏΠΎΠ»Π΅ΡΠ° (ΠΈ ΡΠ°ΠΌΠΎ ΡΠ΅Π·ΠΈ ΠΏΠΎΠ»Π΅ΡΠ°).
- ΠΠ·ΠΏΡΠ°ΡΠ°ΠΌΠ΅ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΡΠΏΠΈΡΡΠΊ Ρ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Π½Π° Π΄ΡΡΠ³ ΡΠΊΡΠΈΠΏΡ Π½Π° PowerShell, ΠΊΠΎΠΉΡΠΎ ΡΠ΅ ΠΏΡΠ΅Π³Π»Π΅Π΄Π° ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΎΠ½Π½ΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° vCenter Π·Π° ΡΡΠ±ΠΈΡΠΈΡ Π·Π° ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° Π²ΠΈΡΡΡΠ°Π»Π½Π° ΠΌΠ°ΡΠΈΠ½Π°, ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ Π½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π΄Π° ΠΏΠΎΡΠΎΡΠΈΠΌ ΠΎΡΠ°ΠΊΠ²Π°Π½ΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ Π½Π° ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° Π²ΠΈΡΡΡΠ°Π»Π½Π°ΡΠ° ΠΌΠ°ΡΠΈΠ½Π° ΠΈ ΠΏΡΠ΅Π΄Π²ΠΈΠ΄Π΅Π½ΠΈΡ ΡΡΠ·Π΄Π°ΡΠ΅Π». Π’ΠΎΠ²Π° Π΅ Π·Π° ΡΠ»ΡΡΠ°Ρ, ΠΊΠΎΠ³Π°ΡΠΎ Π½ΠΈΠΊΠΎΠΉ Π½Π΅ ΠΏΡΠΈΠ·Π½Π°Π²Π° ΡΠΈΡ Π΅ ΠΊΠΎΠ»Π°ΡΠ°. Π’ΠΎΠ·ΠΈ ΡΠΊΡΠΈΠΏΡ Π½Π΅ ΡΠ°Π±ΠΎΡΠΈ Π±ΡΡΠ·ΠΎ, ΠΎΡΠΎΠ±Π΅Π½ΠΎ Π°ΠΊΠΎ ΠΈΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΎΠ½Π½ΠΈ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅, ΡΠ°ΠΊΠ° ΡΠ΅ ΡΠ°Π·Π³Π»Π΅ΠΆΠ΄Π°ΠΌΠ΅ ΡΠ°ΠΌΠΎ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ 2 ΡΠ΅Π΄ΠΌΠΈΡΠΈ ΠΈ ΡΡΡΠΎ ΡΠ°ΠΊΠ° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΠ°Π±ΠΎΡΠ΅Π½ ΠΏΡΠΎΡΠ΅Ρ, ΠΊΠΎΠΉΡΠΎ Π²ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° Π΄Π° ΡΡΡΡΠΈΡΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° Π½ΡΠΊΠΎΠ»ΠΊΠΎ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Π΅Π΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ. ΠΡΠΈΠΌΠ΅ΡΠ½ΠΈΡΡ ΡΠΊΡΠΈΠΏΡ ΡΡΠ΄ΡΡΠΆΠ° ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΈ ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈ Π·Π° ΡΠΎΠ·ΠΈ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΡΠΌ. ΠΠΎΠ±Π°Π²ΡΠΌΠ΅ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠ° Π² csv, ΠΊΠΎΠΉΡΠΎ ΠΎΡΠ½ΠΎΠ²ΠΎ Π·Π°ΡΠ΅ΠΆΠ΄Π°ΠΌΠ΅ Π² R.
- ΠΠΈΠ΅ Π³Π΅Π½Π΅ΡΠΈΡΠ°ΠΌΠ΅ ΠΊΡΠ°ΡΠΈΠ²ΠΎ ΡΠΎΡΠΌΠ°ΡΠΈΡΠ°Π½ xlsx Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ, Π² ΠΊΠΎΠΉΡΠΎ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈΡΠ΅ ΠΏΠΎΠ»Π΅ΡΠ° ΡΠ΅ Π±ΡΠ΄Π°Ρ ΠΌΠ°ΡΠΊΠΈΡΠ°Π½ΠΈ Π² ΡΠ΅ΡΠ²Π΅Π½ΠΎ, ΡΠ΅ Π±ΡΠ΄Π°Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈ ΡΠΈΠ»ΡΡΠΈ ΠΊΡΠΌ Π½ΡΠΊΠΎΠΈ ΠΊΠΎΠ»ΠΎΠ½ΠΈ ΠΈ ΡΠ΅ Π±ΡΠ΄Π°Ρ ΠΏΠΎΡΠΎΡΠ΅Π½ΠΈ Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½ΠΈ ΠΊΠΎΠ»ΠΎΠ½ΠΈ, ΡΡΠ΄ΡΡΠΆΠ°ΡΠΈ ΠΏΡΠ΅Π΄Π²ΠΈΠ΄Π΅Π½ΠΈΡΠ΅ ΡΡΠ·Π΄Π°ΡΠ΅Π»ΠΈ ΠΈ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π½Π° ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° VM.
- ΠΠ΅Π½Π΅ΡΠΈΡΠ°ΠΌΠ΅ ΠΈΠΌΠ΅ΠΉΠ», ΠΊΡΠΌ ΠΊΠΎΠΉΡΠΎ ΠΏΡΠΈΠΊΠ°ΡΠ²Π°ΠΌΠ΅ Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ Ρ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π½Π° Π²Π°Π»ΠΈΠ΄Π½ΠΈΡΠ΅ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ Π½Π° ΠΏΠΎΠ»Π΅ΡΠ°ΡΠ°, ΠΊΠ°ΠΊΡΠΎ ΠΈ ΡΠ°Π±Π»ΠΈΡΠ° Ρ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈ ΠΏΠΎΠ»Π΅ΡΠ°. Π ΡΠ΅ΠΊΡΡΠ° ΠΏΠΎΡΠΎΡΠ²Π°ΠΌΠ΅ ΠΎΠ±ΡΠΈΡ Π±ΡΠΎΠΉ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΡΡΠ·Π΄Π°Π΄Π΅Π½ΠΈ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ, Π²ΡΡΠ·ΠΊΠ° ΠΊΡΠΌ ΡΠΏΠΎΠ΄Π΅Π»Π΅Π½ ΡΠ΅ΡΡΡΡ ΠΈ ΠΌΠΎΡΠΈΠ²Π°ΡΠΈΠΎΠ½Π½Π° ΡΠ½ΠΈΠΌΠΊΠ°. ΠΠΊΠΎ Π½ΡΠΌΠ° Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈ VM, ΠΈΠ·ΠΏΡΠ°ΡΠ°ΠΌΠ΅ Π΄ΡΡΠ³ΠΎ ΠΏΠΈΡΠΌΠΎ Ρ ΠΏΠΎ-ΡΠ°ΡΡΠ»ΠΈΠ²Π° ΠΌΠΎΡΠΈΠ²Π°ΡΠΈΠΎΠ½Π½Π° ΡΠ½ΠΈΠΌΠΊΠ°.
- ΠΠΈΠ΅ Π·Π°ΠΏΠΈΡΠ²Π°ΠΌΠ΅ Π΄Π°Π½Π½ΠΈ Π·Π° Π²ΡΠΈΡΠΊΠΈ VM Π² Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ Π½Π° SQL Server, ΠΊΠ°ΡΠΎ Π²Π·Π΅ΠΌΠ°ΠΌΠ΅ ΠΏΡΠ΅Π΄Π²ΠΈΠ΄ Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΡΠΌ Π½Π° ΠΈΡΡΠΎΡΠΈΡΠ΅ΡΠΊΠΈ ΡΠ°Π±Π»ΠΈΡΠΈ (ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΡΠΌ - Π·Π° ΠΊΠΎΠΉΡΠΎ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ)
ΠΡΡΡΠ½ΠΎΡΡ ΡΠΊΡΠΈΠΏΡΠΎΠ²Π΅
ΠΠ»Π°Π²Π΅Π½ ΡΠ°ΠΉΠ» Ρ R ΠΊΠΎΠ΄
# ΠΡΡΡ ΠΊ ΡΠ°Π±ΠΎΡΠ΅ΠΉ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ (Π½ΡΠΆΠ½ΠΎ Π΄Π»Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΠΉ ΡΠ°Π±ΠΎΡΡ ΡΠ΅ΡΠ΅Π· Π²ΠΈΠ½Π΄ΠΎΠ²ΡΠΉ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊ Π·Π°Π΄Π°Π½ΠΈΠΉ)
setwd("C:ScriptsgetVm")
#### ΠΠΎΠ΄Π³ΡΡΠΆΠ°Π΅ΠΌ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ####
library(tidyverse)
library(xlsx)
library(mailR)
library(rmarkdown)
##### ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΠΏΡΡΠΈ ΠΊ ΠΈΡΡ
ΠΎΠ΄Π½ΡΠΌ ΡΠ°ΠΉΠ»Π°ΠΌ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ #####
source(file = "const.R", local = T, encoding = "utf-8")
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° ΡΠΎ Π²ΡΠ΅ΠΌΠΈ ΠΠ ΠΈ ΡΠ΄Π°Π»ΡΠ΅ΠΌ, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ.
if (file.exists(filenameVmCreationRules)) {file.remove(filenameVmCreationRules)}
#### Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π²ΠΎΡΠ΄ΠΎΠ²ΡΠΊΠΈΠΉ Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ Ρ Π΄ΠΎΠΏΡΡΡΠΈΠΌΡΠΌΠΈ ΠΏΠΎΠ»ΡΠΌΠΈ
render("VM_name_rules.Rmd",
output_format = word_document(),
output_file = filenameVmCreationRules)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° ΡΠΎ Π²ΡΠ΅ΠΌΠΈ ΠΠ ΠΈ ΡΠ΄Π°Π»ΡΠ΅ΠΌ, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ
if (file.exists(allVmXlsxPath)) {file.remove(allVmXlsxPath)}
#### ΠΠ°Π±ΠΈΡΠ°Π΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ ΠΏΠΎ Π²ΡΠ΅ΠΌ ΠΌΠ°ΡΠΈΠ½Π°ΠΌ ΡΠ΅ΡΠ΅Π· PowerShell ΡΠΊΡΠΈΠΏΡ. ΠΠ° Π²ΡΡ
ΠΎΠ΄Π΅ ΠΏΠΎΠ»ΡΡΠΈΠΌ csv.
system(paste0("powershell -File ", getVmPsPath))
# ΠΠΎΠ»Π½ΡΠΉ df
fullXslx_df <- allVmXlsxPath %>%
read.csv2(stringsAsFactors = FALSE)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΡΡΡ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΡ
ΠΏΠΎΠ»Π΅ΠΉ
full_df <- fullXslx_df %>%
mutate(
# Π‘Π½Π°ΡΠ°Π»Π° ΡΠ±ΠΈΡΠ°Π΅ΠΌ Π²ΡΠ΅ Π»ΠΈΡΠ½ΠΈΠ΅ ΠΏΡΠΎΠ±Π΅Π»Ρ ΠΈ ΡΠ°Π±ΡΠ»ΡΡΠΈΠΈ, ΠΏΠΎΡΠΎΠΌ ΡΡΠΈΡΡΠ²Π°Π΅ΠΌ ΡΠ°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ Π·Π°ΠΏΡΡΡΡ, ΠΏΠΎΡΠΎΠΌ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ Π²Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ Π² Π΄ΠΎΠΏΡΡΡΠΈΠΌΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ,
isSubsystemCorrect = Subsystem %>%
gsub("[[:space:]]", "", .) %>%
str_split(., ",") %>%
map(function(x) (all(x %in% AllowedValues$Subsystem))) %>%
as.logical(),
isOwnerCorrect = Owner %in% AllowedValues$Owner,
isCategoryCorrect = Category %in% AllowedValues$Category,
isCreatorCorrect = (!is.na(Creator) & Creator != ''),
isCreation.DateCorrect = map(Creation.Date, IsDate)
)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° ΡΠΎ Π²ΡΠ΅ΠΌΠΈ ΠΠ ΠΈ ΡΠ΄Π°Π»ΡΠ΅ΠΌ, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ.
if (file.exists(filenameAll)) {file.remove(filenameAll)}
#### Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ xslx ΡΠ°ΠΉΠ» Ρ ΠΎΡΡΡΡΠΎΠΌ ####
# ΠΠ±ΡΠΈΠ΅ Π΄Π°Π½Π½ΡΠ΅ Π½Π° ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ Π»ΠΈΡΡ
full_df %>% write.xlsx(file=filenameAll,
sheetName=names[1],
col.names=TRUE,
row.names=FALSE,
append=FALSE)
#### Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ xslx ΡΠ°ΠΉΠ» Ρ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌΠΈ ΠΏΠΎΠ»ΡΠΌΠΈ ####
# Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ df
incorrect_df <- full_df %>%
select(VM.Name,
IP.s,
Owner,
Subsystem,
Creator,
Category,
Creation.Date,
isOwnerCorrect,
isSubsystemCorrect,
isCategoryCorrect,
isCreatorCorrect,
vCenter.Name) %>%
filter(isSubsystemCorrect == F |
isOwnerCorrect == F |
isCategoryCorrect == F |
isCreatorCorrect == F)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° ΡΠΎ Π²ΡΠ΅ΠΌΠΈ ΠΠ ΠΈ ΡΠ΄Π°Π»ΡΠ΅ΠΌ, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ.
if (file.exists(filenameIncVM)) {file.remove(filenameIncVM)}
# Π‘ΠΎΡ
ΡΠ°Π½ΡΠ΅ΠΌ ΡΠΏΠΈΡΠΎΠΊ VM Ρ Π½Π΅Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌΠΈ ΠΏΠΎΠ»ΡΠΌΠΈ Π² csv
incorrect_df %>%
select(VM.Name) %>%
write_csv2(path = filenameIncVM, append = FALSE)
# Π€ΠΈΠ»ΡΡΡΡΠ΅ΠΌ Π΄Π»Ρ Π²ΡΡΠ°Π²ΠΊΠΈ Π² ΠΏΠΎΡΡΡ
incorrect_df_filtered <- incorrect_df %>%
select(VM.Name,
IP.s,
Owner,
Subsystem,
Category,
Creator,
vCenter.Name,
Creation.Date
)
# Π‘ΡΠΈΡΠ°Π΅ΠΌ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΡΡΠΎΠΊ
numberOfRows <- nrow(incorrect_df)
#### ΠΠ°ΡΠ°Π»ΠΎ ΡΡΠ»ΠΎΠ²ΠΈΡ ####
# ΠΠ°Π»ΡΡΠ΅ Π»ΠΈΠ±ΠΎ Ρ Π½Π°Ρ Π΅ΡΡΡ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠ΅ ΠΏΠΎΠ»Ρ, Π»ΠΈΠ±ΠΎ Π½Π΅Ρ.
# ΠΡΠ»ΠΈ Π΅ΡΡΡ - Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ Π΅ΡΡ ΠΎΠ΄ΠΈΠ½ ΡΠΊΡΠΈΠΏΡ
if (numberOfRows > 0) {
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° Ρ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»ΡΠΌΠΈ ΠΈ ΡΠ΄Π°Π»ΡΠ΅ΠΌ, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ.
if (file.exists(creatorsFilePath)) {file.remove(creatorsFilePath)}
# ΠΠ°ΠΏΡΡΠΊΠ°Π΅ΠΌ PowerShell ΡΠΊΡΠΈΠΏΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π½Π°ΠΉΠ΄ΡΡ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Π΅ΠΉ Π½Π°ΠΉΠ΄Π΅Π½Π½ΡΡ
VM. ΠΠ° Π²ΡΡ
ΠΎΠ΄Π΅ ΠΏΠΎΠ»ΡΡΠΈΠΌ csv.
system(paste0("powershell -File ", getCreatorsPath))
# Π§ΠΈΡΠ°Π΅ΠΌ ΡΠ°ΠΉΠ» Ρ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»ΡΠΌΠΈ
creators_df <- creatorsFilePath %>%
read.csv2(stringsAsFactors = FALSE)
# Π€ΠΈΠ»ΡΡΡΡΠ΅ΠΌ Π΄Π»Ρ Π²ΡΡΠ°Π²ΠΊΠΈ Π² ΠΏΠΎΡΡΡ, Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ ΠΈΠ· ΡΠ°Π±Π»ΠΈΡΡ Ρ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»ΡΠΌΠΈ
incorrect_df_filtered <- incorrect_df_filtered %>%
select(VM.Name,
IP.s,
Owner,
Subsystem,
Category,
Creator,
vCenter.Name,
Creation.Date
) %>%
left_join(creators_df, by = "VM.Name") %>%
rename(`ΠΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΡΠΉ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Ρ` = CreatedBy,
`ΠΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΠ°Ρ Π΄Π°ΡΠ° ΡΠΎΠ·Π΄Π°Π½ΠΈΡ` = CreatedOn)
# Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΡΠ΅Π»ΠΎ ΠΏΠΈΡΡΠΌΠ°
emailBody <- paste0(
'<html>
<h3>ΠΠΎΠ±ΡΡΠΉ Π΄Π΅Π½Ρ, ΡΠ²Π°ΠΆΠ°Π΅ΠΌΡΠ΅ ΠΊΠΎΠ»Π»Π΅Π³ΠΈ.</h3>
<p>ΠΠΎΠ»Π½ΡΡ Π°ΠΊΡΡΠ°Π»ΡΠ½ΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΏΠΎ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΡΠΌ ΠΌΠ°ΡΠΈΠ½Π°ΠΌ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° Π΄ΠΈΡΠΊΠ΅ H: Π²ΠΎΡ ΡΡΡ:<p>
<p>\server.ruVM', sourceFileFormat, '</p>
<p>Π’Π°ΠΊΠΆΠ΅ Π²ΠΎ Π²Π»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΡΠΏΠΈΡΠΎΠΊ ΠΠ Ρ <strong>Π½Π΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌΠΈ</strong> ΠΏΠΎΠ»ΡΠΌΠΈ. ΠΡΠ΅Π³ΠΎ ΠΈΡ
<strong>', numberOfRows,'</strong>.</p>
<p>Π ΡΠ°Π±Π»ΠΈΡΠ΅ ΠΏΠΎΡΠ²ΠΈΠ»ΠΎΡΡ 2 Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ. <strong>ΠΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΡΠΉ ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Ρ</strong> ΠΈ <strong>ΠΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΠ°Ρ Π΄Π°ΡΠ° ΡΠΎΠ·Π΄Π°Π½ΠΈΡ</strong>, ΠΊΠΎΡΠΎΡΡΠ΅ Π΄ΠΎΡΡΠ°ΡΡΡΡ ΠΈΠ· Π»ΠΎΠ³ΠΎΠ² vCenter Π·Π° ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ 2 Π½Π΅Π΄Π΅Π»ΠΈ</p>
<p>ΠΡΠΎΡΡΠ±Π° ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Π΅ΠΉ ΠΌΠ°ΡΠΈΠ½ ΡΡΠΎΡΠ½ΠΈΡΡ Π΄Π°Π½Π½ΡΠ΅ ΠΈ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡΡ ΠΏΠΎΠ»Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ. ΠΡΠ°Π²ΠΈΠ»Π° Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΏΠΎΠ»Π΅ΠΉ ΡΠ°ΠΊΠΆΠ΅ Π²ΠΎ Π²Π»ΠΎΠΆΠ΅Π½ΠΈΠΈ</p>
<p><img src="data/meme.jpg"></p>
</html>'
)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π°
if (file.exists(filenameIncorrect)) {file.remove(filenameIncorrect)}
# Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΠΊΡΠ°ΡΠΈΠ²ΡΡ ΡΠ°Π±Π»ΠΈΡΡ Ρ ΡΠΎΡΠΌΠ°ΡΠ°ΠΌΠΈ ΠΈ Ρ.Π΄.
source(file = "email.R", local = T, encoding = "utf-8")
#### Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΠΏΠΈΡΡΠΌΠΎ Ρ ΠΏΠ»ΠΎΡ
ΠΎ ΠΏΠΎΠ΄ΠΏΠΈΡΠ°Π½Π½ΡΠΌΠΈ ΠΌΠ°ΡΠΈΠ½Π°ΠΌΠΈ ####
send.mail(from = emailParams$from,
to = emailParams$to,
subject = "ΠΠ Ρ Π½Π΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌΠΈ ΠΏΠΎΠ»ΡΠΌΠΈ",
body = emailBody,
encoding = "utf-8",
html = TRUE,
inline = TRUE,
smtp = emailParams$smtpParams,
authenticate = TRUE,
send = TRUE,
attach.files = c(filenameIncorrect, filenameVmCreationRules),
debug = FALSE)
#### ΠΠ°Π»ΡΡΠ΅ ΠΏΠΎΠΉΠ΄ΡΡ Π±Π»ΠΎΠΊ, Π΅ΡΠ»ΠΈ Π½Π΅Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌ Ρ ΠΠ ####
} else {
# Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΡΠ΅Π»ΠΎ ΠΏΠΈΡΡΠΌΠ°
emailBody <- paste0(
'<html>
<h3>ΠΠΎΠ±ΡΡΠΉ Π΄Π΅Π½Ρ, ΡΠ²Π°ΠΆΠ°Π΅ΠΌΡΠ΅ ΠΊΠΎΠ»Π»Π΅Π³ΠΈ</h3>
<p>ΠΠΎΠ»Π½ΡΡ Π°ΠΊΡΡΠ°Π»ΡΠ½ΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΏΠΎ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΡΠΌ ΠΌΠ°ΡΠΈΠ½Π°ΠΌ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ Π½Π° Π΄ΠΈΡΠΊΠ΅ H: Π²ΠΎΡ ΡΡΡ:<p>
<p>\server.ruVM', sourceFileFormat, '</p>
<p>Π’Π°ΠΊΠΆΠ΅, Π½Π° ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ, Π²ΡΠ΅ ΠΏΠΎΠ»Ρ ΠΠ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Ρ</p>
<p><img src="data/meme_correct.jpg"></p>
</html>'
)
#### Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΠΏΠΈΡΡΠΌΠΎ Π±Π΅Π· ΠΏΠ»ΠΎΡ
ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΡ
VM ####
send.mail(from = emailParams$from,
to = emailParams$to,
subject = "Π‘Π²ΠΎΠ΄Π½Π°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ",
body = emailBody,
encoding = "utf-8",
html = TRUE,
inline = TRUE,
smtp = emailParams$smtpParams,
authenticate = TRUE,
send = TRUE,
debug = FALSE)
}
####### ΠΠ°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ Π² ΠΠ #####
source(file = "DB.R", local = T, encoding = "utf-8")
Π‘ΠΊΡΠΈΠΏΡ Π·Π° ΠΏΠΎΠ»ΡΡΠ°Π²Π°Π½Π΅ Π½Π° ΡΠΏΠΈΡΡΠΊ Ρ vm Π² PowerShell
# ΠΠ°Π½Π½ΡΠ΅ Π΄Π»Ρ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅
$vCenterNames = @(
"vcenter01",
"vcenter02",
"vcenter03"
)
$vCenterUsername = "myusername"
$vCenterPassword = "mypassword"
$filename = "C:ScriptsgetVmdataallvmall-vm-$(get-date -f yyyy-MM-dd).csv"
$destinationSMB = "server.rumyfolder$vm"
$IP0=""
$IP1=""
$IP2=""
$IP3=""
$IP4=""
$IP5=""
# ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎ Π²ΡΠ΅ΠΌ vCenter, ΡΡΠΎ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡΡ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ. ΠΡΠ΄Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ, Π΅ΡΠ»ΠΈ Π»ΠΎΠ³ΠΈΠ½ ΠΈ ΠΏΠ°ΡΠΎΠ»Ρ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΠ΅ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄ΠΎΠΌΠ΅Π½Π½ΡΠ΅)
Connect-VIServer -Server $vCenterNames -User $vCenterUsername -Password $vCenterPassword
write-host ""
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ ΡΡΠ½ΠΊΡΠΈΡ Ρ ΡΠΈΠΊΠ»ΠΎΠΌ ΠΏΠΎ Π²ΡΠ΅ΠΌ vCenter-Π°ΠΌ
function Get-VMinventory {
# Π ΡΡΠΎΠΉ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π±ΡΠ΄Π΅Ρ ΡΠΏΠΈΡΠΊΠΎ Π²ΡΠ΅Ρ
ΠΠ, ΠΊΠ°ΠΊ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²
$AllVM = Get-VM | Sort Name
$cnt = $AllVM.Count
$count = 1
# ΠΠ°ΡΠΈΠ½Π°Π΅ΠΌ ΡΠΈΠΊΠ» ΠΏΠΎ Π²ΡΠ΅ΠΌ ΠΠ ΠΈ ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ°
foreach ($vm in $AllVM) {
$StartTime = $(get-date)
$IP0 = $vm.Guest.IPAddress[0]
$IP1 = $vm.Guest.IPAddress[1]
$IP2 = $vm.Guest.IPAddress[2]
$IP3 = $vm.Guest.IPAddress[3]
$IP4 = $vm.Guest.IPAddress[4]
$IP5 = $vm.Guest.IPAddress[5]
If ($IP0 -ne $null) {If ($IP0.Contains(":") -ne 0) {$IP0=""}}
If ($IP1 -ne $null) {If ($IP1.Contains(":") -ne 0) {$IP1=""}}
If ($IP2 -ne $null) {If ($IP2.Contains(":") -ne 0) {$IP2=""}}
If ($IP3 -ne $null) {If ($IP3.Contains(":") -ne 0) {$IP3=""}}
If ($IP4 -ne $null) {If ($IP4.Contains(":") -ne 0) {$IP4=""}}
If ($IP5 -ne $null) {If ($IP5.Contains(":") -ne 0) {$IP5=""}}
$cluster = $vm | Get-Cluster | Select-Object -ExpandProperty name
$Bootime = $vm.ExtensionData.Runtime.BootTime
$TotalHDDs = $vm.ProvisionedSpaceGB -as [int]
$CreationDate = $vm.CustomFields.Item("CreationDate") -as [string]
$Creator = $vm.CustomFields.Item("Creator") -as [string]
$Category = $vm.CustomFields.Item("Category") -as [string]
$Owner = $vm.CustomFields.Item("Owner") -as [string]
$Subsystem = $vm.CustomFields.Item("Subsystem") -as [string]
$IPS = $vm.CustomFields.Item("IP") -as [string]
$vCPU = $vm.NumCpu
$CorePerSocket = $vm.ExtensionData.config.hardware.NumCoresPerSocket
$Sockets = $vCPU/$CorePerSocket
$Id = $vm.Id.Split('-')[2] -as [int]
# Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ Π²ΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π² ΠΎΠ΄ΠΈΠ½ ΠΎΠ±ΡΠ΅ΠΊΡ
$Vmresult = New-Object PSObject
$Vmresult | add-member -MemberType NoteProperty -Name "Id" -Value $Id
$Vmresult | add-member -MemberType NoteProperty -Name "VM Name" -Value $vm.Name
$Vmresult | add-member -MemberType NoteProperty -Name "Cluster" -Value $cluster
$Vmresult | add-member -MemberType NoteProperty -Name "Esxi Host" -Value $VM.VMHost
$Vmresult | add-member -MemberType NoteProperty -Name "IP Address 1" -Value $IP0
$Vmresult | add-member -MemberType NoteProperty -Name "IP Address 2" -Value $IP1
$Vmresult | add-member -MemberType NoteProperty -Name "IP Address 3" -Value $IP2
$Vmresult | add-member -MemberType NoteProperty -Name "IP Address 4" -Value $IP3
$Vmresult | add-member -MemberType NoteProperty -Name "IP Address 5" -Value $IP4
$Vmresult | add-member -MemberType NoteProperty -Name "IP Address 6" -Value $IP5
$Vmresult | add-member -MemberType NoteProperty -Name "vCPU" -Value $vCPU
$Vmresult | Add-Member -MemberType NoteProperty -Name "CPU Sockets" -Value $Sockets
$Vmresult | Add-Member -MemberType NoteProperty -Name "Core per Socket" -Value $CorePerSocket
$Vmresult | add-member -MemberType NoteProperty -Name "RAM (GB)" -Value $vm.MemoryGB
$Vmresult | add-member -MemberType NoteProperty -Name "Total-HDD (GB)" -Value $TotalHDDs
$Vmresult | add-member -MemberType NoteProperty -Name "Power State" -Value $vm.PowerState
$Vmresult | add-member -MemberType NoteProperty -Name "OS" -Value $VM.ExtensionData.summary.config.guestfullname
$Vmresult | Add-Member -MemberType NoteProperty -Name "Boot Time" -Value $Bootime
$Vmresult | add-member -MemberType NoteProperty -Name "VMTools Status" -Value $vm.ExtensionData.Guest.ToolsStatus
$Vmresult | add-member -MemberType NoteProperty -Name "VMTools Version" -Value $vm.ExtensionData.Guest.ToolsVersion
$Vmresult | add-member -MemberType NoteProperty -Name "VMTools Version Status" -Value $vm.ExtensionData.Guest.ToolsVersionStatus
$Vmresult | add-member -MemberType NoteProperty -Name "VMTools Running Status" -Value $vm.ExtensionData.Guest.ToolsRunningStatus
$Vmresult | add-member -MemberType NoteProperty -Name "Creation Date" -Value $CreationDate
$Vmresult | add-member -MemberType NoteProperty -Name "Creator" -Value $Creator
$Vmresult | add-member -MemberType NoteProperty -Name "Category" -Value $Category
$Vmresult | add-member -MemberType NoteProperty -Name "Owner" -Value $Owner
$Vmresult | add-member -MemberType NoteProperty -Name "Subsystem" -Value $Subsystem
$Vmresult | add-member -MemberType NoteProperty -Name "IP's" -Value $IPS
$Vmresult | add-member -MemberType NoteProperty -Name "vCenter Name" -Value $vm.Uid.Split('@')[1].Split(':')[0]
# Π‘ΡΠΈΡΠ°Π΅ΠΌ ΠΎΠ±ΡΠ΅Π΅ ΠΈ ΠΎΡΡΠ°Π²ΡΠ΅Π΅ΡΡ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΈ Π²ΡΠ²ΠΎΠ΄ΠΈΠΌ Π½Π° ΡΠΊΡΠ°Π½ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΡ. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΎΡΡ Π΄Π»Ρ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ, Π½ΠΎ ΠΏΠΎ ΡΠ°ΠΊΡΡ ΠΎΠΊΠ°Π·Π°Π»ΠΎΡΡ ΠΎΡΠ΅Π½Ρ ΡΠ΄ΠΎΠ±Π½ΠΎ.
$elapsedTime = $(get-date) - $StartTime
$totalTime = "{0:HH:mm:ss}" -f ([datetime]($elapsedTime.Ticks*($cnt - $count)))
clear-host
Write-Host "Processing" $count "from" $cnt
Write-host "Progress:" ([math]::Round($count/$cnt*100, 2)) "%"
Write-host "You have about " $totalTime "for cofee"
Write-host ""
$count++
# ΠΡΠ²ΠΎΠ΄ΠΈΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, ΡΡΠΎΠ±Ρ ΡΠΈΠΊΠ» "Π·Π½Π°Π»" ΡΡΠΎ ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΡΠΎΡ
ΠΎΠ΄Π°
$Vmresult
}
}
# ΠΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΏΠΎΠ»ΡΡΠΈΠ²ΡΡΡΡΡ ΡΡΠ½ΠΊΡΠΈΡ ΠΈ ΡΡΠ°Π·Ρ Π²ΡΠ³ΡΡΠΆΠ°Π΅ΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π² csv
$allVm = Get-VMinventory | Export-CSV -Path $filename -NoTypeInformation -UseCulture -Force
# ΠΡΡΠ°Π΅ΠΌΡΡ Π²ΡΠ»ΠΎΠΆΠΈΡΡ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠΉ ΡΠ°ΠΉΠ» Π² Π½ΡΠΆΠ½ΠΎΠ΅ Π½Π°ΠΌ ΠΌΠ΅ΡΡΠΎ ΠΈ, Π² ΡΠ»ΡΡΠ°Π΅ ΠΎΡΠΈΠ±ΠΊΠΈ, ΠΏΠΈΡΠ΅ΠΌ Π»ΠΎΠ³.
try
{
Copy-Item $filename -Destination $destinationSMB -Force -ErrorAction SilentlyContinue
}
catch
{
$error | Export-CSV -Path $filename".error" -NoTypeInformation -UseCulture -Force
}
PowerShell ΡΠΊΡΠΈΠΏΡ, ΠΊΠΎΠΉΡΠΎ ΠΈΠ·Π²Π»ΠΈΡΠ° ΠΎΡ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΎΠ½Π½ΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ ΡΡΠ·Π΄Π°ΡΠ΅Π»ΠΈΡΠ΅ Π½Π° Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ ΠΈ Π΄Π°ΡΠ°ΡΠ° Π½Π° ΡΡΡ Π½ΠΎΡΠΎ ΡΡΠ·Π΄Π°Π²Π°Π½Π΅
# ΠΡΡΡ ΠΊ ΡΠ°ΠΉΠ»Ρ, ΠΈΠ· ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π±ΡΠ΄Π΅ΠΌ Π΄ΠΎΡΡΠ°Π²Π°ΡΡ ΡΠΏΠΈΡΠΎΠΊ VM
$VMfilePath = "C:ScriptsgetVmcreators_VMcreators_VM_$(get-date -f yyyy-MM-dd).csv"
# ΠΡΡΡ ΠΊ ΡΠ°ΠΉΠ»Ρ, Π² ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅ΠΌ Π·Π°ΠΏΠΈΡΡΠ²Π°ΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ
$filePath = "C:ScriptsgetVmdatacreatorscreators-$(get-date -f yyyy-MM-dd).csv"
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π²ΠΎΠΊΡΡΠ»ΠΎΡ
Workflow GetCreators-Wf
{
# ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ΄Π΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΏΡΠΈ Π²ΡΠ·ΠΎΠ²Π΅ ΡΠΊΡΠΈΠΏΡΠ°
param([string[]]$VMfilePath)
# ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ Π΄ΠΎΡΡΡΠΏΠ½Ρ ΡΠΎΠ»ΡΠΊΠΎ Π²Π½ΡΡΡΠΈ workflow
$vCenterUsername = "myusername"
$vCenterPassword = "mypassword"
$daysToLook = 14
$start = (get-date).AddDays(-$daysToLook)
$finish = get-date
# ΠΠ½Π°ΡΠ΅Π½ΠΈΡ, ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ΄ΡΡ Π²ΠΏΠΈΡΠ°Π½Ρ Π² csv Π΄Π»Ρ ΠΌΠ°ΡΠΈΠ½, ΠΏΠΎ ΠΊΠΎΡΠΎΡΡΠΌ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π°ΠΉΠ΄Π΅Π½ΠΎ
$UnknownUser = "UNKNOWN"
$UnknownCreatedTime = "0000-00-00"
# ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΠΈ Π²ΡΠ²ΠΎΠ΄Π½ΠΎΠΉ ΡΠ°ΠΉΠ», ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ΄ΡΡ Π΄ΠΎΡΡΡΠΏΠ½Ρ Π²ΠΎ Π²ΡΡΠΌ ΡΠΊΡΠΈΠΏΡΠ΅.
$vCenterNames = @(
"vcenter01",
"vcenter02",
"vcenter03"
)
# ΠΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠΏΠΈΡΠΎΠΊ VM ΠΈΠ· csv ΠΈ Π·Π°Π³ΡΡΠΆΠ°Π΅ΠΌ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ
$list = Import-Csv $VMfilePath -UseCulture | select -ExpandProperty VM.Name
# Π¦ΠΈΠΊΠ», ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎ (ΠΏΠΎ 5 ΠΌΠ°ΡΠΈΠ½ Π·Π° ΡΠ°Π·)
foreach -parallel ($row in $list)
{
# ΠΡΠΎ ΡΠΊΡΠΈΠΏΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΠΈΠ΄ΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ²ΠΎΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΈ ΡΠ΅, ΠΊΠΎΡΠΎΡΡΠ΅ Π΅ΠΌΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Ρ ΡΠ΅ΡΠ΅Π· $Using
InlineScript {
# ΠΡΠ΅ΠΌΡ Π½Π°ΡΠ°Π»Π° Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ°
$StartTime = $(get-date)
Write-Host ""
Write-Host "Processing $Using:row started at $StartTime"
Write-Host ""
# ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΠΌ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ, ΡΡΠΎΠ±Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ Π½ΡΠΌ Π½Π΅ ΠΌΠ΅ΡΠ°Π»Π°ΡΡ Π² ΠΊΠΎΠ½ΡΠΎΠ»ΠΈ
$con = Connect-VIServer -Server $Using:vCenterNames -User $Using:vCenterUsername -Password $Using:vCenterPassword
# ΠΠΎΠ»ΡΡΠ°Π΅ΠΌ ΠΎΠ±ΡΠ΅ΠΊΡ vm
$vm = Get-VM -Name $Using:row
# ΠΠΈΠΆΠ΅ 2 ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ. ΠΠ΄Π½Π° Ρ ΡΠΈΠ»ΡΡΡΠΎΠΌ ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ, Π²ΡΠΎΡΠ°Ρ - Π±Π΅Π·. ΠΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ ΡΠ΅ΠΌ,
$Event = $vm | Get-VIEvent -Start $Using:start -Finish $Using:finish -Types Info | Where { $_.Gettype().Name -eq "VmBeingDeployedEvent" -or $_.Gettype().Name -eq "VmCreatedEvent" -or $_.Gettype().Name -eq "VmRegisteredEvent" -or $_.Gettype().Name -eq "VmClonedEvent"}
# $Event = $vm | Get-VIEvent -Types Info | Where { $_.Gettype().Name -eq "VmBeingDeployedEvent" -or $_.Gettype().Name -eq "VmCreatedEvent" -or $_.Gettype().Name -eq "VmRegisteredEvent" -or $_.Gettype().Name -eq "VmClonedEvent"}
# ΠΠ°ΠΏΠΎΠ»Π½ΡΠ΅ΠΌ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΎΠ³ΠΎ, ΡΠ΄Π°Π»ΠΎΡΡ Π»ΠΈ Π² Π»ΠΎΠ³Π°Ρ
Π½Π°ΠΉΡΠΈ ΡΡΠΎ-ΡΠΎ
If (($Event | Measure-Object).Count -eq 0){
$User = $Using:UnknownUser
$Created = $Using:UnknownCreatedTime
$CreatedFormat = $Using:UnknownCreatedTime
} Else {
If ($Event.Username -eq "" -or $Event.Username -eq $null) {
$User = $Using:UnknownUser
} Else {
$User = $Event.Username
} # Else
$CreatedFormat = $Event.CreatedTime
# ΠΠ΄ΠΈΠ½ ΠΈΠ· ΠΊΠΎΠ»Π»Π΅Π³ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΠΈΠ», ΡΡΠΎΠ±Ρ Π²ΡΠ΅ΠΌΡ Π±ΡΠ»ΠΎ Π² ΡΠ°ΠΊΠΎΠΌ ΡΠΎΡΠΌΠ°ΡΠ΅, ΠΏΠΎΡΡΠΎΠΌΡ Π΄ΡΠ±Π»ΠΈΡΡΠ΅ΠΌ Π΅Π³ΠΎ. Π Π² ΠΠ ΠΏΠΎΠΉΠ΄ΡΡ Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΡΠΉ ΡΠΎΡΠΌΠ°Ρ.
$Created = $Event.CreatedTime.ToString('yyyy-MM-dd')
} # Else
Write-Host "Creator for $vm is $User. Creating object."
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ ΠΎΠ±ΡΠ΅ΠΊΡ. ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ.
$Vmresult = New-Object PSObject
$Vmresult | add-member -MemberType NoteProperty -Name "VM Name" -Value $vm.Name
$Vmresult | add-member -MemberType NoteProperty -Name "CreatedBy" -Value $User
$Vmresult | add-member -MemberType NoteProperty -Name "CreatedOn" -Value $CreatedFormat
$Vmresult | add-member -MemberType NoteProperty -Name "CreatedOnFormat" -Value $Created
# ΠΡΠ²ΠΎΠ΄ΠΈΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΡ
$Vmresult
} # Inline
} # ForEach
}
$Creators = GetCreators-Wf $VMfilePath
# ΠΠ°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π² ΡΠ°ΠΉΠ»
$Creators | select 'VM Name', CreatedBy, CreatedOn | Export-Csv -Path $filePath -NoTypeInformation -UseCulture -Force
Write-Host "CSV generetion finisghed at $(get-date). PROFIT"
Π‘ΠΏΠ΅ΡΠΈΠ°Π»Π½ΠΎ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π·Π°ΡΠ»ΡΠΆΠ°Π²Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ°
ΠΠ΅Π½Π΅ΡΠΈΡΠ°Π½Π΅ Π½Π° ΠΊΡΠ°ΡΠΈΠ² xlsx Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρ ΡΡΡ ΡΠΏΠΈΡΡΠΊ Π½Π° Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π½ΠΎΠ²ΡΡ ΠΊΠ½ΠΈΠ³Ρ
# ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ : "xls" ΠΈ "xlsx"
wb<-createWorkbook(type="xlsx")
# Π‘ΡΠΈΠ»ΠΈ Π΄Π»Ρ ΠΈΠΌΡΠ½ ΡΡΠ΄ΠΎΠ² ΠΈ ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΊ Π² ΡΠ°Π±Π»ΠΈΡΠ°Ρ
TABLE_ROWNAMES_STYLE <- CellStyle(wb) + Font(wb, isBold=TRUE)
TABLE_COLNAMES_STYLE <- CellStyle(wb) + Font(wb, isBold=TRUE) +
Alignment(wrapText=TRUE, horizontal="ALIGN_CENTER") +
Border(color="black", position=c("TOP", "BOTTOM"),
pen=c("BORDER_THIN", "BORDER_THICK"))
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π½ΠΎΠ²ΡΠΉ Π»ΠΈΡΡ
sheet <- createSheet(wb, sheetName = names[2])
# ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΡΠ°Π±Π»ΠΈΡΡ
addDataFrame(incorrect_df_filtered,
sheet, startRow=1, startColumn=1, row.names=FALSE, byrow=FALSE,
colnamesStyle = TABLE_COLNAMES_STYLE,
rownamesStyle = TABLE_ROWNAMES_STYLE)
# ΠΠ΅Π½ΡΠ΅ΠΌ ΡΠΈΡΠΈΠ½Ρ, ΡΡΠΎΠ±Ρ ΡΠΎΡΠΌΠ°ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π±ΡΠ»ΠΎ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΌ
autoSizeColumn(sheet = sheet, colIndex=c(1:ncol(incorrect_df)))
# ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΡΠΈΠ»ΡΡΡΡ
addAutoFilter(sheet, cellRange = "C1:G1")
# ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΡΠΈΠ»Ρ
fo2 <- Fill(foregroundColor="red")
cs2 <- CellStyle(wb,
fill = fo2,
dataFormat = DataFormat("@"))
# ΠΠ°Ρ
ΠΎΠ΄ΠΈΠΌ ΡΡΠ΄Ρ Ρ Π½Π΅Π²Π΅ΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌ ΠΏΠΎΠ»Π΅ΠΌ ΠΠ»Π°Π΄Π΅Π»ΡΡΠ° ΠΈ ΠΏΡΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ ΠΊ Π½ΠΈΠΌ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΡΠΉ ΡΡΠΈΠ»Ρ
rowsOwner <- getRows(sheet, rowIndex = (which(!incorrect_df$isOwnerCorrect) + 1))
cellsOwner <- getCells(rowsOwner, colIndex = which( colnames(incorrect_df_filtered) == "Owner" ))
lapply(names(cellsOwner), function(x) setCellStyle(cellsOwner[[x]], cs2))
# ΠΠ°Ρ
ΠΎΠ΄ΠΈΠΌ ΡΡΠ΄Ρ Ρ Π½Π΅Π²Π΅ΡΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΡΠΌ ΠΏΠΎΠ»Π΅ΠΌ ΠΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΡ ΠΈ ΠΏΡΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ ΠΊ Π½ΠΈΠΌ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΡΠΉ ΡΡΠΈΠ»Ρ
rowsSubsystem <- getRows(sheet, rowIndex = (which(!incorrect_df$isSubsystemCorrect) + 1))
cellsSubsystem <- getCells(rowsSubsystem, colIndex = which( colnames(incorrect_df_filtered) == "Subsystem" ))
lapply(names(cellsSubsystem), function(x) setCellStyle(cellsSubsystem[[x]], cs2))
# ΠΠ½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΎ ΠΏΠΎ ΠΠ°ΡΠ΅Π³ΠΎΡΠΈΠΈ
rowsCategory <- getRows(sheet, rowIndex = (which(!incorrect_df$isCategoryCorrect) + 1))
cellsCategory <- getCells(rowsCategory, colIndex = which( colnames(incorrect_df_filtered) == "Category" ))
lapply(names(cellsCategory), function(x) setCellStyle(cellsCategory[[x]], cs2))
# Π‘ΠΎΠ·Π΄Π°ΡΠ΅Π»Ρ
rowsCreator <- getRows(sheet, rowIndex = (which(!incorrect_df$isCreatorCorrect) + 1))
cellsCreator <- getCells(rowsCreator, colIndex = which( colnames(incorrect_df_filtered) == "Creator" ))
lapply(names(cellsCreator), function(x) setCellStyle(cellsCreator[[x]], cs2))
# Π‘ΠΎΡ
ΡΠ°Π½ΡΠ΅ΠΌ ΡΠ°ΠΉΠ»
saveWorkbook(wb, filenameIncorrect)
Π Π΅Π·ΡΠ»ΡΠ°ΡΡΡ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Π½Π΅ΡΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ:
ΠΠΌΠ°ΡΠ΅ ΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ Π½ΡΠ°Π½Ρ ΠΎΡΠ½ΠΎΡΠ½ΠΎ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΡΠ° Π½Π° ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊΠ° Π½Π° Windows. ΠΠ΅ΡΠ΅ Π½Π΅Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ Π½Π°ΠΌΠ΅ΡΡΡ ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΈΡΠ΅ ΠΏΡΠ°Π²Π° ΠΈ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ, ΡΠ°ΠΊΠ° ΡΠ΅ Π²ΡΠΈΡΠΊΠΎ Π΄Π° Π·Π°ΠΏΠΎΡΠ½Π΅ ΠΊΠ°ΠΊΡΠΎ ΡΡΡΠ±Π²Π°. Π ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Π½Π° ΡΠΎΠ²Π° Π±Π΅ΡΠ΅ ΠΎΡΠΊΡΠΈΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ° R, ΠΊΠΎΡΡΠΎ ΡΠ°ΠΌΠ° ΡΡΠ·Π΄Π°Π²Π° Π·Π°Π΄Π°ΡΠ° Π·Π° ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° R ΡΠΊΡΠΈΠΏΡ ΠΈ Π΄ΠΎΡΠΈ Π½Π΅ Π·Π°Π±ΡΠ°Π²Ρ Π·Π° Π»ΠΎΠ³ ΡΠ°ΠΉΠ»Π°. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΊΠΎΡΠΈΠ³ΠΈΡΠ°ΡΠ΅ Π·Π°Π΄Π°ΡΠ°ΡΠ° ΡΡΡΠ½ΠΎ.
Π§Π°ΡΡ ΠΎΡ R ΠΊΠΎΠ΄ Ρ Π΄Π²Π° ΠΏΡΠΈΠΌΠ΅ΡΠ°, ΠΊΠΎΠΉΡΠΎ ΡΡΠ·Π΄Π°Π²Π° Π·Π°Π΄Π°ΡΠ° Π² Windows Scheduler
library(taskscheduleR)
myscript <- file.path(getwd(), "all_vm.R")
## Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠΊΡΠΈΠΏΡ ΡΠ΅ΡΠ΅Π· 62 ΡΠ΅ΠΊΡΠ½Π΄Ρ
taskscheduler_create(taskname = "getAllVm", rscript = myscript,
schedule = "ONCE", starttime = format(Sys.time() + 62, "%H:%M"))
## Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠΊΡΠΈΠΏΡ ΠΊΠ°ΠΆΠ΄ΡΠΉ Π΄Π΅Π½Ρ Π² 09:10
taskscheduler_create(taskname = "getAllVmDaily", rscript = myscript,
schedule = "WEEKLY",
days = c("MON", "TUE", "WED", "THU", "FRI"),
starttime = "02:00")
## ΡΠ΄Π°Π»ΡΠ΅ΠΌ Π·Π°Π΄Π°ΡΠΈ
taskscheduler_delete(taskname = "getAllVm")
taskscheduler_delete(taskname = "getAllVmDaily")
# Π‘ΠΌΠΎΡΡΠΈΠΌ Π»ΠΎΠ³ΠΈ (ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ 4 ΡΡΡΠΎΡΠΊΠΈ)
tail(readLines("all_vm.log"), sep ="n", n = 4)
ΠΡΠ΄Π΅Π»Π½ΠΎ Π·Π° Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ
Π‘Π»Π΅Π΄ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΡΠ° Π½Π° ΡΠΊΡΠΈΠΏΡΠ° Π·Π°ΠΏΠΎΡΠ½Π°Ρ Π° Π΄Π° ΡΠ΅ ΠΏΠΎΡΠ²ΡΠ²Π°Ρ Π΄ΡΡΠ³ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΈΡΠΊΠ°Ρ Π΄Π° Π½Π°ΠΌΠ΅ΡΡ Π΄Π°ΡΠ°ΡΠ°, Π½Π° ΠΊΠΎΡΡΠΎ VM Π΅ ΠΈΠ·ΡΡΠΈΡΠ°, Π½ΠΎ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΎΠ½Π½ΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ Π²ΡΠ² vCenter Π²Π΅ΡΠ΅ Π±ΡΡ Π° ΠΈΠ·Π½ΠΎΡΠ΅Π½ΠΈ. Π’ΡΠΉ ΠΊΠ°ΡΠΎ ΡΠΊΡΠΈΠΏΡΡΡ ΠΏΠΎΡΡΠ°Π²Ρ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ Π² ΠΏΠ°ΠΏΠΊΠ° Π²ΡΠ΅ΠΊΠΈ Π΄Π΅Π½ ΠΈ Π½Π΅ Ρ ΠΏΠΎΡΠΈΡΡΠ²Π° (ΡΠΈΡΡΠΈΠΌ Π³ΠΎ Ρ ΡΡΡΠ΅ΡΠ΅ ΡΠΈ, ΠΊΠΎΠ³Π°ΡΠΎ ΡΠ΅ ΡΠ΅ΡΠΈΠΌ), ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΡΠ΅Π³Π»Π΅Π΄Π°ΡΠ΅ ΡΡΠ°ΡΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ ΠΈ Π΄Π° Π½Π°ΠΌΠ΅ΡΠΈΡΠ΅ ΠΏΡΡΠ²ΠΈΡ ΡΠ°ΠΉΠ», Π² ΠΊΠΎΠΉΡΠΎ ΡΠ°Π·ΠΈ Π²ΠΈΡΡΡΠ°Π»Π½Π° ΠΌΠ°ΡΠΈΠ½Π° Π½Π΅ ΠΏΡΠΈΡΡΡΡΠ²Π°. ΠΠΎ ΡΠΎΠ²Π° Π½Π΅ Π΅ Π³ΠΎΡΠΈΠ½ΠΎ.
ΠΡΠΊΠ°Ρ Π΄Π° ΡΡΠ·Π΄Π°ΠΌ ΠΈΡΡΠΎΡΠΈΡΠ΅ΡΠΊΠ° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ.
ΠΠ° ΠΏΠΎΠΌΠΎΡ Π΄ΠΎΠΉΠ΄Π΅ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡΡΠ° Π½Π° MS SQL SERVER - ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎ-Π²Π΅ΡΡΠΈΡΠ°Π½Π° Π²ΡΠ΅ΠΌΠ΅Π½Π½Π° ΡΠ°Π±Π»ΠΈΡΠ°. ΠΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΡΠ΅ ΠΏΡΠ΅Π²Π΅ΠΆΠ΄Π° ΠΊΠ°ΡΠΎ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΈ (Π½Π΅ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΈ) ΡΠ°Π±Π»ΠΈΡΠΈ.
ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΡΠΎΡΠ΅ΡΠ΅ΡΠ΅ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ Π½Π°
ΠΠ°ΠΊΡΠ°ΡΠΊΠΎ, Π½ΠΈΠ΅ ΡΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ ΡΠ°Π±Π»ΠΈΡΠ°, ΠΊΠ°ΠΆΠ΅ΠΌ, ΡΠ΅ ΡΠ΅ Ρ ΠΈΠΌΠ°ΠΌΠ΅ Ρ Π²Π΅ΡΡΠΈΡ, ΠΈ SQL Server ΡΡΠ·Π΄Π°Π²Π° 2 Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½ΠΈ ΠΊΠΎΠ»ΠΎΠ½ΠΈ Π·Π° Π΄Π°ΡΠ° ΠΈ ΡΠ°Ρ Π² ΡΠ°Π·ΠΈ ΡΠ°Π±Π»ΠΈΡΠ° (Π΄Π°ΡΠ°ΡΠ°, Π½Π° ΠΊΠΎΡΡΠΎ Π΅ ΡΡΠ·Π΄Π°Π΄Π΅Π½ Π·Π°ΠΏΠΈΡΡΡ ΠΈ Π΄Π°ΡΠ°ΡΠ° Π½Π° ΠΈΠ·ΡΠΈΡΠ°Π½Π΅ Π½Π° Π·Π°ΠΏΠΈΡΠ°) ΠΈ Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½Π° ΡΠ°Π±Π»ΠΈΡΠ°, Π² ΠΊΠΎΡΡΠΎ ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½Ρ ΡΠ΅ Π±ΡΠ΄Π΅ Π½Π°ΠΏΠΈΡΠ°Π½ΠΎ. Π ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Π½Π° ΡΠΎΠ²Π° ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ Π°ΠΊΡΡΠ°Π»Π½Π° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΈ ΡΡΠ΅Π· ΠΏΡΠΎΡΡΠΈ Π·Π°ΡΠ²ΠΊΠΈ, ΠΏΡΠΈΠΌΠ΅ΡΠΈ Π·Π° ΠΊΠΎΠΈΡΠΎ ΡΠ° Π΄Π°Π΄Π΅Π½ΠΈ Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡΠ°, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ ΠΈΠ»ΠΈ ΠΆΠΈΠ·Π½Π΅Π½ΠΈΡ ΡΠΈΠΊΡΠ» Π½Π° ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½Π° Π²ΠΈΡΡΡΠ°Π»Π½Π° ΠΌΠ°ΡΠΈΠ½Π°, ΠΈΠ»ΠΈ ΡΡΡΡΠΎΡΠ½ΠΈΠ΅ΡΠΎ Π½Π° Π²ΡΠΈΡΠΊΠΈ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Π² ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ ΠΌΠΎΠΌΠ΅Π½Ρ Π½Π° Π²ΡΠ΅ΠΌΠ΅.
ΠΡ Π³Π»Π΅Π΄Π½Π° ΡΠΎΡΠΊΠ° Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»Π½ΠΎΡΡΡΠ° ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡΡΠ° Π·Π° Π·Π°ΠΏΠΈΡ Π² Π³Π»Π°Π²Π½Π°ΡΠ° ΡΠ°Π±Π»ΠΈΡΠ° Π½ΡΠΌΠ° Π΄Π° Π·Π°Π²ΡΡΡΠΈ, Π΄ΠΎΠΊΠ°ΡΠΎ Π½Π΅ Π·Π°Π²ΡΡΡΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡΡΠ° Π·Π° Π·Π°ΠΏΠΈΡ Π²ΡΠ² Π²ΡΠ΅ΠΌΠ΅Π½Π½Π°ΡΠ° ΡΠ°Π±Π»ΠΈΡΠ°. Π’Π΅Π·ΠΈ. Π½Π° ΡΠ°Π±Π»ΠΈΡΠΈ Ρ Π³ΠΎΠ»ΡΠΌ Π±ΡΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π·Π° Π·Π°ΠΏΠΈΡ, ΡΠ°Π·ΠΈ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ ΡΡΡΠ±Π²Π° Π΄Π° ΡΠ΅ ΠΏΡΠΈΠ»Π°Π³Π° Ρ ΠΏΠΎΠ²ΠΈΡΠ΅Π½ΠΎ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Π½ΠΎ Π² Π½Π°ΡΠΈΡ ΡΠ»ΡΡΠ°ΠΉ ΡΠΎΠ²Π° Π΅ Π½Π°ΠΈΡΡΠΈΠ½Π° ΡΡΡΠ°Ρ ΠΎΡΠ½ΠΎ Π½Π΅ΡΠΎ.
ΠΠ° Π΄Π° ΠΌΠΎΠΆΠ΅ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΡΡ Π΄Π° ΡΠ°Π±ΠΎΡΠΈ ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ, ΡΡΡΠ±Π²Π°ΡΠ΅ Π΄Π° Π΄ΠΎΠ±Π°Π²Ρ ΠΌΠ°Π»ΠΊΠΎ ΠΏΠ°ΡΡΠ΅ ΠΊΠΎΠ΄ Π² R, ΠΊΠΎΠ΅ΡΠΎ Π΄Π° ΡΡΠ°Π²Π½ΡΠ²Π° Π½ΠΎΠ²Π°ΡΠ° ΡΠ°Π±Π»ΠΈΡΠ° Ρ Π΄Π°Π½Π½ΠΈ Π·Π° Π²ΡΠΈΡΠΊΠΈ Π²ΠΈΡΡΡΠ°Π»Π½ΠΈ ΠΌΠ°ΡΠΈΠ½ΠΈ Ρ ΡΠ°Π·ΠΈ, ΡΡΡ ΡΠ°Π½ΡΠ²Π°Π½Π° Π² Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ ΠΈ Π΄Π° Π·Π°ΠΏΠΈΡΠ²Π° ΡΠ°ΠΌΠΎ ΠΏΡΠΎΠΌΠ΅Π½Π΅Π½ΠΈ ΡΠ΅Π΄ΠΎΠ²Π΅ Π² Π½Π΅Ρ. ΠΠΎΠ΄ΡΡ Π½Π΅ Π΅ ΠΎΡΠΎΠ±Π΅Π½ΠΎ ΡΠΌΠ΅Π½, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ° compareDF, Π½ΠΎ ΡΠ΅ Π²ΠΈ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Ρ ΠΈ Π½Π΅Ρ ΠΏΠΎ-Π΄ΠΎΠ»Ρ.
R ΠΊΠΎΠ΄ Π·Π° Π·Π°ΠΏΠΈΡ Π½Π° Π΄Π°Π½Π½ΠΈ Π² Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ
# ΠΠΎΠ΄ΡΠ΅ΠΏΠ»ΡΠ΅ΠΌ ΠΏΠ°ΠΊΠ΅ΡΡ
library(odbc)
library(compareDF)
# Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΠΊΠΎΠ½Π½Π΅ΠΊΡ
con <- dbConnect(odbc(),
Driver = "ODBC Driver 13 for SQL Server",
Server = DBParams$server,
Database = DBParams$database,
UID = DBParams$UID,
PWD = DBParams$PWD,
Port = 1433)
#### ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ Π΅ΡΡΡ Π»ΠΈ ΡΠ°Π±Π»ΠΈΡΠ°. ΠΡΠ»ΠΈ Π½Π΅Ρ - ΡΠΎΠ·Π΄Π°ΡΠΌ. ####
if (!dbExistsTable(con, DBParams$TblName)) {
#### Π‘ΠΎΠ·Π΄Π°ΡΠΌ ΡΠ°Π±Π»ΠΈΡΡ ####
create <- dbSendStatement(
con,
paste0(
'CREATE TABLE ',
DBParams$TblName,
'(
[Id] [int] NOT NULL PRIMARY KEY CLUSTERED,
[VM.Name] [varchar](255) NULL,
[Cluster] [varchar](255) NULL,
[Esxi.Host] [varchar](255) NULL,
[IP.Address.1] [varchar](255) NULL,
[IP.Address.2] [varchar](255) NULL,
[IP.Address.3] [varchar](255) NULL,
[IP.Address.4] [varchar](255) NULL,
[IP.Address.5] [varchar](255) NULL,
[IP.Address.6] [varchar](255) NULL,
[vCPU] [int] NULL,
[CPU.Sockets] [int] NULL,
[Core.per.Socket] [int] NULL,
[RAM..GB.] [int] NULL,
[Total.HDD..GB.] [int] NULL,
[Power.State] [varchar](255) NULL,
[OS] [varchar](255) NULL,
[Boot.Time] [varchar](255) NULL,
[VMTools.Status] [varchar](255) NULL,
[VMTools.Version] [int] NULL,
[VMTools.Version.Status] [varchar](255) NULL,
[VMTools.Running.Status] [varchar](255) NULL,
[Creation.Date] [varchar](255) NULL,
[Creator] [varchar](255) NULL,
[Category] [varchar](255) NULL,
[Owner] [varchar](255) NULL,
[Subsystem] [varchar](255) NULL,
[IP.s] [varchar](255) NULL,
[vCenter.Name] [varchar](255) NULL,
DateFrom datetime2 GENERATED ALWAYS AS ROW START NOT NULL,
DateTo datetime2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (DateFrom, DateTo)
) ON [PRIMARY]
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = ', DBParams$TblHistName,'));'
)
)
# ΠΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²Π»Π΅Π½Π½ΡΠΉ Π·Π°ΠΏΡΠΎΡ
dbClearResult(create)
} # if
#### ΠΠ°ΡΠ°Π»ΠΎ ΡΠ°Π±ΠΎΡΡ Ρ ΡΠ°Π±Π»ΠΈΡΠ΅ΠΉ ####
# ΠΠ±ΠΎΠ·Π½Π°ΡΠ°Π΅ΠΌ ΡΠ°Π±Π»ΠΈΡΡ, Ρ ΠΊΠΎΡΠΎΡΠΎΠΉ Π±ΡΠ΄Π΅ΠΌ ΡΠ°Π±ΠΎΡΠ°ΡΡ
allVM_db_con <- tbl(con, DBParams$TblName)
#### Π‘ΡΠ°Π²Π½ΠΈΠ²Π°Π΅ΠΌ ΡΠ°Π±Π»ΠΈΡΡ ####
# Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ Ρ ΡΠ°Π±Π»ΠΈΡΡ (ΡΠ±ΠΈΡΠ°Π΅ΠΌ ΡΠ»ΡΠΆΠ΅Π±Π½ΡΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΏΠΎΠ»Ρ)
allVM_db <- allVM_db_con %>%
select(c(-"DateTo", -"DateFrom")) %>%
collect()
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ ΡΠ°Π±Π»ΠΈΡΡ ΡΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ². Π‘ΡΠ°Π²Π½ΠΈΠ²Π°Π΅ΠΌ ΠΏΠΎ Id
# Π£Π΄Π°Π»ΡΠ½Π½ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΡΠ°ΠΌ Π±ΡΠ΄ΡΡ ΠΏΠΎΠΌΠ΅ΡΠ΅Π½Ρ ΡΠ΅ΡΠ΅Π· -, ΡΠΎΠ·Π΄Π°Π½Π½ΡΠ΅ ΡΠ΅ΡΠ΅Π· +, ΠΈΠ·ΠΌΠ΅Π½ΡΠ½Π½ΡΠ΅ ΡΠ΅ΡΠ΅Π· - ΠΈ +
ctable_VM <- fullXslx_df %>%
compare_df(allVM_db,
c("Id"))
#### Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΡΡΡΠΎΠΊ ####
# ΠΡΠ΄ΠΈΡΠ°Π΅ΠΌ Id Π²ΠΈΡΡΡΠ°Π»ΠΎΠΊ, Π·Π°ΠΏΠΈΡΠΈ ΠΎ ΠΊΠΎΡΠΎΡΡΡ
Π½Π°Π΄ΠΎ ΡΠ΄Π°Π»ΠΈΡΡ
remove_Id <- ctable_VM$comparison_df %>%
filter(chng_type == "-") %>%
select(Id)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, ΡΡΠΎ Π΅ΡΡΡ Π·Π°ΠΏΠΈΡΠΈ (Π΅ΡΠ»ΠΈ Π·Π°ΠΏΠΈΡΠ΅ΠΉ Π½Π΅Ρ - ΠΈ ΡΠ΄Π°Π»ΡΡΡ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ Π½ΡΠΆΠ½ΠΎ)
if (remove_Id %>% nrow() > 0) {
# ΠΠΎΠ½ΡΡΡΡΠΈΡΡΠ΅ΠΌ ΡΠ°Π±Π»ΠΎΠ½ Π΄Π»Ρ Π·Π°ΠΏΡΠΎΡΠ° Π½Π° ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ
delete <- dbSendStatement(con,
paste0('
DELETE
FROM ',
DBParams$TblName,
' WHERE "Id"=?
') # paste
) # send
# Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π·Π°ΠΏΡΠΎΡ Π½Π° ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ
dbBind(delete, remove_Id)
# ΠΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²Π»Π΅Π½Π½ΡΠΉ Π·Π°ΠΏΡΠΎΡ
dbClearResult(delete)
} # if
#### ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΡΡΡΠΎΠΊ ####
# ΠΡΠ΄Π΅Π»ΡΠ΅ΠΌ ΡΠ°Π±Π»ΠΈΡΡ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡΡ ΡΡΡΠΎΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½ΡΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ.
allVM_add <- ctable_VM$comparison_df %>%
filter(chng_type == "+") %>%
select(-chng_type)
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, Π΅ΡΡΡ Π»ΠΈ ΡΡΡΠΎΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½ΡΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ (Π΅ΡΠ»ΠΈ Π½Π΅Ρ - Π½Π΅ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ)
if (allVM_add %>% nrow() > 0) {
# ΠΠΈΡΠ΅ΠΌ ΡΠ°Π±Π»ΠΈΡΡ ΡΠΎ Π²ΡΠ΅ΠΌΠΈ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠΌΠΈ Π΄Π°Π½Π½ΡΠΌΠΈ
dbWriteTable(con,
DBParams$TblName,
allVM_add,
overwrite = FALSE,
append = TRUE)
} # if
#### ΠΠ΅ Π·Π°Π±ΡΠ²Π°Π΅ΠΌ ΡΠ΄Π΅Π»Π°ΡΡ Π΄ΠΈΡΠΊΠΎΠ½Π½Π΅ΠΊΡ ####
dbDisconnect(con)
ΠΠ±ΡΠΎ
Π ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Π½Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ΡΠΎ Π½Π° ΡΡΠ΅Π½Π°ΡΠΈΡ ΡΠ΅Π΄ΡΡ Π±Π΅ΡΠ΅ Π²ΡΠ·ΡΡΠ°Π½ΠΎΠ²Π΅Π½ ΠΈ ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ°Π½ Π² ΡΠ°ΠΌΠΊΠΈΡΠ΅ Π½Π° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΌΠ΅ΡΠ΅ΡΠ°. ΠΠΎΠ½ΡΠΊΠΎΠ³Π° ΡΠ΅ ΠΏΠΎΡΠ²ΡΠ²Π°Ρ Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ ΠΏΠΎΠΏΡΠ»Π½Π΅Π½ΠΈ VM, Π½ΠΎ ΡΠΊΡΠΈΠΏΡΡΡ ΡΠ»ΡΠΆΠΈ ΠΊΠ°ΡΠΎ Π΄ΠΎΠ±ΡΠΎ Π½Π°ΠΏΠΎΠΌΠ½ΡΠ½Π΅ ΠΈ ΡΡΠ΄ΠΊΠ° VM ΠΏΠΎΠΏΠ°Π΄Π° Π² ΡΠΏΠΈΡΡΠΊΠ° Π·Π° 2 Π΄Π½ΠΈ ΠΏΠΎΠ΄ΡΠ΅Π΄.
ΠΠ°ΠΏΡΠ°Π²Π΅Π½Π° Π΅ ΠΈ ΠΎΡΠ½ΠΎΠ²Π° Π·Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅ Π½Π° ΠΈΡΡΠΎΡΠΈΡΠ΅ΡΠΊΠΈ Π΄Π°Π½Π½ΠΈ.
Π―ΡΠ½ΠΎ Π΅, ΡΠ΅ Π³ΠΎΠ»ΡΠΌΠ° ΡΠ°ΡΡ ΠΎΡ ΡΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·ΠΈΡΠ° Π½Π΅ Π½Π° ΠΊΠΎΠ»ΡΠ½ΠΎ, Π° ΡΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½ ΡΠΎΡΡΡΠ΅Ρ, Π½ΠΎ Π·Π°Π΄Π°ΡΠ°ΡΠ° Π±Π΅ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½Π° ΠΈ, ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΊΠ°ΠΆΠ΅, Π½Π΅Π·Π°Π΄ΡΠ»ΠΆΠΈΡΠ΅Π»Π½Π°.
R ΠΎΡΠ½ΠΎΠ²ΠΎ ΠΏΠΎΠΊΠ°Π·Π°, ΡΠ΅ Π΅ ΠΎΡΠ»ΠΈΡΠ΅Π½ ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»Π΅Π½ Π΅Π·ΠΈΠΊ, ΠΊΠΎΠΉΡΠΎ Π΅ ΠΈΠ΄Π΅Π°Π»Π΅Π½ Π½Π΅ ΡΠ°ΠΌΠΎ Π·Π° ΡΠ΅ΡΠ°Π²Π°Π½Π΅ Π½Π° ΡΡΠ°ΡΠΈΡΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ, Π½ΠΎ ΠΈ Π΄Π΅ΠΉΡΡΠ²Π° ΠΊΠ°ΡΠΎ ΠΎΡΠ»ΠΈΡΠ΅Π½ βΡΠ»ΠΎΠΉβ ΠΌΠ΅ΠΆΠ΄Ρ Π΄ΡΡΠ³ΠΈ ΠΈΠ·ΡΠΎΡΠ½ΠΈΡΠΈ Π½Π° Π΄Π°Π½Π½ΠΈ.
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com