Public/New-AGMLibMultiVM.ps1
# Copyright 2022 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. Function New-AGMLibMultiVM ([array]$imagelist,$vcenterid,[array]$esxhostlist,[array]$datastorelist,[string]$datastore,[string]$esxhostid,[string]$prefix,[string]$suffix,[switch][alias("c")]$condatesuffix,[switch][alias("i")]$imagesuffix,[string]$mountmode,[string]$poweronvm,[string]$mapdiskstoallesxhosts,[string]$label,[int]$startindex) { <# .SYNOPSIS Mounts a number of new VMs .EXAMPLE New-AGMLibMultiVM -imagelist $imagelist -vcenterid $vcenterid -esxhostlist $esxhostlist -datastorelist $datastorelist -poweronvm false -prefix "recover-" This command will use the output of Get-AGMLibImageRange as $imagelist So we could create a list like this: $imagelist = Get-AGMLibImageRange -fuzzyappname demo-sql -olderlimit 3 We could get a list of vCenters with a command like this: Get-AGMHost -filtervalue "isvcenterhost=true" | select id,hostname,srcid Then set it: $vcenterid = 5552150 The ESXHostlist should be a list of ESX Host IDs. We need the srcid from the vCenter If the vCenter srcid is 4460, we could use this: $esxhostlist = Get-AGMHost -filtervalue "isesxhost=true&vcenterhostid=4460" | select id,hostname The Datastorelist should be a list of datastores. Here is an example command: $datastorelist = ((Get-AGMHost -id 5552166).sources.datastorelist | select-object name| sort-object name | Get-Unique -asstring).name One thing to be careful about is that the datastore list should be available to all the ESX hosts. The prefix is optional but recommended The suffix is optional but recommended There are three mechanisms to get unique VM names: 1) You can specify -i and the Image Name will be appended as a suffix to the VMname 2) You can instead specify -c and the Consistency Date will be appended as a suffix to the VMname 3) If you don't specify -c or -i, then if more than one image from a single application is in the image list, then an incremental numerical suffix will be applied. If you want to control the starting number of that index use -startindex By default it will use a label of "MultiVM Recovery" to make the VMs easier to find .EXAMPLE New-AGMLibMultiVM -imagelist $imagelist -vcenterid $vcenterid -esxhostid $esxhostid -datastore $datastore -poweronvm false -prefix "recover-" If you only have a single ESX host and Datastore you can specify them singly using -esxhostid and -datastore Clearly all your mounts will go to a single ESX Host and datastore If you want the disks mapped to all ESX hosts then use the following: -mapdiskstoallesxhosts true #> if ( (!($AGMSESSIONID)) -or (!($AGMIP)) ) { Get-AGMErrorMessage -messagetoprint "Not logged in or session expired. Please login using Connect-AGM" return } $sessiontest = Get-AGMVersion if ($sessiontest.errormessage) { $sessiontest return } # handle vcenterid if ($vcenterid.id) { if ($vcenterid.id.count -gt 1) { Get-AGMErrorMessage -messagetoprint "There is more than vCenterID specified. This function can only use one vCenterID" return } else { $vcenterid = $vcenterid.id } } # handle esxlist if ($esxhostlist.id) { $esxhostlist = ($esxhostlist).id } if ( (!($esxhostlist)) -and ($esxhostid) ) { $esxhostlist = $esxhostid } # handle datastorelist if ($datastorelist.name) { $datastorelist = ($datastorelist).name | Get-Unique -asstring } if ( (!($datastorelist)) -and ($datastore) ) { $datastorelist = $datastore } if (!($imagelist)) { Get-AGMErrorMessage -messagetoprint "Please supply an imagelist" return } if (!($datastorelist)) { Get-AGMErrorMessage -messagetoprint "Please supply an array of datastores using -datastorelist or a single datastore using -datastore" return } if (!($esxhostlist)) { Get-AGMErrorMessage -messagetoprint "Please supply an array of ESXHost IDs using -esxhostlist or a single ESX Host ID using -esxhostid" return } if (!($vcenterid)) { Get-AGMErrorMessage -messagetoprint "Please supply a vcenterid" return } if (!($mountmode)) { $physicalrdm = 0 $rdmmode = "independentvirtual" } else { if ($mountmode -eq "vrdm") { $physicalrdm = 0 $rdmmode = "independentvirtual" } if ($mountmode -eq "prdm") { $physicalrdm = 1 $rdmmode = "physical" } if ($mountmode -eq "nfs") { $physicalrdm = 2 $rdmmode = "nfs" } } if (!($poweronvm)) { $poweronvm = "true" } if (($poweronvm -ne "true") -and ($poweronvm -ne "false")) { Get-AGMErrorMessage -messagetoprint "Power on VM value of $poweronvm is not valid. Must be true or false" return } if (!($mapdiskstoallesxhosts)) { $mapdiskstoallesxhosts = "false" } if (($mapdiskstoallesxhosts -ne "true") -and ($mapdiskstoallesxhosts -ne "false")) { Get-AGMErrorMessage -messagetoprint "The value of Map to all ESX hosts of $mapdiskstoallesxhosts is not valid. Must be true or false" return } if (!($label)) { $label = "MultiVM Recovery" } $esxhostcount = $esxhostlist.count $datastorecount = $datastorelist.count $esxroundrobin = 0 $dsroundrobin = 0 $lastappid = "" $lastcondate = "" # we use this hash to store the starting index for each appid. The user can specify the starting number or we will start at 1 $appiditeration = @{} if (!($startindex)) { $startindex = 1 } # count number of times each appid appears $appidcount = $imagelist | Group-Object -Property appid -NoElement foreach ($image in $imagelist) { if (($lastappid -eq $image.appid) -and ($lastcondate -eq $image.consistencydate)) { Write-Host "Not mounting AppName:" $image.appname " Jobclass:" $image.jobclass " ImageName:" $image.backupname " ConsistencyDate:" $image.consistencydate "because the previous mount had the same appid and consistency date" } elseif ($image.apptype -eq "VMBackup") { $vmname = $image.appname if ($suffix) { $vmname = $vmname + $suffix } if ($prefix) { $vmname = $prefix + $vmname } if ($imagesuffix) { $vmname = $vmname + "_" + $image.backupname } elseif ($condatesuffix) { $vmname = $vmname + "_" + $image.consistencydate.Replace(" ","_") } else { # to guarantee unique names we will put an index ID after each mount starting at 1 or the specified $startindex per appid where there is more than image per appid $tempid = $image.appid if (($appidcount | where-object {$_.name -eq $tempid}).Count -gt 1) { if (!($appiditeration.$tempid )) { $appiditeration = $appiditeration + @{ $tempid = $startindex } } else { $appiditeration.$tempid += 1 } $vmname = $vmname + "_" + $appiditeration.$tempid } } # we can now set the values needed for the mount $imageid = $image.id $esxhostid = $esxhostlist[$esxroundrobin] $datastore = $datastorelist[$dsroundrobin] $body = [ordered]@{ "@type" = "mountRest"; label = "$label" restoreoptions = @( @{ name = 'mapdiskstoallesxhosts' value = "$mapdiskstoallesxhosts" } ) datastore = $datastore; hypervisor = @{id=$esxhostid} mgmtserver = @{id=$vcenterid} vmname = $vmname; hostname = $vmname; poweronvm = "$poweronvm"; physicalrdm = $physicalrdm; rdmmode = $rdmmode; migratevm = "false"; } $json = $body | ConvertTo-Json Write-Host " Mounting AppName:" $image.appname " Jobclass:" $image.jobclass " ImageName:" $image.backupname " ConsistencyDate:" $image.consistencydate "as:" $vmname "to ESX Host ID" $esxhostid "using Datastore" $datastore Post-AGMAPIData -endpoint /backup/$imageid/mount -body $json $esxroundrobin += 1 $dsroundrobin += 1 if ($esxroundrobin -eq $esxhostcount ) { $esxroundrobin = 0 } if ($dsroundrobin -eq $datastorecount ) { $dsroundrobin = 0 } $lastappid = $image.appid $lastcondate = $image.consistencydate } else { Write-Host "******* Not mounting AppName:" $image.appname "ImageName:" $image.backupname "because it has an apptype of" $image.apptype "*******" } } } |