def revert_to_snapshot(self, volume, snapshot): """Rollback the specified snapshot.""" pvol = utils.get_ldev(volume) svol = utils.get_ldev(snapshot) if (pvol is not None and svol is not None and self.has_snap_pair(pvol, svol)): self.restore_ldev(pvol, svol) else: raise NotImplementedError()
def terminate_connection(self, volume, connector): """Terminate connection between the server and the volume.""" ldev = utils.get_ldev(volume) if ldev is None: utils.output_log(MSG.INVALID_LDEV_FOR_UNMAPPING, volume_id=volume['id']) return # If a fake connector is generated by nova when the host # is down, then the connector will not have a host property, # In this case construct the lock without the host property # so that all the fake connectors to an SVC are serialized if 'host' not in connector: port_hostgroup_map = self.get_port_hostgroup_map(ldev) if not port_hostgroup_map: utils.output_log(MSG.NO_LUN, ldev=ldev) return self.set_terminate_target(connector, port_hostgroup_map) # A synchronization to prevent conflicts between host group creation # and deletion. @coordination.synchronized( 'hbsd-host-%(storage_id)s-%(host)s' % { 'storage_id': self.conf.hitachi_storage_id, 'host': connector.get('host'), } ) def inner(self, volume, connector): deleted_targets = self.detach_ldev(volume, ldev, connector) if self.storage_info['protocol'] == 'FC': target_wwn = [ self.storage_info['wwns'][target] for target in deleted_targets] return {'driver_volume_type': self.driver_info['volume_type'], 'data': {'target_wwn': target_wwn}} return inner(self, volume, connector)
def discard_zero_page(self, volume): """Return the volume's no-data pages to the storage pool.""" if self.conf.hitachi_discard_zero_page: ldev = utils.get_ldev(volume) try: self.client.discard_zero_page(ldev) except utils.HBSDError: utils.output_log(MSG.DISCARD_ZERO_PAGE_FAILED, ldev=ldev)
def create_group_from_src(self, context, group, volumes, snapshots=None, source_vols=None): volumes_model_update = [] new_ldevs = [] events = [] def _create_group_volume_from_src(context, volume, src, from_snapshot): volume_model_update = {'id': volume.id} try: ldev = utils.get_ldev(src) if ldev is None: msg = utils.output_log( MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='snapshot' if from_snapshot else 'volume', id=src.id) self.raise_error(msg) volume_model_update.update( self.create_volume_from_snapshot(volume, src) if from_snapshot else self.create_cloned_volume(volume, src)) except Exception as exc: volume_model_update['msg'] = utils.get_exception_msg(exc) raise loopingcall.LoopingCallDone(volume_model_update) try: from_snapshot = True if snapshots else False for volume, src in zip(volumes, snapshots if snapshots else source_vols): loop = loopingcall.FixedIntervalLoopingCall( _create_group_volume_from_src, context, volume, src, from_snapshot) event = loop.start(interval=0) events.append(event) is_success = True for e in events: volume_model_update = e.wait() if 'msg' in volume_model_update: is_success = False msg = volume_model_update['msg'] else: volumes_model_update.append(volume_model_update) ldev = utils.get_ldev(volume_model_update) if ldev is not None: new_ldevs.append(ldev) if not is_success: self.raise_error(msg) except Exception: with excutils.save_and_reraise_exception(): for new_ldev in new_ldevs: try: self.delete_ldev(new_ldev) except exception.VolumeDriverException: utils.output_log(MSG.DELETE_LDEV_FAILED, ldev=new_ldev) return None, volumes_model_update
def update_group(self, group, add_volumes=None): if add_volumes and volume_utils.is_group_a_cg_snapshot_type(group): for volume in add_volumes: ldev = utils.get_ldev(volume) if ldev is None: msg = utils.output_log(MSG.LDEV_NOT_EXIST_FOR_ADD_GROUP, volume_id=volume.id, group='consistency group', group_id=group.id) self.raise_error(msg) return None, None, None
def delete_snapshot(self, snapshot): """Delete the specified snapshot.""" ldev = utils.get_ldev(snapshot) if ldev is None: utils.output_log(MSG.INVALID_LDEV_FOR_DELETION, method='delete_snapshot', id=snapshot['id']) return try: self.delete_ldev(ldev) except utils.HBSDBusy: raise exception.SnapshotIsBusy(snapshot_name=snapshot['name'])
def delete_volume(self, volume): """Delete the specified volume.""" ldev = utils.get_ldev(volume) if ldev is None: utils.output_log(MSG.INVALID_LDEV_FOR_DELETION, method='delete_volume', id=volume['id']) return try: self.delete_ldev(ldev) except utils.HBSDBusy: raise exception.VolumeIsBusy(volume_name=volume['name'])
def extend_volume(self, volume, new_size): """Extend the specified volume to the specified size.""" ldev = utils.get_ldev(volume) if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_EXTENSION, volume_id=volume['id']) raise utils.HBSDError(msg) if self.check_pair_svol(ldev): msg = utils.output_log(MSG.INVALID_VOLUME_TYPE_FOR_EXTEND, volume_id=volume['id']) raise utils.HBSDError(msg) self.delete_pair(ldev) self.extend_ldev(ldev, volume['size'], new_size)
def create_snapshot(self, snapshot): """Create a snapshot from a volume and return its properties.""" src_vref = snapshot.volume ldev = utils.get_ldev(src_vref) if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume', id=src_vref['id']) raise utils.HBSDError(msg) size = snapshot['volume_size'] new_ldev = self._copy_on_storage(ldev, size, True) return { 'provider_location': str(new_ldev), }
def _create_cgsnapshot_volume(snapshot): pair = {'snapshot': snapshot} try: pair['pvol'] = utils.get_ldev(snapshot.volume) if pair['pvol'] is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume', id=snapshot.volume_id) self.raise_error(msg) size = snapshot.volume_size pair['svol'] = self.create_ldev(size) except Exception as exc: pair['msg'] = utils.get_exception_msg(exc) raise loopingcall.LoopingCallDone(pair)
def delete_snapshot(self, snapshot): """Delete the specified snapshot.""" ldev = utils.get_ldev(snapshot) if ldev is None: utils.output_log(MSG.INVALID_LDEV_FOR_DELETION, method='delete_snapshot', id=snapshot['id']) return try: self.delete_ldev(ldev) except exception.VolumeDriverException as ex: if ex.msg == utils.BUSY_MESSAGE: raise exception.SnapshotIsBusy(snapshot_name=snapshot['name']) else: raise ex
def delete_volume(self, volume): """Delete the specified volume.""" ldev = utils.get_ldev(volume) if ldev is None: utils.output_log(MSG.INVALID_LDEV_FOR_DELETION, method='delete_volume', id=volume['id']) return try: self.delete_ldev(ldev) except exception.VolumeDriverException as ex: if ex.msg == utils.BUSY_MESSAGE: raise exception.VolumeIsBusy(volume_name=volume['name']) else: raise ex
def _create_group_volume_from_src(context, volume, src, from_snapshot): volume_model_update = {'id': volume.id} try: ldev = utils.get_ldev(src) if ldev is None: msg = utils.output_log( MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='snapshot' if from_snapshot else 'volume', id=src.id) self.raise_error(msg) volume_model_update.update( self.create_volume_from_snapshot(volume, src) if from_snapshot else self.create_cloned_volume(volume, src)) except Exception as exc: volume_model_update['msg'] = utils.get_exception_msg(exc) raise loopingcall.LoopingCallDone(volume_model_update)
def unmanage(self, volume): """Prepare the volume for removing it from Cinder management.""" ldev = utils.get_ldev(volume) if ldev is None: utils.output_log(MSG.INVALID_LDEV_FOR_DELETION, method='unmanage', id=volume['id']) return if self.check_pair_svol(ldev): utils.output_log( MSG.INVALID_LDEV_TYPE_FOR_UNMANAGE, volume_id=volume['id'], volume_type=utils.NORMAL_LDEV_TYPE) raise exception.VolumeIsBusy(volume_name=volume['name']) try: self.delete_pair(ldev) except utils.HBSDBusy: raise exception.VolumeIsBusy(volume_name=volume['name'])
def create_volume_from_src(self, volume, src, src_type): """Create a volume from a volume or snapshot and return its properties. """ ldev = utils.get_ldev(src) if ldev is None: msg = utils.output_log( MSG.INVALID_LDEV_FOR_VOLUME_COPY, type=src_type, id=src['id']) raise utils.HBSDError(msg) size = volume['size'] new_ldev = self._copy_on_storage(ldev, size) self.modify_ldev_name(new_ldev, volume['id'].replace("-", "")) return { 'provider_location': str(new_ldev), }
def _delete_group_obj(group, obj, is_snapshot): obj_update = {'id': obj.id} try: if is_snapshot: self.delete_snapshot(obj) else: self.delete_volume(obj) obj_update['status'] = 'deleted' except (utils.HBSDError, exception.VolumeIsBusy, exception.SnapshotIsBusy) as exc: obj_update['status'] = 'available' if isinstance( exc, (exception.VolumeIsBusy, exception.SnapshotIsBusy)) else 'error' utils.output_log( MSG.GROUP_OBJECT_DELETE_FAILED, obj='snapshot' if is_snapshot else 'volume', group='group snapshot' if is_snapshot else 'group', group_id=group.id, obj_id=obj.id, ldev=utils.get_ldev(obj), reason=exc.msg) raise loopingcall.LoopingCallDone(obj_update)
def initialize_connection(self, volume, connector): """Initialize connection between the server and the volume.""" targets = { 'info': {}, 'list': [], 'lun': {}, 'iqns': {}, 'target_map': {}, } ldev = utils.get_ldev(volume) if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_CONNECTION, volume_id=volume['id']) raise utils.HBSDError(msg) target_lun = self.attach_ldev(volume, ldev, connector, targets) return { 'driver_volume_type': self.driver_info['volume_type'], 'data': self.get_properties(targets, target_lun, connector), }
def _create_cgsnapshot(self, context, cgsnapshot, snapshots): pairs = [] events = [] snapshots_model_update = [] def _create_cgsnapshot_volume(snapshot): pair = {'snapshot': snapshot} try: pair['pvol'] = utils.get_ldev(snapshot.volume) if pair['pvol'] is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume', id=snapshot.volume_id) self.raise_error(msg) size = snapshot.volume_size pair['svol'] = self.create_ldev(size) except Exception as exc: pair['msg'] = utils.get_exception_msg(exc) raise loopingcall.LoopingCallDone(pair) try: for snapshot in snapshots: ldev = utils.get_ldev(snapshot.volume) if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume', id=snapshot.volume_id) self.raise_error(msg) for snapshot in snapshots: loop = loopingcall.FixedIntervalLoopingCall( _create_cgsnapshot_volume, snapshot) event = loop.start(interval=0) events.append(event) is_success = True for e in events: pair = e.wait() if 'msg' in pair: is_success = False msg = pair['msg'] pairs.append(pair) if not is_success: self.raise_error(msg) self._create_ctg_snap_pair(pairs) except Exception: for pair in pairs: if 'svol' in pair and pair['svol'] is not None: try: self.delete_ldev(pair['svol']) except exception.VolumeDriverException: utils.output_log(MSG.DELETE_LDEV_FAILED, ldev=pair['svol']) model_update = {'status': fields.GroupSnapshotStatus.ERROR} for snapshot in snapshots: snapshot_model_update = { 'id': snapshot.id, 'status': fields.SnapshotStatus.ERROR } snapshots_model_update.append(snapshot_model_update) return model_update, snapshots_model_update for pair in pairs: snapshot_model_update = { 'id': pair['snapshot'].id, 'status': fields.SnapshotStatus.AVAILABLE, 'provider_location': str(pair['svol']) } snapshots_model_update.append(snapshot_model_update) return None, snapshots_model_update