Cov ntawv ceeb toom txhua hnub txog kev noj qab haus huv ntawm cov tshuab virtual siv R thiab PowerShell

Cov ntawv ceeb toom txhua hnub txog kev noj qab haus huv ntawm cov tshuab virtual siv R thiab PowerShell

nkag

Nyob zoo tav su. Rau ib nrab xyoo tam sim no peb tau khiav ib tsab ntawv (lossis ib txheej ntawm cov ntawv sau) uas tsim cov ntawv ceeb toom ntawm cov xwm txheej ntawm cov tshuab virtual (thiab tsis yog xwb). Kuv txiav txim siab los qhia kuv qhov kev paub tsim thiab tus lej nws tus kheej. Kuv cia siab rau kev thuam thiab tias cov khoom no yuav pab tau rau ib tug neeg.

Tsim kom muaj kev xav tau

Peb muaj ntau lub tshuab virtual (txog 1500 VMs faib thoob 3 vCenters). Cov tshiab raug tsim thiab cov qub raug tshem tawm ntau zaus. Txhawm rau tswj hwm kev txiav txim, ntau qhov kev cai tau ntxiv rau vCenter los faib VMs rau hauv Subsystems, qhia seb lawv puas yog cov xeem, thiab los ntawm leej twg thiab thaum twg lawv tsim. Tib neeg qhov tseem ceeb tau coj mus rau qhov tseeb tias ntau tshaj li ib nrab ntawm cov tshuab tau tso tseg nrog thaj chaw dawb huv, uas nyuaj rau kev ua haujlwm. Ib zaug txhua rau lub hlis, ib tug neeg freaked tawm thiab pib ua hauj lwm ntawm kev hloov kho cov ntaub ntawv no, tab sis qhov tshwm sim tsis muaj feem cuam tshuam tom qab ib lub lim tiam thiab ib nrab.
Cia kuv qhia tam sim ntawd tias txhua tus neeg nkag siab tias yuav tsum muaj cov ntawv thov rau kev tsim cov tshuab, txheej txheem rau lawv cov kev tsim, thiab lwm yam. thiab lwm yam. Thiab tib lub sijhawm, txhua tus neeg ua raws li cov txheej txheem no thiab txhua yam nyob rau hauv kev txiav txim. Hmoov tsis zoo, qhov no tsis yog qhov teeb meem ntawm no, tab sis qhov no tsis yog lub ntsiab lus ntawm tsab xov xwm :)

Feem ntau, qhov kev txiav txim siab tau ua kom automate xyuas qhov tseeb ntawm kev sau hauv cov teb.
Peb tau txiav txim siab tias tsab ntawv niaj hnub nrog cov npe ntawm cov tshuab tsis raug rau txhua tus engineers thiab lawv cov thawj coj yuav yog qhov pib zoo.

Lub sijhawm no, ib tus ntawm kuv cov npoj yaig twb tau siv tsab ntawv hauv PowerShell, uas txhua hnub, raws li lub sijhawm, tau sau cov ntaub ntawv ntawm txhua lub tshuab ntawm txhua lub vCenters thiab tsim 3 csv cov ntaub ntawv (txhua rau nws tus kheej vCenter), uas tau muab tso rau hauv. ib tug common disk. Nws tau txiav txim siab los coj tsab ntawv no los ua lub hauv paus thiab ntxiv nrog cov tshev uas siv R hom lus, uas peb muaj qee qhov kev paub.

Nyob rau hauv cov txheej txheem ntawm kev ua tiav, cov kev daws teeb meem tau txais cov ntaub ntawv los ntawm kev xa ntawv, cov ntaub ntawv nrog cov lus tseem ceeb thiab keeb kwm (ntxiv rau qhov no tom qab), nrog rau kev tshuaj xyuas ntawm vSphere cov cav kom pom cov neeg tsim ntawm vm thiab lub sijhawm ntawm lawv cov creation.

IDE RStudio Desktop thiab PowerShell ISE tau siv rau kev txhim kho.

Tsab ntawv yog launched los ntawm ib txwm Windows virtual tshuab.

Cov lus piav qhia ntawm cov logic dav dav.

Lub logic dav dav ntawm cov ntawv sau yog raws li hauv qab no.

  • Peb sau cov ntaub ntawv ntawm cov tshuab virtual siv PowerShell tsab ntawv, uas peb hu los ntawm R, thiab muab cov txiaj ntsig ua ke rau hauv ib qho csv. Kev sib cuam tshuam rov qab ntawm cov lus tau ua zoo ib yam. (nws muaj peev xwm tsav cov ntaub ntawv ncaj qha los ntawm R rau PowerShell hauv daim ntawv ntawm kev hloov pauv, tab sis qhov no yog qhov nyuaj, thiab muaj csvs nruab nrab ua rau nws yooj yim dua rau kev debug thiab qhia cov txiaj ntsig nruab nrab nrog ib tus neeg).
  • Siv R, peb tsim cov kev siv tsis tau rau cov teb uas nws qhov tseem ceeb peb tab tom kuaj xyuas. - Peb tab tom tsim cov ntaub ntawv lo lus uas yuav muaj cov txiaj ntsig ntawm cov teb no rau kev ntxig rau hauv tsab ntawv xov xwm, uas yuav yog cov lus teb rau cov lus nug ntawm cov npoj yaig "Tsis yog, tab sis kuv yuav ua li cas thiaj ua tau qhov no?"
  • Peb thauj cov ntaub ntawv rau tag nrho VMs los ntawm csv siv R, tsim ib dataframe, tshem tawm tsis tsim nyog teb thiab tsim ib cov ntaub ntawv xlsx cov ntaub ntawv uas yuav muaj cov ntsiab lus qhia rau tag nrho cov VMs, uas peb upload rau ib tug muab kev pab.
  • Peb siv tag nrho cov tshev rau qhov tseeb ntawm kev sau hauv cov teb rau cov ntaub ntawv rau tag nrho VMs thiab tsim ib lub rooj uas tsuas muaj VMs nrog cov teb tsis raug (thiab tsuas yog cov teb no xwb).
  • Peb xa cov txiaj ntsig ntawm VMs mus rau lwm tsab ntawv PowerShell, uas yuav saib vCenter cov cav rau VM tsim cov xwm txheej, uas yuav tso cai rau peb qhia txog lub sijhawm kwv yees ntawm kev tsim VM thiab tus tsim tsim. Qhov no yog rau rooj plaub thaum tsis muaj leej twg lees nws lub tsheb nws yog. Tsab ntawv no tsis ua haujlwm sai, tshwj xeeb tshaj yog tias muaj ntau lub cav, yog li peb tsuas yog saib ntawm 2 lub lis piam dhau los, thiab tseem siv cov kev ua haujlwm uas tso cai rau koj los tshawb nrhiav cov ntaub ntawv ntawm ntau VMs tib lub sijhawm. Tsab ntawv piv txwv muaj cov lus qhia ntxaws txog qhov txheej txheem no. Peb ntxiv qhov tshwm sim rau hauv csv, uas peb rov thauj mus rau R.
  • Peb tsim cov ntaub ntawv zoo nkauj xlsx uas tsis raug sau cov teb yuav raug qhia hauv liab, cov ntxaij lim dej yuav raug siv rau qee kab, thiab cov kab ntxiv uas muaj cov neeg tsim tsim thiab lub sijhawm tsim VM yuav raug qhia.
  • Peb tsim ib qho email, qhov twg peb xa cov ntaub ntawv piav qhia txog qhov tseem ceeb ntawm thaj chaw, nrog rau lub rooj uas tsis raug sau rau hauv cov teb. Hauv cov ntawv peb qhia tag nrho cov VMs tsim tsis raug, qhov txuas mus rau cov peev txheej sib koom thiab cov duab txhawb nqa. Yog tias tsis muaj VMs sau tsis raug, peb xa lwm tsab ntawv nrog daim duab txhawb siab zoo siab dua.
  • Peb sau cov ntaub ntawv rau tag nrho VMs nyob rau hauv SQL Server database, noj mus rau hauv tus account lub txheej txheem ntawm kev siv cov ntaub ntawv keeb kwm (ib tug heev nthuav mechanism - txog qhov twg ntau tom qab)

Tiag tiag scripts

Cov ntaub ntawv tseem ceeb R code

# Путь к рабочей директории (нужно для корректной работы через виндовый планировщик заданий)
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")

Tsab ntawv kom tau txais ib daim ntawv teev npe vm hauv 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
}

Ib tsab ntawv PowerShell uas rho tawm los ntawm cov ntawv teev cov neeg tsim cov tshuab virtual thiab hnub tsim lawv

# Путь к файлу, из которого будем доставать список 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"

Lub tsev qiv ntawv tsim nyog tshwj xeeb xlsx, uas ua rau nws muaj peev xwm ua rau cov ntawv txuas rau tsab ntawv kom meej meej formatted (raws li kev tswj hwm nyiam), thiab tsis yog lub rooj CSV nkaus xwb.

Tsim ib daim ntawv xlsx zoo nkauj nrog cov npe ntawm cov tshuab tsis raug

# Создаём новую книгу
# Возможные значения : "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)

Cov zis zoo li no:

Cov ntawv ceeb toom txhua hnub txog kev noj qab haus huv ntawm cov tshuab virtual siv R thiab PowerShell

Kuj tseem muaj qhov nthuav dav txog kev teeb tsa lub Windows teem caij. Nws yog tsis yooj yim sua kom nrhiav tau txoj cai thiab kev teeb tsa kom txhua yam yuav pib raws li nws yuav tsum tau ua. Raws li qhov tshwm sim, lub tsev qiv ntawv R tau pom, uas nws tus kheej tsim ib txoj haujlwm los tso tawm R tsab ntawv thiab tsis nco qab txog cov ntaub ntawv teev tseg. Tom qab ntawd koj tuaj yeem kho txoj haujlwm manually.

Ib daim R code nrog ob qho piv txwv uas tsim ib txoj haujlwm hauv 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)

Cais txog lub database

Tom qab teeb tsa tsab ntawv, lwm yam teeb meem pib tshwm. Piv txwv li, kuv xav nrhiav hnub uas VM raug tshem tawm, tab sis cov ntawv teev npe hauv vCenter twb dhau lawm. Txij li thaum tsab ntawv muab cov ntaub ntawv tso rau hauv ib lub nplaub tshev txhua hnub thiab tsis ntxuav nws (peb ntxuav nws nrog peb txhais tes thaum peb nco qab), koj tuaj yeem saib los ntawm cov ntaub ntawv qub thiab pom thawj cov ntaub ntawv uas VM no tsis nyob. Tab sis qhov ntawd tsis txias.

Kuv xav tsim cov ntaub ntawv keeb kwm.

Lub functionality ntawm MS SQL SERVER - system-versioned temporal rooj - tuaj cawm. Nws yog feem ntau txhais ua ib ntus (tsis yog ib ntus) rooj.

Koj tuaj yeem nyeem kom meej ntawm official Microsoft cov ntaub ntawv.

Nyob rau hauv luv luv, peb tsim ib lub rooj, hais tias peb yuav muaj nws nrog versioning, thiab SQL Server tsim 2 ntxiv datetime kab nyob rau hauv lub rooj no (hnub tsim cov ntaub ntawv thiab hnub tas sij hawm ntawm cov ntaub ntawv) thiab ib lub rooj ntxiv rau hauv uas hloov. yuav sau. Yog li ntawd, peb tau txais cov ntaub ntawv tshiab thiab, los ntawm cov lus nug yooj yim, cov piv txwv uas tau muab rau hauv cov ntaub ntawv, peb tuaj yeem pom lub neej voj voog ntawm lub tshuab virtual tshwj xeeb, lossis lub xeev ntawm tag nrho VMs ntawm ib qho chaw. hauv lub sijhawm.

Los ntawm kev pom kev ua tau zoo, kev sau ntawv mus rau lub rooj tseem ceeb yuav tsis ua tiav kom txog thaum kev sau ntawv mus rau lub rooj ib ntus ua tiav. Cov. ntawm cov ntxhuav nrog ntau tus sau ua haujlwm, qhov kev ua haujlwm no yuav tsum tau ua nrog ceev faj, tab sis nyob rau hauv peb cov ntaub ntawv nws yog qhov txias heev.

Txhawm rau kom cov txheej txheem ua haujlwm kom raug, kuv yuav tsum tau ntxiv ib qho me me ntawm cov lej hauv R uas yuav piv cov lus tshiab nrog cov ntaub ntawv rau tag nrho VMs nrog ib qho khaws cia hauv cov ntaub ntawv thiab sau tsuas yog hloov kab rau nws. Cov cai tsis yog tshwj xeeb tshaj yog ntse; nws siv lub tsev qiv ntawv sib piv DF, tab sis kuv tseem yuav nthuav tawm hauv qab no.

R code rau sau cov ntaub ntawv mus rau ib tug database

# Подцепляем пакеты
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)

Tag nrho

Raws li qhov tshwm sim ntawm kev ua raws li tsab ntawv, kev txiav txim tau rov qab los thiab tswj tsis pub dhau ob peb lub hlis. Qee lub sij hawm ua tsis raug VMs tshwm sim, tab sis tsab ntawv ua haujlwm ua ib qho kev ceeb toom zoo thiab VM tsis tshua tau nkag mus rau hauv cov npe rau 2 hnub ua ke.

Lub hauv paus tseem tau tsim los tshuaj xyuas cov ntaub ntawv keeb kwm.

Nws yog qhov tseeb tias ntau qhov no tuaj yeem siv tsis tau ntawm lub hauv caug, tab sis nrog cov software tshwj xeeb, tab sis txoj haujlwm tau nthuav dav thiab, ib tus yuav hais tias, xaiv tau.

R tau rov qhia nws tus kheej ua ib yam lus zoo thoob ntiaj teb, uas yog qhov zoo tshaj plaws tsis yog rau kev daws teeb meem kev txheeb cais, tab sis kuj ua raws li "txheej" zoo ntawm lwm cov ntaub ntawv.

Cov ntawv ceeb toom txhua hnub txog kev noj qab haus huv ntawm cov tshuab virtual siv R thiab PowerShell

Tau qhov twg los: www.hab.com

Ntxiv ib saib