示例#1
0
 def _get_root_disk(self, root_device_type, instance, ec2_conn):
     # list of all mounted devices 
     if root_device_type == 'ebs':
         vol_filters = {'attachment.instance-id': instance.id}
         attached_vols = ec2_conn.get_all_volumes(filters=vol_filters)
         for vol in attached_vols:
             if instance.root_device_name == vol.attach_data.device:
                 return vol
         raise ImageAPIError("Failed to find root volume")
     else:
         devices = coreutils.df()
         # root device partition like `df(device='/dev/sda2', ..., mpoint='/')
         for device in devices:
             if device.mpoint == '/':
                 return device
         raise ImageAPIError("Can't find root device")
示例#2
0
    def snapshot(self, op, name):
        rebundle_dir = tempfile.mkdtemp()
        archive_path = ''
        try:
            pl = __node__['platform']
            proj_id = pl.get_numeric_project_id()
            proj_name = pl.get_project_id()
            cloudstorage = pl.get_storage_conn()

            root_part_path = None
            for d in coreutils.df():
                if d.mpoint == '/':
                    root_part_path = d.device
                    break
            else:
                raise ImageAPIError('Failed to find root volume')

            root_part_sysblock_path = glob.glob(
                '/sys/block/*/%s' % os.path.basename(root_part_path))[0]
            root_device = '/dev/%s' % os.path.basename(
                os.path.dirname(root_part_sysblock_path))

            archive_name = '%s.tar.gz' % name.lower()
            archive_path = os.path.join(rebundle_dir, archive_name)

            self._prepare_software()

            gcimagebundle_bin = software.which('gcimagebundle')

            out, err, code = util.system2(
                (gcimagebundle_bin, '-d', root_device, '-e', ','.join(
                    self.exclude_dirs), '-o', rebundle_dir,
                 '--output_file_name', archive_name),
                raise_exc=False)
            if code:
                raise ImageAPIError(
                    'Gcimagebundle util returned non-zero code %s. Stderr: %s'
                    % (code, err))

            LOG.info('Uploading compressed image to cloud storage')
            tmp_bucket_name = 'scalr-images-%s-%s' % (random.randint(
                1, 1000000), int(time.time()))
            remote_dir = 'gcs://%s' % tmp_bucket_name

            def progress_cb(progress):
                LOG.debug('Uploading {perc}%'.format(
                    perc=progress / os.path.getsize(archive_path)))

            uploader = largetransfer.Upload(archive_path,
                                            remote_dir,
                                            simple=True,
                                            progress_cb=progress_cb)
            uploader.apply_async()
            try:
                uploader.join()
            except:
                if uploader.error:
                    error = uploader.error[1]
                else:
                    error = sys.exc_info()[1]
                msg = 'Image upload failed. Error:\n{error}'
                msg = msg.format(error=error)
                self._remove_bucket(tmp_bucket_name, archive_name,
                                    cloudstorage)
                raise ImageAPIError(msg)
        finally:
            shutil.rmtree(rebundle_dir)
            if os.path.exists(archive_path):
                os.remove(archive_path)

        image_name = name.lower().replace('_', '-') + '-' + str(
            int(time.time()))
        self._register_image(image_name, tmp_bucket_name, archive_name,
                             cloudstorage)

        return '%s/images/%s' % (proj_name, image_name)
示例#3
0
    def rebundle(self):
        rebundle_dir = tempfile.mkdtemp()

        try:
            pl = bus.platform
            proj_id = pl.get_numeric_project_id()
            proj_name = pl.get_project_id()
            cloudstorage = pl.get_storage_conn()

            # Determine the root filesystem size
            devices = coreutils.df()
            root_disk = firstmatched(lambda x: x.mpoint == '/', devices)
            if not root_disk:
                raise HandlerError("Can't find root device")
            # in bytes adjusted to 512 block device size
            fssize = (root_disk.size * 1000 / 512) * 512

            # Old code. Should be reworked
            if os.path.exists('/dev/root'):
                root_part_path = os.path.realpath('/dev/root')
            else:
                rootfs_stat = os.stat('/')
                root_device_minor = os.minor(rootfs_stat.st_dev)
                root_device_major = os.major(rootfs_stat.st_dev)
                root_part_path = os.path.realpath('/dev/block/{0}:{1}'.format(
                    root_device_major, root_device_minor))

            root_part_sysblock_path = glob.glob(
                '/sys/block/*/%s' % os.path.basename(root_part_path))[0]
            root_device = '/dev/%s' % os.path.basename(
                os.path.dirname(root_part_sysblock_path))

            arch_name = '%s.tar.gz' % self._role_name.lower()
            arch_path = os.path.join(rebundle_dir, arch_name)

            # update gcimagebundle
            try:
                pkgmgr.latest(self.gcimagebundle_pkg_name)
            except:
                e = sys.exc_info()[1]
                LOG.warn('Gcimagebundle update failed: %s' % e)

            if os_dist.redhat_family:
                semanage = software.which('semanage')
                if not semanage:
                    pkgmgr.installed('policycoreutils-python')
                    semanage = software.which('semanage')

                util.system2((semanage, 'permissive', '-a', 'rsync_t'))

            gc_img_bundle_bin = software.which('gcimagebundle')

            o, e, p = util.system2(
                (gc_img_bundle_bin, '-d', root_device, '-e', ','.join(
                    self.exclude_dirs), '--fssize', str(fssize), '-o',
                 rebundle_dir, '--output_file_name', arch_name),
                raise_exc=False)
            if p:
                raise HandlerError(
                    'Gcimagebundle util returned non-zero code %s. Stderr: %s'
                    % (p, e))

            try:
                LOG.info('Uploading compressed image to cloud storage')
                tmp_bucket_name = 'scalr-images-%s-%s' % (random.randint(
                    1, 1000000), int(time.time()))
                remote_dir = 'gcs://%s' % tmp_bucket_name

                def progress_cb(progress):
                    LOG.debug('Uploading {perc}%'.format(
                        perc=progress / os.path.getsize(arch_path)))

                uploader = largetransfer.Upload(arch_path,
                                                remote_dir,
                                                simple=True,
                                                progress_cb=progress_cb)
                uploader.apply_async()
                try:
                    try:
                        uploader.join()
                    except:
                        if uploader.error:
                            error = uploader.error[1]
                        else:
                            error = sys.exc_info()[1]
                        msg = 'Image upload failed. Error:\n{error}'
                        msg = msg.format(error=error)
                        raise HandlerError(msg)
                except:
                    with util.capture_exception(LOG):
                        objs = cloudstorage.objects()
                        objs.delete(bucket=tmp_bucket_name,
                                    object=arch_name).execute()
                    cloudstorage.buckets().delete(
                        bucket=tmp_bucket_name).execute()
            finally:
                os.unlink(arch_path)

        finally:
            shutil.rmtree(rebundle_dir)

        goog_image_name = self._role_name.lower().replace(
            '_', '-') + '-' + str(int(time.time()))
        try:
            LOG.info('Registering new image %s' % goog_image_name)
            compute = pl.get_compute_conn()

            image_url = 'http://storage.googleapis.com/%s/%s' % (
                tmp_bucket_name, arch_name)

            req_body = dict(name=goog_image_name,
                            sourceType='RAW',
                            rawDisk=dict(source=image_url))

            req = compute.images().insert(project=proj_id, body=req_body)
            operation = req.execute()['name']

            LOG.info('Waiting for image to register')

            def image_is_ready():
                req = compute.globalOperations().get(project=proj_id,
                                                     operation=operation)
                res = req.execute()
                if res['status'] == 'DONE':
                    if res.get('error'):
                        errors = []
                        for e in res['error']['errors']:
                            err_text = '%s: %s' % (e['code'], e['message'])
                            errors.append(err_text)
                        raise Exception('\n'.join(errors))
                    return True
                return False

            util.wait_until(image_is_ready, logger=LOG, timeout=600)

        finally:
            try:
                objs = cloudstorage.objects()
                objs.delete(bucket=tmp_bucket_name, object=arch_name).execute()
                cloudstorage.buckets().delete(bucket=tmp_bucket_name).execute()
            except:
                e = sys.exc_info()[1]
                LOG.error('Failed to remove image compressed source: %s' % e)

        return '%s/images/%s' % (proj_name, goog_image_name)