Public/New-AGMLibGCEInstanceDiscovery.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-AGMLibGCEInstanceDiscovery ([string]$discoveryfile,[switch]$nobackup,[switch]$backup,[string]$usertag,[string]$backupplanlabel,[string]$diskbackuplabel,[string]$credentialid,[string]$sltid,[string]$sltname,[switch]$bootonly,[string]$applianceid,[string]$project,[string]$projectid,[string]$zone,[switch]$textoutput,[decimal]$limit,[switch]$noparallel,[switch]$verbose) { <# .SYNOPSIS Uses a pre-prepared CSV list of cloud credential IDs, appliance IDs, projects and zones to discover new GCE Instances .EXAMPLE New-AGMLibGCEInstanceDiscovery -discoveryfile credentials.csv -nobackup Adds all new GCE Instances discovered in the nominated projects and zones as unmanaged applications .EXAMPLE New-AGMLibGCEInstanceDiscovery -discoveryfile credentials.csv -backup Adds all new GCE Instances discovered in the nominated projects and zones and protects any that have a valid template name .EXAMPLE New-AGMLibGCEInstanceDiscovery -discoveryfile credentials.csv -backup -boot Adds all new GCE Instances discovered in the nominated projects and zones and protects only the boot drive or any that have a valid template name .EXAMPLE New-AGMLibGCEInstanceDiscovery -discoveryfile credentials.csv -backup -backupplanlabel "corporatepolicy" Adds all new GCE Instances discovered in the nominated projects and zones and protects any that have a label named corporatepolicy and a valid template name .EXAMPLE New-AGMLibGCEInstanceDiscovery -credentialid 259643 -applianceid 141805487622 -projectid avwservicelab1 -zone australia-southeast1-b -backupplanlabel backupplan -backup Instead of using a discovery file the four required variables are specified by the user. .EXAMPLE New-AGMLibGCEInstanceDiscovery -credentialid 706606 -applianceid 144091747698 -project avwarglab1 -zone australia-southeast2-a -backupplanlabel backupplan -diskbackuplabel diskbackup -backup In this example the user uses two labels on each Compute Engine instance to determine backup handling. -backupplanlabel backupplan means if the instance has a label of backupplan then use its value as the template name. While -diskbackuplabel diskbackup means if the instance has a label of diskbackup and the value is bootonly then set bootonly backup on that instance. .DESCRIPTION This routine needs a well formatted CSV file that contains cloud credential ID Note the column order is not important. Here is an example of such a file: credentialid,applianceid,project,zone 6654,143112195179,avwarglab1,australia-southeast1-c 6654,143112195179,avwarglab1,australia-southeast2-a 6654,143112195179,avwarglab1,australia-southeast2-b To learn credential ID and appliance ID, use Get-AGMLibCredentialSrcID Then use the desired projects (where the service account for the credential exists) and the desired zones you want to check for new Instances. The default is to fetch 5 Instances at a time. You can change this with -limit. You may need to specify a larger timeout when running Connect-AGM You can also manually supply credentialid, applianceid, project and zone rather than using a CSV file If the following is specified then discovery will occur with no backup plans being applied: -nobackup If the following are specified in combination then all instances will have a backup plan applied to it: -backup -sltname "<name" -backup -sltid <slt ID learned with Get-AGMSLT> If the following is added then only boot disks will be protected: -bootonly If you want to use a label to determine what template is used, then on the Instance set a label 'backupplan' where the value is: - A valid template name - ignored <-- If this is detected then the application will be added as ignored - unmanaged <-- If this is detected then the application will be added as unmanaged Label management has two values that can be set: -backupplanlabel xxxx If the instance has a label named xxxx then use its value as the template name. If the value is 'ignored' or 'unmanaged' then do that instead -diskbackuplabel yyy If the instance has a label of yyy and the value is bootonly then set bootonly backup on that instance. #> if ( (!($AGMSESSIONID)) -or (!($AGMIP)) ) { Get-AGMErrorMessage -messagetoprint "Not logged in or session expired. Please login using Connect-AGM" return } # verbose = textoutput if ($verbose) { $textoutput = $true} if ($textoutput) { $ct = Get-Date write-host "$ct Starting function" } $sessiontest = Get-AGMVersion if ($sessiontest.errormessage) { $sessiontest return } if ($textoutput) { $ct = Get-Date write-host "$ct Session test passed" } # if user wants to say projectid rather than project, we let them if ($projectid) { $project = $projectid} # rename usertag support if ($backupplanlabel) { $usertag = $backupplanlabel} #if user would rather not use a CSV file, we need all the stats if (($credentialid) -and ($applianceid) -and ($project) -and ($zone)) { $searchlist = @() $searchlist += [pscustomobject]@{ credentialid = $credentialid applianceid = $applianceid project = $project zone = $zone } } elseif ($discoveryfile) { $searchlist = Import-Csv -Path $discoveryfile } else { Get-AGMErrorMessage -messagetoprint "Please supply a source csv file correctly formatted as per the help for this function using: -discoveryfile xxxx.csv or supply applianceid,credentialid,project and zone" return; } if (!($limit)) { $limit = 5} $offset = 0 if ($sltid) { $sltgrab = Get-AGMSLT $sltid if ($sltgrab.id.count -ne 1) { Get-AGMErrorMessage -messagetoprint "Failed to find an SLT with ID $sltid" return; } } if ($sltname) { $sltgrab = Get-AGMSLT -filtervalue name=$sltname if ($sltgrab.id.count -ne 1) { Get-AGMErrorMessage -messagetoprint "Failed to find an SLT with name $sltname" return; } $sltid = $sltgrab.id } if ($backup) { if ((!($sltid)) -and (!($backupplanlabel))) { Get-AGMErrorMessage -messagetoprint "When specifying -backup either supply a default template with -sltid or -sltname and/or specify a -backupplanlabel" return; } } if ((!($backup)) -and (!($nobackup))) { Get-AGMErrorMessage -messagetoprint "Please specify either -backup or -nobackup to determine whether discovered instances should be protected or not protected" return; } if ($nobackup) { foreach ($cred in $searchlist) { $done = 0 do { $searchcommand = 'Get-AGMCloudVM -credentialid ' +$cred.credentialid +' -clusterid ' +$cred.applianceid +' -project ' +$cred.project +' -zone ' +$cred.zone +' -limit ' +$limit if ($textoutput) { $ct = Get-Date write-host "$ct Running" $searchcommand } $newvmcommand = Invoke-Expression $searchcommand if ($newvmcommand.totalcount -gt 0) { $offset += 1 $instancelist = "" foreach ($instance in $newvmcommand.items.vm) { $instancelist = $instancelist + "," +$instance.instanceid } # remove leading comma $instancelist = $instancelist.substring(1) $addcommand = 'New-AGMCloudVM -credentialid ' +$cred.credentialid +' -clusterid ' +$cred.applianceid +' -project ' +$cred.project +' -zone ' +$cred.zone +' -instanceid "' +$instancelist +'"' if ($textoutput) { $ct = Get-Date write-host "$ct Running" $addcommand } $addvmcommand = Invoke-Expression $addcommand $addvmcommand | Add-Member -NotePropertyName credentialid -NotePropertyValue $cred.credentialid $addvmcommand | Add-Member -NotePropertyName applianceid -NotePropertyValue $cred.applianceid $addvmcommand | Add-Member -NotePropertyName project -NotePropertyValue $cred.project $addvmcommand | Add-Member -NotePropertyName zone -NotePropertyValue $cred.zone $addvmcommand } else { $done = 1 } } until ($done -eq 1) } } if ($backup) { # learn all the SLTs if ($textoutput) { $ct = Get-Date write-host "$ct Running Get-AGMSLT" } $sltgrab = Get-AGMSLT if ($textoutput) { $ct = Get-Date write-host "$ct Output:" $sltgrab } if ($textoutput) { $ct = Get-Date write-host "$ct Running Get-AGMSLP" } $slpgrab = Get-AGMSLP if ($textoutput) { $ct = Get-Date write-host "$ct Output:" $slpgrab } if ($textoutput) { $ct = Get-Date write-host "$ct Running Get-AGMLibCredentialSrcID" } $srccredgrab = Get-AGMLibCredentialSrcID if ($textoutput) { $ct = Get-Date write-host "$ct Output:" $credgrab } if ($textoutput) { $ct = Get-Date write-host "$ct Running Get-AGMDiskpool" } $diskpooldatagrab = Get-AGMDiskpool -filtervalue pooltype=cloud | Select-object name,@{N='srcid';E={$_.cloudcredential.sources.srcid}} if ($textoutput) { $ct = Get-Date write-host "$ct Output:" $diskpooldatagrab } foreach ($cred in $searchlist) { if ($textoutput) { $ct = Get-Date write-host "$ct Processing this selection" $cred } # we need to learn the srcid $credgrab = ($srccredgrab | where-object {($_.credentialid -eq $cred.credentialid) -and ($_.applianceid -eq $cred.applianceid)}) if ($credgrab.srcid) { $srcid = $credgrab.srcid $diskpoolgrab = $diskpooldatagrab | where-object {($_.srcid -eq $srcid)} if ($diskpoolgrab.name) { $poolname = $diskpoolgrab.name $slplookup = ($slpgrab | where-object {($_.performancepool -eq $poolname) -and ($_.clusterid -eq $cred.applianceid)}) if ($slplookup.id) { $slpid = $slplookup.id } } } if ($slpid) { $done = 0 do { $searchcommand = 'Get-AGMCloudVM -credentialid ' +$cred.credentialid +' -clusterid ' +$cred.applianceid +' -project ' +$cred.project +' -zone ' +$cred.zone +' -limit ' +$limit if ($textoutput) { $ct = Get-Date write-host "$ct Running" $searchcommand } $newvmcommand = Invoke-Expression $searchcommand $newvmcommand | Add-Member -NotePropertyName credentialid -NotePropertyValue $cred.credentialid $newvmcommand | Add-Member -NotePropertyName applianceid -NotePropertyValue $cred.applianceid $newvmcommand | Add-Member -NotePropertyName project -NotePropertyValue $cred.project $newvmcommand | Add-Member -NotePropertyName zone -NotePropertyValue $cred.zone $newvmcommand | Add-Member -NotePropertyName newgceinstances -NotePropertyValue 0 $newvmcommand | Add-Member -NotePropertyName newgceinstancebackup -NotePropertyValue 0 if ($newvmcommand.totalcount -gt 0) { $offset += 1 # we need the instance data $matchinginstances = $newvmcommand.items.vm $instancelist = "" foreach ($instance in $newvmcommand.items.vm) { $instancelist = $instancelist + "," +$instance.instanceid } # remove leading comma if ($instancelist) { $instancelist = $instancelist.substring(1) } if ($instancelist -ne "") { $addappcommand = 'New-AGMCloudVM -credentialid ' +$cred.credentialid +' -clusterid ' +$cred.applianceid +' -project ' +$cred.project +' -zone ' +$cred.zone +' -instanceid "' +$instancelist +'"' if ($textoutput) { $ct = Get-Date write-host "$ct Running" $addappcommand } $newappcommand = Invoke-Expression $addappcommand if ($textoutput) { $ct = Get-Date write-host "$ct Addition of the VM got the following output:" if ($newappcommand.count) { $newappcommand.count } if ($newappcommand.items) { $newappcommand.items } else { $newappcommand } write-host "" } if ($newappcommand.errormessage) { $newappcommand.errormessage $done = 1 } if ($newappcommand.count -ge 1) { # here we build $newslalist which we process afterwards. This step adds the VM... we protect it in the next step $newslalist = @() foreach ($instance in $newappcommand.items) { $appid = $instance.id $newvmcommand.newgceinstances += 1 $newapphostuniquename = $instance.host.sources.uniquename $taggrab = $matchinginstances | where-object {$_.instanceid -eq $newapphostuniquename } | Select-Object tag if ($usertag) { $backupplancheck = $taggrab.tag | select-string $usertag } if ($diskbackuplabel) { $diskbackuplabelcheck = $taggrab.tag | select-string $diskbackuplabel } # if user supplied default sltid then use that if ((!($backupplancheck)) -and ($sltid)) { if (($sltid) -and ($slpid) -and ($appid)) { $newslalist += [pscustomobject]@{ appid = $appid sltid = $sltid slpid = $slpid } $newvmcommand.newgceinstancebackup += 1 } } if ($backupplancheck) { # remove the leadering and trailing { and } $taglist = $taggrab.tag.substring(1,$taggrab.tag.Length-2).Split(",") # now for the backup tag foreach ($tag in $taglist) { $name = $tag.trim().split("=") | Select-object -First 1 $value = $tag.trim().split("=") | Select-object -skip 1 # if the tag name is googlebackupplan we can protect it if ($name | select-string $usertag) { if ($value -eq "ignored") { $jsonbody = '{"ignore":true}' Put-AGMAPIData -endpoint /application/$appid -body $jsonbody } elseif ($value -ne "unmanaged") { if ($sltgrab | where-object {$_.name -eq $value}) { $labelsltid = ($sltgrab | where-object {$_.name -eq $value}).id } elseif ($sltid) { $labelsltid = $sltid } if (($labelsltid) -and ($slpid) -and ($appid)) { $newslalist += [pscustomobject]@{ appid = $appid sltid = $labelsltid slpid = $slpid } $newvmcommand.newgceinstancebackup += 1 } } } } } # if the user is using a label as a hint as to whethe we do boot only per instance if ($diskbackuplabelcheck) { # remove the leadering and trailing { and } $taglist = $taggrab.tag.substring(1,$taggrab.tag.Length-2).Split(",") # now look for the diskbackuplabel foreach ($tag in $taglist) { $name = $tag.trim().split("=") | Select-object -First 1 $value = $tag.trim().split("=") | Select-object -skip 1 # if we find diskbackuplabel and its value is bootonly we use it. In future we could add more logic here if (($name | select-string $diskbackuplabel) -and ($value -eq "bootonly")) { $newslalist | where-object { $_.appid -eq $appid } | Add-Member -MemberType NoteProperty -Name diskbackup -Value "bootonly" } } } } # bootonly routine where user is specifying bootonly via label or for all VMs. We do this per VM $newslalist | ForEach-Object { $appid = $_.appid $diskbackuprule = $_.diskbackup if (($diskbackuprule -eq "bootonly") -or ($bootonly)) { $jsonbody = '{"type":"boot"}' Put-AGMAPIData -endpoint /application/$appid/memberrule -body $jsonbody } } # now we protect the VMs if ( ($((get-host).Version.Major) -gt 5 ) -and (!($noparallel))) { if ($AGMToken) { $newslalist | ForEach-Object -parallel { $newsla = 'New-AGMSLA -appid ' +$_.appid +' -sltid ' +$_.sltid +' -slpid ' +$_.slpid if ($textoutput) { $ct = Get-Date write-host "$ct Running" $newsla } $agmip = $using:agmip $AGMToken = $using:AGMToken $AGMSESSIONID = $using:AGMSESSIONID New-AGMSLA -appid $_.appid -sltid $_.sltid -slpid $_.slpid start-sleep -seconds 5 } -ThrottleLimit $limit } else { $newslalist | ForEach-Object -parallel { $newsla = 'New-AGMSLA -appid ' +$_.appid +' -sltid ' +$_.sltid +' -slpid ' +$_.slpid if ($textoutput) { $ct = Get-Date write-host "$ct Running" $newsla } $agmip = $using:agmip $AGMSESSIONID = $using:AGMSESSIONID $IGNOREAGMCERTS = $using:IGNOREAGMCERTS New-AGMSLA -appid $_.appid -sltid $_.sltid -slpid $_.slpid start-sleep -seconds 5 } -ThrottleLimit $limit } } else { $newslalist | ForEach-Object { $newsla = 'New-AGMSLA -appid ' +$_.appid +' -sltid ' +$_.sltid +' -slpid ' +$_.slpid if ($textoutput) { $ct = Get-Date write-host "$ct Running" $newsla } New-AGMSLA -appid $_.appid -sltid $_.sltid -slpid $_.slpid } } } } } else { $done = 1 } $newvmcommand } until ($done -eq 1) if ($textoutput) { $ct = Get-Date write-host "$ct Complete" } } } } } |