Jump to content
  • PVS Disk Migration Automation



    Recently, a customer asked me to develop a process to continually migrate vDisks from an On-Premises Citrix PVS vDisk Store to a Microsoft Azure-based PVS Store that would be used for Disaster Recovery. The customer was working with our professional service team to automate this process using the Citrix Image Portability Service, but the process was hard because the scripts had to be recreated for each vDisk being migrated. So, we developed a scripted process that would migrate all “appropriate” vDisks from a defined PVS Store to PVS in Azure. 

    Two scripts are currently used in this process. One determines which vDisks to migrate and writes them into a CSV for the migration, and the other performs the migrations. These scripts can be run separately, or the prep script can be configured to run whenever the migration script runs.


    This script will read all of the vDisks in a defined store in PVS and optionally skip it if streaming is not enabled.  If streaming is enabled, the script will process the vDisks one by one.  It will first get the disk versions.  If the version is a base disk or merged base, the script will check to ensure it has not already been migrated.  If it has not, then the vDisk will be added to the migration csv file, which is then used by the second script to migrate vdisks To Azure using IPS.

    A diagram of a software project

Description automatically generated with medium confidence



    This script will take the list of vDisks to migrate and use Citrix Image Portability Service to migrate the vDisk to Azure.

    A screenshot of a computer screen

Description automatically generated

    Script Setup

    Before using the scripts, ensure they are “unblocked” in Windows.  The prep script uses the PVS PowerShell module, which is installed when the PVS console is installed.  The Migration script uses the Image Portability Service PowerShell modules and the Azure PowerShell (AZ) module.  See:

    1. Install the PVS console
    2. Install the AZ PowerShell Module on Windows


    1. Install the Image Portability PowerShell Modules



    The script will automatically upgrade the IPS PowerShell modules if an update is available, but it will not perform the initial installation.


    This document is not intended to define the entire process of setting up the Image Portability Service.  To learn how to work with IPS, see the following PoC guide:


    At a high level, what is required to use the script is:

    1. Obtain a Citrix Cloud API key – Store securely
    2. Deploy a Connector Appliance in Azure in the Resource Location where images will be deployed.
    3. Create an IPS Credential Wallet entry for the target SMB share using the “New-IpsCredentials” CMDLET 

    See the Image Portability link above for details

    1. Create a Share for the source PVS Store
    2. Create a share for the target PVS Store
    3. Install the PVS Console
    4. Install the AZ Module
    5. Install the IPS Modules
      1. "Citrix.Workloads.Portability"
      2. "Citrix.Image.Uploader"
    6. Configure the Scripts
    7. Run the script


    This script will query PVS to determine which vDisks need to be migrated.  Fill out the settings section in lines 26-34.  This information includes:



    $MigratedvDisksCSV = "MigratedvDisks.csv"

    $vDisksToMigrateCSV = "vDisksToMigrate.csv"

    $PVSServer = "PVSSErver3"

    $PVSSite = "Site"

    $PVSStore = "Store"

    $SkipIfNotEnabled = $true


    The CSV names here must match the other script, so it’s best not to change them.  SkipIfNotEnabled means skipping vDisks that are not enabled for streaming.  This looks like this in the console:

    A screenshot of a computer

Description automatically generated

    If you want to migrate all disks, whether enabled or not, then set SkipIfNotEnabled to $false.

    The PVS console must be installed on the machine running the script, and the user running the script must be a PVS administrator.


    This is the script that will upload the vDisk as a managed disk to Azure and then run the IPS process to prepare and publish the vDisks to the Azure PVS server store. 

    All settings must be configured between lines 71 and 149. The script and IPS documentation document the settings. 

    The source share used must be where the vDisks will be obtained. The PVS Store can be shared directly for this purpose, or another share can be used, but then the vDisks must be copied to that share.

    The Target Share can be a share, the PVS Store, or another SMB share in Azure. This script does not add the vDisks to PVS and will not overwrite a vDisk if it is already in the target store. If this is required, a step to delete the existing vDisks must be added to the scripting.

    There are two workflow options for the script and how vDisk processing is overlapped. If the $maxjobs variable is set to 1, then the script will only upload 1 vDisk at a time. As soon as the upload is complete, the next upload will run parallel to the conversion process in Azure. This option will use the least network bandwidth as only one vDisk upload will run simultaneously.  

    A blue arrows with white text

Description automatically generated

    However, if $maxjobs is set to something higher than 1, both the upload, prepare, and publish jobs will be launched in parallel.  If there is enough available bandwidth, this could result in a faster overall migration time. In the following example, $maxjobs is set to 2, so the third job will begin after one of the first two jobs is completed.

    A blue arrows with white text

Description automatically generated

    The two timeout values used within the script are the last important setting to discuss.  The first is the $JobWaitTimeout, which is defined in hours and is used to limit how long each migration job will run.  If you use more parallelized processing with $maxjobs greater than 1, this value should be longer because it includes the vDisk upload time.  I recommend using 6 hours if the upload is included or 4 hours if not.

    The other time variable is $TotalJobTime, which is also defined in hours and is the time after which no new uploads or migration jobs will be added. This can limit the process from affecting performance during working hours.


    Several logs are created for these scripts. A “Log” folder will be created under the directory where the scripts are run.  

    The Migration Prep script creates a log file that documents for each vDisk if it was added to the migration csv file or not and why.

    A close up of a text

Description automatically generated

    The Migration script itself creates a log file every time it runs that documents which disks are being migrated.

    A close-up of a computer screen

Description automatically generated

    And any errors during the jobs and the success or failure of the migration at the end

    A computer screen shot of a message

Description automatically generated

    Then, for each separate vDisk, there is a log for its preparation and publishing operations.

    A screenshot of a computer program

Description automatically generated

    Note: The upload logs will be located in either the migration or vDisk log, depending on whether the upload is performed by the main script or the job scripts. So, if $maxjobs is set to 1, then the upload logs will be in the main log file. If $maxjobs exceeds 1, the uploader logs will be in the vDisk log files.

    Getting the Scripts

    Remember, these scripts are being provided as examples of automating workflow using Citrix PVS and Ips. Please test the scripts thoroughly before using them, as you will accept any responsibility for their use. Please read the following disclaimer. You can download the script files from the link below the disclaimer.



    This software application is provided to you “as is” with no representations, warranties or conditions of any kind. You may use and distribute it at your own risk. CITRIX DISCLAIMS ALL WARRANTIES WHATSOEVER, EXPRESS, IMPLIED, WRITTEN, ORAL OR STATUTORY, INCLUDING WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT. Without limiting the generality of the foregoing, you acknowledge and agree that (a) the software application may exhibit errors, design flaws or other problems, possibly resulting in loss of data or damage to property; (b) it may not be possible to make the software application fully functional; and (c) Citrix may, without notice or liability to you, cease to make available the current version and/or any future versions of the software application. In no event should the code be used to support of ultra-hazardous activities, including but not limited to life support or blasting activities. NEITHER CITRIX NOR ITS AFFILIATES OR AGENTS WILL BE LIABLE, UNDER BREACH OF CONTRACT OR ANY OTHER THEORY OF LIABILITY, FOR ANY DAMAGES WHATSOEVER ARISING FROM USE OF THE SOFTWARE APPLICATION, INCLUDING WITHOUT LIMITATION DIRECT, SPECIAL, INCIDENTAL, PUNITIVE, CONSEQUENTIAL OR OTHER DAMAGES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. You agree to indemnify and defend Citrix against any and all claims arising from your use, modification or distribution of the code.


    User Feedback

    Recommended Comments

    There are no comments to display.

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Create New...