Beispiel #1
0
 def get_snapshot_state(self, snap):
     snapshots = self._new_conn().listSnapshots(id=snap.id)
     if not snapshots:
         raise StorageError(
             'listSnapshots returned empty list for snapshot %s' % snap.id)
     state = snapshots[0].state
     return self.snapshot_state_map[state]
Beispiel #2
0
            def get_free_devname(device):
                if device:
                    device = ebstool.get_ebs_devname(device)

                used_letters = set(row['device'][-1]
                                        for row in Storage.volume_table()
                                        if row['device'] and ( \
                                                row['state'] == 'attached' or ( \
                                                pl.get_instance_type() == 't1.micro' and row['state'] == 'detached')))

                with self.letters_lock:

                    avail_letters = list(
                        set(self.all_letters) - used_letters -
                        self.acquired_letters)

                    volumes = conn.get_all_volumes(
                        filters={
                            'attachment.instance-id': pl.get_instance_id()
                        })

                    for volume in volumes:
                        volume_device = volume.attach_data.device
                        volume_device = re.sub('\d+', '', volume_device)
                        try:
                            avail_letters.remove(volume_device[-1])
                        except ValueError:
                            pass

                    if not device or not (device[-1] in avail_letters
                                          ) or os.path.exists(device):
                        letter = firstmatched(
                            lambda l: not os.path.exists(
                                ebstool.real_devname('/dev/sd%s' % l)),
                            avail_letters)
                        if letter:
                            device = '/dev/sd%s' % letter
                            self.acquired_letters.add(letter)
                        else:
                            raise StorageError(
                                'No free letters for block device name remains'
                            )

                return device
Beispiel #3
0
    def _create(self, **kwargs):
        '''
        @param id: EBS volume id
        @param device: Device name
        @param size: Size in GB
        @param avail_zone: Availability zone
        @param snapshot_id: Snapshot id
        '''
        ebs_vol = None
        pl = bus.platform
        conn = self._new_ec2_conn()

        if conn:
            device = kwargs.get('device')

            def get_free_devname(device):
                if device:
                    device = ebstool.get_ebs_devname(device)

                used_letters = set(row['device'][-1]
                                        for row in Storage.volume_table()
                                        if row['device'] and ( \
                                                row['state'] == 'attached' or ( \
                                                pl.get_instance_type() == 't1.micro' and row['state'] == 'detached')))

                with self.letters_lock:

                    avail_letters = list(
                        set(self.all_letters) - used_letters -
                        self.acquired_letters)

                    volumes = conn.get_all_volumes(
                        filters={
                            'attachment.instance-id': pl.get_instance_id()
                        })

                    for volume in volumes:
                        volume_device = volume.attach_data.device
                        volume_device = re.sub('\d+', '', volume_device)
                        try:
                            avail_letters.remove(volume_device[-1])
                        except ValueError:
                            pass

                    if not device or not (device[-1] in avail_letters
                                          ) or os.path.exists(device):
                        letter = firstmatched(
                            lambda l: not os.path.exists(
                                ebstool.real_devname('/dev/sd%s' % l)),
                            avail_letters)
                        if letter:
                            device = '/dev/sd%s' % letter
                            self.acquired_letters.add(letter)
                        else:
                            raise StorageError(
                                'No free letters for block device name remains'
                            )

                return device

            self._logger.debug('storage._create kwds: %s', kwargs)
            volume_id = kwargs.get('id')

            # TODO: hotfix
            if volume_id and volume_id.startswith('snap-'):
                volume_id = None

            snap_id = kwargs.get('snapshot_id')
            ebs_vol = None
            delete_snap = False
            volume_attached = False
            try:
                if volume_id:
                    self._logger.debug('EBS has been already created')
                    try:
                        ebs_vol = conn.get_all_volumes([volume_id])[0]
                    except IndexError:
                        raise StorageError("EBS volume '%s' doesn't exist." %
                                           volume_id)

                    if ebs_vol.zone != pl.get_avail_zone():
                        self._logger.warn(
                            'EBS volume %s is in the different availability zone (%s). '
                            +
                            'Snapshoting it and create a new EBS volume in %s',
                            ebs_vol.id, ebs_vol.zone, pl.get_avail_zone())
                        volume_id = None
                        delete_snap = True
                        snap_id = ebstool.create_snapshot(
                            conn,
                            ebs_vol,
                            logger=self._logger,
                            wait_completion=True,
                            tags=kwargs.get('tags')).id
                    else:
                        snap_id = None

                if snap_id or not volume_id:
                    self._logger.debug('Creating new EBS')
                    kwargs['avail_zone'] = pl.get_avail_zone()
                    ebs_vol = ebstool.create_volume(conn,
                                                    kwargs.get('size'),
                                                    kwargs.get('avail_zone'),
                                                    snap_id,
                                                    kwargs.get('volume_type'),
                                                    kwargs.get('iops'),
                                                    logger=self._logger,
                                                    tags=kwargs.get('tags'))

                if 'available' != ebs_vol.volume_state():
                    if ebs_vol.attachment_state() == 'attaching':
                        wait_until(
                            lambda: ebs_vol.update(
                            ) and ebs_vol.attachment_state() != 'attaching',
                            timeout=600,
                            error_text='EBS volume %s hangs in attaching state'
                            % ebs_vol.id)

                    if ebs_vol.attach_data.instance_id != pl.get_instance_id():
                        self._logger.debug(
                            'EBS is attached to another instance')
                        self._logger.warning(
                            "EBS volume %s is not available. Detaching it from %s",
                            ebs_vol.id, ebs_vol.attach_data.instance_id)
                        ebstool.detach_volume(conn,
                                              ebs_vol,
                                              force=True,
                                              logger=self._logger)
                    else:
                        self._logger.debug('EBS is attached to this instance')
                        device = ebstool.real_devname(
                            ebs_vol.attach_data.device)
                        wait_until(
                            lambda: os.path.exists(device),
                            sleep=1,
                            timeout=300,
                            error_text=
                            "Device %s wasn't available in a reasonable time" %
                            device)
                        volume_attached = True

                if not volume_attached:
                    device = kwargs.get('device')
                    device = get_free_devname(device)

                    self._logger.debug('Attaching EBS to this instance')
                    device = ebstool.attach_volume(conn,
                                                   ebs_vol,
                                                   pl.get_instance_id(),
                                                   device,
                                                   to_me=True,
                                                   logger=self._logger)[1]

            except:
                self._logger.debug('Caught exception')
                if ebs_vol:
                    self._logger.debug('Detaching EBS')
                    if ebs_vol.update(
                    ) and ebs_vol.attachment_state() != 'available':
                        ebstool.detach_volume(conn,
                                              ebs_vol,
                                              force=True,
                                              logger=self._logger)

                raise StorageError, 'EBS volume construction failed: %s' % str(
                    sys.exc_value), sys.exc_traceback

            finally:
                if delete_snap and snap_id:
                    conn.delete_snapshot(snap_id)
                if device and device[-1] in self.acquired_letters:
                    self.acquired_letters.remove(device[-1])

            kwargs['device'] = device
            kwargs['id'] = ebs_vol.id

        elif kwargs.get('device'):
            kwargs['device'] = ebstool.get_system_devname(kwargs['device'])

        return super(EbsVolumeProvider, self).create(**kwargs)
Beispiel #4
0
 def __init__(self):
     if not Lvm2.usable():
         raise StorageError(
             'LVM2 is not usable. Please check that kernel compiled with dm_mod, dm_snapshot'
         )
Beispiel #5
0
    def _create(self, **kwargs):
        '''
        @param id: volume id
        @param device: Device name
        @param size: Size in GB
        @param zone_id: Availability zone
        @param disk_offering_id: Disk offering ID
        @param snapshot_id: Snapshot id
        '''
        native_vol = None
        pl = bus.platform
        conn = self._new_conn()

        if conn:
            LOG.debug('storage._create kwds: %s', kwargs)

            # Find free devname
            device = kwargs.get('device')
            if device and not os.path.exists(device):
                device_id = voltool.get_deviceid(device)
            else:
                device_id = voltool.get_free_deviceid(conn, pl.get_instance_id())

            # Take volume and snapshot ids
            volume_id = kwargs.get('id')
            snap_id = kwargs.get('snapshot_id')
            if snap_id:
                volume_id = None
            attached = False

            try:
                if volume_id:
                    LOG.debug('Volume %s has been already created', volume_id)
                    try:
                        native_vol = conn.listVolumes(id=volume_id)[0]
                    except IndexError:
                        raise StorageError("Volume %s doesn't exist" % volume_id)
                    else:
                        snap_id = None

                if snap_id or not volume_id:
                    LOG.debug('Creating new volume')
                    disk_offering_id = kwargs.get('disk_offering_id')
                    if not disk_offering_id:
                        # Any size you want
                        disk_offering_id = [dskoffer for dskoffer in conn.listDiskOfferings()
                                        if not dskoffer.disksize and dskoffer.iscustomized][0].id


                    native_vol = voltool.create_volume(conn,
                            name='%s-%02d' % (pl.get_instance_id(), device_id),
                            zone_id=pl.get_avail_zone_id(),
                            size=kwargs.get('size'),
                            disk_offering_id=disk_offering_id,
                            snap_id=snap_id,
                            logger=LOG
                    )


                if voltool.volume_attached(native_vol):
                    if native_vol.virtualmachineid == pl.get_instance_id():
                        LOG.debug('Volume %s is attached to this instance', volume_id)
                        device = voltool.get_system_devname(native_vol.deviceid)
                        attached = True
                    else:
                        LOG.warning('Volume %s is not available. '
                                                                'It is attached to different instance %s. '
                                                                'Now scalarizr will detach it',
                                                                volume_id, native_vol.virtualmachineid)
                        if native_vol.vmstate == 'Stopping':
                            # We should wait for state chage
                            def vm_state_changed():
                                native_vol = conn.listVolumes(id=volume_id or native_vol.id)[0]
                                return voltool.volume_detached(native_vol) or \
                                                native_vol.vmstate != 'Stopping'
                            wait_until(vm_state_changed)

                        if voltool.volume_attached(native_vol):
                            # If stil attached, detaching
                            voltool.detach_volume(conn, volume_id)
                            LOG.debug('Volume %s detached', volume_id)

                if not attached:
                    LOG.debug('Attaching volume %s to this instance', volume_id)
                    device = voltool.attach_volume(conn, native_vol, pl.get_instance_id(), device_id,
                            to_me=True, logger=LOG)[1]

            except:
                exc_type, exc_value, exc_trace = sys.exc_info()
                if native_vol:
                    LOG.debug('Detaching volume')
                    try:
                        conn.detachVolume(id=native_vol.id)
                    except:
                        pass

                raise StorageError, 'Volume construction failed: %s' % exc_value, exc_trace



            kwargs['device'] = device
            kwargs['id'] = native_vol.id
            kwargs['zone_id'] = native_vol.zoneid
            kwargs['disk_offering_id'] = getattr(native_vol, 'diskofferingid', None)

        return super(CSVolumeProvider, self).create(**kwargs)