Start-IpsVsphereExportJob.ps1

<#
 .Synopsis
  Implement an image export job.

 .Description
  Implement an image export job. This function supports exporting image from Vsphere platform
  to disk on SMB file share server.
#>

Function Start-IpsVsphereExportJob
{
    [CmdletBinding(DefaultParameterSetName = 'cmd')]
    Param(
        [Parameter(Mandatory = $true, ParameterSetName = 'file')]
        [Obsolete("Use command-line arguments as input of configuration data.")]
        [string]$ConfigJsonFile,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$CustomerId,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$SmbHost,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [Obsolete("Specifying an alternate SMB port is not supported and this parameter will be ignored.")]
        [string]$SmbPort = $null,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$SmbShare,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$SmbPath,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$SmbDiskName,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$SmbDiskFormat = "VhdDiskFormat",
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$SmbCwId,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$Deployment,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$ResourceLocationId,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$VsphereCwSecretId,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$VsphereHost,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [int]$VspherePort = 443,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$VsphereSslCaCertificateFilePath,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$VsphereSslCaCertificate,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$VCenterSslFingerprint,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [bool]$VsphereSslNoCheckHostname,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$VsphereDataCenter,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$VsphereDataStore,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$VsphereResourcePool = "Resources",
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$VsphereNetwork,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$VsphereHostSystem,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$VsphereCluster,
        [Parameter(Mandatory = $true, ParameterSetName = 'cmd')]
        [string]$SourceDiskName,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$AssetsId,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [HashTable]$Tags = @{},
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [int]$Timeout = 7200,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string]$Prefix = "ce",
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [bool]$JobDebug,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [string[]]$Flags,
        [Parameter(Mandatory = $false, ParameterSetName = 'cmd')]
        [bool]$DryRun = $false,
        [Parameter(Mandatory = $false)]
        [string]$SecureClientId = '',
        [Parameter(Mandatory = $false)]
        [string]$SecureSecret = '',
        [Parameter(Mandatory = $false)]
        [string]$LogFileDir = "",
        [Parameter(Mandatory = $false)]
        [string]$LogFileName = 'ExportVsphereToSmb.log',
        [Parameter(Mandatory = $false)]
        [switch]$OverwriteLog,
        [Parameter(Mandatory = $false)]
        [switch]$Force
    )

    Begin
    {
        Add-PSSnapin Citrix.*
    }
    Process
    {
        # Initialize Logger
        # Set parameter 'Verbose' by internal parameter 'VerbosePreference', since the option -Verbose is occupied by powershell cmdlet
        if($VerbosePreference -eq 'Continue')
        {
            $Verbose = $True
        } else {
            $Verbose = $False
        }
        LogInit $LogFileDir $LogFileName $OverwriteLog $Verbose
        # Initialize config data
        if ($PSCmdlet.ParameterSetName -eq 'file') {
            LogIt "Loading config from $ConfigJsonFile"
            $configData = Get-Content -Raw -Path $ConfigJsonFile | ConvertFrom-Json
            LogIt "Config: $configData" $False
            $CustomerId = $configData.CustomerId
            $SmbHost = $configData.ExportSmb.Host
            $SmbShare = $configData.ExportSmb.Share
            $SmbPath = $configData.ExportSmb.Path
            $SmbDiskName = $configData.ExportSmb.DiskName
            $SmbDiskFormat = $configData.ExportSmb.DiskFormat
            if([String]::IsNullOrWhiteSpace($SmbDiskFormat)) { $SmbDiskFormat = "VhdDiskFormat" }
            $SmbCwId = $configData.ExportSmb.CwId
            $Deployment = $configData.Deployment
            if($configData.psobject.Properties.name -contains "ExportResourceLocationId") { $ResourceLocationId = $configData.ExportResourceLocationId }
            else { $ResourceLocationId = $configData.ResourceLocationId }
            $VsphereCwSecretId = $configData.VsphereCwSecretId
            $VsphereHost = $configData.VsphereHost
            if([String]::IsNullOrWhiteSpace($configData.VspherePort)) { $VspherePort = 443 }
            else { $VspherePort = [int]$configData.VspherePort }
            $VsphereSslCaCertificate = $configData.VsphereSslCaCertificate
            $VCenterSslFingerprint = $configData.VCenterSslFingerprint
            $VsphereSslNoCheckHostname = $configData.VsphereSslNoCheckHostname
            $VsphereDataCenter = $configData.VsphereDataCenter
            $VsphereDataStore = $configData.VsphereDataStore
            if($configData.psobject.Properties.name -contains "VsphereHostSystem") { $VsphereHostSystem = $configData.VsphereHostSystem }
            if($configData.psobject.Properties.name -contains "VsphereCluster") { $VsphereHostSystem = $configData.VsphereCluster }
            if([String]::IsNullOrWhiteSpace($configData.VsphereResourcePool)) { $VsphereResourcePool = "Resources" }
            else { $VsphereResourcePool = $configData.VsphereResourcePool }
            $VsphereNetwork = $configData.VsphereNetwork
            $SourceDiskName = $configData.SourceDiskName
            $AssetsId = $configData.AssetsId
            if($configData.psobject.Properties.name -contains "Tags") { $Tags = Convert-ObjectToHashtable $$configData.Tags }
            if([String]::IsNullOrWhiteSpace($configData.Timeout)) { $Timeout = 7200 }
            else { $Timeout = [int]$configData.Timeout }
            if([String]::IsNullOrWhiteSpace($configData.Prefix)) { $Prefix = "ce" }
            else { $Prefix = $configData.Prefix }
            $JobDebug = $configData.Debug
            $Flags = $configData.Flags
        }

        try {
            # Authenticate to Citrix Cloud
            $parameters = AuthToCitrixCloud $CustomerId $SecureClientId $SecureSecret
            if ([string]::IsNullOrWhiteSpace($SecureClientId) -Or [string]::IsNullOrWhiteSpace($SecureSecret)) {
                $SecureClientId = $parameters.ApiKey
                $SecureSecret = $parameters.SecretKey
            }
        }
        catch {
            LogFatal "Failed to authenticate to Citrix Cloud"
        }

        # Export
        try {
            LogIt "Starting export workflow"
            #
            # Run the export workflow
            #
            Write-Host "***** Call Method: ExportImageJob overwrite: $($Force.IsPresent) *****"
            $platformExportData = @{
                platformCredentialId = $VsphereCwSecretId
                vCenterHost = $VsphereHost
                vCenterPort = $VspherePort
                datacenter = $VsphereDataCenter
                datastore = $VsphereDataStore
                resourcePoolName = $VsphereResourcePool
                network = $VsphereNetwork
                sourceDiskName = $SourceDiskName
            }
            if ($VsphereHostSystem)
            {
                $platformExportData['hostSystem'] = $VsphereHostSystem
            }
            if ($VsphereCluster)
            {
                $platformExportData['cluster'] = $VsphereCluster
            }
            if ($VsphereSslCaCertificateFilePath -And (Test-Path -Path $VsphereSslCaCertificateFilePath -PathType "Leaf"))
            {
                $platformExportData['vCenterSslCaCertificate'] = ((Get-Content $VsphereSslCaCertificateFilePath) -join "`n") + "`n"
            }
            elseif ($VsphereSslCaCertificate)
            {
                # Replace raw string \n -> PowerShell-readable `n
                $VsphereSslCaCertificate = $VsphereSslCaCertificate.replace("\n", "`n")
                $platformExportData['vCenterSslCaCertificate'] = $VsphereSslCaCertificate
            }
            if ($VCenterSslFingerprint)
            {
                $platformExportData['vCenterSslFingerprint'] = $VCenterSslFingerprint
            }
            if ($VsphereSslNoCheckHostname)
            {
                $platformExportData['vCenterSslNoCheckHostname'] = $VsphereSslNoCheckHostname
            }
            if ($SmbPath) {
                $smbDiskPath = "$SmbShare\$SmbPath"
            } else {
                $smbDiskPath = $SmbShare
            }
            # Add default tags
            $Tags['ctx-user'] = ($env:UserName).ToLower()
            
            $exportData = @{
                platform = "vSphere"
                prefix = $Prefix
                ResourceLocationId = $ResourceLocationId
                timeoutInSeconds = $Timeout
                outputStorageLocation = @{
                    type = "SMB"
                    credentialId = $SmbCwId
                    host = $SmbHost
                    sharePath = $smbDiskPath
                }
                outputImageFilename = $SmbDiskName
                outputImageFormat = $SmbDiskFormat
                provisionType = "Thin"
                overwriteTargetFile = $Force.IsPresent
                tags = $Tags
            }
            if ($AssetsId)
            {
                $exportData['assetsId'] = $AssetsId
            }
            if ($JobDebug)
            {
                $exportData['debug'] = $JobDebug
            }
            if ($Flags)
            {
                $exportData['flags'] = $Flags
            }
            # Convert the object to JSON to use in the POST body (Note: Default depth is 2 when serializing)
            $json = ($exportData + $platformExportData) | ConvertTo-Json -Depth 10
            LogIt "$($exportData["provisionType"]) Export POST body $json" $False

            $query = @{
                "async" = $true
                "dryRun" = $DryRun
            }

            # Send the POST
            try {
                $response = Invoke-CCRestMethod 'Post' $Deployment "images/`$export" $CustomerId $SecureClientId $SecureSecret $query $json
                $JobId = $response.id
                LogIt "Image Export started with id $JobId"
            } catch {
                $JobId = "Job failed to start"
                throw "Failed to start export: $_"
            }
        }
        catch {
            LogFatal "Workflow failed: $_"
        }
        finally {
            $output = [PSCustomObject]@{
                CustomerId = $CustomerId
                Deployment = $Deployment
                JobId = $JobId
                LogFileDir = $LogFileDir
                LogFileName = $LogFileName
                SmbHost = $SmbHost
                SmbShare = $SmbShare
                SmbPath = $SmbPath
                SmbDiskName = $SmbDiskName
                SmbDiskFormat = $SmbDiskFormat
                SmbCwId = $SmbCwId
            }
            Write-Output $output

            # Clear credentials at end of pipeline
            if ($PSCmdlet.MyInvocation.PipelinePosition -eq $PSCmdlet.MyInvocation.PipelineLength) {
                Clear-XDCredentials
            }
        }
    }
}