update
This commit is contained in:
+529
@@ -0,0 +1,529 @@
|
||||
<#
|
||||
### step 1
|
||||
gather specs
|
||||
provision virtual machine on hypervisor
|
||||
|
||||
final result:
|
||||
cpu configured, with hot-add
|
||||
memory configured, with hot-add
|
||||
disks 1, 2, and 3 attached with correct sizing
|
||||
network connected
|
||||
virtual machine powered on
|
||||
|
||||
update SCTASK Step 1 completed
|
||||
|
||||
### step 2 - customize Windows Guest OS
|
||||
wait for SCTASK Step 1 completed message
|
||||
configure
|
||||
time zone, mount points, page file, etc
|
||||
|
||||
update SCTASK Step 2 completed
|
||||
|
||||
### step 3 - administration
|
||||
wait for SCTASK Step 2 completed message
|
||||
domain join
|
||||
nd.gov at a minimum
|
||||
install sccm
|
||||
regardless if domain joined
|
||||
|
||||
update SCTASK Step 3 completed
|
||||
|
||||
### step 4 - validation
|
||||
|
||||
|
||||
confirm all agents are installed
|
||||
disks are present and formatted
|
||||
|
||||
#>
|
||||
|
||||
<#
|
||||
.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
|
||||
$NewITDWindowsVmVMwareParams = @{
|
||||
ComputerName = 'itdzmtest300.nd.gov';
|
||||
CPU = 2;
|
||||
MemoryGB = 8;
|
||||
DiskOsGB = 50;
|
||||
DiskSwapGB = 9;
|
||||
DiskDataGB = 20;
|
||||
Subnet = '10.11.12.0/23';
|
||||
OS = 'Windows Server 2022 Datacenter';
|
||||
Environment = "Test";
|
||||
Datacenter = "Bismarck";
|
||||
AppName = "ITD-POC-zmeier";
|
||||
StartupPriority = 4;
|
||||
LicensingRestrictions = "No Licensing Restrictions";
|
||||
Credential = $PrvCred;
|
||||
}
|
||||
|
||||
New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams
|
||||
#>
|
||||
|
||||
function New-ITDWindowsVmVMwareStep1 {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]
|
||||
$FQDN,
|
||||
|
||||
[int]
|
||||
$CPU,
|
||||
|
||||
[int]
|
||||
$MemoryGB,
|
||||
|
||||
[int]
|
||||
$DiskOsGB,
|
||||
|
||||
[int]
|
||||
$DiskSwapGB,
|
||||
|
||||
[int]
|
||||
$DiskDataGB,
|
||||
|
||||
[string]
|
||||
$Subnet,
|
||||
|
||||
[string]
|
||||
$OS,
|
||||
|
||||
[string]
|
||||
$VMEnvironment,
|
||||
|
||||
[string]
|
||||
$Datacenter,
|
||||
|
||||
[string]
|
||||
$AppName,
|
||||
|
||||
[int]
|
||||
$StartupPriority,
|
||||
|
||||
[string]
|
||||
$LicensingRestrictions,
|
||||
|
||||
[PSCredential]
|
||||
$Credential
|
||||
|
||||
)
|
||||
|
||||
begin {
|
||||
|
||||
}
|
||||
|
||||
process {
|
||||
$FQDN = $FQDN.ToLower()
|
||||
$HostName = $FQDN.split('.')[0]
|
||||
|
||||
If ($VMEnvironment -eq "Development") {
|
||||
$VMEnvironment = "Test"
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Prepare Credentials and Connections"
|
||||
$RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password))
|
||||
|
||||
Write-Verbose -Message "Infoblox: Find DNS pre-existing record, or create one"
|
||||
Write-Verbose -Message "FQDN: $FQDN" -Verbose
|
||||
Write-Verbose -Message "Hostname: $Hostname" -Verbose
|
||||
|
||||
Clear-DnsClientCache
|
||||
$InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred
|
||||
$Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd()
|
||||
[Net.IpAddress]$NetworkId = $Cidr.split('/')[0]
|
||||
#######
|
||||
####### Remove 10.10.10.10 references when DNS sync is fixed
|
||||
#######
|
||||
[Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue -Server 10.10.10.10).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 ($null -ne $IpAddress) {
|
||||
If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
|
||||
Write-Verbose -Message "DNS record already exists, CIDR Block match"
|
||||
}
|
||||
Else {
|
||||
Write-Error "DNS record already exists, but does not match CIDR Block"
|
||||
Break
|
||||
}
|
||||
}
|
||||
Else {
|
||||
Write-Verbose -Message "Pre-existing IP address not found, creating new DNS record."
|
||||
try {
|
||||
New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred
|
||||
Start-Sleep -Seconds 5
|
||||
Write-Verbose -Message ("FQDN is " + $FQDN)
|
||||
}
|
||||
catch {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#######
|
||||
####### Review this code after DNS problems resolved - 2024/09/24 zm
|
||||
#######
|
||||
####### [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction Stop -Server 10.10.10.10).IPAddress
|
||||
|
||||
[Net.IPAddress]$IpAddress = (Get-ITDIbDNSRecord -Hostname $FQDN -Credential $RadiusCred).IPv4Address
|
||||
|
||||
If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
|
||||
Write-Error "IP Address already in use." -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Passwordstate: If local administrator password does not exist in vault, create it."
|
||||
If ($FQDN -like "itdcnd*") {
|
||||
$PasswordStateList = "Peoplesoft Share PW"
|
||||
}
|
||||
Else {
|
||||
$PasswordStateList = "CSRC"
|
||||
}
|
||||
|
||||
$GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential
|
||||
If ($null -eq $GuestVMLocalCredential) {
|
||||
Write-Verbose -Message "Passwordstate: Local admin password record does not exist, creating new credentials"
|
||||
$GuestVMLocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $Credential
|
||||
}
|
||||
Else {
|
||||
Write-Verbose -Message "Passwordstate: Local admin password record already exists, use those credentials"
|
||||
}
|
||||
$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
|
||||
|
||||
Write-Verbose -Message "Decide VMware Cluster and Licensing"
|
||||
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 = "SQLe" }
|
||||
"Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "SQLa" }
|
||||
"IBM Websphere" { $ClusterRoot = "WAS" }
|
||||
"Powerschool" { $ClusterRoot = "PS" }
|
||||
"Pexip" { $ClusterRoot = "TEL" }
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Decide Datacenter"
|
||||
switch ($Datacenter) {
|
||||
"Bismarck" { $ClusterInt = 1 }
|
||||
"Mandan" { $ClusterInt = 2 }
|
||||
}
|
||||
|
||||
$Cluster = $ClusterRoot + $ClusterInt
|
||||
Write-Verbose -Message "VMware Cluster is $Cluster, gathering metadata for $Cluster"
|
||||
|
||||
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 = 'EagerZeroedThick'
|
||||
}
|
||||
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 = 'EagerZeroedThick'
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen"
|
||||
$DiskStorageFormat = 'Thin'
|
||||
}
|
||||
}
|
||||
"SQLa1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQLa1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQLa1_FS92_Gen"
|
||||
}
|
||||
"SQLa2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQLa2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQLa2_FS92_Gen"
|
||||
}
|
||||
"SQLe1" {
|
||||
$ViServer = 'itdvmvc1.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQLe1
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQLe1_FS92_Gen"
|
||||
}
|
||||
"SQLe2" {
|
||||
$ViServer = 'itdvmvc2.nd.gov'
|
||||
$ComputeCluster = Get-Cluster SQLe2
|
||||
$VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
|
||||
$DiskStorageFormat = 'EagerZeroedThick'
|
||||
$DatastoreCluster = Get-DatastoreCluster -Name "SQLe2_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
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Validate entered disk sizes"
|
||||
Write-Verbose -Message "DiskOsGB is $DiskOsGB. Validating its not a stupid number." -Verbose
|
||||
switch ($DiskOsGB) {
|
||||
{ $_ -lt 50 } {
|
||||
Write-Verbose -Message "DiskOsGB is 0 or below. Since an OS Disk is required, defaulting to 50GB" -Verbose
|
||||
$DiskOsGB = 50
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message "DiskSwapGB is $DiskSwapGB. Validating its not a stupid number." -Verbose
|
||||
switch ($DiskSwapGB) {
|
||||
{ $_ -le 0 } {
|
||||
Write-Verbose -Message "DiskSwapGB is zero or below. Since an Swap Disk is required, defaulting to `$Memory + 1GB." -Verbose
|
||||
$DiskSwapGB = ($MemoryGB + 1)
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message "DiskDataGB is $DiskDataGB. Validating its not a stupid number." -Verbose
|
||||
switch ($DiskDataGB) {
|
||||
{ $_ -le 0 } {
|
||||
Write-Verbose -Message "DiskDataGB is 0. Since an Data Disk is optional, data disk will not be created." -Verbose
|
||||
$DiskDataGB = 0
|
||||
}
|
||||
{ $_ -gt 500 } {
|
||||
Write-Verbose -Message "DiskDataGB is 500GB or more. DiskDataGB will be set to the maximum of 500GB." -Verbose
|
||||
$DiskDataGB = 500
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Determine Datastore / Datastore Cluster"
|
||||
$DiskTotal = $DiskOsGB + $DiskSwapGB + $DiskDataGB
|
||||
If ($DatastoreCluster) {
|
||||
}
|
||||
Else {
|
||||
$DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $ComputeCluster + "*")
|
||||
}
|
||||
$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"
|
||||
|
||||
Write-Verbose -Message "Determine VMware VM Template for OS: $OS"
|
||||
switch ($OS) {
|
||||
"Windows Server 2012R2 Standard" { $Template = "Windows Server 2012R2 Standard" }
|
||||
"Windows Server 2016 Standard" { $Template = "Windows Server 2016 Standard" }
|
||||
"Windows Server 2019" { $Template = "Windows Server 2019 Standard 1809.19" }
|
||||
"Windows Server 2019 Standard" { $Template = "Windows Server 2019 Standard 1809.19" }
|
||||
"Windows Server 2019 Datacenter" { $Template = "Windows Server 2019 Standard 1809.19" }
|
||||
"Windows Server 2022" { $Template = "Windows Server 2022 Standard 2108.21" }
|
||||
"Windows Server 2022 Datacenter" { $Template = "Windows Server 2022 Standard 2108.21" }
|
||||
"Windows Server 2025" { $Template = "Windows Server 2025 Standard 24H2.6" }
|
||||
Default { Write-Error "Invalid template option: $OS" -ErrorAction Stop }
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Determine VMware Port Group"
|
||||
$PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch
|
||||
$PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_*" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt)
|
||||
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
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Configure Guest OS Customization Spec"
|
||||
$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
|
||||
|
||||
Set-Location C:\Temp
|
||||
$NewVMParams = @{
|
||||
Name = $FQDN;
|
||||
ResourcePool = $ComputeCluster.Name;
|
||||
Datastore = $DatastoreCluster;
|
||||
DiskStorageFormat = $DiskStorageFormat;
|
||||
Location = $FolderLocation;
|
||||
# Removed when using Content Library
|
||||
#Template = $Template;
|
||||
#OSCustomizationSpec = $OSSpec
|
||||
}
|
||||
|
||||
Get-ContentLibraryItem -Name $Template -Server $ViServer | New-VM @NewVMParams
|
||||
$VM = Get-VM -Name $FQDN
|
||||
$VM | Set-VM -OSCustomizationSpec $OSSpec -Confirm:$false
|
||||
|
||||
Write-Verbose -Message "Set vCenter Tags on VM"
|
||||
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 $VMEnvironment) -Server $VIServer
|
||||
New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category LicensingRestrictions -Name $LicensingRestrictions) -Server $VIServer
|
||||
New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category StartupPriority -Name $StartupPriority) -Server $VIServer
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
|
||||
Write-Verbose -Message "Config and Update 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"
|
||||
|
||||
Write-Verbose -Message "Update Disk 1"
|
||||
$VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1"
|
||||
If ($VMDisk1.CapacityGB -lt $DiskOsGB) {
|
||||
Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $DiskOsGB -Confirm:$false
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Config Disk 2"
|
||||
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 $DiskSwapGB) {
|
||||
Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $DiskSwapGB -Confirm:$false
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Config Disk 3"
|
||||
If ($DiskDataGB -gt 0) {
|
||||
Write-Verbose -Message "$DiskDataGB greater than zero"
|
||||
If (!$VMDisk3) {
|
||||
$VM | New-HardDisk `
|
||||
-CapacityGB $DiskDataGB `
|
||||
-StorageFormat Thin `
|
||||
-DiskType Flat `
|
||||
-Persistence Persistent
|
||||
}
|
||||
$VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3"
|
||||
If ($VMDisk3.CapacityGB -lt $DiskDataGB) {
|
||||
Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $DiskDataGB -Confirm:$false
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Set VMware Tools Upgrade Policy to UpgradeAtPowerCycle"
|
||||
$VMView = $VM | Get-View
|
||||
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||
$vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
|
||||
$vmConfigSpec.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle"
|
||||
$VMView.ReconfigVM($vmConfigSpec)
|
||||
|
||||
Write-Verbose -Message "Power On VM"
|
||||
$VM | Start-VM
|
||||
|
||||
Write-Verbose -Message "[$FQDN]:Step 1 End"
|
||||
}
|
||||
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user