40

Is it possible to create a hardware virtual machine (HVM) AMI from an existing paravirtual (PV) AMI.

My initially thought was to start a new PV instance and use the ec2-create-image command to create a new image while specifying HVM as the virutalization type. However, ec2-create-image does not have a command line parameter to specify the virtualization type.

Is there another way to go about doing this?

Adrian Heine
  • 328
  • 4
  • 22
javacavaj
  • 501
  • 1
  • 4
  • 5

5 Answers5

22

Update

AWS has enabled this feature in the EC2 API. It is available as the --virtualization-type option to aws ec2 register-image in the new Boto based awscli.

Original answer

Yes! Unfortunately, there is not a direct way to do so. Also, some PV instances may need kernel and bootloader modifications.

  1. Create a volume from your existing PV AMI. If it was your own PV AMI, you can make a volume from the snapshot. If it is a 3rd party AMI, you will need to launch an instance and take a snapshot.
  2. Launch an HVM instance with any AMI.
  3. Stop that HVM instance.
  4. Detach the root volume from that instance.
  5. Attach the PV volume as the root volume(/dev/sda1 or /dev/sda if it was partitioned) to the HVM instance.
  6. Run ec2-create-image on the HVM instance.
  7. Launch other instances with your new HVM AMI.

If that doesn't work, then before step 5, you will need to attach that volume to a running instance, set up a chroot, and install a kernel and bootloader for your distribution. You may also want to clear logs and any cloud-init cache.

Jeff Strunk
  • 2,107
  • 1
  • 24
  • 29
  • 2
    I tried steps 1-5 and it didn't work for me, as the instance stops after a few seconds. Could someone elaborate on how to set up a chroot, and install a kernel and bootloader? Both the old and new instances are AMI Linux. Thanks. – tolgamorf Mar 26 '15 at 12:55
  • If you have a working PV instance, you can convert it to HVM by running `aws ec2 register-image` with the --virtualization-type flag on the snapshot of the PV image. See `aws ec2 register-image help` for details. – Jeff Strunk Mar 26 '15 at 17:07
  • 2
    I created an HVM image from my PV instance using `aws ec2 register-image`. Then I launched a new HVM instance from that image. However the system won't boot. – tolgamorf Mar 27 '15 at 20:27
  • After digging through the aws ec2 forum, I came up with a solution in which the conversion is done by replacing the files manually. I will write up an answer soon. – tolgamorf Mar 27 '15 at 20:29
  • @tolgamorf do you remember at all what you did? I am having the same problem. – Dmitry Minkovsky Nov 15 '15 at 21:50
  • I guess I can Google too :) https://forums.aws.amazon.com/thread.jspa?messageID=553638 anda probably some others. – Dmitry Minkovsky Nov 15 '15 at 21:52
  • @dimadima my answer is below: http://serverfault.com/a/678867/165528 – tolgamorf Nov 15 '15 at 21:54
  • FYI, the "update" to this answer will not work in most cases. See the answer https://serverfault.com/a/678867/252159 – Tejay Cardon Feb 12 '18 at 16:35
14

In my case, I had to do the conversion manually since the instance that I create using aws ec2 register-image did not boot. My solution is based on this post on the AWS EC2 Forum.

Preparation

Make sure that all the volumes are in the same availability zone.

  1. SSH to your PV machine that you want to migrate from and apply all updates, then log out.

  2. Go to the AWS Console and launch a new HVM instance by selecting the same base AMI that the PV system was created from (in my case, the Amazon 64-bit Linux AMI).

  3. SSH to this new instance and apply all updates, then log out.

  4. Go to the AWS Console and stop the PV instance. Take a snapshot of the root device and create a new volume (SOURCE VOLUME) from this snapshot.

  5. Stop the HVM instance. Take a snapshot of the root device on the new instance and create a new volume (TARGET VOLUME) from this snapshot.

  6. Using the AWS Console:

    • Attach SOURCE VOLUME to the new instance as /dev/xvdf.
    • Attach TARGET VOLUME to the new instance as /dev/xvdg.

Conversion Process

  1. SSH to the new instance and get root access:

    sudo su
    
  2. Mount the source and target drives.

    mkdir -p /mnt/source && mount /dev/xvdf /mnt/source
    mkdir -p /mnt/target && mount /dev/xvdg1 /mnt/target
    

    In my case, the devices were /dev/xvdf (source) and /dev/xvdg1 (target). These may change in your configuration based on the number of partitions and where you attached them (see step 6 in Preparation). Use ls -al /dev/xvd* to see the drives.

  3. Backup /lib/modules/* (If the kernel of the PV ami differs from the new HVM machine. This module is used by some services of AWS.)

  4. Delete everything but /boot on the target volume:

    cd /mnt/target && ls | grep -v boot | xargs rm -Rf
    
  5. Delete /boot on the source volume:

    rm -Rf /mnt/source/boot
    
  6. Copy the source volume's data to the target volume preserving all the attributes:

    rsync -aAXHPv /mnt/source/ /mnt/target
    
  7. Edit /mnt/target/etc/fstab for / partition, so that it references the TARGET VOLUME when mounted on its final location in step (8). Either using a label or simply something along:

    /dev/xvda1 /     ext4    defaults,barrier=0 1 1
    

Then restore /lib/modules/ that was backed up in Step 3. (If the kernel of the PV ami differs from the new HVM machine.)

  1. Stop the system and detach all volumes using the AWS console. Attach the TARGET VOLUME on the new instance as /dev/xvda.

    Be sure to note where the original root device was mounted. In most cases, it should be /dev/xvda.

  2. Start your HVM instance. It should now be an exact duplicate of your PV system. If everything looks OK, you may now delete your PV instance and also SOURCE VOLUME.

Zar
  • 103
  • 3
tolgamorf
  • 241
  • 3
  • 7
  • 1
    Why don't you simply do a `rm -f /boot` and `cp -a /mnt/source/boot /mnt/target`? – michelem Jun 29 '15 at 13:23
  • @Michelem if I remember correctly, I tried doing that in the first place. The machine did not boot. – tolgamorf Jul 13 '15 at 17:08
  • Thanks for this. Just wanted to report some odd behaviour I encountered. After step 3 in the conversion process I realised I had wiped the root directory as well as `/mnt/target`. I retraced my steps and noticed that for some reason `xvdg` was mounted as the root partition (rather than `/dev/sda1` in my case) when starting the instance. So I worked around this by starting the instance and __then__ attaching. – Dan Gravell Nov 19 '15 at 14:38
  • Maybe this is because I am using magnetic storage, and the `xv...` devices automatically override? – Dan Gravell Nov 19 '15 at 14:51
  • Also, when mounting the target in step 6, I had to attach as `/dev/sda1` (including the partition). Maybe this is all because it's expecting a magnetic volume. – Dan Gravell Nov 19 '15 at 15:10
  • Is there a missing/implied step in between "Preparation" and "Conversion Process"? In "Preparation", you stop the HVM instance, but the first step in "Conversion Process" is to ssh to the "new instance". Does this mean we are supposed to restart the HVM instance after the current last step of the "Conversion Process" section? If not, what is the "new instance"? – Dan Tenenbaum Feb 01 '16 at 21:45
  • @DanTenenbaum yes, you are absolutely right. Before beginning the "Conversion Process", you need to start the HVM instance, which is also referred to as "new instance". – tolgamorf Feb 01 '16 at 21:52
  • 1
    @tolgamorf Any chance of updating the answer to reflect this? – Dan Tenenbaum Feb 01 '16 at 21:54
  • Another good thing to mention is that the target volume needs to be the same size (or larger) as the source volume. – Dan Tenenbaum Feb 01 '16 at 23:06
  • 2
    These instructions were really helpful (and worked for me!!) but I have one last suggestion. Since the original question was about making an HVM AMI, don't leave that step implicit, add a final step of stopping the instance and making an AMI from it (and then terminating the instance). Also, I had the exact same issues as @DanGravell and I am not using magnetic storage, so these may be common pitfalls that could be addressed in the answer. – Dan Tenenbaum Feb 02 '16 at 01:06
  • Can you give a little more detail on how we should edit /etc/fstab ? – ozguronur Sep 08 '17 at 13:24
  • @ozguronur that step was added by someone else through an edit. I didn't have to edit `/etc/fstab`. Check out MadHatter's answer step 7.3: https://serverfault.com/questions/439976/create-an-aws-hvm-linux-ami-from-an-existing-paravirtual-linux-ami/723390#723390 – tolgamorf Sep 09 '17 at 23:41
  • 1
    Many thanks! This saved me a lot of time, edited it to clear up the fstab part which confused me a bit. Beware during step (4), I somehow deleted the temporary volume's root and not the targets, breaking that volume and had to restart the process. – Zar Jan 18 '18 at 10:13
  • Many thanks. A tip for large volumes (50GB) and on shaky networks - we found using nohup and backgrounding the rsync operation saved a lot of time ( an hour or so and we lost one rsync due to a network drop) e.g. #nohup rsync -aAXHPv /mnt/source/ /mnt/target & – goelectric Jan 14 '22 at 15:44
10

TLDR:

ec2-register -a x86_64 -d '3.15.7-200.fc20.x86_64' -n 'Fedora_20_HVM_AMI'  --sriov simple --virtualization-type hvm -s snap-b44feb18 --root-device-name /dev/sda1 

Detailed steps:

Answering further based upon Jeff Strunk's response to simplify the steps and giving a bit more details on the ec2 register image:

  1. Create Instance using PV Image. Make / update any changes you want.

  2. Create Image from the above instance.

  3. Find the snapshot id used by the above AMI under EC2 > Elastic Block Store > Snapshot in EC2 Console.

    or if you have the ec2 api tools setup:

    ec2-describe-images ami-id_of_above_created_ami

    and find the snapshot id for the ami

    .. Assumptions for further steps: Your ec2 keys and api tools are set and ready to use:

  4. Register a new HVM AMI using the above snapshot: example:

ec2-register -a x86_64 -d '3.15.7-200.fc20.x86_64' -n 'Fedora_20_HVM_AMI' --sriov simple --virtualization-type hvm -s snap-b44feb18 --root-device-name /dev/sda1

where

  • -d is AMI description
  • -n is AMI name
  • -s is snapshot id from step 3.
  • -a is architecture
  • --virtualization-type is required for making it hvm
  • --sriov is for enabling enhanced networking , though it might be redundant, not sure.

For more information:

Anshu Prateek
  • 201
  • 3
  • 9
  • 2
    Unless I'm doing something wrong, this will not work for marketplace AMIs that restrict instance types. Tried converting the official MongoDB paravirtual AMI to HVM, and while I could create the HVM AMI, it wouldn't launch an HVM-instance with it. – Matt Beckman Aug 25 '14 at 17:46
  • @MattBeckman I think its about the underlying kernel/bootloader support rather than AMI restriction. Above works for fedora but not for amazon linux. There you have to go the way as suggested by Jeff Strunk originaly. – Anshu Prateek Sep 01 '14 at 03:40
  • 1
    It worked @AnshuPrateek – Atmesh Mishra May 09 '18 at 10:41
2

You can do this from inside of the AWS web interface. Navigate to snapshots, click the desired snapshot you wish to convert to hvm and click on actions and then create image. In the dropdown in the create image wizard select HVM.

Justin
  • 5,008
  • 19
  • 58
  • 82
  • 10
    I just tried this, but it loos like the instance won't properly boot. It just gets in the stopped state by itself, few moments after I start it. – ovi Nov 26 '15 at 14:02
1

Having tried all of the suggestions herein, none of which worked for me, I found an excellent blog entry on the subject, at https://www.opswat.com/blog/aws-2015-why-you-need-switch-pv-hvm .

The elements (details) of the procedure are:

  1. Install grub on the PV instance to be migrated (source instance).

  2. Make a precautionary snapshot of the root volume on the source instance (source volume, SV).

  3. Create a temporary HVM instance which will migrate the volume.

    1. I used an Amazon Linux instance
  4. Create a destination volume (DV), and attach both this and the SV to the temporary instance.

    1. The DV should be at least as big as the SV.

    2. Attach the SV as /dev/{sd,xvd}f, and the DV as /dev/{sd,xvd}g.

    3. Partition the DV:

    parted /dev/xvdg --script 'mklabel msdos mkpart primary 1M -1s print quit'

    partprobe /dev/xvdg

    udevadm settle

  5. Resize to minimum size the SV's FS, and using dd image it onto the DV.

    1. Clean the source volume's FS: e2fsck -f /dev/xvdf

    2. Minimise the same: resize2fs -M /dev/xvdf

    3. Observe the output from the resize2fs (eg Resizing the file system on /dev/xvdf to 269020 (4k) blocks) and note it down for the next step.

    4. Duplicate SV to DV: dd if=/dev/xvdf of=/dev/xvdg1 bs=<block size from previous step, here 4k> count=<use block count from last step, here 269020>

    5. Expand the FS on the new partition: resize2fs /dev/xvdg1

  6. Install grub into the DV's boot block

    1. Temporarily create device files on the DV: mount /dev/xvdg1 /mnt; cp -a /dev/xvdg /dev/xvdg1 /mnt/dev/

    2. Install grub files:

    rm -f /mnt/boot/grub/*stage*

    cp /mnt/usr/*/grub/*/*stage* /mnt/boot/grub/

    rm -f /mnt/boot/grub/device.map

    1. Install grub in a chroot environment:

    cat << ARNIE | chroot /mnt grub --batch

    device (hd0) /dev/xvdg

    root (hd0,0)

    setup (hd0)

    ARNIE

  7. Having made some other minor changes on the destination volume, snap the volume, and make an AMI from it.

    1. Tidy up the temporary device files: rm -f /mnt/dev/xvdg /mnt/dev/xvdg1

    2. In /mnt/boot/grub/grub.conf, change root (hd0) to root (hd0,0), add (or replace console=*) console=ttyS0 to kernel line, and if necessary replace root=* with root=LABEL=/ in the kernel line

    3. In /mnt/etc/fstab, ensure that the root FS's line contains a labelled reference, eg

    LABEL=/ / ext4 defaults,noatime 1 1

    1. Label the new root FS with e2label /dev/xvdg1 /

    2. Unmount DV from the temporary instance, detach both SV and DV from the temporary instance.

    3. Snap the DV, and from that snap create an AMI image.

  8. Launch an HVM instance from that HMI. That is your migrated instance.

MadHatter
  • 78,442
  • 20
  • 178
  • 229