AGMPowerCLINewFunctions.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-AGMAppDiscovery ([string]$hostid,[string]$ipaddress,[string]$applianceid) { <# .SYNOPSIS Runs discovery against a host .EXAMPLE New-AGMAppDiscovery -hostid 5678 -applianceid 1415071155 Runs application discovery against the host with ID 5678 for appliance with ID 1415071155 .DESCRIPTION A function to run application discovery #> if ((!($hostid)) -and (!($ipaddress))) { [string]$hostid = Read-Host "Host to perform discovery on (press enter to use IP)" if (!($hostid)) { [string]$ipaddress = Read-Host "Host IP to perform discovery on" } } if (!($applianceid)) { [string]$applianceid = Read-Host "Appliance to perform discovery on" } if ($hostid) { $body = [ordered]@{ host = [ordered]@{ id=$hostid sources= @( @{ clusterid=$applianceid } ) } } } if ($ipaddress) { $body = [ordered]@{ cluster=$applianceid; type="standard"; ipaddress=$ipaddress } } $jsonbody = $body | ConvertTo-Json -depth 4 Post-AGMAPIData -endpoint /host/discover -body $jsonbody } Function New-AGMAppliance ([string]$ipaddress,[string]$username,[string]$password,[SecureString]$passwordenc,[switch]$dryrun) { <# .SYNOPSIS Adds a new appliance to AGM .EXAMPLE New-AGMAppliance ipaddress 10.194.0.38 -username admin -password password -dryrun | select-object approvaltoken,cluster,report This performs a dryrun to test if Appliance add will work. Pay close attention to the errcode in the report field and that the cluster field contains a clusterid. You also need to see an approval token. If everything looks good, run the command again without specifying -dryrun If you are feeling lucky you can choose to skip running the command without -dryrun .EXAMPLE New-AGMAppliance ipaddress 10.194.0.38 -username admin -password password This adds the Appliance and includes a dryrun. After it runs, then run Get-AGMAppliance to confirm the appliance has been added. .DESCRIPTION A function to add Appliances For password handling there are two parameters you can use: -password This is the Appliance password in plain text -passwordenc This is the Appliance password as a secure string. This can be used with Powershell 7 If you don't use either parameter you will be prompted to enter the password in a secure fashion. This can be used with Powershell 7 #> if (!($ipaddress)) { [string]$ipaddress = Read-Host "Appliance IP Address" } if (!($username)) { [string]$username = Read-Host "Appliance username" } if ((!($password)) -and (!($passwordenc))) { # prompt for a password [SecureString]$passwordenc = Read-Host "Password" -AsSecureString [string]$password = (Convertfrom-SecureString $passwordenc -AsPlainText) } if ($passwordenc) { [string]$password = (Convertfrom-SecureString $passwordenc -AsPlainText) } $body = [ordered]@{ ipaddress=$ipaddress; username=$username; password=$password } $jsonbody = $body | ConvertTo-Json $dryrungrab = Post-AGMAPIData -endpoint /cluster/dryrun -body $jsonbody if ($dryrun) { $dryrungrab return } if ($dryrungrab.approvaltoken) { $body = [ordered]@{ ipaddress=$ipaddress; username=$username; password=$password; approvaltoken=$dryrungrab.approvaltoken } $jsonbody = $body | ConvertTo-Json Post-AGMAPIData -endpoint /cluster -body $jsonbody } else { $dryrun } } Function New-AGMCloudVM ([string]$zone,[string]$id,[string]$credentialid,[string]$clusterid,[string]$applianceid,[string]$projectid,[string]$instanceid) { <# .SYNOPSIS Adds new Cloud VMs .EXAMPLE New-AGMCloudVM -credentialid 1234 -zone australia-southeast1-c -applianceid 144292692833 -instanceid 4240202854121875692 Adds VM with ID 4240202854121875692 to specified appliance .DESCRIPTION A function to add Cloud VMs Multiple vmids should be comma separated #> if ($id) { $credentialid = $id } if (!($credentialid)) { [string]$credentialid = Read-Host "Credential ID" } if ($applianceid) { [string]$clusterid = $applianceid} if (!($clusterid)) { $clusterid = Read-Host "Cluster ID" } if (!($projectid)) { [string]$projectid = Read-Host "Project ID" } #if user doesn't specify name and zone, then learn them $credentialgrab = Get-AGMCredential -credentialid $credentialid if (!($credentialgrab.id)) { Get-AGMErrorMessage -messagetoprint "The credential ID $credentialid could not be found." return } else { if (!($zone)) { $zone = $credentialgrab.region } } if (!($zone)) { [string]$zone = Read-Host "Zone Name" } if (!($instanceid)) { [string]$instanceid = Read-Host "Instance IDs (Comma separated)" } $cluster = @{ clusterid = $clusterid} $body = [ordered]@{} if ($AGMToken) { $body += @{ cluster = $cluster; region = $zone; listonly = $false; vmids = $($instanceid.Split(",")) projectid = $projectid; } } else { $body += @{ cluster = $cluster; region = $zone; listonly = $false; vmids = $($instanceid.Split(",")) project = $projectid; } } $json = $body | ConvertTo-Json Post-AGMAPIData -endpoint /cloudcredential/$credentialid/discovervm/addvm -body $json } Function New-AGMConsistencyGroup ([string]$clusterid,[string]$applianceid,[string]$hostid,[string]$description,[string]$groupname) { <# .SYNOPSIS Adds new Consistency Group (CG) .EXAMPLE New-AGMConsistencyGroup -applianceid 144292692833 -groupname "prodhost1" -description "this is a CG" -hostid 12344 To learn applianceid, use this command: Get-AGMAppliance and use the clusterid as applianceid. To learn host ID, use this command: Get-AGMHost Once you have created the Consistency Group you can add applications to it with Set-AGMConsistencyGroupMember Once you have created the Consistency Group you can change the name and description with Set-AGMConsistencyGroup .DESCRIPTION A function to add a Consistency Group #> if ($applianceid) { [string]$clusterid = $applianceid} if (!($clusterid)) { $clusterid = Read-Host "Cluster ID" } if (!($hostid)) { [string]$hostid = Read-Host "Host ID" } if (!($groupname)) { [string]$groupname = Read-Host "Group Name" } # cluster needs to be like: sources":[{"clusterid":"144488110379"},{"clusterid":"143112195179"}] $sources = @() foreach ($cluster in $clusterid.Split(",")) { $sources += [ordered]@{ id = $cluster } } # {"groupname":"testme","description":"description","cluster":{"id":"70194"},"host":{"id":"70631"}} $body = [ordered]@{} $body += [ordered]@{ groupname = $groupname; cluster = $sources; host = [ordered]@{ id = $hostid } } if ($description) { $body += @{ description = $description } } $json = $body | ConvertTo-Json Post-AGMAPIData -endpoint /consistencygroup -body $json } Function New-AGMCredential ([string]$name,[string]$zone,[string]$clusterid,[string]$applianceid,$filename,[string]$projectid,[string]$organizationid,[string]$udsuid) { <# .SYNOPSIS Creates a cloud credential .EXAMPLE New-AGMCredential -name cred1 -zone australia-southeast1-c -applianceid 144292692833 -filename keyfile.json To learn the Appliance ID, use this command and use the clusterid value: Get-AGMAppliance | select clusterid,name Comma separate the Appliance IDs if you have multiple appliances You can add org IDs with -organizationid To learn the Org IDs, use this command: Get-AGMOrg | select-object id,name Comma separate the Org IDs if you have multiple orgs To add an onvault pool, use -udsuid To learn the udsid use this command: Get-AGMDiskPool -filtervalue pooltype=vault | select-object name,udsuid,@{N='appliancename'; E={$_.cluster.name}},@{N='applianceid'; E={$_.cluster.clusterid}} Ensure the pool exists on all the appliances you are adding the credential to. .DESCRIPTION A function to create cloud credentials #> if (!($name)) { [string]$name = Read-Host "Credential Name" } if (!($zone)) { [string]$zone = Read-Host "Default zone" } if ($applianceid) { [string]$clusterid = $applianceid} if (!($clusterid)) { [string]$clusterid = Read-Host "Cluster IDs (comma separated)" } if (!($filename)) { $filename = Read-Host "JSON key file" } if ( Test-Path $filename ) { $jsonkey = Get-Content -Path $filename -raw $jsonkey = $jsonkey.replace("\n","\\n") $jsonkey = $jsonkey.replace("`n","\n ") $jsonkey = $jsonkey.replace('"','\"') } else { Get-AGMErrorMessage -messagetoprint "The file named $filename could not be found." return } if (!($projectid)) { $jsongrab = Get-Content -Path $filename | ConvertFrom-Json if (!($jsongrab.project_id)) { Get-AGMErrorMessage -messagetoprint "The file named $filename does not contain a valid project ID." return } else { $projectid = $jsongrab.project_id } } # cluster needs to be like: sources":[{"clusterid":"144488110379"},{"clusterid":"143112195179"}] $sources = @() foreach ($cluster in $clusterid.Split(",")) { $sources += [ordered]@{ clusterid = $cluster } } $orglist = @() if ($organizationid) { foreach ($org in $organizationid.Split(",")) { $orglist += [ordered]@{ id = $org } } } $body = [ordered]@{} $body += [ordered]@{ name = $name; cloudtype = "GCP"; projectid = $projectid; region = $zone; endpoint = ""; sources = $sources; orglist = $orglist } if ($udsuid) { $body += [ordered]@{ vault_udsuid = $udsuid } } $json = $body | ConvertTo-Json -compress # this section is post editing the JSON to add in the credential. Ideally we should do this using a PS Object rather than an edit like this. $json = $json.Substring(0,$json.Length-1) $json = $json + ',"credential":"' + $jsonkey +'"}' # first we test it $testcredential = Post-AGMAPIData -endpoint /cloudcredential/testconnection -body $json if ($testcredential.errors) { $testcredential return } Post-AGMAPIData -endpoint /cloudcredential -body $json return } Function New-AGMHost ([string]$clusterid,[string]$applianceid,[string]$hostname,[string]$friendlyname,[string]$description,[string]$ipaddress,[string]$alternateip,[string]$hosttype,[string]$organizationid,[string]$secret) { <# .SYNOPSIS Adds new Hosts .EXAMPLE New-AGMHost -applianceid 144292692833 -hostname "prodhost1" -ipaddress "10.0.0.1" Adds Host with name prodhost1 and IP address 10.0.0.1 to specified appliance .EXAMPLE New-AGMHost -applianceid "143112195179,144488110379" -hostname "prodhost1" -ipaddress "10.0.0.1" -friendlyname "mainprod" -description "this is prod, be nice" -alternateip "20.0.0.1,30.0.0.1" Adds Host with name prodhost1 and IP address 10.0.0.1 to two specified appliances, with a friendlyname, text description and two alternate IPs. To learn applianceid, use this command: Get-AGMAppliance and use the clusterid as applianceid. If you have multiple applianceIDs, comma separate them alternateip needs to be a comma separated list of IPs .DESCRIPTION A function to add Hosts #> if ($applianceid) { [string]$clusterid = $applianceid} if (!($clusterid)) { $clusterid = Read-Host "Cluster ID" } if (!($hostname)) { [string]$hostname = Read-Host "Host name" } if (!($ipaddress)) { [string]$ipaddress = Read-Host "IP Address" } if (!($hostype)) { $hosttype = "generic" } # cluster needs to be like: sources":[{"clusterid":"144488110379"},{"clusterid":"143112195179"}] $sources = @() foreach ($cluster in $clusterid.Split(",")) { $sources += [ordered]@{ clusterid = $cluster } } $orglist = @() foreach ($org in $organizationid.Split(",")) { $orglist += [ordered]@{ id = $org } } # alternate IP needs to be like: "alternateip":["10.20.0.1","10.30.0.1"], if ($alternateip) { $alternateipaddresses = @( $($alternateip.Split(",")) ) } $udsagent = [ordered]@{} if ($secret) { $udsagent += [ordered]@{ shared_secret = $secret } } $body = [ordered]@{} $body += [ordered]@{ hosttype = $hosttype; hostname = $hostname; ipaddress = $ipaddress; alternateip = $alternateipaddresses; sources = $sources; orglist = $orglist } if ($description) { $body += @{ description = $description } } if ($friendlyname) { $body += @{ friendlypath = $friendlyname } } if ($secret) { $body += @{ udsagent = $udsagent } } $json = $body | ConvertTo-Json Post-AGMAPIData -endpoint /host -body $json } Function New-AGMMount ([string]$imageid,[string]$targethostid,[string]$jsonbody,[string]$label) { <# .SYNOPSIS Mounts an Image .EXAMPLE New-AGMMount -imageid 1234 -targethostid 5678 Mounts image ID 1234 to target host with ID 5678 .EXAMPLE New-AGMMount -imageid 53776703 -jsonbody '{"@type":"mountRest","label":"test mount","host":{"id":"43673548"},"poweronvm":false,"migratevm":false}' Mounts image ID 53776703 to target host with ID 43673548 with Label "test mount". The jsonbody field needs to be well formed JSON. You can get this by running a mount job in the AGM GUI and then immediately displaying the audit log with: Get-AGMAudit -filtervalue "command~POST https" -limit 1 -sort id:desc .DESCRIPTION A function to mount an Image #> if (!($imageid)) { [string]$imageid = Read-Host "ImageID to mount" } if ( (!($jsonbody)) -and (!($targethostid)) ) { [string]$targethostid = Read-Host "Target host ID to mount $imageid to" if (!($label)) { [string]$label = Read-Host "Label to apply to newly mounted image" } } if ($targethostid) { $body = @{ label = $label; host = @{id=$targethostid} } $jsonbody = $body | ConvertTo-Json } Post-AGMAPIData -endpoint /backup/$imageid/mount -body $jsonbody } Function New-AGMSLA ([string]$appid,[string]$slpid,[string]$sltid,[string]$jsonbody,[string]$scheduler) { <# .SYNOPSIS Creates an SLA .EXAMPLE New-AGMSLA -appid 1234 -sltid 5678 -slpid 9012 -scheduler disabled Creates a new SLA using APPID, SLT ID and SLP ID with scheduler disabled. Details about the new SLA will be returned. The scheduler is disabled so options can be set. You can enable the scheduler with Set-AGMSLA If no options are needed, you don't need to specify scheduler state .DESCRIPTION A function to create an SLA #> if (($id) -and (!($appid)) ) { $appid = $id } if (!($sltid)) { $sltid = Read-Host "SLT ID" } if (!($slpid)) { $slpid = Read-Host "SLP ID" } if (!($jsonbody)) { $application = New-Object -TypeName psobject $application | Add-Member -MemberType NoteProperty -Name id -Value $appid $slp = New-Object -TypeName psobject $slp | Add-Member -MemberType NoteProperty -Name id -Value $slpid $slt = New-Object -TypeName psobject $slt | Add-Member -MemberType NoteProperty -Name id -Value $sltid $body = New-Object -TypeName psobject $body | Add-Member -MemberType NoteProperty -name application -Value $application if (!($scheduler)) { $body | Add-Member -MemberType NoteProperty -Name scheduleoff -Value "false" } if ($scheduler.ToLower() -eq "enable") { $body | Add-Member -MemberType NoteProperty -Name scheduleoff -Value "false" } if ($scheduler.ToLower() -eq "disable") { $body | Add-Member -MemberType NoteProperty -Name scheduleoff -Value "true" } $body | Add-Member -MemberType NoteProperty -name slp -Value $slp $body | Add-Member -MemberType NoteProperty -name slt -Value $slt $jsonbody = $body | ConvertTo-Json } Post-AGMAPIData -endpoint /sla -body $jsonbody } Function New-AGMUser ([string]$name,[string]$timezone,[string]$rolelist,[string]$orglist) { <# .SYNOPSIS Creates a User .EXAMPLE New-AGMUser -name "user@user.user" -rolelist "2,3" -orglist "4,5" Creates a new user .DESCRIPTION A function to create a User #> if (!($name)) { Get-AGMErrorMessage -messagetoprint "Specify a username in email format with -name" return } if ($AGMToken) { if ($name -notlike "*@*") { Get-AGMErrorMessage -messagetoprint "Specify a username in email format with -name" return } } if (!($rolelist)) { Get-AGMErrorMessage -messagetoprint "Specify a comma separated rolelist with -rolelist" return } if ($rolelist) { $rolebody = @() foreach ($role in $rolelist.Split(",")) { $rolebody += New-Object -TypeName psobject -Property @{id="$role"} } } if ($orglist) { $orgbody = @() foreach ($org in $orglist.Split(",")) { $orgbody += New-Object -TypeName psobject -Property @{id="$org"} } } $body = [ordered]@{ name = $name; dataaccesslevel = "0"; timezone = $timezone; rolelist = $rolebody orglist = $orgbody } $jsonbody = $body | ConvertTo-Json Post-AGMAPIData -endpoint /user -body $jsonbody } |