Public/Import-AGMLibOnvault.ps1

# Copyright 2023 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 Import-AGMLibOnVault([string]$diskpoolid,[string]$applianceid,[string]$appid,[switch][alias("f")]$forget,[switch][alias("m")]$monitor,[switch][alias("o")]$ownershiptakeover,[switch]$listapps,[switch]$listdiskpools,[switch]$listapplianceids) 
{
    <#
    .SYNOPSIS
    Imports or forgets OnVault images
    There is no Forget-AGMOnVault command. You perform both import and forget from this function.

    .EXAMPLE
    Import-AGMLibOnvault -listdiskpools

    List all disk pools. The appliance is the Appliance that will be targeted for import.
    You will use the diskpoolid as part of all further commands

    .EXAMPLE
    Import-AGMLibOnvault -diskpoolid 199085 -listapplianceids

    List all appliances that have written to diskpoolid 12717.
    You will use the applianceid as part of all further commands. It is the Appliance that wrote the backups

    .EXAMPLE
    Import-AGMLibOnvault -diskpoolid 199085 -applianceid 144488110379 -listapps

    Examines all OnVault images found in disk pool ID 199085 created by Appliance ID 144488110379 and lists all applications so you can learn app IDs.
    You will use the app ID as part of all commands where you want to import a specific application rather than the whole pool.

    .EXAMPLE
    Import-AGMLibOnvault -diskpoolid 199085 -applianceid 144488110379

    Imports all OnVault images found in disk pool ID 199085 created by Appliance ID 144488110379

    .EXAMPLE
    Import-AGMLibOnvault -diskpoolid 199085 -applianceid 144488110379 -monitor

    Imports all OnVault images found in disk pool ID 199085 created by Appliance ID 144488110379 and monitors until import is complete

    .EXAMPLE
    Import-AGMLibOnVault -diskpoolid 199085 -applianceid 144488110379 -appid 4788
    
    Imports all OnVault images found in disk pool ID 199085 and source App ID 4788 (from the source appliance) created by Appliance ID 144488110379

    .EXAMPLE
    Import-AGMLibOnVault -diskpoolid 199085 -applianceid 144488110379 -appid 4788 -owner
    
    Imports all OnVault images found in disk pool ID 199085 and source App ID 4788 (from the source appliance) created by Appliance ID 144488110379 and takes ownership

    .EXAMPLE
    Import-AGMLibOnVault -diskpoolid 199085 -applianceid 144488110379 -appid 4788 -forget
    
    Forgets all OnVault images imported found in disk pool ID 199085 and source App ID 4788 (from the source appliance) onto Appliance ID 144488110379

    .DESCRIPTION
    A function to import OnVault images

    #>


    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

    }
    # list apps
    if (($listapps) -and ($diskpoolid) -and ($applianceid))
    {
        $applicationgrab = Get-AGMAPIData -endpoint /diskpool/$diskpoolid/vaultclusters/$applianceid 
        if ($applicationgrab.host)
        {
            $printarray = @()
            foreach ($app in $applicationgrab)
            {       
                $printarray += [pscustomobject]@{
                hostname = $app.host.hostname
                appname = $app.application.appname
                appid = $app.application.srcid
                backupcount = $app.backupcount
                }
            }
            $printarray | sort-object hostname,appname
            return
        }
        else {
            Get-AGMErrorMessage -messagetoprint "Failed to find any application images to list"
            return
        }
    }
     # list pools
     if ($listdiskpools)
     {
        $diskpoolgrab = Get-AGMDiskPool -filtervalue pooltype=vault | Sort-Object name
        if ($diskpoolgrab.count -eq 0)
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find any disk pools to list"
            return
        }
        else
        {
            $printarray = @()
            foreach ($pool in $diskpoolgrab)
            {       
                $printarray += [pscustomobject]@{
                poolname = $pool.name
                diskpoolid = $pool.id
                appliancename = $pool.cluster.name
                }
            }
            $printarray | sort-object poolname,appliancename
            return
        }
     }
    # list appliance
    if (($listapplianceids) -and ($diskpoolid))
    {
        $appliancegrab = Get-AGMAPIData -endpoint /diskpool/$diskpoolid/vaultclusters
        if ($appliancegrab.cluster.clusterid.count -eq 0)
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find any appliances to list"
            return
        }
        
        else
        {
            $printarray = @()
            foreach ($appliance in $appliancegrab.cluster)
            {       
                $printarray += [pscustomobject]@{
                appliancename = $appliance.name
                applianceid = $appliance.clusterid
                }
            }
            $printarray | sort-object appliancename
            return
        }
    }


    if ((!($diskpoolid)) -or (!($applianceid)))
    {

        write-host ""
        Write-Host "This function is used to import OnVault images into an Appliance."
        Write-host "We need to determine which pool to import from and which appliance created the images to import"
        Write-host "If importing we also need to decide whether the importing appliance (which owns the selected pool) should take ownership of the imported images"
        Write-host "Alternatively we can decide to have the appliance forget any previously imported images, rather than discover new ones"
        write-host "If you are having what look like timeout issues, please run connect-agm with a -agmtimeout value larger than then the default of 60 seconds"
        Write-host ""

        $diskpoolgrab = Get-AGMDiskPool -filtervalue pooltype=vault | Sort-Object name
        if ($diskpoolgrab.count -eq 0)
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find any disk pools to list"
            return
        }
        if ($diskpoolgrab.count -eq 1)
        {
            $diskpoolid = $diskpoolgrab.id
            write-host "Only one OnVault diskpool was found. We will use this one:" 
            write-host ""
            write-host $diskpoolgrab.name "(ID: $diskpoolid)"
            write-host ""
        }
        else
        {
            write-host "Pool selection menu - which Diskpool will we look into for images to import (which also determines which Appliance we import into)"
            Write-host ""
            $i = 1
            foreach ($pool in $diskpoolgrab)
            { 
                Write-Host -Object "$i`: $($pool.name) (ID: $($pool.id)) on $($pool.cluster.name)"
                $i++
            }
            While ($true) 
            {
                Write-host ""
                $listmax = $diskpoolgrab.name.count
                [int]$poolselection = Read-Host "Please select a Diskpool to import from (1-$listmax)"
                if ($poolselection -lt 1 -or $poolselection -gt $listmax)
                {
                    Write-Host -Object "Invalid selection. Please enter a number in range [1-$($listmax)]"
                } 
                else
                {
                    break
                }
            }
            $diskpoolid = $diskpoolgrab.id[($poolselection - 1)]
        }
        

        write-host "Inspecting the disk pool for source appliances"
        write-host ""
        $appliancegrab = Get-AGMAPIData -endpoint /diskpool/$diskpoolid/vaultclusters
        if ($appliancegrab.cluster.clusterid.count -eq 0)
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find any appliances to list"
            return
        }
        if ($appliancegrab.cluster.clusterid.count -eq 1)
        {
            $applianceid = $appliancegrab.cluster.clusterid
            $appliancename = $appliancegrab.cluster.name
            write-host "Only one Appliance was found. We will use this one:"
            write-host ""
            write-host "$appliancename (ID: $applianceid)"
            write-host ""
        }
        else
        {
            write-host "Source appliance selection menu - which Appliance will we import from (this is the Appliance that made the images)"
            Write-host ""
            $i = 1
            foreach ($appliance in $appliancegrab.cluster)
            { 
                Write-Host -Object "$i`: $($appliance.name) (ID: $($appliance.clusterid))"
                $i++
            }
            While ($true) 
            {
                Write-host ""
                $listmax = $appliancegrab.cluster.name.count
                [int]$appselection = Read-Host "Please select the source appliance (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
                }
            }
            $applianceid = $appliancegrab.cluster.clusterid[($appselection - 1)]
            $appliancename = $appliancegrab.cluster.name[($appselection - 1)]
        }
        Write-Host ""
        write-host "Inspecting the disk pool for source applications created by source Appliance $appliancename"
        $applicationgrab = Get-AGMAPIData -endpoint /diskpool/$diskpoolid/vaultclusters/$applianceid 
        if ($applicationgrab.host)
        {
            $firstarray = @()
            
            foreach ($app in $applicationgrab)
            {       
                $firstarray += [pscustomobject]@{
                hostname = $app.host.hostname
                appname = $app.application.appname
                appid = $app.application.srcid
                backupcount = $app.backupcount
                }
            }
            $listmax = $firstarray.appid.count
            $firstarray = $firstarray | Sort-Object hostname,appname
            $printarray = @()
            $i=1
            foreach ($app in $firstarray)
            {       
                $printarray += [pscustomobject]@{
                id = $i
                hostname = $app.hostname
                appname = $app.appname
                appid = $app.appid
                backupcount = $app.backupcount
                }
                $i++
            }
            if ($listmax -gt 1)
            {
                $appselection = ""
                write-host ""
                write-host "Source applications created by $appliancename"
                write-host ""
                $printarray | Format-Table
                write-host ""
                [int]$appselection = Read-Host "Please select a source application or press enter to import all applications (1-$listmax)"
                if ( $appselection -gt $listmax)
                {
                    Write-Host -Object "Invalid selection. Please enter a number in range ($listmax)"
                } 
                if ($appselection)
                {
                    $appid = $printarray.appid[($appselection - 1)]
                }
            }
            else {
                $printarray
            }
        }
        else {
            Get-AGMErrorMessage -messagetoprint "Failed to find any application images to list"
            return
        }
        write-host "Found the following images."
        $printarray | sort-object hostname,appname | Format-Table

        Write-Host ""
        Write-Host "Do you want to import these images?"
        Write-Host ""
        Write-Host "1`: Yes I want to import them (default)"
        Write-Host "2`: Exit (this is not the disk pool I was looking for)"
        $ownerchoice = Read-Host "Please select from this list (1-2)"
        if ($ownerchoice -eq 2) { return }
        Write-Host ""
        Write-Host "Do you want to have the selected appliance take ownership of any images."
        Write-Host ""
        Write-Host "1`: Don't take ownership (default)"
        Write-Host "2`: Take ownership of any imported images"
        write-host "3`: Forget any imported images (rather than importing new ones)"

        $ownerchoice = Read-Host "Please select from this list (1-3)"
        if ($ownerchoice -eq 2) { $owner = $true}
        if ($ownerchoice -eq 3) { $forget = $true}

        Write-Host ""
        Write-Host "Do you want to monitor the import to completion."
        Write-Host ""
        Write-Host "1`: Monitor the import (default)"
        Write-Host "2`: Dont monitor the import"
        $ownerchoice = Read-Host "Please select from this list (1-2)"
        if ($ownerchoice -eq 1 -or $ownerchoice -eq "") { $monitor = $true}
    
        Clear-Host
        Write-Host "Guided selection is complete. The values entered resulted in the following command:"
        Write-Host ""
        Write-Host -nonewline "Import-AGMLibOnvault -diskpoolid $diskpoolid -applianceid $applianceid" 
        if ($forget) { Write-Host -nonewline " -forget" }
        if ($owner) { Write-Host -nonewline " -owner" }
        if ($monitor) { Write-Host -nonewline " -monitor" }
        if ($appid) { Write-Host -nonewline " -appid $appid" }
        Write-Host ""
        Write-Host "1`: Run the command now. This command will run in the background unless you selected monitor option. (default)"
        Write-Host "2`: Exit without running the command"
        $appuserchoice = Read-Host "Please select from this list (1-2)"
        if ($appuserchoice -eq 2)
        {
            return
        }
    }

    if ($appid)
    {
        if ($owner)
        {
            $import = Import-AGMOnvault -diskpoolid $diskpoolid -applianceid $applianceid -appid $appid -owner
        }
        elseif ($forget)
        {
            $import = Import-AGMOnvault -diskpoolid $diskpoolid -applianceid $applianceid -appid $appid -forget
        }
        else 
        {
            $import = Import-AGMOnvault -diskpoolid $diskpoolid -applianceid $applianceid -appid $appid 
        }
    }
    else {
        if ($owner)
        {
            $import = Import-AGMOnvault -diskpoolid $diskpoolid -applianceid $applianceid -owner
        }
        elseif ($forget)
        {
            $import = Import-AGMOnvault -diskpoolid $diskpoolid -applianceid $applianceid -forget
        }
        else 
        {
            $import = Import-AGMOnvault -diskpoolid $diskpoolid -applianceid $applianceid 
        }
    }

    $importid = $import.id
    if ($monitor -and (!($importid)))
    {
        $import
    }
    elseif ($monitor -and $importid)
    {
        $done = 0
        do 
        {
            $jobgrab = Get-AGMAPIData -endpoint /diskpool/vaultclusters/$importid
            if ($jobgrab.errormessage)
            {   
                $done = 1
                $jobgrab
            }    
            elseif (!($jobgrab.status)) 
            {
                Get-AGMErrorMessage -messagetoprint "Failed to find import with ID $importid"
                $done = 1
            }
            elseif ($jobgrab.status -like "pending")
            {
                write-host "Import status: " $jobgrab.status 
                Start-Sleep -s 5
            }
            elseif ($jobgrab.status -like "running")
            {   
                if ($jobgrab.progress.imagesProcessed)
                {
                    $totalimages = $jobgrab.progress.totalImages
                    write-host "Import status: " $jobgrab.status " Total Images:" $totalimages " Processed: " $jobgrab.progress.imagesProcessed
                }
                else {
                    write-host "Import status: " $jobgrab.status
                }
                Start-Sleep -s 5
            }
            else 
            {
                $done = 1 
            }
        } until ($done -eq 1)
        $importcount = $jobgrab.Result.backup.count
        if ($totalimages)
        {
            $skipped = $totalimages - $importcount
            write-host "Import status: " $jobgrab.status " Skipped:" $skipped " Imported: " $jobgrab.Result.backup.count
        }
        else 
        {
            write-host "Import status: " $jobgrab.status " Imported: " $jobgrab.Result.backup.count
        }
    }
    else {

        $import
    }
}