update
This commit is contained in:
+109
@@ -0,0 +1,109 @@
|
||||
#$AllVMHosts = Get-Cluster AVAYA*,LINUX*,ODM*,ORACLE*,SQL*,SQL2-DR,TEL*,WAS*,WINDOWS* | Get-VMHost | Sort-object Name
|
||||
|
||||
$VMhostNames = @"
|
||||
itdbisvm-av05.nd.gov
|
||||
"@
|
||||
|
||||
$VMhostNames = ConvertTo-Array -MultiLineString $VMhostNames
|
||||
|
||||
$AllVMHosts = Get-VMHost $VMhostNames
|
||||
|
||||
|
||||
$AllVMHosts = Get-Cluster WINDOWS2 | Get-VMHost
|
||||
|
||||
ForEach ($VMHost in $AllVMHosts) {
|
||||
Clear-DnsClientCache
|
||||
$VirtualSwitch = $null
|
||||
$CohesityDNS = $null
|
||||
$IpAddress = $null
|
||||
$VMHostDNS = $VMHost.Name
|
||||
$VirtualSwitch = $VMHost | Get-VirtualSwitch -Name "*Data*"
|
||||
$PortGroup = $VirtualSwitch | Get-VirtualPortGroup | Where-Object Name -Like "dvPG_3534_10.2.170.0_24*"
|
||||
$CohesityDNS = $VMHostDNS.split('.')[0] + 'co.nd.gov'
|
||||
|
||||
# does vmhost already have vmkernel in Cohesity range?
|
||||
If ($VMHost | Get-VMHostNetworkAdapter -VMKernel | Where-Object IP -Like "10.2.170.*") {
|
||||
Write-Warning "VMKernel already exists on $VMHostDNS"
|
||||
}
|
||||
Else {
|
||||
$IpAddress = (Resolve-DnsName -Name $CohesityDNS).IpAddress
|
||||
If ($IpAddress) {
|
||||
New-VMHostNetworkAdapter -VMHost $VMHost `
|
||||
-PortGroup $PortGroup `
|
||||
-VirtualSwitch $VirtualSwitch `
|
||||
-IP $IpAddress `
|
||||
-SubnetMask 255.255.255.0 `
|
||||
-ManagementTrafficEnabled $true `
|
||||
-VMotionEnabled $false `
|
||||
-VsanTrafficEnabled $false
|
||||
}
|
||||
else {
|
||||
Write-Error "IpAddress null for $VMHostDNS"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<# Create DNS records
|
||||
$AllVMHosts = @"
|
||||
itdvmbismgmt01.nd.gov
|
||||
itdvmbismgmt02.nd.gov
|
||||
itdvmbisvapp01.nd.gov
|
||||
itdvmbisvapp02.nd.gov
|
||||
itdvmbiswas04.nd.gov
|
||||
itdvmbiswas05.nd.gov
|
||||
itdvmbisora02.nd.gov
|
||||
itdvmbisora03.nd.gov
|
||||
itdvmbissql09.nd.gov
|
||||
itdvmbissql10.nd.gov
|
||||
itdvmbissql11.nd.gov
|
||||
itdvmbiswin07.nd.gov
|
||||
itdvmbiswin08.nd.gov
|
||||
itdvmbiswin09.nd.gov
|
||||
itdvmbiswin10.nd.gov
|
||||
itdvmbiswin11.nd.gov
|
||||
itdvmbiswin12.nd.gov
|
||||
itdvmbiswin13.nd.gov
|
||||
itdvmbissql07.nd.gov
|
||||
itdvmbissql08.nd.gov
|
||||
itdvmmdnmgmt01.nd.gov
|
||||
itdvmmdnvapp01.nd.gov
|
||||
itdvmmdnsql07.nd.gov
|
||||
itdvmmdnsql08.nd.gov
|
||||
itdvmmdnsql09.nd.gov
|
||||
itdvmmdnlin05.nd.gov
|
||||
itdvmmdnora02.nd.gov
|
||||
itdvmmdnmgmt02.nd.gov
|
||||
itdvmmdnvapp02.nd.gov
|
||||
itdvmmdnsql10.nd.gov
|
||||
itdvmmdnsql11.nd.gov
|
||||
itdvmmdnsql12.nd.gov
|
||||
itdvmmdnlin03.nd.gov
|
||||
itdvmmdnlin04.nd.gov
|
||||
"@
|
||||
$AllVMHosts = ConvertTo-Array -MultiLineString $AllVMHosts
|
||||
#Get-Cluster WINDOWS2,WAS2,SQL2,SQL2-DR,TEL2,PS2,ORACLE2,ODM2,LINUX2,AVAYA2 | Get-VMHost
|
||||
ForEach($VMHost in $AllVMhosts){
|
||||
$CohesityDNS = $VMHost.split('.')[0] + 'co.nd.gov'
|
||||
New-ITDIbDNSRecordNextAvailableIP -CIDR 10.2.170.0/24 -Credential $IbCred -Hostname $CohesityDNS
|
||||
#$CohesityDNS
|
||||
}
|
||||
#>
|
||||
|
||||
# static routes
|
||||
$AllVMHosts = Get-VMHost -Name itdmdnvm-av03.nd.gov
|
||||
$result = [System.Collections.ArrayList]@()
|
||||
ForEach ($VMHost in $AllVMHosts) {
|
||||
$x = $null
|
||||
$esxcli = Get-EsxCli -VMHost $VMHost -V2
|
||||
$params = @{
|
||||
network = '10.2.169.128/26'
|
||||
gateway = '10.2.170.1'
|
||||
}
|
||||
|
||||
$esxcli.network.ip.route.ipv4.add.Invoke($params)
|
||||
|
||||
$x = $esxcli.network.ip.route.ipv4.list.Invoke() | Where-Object {$_.Interface -eq 'vmk2' -and $_.Network -eq '10.2.169.128'}
|
||||
$x | Add-Member -Name "Name" -MemberType NoteProperty -Value $VMHost.Name
|
||||
$null = $result.Add($x)
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#vCenter Credentials
|
||||
$creds = Get-Credential
|
||||
Connect-VIServer itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $creds
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#ConvertTo-Array
|
||||
$VMs=@"
|
||||
itdtaxtga1.nd.gov
|
||||
itdtaxpfa1.nd.gov
|
||||
itdtaxsga1.nd.gov
|
||||
itdtaxsga2.nd.gov
|
||||
itdtaxpga1.nd.gov
|
||||
itdtaxpga2.nd.gov
|
||||
itdtaxpga3.nd.gov
|
||||
"@
|
||||
$VMs=ConvertTo-Array -MultiLineString $VMs
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Move VM to Datastore
|
||||
$VMdatastore = 'VMWINDOWS1_143_A9K_R_SHRDPPLSFTST'
|
||||
Get-VM $VMs | Get-HardDisk
|
||||
Get-VM $VMs | Move-VM -DiskStorageFormat Thin -Datastore $VMdatastore
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Copy Files to/from Remote Computer
|
||||
#$fileloc = "C:\Users\delange\State of North Dakota\-Tm-ITD-Virtualization - Documents\VMware\Upgrades\ESXi\6.5.0Update3preGen9\VMware-ESXi-6.5.0-Update3-13932383-HPE-preGen9-650.U3.9.6.8.8-Jun2019.iso"
|
||||
$fileloc = "C:\users\delange\Downloads\sql.zip"
|
||||
#$fileloc = "O:\Backups\vp_grandforks\vp_grandforks.bak"
|
||||
#$fileloc = "C:\temp3\AccelaSchool\*"
|
||||
#$fileloc = "C:\temp\vp_bis_11252019.bak"
|
||||
#$fileloc = "C:\ITD\vc-itdvmvc1.nd.gov-2020-01-14--19.33-53492.tgz"
|
||||
#$fileloc = "D:\Upgrades\VMware\VMware-VCSA-all-6.5.0-14836121.iso"
|
||||
#$fileloc = "F:\Support Bundles\vc-itdvmvc1.nd.gov-2020-01-07--19.02-29010.tgz"
|
||||
#$destination = "D:\Upgrades\VMware\"
|
||||
#$destination = "D:\delange"
|
||||
#$destination = "C:\users\delange\Downloads\"
|
||||
#$destination = "C:\inetpub\wwwroot\"
|
||||
$destination = "D:\ITD\temp\"
|
||||
#$servers = 'itdvmutil'
|
||||
$servers = 'itdps-update.nd.gov'
|
||||
#$servers = 'itdps-images.nd.gov'
|
||||
#Copy to server
|
||||
foreach ($server in $servers){
|
||||
$s=New-PSSession $server -Credential $creds
|
||||
Copy-Item $fileloc -ToSession $s -Destination $destination
|
||||
}
|
||||
#Copy from server
|
||||
foreach ($server in $servers){
|
||||
$s=New-PSSession $server -Credential $creds
|
||||
Copy-Item $fileloc -FromSession $s -Destination $destination
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Approve New VMs
|
||||
Compare-ITDVMwareVMtoSharePoint -NewBuilds -OutVariable MatchSP | Format-Table
|
||||
$MatchSP -Match $false | Sort-Object Name | Format-Table
|
||||
$VMs=@"
|
||||
itdohrcdbp1.nd.gov
|
||||
itdohrcwebp1.nd.gov
|
||||
"@
|
||||
$VMs=ConvertTo-Array -MultiLineString $VMs
|
||||
Approve-ITDVMwareVMNewBuild -ComputerName $VMs
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Snapshots/Clones
|
||||
#Get Current Snapshots
|
||||
Get-VM | Get-Snapshot | Select-Object Name,VM | Sort-Object -Property Name | Format-Table -AutoSize #| clip.exe
|
||||
#Take Snapshot
|
||||
$SnapId = 2151..2156
|
||||
New-ITDVMwareVMSnapshotTask -id $SnapId -vCenterCredential $creds
|
||||
#Delete Snapshot from Scripted Task
|
||||
$SnapId = 2186
|
||||
Remove-ITDVMwareVMSnapshot -Id $SnapId -vCenterCredential $creds
|
||||
#Delete Snapshot taken manually
|
||||
$VM = 'bnd0704.nd.gov','itdscmt1.nd.gov'
|
||||
Get-VM -Name $VM | Where-Object -Property PowerState -EQ PoweredOn | Get-Snapshot | Remove-Snapshot -Confirm:$false
|
||||
#New Clone
|
||||
$CloneId = 2149
|
||||
New-ITDVMwareVMCloneTask -Id $CloneId -vCenterCredential $creds
|
||||
#Delete Clone
|
||||
$CloneId = 2117
|
||||
Get-VM | Where-Object -Property Name -Like "*$CloneId*"
|
||||
foreach ($Clone in $CloneId){
|
||||
$DeleteClone = Get-VM | Where-Object -Property Name -Like "*$Clone*"
|
||||
$DeleteClone | Remove-VM -DeleteFromDisk -Confirm:$false
|
||||
}
|
||||
#Snap entire vCenter environment at once
|
||||
Get-VM itdvmpsc1*,itdvmvc1*,itdvmpsc2*,itdvmvc2* | New-Snapshot -Name "Converge External PSC"
|
||||
Get-VM itdvmpsct1*,itdvmvct1*,itdvmpsct2*,itdvmvct2* | New-Snapshot -Name "PSCT2 Decommissioned"
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Edit VMs
|
||||
#Add CPU
|
||||
$VMs = 'itdsql16p1.nd.gov'
|
||||
$cpu = '4'
|
||||
Get-VM $VMs
|
||||
Set-VM $VMs -NumCpu $cpu -Confirm:$false
|
||||
#Remove CPU
|
||||
$VMs = 'bnd0557.nd.gov'
|
||||
$cpu = '1'
|
||||
Get-VM -Name $VMs | Shutdown-VMGuest -Confirm:$false
|
||||
#Start-Sleep -Seconds 60
|
||||
Get-VM -Name $VMs
|
||||
Get-VM -Name $VMs | Set-VM -NumCPU $cpu -Confirm:$false
|
||||
Start-VM $VMs -Confirm:$false
|
||||
#Increase RAM
|
||||
$VMs = 'itdcndhf16qps.nd.gov','itdcndhefqps.nd.gov'
|
||||
$ram = '12'
|
||||
Get-VM $VMs
|
||||
Set-VM $VMs -MemoryGB $ram -Confirm:$false
|
||||
#Remove RAM
|
||||
$VMs = ''
|
||||
$ram = ''
|
||||
Get-VM $VMs | Shutdown-VMGuest -Confirm:$false
|
||||
Start-Sleep -Seconds 60
|
||||
Get-VM -Name $VMs | Set-VM -MemoryGB 16 -Confirm:$false
|
||||
Start-VM $VMs -Confirm:$false
|
||||
#Disconnect CDROM
|
||||
$VMs = 'itdcndstrwt7.nd.gov'
|
||||
foreach ($VM in $VMs){
|
||||
Get-VM $VM | Get-CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
#Expand Disks
|
||||
$VM = 'itdcndstvm04.nd.gov'
|
||||
Get-VM | Where-Object -Property Name -Like "*$VM*"
|
||||
Get-VM $VM | Get-HardDisk | Select-Object Name,CapacityGB,Filename
|
||||
$harddisk = "Hard Disk 2"
|
||||
$increasedisk = 3
|
||||
$datastore = Get-VM $VM | Get-HardDisk | Where-Object -Property Name -EQ $harddisk | Get-Datastore
|
||||
Get-Datastore $datastore | Select Name,FreeSpaceGB,CapacityGB
|
||||
$newcap = (Get-VM $VM | Get-HardDisk | Where-Object -Property Name -EQ $harddisk).CapacityGB + $increasedisk
|
||||
$newcap
|
||||
Get-VM $VM | Get-HardDisk | Where-Object -Property Name -EQ $harddisk | Set-HardDisk -CapacityGB $newcap -Confirm:$false
|
||||
#List NumCpu, MemoryGB, Total HardDiskSizeGB
|
||||
$VMs = 'itd1xaes2','itdbiscmsvr','itdredskyaes','itdwfoaes4'
|
||||
$datacenter = 'Primary Datacenter'
|
||||
$harddisk = @{n="HardDiskSizeGB";e={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum}}
|
||||
foreach ($VM in $VMs){
|
||||
Get-Datacenter $datacenter | Get-VM | Where-Object -Property Name -Like "$VM*" | Select-Object -Property Name,NumCpu,MemoryGB,$harddisk
|
||||
}
|
||||
foreach ($VM in $VMs){
|
||||
Get-VM | Where-Object -Property Name -Like "$VM*" | Get-HardDisk | Select-Object Name,CapacityGB,Filename | Sort-Object Filename -Descending
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Port groups
|
||||
#New distributed port group
|
||||
$IP = '10.2.160.240/28' <#10.10.10.10/28#>
|
||||
$VLANid = '3326' <#0001#>
|
||||
New-ITDVMNetwork -CIDR $IP -VLAN $VLANid
|
||||
#Remove distributed port group
|
||||
$portgroup = 'dvPG_'
|
||||
Get-VDPortgroup | Where-Object -Property Name -EQ $portgroup | Remove-VDPortGroup -Confirm:$false
|
||||
#Manually add port group
|
||||
$BismarckVDSwitch = 'dvSwitch3-PDC-AVAYA1-Data'
|
||||
$MandanVDSwitch = 'dvSwitch3-SDC-AVAYA2-Data'
|
||||
$PGName = 'dvPG3_2278_165.234.164.0_27'
|
||||
$VlanId = '2278'
|
||||
Get-VDSwitch -Name $BismarckVDSwitch | New-VDPortGroup -Name $PGName -NumPorts 1 -VlanId $VlanId
|
||||
Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing
|
||||
Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false
|
||||
Get-VDSwitch -Name $MandanVDSwitch | New-VDPortGroup -Name $PGName -NumPorts 1 -VLANID $VlanId
|
||||
Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing
|
||||
Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortGroup | Where-Object {$_.Name -like ("*" + "_" + $VlanId)} | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Delete VMs
|
||||
#Rename VMs for decommission
|
||||
$VMs=@"
|
||||
itdcndstfwp.nd.gov
|
||||
itdcndstfsowp.nd.gov
|
||||
itdcndstfwp1.nd.gov
|
||||
itdcndstfapp1.nd.gov
|
||||
itdcndstfwp2.nd.gov
|
||||
itdcndstfapp2.nd.gov
|
||||
"@
|
||||
$VMs=ConvertTo-Array -MultiLineString $VMs
|
||||
Remove-ITDVMWareVM -ComputerName $VMs | Select-Object -Property Name,PowerState
|
||||
foreach ($VM in $VMs){
|
||||
Get-VM | Where-Object -Property Name -Like "$VM*" | Select-Object -Property Name,PowerState
|
||||
}
|
||||
#Delete VM - FINAL DELETE
|
||||
$deleteVM = foreach ($VM in $VMs){
|
||||
Get-VM | Where-Object -Property Name -Like "$VM*delete*"
|
||||
}
|
||||
$deleteVM.Name
|
||||
$deleteVM | Remove-VM -DeleteFromDisk -Confirm:$false
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Replace VMs
|
||||
$VMs = 'itdexchcasbis2.nd.gov','itdexchcasman2.nd.gov','itdcndhehb.nd.gov','itdcndheclnadd.nd.gov'
|
||||
foreach ($VM in $VMs){
|
||||
$VMold = Get-VM | Where-Object -Property Name -Like "$VM*" | Where-Object -Property PowerState -EQ PoweredOff
|
||||
$VMnew = Get-VM | Where-Object -Property Name -Like "$VM*new*"
|
||||
$VMtags = ($VMold | Get-TagAssignment).Tag | Sort-Object -Unique
|
||||
foreach ($VMtag in $VMtags){
|
||||
New-TagAssignment -Entity $VMnew -Tag $VMtag
|
||||
}
|
||||
Remove-ITDVMWareVM -ComputerName $VMold.Name
|
||||
Set-VM -VM $VMnew -Name $VMold -Confirm:$false
|
||||
}
|
||||
foreach ($VM in $VMs){
|
||||
Get-VM | Where-Object -Property Name -Like "$VM*" | Get-TagAssignment
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Datastores
|
||||
$Datastore = 'VMWINDOWS1_138_A9K_R_BNDFISERV'
|
||||
#Rescan Host Cluster
|
||||
Get-Cluster WINDOWS1 | Get-VMHost | Get-VMHostStorage -RescanAllHba -RescanVmfs
|
||||
#Maintenance Mode
|
||||
$Datastore = 'VMPS1_48_A9K_R','VMPS1_49_A9K_R','VMPS1_50_A9K_R','VMPS1_51_A9K_R','VMPS1_52_A9K_R','VMPS1_53_A9K_R'
|
||||
Get-Datastore $Datastore | Set-Datastore -MaintenanceMode $true -EvacuateAutomatically
|
||||
Get-Datastore $Datastore | Set-Datastore -MaintenanceMode $false
|
||||
#Adding Datastores
|
||||
$VMhost = 'itdbisvm-sql01.nd.gov'
|
||||
#Get CanonicalName
|
||||
Get-ScsiLun -VmHost $VMhost -LunType Disk | Select-Object CanonicalName,CapacityGB | Sort-Object CanonicalName
|
||||
#Create Datastore
|
||||
$Datastore = 'VMSQL1_119_A9K_TAX'
|
||||
$CanonicalName = 'naa.6001738ccce06785000000000018ef24'
|
||||
New-Datastore -VMHost $VMhost -Name $Datastore -Path $CanonicalName -VMFS -FileSystemVersion 6
|
||||
#Removing Datastores
|
||||
#Datastore Unmap
|
||||
$Datastores = 'VMLINUX1_248_V5K_SECLOG','VMLINUX1_249_V5K_SECLOG','VMLINUX1_250_V5K_SECLOG','VMLINUX1_251_V5K_SECLOG'
|
||||
#$Datastores = (Get-DatastoreCluster SQL1_A9K_General | Get-Datastore).Name
|
||||
foreach ($Datastore in $Datastores){
|
||||
Start-ITDVMwareDatastoreUnmap -Datastore $Datastores
|
||||
}
|
||||
#Expand Datastore
|
||||
$Datastore = Get-Datastore 'VMTEL1_124_A9K_VBRICK'
|
||||
$esxi = Get-View -Id ($Datastore.ExtensionData.Host | Select-Object -Last 1 | Select-Object -ExpandProperty Key)
|
||||
$DatastoreSystem = Get-View -Id $esxi.ConfigManager.DatastoreSystem
|
||||
$ExpandOptions = $DatastoreSystem.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef)
|
||||
$DatastoreSystem.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef,$expandOptions.spec)
|
||||
#Disable Storage I/O Control
|
||||
$Datastores = 'VMWINDOWS1_90_A9K','VMWINDOWS1_91_A9K','VMWINDOWS1_92_A9K','VMSQL1_57_A9K','VMLINUX1_99_A9K_ELASTIC'
|
||||
foreach ($Datastore in $Datastores){
|
||||
Get-Datastore $Datastore | Set-Datastore -StorageIOControlEnabled $false
|
||||
}
|
||||
#Unmount/Detach
|
||||
#Unmount/Detach
|
||||
Remove-ITDVmwareDatastoreStep1 -LunId 90
|
||||
#Step2 Storage Admin unmaps LUN from Host
|
||||
#LUN cleanup (after storage unmap, should return empty)
|
||||
Remove-ITDVMwareDatastoreStep3 -LunId 57
|
||||
Remove-ITDVMwareDatastoreStep3 -LunId 90
|
||||
Remove-ITDVMwareDatastoreStep3 -LunId 91
|
||||
Remove-ITDVMwareDatastoreStep3 -LunId 92
|
||||
Remove-ITDVMwareDatastoreStep3 -LunId 99
|
||||
|
||||
$Id = "_90_"
|
||||
$Datastores = Get-Datastore | Where-Object Name -Like ("*_" + $Id + "_*")
|
||||
ForEach ($Datastore in $Datastores) {
|
||||
$SharePointRecord = $null
|
||||
|
||||
$DatastoreHosts = $Datastore | Get-VMHost
|
||||
$VMHostCanonicalName = (Get-ScsiLun -VmHost ($DatastoreHosts | Select -First 1) | where-object RuntimeName -Like "*$Id*").CanonicalName
|
||||
$SharePointRecord = ($SharePointList | Where-Object Title -eq $Datastore.Name)
|
||||
|
||||
If ($SharePointRecord.ExtentName -eq $VMHostCanonicalName) {
|
||||
Write-Verbose ($Datastore.Name + " *** " + $VMHostCanonicalName + " *** CanonicalName accurate in SharePoint, continuing with unmount")
|
||||
|
||||
try {
|
||||
Get-Datastore $Datastore #| Unmount-Datastore
|
||||
$DatastoreHosts | Select-Object -First 1 | Remove-Datastore $Datastore -Confirm:$false -RunASync
|
||||
$DatastoreRemovalSuccess += $Datastore.Name
|
||||
}
|
||||
catch {
|
||||
$DatastoreRemovalFailure += $Datastore.Name
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error ($Datastore.Name + " *** " + " *** CanonicalName mismatch with SharePoint Record")
|
||||
}
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Clusters
|
||||
#Get cluster that VM resides in
|
||||
foreach ($VM in $VMs){
|
||||
Get-VM $VM | Get-Datastore | Select-Object Name
|
||||
}
|
||||
#Get VMs with Resource Reservations
|
||||
$Cluster = 'TEL1'
|
||||
$VMs = Get-Cluster $Cluster | Get-VM
|
||||
$VMs2 = Get-VM | Where-Object {$_.ExtensionData.ResourceConfig.MemoryAllocation.Reservation -ne "0" -or $_.ExtensionData.ResourceConfig.CpuAllocation.Reservation -ne "0"}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Tags
|
||||
$VMs=@"
|
||||
itdintrpmgrp1.nd.gov
|
||||
"@
|
||||
$VMs=ConvertTo-Array -MultiLineString $VMs
|
||||
#Spectrum Protect for VE
|
||||
$TagCat = "Backup Management (IBM Spectrum Protect)"
|
||||
$TagName = "Included"
|
||||
#RPO
|
||||
$TagCat = "VR RPO"
|
||||
$TagName = "ABR"
|
||||
$TagName = "RPO 0:15"
|
||||
$TagName = "RPO 0:30"
|
||||
$TagName = "RPO 1:00"
|
||||
$TagName = "RPO 2:00"
|
||||
$TagName = "RPO 4:00"
|
||||
$TagName = "RPO 8:00"
|
||||
#VR Datastores
|
||||
$TagCat = "VR Datastores"
|
||||
$TagName = "VMAVAYA2_210_A9K_VR"
|
||||
$TagName = "VMLINUX2_212_A9K_VR"
|
||||
$TagName = "VMLINUX2_213_A9K_VR"
|
||||
$TagName = "VMSQL2_218_A9K_VR"
|
||||
$TagName = "VMTEL2_220_A9K_VR"
|
||||
$TagName = "VMTEL2_221_A9K_VR"
|
||||
$TagName = "VMWAS2_222_A9K_VR"
|
||||
$TagName = "VMWAS2_223_A9K_VR"
|
||||
$TagName = "VMWINDOWS2_224_A9K_VR"
|
||||
$TagName = "VMWINDOWS2_225_A9K_VR"
|
||||
$TagName = "VMWINDOWS2_226_A9K_VR"
|
||||
#SRM Type
|
||||
$TagCat = "SRM Type"
|
||||
$TagName = "SRM Reserved"
|
||||
$TagName = "SRM Repurposed Suspend"
|
||||
$TagName = "SRM Repurposed"
|
||||
#HA Host
|
||||
$TagCat = "HA"
|
||||
$TagName = "Dedicated HA Host"
|
||||
#Assign Tag
|
||||
foreach ($VM in $VMs){
|
||||
$VM = Get-VM $VM | Where-Object -Property PowerState -EQ PoweredOn
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
New-TagAssignment -Entity $VM -Tag (Get-Tag -Server $VIServer -Category $TagCat -Name $TagName) -Server $VIServer
|
||||
}
|
||||
foreach ($VMHost in $VMHosts){
|
||||
$VMHost = Get-VMHost $VMHost
|
||||
$VIServer = $VMHost.Uid.split('@')[1].split(':')[0]
|
||||
New-TagAssignment -Entity $VMHost -Tag (Get-Tag -Server $VIServer -Category $TagCat -Name $TagName) -Server $VIServer
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#VMhosts
|
||||
$VMhosts=@"
|
||||
itdbisvm-av01.nd.gov
|
||||
itdbisvm-av02.nd.gov
|
||||
itdbisvm-av03.nd.gov
|
||||
itdbisvm-av04.nd.gov
|
||||
itdbisvm-av05.nd.gov
|
||||
"@
|
||||
$VMhosts=ConvertTo-Array -MultiLineString $VMhosts
|
||||
#VMhosts by Cluster
|
||||
$VMhosts = (Get-Cluster | Where-Object -Property Name -EQ WINDOWS1 | Get-VMHost | Sort-Object).Name
|
||||
#Disable Lockdown Mode
|
||||
foreach ($VMhost in $VMhosts){
|
||||
(Get-VMHost $VMhost | Get-View).ExitLockdownMode()
|
||||
}
|
||||
#Enable Lockdown Mode
|
||||
(Get-VMHost $VMhost | Get-View).EnterLockdownMode()
|
||||
$VMhosts = Get-Datacenter | Where-Object -Property Uid -Like "*itdvmvc*" | Get-VMHost
|
||||
(Get-VMHost $Vmhosts | Get-View).EnterLockdownMode()
|
||||
foreach ($VMhost in $VMhosts){
|
||||
(Get-VMHost $VMhost | Get-View).EnterLockdownMode()
|
||||
}
|
||||
#Enable SSH services
|
||||
Get-VMHost $VMhost | Get-VMHostService | Where-Object {$_.Label -eq "SSH"} | Start-VMHostService
|
||||
Get-VMHost $VMhost | Get-VMHostService | Where-Object {$_.Label -eq "ESXi Shell"} | Start-VMHostService
|
||||
#Get Lockdown Status for all VMhosts
|
||||
$VMhosts = Get-Datacenter | Where-Object -Property Uid -Like "*itdvmvc*" | Get-VMHost
|
||||
$Lockdown = @{N="Lockdown";E={$_.Extensiondata.Config.adminDisabled}}
|
||||
Get-VMHost $VMhosts | Select-Object Name,$Lockdown
|
||||
#Disable Alarms
|
||||
foreach ($VMhost in $VMhosts){
|
||||
$disableHost = Get-VMhost $VMhost
|
||||
$viServer = $disableHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $viServer
|
||||
$alarmEnabled = $disableHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true){
|
||||
$alarmMgr.EnableAlarmActions($disableHost.ExtensionData.MoRef,$false)
|
||||
}
|
||||
$disableHost = $null
|
||||
}
|
||||
#Enable Alarms
|
||||
foreach ($VMhost in $VMhosts){
|
||||
$enableHost = Get-VMhost $VMhost
|
||||
$viServer = $enableHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $viServer
|
||||
$alarmEnabled = $enableHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $false){
|
||||
$alarmMgr.EnableAlarmActions($enableHost.ExtensionData.MoRef,$true)
|
||||
}
|
||||
$enableHost = $null
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Disk Space
|
||||
$VMs=@"
|
||||
itdcndhhpdb.nd.gov
|
||||
itdcndhhpdbdr.nd.gov
|
||||
itdcndhfpdb.nd.gov
|
||||
itdcndhfpdbdr.nd.gov
|
||||
"@
|
||||
$VMs=ConvertTo-Array -MultiLineString $VMs
|
||||
$export = 'C:\temp\usedspace.csv'
|
||||
Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Avaya1 | Export-Csv $export
|
||||
Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Avaya1 | Export-Csv $export -Append
|
||||
Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Linux1 | Export-Csv $export -Append
|
||||
Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable ODM1 | Export-Csv $export -Append
|
||||
Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable PS1 | Export-Csv $export -Append
|
||||
Get-VM $VMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable WAS1 | Export-Csv $export -Append
|
||||
Get-VM $WindowsVMs | Select-Object Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Windows1 | Export-Csv $export -Append
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
$export = "C:\temp2\usedspace.csv"
|
||||
Export-Csv -Path $export -InputObject $Avaya1
|
||||
|
||||
|
||||
Get-VM $VMs | Select-Object @{n="Cluster"; e={($_ | Get-Cluster).Name}},Name,@{n="UsedSpaceGB"; e={[math]::round($_.UsedSpaceGB )}},@{n="ProvisionedSpaceGB"; e={[math]::round($_.ProvisionedSpaceGB )}} -OutVariable Avaya1 | Export-Csv $export
|
||||
@@ -0,0 +1,97 @@
|
||||
Start-Transcript C:\ITDSCRIPT\Logs\GetIPs.txt -Append
|
||||
#Add-PSSnapin VMware.VimAutomation.Core
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false
|
||||
|
||||
#Connect
|
||||
Connect-VIServer itdvmvc1.nd.gov, itdvmvc2.nd.gov
|
||||
|
||||
|
||||
##Windows
|
||||
|
||||
|
||||
#Output File
|
||||
$OutFileWin = "c:\inetpub\wwwroot\Win.txt"
|
||||
$Date = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Get-Item -Path $OutFileWin | Copy-Item -Destination "D:\Backup\Win\$Date-Win.txt"
|
||||
Remove-Item $OutFileWin
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
|
||||
#Get Powered On VM's
|
||||
$vmwin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" `
|
||||
-and ($_.GuestID -eq "windows7Guest" `
|
||||
-or $_.GuestID -eq "windows7_64Guest" `
|
||||
-or $_.GuestID -eq "windows7Server64Guest" `
|
||||
-or $_.GuestID -eq "windows8_64Guest" `
|
||||
-or $_.GuestID -eq "windows8Server64Guest" `
|
||||
-or $_.GuestID -eq "windows9Server64Guest" `
|
||||
-or $_.GuestID -eq "winLonghorn64Guest" `
|
||||
-or $_.GuestID -eq "winLonghornGuest" `
|
||||
-or $_.GuestID -eq "winNetStandardGuest" `
|
||||
-or $_.GuestID -eq "winNetEnterpriseGuest" `
|
||||
-or $_.GuestID -eq "windows9_64Guest") }
|
||||
$vmviewwin = $vmwin | Get-View
|
||||
|
||||
$Outputwin = ""
|
||||
|
||||
#Loop through VM's, NIC's, and IP addresses.
|
||||
Foreach ($v in $vmviewwin) {
|
||||
Foreach ($nic in $v.Guest.Net) {
|
||||
Foreach ($IP in $nic.IPAddress) {
|
||||
If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") {
|
||||
$OutputWin += $IP + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#If ($Outputwin -ne "") {$OutputWin | Out-File $OutFileWin -Encoding utf8 -NoNewline}
|
||||
If ($Outputwin -ne "") { $OutputWin | Out-File $OutFileWin -Encoding ASCII -NoNewline }
|
||||
|
||||
|
||||
|
||||
##Linux
|
||||
|
||||
#Output File
|
||||
$OutFileLin = "c:\inetpub\wwwroot\Lin.txt"
|
||||
$Date = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Get-Item -Path $OutFileLin | Copy-Item -Destination "D:\Backup\Lin\$Date-Lin.txt"
|
||||
Remove-Item $OutFileLin
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
#Get Powered On VM's
|
||||
$vmLin = get-VM | Where-Object { $_.PowerState -eq "PoweredOn" `
|
||||
-and ($_.GuestID -eq "centos6_64Guest" `
|
||||
-or $_.GuestID -eq "centos64Guest" `
|
||||
-or $_.GuestID -eq "centos7_64Guest" `
|
||||
-or $_.GuestID -eq "oracleLinux64Guest" `
|
||||
-or $_.GuestID -eq "oracleLinux7_64Guest" `
|
||||
-or $_.GuestID -eq "rhel4Guest" `
|
||||
-or $_.GuestID -eq "rhel5Guest" `
|
||||
-or $_.GuestID -eq "rhel5_64Guest" `
|
||||
-or $_.GuestID -eq "rhel6Guest" `
|
||||
-or $_.GuestID -eq "rhel6_64Guest" `
|
||||
-or $_.GuestID -eq "rhel7_64Guest" `
|
||||
-or $_.GuestID -eq "sles11_64Guest" `
|
||||
-or $_.GuestID -eq "sles12_64Guest" `
|
||||
-or $_.GuestID -eq "ubuntu64Guest") }
|
||||
$vmviewlin = $vmLin | Get-View
|
||||
|
||||
$OutputLin = ""
|
||||
|
||||
#Loop through VM's, NIC's, and IP addresses.
|
||||
Foreach ($v in $vmviewlin) {
|
||||
Foreach ($nic in $v.Guest.Net) {
|
||||
Foreach ($IP in $nic.IPAddress) {
|
||||
If ($IP -notlike "fe80*" -and $IP -notlike "192.168.*" -and $IP -notlike "172.16*") {
|
||||
$OutputLin += $IP + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#If ($OutputLin -ne "") {$OutputLin | Out-File $OutFileLin -Encoding utf8 -NoNewline}
|
||||
If ($OutputLin -ne "") { $OutputLin | Out-File $OutFileLin -Encoding ASCII -NoNewline }
|
||||
|
||||
|
||||
Stop-Transcript
|
||||
@@ -0,0 +1,133 @@
|
||||
Start-Transcript C:\itdscript\Logs\GetIPsAzureB.txt -Append
|
||||
$VerbosePerfrence = "Continue"
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$OutputPath = "C:\inetpub\wwwroot"
|
||||
|
||||
$WindowsIPs = ""
|
||||
$LinuxIPs = ""
|
||||
$OutFileWin = $OutputPath + "\AzureWin.txt"
|
||||
$OutFileLin = $OutputPath + "\AzureLin.txt"
|
||||
Remove-Item $OutFileWin
|
||||
Remove-Item $OutFileLin
|
||||
|
||||
|
||||
$username="svcitdazurescript@nd.gov"
|
||||
$usernameg="svcitdazurescript@ndstate.onmicrosoft.com"
|
||||
#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat
|
||||
$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString
|
||||
$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString
|
||||
$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password
|
||||
$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg
|
||||
|
||||
Login-AzureRMAccount -Credential $AdminCred -Environment AzureCloud -Verbose
|
||||
|
||||
$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"}
|
||||
foreach($subscription in $subscriptions)
|
||||
{
|
||||
Set-AzureRMContext -SubscriptionObject $subscription
|
||||
$WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"}
|
||||
$LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"}
|
||||
$nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null}
|
||||
|
||||
foreach($vm in $WindowsVMs)
|
||||
{
|
||||
$vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id
|
||||
foreach($vmnicinterface in $vmnicinterfaces)
|
||||
{
|
||||
$nic = $nics | Where-Object {$_.Id -eq $vmnicinterface}
|
||||
$privateip = $nic.IpConfigurations | Select PrivateIPAddress
|
||||
|
||||
If($privateip.count -gt 1)
|
||||
{
|
||||
foreach($private in $privateip)
|
||||
{
|
||||
$WindowsIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseIf($privateip.privateIPAddress -ne $null)
|
||||
{
|
||||
$WindowsIPs += $privateip.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($vm in $LinuxVMs)
|
||||
{
|
||||
$vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id
|
||||
foreach($vmnicinterface in $vmnicinterfaces)
|
||||
{
|
||||
$nic = $nics | Where-Object {$_.Id -eq $vmnicinterface}
|
||||
$privateip = $nic.IpConfigurations | Select PrivateIPAddress
|
||||
|
||||
If($privateip.count -gt 1)
|
||||
{
|
||||
foreach($private in $privateip)
|
||||
{
|
||||
$LinuxIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseif($privateip.privateIPAddress -ne $null)
|
||||
{
|
||||
$LinuxIps += $privateip.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Login-AzureRMAccount -EnvironmentName AzureUSGovernment -Credential $AdminCredg
|
||||
|
||||
$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"}
|
||||
foreach($subscription in $subscriptions)
|
||||
{
|
||||
Set-AzureRMContext -SubscriptionObject $subscription
|
||||
$WindowsVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Windows"}
|
||||
$LinuxVMs = Get-AzureRMVM | Where-Object {$_.StorageProfile.osdisk.ostype -match "Linux" -and $_.StorageProfile.ImageReference.Publisher -ne "infoblox" -and $_.StorageProfile.ImageReference.Publisher -ne "paloaltonetworks" -and $_.StorageProfile.ImageReference.Publisher -ne "juniper-networks"}
|
||||
$nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null}
|
||||
|
||||
foreach($vm in $WindowsVMs)
|
||||
{
|
||||
$vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id
|
||||
foreach($vmnicinterface in $vmnicinterfaces)
|
||||
{
|
||||
$nic = $nics | Where-Object {$_.Id -eq $vmnicinterface}
|
||||
$privateip = $nic.IpConfigurations | Select PrivateIPAddress
|
||||
If($privateip.count -gt 1)
|
||||
{
|
||||
foreach($private in $privateip)
|
||||
{
|
||||
$WindowsIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseIf($privateip.privateIPAddress -ne $null)
|
||||
{
|
||||
$WindowsIPs += $privateip.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($vm in $LinuxVMs)
|
||||
{
|
||||
$vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id
|
||||
foreach($vmnicinterface in $vmnicinterfaces)
|
||||
{
|
||||
$nic = $nics | Where-Object {$_.Id -eq $vmnicinterface}
|
||||
$privateip = $nic.IpConfigurations | Select PrivateIPAddress
|
||||
|
||||
If($privateip.count -gt 1)
|
||||
{
|
||||
foreach($private in $privateip)
|
||||
{
|
||||
$LinuxIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseif($privateip.privateIPAddress -ne $null)
|
||||
{
|
||||
$LinuxIps += $privateip.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
If ($WindowsIPs -ne "" -and $WindowsIPs.Length -gt 150) {$WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline -Force}
|
||||
If ($LinuxIPs -ne ""-and $LinuxIPs.Length -gt 150) {$LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline -Force}
|
||||
@@ -0,0 +1,89 @@
|
||||
start-transcript D:\zm.log -force
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$OutputPath = "C:\inetpub\wwwroot"
|
||||
$OutputBackupPath = "C:\inetpub\wwwroot\AzureBak\"
|
||||
$CurrentDateTime = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
|
||||
|
||||
$BackupIPs = ""
|
||||
$OutFileBak = $OutputPath + "\AzureBak.txt"
|
||||
$OutFileBakBackup = $OutputBackupPath + "\AzureBak-$CurrentDateTime.txt"
|
||||
|
||||
Remove-Item $OutFileBak
|
||||
|
||||
|
||||
$username="svcitdazurescript@nd.gov"
|
||||
$usernameg="svcitdazurescript@ndstate.onmicrosoft.com"
|
||||
#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat
|
||||
$password=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sac.bat | ConvertTo-SecureString
|
||||
$passwordg=Get-Content C:\Users\svcitdazurescript\AppData\Local\Microsoft\sacg.bat | ConvertTo-SecureString
|
||||
$AdminCred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password
|
||||
$AdminCredg=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $usernameg,$passwordg
|
||||
|
||||
Login-AzureRMAccount -Credential $AdminCred -Environment AzureCloud
|
||||
|
||||
$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"}
|
||||
foreach($subscription in $subscriptions)
|
||||
{
|
||||
Set-AzureRMContext -SubscriptionObject $subscription
|
||||
$BackupVMs = Get-AzureRMVM | Where-Object {$_.Tags["Backup"] -match "OS-BackupEnabled"}
|
||||
$nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null}
|
||||
|
||||
foreach($vm in $BackupVMs)
|
||||
{
|
||||
$vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id
|
||||
foreach($vmnicinterface in $vmnicinterfaces)
|
||||
{
|
||||
$nic = $nics | Where-Object {$_.Id -eq $vmnicinterface}
|
||||
$privateip = $nic.IpConfigurations | Select PrivateIPAddress
|
||||
|
||||
If($privateip.count -gt 1)
|
||||
{
|
||||
foreach($private in $privateip)
|
||||
{
|
||||
$BackupIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseIf($privateip.privateIPAddress -ne $null)
|
||||
{
|
||||
$BackupIPs += $privateip.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Login-AzureRMAccount -EnvironmentName AzureUSGovernment -Credential $AdminCredg
|
||||
|
||||
$Subscriptions = Get-AzureRMSubscription | Where-Object {$_.Name -ne "sandbox"}
|
||||
foreach($subscription in $subscriptions)
|
||||
{
|
||||
Set-AzureRMContext -SubscriptionObject $subscription
|
||||
$BackupVMs = Get-AzureRMVM | Where-Object {$_.Tags["Backup"] -match "OS-BackupEnabled"}
|
||||
$nics = Get-AzureRMNetworkInterface | Where-Object {$_.VirtualMachine -NE $null}
|
||||
|
||||
foreach($vm in $BackupVMs)
|
||||
{
|
||||
$vmnicinterfaces = $vm.Networkprofile.NetworkInterfaces.id
|
||||
foreach($vmnicinterface in $vmnicinterfaces)
|
||||
{
|
||||
$nic = $nics | Where-Object {$_.Id -eq $vmnicinterface}
|
||||
$privateip = $nic.IpConfigurations | Select PrivateIPAddress
|
||||
If($privateip.count -gt 1)
|
||||
{
|
||||
foreach($private in $privateip)
|
||||
{
|
||||
$BackupIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseIf($privateip.privateIPAddress -ne $null)
|
||||
{
|
||||
$BackupIPs += $privateip.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
If ($BackupIPs -ne "") {
|
||||
$BackupIPs | Out-File $OutFileBak -Encoding ASCII -NoNewline -Force
|
||||
$BackupUPs | Out-File $OutFileBakBackup -Encoding ascii -NoNewline -Force
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
$servers = @"
|
||||
itdvmbisvdi05lo.nd.gov
|
||||
itdvmbisvdi06lo.nd.gov
|
||||
"@
|
||||
$servers = ConvertTo-Array -MultiLineString $servers
|
||||
|
||||
# validate DNS is configured
|
||||
ForEach($server in $servers){
|
||||
Resolve-DnsName -Name $server
|
||||
}
|
||||
|
||||
#ServerHardware.mpHostInfo.mpIpAddresses
|
||||
|
||||
# requires powershell 5.1 as of 2023/02/09
|
||||
# Generate CSRs
|
||||
ForEach ($server in $servers) {
|
||||
$csr = $Null
|
||||
$connection = Connect-HPEiLO $server -Credential $iLOCred -DisableCertificateAuthentication
|
||||
$FQDN = $connection.Hostname
|
||||
If($FQDN -notlike "itdvm*"){
|
||||
$FQDN = ((Get-HPEiLOServerInfo -Connection $connection).ServerName.split('.')[0] + 'lo' + '.nd.gov')
|
||||
}
|
||||
$Hostname = $FQDN.split('.')[0]
|
||||
|
||||
Start-HPEiLOCertificateSigningRequest -Connection $connection -State "North Dakota" -Country "US" -City "Bismarck" -Organization "State of North Dakota" -OrganizationalUnit "NDIT" -CommonName $FQDN
|
||||
|
||||
do {
|
||||
$csr = (Get-HPEiLOCertificateSigningRequest -Connection $connection -ErrorAction SilentlyContinue).CertificateSigningRequest.TrimEnd()
|
||||
Write-Warning ((Get-Date).tostring() + " pausing for 5 seconds")
|
||||
Start-Sleep -Seconds 5
|
||||
} while ( $csr -eq $null )
|
||||
$csr | Set-Content "D:\iLO\CSRs\$FQDN-csr.txt"
|
||||
Disconnect-HPEiLO -Connection $connection
|
||||
}
|
||||
|
||||
$CsrList = [System.Collections.ArrayList]@()
|
||||
ForEach($server in $servers){
|
||||
$obj=[PSCustomObject]@{
|
||||
'Server' = $Server
|
||||
'CSR' = (Get-Content "D:\iLO\CSRs\$server-csr.txt" -Raw);
|
||||
}
|
||||
|
||||
$null = $CsrList.Add($obj)
|
||||
}
|
||||
|
||||
$CsrList | group-object CSR
|
||||
# If any appear with count not equal to 1, something is broken
|
||||
|
||||
|
||||
|
||||
|
||||
ForEach ($server in $servers){
|
||||
Write-Warning "$server csr to clipboard"
|
||||
Get-Content "D:\iLO\CSRs\$server-csr.txt" | Set-Clipboard
|
||||
Pause
|
||||
}
|
||||
|
||||
|
||||
ForEach ($server in $servers){
|
||||
$certfile = $Null
|
||||
$cert = $Null
|
||||
|
||||
$connection = Connect-HPEiLO $server -Credential $iloCred -DisableCertificateAuthentication
|
||||
$FQDN = $connection.Hostname
|
||||
If($FQDN -notlike "itdvm*"){
|
||||
$FQDN = ((Get-HPEiLOServerInfo -Connection $connection).ServerName.split('.')[0] + 'lo' + '.nd.gov')
|
||||
}
|
||||
$Hostname = $FQDN.split('.')[0]
|
||||
$certfile = ($hostname) + "_nd_gov_cert.cer"
|
||||
$cert = (Get-Content "D:\iLO\Certs\$certfile" -Raw).Replace("`r`n", "`n").Trim()
|
||||
Import-HPEiLOCertificate -Certificate $cert -Connection $connection -Verbose
|
||||
Disconnect-HPEiLO -Connection $connection
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Refresh server hardware, in powershell 7
|
||||
# Connect-OVMgmt
|
||||
$OVServers = Get-OVServer | Sort-Object ServerName
|
||||
Foreach($OVServer in $OVServers){
|
||||
Write-Warning ("Start " + $OVServer.ServerName)
|
||||
$OVServer | Update-OVServer -Async
|
||||
Start-Sleep -Seconds 15
|
||||
}
|
||||
|
||||
|
||||
|
||||
#######################
|
||||
@@ -0,0 +1,19 @@
|
||||
$VMHosts = Get-VMHost
|
||||
|
||||
#SSH Service Status
|
||||
$SSHServiceStatus = $VMHosts | Get-VMHostService | Where-Object Key -eq "TSM-SSH" | select VMhost,Key,Label,Running
|
||||
|
||||
#Disable SSH
|
||||
ForEach($item in ($SSHService | Where-Object Running -eq $true)){
|
||||
Get-VMHost $item.VMHost | Get-VMHostService | Where-Object Key -eq "TSM-SSH" | Stop-VMHostService
|
||||
}
|
||||
|
||||
|
||||
|
||||
#Lockdown status
|
||||
$LockdownStatus = $VMHosts | Select Name,@{n='LockdownMode';e={$_.ExtensionData.Config.LockdownMode}}
|
||||
|
||||
#Enable Lockdown
|
||||
ForEach($VMHost in ($LockdownStatus | Where-Object LockdownMode -eq "lockdownDisabled")){
|
||||
(Get-VMHost $VMHost.Name | Get-View).EnterLockdownMode()
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
$VMHostNames=@"
|
||||
itdvmbisps10.nd.gov
|
||||
itdvmbisps11.nd.gov
|
||||
itdvmbisps12.nd.gov
|
||||
itdvmbisps13.nd.gov
|
||||
itdvmbisps14.nd.gov
|
||||
itdvmbisps15.nd.gov
|
||||
itdvmbisps16.nd.gov
|
||||
itdvmbisps17.nd.gov
|
||||
itdvmbisps18.nd.gov
|
||||
"@
|
||||
|
||||
$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames
|
||||
|
||||
<#$VMHostNames | ForEach-Object{
|
||||
New-ITDVMwareHostScratchFolder -Site Bismarck $_.split('.')[0]
|
||||
}
|
||||
#>
|
||||
foreach ($VMHostName in $VMHostNames){
|
||||
$GetVMHost = Get-VMhost $VMHostName
|
||||
$VMHostParent = $GetVMHost.Parent
|
||||
$HostCluster = Get-Cluster $VMHostParent
|
||||
$NewSpec = New-Object VMware.Vim.ClusterConfigSpec
|
||||
$NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true
|
||||
$HostCluster.ExtensionData.ReconfigureCluster($NewSpec,$true)
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true){
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef,$false)
|
||||
}
|
||||
$VMs = $GetVMHost | Get-VM
|
||||
#Disconnect CDROM and/or VMtools ISO
|
||||
foreach ($VM in $VMs){
|
||||
$GetVM = Get-VM $VM
|
||||
$CDDrive = $GetVM | Get-CDDrive
|
||||
if ($CDDrive | Where-Object {$_.IsoPath -Like "*vmware/isoimages*"}){
|
||||
$GetVM | Dismount-Tools
|
||||
#$CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
elseif ($CDDrive.HostDevice -Like "*drive*"){
|
||||
$CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
#Move Powered Off VMs
|
||||
foreach ($VMHostName in $VMHostNames){
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostParent = $VMHostDetails.Parent.Name
|
||||
$VMHostMigrate = Get-Cluster $VMHostParent | Get-VMHost | Where-Object Name -NE $VMHostName | Select-Object -First 1
|
||||
$VMsPoweredOff = Get-VMHost $VMHostName | Get-VM | Where-Object PowerState -EQ "PoweredOff"
|
||||
Move-VM -VM $VMsPoweredOff -Destination $VMHostMigrate
|
||||
}
|
||||
#Enter Maintenance Mode
|
||||
Set-VMHost -VMHost $VMHostNames -State "Maintenance" -RunAsync
|
||||
#Monitor
|
||||
Get-VMHost -Name $VMHostNames | Select-Object Name,ConnectionState,@{Name="VM.count";E={@($_ | Get-VM | Where-Object {$_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm"}).Count}} | sort-object Name
|
||||
|
||||
# shutdown
|
||||
Get-VMHost -Name $VMHostnames | Stop-VMHost -Confirm:$false
|
||||
|
||||
#status
|
||||
Get-VMHost -Name $VMHostnames
|
||||
|
||||
# OneView, Update Server Profile from Template
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
Get-OVServerProfile -Name $VMHostName.split('.')[0] | Update-OVServerProfile -Async -confirm:$false
|
||||
}
|
||||
|
||||
# Power on
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
Get-OVServer -ServerName $VMHostName | Start-OVServer -Async
|
||||
}
|
||||
|
||||
# Verify on and connected
|
||||
Get-VMHost $VMHostNames
|
||||
|
||||
# attach new host profile
|
||||
Get-VMHost -Name $VMHostnames | Set-VMHost -Profile "MDN 6.5.0 Synergy General 2203"
|
||||
|
||||
# Apply/Remediate Host Profile (invoke)
|
||||
Get-VMHost -Name $VMHostnames | Invoke-VMHostProfile -confirm:$false -RunAsync
|
||||
|
||||
# manual check for dvswitch data-user
|
||||
|
||||
|
||||
#Exit Maintenance Mode and Enable Alarms
|
||||
Set-VMHost -VMHost $VMHostNames -State "Connected" -RunAsync
|
||||
Start-Sleep -Seconds 60
|
||||
foreach ($VMHostName in $VMHostNames){
|
||||
$GetVMHost = Get-VMhost $VMHostName
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $false){
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef,$true)
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
$sctasknum='SCTASK0123474'
|
||||
|
||||
$sctask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $sctasknum -IncludeCustomVariable
|
||||
$request_itemNum = $sctask.request_item.display_value
|
||||
|
||||
$TimeStampString = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
$CommentsToAdd=@"
|
||||
$TimeStampString
|
||||
Added disk
|
||||
"@
|
||||
|
||||
Update-ServiceNowRecord -ID $sctask.number -Values @{comments = $CommentsToAdd} # enter comments into sctask
|
||||
Update-ServiceNowRecord -ID $RitmNum -values @{comments = $CommentsToAdd}
|
||||
If($CloseTask){
|
||||
Update-ServiceNowRecord -Id $sctask.number -Values @{close_notes = $CommentsToAdd; state = "Closed Complete" }
|
||||
}
|
||||
|
||||
|
||||
Update-ServiceNowRecord -ID $sctask.number -Values @{short_description = "VMware VM change for $HostName"}
|
||||
Update-ServiceNowRecord -ID $sctask.number -Values @{assigned_to = "Donald E. Lange"}
|
||||
Update-ServiceNowRecord -ID $sctask.number -Values @{assigned_to = $assignTo.name}
|
||||
|
||||
|
||||
# full auto cpu/memory
|
||||
$SCTaskNum = 'SCTASK0123802'
|
||||
|
||||
$SCTask = Get-ServiceNowRecord -Table 'Catalog Task' -ID $SCTaskNum
|
||||
$RitmNum = $SCTask.request_item.display_value
|
||||
|
||||
$RITM = Get-ServiceNowRecord -Table 'Requested Item' -ID $RitmNum -IncludeCustomVariable
|
||||
|
||||
[string]$HostName = ($RITM.CustomVariable | where-object Name -eq server_name).Value
|
||||
[int]$CPU = ($RITM.CustomVariable | where-object Name -eq Processors).Value
|
||||
[int]$MemoryGB = ($RITM.CustomVariable | where-object Name -eq MemoryGB).Value
|
||||
[int]$Disk1 = ($RITM.CustomVariable | where-object Name -eq disk_1_os).Value
|
||||
[int]$Disk2 = ($RITM.CustomVariable | where-object Name -eq disk_2_swap_disk).Value
|
||||
[int]$Disk3 = ($RITM.CustomVariable | where-object Name -eq disk_3).Value
|
||||
[int]$Disk4 = ($RITM.CustomVariable | where-object Name -eq disk_4).Value
|
||||
[int]$Disk5 = ($RITM.CustomVariable | where-object Name -eq disk_5).Value
|
||||
[int]$Disk6 = ($RITM.CustomVariable | where-object Name -eq disk_6).Value
|
||||
[int]$Disk7 = ($RITM.CustomVariable | where-object Name -eq disk_7).Value
|
||||
[int]$Disk8 = ($RITM.CustomVariable | where-object Name -eq disk_8).Value
|
||||
[int]$Disk9 = ($RITM.CustomVariable | where-object Name -eq disk_9).Value
|
||||
[int]$Disk10 = ($RITM.CustomVariable | where-object Name -eq disk_10).Value
|
||||
[int]$Disk11 = ($RITM.CustomVariable | where-object Name -eq disk_11).Value
|
||||
[int]$Disk12 = ($RITM.CustomVariable | where-object Name -eq disk_12).Value
|
||||
[int]$Disk13 = ($RITM.CustomVariable | where-object Name -eq disk_13).Value
|
||||
[int]$Disk14 = ($RITM.CustomVariable | where-object Name -eq disk_14).Value
|
||||
[int]$Disk15 = ($RITM.CustomVariable | where-object Name -eq disk_15).Value
|
||||
[int]$Disk16 = ($RITM.CustomVariable | where-object Name -eq disk_16).Value
|
||||
|
||||
$VM = Get-VM -Name $HostName* | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
Write-Warning -Message ("VM: " + $VM.Name)
|
||||
|
||||
If($CPU -ne 0){
|
||||
Write-Verbose -Message ($VM.Name + " attempt increasing CPU to " + $CPU)
|
||||
try {
|
||||
$VM | Set-VM -NumCpu $CPU
|
||||
}
|
||||
catch {
|
||||
<#Do this if a terminating exception happens#>
|
||||
}
|
||||
|
||||
}
|
||||
If($MemoryGB -ne 0){
|
||||
Write-Verbose -Message ($VM.Name + " attempt increasing MemoryGB to " + $CPU)
|
||||
try {
|
||||
$VM | Set-VM -MemoryGB $MemoryGB
|
||||
}
|
||||
catch{
|
||||
|
||||
}
|
||||
}
|
||||
If($Disk1){
|
||||
$HardDisk = $VM | Get-HardDisk -Name "Hard disk 1"
|
||||
$Datastore = $HardDisk | Get-Datastore
|
||||
$HardDiskIncreaseGB = $Disk1 - $HardDisk.CapacityGB
|
||||
$FreePercentBefore = ($Datastore.FreeSpaceGB) / $Datastore.CapacityGB
|
||||
$FreePercentAfter = ($Datastore.FreeSpaceGB - $HardDiskIncreaseGB) / $Datastore.CapacityGB
|
||||
|
||||
If ($FreePercentAfter -gt 0.10){
|
||||
Write-Warning -Message ("Hard disk 1: Increasing from " + $HardDisk.CapacityGB + "GB to " + $Disk1 + "GB")
|
||||
#Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore,4)*100 + "% to " + [math]::round($FreePercentAfter,4)*100 + "%")
|
||||
Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore,4) + " to " + [math]::round($FreePercentAfter,4) + "")
|
||||
$VM | Get-HardDisk -Name "Hard disk 1" | Set-HardDisk -CapacityGB $Disk1 -Confirm:$false
|
||||
}
|
||||
Else{
|
||||
Write-Error -Message ("Hard disk 1 failed. 20% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter,4) + ".")
|
||||
}
|
||||
}
|
||||
If($Disk2){
|
||||
#$VM | Get-HardDisk -Name "Hard disk 2" | Set-HardDisk -CapacityGB $Disk2
|
||||
}
|
||||
If($Disk3){
|
||||
#$VM | Get-HardDisk -Name "Hard disk 3" | Set-HardDisk -CapacityGB $Disk3
|
||||
}
|
||||
<#
|
||||
If($Disk4){
|
||||
$VM | Get-HardDisk -Name "Hard disk 4" | Set-HardDisk -CapacityGB $Disk4
|
||||
}
|
||||
If($Disk5){
|
||||
$VM | Get-HardDisk -Name "Hard disk 5" | Set-HardDisk -CapacityGB $Disk5
|
||||
}
|
||||
If($Disk6){
|
||||
$VM | Get-HardDisk -Name "Hard disk 6" | Set-HardDisk -CapacityGB $Disk6
|
||||
}
|
||||
If($Disk7){
|
||||
$VM | Get-HardDisk -Name "Hard disk 7" | Set-HardDisk -CapacityGB $Disk7
|
||||
}
|
||||
If($Disk8){
|
||||
$VM | Get-HardDisk -Name "Hard disk 8" | Set-HardDisk -CapacityGB $Disk8
|
||||
}
|
||||
If($Disk9){
|
||||
$VM | Get-HardDisk -Name "Hard disk 9" | Set-HardDisk -CapacityGB $Disk9
|
||||
}
|
||||
If($Disk10){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk10
|
||||
}
|
||||
If($Disk11){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk11
|
||||
}
|
||||
If($Disk12){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk12
|
||||
}
|
||||
If($Disk13){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk13
|
||||
}
|
||||
If($Disk14){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk14
|
||||
}
|
||||
If($Disk15){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk15
|
||||
}
|
||||
If($Disk16){
|
||||
$VM | Get-HardDisk -Name "Hard disk 10" | Set-HardDisk -CapacityGB $Disk16
|
||||
}#>
|
||||
@@ -0,0 +1,75 @@
|
||||
<#
|
||||
VM level:
|
||||
VM Name
|
||||
Storage provisioned per disk
|
||||
Storage used per disk
|
||||
Free capacity per disk
|
||||
Disk Mode ( dependent persistent vs independent persistent )
|
||||
Disk Type ( Thick, thin, lazy, eager, etc... )
|
||||
Datastore
|
||||
Replication Technology, if applicable
|
||||
Datacenter
|
||||
#>
|
||||
|
||||
$VMStorageList = [System.Collections.ArrayList]@()
|
||||
$AllVMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
ForEach($VM in $AllVMs){
|
||||
$VmObj = [PSCustomObject]@{
|
||||
VMName = $VM.Name;
|
||||
UsedSpaceGB = $VM.UsedSpaceGB;
|
||||
ProvisionedSpaceGB = $VM.ProvisionedSpaceGB;
|
||||
Datastores = ($VM | Get-Datastore).Name
|
||||
DatastoreCluster = ($VM | Get-DatastoreCluster).Name
|
||||
Replication = switch ( ($VM | Get-TagAssignment -Category 'VR RPO').Tag.Name ){
|
||||
{$_ -like "*ABR*"} {"ABR"}
|
||||
{$_ -like "*:*"} {"VR"}
|
||||
Default {$false}
|
||||
}
|
||||
Datacenter = ($VM | Get-Datacenter).Name
|
||||
Disks = $VM | Get-HardDisk | Select-Object Name,CapacityGB,@{n='StorageFormat';e={$_.StorageFormat.ToString()}},@{n='Persistence';e={$_.Persistence.ToString()}}
|
||||
}
|
||||
$null = $VMStorageList.Add($VmObj)
|
||||
}
|
||||
|
||||
$VMStorageList | ConvertTo-Json -Depth 5 | Out-File "C:\temp\VMs.json"
|
||||
|
||||
|
||||
|
||||
|
||||
<#
|
||||
Datastore:
|
||||
Name
|
||||
Capacity provisioned
|
||||
Capacity used
|
||||
Free capacity
|
||||
Associated SAN device backing ( LUN Name )
|
||||
Space Reclamation rate ( MB/s )
|
||||
Datacenter
|
||||
#>
|
||||
|
||||
$AllDatastores = Get-Datastore
|
||||
$DatastoreList = [System.Collections.ArrayList]@()
|
||||
ForEach($Datastore in $AllDatastores){
|
||||
Write-Verbose -Message ("Start " + $Datastore.Name) -Verbose
|
||||
#$Metadata = ($Datastore | Get-ScsiLun | Select-Object -First 1)
|
||||
|
||||
If ( $Datastore.ExtensionData.info.vmfs.UnmapBandwidthSpec.FixedValue){
|
||||
# if reclamation rate is enabled at fixed rate, get that rate
|
||||
$ReclamationRate = ("Enabled at fixed rate: " + $Datastore.ExtensionData.info.vmfs.UnmapBandwidthSpec.FixedValue + " MB/s")
|
||||
} Else {
|
||||
$ReclamationRate = "UnmapBandwidthSpec is null. Enabled at Low priority: Deleted or unmapped blocks are reclaimed on the LUN at low priority"
|
||||
}
|
||||
|
||||
$DatastoreObj = [PSCustomObject]@{
|
||||
Name = $Datastore.Name;
|
||||
CapacityGB = $Datastore.CapacityGB;
|
||||
UsedSpaceGB = ($Datastore.CapacityGB - $Datastore.FreeSpaceGB);
|
||||
FreeSpaceGB = $Datastore.FreeSpaceGB;
|
||||
CanonicalName = ($Datastore | Get-ScsiLun | Select-Object -First 1).CanonicalName;
|
||||
SpaceReclamationRate = $ReclamationRate;
|
||||
Datacenter = ($VMHostToUse | Get-Datacenter).Name
|
||||
}
|
||||
$null = $DatastoreList.Add($DatastoreObj)
|
||||
}
|
||||
|
||||
$DatastoreList | ConvertTo-Json -Depth 5 | Out-File "C:\temp\Datastores.json"
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Daily HPE OneView enclosure and server inventory for PowerBI trending and lifecycle planning.
|
||||
|
||||
.DESCRIPTION
|
||||
Iterates across all configured HPE OneView appliances, collecting enclosure and server
|
||||
hardware metadata including compute capacity, power state, and server profile assignment.
|
||||
Exports timestamped CSVs and inserts into SQL each run.
|
||||
Append daily runs to build a historical dataset for PowerBI trend analysis and
|
||||
physical hardware purchasing / lifecycle decisions.
|
||||
|
||||
Appliances processed:
|
||||
itdoneviewp1.nd.gov - Rack servers only (no enclosures)
|
||||
itdbissyncompp1.nd.gov - Synergy enclosures + servers
|
||||
itdmdnsyncompp1.nd.gov - Synergy enclosures + servers
|
||||
|
||||
.NOTES
|
||||
Run the following DDL once to create the destination tables:
|
||||
|
||||
DROP TABLE IF EXISTS [dbo].[VMware_Trends_Enclosure]
|
||||
|
||||
CREATE TABLE [dbo].[VMware_Trends_Enclosure] (
|
||||
[ReportDate] DATETIME2 NOT NULL,
|
||||
[ApplianceConnection] NVARCHAR(100) NULL,
|
||||
[EnclosureName] NVARCHAR(255) NOT NULL,
|
||||
[EnclosureModel] NVARCHAR(255) NULL,
|
||||
[EnclosureSerialNumber] NVARCHAR(100) NULL,
|
||||
[Status] NVARCHAR(50) NULL,
|
||||
[DeviceBayCount] INT NULL
|
||||
)
|
||||
|
||||
DROP TABLE IF EXISTS [dbo].[VMware_Trends_Server]
|
||||
|
||||
CREATE TABLE [dbo].[VMware_Trends_Server] (
|
||||
[ReportDate] DATETIME2 NOT NULL,
|
||||
[ApplianceConnection] NVARCHAR(100) NULL,
|
||||
[EnclosureName] NVARCHAR(255) NULL,
|
||||
[BayNumber] INT NULL,
|
||||
[ServerHardwareName] NVARCHAR(255) NOT NULL,
|
||||
[ServerName] NVARCHAR(255) NULL,
|
||||
[ServerModel] NVARCHAR(255) NULL,
|
||||
[ServerSerialNumber] NVARCHAR(100) NULL,
|
||||
[Status] NVARCHAR(50) NULL,
|
||||
[PowerState] NVARCHAR(50) NULL,
|
||||
[ServerProfileName] NVARCHAR(255) NULL,
|
||||
[ProcessorType] NVARCHAR(255) NULL,
|
||||
[ProcessorCount] INT NULL,
|
||||
[MemoryGB] DECIMAL(10,2) NULL,
|
||||
[FormFactor] NVARCHAR(100) NULL
|
||||
)
|
||||
|
||||
EnclosureName and BayNumber are NULL for rack-mounted servers not seated in an enclosure.
|
||||
ServerName is the iLO/DNS hostname populated once a server profile is assigned.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
)
|
||||
|
||||
#region --- Setup ---------------------------------------------------------------
|
||||
[string[]] $OVHostnames = @(
|
||||
'itdoneviewp1.nd.gov',
|
||||
'itdbissyncompp1.nd.gov',
|
||||
'itdmdnsyncompp1.nd.gov'
|
||||
)
|
||||
[string] $OutputPath = 'C:\temp\OV_Trends\'
|
||||
[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1'
|
||||
[string] $Database = 'ITD-Systems-Automation'
|
||||
[string] $EnclosureTable = 'VMware_Trends_Enclosure'
|
||||
[string] $ServerTable = 'VMware_Trends_Server'
|
||||
[System.Management.Automation.PSCredential] $OVCredential = $PrvCred #$Secret:ndgov_svcitdvmhpe
|
||||
[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1
|
||||
|
||||
$RunDate = Get-Date
|
||||
$DateStamp = $RunDate.ToString('yyyyMMdd')
|
||||
$Timestamp = $RunDate.ToString('yyyy-MM-dd')
|
||||
|
||||
if (-not (Test-Path -Path $OutputPath)) {
|
||||
New-Item -ItemType Directory -Path $OutputPath | Out-Null
|
||||
}
|
||||
|
||||
Start-Transcript -Path (Join-Path $OutputPath "OVServerInventory_$DateStamp.log") -Append
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Collect Data From All Appliances -----------------------------------
|
||||
|
||||
$AllEnclosureResults = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
$AllServerResults = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
|
||||
foreach ($OVHostname in $OVHostnames) {
|
||||
|
||||
Write-Verbose "Connecting to HPE OneView: $OVHostname"
|
||||
Connect-OVMgmt -Hostname $OVHostname -Credential $OVCredential -AuthLoginDomain nd.gov -LoginAcknowledge
|
||||
|
||||
#--- Enclosures ------------------------------------------------------------
|
||||
|
||||
Write-Verbose "[$OVHostname] Gathering enclosures..."
|
||||
$Enclosures = Get-OVEnclosure
|
||||
|
||||
# Build URI map for server lookups (only populated if there are enclosures)
|
||||
$EnclosureUriMap = @{}
|
||||
foreach ($Enclosure in $Enclosures) {
|
||||
$EnclosureUriMap[$Enclosure.uri] = $Enclosure.name
|
||||
|
||||
$AllEnclosureResults.Add([PSCustomObject]@{
|
||||
ReportDate = $Timestamp
|
||||
ApplianceConnection = $OVHostname
|
||||
EnclosureName = $Enclosure.name
|
||||
EnclosureModel = $Enclosure.model
|
||||
EnclosureSerialNumber = $Enclosure.serialNumber
|
||||
Status = $Enclosure.status
|
||||
DeviceBayCount = ($Enclosure.deviceBays | Measure-Object).Count
|
||||
})
|
||||
}
|
||||
|
||||
#--- Servers ---------------------------------------------------------------
|
||||
|
||||
Write-Verbose "[$OVHostname] Gathering servers..."
|
||||
$Servers = Get-OVServer | Where-Object { $_.serverName -like 'itdvm*' }
|
||||
|
||||
# Build profile URI map for this appliance
|
||||
$ProfileUriMap = @{}
|
||||
Get-OVServerProfile | ForEach-Object {
|
||||
$ProfileUriMap[$_.uri] = $_.name
|
||||
}
|
||||
|
||||
Write-Verbose "[$OVHostname] Processing $($Servers.Count) servers..."
|
||||
|
||||
foreach ($Server in $Servers) {
|
||||
|
||||
$EnclosureName = if ($Server.locationUri) {
|
||||
$EnclosureUriMap[$Server.locationUri]
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
$ProfileName = if ($Server.serverProfileUri) {
|
||||
$ProfileUriMap[$Server.serverProfileUri]
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
$MemoryGB = if ($null -ne $Server.memoryMb -and $Server.memoryMb -gt 0) {
|
||||
[Math]::Round($Server.memoryMb / 1024, 2)
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
$AllServerResults.Add([PSCustomObject]@{
|
||||
ReportDate = $Timestamp
|
||||
ApplianceConnection = $OVHostname
|
||||
EnclosureName = $EnclosureName
|
||||
BayNumber = if ($null -ne $Server.position) { [int]$Server.position } else { $null }
|
||||
ServerHardwareName = $Server.name
|
||||
ServerName = $Server.serverName
|
||||
ServerModel = $Server.model
|
||||
ServerSerialNumber = $Server.serialNumber
|
||||
Status = $Server.status
|
||||
PowerState = $Server.powerState
|
||||
ServerProfileName = $ProfileName
|
||||
ProcessorType = $Server.processorType
|
||||
ProcessorCount = if ($null -ne $Server.processorCount) { [int]$Server.processorCount } else { $null }
|
||||
MemoryGB = $MemoryGB
|
||||
FormFactor = $Server.formFactor
|
||||
})
|
||||
}
|
||||
|
||||
Disconnect-OVMgmt
|
||||
Write-Verbose "[$OVHostname] Disconnected."
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Export CSVs --------------------------------------------------------
|
||||
|
||||
$EnclosureCsv = Join-Path $OutputPath "OVEnclosures_$DateStamp.csv"
|
||||
$ServerCsv = Join-Path $OutputPath "OVServers_$DateStamp.csv"
|
||||
|
||||
$AllEnclosureResults | Export-Csv -Path $EnclosureCsv -NoTypeInformation
|
||||
$AllServerResults | Export-Csv -Path $ServerCsv -NoTypeInformation
|
||||
|
||||
Write-Verbose "Exported $($AllEnclosureResults.Count) enclosure records to: $EnclosureCsv"
|
||||
Write-Verbose "Exported $($AllServerResults.Count) server records to: $ServerCsv"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- SQL Insert: Enclosures ---------------------------------------------
|
||||
|
||||
$EnclosureTable_DT = [System.Data.DataTable]::new()
|
||||
|
||||
$EnclosureColDefs = [ordered]@{
|
||||
ReportDate = [datetime]
|
||||
ApplianceConnection = [string]
|
||||
EnclosureName = [string]
|
||||
EnclosureModel = [string]
|
||||
EnclosureSerialNumber = [string]
|
||||
Status = [string]
|
||||
DeviceBayCount = [int]
|
||||
}
|
||||
|
||||
foreach ($Col in $EnclosureColDefs.GetEnumerator()) {
|
||||
$Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
|
||||
$Column.AllowDBNull = $true
|
||||
[void]$EnclosureTable_DT.Columns.Add($Column)
|
||||
}
|
||||
|
||||
foreach ($Row in $AllEnclosureResults) {
|
||||
$DataRow = $EnclosureTable_DT.NewRow()
|
||||
foreach ($Col in $EnclosureColDefs.Keys) {
|
||||
$Val = $Row.$Col
|
||||
$DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
|
||||
}
|
||||
[void]$EnclosureTable_DT.Rows.Add($DataRow)
|
||||
}
|
||||
|
||||
Write-SqlTableData -ServerInstance $ServerInstance -DatabaseName $Database -SchemaName 'dbo' `
|
||||
-TableName $EnclosureTable -Credential $SqlCredential -InputData $EnclosureTable_DT
|
||||
|
||||
Write-Verbose "Inserted $($EnclosureTable_DT.Rows.Count) enclosure records into [$Database].[dbo].[$EnclosureTable]"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- SQL Insert: Servers ------------------------------------------------
|
||||
|
||||
$ServerTable_DT = [System.Data.DataTable]::new()
|
||||
|
||||
$ServerColDefs = [ordered]@{
|
||||
ReportDate = [datetime]
|
||||
ApplianceConnection = [string]
|
||||
EnclosureName = [string]
|
||||
BayNumber = [int]
|
||||
ServerHardwareName = [string]
|
||||
ServerName = [string]
|
||||
ServerModel = [string]
|
||||
ServerSerialNumber = [string]
|
||||
Status = [string]
|
||||
PowerState = [string]
|
||||
ServerProfileName = [string]
|
||||
ProcessorType = [string]
|
||||
ProcessorCount = [int]
|
||||
MemoryGB = [decimal]
|
||||
FormFactor = [string]
|
||||
}
|
||||
|
||||
foreach ($Col in $ServerColDefs.GetEnumerator()) {
|
||||
$Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
|
||||
$Column.AllowDBNull = $true
|
||||
[void]$ServerTable_DT.Columns.Add($Column)
|
||||
}
|
||||
|
||||
foreach ($Row in $AllServerResults) {
|
||||
$DataRow = $ServerTable_DT.NewRow()
|
||||
foreach ($Col in $ServerColDefs.Keys) {
|
||||
$Val = $Row.$Col
|
||||
$DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
|
||||
}
|
||||
[void]$ServerTable_DT.Rows.Add($DataRow)
|
||||
}
|
||||
|
||||
Write-SqlTableData -ServerInstance $ServerInstance -DatabaseName $Database -SchemaName 'dbo' `
|
||||
-TableName $ServerTable -Credential $SqlCredential -InputData $ServerTable_DT
|
||||
|
||||
Write-Verbose "Inserted $($ServerTable_DT.Rows.Count) server records into [$Database].[dbo].[$ServerTable]"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Cleanup ------------------------------------------------------------
|
||||
Stop-Transcript
|
||||
|
||||
#endregion
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Daily VMware Cluster metadata report for PowerBI trending and capacity planning.
|
||||
|
||||
.DESCRIPTION
|
||||
Collects cluster-level metadata from vCenter including DRS/HA configuration,
|
||||
aggregate compute capacity, and effective resource availability.
|
||||
Exports a timestamped CSV and inserts into SQL each run.
|
||||
Append daily runs to build a historical dataset for PowerBI trend analysis.
|
||||
|
||||
.NOTES
|
||||
Run the following DDL once to create the destination table:
|
||||
|
||||
DROP TABLE IF EXISTS [dbo].[VMware_Trends_Cluster]
|
||||
|
||||
CREATE TABLE [dbo].[VMware_Trends_Cluster] (
|
||||
[ReportDate] DATETIME2 NOT NULL,
|
||||
[ClusterName] NVARCHAR(255) NOT NULL,
|
||||
[Datacenter] NVARCHAR(100) NULL,
|
||||
[DrsEnabled] BIT NOT NULL,
|
||||
[DrsMode] NVARCHAR(50) NULL,
|
||||
[HaEnabled] BIT NOT NULL,
|
||||
[HostCount] INT NULL,
|
||||
[EffectiveHostCount] INT NULL,
|
||||
[TotalCpuCores] INT NULL,
|
||||
[TotalCpuMhz] INT NULL,
|
||||
[EffectiveCpuMhz] INT NULL,
|
||||
[TotalMemoryGB] DECIMAL(10,2) NULL,
|
||||
[EffectiveMemoryGB] DECIMAL(10,2) NULL,
|
||||
[UsedMemoryGB] DECIMAL(10,2) NULL,
|
||||
[VMCount] INT NULL
|
||||
)
|
||||
|
||||
TotalCpuMhz, EffectiveCpuMhz, TotalMemoryGB, and EffectiveMemoryGB come from
|
||||
vCenter's cluster summary (real-time aggregate).
|
||||
UsedMemoryGB is summed from each host's current MemoryUsageGB.
|
||||
TotalCpuCores is summed from each host's hardware CpuInfo.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
)
|
||||
|
||||
#region --- Setup ---------------------------------------------------------------
|
||||
[string] $OutputPath = 'C:\temp\VM_Trends\'
|
||||
[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1'
|
||||
[string] $Database = 'ITD-Systems-Automation'
|
||||
[string] $Table = 'VMware_Trends_Cluster'
|
||||
[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1
|
||||
|
||||
$RunDate = Get-Date
|
||||
$DateStamp = $RunDate.ToString('yyyyMMdd')
|
||||
$Timestamp = $RunDate.ToString('yyyy-MM-dd')
|
||||
|
||||
if (-not (Test-Path -Path $OutputPath)) {
|
||||
New-Item -ItemType Directory -Path $OutputPath | Out-Null
|
||||
}
|
||||
|
||||
Start-Transcript -Path (Join-Path $OutputPath "ClusterMetadataReport_$DateStamp.log") -Append
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Build Cluster -> Datacenter Lookup ---------------------------------
|
||||
|
||||
Write-Verbose 'Building cluster-to-datacenter map...'
|
||||
$ClusterDatacenterMap = @{}
|
||||
|
||||
Get-Datacenter | ForEach-Object {
|
||||
$DatacenterName = $_.Name
|
||||
Get-Cluster -Location $_ | ForEach-Object {
|
||||
$ClusterDatacenterMap[$_.Name] = $DatacenterName
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Collect Cluster Data -----------------------------------------------
|
||||
|
||||
Write-Verbose 'Gathering clusters...'
|
||||
$AllClusters = Get-Cluster
|
||||
|
||||
Write-Verbose "Processing $($AllClusters.Count) clusters..."
|
||||
|
||||
$Results = foreach ($Cluster in $AllClusters) {
|
||||
|
||||
$Summary = $Cluster.ExtensionData.Summary # reuse for all summary fields
|
||||
|
||||
#--- Aggregate host-level stats that vCenter summary does not expose
|
||||
$ClusterHosts = Get-VMHost -Location $Cluster
|
||||
$TotalCpuCores = ($ClusterHosts | ForEach-Object {
|
||||
$_.ExtensionData.Hardware.CpuInfo.NumCpuCores
|
||||
} | Measure-Object -Sum).Sum
|
||||
$UsedMemoryGB = [Math]::Round(
|
||||
($ClusterHosts | Measure-Object -Property MemoryUsageGB -Sum).Sum, 2
|
||||
)
|
||||
$VMCount = ($ClusterHosts | ForEach-Object {
|
||||
($_.ExtensionData.Vm | Measure-Object).Count
|
||||
} | Measure-Object -Sum).Sum
|
||||
|
||||
#--- Capacity from cluster summary
|
||||
$TotalCpuMhz = $Summary.TotalCpu # MHz
|
||||
$EffectiveCpuMhz = $Summary.EffectiveCpu # MHz
|
||||
$TotalMemoryGB = [Math]::Round($Summary.TotalMemory / 1GB, 2) # bytes -> GB
|
||||
$EffectiveMemGB = [Math]::Round($Summary.EffectiveMemory / 1KB, 2) # MB -> GB
|
||||
|
||||
[PSCustomObject]@{
|
||||
ReportDate = $Timestamp
|
||||
ClusterName = $Cluster.Name
|
||||
Datacenter = $ClusterDatacenterMap[$Cluster.Name]
|
||||
DrsEnabled = $Cluster.DrsEnabled
|
||||
DrsMode = $Cluster.DrsAutomationLevel
|
||||
HaEnabled = $Cluster.HAEnabled
|
||||
HostCount = $Summary.NumHosts
|
||||
EffectiveHostCount = $Summary.NumEffectiveHosts
|
||||
TotalCpuCores = [int]$TotalCpuCores
|
||||
TotalCpuMhz = $TotalCpuMhz
|
||||
EffectiveCpuMhz = $EffectiveCpuMhz
|
||||
TotalMemoryGB = $TotalMemoryGB
|
||||
EffectiveMemoryGB = $EffectiveMemGB
|
||||
UsedMemoryGB = $UsedMemoryGB
|
||||
VMCount = [int]$VMCount
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Export CSV ---------------------------------------------------------
|
||||
|
||||
$OutputFile = Join-Path $OutputPath "ClusterMetadata_$DateStamp.csv"
|
||||
$Results | Export-Csv -Path $OutputFile -NoTypeInformation
|
||||
Write-Verbose "Exported $($Results.Count) cluster records to: $OutputFile"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- SQL Insert ---------------------------------------------------------
|
||||
|
||||
$DataTable = [System.Data.DataTable]::new()
|
||||
|
||||
$ColDefs = [ordered]@{
|
||||
ReportDate = [datetime]
|
||||
ClusterName = [string]
|
||||
Datacenter = [string]
|
||||
DrsEnabled = [bool]
|
||||
DrsMode = [string]
|
||||
HaEnabled = [bool]
|
||||
HostCount = [int]
|
||||
EffectiveHostCount = [int]
|
||||
TotalCpuCores = [int]
|
||||
TotalCpuMhz = [int]
|
||||
EffectiveCpuMhz = [int]
|
||||
TotalMemoryGB = [decimal]
|
||||
EffectiveMemoryGB = [decimal]
|
||||
UsedMemoryGB = [decimal]
|
||||
VMCount = [int]
|
||||
}
|
||||
|
||||
foreach ($Col in $ColDefs.GetEnumerator()) {
|
||||
$Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
|
||||
$Column.AllowDBNull = $true
|
||||
[void]$DataTable.Columns.Add($Column)
|
||||
}
|
||||
|
||||
foreach ($Row in $Results) {
|
||||
$DataRow = $DataTable.NewRow()
|
||||
foreach ($Col in $ColDefs.Keys) {
|
||||
$Val = $Row.$Col
|
||||
$DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
|
||||
}
|
||||
[void]$DataTable.Rows.Add($DataRow)
|
||||
}
|
||||
|
||||
$SqlParams = @{
|
||||
ServerInstance = $ServerInstance
|
||||
DatabaseName = $Database
|
||||
SchemaName = 'dbo'
|
||||
TableName = $Table
|
||||
Credential = $SqlCredential
|
||||
InputData = $DataTable
|
||||
}
|
||||
Write-SqlTableData @SqlParams
|
||||
|
||||
Write-Verbose "Inserted $($DataTable.Rows.Count) cluster records into [$Database].[dbo].[$Table]"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Cleanup -------------------------------------------------------------
|
||||
Stop-Transcript
|
||||
|
||||
#endregion
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Daily VMware Host metadata report for PowerBI trending and hardware capacity planning.
|
||||
|
||||
.DESCRIPTION
|
||||
Collects ESXi host metadata from vCenter including hardware, compute capacity, and
|
||||
version information. Exports a timestamped CSV and inserts into SQL each run.
|
||||
Append daily runs to build a historical dataset for PowerBI trend analysis and
|
||||
physical hardware purchasing / lifecycle decisions.
|
||||
|
||||
.NOTES
|
||||
Run the following DDL once to create the destination table:
|
||||
|
||||
DROP TABLE IF EXISTS [dbo].[VMware_Trends_Host]
|
||||
|
||||
CREATE TABLE [dbo].[VMware_Trends_Host] (
|
||||
[ReportDate] DATETIME2 NOT NULL,
|
||||
[HostName] NVARCHAR(255) NOT NULL,
|
||||
[Datacenter] NVARCHAR(100) NULL,
|
||||
[Cluster] NVARCHAR(100) NULL,
|
||||
[ConnectionState] NVARCHAR(50) NULL,
|
||||
[PowerState] NVARCHAR(50) NULL,
|
||||
[InMaintenanceMode] BIT NOT NULL,
|
||||
[Model] NVARCHAR(255) NULL,
|
||||
[ProcessorType] NVARCHAR(255) NULL,
|
||||
[CpuSockets] INT NULL,
|
||||
[CoresPerSocket] INT NULL,
|
||||
[TotalCpuCores] INT NULL,
|
||||
[CpuMhz] INT NULL,
|
||||
[TotalCpuMhz] INT NULL,
|
||||
[MemoryTotalGB] DECIMAL(10,2) NULL,
|
||||
[MemoryUsageGB] DECIMAL(10,2) NULL,
|
||||
[VMCount] INT NULL,
|
||||
[EsxiVersion] NVARCHAR(50) NULL,
|
||||
[EsxiBuild] NVARCHAR(50) NULL,
|
||||
[UptimeDays] DECIMAL(10,2) NULL
|
||||
)
|
||||
|
||||
MemoryUsageGB reflects real-time memory consumed by running VMs at the time of collection.
|
||||
UptimeDays will be NULL for hosts that are powered off or disconnected.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
)
|
||||
|
||||
#region --- Setup ---------------------------------------------------------------
|
||||
[string] $OutputPath = 'C:\temp\VM_Trends\'
|
||||
[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1'
|
||||
[string] $Database = 'ITD-Systems-Automation'
|
||||
[string] $Table = 'VMware_Trends_Host'
|
||||
[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1
|
||||
|
||||
$RunDate = Get-Date
|
||||
$DateStamp = $RunDate.ToString('yyyyMMdd')
|
||||
$Timestamp = $RunDate.ToString('yyyy-MM-dd')
|
||||
|
||||
if (-not (Test-Path -Path $OutputPath)) {
|
||||
New-Item -ItemType Directory -Path $OutputPath | Out-Null
|
||||
}
|
||||
|
||||
Start-Transcript -Path (Join-Path $OutputPath "VMHostMetadataReport_$DateStamp.log") -Append
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-host queries) -
|
||||
|
||||
Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...'
|
||||
$HostClusterMap = @{}
|
||||
$HostDatacenterMap = @{}
|
||||
|
||||
Get-Datacenter | ForEach-Object {
|
||||
$DatacenterName = $_.Name
|
||||
Get-VMHost -Location $_ | ForEach-Object {
|
||||
$HostDatacenterMap[$_.Name] = $DatacenterName
|
||||
}
|
||||
}
|
||||
|
||||
Get-Cluster | ForEach-Object {
|
||||
$ClusterName = $_.Name
|
||||
Get-VMHost -Location $_ | ForEach-Object {
|
||||
$HostClusterMap[$_.Name] = $ClusterName
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Collect Host Data --------------------------------------------------
|
||||
|
||||
Write-Verbose 'Gathering hosts...'
|
||||
$AllHosts = $HostDatacenterMap.Keys | ForEach-Object { Get-VMHost -Name $_ }
|
||||
|
||||
Write-Verbose "Processing $($AllHosts.Count) hosts..."
|
||||
|
||||
$Results = foreach ($VMHost in $AllHosts) {
|
||||
|
||||
$Ext = $VMHost.ExtensionData # single API object -- reuse for all fields
|
||||
|
||||
#--- CPU info from hardware summary
|
||||
$CpuSockets = $Ext.Hardware.CpuInfo.NumCpuPackages
|
||||
$TotalCpuCores = $Ext.Hardware.CpuInfo.NumCpuCores
|
||||
$CoresPerSocket = if ($CpuSockets -gt 0) { [int]($TotalCpuCores / $CpuSockets) } else { $null }
|
||||
$CpuMhz = $Ext.Hardware.CpuInfo.Hz / 1000000 # Hz -> MHz
|
||||
$TotalCpuMhz = $Ext.Summary.Hardware.CpuMhz * $TotalCpuCores
|
||||
|
||||
#--- Memory
|
||||
$MemoryTotalGB = [Math]::Round($VMHost.MemoryTotalGB, 2)
|
||||
$MemoryUsageGB = [Math]::Round($VMHost.MemoryUsageGB, 2)
|
||||
|
||||
#--- VM count on this host right now
|
||||
$VMCount = ($Ext.Vm | Measure-Object).Count
|
||||
|
||||
#--- Uptime (null when host is powered off / disconnected)
|
||||
$UptimeDays = $null
|
||||
$BootTime = $Ext.Runtime.BootTime
|
||||
if ($null -ne $BootTime) {
|
||||
$UptimeDays = [Math]::Round(($RunDate - $BootTime).TotalDays, 2)
|
||||
}
|
||||
|
||||
[PSCustomObject]@{
|
||||
ReportDate = $Timestamp
|
||||
HostName = $VMHost.Name
|
||||
Datacenter = $HostDatacenterMap[$VMHost.Name]
|
||||
Cluster = $HostClusterMap[$VMHost.Name]
|
||||
ConnectionState = $VMHost.ConnectionState
|
||||
PowerState = $VMHost.PowerState
|
||||
InMaintenanceMode = $VMHost.ExtensionData.Runtime.InMaintenanceMode
|
||||
Model = $Ext.Hardware.SystemInfo.Model
|
||||
ProcessorType = $VMHost.ProcessorType
|
||||
CpuSockets = $CpuSockets
|
||||
CoresPerSocket = $CoresPerSocket
|
||||
TotalCpuCores = $TotalCpuCores
|
||||
CpuMhz = [int]$CpuMhz
|
||||
TotalCpuMhz = $TotalCpuMhz
|
||||
MemoryTotalGB = $MemoryTotalGB
|
||||
MemoryUsageGB = $MemoryUsageGB
|
||||
VMCount = $VMCount
|
||||
EsxiVersion = $VMHost.Version
|
||||
EsxiBuild = $VMHost.Build
|
||||
UptimeDays = $UptimeDays
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Export CSV ---------------------------------------------------------
|
||||
|
||||
$OutputFile = Join-Path $OutputPath "VMHostMetadata_$DateStamp.csv"
|
||||
$Results | Export-Csv -Path $OutputFile -NoTypeInformation
|
||||
Write-Verbose "Exported $($Results.Count) host records to: $OutputFile"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- SQL Insert ---------------------------------------------------------
|
||||
|
||||
$DataTable = [System.Data.DataTable]::new()
|
||||
|
||||
$ColDefs = [ordered]@{
|
||||
ReportDate = [datetime]
|
||||
HostName = [string]
|
||||
Datacenter = [string]
|
||||
Cluster = [string]
|
||||
ConnectionState = [string]
|
||||
PowerState = [string]
|
||||
InMaintenanceMode = [bool]
|
||||
Model = [string]
|
||||
ProcessorType = [string]
|
||||
CpuSockets = [int]
|
||||
CoresPerSocket = [int]
|
||||
TotalCpuCores = [int]
|
||||
CpuMhz = [int]
|
||||
TotalCpuMhz = [int]
|
||||
MemoryTotalGB = [decimal]
|
||||
MemoryUsageGB = [decimal]
|
||||
VMCount = [int]
|
||||
EsxiVersion = [string]
|
||||
EsxiBuild = [string]
|
||||
UptimeDays = [decimal]
|
||||
}
|
||||
|
||||
foreach ($Col in $ColDefs.GetEnumerator()) {
|
||||
$Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
|
||||
$Column.AllowDBNull = $true
|
||||
[void]$DataTable.Columns.Add($Column)
|
||||
}
|
||||
|
||||
foreach ($Row in $Results) {
|
||||
$DataRow = $DataTable.NewRow()
|
||||
foreach ($Col in $ColDefs.Keys) {
|
||||
$Val = $Row.$Col
|
||||
$DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
|
||||
}
|
||||
[void]$DataTable.Rows.Add($DataRow)
|
||||
}
|
||||
|
||||
$SqlParams = @{
|
||||
ServerInstance = $ServerInstance
|
||||
DatabaseName = $Database
|
||||
SchemaName = 'dbo'
|
||||
TableName = $Table
|
||||
Credential = $SqlCredential
|
||||
InputData = $DataTable
|
||||
}
|
||||
Write-SqlTableData @SqlParams
|
||||
|
||||
Write-Verbose "Inserted $($DataTable.Rows.Count) host records into [$Database].[dbo].[$Table]"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Cleanup -------------------------------------------------------------
|
||||
Stop-Transcript
|
||||
|
||||
#endregion
|
||||
+299
@@ -0,0 +1,299 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Daily VM metadata report for PowerBI trending and hardware capacity planning.
|
||||
|
||||
.DESCRIPTION
|
||||
Collects VM metadata from vCenter including compute, storage, OS, and VMware Tools
|
||||
information using only data available within vCenter (no direct guest connections).
|
||||
Exports a timestamped CSV each run -- append daily runs to build a historical dataset
|
||||
suitable for PowerBI trend analysis and physical hardware purchasing decisions.
|
||||
|
||||
.PARAMETER vCenterServers
|
||||
One or more vCenter server hostnames. Defaults to itdvmvc1.nd.gov and itdvmvc2.nd.gov.
|
||||
|
||||
.PARAMETER DatacenterFilter
|
||||
Wildcard filter applied to datacenter names. Defaults to 'Primary*'.
|
||||
|
||||
.PARAMETER OutputPath
|
||||
Directory where CSV and log files are written.
|
||||
Defaults to C:\ITDSCRIPT\Reports\VMMetadata.
|
||||
|
||||
.PARAMETER CredentialPath
|
||||
Path to a saved PSCredential XML file for unattended/scheduled runs.
|
||||
Create one interactively with:
|
||||
Get-Credential | Export-Clixml -Path C:\ITDSCRIPT\Creds\vCenter.xml
|
||||
When omitted the script prompts for credentials.
|
||||
|
||||
.EXAMPLE
|
||||
# Interactive run
|
||||
.\VMware-VMDailyMetadataReport.ps1
|
||||
|
||||
.EXAMPLE
|
||||
# Scheduled / unattended run
|
||||
.\VMware-VMDailyMetadataReport.ps1 -CredentialPath 'C:\ITDSCRIPT\Creds\vCenter.xml'
|
||||
|
||||
.NOTES
|
||||
Run the following DDL once to create the destination table:
|
||||
|
||||
DROP TABLE IF EXISTS [dbo].[VMware_Trends_VM]
|
||||
|
||||
CREATE TABLE [dbo].[VMware_Trends_VM] (
|
||||
[ReportDate] DATETIME2 NOT NULL,
|
||||
[VMName] NVARCHAR(255) NOT NULL,
|
||||
[Datacenter] NVARCHAR(100) NULL,
|
||||
[Cluster] NVARCHAR(100) NULL,
|
||||
[PowerState] NVARCHAR(50) NULL,
|
||||
[IsSRMPlaceholder] BIT NOT NULL,
|
||||
[StoragePlatform] NVARCHAR(100) NULL,
|
||||
[GuestOS] NVARCHAR(255) NULL,
|
||||
[vCPUs] INT NULL,
|
||||
[MemoryGB] DECIMAL(10,2) NULL,
|
||||
[ProvisionedSpaceGB] DECIMAL(12,2) NULL,
|
||||
[UsedSpaceGB] DECIMAL(12,2) NULL,
|
||||
[GuestDiskCapacityGB] DECIMAL(12,2) NULL,
|
||||
[GuestDiskUsedGB] DECIMAL(12,2) NULL,
|
||||
[ToolsRunningStatus] NVARCHAR(100) NULL,
|
||||
[ToolsVersionStatus] NVARCHAR(100) NULL,
|
||||
[ToolsVersion] NVARCHAR(50) NULL,
|
||||
[Tag_DRProtection] NVARCHAR(100) NULL,
|
||||
[Tag_AppName] NVARCHAR(255) NULL,
|
||||
[Tag_VRDatastores] NVARCHAR(255) NULL,
|
||||
[Tag_VRRPO] NVARCHAR(100) NULL,
|
||||
[Tag_DTAP] NVARCHAR(50) NULL,
|
||||
[Tag_StartupPriority] NVARCHAR(100) NULL,
|
||||
[Tag_SRMRecoveryType] NVARCHAR(100) NULL,
|
||||
[Tag_LicensingRestrictions] NVARCHAR(255) NULL
|
||||
)
|
||||
|
||||
Guest OS disk capacity / used columns are NULL for powered-off VMs and SRM placeholders.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
)
|
||||
|
||||
#region --- Setup ---------------------------------------------------------------
|
||||
[string] $OutputPath = 'C:\temp\VM_Trends\'
|
||||
[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1'
|
||||
[string] $Database = 'ITD-Systems-Automation'
|
||||
[string] $Table = 'VMware_Trends_VM'
|
||||
[System.Management.Automation.PSCredential] $SqlCredential = $SqlCred #$Secret:sql_itdpsu1
|
||||
[System.Management.Automation.PSCredential] $vCenterCredential = $PrvCred
|
||||
|
||||
$RunDate = Get-Date
|
||||
$DateStamp = $RunDate.ToString('yyyyMMdd')
|
||||
$Timestamp = $RunDate.ToString('yyyy-MM-dd')
|
||||
|
||||
if (-not (Test-Path -Path $OutputPath)) {
|
||||
New-Item -ItemType Directory -Path $OutputPath | Out-Null
|
||||
}
|
||||
|
||||
Start-Transcript -Path (Join-Path $OutputPath "VMMetadataReport_$DateStamp.log") -Append
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-VM API calls) -
|
||||
|
||||
Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...'
|
||||
$HostClusterMap = @{}
|
||||
$HostDatacenterMap = @{}
|
||||
|
||||
Get-Datacenter | ForEach-Object {
|
||||
$DatacenterName = $_.Name
|
||||
Get-VMHost -Location $_ | ForEach-Object {
|
||||
$HostDatacenterMap[$_.Name] = $DatacenterName
|
||||
}
|
||||
}
|
||||
|
||||
Get-Cluster | ForEach-Object {
|
||||
$ClusterName = $_.Name
|
||||
Get-VMHost -Location $_ | ForEach-Object {
|
||||
$HostClusterMap[$_.Name] = $ClusterName
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Collect VM Data -----------------------------------------------------
|
||||
|
||||
Write-Verbose "Gathering VMs"
|
||||
|
||||
# Include ALL VMs (SRM placeholders flagged via column, not excluded).
|
||||
# vCLS agent VMs are excluded -- they are vSphere internal and not customer workloads.
|
||||
$AllVMs = Get-VM | Where-Object { $_.Name -notlike 'vCLS*' }
|
||||
|
||||
#--- Pre-fetch all tag assignments in one API call (avoids per-VM Get-TagAssignment)
|
||||
Write-Verbose 'Pre-fetching VM tag assignments...'
|
||||
$TagLookup = @{}
|
||||
Get-TagAssignment -Entity $AllVMs | ForEach-Object {
|
||||
$VMId = $_.Entity.Id
|
||||
$Cat = $_.Tag.Category.Name
|
||||
$TagName = $_.Tag.Name
|
||||
if (-not $TagLookup.ContainsKey($VMId)) { $TagLookup[$VMId] = @{} }
|
||||
if ($TagLookup[$VMId].ContainsKey($Cat)) {
|
||||
$TagLookup[$VMId][$Cat] += "; $TagName"
|
||||
} else {
|
||||
$TagLookup[$VMId][$Cat] = $TagName
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Processing $($AllVMs.Count) VMs..."
|
||||
|
||||
$Results = foreach ($VM in $AllVMs) {
|
||||
|
||||
$Ext = $VM.ExtensionData # single API object -- reuse for all fields
|
||||
|
||||
#--- SRM placeholder detection
|
||||
$IsSRMPlaceholder = $Ext.Summary.Config.ManagedBy.Type -eq 'placeholderVm'
|
||||
|
||||
#--- Cluster / Datacenter (null-safe: standalone hosts have no cluster entry)
|
||||
$ClusterName = $HostClusterMap[$VM.VMHost.Name]
|
||||
$DatacenterName = $HostDatacenterMap[$VM.VMHost.Name]
|
||||
|
||||
#--- Tag assignments (pre-fetched; null when category not assigned to this VM)
|
||||
$VMTags = if ($TagLookup.ContainsKey($VM.Id)) { $TagLookup[$VM.Id] } else { @{} }
|
||||
|
||||
#--- Storage platform parsed from datastore name convention: VMCLUSTER_LUN_PLATFORM_Desc
|
||||
# Segment 2 = storage platform identifier (e.g. FS92, A9K).
|
||||
# Cluster grouping uses the compute Cluster column -- no need to re-derive it here.
|
||||
$StoragePlatforms = foreach ($DSName in $Ext.Config.DatastoreUrl.Name) {
|
||||
$Segments = $DSName -split '_'
|
||||
if ($Segments.Count -ge 3) { $Segments[2] }
|
||||
}
|
||||
$StoragePlatform = ($StoragePlatforms | Sort-Object -Unique) -join '; '
|
||||
|
||||
#--- VMware Tools guest disk info
|
||||
# Populated only when Tools is running; null otherwise.
|
||||
$GuestDiskCapacityGB = $null
|
||||
$GuestDiskUsedGB = $null
|
||||
if ($Ext.Guest.Disk) {
|
||||
$TotalCapBytes = ($Ext.Guest.Disk | Measure-Object -Property Capacity -Sum).Sum
|
||||
$TotalFreeBytes = ($Ext.Guest.Disk | Measure-Object -Property FreeSpace -Sum).Sum
|
||||
$GuestDiskCapacityGB = [Math]::Round($TotalCapBytes / 1GB, 2)
|
||||
$GuestDiskUsedGB = [Math]::Round(($TotalCapBytes - $TotalFreeBytes) / 1GB, 2)
|
||||
}
|
||||
|
||||
[PSCustomObject]@{
|
||||
# --- Identity & grouping
|
||||
ReportDate = $Timestamp # for PowerBI time-series/trend axis
|
||||
VMName = $VM.Name
|
||||
Datacenter = $DatacenterName
|
||||
Cluster = $ClusterName
|
||||
PowerState = $VM.PowerState
|
||||
IsSRMPlaceholder = $IsSRMPlaceholder
|
||||
StoragePlatform = $StoragePlatform
|
||||
GuestOS = $Ext.Guest.GuestFullName
|
||||
|
||||
# --- Compute
|
||||
vCPUs = $VM.NumCpu
|
||||
MemoryGB = $VM.MemoryGB
|
||||
|
||||
# --- Datastore-level storage
|
||||
# ProvisionedSpaceGB : maximum the VM could consume (thin disks counted at max size)
|
||||
# UsedSpaceGB : bytes actually committed on datastores right now
|
||||
ProvisionedSpaceGB = [Math]::Round($VM.ProvisionedSpaceGB, 2)
|
||||
UsedSpaceGB = [Math]::Round($VM.UsedSpaceGB, 2)
|
||||
|
||||
# --- Guest OS-level storage (from VMware Tools; null when Tools not running)
|
||||
# GuestDiskCapacityGB : sum of all volume capacities seen inside the guest
|
||||
# GuestDiskUsedGB : sum of space consumed across those volumes
|
||||
GuestDiskCapacityGB = $GuestDiskCapacityGB
|
||||
GuestDiskUsedGB = $GuestDiskUsedGB
|
||||
|
||||
# --- VMware Tools
|
||||
# ToolsRunningStatus : guestToolsRunning | guestToolsNotRunning | guestToolsExecutingScripts
|
||||
# ToolsVersionStatus : guestToolsCurrent | guestToolsNeedUpgrade | guestToolsUnmanaged | guestToolsTooNew
|
||||
# ToolsVersion : numeric build version string reported by vCenter
|
||||
ToolsRunningStatus = $Ext.Guest.ToolsRunningStatus
|
||||
ToolsVersionStatus = $Ext.Guest.ToolsVersionStatus
|
||||
ToolsVersion = $Ext.Guest.ToolsVersion
|
||||
|
||||
# --- vCenter Tags
|
||||
Tag_DRProtection = $VMTags['DR Protection']
|
||||
Tag_AppName = $VMTags['AppName']
|
||||
Tag_VRDatastores = $VMTags['VR Datastores']
|
||||
Tag_VRRPO = $VMTags['VR RPO']
|
||||
Tag_DTAP = $VMTags['DTAP']
|
||||
Tag_StartupPriority = $VMTags['StartupPriority']
|
||||
Tag_SRMRecoveryType = $VMTags['SRM Recovery Type']
|
||||
Tag_LicensingRestrictions = $VMTags['LicensingRestrictions']
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
<#region --- Export CSV ---------------------------------------------------------
|
||||
|
||||
$OutputFile = Join-Path $OutputPath "VMMetadata_$DateStamp.csv"
|
||||
$Results | Export-Csv -Path $OutputFile -NoTypeInformation
|
||||
Write-Verbose "Exported $($Results.Count) VM records to: $OutputFile"
|
||||
|
||||
#endregion
|
||||
#>
|
||||
#region --- SQL Insert ---------------------------------------------------------
|
||||
|
||||
# Build a typed DataTable so Write-SqlTableData knows each column's type
|
||||
# even when nullable columns contain null values. Type inference from raw
|
||||
# PSCustomObjects fails when the first row has a null in a numeric column.
|
||||
$DataTable = [System.Data.DataTable]::new()
|
||||
|
||||
$ColDefs = [ordered]@{
|
||||
ReportDate = [datetime]
|
||||
VMName = [string]
|
||||
Datacenter = [string]
|
||||
Cluster = [string]
|
||||
PowerState = [string]
|
||||
IsSRMPlaceholder = [bool]
|
||||
StoragePlatform = [string]
|
||||
GuestOS = [string]
|
||||
vCPUs = [int]
|
||||
MemoryGB = [decimal]
|
||||
ProvisionedSpaceGB = [decimal]
|
||||
UsedSpaceGB = [decimal]
|
||||
GuestDiskCapacityGB = [decimal]
|
||||
GuestDiskUsedGB = [decimal]
|
||||
ToolsRunningStatus = [string]
|
||||
ToolsVersionStatus = [string]
|
||||
ToolsVersion = [string]
|
||||
Tag_DRProtection = [string]
|
||||
Tag_AppName = [string]
|
||||
Tag_VRDatastores = [string]
|
||||
Tag_VRRPO = [string]
|
||||
Tag_DTAP = [string]
|
||||
Tag_StartupPriority = [string]
|
||||
Tag_SRMRecoveryType = [string]
|
||||
Tag_LicensingRestrictions = [string]
|
||||
}
|
||||
|
||||
foreach ($Col in $ColDefs.GetEnumerator()) {
|
||||
$Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
|
||||
$Column.AllowDBNull = $true
|
||||
[void]$DataTable.Columns.Add($Column)
|
||||
}
|
||||
|
||||
foreach ($Row in $Results) {
|
||||
$DataRow = $DataTable.NewRow()
|
||||
foreach ($Col in $ColDefs.Keys) {
|
||||
$Val = $Row.$Col
|
||||
$DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
|
||||
}
|
||||
[void]$DataTable.Rows.Add($DataRow)
|
||||
}
|
||||
|
||||
$SqlParams = @{
|
||||
ServerInstance = $ServerInstance
|
||||
DatabaseName = $Database
|
||||
SchemaName = 'dbo'
|
||||
TableName = $Table
|
||||
Credential = $SqlCredential
|
||||
InputData = $DataTable
|
||||
}
|
||||
Write-SqlTableData @SqlParams
|
||||
|
||||
Write-Verbose "Inserted $($DataTable.Rows.Count) VM records into [$Database].[dbo].[$Table]"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Cleanup -------------------------------------------------------------
|
||||
Stop-Transcript
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1,95 @@
|
||||
$VMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }
|
||||
|
||||
$SettingName = @(
|
||||
"tools.setInfo.sizeLimit",
|
||||
"isolation.device.edit.disable",
|
||||
"isolation.device.connectable.disable",
|
||||
"isolation.tools.copy.disable",
|
||||
"isolation.tools.dnd.disable",
|
||||
"isolation.tools.setGUIOptions.enable",
|
||||
"RemoteDisplay.vnc.enabled",
|
||||
"isolation.tools.paste.disable",
|
||||
"isolation.tools.diskShrink.disable",
|
||||
"isolation.tools.diskWiper.disable",
|
||||
"log.keepOld",
|
||||
"log.rotateSize"
|
||||
)
|
||||
|
||||
$Result = [System.Collections.ArrayList]@()
|
||||
ForEach ($VM in $VMs) {
|
||||
$GetAdvSetting = Get-AdvancedSetting -Entity $VM -Name $SettingName | select Entity, Name, Value
|
||||
$obj = [PSCustomObject]@{
|
||||
'Entity' = $VM.Name
|
||||
"tools.setInfo.sizeLimit" = ($GetAdvSetting | Where-Object Name -EQ 'tools.setInfo.sizeLimit').Value
|
||||
"isolation.device.edit.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.edit.disable').Value
|
||||
"isolation.device.connectable.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.device.connectable.disable').Value
|
||||
"isolation.tools.copy.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.copy.disable').Value
|
||||
"isolation.tools.dnd.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.dnd.disable').Value
|
||||
"isolation.tools.setGUIOptions.enable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.setGUIOptions.enable').Value
|
||||
"RemoteDisplay.vnc.enabled" = ($GetAdvSetting | Where-Object Name -EQ 'RemoteDisplay.vnc.enabled').Value
|
||||
"isolation.tools.paste.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.paste.disable').Value
|
||||
"isolation.tools.diskShrink.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskShrink.disable').Value
|
||||
"isolation.tools.diskWiper.disable" = ($GetAdvSetting | Where-Object Name -EQ 'isolation.tools.diskWiper.disable').Value
|
||||
"log.keepOld" = ($GetAdvSetting | Where-Object Name -EQ 'log.keepOld').Value
|
||||
"log.rotateSize" = ($GetAdvSetting | Where-Object Name -EQ 'log.rotateSize').Value
|
||||
}
|
||||
$Result.Add($obj)
|
||||
}
|
||||
|
||||
$Result
|
||||
|
||||
|
||||
<# Blank Loop
|
||||
ForEach-Object( ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'' -ne "VALUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name '' -Value TRUE -Confirm:$false -Force:$true
|
||||
}
|
||||
#>
|
||||
|
||||
# remediate VMs
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'tools.setInfo.sizeLimit' -ne 1048576 }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'tools.setInfo.sizeLimit' -Value '1048576' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.device.edit.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.device.edit.disable' -Value 'TRUE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.device.connectable.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.device.connectable.disable' -Value TRUE -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.copy.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.tools.copy.disable' -Value 'TRUE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.dnd.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.tools.dnd.disable' -Value 'TRUE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.setGUIOptions.enable' -ne "FALSE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.tools.setGUIOptions.enable' -Value 'FALSE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'RemoteDisplay.vnc.enabled' -ne "FALSE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'RemoteDisplay.vnc.enabled' -Value 'FALSE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.paste.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.tools.paste.disable' -Value 'TRUE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.diskShrink.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.tools.diskShrink.disable' -Value 'TRUE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'isolation.tools.diskWiper.disable' -ne "TRUE" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'isolation.tools.diskWiper.disable' -Value 'TRUE' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'log.keepOld' -ne "10" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'log.keepOld' -Value '10' -Confirm:$false -Force:$true
|
||||
}
|
||||
|
||||
ForEach ($VM in ($Result | Where-Object { $_.Entity -notlike "vCLS*" -and $_.'log.rotateSize' -ne "1024000" }).Entity ) {
|
||||
New-AdvancedSetting -Entity $VM -Name 'log.rotateSize' -Value '1024000' -Confirm:$false -Force:$true
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
$VMHostNames = @"
|
||||
itdbisvm-gen05.nd.gov
|
||||
"@
|
||||
$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames
|
||||
|
||||
# set maintenance and disable alarms
|
||||
Get-VMHost -Name $VMHostNames | Set-VMHost -State "Maintenance" -RunAsync
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost -Name $VMHostname
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
}
|
||||
|
||||
#Create Management Switch And Move Adapter
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$vmnic0 = Get-VMHostNetworkAdapter -VMHost $VMHostName -Name "vmnic0"
|
||||
$vmk0 = Get-VMHost $VMHostName | Get-VMHostNetworkAdapter -Name vmk0
|
||||
New-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT"
|
||||
Get-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT" | New-VirtualPortGroup -Name "sPG-MGMT"
|
||||
$MGMTPG = Get-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT" | Get-VirtualPortGroup -Name "sPG-MGMT"
|
||||
$MGMTSwitch = Get-VirtualSwitch -VMHost $VMHostName -Name "sSwitch-MGMT"
|
||||
Add-VirtualSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmnic0 -VirtualSwitch $MGMTSwitch -Confirm:$false
|
||||
Add-VirtualSwitchPhysicalNetworkAdapter -VMHostPhysicalNic $vmnic0 -VirtualSwitch $MGMTSwitch -VirtualNicPortgroup $MGMTPG -VMHostVirtualNic $vmk0 -Confirm:$false
|
||||
}
|
||||
|
||||
# remove vmk1 and vmk2
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost -Name $VMHostName | Get-VMHostNetworkAdapter -Name vmk1, vmk2 | Remove-VMHostNetworkAdapter -Confirm:$false
|
||||
}
|
||||
|
||||
# remove distributed switches
|
||||
$BackupVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-Backup'
|
||||
$DataVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-Data-Server'
|
||||
$vMotionVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-VMotion'
|
||||
$MgmtVDSwitch = Get-VDSwitch -Name 'dvSwitch-SDC-MGMT'
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Remove-VDSwitchVMHost -VDSwitch $BackupVDSwitch -VMHost $VMHostName -Confirm:$false
|
||||
Remove-VDSwitchVMHost -VDSwitch $DataVDSwitch -VMHost $VMHostName -Confirm:$false
|
||||
Remove-VDSwitchVMHost -VDSwitch $vMotionVDSwitch -VMHost $VMHostName -Confirm:$false
|
||||
Remove-VDSwitchVMHost -VDSwitch $MgmtVDSwitch -VMHost $VMHostName -Confirm:$false
|
||||
}
|
||||
# remove from inventory
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost -Name $VMHostName | Remove-VMHost -Confirm:$false
|
||||
}
|
||||
|
||||
# scrub DNS
|
||||
# scrub Passwordstate
|
||||
# scrub Active Directory
|
||||
|
||||
# send storage team request to remove SAN
|
||||
# send cohesity team request to remove host mappings for backup vmkernels
|
||||
@@ -0,0 +1,15 @@
|
||||
$cluster = Get-Cluster
|
||||
|
||||
$hosti = $cluster | Get-VMHost
|
||||
|
||||
$report333 = foreach ($esxi in $hosti) {
|
||||
|
||||
Get-VMHosthba -VMHost $esxi -type FibreChannel | where{$_.STatus -eq 'online'} |
|
||||
|
||||
Select @{N="Host";E={$esxi.Name}},
|
||||
|
||||
@{N='HBA Node WWN';E={$wwn = "{0:X}" -f $_.NodeWorldWideName; (0..7 | %{$wwn.Substring($_*2,2)}) -join ':'}},
|
||||
|
||||
@{N='HBA Node WWP';E={$wwp = "{0:X}" -f $_.PortWorldWideName; (0..7 | %{$wwp.Substring($_*2,2)}) -join ':'}}
|
||||
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
# VMhost Advanced Options -- see OneNote for documentation
|
||||
# used to customize the first host of each model per datacenter (host profile will be extracted from this), run the entire code
|
||||
# also used for customizations that made host profiles angry
|
||||
|
||||
# add to distributed switches first
|
||||
# pre create the syslog folder for each host
|
||||
# set the logdir datastore/path value using code below
|
||||
# if this is not the first host per datacenter, stop after logdir value, host profile SHOULD do the rest
|
||||
|
||||
|
||||
$VMHostName = 'itdvmmdntel08.nd.gov'
|
||||
$VMHost = Get-VMHost -Name $VMHostName
|
||||
$VMHostCluster = $VMHost | Get-Cluster
|
||||
$VMHostDatacenter = $VMHost | Get-Datacenter
|
||||
$EsxCli = Get-EsxCli -VMHost $VMHostName -V2
|
||||
|
||||
# set advanced settings
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name UserVars.ESXiShellInteractiveTimeOut | Set-AdvancedSetting -Value 300 -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name UserVars.ESXiShellTimeOut | Set-AdvancedSetting -Value 900 -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name UserVars.DcuiTimeOut | Set-AdvancedSetting -Value 600 -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.solo.enableMob | Set-AdvancedSetting -Value false -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.hostsvc.esxAdminsGroupAutoAdd | Set-AdvancedSetting -Value false -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.hostsvc.esxAdminsGroup | Set-AdvancedSetting -Value "" -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Config.HostAgent.plugins.vimsvc.authValidateInterval | Set-AdvancedSetting -Value 90 -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.certificate.strictX509Compliance | Set-AdvancedSetting -Value true -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logLevel | Set-AdvancedSetting -Value info -Confirm:$false
|
||||
|
||||
|
||||
# scratch and syslog
|
||||
switch ($VMHostDatacenter.Name) {
|
||||
'Primary Datacenter' {
|
||||
$ScratchPath = '/vmfs/volumes/5ef4c13d-6318953e-620e-6cc217314910/scratch'
|
||||
$LogDirDatastore = 'VMALL1_006_FS92_SCRATCH'
|
||||
}
|
||||
'Secondary Datacenter' {
|
||||
$ScratchPath = '/vmfs/volumes/5ef4be61-1084f19b-ca0a-6cc217314690/scratch'
|
||||
$LogDirDatastore = 'VMALL2_007_FS92_SCRATCH'
|
||||
}
|
||||
'DCN Datacenter' {
|
||||
$ScratchPath = '/vmfs/volumes/6463c3f5-1ffe01b3-3837-e0071befea78/scratch'
|
||||
$LogDirDatastore = 'VMDCN1_40_V5K'
|
||||
}
|
||||
'Grand Forks Vantis' {
|
||||
$ScratchPath = '[VMVNTS_040_V5K] syslog/itdvmgfvnts02'
|
||||
$LogDirDatastore = 'VMVNTS_040_V5K'
|
||||
}
|
||||
'Test Primary Datacenter' {
|
||||
$ScratchPath = '/vmfs/volumes/5f36e52c-93f96f5c-3c43-6cc2172ed4d0/scratch'
|
||||
$LogDirDatastore = 'VMTEST_001_FS92_SCRATCH'
|
||||
}
|
||||
'Test Secondary Datacenter' {
|
||||
$ScratchPath = '/vmfs/volumes/5f36e52c-93f96f5c-3c43-6cc2172ed4d0/scratch'
|
||||
$LogDirDatastore = 'VMTEST_001_FS92_SCRATCH'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#Get-VMHost -Name $VMHostname | Get-AdvancedSetting -Name ScratchConfig.ConfiguredScratchLocation | Set-AdvancedSetting -Value ($ScratchPath + $VMhostName.split('.')[0]) -Confirm:$false
|
||||
#Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDir | Set-AdvancedSetting -Value "$LogDirDatastore] syslog" -Confirm:$false
|
||||
#Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDirUnique | Set-AdvancedSetting -Value true -Confirm:$false
|
||||
|
||||
# 2024 syslog values
|
||||
$VMHostNameShort = $VMHostName.split('.')[0]
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDir | Set-AdvancedSetting -Value ("[$LogDirDatastore] syslog/$VMHostNameShort") -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logDirUnique | Set-AdvancedSetting -Value false -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name Syslog.global.logHost | Set-AdvancedSetting -Value "tcp://itdvmlogging1.nd.gov:514" -Confirm:$false
|
||||
|
||||
# Pub 1075 requirements, no longer included in host profile
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name "Security.PasswordQualityControl" | Set-AdvancedSetting -Value "retry=3 min=disabled,disabled,disabled,disabled,14" -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name "Security.AccountLockFailures" | Set-AdvancedSetting -Value "3" -Confirm:$false
|
||||
Get-VMHost -Name $VMHostName | Get-AdvancedSetting -Name "Security.PasswordHistory" | Set-AdvancedSetting -Value "24" -Confirm:$false
|
||||
|
||||
# static routes for backups
|
||||
switch ($VMHostDatacenter.Name) {
|
||||
'Primary Datacenter' { $Environment = 'Production-General' }
|
||||
'Secondary Datacenter' { $Environment = 'Production-General' }
|
||||
'DCN Datacenter' { $Environment = 'Production-DCN' }
|
||||
'Grand Forks Vantis' { $Environment = $null }
|
||||
'Test Primary Datacenter' { $Environment = 'Sandbox' }
|
||||
'Test Secondary Datacenter' { $Environment = 'Sandbox' }
|
||||
}
|
||||
|
||||
switch ($Environment) {
|
||||
'Production-General' {
|
||||
$vmk0IP = (Resolve-DnsName -Name $VMHostName).IPAddress
|
||||
$vmk1IP = '10.8.142.' + $vmk0IP.split('.')[3]
|
||||
$vmk2IP = '10.2.170.' + $vmk0IP.split('.')[3]
|
||||
}
|
||||
}
|
||||
|
||||
switch ($VMHostDatacenter.Name) {
|
||||
'Primary Datacenter' {
|
||||
Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-PDC-VMotion' -PortGroup 'dvPG_PDC_VMotion' -IP $vmk1IP -SubnetMask 255.255.254.0 -VMotionEnabled $true
|
||||
Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-PDC-Backup' -PortGroup 'dvPG_3534_10.2.170.0_24' -IP $vmk2IP -SubnetMask 255.255.255.0
|
||||
}
|
||||
'Secondary Datacenter' {
|
||||
Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-SDC-VMotion' -PortGroup 'dvPG_SDC_VMotion' -IP $vmk1IP -SubnetMask 255.255.254.0 -VMotionEnabled $true
|
||||
Get-VMHost -Name $VMHostname | New-VMHostNetworkAdapter -VirtualSwitch 'dvSwitch-SDC-Backup' -PortGroup 'dvPG_3534_10.2.170.0_24' -IP $vmk2IP -SubnetMask 255.255.255.0
|
||||
}
|
||||
'DCN Datacenter' {
|
||||
}
|
||||
'Grand Forks Vantis' {
|
||||
}
|
||||
}
|
||||
|
||||
# set vmkernel capabilities
|
||||
Get-VMHostNetworkAdapter -VMHost $VMHostName -Name vmk0 | Set-VMHostNetworkAdapter -VSphereReplicationEnabled $true -VSphereReplicationNfcEnabled $true -Confirm:$false
|
||||
Get-VMHostNetworkAdapter -VMHost $VMHostName -Name vmk1 | Set-VMHostNetworkAdapter -VMotionEnabled $true -Confirm:$false
|
||||
Get-VMHostNetworkAdapter -VMHost $VMHostName -Name vmk2 | Set-VMHostNetworkAdapter -VSphereBackupNfcEnabled $true -Confirm:$false
|
||||
|
||||
# core dump - disable coredump file, enable network coredump
|
||||
$CoreDumpArgs = $EsxCli.system.coredump.file.set.CreateArgs()
|
||||
$CoreDumpArgs.enable = $false
|
||||
$EsxCli.system.coredump.file.set.invoke($CoreDumpArgs)
|
||||
$CoreDumpArgs = $EsxCli.system.coredump.network.set.CreateArgs()
|
||||
$CoreDumpArgs.serverport = 6500
|
||||
$CoreDumpArgs.interfacename = 'vmk0'
|
||||
switch ($VMHostDatacenter.Name) {
|
||||
'Primary Datacenter' { $CoreDumpArgs.serveripv4 = '10.8.145.25' }
|
||||
'Secondary Datacenter' { $CoreDumpArgs.serveripv4 = '10.8.145.26' }
|
||||
'DCN Datacenter' { $CoreDumpArgs.serveripv4 = '10.8.145.25' }
|
||||
'Grand Forks Vantis' { $CoreDumpArgs.serveripv4 = '10.8.145.25' }
|
||||
}
|
||||
#$CoreDumpArgs.serveripv4 = '10.8.145.25'
|
||||
$EsxCli.system.coredump.network.set.invoke($CoreDumpArgs)
|
||||
$CoreDumpArgs = $EsxCli.system.coredump.network.set.CreateArgs()
|
||||
$CoreDumpArgs.enable = $true
|
||||
$EsxCli.system.coredump.network.set.invoke($CoreDumpArgs)
|
||||
$EsxCli.system.coredump.network.get.invoke()
|
||||
|
||||
# ntp - set NTP server and set service to start/stop with host
|
||||
Get-VMHost -Name $VMHostName | Add-VMHostNtpServer 10.2.7.40, 10.10.10.10
|
||||
Get-VMHost -Name $VMHostName | Get-VMHostService | where { $_.Key -eq "ntpd" } | Set-VMHostService -Policy On
|
||||
|
||||
# static route for backups
|
||||
$ParamsToAdd = @{
|
||||
network = '10.2.169.0/24'
|
||||
}
|
||||
switch ($VMHostDatacenter.Name) {
|
||||
'Primary Datacenter' { $ParamsToAdd.gateway = '10.2.170.1' }
|
||||
'Secondary Datacenter' { $ParamsToAdd.gateway = '10.2.170.1' }
|
||||
'DCN Datacenter' { $CoreDumpArgs.serveripv4 = '10.2.118.241' }
|
||||
'Grand Forks Vantis' { $CoreDumpArgs.serveripv4 = '' }
|
||||
}
|
||||
$EsxCli.network.ip.route.ipv4.add.Invoke($ParamsToAdd)
|
||||
|
||||
<#$params = @{
|
||||
network = '10.2.169.0/24' ## check subnet mask, should be /24 after collapsing the Cohesity subnets
|
||||
gateway = '10.2.170.1' ## General 10.2.170.1, VDI 10.2.15.1, TEST 10.2.168.241 # DCN 10.2.118.241
|
||||
} #>
|
||||
#$x = $esxcli.network.ip.route.ipv4.list.Invoke() | Where-Object {$_.Interface -eq 'vmk2' -and $_.Network -eq '10.2.169.128'}
|
||||
#$x | Add-Member -Name "Name" -MemberType NoteProperty -Value $VMHost.Name
|
||||
#$null = $result.Add($x)
|
||||
|
||||
<## to remove static route
|
||||
$paramsToRemove = @{
|
||||
network = '10.2.169.0/24'
|
||||
gateway = '10.2.170.1'
|
||||
}
|
||||
$EsxCli.network.ip.route.ipv4.remove.Invoke($paramsToRemove)
|
||||
##>
|
||||
|
||||
# sshServer firewall
|
||||
### 10.8.145.46 itdvmutilp3, 10.29.40.0/23 adminvpn
|
||||
Get-VMHost -Name $VMHostName | Get-VMHostFirewallException -Name 'SSH Server' | Set-VMHostFirewallException -Enabled $true
|
||||
$sshArgs = $EsxCli.network.firewall.ruleset.set.CreateArgs()
|
||||
$sshArgs.enabled = $true
|
||||
$sshArgs.allowedall = $false
|
||||
$sshArgs.rulesetid = 'sshServer'
|
||||
$EsxCli.network.firewall.ruleset.set.invoke($sshArgs)
|
||||
$AllowedIpArgs = $EsxCli.network.firewall.ruleset.allowedip.add.CreateArgs()
|
||||
$AllowedIpArgs.ipaddress = "10.8.145.46"
|
||||
$AllowedIpArgs.rulesetid = 'sshServer'
|
||||
$EsxCli.network.firewall.ruleset.allowedip.add.invoke($AllowedIpArgs)
|
||||
$AllowedIpArgs = $EsxCli.network.firewall.ruleset.allowedip.add.CreateArgs()
|
||||
$AllowedIpArgs.ipaddress = "10.29.40.0/23"
|
||||
$AllowedIpArgs.rulesetid = 'sshServer'
|
||||
$EsxCli.network.firewall.ruleset.allowedip.add.invoke($AllowedIpArgs)
|
||||
|
||||
(Get-VMHost -Name $VMHostName | Get-View).EnterLockdownMode()
|
||||
|
||||
|
||||
|
||||
<#ForEach($VMHostName in $VMHostNames){
|
||||
write-warning $VMHostName
|
||||
$EsxCli = Get-EsxCli -VMHost $VMHostName -V2
|
||||
$esxcli.network.ip.route.ipv4.list.Invoke() | Where-Object {$_.Interface -eq 'vmk2' -and $_.Network -eq '10.2.169.128'}
|
||||
}#>
|
||||
@@ -0,0 +1,38 @@
|
||||
$VMHostNames = @"
|
||||
itdvmmdnwin11.nd.gov
|
||||
itdvmmdnwin12.nd.gov
|
||||
"@
|
||||
$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames
|
||||
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$RootCred = $null
|
||||
$RootCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred
|
||||
|
||||
Disable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode
|
||||
|
||||
$null = Connect-VIServer $VMHostName -Credential $RootCred
|
||||
|
||||
If (-not ($?)) {
|
||||
Write-Warning ($VMHostName + " password failed")
|
||||
}
|
||||
else {
|
||||
Disconnect-VIServer $VMHostName -Force -Confirm:$false
|
||||
}
|
||||
Enable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode
|
||||
}
|
||||
|
||||
|
||||
$VMHostNames = @"
|
||||
itdvmmdnwin11.nd.gov
|
||||
itdvmmdnwin12.nd.gov
|
||||
"@
|
||||
$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames
|
||||
$VmDefaultCred = Get-Secret VMDefault
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
Disable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode
|
||||
$VMHostCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred
|
||||
Connect-VIServer -Server $VMHostName -Credential $VmDefaultCred
|
||||
Set-VMHostAccount -Server $VMHostName -UserAccount root -Password $VMHostCred.GetNetworkCredential().Password
|
||||
Disconnect-VIServer -Server $VMHostname -Confirm:$false
|
||||
Enable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
Get-VMHost | Select-Object Name,Model,MemoryTotalGB,ProcessorType,@{n='NumCpuPackages';e={$_.ExtensionData.Hardware.CpuInfo.NumCpuPackages}},@{n='CoresPerSocket';e={$_.ExtensionData.Hardware.CpuInfo.NumCpuCores / $_.ExtensionData.Hardware.CpuInfo.NumCpuPackages}},@{n='NumCpuCores';e={$_.ExtensionData.Hardware.CpuInfo.NumCpuCores}}
|
||||
|
||||
Get-Cluster | Where-Object {$_.Name -notlike "WINDOWS*" -or $_.Name -notlike "PS*" -or $_.Name -notlike "SQL*"} | Get-VM | Where-Object {$_.Guest.OSFullName -match "Windows"}
|
||||
@@ -0,0 +1,363 @@
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
$creds = Get-Credential
|
||||
#Connect VC1
|
||||
Connect-VIServer 'itdvmvc1.nd.gov' -Credential $creds
|
||||
#Connect VC2
|
||||
Connect-VIServer 'itdvmvc2.nd.gov' -Credential $creds
|
||||
#Connect VCT1
|
||||
Connect-VIServer 'itdvmvct1.nd.gov' -Credential $creds
|
||||
#Connect VCT2
|
||||
Connect-VIServer 'itdvmvct2.nd.gov' -Credential $creds
|
||||
#Connect OneView
|
||||
Connect-HPOVMgmt -Hostname 'itdoneviewp1.nd.gov' -Credential $creds -LoginAcknowledge
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#VMHosts to Patch
|
||||
$VMHostNames = @"
|
||||
itdvmmdnav04.nd.gov
|
||||
itdvmmdnav05.nd.gov
|
||||
"@
|
||||
$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Disable Alarms and Disconnect CDROM
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost $VMHostName
|
||||
#$VMHostParent = $GetVMHost.Parent
|
||||
$HostCluster = Get-Cluster -VMHost $VMHostName
|
||||
<#$NewSpec = New-Object VMware.Vim.ClusterConfigSpec
|
||||
$NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true
|
||||
$HostCluster.ExtensionData.ReconfigureCluster($NewSpec, $true)
|
||||
#>
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
$VMs = $GetVMHost | Get-VM
|
||||
#Disconnect CDROM and/or VMtools ISO
|
||||
foreach ($VM in $VMs) {
|
||||
$GetVM = Get-VM $VM
|
||||
$CDDrive = $GetVM | Get-CDDrive
|
||||
if ($CDDrive | Where-Object { $_.IsoPath -Like "*vmware/isoimages*" }) {
|
||||
$GetVM | Dismount-Tools
|
||||
#$CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
elseif ($CDDrive.HostDevice -Like "*drive*") {
|
||||
$CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
#Move Powered Off VMs
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostParent = $VMHostDetails.Parent.Name
|
||||
$VMHostMigrate = Get-Cluster $VMHostParent | Get-VMHost | Where-Object Name -NE $VMHostName | Select-Object -First 1
|
||||
$VMsPoweredOff = Get-VMHost $VMHostName | Get-VM | Where-Object PowerState -EQ "PoweredOff"
|
||||
If ($VMsPoweredOff) { Move-VM -VM $VMsPoweredOff -Destination $VMHostMigrate }
|
||||
}
|
||||
#Enter Maintenance Mode
|
||||
Set-VMHost -VMHost $VMHostNames -State "Maintenance" -RunAsync
|
||||
Start-Sleep -Seconds 10
|
||||
|
||||
#Monitor
|
||||
Get-VMHost -Name $VMHostNames | Select-Object Name, ConnectionState, @{Name = "VM.count"; E = { @($_ | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm" }).Count } }
|
||||
|
||||
# Move to HostUpgradesInProgress Folder
|
||||
Get-VMHost -Name $VMHostNames | Move-VMHost -Destination "HostUpgradesInProgress"
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Shutdown Host
|
||||
Stop-VMHost -VMHost $VMHostNames -Confirm:$false
|
||||
#Monitor
|
||||
Get-VMHost $VMHostNames | Select-Object -Property Name, ConnectionState, CpuUsageMhz
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Verify OneView Server Profile Power State -EQ Off
|
||||
<#foreach ($VMHostName in $VMHostNames){
|
||||
$HPOVServerProfile = Get-HPOVServerProfile -Name $VMHostName
|
||||
$HPOVServer = $HPOVServerProfile | Get-HPOVServer
|
||||
if ($HPOVServer.powerState -EQ "On"){
|
||||
$HPOVServer | Update-HPOVServer -Async
|
||||
}
|
||||
}#>
|
||||
|
||||
# ensure server power is off
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$HPOVServerProfile = Get-OVServerProfile -Name $VMHostName
|
||||
$HPOVServer = $HPOVServerProfile | Get-OVServer
|
||||
if ($HPOVServer.powerState -EQ "On") {
|
||||
$HPOVServer | Update-OVServer -Async
|
||||
}
|
||||
}
|
||||
#Monitor
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-OVServer -ServerName $VMHostName | Select-Object serverName, powerState
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Join OneView Template to Host
|
||||
$HPOVtemplates = Get-OVServerProfileTemplate
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0]
|
||||
switch ($VMHostVIserver) {
|
||||
itdvmvc1.nd.gov { $HPOVtemplDataCenter = "BIS" }
|
||||
Default { $HPOVtemplDataCenter = "MDN" }
|
||||
}
|
||||
$VMHostParent = $VMHostDetails.Parent.Name
|
||||
<#switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) {
|
||||
Avaya { $HPOVtemplType = "Avaya" }
|
||||
TEL { $HPOVtemplType = "Avaya" }
|
||||
DCN { $HPOVtemplType = "DCN" }
|
||||
DES { $HPOVtemplType = "DES" }
|
||||
Oracle { $HPOVtemplType = "Oracle" }
|
||||
SQL { $HPOVtemplType = "SQL" }
|
||||
SQL2-D { $HPOVtemplType = "SQL" }
|
||||
TEST { $HPOVtemplType = "Test" }
|
||||
Default { $HPOVtemplType = "General" }
|
||||
}#>
|
||||
|
||||
If($VMHostName -like "*sql*" -or $VMHostName -like "*ora*"){
|
||||
$HPOVtemplType = "SQL"
|
||||
}
|
||||
Else{
|
||||
$HPOVtemplType = "General"
|
||||
}
|
||||
|
||||
$HPOVtemplModel = $VMHostDetails.Model.Split()[2]
|
||||
$NewHPOVtempl = $HPOVtemplates | Where-Object { $_.Name -Like "*$HPOVtemplDataCenter*" -and $_.Name -Like "*$HPOVtemplType*" -and $_.Name -Like "*$HPOVtemplModel*" } | Sort-Object Name | Select-Object -Last 1
|
||||
Join-OVServerProfileToTemplate -Template $NewHPOVtempl -ServerProfile $VMHostName
|
||||
}
|
||||
#Monitor
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-OVServerProfile -Name $VMHostName
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Check iLO Health Status
|
||||
<#
|
||||
foreach ($VMHostName in $VMHostNames){
|
||||
$iLOHostName = ($VMHostName.split(".")[0])+"lo.nd.gov"
|
||||
$iLoConnection = Connect-HPEiLO $iLOHostName -Credential $creds
|
||||
Get-HPEiLOHealthSummary -Connection $iLoConnection | Select-Object Hostname,Status
|
||||
Disconnect-HPEiLO -Connection $iLoConnection
|
||||
}#>
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Update OneView Server Template
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-OVServerProfile -Name $VMHostName | Update-OVServerProfile -Confirm:$false -Async
|
||||
Start-Sleep -Seconds 30
|
||||
}
|
||||
#powershell finished in 20m, but continued to run for 36min
|
||||
#Monitor
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-OVServerProfile -Name $VMHostName | Select-Object Name, State
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Start OneView Server Profile
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$wait = $true
|
||||
While ($wait -EQ $true) {
|
||||
$HPOVServerProfile = Get-OVServerProfile -Name $VMHostName
|
||||
if ($HPOVServerProfile.Status -NE "OK") {
|
||||
$wait = $true
|
||||
Start-Sleep -Seconds 60
|
||||
}
|
||||
else {
|
||||
$wait = $false
|
||||
$HPOVServerProfile | Start-OVServer -Async
|
||||
}
|
||||
}
|
||||
}
|
||||
#Monitor
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-OVServerProfile -Name $VMHostName
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
# manual full install of v7.0u3 now
|
||||
<# ISO connected from workstation via iLO -
|
||||
boot @ 9:43
|
||||
initial install screen @ 10:00
|
||||
ISO connect from vmutil
|
||||
boot @ 10:01
|
||||
initial install screen @ 10:10
|
||||
#>
|
||||
|
||||
# remove old from vcenter inventory
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost -Name $VMHostName | Remove-VMHost -Confirm:$false
|
||||
start-sleep -Seconds 3
|
||||
}
|
||||
|
||||
# add to vcenter
|
||||
$VmDefaultCred = Get-Secret VMDefault
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Add-VMHost -Name $VMHostName -Credential $VmDefaultCred -Location "HostUpgradesInProgress" -Force -Server $ViServer
|
||||
Start-Sleep -Seconds 3
|
||||
}
|
||||
|
||||
# license host
|
||||
Get-VMHost -Name $VMHostNames | Set-VMHost -LicenseKey '2M63H-8T391-P8YG4-00MR4-ARNP0'
|
||||
|
||||
# set maintenance and disable alarms
|
||||
Get-VMHost -Name $VMHostNames | Set-VMHost -State "Maintenance" -RunAsync
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost -Name $VMHostname
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
}
|
||||
|
||||
# Set root password
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$VMHostCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred
|
||||
Connect-VIServer -Server $VMHostName -Credential $VmDefaultCred
|
||||
Set-VMHostAccount -Server $VMHostName -UserAccount root -Password $VMHostCred.GetNetworkCredential().Password
|
||||
Disconnect-VIServer -Server $VMHostname -Confirm:$false
|
||||
<#$EsxCli = Get-EsxCli -VMHost $VMHostName
|
||||
/vmfs/volumes/5a737d2f-b45bb27d-7f74-e0071befea78/Scratch/itdbisvm-dcn01
|
||||
|
||||
$args = $EsxCli.system.account.set.CreateArgs()
|
||||
$args.id = "root"
|
||||
$args.password = $VMHostCred.GetNetworkCredential().Password
|
||||
$args.passwordconfirmation = $VMHostCred.GetNetworkCredential().Password
|
||||
$output = $EsxCli.system.account.set.invoke(@{
|
||||
id = $VMHostCred.UserName;
|
||||
password = $VMHostCred.GetNetworkCredential().Password;
|
||||
passwordconfirmation = $VMHostCred.GetNetworkCredential().Password;
|
||||
})#>
|
||||
}
|
||||
|
||||
#Patch via Update Manager
|
||||
#Monitor ConnectionState
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
$VMHost | Select-Object -Property Name, ConnectionState
|
||||
}
|
||||
|
||||
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
$VMHostVIserver = $VMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
#$VMHostBaseline = Get-Baseline -Server $VMHostVIserver | Where-Object Name -Like "*ESXi 6.5.0*"
|
||||
$VMHostBaselineUpgrade = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-ProLiant" }
|
||||
$VMHostBaselinePatch = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3 Patch" }
|
||||
$VMHostBaselineAll = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-ProLiant" -or $_.Name -EQ "7.0U3 Patch"}
|
||||
Attach-Baseline -Baseline $VMHostBaselineUpgrade -Entity $VMHost
|
||||
Attach-Baseline -Baseline $VMHostBaselinePatch -Entity $VMHost
|
||||
}
|
||||
#Remediate Baseline --- Do this in the GUI with all hosts in the same folder
|
||||
<#
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Scan-Inventory -Entity $VMHost
|
||||
}
|
||||
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Stage-Patch -Entity $VMHost -Baseline $VMhostBaselineUpgrade
|
||||
Stage-Patch -Entity $VMHost -Baseline $VMhostBaselinePatch -RunASync
|
||||
}
|
||||
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselineAll -RunAsync -Confirm:$false
|
||||
}#>
|
||||
|
||||
#Monitor
|
||||
Get-Task | Where-Object Name -Like "*Remediate*"
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Attach Host Profile and Test Compliance
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$CurrentHostProfiles = Get-VMHostProfile
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0]
|
||||
switch ($VMHostVIserver) {
|
||||
itdvmvc1.nd.gov { $VMHostVIserver = "BIS" }
|
||||
Default { $VMHostVIServer = "MDN" }
|
||||
}
|
||||
$VMHostParent = $VMHostDetails.Parent.Name
|
||||
switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) {
|
||||
Avaya { $VMHostProfile = "Avaya" }
|
||||
TEL { $VMHostProfile = "TEL" }
|
||||
Default { $VMHostProfile = "General" }
|
||||
}
|
||||
#$VMHostBuild = $VMHostDetails.Build
|
||||
#$VMHostVersion = $VMHostDetails.Version
|
||||
#$VMHostProfileName = $CurrentHostProfiles | Where-Object {$_.Name -Like "*$VMHostVIserver*" -and $_.Name -Like "*$VMHostVersion*" -and $_.Name -Like "*$VMHostBuild*" -and $_.Name -Like "*$VMHostProfile*"} | Sort-Object Name | Select-Object -First 1
|
||||
$VMHostProfileName = $CurrentHostProfiles | Where-Object { $_.Name -like "*$VMHostVIserver*" -and $_.Name -Like "*7.0.3*" -and $_.Name -like "*$VMHostProfile*" -and $_.Name -like "*BL460c*" }
|
||||
Invoke-VMHostProfile -Entity $VMHostDetails -Profile $VMHostProfileName -AssociateOnly -Confirm:$false
|
||||
}
|
||||
# import host customization csv
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost -Name $VMHostName | Test-VMHostProfileCompliance
|
||||
}
|
||||
#Remediate Host Profile
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostProfileCompliance = $VMhostDetails | Test-VMHostProfileCompliance #### ???????
|
||||
if ($VMHostProfileCompliance.ExtensionData.ComplianceStatus -Like "*non*") {
|
||||
Invoke-VMHostProfile -Entity $VMhostDetails -Confirm:$false
|
||||
}
|
||||
$VMhostDetails | Test-VMHostProfileCompliance
|
||||
}
|
||||
|
||||
# reboot hosts 0_Offline, Before Upgrade v7.0U3h
|
||||
Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false
|
||||
|
||||
#Test Host Profile Compliance
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost $VMHostName | Test-VMHostProfileCompliance
|
||||
}
|
||||
# maybe reboot again sometimes maybe
|
||||
Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false
|
||||
|
||||
#Exit Maintenance Mode and Enable Alarms
|
||||
Set-VMHost -VMHost $VMHostNames -State "Connected" -RunAsync
|
||||
Start-Sleep -Seconds 30
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost $VMHostName
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $false) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $true)
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#$VMCluster = Get-Cluster $VMHostParent #| Set-Cluster -HAAdmissionControlEnabled:$false -Confirm:$false
|
||||
#$HAFailoverHost = Get-VMHost | Where-Object {$_.Id -Match ((Get-Cluster $VMHostParent).extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)}
|
||||
#get-vmhost | where-object {$_.id -eq ($vmcluster.extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)}
|
||||
|
||||
<#
|
||||
foreach ($VMHostProfile in $VMHostProfiles){
|
||||
Export-VMHostProfile -FilePath $FilePath$Profile".xml" -Profile $VMHostProfile
|
||||
}
|
||||
Import-VMHostProfile -FilePath $FilePath"TestHostProfile.xml" -Name "Test Scripting"
|
||||
#>
|
||||
+481
@@ -0,0 +1,481 @@
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
$creds = Get-Credential
|
||||
#Connect VC1
|
||||
Connect-VIServer 'itdvmvc1.nd.gov' -Credential $creds
|
||||
#Connect VC2
|
||||
Connect-VIServer 'itdvmvc2.nd.gov' -Credential $creds
|
||||
#Connect VCT1
|
||||
Connect-VIServer 'itdvmvct1.nd.gov' -Credential $creds
|
||||
#Connect VCT2
|
||||
Connect-VIServer 'itdvmvct2.nd.gov' -Credential $creds
|
||||
#Connect OneView
|
||||
Connect-HPOVMgmt -Hostname 'itdoneviewp1.nd.gov' -Credential $creds -LoginAcknowledge
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#VMHosts to Patch
|
||||
$VMHostNames = @"
|
||||
itdvmbiswin19.nd.gov
|
||||
itdvmbislin10.nd.gov
|
||||
itdvmbiswas08.nd.gov
|
||||
itdvmbissql14.nd.gov
|
||||
itdvmbissql15.nd.gov
|
||||
itdvmbistel09.nd.gov
|
||||
itdvmbisvapp04.nd.gov
|
||||
itdvmbissqla02.nd.gov
|
||||
itdvmbiswas09.nd.gov
|
||||
itdvmbiswin08.nd.gov
|
||||
itdvmbiswin14.nd.gov
|
||||
itdvmbisps18.nd.gov
|
||||
"@
|
||||
$VMHostNames = ConvertTo-Array -MultiLineString $VMHostNames
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Disable Alarms and Disconnect CDROM
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Write-Warning -Message ("Start $VMHostName")
|
||||
$GetVMHost = Get-VMHost $VMHostName
|
||||
#$VMHostParent = $GetVMHost.Parent
|
||||
#$HostCluster = Get-Cluster -VMHost $VMHostName
|
||||
<#$NewSpec = New-Object VMware.Vim.ClusterConfigSpec
|
||||
$NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true
|
||||
$HostCluster.ExtensionData.ReconfigureCluster($NewSpec, $true)
|
||||
#>
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
$VMs = $GetVMHost | Get-VM
|
||||
#Disconnect CDROM and/or VMtools ISO
|
||||
|
||||
foreach ($VM in $VMs) {
|
||||
$GetVM = Get-VM $VM
|
||||
$CDDrive = $GetVM | Get-CDDrive
|
||||
if ($CDDrive | Where-Object { $_.IsoPath -Like "*vmware/isoimages*" }) {
|
||||
$GetVM | Dismount-Tools
|
||||
#$CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
elseif ($CDDrive.HostDevice -Like "*drive*") {
|
||||
$CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
#Move Powered Off VMs
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostParent = $VMHostDetails.Parent.Name
|
||||
$VMHostMigrate = Get-Cluster $VMHostParent | Get-VMHost | Where-Object Name -NE $VMHostName | Select-Object -First 1
|
||||
$VMsPoweredOff = Get-VMHost $VMHostName | Get-VM | Where-Object PowerState -EQ "PoweredOff"
|
||||
If ($VMsPoweredOff) { Move-VM -VM $VMsPoweredOff -Destination $VMHostMigrate }
|
||||
}
|
||||
#Enter Maintenance Mode
|
||||
Set-VMHost -VMHost $VMHostNames -State "Maintenance" -RunAsync
|
||||
|
||||
#Monitor
|
||||
Get-VMHost -Name $VMHostNames | Sort-Object Name | Select-Object Name, ConnectionState, @{Name = "VM.count"; E = { @($_ | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm" }).Count } }
|
||||
|
||||
# Move to HostUpgradesInProgress Folder ??? -- if host is moved out of the cluster, may break affinity rules
|
||||
#Get-VMHost -Name $VMHostNames | Move-VMHost -Destination "HostUpgradesInProgress"
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#Shutdown Host
|
||||
Stop-VMHost -VMHost $VMHostNames -Confirm:$false
|
||||
#Monitor
|
||||
Get-VMHost $VMHostNames | Select-Object -Property Name, ConnectionState, CpuUsageMhz
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
##Verify OneView Server Profile Power State -EQ Off
|
||||
#<#foreach ($VMHostName in $VMHostNames){
|
||||
# $HPOVServerProfile = Get-HPOVServerProfile -Name $VMHostName
|
||||
# $HPOVServer = $HPOVServerProfile | Get-HPOVServer
|
||||
# if ($HPOVServer.powerState -EQ "On"){
|
||||
# $HPOVServer | Update-HPOVServer -Async
|
||||
# }
|
||||
# }#>
|
||||
#
|
||||
## ensure server power is off
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# $HPOVServerProfile = Get-OVServerProfile -Name $VMHostName.Split('.')[0]
|
||||
# $HPOVServer = $HPOVServerProfile | Get-OVServer
|
||||
# if ($HPOVServer.powerState -EQ "On") {
|
||||
# $HPOVServer | Update-OVServer -Async
|
||||
# }
|
||||
#}
|
||||
##Monitor
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# Get-OVServer -ServerName $VMHostName.split('.')[0] | Select-Object serverName, powerState
|
||||
#}
|
||||
##----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
##Join OneView Template to Host
|
||||
#$HPOVtemplates = Get-OVServerProfileTemplate
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# $VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
# <#$VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0]
|
||||
# switch ($VMHostVIserver) {
|
||||
# itdvmvc1.nd.gov { $HPOVtemplDataCenter = "BIS" }
|
||||
# Default { $HPOVtemplDataCenter = "MDN" }
|
||||
# }#>
|
||||
# $VMHostParent = $VMHostDetails.Parent.Name
|
||||
# switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) {
|
||||
# Avaya { $HPOVtemplType = "Avaya" }
|
||||
# TEL { $HPOVtemplType = "Avaya" }
|
||||
# DCN { $HPOVtemplType = "DCN" }
|
||||
# DES { $HPOVtemplType = "DES" }
|
||||
# Oracle { $HPOVtemplType = "Oracle" }
|
||||
# SQL { $HPOVtemplType = "SQL" } # database
|
||||
# SQL2-D { $HPOVtemplType = "SQL" }
|
||||
# TEST { $HPOVtemplType = "Test" }
|
||||
# Default { $HPOVtemplType = "General" }
|
||||
# }
|
||||
# $HPOVtemplModel = $VMHostDetails.Model.Split()[2]
|
||||
# $NewHPOVtempl = $HPOVtemplates | Where-Object { $_.Name -Like "*$HPOVtemplDataCenter*" -and $_.Name -Like "*$HPOVtemplType*" -and $_.Name -Like "*$HPOVtemplModel*" } | Sort-Object Name | Select-Object -Last 1
|
||||
# Join-OVServerProfileToTemplate -Template $NewHPOVtempl -ServerProfile $VMHostName.Split('.')[0]
|
||||
#}
|
||||
##Monitor
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# Get-OVServerProfile -Name $VMHostName.Split('.')[0]
|
||||
#}
|
||||
##----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
##Check iLO Health Status
|
||||
#<#
|
||||
# foreach ($VMHostName in $VMHostNames){
|
||||
# $iLOHostName = ($VMHostName.split(".")[0])+"lo.nd.gov"
|
||||
# $iLoConnection = Connect-HPEiLO $iLOHostName -Credential $creds
|
||||
# Get-HPEiLOHealthSummary -Connection $iLoConnection | Select-Object Hostname,Status
|
||||
# Disconnect-HPEiLO -Connection $iLoConnection
|
||||
# }#>
|
||||
##----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
##Update OneView Server Template
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# Get-OVServerProfile -Name $VMHostName.Split('.')[0] | Update-OVServerProfile -Confirm:$false -Async
|
||||
# Start-Sleep -Seconds 30
|
||||
#}
|
||||
##powershell finished in 20m, but continued to run for 36min
|
||||
##Monitor
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# Get-OVServerProfile -Name $VMHostName | Select-Object Name, State
|
||||
#}
|
||||
##----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
##Start OneView Server Profile
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# #$wait = $true
|
||||
# #While ($wait -EQ $true) {
|
||||
# $HPOVServerProfile = Get-OVServerProfile -Name $VMHostName.split('.')[0]
|
||||
# #if ($HPOVServerProfile.Status -NE "OK") {
|
||||
# #$wait = $true
|
||||
# #Start-Sleep -Seconds 60
|
||||
# #}
|
||||
# #else {
|
||||
# #$wait = $false
|
||||
# $HPOVServerProfile | Start-OVServer -Async
|
||||
# Start-Sleep -Seconds 5
|
||||
# #}
|
||||
# #}
|
||||
#}
|
||||
#
|
||||
## mount ISO in iLO
|
||||
#
|
||||
##Monitor
|
||||
#foreach ($VMHostName in $VMHostNames) {
|
||||
# Get-OVServerProfile -Name $VMHostName.Split('.')[0]
|
||||
#}
|
||||
##----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
## manual full install of v7.0u3 now
|
||||
#<# ISO connected from workstation via iLO -
|
||||
# boot @ 9:43
|
||||
# initial install screen @ 10:00
|
||||
# ISO connect from vmutil
|
||||
# boot @ 10:01
|
||||
# initial install screen @ 10:10
|
||||
##>
|
||||
|
||||
# remove old from vcenter inventory
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost -Name $VMHostNames | Remove-VMHost -Confirm:$false
|
||||
}
|
||||
|
||||
# add to vcenter
|
||||
$VmDefaultCred = Get-Secret VMDefault
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
Add-VMHost -Name $VMHostName -Credential $VmDefaultCred -Location "Secondary Datacenter" -Server $VIServer -Force
|
||||
}
|
||||
|
||||
# license host
|
||||
Get-VMHost -Name $VMHostNames | Set-VMHost -LicenseKey 'M04W3-FEJ0H-P8J61-LMRKH-C4D1K'
|
||||
|
||||
# not avaya '2M63H-8T391-P8YG4-00MR4-ARNP0'
|
||||
# avaya '3001L-FT19L-28PGX-099A2-2XQNH'
|
||||
# VDI Desktop 'L56AQ-0VH1K-488GT-0NQU2-ADG64'
|
||||
Start-Sleep -seconds 3
|
||||
|
||||
# set maintenance and disable alarms
|
||||
Get-VMHost -Name $VMHostNames | Set-VMHost -State "Maintenance" -RunAsync
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost -Name $VMHostname
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
}
|
||||
|
||||
# Set root password
|
||||
ForEach ($VMHostName in $VMHostNames) {
|
||||
$VMHostCred = Get-ITDPassword -Title $VMHostName -UserName root -Credential $PrvCred
|
||||
Connect-VIServer -Server $VMHostName -Credential $VmDefaultCred
|
||||
Set-VMHostAccount -Server $VMHostName -UserAccount root -Password $VMHostCred.GetNetworkCredential().Password
|
||||
Disconnect-VIServer -Server $VMHostname -Confirm:$false
|
||||
<#
|
||||
$EsxCli = Get-EsxCli -VMHost $VMHostName
|
||||
$args = $EsxCli.system.account.set.CreateArgs()
|
||||
$args.id = "root"
|
||||
$args.password = $VMHostCred.GetNetworkCredential().Password
|
||||
$args.passwordconfirmation = $VMHostCred.GetNetworkCredential().Password
|
||||
$output = $EsxCli.system.account.set.invoke(@{
|
||||
id = $VMHostCred.UserName;
|
||||
password = $VMHostCred.GetNetworkCredential().Password;
|
||||
passwordconfirmation = $VMHostCred.GetNetworkCredential().Password;
|
||||
})
|
||||
#>
|
||||
}
|
||||
|
||||
# M.2 drives only, remove datastore1 from vmhost .... will get errors but still work
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
Remove-Datastore -Datastore "datastore1*" -VMHost $VMHostName -Confirm:$false
|
||||
}
|
||||
|
||||
|
||||
#Patch via Update Manager
|
||||
#Monitor ConnectionState
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
$VMHost | Select-Object -Property Name, ConnectionState
|
||||
}
|
||||
|
||||
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
$VMHostVIserver = $VMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
#$VMHostBaseline = Get-Baseline -Server $VMHostVIserver | Where-Object Name -Like "*ESXi 6.5.0*"
|
||||
$VMHostBaselineUpgrade = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-Synergy" }
|
||||
$VMHostBaselinePatch = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-Patch" }
|
||||
$VMHostBaselineTools = Get-Baseline -Server $VMHostVIserver | Where-Object {$_.Name -EQ "VMware Tools"}
|
||||
$VMHostBaselineAll = Get-Baseline -Server $VMHostVIserver | Where-Object { $_.Name -EQ "vSphere 7.0U3-Synergy" -or $_.Name -EQ "vSphere 7.0U3-Patch" -or $_.Name -EQ "VMware Tools"}
|
||||
Attach-Baseline -Baseline $VMHostBaselineUpgrade -Entity $VMHost
|
||||
Attach-Baseline -Baseline $VMHostBaselinePatch -Entity $VMHost
|
||||
Attach-Baseline -Baseline $VMHostBaselineTools -Entity $VMHost
|
||||
}
|
||||
#Remediate Baseline # do manually with VUM on the Host Folder
|
||||
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Scan-Inventory -Entity $VMHost -RunASync
|
||||
}
|
||||
|
||||
Foreach ($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
#Stage-Patch -Entity $VMHost -Baseline $VMhostBaselineUpgrade -RunAsync
|
||||
Stage-Patch -Entity $VMHost -Baseline $VMhostBaselinePatch -RunASync
|
||||
Stage-Patch -Entity $VMHost -Baseline $VMHostBaselineTools -RunASync
|
||||
}
|
||||
|
||||
ForEach ($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselinePatch -RunAsync -Confirm:$false
|
||||
}
|
||||
|
||||
ForEach ($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselineTools -RunAsync -Confirm:$false
|
||||
}#>
|
||||
|
||||
ForEach ($VMHostName in $VMHostNames){
|
||||
$VMHost = Get-VMHost $VMHostName
|
||||
Remediate-Inventory -Entity $VMHost -Baseline $VMHostBaselineAll -RunAsync -Confirm:$false
|
||||
}
|
||||
|
||||
#Monitor
|
||||
Get-Task | Where-Object Name -Like "*Remediate*"
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
<# 2024/07/30 attach, test, invoke that works
|
||||
|
||||
$VMHosts = Get-Datacenter -Name Primary* | Get-VMHost | where-object Name -notlike "*av*"
|
||||
ForEach($VMHost in $VMHosts){
|
||||
Write-Warning -Message ("Start" + $VMHost.Name)
|
||||
$VMHost | Invoke-VMHostProfile -Profile $HostProfile -AssociateOnly -Confirm:$false
|
||||
$VMHost | Test-VMHostProfileCompliance
|
||||
}
|
||||
|
||||
ForEach($VMHost in $VMHosts){
|
||||
$VMHost | Invoke-VMHostProfile -Confirm:$false
|
||||
}
|
||||
|
||||
|
||||
#>
|
||||
|
||||
#Attach Host Profile and Test Compliance
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$CurrentHostProfiles = Get-VMHostProfile
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostVIserver = $VMHostDetails.Uid.Split('@')[1].Split(':')[0]
|
||||
switch ($VMHostVIserver) {
|
||||
itdvmvc1.nd.gov { $VMHostVIserver = "BIS" }
|
||||
Default { $VMHostVIServer = "MDN" }
|
||||
}
|
||||
$VMHostParent = $VMHostDetails.Parent.Name
|
||||
switch ($VMHostParent.substring(0, $VMHostParent.Length - 1)) {
|
||||
Avaya { $VMHostProfile = "Avaya" }
|
||||
TEL { $VMHostProfile = "TEL" }
|
||||
Default { $VMHostProfile = "General" }
|
||||
}
|
||||
#$VMHostBuild = $VMHostDetails.Build
|
||||
#$VMHostVersion = $VMHostDetails.Version
|
||||
#$VMHostProfileName = $CurrentHostProfiles | Where-Object {$_.Name -Like "*$VMHostVIserver*" -and $_.Name -Like "*$VMHostVersion*" -and $_.Name -Like "*$VMHostBuild*" -and $_.Name -Like "*$VMHostProfile*"} | Sort-Object Name | Select-Object -First 1
|
||||
$VMHostProfileName = $CurrentHostProfiles | Where-Object { $_.Name -like "*$VMHostVIserver*" -and $_.Name -Like "*7.0.3*" -and $_.Name -like "*$VMHostProfile*" -and $_.Name -like "*Synergy*" } | Sort-Object -Descending Name | Select -First 1
|
||||
Invoke-VMHostProfile -Entity $VMHostDetails -Profile $VMHostProfileName -AssociateOnly -Confirm:$false
|
||||
}
|
||||
# import host customization csv now
|
||||
|
||||
# then continue
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost -Name $VMHostName | Test-VMHostProfileCompliance
|
||||
}
|
||||
#Remediate Host Profile
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$VMHostDetails = Get-VMHost -Name $VMHostName
|
||||
$VMHostProfileCompliance = $VMhostDetails | Test-VMHostProfileCompliance #### ???????
|
||||
if ($VMHostProfileCompliance.ExtensionData.ComplianceStatus -Like "*non*") {
|
||||
Invoke-VMHostProfile -Entity $VMhostDetails -Confirm:$false
|
||||
}
|
||||
$VMhostDetails | Test-VMHostProfileCompliance
|
||||
}
|
||||
#Test Host Profile Compliance
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost $VMHostName | Test-VMHostProfileCompliance
|
||||
}
|
||||
|
||||
# Host requires reboot before previously applied configuration changes will take effect
|
||||
Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false
|
||||
|
||||
#Test Host Profile Compliance again
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Get-VMHost $VMHostName | Test-VMHostProfileCompliance
|
||||
}
|
||||
|
||||
# move hosts back to their clusters
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
switch ($VMHostName.substring(8).split('.')[0].substring(0,2)){
|
||||
'ps' {$ClusterStr = "PS"}
|
||||
}
|
||||
switch ($VMHostVIserver){
|
||||
'itdvmvc1.nd.gov' {$ClusterInt = 1}
|
||||
'itdvmvc2.nd.gov' {$ClusterInt = 2}
|
||||
}
|
||||
$ClusterName = $ClusterStr + $ClusterInt
|
||||
Move-VMHost -VMHost $VMHostName -Destination (Get-Cluster -Name $ClusterName)
|
||||
}
|
||||
|
||||
# restart again because HA is being weird
|
||||
Get-VMHost -Name $VMHostNames | Restart-VMHost -Confirm:$false
|
||||
|
||||
# monitor
|
||||
Get-VMHost -Name $VMHostNames
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#Monitor
|
||||
Get-VMHost -Name $VMHostNames | Sort-Object Name | Select-Object Name, ConnectionState, @{Name = "VM.count"; E = { @($_ | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -NE "placeholderVm" }).Count } }
|
||||
|
||||
#Exit Maintenance Mode and Enable Alarms
|
||||
ForEach($VMHostName in $VMHostNames){
|
||||
Set-VMHost -VMHost $VMHostName -State "Connected" -RunAsync
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost $VMHostName
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $false) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $true)
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#$VMCluster = Get-Cluster $VMHostParent #| Set-Cluster -HAAdmissionControlEnabled:$false -Confirm:$false
|
||||
#$HAFailoverHost = Get-VMHost | Where-Object {$_.Id -Match ((Get-Cluster $VMHostParent).extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)}
|
||||
#get-vmhost | where-object {$_.id -eq ($vmcluster.extensiondata.configuration.dasconfig.admissioncontrolpolicy.failoverhosts.value)}
|
||||
|
||||
<#
|
||||
foreach ($VMHostProfile in $VMHostProfiles){
|
||||
Export-VMHostProfile -FilePath $FilePath$Profile".xml" -Profile $VMHostProfile
|
||||
}
|
||||
Import-VMHostProfile -FilePath $FilePath"TestHostProfile.xml" -Name "Test Scripting"
|
||||
#>
|
||||
#Get-OVServer -ov x
|
||||
#$x | select Name,processorType,processorCount,processorCoreCount,serialnumber,memorymb,generation
|
||||
|
||||
|
||||
|
||||
## disable alarms entire datacenter
|
||||
$VMHostNames=(Get-Datacenter primary* | Get-VMHost).Name
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
Write-Warning -Message ("Start $VMHostName")
|
||||
$GetVMHost = Get-VMHost $VMHostName
|
||||
#$VMHostParent = $GetVMHost.Parent
|
||||
#$HostCluster = Get-Cluster -VMHost $VMHostName
|
||||
<#$NewSpec = New-Object VMware.Vim.ClusterConfigSpec
|
||||
$NewSpec.DasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
|
||||
$NewSpec.DasConfig.AdmissionControlPolicy.AutoComputePercentages = $true
|
||||
$HostCluster.ExtensionData.ReconfigureCluster($NewSpec, $true)
|
||||
#>
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
}
|
||||
|
||||
## enable alarms for entire datacenter
|
||||
$VMHostNames = (Get-VMHost).Name
|
||||
foreach ($VMHostName in $VMHostNames) {
|
||||
$GetVMHost = Get-VMHost $VMHostName
|
||||
$VIServer = $GetVMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $GetVMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $false) {
|
||||
$alarmMgr.EnableAlarmActions($GetVMHost.ExtensionData.MoRef, $true)
|
||||
}
|
||||
$GetVMHost = $null
|
||||
}
|
||||
@@ -0,0 +1,971 @@
|
||||
$IaasAuto = Get-Credential -UserName ndgov\svcitdiaasauto
|
||||
$StdCred = $IaasAuto
|
||||
$PrvCred = $IaasAuto
|
||||
|
||||
$FQDNs = @"
|
||||
itdzmtest111.ndtestdev.nd.dev
|
||||
"@
|
||||
|
||||
$FQDNs = ConvertTo-Array -MultiLineString $FQDNs
|
||||
|
||||
ForEach ($FQDN in $FQDNs) {
|
||||
Write-Warning "[$FQDN]:Start"
|
||||
$SPCred = $StdCred
|
||||
$ADCred = $PrvCred
|
||||
$PSCred = $PrvCred
|
||||
$VMCred = $PrvCred
|
||||
$CcmCred = $PrvCred
|
||||
#>
|
||||
<# Get Credentials
|
||||
|
||||
$SPCred = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
$ADCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'
|
||||
$PSCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'
|
||||
$IBCred = New-Object System.Management.Automation.PSCredential ($PSCred.UserName.split('\')[1], $ADCred.Password)
|
||||
$VMCred = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$CcmCred = Get-AutomationPSCredential -Name 'ITD IaaS Automation'#>
|
||||
#>
|
||||
Clear-DnsClientCache
|
||||
$SharePointList = Get-ITDVMwareSharePointVMGuestList -Credential $SPCred
|
||||
Write-Warning ("SPList count: " + $SharePointList.count)
|
||||
$SPItem = $SharePointList | Where-Object Title -EQ $FQDN
|
||||
If ($null -eq $SPItem.Cluster) {
|
||||
Write-Error "VMware Cluster not specified in SharePoint"
|
||||
Stop
|
||||
}
|
||||
Write-Warning $SPItem
|
||||
$HostName = $FQDN.split('.')[0]
|
||||
|
||||
# Infoblox
|
||||
[Net.IpAddress]$NetworkId = $SPItem.CIDR.split('/')[0]
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
$SubnetMaskInt = $SPItem.Cidr.split('/')[1]
|
||||
$Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2))
|
||||
[Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(),
|
||||
([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(),
|
||||
([math]::Truncate(($Int64 % 65536) / 256)).ToString(),
|
||||
([math]::Truncate($Int64 % 256)).ToString()
|
||||
$IPSplit = $SPItem.Cidr.Split('.')
|
||||
[Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($SPItem.Cidr.split('/')[0].split('.')[-1] -as [int]) + 1) )
|
||||
<#
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Verbose "IP Address and CIDR Block match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop
|
||||
}
|
||||
#>
|
||||
|
||||
If ($IpAddress) {
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Warning "DNS record already exists, CIDR Block match"
|
||||
}
|
||||
else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block"
|
||||
Break
|
||||
}
|
||||
}
|
||||
Else {
|
||||
New-ITDIbDNSRecordNextAvailableIP -Hostname $SPItem.Title -CIDR $SPItem.CIDR -Credential $RadiusCred
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
}
|
||||
#>
|
||||
If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
|
||||
Write-Error "IP Address already in use." -ErrorAction Stop
|
||||
}
|
||||
|
||||
# Passwordstate BB before baseline, AB after baseline
|
||||
If ($FQDN -like "itdcnd*") {
|
||||
$PasswordStateList = "Peoplesoft Share PW"
|
||||
}
|
||||
Else {
|
||||
$PasswordStateList = "CSRC"
|
||||
}
|
||||
|
||||
$LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred
|
||||
#$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredential = $GuestCredentialBB
|
||||
|
||||
# VMware
|
||||
Connect-ITDvCenter -Credential $VMCred
|
||||
If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) {
|
||||
Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop
|
||||
Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
switch ($SPItem.Cluster) {
|
||||
"WINDOWS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WINDOWS1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
If ($SPItem.LicensingRestrictions -like "*SQL*") {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL"
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen"
|
||||
}
|
||||
}
|
||||
"WINDOWS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WINDOWS2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
If ($SPItem.LicensingRestrictions -like "*SQL*") {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL"
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen"
|
||||
}
|
||||
}
|
||||
"SQL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQL1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen"
|
||||
}
|
||||
"SQL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQL2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen"
|
||||
}
|
||||
"WAS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WAS1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen"
|
||||
}
|
||||
"WAS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WAS2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen"
|
||||
}
|
||||
"PS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster PS1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen"
|
||||
}
|
||||
"PS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster PS2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen"
|
||||
}
|
||||
"TEL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster TEL1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen"
|
||||
}
|
||||
"TEL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster TEL2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen"
|
||||
}
|
||||
Default {
|
||||
Write-Error "Cluster not found" -ErrorAction Stop
|
||||
}
|
||||
<#
|
||||
"DCN1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-DCN-vMotion-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
#>
|
||||
}
|
||||
|
||||
# verify disk will fit
|
||||
|
||||
$DiskTotal = $SPItem.Disk1 + $SPItem.Disk2 + $SPItem.Disk3
|
||||
If ($DatastoreCluster) {
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $SPItem.Cluster + "*")
|
||||
}
|
||||
$ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1)
|
||||
If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) {
|
||||
Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
}
|
||||
else {
|
||||
Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop
|
||||
}
|
||||
|
||||
$FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds"
|
||||
|
||||
switch ($SPItem.OS) {
|
||||
"Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" }
|
||||
"Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" }
|
||||
"Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" }
|
||||
"Windows Server 2019 Datacenter (64-Bit)" { $Template = "Windows Server 2019 Standard" }
|
||||
"Windows Server 2022 Datacenter (64-Bit)" { $Template = "Windows Server 2022 Standard" }
|
||||
Default { Write-Error "Invalid template" -ErrorAction Stop }
|
||||
}
|
||||
|
||||
$PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch
|
||||
$PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_" + $SPItem.Vlan_Id + "*")
|
||||
If (!($PortGroup)) {
|
||||
Write-Error "Virtual port group not found" -ErrorAction Stop
|
||||
Stop
|
||||
}
|
||||
If (@($PortGroup).count -gt 1) {
|
||||
Write-Error "Multiple port groups found" -ErrorAction Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
$NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S"))
|
||||
Write-Warning "NewOSSpecName = $NewOSSpecName"
|
||||
Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | `
|
||||
Set-OSCustomizationSpec `
|
||||
-NamingScheme fixed `
|
||||
-NamingPrefix $Hostname `
|
||||
-AdminPassword $GuestCredentialBB.GetNetworkCredential().Password
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | `
|
||||
Get-OSCustomizationNicMapping | `
|
||||
Set-OSCustomizationNicMapping `
|
||||
-IpMode UseStaticIP `
|
||||
-IpAddress $IpAddress.IPAddressToString `
|
||||
-SubnetMask $SubnetMask.IPAddressToString `
|
||||
-DefaultGateway $DefaultGateway.IPAddressToString `
|
||||
-Dns "10.2.7.40", "10.10.10.10"
|
||||
|
||||
$OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer
|
||||
<#
|
||||
$NewVMParams = @{
|
||||
Name = $FQDN;
|
||||
ResourcePool = $SPItem.Cluster;
|
||||
Datastore = $DatastoreCluster;
|
||||
DiskStorageFormat = $DiskStorageFormat;
|
||||
Template = $Template;
|
||||
Location = $FolderLocation;
|
||||
OSCustomizationSpec = $OSSpec;
|
||||
}
|
||||
$NewVMParams
|
||||
|
||||
New-VM @NewVMParams
|
||||
#>
|
||||
|
||||
#Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294
|
||||
# seems fixed on 2022/07/01
|
||||
try {
|
||||
Write-Warning $FQDN
|
||||
Write-Warning $ComputeCluster.Name
|
||||
Write-Warning $DatastoreCluster
|
||||
Write-Warning $DiskStorageFormat
|
||||
Write-Warning $Template
|
||||
Write-Warning $FolderLocation
|
||||
Write-Warning $OSSpec
|
||||
New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec
|
||||
}
|
||||
catch {
|
||||
Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
#If (!($BuildError)) {
|
||||
$VM = Get-VM -Name $FQDN
|
||||
|
||||
# Ensure CPU/Memory Hot-Add Enabled
|
||||
$vmView = $VM | Get-View
|
||||
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||
$vmOptValCPU = New-Object VMware.Vim.OptionValue
|
||||
$vmOptValMem = New-Object VMware.Vim.OptionValue
|
||||
$vmOptValCPU.Key = "vcpu.hotadd"
|
||||
$vmOptValMem.Key = "mem.hotadd"
|
||||
$vmOptValCPU.Value = "true"
|
||||
$vmOptValMem.Value = "true"
|
||||
$vmConfigSpec.ExtraConfig += $vmOptValCPU
|
||||
$vmConfigSpec.ExtraConfig += $vmOptValMem
|
||||
$vmView.ReconfigVM($vmConfigSpec)
|
||||
|
||||
# Set CPU, Memory, Network
|
||||
$VM | Set-VM -NumCpu $SPItem.Processors -MemoryGB $SPItem.RAM -Confirm:$false
|
||||
$VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false
|
||||
|
||||
# Power On VM
|
||||
$VM | Start-VM
|
||||
|
||||
# Wait for Customization to finish
|
||||
$VMStarted = $false
|
||||
$VMCustomizationStarted = $false
|
||||
$VMCustomizationResult = $false
|
||||
|
||||
While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) {
|
||||
Write-Warning ("Customization wait loop started " + (Get-Date))
|
||||
Write-Verbose "Current Status:"
|
||||
Write-Verbose ("VMStarted: " + $VMStarted)
|
||||
Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted)
|
||||
Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult)
|
||||
$GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue }
|
||||
Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds")
|
||||
If ($VMStarted -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) {
|
||||
$VMStarted = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine started"
|
||||
}
|
||||
}
|
||||
If ($VMCustomizationStarted -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) {
|
||||
$VMCustomizationStarted = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine customization started"
|
||||
}
|
||||
}
|
||||
If ($VMCustomizationResult -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) {
|
||||
$VMCustomizationResult = $true
|
||||
Write-Error "[$FQDN]:Virtual machine customization failed"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) {
|
||||
$VMCustomizationResult = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine customization completed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Delete OS Customization Spec
|
||||
# Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false
|
||||
|
||||
# Add/Expand Disks
|
||||
Write-Warning -Message "[$FQDN]:Modify disks 1,2,3"
|
||||
$VMDisk = $VM | Get-HardDisk
|
||||
$VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
$VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2"
|
||||
$VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
|
||||
If ($SPItem.Disk1) {
|
||||
If (!$VMDisk1) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $SPItem.Disk1 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
If ($VMDisk1.CapacityGB -lt $SPItem.Disk1) {
|
||||
Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $SPItem.Disk1 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
If ($SPItem.Disk2) {
|
||||
If (!$VMDisk2) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $SPItem.Disk2 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2"
|
||||
If ($VMDisk2.CapacityGB -lt $SPItem.Disk2) {
|
||||
Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $SPItem.Disk2 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
If ($SPItem.Disk3) {
|
||||
If (!$VMDisk3) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $SPItem.Disk3 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
If ($VMDisk3.CapacityGB -lt $SPItem.Disk3) {
|
||||
Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $SPItem.Disk3 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
# skipping tag assignment for now
|
||||
# Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose
|
||||
|
||||
# Run Guest OS code
|
||||
# Enable RDP with NLA - can be done with GPO
|
||||
# Enable WinRM - ITD WinRM enable
|
||||
# Configure Power Plan - ITD-PowerPlan-HighPerformance
|
||||
# Activate Windows, KMS on-premise, Azure to Azure
|
||||
# DVD Drive to Z:
|
||||
# Expand C:
|
||||
# Partition/Format the rest, GPT/NTFS
|
||||
# Configure Page File Disk
|
||||
# Enabling server manager performance monitors
|
||||
# Configure Time Zone and NTP - no GPO available
|
||||
# Disable Windows Firewall
|
||||
# Join AD
|
||||
|
||||
#Initialize-ITDServer -Credential $ADCred
|
||||
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Assigning WMI Tag 000-Prod, SCCM will change it later if required"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Move DVD Drive Mount
|
||||
try {
|
||||
Write-Verbose "Create new Class"
|
||||
$Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null);
|
||||
|
||||
$Class["__CLASS"] = "ITD";
|
||||
$Class.Qualifiers.Add("Static", $true)
|
||||
$Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false)
|
||||
$Class.Properties["MyKey"].Qualifiers.Add("Key", $true)
|
||||
|
||||
$Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false)
|
||||
$Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false)
|
||||
$Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false)
|
||||
|
||||
$Class.Put()
|
||||
|
||||
Write-Verbose "Create single ITD Object"
|
||||
Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" }
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Checking for DVD drive..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Move DVD Drive Mount
|
||||
try {
|
||||
$dvd_letter = 'Z'
|
||||
$dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1
|
||||
if ($dvd.Name -notmatch $dvd_letter) {
|
||||
Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:"
|
||||
|
||||
Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null
|
||||
|
||||
Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:"
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "No DVD drive changes required, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Checking for unpartitioned space on C: disk..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Expand C: Partition To Maximum Extent
|
||||
|
||||
|
||||
try {
|
||||
$cSize = ( Get-Partition -DriveLetter C ).Size
|
||||
$cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax
|
||||
|
||||
if ($cSize -lt $cMaxSize) {
|
||||
Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..."
|
||||
|
||||
Resize-Partition -DriveLetter C -Size $cMaxSize
|
||||
|
||||
Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "C: is already at maximum size, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Start Extra Disk(s) config"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Initialize Additional Disks
|
||||
try {
|
||||
# Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default
|
||||
$disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number
|
||||
|
||||
if ($disks) {
|
||||
Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks."
|
||||
|
||||
# Prevent the "You must format this partition before using it." popup
|
||||
if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue }
|
||||
|
||||
foreach ($disk in $disks) {
|
||||
if ($disk.IsOffline) {
|
||||
Set-Disk $disk.Number -IsOffline $false
|
||||
Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..."
|
||||
}
|
||||
|
||||
if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false }
|
||||
if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue }
|
||||
|
||||
$diskParam = @{
|
||||
FileSystem = 'NTFS'
|
||||
Confirm = $false
|
||||
}
|
||||
|
||||
$driveLetter = [Int][Char]'D'
|
||||
while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) {
|
||||
$driveLetter++
|
||||
}
|
||||
|
||||
$diskParam.DriveLetter = [Char]$driveLetter
|
||||
|
||||
if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) {
|
||||
$diskParam.NewFileSystemLabel = 'Temporary Storage'
|
||||
}
|
||||
elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) {
|
||||
$diskParam.NewFileSystemLabel = 'Data'
|
||||
}
|
||||
|
||||
[void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize)
|
||||
[void](Format-Volume @diskParam)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "No unpartitioned disks found, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
finally {
|
||||
if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue }
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Start Page File Configuration"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Configure Page File
|
||||
if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) {
|
||||
Write-Verbose -Message "Setting up pagefile.sys on D:..."
|
||||
|
||||
try {
|
||||
if (-not [IO.File]::Exists('D:\pagefile.sys')) {
|
||||
$autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges
|
||||
$autoPage.AutomaticManagedPagefile = $false
|
||||
[void]$autoPage.Put()
|
||||
|
||||
Write-Verbose -Message "Disabled automatic pagefile management."
|
||||
|
||||
$pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges
|
||||
$pageFile.Delete()
|
||||
|
||||
Write-Verbose -Message "Deleted C:\pagefile.sys."
|
||||
|
||||
Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null
|
||||
|
||||
Write-Verbose -Message "System managed page file created on D:\pagefile.sys."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Pagefile already configured on D:, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..."
|
||||
Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Enabling Remote Management..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Configure Remote Management (RDP/PoSH)
|
||||
try {
|
||||
Write-Verbose -Message "Checking WinRM..."
|
||||
|
||||
if (Test-WSMan -ErrorAction SilentlyContinue) {
|
||||
Write-Verbose -Message "WinRM is already enabled."
|
||||
}
|
||||
else {
|
||||
Enable-PSRemoting -Force
|
||||
|
||||
Write-Verbose -Message "WinRM is now enabled."
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Checking RDP..."
|
||||
|
||||
$RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices
|
||||
$NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'"
|
||||
if ($RDP.AllowTSConnections -eq 0) {
|
||||
Write-Verbose -Message "RDP is disabled, enabling..."
|
||||
|
||||
$RDP.SetAllowTSConnections(1, 1) | Out-Null
|
||||
|
||||
Write-Verbose -Message "RDP is enabled."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "RDP is already enabled, checking NLA security..."
|
||||
}
|
||||
|
||||
if ($NLA.UserAuthenticationRequired -eq 0) {
|
||||
Write-Verbose -Message "RDP is not NLA secured, enabling..."
|
||||
|
||||
$NLA.SetUserAuthenticationRequired(1) | Out-Null
|
||||
|
||||
Write-Verbose -Message "RDP is now NLA secured."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "RDP is already NLA secured."
|
||||
}
|
||||
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Checking current power plan..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Configure Power Plan
|
||||
try {
|
||||
$powerPlans = powercfg -l
|
||||
|
||||
if ($powerPlans -match '\*$' -notmatch 'High performance') {
|
||||
$currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value
|
||||
|
||||
Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..."
|
||||
|
||||
$highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value
|
||||
[void](powercfg -setactive $highPerformance)
|
||||
|
||||
Write-Verbose -Message "Power plan set to High Performance."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Power plan already configured for High Performance."
|
||||
}
|
||||
|
||||
[void](& w32tm.exe /resync /nowait)
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$TimeSyncFunc = {
|
||||
# Configure Time/Date Settings
|
||||
Write-Verbose -Message "Checking current time/date settings..."
|
||||
$Domain = "<DomainName>"
|
||||
try {
|
||||
if ((Get-TimeZone).Id -ne 'Central Standard Time') {
|
||||
Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time."
|
||||
|
||||
Set-TimeZone -Id 'Central Standard Time'
|
||||
|
||||
Write-Verbose -Message "Time zone set to Central Standard Time."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Time zone is already set to Central Standard Time."
|
||||
}
|
||||
<#
|
||||
Write-Verbose -Message "Beginning a time synchronization..."
|
||||
|
||||
if ((Get-Service W32Time).Status -eq 'Stopped') {
|
||||
Start-Service W32Time
|
||||
}
|
||||
|
||||
[void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update)
|
||||
|
||||
[void](& w32tm.exe /resync /nowait)
|
||||
|
||||
# Start background job to check time service
|
||||
$tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock {
|
||||
do {
|
||||
$tmOut = & w32tm.exe /query /status /verbose
|
||||
|
||||
Start-Sleep -Seconds 10
|
||||
} until($tmOut -match '^Last Sync Error: 0\D+$')
|
||||
}
|
||||
|
||||
# If after three minutes time still has not synched, move on. This usually causes no problems.
|
||||
if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') {
|
||||
Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful."
|
||||
}
|
||||
else {
|
||||
[void](Stop-Job -Job $tmJob)
|
||||
Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed."
|
||||
}
|
||||
#>
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
$TimeSyncScriptBlock = $TimeSyncFunc -replace '<DomainName>', $DomainName
|
||||
$VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock
|
||||
#>
|
||||
Write-Warning -Message "[$FQDN]:Enabling the server manager performance monitors..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Enable Performance Counters
|
||||
|
||||
|
||||
try {
|
||||
if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) {
|
||||
Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask
|
||||
|
||||
Write-Verbose -Message "Performance monitors enabled."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Performance monitors already enabled, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Disable Windows Firewall"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Disable Windows Firewall
|
||||
Write-Verbose -Message "Checking for active Windows Firewall..."
|
||||
|
||||
if ((Get-NetFirewallProfile).Enabled -contains 'True') {
|
||||
Write-Verbose -Message "Windows Firewall is still enabled, disabling it..."
|
||||
|
||||
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False
|
||||
|
||||
Write-Verbose -Message "Windows Firewall disabled."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Windows Firewall already disabled, continuing..."
|
||||
}
|
||||
}
|
||||
|
||||
# Active Directory
|
||||
Write-Warning "[$FQDN]:Join Active Directory (if required)"
|
||||
$DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1)
|
||||
$AppName = $SPItem.AppName
|
||||
switch ($DomainName) {
|
||||
'nd.gov' {
|
||||
$SearchBaseDomain = "dc=nd,dc=gov"
|
||||
}
|
||||
'ndcloud.gov' {
|
||||
$SearchBaseDomain = "dc=ndcloud,dc=gov"
|
||||
}
|
||||
}
|
||||
|
||||
If ($DomainName -eq "nd.gov") {
|
||||
$OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName }
|
||||
If (!($OUAppName)) {
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' }
|
||||
}
|
||||
$ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname }
|
||||
If ($ExistingADComputer) {
|
||||
If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") {
|
||||
Write-Warning "AD object already exists, OU path does match"
|
||||
$OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(?<!\\),', ''
|
||||
}
|
||||
Else {
|
||||
Write-Error "AD object already exists, OU path mismatch"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
}
|
||||
Else {
|
||||
switch ($SPItem.Environment) {
|
||||
'Test' {
|
||||
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Non-Prod" }
|
||||
Else { $EnvString = "Test" }
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -Like "*$EnvString*"
|
||||
}
|
||||
'Production' {
|
||||
$EnvString = "Prod"
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -Like "*$EnvString*"
|
||||
}
|
||||
}
|
||||
If ($OuAppNameEnv) { $OUFinal = $OUAppNameEnv.DistinguishedName }
|
||||
Else { $OuFinal = $OUAppName.DistinguishedName }
|
||||
|
||||
#New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json)
|
||||
}
|
||||
|
||||
$FirstScriptBlock = { $DomainJoinCred = New-Object System.Management.Automation.PSCredential('svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) }
|
||||
$SecondScriptText = 'Add-Computer -DomainName <DomainName> -OUPath "<OuPath>" -Credential $DomainJoinCred'
|
||||
$SecondScriptText = $SecondScriptText -replace '<DomainName>', $DomainName
|
||||
$SecondScriptText = $SecondScriptText -replace '<OuPath>', $OuFinal
|
||||
$SecondScriptText = $SecondScriptText -replace '<OuPath>', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain)
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join"
|
||||
$InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText")
|
||||
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after"
|
||||
Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false
|
||||
Wait-Tools -VM (Get-VM -Name $FQDN)
|
||||
Start-Sleep -Seconds 90
|
||||
}
|
||||
|
||||
Write-Warning ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date))
|
||||
Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force
|
||||
Write-Warning ("[$FQDN]:SCCM client copy complete " + (Get-Date))
|
||||
#E:\AutoBuild\SCCM_Client\
|
||||
|
||||
# Check if SCCM automatically installed the SCCM client and registered it
|
||||
$CcmRegistered = $false
|
||||
$CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log
|
||||
}
|
||||
If ($CcmRegistration.ScriptOutput -match "Client is registered") {
|
||||
Write-Warning "Client is registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") {
|
||||
Write-Warning "Client is already registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
If ($CcmRegistered -eq $false) {
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
|
||||
If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) {
|
||||
Write-Warning "CCM client is already installing"
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) {
|
||||
Write-Warning "CCM client is already installed"
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
Else {
|
||||
Write-Warning -Message "Installing SCCM Client..."
|
||||
Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Register SCCM Client"
|
||||
While ($CcmRegistered -eq $false) {
|
||||
$CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log
|
||||
}
|
||||
If ($CcmRegistration.ScriptOutput -match "Client is registered") {
|
||||
Write-Warning "Client is registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") {
|
||||
Write-Warning "Client is already registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 }
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Approve SCCM Client"
|
||||
#Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL
|
||||
Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock {
|
||||
Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
|
||||
$PSDrives = Get-PSDrive
|
||||
If ($PSDrives | Where-Object Name -EQ "ITD") {
|
||||
# ITD Drive exists, do nothing
|
||||
}
|
||||
else {
|
||||
New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov
|
||||
}
|
||||
|
||||
Set-Location ITD:\
|
||||
$Device = Get-CMDevice -Name $args[0]
|
||||
If ($Device.IsApproved -eq 0) {
|
||||
Approve-CMDevice -DeviceName $args[0]
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
[void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
[void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
|
||||
}
|
||||
#Start-Sleep -Seconds 180
|
||||
|
||||
Write-Warning -Message '[$FQDN]:Waiting for network connectivity / Then KVM Activation...'
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
# Pause until network connectivity is available
|
||||
|
||||
$KMS = 'kms.nd.gov'
|
||||
|
||||
try {
|
||||
$nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock {
|
||||
Param ( [String]$KMS )
|
||||
do {
|
||||
$nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet
|
||||
|
||||
Start-Sleep -Seconds 10
|
||||
} until($nwStatus)
|
||||
} -ArgumentList $KMS
|
||||
|
||||
# If after 30 seconds the network connection is not responding continue on
|
||||
if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') {
|
||||
Write-Verbose -Message 'Network connectivity has been verified.'
|
||||
}
|
||||
else {
|
||||
[void](Stop-Job -Job $nwJob)
|
||||
Write-Verbose -Message 'Network connectivity could not be verified.'
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
|
||||
# Activate via KMS
|
||||
Write-Verbose -Message "Activating windows against $KMS..."
|
||||
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit
|
||||
}
|
||||
try {
|
||||
cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null
|
||||
cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null
|
||||
|
||||
Write-Verbose -Message "Checking activation status..."
|
||||
|
||||
$kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli
|
||||
|
||||
if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') {
|
||||
Write-Verbose -Message "Windows successfully activated."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct."
|
||||
Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
Write-Warning "[$FQDN]:End"
|
||||
}
|
||||
|
||||
|
||||
|
||||
Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { Get-Process -Name ccmexec*, cohesity*, cyserver*, nessus*, vmtoolsd* }
|
||||
|
||||
Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in"
|
||||
Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock {
|
||||
[void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto
|
||||
|
||||
$VMHosts = Get-Datacenter -Name "Grand Forks Vantis" | Get-VMHost
|
||||
|
||||
ForEach ($VMHost in $VMHosts) {
|
||||
Write-Verbose -Message ("Start: " + $VMHost.Name) -Verbose
|
||||
|
||||
$VMHostStatus = Get-ITDVMwareVMHostStatus -Name $VMHost.Name
|
||||
|
||||
# if accurate, enable lockdown
|
||||
If ($VMHostStatus.LockdownMode -eq 'lockdowndisabled') {
|
||||
Write-Verbose -Message ("Lockdown is already disabled on " + $VMHost.Name + ", no change") -Verbose
|
||||
$NoChange = $true
|
||||
}
|
||||
Else {
|
||||
Write-Verbose -Message ("Lockdown is enabled on " + $VMHost.Name + ", disabling now") -Verbose
|
||||
Disable-ITDVMwareVMHostFeature -Name $VMHost.Name -LockdownMode
|
||||
|
||||
}
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
# confirm lockdown is enabled
|
||||
$VMHostStatusCheck = Get-ITDVMwareVMHostStatus -Name $VMHost.Name
|
||||
}
|
||||
|
||||
Disconnect-ITDvCenter
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[switch]
|
||||
$IncludeInProgress
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
New-ITDServiceNowSession -Credential $Secret:snow_vmcred -Environment Production
|
||||
Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcauto
|
||||
|
||||
If($PSBoundParameters.ContainsKey("IncludeInProgress")){
|
||||
$Filter = 'short_descriptionSTARTSWITHLockdown mode is disabled on VMware host^state=1^ORstate=2'
|
||||
} Else {
|
||||
$Filter = 'state=1^short_descriptionSTARTSWITHLockdown Mode is disabled on VMware host'
|
||||
}
|
||||
|
||||
$Incidents = Get-ITDServiceNowRecord -ItemType Incident -Filter $Filter | Sort-Object {$_.number.value}
|
||||
|
||||
ForEach ($Incident in $Incidents) {
|
||||
# reset variables for each loop
|
||||
$VMHostName = $null
|
||||
$VMHostStatus = $null
|
||||
$VMHostStatusCheck = $null
|
||||
$NoChange = $null
|
||||
|
||||
$VMHostName = $Incident.short_description.display_value.split(' ')[-1]
|
||||
|
||||
Write-Verbose -Message ("Start " + $Incident.number.display_value + " for host " + $VMHostName) -Verbose
|
||||
# confirm ticket is accurate, that host has lockdown mode disabled
|
||||
$VMHostStatus = Get-ITDVMwareVMHostStatus -Name $VMHostName
|
||||
|
||||
# if accurate, enable lockdown
|
||||
If ($VMHostStatus.LockdownMode -eq 'lockdowndisabled') {
|
||||
Write-Verbose -Message ("Lockdown is still disabled on " + $VMHostName + ", enabling lockdown mode") -Verbose
|
||||
Enable-ITDVMwareVMHostFeature -Name $VMHostName -LockdownMode
|
||||
}
|
||||
Else {
|
||||
Write-Verbose -Message ("Lockdown is already enabled on " + $VMHostName + ", no change") -Verbose
|
||||
$NoChange = $true
|
||||
}
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
# confirm lockdown is enabled
|
||||
$VMHostStatusCheck = Get-ITDVMwareVMHostStatus -Name $VMHostName
|
||||
|
||||
# update ticket with current status
|
||||
If ($VMHostStatusCheck.LockdownMode -eq 'lockdowndisabled') {
|
||||
# update work notes if disabled
|
||||
Write-Verbose -Message ("Lockdown is still disabled on " + $VMHostName + ", update incident work notes") -Verbose
|
||||
$WorkNotesMsg = ("Lockdown is still disabled on " + $VMHostName + " after attempted remediation, manual review required.")
|
||||
Update-ITDServiceNowRecord -ItemType Incident -Number $Incident.number.display_value -Values @{
|
||||
work_notes = $WorkNotesMsg
|
||||
state = 'On Hold'
|
||||
}
|
||||
}
|
||||
Else {
|
||||
# close if enabled
|
||||
If ($NoChange) {
|
||||
Write-Verbose -Message ("Lockdown was already enabled on " + $VMHostName + ", closing incident") -Verbose
|
||||
$close_notes = ("Lockdown was already enabled on " + $VMHostName + " when checked, closing incident")
|
||||
}
|
||||
Else {
|
||||
Write-Verbose -Message ("Lockdown successfully enabled on " + $VMHostName + ", closing incident") -Verbose
|
||||
$close_notes = ("Lockdown successfully auto-enabled on " + $VMHostName);
|
||||
}
|
||||
Write-Verbose -Message ("Lockdown successfully enabled on " + $VMHostName + ", closing incident") -Verbose
|
||||
Update-ITDServiceNowRecord -ItemType Incident -Number $Incident.number.display_value -Values @{
|
||||
close_code = 'Solved (Permanently)'
|
||||
close_notes = $close_notes
|
||||
u_underlying_cause = 'Configuration';
|
||||
state = 'Closed'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Disconnect-ITDvCenter
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks VMware host lockdown mode status and creates incidents for disabled hosts.
|
||||
|
||||
.DESCRIPTION
|
||||
Recurring PSU schedule task, ~8am.
|
||||
|
||||
This script connects to the ITD vCenter, retrieves all VMware hosts, and checks their lockdown mode status.
|
||||
If lockdown mode is disabled on any hosts, it creates a ServiceNow incident for review.
|
||||
|
||||
.EXAMPLE
|
||||
.\VMware-LockdownTickets.ps1
|
||||
|
||||
.NOTES
|
||||
Requires VMware PowerCLI and ITD ServiceNow modules.
|
||||
Service account credentials must be available via $PrvCred and $Secret:ndgov_svcitdvmvcro.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
New-ITDServiceNowSession -Credential $Secret:snow_vmcred -Environment Production
|
||||
Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro
|
||||
|
||||
$AllVMHosts = Get-VMHost
|
||||
$CurrentState = Get-ITDVMwareVMHostStatus -Name $AllVMHosts
|
||||
$LockdownDisabled = $CurrentState | where-object lockdownmode -eq lockdowndisabled
|
||||
|
||||
If ($LockdownDisabled) {
|
||||
|
||||
ForEach ($VMHost in ($LockdownDisabled | Select -First 2)) {
|
||||
Write-Verbose -Message "Start $($VMHost.Name) incident creation"
|
||||
$NewIncidentParams = @{
|
||||
CallerUsername = 'svcvmwareadm';
|
||||
ShortDescription = ("Lockdown Mode is disabled on VMware host " + $VMHost.Name);
|
||||
Description = ("Lockdown Mode is disabled on VMware host " + $VMHost.Name + ". Lockdown mode is a required for CIS hardening compliance 3.20 (L1)");
|
||||
Impact = 3;
|
||||
Urgency = 1;
|
||||
Category = 'Cloud Platforms'
|
||||
Subcategory = 'Virtualization'
|
||||
AssignmentGroup = 'NDIT-Cloud Platforms'
|
||||
}
|
||||
New-ITDServiceNowIncident @NewIncidentParams
|
||||
}
|
||||
}
|
||||
|
||||
Disconnect-ITDvCenter
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,982 @@
|
||||
#$IaasAuto = Get-Credential -UserName ndgov\svcitdiaasauto
|
||||
#$StdCred = $IaasAuto
|
||||
#$PrvCred = $IaasAuto
|
||||
|
||||
$FQDN = "itdzmtest001.nd.gov"
|
||||
$CPU = 1
|
||||
$MemoryGB = 4
|
||||
$OS = "Windows Server 2019 Standard (64-Bit)"
|
||||
$Environment = "Production"
|
||||
$AppName = "Shared-PowerSchool"
|
||||
$LicensingRestrictions = "Powerschool"
|
||||
$VLAN = 1161
|
||||
$Datacenter = "Bismarck"
|
||||
|
||||
Write-Warning "[$FQDN]:Start"
|
||||
$SPCred = $StdCred
|
||||
$ADCred = $IaasAuto
|
||||
$PSCred = $PrvCred
|
||||
$VMCred = $PrvCred
|
||||
$CcmCred = $PrvCred
|
||||
#$RadiusCred = $RadiusCred
|
||||
$RadiusCred = New-Object System.Management.Automation.PSCredential($PrvCred.username.split('\')[1], ($PrvCred.Password))
|
||||
|
||||
Clear-DnsClientCache
|
||||
$HostName = $FQDN.split('.')[0]
|
||||
|
||||
# Infoblox
|
||||
$InfobloxVlanMetadata = Get-ITDIbVlan -Vlan $VLAN -Credential $RadiusCred
|
||||
$CIDR = $InfobloxVlanMetadata.AssignedTo
|
||||
[Net.IpAddress]$NetworkId = $Cidr.split('/')[0]
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
$SubnetMaskInt = $CIDR.split('/')[1]
|
||||
$Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2))
|
||||
[Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(),
|
||||
([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(),
|
||||
([math]::Truncate(($Int64 % 65536) / 256)).ToString(),
|
||||
([math]::Truncate($Int64 % 256)).ToString()
|
||||
$IPSplit = $CIDR.Split('.')
|
||||
[Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) )
|
||||
<#
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Verbose "IP Address and CIDR Block match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block" -ErrorAction Stop
|
||||
}
|
||||
#>
|
||||
|
||||
If ($IpAddress) {
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Warning "DNS record already exists, CIDR Block match"
|
||||
}
|
||||
else {
|
||||
Write-Error "DNS record already exists, and does not match CIDR Block"
|
||||
Break
|
||||
}
|
||||
}
|
||||
Else {
|
||||
New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress
|
||||
}
|
||||
#>
|
||||
If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
|
||||
Write-Error "IP Address already in use." -ErrorAction Stop
|
||||
}
|
||||
|
||||
# Passwordstate BB before baseline, AB after baseline
|
||||
If ($FQDN -like "itdcnd*") {
|
||||
$PasswordStateList = "Peoplesoft Share PW"
|
||||
}
|
||||
Else {
|
||||
$PasswordStateList = "CSRC"
|
||||
}
|
||||
|
||||
|
||||
# Passwordstate validation WIP
|
||||
<#$ExistingPassword = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $PSCred -ErrorAction SilentlyContinue
|
||||
If($ExistingPassword){
|
||||
$LocalCredential = $ExistingPassword
|
||||
}#>
|
||||
|
||||
|
||||
|
||||
$LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred
|
||||
#$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredential = $GuestCredentialBB
|
||||
|
||||
# VMware
|
||||
Connect-ITDvCenter -Credential $VMCred
|
||||
If (Get-VM -Name $FQDN -ErrorAction SilentlyContinue) {
|
||||
Write-Error "Virtual machine with the name $FQDN already exists." -ErrorAction Stop
|
||||
Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
switch ($LicensingRestrictions) {
|
||||
"No Licensing Restrictions" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" }
|
||||
"Microsoft SQL Enterprise" { $ClusterRoot = "SQL" }
|
||||
"Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "WINDOWS" }
|
||||
"IBM Websphere" { $ClusterRoot = "WAS" }
|
||||
"Powerschool" { $ClusterRoot = "PS" }
|
||||
"Pexip" { $ClusterRoot = "TEL" }
|
||||
}
|
||||
|
||||
switch ($Datacenter) {
|
||||
"Bismarck" { $ClusterInt = 1 }
|
||||
"Mandan" { $ClusterInt = 2 }
|
||||
}
|
||||
|
||||
$Cluster = $ClusterRoot + $ClusterInt
|
||||
|
||||
switch ($Cluster) {
|
||||
"WINDOWS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WINDOWS1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
|
||||
If ($LicensingRestrictions -like "*SQL*") {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL"
|
||||
$DiskStorageFormat = 'EagerZeroThick'
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
}
|
||||
"WINDOWS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WINDOWS2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
If ($LicensingRestrictions -like "*SQL*") {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL"
|
||||
$DiskStorageFormat = 'EagerZeroThick'
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
}
|
||||
"SQL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQL1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQL1_FS92_Gen"
|
||||
}
|
||||
"SQL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQL2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQL2_FS92_Gen"
|
||||
}
|
||||
"WAS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WAS1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen"
|
||||
}
|
||||
"WAS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster WAS2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen"
|
||||
}
|
||||
"PS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster PS1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen"
|
||||
}
|
||||
"PS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster PS2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen"
|
||||
}
|
||||
"TEL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster TEL1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen"
|
||||
}
|
||||
"TEL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster TEL2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen"
|
||||
}
|
||||
Default {
|
||||
Write-Error "Cluster not found" -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
# verify disk will fit
|
||||
$DiskTotal = 70
|
||||
If ($DatastoreCluster) {
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $SPItem.Cluster + "*")
|
||||
}
|
||||
$ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1)
|
||||
If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) {
|
||||
Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
}
|
||||
else {
|
||||
Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop
|
||||
}
|
||||
|
||||
$FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds"
|
||||
|
||||
switch ($OS) {
|
||||
"Windows Server 2012R2 Standard (64-Bit)" { $Template = "Windows Server 2012R2 Standard" }
|
||||
"Windows Server 2016 Standard (64-Bit)" { $Template = "Windows Server 2016 Standard" }
|
||||
"Windows Server 2019 Standard (64-Bit)" { $Template = "Windows Server 2019 Standard" }
|
||||
"Windows Server 2019 Datacenter (64-Bit)" { $Template = "Windows Server 2019 Standard" }
|
||||
"Windows Server 2022 Datacenter (64-Bit)" { $Template = "Windows Server 2022 Standard" }
|
||||
Default { Write-Error "Invalid template" -ErrorAction Stop }
|
||||
}
|
||||
|
||||
$PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch
|
||||
$PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_" + $VLAN + "*")
|
||||
If (!($PortGroup)) {
|
||||
Write-Error "Virtual port group not found" -ErrorAction Stop
|
||||
Stop
|
||||
}
|
||||
If (@($PortGroup).count -gt 1) {
|
||||
Write-Error "Multiple port groups found" -ErrorAction Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
$NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S"))
|
||||
Write-Warning "NewOSSpecName = $NewOSSpecName"
|
||||
Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | `
|
||||
Set-OSCustomizationSpec `
|
||||
-NamingScheme fixed `
|
||||
-NamingPrefix $Hostname `
|
||||
-AdminPassword $GuestCredentialBB.GetNetworkCredential().Password
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | `
|
||||
Get-OSCustomizationNicMapping | `
|
||||
Set-OSCustomizationNicMapping `
|
||||
-IpMode UseStaticIP `
|
||||
-IpAddress $IpAddress.IPAddressToString `
|
||||
-SubnetMask $SubnetMask.IPAddressToString `
|
||||
-DefaultGateway $DefaultGateway.IPAddressToString `
|
||||
-Dns "10.2.7.40", "10.10.10.10"
|
||||
|
||||
$OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer
|
||||
<#
|
||||
$NewVMParams = @{
|
||||
Name = $FQDN;
|
||||
ResourcePool = $SPItem.Cluster;
|
||||
Datastore = $DatastoreCluster;
|
||||
DiskStorageFormat = $DiskStorageFormat;
|
||||
Template = $Template;
|
||||
Location = $FolderLocation;
|
||||
OSCustomizationSpec = $OSSpec;
|
||||
}
|
||||
$NewVMParams
|
||||
|
||||
New-VM @NewVMParams
|
||||
#>
|
||||
|
||||
#Set-Location C:\Temp # required to make New-VM work, https://communities.vmware.com/thread/591294
|
||||
# seems fixed on 2022/07/01
|
||||
try {
|
||||
Write-Warning $FQDN
|
||||
Write-Warning $ComputeCluster.Name
|
||||
Write-Warning $DatastoreCluster
|
||||
Write-Warning $DiskStorageFormat
|
||||
Write-Warning $Template
|
||||
Write-Warning $FolderLocation
|
||||
Write-Warning $OSSpec
|
||||
New-VM -Name $FQDN -ResourcePool $ComputeCluster.Name -Datastore $DatastoreCluster -DiskStorageFormat $DiskStorageFormat -Template $Template -Location $FolderLocation -OSCustomizationSpec $OSSpec
|
||||
}
|
||||
catch {
|
||||
Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
#If (!($BuildError)) {
|
||||
$VM = Get-VM -Name $FQDN
|
||||
|
||||
# Ensure CPU/Memory Hot-Add Enabled
|
||||
$vmView = $VM | Get-View
|
||||
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||
$vmOptValCPU = New-Object VMware.Vim.OptionValue
|
||||
$vmOptValMem = New-Object VMware.Vim.OptionValue
|
||||
$vmOptValCPU.Key = "vcpu.hotadd"
|
||||
$vmOptValMem.Key = "mem.hotadd"
|
||||
$vmOptValCPU.Value = "true"
|
||||
$vmOptValMem.Value = "true"
|
||||
$vmConfigSpec.ExtraConfig += $vmOptValCPU
|
||||
$vmConfigSpec.ExtraConfig += $vmOptValMem
|
||||
$vmView.ReconfigVM($vmConfigSpec)
|
||||
|
||||
# Set CPU, Memory, Network
|
||||
$VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false
|
||||
$VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false
|
||||
|
||||
# Power On VM
|
||||
$VM | Start-VM
|
||||
|
||||
# Wait for Customization to finish
|
||||
$VMStarted = $false
|
||||
$VMCustomizationStarted = $false
|
||||
$VMCustomizationResult = $false
|
||||
|
||||
While ($VMStarted -eq $false -or $VMCustomizationStarted -eq $false -or $VMCustomizationResult -eq $false) {
|
||||
Write-Warning ("Customization wait loop started " + (Get-Date))
|
||||
Write-Verbose "Current Status:"
|
||||
Write-Verbose ("VMStarted: " + $VMStarted)
|
||||
Write-Verbose ("VMCustomizationStarted: " + $VMCustomizationStarted)
|
||||
Write-Verbose ("VMCustomizationResult: " + $VMCustomizationResult)
|
||||
$GetVIEventRuntime = Measure-Command -Expression { $VMEvents = Get-VIEvent -Entity $VM -Server $ViServer -ErrorAction SilentlyContinue }
|
||||
Write-Verbose ("Get-VIEvent last run time: " + $GetVIEventRuntime.TotalSeconds + " seconds")
|
||||
If ($VMStarted -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "VMStartingEvent" })) {
|
||||
$VMStarted = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine started"
|
||||
}
|
||||
}
|
||||
If ($VMCustomizationStarted -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationStartedEvent" })) {
|
||||
$VMCustomizationStarted = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine customization started"
|
||||
}
|
||||
}
|
||||
If ($VMCustomizationResult -eq $false) {
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationFailed" })) {
|
||||
$VMCustomizationResult = $true
|
||||
Write-Error "[$FQDN]:Virtual machine customization failed"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
If (@($VMEvents | Where-Object { $_.GetType().Name -eq "CustomizationSucceeded" })) {
|
||||
$VMCustomizationResult = $true
|
||||
Write-Warning "[$FQDN]:Virtual machine customization completed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Delete OS Customization Spec
|
||||
# Get-OSCustomizationSpec -Name $NewOSSpecName | Remove-OSCustomizationSpec -Confirm:$false
|
||||
|
||||
# Add/Expand Disks
|
||||
Write-Warning -Message "[$FQDN]:Modify disks 1,2,3"
|
||||
$VMDisk = $VM | Get-HardDisk
|
||||
$VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
$VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2"
|
||||
$VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
|
||||
|
||||
$VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
If ($VMDisk1.CapacityGB -lt 60) {
|
||||
Set-HardDisk -HardDisk $VMDisk1 -CapacityGB 60 -Confirm:$false
|
||||
}
|
||||
|
||||
If (!$VMDisk2) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB ($MemoryGB + 1) `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2"
|
||||
If ($VMDisk2.CapacityGB -lt ($MemoryGB + 1)) {
|
||||
Set-HardDisk -HardDisk $VMDisk2 -CapacityGB ($MemoryGB + 1) -Confirm:$false
|
||||
}
|
||||
|
||||
If (!$VMDisk3) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB 20 `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
If ($VMDisk3.CapacityGB -lt 20) {
|
||||
Set-HardDisk -HardDisk $VMDisk3 -CapacityGB 20 -Confirm:$false
|
||||
}
|
||||
|
||||
# skipping tag assignment for now
|
||||
# Set-ITDVMwareVMTagFromSharePoint -ComputerName $FQDN -SharePointCredential $SPCred -Verbose
|
||||
|
||||
# Run Guest OS code
|
||||
# Enable RDP with NLA - can be done with GPO
|
||||
# Enable WinRM - ITD WinRM enable
|
||||
# Configure Power Plan - ITD-PowerPlan-HighPerformance
|
||||
# Activate Windows, KMS on-premise, Azure to Azure
|
||||
# DVD Drive to Z:
|
||||
# Expand C:
|
||||
# Partition/Format the rest, GPT/NTFS
|
||||
# Configure Page File Disk
|
||||
# Enabling server manager performance monitors
|
||||
# Configure Time Zone and NTP - no GPO available
|
||||
# Disable Windows Firewall
|
||||
# Join AD
|
||||
|
||||
#Initialize-ITDServer -Credential $ADCred
|
||||
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Assigning WMI Tag 000-Prod, SCCM will change it later if required"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Move DVD Drive Mount
|
||||
try {
|
||||
Write-Verbose "Create new Class"
|
||||
$Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null);
|
||||
|
||||
$Class["__CLASS"] = "ITD";
|
||||
$Class.Qualifiers.Add("Static", $true)
|
||||
$Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false)
|
||||
$Class.Properties["MyKey"].Qualifiers.Add("Key", $true)
|
||||
|
||||
$Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false)
|
||||
$Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false)
|
||||
$Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false)
|
||||
|
||||
$Class.Put()
|
||||
|
||||
Write-Verbose "Create single ITD Object"
|
||||
Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" }
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Checking for DVD drive..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Move DVD Drive Mount
|
||||
try {
|
||||
$dvd_letter = 'Z'
|
||||
$dvd = Get-WmiObject -Class Win32_Volume -Filter "DriveType=5" | Select-Object -First 1
|
||||
if ($dvd.Name -notmatch $dvd_letter) {
|
||||
Write-Verbose -Message "Found DVD drive, switching to $dvd_letter`:"
|
||||
|
||||
Set-WmiInstance -InputObject $dvd -Arguments @{DriveLetter = "$dvd_letter`:" } | Out-Null
|
||||
|
||||
Write-Verbose -Message "DVD drive moved to drive letter $dvd_letter`:"
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "No DVD drive changes required, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Checking for unpartitioned space on C: disk..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Expand C: Partition To Maximum Extent
|
||||
|
||||
|
||||
try {
|
||||
$cSize = ( Get-Partition -DriveLetter C ).Size
|
||||
$cMaxSize = ( Get-PartitionSupportedSize -DriveLetter C ).SizeMax
|
||||
|
||||
if ($cSize -lt $cMaxSize) {
|
||||
Write-Verbose -Message "Expanding C: from $($csize / 1GB)GB to $($cMaxSize / 1GB)GB..."
|
||||
|
||||
Resize-Partition -DriveLetter C -Size $cMaxSize
|
||||
|
||||
Write-Verbose -Message "C: expanded to $($cMaxSize / 1GB)GB."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "C: is already at maximum size, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Start Extra Disk(s) config"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Initialize Additional Disks
|
||||
try {
|
||||
# Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default
|
||||
$disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number
|
||||
|
||||
if ($disks) {
|
||||
Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks."
|
||||
|
||||
# Prevent the "You must format this partition before using it." popup
|
||||
if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue }
|
||||
|
||||
foreach ($disk in $disks) {
|
||||
if ($disk.IsOffline) {
|
||||
Set-Disk $disk.Number -IsOffline $false
|
||||
Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..."
|
||||
}
|
||||
|
||||
if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false }
|
||||
if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue }
|
||||
|
||||
$diskParam = @{
|
||||
FileSystem = 'NTFS'
|
||||
Confirm = $false
|
||||
}
|
||||
|
||||
$driveLetter = [Int][Char]'D'
|
||||
while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) {
|
||||
$driveLetter++
|
||||
}
|
||||
|
||||
$diskParam.DriveLetter = [Char]$driveLetter
|
||||
|
||||
if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) {
|
||||
$diskParam.NewFileSystemLabel = 'Temporary Storage'
|
||||
}
|
||||
elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) {
|
||||
$diskParam.NewFileSystemLabel = 'Data'
|
||||
}
|
||||
|
||||
[void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize)
|
||||
[void](Format-Volume @diskParam)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "No unpartitioned disks found, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
finally {
|
||||
if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue }
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Start Page File Configuration"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Configure Page File
|
||||
if (Get-Partition -DriveLetter D -ErrorAction SilentlyContinue) {
|
||||
Write-Verbose -Message "Setting up pagefile.sys on D:..."
|
||||
|
||||
try {
|
||||
if (-not [IO.File]::Exists('D:\pagefile.sys')) {
|
||||
$autoPage = Get-WmiObject -Class Win32_ComputerSystem -EnableAllPrivileges
|
||||
$autoPage.AutomaticManagedPagefile = $false
|
||||
[void]$autoPage.Put()
|
||||
|
||||
Write-Verbose -Message "Disabled automatic pagefile management."
|
||||
|
||||
$pageFile = Get-WmiObject -Class Win32_PageFileSetting -EnableAllPrivileges
|
||||
$pageFile.Delete()
|
||||
|
||||
Write-Verbose -Message "Deleted C:\pagefile.sys."
|
||||
|
||||
Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{ Name = "D:\pagefile.sys"; InitialSize = 0; MaximumSize = 0; } -EnableAllPrivileges | Out-Null
|
||||
|
||||
Write-Verbose -Message "System managed page file created on D:\pagefile.sys."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Pagefile already configured on D:, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Page file drive not found, cannot set up page file. Continuing server configuration..."
|
||||
Write-Warning "Page file drive not found, cannot set up page file. Continuing server configuration..."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Enabling Remote Management..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Configure Remote Management (RDP/PoSH)
|
||||
try {
|
||||
Write-Verbose -Message "Checking WinRM..."
|
||||
|
||||
if (Test-WSMan -ErrorAction SilentlyContinue) {
|
||||
Write-Verbose -Message "WinRM is already enabled."
|
||||
}
|
||||
else {
|
||||
Enable-PSRemoting -Force
|
||||
|
||||
Write-Verbose -Message "WinRM is now enabled."
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Checking RDP..."
|
||||
|
||||
$RDP = Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices
|
||||
$NLA = Get-WmiObject Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'"
|
||||
if ($RDP.AllowTSConnections -eq 0) {
|
||||
Write-Verbose -Message "RDP is disabled, enabling..."
|
||||
|
||||
$RDP.SetAllowTSConnections(1, 1) | Out-Null
|
||||
|
||||
Write-Verbose -Message "RDP is enabled."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "RDP is already enabled, checking NLA security..."
|
||||
}
|
||||
|
||||
if ($NLA.UserAuthenticationRequired -eq 0) {
|
||||
Write-Verbose -Message "RDP is not NLA secured, enabling..."
|
||||
|
||||
$NLA.SetUserAuthenticationRequired(1) | Out-Null
|
||||
|
||||
Write-Verbose -Message "RDP is now NLA secured."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "RDP is already NLA secured."
|
||||
}
|
||||
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Checking current power plan..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Configure Power Plan
|
||||
try {
|
||||
$powerPlans = powercfg -l
|
||||
|
||||
if ($powerPlans -match '\*$' -notmatch 'High performance') {
|
||||
$currentPlan = [regex]::Match($powerPlans, '(?<=(\())[^)]+(?=(\)\s\*))').Value
|
||||
|
||||
Write-Verbose -Message "Power plan is currently set to $currentPlan, changing to High Performance..."
|
||||
|
||||
$highPerformance = [regex]::Match($powerPlans, '([\d\w-\S]+)(?=\s+\(High performance\))').Value
|
||||
[void](powercfg -setactive $highPerformance)
|
||||
|
||||
Write-Verbose -Message "Power plan set to High Performance."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Power plan already configured for High Performance."
|
||||
}
|
||||
|
||||
[void](& w32tm.exe /resync /nowait)
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$TimeSyncFunc = {
|
||||
# Configure Time/Date Settings
|
||||
Write-Verbose -Message "Checking current time/date settings..."
|
||||
$Domain = "<DomainName>"
|
||||
try {
|
||||
if ((Get-TimeZone).Id -ne 'Central Standard Time') {
|
||||
Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time."
|
||||
|
||||
Set-TimeZone -Id 'Central Standard Time'
|
||||
|
||||
Write-Verbose -Message "Time zone set to Central Standard Time."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Time zone is already set to Central Standard Time."
|
||||
}
|
||||
<#
|
||||
Write-Verbose -Message "Beginning a time synchronization..."
|
||||
|
||||
if ((Get-Service W32Time).Status -eq 'Stopped') {
|
||||
Start-Service W32Time
|
||||
}
|
||||
|
||||
[void](& w32tm.exe /config /manualpeerlist:$Domain /syncfromflags:all /update)
|
||||
|
||||
[void](& w32tm.exe /resync /nowait)
|
||||
|
||||
# Start background job to check time service
|
||||
$tmJob = Start-Job -Name 'ManualTimeSync' -ScriptBlock {
|
||||
do {
|
||||
$tmOut = & w32tm.exe /query /status /verbose
|
||||
|
||||
Start-Sleep -Seconds 10
|
||||
} until($tmOut -match '^Last Sync Error: 0\D+$')
|
||||
}
|
||||
|
||||
# If after three minutes time still has not synched, move on. This usually causes no problems.
|
||||
if ((Wait-Job -Job $tmJob -Timeout 180).State -eq 'Completed') {
|
||||
Write-Warning -Message "Time synchronization with $($Domain.ToLower()) successful."
|
||||
}
|
||||
else {
|
||||
[void](Stop-Job -Job $tmJob)
|
||||
Write-Warning -Message "Time synchronization with $($Domain.ToLower()) failed."
|
||||
}
|
||||
#>
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
$TimeSyncScriptBlock = $TimeSyncFunc -replace '<DomainName>', $DomainName
|
||||
$VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $TimeSyncScriptBlock
|
||||
#>
|
||||
Write-Warning -Message "[$FQDN]:Enabling the server manager performance monitors..."
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Enable Performance Counters
|
||||
|
||||
|
||||
try {
|
||||
if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) {
|
||||
Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask
|
||||
|
||||
Write-Verbose -Message "Performance monitors enabled."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Performance monitors already enabled, continuing..."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Disable Windows Firewall"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText {
|
||||
# Disable Windows Firewall
|
||||
Write-Verbose -Message "Checking for active Windows Firewall..."
|
||||
|
||||
if ((Get-NetFirewallProfile).Enabled -contains 'True') {
|
||||
Write-Verbose -Message "Windows Firewall is still enabled, disabling it..."
|
||||
|
||||
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False
|
||||
|
||||
Write-Verbose -Message "Windows Firewall disabled."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Windows Firewall already disabled, continuing..."
|
||||
}
|
||||
}
|
||||
|
||||
# Active Directory
|
||||
Write-Warning "[$FQDN]:Join Active Directory (if required)"
|
||||
$DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1)
|
||||
switch ($DomainName) {
|
||||
'nd.gov' {
|
||||
$SearchBaseDomain = "dc=nd,dc=gov"
|
||||
}
|
||||
'ndcloud.gov' {
|
||||
$SearchBaseDomain = "dc=ndcloud,dc=gov"
|
||||
}
|
||||
}
|
||||
|
||||
If ($DomainName -eq "nd.gov") {
|
||||
$OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter {Name -eq $AppName}
|
||||
If (!($OUAppName)) {
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' }
|
||||
}
|
||||
$ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname }
|
||||
If ($ExistingADComputer) {
|
||||
If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") {
|
||||
Write-Warning "AD object already exists, OU path does match"
|
||||
$OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(?<!\\),', ''
|
||||
}
|
||||
Else {
|
||||
Write-Error "AD object already exists, OU path mismatch"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
}
|
||||
Else {
|
||||
switch ($SPItem.Environment) {
|
||||
'Test' {
|
||||
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Non-Prod" }
|
||||
Else { $EnvString = "Test" }
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -Like "*$EnvString*"
|
||||
}
|
||||
'Production' {
|
||||
$EnvString = "Prod"
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -Like "*$EnvString*"
|
||||
}
|
||||
}
|
||||
If ($OuAppNameEnv) { $OUFinal = $OUAppNameEnv.DistinguishedName }
|
||||
Else { $OuFinal = $OUAppName.DistinguishedName }
|
||||
|
||||
#New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json)
|
||||
}
|
||||
|
||||
$FirstScriptBlock = { $DomainJoinCred = New-Object System.Management.Automation.PSCredential('svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) }
|
||||
$SecondScriptText = 'Add-Computer -DomainName <DomainName> -OUPath "<OuPath>" -Credential $DomainJoinCred'
|
||||
$SecondScriptText = $SecondScriptText -replace '<DomainName>', $DomainName
|
||||
$SecondScriptText = $SecondScriptText -replace '<OuPath>', $OuFinal
|
||||
$SecondScriptText = $SecondScriptText -replace '<OuPath>', ("OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain)
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Invoke-VMScript to AD join"
|
||||
$InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText")
|
||||
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptType PowerShell -ScriptText $InvokeVMScriptFunc
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Restart VMGuest, wait for Tools, then 90 seconds after"
|
||||
Get-VM -Name $FQDN | Restart-VMGuest -Confirm:$false
|
||||
Wait-Tools -VM (Get-VM -Name $FQDN)
|
||||
Start-Sleep -Seconds 90
|
||||
}
|
||||
|
||||
Write-Warning ("[$FQDN]:Copying SCCM client installer to C:\temp... " + (Get-Date))
|
||||
Copy-VMGuestFile -Source C:\SCCM_Client\ -Destination C:\temp\SCCM_Client -VM (Get-VM -Name $FQDN) -LocalToGuest -GuestCredential $GuestCredentialAB -Force
|
||||
Write-Warning ("[$FQDN]:SCCM client copy complete " + (Get-Date))
|
||||
#E:\AutoBuild\SCCM_Client\
|
||||
|
||||
# Check if SCCM automatically installed the SCCM client and registered it
|
||||
$CcmRegistered = $false
|
||||
$CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log
|
||||
}
|
||||
If ($CcmRegistration.ScriptOutput -match "Client is registered") {
|
||||
Write-Warning "Client is registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") {
|
||||
Write-Warning "Client is already registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
If ($CcmRegistered -eq $false) {
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
|
||||
If (Get-Process -Name ccmsetup -ErrorAction SilentlyContinue) {
|
||||
Write-Warning "CCM client is already installing"
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf (Get-Process -Name ccmexec -ErrorAction SilentlyContinue) {
|
||||
Write-Warning "CCM client is already installed"
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
Else {
|
||||
Write-Warning -Message "Installing SCCM Client..."
|
||||
Invoke-Expression -Command "C:\temp\SCCM_Client\ccmsetup.exe SMSSITECODE=ITD SMSMP=itdsccmp2.nd.gov DNSSUFFIX=nd.gov"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Register SCCM Client"
|
||||
While ($CcmRegistered -eq $false) {
|
||||
$CcmRegistration = Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
Get-Content C:\windows\ccm\logs\ClientIDManagerStartup.log
|
||||
}
|
||||
If ($CcmRegistration.ScriptOutput -match "Client is registered") {
|
||||
Write-Warning "Client is registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistration.ScriptOutput -match "Client is already registered") {
|
||||
Write-Warning "Client is already registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 30 }
|
||||
}
|
||||
|
||||
Write-Warning -Message "[$FQDN]:Approve SCCM Client"
|
||||
#Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL
|
||||
Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock {
|
||||
Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
|
||||
$PSDrives = Get-PSDrive
|
||||
If ($PSDrives | Where-Object Name -EQ "ITD") {
|
||||
# ITD Drive exists, do nothing
|
||||
}
|
||||
else {
|
||||
New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov
|
||||
}
|
||||
|
||||
Set-Location ITD:\
|
||||
$Device = Get-CMDevice -Name $args[0]
|
||||
If ($Device.IsApproved -eq 0) {
|
||||
Approve-CMDevice -DeviceName $args[0]
|
||||
}
|
||||
}
|
||||
|
||||
# vcenter tags
|
||||
#AppName Tag
|
||||
|
||||
New-TagAssignment -Entity (Get-VM $FQDN -server $VIServer) -Tag (Get-Tag -Server $VIServer -Category AppName -Name $AppName) -Server $VIServer
|
||||
New-TagAssignment -Entity (Get-VM $FQDN -server $VIServer) -Tag (Get-Tag -Server $VIServer -Category DTAP -Name $Environment) -Server $VIServer
|
||||
|
||||
|
||||
Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
[void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
|
||||
}
|
||||
|
||||
Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy"
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
[void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
|
||||
}
|
||||
#Start-Sleep -Seconds 180
|
||||
|
||||
Write-Warning -Message '[$FQDN]:Waiting for network connectivity / Then KVM Activation...'
|
||||
Get-VM -Name $FQDN | Invoke-VMScript -GuestCredential $GuestCredentialAB -ScriptType PowerShell -ScriptText {
|
||||
# Pause until network connectivity is available
|
||||
|
||||
$KMS = 'kms.nd.gov'
|
||||
|
||||
try {
|
||||
$nwJob = Start-Job -Name 'NetworkCheck' -ScriptBlock {
|
||||
Param ( [String]$KMS )
|
||||
do {
|
||||
$nwStatus = Test-NetConnection -ComputerName $KMS -Port 1688 -InformationLevel Quiet
|
||||
|
||||
Start-Sleep -Seconds 10
|
||||
} until($nwStatus)
|
||||
} -ArgumentList $KMS
|
||||
|
||||
# If after 30 seconds the network connection is not responding continue on
|
||||
if ((Wait-Job -Job $nwJob -Timeout 30).State -eq 'Completed') {
|
||||
Write-Verbose -Message 'Network connectivity has been verified.'
|
||||
}
|
||||
else {
|
||||
[void](Stop-Job -Job $nwJob)
|
||||
Write-Verbose -Message 'Network connectivity could not be verified.'
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
|
||||
# Activate via KMS
|
||||
Write-Verbose -Message "Activating windows against $KMS..."
|
||||
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit
|
||||
}
|
||||
try {
|
||||
cscript C:\Windows\System32\slmgr.vbs /skms $KMS | Out-Null
|
||||
cscript C:\Windows\System32\slmgr.vbs /ato | Out-Null
|
||||
|
||||
Write-Verbose -Message "Checking activation status..."
|
||||
|
||||
$kmsOut = cscript C:\Windows\System32\slmgr.vbs /dli
|
||||
|
||||
if (($kmsOut | Select-String -Pattern '^License Status:') -match 'Licensed') {
|
||||
Write-Verbose -Message "Windows successfully activated."
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct."
|
||||
Write-Warning -Message "Windows failed to activate, run slmgr commands manually. Ensure server time is correct."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Throw $_
|
||||
Break
|
||||
}
|
||||
}
|
||||
Write-Warning "[$FQDN]:End"
|
||||
|
||||
|
||||
<#
|
||||
Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock { Get-Process -Name ccmexec*, cohesity*, cyserver*, nessus*, vmtoolsd* }
|
||||
|
||||
Write-Warning "[$FQDN]:Trigger SCCM MachinePolicy First Check-in"
|
||||
Invoke-Command -ComputerName $FQDNs -Credential $PrvCred -ScriptBlock {
|
||||
[void] ([wmiclass] "\\localhost\root\ccm:SMS_Client").TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
|
||||
}#>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
$OVServers = Get-OVServer
|
||||
|
||||
ForEach($OVServer in $OVServers){
|
||||
$Enclosure = $OVServer.Name.split('_')[0]
|
||||
$VMHost = Get-VMHost -Name $OVServer.ServerName
|
||||
$ViServer = $VMHost.Uid.Split("@")[1].Split(':')[0]
|
||||
$OldTagAssignment = $VMhost | Get-TagAssignment
|
||||
$OldTag = $OldTagAssignment.Tag
|
||||
$NewTag = Get-Tag -Category "HPE Enclosure" -Name $Enclosure -Server $ViServer
|
||||
|
||||
If ($OldTag -eq $NewTag){
|
||||
|
||||
}
|
||||
Else{
|
||||
$OldTagAssignment | Remove-TagAssignment -Confirm:$false
|
||||
$VMHost | New-TagAssignment -Tag $NewTag
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
function Set-ITDVMwareVMTag {
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[string]
|
||||
$ComputerName,
|
||||
|
||||
[string]
|
||||
$AppName,
|
||||
|
||||
[string]
|
||||
$Dtap,
|
||||
|
||||
[string]
|
||||
$OperatingSystem,
|
||||
|
||||
[string]
|
||||
$StartupPriority
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
$VMs = Get-VM -Name $ComputerName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If ($VMs) {
|
||||
ForEach ($VM in $VMs) {
|
||||
#AppName Tag
|
||||
Write-Verbose ($VM.Name + ": AppName Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category AppName -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
$NewTagName = $AppName
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " AppName old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works
|
||||
|
||||
#Get-Tag -Category AppName -Name $NewTagName -Server $VIServer
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category AppName -Name $NewTagName) -Server $VIServer
|
||||
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)#
|
||||
}
|
||||
Write-Verbose ($VM.Name + ": AppName Tag End")
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
#DTAP Tag
|
||||
Write-Verbose ($VM.Name + ": DTAP Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category DTAP -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
$NewTagName = $DTAP
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " DTAP old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works
|
||||
|
||||
#Get-Tag -Category AppName -Name $NewTagName -Server $VIServer
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category DTAP -Name $NewTagName) -Server $VIServer
|
||||
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)
|
||||
}
|
||||
Write-Verbose ($VM.Name + ": DTAP Tag End")
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
#Startup Priority
|
||||
Write-Verbose ($VM.Name + ": StartupPriority Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category 'StartupPriority' -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
$NewTagName = $StartupPriority
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " StartupPriority old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works
|
||||
|
||||
#Get-Tag -Category AppName -Name $NewTagName -Server $VIServer
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'StartupPriority' -Name $NewTagName) -Server $VIServer
|
||||
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)
|
||||
}
|
||||
Write-Verbose ($VM.Name + ": StartupPriority Tag End")
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
# OS Tag
|
||||
Write-Verbose ($VM.Name + ": OS Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category "Operating System" -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
$NewTagName = $OperatingSystem
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " OS old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") }
|
||||
If ($NewTagName -ne "None") {
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'Operating System' -Name $NewTagName) -Server $VIServer
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)
|
||||
}
|
||||
else {
|
||||
Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer)
|
||||
}
|
||||
}
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
Write-Verbose ($VM.Name + ": OS Tag End")
|
||||
|
||||
# Licensing Tag
|
||||
Write-Verbose ($VM.Name + ": Licensing Restrictions Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category "LicensingRestrictions" -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
$NewTagName = $LicensingRestrictions
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " Licensing old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") }
|
||||
If ($NewTagName -ne "None") {
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'LicensingRestrictions' -Name $NewTagName) -Server $VIServer
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)
|
||||
}
|
||||
else {
|
||||
Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer)
|
||||
}
|
||||
}
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
Write-Verbose ($VM.Name + ": Licensing Tag End")
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
|
||||
<# SRM Recovery Type Tags
|
||||
Write-Verbose ($VM.Name + ": SRM Recovery Type Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category "SRM Recovery Type" -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
If ($VM.ExtensionData.summary.config.ManagedBy.Type -eq "placeholderVm" ) {
|
||||
#If VM is placeholder
|
||||
$NewTagName = "Placeholder"
|
||||
}
|
||||
Else {
|
||||
$NewTagName = $SPItem.SRM_RecoveryVMtype
|
||||
}
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " SRM Recovery Type old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$False -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") }
|
||||
If ($NewTagName -ne "None") {
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'SRM Recovery Type' -Name $NewTagName) -Server $VIServer
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)
|
||||
}
|
||||
else {
|
||||
Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer)
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose ($VM.Name + ": SRM Recovery Type Tag End")#>
|
||||
|
||||
$OldTag = $null
|
||||
$VIServer = $null
|
||||
$OldTagName = $null
|
||||
$NewTagName = $null
|
||||
|
||||
<#VR RPO Tag
|
||||
Write-Verbose ($VM.Name + ": SRM Tag Start")
|
||||
$OldTag = Get-TagAssignment -Category 'VR RPO' -Entity $VM
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
$OldTagName = $OldTag.tag.name
|
||||
$NewTagName = $SPItem.DR_Protection -replace "VMware: "
|
||||
|
||||
If ($OldTagName -ne $NewTagName) {
|
||||
Write-Verbose ($VM.Name + " SRM old and new tags different")
|
||||
Write-Verbose ("Old Tag " + $OldTagName)
|
||||
Write-Verbose ("New Tag " + $NewTagName)
|
||||
|
||||
If ($OldTag) { $OldTag | Remove-TagAssignment -Confirm:$false -ErrorAction SilentlyContinue; Write-Host ($VM.Name + " Tag Removed") } #Errors with Remove-TagAssignment : Cannot bind argument to parameter 'TagAssignment' because it is null. --- but still works
|
||||
#Get-Tag -Category AppName -Name $NewTagName -Server $VIServer
|
||||
If ($NewTagName -ne "None") {
|
||||
New-TagAssignment -Entity (Get-VM $VM.Name -Server $VIServer -OutVariable VM) -Tag (Get-Tag -Server $VIServer -Category 'VR RPO' -Name $NewTagName) -Server $VIServer
|
||||
Write-Verbose ($VM.Name + " tag updated " + $VIServer)
|
||||
}
|
||||
else {
|
||||
Write-Verbose ($VM.Name + " tag invalid or None " + $VIServer)
|
||||
}
|
||||
|
||||
}#>
|
||||
}
|
||||
}
|
||||
Else {
|
||||
|
||||
}
|
||||
#}
|
||||
<#catch {
|
||||
Write-Error ($VM.Name + " tag errored")
|
||||
Write-Error $error[-1]
|
||||
}#>
|
||||
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
$AllVMs = Get-Datacenter -Name Primary* | Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "vCLS*" }
|
||||
|
||||
$AllVMs | Select Name,NumCpu,MemoryGB,@{n='Cluster';e={$_.VMHost | Get-Cluster}},@{n='SRM Recovery Type';e={($_ | Get-TagAssignment -Category "SRM Recovery Type").Tag.Name}} -OutVariable result
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Daily VM metadata report for PowerBI trending and hardware capacity planning.
|
||||
|
||||
.DESCRIPTION
|
||||
Collects VM metadata from vCenter including compute, storage, OS, and VMware Tools
|
||||
information using only data available within vCenter (no direct guest connections).
|
||||
Exports a timestamped CSV each run -- append daily runs to build a historical dataset
|
||||
suitable for PowerBI trend analysis and physical hardware purchasing decisions.
|
||||
|
||||
.PARAMETER vCenterServers
|
||||
One or more vCenter server hostnames. Defaults to itdvmvc1.nd.gov and itdvmvc2.nd.gov.
|
||||
|
||||
.PARAMETER DatacenterFilter
|
||||
Wildcard filter applied to datacenter names. Defaults to 'Primary*'.
|
||||
|
||||
.PARAMETER OutputPath
|
||||
Directory where CSV and log files are written.
|
||||
Defaults to C:\ITDSCRIPT\Reports\VMMetadata.
|
||||
|
||||
.PARAMETER CredentialPath
|
||||
Path to a saved PSCredential XML file for unattended/scheduled runs.
|
||||
Create one interactively with:
|
||||
Get-Credential | Export-Clixml -Path C:\ITDSCRIPT\Creds\vCenter.xml
|
||||
When omitted the script prompts for credentials.
|
||||
|
||||
.EXAMPLE
|
||||
# Interactive run
|
||||
.\VMware-VMDailyMetadataReport.ps1
|
||||
|
||||
.EXAMPLE
|
||||
# Scheduled / unattended run
|
||||
.\VMware-VMDailyMetadataReport.ps1 -CredentialPath 'C:\ITDSCRIPT\Creds\vCenter.xml'
|
||||
|
||||
.NOTES
|
||||
Scheduled Task suggestion (run as service account that owns the credential XML):
|
||||
Program : powershell.exe
|
||||
Args : -NonInteractive -ExecutionPolicy Bypass -File "C:\ITDSCRIPT\VMware-VMDailyMetadataReport.ps1" -CredentialPath "C:\ITDSCRIPT\Creds\vCenter.xml"
|
||||
Trigger : Daily at 06:00
|
||||
|
||||
Guest OS disk capacity / used columns are populated only for powered-on VMs with
|
||||
VMware Tools running; they will be empty for powered-off VMs and SRM placeholders.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string] $OutputPath = 'C:\temp\VM_Trends\'
|
||||
)
|
||||
|
||||
#region --- Setup ---------------------------------------------------------------
|
||||
|
||||
$RunDate = Get-Date
|
||||
$DateStamp = $RunDate.ToString('yyyyMMdd')
|
||||
$Timestamp = $RunDate.ToString('yyyy-MM-dd HH:mm:ss')
|
||||
|
||||
if (-not (Test-Path -Path $OutputPath)) {
|
||||
New-Item -ItemType Directory -Path $OutputPath | Out-Null
|
||||
}
|
||||
|
||||
Start-Transcript -Path (Join-Path $OutputPath "VMMetadataReport_$DateStamp.log") -Append
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Build VMHost -> Cluster/Datacenter Lookups (avoids per-VM API calls) -
|
||||
|
||||
Write-Verbose 'Building host-to-cluster and host-to-datacenter maps...'
|
||||
$HostClusterMap = @{}
|
||||
$HostDatacenterMap = @{}
|
||||
|
||||
Get-Datacenter | ForEach-Object {
|
||||
$DatacenterName = $_.Name
|
||||
Get-VMHost -Location $_ | ForEach-Object {
|
||||
$HostDatacenterMap[$_.Name] = $DatacenterName
|
||||
}
|
||||
}
|
||||
|
||||
Get-Cluster | ForEach-Object {
|
||||
$ClusterName = $_.Name
|
||||
Get-VMHost -Location $_ | ForEach-Object {
|
||||
$HostClusterMap[$_.Name] = $ClusterName
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Collect VM Data -----------------------------------------------------
|
||||
|
||||
Write-Verbose "Gathering VMs"
|
||||
|
||||
# Include ALL VMs (SRM placeholders flagged via column, not excluded).
|
||||
# vCLS agent VMs are excluded -- they are vSphere internal and not customer workloads.
|
||||
$AllVMs = Get-VM | Where-Object { $_.Name -notlike 'vCLS*' }
|
||||
|
||||
Write-Verbose "Processing $($AllVMs.Count) VMs..."
|
||||
|
||||
$Results = foreach ($VM in $AllVMs) {
|
||||
|
||||
$Ext = $VM.ExtensionData # single API object -- reuse for all fields
|
||||
|
||||
#--- SRM placeholder detection
|
||||
$IsSRMPlaceholder = $Ext.Summary.Config.ManagedBy.Type -eq 'placeholderVm'
|
||||
|
||||
#--- Cluster / Datacenter (null-safe: standalone hosts have no cluster entry)
|
||||
$ClusterName = $HostClusterMap[$VM.VMHost.Name]
|
||||
$DatacenterName = $HostDatacenterMap[$VM.VMHost.Name]
|
||||
|
||||
#--- Storage platform parsed from datastore name convention: VMCLUSTER_LUN_PLATFORM_Desc
|
||||
# Segment 2 = storage platform identifier (e.g. FS92, A9K).
|
||||
# Cluster grouping uses the compute Cluster column -- no need to re-derive it here.
|
||||
$StoragePlatforms = foreach ($DSName in $Ext.Config.DatastoreUrl.Name) {
|
||||
$Segments = $DSName -split '_'
|
||||
if ($Segments.Count -ge 3) { $Segments[2] }
|
||||
}
|
||||
$StoragePlatform = ($StoragePlatforms | Sort-Object -Unique) -join '; '
|
||||
|
||||
#--- VMware Tools guest disk info
|
||||
# Populated only when Tools is running; null otherwise.
|
||||
$GuestDiskCapacityGB = $null
|
||||
$GuestDiskUsedGB = $null
|
||||
if ($Ext.Guest.Disk) {
|
||||
$TotalCapBytes = ($Ext.Guest.Disk | Measure-Object -Property Capacity -Sum).Sum
|
||||
$TotalFreeBytes = ($Ext.Guest.Disk | Measure-Object -Property FreeSpace -Sum).Sum
|
||||
$GuestDiskCapacityGB = [Math]::Round($TotalCapBytes / 1GB, 2)
|
||||
$GuestDiskUsedGB = [Math]::Round(($TotalCapBytes - $TotalFreeBytes) / 1GB, 2)
|
||||
}
|
||||
|
||||
[PSCustomObject]@{
|
||||
# --- Identity & grouping
|
||||
ReportDate = $Timestamp # for PowerBI time-series/trend axis
|
||||
VMName = $VM.Name
|
||||
Datacenter = $DatacenterName
|
||||
Cluster = $ClusterName
|
||||
PowerState = $VM.PowerState
|
||||
IsSRMPlaceholder = $IsSRMPlaceholder
|
||||
StoragePlatform = $StoragePlatform
|
||||
GuestOS = $Ext.Guest.GuestFullName
|
||||
|
||||
# --- Compute
|
||||
vCPUs = $VM.NumCpu
|
||||
MemoryGB = $VM.MemoryGB
|
||||
|
||||
# --- Datastore-level storage
|
||||
# ProvisionedSpaceGB : maximum the VM could consume (thin disks counted at max size)
|
||||
# UsedSpaceGB : bytes actually committed on datastores right now
|
||||
ProvisionedSpaceGB = [Math]::Round($VM.ProvisionedSpaceGB, 2)
|
||||
UsedSpaceGB = [Math]::Round($VM.UsedSpaceGB, 2)
|
||||
|
||||
# --- Guest OS-level storage (from VMware Tools; null when Tools not running)
|
||||
# GuestDiskCapacityGB : sum of all volume capacities seen inside the guest
|
||||
# GuestDiskUsedGB : sum of space consumed across those volumes
|
||||
GuestDiskCapacityGB = $GuestDiskCapacityGB
|
||||
GuestDiskUsedGB = $GuestDiskUsedGB
|
||||
|
||||
# --- VMware Tools
|
||||
# ToolsRunningStatus : guestToolsRunning | guestToolsNotRunning | guestToolsExecutingScripts
|
||||
# ToolsVersionStatus : guestToolsCurrent | guestToolsNeedUpgrade | guestToolsUnmanaged | guestToolsTooNew
|
||||
# ToolsVersion : numeric build version string reported by vCenter
|
||||
ToolsRunningStatus = $Ext.Guest.ToolsRunningStatus
|
||||
ToolsVersionStatus = $Ext.Guest.ToolsVersionStatus
|
||||
ToolsVersion = $Ext.Guest.ToolsVersion
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Export --------------------------------------------------------------
|
||||
|
||||
$OutputFile = Join-Path $OutputPath "VMMetadata_$DateStamp.csv"
|
||||
$Results | Export-Csv -Path $OutputFile -NoTypeInformation
|
||||
|
||||
Write-Verbose "Exported $($Results.Count) VM records to: $OutputFile"
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Cleanup -------------------------------------------------------------
|
||||
Stop-Transcript
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1,42 @@
|
||||
# report current status
|
||||
$AllVMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$WS2022VMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestFullName -like "*2022*" } | Sort-Object Name
|
||||
$WS2022VMs | select Name, @{n = 'EfiSecureBootEnabled'; e = { $_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled } }
|
||||
|
||||
|
||||
|
||||
$VMNames = @"
|
||||
itdexchtest1.testnd.gov
|
||||
itdexchtest2.testnd.gov
|
||||
itdexch1.nd.gov
|
||||
itdexch2.nd.gov
|
||||
"@
|
||||
|
||||
$VMNames = ConvertTo-Array -MultiLineString $VMNames
|
||||
|
||||
# power off VMs
|
||||
ForEach ($VMName in $VMNames) {
|
||||
Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Stop-VMGuest -Confirm:$false
|
||||
}
|
||||
|
||||
# wait for all to be powered off
|
||||
Get-VM -Name $VMNames
|
||||
|
||||
# disable secure boot on all of them
|
||||
ForEach ($VMname in $VMNames) {
|
||||
$vm = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||
$spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi
|
||||
$boot = New-Object VMware.Vim.VirtualMachineBootOptions
|
||||
$boot.EfiSecureBootEnabled = $false # false to disable obviously
|
||||
$spec.BootOptions = $boot
|
||||
$vm.ExtensionData.ReconfigVM($spec)
|
||||
}
|
||||
|
||||
# validate
|
||||
Get-VM -Name $VMNames | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }| select Name, @{n = 'EfiSecureBootEnabled'; e = { $_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled } }
|
||||
|
||||
# power on
|
||||
ForEach($VMName in $VMNames){
|
||||
Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Start-VM
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
# report current status
|
||||
$AllVMs = Get-VM | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$WS2022VMs = $AllVMs | Where-Object { $_.ExtensionData.Guest.GuestFullName -like "*2022*" } | Sort-Object Name
|
||||
$WS2022VMs | select Name, @{n = 'EfiSecureBootEnabled'; e = { $_.ExtensionData.Config.BootOptions.EfiSecureBootEnabled } }
|
||||
|
||||
|
||||
|
||||
$VMNames = @"
|
||||
itdaddressprot2.nd.gov
|
||||
itdqlikreptst1.ndcloud.gov
|
||||
itdqlikrepprd1.ndcloud.gov
|
||||
itdexch1.nd.gov
|
||||
itdexch2.nd.gov
|
||||
itdexchtest1.testnd.gov
|
||||
itdexchtest2.testnd.gov
|
||||
"@
|
||||
|
||||
$VMNames = ConvertTo-Array -MultiLineString $VMNames
|
||||
|
||||
# power off VMs
|
||||
ForEach ($VMName in $VMNames) {
|
||||
Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Stop-VMGuest -Confirm:$false
|
||||
}
|
||||
|
||||
# wait for all to be powered off
|
||||
Get-VM -Name $VMNames
|
||||
|
||||
# disable secure boot on all of them
|
||||
ForEach ($VMname in $VMNames) {
|
||||
$vm = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||
$spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi
|
||||
$boot = New-Object VMware.Vim.VirtualMachineBootOptions
|
||||
$boot.EfiSecureBootEnabled = $true # false to disable obviously
|
||||
$spec.BootOptions = $boot
|
||||
$vm.ExtensionData.ReconfigVM($spec)
|
||||
}
|
||||
|
||||
# power on
|
||||
ForEach($VMName in $VMNames){
|
||||
Get-VM -Name $VMName | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Start-VM
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
# Dump list of VMs from ServiceNow
|
||||
Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "serial_numberSTARTSWITHvmware" -IncludeTotalCount | Export-Csv "C:\temp\CMDB_VMwareDump.csv"
|
||||
|
||||
# Disable DRS on all clusters
|
||||
Get-Cluster LINUX*, MGMT*, ORACLE1, PS*, SQLa*, SQLe*, VAPP*, WAS*, WINDOWS* | Set-Cluster -DrsEnabled $false
|
||||
|
||||
# Dump location of all VMs to CSV
|
||||
Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } | select Name, PowerState, NumCpu, MemoryGB, VMHost, @{n = 'Datastores'; e = { ($_ | Get-Datastore).Name } } | Export-Csv "D:\State of North Dakota\-Tm-ITD-Virtualization - Documents\VMinfo.csv"
|
||||
|
||||
# VM array
|
||||
$VMHosts = @(
|
||||
'itdvmbismgmt02.nd.gov',
|
||||
'itdvmbismgmt03.nd.gov',
|
||||
'itdvmmdnmgmt01.nd.gov',
|
||||
'itdvmbismgmt02.nd.gov'
|
||||
)
|
||||
|
||||
# Disable lockdown on MGMT hosts
|
||||
$VMHosts | ForEach-Object {
|
||||
(Get-VMHost -Name $_ | Get-View).ExitLockdownMode()
|
||||
}
|
||||
|
||||
# connect to mgmt cluster
|
||||
$VMHosts | ForEach-Object {
|
||||
Connect-VIServer -Server $_ -Credential (Get-ITDPassword -Title $_ -UserName root -Credential $PrvCred)
|
||||
}
|
||||
|
||||
## verify lockdown mode is disabled manually
|
||||
|
||||
# get list of VMs | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$VMs = Get-VM | Where-Object { $_.Name -notlike "vCLS*" -and $_.PowerState -eq "PoweredOn" -and $_.Name -notlike "itdvmutil*" -and $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm"} | Sort-Object Name
|
||||
|
||||
# Cleanup snapshots on MGMT cluster
|
||||
$VMs | Get-Snapshot | Where-Object Name -NotLike "*9.0.2*" | Remove-Snapshot -RunAsync
|
||||
|
||||
# Shutdown all appliance VMs on MGMT cluster
|
||||
$VMs | Stop-VMGuest -Confirm:$false #-RunAsync
|
||||
|
||||
# Wait for VMs to power off
|
||||
Get-VM -Name $VMs.Name | Sort-Object Name
|
||||
#Get-Cluster MGMT1, MGMT2 | Get-VM | Where-Object { $_.Name -notlike "itdvmutil*" } | Sort-Object Name
|
||||
|
||||
# Create offline snapshots
|
||||
$VMs | New-Snapshot -Name "9_Before 8.0 U3e Upgrade" -Description "9_Before 8.0 U3e Upgrade" -Confirm:$false -RunAsync
|
||||
|
||||
# Power on all VMs on MGMT cluster
|
||||
$VMs | Start-VM -Confirm:$false
|
||||
|
||||
Break
|
||||
|
||||
## online mid-upgrade snapshots
|
||||
$VMs | New-Snapshot -Name "1_vc_upgrade_complete" -Description "2_vc1_stage2_complete" -Confirm:$false -RunAsync -Memory
|
||||
|
||||
Get-VM -Name itdvmvc*,itdvmsrm*, itdvmvra* | Where-Object {$_.Name -notlike "*7.0*"} | Stop-VMGuest -Confirm:$false
|
||||
|
||||
# post upgrade snapshot
|
||||
Get-VM -Name itdvmvc*,itdvmsrm*, itdvmvra* | New-Snapshot -Name "2_vc_upgrade_complete" -Description "2_vc1_stage2_complete" -Confirm:$false -RunAsync -Memory
|
||||
Get-VM -Name itdvmvc*,itdvmsrm*, itdvmvra* | Start-VM
|
||||
##### after upgrade
|
||||
|
||||
# Enable DRS on clusters that should have it
|
||||
Get-Cluster LINUX*, MGMT*, ORACLE1, PS*, SQLa*, SQLe*, VAPP*, WAS*, WINDOWS* | Set-Cluster -DrsEnabled $true
|
||||
|
||||
# Enable lockdown on MGMT hosts
|
||||
(Get-VMHost itdvmbismgmt01.nd.gov | Get-View).EnterLockdownMode()
|
||||
(Get-VMHost itdvmbismgmt02.nd.gov | Get-View).EnterLockdownMode()
|
||||
(Get-VMHost itdvmmdnmgmt01.nd.gov | Get-View).EnterLockdownMode()
|
||||
(Get-VMHost itdvmmdnmgmt02.nd.gov | Get-View).EnterLockdownMode()
|
||||
|
||||
# reconfigure distributed switch to use both vnics
|
||||
#### manual
|
||||
@@ -0,0 +1,13 @@
|
||||
$AllVMs = Get-VM | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$data = $AllVMs | `
|
||||
Select-Object Name, `
|
||||
VMHost, `
|
||||
UsedSpaceGB, `
|
||||
ProvisionedSpaceGB #, `
|
||||
#@{n = 'Disks'; e = { $_ | Get-HardDisk | Select Name, FileName, CapacityGB } }, `
|
||||
#@{n = 'VRDatastore'; e = { ($_ | Get-TagAssignment | Where-Object Tag -like "*_VR").Tag } } `
|
||||
#@{n = 'PortGroups'; e = { $_ | Get-VirtualPortGroup } }
|
||||
|
||||
$data | export-csv "C:\users\zmeier\desktop\VMs_20200122.csv"
|
||||
|
||||
get-vm itdvmpsc1*,itdvmvc1*,itdvmpsc2*,itdvmvc2* | new-snapshot -name "VC1-6.7 U3-Stage1 Complete"
|
||||
Reference in New Issue
Block a user