Public/Move-RubrikMountVMDK.ps1

#Requires -Version 3
function Move-RubrikMountVMDK
{
    <#
            .SYNOPSIS
            Moves the VMDKs from a Live Mount to another VM
            .DESCRIPTION
            The Move-RubrikMountVMDK cmdlet is used to attach VMDKs from a Live Mount to another VM, typically for restore or testing purposes.
            .NOTES
            Written by Chris Wahl for community usage
            Twitter: @ChrisWahl
            GitHub: chriswahl
            .LINK
            https://github.com/rubrikinc/PowerShell-Module
    #>


    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,Position = 0,HelpMessage = 'Source Virtual Machine',ValueFromPipeline = $true)]
        [Alias('Name')]
        [ValidateNotNullorEmpty()]
        [String]$SourceVM,
        [Parameter(Mandatory = $false,Position = 1,HelpMessage = 'Target Virtual Machine',ValueFromPipeline = $true)]
        [ValidateNotNullorEmpty()]
        [String]$TargetVM,
        [Parameter(Mandatory = $true,Position = 2,HelpMessage = 'vCenter FQDN or IP address')]
        [ValidateNotNullorEmpty()]
        [String]$vCenter,
        [Parameter(Mandatory = $true,Position = 3,HelpMessage = 'Backup date in MM/DD/YYYY HH:MM format',ValueFromPipeline = $true)]
        [ValidateNotNullorEmpty()]
        [String]$Date,
        [Parameter(Mandatory = $false,Position = 4,HelpMessage = 'Rubrik FQDN or IP address')]
        [ValidateNotNullorEmpty()]
        [String]$Server = $global:RubrikServer
    )

    Process {

        Write-Verbose -Message 'Validating the Rubrik API token exists'
        if (-not $global:RubrikToken) 
        {
            Write-Warning -Message 'You are not connected to a Rubrik server. Using Connect-Rubrik cmdlet.'
            Connect-Rubrik
        }

        Write-Verbose -Message 'Importing required modules and snapins'
        $powercli = Get-PSSnapin -Name VMware.VimAutomation.Core -Registered
        try 
        {
            switch ($powercli.Version.Major) {
                {
                    $_ -ge 6
                }
                {
                    Import-Module -Name VMware.VimAutomation.Core -ErrorAction Stop
                    Write-Verbose -Message 'PowerCLI 6+ module imported'
                }
                5
                {
                    Add-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction Stop
                    Write-Warning -Message 'PowerCLI 5 snapin added; recommend upgrading your PowerCLI version'
                }
                default 
                {
                    throw 'This script requires PowerCLI version 5 or later'
                }
            }
        }
        catch 
        {
            throw $_
        }

        
        Write-Verbose -Message 'Allowing untrusted SSL certs'
        Add-Type -TypeDefinition @"
        using System.Net;
        using System.Security.Cryptography.X509Certificates;
        public class TrustAllCertsPolicy : ICertificatePolicy {
            public bool CheckValidationResult(
                ServicePoint srvPoint, X509Certificate certificate,
                WebRequest request, int certificateProblem) {
                return true;
            }
        }
"@

        [System.Net.ServicePointManager]::CertificatePolicy = New-Object -TypeName TrustAllCertsPolicy


        Write-Verbose -Message 'Creating an Instant Mount (clone) of the Source VM'
        New-RubrikMount -VM $SourceVM -Date $Date
        Start-Sleep -Seconds 2
        [array]$mounts = Get-RubrikMount -VM $SourceVM
        $i = 0
        
        Write-Verbose -Message 'Checking for quantity of mounts in the system'
        if ($mounts -ne $null) 
        {
            Write-Verbose -Message 'Finding the correct mount'
            foreach ($_ in $mounts.MountName)
            {            
                if ($_ -eq $null)
                {
                    break
                }
                $i++
            }
        
            While ($mounts[$i].MountName -eq $null)
            {
                [array]$mounts = Get-RubrikMount -VM $SourceVM
                Start-Sleep -Seconds 2
            }
        }
        else
        {
            Write-Verbose -Message 'No other mounts found, waiting for new mount to load'
            While ($mounts.MountName -eq $null)
            {
                [array]$mounts = Get-RubrikMount -VM $SourceVM
                Start-Sleep -Seconds 2
            }
        }
        Write-Verbose -Message 'Mount is online. vSphere data loaded into the system.'

        Write-Verbose -Message 'Ignoring self-signed SSL certificates for vCenter Server (optional)'
        $null = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -DisplayDeprecationWarnings:$false -Scope User -Confirm:$false

        Write-Verbose -Message 'Connecting to vCenter'
        try 
        {
            $null = Connect-VIServer -Server $vCenter -ErrorAction Stop
        }
        catch 
        {
            throw 'Could not connect to vCenter'
        }
    
        Write-Verbose -Message 'Gathering details on the Instant Mount'
        $MountVM = $null
        While ($MountVM.PowerState -ne 'PoweredOn')
        {
            $MountVM = Get-VM -Name $mounts[$i].MountName
            Start-Sleep -Seconds 2
        }

        Write-Verbose -Message 'Powering off the Instant Mount'
        $null = Stop-VM -VM $MountVM -Confirm:$false

        Write-Verbose -Message 'Gathering details on the Target VM'
        if (!$TargetVM) 
        {
            $TargetVM = $SourceVM
        }
        $TargetHost = Get-VMHost -VM $TargetVM

        Write-Verbose -Message 'Mounting Rubrik datastore to the Target Host'
        $MountDatastore = Get-VM $MountVM | Get-Datastore
        if (!(Get-VMHost $TargetHost | Get-Datastore -Name $MountDatastore)) 
        {
            $null = New-Datastore -Name $MountDatastore.Name -VMHost $TargetHost -NfsHost $MountDatastore.RemoteHost -Path $MountDatastore.RemotePath -Nfs
        }

        Write-Verbose -Message 'Migrating the Mount VMDKs to VM'
        [array]$MountVMdisk = Get-HardDisk $MountVM
        foreach ($_ in $MountVMdisk)
        {
            try
            {
                $null = Remove-HardDisk -HardDisk $_ -DeletePermanently:$false -Confirm:$false
                $null = New-HardDisk -VM $TargetVM -DiskPath $_.Filename
            }
            catch
            {
                throw 'Unable to attach VMDKs to the TargetVM'
            }
        }
        
        Write-Verbose -Message 'Offering cleanup options'
        $title = 'Setup is complete!'
        $message = "A Mount of $SourceVM has been created, and all VMDKs associated with the mount have been attached.`rYou may now start testing.`r`rWhen finished:`rSelect YES to automatically cleanup the attached VMDKs and mount`rSelect NO to leave the mount and VMDKs intact."

        $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', `
        'Automated Removal: This script will detatch the VMDK(s) and discard the Mount VM'

        $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', `
        'Manual Removal: VMDK(s) will remain attached and Mount VM will remain in vCenter'

        $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

        $result = $host.ui.PromptForChoice($title, $message, $options, 0) 

        switch ($result)
        {
            0 
            {
                Write-Verbose -Message 'Removing VMDKs from the VM'
                [array]$SourceVMdisk = Get-HardDisk $TargetVM
                foreach ($_ in $SourceVMdisk)
                {
                    if ($_.Filename -eq $MountVMdisk.Filename)
                    {
                        Write-Verbose -Message "Removing $_ from $TargetVM"
                        Remove-HardDisk -HardDisk $_ -DeletePermanently:$false -Confirm:$false
                    }
                }
        
                Write-Verbose -Message 'Deleting the Instant Mount'
                $uri = 'https://'+$global:RubrikServer+':443/job/type/unmount'

                $body = @{
                    mountId = $mounts[0].RubrikID
                    force   = 'false'
                }

                try 
                {
                    $r = Invoke-WebRequest -Uri $uri -Headers $global:RubrikHead -Method POST -Body (ConvertTo-Json -InputObject $body)
                    if ($r.StatusCode -ne '200') 
                    {
                        throw 'Did not receive successful status code from Rubrik for Mount removal request'
                    }
                    Write-Verbose -Message "Success: $($r.Content)"
                }
                catch 
                {
                    throw 'Error connecting to Rubrik server'
                }
            }
            1 
            {
                Write-Verbose -Message 'You selected No. Exiting script'
            }
        }

    } # End of process
} # End of function