update
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
trigger:
|
||||
- main
|
||||
|
||||
name: 'ITD.Infra-VMware.Administration'
|
||||
|
||||
variables:
|
||||
major: 2
|
||||
minor: 0
|
||||
patch: $(Build.BuildID)
|
||||
buildVer: $(major).$(minor).$(Build.BuildID)
|
||||
|
||||
pool: itdwinautop1
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
jobs:
|
||||
- job: Build
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
inputs:
|
||||
filePath: '$(System.DefaultWorkingDirectory)/Build/build.ps1'
|
||||
- task: NuGetCommand@2
|
||||
inputs:
|
||||
command: 'pack'
|
||||
packagesToPack: '$(System.DefaultWorkingDirectory)/ITD.Infra-VMware.Administration.nuspec'
|
||||
versioningScheme: byEnvVar
|
||||
versionEnvVar: buildVer
|
||||
buildProperties: 'VERSIONHERE=$(buildVer)'
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'NuGetPackage'
|
||||
publishLocation: 'Container'
|
||||
- stage: Deploy
|
||||
jobs:
|
||||
- job: Deploy
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: 'NuGetPackage'
|
||||
itemPattern: '**'
|
||||
targetPath: '$(Pipeline.Workspace)'
|
||||
- task: NuGetCommand@2
|
||||
inputs:
|
||||
command: 'push'
|
||||
packagesToPush: '$(Pipeline.Workspace)/ITD.Infra-VMware.Administration.$(major).$(minor).$(Build.BuildID).nupkg'
|
||||
nuGetFeedType: external
|
||||
publishFeedCredentials: 'ITD_PwshGallery'
|
||||
@@ -0,0 +1,17 @@
|
||||
$buildVersion = $env:BUILDVER
|
||||
$moduleName = 'ITD.Infra-VMware.Administration'
|
||||
|
||||
$manifestPath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psd1"
|
||||
$modulePath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psm1"
|
||||
|
||||
## Update build version in manifest
|
||||
$manifestContent = Get-Content -Path $manifestPath -Raw
|
||||
$manifestContent = $manifestContent -replace '<ModuleVersion>', $buildVersion
|
||||
|
||||
## Update functions to export in manifest
|
||||
Import-Module $modulePath
|
||||
$funcStrings = (Get-Module ITD.Infra-VMware.Administration).ExportedCommands.Values.Name
|
||||
$funcStrings = "'$($funcStrings -join "','")'"
|
||||
$manifestContent = $manifestContent -replace "<FunctionsToExport>", $funcStrings
|
||||
|
||||
$manifestContent | Set-Content -Path $manifestPath
|
||||
+688
@@ -0,0 +1,688 @@
|
||||
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Changes Portgroup on all NICs on specified VMs
|
||||
.EXAMPLE
|
||||
Set-ITDVMwareVMNicPortGroup -Computer itdsrv1.nd.gov -Vlan 1394 -Credential $AdminCred
|
||||
#>
|
||||
function Set-ITDVMwareVMNicPortGroup {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string[]]
|
||||
$ComputerName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]
|
||||
$Vlan,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
Begin {
|
||||
Connect-ITDvCenter -Credential $Credential
|
||||
|
||||
Write-Verbose "Connected to: $global:DefaultVIServers"
|
||||
If ($global:DefaultVIServers.Count -gt 0) {
|
||||
Write-Verbose "connected to VI server(s)"
|
||||
}
|
||||
Else {
|
||||
Write-Warning "not connected to any VIservers, stopping script"
|
||||
break
|
||||
break
|
||||
}
|
||||
|
||||
$AvailablePortGroup = Get-VirtualPortGroup -WarningAction SilentlyContinue
|
||||
}
|
||||
Process {
|
||||
ForEach ($c in $ComputerName) {
|
||||
Write-Verbose "[$c]:Start"
|
||||
$CurrentVM = $null
|
||||
$CurrentVMs = $null
|
||||
$Datacenter1 = $null
|
||||
$Datacenter2 = $null
|
||||
$DestinationFolder = $null
|
||||
$CurrentDatacenter = $null
|
||||
|
||||
$CurrentVMs = Get-VM -Name $c -ErrorAction SilentlyContinue
|
||||
|
||||
If ($CurrentVMs.Count -lt 1) {
|
||||
Write-Warning "[$c]:VM name not found, please check it and try again ******"
|
||||
}
|
||||
Else {
|
||||
If ($CurrentVMs.Count -gt 2) {
|
||||
Write-Warning "[$c]:More than two results found, process this VM manually"
|
||||
}
|
||||
Else {
|
||||
If ($CurrentVMs.Count -eq 2) {
|
||||
Write-Verbose "[$c]:Two results found"
|
||||
$Datacenter1 = ($CurrentVMs[0] | Get-Datacenter).Name
|
||||
$Datacenter2 = ($CurrentVMs[1] | Get-Datacenter).Name
|
||||
|
||||
Write-Verbose "[$c]:Check for SRM"
|
||||
If ( ( ($Datacenter1 -eq "Primary Datacenter") -or ($Datacenter2 -eq "Primary Datacenter") ) -and ( ($Datacenter1 -eq "Secondary Datacenter") -or ($Datacenter2 -eq "Secondary Datacenter") ) ) {
|
||||
Write-Warning "[$c]:One result in both Primary and Secondary Datacenters, assuming SRM and continuing"
|
||||
If ($Datacenter1 -eq "Primary Datacenter") {
|
||||
$CurrentVM = $CurrentVMs[0]
|
||||
}
|
||||
If ($Datacenter2 -eq "Primary Datacenter") {
|
||||
$CurrentVM = $CurrentVMs[1]
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Warning "[$c]:Exactly two results in the same datacenter... Congratulations, you've acheieved the impossible."
|
||||
break
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Verbose "[$c]:One match found"
|
||||
$CurrentVM = $CurrentVMs
|
||||
}
|
||||
|
||||
If ($CurrentVM) {
|
||||
$CurrentDatacenter = ($CurrentVM | Get-Datacenter).Name
|
||||
Switch ($CurrentDatacenter) {
|
||||
"Primary Datacenter" {
|
||||
$VirtualSwitch = "PDC"
|
||||
}
|
||||
"Secondary Datacenter" {
|
||||
$VirtualSwitch = "SDC"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$VLANsearch = '_' + $VLAN
|
||||
$VMVLAN = $AvailablePortGroup | `
|
||||
Where-Object { $_.Name -Like "*$VLANsearch" -and $_.VirtualSwitch -like "*$VirtualSwitch*" }
|
||||
$CurrentVM | Get-NetworkAdapter | `
|
||||
Set-NetworkAdapter -NetworkName $VMVLAN -Confirm:$false -RunAsync
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Verbose "[$c]:End Remove"
|
||||
}
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Creates new distributed virtual port group with name standard
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
.EXAMPLE
|
||||
New-ITDVMwarePortGroup -CIDR 10.2.60.0/23 -VLAN 1394
|
||||
.EXAMPLE
|
||||
New-ITDVMwarePortGroup -CIDR 10.2.60.0/23 -VLAN 1394 -Credential $Credential
|
||||
#>
|
||||
function New-ITDVMwarePortGroup {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string]
|
||||
$CIDR,
|
||||
|
||||
[int]
|
||||
$VLAN,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
Begin {
|
||||
Connect-ITDvCenter -Credential $Credential
|
||||
$BismarckVDSwitch = 'dvSwitch-PDC-Data'
|
||||
$MandanVDSwitch = 'dvSwitch-SDC-Data'
|
||||
$IP = $CIDR.split('/')[0]
|
||||
$Mask = $CIDR.split('/')[1]
|
||||
$VLANstring = $VLAN.ToString('0000')
|
||||
}
|
||||
Process {
|
||||
#$PGName="dvPG-$CIDR" + "_" + "$VLAN"
|
||||
$PGName = "dvPG_" + $VLANstring + "_" + $IP + "_" + $Mask
|
||||
Get-VDSwitch -Name $BismarckVDSwitch | New-VDPortgroup -Name $PGName -NumPorts 1 -VlanId $VLAN
|
||||
Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing
|
||||
Get-VDSwitch -Name $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false
|
||||
|
||||
Get-VDSwitch -Name $MandanVDSwitch | New-VDPortgroup -Name $PGName -NumPorts 1 -VlanId $VLAN
|
||||
Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -FailoverDetectionPolicy BeaconProbing
|
||||
Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*" + "_" + $VLAN) } | Get-VDPortgroupOverridePolicy | Set-VDPortgroupOverridePolicy -BlockOverrideAllowed $false -ResetPortConfigAtDisconnect $false
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Find-ITDVMDatastoreClusterMaxAverageDatastoreFreeSpace ($Cluster) {
|
||||
$MaxDsCFreeSpaceAvgPerDiskGB = $null
|
||||
$MaxDsCName = $null
|
||||
|
||||
$AvailableDsC = Get-DatastoreCluster | Where-Object Name -Like *$Cluster*
|
||||
$AvailableDsCCount = ($AvailableDsC | Measure-Object).Count
|
||||
Write-Verbose "Found $AvailableDsCCount datastore clusters matching $Cluster"
|
||||
|
||||
ForEach ($d in $AvailableDsC) {
|
||||
$DsCFreeSpaceInfo = Get-DatastoreCluster -Name $d.Name | Get-Datastore | Select-Object FreeSpaceGB | Measure-Object -Property FreeSpaceGB -Average -Sum
|
||||
$CurrentDsCFreeSpaceAvgPerDiskGB = $DsCFreeSpaceInfo.Average
|
||||
|
||||
# If first in datastore clusters to check
|
||||
If ($MaxDsCFreeSpaceAvgPerDiskGB -eq $null) {
|
||||
Write-Verbose "First datastore cluster, default max datastore cluster"
|
||||
$MaxDsCFreeSpaceAvgPerDiskGB = $CurrentDsCFreeSpaceAvgPerDiskGB
|
||||
$MaxDsCName = $d.Name
|
||||
}
|
||||
|
||||
# Is current Ds cluster avg free space per datastore is larger than max
|
||||
If ($CurrentDsCFreeSpaceAvgPerDiskGB -gt $MaxDsCFreeSpaceAvgPerDiskGB) {
|
||||
Write-Verbose "Current larger than Max"
|
||||
$MaxDsCFreeSpaceAvgPerDiskGB = $CurrentDsCFreeSpaceAvgPerDiskGB
|
||||
$MaxDsCName = $d.Name
|
||||
}
|
||||
|
||||
Write-Verbose "CurrentDsCName: $d"
|
||||
Write-Verbose "CurrentDsCFreeSpaceAvgPerDiskGB = $CurrentDsCFreeSpaceAvgPerDiskGB"
|
||||
Write-Verbose "MaxDsCFreeSpaceAvgPerDiskGB = $MaxDsCFreeSpaceAvgPerDiskGB"
|
||||
}
|
||||
|
||||
Write-Verbose "Return MaxDsCFreeSpaceName: $MaxDsCName"
|
||||
return $MaxDsCName
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Short description
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
.EXAMPLE
|
||||
Example of how to use this cmdlet
|
||||
.EXAMPLE
|
||||
Another example of how to use this cmdlet
|
||||
.INPUTS
|
||||
Inputs to this cmdlet (if any)
|
||||
.OUTPUTS
|
||||
Output from this cmdlet (if any)
|
||||
.NOTES
|
||||
General notes
|
||||
.COMPONENT
|
||||
The component this cmdlet belongs to
|
||||
.ROLE
|
||||
The role this cmdlet belongs to
|
||||
.FUNCTIONALITY
|
||||
The functionality that best describes this cmdlet
|
||||
#>
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMWare-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
#$List = (Invoke-WebRequest -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestListTst {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMWare-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
#$List = (Invoke-WebRequest -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Runs Unmap cmds from VMhost to cleanup dirty data blocks on A9K storage
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
.EXAMPLE
|
||||
Example of how to use this cmdlet
|
||||
.EXAMPLE
|
||||
Another example of how to use this cmdlet
|
||||
.INPUTS
|
||||
Inputs to this cmdlet (if any)
|
||||
.OUTPUTS
|
||||
Output from this cmdlet (if any)
|
||||
.NOTES
|
||||
General notes
|
||||
.COMPONENT
|
||||
The component this cmdlet belongs to
|
||||
.ROLE
|
||||
The role this cmdlet belongs to
|
||||
.FUNCTIONALITY
|
||||
The functionality that best describes this cmdlet
|
||||
#>
|
||||
function Start-ITDVMwareDatastoreUnmap {
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[string[]]
|
||||
$Datastore,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$ConnectITDvCenterParams = @{ }
|
||||
If ($Credential) { $ConnectITDvCenterParams += @{Credential = $Credential } }
|
||||
Connect-ITDvCenter @ConnectITDvCenterParams
|
||||
}
|
||||
|
||||
process {
|
||||
$Clusters = Get-Datacenter Secondary*, Primary* | Get-Cluster
|
||||
ForEach ($Cluster in $Clusters) {
|
||||
$esxcli = $null
|
||||
$Datastores = $null
|
||||
$VMHost = $null
|
||||
|
||||
$Datastores = $Cluster | Get-Datastore | Where-Object { $_.Name -notlike "*TEMPL*" -and $_.Name -like "*$Datastore*" -and $_.Name -like "*A9K*" } | Sort-Object Name
|
||||
$VMHost = $Cluster | Get-VMHost | Where-Object ConnectionState -EQ "Connected" | Select-Object -First 1
|
||||
$esxcli = Get-EsxCli -VMHost $VMHost
|
||||
|
||||
ForEach ($ds in $Datastores) {
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$ds]:Start $TimeStamp on $VMHost"
|
||||
|
||||
$esxcli.storage.vmfs.unmap($null, $ds, $null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Short description
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
.EXAMPLE
|
||||
Example of how to use this cmdlet
|
||||
.EXAMPLE
|
||||
Another example of how to use this cmdlet
|
||||
.INPUTS
|
||||
Inputs to this cmdlet (if any)
|
||||
.OUTPUTS
|
||||
Output from this cmdlet (if any)
|
||||
.NOTES
|
||||
General notes
|
||||
.COMPONENT
|
||||
The component this cmdlet belongs to
|
||||
.ROLE
|
||||
The role this cmdlet belongs to
|
||||
.FUNCTIONALITY
|
||||
The functionality that best describes this cmdlet
|
||||
#>
|
||||
function Remove-ITDVMwareDatastoreStep1 {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[int[]]
|
||||
$LunId,
|
||||
|
||||
[PSCredential]
|
||||
$vCenterCredential,
|
||||
|
||||
[PSCredential]
|
||||
$SharePointCredential
|
||||
)
|
||||
|
||||
begin {
|
||||
$ConnectITDvCenterParams = @{ }
|
||||
If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } }
|
||||
Connect-ITDvCenter @ConnectITDvCenterParams
|
||||
$VMwareList = Get-Datastore
|
||||
|
||||
$GetITDVMwareSharePointDatastoreRecordParams = @{ }
|
||||
If ($SharePointCredential) { $GetITDVMwareSharePointDatastoreRecordParams = @{Credential = $SharePointCredential } }
|
||||
#$SharePointList = Get-ITDVMwareSharePointDatastoreRecord | select *,@{n='Name';e={$_.Title}}
|
||||
$SharePointList = Get-ITDVMwareSharePointDatastoreRecord @GetITDVMwareSharePointDatastoreRecordParams | Select-Object *, @{n = 'Name'; e = { $_.Title } }
|
||||
}
|
||||
|
||||
process {
|
||||
$DatastoreRemovalSuccess = @()
|
||||
$DatastoreRemovalFailure = @()
|
||||
|
||||
ForEach ($Id in $LunId) {
|
||||
$DatastoreID = $null
|
||||
$Datastore = $null
|
||||
|
||||
$Datastores = Get-Datastore | Where-Object Name -Like ("*_" + $Id + "_*")
|
||||
ForEach ($Datastore in $Datastores) {
|
||||
$SharePointRecord = $null
|
||||
|
||||
$DatastoreHosts = $Datastore | Get-VMHost
|
||||
$VMHostCanonicalName = (Get-ScsiLun -VmHost ($DatastoreHosts | Select-Object -First 1) | Where-Object RuntimeName -Like "*L$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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Short description
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
.EXAMPLE
|
||||
Example of how to use this cmdlet
|
||||
.EXAMPLE
|
||||
Another example of how to use this cmdlet
|
||||
.INPUTS
|
||||
Inputs to this cmdlet (if any)
|
||||
.OUTPUTS
|
||||
Output from this cmdlet (if any)
|
||||
.NOTES
|
||||
General notes
|
||||
.COMPONENT
|
||||
The component this cmdlet belongs to
|
||||
.ROLE
|
||||
The role this cmdlet belongs to
|
||||
.FUNCTIONALITY
|
||||
The functionality that best describes this cmdlet
|
||||
#>
|
||||
function Remove-ITDVMwareDatastoreStep3 {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[int[]]
|
||||
$LunId,
|
||||
|
||||
[PSCredential]
|
||||
$vCenterCredential,
|
||||
|
||||
[PSCredential]
|
||||
$SharePointCredential
|
||||
)
|
||||
|
||||
begin {
|
||||
$ConnectITDvCenterParams = @{ }
|
||||
If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } }
|
||||
Connect-ITDvCenter @ConnectITDvCenterParams
|
||||
$VMwareList = Get-Datastore
|
||||
|
||||
$GetITDVMwareSharePointDatastoreRecordParams = @{ }
|
||||
If ($SharePointCredential) { $GetITDVMwareSharePointDatastoreRecordParams = @{Credential = $SharePointCredential } }
|
||||
#$SharePointList = Get-ITDVMwareSharePointDatastoreRecord | select *,@{n='Name';e={$_.Title}}
|
||||
$SharePointList = Get-ITDVMwareSharePointDatastoreRecord @GetITDVMwareSharePointDatastoreRecordParams | Select-Object *, @{n = 'Name'; e = { $_.Title } }
|
||||
}
|
||||
|
||||
process {
|
||||
$DeviceUidToRemove = @()
|
||||
ForEach ($Id in $LunId) {
|
||||
$DeviceUidToRemove += $SharePointList | Where-Object Name -Like "*$Id*" | Select-Object *, @{n = 'HostCluster'; e = { $_.Name.split('_')[0] -replace "VM" } }
|
||||
}
|
||||
$DeviceUidToRemove = $DeviceUidToRemove | Sort-Object HostCluster
|
||||
|
||||
If (@($DeviceUidToRemove).count -ne @($LunId).count) { Write-Error "LunId and datastore search count mismatch, verify SharePoint manually before continuing" }
|
||||
else {
|
||||
|
||||
#confirmation prompt
|
||||
Write-Warning "The following SAN volumes will be detached from the VMware hosts. Please confirm this list is correct:"
|
||||
$DeviceUidToRemove | ForEach-Object { Write-Warning ($_.Name + " *** " + $_.ExtentName) }
|
||||
Pause
|
||||
$HostClusters = $DeviceUidToRemove | Group-Object HostCluster
|
||||
ForEach ($HostCluster in $HostClusters) {
|
||||
$VMHosts = Get-Cluster $HostCluster.Name | Get-VMHost
|
||||
|
||||
ForEach ($DeviceUid in @($DeviceUidToRemove | Where-Object HostCluster -EQ $HostCluster)) {
|
||||
$removeUID = Get-ScsiLun -VmHost $VMHosts | Where-Object CanonicalName -EQ $DeviceUid | Select-Object -First 1
|
||||
If ($removeUID) {
|
||||
foreach ($VMHost in $VMHosts) {
|
||||
$esxcli = Get-EsxCli -VMHost $VMHost -V2
|
||||
#$esxcli.storage.core.device.detached.remove.invoke(@{device = $removeUID})
|
||||
}
|
||||
}
|
||||
}
|
||||
Get-VMHostStorage -VMHost $VMhosts -RescanAllHba -RescanVmfs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-ITDVMwareAlarmState {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true,
|
||||
ParameterSetName = 'Entity'
|
||||
)]
|
||||
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]
|
||||
$Entity,
|
||||
|
||||
[switch]
|
||||
$Recurse = $false
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$Entity = Get-Inventory -Id $Entity.Id
|
||||
if ($Recurse) {
|
||||
$VMObjects = @($Entity)
|
||||
$VMObjects += Get-Inventory -Location $Entity
|
||||
}
|
||||
else {
|
||||
$VMObjects = $Entity
|
||||
}
|
||||
$VMObjects | Select-Object Name, `
|
||||
@{N = "Type"; E = { $_.GetType().Name.Replace("Impl", "").Replace("Wrapper", "") } }, `
|
||||
@{N = "Alarm actions enabled"; E = { $_.ExtensionData.alarmActionsEnabled } }
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Set-ITDVMwareAlarmState {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
|
||||
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]
|
||||
$Entity,
|
||||
|
||||
[switch]
|
||||
$Enabled,
|
||||
|
||||
[switch]
|
||||
$Recurse
|
||||
)
|
||||
|
||||
begin {
|
||||
$alarmMgr = Get-View AlarmManager
|
||||
}
|
||||
|
||||
process {
|
||||
if ($Recurse) {
|
||||
$VMObjects = @($Entity)
|
||||
$VMObjects += Get-Inventory -Location $Entity
|
||||
}
|
||||
else {
|
||||
$VMObjects = $Entity
|
||||
}
|
||||
|
||||
$VMObjects | ForEach-Object {
|
||||
$alarmMgr.EnableAlarmActions($_.Extensiondata.MoRef, $Enabled)
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Expand-ITDVMwareDatastore {
|
||||
param (
|
||||
[string[]]
|
||||
$LunId
|
||||
)
|
||||
|
||||
$HostsToRescan = @()
|
||||
ForEach ($Id in $LunId) {
|
||||
$Datastore = Get-Datastore "*$Id*"
|
||||
$HostSystem = Get-View -Id ($Datastore.ExtensionData.Host | Select-Object -First 1 | Select-Object -ExpandProperty Key)
|
||||
$DatastoreSystem = Get-View -Id $HostSystem.ConfigManager.DatastoreSystem
|
||||
$ExpandOptions = $DatastoreSystem.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef)
|
||||
$DatastoreSystem.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef, $ExpandOptions.spec)
|
||||
$HostsToRescan += $Datastore | Get-VMHost | Sort-Object Name
|
||||
}
|
||||
}
|
||||
|
||||
function New-ITDVMwareHostScratchFolder {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[ValidateSet("Bismarck", "Mandan")]
|
||||
[string]
|
||||
$Site,
|
||||
|
||||
[string]
|
||||
$VMHost
|
||||
)
|
||||
Begin {
|
||||
}
|
||||
|
||||
Process {
|
||||
switch ($Site) {
|
||||
"Bismarck" {
|
||||
$vCenter = "itdvmvc1.nd.gov@443"
|
||||
$Datacenter = "Primary Datacenter"
|
||||
$Datastore = "VMALL1_006_FS92_SCRATCH"
|
||||
}
|
||||
"Mandan" {
|
||||
$vCenter = "itdvmvc2.nd.gov@443"
|
||||
$Datacenter = "Secondary Datacenter"
|
||||
$Datastore = "VMALL2_007_FS92_SCRATCH"
|
||||
}
|
||||
}
|
||||
New-Item -Path "vmstores:\$vCenter\$Datacenter\$Datastore\scratch" -Name $VMHost -ItemType Directory
|
||||
}
|
||||
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Set-ITDVMwareHostMaintenance {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string[]]
|
||||
$Name,
|
||||
|
||||
[ValidateSet("Enter", "Exit")]
|
||||
[string]
|
||||
$Status
|
||||
)
|
||||
Begin {
|
||||
|
||||
}
|
||||
Process {
|
||||
ForEach ($n in $Name) {
|
||||
$VMHost = $null
|
||||
$VMHost = Get-VMHost $n
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
|
||||
switch ($Status) {
|
||||
"Enter" {
|
||||
$VMHost | Set-VMHost -State "Maintenance" -RunAsync
|
||||
$ViServer = $VMHost.Uid.split('@')[1].split(':')[0]
|
||||
$alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
"Exit" {
|
||||
$VMHost | Set-VMHost -State "Connected" -RunAsync
|
||||
$ViServer = $VMHost.Uid.split('@')[1].split(':')[0]
|
||||
$alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Get-VMHost $Name | Select-Object Name, ConnectionState, @{n = 'Alarms'; e = { $_.ExtensionData.AlarmActionsEnabled } }
|
||||
}
|
||||
|
||||
End {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>ITD.Infra-VMware.Administration</id>
|
||||
<version>$VERSIONHERE$</version>
|
||||
<authors>Zack Meier / Don Lange</authors>
|
||||
<description>Functions for VMware administration</description>
|
||||
</metadata>
|
||||
</package>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
@{
|
||||
RootModule = 'ITD.Infra-VMware.Administration.psm1'
|
||||
ModuleVersion = '<ModuleVersion>'
|
||||
GUID = 'b940f358-3867-4785-81d2-4bab53872613'
|
||||
Author = 'Zack Meier / Don Lange '
|
||||
CompanyName = 'State of North Dakota'
|
||||
PowerShellVersion = '5.1'
|
||||
CompatiblePSEditions = 'Desktop','Core'
|
||||
FunctionsToExport = @(<FunctionsToExport>)
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#Get public and private function definition files.
|
||||
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue )
|
||||
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue )
|
||||
|
||||
#Dot source the files
|
||||
Foreach($import in @($Public + $Private))
|
||||
{
|
||||
Try
|
||||
{
|
||||
. $import.fullname
|
||||
}
|
||||
Catch
|
||||
{
|
||||
Write-Error -Message "Failed to import function $($import.fullname): $_"
|
||||
}
|
||||
}
|
||||
|
||||
# Here I might...
|
||||
# Read in or create an initial config file and variable
|
||||
# Export Public functions ($Public.BaseName) for WIP modules
|
||||
# Set variables visible to the module and its functions only
|
||||
|
||||
Export-ModuleMember -Function $Public.Basename
|
||||
@@ -0,0 +1,36 @@
|
||||
<#
|
||||
.Synopsis
|
||||
Connects to ITD's vCenter servers
|
||||
.DESCRIPTION
|
||||
Connects to ITD's vCenter servers
|
||||
.EXAMPLE
|
||||
Connect-ITDvCenter -Credential $PSCredential
|
||||
#>
|
||||
function Connect-ITDvCenter {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
Begin {
|
||||
Import-Module VMware.VimAutomation.Core
|
||||
$VIServers = "itdvmvc1.nd.gov", "itdvmvc2.nd.gov"
|
||||
}
|
||||
Process {
|
||||
If ($Global:DefaultVIServers) {
|
||||
Write-Verbose "VIServers already connected"
|
||||
}
|
||||
Else {
|
||||
If ($Credential) {
|
||||
Connect-VIServer -Server $VIServers -Credential $Credential | Out-Null
|
||||
}
|
||||
Else {
|
||||
Connect-VIServer -Server $VIServers | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
function Disable-ITDVMwareVMHostFeature {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string[]]
|
||||
$Name,
|
||||
|
||||
[switch]
|
||||
$LockdownMode,
|
||||
|
||||
[switch]
|
||||
$SSH,
|
||||
|
||||
[switch]
|
||||
$AlarmActions
|
||||
)
|
||||
Begin {
|
||||
|
||||
}
|
||||
Process {
|
||||
$VMHosts = Get-VMHost -Name $Name
|
||||
ForEach ($VMHost in $VMHosts) {
|
||||
If ($LockdownMode) {
|
||||
($VMHost | Get-View).ExitLockdownMode()
|
||||
}
|
||||
If ($SSH) {
|
||||
Get-VMHostService -VMHost $VMHost | Where-Object { $_.key -eq 'TSM-SSH' } | Stop-VMHostService -Confirm:$false | Select-Object VMHost, Key, Label, Running
|
||||
}
|
||||
If ($AlarmActions) {
|
||||
$VIServer = $VMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $VMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $true) {
|
||||
$alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<#
|
||||
.Synopsis
|
||||
Disconnects from ITD's vCenter servers
|
||||
.DESCRIPTION
|
||||
Disconnects from ITD's vCenter servers
|
||||
.EXAMPLE
|
||||
Disconnect-ITDvCenter
|
||||
#>
|
||||
function Disconnect-ITDvCenter {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
)
|
||||
|
||||
Begin {
|
||||
$VIServers = "itdvmvc1.nd.gov", "itdvmvc2.nd.gov"
|
||||
}
|
||||
Process {
|
||||
Disconnect-VIServer -Server $VIServers -Confirm:$false
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
function Enable-ITDVMwareVMHostFeature {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string[]]
|
||||
$Name,
|
||||
|
||||
[switch]
|
||||
$LockdownMode,
|
||||
|
||||
[switch]
|
||||
$AlarmActions,
|
||||
|
||||
[switch]
|
||||
$SSH
|
||||
)
|
||||
Begin {
|
||||
|
||||
}
|
||||
Process {
|
||||
$VMHosts = Get-VMHost -Name $Name
|
||||
ForEach ($VMHost in $VMHosts) {
|
||||
If ($LockdownMode) {
|
||||
($VMHost | Get-View).EnterLockdownMode()
|
||||
}
|
||||
If ($SSH) {
|
||||
Get-VMHostService -VMHost $VMHost | Where-Object { $_.key -eq 'TSM-SSH' } | Start-VMHostService -Confirm:$false | Select-Object VMHost, Key, Label, Running
|
||||
}
|
||||
If ($AlarmActions) {
|
||||
$VIServer = $VMHost.Uid.Split('@')[1].Split(':')[0]
|
||||
$alarmMgr = Get-View AlarmManager -Server $VIServer
|
||||
$alarmEnabled = $VMHost.ExtensionData.AlarmActionsEnabled
|
||||
if ($alarmEnabled -eq $false) {
|
||||
$alarmMgr.EnableAlarmActions($VMHost.ExtensionData.MoRef, $true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
$PowerBi = Import-Csv -Path D:\Downloads\serverinventory20251002.csv
|
||||
$SRM = Import-Csv -Path D:\Downloads\itdvmvc1.nd.gov-itdvmvc2.nd.gov-20251002-102657.csv
|
||||
$VMs = Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -eq "placeholderVm" }
|
||||
|
||||
$Result = [System.Collections.ArrayList]@()
|
||||
foreach ($pbi in $PowerBi) {
|
||||
Write-Verbose -Message ($pbi.'Host Name') -Verbose
|
||||
$obj = $null
|
||||
|
||||
$obj = [PSCustomObject]@{
|
||||
PowerBi = $pbi.'Host Name'
|
||||
Placeholder = $VMs | Where-Object Name -EQ $pbi.'Host Name' | Select-Object -ExpandProperty Name -First 1;
|
||||
SRM = $SRM | Where-Object "Virtual Machine" -EQ $pbi.'Host Name' | Select-Object -ExpandProperty "Virtual Machine"
|
||||
CMDB = ((Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("name=" + $pbi.'Host Name'.split('.')[0])).name.display_value)
|
||||
}
|
||||
$null = $Result.Add($obj)
|
||||
}
|
||||
|
||||
foreach ($VM in $VMs) {
|
||||
if ($Result | Where-Object Placeholder -EQ $VM.Name) {
|
||||
#do nothing
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message ($VM.Name) -Verbose
|
||||
$obj = [PSCustomObject]@{
|
||||
PowerBi = $PowerBi | Where-Object 'Host Name' -EQ $pbi.'Host Name'
|
||||
Placeholder = $VM.Name;
|
||||
SRM = $SRM | Where-Object "Virtual Machine" -EQ $pbi.'Host Name'
|
||||
CMDB = ((Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter ("name=" + $pbi.'Host Name'.split('.')[0])).name.display_value);
|
||||
}
|
||||
$null = $Result.Add($obj)
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Usage report for VMware datastores.
|
||||
.DESCRIPTION
|
||||
Usage report for VMware datastores.
|
||||
.NOTES
|
||||
Requires VMware PowerCLI module.
|
||||
Requires connection to vCenter.
|
||||
.EXAMPLE
|
||||
Get-ITDVMwareDatastoreReport
|
||||
Retrieves a report of all datastores in the vCenter.
|
||||
.EXAMPLE
|
||||
Get-ITDVMwareDatastoreReport -Name "*78*"
|
||||
Retrieves a report of all datastores in the vCenter that match the name pattern "*78*".
|
||||
.PARAMETER Name
|
||||
The name of the datastore to retrieve. If not specified, all datastores will be returned.
|
||||
Supports wildcards.
|
||||
#>
|
||||
|
||||
function Get-ITDVMwareDatastoreReport {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
if ($PSBoundParameters.ContainsKey('Name')) {
|
||||
$AllDatastores = Get-Datastore -Name $Name
|
||||
}
|
||||
else {
|
||||
$AllDatastores = Get-Datastore
|
||||
}
|
||||
|
||||
foreach ($Datastore in $AllDatastores) {
|
||||
$FreeSpaceGB = $Datastore.FreeSpaceGB
|
||||
$CapacityGB = $Datastore.CapacityGB
|
||||
$UsedSpaceGB = $CapacityGB - $FreeSpaceGB
|
||||
$obj = [PSCustomObject]@{
|
||||
Name = $Datastore.Name;
|
||||
Datacenter = $Datastore.Datacenter.Name
|
||||
FreeSpaceGB = $FreeSpaceGB;
|
||||
UsedSpaceGB = ($CapacityGB - $FreeSpaceGB);
|
||||
CapacityGB = $CapacityGB;
|
||||
FreePercent = [math]::round($Datastore.FreeSpaceGB / $Datastore.CapacityGB * 100, 2);
|
||||
}
|
||||
#$null = $Result.Add($obj)
|
||||
Write-Output $obj
|
||||
}
|
||||
}
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
# servicenow cmdb ci dr protection
|
||||
# vcenter placeholder
|
||||
|
||||
$AllVMwareVMs = Get-Datacenter | Where-Object {$_.Name -like "*Primary*" -or $_.Name -like "*Secondary*" -or $_.Name -like "*DCN*"} | Get-VM | Where-Object { $_.Name -notlike "vCLS*" } | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -ne "placeholderVm" } | Sort-Object Name
|
||||
$AllVMwarePlaceholders = $AllVMwareVMs | Where-Object { $_.ExtensionData.Summary.Config.ManagedBy.Type -eq "placeholderVm" }
|
||||
$AllCmdbCi = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "operational_status!=6^u_nd_dr_protectionLIKEVMware" -IncludeTotalCount | Select-Object @{n = 'CiName'; e = { $_.name.display_value } }, @{n = 'CiFqdn'; e = { $_.fqdn.display_value } }, @{n = 'CiOpStatus'; e = { $_.operational_status.display_value } }, @{n = 'DRProtection'; e = { $_.u_nd_dr_protection.display_value } } | Sort-Object CiName
|
||||
|
||||
$ArrayList = [System.Collections.ArrayList]@()
|
||||
|
||||
# check for placeholder
|
||||
ForEach ($Ci in $AllCmdbCi) {
|
||||
$PlaceholderBool = $null
|
||||
$VMBool = $null
|
||||
|
||||
If($AllVMwareVMs | Where-Object { $_.Name -eq $Ci.CiFqdn }) {
|
||||
$VMBool = $true
|
||||
}
|
||||
else {
|
||||
$VMBool = $false
|
||||
}
|
||||
|
||||
If ($AllVMwarePlaceholders | Where-Object { $_.Name -eq $Ci.CiFqdn }) {
|
||||
$PlaceholderBool = $true
|
||||
}
|
||||
else {
|
||||
$PlaceholderBool = $false
|
||||
}
|
||||
|
||||
$obj = [PSCustomObject]@{
|
||||
CiName = $Ci.CiName
|
||||
CiFqdn = $Ci.CiFqdn
|
||||
CiOpStatus = $Ci.CiOpStatus
|
||||
DRProtection = $Ci.DRProtection
|
||||
VMExists = $VMBool
|
||||
Placeholder = $PlaceholderBool
|
||||
}
|
||||
|
||||
$null = $ArrayList.Add($obj)
|
||||
}
|
||||
|
||||
# verify no extra entries in vm list / confirm all vms have cmdb entries
|
||||
ForEach ($VM in $AllVMwareVMs) {
|
||||
If (-not ($ArrayList | Where-Object { $_.CiFqdn -eq $VM.Name })) {
|
||||
#Write-Host "VM $($VM.Name) does not have a corresponding CMDB entry." -ForegroundColor Red
|
||||
$obj = [PSCustomObject]@{
|
||||
CiName = $null
|
||||
CiFqdn = $null
|
||||
CiOpStatus = $null
|
||||
DRProtection = $null
|
||||
VMExists = $VM.Name
|
||||
PlaceholderExists = $null
|
||||
}
|
||||
$null = $ArrayList.Add($obj)
|
||||
}
|
||||
}
|
||||
|
||||
# verify no extra entries in placeholder list / confirm all placeholders have cmdb entries
|
||||
ForEach ($Placeholder in $AllVMwarePlaceholders) {
|
||||
If (-not ($ArrayList | Where-Object { $_.CiFqdn -eq $Placeholder.Name })) {
|
||||
#Write-Host "Placeholder VM $($Placeholder.Name) does not have a corresponding CMDB entry." -ForegroundColor Red
|
||||
$obj = [PSCustomObject]@{
|
||||
CiName = $null
|
||||
CiFqdn = $Placeholder.Name
|
||||
CiOpStatus = $null
|
||||
DRProtection = $null
|
||||
VMExists = $null
|
||||
PlaceholderExists = $true
|
||||
}
|
||||
$null = $ArrayList.Add($obj)
|
||||
}
|
||||
}
|
||||
|
||||
$ArrayList | Sort-Object CiFqdn | Format-Table -AutoSize
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Short description
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
.EXAMPLE
|
||||
Example of how to use this cmdlet
|
||||
.EXAMPLE
|
||||
Another example of how to use this cmdlet
|
||||
.INPUTS
|
||||
Inputs to this cmdlet (if any)
|
||||
.OUTPUTS
|
||||
Output from this cmdlet (if any)
|
||||
.NOTES
|
||||
General notes
|
||||
.COMPONENT
|
||||
The component this cmdlet belongs to
|
||||
.ROLE
|
||||
The role this cmdlet belongs to
|
||||
.FUNCTIONALITY
|
||||
The functionality that best describes this cmdlet
|
||||
#>
|
||||
function Get-ITDVMwareVMHAEventList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$Date = Get-Date
|
||||
$HAVMrestartold = 5
|
||||
Get-VIEvent -MaxSamples 100000 -Start ($Date).AddDays(-$HAVMrestartold) -type warning | Where-Object { $_.FullFormattedMessage -match "restarted" } | Select-Object CreatedTime, ObjectName, FullFormattedMessage | Sort-Object CreatedTime -Descending
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves HBA (Host Bus Adapter) device information, including WWN (World Wide Name) and WWP (World Wide Port Name), for specified VMware ESXi hosts.
|
||||
|
||||
.DESCRIPTION
|
||||
This function connects to one or more VMware ESXi hosts and gathers detailed information about their HBA devices. The information collected includes the device name, WWN, WWP, and other relevant properties. This is useful for inventory, troubleshooting, or auditing storage connectivity in a VMware environment.
|
||||
|
||||
.PARAMETER VMHost
|
||||
Specifies the ESXi host(s) from which to retrieve HBA information. Accepts one or more host names or objects.
|
||||
|
||||
.EXAMPLE
|
||||
Get-ITDVMwareVMHostHBA -VMHost "esxi01.domain.local"
|
||||
Retrieves HBA information from the specified ESXi host.
|
||||
|
||||
.EXAMPLE
|
||||
Get-ITDVMwareVMHostHBA
|
||||
Retrieves HBA information from all connected ESXi hosts.
|
||||
#>
|
||||
|
||||
function Get-ITDVMwareVMHostHBA {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]
|
||||
$VMHostName
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
If ($PSBoundParameters.ContainsKey('VMHostName')) {
|
||||
$AllVMHosts = Get-VMHost -Name $VMHostName
|
||||
}
|
||||
Else {
|
||||
$AllVMHosts = Get-VMHost
|
||||
}
|
||||
|
||||
ForEach ($VMHost in $AllVMHosts) {
|
||||
$HBAs = $null
|
||||
$HBAs = Get-VMHostHba -VMHost $VMHost -Type FibreChannel
|
||||
ForEach ($HBA in $HBAs) {
|
||||
$wwn = "{0:X}" -f $HBA.NodeWorldWideName
|
||||
$wwp = "{0:X}" -f $HBA.PortWorldWideName
|
||||
$obj = [PSCustomObject]@{
|
||||
'VMHostName' = $VMHost.Name;
|
||||
'Device' = $HBA.Device;
|
||||
'Model' = $HBA.Model;
|
||||
'Status' = $HBA.Status;
|
||||
'NodeWorldWideName' = (0..7 | ForEach-Object { $wwn.Substring($_ * 2, 2) }) -join ':'
|
||||
'PortWorldWideName' = (0..7 | ForEach-Object { $wwp.Substring($_ * 2, 2) }) -join ':'
|
||||
}
|
||||
Write-Output $obj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
function Get-ITDVMwareVMHostStatus {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
Begin {
|
||||
}
|
||||
|
||||
Process {
|
||||
If ($Name) {
|
||||
Get-VMHost -Name $Name | Select-Object Name, ConnectionState, `
|
||||
@{n = 'AlarmActionsEnabled'; e = { $_.ExtensionData.AlarmActionsEnabled } }, `
|
||||
@{n = "LockdownMode"; e = { $_.ExtensionData.Config.LockdownMode } }, `
|
||||
@{n = 'TSM-SSH'; e = { ($_ | Get-VMHostService | Where-Object { $_.Key -eq "TSM-SSH" }).Running } }
|
||||
}
|
||||
Else {
|
||||
Get-VMHost | Select-Object Name, ConnectionState, `
|
||||
@{n = 'AlarmActionsEnabled'; e = { $_.ExtensionData.AlarmActionsEnabled } }, `
|
||||
@{n = "LockdownMode"; e = { $_.ExtensionData.Config.LockdownMode } }, `
|
||||
@{n = 'TSM-SSH'; e = { ($_ | Get-VMHostService | Where-Object { $_.Key -eq "TSM-SSH" }).Running } }
|
||||
}
|
||||
}
|
||||
|
||||
End {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
function New-ITDVMNetwork {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$CIDR,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateLength(3, 4)]
|
||||
[string]
|
||||
$VlanId,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateSet("Data-Server", "Data-User")]
|
||||
[string]
|
||||
$DataType,
|
||||
|
||||
#[PSCredential]
|
||||
#$SharePointCredential,
|
||||
|
||||
[PSCredential]
|
||||
$vCenterCredential
|
||||
)
|
||||
|
||||
begin {
|
||||
If ($VlanId -eq "MAC" -or $VlanId -eq "MAG") {
|
||||
$Hypervisor = "Azure"
|
||||
}
|
||||
Else {
|
||||
$Hypervisor = "VMware"
|
||||
}
|
||||
Write-Verbose "Hypervisor $Hypervisor"
|
||||
#VMware
|
||||
If ($Hypervisor -eq "VMware") {
|
||||
$ConnectITDvCenterParams = @{ }
|
||||
If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } }
|
||||
Connect-ITDvCenter @ConnectITDvCenterParams
|
||||
|
||||
switch ($DataType) {
|
||||
'Data-Server' {
|
||||
$BismarckVDSwitch = 'dvSwitch-PDC-Data-Server'
|
||||
$MandanVDSwitch = 'dvSwitch-SDC-Data-Server'
|
||||
}
|
||||
'Data-User' {
|
||||
$BismarckVDSwitch = 'dvSwitch-PDC-Data-User'
|
||||
$MandanVDSwitch = 'dvSwitch-SDC-Data-User'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$PortGroupList = Get-VirtualPortGroup
|
||||
}
|
||||
|
||||
<#SharePoint
|
||||
$InvokeWebRequestParams = $null
|
||||
If ($SharePointCredential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$RequestDigest = Invoke-RestMethod -Uri $UrlContextInfo -Method Post -UseDefaultCredentials
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$List = Invoke-RestMethod -uri $UrlList -UseDefaultCredentials
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItems = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000'
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
}
|
||||
#>
|
||||
}
|
||||
|
||||
process {
|
||||
try {
|
||||
<#
|
||||
If ($SharePointCredential) { $GetITDVMwareSharePointNetworkListParams += @{Credential = $SharePointCredential } }
|
||||
$NetworkList = Get-ITDVMwareSharePointNetworkList @GetITDVMwareSharePointNetworkListParams
|
||||
#>
|
||||
$NetworkId = $CIDR.split('/')[0]
|
||||
$NetworkMask = $CIDR.split('/')[1]
|
||||
|
||||
If ($VlanId -match "^\d+$" -and $VlanId.length -eq 3) {
|
||||
$VlanId = "0" + $VlanId
|
||||
}
|
||||
|
||||
<# Verify CIDR not already in SharePoint
|
||||
If (@($NetworkList | Where-Object CIDR -EQ $CIDR)) {
|
||||
Write-Error "CIDR already exists in SharePoint"
|
||||
}
|
||||
#>
|
||||
|
||||
# If VMware, do more checks then create port group
|
||||
If ($Hypervisor -eq "VMware") {
|
||||
# verify VlanId not already in sharepoint
|
||||
If (@($NetworkList | Where-Object Vlan_Id -EQ $VlanId)) {
|
||||
Write-Error "Vlan Id already exists in SharePoint"
|
||||
Exit
|
||||
}
|
||||
|
||||
# verify Vlan Id not already in vmware portgroup
|
||||
If (@($PortGrouplist | Where-Object { $_.Name.split('_')[2] -eq $NetworkId })) {
|
||||
Write-Error "Network_Id already exists in VMware PortGroup name"
|
||||
Exit
|
||||
}
|
||||
If (@($PortGrouplist | Where-Object { $_.Name.split('_')[1] -eq $VlanId } )) {
|
||||
Write-Error "VlanId already exists in VMware PortGroup name"
|
||||
Exit
|
||||
}
|
||||
|
||||
# Add new port group to VMware
|
||||
$PGName = "dvPG_" + $VlanId + "_" + $NetworkId + "_" + $NetworkMask
|
||||
|
||||
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 $BismarckVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDSecurityPolicy | Set-VDSecurityPolicy -MacChanges $false -AllowPromiscuous $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
|
||||
Get-VDSwitch -Name $MandanVDSwitch | Get-VDPortgroup | Where-Object { $_.Name -like ("*_" + $VlanId + "_*") } | Get-VDSecurityPolicy | Set-VDSecurityPolicy -MacChanges $false -AllowPromiscuous $false
|
||||
}
|
||||
|
||||
# Get PA7050 Zone info
|
||||
If ($Hypervisor -eq "Azure") {
|
||||
$Secure = "True"
|
||||
$PA_Zone = "Azure"
|
||||
$AutoUpdate = $false
|
||||
|
||||
}
|
||||
If ($Hypervisor -eq "VMware") {
|
||||
#$PAInterface = Get-ITDPAInterface -Number ($VlanId.TrimStart('0'))
|
||||
#If (@($PAInterface).count -gt 1) {
|
||||
# Write-Error "More than one PA Interface found"
|
||||
# exit
|
||||
#}
|
||||
#else {
|
||||
# $Secure = [string]$PAInterface.ZeroTrust
|
||||
# $PA_Zone = $PAInterface.Zone
|
||||
# $AutoUpdate = $true
|
||||
#}
|
||||
}
|
||||
|
||||
<# Add to SharePoint
|
||||
[PSCustomObject]$NewRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName }
|
||||
}
|
||||
$NewRecord += @{Title = ("new_" + $env:USERNAME) }
|
||||
$NewRecord += @{CIDR = $CIDR }
|
||||
$NewRecord += @{DataType = $DataType }
|
||||
$NewRecord += @{Vlan_Id = $VlanId }
|
||||
$NewRecord += @{PA_Zone = $PA_Zone }
|
||||
$NewRecord += @{Secure = $Secure }
|
||||
$NewRecord += @{AutoUpdate = $AutoUpdate }
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItems;
|
||||
Method = "Post";
|
||||
Body = $NewRecord | ConvertTo-Json;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $Header;
|
||||
UseBasicParsing = $AutoUpdate;
|
||||
}
|
||||
If ($SharePointCredential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
#>
|
||||
}
|
||||
catch {
|
||||
Write-Error $error[0]
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
|
||||
function Remove-ITDVMwareCdDriveMedia {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string[]]
|
||||
$ComputerName,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
Begin {
|
||||
Connect-ITDvCenter -Credential $Credential
|
||||
Write-Verbose "Connected to: $global:DefaultVIServers"
|
||||
If ($global:DefaultVIServers.Count -gt 0) {
|
||||
Write-Verbose "connected to VI server(s)"
|
||||
}
|
||||
Else {
|
||||
Write-Warning "not connected to any VIservers, stopping script"
|
||||
break
|
||||
break
|
||||
}
|
||||
}
|
||||
Process {
|
||||
ForEach ($c in $ComputerName) {
|
||||
$CurrentVM = $null
|
||||
|
||||
$CurrentVM = Get-VM -Name $c
|
||||
$CurrentVM | Get-CDDrive | Set-CDDrive -NoMedia -Confirm:$false
|
||||
}
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
function Remove-ITDVMwareOSCustomizationSpecOrphan {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[int]
|
||||
$DaysToKeep = 60
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$OSCustomizationSpecToRemove = Get-OSCustomizationSpec | Where-Object { $_.Name -like "AutoBuild-*" -and $_.LastUpdate -lt ((Get-Date).AddDays($DaysToKeep)) }
|
||||
$OSCustomizationSpecToRemove | Remove-OSCustomizationSpec -Confirm:$false
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A short one-line action-based description, e.g. 'Tests if a function is valid'
|
||||
.DESCRIPTION
|
||||
A longer description of the function, its purpose, common use cases, etc.
|
||||
.NOTES
|
||||
Information or caveats about the function e.g. 'This function is not supported in Linux'
|
||||
.LINK
|
||||
Specify a URI to a help page, this will show when Get-Help -Online is used.
|
||||
.EXAMPLE
|
||||
Test-MyTestFunction -Verbose
|
||||
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
|
||||
#>
|
||||
|
||||
function Set-ITDVMwareHostMaintenance {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Enclosure', Mandatory = $true)]
|
||||
[string]
|
||||
$EnclosureName,
|
||||
|
||||
[Parameter(ParameterSetName = 'Manual', Mandatory = $true)]
|
||||
[string[]]
|
||||
$VMHostName,
|
||||
|
||||
[ValidateSet('Maintenance', 'Online', 'Connected')]
|
||||
[string]
|
||||
$State
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
switch ($PSCmdlet.ParameterSetName) {
|
||||
'Enclosure' {
|
||||
Write-Verbose "Setting all VMHosts in enclosure $EnclosureName to $State mode."
|
||||
try {
|
||||
$VMHostName = (Get-OVServer | Where-Object Name -like $EnclosureName -ErrorAction Stop).ServerName
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to retrieve enclosure $EnclosureName. Error: $_"
|
||||
throw
|
||||
}
|
||||
}
|
||||
'Manual' {
|
||||
Write-Verbose "Setting specified VMHosts to $State mode."
|
||||
}
|
||||
}
|
||||
|
||||
switch ($State) {
|
||||
'Maintenance' {
|
||||
Write-Verbose "Setting VMHost $VMHostName to Maintenance mode."
|
||||
try {
|
||||
Get-VMHost -Name $VMHostName | Set-VMHost -State Maintenance -Confirm:$false -RunAsync
|
||||
Disable-ITDVMwareVMHostFeature -Name $VMHostName -AlarmActions
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to set VMHost $VMHostName to Maintenance mode. Error: $_"
|
||||
throw
|
||||
}
|
||||
}
|
||||
'Online' {
|
||||
Write-Verbose "Setting VMHost $VMHostName to Online mode."
|
||||
Get-VMHost -Name $VMHostName | Set-VMHost -State Connected -Confirm:$false -RunAsync
|
||||
Enable-ITDVMwareVMHostFeature -Name $VMHostName -AlarmActions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Introduction
|
||||
TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.
|
||||
|
||||
# Getting Started
|
||||
TODO: Guide users through getting your code up and running on their own system. In this section you can talk about:
|
||||
1. Installation process
|
||||
2. Software dependencies
|
||||
3. Latest releases
|
||||
4. API references
|
||||
|
||||
# Build and Test
|
||||
TODO: Describe and show how to build your code and run the tests.
|
||||
|
||||
# Contribute
|
||||
TODO: Explain how other users and developers can contribute to make your code better.
|
||||
|
||||
If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files:
|
||||
- [ASP.NET Core](https://github.com/aspnet/Home)
|
||||
- [Visual Studio Code](https://github.com/Microsoft/vscode)
|
||||
- [Chakra Core](https://github.com/Microsoft/ChakraCore)
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
function Get-ITDVMwareSharePointNetworkList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000' + '&$select=ID,Title,Vlan_Id,CIDR,PA_Zone,Secure,AutoUpdate'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true
|
||||
}
|
||||
|
||||
$List = (Invoke-RestMethod @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
#$List = (Invoke-RestMethod -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDPAInterface {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[string[]]
|
||||
$Number
|
||||
)
|
||||
|
||||
begin {
|
||||
#[xml]$RawXmlZones = (Invoke-RestMethod -Uri 'https://itdnettools.nd.gov/rktest/7050zones.py').Content
|
||||
$RawXmlZones = (Invoke-RestMethod -Uri 'https://itdnettools.nd.gov/rktest/7050zones.py')
|
||||
$Zones = $RawXmlZones.response.result.zone.entry
|
||||
$UniversalDenyZones = Get-ITDPAUniversalDenyZone
|
||||
}
|
||||
|
||||
process {
|
||||
$result = @()
|
||||
ForEach ($Zone in $Zones) {
|
||||
#$Interfaces = $Zone.network.layer3.member | ForEach-Object{$_ -replace 'ae1.'}
|
||||
$Interfaces = $Zone.network.layer3.member | ForEach-Object { $_ -replace "ethernet\d/\d\d." }
|
||||
If ($Number) {
|
||||
$Interfaces = (Compare-Object -ReferenceObject $Interfaces -DifferenceObject $Number -ExcludeDifferent -IncludeEqual).InputObject
|
||||
}
|
||||
ForEach ($Interface in $Interfaces) {
|
||||
$obj = [PSCustomObject]@{
|
||||
Interface = $Interface;
|
||||
Zone = $Zone.name
|
||||
ZeroTrust = If (@($UniversalDenyZones) -eq $Zone.Name) { $true }Else { $false };
|
||||
}
|
||||
$result += $obj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
Write-Output $result
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDPAUniversalDenyZone {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
|
||||
)
|
||||
|
||||
Begin {
|
||||
$Inbound = (((((Invoke-RestMethod -Uri 'http://itdnettools.nd.gov/rktest/7050denyinbound.py?policy=Universal%20Zone%20Deny%20Inbound') -split '[\r\n]+') | Where-Object { $_ -match "<member>" -and $_ -notmatch "any" -and $_ -notmatch "Deny" }) -replace "<member>") -replace "</member>") -Replace " " | Sort-Object
|
||||
$Outbound = (((((Invoke-RestMethod -Uri 'http://itdnettools.nd.gov/rktest/7050denyinbound.py?policy=Universal%20Zone%20Deny%20Outbound') -split '[\r\n]+') | Where-Object { $_ -match "<member>" -and $_ -notmatch "any" -and $_ -notmatch "Deny" }) -replace "<member>") -replace "</member>") -Replace " " | Sort-Object
|
||||
}
|
||||
Process {
|
||||
$result = Compare-Object -ReferenceObject $Inbound -DifferenceObject $Outbound -IncludeEqual | Sort-Object InputObject
|
||||
}
|
||||
End {
|
||||
Write-Output ($result | Where-Object SideIndicator -EQ '==').InputObject
|
||||
}
|
||||
}
|
||||
|
||||
function Set-ITDVMwareSharePointNetworkRecord {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string]
|
||||
$Vlan_Id,
|
||||
|
||||
[string]
|
||||
$PA_Zone,
|
||||
|
||||
[ValidateSet("True", "False")]
|
||||
[string]
|
||||
$Secure,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
Begin {
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$RequestDigest = Invoke-RestMethod -Uri $UrlContextInfo -Method Post -UseDefaultCredentials
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$List = Invoke-RestMethod -uri $UrlList -UseDefaultCredentials
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
#$ListItems=((Invoke-RestMethod -Uri $UrlListItem -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
$ListItems = ((Invoke-RestMethod @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
}
|
||||
Process {
|
||||
$RecordToModify = $ListItems | Where-Object Vlan_id -EQ $Vlan_Id
|
||||
If (@($RecordToModify).count -gt 1) {
|
||||
Write-Warning "More than one result, skipping $Vlan_Id"
|
||||
}
|
||||
Else {
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Networks')/items($IDtoModify)"
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName }
|
||||
}
|
||||
|
||||
If ($PA_Zone) { $SetRecord += @{PA_Zone = $PA_Zone } }
|
||||
If ($Secure) { $SetRecord += @{Secure = $Secure } }
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
}
|
||||
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
$SharePointList = Get-ITDVMwareSharePointNetworkList -Credential $SharePointCredential
|
||||
|
||||
$PAInterfaces = Get-ITDPAInterface -ErrorAction SilentlyContinue # | select *, @{n = 'Vlan_Id'; e = { $_.Interface.PadLeft(4, '0') } }
|
||||
|
||||
If ($null -eq $PAInterfaces) {
|
||||
|
||||
}
|
||||
Else {
|
||||
ForEach ($SPItem in $SharePointList) {
|
||||
Write-Warning ($SPItem.Vlan_Id + ", " + $SPItem.CIDR + " - Start")
|
||||
$change = $false
|
||||
|
||||
If ($SPItem.AutoUpdate -eq $true) {
|
||||
$SetITDVMwareSharePointVMNetworkParams = $null
|
||||
|
||||
$PAItem = $PAInterfaces | Where-Object Interface -EQ ($SPItem.Vlan_Id -as [int])
|
||||
$SetITDVMwareSharePointVMNetworkParams = @{Vlan_Id = $SPItem.Vlan_Id;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
If ($PAItem.ZeroTrust) {
|
||||
If ($SPItem.Secure -ne $PAItem.ZeroTrust) {
|
||||
$SetITDVMwareSharePointVMNetworkParams += @{Secure = [bool]$PAItem.ZeroTrust }
|
||||
$change = $true
|
||||
}
|
||||
}
|
||||
Else {
|
||||
If ($SPItem.Secure -eq $false) {
|
||||
# Secure is accurate
|
||||
}
|
||||
Else {
|
||||
$SetITDVMwareSharePointVMNetworkParams += @{Secure = $false }
|
||||
$change = $true
|
||||
}
|
||||
}
|
||||
|
||||
If ($SPItem.PA_Zone -ne $PAItem.Zone) {
|
||||
$SetITDVMwareSharePointVMNetworkParams += @{PA_Zone = $PAItem.Zone }
|
||||
$change = $true
|
||||
}
|
||||
|
||||
If ($Change -eq $true) {
|
||||
Write-Warning ("Set VM network metadata: Vlan " + $SPItem.Vlan_Id + ", " + $SPItem.CIDR)
|
||||
Set-ITDVMwareSharePointNetworkRecord @SetITDVMwareSharePointVMNetworkParams
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 5;
|
||||
Platform = 'PowerShell-VMware-NetworkSync';
|
||||
}
|
||||
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54'
|
||||
$AppId = '60244573-7130-4026-9c6d-47de73f8ca29'
|
||||
$SecureStringPwd = "sQV8Q~sNLcrDl2RgB32gsSEsDVgdFhNMcBdPoaEX"
|
||||
#$zm = Get-Credential -username $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force)
|
||||
|
||||
$PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AppId, ($SecureStringPwd | ConvertTo-SecureString -AsPlainText -Force)
|
||||
Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $tenantId
|
||||
|
||||
# laptop
|
||||
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
||||
+843
@@ -0,0 +1,843 @@
|
||||
# https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d
|
||||
<#
|
||||
$ComputerName = 'itddotfrsql3.nd.gov'
|
||||
$CPU = 8
|
||||
$MemoryGB = 32
|
||||
$OS = 'Windows Server 2019 Datacenter'
|
||||
$Subnet = '10.21.12.0/22'
|
||||
$Environment = "Production"
|
||||
$Platform = "Azure"
|
||||
$AppName = 'DOT-FacialRec'
|
||||
$LicensingRestrictions='Microsoft SQL Enterprise'
|
||||
$Credential = $PrvCred
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
<# New-ITDVMwareWindowsVMAA
|
||||
#>
|
||||
|
||||
function New-ITDAzureWindowsVMAA {
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$ComputerName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]
|
||||
$CPU,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]
|
||||
$MemoryGB,
|
||||
|
||||
#[Parameter(Mandatory = $true)]
|
||||
#[int]
|
||||
#$DiskOS,
|
||||
|
||||
#[Parameter(Mandatory = $true)]
|
||||
#[int]
|
||||
#$DiskData,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$Subnet,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$OS,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$Environment,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$AppName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$LicensingRestrictions
|
||||
|
||||
#[Parameter(Mandatory = $true)]
|
||||
#[PSCredential]
|
||||
#$Credential
|
||||
)
|
||||
|
||||
|
||||
$Body = "
|
||||
ComputerName=$ComputerName
|
||||
CPU=$CPU
|
||||
MemoryGB=$MemoryGB
|
||||
VlanId=$VlanId
|
||||
OS=$OS
|
||||
Environment=$Environment
|
||||
Datacenter=$Datacenter
|
||||
LicensingRestrictions=$LicensingRestrictions
|
||||
AppName=$AppName
|
||||
|
||||
RunningOn=$env:computername
|
||||
RunningAs=$env:username
|
||||
Credential=$Credential.UserName
|
||||
"
|
||||
Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $Body -Subject "AutoBuildAzure-$ComputerName"
|
||||
|
||||
$FQDN = $ComputerName
|
||||
$tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54'
|
||||
|
||||
If ($Credential) {
|
||||
$IaasAuto = $Credential
|
||||
}
|
||||
|
||||
#$IaasAutoAzApp = Get-AutomationPSCredential -Name 'Azure IaaS Service Principal'
|
||||
|
||||
Write-Warning "[$FQDN]:Start"
|
||||
$SPCred = $IaasAuto
|
||||
$ADCred = $IaasAuto
|
||||
$PSCred = $IaasAuto
|
||||
$VMCred = $IaasAuto
|
||||
$CcmCred = $IaasAuto
|
||||
|
||||
#$RadiusCred = $RadiusCred
|
||||
$RadiusCred = New-Object System.Management.Automation.PSCredential($IaasAuto.username.split('\')[1], ($IaaSAuto.Password))
|
||||
|
||||
Clear-DnsClientCache
|
||||
$HostName = $FQDN.split('.')[0]
|
||||
|
||||
|
||||
|
||||
# Infoblox
|
||||
#$InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred # not valid for Azure
|
||||
#$Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd()
|
||||
$Cidr = $Subnet
|
||||
[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 = $Subnet.Split('.')
|
||||
[Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) )
|
||||
|
||||
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
|
||||
Start-Sleep -Seconds 5
|
||||
[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
|
||||
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.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
#$GuestCredential = $GuestCredentialBB
|
||||
|
||||
switch ($Environment) {
|
||||
{ $_ -eq 'Test' -or $_ -eq 'Development' } {
|
||||
Write-Warning 'Environment is Test or Development'
|
||||
$EnvShortString = 'tst'
|
||||
#$VMSizeFilter="*_B*s*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
|
||||
$Subscription = "npd01"
|
||||
$VNet = "vnet-npd01-001"
|
||||
$VNetSubnet = "sn-shared-zerotrust-npd-10.21.8.0_22"
|
||||
}
|
||||
'Production' {
|
||||
Write-Warning 'Environment is Production'
|
||||
$EnvShortString = 'prd'
|
||||
#$VMSizeFilter="*_D*s_*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
$Subscription = "prd01"
|
||||
$VNet = "vnet-prd01-001"
|
||||
$VnetSubnet = "sn-shared-zerotrust-prd-10.21.12.0_22"
|
||||
}
|
||||
'CARES-tst' {
|
||||
Write-Warning 'Environment is CARES-tst'
|
||||
$EnvShortString = 'tst'
|
||||
#$VMSizeFilter="*_D*s_*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
$Subscription = "cares01"
|
||||
$VNet = "vnet-infra-azurenetworking-cares01-npd"
|
||||
$VnetSubnet = "sn-shared-zerotrust-npd-10.69.254.0_24"
|
||||
}
|
||||
'CARES-prd' {
|
||||
Write-Warning 'Environment is CARES-prd'
|
||||
$EnvShortString = 'prd'
|
||||
#$VMSizeFilter="*_D*s_*"
|
||||
$VMSizeFilter1 = "*_D[0-9]*s_v3"
|
||||
$VMSizeFilter2 = "*_E[0-9]*s_v3"
|
||||
$VMSizeFilter3 = "*_F[0-9]*s_v2"
|
||||
$Subscription = "cares01"
|
||||
$VNet = "vnet-infra-azurenetworking-cares01-prd"
|
||||
$VnetSubnet = "sn-shared-zerotrust-prd-10.69.126.0_24"
|
||||
}
|
||||
|
||||
Default {
|
||||
Write-Error "Environment failed" -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
switch ($OS) {
|
||||
"Windows Server 2019 Datacenter" {
|
||||
$VMOS = "Windows"
|
||||
$Publisher = "MicrosoftWindowsServer"
|
||||
$Offer = "WindowsServer"
|
||||
$sku = "2019-Datacenter"
|
||||
}
|
||||
"Windows Server 2022 Datacenter" {
|
||||
$VMOS = "Windows"
|
||||
$Publisher = "MicrosoftWindowsServer"
|
||||
$Offer = "WindowsServer"
|
||||
$sku = "2022-datacenter"
|
||||
}
|
||||
Default { Write-Error "Invalid operating system" -ErrorAction Stop }
|
||||
}
|
||||
|
||||
# finalize VM size
|
||||
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
||||
|
||||
$location = "centralus"
|
||||
$VMSize = Get-AzVMSize -Location $location | `
|
||||
Where-Object { $_.Name -Like "$VMSizeFilter1" -or $_.Name -Like "$VMSizeFilter2" -or $_.Name -Like "$VMSizeFilter3" } | `
|
||||
Where-Object { $_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024) } | `
|
||||
Where-Object Name -NotMatch "_Promo" | `
|
||||
Sort-Object NumberOfCores, MemoryInMB | `
|
||||
Select-Object -First 1
|
||||
|
||||
|
||||
# resource group things
|
||||
$VMOwner = $AppName.split('-')[0].ToLower()
|
||||
$VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " "
|
||||
#$IPAddress = (Resolve-DnsName -Name $ComputerName -ErrorAction Stop).IpAddress
|
||||
$ResourceGroup = "rg-$VMOwner-$VMFunction-$EnvShortString"
|
||||
If ($ResourceGroupIndex) { $ResourceGroup = $ResourceGroup + "-$ResourceGroupIndex" }
|
||||
$VMName = "vm-$HostName-$EnvShortString"
|
||||
|
||||
|
||||
$NewITDAzureRMVMParams = @{
|
||||
VMFQDN = $ComputerName
|
||||
VMSubscription = $Subscription
|
||||
VMEnvironment = $EnvShortString
|
||||
VMOwner = $VMOwner
|
||||
VMFunction = $VMFunction
|
||||
VMSize = $VMSize.Name
|
||||
VMOS = $VMOS
|
||||
VMPublisher = $Publisher
|
||||
VMOffer = $Offer
|
||||
VMSku = $sku
|
||||
VMVnetName = $VNet
|
||||
VMSubnet = $VNetSubnet
|
||||
VMLocation = $location
|
||||
VMIP = $IPAddress.IPAddressToString
|
||||
VMCredential = $LocalCredential
|
||||
AppName = $AppName
|
||||
}
|
||||
<#
|
||||
$VMFQDN = $ComputerName
|
||||
$VMSubscription = $Subscription
|
||||
$VMEnvironment = $EnvShortString
|
||||
$VMOwner = $VMOwner
|
||||
$VMFunction = $VMFunction
|
||||
$VMSize = $VMSize.Name
|
||||
$VMOS = $VMOS
|
||||
$VMPublisher = $Publisher
|
||||
$VMOffer = $Offer
|
||||
$VMSku = $sku
|
||||
$VMVnetName = $VNet
|
||||
$VMSubnet = $VNetSubnet
|
||||
$VMLocation = $location
|
||||
$VMIP = $IPAddress
|
||||
$VMCredential = $LocalCredential
|
||||
$AppName = $AppName
|
||||
#>
|
||||
New-ITDAzureRMVM @NewITDAzureRMVMParams
|
||||
|
||||
# wait for build
|
||||
$VMName = ('vm-' + $ComputerName.split('.')[0] + '-' + $EnvShortString)
|
||||
|
||||
$VMStatus = $null
|
||||
$VMCreation = $Null
|
||||
While ($VMCreation -ne "Complete") {
|
||||
If (( (Get-AzVM -ResourceGroupName $ResourceGroup -Name $VMName -Status).Statuses | Where-Object Code -Match "PowerState").Code -eq "PowerState/running") {
|
||||
$VMCreation = "Complete"
|
||||
}
|
||||
else {
|
||||
Start-Sleep -Seconds 300
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 30
|
||||
|
||||
# Add extra disk
|
||||
Add-ITDAzureRMNewDataDisk -VMName $VMName -SizeGB 20
|
||||
|
||||
# pre-firewall Guest OS customization
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\1-SetWMITags.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\3-Disks.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\5-TimeZone.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\6-PerformanceCounters.ps1'
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\7-DisableWindowsFirewall.ps1'
|
||||
|
||||
# determine Active Directory Forest and OU
|
||||
$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=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName }
|
||||
If (!($OUAppName)) {
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,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 ("*" + $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 ($Environment) {
|
||||
'Test' {
|
||||
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Non-Prod" }
|
||||
Else { $EnvString = "Test" }
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
|
||||
}
|
||||
'Production' {
|
||||
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Prod" }
|
||||
Else { $EnvString = "Prod" }
|
||||
|
||||
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$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)
|
||||
}
|
||||
}
|
||||
|
||||
# disconnect, wait for firewall, then reconnect
|
||||
Disconnect-AzAccount
|
||||
While ($PingStatus -eq $false) {
|
||||
$PingTest = Test-NetConnection -ComputerName $FQDN
|
||||
If ($PingTest.PingSuccedded -eq $true) {
|
||||
$PingStatus = $true
|
||||
}
|
||||
Start-Sleep -Seconds 300
|
||||
}
|
||||
|
||||
|
||||
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
||||
Set-AzContext -Subscription $Subscription
|
||||
|
||||
|
||||
|
||||
# post-firewall Guest OS customization
|
||||
switch ($DomainName) {
|
||||
'nd.gov' {
|
||||
Write-Warning "Attempting domain join nd.gov"
|
||||
Write-Warning "Domain: $DomainName"
|
||||
Write-Warning "OuPath: $OuFinal"
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\8-Domain-ndgov.ps1' -Parameter @{"DomainName" = 'nd.gov'; "OuPath" = ' CN=ITDSOSCMTSQL22,OU=SOS-BLS,OU=SOS-All,OU=Windows,OU=SERVERS,OU=COMPUTERS,OU=ITD,DC=nd,DC=gov' }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Write-Verbose -Message "Activating windows against $KMS..."
|
||||
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\9-KMS.ps1'
|
||||
|
||||
<#
|
||||
Write-Warning "[$FQDN]:Register SCCM Client"
|
||||
$CcmRegistered = $false
|
||||
While ($CcmRegistered -eq $false) {
|
||||
$CcmResult = Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\10-SCCM-a.ps1'
|
||||
If ($CcmResult.Value -match "SCCM Client is registered") {
|
||||
Write-Warning "Client is registered."
|
||||
$CcmRegistered = $true
|
||||
}
|
||||
ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 60 }
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
|
||||
}
|
||||
|
||||
function New-ITDAzureRMVM {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
# VM Computer Name (FQDN)
|
||||
[Parameter(Mandatory = $true, Position = 0)]
|
||||
[String]
|
||||
$VMFQDN,
|
||||
|
||||
# VM Subscription (tst,prd,dr)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMSubscription,
|
||||
|
||||
# Environment (tst,prd,dr)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMEnvironment,
|
||||
|
||||
# Owner (infra,shared,ITD,DHS,etc)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMOwner,
|
||||
|
||||
# Function (testdc, POC, etc)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMFunction,
|
||||
|
||||
#[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$ResourceGroupIndexNumber,
|
||||
|
||||
# Azure VM Size
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMSize,
|
||||
|
||||
# Azure OS (Windows or Linux)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMOS,
|
||||
|
||||
# Availability Set
|
||||
[switch]
|
||||
$VMAS,
|
||||
|
||||
# Availability Set Tier
|
||||
[string]
|
||||
$VMASTier,
|
||||
|
||||
# Availability Zone
|
||||
[ValidateSet(1, 2, 3)]
|
||||
[int]
|
||||
$VMAvailZone,
|
||||
|
||||
# Azure Publisher
|
||||
[string]
|
||||
$VMPublisher,
|
||||
|
||||
# Azure Offer
|
||||
[string]
|
||||
$VMOffer,
|
||||
|
||||
# Azure Sku
|
||||
[string]
|
||||
$VMSku,
|
||||
|
||||
# Azure vNet
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMVNetName,
|
||||
|
||||
# Azure Subnet
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMSubnet,
|
||||
|
||||
# Azure Location
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMLocation,
|
||||
|
||||
# Azure Private IP
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$VMIP,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCredential]
|
||||
$VMCredential,
|
||||
|
||||
# App name to be used for the RG
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$AppName
|
||||
)
|
||||
Begin {
|
||||
$VMName = $VMFQDN.Split('.')[0]
|
||||
#$VMIndexNumber = "001"
|
||||
$VMIPConfigName = "ipconfig-$VMName-$VMEnvironment"
|
||||
$VMNicName = "nic-$VMName-$VMEnvironment" ######
|
||||
$VMObjectName = "vm-$VMName-$VMEnvironment"
|
||||
$ResourceGroup = "rg-$VMOwner-$VMFunction-$VMEnvironment"
|
||||
#If($ResourceGroupIndexNumber){$ResourceGroup = $ResourceGroup + "-$ResourceGroupIndexNumber"}
|
||||
#removing diag storage account because replaced by managed storage accounts for boot diagnostics
|
||||
#$VMDiagStorageAcct = "sa" + $VMOwner + $VMFunction + "diag" + $VMEnvironment
|
||||
$VMOSDiskName = "vm-$VMName-os-$VMEnvironment"
|
||||
|
||||
<#
|
||||
If($VMASTier)
|
||||
{
|
||||
$VMASName = "as-$VMOwner-$VMFunction-$VMASTier-$VMEnvironment"
|
||||
}
|
||||
Else
|
||||
{
|
||||
$VMASName = "as-$VMOwner-$VMFunction-$VMEnvironment"
|
||||
}
|
||||
#>
|
||||
|
||||
<#
|
||||
Write-Verbose "Checking Storage Account Length"
|
||||
If (($VmDiagStorageAcct.Length) -gt 24){
|
||||
Write-Verbose "Storage Account Length is too long. Truncating function...."
|
||||
$TruncateCharacters = $VmDiagStorageAcct.Length - 24
|
||||
$ShortVMFunction = $VMFunction.Substring(0, ($VMFunction.length) - $TruncateCharacters)
|
||||
$VMDiagStorageAcct = "sa" + $VMOwner + $ShortVMFunction + "diag" + $VMEnvironment
|
||||
}
|
||||
|
||||
If (($VmDiagStorageAcct.Length) -gt 24){
|
||||
Write-Verbose "Storage Account Length is too long after truncating. Terminating Build"
|
||||
Return
|
||||
}
|
||||
#>
|
||||
Write-Verbose "Verifying Applicable Inputs are Lowercase"
|
||||
$VMIPConfigName = $VMIPConfigName.ToLower()
|
||||
$VMNicName = $VMNicName.ToLower()
|
||||
$VMObjectName = $VMObjectName.ToLower()
|
||||
$ResourceGroup = $ResourceGroup.ToLower()
|
||||
#$VMDiagStorageAcct = $VMDiagStorageAcct.ToLower()
|
||||
$VMOSDiskName = $VMOSDiskName.ToLower()
|
||||
}
|
||||
Process {
|
||||
Set-AzContext $VMSubscription
|
||||
$ResGroupExist = ""
|
||||
Write-Verbose "Creating Resource Group if it doesn't exist"
|
||||
$ResGroupExist = Get-AzResourceGroup -Name $ResourceGroup -ErrorAction SilentlyContinue
|
||||
|
||||
|
||||
If (@($ResGroupExist).count -gt 1) {
|
||||
Write-Error "Multiple Resource Groups matched" -ErrorAction Stop
|
||||
}
|
||||
If (@($ResGroupExist).count -lt 1) {
|
||||
Write-Warning "No matching resource group found, creating it now"
|
||||
New-AzResourceGroup -Name $ResourceGroup -Location $VMLocation -Tag @{ApplicationName = $AppName }
|
||||
$ResourceGroupName = $ResourceGroupSearch.ResourceGroupName
|
||||
#Write-Error "No Resource Groups matched" -ErrorAction Stop
|
||||
}
|
||||
If (@($ResGroupExist).count -eq 1) {
|
||||
Write-Warning "Exactly one matching resource group found"
|
||||
$ResourceGroupName = $ResourceGroupSearch.ResourceGroupName
|
||||
}
|
||||
|
||||
<#
|
||||
Write-Verbose "Checking Storage Account Availability in Subscription"
|
||||
If (!(Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $VMDiagStorageAcct}))
|
||||
{
|
||||
If ((Get-AzureRmStorageAccountNameAvailability -Name $VMDiagStorageAcct).NameAvailable -eq $True)
|
||||
{
|
||||
|
||||
New-AzureRmStorageAccount -Name $VMDiagStorageAcct -Location $VMLocation -ResourceGroupName $ResourceGroup -SkuName "Standard_LRS" -EnableHttpsTrafficOnly $true
|
||||
#Start-Sleep -Seconds 5
|
||||
Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct | Update-AzureRmStorageAccountNetworkRuleSet -DefaultAction Deny -Bypass None
|
||||
#Update-AzureRmStorageAccountNetworkRuleSet -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct -DefaultAction Deny -Bypass None
|
||||
Add-AzureRmStorageAccountNetworkRule -ResourceGroupName $ResourceGroup -AccountName $VMDiagStorageAcct -IPAddressOrRange "165.234.248.3"
|
||||
}
|
||||
Else
|
||||
{
|
||||
Write-Verbose "Storage Account already exists. Re-run with a valid storage account"
|
||||
Return
|
||||
}
|
||||
}
|
||||
#>
|
||||
<#
|
||||
Write-Verbose "Evaluating Availability Set"
|
||||
If($VMAS)
|
||||
{
|
||||
Write-Verbose "Checking for existing Availability Set"
|
||||
$VMASExist = Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -ErrorAction SilentlyContinue
|
||||
If($VMASExisting)
|
||||
{
|
||||
$VMASID = $VMASExist.id
|
||||
}
|
||||
Else
|
||||
{
|
||||
New-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -Location $VMLocation -PlatformFaultDomainCount 3 -PlatformUpdateDomainCount 5 -Sku Aligned
|
||||
$VMASID = (Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName).id
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
Write-Verbose "Preparing Network Config"
|
||||
$VNet = (Get-AzVirtualNetwork | where { $_.Name -eq $VMVNetName })
|
||||
$VNetID = $VNet.id
|
||||
$Subnet = ($VNet.Subnets | where { $_.Name -eq $VMSubnet })
|
||||
$SubnetName = $Subnet.name
|
||||
$SubnetID = $Subnet.id
|
||||
|
||||
Write-Verbose "Creating IPConfig and NIC"
|
||||
$IPConfig = New-AzNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $VMIP -PrivateIpAddressVersion IPv4 -Subnet $Subnet
|
||||
$VMNIC = New-AzNetworkInterface -IpConfigurationName $IPConfig -Location $VMLocation -Name $VMNICName -ResourceGroupName $ResourceGroup -SubnetId $SubnetID
|
||||
$VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static"
|
||||
$VMNIC.IpConfigurations[0].PrivateIpAddress = $VMIP
|
||||
Set-AzNetworkInterface -NetworkInterface $VMNIC
|
||||
|
||||
Write-Verbose "Building VM Config"
|
||||
#If($VMAS)
|
||||
#{
|
||||
#$vmConfig = New-AzVMConfig -VMName $VMObjectName -VMSize $VMSize -AvailabilitySetId $VMASID
|
||||
#}
|
||||
#Else
|
||||
#{
|
||||
#If($VMAvailZone)
|
||||
#{
|
||||
# Write-Verbose "AvailZone $VMAvailZone"
|
||||
# $vmConfigParams = @{
|
||||
# VMName = $VMObjectName
|
||||
# VMSize = $VMSize
|
||||
# Zone = $VMAvailZone
|
||||
# }
|
||||
#}
|
||||
#Else
|
||||
#{
|
||||
# Write-Verbose "No AvailZone"
|
||||
$vmConfigParams = @{
|
||||
VMName = $VMObjectName
|
||||
VMSize = $VMSize
|
||||
}
|
||||
#}
|
||||
#$vmConfig = New-AzureRmVMConfig -VMName $VMObjectName -VMSize $VMSize
|
||||
$vmConfig = New-AzVMConfig @vmConfigParams
|
||||
#}
|
||||
|
||||
|
||||
|
||||
$vmConfig | Set-AzVMOSDisk -Name $VMOSDiskName -CreateOption FromImage
|
||||
If ($VMOS -eq "Windows") {
|
||||
$vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $VMCredential
|
||||
$vmConfig | Set-AzVMSourceImage -PublisherName $VMPublisher -Offer $VMOffer -Skus $VMSku -Version latest
|
||||
}
|
||||
If ($VMOS -eq "Linux") {
|
||||
$vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $VMCredential
|
||||
Switch ($VMSubscription) {
|
||||
#"npd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"}
|
||||
#"infra01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"}
|
||||
#"prd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-002"}
|
||||
|
||||
"npd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103" }
|
||||
"infra01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403" }
|
||||
"prd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003" }
|
||||
}
|
||||
}
|
||||
|
||||
$vmConfig | Add-AzVMNetworkInterface -Id $VMNIC.ID
|
||||
#$vmConfig | Set-AzureRmVMBootDiagnostics -Enable -ResourceGroupName $ResourceGroup -StorageAccountName $VMDiagStorageAcct
|
||||
##set to use managed storage account after module conversion to Az
|
||||
#$vmConfig | Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup
|
||||
Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup
|
||||
|
||||
Write-Verbose "Creating VM"
|
||||
New-AzVM -VM $vmConfig -ResourceGroupName $resourceGroup -Location $VMLocation -DisableBginfoExtension -LicenseType "Windows_Server" -AsJob
|
||||
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
function Add-ITDAzureRMNewDataDisk {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string]
|
||||
$VMName,
|
||||
|
||||
[int[]]
|
||||
$SizeGB
|
||||
)
|
||||
|
||||
Begin {
|
||||
$search = @()
|
||||
$Hostname = $VMName.split('-')[1]
|
||||
$Environment = $VMName.split('-')[2]
|
||||
|
||||
Get-AzSubscription | ForEach-Object {
|
||||
$Subscription = $_
|
||||
Set-AzContext $_ | Out-Null
|
||||
$search += Get-AzVM | Where-Object Name -EQ $VMName | Select-Object *, @{n = 'SubscriptionName'; e = { $Subscription.Name } }
|
||||
}
|
||||
}
|
||||
Process {
|
||||
If ($search.count -eq 1) {
|
||||
Set-AzContext $search.SubscriptionName
|
||||
$ResourceGroup = $search.ResourceGroupName.ToLower()
|
||||
$Location = (Get-AzResourceGroup -Name $ResourceGroup).Location
|
||||
$VM = Get-AzVM -Name $VMName -ResourceGroupName $ResourceGroup
|
||||
$Zone = $VM.Zones
|
||||
|
||||
|
||||
ForEach ($Size in $SizeGB) {
|
||||
$ExistingDisks = @($VM.StorageProfile.DataDisks | Select-Object *, @{n = 'ItdId'; e = { [int]($_.Name -replace "vm-$hostname-app-$environment-") } })
|
||||
|
||||
$NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | Select-Object -First 1).ItdId + 1
|
||||
$NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000")
|
||||
$NewDiskName = "vm-$Hostname-app-$Environment-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001
|
||||
|
||||
$LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1
|
||||
|
||||
$count = 0
|
||||
If ($ExistingDisks) {
|
||||
while ($Size -match $ExistingDisks.DiskSizeGB) {
|
||||
$count++
|
||||
Write-Warning "SizeGB: $Size, Count: $count"
|
||||
If ($count -ge 11) {
|
||||
Write-Error "Disk size not available" -ErrorAction Stop
|
||||
}
|
||||
Else {
|
||||
$Size = $Size - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Warning "SizeGB: $Size, Count: $count"
|
||||
|
||||
$AzureRmDiskConfigParams = @{
|
||||
DiskSizeGB = $Size
|
||||
Location = $Location
|
||||
CreateOption = "Empty"
|
||||
SkuName = "Premium_LRS"
|
||||
}
|
||||
|
||||
If ($Zone) {
|
||||
Write-Verbose "VM is located in Zone $Zone"
|
||||
$AzureRmDiskConfigParams += @{Zone = $Zone }
|
||||
}
|
||||
#$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS
|
||||
$DiskConfig = New-AzDiskConfig @AzureRmDiskConfigParams
|
||||
|
||||
If (!(Get-AzDisk -ResourceGroupName $ResourceGroup -DiskName $NewDiskName -ErrorAction SilentlyContinue)) {
|
||||
$NewDisk = New-AzDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroup
|
||||
|
||||
$VM = Add-AzVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly
|
||||
Update-AzVM -VM $VM -ResourceGroupName $ResourceGroup -AsJob
|
||||
}
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Error "Search count invalid" -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
End {
|
||||
}
|
||||
}
|
||||
|
||||
$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation'
|
||||
|
||||
$IaasAutoCred = $IaaSAutoAz
|
||||
<#
|
||||
New-ITDAzureWindowsVMAA `
|
||||
-ComputerName itdbuilddba.nd.gov `
|
||||
-CPU 2 `
|
||||
-MemoryGB 8 `
|
||||
-Subnet '10.21.8.0/22'`
|
||||
-OS 'Windows Server 2019 Datacenter' `
|
||||
-Environment 'Test' `
|
||||
-AppName 'Infra-SoftDev-TFS' `
|
||||
-LicensingRestrictions 'No Licensing Restrictions' `
|
||||
-verbose
|
||||
#>
|
||||
|
||||
<#
|
||||
|
||||
$params = @{
|
||||
ComputerName = "itdpurshir1.nd.gov"
|
||||
CPU = 2;
|
||||
MemoryGB = 8;
|
||||
Subnet = '10.69.254.0/24';
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = 'CARES-tst';
|
||||
AppName = 'ITD-POC-Purview';
|
||||
LicensingRestrictions = 'No Licensing Restrictions';
|
||||
Verbose = $true;
|
||||
}
|
||||
|
||||
New-ITDAzureWindowsVMAA @params
|
||||
#>
|
||||
$params = @{
|
||||
ComputerName = "itdsoscmtsql22.nd.gov"
|
||||
CPU = 4;
|
||||
MemoryGB = 16;
|
||||
Subnet = '10.21.8.0/22';
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = 'Test';
|
||||
AppName = 'SOS-BLS';
|
||||
LicensingRestrictions = 'Microsoft SQL Standard';
|
||||
Verbose = $true;
|
||||
}
|
||||
|
||||
New-ITDAzureWindowsVMAA @params
|
||||
|
||||
|
||||
|
||||
#>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
$RestMethodParams = @{
|
||||
Method = 'Post';
|
||||
Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d';
|
||||
Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV'};
|
||||
Body = [PSCustomObject]@{
|
||||
ComputerName = 'itddhsharvestp1.nd.gov';
|
||||
CPU = 2;
|
||||
MemoryGB = 24;
|
||||
VlanId = 3822;
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = 'Production';
|
||||
Datacenter = 'Bismarck';
|
||||
AppName = 'DHS-Orchard-Harvest';
|
||||
LicensingRestrictions = 'No Licensing Restrictions';
|
||||
} | ConvertTo-Json;
|
||||
}
|
||||
|
||||
Invoke-RestMethod @RestMethodParams | ConvertTo-Json
|
||||
+1102
File diff suppressed because it is too large
Load Diff
+1101
File diff suppressed because it is too large
Load Diff
+358
@@ -0,0 +1,358 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq '6EE8DaFMbswirY38qPfewwT82G9Bdiv8p3SKEdisX88mfnFfiredy6uti4nJprecedegJkTGBHDV3alpineePkM5grainsE56xp3JmuffWjwL') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$FQDN = 'itdzmbuild01.nd.gov'
|
||||
|
||||
# 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 ($ADCred.UserName.split('\')[1], $ADCred.Password)
|
||||
$VMCred = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
|
||||
Clear-DnsClientCache
|
||||
$SharePointList = Get-ITDVMwareSharePointVMGuestListTst -Credential $SPCred
|
||||
$SPItem = $SharePointList | Where-Object Title -eq $FQDN
|
||||
$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 $IBCred
|
||||
}
|
||||
|
||||
If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
|
||||
Write-Error "IP Address already in use." -ErrorAction Stop
|
||||
}
|
||||
|
||||
# Active Directory
|
||||
If ($PSEdition -eq 'Core') { Import-Module ActiveDirectory -UseWindowsPowerShell }
|
||||
$Filter = ("{Name -eq '" + $SPItem.AppName + "'}")
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase "OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD,dc=nd,dc=gov" -Filter $Filter
|
||||
If (!($OUAppName)) {
|
||||
$OUAppName = Get-ADOrganizationalUnit -SearchBase "OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD,dc=nd,dc=gov" -Filter { Name -eq 'All-General' }
|
||||
}
|
||||
$ExistingADComputer = Get-ADComputer -Identity $Hostname -ErrorAction SilentlyContinue
|
||||
If ($ExistingADComputer) {
|
||||
If ($ExistingADComputer.DistinguishedName -like ("*" + $SPItem.AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") {
|
||||
Write-Warning "AD object already exists, OU path does match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "AD object already exists, OU path mismatch"
|
||||
Exit
|
||||
Exit
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch ($SPItem.Environment) {
|
||||
'Test' {
|
||||
$OUAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -like "*Test*"
|
||||
}
|
||||
'Production' {
|
||||
$OUAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -like "*Prod*"
|
||||
}
|
||||
}
|
||||
If ($OUAppNameEnv) { $OUFinal = $OUAppNameEnv }
|
||||
Else { $OUFinal = $OUAppName }
|
||||
|
||||
New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json)
|
||||
}
|
||||
|
||||
# Passwordstate
|
||||
$LocalCredential = New-ITDPassword -Title $FQDN -Username itdadmin -Description 'Local Administrator' -PasswordList CSRC -Credential $PrvCred
|
||||
$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))
|
||||
|
||||
# VMware
|
||||
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'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"WINDOWS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"SQL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
}
|
||||
"SQL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
}
|
||||
"WAS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"WAS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"PS1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-PS1-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"PS2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-PS2-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"TEL1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"TEL2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
"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
|
||||
$DatastoreCluster = Get-DatastoreCluster | Where-Object Name -like ("*" + $SPItem.Cluster + "*")
|
||||
$ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select -First 1)
|
||||
If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) {
|
||||
Write-Verbose ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
|
||||
}
|
||||
else {
|
||||
Write-Verbose ("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 = Get-Folder -Server $ViServer -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" }
|
||||
Default {}
|
||||
}
|
||||
|
||||
$PortGroupsAvailable = Get-VDPortGroup -Server $ViServer -VDSwitch $VirtualSwitch
|
||||
$PortGroup = $PortGroupsAvailable | Where-Object Name -eq ("dvPG_" + $SPItem.Vlan_Id + "_" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt)
|
||||
If (!($PortGroup)) {
|
||||
Write-Error "Virtual port group not found" -ErrorAction Stop
|
||||
Stop
|
||||
}
|
||||
|
||||
$NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S"))
|
||||
Get-OSCustomizationSpec -Name "Windows (Auto)" -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName | `
|
||||
Set-OSCustomizationSpec `
|
||||
-NamingScheme fixed `
|
||||
-NamingPrefix $Hostname `
|
||||
-AdminPassword $GuestCredentialBB.GetNetworkCredential().Password `
|
||||
|
||||
Get-OSCustomizationSpec -Name $NewOSSpecName | `
|
||||
Get-OSCustomizationNicMapping | `
|
||||
Set-OSCustomizationNicMapping `
|
||||
-IpMode UseStaticIP `
|
||||
-IpAddress $IpAddress.IPAddressToString `
|
||||
-SubnetMask $SubnetMask.IPAddressToString `
|
||||
-DefaultGateway $DefaultGateway.IPAddressToString `
|
||||
-Dns "10.2.7.40", "10.2.5.40"
|
||||
|
||||
$OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName
|
||||
|
||||
$NewVMParams = @{
|
||||
Name = $FQDN;
|
||||
ResourcePool = $SPItem.Cluster;
|
||||
Datastore = $DatastoreCluster;
|
||||
DiskStorageFormat = $DiskStorageFormat;
|
||||
Template = $Template;
|
||||
Location = $FolderLocation;
|
||||
OSCustomizationSpec = $OSSpec;
|
||||
}
|
||||
|
||||
New-VM @NewVMParams
|
||||
|
||||
#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
|
||||
$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 = $VMDisk | 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 = $VMDisk | 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 = $VMDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
If ($VMDisk3.CapacityGB -lt $SPItem.Disk3) {
|
||||
Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $SPItem.Disk3 -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
# Run Guest OS code
|
||||
|
||||
$InvokeVMScriptFunc = {
|
||||
|
||||
}
|
||||
|
||||
$VM | Invoke-VMScript -GuestCredential $GuestCredentialBB -ScriptText $InvokeVMScriptFunc
|
||||
#}
|
||||
}
|
||||
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
"target_platform","target_hostname","target_cpus","target_memory","target_osdisk","target_datadisk","target_subnet","target_os","target_environment","target_vm_app_name","target_datacenter","target_licensingrestrictions"
|
||||
"VMware","itdzmtest110.nd.gov","1","4","50","20","10.11.12.0/23","Windows Server 2022 Datacenter","Production","ITD-POC-zmeier","Bismarck","No Licensing Restrictions"
|
||||
|
+64
@@ -0,0 +1,64 @@
|
||||
$DriveLetter = 'D'
|
||||
$CsvPath = ($DriveLetter + ":\AutoBuildInputFiles\")
|
||||
$FailedPath = ($DriveLetter + ":\AutoBuildInputFiles\Failed")
|
||||
$CompletedPath = ($DriveLetter + ":\AutoBuildInputFiles\Completed")
|
||||
|
||||
$GetBuildFile = Get-ChildItem -Path $CsvPath -Filter *.csv | Sort-Object LastWriteTime | select -First 1
|
||||
|
||||
#$IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation'
|
||||
$IaasAutoCred = $PrvCred
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false -InvalidCertificateAction Ignore
|
||||
|
||||
$InputParams = Import-Csv -Path $GetBuildFile.FullName
|
||||
|
||||
$ComputerName = $InputParams.target_hostname.ToLower()
|
||||
Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $InputParams -Subject ("AutoBuildFromFile-$ComputerName-" + $InputParams.target_platform)
|
||||
|
||||
try {
|
||||
switch ($InputParams.target_platform) {
|
||||
'azure' {
|
||||
|
||||
}
|
||||
'vmware' {
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $IaasAutoCred
|
||||
|
||||
New-ITDVMwareWindowsVM -ComputerName $ComputerName `
|
||||
-CPU $InputParams.target_cpus `
|
||||
-MemoryGB $InputParams.target_memory `
|
||||
-DiskOS $InputParams.target_osdisk `
|
||||
-DiskData $InputParams.target_datadisk `
|
||||
-Subnet $InputParams.target_subnet `
|
||||
-OS $InputParams.target_os `
|
||||
-Environment $InputParams.target_environment `
|
||||
-Datacenter $InputParams.target_datacenter `
|
||||
-AppName $InputParams.target_vm_app_name `
|
||||
-LicensingRestrictions $InputParams.target_licensingrestrictions `
|
||||
-Credential $IaasAutoCred `
|
||||
-Verbose
|
||||
|
||||
Move-Item -Path $GetBuildFile.FullName -Destination $CompletedPath
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 240;
|
||||
Platform = 'PowerShell-VMware-VMWindows';
|
||||
}
|
||||
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$error[0]
|
||||
Write-Warning "Email vmware admins about failure"
|
||||
$Body = $error[0] | Select-Object *
|
||||
Send-MailMessage -From autobuild@nd.gov -To "zmeier@nd.gov" -Subject "Failure-AutoBuildFromFile-$ComputerName" -SmtpServer apprelay.nd.gov -Body $Body
|
||||
|
||||
Write-Warning "Error detected. Moving csv input file to folder Failed"
|
||||
Move-Item -Path $GetBuildFile.FullName -Destination $FailedPath
|
||||
}
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
$RestMethodParams = @{
|
||||
Method = 'Post';
|
||||
Uri = 'https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d';
|
||||
Headers = @{ITD = 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV' };
|
||||
Body = [PSCustomObject]@{
|
||||
target_platform = "VMware"
|
||||
target_hostname = 'itdcndsperms.nd.gov';
|
||||
target_cpus = 1;
|
||||
target_memory = 8;
|
||||
target_osdisk = 100;
|
||||
target_datadisk = 20; # this is now swap
|
||||
target_subnet = '10.221.8.0/28';
|
||||
target_os = 'Windows Server 2019 Datacenter';
|
||||
target_environment = 'Production';
|
||||
target_vm_app_name = 'Shared-PeopleSoft-State';
|
||||
target_datacenter = 'Bismarck';
|
||||
target_licensingrestrictions = 'No Licensing Restrictions';
|
||||
} | ConvertTo-Json;
|
||||
}
|
||||
|
||||
Invoke-RestMethod @RestMethodParams
|
||||
|
||||
$VMNames=@"
|
||||
itdcndhftdb22.nd.gov
|
||||
itdcndhhtdb22.nd.gov
|
||||
"@
|
||||
$VMNames = ConvertTo-Array -MultiLineString $VMNames
|
||||
|
||||
Invoke-Command -ComputerName $VMNames -Credential $PrvCred -ScriptBlock {
|
||||
Get-Process -Name ccmexec*,cohesity*,cortex*,nessus*,vmtoolsd*
|
||||
} | sort-object PSComputerName
|
||||
+1131
File diff suppressed because it is too large
Load Diff
+23
@@ -0,0 +1,23 @@
|
||||
#https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=4cWZz%2fq97AqMdlNak6qv2lUurLPFsWmPJmovLmAE%2fNg%3d
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'mXJU74ABYyDHcVY6iJihPDk8LidJ2ibBA2sA3RAwKaBHS6Gw7Rr2Zz5JZAhPm6wMuvY7X54ZzJxAXaM7ig3PHG4MKvtkBf8X7q3jGNcePgUqg9WCwCSJ3JWG7AA6M39x4vpihKeZV') {
|
||||
Write-Verbose "Header has required data"
|
||||
Write-Host $
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$ComputerName = $InputParams.target_hostname.ToLower()
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
$InputParams | Export-Csv "E:\AutoBuildInputFiles\$ComputerName-$Timestamp.csv"
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'PJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5svBxbnq2g9M7cQJtFN3iGU4kD4p') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | select -first 1).Name }
|
||||
|
||||
switch ($Duration) {
|
||||
{$Duration -ge 1 -and $Duration -le 7}
|
||||
{
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found"
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" }
|
||||
}
|
||||
}
|
||||
{$Duration -ge 8}
|
||||
{
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
Write-Verbose "Exactly one clone match found"
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Clone Id #$Id match not found for $VMName" }
|
||||
}
|
||||
}
|
||||
Default {
|
||||
Write-Error "Duration less than zero."
|
||||
}
|
||||
}
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
write-verbose "Updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
# 2021 https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=EHlEzPMvDt02gdqMb9wlkdt1FrbmlZjbfQpFTtoIrBc%3d
|
||||
# content-type application/x-www-form-urlencoded
|
||||
# 2022 https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=%2b6PP2%2bd3FDLqb4bgMs%2b4V1%2bDAMw0tPxN%2f4Ee0eWMa5Q%3d
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'VRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtHAKpueFYU4L3N9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirMXTKqtHssnNGBrew3gxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$SPListItem = $ListItems | Where-object Id -eq $InputParams.Id
|
||||
If ($SPListItem.Title -ne $InputParams.HostName) {
|
||||
Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname)
|
||||
Exit
|
||||
}
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$SnapTime = [DateTime]$SPListItem.DateTime
|
||||
|
||||
$NotifyEmail = $SPListItem.Author.Email
|
||||
If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail }
|
||||
|
||||
$tryCount = 0
|
||||
#while ($tryCount -lt 5) {
|
||||
try {
|
||||
$tryCount++
|
||||
|
||||
|
||||
|
||||
$SnapName = "AutoSnap_" + $SPListItem.ID
|
||||
$SnapExpireDateTime = $SnapTime.AddDays($SPListItem.Duration)
|
||||
If ($SnapExpireDateTime.DayOfWeek -eq "Saturday" -or $SnapExpireDateTime.DayOfWeek -eq "Sunday") {
|
||||
$SnapExpireDateTime = $SnapExpireDateTime.AddDays(2)
|
||||
}
|
||||
$SnapDeleteDateTime = $SnapExpireDateTime.AddDays(2)
|
||||
|
||||
$SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
|
||||
$SnapDescription = "AutoSnap_" + 1080 + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
|
||||
$snapMemory = $false
|
||||
$snapQuiesce = $false
|
||||
|
||||
Write-Warning $VMName
|
||||
Write-Warning $SnapName
|
||||
Write-Warning ("SharePoint: " + $SnapTime)
|
||||
If ($SnapTime -lt (Get-Date)) {
|
||||
$SnapTime = (Get-Date).AddSeconds(30)
|
||||
}
|
||||
Write-Warning ("PowerShell: " + $SnapTime)
|
||||
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name }
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
|
||||
$si = Get-View ServiceInstance -Server $VIServer
|
||||
$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer
|
||||
|
||||
$spec = New-Object VMware.Vim.ScheduledTaskSpec
|
||||
$spec.Name = $SnapName, $VMname -join '_'
|
||||
$spec.Description = "$SnapDescription"
|
||||
$spec.Enabled = $true
|
||||
$spec.Notification = $NotifyEmail
|
||||
|
||||
$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
|
||||
$spec.Scheduler.runat = $SnapTime
|
||||
|
||||
$spec.Action = New-Object VMware.Vim.MethodAction
|
||||
$spec.Action.Name = "CreateSnapshot_Task"
|
||||
|
||||
@($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object {
|
||||
$arg = New-Object VMware.Vim.MethodActionArgument
|
||||
$arg.Value = $_
|
||||
$spec.Action.Argument += $arg
|
||||
}
|
||||
|
||||
# prep for update SharePoint record status
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
# Create vCenter scheduled task
|
||||
$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)
|
||||
Start-Sleep -Seconds 3
|
||||
}<#
|
||||
catch [System.Management.Automation.MethodInvocationException] {
|
||||
If ($tryCount -lt 4) {
|
||||
If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") {
|
||||
Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again")
|
||||
}
|
||||
write-warning $trycount
|
||||
}
|
||||
Else {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
}#>
|
||||
catch {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed default message"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
#}
|
||||
|
||||
# update SharePoint record status
|
||||
If ($Status -ne "Errored") { $Status = "Scheduled" }
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = $Status;
|
||||
}
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 5;
|
||||
Platform = 'PowerShell-VMware-SnapshotNew';
|
||||
}
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
}
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
|
||||
)
|
||||
$StartTime = Get-Date
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$ListToRemove = $SnapshotList | Where-Object { $_.Status -eq "Expired, Delete Approved" } | Sort-Object AutoDelete
|
||||
|
||||
ForEach ($SPRecord in $ListToRemove) {
|
||||
$Id = $null
|
||||
$VMName = $null
|
||||
$SnapName = $null
|
||||
|
||||
$Id = $SPRecord.ID
|
||||
$VMName = $SPRecord.Title
|
||||
$SnapName = "AutoSnap_" + $Id
|
||||
|
||||
$SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName
|
||||
$Datastore = Get-VM $VMName | Get-Datastore
|
||||
$ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0]
|
||||
|
||||
Write-Warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer)
|
||||
|
||||
try {
|
||||
$SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
while ($SnapshotTaskCount -ge 1) {
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds."
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
$timestamp = $null
|
||||
$SnapshotTaskCount = @(Get-Task | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
}
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal."
|
||||
$SnapshotToRemove | Remove-Snapshot -Confirm:$false
|
||||
}
|
||||
catch {
|
||||
Write-Error "Snapshot Removal failed";
|
||||
Write-Error $Error[1];
|
||||
exit
|
||||
}
|
||||
|
||||
#update SharePoint field
|
||||
Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)"
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Removed';
|
||||
SnapshotRemoved = [datetime](Get-Date);
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
Disconnect-VIServer -Server * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
|
||||
$DiffTime = [math]::round((4+((Get-Date) - $StartTime).Minutes),0)
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Deprovisioning';
|
||||
Units = $DiffTime;
|
||||
Platform = 'PowerShell-VMware-SnapshotRemove';
|
||||
}
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://share.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$ListToUpdate = $SnapshotList | where-object { $_.Status -eq "Scheduled" } | Sort-Object DateTime
|
||||
|
||||
#$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
#If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | select -first 1).Name }
|
||||
|
||||
ForEach($SPRecord in $ListToUpdate)
|
||||
{
|
||||
$VM = $null
|
||||
$Taken = $null
|
||||
$VMName = $null
|
||||
$Duration = $null
|
||||
$Id = $null
|
||||
$VMSnapshot = $null
|
||||
$Task = $null
|
||||
|
||||
If( (($SPRecord.DateTime) -as [datetime]).ToLocalTime() -lt (Get-Date) ) # If datetime has passed
|
||||
{
|
||||
$VMName = $SPRecord.Title
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
$Duration = $SPRecord.Duration
|
||||
$Id = $SPRecord.Id
|
||||
|
||||
switch ($Duration) {
|
||||
{$Duration -ge 1 -and $Duration -le 7}
|
||||
{
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found"
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots).count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else {
|
||||
$Taken = $false
|
||||
Write-Verbose "Snapshot Id #$Id match not found on $VMName"
|
||||
Write-Error "Snapshot $Id for $VMName not found."
|
||||
}
|
||||
}
|
||||
}
|
||||
{$Duration -ge 8}
|
||||
{
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
Write-Verbose "Exactly one clone match found"
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else {
|
||||
$Taken = $false
|
||||
Write-Verbose "Clone Id #$Id match not found for $VMName"
|
||||
Write-Error "Clone $Id for $VMName not found."
|
||||
}
|
||||
}
|
||||
}
|
||||
Default {
|
||||
Write-Error "Duration less than zero."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
write-verbose "Updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
#Status = 'Taken';
|
||||
Status = If ($Taken -eq $true) {'Taken'} Else {'Errored'};
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
}
|
||||
|
||||
$postParams = [PSCustomObject]@{
|
||||
AutomationName = "Infra-VMware";
|
||||
Action = 'Provisioning';
|
||||
Units = 1;
|
||||
Platform = 'PowerShell-VMware-SnapshotUpdateStatus';
|
||||
}
|
||||
Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json)
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false -ErrorAction SilentlyContinue
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"Id": "575",
|
||||
"Hostname":"itdfmauditp1.nd.gov"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"WebhookName": "rh-VMware-UpdateVMSnapshotStatus-prd",
|
||||
"RequestBody": "[\n {\n \"Id\": \"68\",\n \"HostName\": \"itddeqappt1.nd.gov\",\n \"DateTime\": \"2/5/2020 7:00 PM\",\n \"Duration\": \"8\",\n \"NotifyEmail\": \"\"\n }\n]",
|
||||
"RequestHeader": {
|
||||
"Connection": "Close",
|
||||
"Expect": "100-continue",
|
||||
"Host": "s25events.azure-automation.net",
|
||||
"ITD": "PJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5svBxbnq2g9M7cQJtFN3iGU4kD4p",
|
||||
"x-ms-request-id": "5ee3253c-5bb4-4aea-a950-6149ddb0436e"
|
||||
}
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'w3gVRLEq2Yi7yzWW8fpKNCPTKqtHssnNGBref5BDtxXkr3mZA3NB5gUcnHfr9sdhXC53y7gWHAKpueFYU4L3NMXV7DszCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirpR3kjiLgi3FpRPgUWus9Zx') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$Id = $InputParams.Id
|
||||
$VMName = $InputParams.Hostname
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$Request = $SnapshotList | where-object ID -eq $id
|
||||
$SnapName = "AutoSnap_" + $Id
|
||||
|
||||
$SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName
|
||||
$Datastore = Get-VM $VMName | Get-Datastore
|
||||
$ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0]
|
||||
|
||||
write-warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer)
|
||||
|
||||
|
||||
#try {
|
||||
$SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object {$_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running"}).count
|
||||
write-warning $SnapshotTaskCount
|
||||
while ($SnapshotTaskCount -ge 1) {
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds."
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
$timestamp = $null
|
||||
$SnapshotTaskCount = @(Get-Task | Where-Object {$_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running"}).count
|
||||
write-warning $SnapshotTaskCount
|
||||
}
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal."
|
||||
$SnapshotToRemove | Remove-Snapshot -Confirm:$false -RunAsync
|
||||
<#}
|
||||
catch {
|
||||
Write-Error "Snapshot Removal failed";
|
||||
Write-Error $Error[1];
|
||||
exit
|
||||
}#>
|
||||
|
||||
#update SharePoint field
|
||||
Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Removed';
|
||||
SnapshotRemoved = [datetime](Get-Date);
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
#$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Clone Id #$Id match not found for $VMName" }
|
||||
}
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
$VMClone = $VMClones
|
||||
Write-Verbose "Exactly one clone match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | sort-object Name | select -first 1).Name }
|
||||
|
||||
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" }
|
||||
}
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $VMSnapshot.Created;
|
||||
AutoExpire = ($VMSnapshot.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($VMSnapshot.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object] $WebhookData
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL
|
||||
Method = "Get"
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'HAKpueFYU4L3NMXTKqtHssnNGBrew3gVRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkir') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List2 = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$SPListItem = $ListItems | Where-object Id -eq $InputParams.Id
|
||||
If ($SPListItem.Title -ne $InputParams.HostName) {
|
||||
Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname)
|
||||
Exit
|
||||
}
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$SnapTime = ([DateTime]$SPListItem.DateTime).AddMinutes($Duration * 3)
|
||||
|
||||
$NotifyEmail = $SPListItem.Author.Email
|
||||
If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail }
|
||||
|
||||
$tryCount = 0
|
||||
# while ($tryCount -lt 5) {
|
||||
try {
|
||||
$tryCount++
|
||||
Write-Warning ("SharePoint: " + $SnapTime)
|
||||
If ($SnapTime -lt (Get-Date)) {
|
||||
$SnapTime = (Get-Date).AddSeconds(30)
|
||||
}
|
||||
Write-Warning ("PowerShell: " + $SnapTime)
|
||||
|
||||
$SnapName = "AutoSnap_" + $SPListItem.ID
|
||||
$SnapExpireDateTime = $SnapTime.AddMinutes($SPListItem.Duration * 3)
|
||||
$SnapDeleteDateTime = $SnapExpireDateTime.AddMinutes(30)
|
||||
|
||||
$SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
|
||||
$snapMemory = $false
|
||||
$snapQuiesce = $false
|
||||
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name }
|
||||
|
||||
$VIServer = $VM.Uid.split('@')[1].split(':')[0]
|
||||
|
||||
$si = Get-View ServiceInstance -Server $VIServer
|
||||
$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer
|
||||
|
||||
$spec = New-Object VMware.Vim.ScheduledTaskSpec
|
||||
$spec.Name = $SnapName, $VMname -join '_'
|
||||
$spec.Description = "$SnapDescription"
|
||||
$spec.Enabled = $true
|
||||
$spec.Notification = $NotifyEmail
|
||||
|
||||
$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
|
||||
$spec.Scheduler.runat = $SnapTime
|
||||
|
||||
$spec.Action = New-Object VMware.Vim.MethodAction
|
||||
$spec.Action.Name = "CreateSnapshot_Task"
|
||||
|
||||
@($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object {
|
||||
$arg = New-Object VMware.Vim.MethodActionArgument
|
||||
$arg.Value = $_
|
||||
$spec.Action.Argument += $arg
|
||||
}
|
||||
|
||||
# prep for update SharePoint record status
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
# Create vCenter scheduled task
|
||||
$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)
|
||||
Start-Sleep -Seconds 3
|
||||
}
|
||||
catch [System.Management.Automation.MethodInvocationException] {
|
||||
If ($tryCount -lt 4) {
|
||||
If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") {
|
||||
Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again")
|
||||
}
|
||||
write-warning $trycount
|
||||
}
|
||||
Else {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
}
|
||||
catch {
|
||||
write-error "vCenter Snapshot Scheduled Task Creation failed default message"
|
||||
write-error $error[1]
|
||||
Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
|
||||
$Status = "Errored"
|
||||
exit
|
||||
}
|
||||
#}
|
||||
|
||||
# update SharePoint record status
|
||||
If ($Status -ne "Errored") { $Status = "Scheduled" }
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = $Status;
|
||||
}
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
Else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
|
||||
)
|
||||
|
||||
function Get-ITDVMwareSharePointSnapshotRequestList {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[PSCredential]
|
||||
$Credential
|
||||
)
|
||||
|
||||
begin {
|
||||
$InvokeWebRequestParams = @{ }
|
||||
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
|
||||
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
|
||||
|
||||
$URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail,AutoExpire,AutoDelete&$expand=Author/Id'
|
||||
$InvokeWebRequestParams += @{
|
||||
Uri = $URL;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
}
|
||||
|
||||
$List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
$List.d.results
|
||||
}
|
||||
}
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'w3gVRLEq2Yi7yzWW8fpKNCPTKqtHssnNGBref5BDtxXkr3mZA3NB5gUcnHfr9sdhXC53y7gWHAKpueFYU4L3NMXV7DszCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkirpR3kjiLgi3FpRPgUWus9Zx') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential
|
||||
$ListToRemove = $SnapshotList | where-object { $_.Status -eq "Expired, Delete Approved" } | Sort-Object AutoDelete
|
||||
|
||||
ForEach ($SPRecord in $ListToRemove) {
|
||||
$Id = $null
|
||||
$VMName = $null
|
||||
$SnapName = $null
|
||||
|
||||
$Id = $SPRecord.ID
|
||||
$VMName = $SPRecord.Title
|
||||
$SnapName = "AutoSnap_" + $Id
|
||||
|
||||
$SnapshotToRemove = Get-Snapshot -Name $SnapName -VM $VMName
|
||||
$Datastore = Get-VM $VMName | Get-Datastore
|
||||
$ViServer = $SnapshotToRemove.uid.split('@')[1].split(':')[0]
|
||||
|
||||
Write-Warning ($SnapshotToRemove.Name + " for " + $SnapshotToRemove.VM + " on " + $Datastore + " on " + $ViServer)
|
||||
|
||||
try {
|
||||
$SnapshotTaskCount = @(Get-Task -Server $ViServer | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
while ($SnapshotTaskCount -ge 1) {
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, pausing 60 seconds."
|
||||
Start-Sleep -Seconds 60
|
||||
|
||||
$timestamp = $null
|
||||
$SnapshotTaskCount = @(Get-Task | Where-Object { $_.Name -eq "RemoveSnapshot_Task" -and $_.State -eq "Running" }).count
|
||||
Write-Warning $SnapshotTaskCount
|
||||
}
|
||||
$timestamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Write-Warning "[$timestamp]:$SnapshotTaskCount RemoveSnapshot_Task already running, starting removal."
|
||||
$SnapshotToRemove | Remove-Snapshot -Confirm:$false
|
||||
}
|
||||
catch {
|
||||
Write-Error "Snapshot Removal failed";
|
||||
Write-Error $Error[1];
|
||||
exit
|
||||
}
|
||||
|
||||
#update SharePoint field
|
||||
Write-Verbose "Exactly one match found, updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
#$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
#If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; break }
|
||||
#$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Removed';
|
||||
SnapshotRemoved = [datetime](Get-Date);
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
}
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[object]
|
||||
$WebhookData
|
||||
)
|
||||
|
||||
If ($WebhookData) {
|
||||
If ($WebhookData.RequestHeader.ITD -eq 'vBxbnq2g9M7cQJtFN3iGU4kD4pPJaSEgC5HML5ZuZk6wKfZQrpj2XfuQ5s') {
|
||||
Write-Verbose "Header has required data"
|
||||
}
|
||||
Else {
|
||||
Write-Error "Header missing required data"
|
||||
exit;
|
||||
}
|
||||
|
||||
$InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
|
||||
$vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto'
|
||||
$SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential
|
||||
|
||||
$VMName = $InputParams.HostName
|
||||
$Id = $InputParams.Id
|
||||
$Duration = $InputParams.Duration
|
||||
|
||||
$VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
|
||||
If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | sort-object Name | select -first 1).Name }
|
||||
|
||||
switch ($Duration) {
|
||||
{$Duration -ge 1 -and $Duration -le 7}
|
||||
{
|
||||
Write-Verbose "Duration = Snapshot"
|
||||
$VMSnapshots = $VM | Get-Snapshot | where-object Description -like "AutoSnap_$Id*"
|
||||
|
||||
If (@($VMSnapshots).count -eq 1) {
|
||||
Write-Verbose "Exactly one snapshot match found"
|
||||
$Taken = $true
|
||||
$VMSnapshot = $VMSnapshots
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMSnapshots | where-object Description -like "AutoSnap_$Id*").count -gt 1) {
|
||||
Write-Error "More than one snapshot match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Snapshot Id #$Id match not found on $VMName" }
|
||||
}
|
||||
}
|
||||
{$Duration -ge 8}
|
||||
{
|
||||
Write-Verbose "Duration = Clone"
|
||||
$VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id)
|
||||
|
||||
If (@($VMClones).count -eq 1) {
|
||||
Write-Verbose "Exactly one clone match found"
|
||||
$Taken = $true
|
||||
$VMClone = $VMClones
|
||||
$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoClone_$Id*")
|
||||
}
|
||||
else {
|
||||
if (@($VMClones).count -gt 1) {
|
||||
Write-Error "More than one VM clone match found, abort"
|
||||
Exit
|
||||
}
|
||||
else { Write-Verbose "Clone Id #$Id match not found for $VMName" }
|
||||
}
|
||||
}
|
||||
Default {
|
||||
Write-Error "Duration less than zero."
|
||||
}
|
||||
}
|
||||
|
||||
If ($Taken -eq $true) {
|
||||
write-verbose "Updating SharePoint fields named Status and SnapshotTaken"
|
||||
$UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlContextInfo;
|
||||
Method = "Post";
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
|
||||
|
||||
$UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlList;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
$List = Invoke-RestMethod @InvokeWebRequestParams
|
||||
$ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName
|
||||
|
||||
$UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000'
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlListItem;
|
||||
Method = "Get";
|
||||
UseBasicParsing = $true;
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" };
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
$ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
|
||||
|
||||
$header = @{
|
||||
"accept" = "application/json;odata=verbose"
|
||||
"X-RequestDigest" = $RequestDigest
|
||||
"IF-MATCH" = '*'
|
||||
"X-HTTP-Method" = "MERGE"
|
||||
}
|
||||
|
||||
$RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
|
||||
If (@($RecordToModify).count -gt 1) { Write-Error "More than one record, stopping"; break }
|
||||
$IDtoModify = $RecordToModify.ID
|
||||
|
||||
$UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
|
||||
$InvokeWebRequestParams = @{
|
||||
Uri = $UrlItem;
|
||||
Method = "Get";
|
||||
Headers = @{ "Accept" = "application/json;odata=verbose" }
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential
|
||||
}
|
||||
|
||||
[PSCustomObject]$SetRecord = @{
|
||||
"__metadata" = @{type = $ListItemEntityTypeFullName };
|
||||
Status = 'Taken';
|
||||
SnapshotTaken = $Task.PrevRunTime;
|
||||
AutoExpire = ($Task.Description -split '[\r\n]+')[1].split('_')[1];
|
||||
AutoDelete = ($Task.Description -split '[\r\n]+')[2].split('_')[1];
|
||||
}
|
||||
|
||||
$body = $SetRecord | ConvertTo-Json
|
||||
$InvokeWebRequestParams = @{
|
||||
|
||||
Uri = $UrlItem;
|
||||
Method = "Post";
|
||||
Body = $body;
|
||||
ContentType = "application/json;odata=verbose";
|
||||
Headers = $header;
|
||||
UseBasicParsing = $true;
|
||||
Credential = $SharePointCredential;
|
||||
}
|
||||
Invoke-RestMethod @InvokeWebRequestParams
|
||||
|
||||
Disconnect-VIServer * -Confirm:$false
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Write-Error "Runbook must be started from webhook"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"Id": "{ItemProperty:ID}",
|
||||
"HostName": "{ItemProperty:HostName}",
|
||||
"DateTime": "{ItemProperty:DateTime}",
|
||||
"Duration": "{ItemProperty:Duration}"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"Id": "566",
|
||||
"HostName": "itdscmt1.nd.gov"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,655 @@
|
||||
function Import-ITDVMwareSRMExport {
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[string]
|
||||
$Path
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
[xml]$Global:SrmXml = Get-Content -Path $Path
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMDatacenter {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
((($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter | Where-Object id -EQ $i)
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
ForEach ($n in $Name) {
|
||||
((($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter | Where-Object name -Like "*$n*")
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
((($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
function Get-ITDVMwareSRMVMFolder {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$VMInventoryFolders = (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder.InventoryFolder
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
$VMInventoryFolders | Where-Object id -Like "*$i*"
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
ForEach ($n in $Name) {
|
||||
$VMInventoryFolders | Where-Object name -Like "*$n*"
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
$VMInventoryFolders
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMHostFolder {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
Foreach ($i in $Id) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder | Where-Object id -EQ $i
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
Foreach ($i in $Id) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder | Where-Object name -Like "*$n*"
|
||||
}
|
||||
|
||||
}
|
||||
'Default' {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
function Get-ITDVMwareSRMComputeResource {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'ResPoolId')]
|
||||
[string[]]
|
||||
$ResPoolId,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource | Where-Object { $_.id -like "*$i*" }
|
||||
}
|
||||
}
|
||||
'ResPoolId' {
|
||||
ForEach ($i in $ResPoolId) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource | Where-Object { $_.resourcepool.id -like "*$i*" }
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
If ($Name) {
|
||||
ForEach ($n in $Name) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource | Where-Object { $_.name -like "*$n*" }
|
||||
}
|
||||
}
|
||||
Else {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMVMHost {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource.hosts | Where-Object { $_.id -like "*$i*" }
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
ForEach ($n in $Name) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource.hosts | Where-Object { $_.name -like "*$n*" }
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.hostFolder.ComputeResource.hosts
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMDatastore {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.datastore | Where-Object id -Like "*$i*"
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
ForEach ($n in $Name) {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.datastore | Where-Object { $_.name -like "*$n*" }
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.datastore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMNetwork {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$dvportgrouplist = (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.NetworkFolder.InventoryFolder.DistributedVirtualPortgroup
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
#(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.NetworkFolder.InventoryFolder.DistributedVirtualPortgroup | Where-Object { $_.id -eq "*$i*" }
|
||||
$dvportgrouplist | where-object id -eq $i
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
ForEach ($n in $Name) {
|
||||
#(($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.NetworkFolder.InventoryFolder.DistributedVirtualPortgroup | Where-Object { $_.name -eq "*$n*" }
|
||||
$dvportgrouplist | where-object name -eq $n
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
$dvportgrouplist
|
||||
}
|
||||
}
|
||||
}
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMVM {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$VMInventory = (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder.VirtualMachine + (($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ Inventory).Attributes.InventoryTree).root.datacenter.vmFolder.InventoryFolder.InventoryFolder.VirtualMachine
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
ForEach ($i in $Id) {
|
||||
$VMInventory | Where-Object { $_.id -like "*$i*" }
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
ForEach ($n in $Name) {
|
||||
$VMInventory | Where-Object { $_.name -like "*$n*" }
|
||||
}
|
||||
}
|
||||
<#'Default' {
|
||||
$VMInventory
|
||||
}#>
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMProtectionGroup {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[Parameter(ParameterSetName = 'Name')]
|
||||
[string[]]
|
||||
$Name,
|
||||
|
||||
[switch]
|
||||
$Detailed,
|
||||
|
||||
[ValidateScript( { $Detailed -eq $true })]
|
||||
[switch]
|
||||
$Formatted
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$ProtectionGroups = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ "ProtectionGroups").Attributes.Folder.vmProtectionGroup
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
$ProtectionGroupsSearch = $Id | ForEach-Object {
|
||||
$ProtectionGroups | Where-Object Id -Like "*$_*"
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
$ProtectionGroupsSearch = $Name | ForEach-Object {
|
||||
$ProtectionGroups | Where-Object Name -Like "*$_*"
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
$ProtectionGroupsSearch = $ProtectionGroups
|
||||
}
|
||||
}
|
||||
|
||||
$AllVrDatastores = Get-ChildItem -Path "vmstores:\itdvmvc2.nd.gov@443\Secondary Datacenter\" | Where-Object Name -Like "*_VR*"
|
||||
$VrFolders = $AllVrDatastores | Get-ChildItem | Where-Object ItemType -EQ "Folder"
|
||||
|
||||
If ($Detailed) {
|
||||
$DetailedResult = [System.Collections.ArrayList]@()
|
||||
ForEach ($ProtectionGroup in $ProtectionGroupsSearch) {
|
||||
Write-Warning -Message ("Start Protection Group Loop for " + $ProtectionGroup.Name.TrimStart().TrimEnd() )
|
||||
$AbrDatastores = $null
|
||||
If ($ProtectionGroup.datastores) {
|
||||
$AbrDatastores = Get-ITDVMwareSRMDatastore -Id ($ProtectionGroup.datastores | select -Unique).TrimStart().TrimEnd()
|
||||
}
|
||||
Else {
|
||||
$AbrDatastores = $null
|
||||
}
|
||||
|
||||
$VMs = (Get-ITDVMwareSRMVM -Id ($ProtectionGroup.ProtectionProperties.id)).Name
|
||||
$VrDatastores = [System.Collections.ArrayList]@()
|
||||
ForEach ($VM in $VMs) {
|
||||
$null = $VRDatastores.add( ($VRFolders | Where-Object Name -Like "$VM*").Datastore)
|
||||
}
|
||||
$VrDatastores = $VRDatastores | Select-Object -Unique Name
|
||||
|
||||
|
||||
$PGobj = [PSCustomObject]@{
|
||||
Name = $ProtectionGroup.Name.TrimStart().TrimEnd();
|
||||
ReplicationType = $ProtectionGroup.ReplicationProviderType.TrimStart().TrimEnd();
|
||||
ArrayPairKey = ( $ProtectionGroup.arrayPairKey | ForEach-Object { If ($_.GetType().Name -eq 'String') { $_.TrimStart().TrimEnd() } } | Select-Object -Unique )
|
||||
Folder = ( Get-ITDVMwareSRMVMFolder -Id ($ProtectionGroup.ProtectionProperties.folder | select -Unique).TrimStart().TrimEnd() ).Name.TrimStart().TrimEnd();
|
||||
ResourceGroup = ( Get-ITDVMwareSRMComputeResource -ResPoolId ($ProtectionGroup.ProtectionProperties.resourceGroup | select -Unique).TrimStart().TrimEnd() ).Name.TrimStart().TrimEnd();
|
||||
Network = ( Get-ITDVMwareSRMNetwork -Id ($ProtectionGroup.ProtectionProperties.RecoveryLocationSettings.DeviceInfo.NetworkDeviceBacking.network | select -Unique).TrimStart().TrimEnd() ).Name.TrimStart().TrimEnd();
|
||||
AbrDatastores = If ($AbrDatastores -ne $null) { ($AbrDatastores.name.TrimStart().TrimEnd() ) };
|
||||
VrDatastores = $VrDatastores.Name | Select-Object -Unique
|
||||
VM = ( Get-ITDVMwareSRMVM -Id ($ProtectionGroup.ProtectionProperties.id.TrimStart().TrimEnd()) ).Name.TrimStart().TrimEnd();
|
||||
}
|
||||
$null = $DetailedResult.add($PGobj)
|
||||
}
|
||||
|
||||
If ($Formatted) {
|
||||
$FormattedResult = $DetailedResult | select Name, ReplicationType, ArrayPairKey, `
|
||||
@{n = 'Folder'; e = { ($_.Folder | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = "ResourceGroup"; e = { ($_.ResourceGroup | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = "Network"; e = { ($_.Network | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'AbrDatastores'; e = { ($_.AbrDatastores | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'VrDatastores'; e = { ($_.VrDatastores | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'VM'; e = { ($_.VM | Sort-Object | Out-String).TrimEnd() } }
|
||||
}
|
||||
}
|
||||
}
|
||||
end {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
If ($Detailed) {
|
||||
If ($Formatted) {
|
||||
Write-Output $FormattedResult
|
||||
}
|
||||
else {
|
||||
Write-Output $DetailedResult
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Output $ProtectionGroupsSearch
|
||||
}
|
||||
}
|
||||
'Name' {
|
||||
If ($Detailed) {
|
||||
If ($Formatted) {
|
||||
Write-Output $FormattedResult
|
||||
}
|
||||
else {
|
||||
Write-Output $DetailedResult
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Output $ProtectionGroupsSearch
|
||||
}
|
||||
}
|
||||
'Default' {
|
||||
If ($Detailed) {
|
||||
If ($Formatted) {
|
||||
Write-Output $FormattedResult
|
||||
}
|
||||
else {
|
||||
Write-Output $DetailedResult
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Output $ProtectionGroups
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMVMSettings {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'Id')]
|
||||
[string[]]
|
||||
$Id,
|
||||
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
[switch]
|
||||
$Detailed
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'Id' {
|
||||
$VMSettingsSearch = $Id | ForEach-Object {
|
||||
($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ VMSettings).Attributes.VMSettings | Where-Object Id -Like "*$_*"
|
||||
}
|
||||
|
||||
}
|
||||
'Default' {
|
||||
$VMSettingsSearch = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ VMSettings).Attributes.VMSettings
|
||||
}
|
||||
}
|
||||
|
||||
If ($Detailed) {
|
||||
$DetailedResult = [System.Collections.ArrayList]@()
|
||||
ForEach ($VMSetting in $VMSettingsSearch) {
|
||||
$VMSettingObj = [PSCustomObject]@{
|
||||
Id = $VMSetting.id.TrimStart().TrimEnd();
|
||||
Name = (Get-ITDVMwareSRMVM -Id $VMSetting.Id.TrimStart().TrimEnd()).Name.TrimStart().TrimEnd();
|
||||
#recoveryPriority = $VMSetting.recoveryPriority;
|
||||
recoveryPriorityGui = switch ($VMSetting.recoveryPriority.TrimStart().TrimEnd()) {
|
||||
25 { 1 }
|
||||
40 { 2 }
|
||||
50 { 3 }
|
||||
60 { 4 }
|
||||
75 { 5 }
|
||||
}
|
||||
}
|
||||
$null = $DetailedResult.add($VMSettingObj)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
If ($Detailed) {
|
||||
Write-Output $DetailedResult
|
||||
}
|
||||
Else {
|
||||
$VMSettingsSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ITDVMwareSRMRecoveryPlan {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string[]]
|
||||
$Name,
|
||||
|
||||
[switch]
|
||||
$Formatted
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$RecoveryPlans = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ RecoveryPlans).Attributes.Folder.RecoveryPlan
|
||||
If ($Name) {
|
||||
$RecoveryPlansSearch = $Name | ForEach-Object {
|
||||
$RecoveryPlans | Where-Object name -Like "*$_*"
|
||||
}
|
||||
}
|
||||
else {
|
||||
$RecoveryPlansSearch = $RecoveryPlans
|
||||
}
|
||||
$DetailedResult = [System.Collections.ArrayList]@()
|
||||
ForEach ($RecoveryPlan in $RecoveryPlansSearch) {
|
||||
Write-Warning -Message ("Start Recovery Plan Loop for " + $RecoveryPlan.Name.TrimStart().TrimEnd() )
|
||||
$ProtectionGroupDetailed = Get-ITDVMwareSRMProtectionGroup -Id $RecoveryPlan.protectionGroups.TrimStart().TrimEnd() -Detailed
|
||||
|
||||
$AbrDatastores = $ProtectionGroupDetailed.AbrDatastores | Select-Object -Unique | Sort-Object
|
||||
$VrDatastores = $ProtectionGroupDetailed.VrDatastores | Select-Object -Unique | Sort-Object
|
||||
$Network = $ProtectionGroupDetailed.Network | Select-Object -Unique | Sort-Object
|
||||
|
||||
$VMSettings = Get-ITDVMwareSRMVMSettings -Id (Get-ITDVMwareSRMVM -Name $ProtectionGroupDetailed.VM).Id.TrimStart().TrimEnd() -Detailed
|
||||
If ($RecoveryPlan.Callouts) {
|
||||
$Callouts = [System.Collections.ArrayList]@()
|
||||
$RecoveryPlan.Callouts.CalloutSpec | ForEach-Object {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$RPobj = [PSCustomObject]@{
|
||||
Name = $RecoveryPlan.Name.TrimStart().TrimEnd();
|
||||
ProtectionGroups = $ProtectionGroupDetailed.Name | Sort-Object;
|
||||
Network = $Network;
|
||||
AbrDatastores = $AbrDatastores;
|
||||
VrDatastores = $VrDatastores;
|
||||
BeforePriority1 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority1Vms').RecoveryPrompt | select promptText, Description
|
||||
Priority1VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 1).Name;
|
||||
BeforePriority2 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority2Vms').RecoveryPrompt | select promptText, Description
|
||||
Priority2VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 2).Name;
|
||||
BeforePriority3 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority3Vms').RecoveryPrompt | select promptText, Description
|
||||
Priority3VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 3).Name;
|
||||
BeforePriority4 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority4Vms').RecoveryPrompt | select promptText, Description
|
||||
Priority4VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 4).Name;
|
||||
BeforePriority5 = ($RecoveryPlan.Callouts.CallOutSpec | Where-Object position -EQ 'beforeRecoverPriority5Vms').RecoveryPrompt | select promptText, Description
|
||||
Priority5VMs = ($VMSettings | Where-Object recoveryPriorityGui -EQ 5).Name;
|
||||
}
|
||||
|
||||
$null = $DetailedResult.Add($RPobj)
|
||||
}
|
||||
|
||||
If ($Formatted) {
|
||||
$FormattedResult = $DetailedResult | select Name, `
|
||||
@{n = 'ProtectionGroups'; e = { ($_.ProtectionGroups | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'Network'; e = { ($_.Network | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'AbrDatastores'; e = { ($_.AbrDatastores | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'VrDatastores'; e = { ($_.VrDatastores | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'BeforePriority1'; e = { $_.BeforePriority1 | Out-String } }, `
|
||||
@{n = 'Priority1VMs'; e = { ($_.Priority1VMs | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'BeforePriority2'; e = { $_.BeforePriority2 | Out-String } }, `
|
||||
@{n = 'Priority2VMs'; e = { ($_.Priority2VMs | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'BeforePriority3'; e = { $_.BeforePriority3 | Out-String } }, `
|
||||
@{n = 'Priority3VMs'; e = { ($_.Priority3VMs | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'BeforePriority4'; e = { $_.BeforePriority4 | Out-String } }, `
|
||||
@{n = 'Priority4VMs'; e = { ($_.Priority4VMs | Sort-Object | Out-String).TrimEnd() } }, `
|
||||
@{n = 'BeforePriority5'; e = { $_.BeforePriority5 | Out-String } }, `
|
||||
@{n = 'Priority5VMs'; e = { ($_.Priority5VMs | Sort-Object | Out-String).TrimEnd() } }
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
If ($Formatted) {
|
||||
Write-Output $FormattedResult
|
||||
}
|
||||
Else {
|
||||
Write-Output $DetailedResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-ITDVMwareSRMMasterPlan {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
begin {
|
||||
$RecoveryPlans = ($Global:SrmXml.configurablesWrapper.data.object | Where-Object Type -EQ RecoveryPlans).Attributes.Folder.RecoveryPlan
|
||||
}
|
||||
|
||||
process {
|
||||
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+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"
|
||||
@@ -0,0 +1,8 @@
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S"
|
||||
$TranscriptPath = "D:\PowerShellTasks\CompareVMSRMList\Logs\CompareVMSRMList-$Timestamp.log"
|
||||
Start-Transcript $TranscriptPath
|
||||
|
||||
$result = Compare-ITDVMwareVMSRMList -vCenterCredential $svcitdvmvcauto -SharePointCredential $svcitdiaassprw -Verbose
|
||||
$body = "" + ($result | ConvertTo-Html)
|
||||
|
||||
Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Body $body -SmtpServer apprelay1.nd.gov -BodyAsHtml -Subject "VMware SRM conflicts" -Verbose
|
||||
@@ -0,0 +1,146 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
GetAzureVMGuestIPsForPA
|
||||
run as ndgov\svcitdiaasauto
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 2pm - repeat every 1 hour indefinitely
|
||||
Actions
|
||||
"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\GetAzureVMGuestIPsForPA\GetAzureVMGuestIPsForPA.ps1"
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
|
||||
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Start-Transcript F:\GetAzureVMGuestIPsForPA\Logs\GetAzureVMGuestIPsForPA-$Timestamp.log
|
||||
$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
|
||||
|
||||
$WindowsIpArray = [string]@()
|
||||
$LinuxIpArray = [string]@()
|
||||
|
||||
# replace with PowerShell.SecretManagement
|
||||
#$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
|
||||
|
||||
# Prepare credentials
|
||||
$svcitdazurescript = Get-Secret -Name svcitdazurescript
|
||||
$MacCred = New-Object System.Management.Automation.PSCredential("svcitdazurescript@nd.gov", $svcitdazurescript.Password)
|
||||
# no VMs or PAs in AzureGov yet (2023/09/26) $MagCred = Get-Secret -Name svcitdazurescriptgov
|
||||
|
||||
# Azure Commercial
|
||||
$AzAccount = Connect-AzAccount -Credential $MacCred -Environment AzureCloud -Verbose
|
||||
$Subscriptions = Get-AzSubscription | Where-Object { $_.Name -ne "sandbox" -and $_.Name -notlike "Visual Studio*" -and $_.Name -notlike "Azure subscription*" -and $_.Name -notlike "Access to Azure Active Directory*"}
|
||||
foreach ($subscription in $subscriptions) {
|
||||
Set-AzContext -Subscription $subscription
|
||||
$WindowsVMs = Get-AzVM | Where-Object { $_.StorageProfile.osdisk.ostype -match "Windows" }
|
||||
$LinuxVMs = Get-AzVM | 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-AzNetworkInterface | 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) {
|
||||
Write-Warning -Message ($VM.Name + "zzzzz")
|
||||
$WindowsIPs += $private.privateIPAddress + "`n"
|
||||
}
|
||||
}
|
||||
elseIf ($privateip.privateIPAddress -ne $null) {
|
||||
Write-Warning -Message ($VM.Name + "xxxxx")
|
||||
$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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#Azure Gov
|
||||
<# no VMs or PAs in AzureGov yet (2023/09/26)
|
||||
$AzAccount = Connect-AzAccount -Credential $MagCred -Environment AzureUSGovernment -Verbose
|
||||
|
||||
$Subscriptions = Get-AzureRMSubscription | Where-Object { $_.Name -ne "sandbox" }
|
||||
foreach ($subscription in $subscriptions) {
|
||||
Set-AzContext -Subscription $subscription
|
||||
$WindowsVMs = Get-AzVM | Where-Object { $_.StorageProfile.osdisk.ostype -match "Windows" }
|
||||
$LinuxVMs = Get-AzVM | 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-AzNetworkInterface | 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 }
|
||||
|
||||
$WindowsIPs | Out-File $OutFileWin -Encoding ASCII -NoNewline -Force
|
||||
$LinuxIPs | Out-File $OutFileLin -Encoding ASCII -NoNewline -Force
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Get IPs for PA
|
||||
run as ndgov\!itdvcenterppa
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 11am
|
||||
Daily, 11pm
|
||||
Actions
|
||||
old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPs.ps1"
|
||||
new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\GetVMwareVMGuestIPsForPA\GetVMwareVMGuestIPsForPA.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Start-Transcript F:\GetVMwareVMGuestIPsForPA\Logs\GetVMwareVMGuestIPsForPA-$Timestamp.log
|
||||
#Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false
|
||||
#Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false
|
||||
|
||||
#Connect
|
||||
Connect-VIServer -Server 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 "F:\GetVMwareVMGuestIPsForPA\Backup\Win\$Timestamp-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" `
|
||||
-or $_.GuestID -eq "windows2019srv_64Guest" `
|
||||
-or $_.GuestID -eq "windows2019srvNext_64Guest" `
|
||||
-or $_.GuestID -eq "windows2022srvNext_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 "F:\GetVMwareVMGuestIPsForPA\Backup\Lin\$Timestamp-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 "other26xLinux64Guest" `
|
||||
-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 "rhel8_64Guest" `
|
||||
-or $_.GuestID -eq "rhel9_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 }
|
||||
|
||||
Disconnect-Viserver -Server itdvmvc1.nd.gov,itdvmvc2.nd.gov -Confirm:$false
|
||||
Stop-Transcript
|
||||
@@ -0,0 +1,116 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Get IPs for PA
|
||||
run as ndgov\!itdvcenterppa
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 11am
|
||||
Daily, 11pm
|
||||
Actions
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPs.ps1"
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
|
||||
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" `
|
||||
-or $_.GuestID -eq "windows2019srv_64Guest" `
|
||||
-or $_.GuestID -eq "windows2019srvNext_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,149 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Get IPs for PA - Azure
|
||||
run as ndgov\svcitdazurescript
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 2pm - repeat every 1 hour indefinitely
|
||||
Actions
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPsAzure.ps1"
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
|
||||
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}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Get IPs for PA - Azure Backup
|
||||
run as ndgov\svcitdazurescript
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 4:12pm - repeat every 1 hour indefinitely
|
||||
Actions
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPsAzureBackup.ps1"
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
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,134 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Get IPs for PA - Azure Backup
|
||||
run as ndgov\!itdvcenterscript
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 11:30am - repeat every 1 hour indefinitely
|
||||
Actions
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\GetIPsMonitor.ps1"
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
|
||||
#cdfelchle 7/12/16
|
||||
|
||||
#Files to Monitor
|
||||
$FileCheckWin = "c:\inetpub\wwwroot\win.txt"
|
||||
$FileCheckLin = "c:\inetpub\wwwroot\lin.txt"
|
||||
$FileCheckBak = "c:\inetpub\wwwroot\AzureBak.txt"
|
||||
$FileCheckWinAz = "c:\inetpub\wwwroot\Azurewin.txt"
|
||||
$FileCheckLinAz = "c:\inetpub\wwwroot\Azurelin.txt"
|
||||
|
||||
#E-mail Initialization and Construction
|
||||
$emailSubject = "VMware-PA Integration Failure"
|
||||
$emailRelay = "apprelay2.nd.gov"
|
||||
$emailBody =
|
||||
"Scripting Server Error Report (ITDVMVCP1SCRIPT)
|
||||
------------------------------------------
|
||||
"
|
||||
$emailRecipients = "itdvctremailalerts@nd.gov"
|
||||
$emailSender = "itdvmvcp1script@nd.gov"
|
||||
|
||||
#File Presence Check
|
||||
$WindowsPresent = Test-Path $FileCheckWin
|
||||
$LinuxPresent = Test-Path $FileCheckLin
|
||||
$AzureWindowsPresent = Test-Path $FileCheckWinAz
|
||||
$AzureLinuxPresent = Test-Path $FileCheckLinAz
|
||||
$AzureBakPresent = Test-Path $FileCheckBak
|
||||
|
||||
|
||||
#Flag to send e-mail
|
||||
$SendEmail = $False
|
||||
|
||||
|
||||
#File Presence Check
|
||||
If ($WindowsPresent -eq $False){
|
||||
$SendEmail = $True
|
||||
$emailBody += $FileCheckWin + " --- Missing File`n"
|
||||
}
|
||||
|
||||
If ($LinuxPresent -eq $False){
|
||||
$SendEmail = $True
|
||||
$emailBody += $FileCheckLin + " --- Missing File`n"
|
||||
}
|
||||
|
||||
If ($AzureWindowsPresent -eq $False){
|
||||
$SendEmail = $True
|
||||
$emailBody += $FileCheckWinAz + " --- Missing File`n"
|
||||
}
|
||||
|
||||
If ($AzureLinuxPresent -eq $False){
|
||||
$SendEmail = $True
|
||||
$emailBody += $FileCheckLinAz + " --- Missing File`n"
|
||||
}
|
||||
|
||||
If ($AzureBakPresent -eq $False){
|
||||
$SendEmail = $True
|
||||
$emailBody += $FileCheckBak + " --- Missing File`n"
|
||||
}
|
||||
|
||||
|
||||
#File Size Check
|
||||
If ($WindowsPresent -eq $True -and (Get-Item $FileCheckWin).length -lt 1000){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckWin --- File size is less than 1kb`n"
|
||||
}
|
||||
|
||||
If ($LinuxPresent -eq $True -and (Get-Item $FileCheckLin).length -lt 1000){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckLin --- File size is less than 1kb`n"
|
||||
}
|
||||
|
||||
If ($AzureWindowsPresent -eq $True -and (Get-Item $FileCheckWinAz).length -lt 100){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckWinAz --- File size is less than 1kb`n"
|
||||
}
|
||||
|
||||
If ($AzureLinuxPresent -eq $True -and (Get-Item $FileCheckLinAz).length -lt 100){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckLinAz --- File size is less than 1kb`n"
|
||||
}
|
||||
|
||||
If ($AzureBakPresent -eq $True -and (Get-Item $FileCheckBak).length -lt 10){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckBak --- File size is less than 10 bytes`n"
|
||||
}
|
||||
|
||||
|
||||
|
||||
#File Age Check
|
||||
$CurrentTime = Get-Date
|
||||
|
||||
If ($WindowsPresent -eq $True -and (Get-Item $FileCheckWin).LastWriteTime -lt $CurrentTime.AddHours(-13)){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckWin --- File is older than 12 hours`n"
|
||||
}
|
||||
|
||||
If ($LinuxPresent -eq $True -and (Get-Item $FileCheckLin).LastWriteTime -lt $CurrentTime.AddHours(-13)){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckLin --- File is older than 12 hours`n"
|
||||
}
|
||||
|
||||
If ($AzureWindowsPresent -eq $True -and (Get-Item $FileCheckWinAz).LastWriteTime -lt $CurrentTime.AddHours(-13)){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckWinAz --- File is older than 12 hours`n"
|
||||
}
|
||||
|
||||
If ($AzureLinuxPresent -eq $True -and (Get-Item $FileCheckLinAz).LastWriteTime -lt $CurrentTime.AddHours(-13)){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckLinAz --- File is older than 12 hours`n"
|
||||
}
|
||||
|
||||
If ($AzureBakPresent -eq $True -and (Get-Item $FileCheckBak).LastWriteTime -lt $CurrentTime.AddHours(-13)){
|
||||
$SendEmail = $True
|
||||
$emailBody += "$FileCheckBak --- File is older than 12 hours`n"
|
||||
}
|
||||
|
||||
|
||||
If ($SendEmail -eq $True){
|
||||
Send-MailMessage -To $emailRecipients -From $emailSender -Subject $emailSubject -Body $emailBody -SmtpServer $emailRelay
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Old-VMware Billing
|
||||
run as ndgov\!itdvcenterscript (required for SQL Database access)
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 5am
|
||||
Actions
|
||||
old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\vmconfig.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
|
||||
Start-Transcript C:\ITDSCRIPT\Logs\VMConfig.txt
|
||||
Add-PSSnapin VMware.VimAutomation.Core
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false
|
||||
Connect-VIServer -Server itdvmvcp1.nd.gov,itdvmvcp2.nd.gov,itdvmvc1.nd.gov,itdvmvc2.nd.gov
|
||||
#Connect-VIServer -Server itdvmvcp2.nd.gov
|
||||
|
||||
|
||||
###########################
|
||||
## Functions #
|
||||
###########################
|
||||
|
||||
###
|
||||
### Override Invoke-SQLCmd cmdlet in order to display proper error Handling.
|
||||
###
|
||||
function Invoke-SQLCmd ([string] $ServerInstance, [string] $Database, [String] $Query)
|
||||
{
|
||||
Try
|
||||
{
|
||||
$conn = new-object system.data.SqlClient.SqlConnection("Data Source=$ServerInstance;Integrated Security=TRUE;Initial Catalog=$Database");
|
||||
$ds = new-object "System.Data.DataSet" "dsChildSites"
|
||||
|
||||
$da = new-object "System.Data.SqlClient.SqlDataAdapter" ($Query, $conn)
|
||||
$fillcnt = $da.Fill($ds)
|
||||
$conn.Close()
|
||||
|
||||
$dtChild = new-object "System.Data.DataTable" "dsChildSites"
|
||||
$dtChild = $ds.Tables[0]
|
||||
$dtChild | FOREACH-OBJECT -process {
|
||||
$_
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
write-output $Query
|
||||
Throw $_
|
||||
}
|
||||
}
|
||||
|
||||
#$Servers = Get-VM | Where-Object {$_.PowerState -like 'PoweredOn'} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name
|
||||
$Servers = Get-VM | Where-Object {($_ | Get-Harddisk).count -ne 0} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name
|
||||
|
||||
|
||||
$SQLServer = "ITDSQL16P1\SQL16P1"
|
||||
$DB = "ITD-SRS-Billing"
|
||||
|
||||
$Connection = New-Object System.Data.SQLClient.SQLConnection
|
||||
$Connection.ConnectionString = "server='$SQLServer';database='$DB';Integrated Security=TRUE;"
|
||||
$Connection.Open()
|
||||
$Command = New-Object System.Data.SQLClient.SQLCommand
|
||||
$Command.Connection = $Connection
|
||||
|
||||
$Date = "'" + (Get-Date).ToString('yyyy/MM/dd') + "'"
|
||||
|
||||
$sql = "delete from [VMware_VCenter_VMs] where snapshotdate = $Date;"
|
||||
Invoke-SQLCmd -ServerInstance $SQLServer -Database $DB -Query $sql
|
||||
|
||||
foreach($Server in $Servers) {
|
||||
$ServerName = "'" + $Server.Name + "'"
|
||||
$ServerMemoryMB = $Server.MemoryMB
|
||||
$ServerNumCPU = $Server.NumCPU
|
||||
$ServerHardDiskSizeGB = $Server.HardDiskSizeGB
|
||||
$ServerHost = "'" + $Server.VMHost + "'"
|
||||
$sql ="INSERT INTO [VMware_VCenter_VMs] (ServerName, SnapshotDate, VMName, Memory_MB, Num_VCPU, Disk_MB, ESXHostName) Values ('None', $Date, $ServerName, $ServerMemoryMB, $ServerNumCPU, $ServerHardDiskSizeGB, $ServerHost);"
|
||||
Invoke-SQLCmd -ServerInstance $SQLServer -Database $DB -Query $sql
|
||||
|
||||
}
|
||||
|
||||
$Connection.Close()
|
||||
Stop-Transcript
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
SetVMTagAndMoveToAppNameFolder
|
||||
run as ndgov\svcitdiaassched
|
||||
run whether user is logged on or not
|
||||
run with highest privileges
|
||||
Triggers
|
||||
Daily, 1pm
|
||||
Actions
|
||||
old powershell.exe -file "D:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SetVMTagAndMoveToAppNameFolderTask.ps1"
|
||||
new "C:\Program Files\PowerShell\7\pwsh.exe" -file "F:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SetVMTagAndMoveToAppNameFolderTask.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 3 days
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S"
|
||||
$TranscriptPath = "F:\SetVMTagAndMoveToAppNameFolder\Logs\SetVMTagAndMoveToAppNameFolderTask-$Timestamp.log"
|
||||
Start-Transcript $TranscriptPath
|
||||
|
||||
Connect-ITDvCenter -Credential $svcitdvmvcauto
|
||||
|
||||
Set-ITDVMwareVMTagFromSharePoint -SharePointCredential $svcitdiaassprw -Verbose
|
||||
|
||||
Move-ITDVMwareVMToAppNameFolder -Credential $svcitdvmvcauto -Verbose
|
||||
|
||||
Disconnect-VIServer -Server * -Force -Confirm:$false
|
||||
@@ -0,0 +1,12 @@
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S"
|
||||
$TranscriptPath = "D:\PowerShellTasks\StartDatastoreUnmap\Logs\StartDatastoreUnmapTask-$Timestamp.log"
|
||||
Start-Transcript $TranscriptPath
|
||||
|
||||
try
|
||||
{
|
||||
Start-ITDVMwareDatastoreUnmap -Credential $svcitdvmvcauto -Verbose
|
||||
}
|
||||
catch
|
||||
{
|
||||
Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Subject "Task StartITDVMwareDatastoreUnmap errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
SetVMTagNadMovToAppNameFolder
|
||||
run as ndgov\svcitdiaassched
|
||||
run whether user is logged on or not
|
||||
run with highest privileges
|
||||
Triggers
|
||||
Daily, 8am
|
||||
Disabled
|
||||
Actions
|
||||
powershell.exe -file "D:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SyncVMwareAppNameTagsFromSharePoint.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 3 days
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S"
|
||||
$TranscriptPath = "D:\PowerShellTasks\SyncVMwareAppNameTagsFromSharePoint\Logs\SyncVMwareAppNameTagsFromSharePointTask-$Timestamp.log"
|
||||
Start-Transcript $TranscriptPath
|
||||
|
||||
try {
|
||||
Sync-ITDVMwareSharePointAppNameTags -vCenterCredential $svcitdvmvcauto -SharePointCredential $svcitdiaassprw -Verbose
|
||||
}
|
||||
catch {
|
||||
Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Subject "Task SyncVMwareAppNameTagsFromSharePoint errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
SetVMTagNadMovToAppNameFolder
|
||||
run as ndgov\svcitdiaassched
|
||||
run whether user is logged on or not
|
||||
run with highest privileges
|
||||
Triggers
|
||||
Daily, 10:15am, repeat every 8 hours
|
||||
Actions
|
||||
"C:\Program Files\PowerShell\7\pwsh.exe" -file "D:\PowerShellTasks\SyncVMwareDatastoresToSharePoint\SyncVMwareDatastoresToSharePoint.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 3 days
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S"
|
||||
$TranscriptPath = "F:\SyncVMwareDatastoresToSharePoint\Logs\SyncVMwareDatastoresToSharePoint-$Timestamp.log"
|
||||
Start-Transcript $TranscriptPath
|
||||
|
||||
try
|
||||
{
|
||||
Connect-ITDvCenter -Credential $svcitdvmvcauto
|
||||
Sync-ITDVMwareSharePointDatastoreRecord -SharePointCredential $svcitdiaassprw -verbose
|
||||
Disconnect-VIServer -Server * -Confirm:$flse
|
||||
}
|
||||
catch
|
||||
{
|
||||
Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvcp1script@nd.gov -Subject "Task SyncVMwareDatastoresToSharePoint errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov
|
||||
}
|
||||
|
||||
|
||||
Stop-Transcript
|
||||
@@ -0,0 +1,10 @@
|
||||
Connect-HPOVMgmt -Hostname itdoneviewp1.nd.gov -Credential $AdminCred -LoginAcknowledge
|
||||
|
||||
$VMwareHosts = Get-VMHost
|
||||
$HPOVServers = Get-HPOVServer | Select-Object *,@{n='Enclosure';e={$_.Name.split(',')[0]}}
|
||||
|
||||
ForEach($VMwareHost in $VMwareHosts)
|
||||
{
|
||||
$HPOVServer = $HPOVServers | where-object ServerName -eq $VMwareHost.Name
|
||||
$VMwareHost | New-TagAssignment -Tag $HPOVServer.Enclosure -Server $VMwareHost.Uid.split('@')[1].split(':')[0]
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
SyncVMwareSharePointTags
|
||||
run as ndgov\svcitdiaassched
|
||||
run whether user is logged on or not
|
||||
run with highest privileges
|
||||
Triggers
|
||||
Daily, 10:15am, repeat every 8 hours
|
||||
Actions
|
||||
powershell.exe -file "D:\PowerShellTasks\SetVMTagAndMoveToAppNameFolder\SyncVMwareTagsFromSharePoint.ps1"
|
||||
"C:\Program Files\PowerShell\7\pwsh.exe" -file "F:\SyncVMwareTagsFromSharePoint\SyncVMwareTagsFromSharePointTask.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 3 days
|
||||
if the running task does not end when requested, force it to stop
|
||||
#>
|
||||
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d-%H%M%S"
|
||||
$TranscriptPath = "F:\SyncVMwareTagsFromSharePoint\Logs\SyncVMwareTagsFromSharePointTask-$Timestamp.log"
|
||||
Start-Transcript $TranscriptPath
|
||||
|
||||
|
||||
|
||||
try {
|
||||
#Sync-ITDVMwareSharePointTags -vCenterCredential $svcitdvmvcauto -SharePointCredential $svcitdiaassprw -Verbose
|
||||
|
||||
Connect-ITDvCenter -Credential $svcitdvmvcauto
|
||||
Sync-ITDVMwareSharePointTags -SharePointCredential $svcitdiaassprw -Verbose
|
||||
Disconnect-VIServer -Server * -Confirm:$false
|
||||
}
|
||||
catch {
|
||||
Send-MailMessage -To itdvctremailalerts@nd.gov -From itdvmvc1script@nd.gov -Subject "Task SyncVMwareTagsFromSharePoint errored" -Body "Task started $TimeStamp.`nCheck logs for further information" -SmtpServer apprelay1.nd.gov
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<# Scheduled Task metadata
|
||||
General
|
||||
Old-VMware Billing
|
||||
run as ndgov\!itdvcenterscript (required for SQL Database access)
|
||||
run whether user is logged on or not
|
||||
Triggers
|
||||
Daily, 5am
|
||||
Actions
|
||||
old-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file "C:\itdscript\vmconfig.ps1"
|
||||
new-"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\SyncVMwareVMsToSql\SyncVMwareVMsToSql.ps1"
|
||||
"C:\Program Files\PowerShell\7\pwsh.exe" -noninteractive -file "F:\SyncVMwareVMsToSql\SyncVMwareVMsToSql.ps1"
|
||||
|
||||
Settings
|
||||
allow task to be run on demand
|
||||
stop the task if it runs longer than 1 hour -eq $true
|
||||
if the running task does not end when requested, force it to stop
|
||||
|
||||
SQL Query to check for most recent 2500 records
|
||||
SELECT TOP (2500) [ServerName]
|
||||
,[SnapshotDate]
|
||||
,[VMName]
|
||||
,[Memory_MB]
|
||||
,[Num_VCPU]
|
||||
,[Disk_MB]
|
||||
,[ESXHostName]
|
||||
FROM [ITD-SRS-Billing].[dbo].[VMWare_VCenter_VMs]
|
||||
ORDER BY SnapshotDate DESC, VMName ASC
|
||||
|
||||
#>
|
||||
$Secret:!itdvcenterscript
|
||||
$TimeStamp = Get-Date -UFormat "%Y%m%d%H%M%S"
|
||||
Start-Transcript F:\SyncVMwareVMsToSql\Logs\SyncVMwareVMsToSql-$Timestamp.log
|
||||
|
||||
Set-PowerCLIConfiguration -DefaultVIServerMode multiple -Scope Session -Confirm:$false
|
||||
Connect-ITDvCenter
|
||||
|
||||
$Datacenters = Get-Datacenter | Where-Object {$_.Name -notlike "*Normandy*" -and $_.Name -notlike "*Vantis*"}
|
||||
$VMs = $Datacenters | Get-VM | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" -and $_.Name -notlike "itdzmtest*"} | Select Name, NumCPU, @{label="MemoryMB"; expression={$_.MemoryGB * 1024}}, @{label="HardDiskSizeGB"; expression={(Get-HardDisk -VM $_ | Measure-Object -Sum CapacityGB).Sum * 1024}}, VMHost | Sort-Object Name
|
||||
|
||||
|
||||
$SqlServer = "itdsql22p1.nd.gov\SQL22P1"
|
||||
$Database = "ITD-SRS-Billing"
|
||||
$Date = "'" + (Get-Date).ToString('yyyy/MM/dd') + "'"
|
||||
|
||||
# remove today's entries if already there
|
||||
Write-Verbose -Message "remove today's entries if already there"
|
||||
$SqlQuery = "delete from [VMware_VCenter_VMs] where snapshotdate = $Date;"
|
||||
Invoke-SQLCmd -ServerInstance $SqlServer -Database $Database -Query $SqlQuery
|
||||
|
||||
foreach($VM in $VMs) {
|
||||
Write-Verbose -Message ("Begin " + $VM.Name)
|
||||
$VMName = "'" + $VM.Name + "'"
|
||||
$VMMemoryMB = $VM.MemoryMB
|
||||
$VMNumCPU = $VM.NumCPU
|
||||
$VMHardDiskSizeGB = $VM.HardDiskSizeGB
|
||||
$VMHost = "'" + $VM.VMHost + "'"
|
||||
$SqlQuery ="INSERT INTO [VMware_VCenter_VMs] (ServerName, SnapshotDate, VMName, Memory_MB, Num_VCPU, Disk_MB, ESXHostName) Values ('None', $Date, $VMName, $VMMemoryMB, $VMNumCPU, $VMHardDiskSizeGB, $VMHost);"
|
||||
Invoke-SQLCmd -ServerInstance $SqlServer -Database $Database -Query $SqlQuery
|
||||
|
||||
}
|
||||
|
||||
Stop-Transcript
|
||||
Reference in New Issue
Block a user