You have a running instance, perhaps with EBS volumes attached, and you want to make a clone of that instance.
Use the get_userdata
and clone_instance
functions in this recipe to create a copy of an existing instance,
including copies of all attached EBS volumes based on the latest
available snapshots.
For this recipe, let’s assume that you have a running instance. It could have one or more EBS volumes attached to it. Let’s also assume that, for some reason, you want to create another instance that is an exact copy of the currently running instance. You may want to do this because the running instance appears to be having issues or it may be that you want to debug an issue without disturbing your production instance.
Whatever the reason may be, this recipe defines a function to help us clone a running instance. To accomplish this, we need to gather some information:
We need to know the AMI, keypair, security groups,
availability zone, instance type, etc. of the current instance. We
can get all of that information easily from the boto
Instance
object that represents the current instance.
We need to make copies of all EBS volumes that are attached to the instance. For this recipe, we will assume that the latest snapshot of the volumes represents the state we want to recreate.
We need the user_data
that was passed to the
instance when it was started. This data could include data and/or
scripts that are run when the instance is launched as shown in Executing Custom Scripts upon Instance Startup.
Example 2-11. Clone a Running Instance
import boto from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType import os import base64 def clone_instance(instance): """ Make an clone of an existing Instance object. instance The Instance object to clone. """ new_bdm = None ec2 = instance.connection if instance.block_device_mapping: root_device_name = instance.get_attribute('rootDeviceName')['rootDeviceName'] user_data = instance.get_attribute('userData')['userData'] # user_data comes back base64 encoded. Need to decode it so it # can get re-encoded by run_instance ! user_data = base64.b64decode(user_data) new_bdm = BlockDeviceMapping() for dev in instance.block_device_mapping: # if this entry is about the root device, skip it if dev != root_device_name: bdt = instance.block_device_mapping[dev] if bdt.volume_id: volume = ec2.get_all_volumes([bdt.volume_id])[0] snaps = volume.snapshots() if len(snaps) == 0: print 'No snapshots available for %s' % volume.id else: # sort the list of snapshots, newest is at the end now snaps.sort(key=lambda snap: snap.start_time) latest_snap = snaps[-1] new_bdt = BlockDeviceType() new_bdt.snapshot_id = latest_snap.id new_bdm[dev] = new_bdt return ec2.run_instances(instance.image_id, key_name=instance.key_name, security_groups=[g.name for g in instance.groups], user_data=user_data, instance_type=instance.instance_type, kernel_id=instance.kernel, ramdisk_id=instance.ramdisk, monitoring_enabled=instance.monitored, placement=instance.placement, block_device_map=new_bdm).instances[0]