update
This commit is contained in:
+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"
|
||||
}
|
||||
Reference in New Issue
Block a user