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]
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
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)
def __init__(self): if not Lvm2.usable(): raise StorageError( 'LVM2 is not usable. Please check that kernel compiled with dm_mod, dm_snapshot' )
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)