Public/Remove-AGMLibMount.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 Remove-AGMLibMount([string]$label,[string]$imagename,[string]$imageid,[string]$limit,[switch][alias("d")]$delete,[switch][alias("g")]$gceinstanceforget,[switch][alias("p")]$preservevm,[switch][alias("f")]$force)
{
    <#
    .SYNOPSIS
    Unmounts a nominated image or images
 
    .EXAMPLE
    Remove-AGMLibMount
    You will be prompted for image Name
 
    .EXAMPLE
    Remove-AGMLibMount -imagename Image_2133445
    Unmounts Image_2133445 but does not delete it
 
    .EXAMPLE
    Remove-AGMLibMount -imagename Image_2133445 -d
    Unmounts Image_2133445 and deletes it from Appliance and from the cloud if a mount is a Compute Engine Instance created from Persistent Disk Snapshot
 
    .EXAMPLE
    Remove-AGMLibMount -imagename Image_2133445 -p
    For Google Cloud Persistent Disk (PD) mounts
    Unmounts Image_2133445 and deletes it on Appliance Side but preserves it on Google side.
 
    .DESCRIPTION
    A function to unmount images
 
    -delete (-d) Is used to unmount and delete an image. If not specified then an unmount is done, but the image is retained on the Appliance Side
    -force (-f) Removes the mount even if the host-side command to remove the mounted application fails. This can leave artifacts on the Host and should be used with caution
    -preservevm (-p) This applies to Compute Engine Instances created from Persistent Disk Snapshot. When used the Appliance Image of the mount is removed, but on the GCP side the new VM is retained.
    -gceinstanceforget Forgets all mounted Compute Engine Instance. This is the same as running -preservevm against them
 
    #>


    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 ((!($imagename)) -and (!($label)) -and (!($imageid)) -and (!($gceinstanceforget)))
    {
        Clear-Host
        Write-Host "This function is designed to assist you removing mounted images."
        Write-Host "We do this by selecting an image or a range of images using their label"
        Read-Host -Prompt "Press enter to display the current mounts"
        Clear-Host
        $mountgrab = Get-AGMLibActiveImage 
        if (!($mountgrab.imagename))
        {
            $mountgrab
            return
        }
        if ($mountgrab.id.count -eq 0)
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find any mounted images with Get-AGMLibActiveImage"
            return
        }
        
        $printarray = @()
        $i = 1
        foreach ($mount in $mountgrab)
        {
            $printarray += [pscustomobject]@{
                id = $i
                imageid = $mount.id
                imagename = $mount.imagename
                apptype = $mount.apptype
                hostname = $mount.hostname
                appname = $mount.appname
                mountedhost = $mount.mountedhost
                imagestate = $mount.imagestate
                label = $mount.label
            }
            $i += 1
        }
        $printarray | format-table
       
        if ($printarray.imageid.count -eq 1)
        {
            write-host ""
            Write-host "Only one image found, this is the one we will work with"
            $imageid = $printarray.imageid
            $apptype = $printarray.apptype
            $imagestate = $printarray.imagestate
            $imagename = $printarray.imagename
        }
        else 
        {
            write-host ""
            Write-host "Unmount selection method:"
            Write-Host "1`: Select one image by ImageName"
            Write-Host "2`: Select a label"
            Write-Host "3`: Forget all GCE Instances"
        
            While ($true) 
            {
                $userchoice = Read-Host "Please select from this list [1-3]"
                if ($userchoice -lt "1" -or $userchoice -gt "3")
                {
                    Write-Host -Object "Invalid selection. Please enter either 1-3"
                } 
                else
                {
                    break
                }
            }
            if ($userchoice -eq "1") 
            {        
                While ($true) 
                {
                    $listmax = $printarray.imageid.count
                    [int]$userselection1 = Read-Host "Please select the ID of one image in the list. This image will be unmounted (1-$listmax)"
                    if ($userselection1 -lt 1 -or $userselection1 -gt $listmax)
                    {
                        Write-Host -Object "Invalid selection. Please enter a number in range [1-$listmax)]"
                    } 
                    else
                    {
                        break
                    }
                }
                $imageid = $printarray.imageid[($userselection1 - 1)]
                $apptype = $printarray.apptype[($userselection1 - 1)]
                $imagestate = $printarray.imagestate[($userselection1 - 1)]
                $imagename = $printarray.imagename[($userselection1 - 1)]
            }
            
            if ($userchoice -eq "2") 
            { 
                While ($true) 
                {
                    $listmax = $printarray.count
                    [int]$userselection2 = Read-Host "Please select the ID of one image in the list. All images with the matching label will be unmounted (1-$listmax)"
                    if ($userselection2 -lt 1 -or $userselection2 -gt $listmax)
                    {
                        Write-Host -Object "Invalid selection. Please enter a number in range [1-$listmax)]"
                    } 
                    else
                    {
                        break
                    }
                }
                $label = $printarray.label[($userselection2 - 1)]        
            }
            if ($userchoice -eq "3")
            {
                $gceinstanceforget = $true
            }
        }
        if ($gceinstanceforget -eq $false)
        {
            Write-Host ""
            Write-host "Delete setting"
            Write-Host "1`: Unmount and delete"
            Write-Host "2`: Unmount"
            $userchoice = ""
            While ($true) 
            {
                [int]$userchoice = Read-Host "Please select from this list (1-2)"
                if ($userchoice -lt 1 -or $userchoice -gt 2)
                {
                    Write-Host -Object "Invalid selection. Please enter a number in range [1-2)]"
                } 
                else
                {
                    break
                }
            }
            if ($userchoice -eq 1) { $delete = $true }
            write-host ""
            Write-host "Force setting"
            Write-Host "1`: Do not force the unmount if host side commands do not release the disk (default)"
            Write-Host "2`: Force the unmount"
            [int]$userchoice = Read-Host "Please select from this list (1-2)"
            if ($userchoice -eq 2) { $force = $true }
            if (($apptype -eq "GCPInstance") -or ($label))
            {
                write-host ""
                Write-host "Preserve VM setting (this only applies to GCE mounts in Google Cloud)"
                Write-Host "1`: Delete the VM on both the GCP side and the Backup Appliance Side (default)"
                Write-Host "2`: Preserve the VM on the GCP side"
                [int]$userchoice = Read-Host "Please select from this list (1-2)"
                if ($userchoice -eq 2) { $preservevm = $true }
            }
        }
        Write-Host "Guided selection is complete. The values entered resulted in the following command:"
        Write-Host ""
        Write-Host -nonewline "Remove-AGMLibMount"
        if ($imagename) { write-host -nonewline " -imagename $imagename" }
        if ($label) { write-host -nonewline " -label `"$label`"" }
        if ($delete) { write-host -nonewline " -delete" }
        if ($force) { write-host -nonewline " -force" }
        if ($preservevm) { write-host -nonewline " -preservevm" }
        if ($gceinstanceforget) { write-host -nonewline " -gceinstanceforget" }
        Write-Host ""
        Write-Host "1`: Run the command now and exit (default)"
        Write-Host "2`: Exit without running the command"
        $everyuserchoice = Read-Host "Please select from this list (1-2)"
        if ($everyuserchoice -eq 2)
        {
            return
        }
    }
    if ($imageid)
    {
        $id = $imageid
    }
    if ($imagename)
    {
        $imagegrab = Get-AGMLibActiveImage | where-object {$_.imagename -eq $imagename}
        if ($imagegrab.id)
        {
            $id = $imagegrab.id
            $imagestate = $imagegrab.imagestate
        }
        else 
        {
            Get-AGMErrorMessage -messagetoprint "Failed to find $imagename"
            return
        }
    }

    if ($delete)
    { 
        $deleterequest="true"
    }
    else 
    {
        $deleterequest="false"
    }
    if ($force)
    { 
        $forcerequest="true"
    }
    else 
    {
        $forcerequest="false"
    }
    if ($preservevm)
    { 
        $preservevmrequest="true"
    }
    else 
    {
        $preservevmrequest="false"
    }

    if ($label)
    {
        $mountlist = Get-AGMLibActiveImage | where-object  {$_.label -eq "$label"}
        foreach ($mount in $mountlist)
        {
            $id = $mount.id
            $body = @{delete=$deleterequest;force=$forcerequest;preservevm=$preservevmrequest}
            $json = $body | ConvertTo-Json
            if ($mount.imagestate -ne "Unmounted")
            {   
                Post-AGMAPIData -endpoint /backup/$id/unmount -body $json
            }
            else 
            {
                Remove-AGMImage -imageid $id
            }
        }
    }
    elseif ($gceinstanceforget) 
    {
        if ( $((get-host).Version.Major) -gt 5 )
        {
            if (!($limit)) { $limit = 10 }
            $mountlist = Get-AGMLibActiveImage | where-object  {$_.apptype -eq "GCPInstance"}
            if ($AGMToken)
            {
            $mountlist | ForEach-Object -parallel {
                    $body = @{delete=$true;preservevm=$true}
                    $json = $body | ConvertTo-Json
                    $agmip = $using:agmip 
                    $AGMToken = $using:AGMToken 
                    $AGMSESSIONID = $using:AGMSESSIONID
                    $id = $_.id
                    Post-AGMAPIData -endpoint /backup/$id/unmount -body $json
                } -ThrottleLimit $limit
            }
            else 
            {
                $mountlist | ForEach-Object -parallel {
                    $body = @{delete=$true;preservevm=$true}
                    $json = $body | ConvertTo-Json
                    $agmip = $using:agmip 
                    $AGMSESSIONID = $using:AGMSESSIONID
                    $IGNOREAGMCERTS = $using:IGNOREAGMCERTS
                    $id = $_.id
                    Post-AGMAPIData -endpoint /backup/$id/unmount -body $json
                } -ThrottleLimit $limit
            }
        }
        else {
            $mountlist = Get-AGMLibActiveImage | where-object  {$_.apptype -eq "GCPInstance"}
            foreach ($mount in $mountlist)
            {
                $id = $mount.id
                $body = @{delete=$true;preservevm=$true}
                $json = $body | ConvertTo-Json
                Post-AGMAPIData -endpoint /backup/$id/unmount -body $json
            }
        }
    }
    else
    {
        $body = @{delete=$deleterequest;force=$forcerequest;preservevm=$preservevmrequest}
        $json = $body | ConvertTo-Json
        if ($imagestate -ne "Unmounted")
        {        
        
            Post-AGMAPIData -endpoint /backup/$id/unmount -body $json    
        }
        else 
        {
            Remove-AGMImage -imagename $imagename
        }
    }
}