Akụkọ kwa ụbọchị gbasara ahụike igwe mebere na-eji R na PowerShell

Akụkọ kwa ụbọchị gbasara ahụike igwe mebere na-eji R na PowerShell

entry

Ehihie ọma. Ruo ọkara afọ ugbu a, anyị na-agba ọsọ edemede (ma ọ bụ kama otu edemede) nke na-ewepụta akụkọ banyere ọnọdụ igwe mebere (ọ bụghị naanị). Ekpebiri m ịkọrọ ahụmịhe okike m na koodu n'onwe ya. Enwere m olileanya maka nkatọ yana na ihe a nwere ike ịbara mmadụ uru.

Nhazi nke mkpa

Anyị nwere ọtụtụ igwe mebere (ihe dịka 1500 VM kesara gafee 3 vCenters). A na-emepụta ndị ọhụrụ, a na-ehichapụkwa ndị ochie ọtụtụ mgbe. Iji dowe usoro, agbakwunyere ọtụtụ ubi omenala na vCenter iji kewaa VM ka ọ bụrụ Sistemụ Sistemụ, gosi ma ha bụ ndị nwalere, yana onye na mgbe e kere ha. Ihe na-akpata mmadụ mere ka eziokwu ahụ bụrụ na ihe karịrị ọkara nke igwe na-ahapụ oghere oghere, nke na-eme ka ọrụ ahụ sie ike. Otu ugboro n'ọnwa isii ọ bụla, mmadụ na-ama jijiji wee malite ịrụ ọrụ na-emelite data a, mana nsonaazụ ahụ kwụsịrị ịdị mkpa mgbe otu izu na ọkara gasịrị.
Ka m dokwuo anya ozugbo na onye ọ bụla ghọtara na a ghaghị inwe ngwa maka ịmepụta igwe, usoro maka ịmepụta ha, wdg. were gabazie. Ma n'otu oge ahụ, onye ọ bụla na-agbaso usoro a na ihe niile dị n'usoro. N'ụzọ dị mwute, nke a abụghị ikpe ebe a, mana nke a abụghị isiokwu nke isiokwu :)

N'ozuzu, e mere mkpebi ka akpaaka ịlele izi ezi nke njuputa n'ubi.
Anyị kpebiri na akwụkwọ ozi kwa ụbọchị nwere ndepụta igwe anaghị ezighi ezi nye ndị injinia niile nwere ọrụ na ndị isi ha ga-abụ mmalite dị mma.

N'oge a, otu n'ime ndị ọrụ ibe m emejuputalarị edemede na PowerShell, nke kwa ụbọchị, dị ka usoro nhazi, na-anakọta ozi na igwe niile nke vCenters niile wee mepụta akwụkwọ csv 3 (nke ọ bụla maka vCenter nke ya), nke a na-ebugo na ya. diski nkịtị. E kpebiri iwere edemede a dị ka ntọala wee tinye ya na ndenye ego site na iji asụsụ R, nke anyị nwere ahụmahụ.

N'ime usoro nke imecha, ihe ngwọta ahụ nwetara ozi site na mail, nchekwa data nwere isi na tebụl akụkọ ihe mere eme (karịa na nke a mechara), yana nyocha nke vSphere logs iji chọta ndị na-emepụta vm n'ezie na oge e kere ha.

Ejiri IDE RStudio Desktop na PowerShell ISE maka mmepe.

Ewepụtara edemede ahụ site na igwe mebere Windows oge niile.

Nkọwa nke izugbe mgbagha.

Echiche izugbe nke script dị ka ndị a.

  • Anyị na-anakọta data na igwe mebere site na iji edemede PowerShell, nke anyị na-akpọ site na R, wee jikọta nsonaazụ ya n'otu csv. A na-eme mgbanwe mgbanwe n'etiti asụsụ n'otu aka ahụ. (ọ ga-ekwe omume ịbuba data ozugbo site na R gaa na PowerShell n'ụdị mgbanwe, mana nke a siri ike, yana inwe csvs etiti na-eme ka ọ dị mfe ịmegharị na ịkekọrịta nsonaazụ etiti na mmadụ).
  • Iji R, anyị na-etolite paramita dị mma maka mpaghara ndị ụkpụrụ anyị na-enyocha. - Anyị na-eke akwụkwọ okwu nke ga-enwe ụkpụrụ nke mpaghara ndị a maka itinye n'ime leta ozi, nke ga-abụ azịza nye ajụjụ ndị ọrụ ibe "Ee e, mana olee otu m ga-esi mejupụta nke a?"
  • Anyị na-ebufe data maka VM niile site na csv site na iji R, mepụta dataframe, wepụ ubi na-adịghị mkpa wee mepụta akwụkwọ xlsx ozi nke ga-enwe ozi nchịkọta maka VM niile, nke anyị na-ebugote na akụrụngwa nkekọrịta.
  • Anyị na-etinye nlele niile maka izi ezi nke njuputa n'ọhịa na dataframe maka VM niile wee mepụta tebụl nwere naanị VM nwere oghere na-ezighi ezi (na naanị mpaghara ndị a).
  • Anyị na-eziga ndepụta VM ga-esi na ya pụta na edemede PowerShell ọzọ, nke ga-eleba anya na vCenter logs maka ihe omume okike VM, nke ga-enye anyị ohere igosi oge atụmatụ nke okike nke VM na onye okike zubere. Nke a bụ maka ikpe mgbe ọ nweghị onye na-anabata ụgbọ ala onye ọ bụ. Edemede a anaghị arụ ọrụ ngwa ngwa, ọkachasị ma ọ bụrụ na enwere ọtụtụ ndekọ, yabụ anyị na-ele naanị izu 2 ikpeazụ, ma na-ejikwa usoro ọrụ na-enye gị ohere ịchọ ozi na ọtụtụ VM n'otu oge. Edemede ihe atụ nwere nkọwa zuru ezu gbasara usoro a. Anyị na-agbakwunye nsonaazụ ya na csv, nke anyị na-etinye ọzọ na R.
  • Anyị na-emepụta akwụkwọ xlsx a haziri nke ọma nke a ga-egosipụta n'ubi na-ezighi ezi na-acha uhie uhie, a ga-etinye ihe nzacha na kọlụm ụfọdụ, yana kọlụm ndị ọzọ nwere ndị okike e bu n'obi na oge ịmepụta VM ga-egosi.
  • Anyị na-ewepụta ozi-e, ebe anyị na-agbakwunye akwụkwọ na-akọwa ụkpụrụ ubi dị mma, yana tebụl nke jupụtara n'ubi na-ezighi ezi. N'edemede a anyị na-egosi ọnụọgụ VM emepụtara ezighi ezi, njikọ nke akụrụngwa na-ekekọrịta na foto mkpali. Ọ bụrụ na enweghị VM ezughị oke, anyị na-eziga leta ọzọ nwere foto mkpali obi ụtọ karịa.
  • Anyị na-edekọ data maka VM niile na nchekwa data SQL Server, na-eburu n'uche usoro etinyere nke tebụl akụkọ ihe mere eme (usoro na-atọ ụtọ nke ukwuu - nke ọzọ mechara)

N'ezie scripts

Isi faịlụ koodu 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")

Ederede maka ịnweta ndepụta vm na 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
}

Edemede PowerShell nke na-ewepụta n'ime ndekọ ndị mepụtara igwe mebere na ụbọchị emere ha

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

Ọbá akwụkwọ ahụ kwesịrị nlebara anya pụrụ iche xlsx, nke mere ka o kwe omume ime ka ntinye aka na leta ahụ ahazi nke ọma (dị ka njikwa mmasị), ọ bụghị naanị tebụl CSV.

Na-emepụta akwụkwọ xlsx mara mma nke nwere ndepụta nke igwe mejuru ezighi ezi

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

Nsonaazụ a dị ka nke a:

Akụkọ kwa ụbọchị gbasara ahụike igwe mebere na-eji R na PowerShell

Enwekwara ihe na-adọrọ mmasị gbasara ịtọ ntọala Windows. Ọ gaghị ekwe omume ịchọta ikike na ntọala ziri ezi ka ihe niile wee malite dịka o kwesịrị. N'ihi ya, a chọtara ọbá akwụkwọ R, nke n'onwe ya na-emepụta ọrụ iji malite edemede R ma ghara ichefu banyere faịlụ log. Mgbe ahụ ị nwere ike iji aka dozie ọrụ ahụ.

Mpempe koodu R nwere ihe atụ abụọ na-emepụta ọrụ na Nhazi 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)

Iche iche banyere nchekwa data

Mgbe ịtọlitechara edemede ahụ, nsogbu ndị ọzọ malitere ịpụta. Dịka ọmụmaatụ, achọrọ m ịchọta ụbọchị mgbe ehichapụrụ VM, mana ndekọ na vCenter agwụlarị. Ebe ọ bụ na script na-etinye faịlụ na nchekwa kwa ụbọchị ma ghara ihicha ya (anyị na-eji aka anyị na-ehicha ya mgbe anyị chetara), ị nwere ike lelee faịlụ ochie wee chọta faịlụ mbụ nke VM a na-anọghị. Mana nke ahụ adịghị mma.

Achọrọ m ịmepụta nchekwa data akụkọ ihe mere eme.

Ọrụ MS SQL SERVER - tebulu nwa oge nwere ụdị sistemụ - bịara napụta. A na-atụgharịkarị ya ka tebụl nwa oge (ọ bụghị nwa oge).

Ị nwere ike ịgụ n'ụzọ zuru ezu na akwụkwọ Microsoft gọọmentị.

Na nkenke, anyị na-emepụta tebụl, na-ekwu na anyị ga-enwe ya na nsụgharị, na SQL Server na-emepụta 2 ọzọ kọlụm datetime na tebụl a (ụbọchị e kere ihe ndekọ ahụ na ụbọchị njedebe nke ndekọ) na tebụl ọzọ nke mgbanwe. a ga-ede. N'ihi ya, anyị na-enweta ozi ọhụrụ na, site na ajụjụ ndị dị mfe, ihe atụ nke e nyere na akwụkwọ ahụ, anyị nwere ike ịhụ ma ọ bụ usoro ndụ nke otu igwe mebere, ma ọ bụ ọnọdụ VM niile n'otu oge. n'oge.

Site n'echiche arụmọrụ, azụmahịa ederede na tebụl bụ isi agaghị emecha ruo mgbe ederede ederede na tebụl nwa oge ga-agwụ. Ndị ahụ. na tebụl nwere ọnụ ọgụgụ buru ibu nke ọrụ ide ihe, a ga-eji nlezianya rụọ ọrụ a, ma n'ọnọdụ anyị ọ bụ ihe dị mma n'ezie.

Ka usoro ahụ wee rụọ ọrụ nke ọma, ekwesịrị m ịgbakwunye obere koodu na R nke ga-eji tebụl ọhụrụ tụnyere data maka VM niile na nke echekwara na nchekwa data wee dee naanị ahịrị gbanwere na ya. Koodu adịghị akọ nke ọma; ọ na-eji ọba akwụkwọ atụnyere DF, mana m ga-egosikwa ya n'okpuru.

Koodu R maka ide data na nchekwa data

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

Ọnụ

N'ihi mmejuputa nke edemede ahụ, eweghachiri ma debe usoro n'ime ọnwa ole na ole. Mgbe ụfọdụ VM jupụtara na-ezighi ezi na-apụta, mana edemede ahụ na-arụ ọrụ dị ka ezigbo ncheta yana VM na-adịghị ahụkebe na-abanye na ndepụta ahụ maka ụbọchị 2 n'usoro.

Emekwara ntọala maka nyocha data akụkọ ihe mere eme.

O doro anya na ọtụtụ n'ime ihe ndị a nwere ike ime ka ọ bụghị na ikpere, ma na ngwanrọ pụrụ iche, ma ọrụ ahụ bụ ihe na-adọrọ mmasị na, otu onye nwere ike ịsị, nhọrọ.

R egosila ọzọ na ọ bụ asụsụ zuru ụwa ọnụ magburu onwe ya, nke zuru oke ọ bụghị nanị maka idozi nsogbu ndekọ ọnụ ọgụgụ, ma na-arụkwa ọrụ dị ka "oyi akwa" magburu onwe ya n'etiti isi mmalite data ndị ọzọ.

Akụkọ kwa ụbọchị gbasara ahụike igwe mebere na-eji R na PowerShell

isi: www.habr.com

Tinye a comment