github.com/openshift/installer@v1.4.17/upi/vsphere/powercli/upi-functions.ps1 (about) 1 #!/usr/bin/pwsh 2 3 function New-OpenShiftVM { 4 param( 5 [Parameter(Mandatory=$true)] 6 $Datastore, 7 $FailureDomain, 8 [Parameter(Mandatory=$true)] 9 [string]$IgnitionData, 10 [switch]$LinkedClone, 11 $Location, 12 $MemoryMB, 13 [Parameter(Mandatory=$true)] 14 [string]$Name, 15 $Network, 16 $Networking, 17 $NumCpu, 18 $ReferenceSnapshot, 19 $ResourcePool, 20 $SecureBoot, 21 $StoragePolicy, 22 [Parameter(Mandatory=$true)] 23 $Tag, 24 [Parameter(Mandatory=$true)] 25 $Template, 26 $VMHost 27 ) 28 29 #Write-Output $IgnitionData 30 31 # Create arg collection for New-VM 32 $args = $PSBoundParameters 33 $args.Remove('Template') > $null 34 $args.Remove('IgnitionData') > $null 35 $args.Remove('Tag') > $null 36 $args.Remove('Networking') > $null 37 $args.Remove('Network') > $null 38 $args.Remove('MemoryMB') > $null 39 $args.Remove('NumCpu') > $null 40 $args.Remove('SecureBoot') > $null 41 foreach ($key in $args.Keys){ 42 if ($NULL -eq $($args.Item($key)) -or $($args.Item($key)) -eq "") { 43 $args.Remove($key) > $null 44 } 45 } 46 47 # If storage policy is set, lets pull the mo ref 48 if ($NULL -ne $StoragePolicy -and $StoragePolicy -ne "") 49 { 50 $storagePolicyRef = Get-SpbmStoragePolicy -Id $StoragePolicy 51 $args["StoragePolicy"] = $storagePolicyRef 52 } 53 54 # Clone the virtual machine from the imported template 55 # $vm = New-VM -VM $Template -Name $Name -Datastore $Datastore -ResourcePool $ResourcePool #-Location $Folder #-LinkedClone -ReferenceSnapshot $Snapshot 56 $vm = New-VM -VM $Template @args 57 58 # Assign tag so we can later clean up 59 New-TagAssignment -Entity $vm -Tag $Tag > $null 60 61 # Update VM specs. New-VM does not honor the passed in parameters due to Template being used. 62 if ($null -ne $MemoryMB -And $null -ne $NumCpu) 63 { 64 Set-VM -VM $vm -MemoryMB $MemoryMB -NumCpu $NumCpu -CoresPerSocket 4 -Confirm:$false > $null 65 } 66 #Get-HardDisk -VM $vm | Select-Object -First 1 | Set-HardDisk -CapacityGB 120 -Confirm:$false > $null 67 updateDisk -VM $vm -CapacityGB 120 68 69 # Configure Network (Assuming template networking may not be correct if shared across clusters) 70 $pg = Get-VirtualPortgroup -Name $Network -VMHost $(Get-VMHost -VM $vm) 2> $null 71 $vm | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $pg -confirm:$false > $null 72 73 # Assign advanced settings 74 New-AdvancedSetting -Entity $vm -name "disk.enableUUID" -value "TRUE" -confirm:$false -Force > $null 75 New-AdvancedSetting -Entity $vm -name "stealclock.enable" -value "TRUE" -confirm:$false -Force > $null 76 New-AdvancedSetting -Entity $vm -name "guestinfo.ignition.config.data.encoding" -value "base64" -confirm:$false -Force > $null 77 New-AdvancedSetting -Entity $vm -name "guestinfo.ignition.config.data" -value $IgnitionData -confirm:$false -Force > $null 78 New-AdvancedSetting -Entity $vm -name "guestinfo.hostname" -value $Name -Confirm:$false -Force > $null 79 80 # Create ip kargs 81 # "guestinfo.afterburn.initrd.network-kargs" = "ip=${var.ipaddress}::${cidrhost(var.machine_cidr, 1)}:${cidrnetmask(var.machine_cidr)}:${var.vmname}:ens192:none:${join(":", var.dns_addresses)}" 82 # Example: ip=<ip_address>::<gateway>:<netmask>:<hostname>:<iface>:<protocol>:<dns_address> 83 if ($null -ne $Networking) 84 { 85 $kargs = "ip=$($Networking.ipAddress)::$($Networking.gateway):$($Networking.netmask):$($Networking.hostname):ens192:none:$($Networking.dns)" 86 New-AdvancedSetting -Entity $vm -name "guestinfo.afterburn.initrd.network-kargs" -value $kargs -Confirm:$false -Force > $null 87 } 88 89 # Enable secure boot if needed 90 if ($true -eq $SecureBoot) 91 { 92 Set-SecureBoot -VM $vm 93 } 94 95 return $vm 96 } 97 98 # This function was created to work around issue in vSphere 8.0 where vCenter crashed 99 # when Set-HardDisk is called. 100 function updateDisk { 101 param ( 102 $CapacityGB, 103 $VM 104 ) 105 106 $newDiskSizeKB = $CapacityGB * 1024 * 1024 107 $newDiskSizeBytes = $newDiskSizeKB * 1024 108 109 $vmMo = get-view -id $VM.ExtensionData.MoRef 110 111 $devices = $vmMo.Config.Hardware.Device 112 113 $spec = New-Object VMware.Vim.VirtualMachineConfigSpec 114 $spec.DeviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1) 115 $spec.DeviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec 116 $spec.DeviceChange[0].Operation = 'edit' 117 118 foreach($d in $devices) { 119 if ($d.DeviceInfo.Label.Contains("Hard disk")) { 120 $spec.DeviceChange[0].Device = $d 121 } 122 } 123 124 $spec.DeviceChange[0].Device.CapacityInBytes = $newDiskSizeBytes 125 $spec.DeviceChange[0].Device.CapacityInKB = $newDiskSizeKB 126 127 $vmMo.ReconfigVM_Task($spec) > $null 128 } 129 130 function New-VMConfigs { 131 $virtualMachines = @" 132 { 133 "virtualmachines": {} 134 } 135 "@ | ConvertFrom-Json -Depth 2 136 $fds = ConvertFrom-Json $failure_domains 137 138 # Generate Bootstrap 139 $vm = createNode -FailureDomain $fds[0] -Type "bootstrap" -VCenter $vcenter -IPAddress $bootstrap_ip_address 140 add-member -Name "bootstrap" -value $vm -MemberType NoteProperty -InputObject $virtualMachines.virtualmachines 141 142 # Generate Control Plane 143 for (($i =0); $i -lt $control_plane_count; $i++) { 144 $vm = createNode -FailureDomain $fds[$i % $fds.Length] -Type "master" -VCenter $vcenter -IPAddress $control_plane_ip_addresses[$i] 145 add-member -Name $control_plane_hostnames[$i] -value $vm -MemberType NoteProperty -InputObject $virtualMachines.virtualmachines 146 } 147 148 # Generate Compute 149 for (($i =0); $i -lt $compute_count; $i++) { 150 $vm = createNode -FailureDomain $fds[$i % $fds.Length] -Type "worker" -VCenter $vcenter -IPAddress $compute_ip_addresses[$i] 151 add-member -Name $compute_hostnames[$i] -value $vm -MemberType NoteProperty -InputObject $virtualMachines.virtualmachines 152 } 153 154 return $virtualMachines | ConvertTo-Json 155 } 156 157 function createNode { 158 param ( 159 $FailureDomain, 160 $IPAddress, 161 $Type, 162 $VCenter 163 ) 164 165 $vmConfig = @" 166 { 167 "server": "$($VCenter)", 168 "datacenter": "$($FailureDomain. datacenter)", 169 "cluster": "$($FailureDomain.cluster)", 170 "network": "$($FailureDomain.network)", 171 "datastore": "$($FailureDomain.datastore)", 172 "type": "$($Type)", 173 "ip": "$($IPAddress)" 174 } 175 "@ 176 return ConvertFrom-Json -InputObject $vmConfig 177 } 178 179 function New-LoadBalancerIgnition { 180 param ( 181 [string]$sshKey 182 ) 183 184 $haproxyService = (Get-Content -Path ./lb/haproxy.service -Raw) | ConvertTo-Json 185 186 $api = $control_plane_ip_addresses + $bootstrap_ip_address 187 if ($compute_count -gt 0) 188 { 189 $ingress = $compute_ip_addresses 190 } else { 191 $ingress = $control_plane_ip_addresses 192 } 193 194 $Binding = @{ 'lb_ip_address' = $lb_ip_address; 'api' = $api; 'ingress' = $ingress } 195 $haproxyConfig = Invoke-EpsTemplate -Path "lb/haproxy.erb.tmpl" -Binding $Binding 196 197 $haproxyConfig = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($haproxyConfig)) 198 199 $lbIgnition = @" 200 { 201 "ignition": { "version": "3.0.0" }, 202 "passwd": { 203 "users": [ 204 { 205 "name": "core", 206 "sshAuthorizedKeys": [ 207 "$($sshKey)" 208 ] 209 } 210 ] 211 }, 212 "storage": { 213 "files": [{ 214 "path": "/etc/haproxy/haproxy.conf", 215 "mode": 420, 216 "contents": { "source": "data:text/plain;charset=utf-8;base64,$($haproxyConfig)" } 217 }] 218 }, 219 "systemd": { 220 "units": [{ 221 "name": "haproxy.service", 222 "enabled": true, 223 "contents": $($haproxyService) 224 }] 225 } 226 } 227 "@ 228 return $lbIgnition 229 } 230 231 function New-VMNetworkConfig { 232 param( 233 $DNS, 234 $Gateway, 235 $Hostname, 236 $IPAddress, 237 $Netmask 238 ) 239 $network = $null 240 241 $network = @" 242 { 243 "ipAddress": "$($IPAddress)", 244 "netmask": "$($Netmask)", 245 "dns": "$($DNS)", 246 "hostname": "$($Hostname)", 247 "gateway": "$($Gateway)" 248 } 249 "@ 250 return ConvertFrom-Json -InputObject $network 251 } 252 253 function New-OpenshiftVMs { 254 param( 255 $NodeType 256 ) 257 258 Write-Output "Creating $($NodeType) VMs" 259 260 $jobs = @() 261 $vmStep = (100 / $vmHash.virtualmachines.Count) 262 $vmCount = 1 263 foreach ($key in $vmHash.virtualmachines.Keys) { 264 $node = $vmHash.virtualmachines[$key] 265 266 if ($NodeType -ne $node.type) { 267 continue 268 } 269 270 $jobs += Start-ThreadJob -n "create-vm-$($metadata.infraID)-$($key)" -ScriptBlock { 271 param($key,$node,$vm_template,$metadata,$tag,$scriptdir,$cliContext) 272 . .\variables.ps1 273 . ${scriptdir}\upi-functions.ps1 274 Use-PowerCLIContext -PowerCLIContext $cliContext 275 276 $name = "$($metadata.infraID)-$($key)" 277 Write-Output "Creating $($name)" 278 279 $rp = Get-ResourcePool -Name $($metadata.infraID) -Location $(Get-Cluster -Name $($node.cluster)) -Server $vcenter 280 ##$datastore = Get-Datastore -Name $node.datastore -Server $node.server 281 $datastoreInfo = Get-Datastore -Name $node.datastore -Location $node.datacenter 282 283 # Pull network config for each node 284 if ($node.type -eq "master") { 285 $numCPU = $control_plane_num_cpus 286 $memory = $control_plane_memory 287 } elseif ($node.type -eq "worker") { 288 $numCPU = $compute_num_cpus 289 $memory = $compute_memory 290 } else { 291 # should only be bootstrap 292 $numCPU = $control_plane_num_cpus 293 $memory = $control_plane_memory 294 } 295 $ip = $node.ip 296 $network = New-VMNetworkConfig -Hostname $name -IPAddress $ip -Netmask $netmask -Gateway $gateway -DNS $dns 297 298 # Get the content of the ignition file per machine type (bootstrap, master, worker) 299 $bytes = Get-Content -Path "./$($node.type).ign" -AsByteStream 300 $ignition = [Convert]::ToBase64String($bytes) 301 302 # Get correct template / folder 303 $folder = Get-Folder -Name $clustername -Location $node.datacenter 304 $template = Get-VM -Name $vm_template -Location $($node.datacenter) 305 306 # Clone the virtual machine from the imported template 307 #$vm = New-OpenShiftVM -Template $template -Name $name -ResourcePool $rp -Datastore $datastoreInfo -Location $folder -LinkedClone -ReferenceSnapshot $snapshot -IgnitionData $ignition -Tag $tag -Networking $network -NumCPU $numCPU -MemoryMB $memory 308 $vm = New-OpenShiftVM -Template $template -Name $name -ResourcePool $rp -Datastore $datastoreInfo -Location $folder -IgnitionData $ignition -Tag $tag -Networking $network -Network $node.network -SecureBoot $secureboot -StoragePolicy $storagepolicy -NumCPU $numCPU -MemoryMB $memory 309 310 # Assign tag so we can later clean up 311 # New-TagAssignment -Entity $vm -Tag $tag 312 # New-AdvancedSetting -Entity $vm -name "guestinfo.ignition.config.data" -value $ignition -confirm:$false -Force > $null 313 # New-AdvancedSetting -Entity $vm -name "guestinfo.hostname" -value $name -Confirm:$false -Force > $null 314 315 if ($node.type -eq "master" -And $delayVMStart) { 316 # To give bootstrap some time to start, lets wait 2 minutes 317 Start-ThreadJob -ThrottleLimit 5 -InputObject $vm { 318 Start-Sleep -Seconds 90 319 $input | Start-VM 320 } 321 } elseif ($node.type -eq "worker" -And $delayVMStart) { 322 # Workers are not needed right away, gotta wait till masters 323 # have started machine-server. wait 7 minutes to start. 324 Start-ThreadJob -ThrottleLimit 5 -InputObject $vm { 325 Start-Sleep -Seconds 600 326 $input | Start-VM 327 } 328 } 329 else { 330 $vm | Start-VM 331 } 332 } -ArgumentList @($key,$node,$vm_template,$metadata,$tag,$SCRIPTDIR,$cliContext) 333 Write-Progress -id 222 -Activity "Creating virtual machines" -PercentComplete ($vmStep * $vmCount) 334 $vmCount++ 335 } 336 Wait-Job -Job $jobs 337 foreach ($job in $jobs) { 338 Receive-Job -Job $job 339 } 340 } 341 342 # This function is used to set secure boot. 343 function Set-SecureBoot { 344 param( 345 $VM 346 ) 347 348 $spec = New-Object VMware.Vim.VirtualMachineConfigSpec 349 $spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi 350 351 $boot = New-Object VMware.Vim.VirtualMachineBootOptions 352 $boot.EfiSecureBootEnabled = $true 353 354 $spec.BootOptions = $boot 355 356 $VM.ExtensionData.ReconfigVM($spec) 357 }