def wait_replica_ready(self, replica_id, interval=None, timeout=None): LOG.debug('Wait synchronize complete.') running_status_normal = (constants.REPLICA_RUNNING_STATUS_NORMAL, constants.REPLICA_RUNNING_STATUS_SYNCED) running_status_sync = (constants.REPLICA_RUNNING_STATUS_SYNC, constants.REPLICA_RUNNING_STATUS_INITIAL_SYNC) health_status_normal = constants.REPLICA_HEALTH_STATUS_NORMAL def _replica_ready(): info = self.op.get_replica_info(replica_id) if (self.op.is_running_status(running_status_normal, info) and self.op.is_health_status(health_status_normal, info)): return True if not self.op.is_running_status(running_status_sync, info): msg = (_('Wait synchronize failed. Running status: %s.') % info.get(constants.REPLICA_RUNNING_STATUS_KEY)) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) return False if not interval: interval = constants.DEFAULT_WAIT_INTERVAL if not timeout: timeout = constants.DEFAULT_WAIT_TIMEOUT huawei_utils.wait_for_condition(_replica_ready, interval, timeout)
def _ensure_hypermetro_removed_from_cg(self, metro_id, metrogroup_id): def _check_removed(): return not self._check_metro_in_cg(metro_id, metrogroup_id) huawei_utils.wait_for_condition(_check_removed, constants.DEFAULT_WAIT_INTERVAL, constants.DEFAULT_WAIT_INTERVAL * 10)
def _ensure_hypermetro_not_in_group(self, metrogroup_id, metro_ids): for metro_id in metro_ids: huawei_utils.wait_for_condition( lambda: not self._check_metro_in_group( metrogroup_id, metro_id), constants.DEFAULT_WAIT_INTERVAL, constants.DEFAULT_WAIT_INTERVAL * 10) self.local_cli.sync_hypermetro(metro_id)
def wait_replicg_ready(self, replicg_id, interval=None, timeout=None): LOG.info(_LI('Wait synchronize complete.')) running_status_normal = (constants.REPLICG_STATUS_NORMAL, ) running_status_sync = (constants.REPLICG_STATUS_SYNCING, ) def _replicg_ready(): info = self.rmt_cgop.get_replicg_info(replicg_id) if (info.get('RUNNINGSTATUS') in running_status_normal and info.get('HEALTHSTATUS') == constants.REPLICG_HEALTH_NORMAL): return True if info.get('RUNNINGSTATUS') not in running_status_sync: msg = (_('Wait synchronize failed. Running status: %s.') % info.get('RUNNINGSTATUS')) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) return False if not interval: interval = constants.DEFAULT_WAIT_INTERVAL if not timeout: timeout = constants.DEFAULT_WAIT_TIMEOUT huawei_utils.wait_for_condition(_replicg_ready, interval, timeout)
def wait_second_access(self, replica_id, access_level): def _check_access(): info = self.op.get_replica_info(replica_id) if info.get('SECRESACCESS') == access_level: return True return False interval = constants.DEFAULT_REPLICA_WAIT_INTERVAL timeout = constants.DEFAULT_REPLICA_WAIT_TIMEOUT huawei_utils.wait_for_condition(_check_access, interval, timeout)
def wait_split_ready(self, replicg_id): def _check_state(): info = self.rmt_cgop.get_replicg_info(replicg_id) if info.get('RUNNINGSTATUS') == constants.REPLICG_STATUS_SPLITED: return True return False interval = constants.DEFAULT_REPLICA_WAIT_INTERVAL timeout = constants.DEFAULT_REPLICA_WAIT_TIMEOUT huawei_utils.wait_for_condition(_check_state, interval, timeout)
def create_volume_from_snapshot(self, volume, snapshot): """Create a volume from a snapshot. We use LUNcopy to copy a new volume from snapshot. The time needed increases as volume size does. """ snapshotname = huawei_utils.encode_name(snapshot['id']) snapshot_id = snapshot.get('provider_location', None) if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is None: err_msg = (_( 'create_volume_from_snapshot: Snapshot %(name)s ' 'does not exist.') % {'name': snapshotname}) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) lun_info = self.create_volume(volume) tgt_lun_id = lun_info['ID'] luncopy_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'create_volume_from_snapshot: src_lun_id: %(src_lun_id)s, ' 'tgt_lun_id: %(tgt_lun_id)s, copy_name: %(copy_name)s.'), {'src_lun_id': snapshot_id, 'tgt_lun_id': tgt_lun_id, 'copy_name': luncopy_name}) event_type = 'LUNReadyWaitInterval' wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) def _volume_ready(): result = self.restclient.get_lun_info(tgt_lun_id) if (result['HEALTHSTATUS'] == constants.STATUS_HEALTH and result['RUNNINGSTATUS'] == constants.STATUS_VOLUME_READY): return True return False huawei_utils.wait_for_condition(self.xml_file_path, _volume_ready, wait_interval, wait_interval * 10) self._copy_volume(volume, luncopy_name, snapshot_id, tgt_lun_id) return {'ID': lun_info['ID'], 'lun_info': lun_info}
def _sync_metro(self, metro_id): def _is_sync_complete(): return self._is_sync_complete(metro_id) try: self.client.sync_hypermetro(metro_id) huawei_utils.wait_for_condition( _is_sync_complete, constants.HYPERMETRO_WAIT_INTERVAL, constants.DEFAULT_WAIT_TIMEOUT) except Exception as err: raise exception.VolumeBackendAPIException(data=err)
def _wait_volume_ready(self, lun_id): wait_interval = self.configuration.lun_ready_wait_interval def _volume_ready(): result = self.rmt_client.get_lun_info(lun_id) if (result['HEALTHSTATUS'] == constants.STATUS_HEALTH and result['RUNNINGSTATUS'] == constants.STATUS_VOLUME_READY): return True return False huawei_utils.wait_for_condition(_volume_ready, wait_interval, wait_interval * 10)
def _wait_volume_ready(self, lun_id): event_type = "LUNReadyWaitInterval" wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) def _volume_ready(): result = self.rmt_client.get_lun_info(lun_id) if ( result["HEALTHSTATUS"] == constants.STATUS_HEALTH and result["RUNNINGSTATUS"] == constants.STATUS_VOLUME_READY ): return True return False huawei_utils.wait_for_condition(self.xml_file_path, _volume_ready, wait_interval, wait_interval * 10)
def create_volume_from_snapshot(self, volume, snapshot): """Create a volume from a snapshot. We use LUNcopy to copy a new volume from snapshot. The time needed increases as volume size does. """ snapshotname = huawei_utils.encode_name(snapshot["id"]) snapshot_id = snapshot.get("provider_location", None) if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is None: err_msg = _("create_volume_from_snapshot: Snapshot %(name)s " "does not exist.") % { "name": snapshotname } LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) lun_info = self.create_volume(volume) tgt_lun_id = lun_info["ID"] luncopy_name = huawei_utils.encode_name(volume["id"]) LOG.info( _LI( "create_volume_from_snapshot: src_lun_id: %(src_lun_id)s, " "tgt_lun_id: %(tgt_lun_id)s, copy_name: %(copy_name)s." ), {"src_lun_id": snapshot_id, "tgt_lun_id": tgt_lun_id, "copy_name": luncopy_name}, ) event_type = "LUNReadyWaitInterval" wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) def _volume_ready(): result = self.restclient.get_lun_info(tgt_lun_id) if ( result["HEALTHSTATUS"] == constants.STATUS_HEALTH and result["RUNNINGSTATUS"] == constants.STATUS_VOLUME_READY ): return True return False huawei_utils.wait_for_condition(self.xml_file_path, _volume_ready, wait_interval, wait_interval * 10) self._copy_volume(volume, luncopy_name, snapshot_id, tgt_lun_id) return {"ID": lun_info["ID"], "lun_info": lun_info}
def _wait_volume_ready(self, lun_id): event_type = 'LUNReadyWaitInterval' wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) def _volume_ready(): result = self.restclient.get_lun_info(lun_id) if (result['HEALTHSTATUS'] == constants.STATUS_HEALTH and result['RUNNINGSTATUS'] == constants.STATUS_VOLUME_READY): return True return False huawei_utils.wait_for_condition(self.xml_file_path, _volume_ready, wait_interval, wait_interval * 10)
def switch(self, replica_id): self.split(replica_id) self.unprotect_second(replica_id) self.op.switch(replica_id) # Wait to be primary def _wait_switch_to_primary(): info = self.op.get_replica_info(replica_id) if self.op.is_primary(info): return True return False interval = constants.DEFAULT_REPLICA_WAIT_INTERVAL timeout = constants.DEFAULT_REPLICA_WAIT_TIMEOUT huawei_utils.wait_for_condition(_wait_switch_to_primary, interval, timeout)
def _wait_until_role(self, rep_id, is_primary): def _role_check(): info = self.get_info(rep_id) if info['HEALTHSTATUS'] != constants.REPLICA_HEALTH_STATUS_NORMAL: msg = _('Replication status %s is abnormal.' ) % info['HEALTHSTATUS'] LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) if info['ISPRIMARY'] == is_primary: return True return False huawei_utils.wait_for_condition(_role_check, constants.DEFAULT_WAIT_INTERVAL, constants.DEFAULT_WAIT_TIMEOUT)
def wait_expect_state(self, replica_id, running_status, health_status=None, interval=None, timeout=None): def _check_state(): info = self.op.get_replica_info(replica_id) if self.op.is_running_status(running_status, info): if (not health_status or self.op.is_health_status(health_status, info)): return True return False if not interval: interval = constants.DEFAULT_REPLICA_WAIT_INTERVAL if not timeout: timeout = constants.DEFAULT_REPLICA_WAIT_TIMEOUT huawei_utils.wait_for_condition(_check_state, interval, timeout)
def _wait_until_status(self, rep_id, expect_statuses): def _status_check(): info = self.get_info(rep_id) if info['HEALTHSTATUS'] != constants.REPLICA_HEALTH_STATUS_NORMAL: msg = _('Replication status %s is abnormal.' ) % info['HEALTHSTATUS'] LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) if info['RUNNINGSTATUS'] in expect_statuses: return True return False huawei_utils.wait_for_condition(_status_check, constants.DEFAULT_WAIT_INTERVAL, constants.DEFAULT_WAIT_TIMEOUT)
def _copy_volume(self, volume, copy_name, src_lun, tgt_lun): luncopy_id = self.restclient.create_luncopy(copy_name, src_lun, tgt_lun) event_type = "LUNcopyWaitInterval" wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) try: self.restclient.start_luncopy(luncopy_id) def _luncopy_complete(): luncopy_info = self.restclient.get_luncopy_info(luncopy_id) if luncopy_info["status"] == constants.STATUS_LUNCOPY_READY: # luncopy_info['status'] means for the running status of # the luncopy. If luncopy_info['status'] is equal to '40', # this luncopy is completely ready. return True elif luncopy_info["state"] != constants.STATUS_HEALTH: # luncopy_info['state'] means for the healthy status of the # luncopy. If luncopy_info['state'] is not equal to '1', # this means that an error occurred during the LUNcopy # operation and we should abort it. err_msg = ( _( "An error occurred during the LUNcopy operation. " "LUNcopy name: %(luncopyname)s. " "LUNcopy status: %(luncopystatus)s. " "LUNcopy state: %(luncopystate)s." ) % { "luncopyname": luncopy_id, "luncopystatus": luncopy_info["status"], "luncopystate": luncopy_info["state"], }, ) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) huawei_utils.wait_for_condition(self.xml_file_path, _luncopy_complete, wait_interval) except Exception: with excutils.save_and_reraise_exception(): self.restclient.delete_luncopy(luncopy_id) self.delete_volume(volume) self.restclient.delete_luncopy(luncopy_id)
def _copy_volume(self, volume, copy_name, src_lun, tgt_lun): luncopy_id = self.restclient.create_luncopy(copy_name, src_lun, tgt_lun) event_type = 'LUNcopyWaitInterval' wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) try: self.restclient.start_luncopy(luncopy_id) def _luncopy_complete(): luncopy_info = self.restclient.get_luncopy_info(luncopy_id) if luncopy_info['status'] == constants.STATUS_LUNCOPY_READY: # luncopy_info['status'] means for the running status of # the luncopy. If luncopy_info['status'] is equal to '40', # this luncopy is completely ready. return True elif luncopy_info['state'] != constants.STATUS_HEALTH: # luncopy_info['state'] means for the healthy status of the # luncopy. If luncopy_info['state'] is not equal to '1', # this means that an error occurred during the LUNcopy # operation and we should abort it. err_msg = ( _('An error occurred during the LUNcopy operation. ' 'LUNcopy name: %(luncopyname)s. ' 'LUNcopy status: %(luncopystatus)s. ' 'LUNcopy state: %(luncopystate)s.') % { 'luncopyname': luncopy_id, 'luncopystatus': luncopy_info['status'], 'luncopystate': luncopy_info['state'] }, ) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) huawei_utils.wait_for_condition(self.xml_file_path, _luncopy_complete, wait_interval) except Exception: with excutils.save_and_reraise_exception(): self.restclient.delete_luncopy(luncopy_id) self.delete_volume(volume) self.restclient.delete_luncopy(luncopy_id)
def _migrate_lun(self, src_id, dst_id): try: self.restclient.create_lun_migration(src_id, dst_id) def _is_lun_migration_complete(): return self._is_lun_migration_complete(src_id, dst_id) wait_interval = constants.MIGRATION_WAIT_INTERVAL huawei_utils.wait_for_condition(self.xml_file_path, _is_lun_migration_complete, wait_interval) # Clean up if migration failed. except Exception as ex: raise exception.VolumeBackendAPIException(data=ex) finally: if self._is_lun_migration_exist(src_id, dst_id): self.restclient.delete_lun_migration(src_id, dst_id) self._delete_lun_with_check(dst_id) LOG.debug("Migrate lun %s successfully.", src_id) return True
def wait_volume_online(self, client, lun_info, interval=None, timeout=None): online_status = constants.STATUS_VOLUME_READY if lun_info.get('RUNNINGSTATUS') == online_status: return lun_id = lun_info['ID'] def _wait_online(): info = client.get_lun_info(lun_id) return info.get('RUNNINGSTATUS') == online_status if not interval: interval = constants.DEFAULT_REPLICA_WAIT_INTERVAL if not timeout: timeout = constants.DEFAULT_REPLICA_WAIT_TIMEOUT huawei_utils.wait_for_condition(_wait_online, interval, timeout)
def execute(self, domain_id, local_lun_id, remote_lun_id): hypermetro_param = {"DOMAINID": domain_id, "HCRESOURCETYPE": '1', "ISFIRSTSYNC": False, "LOCALOBJID": local_lun_id, "REMOTEOBJID": remote_lun_id, "SPEED": self.hypermetro_configs['sync_speed']} if self.sync: hypermetro_param.update({"ISFIRSTSYNC": True}) hypermetro_pair = self.client.create_hypermetro( hypermetro_param) if self.sync: self.client.sync_hypermetro(hypermetro_pair['ID']) if strutils.bool_from_string( self.hypermetro_configs['metro_sync_completed']): huawei_utils.wait_for_condition( lambda: self._is_sync_completed(hypermetro_pair['ID']), constants.DEFAULT_WAIT_INTERVAL, constants.DEFAULT_WAIT_TIMEOUT) return {'hypermetro_id': hypermetro_pair['ID']}