Litlaleho tsa letsatsi le letsatsi ka bophelo bo botle ba mechini ea sebele e sebelisang R le PowerShell

Litlaleho tsa letsatsi le letsatsi ka bophelo bo botle ba mechini ea sebele e sebelisang R le PowerShell

ho kena

Lumelang. Ka halofo ea selemo joale re ntse re tsamaisa script (kapa ho e-na le sete sa mangolo) se hlahisang litlaleho ka boemo ba mechine ea sebele (eseng feela). Ke entse qeto ea ho arolelana phihlelo ea ka ea pōpo le khoutu ka boeona. Ke na le tšepo ea ho nyatsoa le hore boitsebiso bona bo ka ba molemo ho motho e mong.

Sebopeho sa tlhoko

Re na le mechini e mengata ea sebele (e ka bang 1500 VM e ajoa ho li-vCenters tse 3). Tse ncha lia etsoa 'me tsa khale li hlakoloa hangata. Ho boloka taolo, likarolo tse 'maloa tsa moetlo li kentsoe ho vCenter ho arola li-VM ho li-subsystems, ho bonts'a hore na ke tsa liteko, le hore na li entsoe ke mang le neng. Lebaka la batho le ile la lebisa tabeng ea hore karolo e fetang halofo ea mechine e ne e siiloe ka masimo a se nang letho, e leng se ileng sa thatafatsa mosebetsi. Hang ka mor'a likhoeli tse ling le tse ling tse tšeletseng, motho e mong o ile a tsieleha 'me a qala ho sebetsa ho ntlafatsa lintlha tsena, empa sephetho se ile sa khaotsa ho sebetsa ka mor'a beke le halofo.
E re ke hlakise hang-hang hore motho e mong le e mong oa utloisisa hore ho tlameha ho be le likopo tsa ho theha mechini, mokhoa oa ho bopa, joalo-joalo. joalo joalo. Mme ka nako e ts'oanang, motho e mong le e mong o latela ts'ebetso ena ka tieo mme tsohle li lokile. Ka bomalimabe, ha ho joalo mona, empa sena ha se taba ea sengoloa :)

Ka kakaretso, ho ile ha etsoa qeto ea ho iketsetsa ho hlahloba ho nepahala ha ho tlatsa masimo.
Re ile ra etsa qeto ea hore lengolo la letsatsi le letsatsi le nang le lethathamo la mechine e tlatsitsoeng ka phoso ho lienjineri tsohle tse ikarabellang le baokameli ba bona e tla ba qalo e ntle.

Ka nako ena, e mong oa basebetsi-'moho le 'na o ne a se a kentse script ho PowerShell, eo letsatsi le leng le le leng, ho ea ka kemiso, e neng e bokella tlhahisoleseding ka mechine eohle ea li-vCenters' me a hlahisa litokomane tsa 3 csv (e 'ngoe le e' ngoe bakeng sa vCenter ea eona), e neng e kenngoa ho disk e tloaelehileng. Ho ile ha etsoa qeto ea ho nka mongolo ona e le motheo le ho o tlatselletsa ka licheke ho sebelisa puo ea R, eo re bileng le boiphihlelo ka eona.

Ha ho ntse ho phetheloa, tharollo e ile ea fumana tlhahisoleseding ka poso, database e nang le tafole e kholo le ea histori (ho feta ka sena hamorao), hammoho le tlhahlobo ea li-logs tsa vSphere ho fumana baetsi ba sebele ba vm le nako ea pōpo ea bona.

IDE RStudio Desktop le PowerShell ISE li ne li sebelisetsoa nts'etsopele.

Script e qalisoa ho tloha mochine o tloaelehileng oa Windows.

Tlhaloso ea logic e akaretsang.

Tlhaloso e akaretsang ea lingoloa ke e latelang.

  • Re bokella lintlha ka mechini ea sebele re sebelisa mongolo oa PowerShell, oo re o bitsang ka R, ebe o kopanya sephetho ho csv e le 'ngoe. Tšebelisano e fapaneng lipakeng tsa lipuo e etsoa ka mokhoa o ts'oanang. (ho ne ho ka khoneha ho khanna data ka ho toba ho tloha ho R ho ea ho PowerShell ka mokhoa oa mefuta-futa, empa sena se thata, 'me ho ba le li-csv tse mahareng ho etsa hore ho be bonolo ho lokisa le ho arolelana liphetho tsa lipakeng le motho e mong).
  • Re sebelisa R, re theha liparamente tse sebetsang bakeng sa masimo ao re a hlahlobang litekanyetso tsa tsona. - Re theha tokomane ea mantsoe e tla ba le boleng ba likarolo tsena bakeng sa ho kenngoa lengolong la tlhahisoleseling, e tla ba karabo ea lipotso tsa basebetsi mmoho "Che, empa ke tla tlatsa see joang?"
  • Re kenya data bakeng sa li-VM tsohle ho tsoa ho csv re sebelisa R, re theha dataframe, re tlosa libaka tse sa hlokahaleng mme re theha tokomane ea xlsx ea tlhahisoleseling e tla ba le tlhaiso-leseling ea kakaretso bakeng sa li-VM tsohle, tseo re li kenyang mohloling o arolelanoang.
  • Re sebelisa licheke tsohle bakeng sa ho nepahala ha ho tlatsa masimo ho dataframe bakeng sa li-VM tsohle mme re theha tafole e nang le li-VM feela tse nang le masimo a tlatsitsoeng ka phoso (le masimo ana feela).
  • Re romela lethathamo le hlahang la li-VM ho mongolo o mong oa PowerShell, o tla sheba lits'oants'o tsa vCenter bakeng sa liketsahalo tsa pōpo ea VM, e leng se tla re lumella ho bontša nako e hakantsoeng ea pōpo ea VM le moetsi ea reriloeng. Sena ke sa nyeoe ha ho se motho ea lumelang hore na koloi ke ea mang. Script ena ha e sebetse ka potlako, haholo-holo haeba ho na le li-log tse ngata, kahoo re sheba feela libeke tsa ho qetela tsa 2, hape re sebelisa mokhoa oa ho sebetsa o u lumellang ho batla tlhahisoleseding ho li-VM tse 'maloa ka nako e le' ngoe. Mohlala oa script o na le litlhaloso tse qaqileng ka mochine ona. Re kenya sephetho ho csv, eo re e kenyang hape ho R.
  • Re hlahisa tokomane e hlophisitsoeng hantle ea xlsx eo ho eona likarolo tse tlatsitsoeng ka phoso li tla totobatsoa ka bofubelu, li-filters li tla sebelisoa ho likholomo tse ling, 'me ho tla bontšoa likholomo tse ling tse nang le baqapi ba reriloeng le nako ea tlhahiso ea VM.
  • Re hlahisa lengolo-tsoibila, moo re hokelang tokomane e hlalosang boleng ba tšimo e nepahetseng, hammoho le tafole e nang le likarolo tse sa tlatsoang hantle. Mongolong re bonts'a palo eohle ea li-VM tse entsoeng ka phoso, sehokelo sa sesebelisoa se arolelanoang le setšoantšo se khothatsang. Haeba ho se na li-VM tse tlatsitsoeng ka phoso, re romella lengolo le leng le nang le setšoantšo se khothatsang haholoanyane.
  • Re rekota datha bakeng sa li-VM tsohle sebakeng sa polokelo ea SQL Server, re ela hloko mokhoa o kentsoeng ts'ebetsong oa litafole tsa nalane (mochine o khahlisang haholo - oo hamorao o tla feta)

Ha e le hantle mangolo

Main R khoutu faele

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

Script bakeng sa ho fumana lethathamo la vm ho 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
}

Sengoloa sa PowerShell se ntšitseng ho li-log baqapi ba metjhini ea sebele le letsatsi leo ba e entseng ka eona

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

Laebrari e lokeloa ke tlhokomelo e khethehileng xlsx, e entseng hore ho khonehe ho etsa hore sephutheloana sa lengolo se hlophisehe ka ho hlaka (joalokaha batsamaisi ba rata), eseng feela tafole ea CSV.

Ho hlahisa tokomane e ntle ea xlsx e nang le lethathamo la mochini o tlatsitsoeng ka phoso

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

Sephetho se shebahala tjena:

Litlaleho tsa letsatsi le letsatsi ka bophelo bo botle ba mechini ea sebele e sebelisang R le PowerShell

Ho ne ho boetse ho na le nuance e khahlisang mabapi le ho theha Windows scheduler. Ho ne ho sa khonehe ho fumana litokelo le litlhophiso tse nepahetseng e le hore ntho e 'ngoe le e' ngoe e qale kamoo e lokelang ho qala kateng. Ka lebaka leo, laebrari ea R e ile ea fumanoa, e leng eona e etsang mosebetsi oa ho qala R script mme ha e lebale le ka faele ea log. Joale o ka lokisa mosebetsi ka letsoho.

Karolo ea R khoutu e nang le mehlala e 'meli e hlahisang mosebetsi ho 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)

Ka thoko mabapi le database

Kamora ho theha script, litaba tse ling li ile tsa qala ho hlaha. Ka mohlala, ke ne ke batla ho fumana letsatsi leo VM e hlakotsoeng ka lona, ​​​​empa lifate tsa vCenter li ne li se li tsofetse. Kaha script e beha lifaele ka har'a foldara letsatsi le leng le le leng 'me ha e e hloekise (re e hloekisa ka matsoho ha re hopola), u ka sheba lifaele tsa khale' me u fumane faele ea pele eo VM ena e seng teng. Empa seo ha se monate.

Ke ne ke batla ho theha pokello ea nalane ea nalane.

Ts'ebetso ea MS SQL SERVER - tafole ea temporal e fetoletsoeng - e ile ea thusa. Hangata e fetoleloa e le litafole tsa nakoana (eseng tsa nakoana).

U ka bala ka ho qaqileng ho litokomane tsa molao tsa Microsoft.

Ka bokhutšoanyane, re theha tafole, re re re tla ba le eona ka phetolelo, 'me SQL Server e theha litšiea tse ling tsa 2 tafoleng ena (letsatsi leo rekoto e entsoeng ka lona le letsatsi la ho fela ha tlaleho) le tafole e eketsehileng eo ho eona liphetoho li fetohang. e tla ngoloa. Ka lebaka leo, re fumana lintlha tsa morao-rao, 'me, ka lipotso tse bonolo, tseo mehlala ea tsona e fanoeng litokomaneng, re ka bona bophelo ba mochine o itseng oa sebele, kapa boemo ba li-VM tsohle ka nako e itseng. ka nako.

Ho ea ka pono ea ts'ebetso, transaction ea ho ngola ho ea tafoleng e kholo e ke ke ea phethoa ho fihlela transaction ea ho ngola ho ea tafoleng ea nakoana e phethoa. Tseo. litafoleng tse nang le palo e kholo ea mesebetsi ea ho ngola, ts'ebetso ena e lokela ho kenngoa ts'ebetsong ka hloko, empa molemong oa rona ke ntho e ntle haholo.

E le hore mochine o sebetse ka mokhoa o nepahetseng, ke ne ke tlameha ho kenya khoutu e nyenyane ho R e neng e tla bapisa tafole e ncha le data bakeng sa li-VM tsohle le e bolokiloeng polokelong ea boitsebiso le ho ngola mela e fetotsoeng feela ho eona. Khoutu ha e bohlale haholo; e sebelisa laeborari ea bapisa eaDF, empa ke tla e hlahisa ka tlase.

R khoutu ea ho ngola data ho 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)

Kakaretso

Ka lebaka la ts'ebetsong ea script, taelo e ile ea tsosolosoa 'me ea bolokoa ka mor'a likhoeli tse seng kae. Ka linako tse ling ho hlaha li-VM tse tlatsitsoeng ka phoso, empa mongolo o sebetsa e le khopotso e ntle mme VM e sa tloaelehang e kena lenaneng matsatsi a 2 ka tatellano.

Ho ile ha boela ha etsoa motheo oa ho hlahloba lintlha tsa histori.

Ho hlakile hore boholo ba sena bo ka kenngoa ts'ebetsong eseng ka lengole, empa ka software e khethehileng, empa mosebetsi o ne o thahasellisa 'me, motho a ka re, ka boikhethelo.

R e boetse e iponahalitse e le puo e babatsehang ea bokahohle, e phethahetseng eseng feela bakeng sa ho rarolla mathata a lipalo-palo, empa hape e sebetsa e le "lera" e babatsehang pakeng tsa mehloli e meng ea data.

Litlaleho tsa letsatsi le letsatsi ka bophelo bo botle ba mechini ea sebele e sebelisang R le PowerShell

Source: www.habr.com

Eketsa ka tlhaloso