Migrating Virtual Machines

Migrating a VM from AWS EC2 to Zadara Cloud Services

This document will walk through the process of migrating a virtual machine instance from EC2 in Amazon Web Services to Zadara Cloud Services.

Preparing for Migration

Before beginning, be aware that AWS has very definite rules about which VMs may be migrated out of AWS EC2.  The full set of rules can be found here Essentially, an AWS VM that is being exported, must meet the following conditions:

  1. Must not have been created from an AWS first-party AMI or Subscription AMI.

  2. Must have only one disk (the boot drive) and only one Network Interface.

  3. Must not use a fixed Virtual Hard Disk.

If the VM qualifies for export, do the following:

  1. Shut down the VM via the AWS Console or AWS CLI.

  2. Record the ID of the instance that will migrate via the AWS Console or CLI.

  3. Verify that there is an S3 bucket in which to store the exported image before transferring it to Zadara Cloud Services.

  4. This S3 bucket must have its permissions set to allow AWS’s ‘vm-import-export’ to have List, Upload/Delete, and Manage Permissions rights.

Exporting the VM from AWS EC2 to AWS S3

When exporting a VM from EC2,  export the boot volume of the EC2 instance into a vmdk, contained in an OVA file, and formatted for the target platform of VMware. This export can be initiated with the following single AWS EC2 CLI command.

aws ec2 create-instance-export-task --instance-id <Instance ID> \
 --target-environment vmware \
 --export-to-s3-task DiskImageFormat=vmdk,ContainerFormat=ova,S3Bucket=<Name of S3 Bucket>,S3Prefix=<Prefix>

Where:

  • <Instance ID> is the ID string of the instance exported, as noted earlier.

  • –target-environment vmware - When exporting an OVA to be imported into Zadara Cloud Services, the –target-environment should always be ‘vmware’.

  • <Name of S3 Bucket> is the name of the S3 Bucket to use in order to house the exported VM for transfer to Zadara Cloud Services.

  • <Prefix> is the export process defined by some alphanumeric string.

The exported instance will be named ‘<Prefix>-<Instance ID>’ in the S3 Bucket of your choice. So, for example, an ID of “i-1234546” and a prefix of “exported” would result in an exported object with the name “exported-i-123456.ova” in your S3 Bucket.

Complete AWS documentation for this command can be found here.

Monitoring the Export Progress

Once the export is initiated, the export details are displayed.

  • Record the ExportTaskID from the table displayed.

Monitor the progress of the export job with the command:

aws ec2 describe-export-tasks --export-task-ids <ExportTaskID>

Note

There is no progress percentage, but wait for the State field to become ‘completed’ or ‘complete’. The amount of time this takes varies, depending on the current AWS activity and the overall size and complexity of the VM being exported.

Preparing the OVA for Import

Once the export has been completed, locate the <Prefix>-<InstanceID>.ova object in your S3 bucket.

If public access to the OVA object is allowed, then do the following:

  • In the Properties tab, set the permissions to allow “Everyone to Open/Download”. This allows Zadara Cloud Services to import the file.

  • Locate the object URL in the Properties page of the exported ova file in S3, and record this URL for use in the Zadara Cloud Services Create Image workflow.

If public access to the file is not provided, skip the the above, and instead, download the image from S3.

Importing the OVA into Zadara Cloud Services and Converting it into a VM

Do the following to import the AWS OVA image and convert it into a Zadara Cloud Services OVA image and Zadara Cloud Services VM.

  1. Login to the Zadara Cloud Services GUI as a Tenant Admin or Admin.

  2. In the Compute > Instances view, click Import VM.

The Import VM dialog is displayed. Do the following:

  1. Enter the Name of the VM which will be spawned from the image.

  2. Enter the Name of the image which it will be called in Zadara Cloud Services.

  3. Select the Storage Pool in which the imported image will be created.

  4. An Admin User, may also specify that the image should be Public, available to all users in the cluster,  instead of just being available to the users of the project of the logged-in user.

  5. Import Method

    1. URL - If in step ‘Preparing the OVA for Import’, above, public access to the OVA object was allowed.

    • Select ‘URL’ as the Import Method.

    • Enter the URL of the S3 object into the URL field.

    1. File - If in step ‘Preparing the OVA for Import’, above, public access to the OVA object was not allowed, but rather downloaded it to your system, either drop the file in the appropriate area or browse for it on your system.

  6. Click Finish.

Once complete, this process creates three new entities in the Zadara Cloud Services region:

  • A VM that appears in the VM list (Menu > Compute > Instances).

  • A volume – the boot volume of the VM. This volume appears in the volume list (Menu > Storage > Block Storage). This volume has the same name as the VM.

  • An image that appears in the image list (Menu > Applications > Image).

Migrating VMs from Zadara Cloud Services to AWS

Migrate a VM from Zadara Cloud Services to AWS. The basic procedure is to:

  1. Clone a volume.

  2. Attach the cloned volume to a physical server (a stratonode).

  3. Copy the volume to external storage.

  4. Upload the volume file to Amazon S3.

  5. Create an AWS AMI from the volume.

    Launch a new EC2 instance from this newly created AWS AMI, if needed. The AWS AMI is based on your original Zadara Cloud Services VM.

Here is an example of how to do this migration.

Clone a volume

Clone the boot volume of the VM when migrating. Do this through the Zadara Cloud Services GUI, or ssh into a stratonode and run the following CLI commands.

To clone the boot volume, you need to plug in the sourceId of the boot volume with the volume create command.

First get the sourceId, using the volume list command:

[root@stratonode0 ~]# symp volume list -f json -c name -c sourceId
...
{
    "sourceId": "665a9c31-11e0-473b-a792-7b110684dd36",
    "name": "VM1"
}
...

In this example, the name of the VM is VM1, so the sourceId is 665a9c31-11e0-473b-a792-7b110684dd36. Now clone the volume by using the volume create command. Plug in the following values:

  • sourceId

  • Name of the new clone to be used

[root@stratonode0 ~]# symp volume create --source-id 665a9c31-11e0-473b-a792-7b110684dd36 my_new_copied_VM1_boot_disk
+---------------------+--------------------------------------+
| Field               | Value                                |
+=====================+======================================+
| id                  | 7b02f685-d48c-4b3f-93f8-e9f5cf4e4756 |
+---------------------+--------------------------------------+
| name                | my_new_copied_VM1_boot_disk          |
+---------------------+--------------------------------------+
| status              | ready                                |
+---------------------+--------------------------------------+
| storagePool         | a93b9655-cc32-4734-9766-7fe2a5121d52 |
+---------------------+--------------------------------------+
| projectID           | 7275c7cd700b43ee974fc107dbe1a816     |
+---------------------+--------------------------------------+
| attachedTo          | None                                 |
+---------------------+--------------------------------------+
| taskThroughputMbps  | None                                 |
+---------------------+--------------------------------------+
| attachedHost        | None                                 |
+---------------------+--------------------------------------+
| attachedDevice      | None                                 |
+---------------------+--------------------------------------+
| createdAt           | 2017-05-16T19:55:52Z                 |
+---------------------+--------------------------------------+
| size                | 1.0                                  |
+---------------------+--------------------------------------+
| accessMode          | read-write                           |
+---------------------+--------------------------------------+
| userID              | admin                                |
+---------------------+--------------------------------------+
| taskProgress        | None                                 |
+---------------------+--------------------------------------+
| health              | healthy                              |
+---------------------+--------------------------------------+
| attachmentType      | None                                 |
+---------------------+--------------------------------------+
| deletedAt           | None                                 |
+---------------------+--------------------------------------+
| description         | None                                 |
+---------------------+--------------------------------------+
| tags                |                                      |
+---------------------+--------------------------------------+
| replicationSourceID | None                                 |
+---------------------+--------------------------------------+
| properties          | {}                                   |
+---------------------+--------------------------------------+
| info                | None                                 |
+---------------------+--------------------------------------+
| bootable            | True                                 |
+---------------------+--------------------------------------+
| sourceId            | 665a9c31-11e0-473b-a792-7b110684dd36 |
+---------------------+--------------------------------------+
| attachedMode        | None                                 |
+---------------------+--------------------------------------+
| attachedAt          | None                                 |
+---------------------+--------------------------------------+

Make a note of this cloned volume’s id. In this case it is 7b02f685-d48c-4b3f-93f8-e9f5cf4e4756.

Attach the cloned volume to a physical server

Attach this cloned volume to a physical server (a stratonode). You attach the volume by using the mancala volumes attach-to-host command. Plug in the following values:

  • Volume id

  • Name of the physical server

In this example, attach the volume to stratonode0, whose full name is stratonode0.node.strato

[root@stratonode0 ~]# mancala volumes attach-to-host 7b02f685-d48c-4b3f-93f8-e9f5cf4e4756 stratonode0.node.strato
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|       Property      |                                                                                        Value                                                               |
+=====================+============================================================================================================================================================+
|      accessMode     |                                                                                      read-write                                                            |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|     attachments     | [{'computeID': None, 'ownerToken': None, 'hosts': , 'mode': 'read-write', 'time': 1494964939, 'owner': None, 'mountpoint': u'/dev/nbd63', 'type': 'hbd'}]  |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|    bitmapVolumeID   |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|       bootable      |                                                                                         True                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      createdAt      |                                                                                      1494964552                                                            |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      deletedAt      |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|     description     |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|        health       |                                                                                       healthy                                                              |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|          id         |                                                                         7b02f685-d48c-4b3f-93f8-e9f5cf4e4756                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      isTracked      |                                                                                        False                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|         kind        |                                                                                        volume                                                              |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|         name        |                                                                             my_new_copied_VM1_boot_disk                                                    |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|         pool        |                                                                         a93b9655-cc32-4734-9766-7fe2a5121d52                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      projectID      |                                                                           7275c7cd700b43ee974fc107dbe1a816                                                 |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      properties     |                                                                                          {}                                                                |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| replicationSourceID |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|         size        |                                                                                          40                                                                |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|       sourceID      |                                                                         665a9c31-11e0-473b-a792-7b110684dd36                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|        state        |                                                                                        ready                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      stateInfo      |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|     taskProgress    |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|  taskThroughputMbps |                                                                                         None                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
|        userID       |                                                                                        admin                                                               |
+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+

Make a note of this volume’s mountpoint, which is listed as a value in the attachments property. In this example, the mountpoint is /dev/nbd63.

Copy the volume to external storage

Copy the volume from block to file, using the dd utility.

  • Set the input file argument (if=xxx) to the mountpoint which was noted in the output from the mancala command earlier in this procedure. In this example, the input file mountpoint is /dev/nbd63.

  • Set the output file argument (of=yyy) to some convenient storage location such as a share/NFS, USB mass storage flash device, etc. In this example, assume that a USB flash drive was mounted to the mountpoint:

    /media/flash

Copy the volume to the flash drive:

# dd if=/dev/nbd63 of=/media/flash/cirros-ex.raw
      81920+0 records in
      81920+0 records out
      41943040 bytes (42 MB) copied, 0.597927 s, 70.1 MB/s

Upload the volume file to Amazon S3

Copy the volume file from the flash drive to a machine that has the following Amazon utilities installed and configured:

Make sure to have the Amazon Access and Secret keys. Plug in these keys by running:

$ s3cmd --configure

and answering the prompts.

Do a s3cmd put to upload the volume file to your Amazon S3 bucket, for example:

$ s3cmd put /media/flash/cirros-ex.raw s3://bucket-cs1/cirros-ex.raw

Create an AWS AMI from the volume

Create an AWS AMI from the volume that was just uploaded to S3, by using the aws ec2 import-image command.

Before running import-image, set up some role prerequisites – define a new role, indicate what the role is authorized to do, and indicate which users can assume the role.

Start by creating the following files:

File

What is the purpose of the file?

Sample contents

trust-policy.json

Specifies which users can assume the role being created.

{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::12345:root" },
"Action": "sts:AssumeRole"
}
}

role-policy.json

Specifies what this role is authorized to do.

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "ec2:import-image",
  }
}

Now use the create-role command to create a new role called vmimport. Call the role vmimport because vmimport is the default role that the import-image command uses (and import-image will be run very soon).

Specify which users can assume this role by using the --assume-role-policy-document argument to point to the trust-policy.json file that was created.

$ aws iam create-role –role-name vmimpt –assume-role-policy-document file:///root/trust-policy.json

Assign the new vmimport role its policy – the policy in role-policy.json that says it can run the import-image command:

$ aws iam put-role-policy –role-name vmimport –policy-name vmimport –policy-document file://role-policy.json

Create the containers.json file. This file tells the import-image command to use the Zadara Cloud Services volume that was just put in an S3 bucket:

File

What is the purpose of the file?

Sample contents

containers.json

Tells import-image to use the Zadara Cloud Services volume that was just put in an S3 bucket.

Create the AWS AMI by running the import-image command:

$ aws ec2 import-image –description “cirros” –disk-containers file://containers.json

The output from this command includes a <task_ID>. Make a note of this, in order to check the status of the import operation in the next step.

Check the status of the import operation:

$ aws ec2 describe-import-image-tasks –import-task-ids <task_ID>

Upon successful completion of the import operation, the new AMI appears in the list of available AMIs.

Launch a new EC2 instance from the newly created AWS AMI.

Migrating a Virtual Machine from VMware

  1. First, export a VM from VMware vCenter into the OVA format. Refer to the VMware documentation for information about the OVA export.

  2. Then, import the OVA file into Zadara Cloud Services. During the import, Zadara Cloud Services both converts the OVA file into a QCOW2 image and also creates a VM. This is unlike uploading a KVM image. In this case, when uploading an OVA file upload an entire VM, including its volumes if available.

To import an OVA VM

  1. Click Menu > Compute > Instances > Import. The Import VM dialog box appears.

  2. Fill in the following:

  • VM Name: Name of the VM to create within Zadara Cloud Services.

  • Image Name: Name of the image to create within Zadara Cloud Services.

  • Storage  Pool: Select the storage pool to store the Zadara Cloud Services image and VM created.

  • Firmware Type: Select the firmware type of the original VM – either BIOS or UEFI.

  • Public - Check this box to make the image available to all projects in all tenants. If ‘public’ is not checked, the image will be available to your project only.

  • Import Method

You can import either by URL or by File:

       * URL - Enter the URL where the OVA file is located.

        *  Skip SSL verification: Opt to skip SSL verification if needed.

       * File - Select the OVA file by either dragging it into the box or using the Browse button.

  1. Click OK.

Zadara Cloud Services uploads and converts the OVA file. This takes a few minutes.

Once complete, this process creates three new entities in the Zadara Cloud Services region:

  • A VM that appears in the VM list (Menu > Compute > Instances).

  • A volume – the boot volume of the VM. This volume appears in the volume list (Menu > Storage > Block Storage). This volume has the same name as the VM.

  • An image that appears in the image list (Menu > Applications > Image).

VMware Virtual Machine migration using the CLI

When migrate a VM from VMware into Zadara Cloud Services first export an image from vCenter into the OVA format. You then import the OVA image into Zadara Cloud Services.

During the import, Zadara Cloud Services converts the OVA image into the QCOW2 format. This section describes how to import a VM using the CLI.

To import a VM into Zadara Cloud Services

  1. Export the VM from VMware vCenter. Save the exported image as an OVA file, as described in the VMware documentation.

  2. Install the symp client on a Linux machine. Use the symp client to run Zadara Cloud Services CLI commands.

  3. Place the OVA file on the Linux machine where the symp client was just installed, or an a NAS share that the machine can access.

  4. Get the ID of the storage pool where to place the VMware VM. To do this, run the storage pool list command. This example uses the -c argument to display just the name and ID of the storage pool:

    $ symp storage pool list -f json -c name -c id
    [
      {
        "id": "9e740eb2-99f3-4600-b07f-16dfdbe81311",
        "name": "test-pool"
      }
    ]
    
  5. Import the VMware VM into Zadara Cloud Services by using the conversions create command. This command converts the OVA into a Zadara Cloud Services VM, and imports it into the storage pool specified. Pass in the following values with the conversions create command:

    • Path to the OVA file, using the –file argument.

    • Image name. When the conversions create command imports the OVA, it also creates an image. Specify a name for this image, using  the –image-name argument.

    • Name to give this VM within the Zadara Cloud Services, using the –vm-name argument.

    • Storage pool ID

    $ symp conversions create --file dsl-4-4-10.ova --image-name dsl-4-4-10 --vm-name vm-from-ova 9e740eb2-99f3-4600-b07f-16dfdbe81311
    

View the newly imported VM by running the vm list command, or by using the GUI – Compute > Virtual Machines view.

Exporting Zadara Cloud Services Images in QCOW2

There may be times when export a volume from the Zadara Cloud Services platform is necessary. For example, when downloading it to a PC for backup, or uploading it to another hypervisor.

The basic procedure for exporting a volume is to attach the volume to a Zadara Cloud Services host, convert it to a QCOW2 file, then export the QCOW2 file out of the system.

  1. Turn off the VM.

  2. Clone the volume.

  3. Find and copy the volume’s UUID (Menu > Storage > Volumes > volume_name)

  4. SSH into to any host in the cluster.

  5. Issue the following mancala command:

    mancala volumes attach-to-host <volume_id> <host-name>

    Example:

    [root@stratonode1 mancala0]# mancala volumes attach-to-host 64e3e44c-7d9e-402d-8924-ce9e61883450 stratonode1.node.strato
    +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |       Property      |                                                                                        Value                                                                                         |
    +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |      accessMode     |                                                                                      read-write                                                                                      |
    |     attachments     | [{'computeID': None, 'ownerToken': None, 'hosts': , 'mode': 'read-write', 'time': 1528738936, 'owner': None, 'mountpoint': u'/dev/nbd62', 'type': 'hbd'}]                            |
    |    bitmapVolumeID   |                                                                                         None                                                                                         |
    |       bootable      |                                                                                        False                                                                                         |
    |      createdAt      |                                                                                      1528737478                                                                                      |
    |      deletedAt      |                                                                                         None                                                                                         |
    |     description     |                                                                                         None                                                                                         |
    |        health       |                                                                                       healthy                                                                                        |
    |      healthInfo     |                                                                                         None                                                                                         |
    |          id         |                                                                         64e3e44c-7d9e-402d-8924-ce9e61883450                                                                         |
    |      isTracked      |                                                                                        False                                                                                         |
    |         kind        |                                                                                        volume                                                                                        |
    |         name        |                                                                              testexport_11Jun2018_1317                                                                               |
    |         pool        |                                                                         c9e2297b-ba04-4919-9138-d595847cf741                                                                         |
    |      projectID      |                                                                           53e99283cf03479e9b12177d512fbb39                                                                           |
    |      properties     |                                                                                          {}                                                                                          |
    | replicationSourceID |                                                                                         None                                                                                         |
    |         size        |                                                                                         3072                                                                                         |
    |       sourceID      |                                                                         20412ae4-f447-4a9f-8f10-2f607e27f794                                                                         |
    |        state        |                                                                                        ready                                                                                         |
    |      stateInfo      |                                                                                         None                                                                                         |
    +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    

    This command mounts the volume as a block device on the specified host. Verify this with an lsblk command.

  6. Look at the command output and find the block device ID – this ID is the mountpoint value listed next to the attachments property.

    In the example above the block device ID is: /dev/nbd62

  7. Based on the size of the volume exported, look for free space on /mnt/mancalaX to view where to put the export file.

    To check free space issue a zpool list command, then check the FREE column to pick the disk that looks like it has the most free space.

    Example:

    [root@stratonode1 mancala0]# zpool list
    NAME       SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
    mancala0  1.81T  9.77G  1.80T         -     0%     0%  1.00x  ONLINE  -
    mancala1  1.81T  9.55G  1.80T         -     0%     0%  1.00x  ONLINE  -
    
  8. Once the decision to which disk to export the volume to has been made, export the volume by using this qemu-img command, which converts the volume file to QCOW2 and exports it to the disk decided upon:

``qemu-img convert -f host_device -O qcow2 <block-device-id> <output-file-location-and-name>``

Example:

# qemu-img convert -f host_device -O qcow2 /dev/nbd62 /mnt/mancala0/file.qcow2