Π•ΠΆΠ΅Π΄Π½Π΅Π²Π½Ρ‹Π΅ ΠΎΡ‚Ρ‡Ρ‘Ρ‚Ρ‹ ΠΏΠΎ ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ R ΠΈ PowerShell

Π•ΠΆΠ΅Π΄Π½Π΅Π²Π½Ρ‹Π΅ ΠΎΡ‚Ρ‡Ρ‘Ρ‚Ρ‹ ΠΏΠΎ ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ R ΠΈ PowerShell

ВступлСниС

Π”Π΅Π½ΡŒ Π΄ΠΎΠ±Ρ€Ρ‹ΠΉ. Π£ΠΆΠ΅ ΠΏΠΎΠ» Π³ΠΎΠ΄Π° Ρƒ нас Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ скрипт (Ρ‚ΠΎΡ‡Π½Π΅Π΅ Π½Π°Π±ΠΎΡ€ скриптов), Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ ΠΎΡ‚Ρ‡Ρ‘Ρ‚Ρ‹ ΠΏΠΎ ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин (ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ). РСшил ΠΏΠΎΠ΄Π΅Π»ΠΈΡ‚ΡŒΡΡ ΠΎΠΏΡ‹Ρ‚ΠΎΠΌ создания ΠΈ самим ΠΊΠΎΠ΄ΠΎΠΌ. Π Π°ΡΡΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽ Π½Π° ΠΊΡ€ΠΈΡ‚ΠΈΠΊΡƒ ΠΈ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΌ.

Π€ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ потрСбности

Π’ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин Ρƒ нас ΠΌΠ½ΠΎΠ³ΠΎ (порядка 1500 Π’Πœ распрСдСлённых ΠΏΠΎ 3-ΠΌ vCenter). Π‘ΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Π½ΠΎΠ²Ρ‹Π΅ ΠΈ ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ старыС достаточно часто. Для сохранСния порядка Π±Ρ‹Π»ΠΎ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ нСсколько custom ΠΏΠΎΠ»Π΅ΠΉ Π² vCenter, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·Π΄Π΅Π»ΡΡ‚ΡŒ Π’Πœ Π½Π° ΠŸΠΎΠ΄ΡΠΈΡΡ‚Π΅ΠΌΡ‹, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ тСстовыС Π»ΠΈ ΠΎΠ½ΠΈ, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΊΠ΅ΠΌ ΠΈ ΠΊΠΎΠ³Π΄Π° созданы. ЧСловСчСский Ρ„Π°ΠΊΡ‚ΠΎΡ€ ΠΏΡ€ΠΈΠ²Ρ‘Π» ΠΊ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Ρ‹ машин ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ с Π½Π΅Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌΠΈ полями, Ρ‡Ρ‚ΠΎ услоТняло Ρ€Π°Π±ΠΎΡ‚Ρƒ. Π Π°Π· Π² ΠΏΠΎΠ» Π³ΠΎΠ΄Π° ΠΊΡ‚ΠΎ-Ρ‚ΠΎ психовал, Π·Π°Ρ‚Π΅Π²Π°Π» Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΠΎ Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ этих Π΄Π°Π½Π½Ρ‹Ρ…, Π½ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ пСрСставал Π±Ρ‹Ρ‚ΡŒ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌ ΡƒΠΆΠ΅ Π½Π΅Π΄Π΅Π»ΠΈ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠΎΠ»Ρ‚ΠΎΡ€Ρ‹.
Π‘Ρ€Π°Π·Ρƒ ΡƒΡ‚ΠΎΡ‡Π½ΡŽ, Ρ‡Ρ‚ΠΎ всС ΠΏΠΎΠ½ΠΈΠΌΠ°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ заявки Π½Π° созданиС машин, процСсс ΠΏΠΎ ΠΈΡ… созданию, ΠΈ Ρ‚.Π΄. ΠΈ Ρ‚.ΠΏ. И ΠΏΡ€ΠΈ этом всС этому процСссу Π½Π΅ΡƒΠΊΠΎΡΠ½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ ΠΈ Π²ΠΎ всём порядок. Π£ нас, ΠΊ соТалСнию, Π½Π΅ Ρ‚Π°ΠΊ, Π½ΠΎ это Π½Π΅ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ ΡΡ‚Π°Ρ‚ΡŒΠΈ πŸ™‚

Π’ ΠΎΠ±Ρ‰Π΅ΠΌ, Π±Ρ‹Π»ΠΎ принято Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΠΈ заполнСния ΠΏΠΎΠ»Π΅ΠΉ.
РСшили, Ρ‡Ρ‚ΠΎ Π΅ΠΆΠ΅Π΄Π½Π΅Π²Π½ΠΎΠ΅ письмо со списком Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Ρ… машин Π½Π° всСх отвСтствСнных ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€ΠΎΠ² ΠΈ ΠΈΡ… Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΈΠΊΠΎΠ² Π±ΡƒΠ΄Π΅Ρ‚ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ Π½Π°Ρ‡Π°Π»ΠΎΠΌ.

На этот ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· ΠΊΠΎΠ»Π»Π΅Π³ ΡƒΠΆΠ΅ Π±Ρ‹Π» Π²Π½Π΅Π΄Ρ€Ρ‘Π½ скрипт Π½Π° PowerShell, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ дСнь ΠΏΠΎ Ρ€Π°ΡΠΏΠΈΡΠ°Π½ΠΈΡŽ собирал ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΏΠΎ всСм машинам всСх vCenter-ΠΎΠ² ΠΈ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Π» 3 csv Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π° (ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎ своСму vCenter), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ΠΊΠ»Π°Π΄Ρ‹Π²Π°Π»ΠΈΡΡŒ Π½Π° ΠΎΠ±Ρ‰ΠΈΠΉ диск. Π‘Ρ‹Π»ΠΎ принято Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π²Π·ΡΡ‚ΡŒ этот скрипт Π·Π° основу ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°ΠΌΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ языка R, ΠΏΠΎ Ρ€Π°Π±ΠΎΡ‚Π΅ с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π±Ρ‹Π» Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚.

Π’ процСссС Π΄ΠΎΡ€Π°Π±ΠΎΡ‚ΠΊΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ обросло ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΠΎ ΠΏΠΎΡ‡Ρ‚Π΅, Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ… с основной ΠΈ историчСской Ρ‚Π°Π±Π»ΠΈΡ†Π΅ΠΉ (ΠΎΠ± этом ΠΏΠΎΠ·Π΄Π½Π΅Π΅), Π° Ρ‚Π°ΠΊΠΆΠ΅ Π°Π½Π°Π»ΠΈΠ·ΠΎΠΌ Π»ΠΎΠ³ΠΎΠ² vSphere для поиска фактичСских создатСлСй vm ΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈΡ… создания.

Для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ использовались IDE RStudio Desktop ΠΈ PowerShell ISE.

Π‘ΠΊΡ€ΠΈΠΏΡ‚ запускаСтся с ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ Π²ΠΈΠ½Π΄ΠΎΠ²ΠΎΠΉ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ ΠΌΠ°ΡˆΠΈΠ½Ρ‹.

ОписаниС ΠΎΠ±Ρ‰Π΅ΠΉ Π»ΠΎΠ³ΠΈΠΊΠΈ.

ΠžΠ±Ρ‰Π°Ρ Π»ΠΎΠ³ΠΈΠΊΠ° скриптов ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»Π°ΡΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ.

  • Π‘ΠΎΠ±ΠΈΡ€Π°Π΅ΠΌ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌ машинам с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ PowerShell скрипта, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ‡Π΅Ρ€Π΅Π· R, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ объСдиняСм Π² ΠΎΠ΄ΠΈΠ½ csv. ΠžΠ±Ρ€Π°Ρ‚Π½ΠΎΠ΅ взаимодСйствиС ΠΌΠ΅ΠΆΠ΄Ρƒ языками сдСлано Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ. (ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π³ΠΎΠ½ΡΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ ΠΈΠ· R Π² PowerShell Π² Π²ΠΈΠ΄Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, Π½ΠΎ это слоТно, Π΄Π° ΠΈ имСя ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹Π΅ csv Π»Π΅Π³Ρ‡Π΅ Π΄Π΅Π±Π°ΠΆΠΈΡ‚ΡŒ ΠΈ Π΄Π΅Π»ΠΈΡ‚ΡŒΡΡ с ΠΊΠ΅ΠΌ-Ρ‚ΠΎ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΌΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌΠΈ).
  • Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ R Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ допустимыС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ для ΠΏΠΎΠ»Π΅ΠΉ, значСния ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΌΡ‹ провСряСм. β€” Π€ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ word Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ значСния этих ΠΏΠΎΠ»Π΅ΠΉ для вставки Π² ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½ΠΎΠ΅ письмо, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠΌ Π½Π° вопросы ΠΊΠΎΠ»Π»Π΅Π³ "НС Π½Ρƒ Π° ΠΊΠ°ΠΊ я это Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ?".
  • Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ всСм Π’Πœ ΠΈΠ· csv с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ R, Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ dataframe, ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ Π½Π΅Π½ΡƒΠΆΠ½Ρ‹Π΅ поля ΠΈ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹ΠΉ xlsx Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΡΠ²ΠΎΠ΄Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΏΠΎ всСм Π’Πœ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹ΠΊΠ»Π°Π΄Ρ‹Π²Π°Π΅ΠΌ Π½Π° ΠΎΠ±Ρ‰ΠΈΠΉ рСсурс.
  • К dataframe ΠΏΠΎ всСм Π’Πœ примСняСм всС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΠΈ заполнСния ΠΏΠΎΠ»Π΅ΠΉ ΠΈ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ, ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‰ΡƒΡŽ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π’Πœ с Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌΠΈ полями (ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ эти поля).
  • ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΉ список Π’Πœ отправляСм Π½Π° Π΄Ρ€ΡƒΠ³ΠΎΠΉ PowerShell скрипт, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π»ΠΎΠ³ΠΈ vCenter Π½Π° ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ событий создания Π’Πœ, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΠΎΠ΅ врСмя создания Π’Πœ ΠΈ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΠΎΠ³ΠΎ создатСля. Π­Ρ‚ΠΎ Π½Π° случай, ΠΊΠΎΠ³Π΄Π° Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ сознаётся, Ρ‡ΡŒΡ машина. Π”Π°Π½Π½Ρ‹ΠΉ скрипт Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½Π΅ быстро, особСнно, Ссли Π»ΠΎΠ³ΠΎΠ² ΠΌΠ½ΠΎΠ³ΠΎ, поэтому смотрим Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послСдниС 2 Π½Π΅Π΄Π΅Π»ΠΈ, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ workflow, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ поиск ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΏΠΎ нСскольким Π’Πœ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ. Π’ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ скрипта Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ ΠΏΠΎ Π΄Π°Π½Π½ΠΎΠΌΡƒ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡƒ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ складываСм Π² csv, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠΏΡΡ‚ΡŒ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π² R.
  • Π€ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ красиво ΠΎΡ‚Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ xlsx Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π΄Π΅Π»Π΅Π½Ρ‹ красным Ρ†Π²Π΅Ρ‚ΠΎΠΌ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ поля, ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½Ρ‹ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ ΠΊ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°ΠΌ, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, содСрТащиС ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌΡ‹Ρ… создатСлСй ΠΈ врСмя создания Π’Πœ.
  • Π€ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ элСктронноС письмо, ΠΊΡƒΠ΄Π° Π²ΠΊΠ»Π°Π΄Ρ‹Π²Π°Π΅ΠΌ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΠΉ допустимыС значСния ΠΏΠΎΠ»Π΅ΠΉ, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ с Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹ΠΌΠΈ Π²ΠΌ. Π’ тСкстС ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ ΠΎΠ±Ρ‰Π΅Π΅ количСство Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ созданных Π’Πœ, ссылку Π½Π° ΠΎΠ±Ρ‰ΠΈΠΉ рСсурс ΠΈ ΠΌΠΎΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΎΠ½Π½ΡƒΡŽ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΡƒ. Если Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Ρ… Π’Πœ Π½Π΅Ρ‚ β€” отправляСм Π΄Ρ€ΡƒΠ³ΠΎΠ΅ письмо с Π±ΠΎΠ»Π΅Π΅ радостной ΠΌΠΎΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΎΠ½Π½ΠΎΠΉ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠΎΠΉ.
  • ЗаписываСм Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎ всСм Π’Πœ Π² Π‘Π” 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, которая ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ»Π° ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π²Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΊ ΠΏΠΈΡΡŒΠΌΡƒ наглядно ΠΎΡ‚Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ (ΠΊΠ°ΠΊ Π»ΡŽΠ±ΠΈΡ‚ руководство), Π° Π½Π΅ просто csv Ρ‚Π°Π±Π»ΠΈΡ†Π΅ΠΉ.

Π€ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ красивого 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)

На Π²Ρ‹Ρ…ΠΎΠ΄Π΅ получаСтся ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Π²ΠΎΡ‚ Ρ‚Π°ΠΊ:

Π•ΠΆΠ΅Π΄Π½Π΅Π²Π½Ρ‹Π΅ ΠΎΡ‚Ρ‡Ρ‘Ρ‚Ρ‹ ΠΏΠΎ ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ R ΠΈ PowerShell

Π’Π°ΠΊΠΆΠ΅ Π±Ρ‹Π» интСрСсный нюанс ΠΏΠΎ настройкС Windows scheduller. Никак Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π»ΠΎΡΡŒ ΠΏΠΎΠ΄ΠΎΠ±Ρ€Π°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΏΡ€Π°Π² ΠΈ настроСк, Ρ‡Ρ‚ΠΎΠ±Ρ‹ всё Π·Π°ΠΏΡƒΡΠΊΠ°Π»ΠΎΡΡŒ, ΠΊΠ°ΠΊ Π½ΡƒΠΆΠ½ΠΎ. Π’ ΠΈΡ‚ΠΎΠ³Π΅ Π±Ρ‹Π»Π° Π½Π°ΠΉΠ΄Π΅Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° R, которая сама создаёт Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΏΠΎ запуску R скрипта ΠΈ Π΄Π°ΠΆΠ΅ Π½Π΅ Π·Π°Π±Ρ‹Π²Π°Π΅Ρ‚ ΠΏΡ€ΠΎ Ρ„Π°ΠΉΠ» для Π»ΠΎΠ³ΠΎΠ². ΠŸΠΎΡ‚ΠΎΠΌ ΠΌΠΎΠΆΠ½ΠΎ Ρ€ΡƒΡ‡ΠΊΠ°ΠΌΠΈ ΠΏΠΎΠ΄ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π·Π°Π΄Π°Π½ΠΈΠ΅.

ΠšΡƒΡΠΎΡ‡Π΅ΠΊ ΠΊΠΎΠ΄Π° Π½Π° R с двумя ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаёт Π·Π°Π΄Π°Π½ΠΈΠ΅ Π² ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ΅ Windows

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)

ΠžΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ ΠΏΡ€ΠΎ Π‘Π”

ПослС настройки скрипта стали ΠΏΡ€ΠΎΡΠ²Π»ΡΡ‚ΡŒΡΡ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ вопросы. НапримСр, Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π½Π°ΠΉΡ‚ΠΈ Π΄Π°Ρ‚Ρƒ, ΠΊΠΎΠ³Π΄Π° Π’Πœ Π±Ρ‹Π»Π° ΡƒΠ΄Π°Π»Π΅Π½Π°, Π° Π»ΠΎΠ³ΠΈ Π² vCenter ΡƒΠΆΠ΅ ΠΏΠΎΡ‚Ρ‘Ρ€Π»ΠΈΡΡŒ. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ скрипт складываСт Ρ„Π°ΠΉΠ»Ρ‹ Π² ΠΏΠ°ΠΏΠΊΡƒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ дСнь ΠΈ Π½Π΅ чистит (чистим Ρ€ΡƒΠΊΠ°ΠΌΠΈ, ΠΊΠΎΠ³Π΄Π° вспоминаСм), Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ старыС Ρ„Π°ΠΉΠ»Ρ‹ ΠΈ Π½Π°ΠΉΡ‚ΠΈ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ„Π°ΠΉΠ», Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π΄Π°Π½Π½ΠΎΠΉ Π’Πœ Π½Π΅Ρ‚. Но это Π½Π΅ ΠΊΡ€ΡƒΡ‚ΠΎ.

Π—Π°Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΈΡΡ‚ΠΎΡ€ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π‘Π”.

На ΠΏΠΎΠΌΠΎΡ‰ΡŒ ΠΏΡ€ΠΈΡˆΡ‘Π» Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π» MS SQL SERVER β€” system-versioned temporal table. Π•Π³ΠΎ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ пСрСводят, ΠΊΠ°ΠΊ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Π«Π΅ (Π½Π΅ Π²Ρ€Π•ΠΌΠ΅Π½Π½Ρ‹Π΅) Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹.

МоТно ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π² ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ Microsoft.

Если Π²ΠΊΡ€Π°Ρ‚Ρ†Π΅ β€” создаём Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ, Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ с Π²Π΅Ρ€ΡΠΈΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ SQL Server создаёт 2 Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ datetime ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Π² этой Ρ‚Π°Π±Π»ΠΈΡ†Π΅ (Π΄Π°Ρ‚Ρƒ создания записи ΠΈ Π΄Π°Ρ‚Ρƒ окончания ΠΆΠΈΠ·Π½ΠΈ записи) ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΈΡΠ°Ρ‚ΡŒΡΡ измСнСния. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΈ, ΠΏΡƒΡ‚Ρ‘ΠΌ нСслоТных запросов, ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π΄Π°Π½Ρ‹ Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ, ΠΌΠΎΠΆΠ΅ΠΌ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Π»ΠΈΠ±ΠΎ ΠΆΠΈΠ·Π½Π΅Π½Π½Ρ‹ΠΉ Ρ†ΠΈΠΊΠ» ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ ΠΌΠ°ΡˆΠΈΠ½Ρ‹, Π»ΠΈΠ±ΠΎ состояниС всСх Π’Πœ Π½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.

Π‘ Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ β€” транзакция записи Π² ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π°, ΠΏΠΎΠΊΠ° Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ транзакция записи Π² Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. Π’.Π΅. Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ… с большим количСством ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ записи этот Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π» Π½Π°Π΄ΠΎ Π²Π½Π΅Π΄Ρ€ΡΡ‚ΡŒ с ΠΎΡΡ‚ΠΎΡ€ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ, Π½ΠΎ Π² нашСм случаС это прям ΠΎΡ‡Π΅Π½ΡŒ ΠΏΡ€ΠΈΠΊΠΎΠ»ΡŒΠ½Π°Ρ ΡˆΡ‚ΡƒΠΊΠ°.

Для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π» ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Π½Π° 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)

Π˜Ρ‚ΠΎΠ³ΠΎ

Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ внСдрСния скрипта, Π·Π° нСсколько мСсяцСв Π±Ρ‹Π» Π½Π°Π²Π΅Π΄Ρ‘Π½ ΠΈ поддСрТиваСтся порядок. Иногда Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½Ρ‹Π΅ Π’Πœ ΠΏΠΎΡΠ²Π»ΡΡŽΡ‚ΡΡ, Π½ΠΎ скрипт слуТит Π½Π΅ΠΏΠ»ΠΎΡ…ΠΈΠΌ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π½ΠΈΠ΅ΠΌ ΠΈ рСдкая Π’Πœ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² список 2 дня подряд.

Π’Π°ΠΊΠΆΠ΅ Π±Ρ‹Π» сдСлан Π·Π°Π΄Π΅Π» Π½Π° Π°Π½Π°Π»ΠΈΠ· историчСских Π΄Π°Π½Π½Ρ‹Ρ….

ΠŸΠΎΠ½ΡΡ‚Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠ΅ ΠΈΠ· этого ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ "Π½Π° ΠΊΠΎΠ»Π΅Π½ΠΊΠ΅", Π° ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒΠ½Ρ‹ΠΌ ПО, Π½ΠΎ Π·Π°Π΄Π°Ρ‡Π° Π±Ρ‹Π»Π° интСрСсной ΠΈ, ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ, Ρ„Π°ΠΊΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ.

R Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠΉ Ρ€Π°Π· ΠΏΠΎΠΊΠ°Π·Π°Π» сСбя прСкрасным ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Ρ‹ΠΌ языком, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСкрасно ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ статистичСских Π·Π°Π΄Π°Ρ‡, Π½ΠΎ ΠΈ выступаСт прСкрасной "ΠΏΡ€ΠΎΠΊΠ»Π°Π΄ΠΊΠΎΠΉ" ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ источниками Π΄Π°Π½Π½Ρ‹Ρ….

Π•ΠΆΠ΅Π΄Π½Π΅Π²Π½Ρ‹Π΅ ΠΎΡ‚Ρ‡Ρ‘Ρ‚Ρ‹ ΠΏΠΎ ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ R ΠΈ PowerShell

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com