Aithisgean làitheil air slàinte innealan brìgheil a ’cleachdadh R agus PowerShell

Aithisgean làitheil air slàinte innealan brìgheil a ’cleachdadh R agus PowerShell

Clàrachadh

Feasgar math. Airson leth-bhliadhna a-nis tha sinn air a bhith a’ ruith sgriobt (no an àite seata de sgriobtaichean) a ghineas aithisgean air inbhe innealan brìgheil (agus chan ann a-mhàin). Cho-dhùin mi an t-eòlas cruthachaidh agam agus an còd fhèin a cho-roinn. Tha mi an dòchas càineadh agus gum faodadh an stuth seo a bhith feumail do chuideigin.

Cruthachadh feum

Tha tòrr innealan brìgheil againn (timcheall air 1500 VM air an sgaoileadh thairis air 3 vCenters). Thèid feadhainn ùra a chruthachadh agus thèid seann fheadhainn a dhubhadh às gu math tric. Gus òrdugh a chumail, chaidh grunn raointean gnàthaichte a chur ri vCenter gus VMn a roinn ann an Subsystems, comharrachadh an e feadhainn deuchainn a th’ annta, agus cò leis agus cuin a chaidh an cruthachadh. Dh'adhbhraich am bàillidh daonna gu robh còrr air leth de na h-innealan air am fàgail le raointean bàn, a bha a’ dèanamh an obair iom-fhillte. Aon uair gach sia mìosan, chaidh cuideigin a-mach agus thòisich e ag obair air an dàta seo ùrachadh, ach sguir an toradh a bhith buntainneach às deidh seachdain gu leth.
Leig leam soilleireachadh anns a ’bhad gu bheil a h-uile duine a’ tuigsinn gum feum tagraidhean a bhith ann airson innealan a chruthachadh, pròiseas airson an cruthachadh, msaa. Agus mar sin air adhart. Agus aig an aon àm, tha a h-uile duine gu cruaidh a 'leantainn a' phròiseas seo agus tha a h-uile dad ann an òrdugh. Gu mì-fhortanach, chan eil seo fìor an seo, ach chan e seo cuspair an artaigil :)

San fharsaingeachd, chaidh co-dhùnadh fèin-ghluasad a dhèanamh air ceartachd lìonadh nan raointean.
Cho-dhùin sinn gum biodh litir làitheil le liosta de dh’ innealan air an lìonadh gu ceàrr gu gach innleadair cunntachail agus an ceannardan na thoiseach tòiseachaidh math.

Aig an ìre seo, bha aon de mo cho-obraichean air sgriobt a chuir an gnìomh mar-thà ann an PowerShell, a chruinnich a h-uile latha, a rèir clàr-ama, fiosrachadh air a h-uile inneal de gach vCenters agus a chruthaich 3 sgrìobhainnean csv (gach fear airson an vCenter aige fhèin), a chaidh a luchdachadh suas gu diosc cumanta. Chaidh co-dhùnadh an sgriobt seo a ghabhail mar bhunait agus cuir ris le sgrùdaidhean a’ cleachdadh a’ chànan R, leis an robh beagan eòlais againn.

Anns a 'phròiseas crìochnachaidh, fhuair am fuasgladh fiosrachadh tron ​​​​phost, stòr-dàta le prìomh chlàr eachdraidheil (barrachd air seo nas fhaide air adhart), a bharrachd air mion-sgrùdadh air logaichean vSphere gus fìor luchd-cruthachaidh vm a lorg agus àm an cruthachaidh.

Chaidh IDE RStudio Desktop agus PowerShell ISE a chleachdadh airson leasachadh.

Tha an sgriobt air a chuir air bhog bho inneal brìgheil Windows àbhaisteach.

Tuairisgeul coitcheann logic.

Tha loidsig coitcheann nan sgriobtaichean mar a leanas.

  • Bidh sinn a’ cruinneachadh dàta air innealan brìgheil a’ cleachdadh sgriobt PowerShell, a chanas sinn tro R, agus a’ cothlamadh an toradh ann an aon csv. Tha an eadar-obrachadh cùil eadar cànanan air a dhèanamh san aon dòigh. (Bha e comasach dàta a dhràibheadh ​​​​gu dìreach bho R gu PowerShell ann an cruth caochladairean, ach tha seo duilich, agus le csvs eadar-mheadhanach ga dhèanamh nas fhasa toraidhean eadar-mheadhanach a dheasbad agus a cho-roinn le cuideigin).
  • A’ cleachdadh R, bidh sinn a’ cruthachadh pharamadairean dligheach airson nan raointean aig a bheil luachan a tha sinn a’ sgrùdadh. - Tha sinn a’ cruthachadh sgrìobhainn facal anns am bi luachan nan raointean sin airson a chuir a-steach don litir fiosrachaidh, a bhios mar fhreagairt do cheistean cho-obraichean “Chan eil, ach ciamar a bu chòir dhomh seo a lìonadh?”
  • Bidh sinn a’ luchdachadh dàta airson a h-uile VM bho csv a’ cleachdadh R, a’ cruthachadh frèam dàta, a’ toirt air falbh raointean neo-riatanach agus a’ cruthachadh sgrìobhainn xlsx fiosrachaidh anns am bi fiosrachadh geàrr-chunntas airson a h-uile VM, a luchdaicheas sinn suas gu goireas co-roinnte.
  • Bidh sinn a’ cur a h-uile seic an sàs airson ceartachd lìonadh nan raointean ris an dataframe airson a h-uile VM agus cruthaichidh sinn clàr anns nach eil ach VMan le raointean air an lìonadh gu ceàrr (agus dìreach na raointean sin).
  • Bidh sinn a’ cur an liosta de VM a thig às gu sgriobt PowerShell eile, a choimheadas air na logaichean vCenter airson tachartasan cruthachaidh VM, a leigeas leinn an ùine tuairmseach airson cruthachadh an VM agus an neach-cruthachaidh a chomharrachadh. Tha seo fìor nuair nach eil duine ag aideachadh cò an càr a th’ ann. Chan obraich an sgriobt seo gu sgiobalta, gu sònraichte ma tha tòrr logaichean ann, agus mar sin cha bhith sinn a’ coimhead ach air na seachdainean 2 mu dheireadh, agus cuideachd a ’cleachdadh sruth-obrach a leigeas leat fiosrachadh a lorg air grunn VM aig an aon àm. Anns an sgriobt eisimpleir tha beachdan mionaideach air an uidheamachd seo. Cuiridh sinn an toradh ann an csv, a luchdaicheas sinn a-rithist gu R.
  • Bidh sinn a’ gineadh sgrìobhainn xlsx le cruth breagha anns an tèid raointean a tha air an lìonadh gu ceàrr a chomharrachadh ann an dearg, thèid sìoltachain a chuir an sàs ann an cuid de cholbhan, agus thèid colbhan a bharrachd anns a bheil an luchd-cruthachaidh a tha san amharc agus àm cruthachadh an VM a chomharrachadh.
  • Bidh sinn a’ gineadh post-d, far am bi sinn a’ ceangal sgrìobhainn a’ toirt cunntas air na luachan raoin dligheach, a bharrachd air clàr le raointean air an lìonadh gu ceàrr. Anns an teacsa tha sinn a’ comharrachadh an àireamh iomlan de VM a chaidh a chruthachadh gu ceàrr, ceangal gu goireas co-roinnte agus dealbh brosnachail. Mura h-eil VMan air an lìonadh gu ceàrr, cuiridh sinn litir eile le dealbh brosnachail nas toilichte.
  • Bidh sinn a’ clàradh dàta airson a h-uile VM ann an stòr-dàta SQL Server, a’ toirt aire do uidheamachd bùird eachdraidheil a chaidh a chuir an gnìomh (inneal fìor inntinneach - mu dheidhinn dè nas fhaide air adhart)

Dìreach sgriobtaichean

Prìomh fhaidhle còd 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")

Sgriobt airson liosta de vm fhaighinn ann an 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
}

Sgriobt PowerShell a bheir a-mach às na logaichean luchd-cruthachaidh innealan brìgheil agus ceann-latha an cruthachadh

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

Tha an leabharlann airidh air aire shònraichte xlsx, a rinn e comasach an ceangal ris an litir a chuir ann an cruth soilleir (mar as toil leis an luchd-stiùiridh), agus chan e dìreach clàr CSV.

A’ cruthachadh sgrìobhainn xlsx breagha le liosta de dh’ innealan air an lìonadh gu ceàrr

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

Tha an toradh a’ coimhead rudeigin mar seo:

Aithisgean làitheil air slàinte innealan brìgheil a ’cleachdadh R agus PowerShell

Bha nuance inntinneach ann cuideachd mu bhith a’ stèidheachadh clàr-ama Windows. Bha e do-dhèanta na còraichean agus na suidheachaidhean ceart a lorg gus an tòisicheadh ​​​​a h-uile càil mar a bu chòir. Mar thoradh air an sin, chaidh an leabharlann R a lorg, a tha ann fhèin a 'cruthachadh gnìomh airson sgriobt R a chuir air bhog agus nach eil eadhon a' dìochuimhneachadh mun fhaidhle log. An uairsin faodaidh tu an obair a cheartachadh le làimh.

Pìos de chòd R le dà eisimpleir a chruthaicheas gnìomh ann an Clàr-ama 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)

Air leth mu dheidhinn an stòr-dàta

Às deidh an sgriobt a chuir air dòigh, thòisich cùisean eile a’ nochdadh. Mar eisimpleir, bha mi airson an ceann-latha a lorg nuair a chaidh an VM a dhubhadh às, ach bha na logaichean ann an vCenter air an caitheamh a-mach mu thràth. Leis gu bheil an sgriobt a’ cur faidhlichean ann am pasgan a h-uile latha agus nach eil e ga ghlanadh (bidh sinn ga ghlanadh le ar làmhan nuair a chuimhnicheas sinn), faodaidh tu coimhead tro sheann fhaidhlichean agus lorg a’ chiad fhaidhle anns nach eil an VM seo an làthair. Ach chan eil sin fionnar.

Bha mi airson stòr-dàta eachdraidheil a chruthachadh.

Thàinig comas-gnìomh MS SQL SERVER - clàr ùine le dreach siostam - gu teasairginn. Mar as trice tha e air eadar-theangachadh mar chlàran sealach (chan e sealach).

Faodaidh tu leughadh gu mionaideach aig Sgrìobhainnean oifigeil Microsoft.

Ann an ùine ghoirid, cruthaichidh sinn clàr, abair gum bi e againn le tionndadh, agus cruthaichidh SQL Server 2 cholbh ceann-latha a bharrachd sa chlàr seo (ceann-latha a chaidh an clàr a chruthachadh agus ceann-latha crìochnachaidh a’ chlàir) agus clàr a bharrachd anns a bheil atharrachaidhean thèid a sgrìobhadh. Mar thoradh air an sin, bidh sinn a’ faighinn fiosrachadh as ùire agus, tro cheistean sìmplidh, agus tha eisimpleirean dhiubh sin air an toirt seachad anns na sgrìobhainnean, chì sinn an dàrna cuid cearcall-beatha inneal brìgheil sònraichte, no suidheachadh a h-uile VM aig àm sònraichte. ann an ùine.

Bho shealladh dèanadais, cha bhi an gnothach sgrìobhaidh chun phrìomh chlàr crìochnaichte gus an tèid an gnothach sgrìobhaidh chun chlàr sealach a chrìochnachadh. An fheadhainn sin. air bùird le àireamh mhòr de ghnìomhachd sgrìobhaidh, bu chòir an gnìomh seo a chuir an gnìomh gu faiceallach, ach anns a’ chùis againn tha e na rud fìor fhionnar.

Gus an obraich an uidheamachd gu ceart, bha agam ri pìos beag de chòd a chuir ann an R a dhèanadh coimeas eadar an clàr ùr agus dàta airson a h-uile VM leis an fhear a tha air a stòradh san stòr-dàta agus dìreach sreathan atharraichte a sgrìobhadh thuige. Chan eil an còd gu sònraichte glic; bidh e a’ cleachdadh an leabharlann CompareDF, ach bidh mi ga thaisbeanadh gu h-ìosal cuideachd.

R còd airson dàta a sgrìobhadh gu stòr-dàta

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

Iomlan

Mar thoradh air buileachadh an sgriobt, chaidh òrdugh ath-nuadhachadh agus a chumail suas taobh a-staigh beagan mhìosan. Aig amannan nochdaidh VMan air an lìonadh gu ceàrr, ach tha an sgriobt na dheagh chuimhneachan agus bidh VM tearc a ’faighinn a-steach don liosta airson 2 latha ann an sreath.

Chaidh obair talmhainn a dhèanamh cuideachd airson mion-sgrùdadh dàta eachdraidheil.

Tha e soilleir gum faodar mòran de seo a chuir an gnìomh chan ann air a ’ghlùin, ach le bathar-bog sònraichte, ach bha an obair inntinneach agus, dh’ fhaodadh aon a ràdh, roghainneil.

Tha R air nochdadh a-rithist gu bhith na shàr chànan uile-choitcheann, a tha foirfe chan ann a-mhàin airson fuasgladh fhaighinn air duilgheadasan staitistigeil, ach a tha cuideachd ag obair mar “sreath” sàr-mhath eadar stòran dàta eile.

Aithisgean làitheil air slàinte innealan brìgheil a ’cleachdadh R agus PowerShell

Source: www.habr.com

Cuir beachd ann