def get_buckets(self): try: buckets = self.conn.get_all_buckets() except TypeError: #hack until boto fixes get_all_buckets raise exception.AWSError("AWS credentials are not valid") return buckets
def get_image_files(self, image_id): """ Return list of files on S3 for image_id The list includes the image's manifest and part files """ image = self.get_image(image_id) if image.root_device_type == 'ebs': raise exception.AWSError( "Image %s is an EBS image. No image files on S3." % image_id) bucket = self.get_image_bucket(image) return self._get_image_files(image, bucket)
def _create_image_from_ebs(self, size=15): log.info("Creating EBS image...") imgid = self.ec2.create_image(self.host.id, self.name, self.description) log.info("Waiting for AMI %s to become available..." % imgid, extra=dict(__nonewline__=True)) img = self.ec2.get_image(imgid) s = Spinner() s.start() while img.state == "pending": time.sleep(15) if img.update() == "failed": raise exception.AWSError( "EBS image creation failed for AMI %s" % imgid) s.stop() return imgid
def _create_image_from_ebs(self, size=15): log.info("Creating new EBS AMI...") imgid = self.ec2.create_image(self.host.id, self.name, self.description) img = self.ec2.get_image(imgid) log.info("New EBS AMI created: %s" % imgid) root_dev = self.host.root_device_name if root_dev in self.host.block_device_mapping: log.info("Fetching block device mapping for %s" % imgid, extra=dict(__nonewline__=True)) s = Spinner() try: s.start() while root_dev not in img.block_device_mapping: img = self.ec2.get_image(imgid) time.sleep(5) finally: s.stop() snapshot_id = img.block_device_mapping[root_dev].snapshot_id snap = self.ec2.get_snapshot(snapshot_id) self.ec2.wait_for_snapshot(snap) else: log.warn("Unable to find root device - cant wait for snapshot") log.info("Waiting for %s to become available..." % imgid, extra=dict(__nonewline__=True)) s = Spinner() try: s.start() while img.state == "pending": time.sleep(15) if img.update() == "failed": raise exception.AWSError( "EBS image creation failed for %s" % imgid) finally: s.stop() return imgid
def migrate_image(self, image_id, destbucket, migrate_manifest=False, kernel_id=None, ramdisk_id=None, region=None, cert=None, private_key=None): """ Migrate image_id files to destbucket """ if migrate_manifest: utils.check_required(['ec2-migrate-manifest']) if not cert: raise exception.BaseException("no cert specified") if not private_key: raise exception.BaseException("no private_key specified") if not kernel_id: raise exception.BaseException("no kernel_id specified") if not ramdisk_id: raise exception.BaseException("no ramdisk_id specified") image = self.get_image(image_id) if image.root_device_type == "ebs": raise exception.AWSError( "The image you wish to migrate is EBS-based. " + "This method only works for instance-store images") ibucket = self.get_image_bucket(image) files = self._get_image_files(image, ibucket) if not files: log.info("No files found for image: %s" % image_id) return log.info("Migrating image: %s" % image_id) widgets = [files[0].name, progressbar.Percentage(), ' ', progressbar.Bar(marker=progressbar.RotatingMarker()), ' ', progressbar.ETA(), ' ', ' '] counter = 0 num_files = len(files) pbar = progressbar.ProgressBar(widgets=widgets, maxval=num_files).start() for f in files: widgets[0] = "%s: (%s/%s)" % (f.name, counter + 1, num_files) # copy file to destination bucket with the same name f.copy(destbucket, f.name) pbar.update(counter) counter += 1 pbar.finish() if migrate_manifest: dbucket = self.s3.get_bucket(destbucket) manifest_key = dbucket.get_key(self.get_image_manifest(image)) f = tempfile.NamedTemporaryFile() manifest_key.get_contents_to_file(f.file) f.file.close() cmd = ('ec2-migrate-manifest -c %s -k %s -m %s --kernel %s ' + '--ramdisk %s --no-mapping ') % (cert, private_key, f.name, kernel_id, ramdisk_id) register_cmd = "ec2-register %s/%s" % (destbucket, manifest_key.name) if region: cmd += '--region %s' % region register_cmd += " --region %s" % region log.info("Migrating manifest file...") retval = os.system(cmd) if retval != 0: raise exception.BaseException( "ec2-migrate-manifest failed with status %s" % retval) f.file = open(f.name, 'r') manifest_key.set_contents_from_file(f.file) # needed so that EC2 has permission to READ the manifest file manifest_key.add_email_grant('READ', '*****@*****.**') f.close() os.unlink(f.name + '.bak') log.info("Manifest migrated successfully. You can now run:\n" + register_cmd + "\nto register your migrated image.")
def create_image(self, size=15): host = self.host host_ssh = self.host_ssh self.clean_private_data() if self.host.root_device_type == "ebs": log.info("Creating EBS image...") imgid = self.ec2.create_image(host.id, self.name, self.description) s = Spinner() log.log(INFO_NO_NEWLINE, "Waiting for AMI %s to become available..." % imgid) s.start() img = self.ec2.get_image(imgid) while img.update() == "pending": time.sleep(15) s.stop() if img.update() == "failed": raise exception.AWSError( "EBS image creation failed for AMI %s" % imgid) return imgid log.info("Creating new EBS-backed image from instance-store instance") log.info("Creating new root volume...") vol = self.ec2.create_volume(size, host.placement) log.info("Created new volume: %s" % vol.id) while vol.update() != 'available': time.sleep(5) dev = None for i in string.ascii_lowercase[::-1]: dev = '/dev/sd%s' % i if not dev in host.block_device_mapping: break log.info("Attaching volume %s to instance %s on %s" % (vol.id, host.id, dev)) vol.attach(host.id, dev) while vol.update() != 'in-use': time.sleep(5) while not host_ssh.path_exists(dev): time.sleep(5) host_ssh.execute('mkfs.ext3 -F %s' % dev) mount_point = '/ebs' while host_ssh.path_exists(mount_point): mount_point += '1' host_ssh.mkdir(mount_point) log.info("Mounting %s on %s" % (dev, mount_point)) host_ssh.execute('mount %s %s' % (dev, mount_point)) log.info("Configuring /etc/fstab") host_ssh.remove_lines_from_file('/etc/fstab', '/mnt') fstab = host_ssh.remote_file('/etc/fstab', 'a') fstab.write('/dev/sdb1 /mnt auto defaults,nobootwait 0 0\n') fstab.close() log.info("Syncing root filesystem to new volume (%s)" % vol.id) host_ssh.execute( 'rsync -avx --exclude %(mpt)s --exclude /root/.ssh / %(mpt)s' % \ {'mpt': mount_point}) log.info("Unmounting %s from %s" % (dev, mount_point)) host_ssh.execute('umount %s' % mount_point) log.info("Detaching volume %s from %s" % (dev, mount_point)) vol.detach() while vol.update() != 'available': time.sleep(5) snap = self.ec2.create_snapshot(vol, description=self.snapshot_description, wait_for_snapshot=True) log.info("New snapshot created: %s" % snap.id) bmap = self.ec2.create_root_block_device_map(snap.id, add_ephemeral_drives=True) log.info("Registering new image...") img_id = self.ec2.register_image(name=self.name, description=self.description, architecture=host.architecture, kernel_id=self.kernel_id, ramdisk_id=self.ramdisk_id, root_device_name='/dev/sda1', block_device_map=bmap) return img_id