Public/Restore-AGMLibSAPHANA.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 Restore-AGMLibSAPHANA ([string]$appid,[string]$targethostid,[string]$mountapplianceid,[string]$imagename,[string]$imageid,[string]$targethostname,[string]$appname,[string]$recoverypoint,[string]$label,[string]$dbsid,[string]$userstorekey,[string]$jsonprint,[switch][alias("g")]$guided,[switch]$preflight,[switch]$replacesource,[switch]$copyhdbstorekey) 
{
    <#
    .SYNOPSIS
    Restores a SAP HANA Database Image. Note that this command has different syntax requirements when issued to an AGM versus a Management Console.

    .EXAMPLE
    Restore-AGMLibSAPHANA
    You will be prompted through a guided menu.

    .EXAMPLE
    Restore-AGMLibSAPHANA -appid 577110 -mountapplianceid 141767697828 -targethostid 483699 -dbsid "TGT" -userstorekey "ACTBACKUP"
    Restores an SAP HANA Database with specified SID when using Google Cloud Backup and DR

    .EXAMPLE
    Restore-AGMLibSAPHANA -appid 577110 -userstorekey "ACTBACKUP"
    Restores an SAP HANA Database when sent to Actifio Global Manager

    .DESCRIPTION
    A function to restore a SAP HANA database

    * Image selection can be done three ways:

    1) Run this command in guided mode to learn the available images and select one
    2) Learn the imagename and specify that as part of the command with -imagename
    3) Learn the Appid and Cluster ID for the appliance that will restore the image and then use -appid and -mountapplianceid
    This will use the latest snapshot, StreamSnap or OnVault image on that appliance. AGM does not need the Cluster ID

    * Restore host options (Google Cloud Backup and DR only)
    -mountapplianceid The appliance where the restore will be run.
    -targethostname The target host specified by name (targethostid can also be used)
    -targethostid The target host specified by id (targethostname can also be used)

    * required settings
    -userstorekey xxxx name of the HANA database user store key on the target server where a new SAP HANA Instance will get restored

    * Other options
     -label Label for restore, recommended
    -recoverypoint The point in time to roll forward to, in ISO8601 format like 2020-09-02 19:00:02

    #>


    # its pointless procededing without a connection.
    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
    }

    if (($appname) -and (!($appid)) )
    {
        $appgrab = Get-AGMApplication -filtervalue appname=$appname
        if ($appgrab.id.count -ne 1)
        { 
            Get-AGMErrorMessage -messagetoprint "Failed to resolve $appname to a single App ID. Use Get-AGMLibApplicationID and try again specifying -appid."
            return
        }
        else {
            $appid = $appgrab.id
            $apptype = $appgrab.apptype
        }
    }

    if ( ($appid) -and (!($appname)) )
    {
        $appgrab = Get-AGMApplication -id $appid
        if(!($appgrab))
        {
            Get-AGMErrorMessage -messagetoprint "Cannot find appid $appid"
            return
        }
        else 
        {
            $appname = ($appgrab).appname
            $apptype = $appgrab.apptype
        }
    }

    # if recovery point specified without imagename or ID
    if ( ($recoverypoint) -and (!($imagename)) -and (!($imageid)) -and ($appid) )
    {
        $imagecheck = Get-AGMImage -filtervalue "appid=$appid&consistencydate<$recoverypoint&endpit>$recoverypoint" -sort id:desc -limit 1
        if (!($imagecheck))
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find an image for appid $appid with a recovery point suitable for required ENDPit $recoverypoint "
            return
        }
    }

    # learn about the image if supplied a name
    if ( ($imagename) -and (!($imageid)) )
    {
        $imagecheck = Get-AGMImage -filtervalue backupname=$imagename
        if (!($imagecheck))
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find $imagename using: Get-AGMImage -filtervalue backupname=$imagename"
            return
        }
        else 
        {
            $imagegrab = Get-AGMImage -id $imagecheck.id
            $imageid = $imagegrab.id
            $consistencydate = $imagegrab.consistencydate
            $endpit = $imagegrab.endpit
            $appname = $imagegrab.appname
            $appid = $imagegrab.application.id
            $apptype = $imagegrab.apptype      
            $mountapplianceid = $imagegrab.cluster.clusterid   
            $dbsid = ($imagegrab.provisioningoptions | where-object {($_.key -eq "dbsid")}).value
            if (!($userstorekey)) { $userstorekey = ($imagegrab.provisioningoptions | where-object {($_.key -eq "DBUSER")}).value }
        }
    }

    # learn about the image if supplied an ID
    if ( ($imageid) -and (!($imagename)) )
    {
        $imagegrab = Get-AGMImage -filtervalue id=$imageid
        if (!($imagegrab))
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find Image ID $imageid using: Get-AGMImage -filtervalue id=$imageid"
            return
        }
        else 
        {
            $consistencydate = $imagegrab.consistencydate
            $endpit = $imagegrab.endpit
            $appname = $imagegrab.appname
            $appid = $imagegrab.application.id
            $apptype = $imagegrab.apptype      
            $mountapplianceid = $imagegrab.cluster.clusterid
            $dbsid = ($imagegrab.provisioningoptions | where-object {($_.key -eq "dbsid")}).value
            if (!($userstorekey)) { $userstorekey = ($imagegrab.provisioningoptions | where-object {($_.key -eq "DBUSER")}).value }
        }
    }



    # if the user gave us nothing to start work, then enter guided mode
    if (( (!($appname)) -and (!($imagename)) -and (!($appid)) ) -or ($guided))
    {
        $guided = $true

        # first we need to work out which appliance we are mounting from
        $appliancegrab = Get-AGMAppliance | select-object name,clusterid | sort-object name
        if ($appliancegrab.count -eq 0)
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find any appliances to list."
            return
        }
        if ($appliancegrab.name.count -eq 1)
        {
            $mountapplianceid = $appliancegrab.clusterid
            $mountappliancename =  $appliancegrab.name
        }
        else
        {
            Clear-Host
            write-host "Appliance selection menu - which Appliance will run this restore"
            Write-host ""
            $i = 1
            foreach ($appliance in $appliancegrab)
            { 
                Write-Host -Object "$i`: $($appliance.name)"
                $i++
            }
            While ($true) 
            {
                Write-host ""
                $listmax = $appliancegrab.name.count
                [int]$appselection = Read-Host "Please select the Appliance that will run the restore (1-$listmax)"
                if ($appselection -lt 1 -or $appselection -gt $listmax)
                {
                    Write-Host -Object "Invalid selection. Please enter a number in range [1-$($listmax)]"
                } 
                else
                {
                    break
                }
            }
            $mountapplianceid =  $appliancegrab.clusterid[($appselection - 1)]
            $mountappliancename =  $appliancegrab.name[($appselection - 1)]
        }
        write-host ""
        write-host "Running guided mode"
        write-host ""
        write-host "Application Select menu"
        write-host ""
        write-host "Select application status for SAP HANA apps with images"
        Write-host ""
        Write-Host "1`: Managed local apps (default)"
        Write-Host "2`: Unmanaged or imported apps"
        Write-Host "3`: Imported/mirrored apps (from other Appliances). If you cannot see imported apps, you may need to first run: Import-AGMLibOnVault"
        Write-Host ""
        [int]$userselectionapps = Read-Host "Please select from this list (1-3)"
        if ($userselectionapps -eq "" -or $userselectionapps -eq 1)  { $applist = Get-AGMApplication -filtervalue "managed=true&apptype=SAPHANA&sourcecluster=$mountapplianceid" | sort-object appname }
        if ($userselectionapps -eq 2) { $applist = Get-AGMApplication -filtervalue "managed=false&apptype=SAPHANA&sourcecluster=$mountapplianceid" | sort-object appname  }
        if ($userselectionapps -eq 3) { $applist = Get-AGMApplication -filtervalue "apptype=SAPHANA&sourcecluster!$mountapplianceid&clusterid=$mountapplianceid" | sort-object appname }

        if ($applist.count -eq 0)
        {
            if ($userselectionapps -eq "" -or $userselectionapps -eq 1)  { Get-AGMErrorMessage -messagetoprint "There are no managed SAP HANA apps to list" }
            if ($userselectionapps -eq 2)  { Get-AGMErrorMessage -messagetoprint "There are no unmanaged SAP HANA apps to list" }
            if ($userselectionapps -eq 3)  { Get-AGMErrorMessage -messagetoprint "There are no imported SAP HANA apps to list. You may need to run Import-AGMLibOnVault first" }
            return
        }
        if ($applist.id.count -eq 0)
        { 
            Get-AGMErrorMessage -messagetoprint "Failed to find any $apptype apps"
            return
        }
        $i = 1
        foreach ($app in $applist)
        { 
            $applistname = $app.appname
            $appliance = $app.cluster.name 
            Write-Host -Object "$i`: $applistname ($appliance)"
            $i++
        }
        While ($true) 
        {
            Write-host ""
            $listmax = $applist.appname.count
            [int]$appselection = Read-Host "Please select an Application (1-$listmax)"
            if ($appselection -lt 1 -or $appselection -gt $listmax)
            {
                Write-Host -Object "Invalid selection. Please enter a number in range [1-$($listmax)]"
            } 
            else
            {
                break
            }
        }
        if ($applist.appname.count -eq 1)
        {
            $appname = $applist.appname
            $appid = $applist.id
        }
        else 
        {
            $appname = $applist.appname[($appselection - 1)]
            $appid = $applist.id[($appselection - 1)]
        }
    }

    if ( ($targethostname) -and (!($targethostid)) )
    {
        $hostcheck = Get-AGMHost -filtervalue hostname=$targethostname
        if ($hostcheck.id.count -ne 1)
        { 
            Get-AGMErrorMessage -messagetoprint "Failed to resolve $targethostname to a single host ID. Use Get-AGMLibHostID and try again specifying -targethostid"
            return
        }
        else {
            $hostgrab = Get-AGMHost -id $hostcheck.id
            $targethostid = $hostgrab.id
        }
    }

    if ( ($targethostid) -and (!($targethostname)) )
    {
        $hostgrab = Get-AGMHost -filtervalue id=$targethostid
        if (!($hostgrab))
        {
            Get-AGMErrorMessage -messagetoprint "Failed to resolve $targethostid to a single host ID. Use Get-AGMLibHostID and try again specifying -targethostid"
            return
        }
        $targethostid = $targethostid
        $targethostname=$hostgrab.hostname
    }
    
    # this if for guided menu
    if ($guided)
    {
       if (!($label))
       {
           Clear-Host
           [string]$label = Read-host "Label"
       }
        
        if (!($imagename))
        {  
             # prefered sourcce
             write-host ""
             $userselection = ""
             Write-Host "Image selection"
             Write-Host "1`: Use the most recent backup for lowest RPO (default)"
             Write-Host "2`: Select a backup"
             Write-Host ""
             While ($true) 
             {
                 [int]$userselection = Read-Host "Please select from this list (1-2)"
                 if ($userselection -eq "") { $userselection = 1 }
                 if ($userselection -lt 1 -or $userselection -gt 2)
                 {
                     Write-Host -Object "Invalid selection. Please enter a number in range [1-2]"
                 } 
                 else
                 {
                     break
                 }
             }
             if ($userselection -eq 1)
             {
 
                 $imagelist1 = Get-AGMImage -filtervalue "appid=$appid&jobclass=snapshot&jobclass=StreamSnap&jobclass=OnVault&targetuds=$mountapplianceid" -sort "consistencydate:desc,jobclasscode:desc" -limit 1
                 
                 if ($imagelist1.id.count -eq 1)
                 {   
                    $imagegrab = Get-AGMImage -id $($imagelist1).id
                    $imagename = $imagegrab.backupname                
                    $consistencydate = $imagegrab.consistencydate
                    $endpit = $imagegrab.endpit
                    $appname = $imagegrab.appname
                    $appid = $imagegrab.application.id
                    $apptype = $imagegrab.apptype      
                    $jobclass = $imagegrab.jobclass
                    $mountapplianceid = $imagegrab.cluster.clusterid
                    $mountappliancename = $imagegrab.cluster.name
                    $sourcehostname = $imagegrab.host.hostname
                    $sourcehostid = $imagegrab.host.id
                    $sourcedbuser = ($imagegrab.provisioningoptions | where-object {($_.key -eq "DBUSER")}).value
                    write-host "Found one $jobclass image $imagename, consistency date $consistencydate on $mountappliancename"
                     Write-host ""
                 }
                 else 
                 {
                     Get-AGMErrorMessage -messagetoprint "Failed to fetch an image for appid $appid"   
                     return
                 }
             }
             if ($userselection -eq 2) 
             { 
                $imagelist1 = Get-AGMImage -filtervalue "appid=$appid&jobclass=snapshot&jobclass=StreamSnap&jobclass=OnVault&targetuds=$mountapplianceid"  | Sort-Object consistencydate,jobclass
                if ($imagelist1.id.count -eq 0)
                {
                    Get-AGMErrorMessage -messagetoprint "Failed to fetch any Images for appid $appid"
                    return
                }
                $imagelist = $imagelist1  | Sort-Object consistencydate
                if ($imagelist1.id.count -eq 1)
                {
                    $imagegrab = Get-AGMImage -id $($imagelist1).id
                    $imagename = $imagegrab.backupname                
                    $consistencydate = $imagegrab.consistencydate
                    $endpit = $imagegrab.endpit
                    $appname = $imagegrab.appname
                    $appid = $imagegrab.application.id
                    $apptype = $imagegrab.apptype      
                    $jobclass = $imagegrab.jobclass
                    $mountapplianceid = $imagegrab.cluster.clusterid
                    $mountappliancename = $imagegrab.cluster.name
                    $sourcehostname = $imagegrab.host.hostname
                    $sourcehostid = $imagegrab.host.id

                    $sourcedbuser = ($imagegrab.provisioningoptions | where-object {($_.key -eq "DBUSER")}).value
                    write-host "Found one $jobclass image $imagename, consistency date $consistencydate on $mountappliancename"
                } 
                else
                {
                    Clear-Host
                    Write-Host "Image list. Choose the best jobclass and consistency date on the best appliance"
                    write-host ""
                    $i = 1
                    foreach ($image in $imagelist)
                    { 
                        $image | Add-Member -NotePropertyName select -NotePropertyValue $i
                        $image | Add-Member -NotePropertyName appliancename -NotePropertyValue $image.cluster.name
                        $i++
                    }
                    #print the list
                    $imagelist | select-object select,consistencydate,jobclass,appliancename,backupname,id | Format-table *
                    # ask the user to choose
                    While ($true) 
                    {
                        Write-host ""
                        $listmax = $imagelist.Length
                        [int]$imageselection = Read-Host "Please select an image (1-$listmax)"
                        if ($imageselection -lt 1 -or $imageselection -gt $imagelist.Length)
                        {
                            Write-Host -Object "Invalid selection. Please enter a number in range [1-$($imagelist.Length)]"
                        } 
                        else
                        {
                            break
                        }
                    }
                    $imageid =  $imagelist[($imageselection - 1)].id
                    $imagegrab = Get-AGMImage -id $imageid
                    $imagename = $imagegrab.backupname                
                    $consistencydate = $imagegrab.consistencydate
                    $endpit = $imagegrab.endpit
                    $appname = $imagegrab.appname
                    $appid = $imagegrab.application.id
                    $apptype = $imagegrab.apptype      
                    $mountapplianceid = $imagegrab.cluster.clusterid
                    $mountappliancename = $imagegrab.cluster.name 
                    $sourcehostname = $imagegrab.host.hostname
                    $sourcehostid = $imagegrab.host.id
                    $sourcedbuser = ($imagegrab.provisioningoptions | where-object {($_.key -eq "DBUSER")}).value
                }
             }
        }
        
        # now we check the log date
        if ($endpit)
        {
            write-host ""
            $recoverypoint = Read-Host "Roll forward time (hitting enter to use all available logs)`: $consistencydate to $endpit"
            if ($recoverypoint)
            {
                if ([datetime]$recoverypoint -lt $consistencydate)
                {
                    Get-AGMErrorMessage -messagetoprint "Specified recovery point $recoverypoint is earlier than image consistency date $consistencydate. Specify an earlier image."
                    return
                }
                elseif ([datetime]$recoverypoint -gt $endpit)
                {
                    Get-AGMErrorMessage -messagetoprint "Specified recovery point $recoverypoint is later than available logs that go to $endpit"
                    return
                }
            }
            else {
                $recoverypoint = $endpit
            }
        }
        


        if ( (!($targethostname)) -and (!($targethostid)))
        {
            # target host
            if ($AGMToken)
            {
                write-host ""
                $userselection = ""
                Write-Host "Target host selection"
                Write-Host "1`: Restore back to the source host (default)"
                Write-Host "2`: Restore to a new target"
                Write-Host ""
                While ($true) 
                {
                    [int]$targetselection = Read-Host "Please select from this list (1-2)"
                    if ($targetselection -eq "") { $targetselection = 1 }
                    if ($targetselection -lt 1 -or $targetselection -gt 2)
                    {
                        Write-Host -Object "Invalid selection. Please enter a number in range [1-2]"
                    } 
                    else
                    {
                        break
                    }
                }
                write-host ""
                $userstorekey = read-host "SAP HANA Target user store key or press enter to use $sourcedbuser"
            }
            else {
                # we need to ask for SAB DB User Store-key
                write-host ""
                While ($true) 
                {
                    [string]$userstorekey = Read-Host "SAP DB User Store Key"
                    if (!($userstorekey))
                    {
                        write-host "User key field cannot be blank" 
                    } 
                    else
                    {
                        break
                    }
                }
                # we can only restore to source host
                $targetselection = 1
            }
            if ($targetselection -eq 1)
            {
                $targethostname = $sourcehostname
                $targethostid = $sourcehostid
            }
            else 
            {
                $hostgrab = Get-AGMHost -filtervalue "sourcecluster=$mountapplianceid" | sort-object name
                if ($hostgrab -eq "" )
                {
                    Get-AGMErrorMessage -messagetoprint "Cannot find any Linux hosts"
                    return
                }
                Clear-Host
                Write-Host "Target host selection menu"
                $i = 1
                $printarray = @()
                foreach ($listedhost in $hostgrab)
                { 
                    $printarray += [pscustomobject]@{
                        id = $i
                        hostname = $listedhost.name
                        hostid = $listedhost.id
                        vmtype = $listedhost.vmtype
                    }
                    $i++
                }
                #print the list
                $printarray | Format-table 
                write-host ""
                While ($true) 
                {
                    $listmax = $hostgrab.name.count
                    [int]$hostselection = Read-Host "Please select a host (1-$listmax)"
                    if ($hostselection -lt 1 -or $hostselection -gt $listmax)
                    {
                        Write-Host -Object "Invalid selection. Please enter a number in range [1-$($listmax)]"
                    } 
                    else
                    {
                        break
                    }
                }
                if ($hostgrab.name.count -eq 1)
                {
                    $targethostname =  $hostgrab.name
                    $targethostid = $hostgrab.id
                } else {
                    $targethostname =  $hostgrab.name[($hostselection - 1)]
                    $targethostid = $hostgrab.id[($hostselection - 1)]
                }
                $hostgrab = Get-AGMHost -id $targethostid
                $targethostid = $hostgrab.id

                 # target host
                write-host ""
                $replacehostselection = ""
                Write-Host "REPLACE ORIGINAL APPLICATION IDENTITY"
                Write-Host "1`: No (default)"
                Write-Host "2`: Yes"
                Write-Host ""
                [int]$replacehostselection = Read-Host "Please select from this list (1-2)"

                if ($replacehostselection -eq "") { $replacehostselection = 1 }
                if ($replacehostselection -eq 1) { $replacesource = $false }
                if ($replacehostselection -eq 2) { $replacesource = $true }
            }
        }
    

        write-host ""
        if ($userstorekey -eq "")
        {
            $userstorekey = $sourcedbuser
        } 
        if (!($AGMToken))
        {
            write-host ""
            $userselection = ""
            Write-Host "Copy HDB User Store Key to target Host"
            Write-Host "1`: No (default)"
            Write-Host "2`: Yes"
            Write-Host ""
            [int]$replacehostselection = Read-Host "Please select from this list (1-2)"

            if ($replacehostselection -eq "") { $replacehostselection = 1 }
            if ($replacehostselection -eq 1) { $copyhdbstorekey = $false }
            if ($replacehostselection -eq 2) { $copyhdbstorekey = $true }
        }

        Write-host ""

    
        # we are done
       Clear-Host  
        Write-Host "Guided selection is complete. The values entered resulted in the following commands."
        if ($AGMToken)
        {
            Write-host "You should run the pre-flight first (first command) to validate restore will run without error before running the actual restore (second command)."
            Write-Host ""
        
            Write-Host -nonewline "Restore-AGMLibSAPHANA -appid $appid -mountapplianceid $mountapplianceid -imagename $imagename -targethostid $targethostid -userstorekey `"$userstorekey`""
            if ($label)
            {
                Write-Host -nonewline " -label `"$label`""
            }
            if ($recoverypoint)
            {
                Write-Host -nonewline " -recoverypoint `"$recoverypoint`""
            }
            if ($replacesource -eq $true)
            {
                Write-Host -nonewline " -replacesource"
            }
            Write-Host -nonewline " -preflight"
        }
        Write-Host ""
        Write-Host -nonewline "Restore-AGMLibSAPHANA -appid $appid -imagename $imagename -userstorekey `"$userstorekey`""
        if ($label)
        {
            Write-Host -nonewline " -label `"$label`""
        }
        if ($recoverypoint)
        {
            Write-Host -nonewline " -recoverypoint `"$recoverypoint`""
        }
        if ($replacesource -eq $true)
        {
            Write-Host -nonewline " -replacesource"
        }
        if ($copyhdbstorekey -eq $true)
        {
            Write-Host -nonewline " -copyhdbstorekey"
        }
        Write-Host ""
        Read-Host "Please enter to exit"
        return
    }



    if (($appid) -and ($mountapplianceid) -and (!($imageid)))
    {
        # if we are not running guided mode but we have an appid without imageid, then lets get the latest image on the mountappliance ID
        $imagegrab = Get-AGMImage -filtervalue "appid=$appid&targetuds=$mountapplianceid&jobclass=snapshot&jobclass=StreamSnap&jobclass=OnVault" -sort "consistencydate:desc,jobclasscode:asc" -limit 1
        if ($imagegrab.id.count -eq 1)
        {   
            $imagegrab1 = Get-AGMImage -id $($imagegrab).id
            $imageid = $imagegrab1.id
            $imagename = $imagegrab1.backupname
            $targethostid = $imagegrab1.host.id
            
            $dbsid = ($imagegrab1.provisioningoptions | where-object {($_.key -eq "dbsid")}).value
            if (!($userstorekey)) { $userstorekey = ($imagegrab1.provisioningoptions | where-object {($_.key -eq "DBUSER")}).value }
            if ($imagegrab1.endpit) { $recoverypoint = $imagegrab1.endpit }
        } 
        else 
        {
            Get-AGMErrorMessage -messagetoprint "Failed to fetch a snapshot, StreamSnap or OnVault Image for appid $appid on appliance with clusterID $mountapplianceid"
            return
        }
    }

    if (($targethostid -eq "") -and ($AGMToken))
    {
        Get-AGMErrorMessage -messagetoprint "Cannot proceed without a targethostid or targethostname"
        return
    }

    
    # learn about the image
    if (!($imagename)) 
    {
        Get-AGMErrorMessage -messagetoprint "No image was found to mount"
        return
    }

    # recovery point handling
    if ($recoverypoint)
    {
        $recoverytime = Convert-ToUnixDate $recoverypoint
    }
    
    if (!($label))
    {
        $label = ""
    }


    if (!($userstorekey))
    {
        Get-AGMErrorMessage -messagetoprint "No HANA user store key was specified"
        return
    }


    $provisioningoptions = @()
    $provisioningoptions = $provisioningoptions +[ordered]@{
        name = 'dbsid'
        value = $dbsid
    }
    $provisioningoptions = $provisioningoptions +[ordered]@{
        name = 'DBUSER'
        value = $userstorekey
    }
    # this is for 10.0.x only
    if (!($copyhdbstorekey)) { $copyhdbstorekey = $false}
    # build body
    $body = [ordered]@{}
    if ($label) { $body = $body + [ordered]@{ label = $label; }}
    if ($AGMToken)
    {
        if ($replacesource -eq $true) { $body = $body + [ordered]@{ replacesource = $true; } } else { $body = $body + [ordered]@{ replacesource = $false; } }
        $body = $body + [ordered]@{
            host = @{id=$targethostid};
            hostclusterid = $mountapplianceid;
            provisioningoptions = $provisioningoptions;
        }
    }
    else {
        $restoreoptions = @()
        $restoreoptions = $restoreoptions +[ordered]@{
            name = 'copyhdbstorekey'
            value = $copyhdbstorekey
        }
        $restoreoptions = $restoreoptions +[ordered]@{
            name = 'restoreuserstorekey'
            value = $userstorekey
        }
        
        $body = $body + [ordered]@{
            restoreoptions = $restoreoptions
        }
    }
    if ($recoverytime)
    {
        $body = $body +[ordered]@{ recoverytime = [string]$recoverytime }
    }
    

    $json = $body | ConvertTo-Json -depth 10


    if ($jsonprint -eq "yes")
    {
        $compressedjson = $body | ConvertTo-Json -compress -depth 10
        Write-host "This is the final command:"
        Write-host ""
        Write-host "Post-AGMAPIData -endpoint /backup/$imageid/restore -body `'$compressedjson`'"
        return
    }

    if ($preflight)
    {
        $preflighttest = Post-AGMAPIData  -endpoint /backup/$imageid/restorepreflight -body $json
        if ($preflighttest.testlist)
        {
            $preflighttest.testlist
        }
        else {
            $preflighttest
        }
    }
    else {
        Post-AGMAPIData  -endpoint /backup/$imageid/restore -body $json
    }
}