From 415d6d2d953ed21f7241e880a43c78ab80dad252 Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 09:20:33 +0100 Subject: [PATCH 1/9] Update Move-ClusterHostNetworkingTovSS Update customfields logic for VCF.PowerCli Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 151a813..4f90d9a 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -3407,7 +3407,8 @@ Function Move-ClusterHostNetworkingTovSS { New-CustomAttribute -Name vdsConfiguration -TargetType Cluster | Out-Null } - $storedVdsConfiguration = (((Get-Cluster).customfields | Where-Object { $_.key -eq "vdsConfiguration" }).value) | ConvertFrom-Json + $index = [System.Array]::IndexOf((Get-Cluster).customfields.keys, "vdsConfiguration") + $storedVdsConfiguration = @((Get-Cluster).customfields.values)[$index] | ConvertFrom-Json If (!$storedVdsConfiguration) { $clustervdsConfiguration = @() Foreach ($vds in $clusterVdswitchNames) { From de05595ee414e7137f9e7a0315051de5c98bde7d Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 11:25:54 +0100 Subject: [PATCH 2/9] Update New-NSXManagerOvaDeployment Update New-NSXManagerOvaDeployment to handle temp cluster name Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 4f90d9a..6552240 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -2363,12 +2363,17 @@ Function New-NSXManagerOvaDeployment { $vmDatastore = $extractedSDDCData.mgmtDomainInfrastructure.vsan_datastore #Following parameters converted to known entities for 9.0. Consider refactoring in 9.1 if data is saved in manifest.json - #$vmNetwork = $extractedSDDCData.mgmtDomainInfrastructure.port_group - $vmNetwork = "vcfir-cl01-vds01-pg-vm-mgmt" - #$datacenterName = $extractedSDDCData.mgmtDomainInfrastructure.datacenter - $datacenterName = "vcfir-dc01" - #$clusterName = $extractedSDDCData.mgmtDomainInfrastructure.cluster - $clusterName = "vcfir-cl01" + if (!$extractedSDDCData.mgmtDomainInfrastructure.cluster) { + $vmNetwork = "vcfir-cl01-vds01-pg-vm-mgmt" + $datacenterName = "vcfir-dc01" + $clusterName = "vcfir-cl01" + } else { + $vmNetwork = $extractedSDDCData.mgmtDomainInfrastructure.port_group + $datacenterName = $extractedSDDCData.mgmtDomainInfrastructure.datacenter + $clusterName = $extractedSDDCData.mgmtDomainInfrastructure.cluster + } + + # NSX Manager Appliance Configuration $nsxManagerVMName = $selectedNsxManager.vmName From 16462c772b473cd3e548e1a3f6645a35c013be8e Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 11:34:13 +0100 Subject: [PATCH 3/9] Update VMware.CloudFoundation.InstanceRecovery.psm1 Update example values for OVA filenames Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 6552240..fe8693d 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -2294,7 +2294,7 @@ Function New-NSXManagerOvaDeployment { The New-NSXManagerOvaDeployment resents a list of NSX Mangers associated with the provided VCF Workload Domain, and deploys an NSX Manager from OVA using data previously extracted from the VCF SDDC Manager Backup .EXAMPLE - New-NSXManagerOvaDeployment -tempvCenterFqdn "sfo-m01-vc02.sfo.rainpole.io" -tempvCenterAdmin "administrator@vsphere.local" -tempvCenterAdminPassword "VMw@re1!" -extractedSDDCDataFile ".\extracted-sddc-data.json" -workloadDomain "sfo-m01" -restoredNsxManagerDeploymentSize medium -nsxManagerOvaFile "F:\OVA\nsx-unified-appliance-3.2.2.1.0.21487565.ova" + New-NSXManagerOvaDeployment -tempvCenterFqdn "sfo-m01-vc02.sfo.rainpole.io" -tempvCenterAdmin "administrator@vsphere.local" -tempvCenterAdminPassword "VMw@re1!" -extractedSDDCDataFile ".\extracted-sddc-data.json" -workloadDomain "sfo-m01" -restoredNsxManagerDeploymentSize medium -nsxManagerOvaFile "F:\OVA\nsx-unified-appliance-9.0.0.0.24733065.ova" .PARAMETER vCenterFqdn FQDN of the target vCenter to deploy the NSX Manager OVA to @@ -2434,7 +2434,7 @@ Function New-vCenterOvaDeployment { The New-vCenterOvaDeployment deploys a vCenter appliance from OVA using data previously extracted from the VCF SDDC Manager Backup .EXAMPLE - New-vCenterOvaDeployment -tempvCenterFqdn "sfo-m01-vc02.sfo.rainpole.io" -tempvCenterAdmin "administrator@vsphere.local" -tempvCenterAdminPassword "VMw@re1!" -extractedSDDCDataFile ".\extracted-sddc-data.json" -workloadDomain "sfo-m01" -restoredvCenterDeploymentSize "small" -vCenterOvaFile "F:\OVA\VMware-vCenter-Server-Appliance-7.0.3.01400-21477706_OVF10.ova" + New-vCenterOvaDeployment -tempvCenterFqdn "sfo-m01-vc02.sfo.rainpole.io" -tempvCenterAdmin "administrator@vsphere.local" -tempvCenterAdminPassword "VMw@re1!" -extractedSDDCDataFile ".\extracted-sddc-data.json" -workloadDomain "sfo-m01" -restoredvCenterDeploymentSize "small" -vCenterOvaFile "F:\OVA\VMware-vCenter-Server-Appliance-9.0.0.0.24755230_OVF10.ova" .PARAMETER vCenterFqdn FQDN of the target vCenter to deploy the vCenter OVA to From a53728248b3f06a1549d9450575f934902faa92b Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 11:43:53 +0100 Subject: [PATCH 4/9] Removing legacy code Removing legacy & deprecated code/functions Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 254 +------------------ 1 file changed, 3 insertions(+), 251 deletions(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index fe8693d..f44798e 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -282,24 +282,12 @@ Function Confirm-VCFInstanceRecoveryPreReqs { LogMessage -type INFO -message "[$jumpboxName] Posh-SSH Module found" } - $isPowerCLIInstalled = Get-InstalledModule -name "VMware.PowerCLI" -ErrorAction SilentlyContinue + $isPowerCLIInstalled = Get-InstalledModule -name "VCF.PowerCLI" -ErrorAction SilentlyContinue If (!$isPowerCLIInstalled) { - LogMessage -type WARNING -message "[$jumpboxName] PowerCLI Module Missing. Please install" + LogMessage -type WARNING -message "[$jumpboxName] VCF PowerCLI Module Missing. Please install" } else { LogMessage -type INFO -message "[$jumpboxName] PowerCLI Module found" } - $isPowerCLISddcmModuleInstalled = Get-InstalledModule -name "VMware.Sdk.Vcf.SddcManager" -RequiredVersion "5.1.0" -ErrorAction SilentlyContinue - If (!$isPowerCLISddcmModuleInstalled) { - LogMessage -type WARNING -message "[$jumpboxName] VMware.Sdk.Vcf.SddcManager Module Missing. Please install" - } else { - LogMessage -type INFO -message "[$jumpboxName] VMware.Sdk.Vcf.SddcManager Module found" - } - $isPowerCLICloudBuilderModuleInstalled = Get-InstalledModule -name "VMware.Sdk.Vcf.CloudBuilder" -RequiredVersion "5.1.0" -ErrorAction SilentlyContinue - If (!$isPowerCLICloudBuilderModuleInstalled) { - LogMessage -type WARNING -message "[$jumpboxName] VMware.Sdk.Vcf.CloudBuilder Module Missing. Please install" - } else { - LogMessage -type INFO -message "[$jumpboxName] VMware.Sdk.Vcf.CloudBuilder Module found" - } $installedSoftware = Get-InstalledSoftware If (!($installedSoftware -match "OpenSSL")) { @@ -2532,7 +2520,7 @@ Function New-SDDCManagerOvaDeployment { The New-SDDCManagerOvaDeployment deploys an SDDC Manager appliance from OVA using data previously extracted from the VCF SDDC Manager Backup .EXAMPLE - New-SDDCManagerOvaDeployment -tempvCenterFqdn "sfo-m01-vc02.sfo.rainpole.io" -tempvCenterAdmin "administrator@vsphere.local" -tempvCenterAdminPassword "VMw@re1!" -extractedSDDCDataFile ".\extracted-sddc-data.json" -sddcManagerOvaFile "F:\OVA\VCF-SDDC-Manager-Appliance-4.5.1.0-21682411.ova" -rootUserPassword "VMw@re1!" -vcfUserPassword "VMw@re1!" -localUserPassword "VMw@re1!VMw@re1!" -basicAuthUserPassword "VMw@re1!" + New-SDDCManagerOvaDeployment -tempvCenterFqdn "sfo-m01-vc02.sfo.rainpole.io" -tempvCenterAdmin "administrator@vsphere.local" -tempvCenterAdminPassword "VMw@re1!" -extractedSDDCDataFile ".\extracted-sddc-data.json" -sddcManagerOvaFile "F:\OVA\VCF-SDDC-Manager-Appliance-9.0.0.0.24703748.ova" -rootUserPassword "VMw@re1!" -vcfUserPassword "VMw@re1!" -localUserPassword "VMw@re1!VMw@re1!" -basicAuthUserPassword "VMw@re1!" .PARAMETER vCenterFqdn FQDN of the target vCenter to deploy the SDDC Manager OVA to @@ -5661,18 +5649,6 @@ Function Add-AdditionalNSXManagers { } Until ($sshSession) $stream = New-SSHShellStream -SSHSession $sshSession - <# - If ($nsxManagerVersion -lt "400") - { - LogMessage -type INFO -message "[$nsxManagerFQDN] Deactivating Cluster" - $unwantedOutput = $stream.Read() - $stream.writeline("deactivate cluster") - Start-Sleep 5 - $stream.writeline("yes") - Start-Sleep 2 - } - #> - LogMessage -type INFO -message "[$nsxManagerFQDN] Getting Cluster ID" $unwantedOutput = $stream.Read() Start-Sleep 2 @@ -5694,18 +5670,6 @@ Function Add-AdditionalNSXManagers { $certApiThumbprint = $stream.Readline() LogMessage -type INFO -message "[$nsxManagerFQDN] Cert Thumbprint: $certApiThumbprint retrieved" - <# - If ($nsxManagerVersion -lt "400") - { - Foreach ($otherclusterNodeID in $otherclusterNodeIDs) - { - $unwantedOutput = $stream.Read() - Start-Sleep 2 - $stream.writeline("detach node $otherclusterNodeID") - #Need to undersand how to monitor here - } - } - #> #Close SSH Session Remove-SSHSession -SSHSession $sshSession | Out-Null @@ -5753,31 +5717,6 @@ Function Add-AdditionalNSXManagers { #Close SSH Session Remove-SSHSession -SSHSession $sshSession | Out-Null - - <# - If ($nsxManagerVersion -lt "400") - { - #Restore Certificate on Manager - $clusterNodeID = ($clusterNodes | Where-Object {$_.fqdn -eq $nsxManagerFQDN}).node_uuid - $clusterNodeCertificateID = ($signedCertificates | Where-Object {$_.tags.scope -eq $otherNsxManager.ip}).id - - LogMessage -type INFO -message "[$nsxManagerFQDN] Setting Node Certificate" - $uri = "https://$nsxManagerFQDN/api/v1/node/services/http?action=apply_certificate&certificate_id=$clusterNodeCertificateID" - $setCertificate = Invoke-WebRequest -Method POST -URI $uri -ContentType application/json -headers $headers - - $managementDomain = ($extractedSddcData.workloadDomains | Where-Object {$_.domainType -eq "MANAGEMENT"}) - $managementDomainName = ($extractedSddcData.workloadDomains | Where-Object {$_.domainType -eq "MANAGEMENT"}).domainName - $vCenterFqdn = $managementDomain.vCenterDetails.fqdn - $vCenterAdmin = ($extractedSddcData.passwords | Where-Object {($_.entityType -eq "PSC") -and ($_.domainName -eq $managementDomainName)}).username - $vCenterAdminPassword = ($extractedSddcData.passwords | Where-Object {($_.entityType -eq "PSC") -and ($_.domainName -eq $managementDomainName)}).password - - #Restart Manager - $vCenterConnection = Connect-VIServer $vCenterFqdn -user $vCenterAdmin -password $vCenterAdminPassword - LogMessage -type INFO -message "[$nsxManagerFQDN] Restarting Appliance" - Get-VM -Name $nsxManagerFQDN | Restart-VM -confirm:$false | Out-Null - Disconnect-VIServer -Server $global:DefaultVIServers -Force -Confirm:$false - } - #> } } else { LogMessage -type ERROR -message "[$jumpboxName] Unable to determine NSX Manager Version. Check that it was successfully restored." @@ -5788,192 +5727,5 @@ Export-ModuleMember -Function Add-AdditionalNSXManagers #EndRegion NSXT Functions #Region Marked for Deprecation -Function Resolve-PhysicalHostTransportNodes { - <# - .SYNOPSIS - Resolves the state of ESXi Transport Nodes in a restored NSX Manager when the ESXi hosts have been rebuilt - - .DESCRIPTION - The Resolve-PhysicalHostTransportNodes cmdlet resolves the state of ESXi Transport Nodes in a restored NSX Manager when the ESXi hosts have been rebuilt - - .EXAMPLE - Resolve-PhysicalHostTransportNodes -vCenterFQDN "sfo-m01-vc01.sfo.rainpole.io" -vCenterAdmin "administrator@vsphere.local" -vCenterAdminPassword "VMw@re1!" -clusterName "sfo-m01-cl01" -NsxManagerFQDN "sfo-m01-nsx01a.sfo.rainpole.io" -NsxManagerAdmin "admin" -NsxManagerAdminPassword "VMw@re1!VMw@re1!" - - .PARAMETER vCenterFQDN - FQDN of the vCenter instance that hosts the cluster whose hosts need to be resolved - - .PARAMETER vCenterAdmin - Admin user of the vCenter instance that hosts the cluster whose hosts need to be resolved - - .PARAMETER vCenterAdminPassword - Admin password for the vCenter instance that hosts the cluster whose hosts need to be resolved - - .PARAMETER clusterName - Name of the vSphere cluster instance whose hosts need to be resolved - - .PARAMETER nsxManagerFqdn - FQDN of the NSX Manager where hosts need to be resolved - - .PARAMETER nsxManagerAdmin - Admin user of the NSX Manager where hosts need to be resolved - - .PARAMETER nsxManagerAdminPassword - Admin Password of the NSX Manager where hosts need to be resolved - #> - - Param( - [Parameter (Mandatory = $true)][String] $vCenterFQDN, - [Parameter (Mandatory = $true)][String] $vCenterAdmin, - [Parameter (Mandatory = $true)][String] $vCenterAdminPassword, - [Parameter (Mandatory = $true)][String] $clusterName, - [Parameter (Mandatory = $true)][String] $nsxManagerFqdn, - [Parameter (Mandatory = $true)][String] $nsxManagerAdmin, - [Parameter (Mandatory = $true)][String] $nsxManagerAdminPassword - ) - $jumpboxName = hostname - LogMessage -type NOTE -message "[$jumpboxName] Starting Task $($MyInvocation.MyCommand)" - LogMessage -type INFO -message "[$jumpboxName] Checking NSX Manager Version" - - $headers = VCFIRCreateHeader -username $nsxManagerAdmin -password $nsxManagerAdminPassword - - #Check for Compatible NSX Manager version - $uri = "https://$nsxManagerFqdn/api/v1/node" - $nsxManagerVersion = [INT](((((Invoke-WebRequest -Method GET -URI $uri -ContentType application/json -headers $headers).content | ConvertFrom-Json).product_version).replace(".", "")).substring(0, 3)) - - If ($nsxManagerVersion) { - If ($nsxManagerVersion -lt "412") { - $vCenterConnection = Connect-VIServer -server $vCenterFQDN -username $vCenterAdmin -password $vCenterAdminPassword - LogMessage -type INFO -message "[$clusterName] Getting Hosts" - $clusterHosts = (Get-Cluster -name $clusterName | Get-VMHost).name - #LogMessage -type INFO -message "[$clusterName] Getting MoRef" - #$clusterMoRef = (Get-Cluster -name $clusterName).ExtensionData.MoRef.Value - - #Get TransportNodes - $uri = "https://$nsxManagerFqdn/api/v1/transport-nodes/" - LogMessage -type INFO -message "[$nsxManagerFqdn] Getting Transport Nodes" - $transportNodeContents = (Invoke-WebRequest -Method GET -URI $uri -ContentType application/json -headers $headers).content | ConvertFrom-Json - $allHostTransportNodes = ($transportNodeContents.results | Where-Object { ($_.resource_type -eq "TransportNode") -and ($_.node_deployment_info.os_type -eq "ESXI") }) - LogMessage -type INFO -message "[$nsxManagerFqdn] Filtering Transport Nodes to members of cluster $clusterName" - $hostIDs = ($allHostTransportNodes | Where-Object { $_.display_name -in $clusterHosts }).id - - #Get TransportNodes - <# $uri = "https://$nsxManagerFqdn/api/v1/fabric/compute-collections" - LogMessage -type INFO -message "[$nsxManagerFqdn] Getting Transport Nodes IDs" - $computeCollections = (Invoke-WebRequest -Method GET -URI $uri -ContentType application/json -headers $headers).content | ConvertFrom-Json - $clusterExternalId = ($computeCollections.results | Where-Object {$_.cm_local_id -eq $clusterMoRef}).external_id - $uri = "https://$nsxManagerFqdn/api/v1/fabric/compute-collections/$clusterExternalId/member-status" - $hostIDs = ((Invoke-WebRequest -Method GET -URI $uri -ContentType application/json -headers $headers).content | ConvertFrom-Json).results.node_id - #> - #Resolve Hosts - Foreach ($hostID in $hostIDs) { - $body = "{`"id`":5726703,`"method`":`"resolveError`",`"params`":[{`"errors`":[{`"user_metadata`":{`"user_input_list`":[]},`"error_id`":26080,`"entity_id`":`"$hostID`"}]}]}" - $uri = "https://$nsxManagerFqdn/nsxapi/rpc/call/ErrorResolverFacade" - LogMessage -type INFO -message "[$nsxManagerFqdn] Resolving NSX Installation on $(($allHostTransportNodes | Where-Object {$_.id -eq $hostID}).display_name)" - #LogMessage -type INFO -message "[$nsxManagerFqdn] Resolving NSX Installation on $hostID" - $response = Invoke-WebRequest -Method POST -URI $uri -ContentType application/json -headers $headers -body $body - } - } else { - LogMessage -type NOTE -message "[$jumpboxName] This cmdlet is not required with NSX Manager version 4.1.2 and later" - } - - } else { - LogMessage -type ERROR -message "[$jumpboxName] Unable to determine NSX Manager Version. Check that it was successfully restored." - } - LogMessage -type NOTE -message "[$jumpboxName] Completed Task $($MyInvocation.MyCommand)" -} -#Export-ModuleMember -Function Resolve-PhysicalHostTransportNodes - -Function Move-ClusterVMsToFirstHost { - <# - .SYNOPSIS - Moves all VMs in a cluster to a single ESXi host - - .DESCRIPTION - The Move-ClusterVMsToFirstHost cmdlet moves all VMs in a cluster to a single ESXi host - - .EXAMPLE - Move-ClusterVMsToFirstHost -vCenterFQDN "sfo-m01-vc02.sfo.rainpole.io" -vCenterAdmin "administrator@vsphere.local" -vCenterAdminPassword "VMw@re1!" -clusterName "sfo-m01-cl01" - - .PARAMETER vCenterFQDN - FQDN of the vCenter instance hosting the VMs to be moved - - .PARAMETER vCenterAdmin - Admin user of the vCenter instance hosting the VMs to be moved - - .PARAMETER vCenterAdminPassword - Admin password for the vCenter instance hosting the VMs to be moved - - .PARAMETER clusterName - Name of the vSphere cluster instance hosting the VMs to be moved - #> - - Param( - [Parameter (Mandatory = $true)][String] $vCenterFQDN, - [Parameter (Mandatory = $true)][String] $vCenterAdmin, - [Parameter (Mandatory = $true)][String] $vCenterAdminPassword, - [Parameter (Mandatory = $true)][String] $clusterName - - ) - $jumpboxName = hostname - LogMessage -type NOTE -message "[$jumpboxName] Starting Task $($MyInvocation.MyCommand)" - $vCenterConnection = connect-viserver $vCenterFQDN -user $vCenterAdmin -password $vCenterAdminPassword - $vms = Get-Cluster -Name $clusterName | Get-VM | Where-Object { $_.Name -notlike "vCLS*" } | Select-Object Name, VMhost - $firstHost = ((Get-cluster -name $clusterName | Get-VMHost | Sort-Object -property Name)[0]).Name - Foreach ($vm in $vms) { - if ($vm.vmHost.Name -ne $firstHost) { - Get-VM -Name $vm.name | Move-VM -Location $firstHost -Runasync | Out-Null - LogMessage -type INFO -message "[$($vm.name)] Moving to $firstHost" - } - } - Do { - $runningTasks = Get-Task | Where-Object { ($_.Name -eq "RelocateVM_Task") -and ($_.State -eq "running") } - Sleep 5 - } Until (!$runningTasks) - Disconnect-VIServer -Server $global:DefaultVIServers -Force -Confirm:$false - LogMessage -type NOTE -message "[$jumpboxName] Completed Task $($MyInvocation.MyCommand)" -} -#Export-ModuleMember -Function Move-ClusterVMsToFirstHost -Function Remove-StandardSwitch { - <# - .SYNOPSIS - Removes a temporary standard switch from all hosts in a cluster - - .DESCRIPTION - The Remove-StandardSwitch cmdlet removes a temporary standard switch from all hosts in a cluster - - .EXAMPLE - Remove-StandardSwitch -vCenterFQDN "sfo-m01-vc01.sfo.rainpole.io" -vCenterAdmin "administrator@vsphere.local" -vCenterAdminPassword "VMw@re1!" -clusterName "sfo-m01-cl01" - - .PARAMETER vCenterFQDN - FQDN of the vCenter instance hosting the ESXi hosts from which the standard switch will be removed - - .PARAMETER vCenterAdmin - Admin user of the vCenter instance hosting the ESXi hosts from which the standard switch will be removed - - .PARAMETER vCenterAdminPassword - Admin password for the vCenter instance hosting the ESXi hosts from which the standard switch will be removed - - .PARAMETER clusterName - Name of the vSphere cluster instance hosting the ESXi hosts from which the standard switch will be removed - #> - - Param( - [Parameter (Mandatory = $true)][String] $vCenterFQDN, - [Parameter (Mandatory = $true)][String] $vCenterAdmin, - [Parameter (Mandatory = $true)][String] $vCenterAdminPassword, - [Parameter (Mandatory = $true)][String] $clusterName - ) - $jumpboxName = hostname - LogMessage -type NOTE -message "[$jumpboxName] Starting Task $($MyInvocation.MyCommand)" - $vCenterConnection = connect-viserver $vCenterFQDN -user $vCenterAdmin -password $vCenterAdminPassword - $vmHosts = (Get-cluster -name $clusterName | Get-VMHost).Name | Sort-Object - foreach ($vmhost in $vmHosts) { - LogMessage -type INFO -message "[$vmhost] Removing standard vSwitch" - Get-VMHost -Name $vmhost | Get-VirtualSwitch -Name "vSwitch0" | Remove-VirtualSwitch -Confirm:$false | Out-Null - } - Disconnect-VIServer -Server $global:DefaultVIServers -Force -Confirm:$false - LogMessage -type NOTE -message "[$jumpboxName] Completed Task $($MyInvocation.MyCommand)" -} -#Export-ModuleMember -Function Remove-StandardSwitch #EndRegion Marked for Deprecation From da1141e4365de1247021f847d6c315de90fe4d8e Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 11:50:15 +0100 Subject: [PATCH 5/9] Removing legacy code Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 35 ++++---------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index f44798e..2709a03 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -557,17 +557,10 @@ Function New-ExtractDataFromSDDCBackup { $lineContent = $psqlContent | Select-Object -Index $vCentersStartingLineNumber If ($lineContent -ne '\.') { $vCenterID = $lineContent.split("`t")[0] - If ($sddcManagerObject.version -like "4.4.*") { - $vCenterVersion = $lineContent.split("`t")[10] - $vCenterFqdn = $lineContent.split("`t")[11] - $vCenterIp = $lineContent.split("`t")[12] - $vCenterVMname = $lineContent.split("`t")[13] - } else { - $vCenterVersion = $lineContent.split("`t")[9] - $vCenterFqdn = $lineContent.split("`t")[10] - $vCenterIp = (Resolve-DnsName $vCenterFqdn).IPAddress - $vCenterVMname = $lineContent.split("`t")[12] - } + $vCenterVersion = $lineContent.split("`t")[9] + $vCenterFqdn = $lineContent.split("`t")[10] + $vCenterIp = (Resolve-DnsName $vCenterFqdn).IPAddress + $vCenterVMname = $lineContent.split("`t")[12] $vCenterDomainID = ($hostsAndDomains | Where-Object { $_.hostId -eq (($hostsandVcenters | Where-Object { $_.vCenterID -eq $vCenterID })[0].hostID) }).domainID $vCenters += [pscustomobject]@{ 'vCenterID' = $vCenterID @@ -986,11 +979,7 @@ Function New-ExtractDataFromSDDCBackup { $domainName = $lineContent.split("`t")[3] $domainType = $lineContent.split("`t")[6] $vCenter = $vCenters | Where-Object { $_.vCenterDomainID -eq $domainId } - If ($sddcManagerObject.version -like "4.4.*") { - $ssoDomain = ($pscs | Where-Object { $_.id -eq (($vCentersAndPscs | Where-Object { $_.vcenterId -eq $vcenter.vCenterID }).pscId) }).ssoDomain - } else { - $ssoDomain = $lineContent.split("`t")[11] - } + $ssoDomain = $lineContent.split("`t")[11] $vCenterDetails = [pscustomobject]@{ 'id' = $vCenter.vCenterID 'version' = $vCenter.vCenterVersion @@ -1012,18 +1001,7 @@ Function New-ExtractDataFromSDDCBackup { $vmotionNetwork = $networks | Where-Object { ($_.type -eq "VMOTION") -and ($_.id -in $domainNetworks) } $vsanNetwork = $networks | Where-Object { ($_.type -eq "VSAN") -and ($_.id -in $domainNetworks) } - <# - $mgmtNetworkDetails = @() - $mgmtNetworkDetails += [pscustomobject]@{ #Review - 'type' = "MANAGEMENT" - 'subnet_mask' = $metaDataJSON.netmask - 'subnet' = $managementSubnet - 'mtu' = "1500" # Review - 'vlanID' = ($virtualDistributedSwitches.portgroups | Where-Object { $_.name -eq $metadataJSON.port_group }).vlanId - 'gateway' = $metaDataJSON.gateway - 'portgroupKey' = $metadataJSON.port_group - } - #> + $nsxClusterDetailsObject = New-Object -type psobject $nsxClusterDetailsObject | Add-Member -NotePropertyName 'clusterVip' -NotePropertyValue ($nsxtManagerClusters | Where-Object { $_.domainIDs -contains $domainId }).clusterVip $nsxClusterDetailsObject | Add-Member -NotePropertyName 'clusterFqdn' -NotePropertyValue ($nsxtManagerClusters | Where-Object { $_.domainIDs -contains $domainId }).clusterFqdn @@ -1044,7 +1022,6 @@ Function New-ExtractDataFromSDDCBackup { 'ssoDomain' = $ssoDomain 'networkPool' = $poolName 'vCenterDetails' = $vCenterDetails - #'mgmtNetworkDetails' = $mgmtNetworkDetails 'nsxClusterDetails' = $nsxClusterDetailsObject 'nsxNodeDetails' = ($nsxtManagerClusters | Where-Object { $_.domainIDs -contains $domainId }).nsxNodes 'vsphereClusterDetails' = @($clusters | Where-Object { $_.vCenterID -eq $vcenterDetails.id }) From c0dff250eb77eb23d3791e8793c0aaa84fcce6a1 Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 12:05:59 +0100 Subject: [PATCH 6/9] Housekeeping Updating versions Signed-off-by: Brian O'Connell --- CHANGELOG.md | 31 +---- VMware.CloudFoundation.InstanceRecovery.psd1 | 6 +- VMware.CloudFoundation.InstanceRecovery.psm1 | 2 +- .../functions/Move-ClusterVMsToFirstHost.md | 109 ------------------ docs/index.md | 17 ++- 5 files changed, 14 insertions(+), 151 deletions(-) delete mode 100644 docs/documentation/functions/Move-ClusterVMsToFirstHost.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e99f88..0f6a417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,7 @@ # Release History -## v1.0.13 +## v9.0.1 -> Released: 2025-01-28 +> Released: 2025-09-23 -- Enhanced `New-RebuiltVsanDatastore` to handle VSAN_MAX clusters correctly - -## v1.0.12 - -> Released: 2024-09-02 - -- Enhanced `New-ExtractDataFromSDDCBackup` to leverage the vCenter Server backup for additional data. -- Added `New-PartialManagementDomainDeployment` to perform the partial bringup. -- Added support for clusters with multiple vDS. -- Added support for VMware Cloud Foundation 5.2.x. -- Enhanced ` upport for vSAN ESA configurations. -- Enhanced `Remove-NonResponsiveHosts` to resolve handling transport node cleanup in versions of VCF using NSX 3.1.3 or higher. -- Added check to `Confirm-VCFInstanceRecoveryPreReqs` for more than 1 concurrent VI server connections. -- Added documentation for new & updated functions. - -## v1.0.10 - -> Released: 2024-05-29 - -- Made `New-RebuiltVdsConfigure` more idempotent so that it can be rerun. - -## v1.0.9 - -> Released: 2024-03-27 - -- Initial release of `VMware.CloudFoundation.InstanceRecovery`. +- Initial release of `VMware.CloudFoundation.InstanceRecovery` for VCF 9.x. diff --git a/VMware.CloudFoundation.InstanceRecovery.psd1 b/VMware.CloudFoundation.InstanceRecovery.psd1 index 96d1869..b5d2539 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psd1 +++ b/VMware.CloudFoundation.InstanceRecovery.psd1 @@ -4,7 +4,7 @@ # Module manifest for module 'VMware.CloudFoundation.InstanceRecovery' # Generated by: Broadcom -# Generated on: 2025-06-04 +# Generated on: 2025-09-23 @{ @@ -12,7 +12,7 @@ RootModule = '.\VMware.CloudFoundation.InstanceRecovery.psm1' # Version number of this module. - ModuleVersion = '1.0.13.1003' + ModuleVersion = '9.0.1.1001' # Supported PSEditions # CompatiblePSEditions = @() @@ -33,7 +33,7 @@ Description = 'PowerShell Module for VMware Cloud Foundation Instance Recovery' # Minimum version of the PowerShell engine required by this module - PowerShellVersion = '7.2.0' + PowerShellVersion = '7.5.3' # Name of the PowerShell host required by this module # PowerShellHostName = '' diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 2709a03..3680e2a 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -1,4 +1,4 @@ -# Copyright 2024 Broadcom. All Rights Reserved. +# Copyright 2025 Broadcom. All Rights Reserved. # SPDX-License-Identifier: BSD-2 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE diff --git a/docs/documentation/functions/Move-ClusterVMsToFirstHost.md b/docs/documentation/functions/Move-ClusterVMsToFirstHost.md deleted file mode 100644 index 86f10a6..0000000 --- a/docs/documentation/functions/Move-ClusterVMsToFirstHost.md +++ /dev/null @@ -1,109 +0,0 @@ -# Move-ClusterVMsToFirstHost - -## Synopsis - -Moves all virtual machines in a cluster to a single ESXi host. - -## Syntax - -```powershell -Move-ClusterVMsToFirstHost [-vCenterFQDN] [-vCenterAdmin] [-vCenterAdminPassword] [-clusterName] [-ProgressAction ] [] -``` - -## Description - -The `Move-ClusterVMsToFirstHost` cmdlet moves all virtual machines in a cluster to a single ESXi host. - -## Examples - -### Example 1 - -```powershell -Move-ClusterVMsToFirstHost -vCenterFQDN "sfo-m01-vc02.sfo.rainpole.io" -vCenterAdmin "administrator@vsphere.local" -vCenterAdminPassword "VMw@re1!" -clusterName "sfo-m01-cl01" -``` - -## Parameters - -### -vCenterFQDN - -Fully qualified domain name of the vCenter Server instance hosting the virtual machines to be moved. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: 1 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -vCenterAdmin - -Admin user for the vCenter Server instance hosting the virtual machines to be moved. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: 2 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -vCenterAdminPassword - -Admin password for the vCenter Server instance hosting the virtual machines to be moved. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: 3 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -clusterName - -Name of the vSphere cluster instance hosting the virtual machines to be moved. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: 4 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -ProgressAction - -Progress Action. - -```yaml -Type: ActionPreference -Parameter Sets: (All) -Aliases: proga - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### Common Parameters - -This cmdlet supports the common parameters: `-Debug`, `-ErrorAction`, `-ErrorVariable`, `-InformationAction`, `-InformationVariable`, `-OutVariable`, `-OutBuffer`, `-PipelineVariable`, `-Verbose`, `-WarningAction`, and `-WarningVariable`. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). diff --git a/docs/index.md b/docs/index.md index 4cd3690..360f458 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,10 +16,9 @@ the use of PowerShell cmdlets. The following table lists the supported releases for this module. -| Platform | Support | -|--------------------------------------------------------------| ----------------------------------- | -| :fontawesome-solid-cloud:   VMware Cloud Foundation 5.2 | :fontawesome-solid-check:{ .green } | -| :fontawesome-solid-cloud:   VMware Cloud Foundation 5.1 | :fontawesome-solid-check:{ .green } | +| Platform | Support | +|----------------------------------------------------------------| ----------------------------------- | +| :fontawesome-solid-cloud:   VMware Cloud Foundation 9.0.x | :fontawesome-solid-check:{ .green } | ### PowerShell @@ -27,7 +26,7 @@ The following table lists the supported editions and versions of PowerShell for Edition | Version ---------------------------------------------------------------------|---------- -:material-powershell:   [PowerShell Core][microsoft-powershell] | >= 7.2.0 +:material-powershell:   [PowerShell Core][microsoft-powershell] | >= 7.5.3 ### Module Dependencies @@ -35,17 +34,15 @@ The following table lists the required dependencies for this module. Dependency | Version | Publisher | Reference -----------------------------------------------------|-----------|---------------------------|--------------------------------------------------------------------------- -[VMware.PowerCLI][psgallery-module-powercli] | 13.3.0 | Broadcom | :fontawesome-solid-book:   [Documentation][developer-module-powercli] -[Posh-SSH][psgallery-module-poshssh] | 3.0.8 | Carlos Perez | :fontawesome-brands-github:   [GitHUb][github-module-poshssh] +[VCF.PowerCLI][psgallery-module-powercli] | 9.0.0 | Broadcom | :fontawesome-solid-book:   [Documentation][developer-module-powercli] +[Posh-SSH][psgallery-module-poshssh] | 3.2.4 | Carlos Perez | :fontawesome-brands-github:   [GitHUb][github-module-poshssh] [OpenSSL for Windows][download-win64openssl] | 3.2.1 | Shining Light Productions | :octicons-package-dependencies-24:   [Download][download-win64openssl] [microsoft-powershell]: https://docs.microsoft.com/en-us/powershell -[psgallery-module-7zip4powershell]: https://www.powershellgallery.com/packages/7Zip4Powershell [psgallery-module-poshssh]: https://www.powershellgallery.com/packages/Posh-SSH -[psgallery-module-powercli]: https://www.powershellgallery.com/packages/VMware.PowerCLI +[psgallery-module-powercli]: https://www.powershellgallery.com/packages/VCF.PowerCLI [psgallery-module-recovery]: https://www.powershellgallery.com/packages/VMware.CloudFoundation.InstanceRecovery [developer-module-powercli]: https://developer.broadcom.com/powercli [docs-module-powervcf]: https://vmware.github.io/powershell-module-for-vmware-cloud-foundation -[github-module-7zip4powershell]: https://github.com/thoemmi/7Zip4Powershell [github-module-poshssh]: https://github.com/darkoperator/Posh-SSH [download-win64openssl]: https://slproweb.com/products/Win32OpenSSL.html From 24846e2c9a18a735be8185b0fbe6ff580ca4c349 Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 13:00:55 +0100 Subject: [PATCH 7/9] Update Add-AdditionalNSXManagers Update Add-AdditionalNSXManagers to refactor credential retrieval Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 3680e2a..661a85c 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -5589,8 +5589,8 @@ Function Add-AdditionalNSXManagers { $nsxManagerFQDN = $selectedNsxManager.hostname - $nsxManagerAdminUsername = ($extractedSddcData.passwords | Where-Object { ($_.entityType -eq "NSXT_MANAGER") -and ($_.domainName -eq $workloadDomain) -and ($_.credentialType -eq "API") }).username - $nsxManagerAdminPassword = ($extractedSddcData.passwords | Where-Object { ($_.entityType -eq "NSXT_MANAGER") -and ($_.domainName -eq $workloadDomain) -and ($_.credentialType -eq "API") }).password + $nsxManagerAdminUsername = ($extractedSddcData.passwords | Where-Object { ($_.entityType -eq "NSXT_MANAGER") -and ($_.domainName -eq $workloadDomain) -and ($_.username -eq "admin") }).username + $nsxManagerAdminPassword = ($extractedSddcData.passwords | Where-Object { ($_.entityType -eq "NSXT_MANAGER") -and ($_.domainName -eq $workloadDomain) -and ($_.username -eq "admin") }).password #Create Headers $headers = VCFIRCreateHeader -username $nsxManagerAdminUsername -password $nsxManagerAdminPassword From 7faeec94164b41e9aecbc8087ca50bc92025eba0 Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Tue, 23 Sep 2025 15:49:43 +0100 Subject: [PATCH 8/9] Update Add-AdditionalNSXManagers Update Add-AdditionalNSXManagers to poll for stable status Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 661a85c..935fc65 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -5684,14 +5684,23 @@ Function Add-AdditionalNSXManagers { $response = $stream.Read() } Until ($response -like "*Join operation successful*") - Do { + <# Do { Start-Sleep 10 $stream.writeline("get cluster status") Start-Sleep 5 $response = $stream.Read() } Until ($response -notlike "*DOWN*") + #> + Do { + <# Start-Sleep 10 + $stream.writeline("get cluster status") + Start-Sleep 5 + $response = $stream.Read() #> + LogMessage -type INFO -message "[$nsxManagerFQDN] Monitoring cluster rebuild status" + $response = ((curl -k -s -u "admin:$nsxManagerAdminPassword" "https://$nsxManagerFqdn/api/v1/cluster/status") | ConvertFrom-Json).mgmt_cluster_status.status + } Until ($response -eq "stable") #Close SSH Session Remove-SSHSession -SSHSession $sshSession | Out-Null } From 73911a769c0cecfd54dc4ca69c4fd8c222f54d01 Mon Sep 17 00:00:00 2001 From: Brian O'Connell Date: Wed, 24 Sep 2025 09:55:06 +0100 Subject: [PATCH 9/9] Update New-vCenterOvaDeployment Update New-vCenterOvaDeployment to handle WLD VC deployment Signed-off-by: Brian O'Connell --- VMware.CloudFoundation.InstanceRecovery.psm1 | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/VMware.CloudFoundation.InstanceRecovery.psm1 b/VMware.CloudFoundation.InstanceRecovery.psm1 index 935fc65..b5712a5 100644 --- a/VMware.CloudFoundation.InstanceRecovery.psm1 +++ b/VMware.CloudFoundation.InstanceRecovery.psm1 @@ -2441,12 +2441,16 @@ Function New-vCenterOvaDeployment { $workloadDomainDetails = ($extractedSDDCData.workloadDomains | Where-Object { $_.domainName -eq $workloadDomain }) $vmDatastore = $extractedSDDCData.mgmtDomainInfrastructure.vsan_datastore #Following parameters converted to known entities for 9.0. Consider refactoring in 9.1 if data is saved in manifest.json - #$vmNetwork = $extractedSDDCData.mgmtDomainInfrastructure.port_group - $vmNetwork = "vcfir-cl01-vds01-pg-vm-mgmt" - #$datacenterName = $extractedSDDCData.mgmtDomainInfrastructure.datacenter - $datacenterName = "vcfir-dc01" - #$clusterName = $extractedSDDCData.mgmtDomainInfrastructure.cluster - $clusterName = "vcfir-cl01" + if (!$extractedSDDCData.mgmtDomainInfrastructure.cluster) { + $vmNetwork = "vcfir-cl01-vds01-pg-vm-mgmt" + $datacenterName = "vcfir-dc01" + $clusterName = "vcfir-cl01" + } + else { + $vmNetwork = $extractedSDDCData.mgmtDomainInfrastructure.port_group + $datacenterName = $extractedSDDCData.mgmtDomainInfrastructure.datacenter + $clusterName = $extractedSDDCData.mgmtDomainInfrastructure.cluster + } $restoredvCenterVMName = $workloadDomainDetails.vCenterDetails.vmname $restoredvCenterIpAddress = $workloadDomainDetails.vCenterDetails.ip $restoredvCenterFqdn = $workloadDomainDetails.vCenterDetails.fqdn