def check_param(self): """Check parameter values and consistency among them.""" utils.check_opt_value(self.conf, _INHERITED_VOLUME_OPTS) utils.check_opts(self.conf, common_opts) utils.check_opts(self.conf, self.driver_info['volume_opts']) if (self.conf.vsp_default_copy_method == 'THIN' and not self.conf.vsp_thin_pool): msg = utils.output_log(MSG.INVALID_PARAMETER, param='vsp_thin_pool') raise exception.VSPError(msg) if self.conf.vsp_ldev_range: self.storage_info['ldev_range'] = self._range2list( 'vsp_ldev_range') if (not self.conf.vsp_target_ports and not self.conf.vsp_compute_target_ports): msg = utils.output_log(MSG.INVALID_PARAMETER, param='vsp_target_ports or ' 'vsp_compute_target_ports') raise exception.VSPError(msg) for opt in _REQUIRED_COMMON_OPTS: if not self.conf.safe_get(opt): msg = utils.output_log(MSG.INVALID_PARAMETER, param=opt) raise exception.VSPError(msg) if self.storage_info['protocol'] == 'iSCSI': self.check_param_iscsi()
def create_cloned_volume(self, volume, src_vref): """Create a clone of the specified volume and return its properties.""" ldev = utils.get_ldev(src_vref) # When 'ldev' is 0, it should be true. # Therefore, it cannot remove 'is not None'. if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume', id=src_vref['id']) raise exception.VSPError(msg) size = volume['size'] metadata = utils.get_volume_metadata(volume) if size < src_vref['size']: msg = utils.output_log(MSG.INVALID_VOLUME_SIZE_FOR_COPY, type='volume', volume_id=volume['id']) raise exception.VSPError(msg) elif (size > src_vref['size'] and not self.check_vvol(ldev) and self.get_copy_method(metadata) == "THIN"): msg = utils.output_log(MSG.INVALID_VOLUME_SIZE_FOR_TI, copy_method=utils.THIN, type='volume', volume_id=volume['id']) raise exception.VSPError(msg) sync = size > src_vref['size'] new_ldev = self._copy_ldev(ldev, src_vref['size'], metadata, sync) if sync: self.delete_pair(new_ldev) self.extend_ldev(new_ldev, src_vref['size'], size) return { 'provider_location': six.text_type(new_ldev), }
def check_param_iscsi(self): """Check iSCSI-related parameter values and consistency among them.""" if self.conf.vsp_use_chap_auth: if not self.conf.vsp_auth_user: msg = utils.output_log(MSG.INVALID_PARAMETER, param='vsp_auth_user') raise exception.VSPError(msg) if not self.conf.vsp_auth_password: msg = utils.output_log(MSG.INVALID_PARAMETER, param='vsp_auth_password') raise exception.VSPError(msg)
def get_copy_method(self, metadata): """Return copy method(FULL or THIN).""" method = metadata.get('copy_method', self.conf.vsp_default_copy_method) if method not in _COPY_METHOD: msg = utils.output_log(MSG.INVALID_PARAMETER_VALUE, meta='copy_method') raise exception.VSPError(msg) if method == 'THIN' and not self.conf.vsp_thin_pool: msg = utils.output_log(MSG.INVALID_PARAMETER, param='vsp_thin_pool') raise exception.VSPError(msg) return method
def extend_volume(self, volume, new_size): """Extend the specified volume to the specified size.""" ldev = utils.get_ldev(volume) # When 'ldev' is 0, it should be true. # Therefore, it cannot remove 'is None'. if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_EXTENSION, volume_id=volume['id']) raise exception.VSPError(msg) if self.check_vvol(ldev): msg = utils.output_log(MSG.INVALID_VOLUME_TYPE_FOR_EXTEND, volume_id=volume['id']) raise exception.VSPError(msg) self.delete_pair(ldev) self.extend_ldev(ldev, volume['size'], new_size)
def get_properties_iscsi(self, targets, multipath): """Check if specified iSCSI targets exist and store their IQNs.""" if not multipath: target_list = targets['list'][:1] else: target_list = targets['list'][:] for target in target_list: if target not in targets['iqns']: port, gid = target result = self.run_raidcom('get', 'host_grp', '-port', port) match = re.search( r"^CL\w-\w+ +%s +\S+ +(?P<iqn>\S+) +\w+ +\w +\d+ " % gid, result[1], re.M) if not match: msg = utils.output_log(MSG.RESOURCE_NOT_FOUND, resource='Target IQN') raise exception.VSPError(msg) targets['iqns'][target] = match.group('iqn') LOG.debug( 'Found iqn of the iSCSI target. (port: %(port)s, ' 'gid: %(gid)s, target iqn: %(iqn)s)', { 'port': port, 'gid': gid, 'iqn': match.group('iqn') }) return super(VSPHORCMISCSI, self).get_properties_iscsi(targets, multipath)
def initialize_connection(self, volume, connector): """Initialize connection between the server and the volume.""" targets = { 'info': {}, 'list': [], 'lun': {}, 'iqns': {}, } ldev = utils.get_ldev(volume) # When 'ldev' is 0, it should be true. # Therefore, it cannot remove 'is None'. if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_CONNECTION, volume_id=volume['id']) raise exception.VSPError(msg) if (self.find_targets_from_storage(targets, connector, self.storage_info['ports']) and self.conf.vsp_group_request): self.create_mapping_targets(targets, connector) utils.require_target_existed(targets) targets['list'].sort() for port in self.storage_info['ports']: targets['lun'][port] = False target_lun = int(self.map_ldev(targets, ldev)) return { 'driver_volume_type': self.driver_info['volume_type'], 'data': self.get_properties(targets, connector, target_lun), }
def get_hba_ids_from_connector(self, connector): """Return the HBA ID stored in the connector.""" if self.driver_info['hba_id'] in connector: return connector[self.driver_info['hba_id']] msg = utils.output_log(MSG.RESOURCE_NOT_FOUND, resource=self.driver_info['hba_id_type']) raise exception.VSPError(msg)
def connect_storage(self): """Prepare for using the storage.""" target_ports = self.conf.vsp_target_ports compute_target_ports = self.conf.vsp_compute_target_ports pair_target_ports = self.conf.vsp_horcm_pair_target_ports super(VSPHORCMISCSI, self).connect_storage() result = self.run_raidcom('get', 'port') for port in _ISCSI_PORT_PATTERN.findall(result[1]): if (target_ports and port in target_ports and self._set_target_portal(port)): self.storage_info['controller_ports'].append(port) if (compute_target_ports and port in compute_target_ports and (port in self.storage_info['portals'] or self._set_target_portal(port))): self.storage_info['compute_ports'].append(port) if pair_target_ports and port in pair_target_ports: self.storage_info['pair_ports'].append(port) self.check_ports_info() if pair_target_ports and not self.storage_info['pair_ports']: msg = utils.output_log(MSG.RESOURCE_NOT_FOUND, resource="Pair target ports") raise exception.VSPError(msg) utils.output_log(MSG.SET_CONFIG_VALUE, object='pair target port list', value=self.storage_info['pair_ports']) utils.output_log(MSG.SET_CONFIG_VALUE, object='port-<IP address:port> list', value=self.storage_info['portals'])
def check_ports_info(self): """Check if available storage ports exist.""" if (self.conf.vsp_target_ports and not self.storage_info['controller_ports']): msg = utils.output_log(MSG.RESOURCE_NOT_FOUND, resource="Target ports") raise exception.VSPError(msg) if (self.conf.vsp_compute_target_ports and not self.storage_info['compute_ports']): msg = utils.output_log(MSG.RESOURCE_NOT_FOUND, resource="Compute target ports") raise exception.VSPError(msg) utils.output_log(MSG.SET_CONFIG_VALUE, object='target port list', value=self.storage_info['controller_ports']) utils.output_log(MSG.SET_CONFIG_VALUE, object='compute target port list', value=self.storage_info['compute_ports'])
def _range2list(self, param): """Analyze a 'xxx-xxx' string and return a list of two integers.""" values = [ _str2int(value) for value in self.conf.safe_get(param).split('-') ] if (len(values) != 2 or values[0] is None or values[1] is None or values[0] > values[1]): msg = utils.output_log(MSG.INVALID_PARAMETER, param=param) raise exception.VSPError(msg) return values
def connect_storage(self): """Prepare for using the storage.""" self.storage_info['pool_id'] = self.get_pool_id() # When 'pool_id' is 0, it should be true. # Therefore, it cannot remove 'is None'. if self.storage_info['pool_id'] is None: msg = utils.output_log(MSG.POOL_NOT_FOUND, pool=self.conf.vsp_pool) raise exception.VSPError(msg) utils.output_log(MSG.SET_CONFIG_VALUE, object='DP Pool ID', value=self.storage_info['pool_id'])
def run_and_verify_storage_cli(self, *cmd, **kwargs): """Run storage CLI and return the result or raise an exception.""" do_raise = kwargs.pop('do_raise', True) ignore_error = kwargs.get('ignore_error') success_code = kwargs.get('success_code', set([0])) (ret, stdout, stderr) = self.run_storage_cli(*cmd, **kwargs) if (ret not in success_code and not utils.check_ignore_error(ignore_error, stderr)): msg = utils.output_log( MSG.STORAGE_COMMAND_FAILED, cmd=utils.mask_password(cmd), ret=ret, out=' '.join(stdout.splitlines()), err=' '.join(stderr.splitlines())) if do_raise: raise exception.VSPError(msg) return ret, stdout, stderr
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) # When 'ldev' is 0, it should be true. # Therefore, it cannot remove 'is None'. if ldev is None: msg = utils.output_log(MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume', id=src_vref['id']) raise exception.VSPError(msg) size = snapshot['volume_size'] metadata = utils.get_volume_metadata(src_vref) new_ldev = self._copy_ldev(ldev, size, metadata) return { 'provider_location': six.text_type(new_ldev), }
def set_hba_ids(self, port, gid, hba_ids): """Connect all specified HBAs with the specified port.""" registered_wwns = [] for wwn in hba_ids: try: self.run_raidcom('add', 'hba_wwn', '-port', '-'.join([port, gid]), '-hba_wwn', wwn) registered_wwns.append(wwn) except exception.VSPError: utils.output_log(MSG.ADD_HBA_WWN_FAILED, port=port, gid=gid, wwn=wwn) if not registered_wwns: msg = utils.output_log(MSG.NO_HBA_WWN_ADDED_TO_HOST_GRP, port=port, gid=gid) raise exception.VSPError(msg)
def require_target_existed(targets): """Check if the target list includes one or more members.""" if not targets['list']: msg = output_log(MSG.NO_CONNECTED_TARGET) raise exception.VSPError(msg)