def initialize_connection(self, volume, connector): """Attach K2 volume to host.""" # Check wwpns in host connector. if not connector.get('wwpns'): msg = _("No wwpns found in host connector.") LOG.error(msg) raise common.KaminarioCinderDriverException(reason=msg) # To support replication failback temp_client = None if (hasattr(volume, 'replication_status') and volume.replication_status == K2_REP_FAILED_OVER): temp_client = self.client self.client = self.target # Get target wwpns. target_wwpns = self.get_target_info(volume) # Map volume. lun = self.k2_initialize_connection(volume, connector) # Create initiator-target mapping. target_wwpns, init_target_map = self._build_initiator_target_map( connector, target_wwpns) # To support replication failback if temp_client: self.client = temp_client # Return target volume information. conn_info = {'driver_volume_type': 'fibre_channel', 'data': {"target_discovered": True, "target_lun": lun, "target_wwn": target_wwpns, "initiator_target_map": init_target_map}} fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Attach K2 volume to host.""" # Check wwpns in host connector. if not connector.get('wwpns'): msg = _("No wwpns found in host connector.") LOG.error(msg) raise common.KaminarioCinderDriverException(reason=msg) # To support replication failback temp_client = None if (hasattr(volume, 'replication_status') and volume.replication_status == K2_REP_FAILED_OVER): temp_client = self.client self.client = self.target # Get target wwpns. target_wwpns = self.get_target_info(volume) # Map volume. lun = self.k2_initialize_connection(volume, connector) # Create initiator-target mapping. target_wwpns, init_target_map = self._build_initiator_target_map( connector, target_wwpns) # To support replication failback if temp_client: self.client = temp_client # Return target volume information. conn_info = {'driver_volume_type': 'fibre_channel', 'data': {"target_discovered": True, "target_lun": lun, "target_wwn": target_wwpns, "initiator_target_map": init_target_map}} fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): LOG.debug( 'enter: initialize_connection: volume ' '%(vol)s with connector %(conn)s', { 'vol': volume.id, 'conn': connector }) volume_name = self._convert_name(volume.name) ret = self._cmd.create_lun_map(volume_name, self.protocol, connector['wwpns']) if ret['key'] == 0: if 'lun' in ret['arr']: lun_id = int(ret['arr']['lun']) else: msg = (_('_create_fc_lun: Lun id did not find ' 'when volume %s create lun map.') % volume['id']) raise exception.VolumeBackendAPIException(data=msg) target_wwpns = self._get_connected_wwpns() if len(target_wwpns) == 0: if self._check_multi_attached(volume, connector) < 1: self._cmd.delete_lun_map(volume_name, self.protocol, connector['wwpns']) msg = (_('_create_fc_lun: Did not find ' 'available fc wwpns when volume %s ' 'create lun map.') % volume['id']) raise exception.VolumeBackendAPIException(data=msg) initiator_target = {} for initiator_wwpn in connector['wwpns']: initiator_target[str(initiator_wwpn)] = target_wwpns properties = { 'driver_volume_type': 'fibre_channel', 'data': { 'target_wwn': target_wwpns, 'target_discovered': False, 'target_lun': lun_id, 'volume_id': volume['id'] } } properties['data']['initiator_target_map'] = initiator_target elif ret['key'] == 303: raise exception.VolumeNotFound(volume_id=volume_name) else: msg = (_('failed to map the volume %(vol)s to ' 'connector %(conn)s.') % { 'vol': volume['id'], 'conn': connector }) raise exception.VolumeBackendAPIException(data=msg) zone_utils.add_fc_zone(properties) LOG.debug( 'leave: initialize_connection: volume ' '%(vol)s with connector %(conn)s', { 'vol': volume.id, 'conn': connector }) return properties
def initialize_connection_with_empty_map(self, volume, connector): conn_info = { 'driver_volume_type': 'fibre_channel', 'data': { 'initiator_target_map': {}, }} fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): conn_info = { 'driver_volume_type': 'fibre_channel', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} fczm_utils.add_fc_zone(conn_info) return conn_info
def no_zone_initialize_connection(self, volume, connector): """This shouldn't call the ZM.""" conn_info = { 'driver_volume_type': 'bogus', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Perform work so that an FC connection can be made. To be able to create a FC connection from a given host to a volume, we must: 1. Translate the given WWNN to a host name 2. Create new host on the storage system if it does not yet exist 3. Map the volume to the host if it is not already done 4. Return the connection information for relevant nodes (in the proper I/O group) """ LOG.debug( 'enter: initialize_connection: volume %(vol)s with ' 'connector %(conn)s.', {'vol': volume, 'conn': connector}) vdisk_name = volume['name'] vdisk_id = volume['id'] vdisk_params = self._get_vdisk_params(volume['volume_type_id']) # TODO(edwin): might fix it after vdisk copy function is # ready in FlashSystem thin-provision layer. As this validation # is to check the vdisk which is in copying, at present in firmware # level vdisk doesn't allow to map host which it is copy. New # vdisk clone and snapshot function will cover it. After that the # _wait_vdisk_copy_completed need some modification. self._wait_vdisk_copy_completed(vdisk_name) self._driver_assert( self._is_vdisk_defined(vdisk_name), (_('initialize_connection: vdisk %s is not defined.') % vdisk_name)) lun_id = self._map_vdisk_to_host(vdisk_name, connector) properties = {} try: properties = self._get_vdisk_map_properties( connector, lun_id, vdisk_name, vdisk_id, vdisk_params) except exception.VolumeBackendAPIException: with excutils.save_and_reraise_exception(): self.terminate_connection(volume, connector) LOG.error('initialize_connection: Failed to collect ' 'return properties for volume %(vol)s and ' 'connector %(conn)s.', {'vol': volume, 'conn': connector}) LOG.debug( 'leave: initialize_connection:\n volume: %(vol)s\n connector ' '%(conn)s\n properties: %(prop)s.', {'vol': volume, 'conn': connector, 'prop': properties}) fczm_utils.add_fc_zone(properties) return properties
def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. Assign any created volume to a compute node/host so that it can be used from that host. The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. The initiator_target_map is a map that represents the remote wwn(s) and a list of wwns which are visible to the remote wwn(s). Example return values: FC: .. code-block:: json { 'driver_volume_type': 'fibre_channel' 'data': { 'target_discovered': True, 'target_lun': 1, 'target_wwn': ['1234567890123', '0987654321321'], 'initiator_target_map': { '1122334455667788': ['1234567890123', '0987654321321'] } } } iSCSI: .. code-block:: json { 'driver_volume_type': 'iscsi' 'data': { 'target_discovered': True, 'target_iqns': ['iqn.2010-10.org.openstack:volume-00001', 'iqn.2010-10.org.openstack:volume-00002'], 'target_portals': ['127.0.0.1:3260', '127.0.1.1:3260'], 'target_luns': [1, 1], } } """ LOG.debug( "Entering initialize_connection" " - connector: %(connector)s.", {'connector': connector}) conn_info = self.adapter.initialize_connection(volume, connector) LOG.debug( "Exit initialize_connection" " - Returning connection info: %(conn_info)s.", {'conn_info': conn_info}) zm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. Assign any created volume to a compute node/host so that it can be used from that host. The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. The initiator_target_map is a map that represents the remote wwn(s) and a list of wwns which are visible to the remote wwn(s). Example return values: FC: .. code-block:: json { 'driver_volume_type': 'fibre_channel' 'data': { 'target_discovered': True, 'target_lun': 1, 'target_wwn': ['1234567890123', '0987654321321'], 'initiator_target_map': { '1122334455667788': ['1234567890123', '0987654321321'] } } } iSCSI: .. code-block:: json { 'driver_volume_type': 'iscsi' 'data': { 'target_discovered': True, 'target_iqns': ['iqn.2010-10.org.openstack:volume-00001', 'iqn.2010-10.org.openstack:volume-00002'], 'target_portals': ['127.0.0.1:3260', '127.0.1.1:3260'], 'target_luns': [1, 1], } } """ LOG.debug("Entering initialize_connection" " - connector: %(connector)s.", {'connector': connector}) conn_info = self.adapter.initialize_connection(volume, connector) LOG.debug("Exit initialize_connection" " - Returning connection info: %(conn_info)s.", {'conn_info': conn_info}) zm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Initialize connection between the server and the volume.""" conn_info = super(HBSDRESTFC, self).initialize_connection( volume, connector) if self.conf.hitachi_zoning_request: init_targ_map = utils.build_initiator_target_map( connector, conn_info['data']['target_wwn'], self._lookup_service) if init_targ_map: conn_info['data']['initiator_target_map'] = init_targ_map fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection_snapshot(self, snapshot, connector, **kwargs): LOG.info('Initialize FC connection for snapshot %(id)s, ' 'connector info %(conn)s.', {'id': snapshot.id, 'conn': connector}) mapping_info = huawei_flow.initialize_fc_connection( snapshot, constants.SNAPSHOT_TYPE, connector, self.fc_san, self.local_cli, self.configuration) mapping_info.pop('aval_host_lun_ids', None) conn = {'driver_volume_type': 'fibre_channel', 'data': mapping_info} LOG.info('Initialize FC connection successfully: %s.', conn) zm_utils.add_fc_zone(conn) return conn
def initialize_connection(self, volume, connector): LOG.info( 'Initialize FC connection for volume %(id)s, ' 'connector info %(conn)s.', { 'id': volume.id, 'conn': connector }) metadata = huawei_utils.get_volume_private_data(volume) if metadata.get('hypermetro'): if (not connector.get('multipath') and self.configuration.enforce_multipath_for_hypermetro): msg = _("Mapping hypermetro volume must use multipath.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) elif (not connector.get('multipath') and not self.configuration.enforce_multipath_for_hypermetro): LOG.warning("Mapping hypermetro volume not use multipath," " so just mapping the local lun.") if not self.hypermetro_rmt_cli: msg = _("Mapping hypermetro volume requires remote.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) local_mapping = huawei_flow.initialize_fc_connection( volume, constants.LUN_TYPE, connector, self.fc_san, self.local_cli, self.configuration) if metadata.get('hypermetro') and connector.get('multipath'): hypermetro = huawei_utils.get_hypermetro(self.local_cli, volume) if not hypermetro: msg = _("Mapping hypermetro remote volume error.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) remote_mapping = huawei_flow.initialize_remote_fc_connection( hypermetro['ID'], connector, self.fc_san, self.hypermetro_rmt_cli, self.configuration) same_host_lun_id = self._change_same_host_lun_id( local_mapping, remote_mapping) mapping_info = self._merge_fc_mapping(local_mapping, remote_mapping, same_host_lun_id) else: mapping_info = local_mapping mapping_info.pop('aval_host_lun_ids', None) conn = {'driver_volume_type': 'fibre_channel', 'data': mapping_info} LOG.info('Initialize FC connection successfully: %s.', conn) zm_utils.add_fc_zone(conn) return conn
def initialize_connection(self, volume, connector): self.common.client_login() try: data = {} data['target_lun'] = self.common.map_volume( volume, connector, 'wwpns') ports, init_targ_map = self.get_init_targ_map(connector) data['target_discovered'] = True data['target_wwn'] = ports data['initiator_target_map'] = init_targ_map info = {'driver_volume_type': 'fibre_channel', 'data': data} fczm_utils.add_fc_zone(info) return info finally: self.common.client_logout()
def _initialize_connection_common(self, volume, connector, common, host, target_wwns, init_targ_map, numPaths, remote_client=None): # check if a VLUN already exists for this host existing_vlun = common.find_existing_vlun(volume, host, remote_client) vlun = None if existing_vlun is None: # now that we have a host, create the VLUN if self.lookup_service and numPaths == 1: nsp = None active_fc_port_list = ( common.get_active_fc_target_ports(remote_client)) for port in active_fc_port_list: if port['portWWN'].lower() == target_wwns[0].lower(): nsp = port['nsp'] break vlun = common.create_vlun(volume, host, nsp, None, remote_client) else: vlun = common.create_vlun(volume, host, None, None, remote_client) else: vlun = existing_vlun info_backend = { 'driver_volume_type': 'fibre_channel', 'data': { 'target_lun': vlun['lun'], 'target_discovered': True, 'target_wwn': target_wwns, 'initiator_target_map': init_targ_map } } encryption_key_id = volume.get('encryption_key_id') info_backend['data']['encrypted'] = encryption_key_id is not None fczm_utils.add_fc_zone(info_backend) return info_backend
def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. Assign any created volume to a compute node/host so that it can be used from that host. The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. Example return values: .. code-block:: json { 'driver_volume_type': 'fibre_channel' 'data': { 'target_discovered': True, 'target_lun': 1, 'target_wwn': '1234567890123', } } or { 'driver_volume_type': 'fibre_channel' 'data': { 'target_discovered': True, 'target_lun': 1, 'target_wwn': ['1234567890123', '0987654321321'], } } :param volume: the cinder volume object :param connector: the connector object :returns: dict -- the target_wwns and initiator_target_map """ device_info = self.common.initialize_connection( volume, connector) if device_info: conn_info = self.populate_data(device_info, volume, connector) fczm_utils.add_fc_zone(conn_info) return conn_info else: return {}
def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. Assign any created volume to a compute node/host so that it can be used from that host. The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. Example return values: .. code-block:: json { 'driver_volume_type': 'fibre_channel' 'data': { 'target_discovered': True, 'target_lun': 1, 'target_wwn': '1234567890123', } } or { 'driver_volume_type': 'fibre_channel' 'data': { 'target_discovered': True, 'target_lun': 1, 'target_wwn': ['1234567890123', '0987654321321'], } } :param volume: the cinder volume object :param connector: the connector object :returns: dict -- the target_wwns and initiator_target_map """ device_info = self.common.initialize_connection( volume, connector) if device_info: conn_info = self.populate_data(device_info, volume, connector) fczm_utils.add_fc_zone(conn_info) return conn_info else: return {}
def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info.""" LOG.debug('initialize_connection, volume id: %(vid)s, ' 'wwpns: %(wwpns)s, enter method.', {'vid': volume['id'], 'wwpns': connector['wwpns']}) info = self.common.initialize_connection(volume, connector) data = info['data'] init_tgt_map = ( self.common.build_fc_init_tgt_map(connector, data['target_wwn'])) data['initiator_target_map'] = init_tgt_map info['data'] = data LOG.debug('initialize_connection, ' 'info: %s, exit method.', info) fczm_utils.add_fc_zone(info) return info
def initialize_connection(self, volume, connector): self.common.client_login() try: data = {} data['target_lun'] = self.common.map_volume(volume, connector, 'wwpns') ports, init_targ_map = self.get_init_targ_map(connector) data['target_discovered'] = True data['target_wwn'] = ports data['initiator_target_map'] = init_targ_map info = {'driver_volume_type': 'fibre_channel', 'data': data} fczm_utils.add_fc_zone(info) return info finally: self.common.client_logout()
def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info.""" properties = {} properties['volume_id'] = volume.id properties['target_discovered'] = False properties['target_wwn'] = [] init_ports = self._build_initport_list(connector) itls = self.common.initialize_connection(volume, 'FC', init_ports, connector['host']) target_wwns = None initiator_target_map = None if itls: properties['target_lun'] = itls[0]['hlu'] target_wwns, initiator_target_map = ( self._build_initiator_target_map(itls, connector)) properties['target_wwn'] = target_wwns properties['initiator_target_map'] = initiator_target_map auth = None try: auth = volume.provider_auth except AttributeError: pass if auth: (auth_method, auth_username, auth_secret) = auth.split() properties['auth_method'] = auth_method properties['auth_username'] = auth_username properties['auth_password'] = auth_secret LOG.debug('FC properties: %s', properties) conn_info = { 'driver_volume_type': 'fibre_channel', 'data': properties, } fczm_utils.add_fc_zone(conn_info) return conn_info
def _initialize_connection_fc(self, volume, connector): volume_name = self._make_volume_name(volume) infinidat_volume = self._get_infinidat_volume_by_name(volume_name) ports = [wwn.WWN(wwpn) for wwpn in connector['wwpns']] for port in ports: infinidat_host = self._get_or_create_host(port) mapping = self._get_or_create_mapping(infinidat_host, infinidat_volume) lun = mapping.get_lun() # Create initiator-target mapping. target_wwpns = list(self._get_online_fc_ports()) target_wwpns, init_target_map = self._build_initiator_target_map( connector, target_wwpns) conn_info = dict(driver_volume_type='fibre_channel', data=dict(target_discovered=False, target_wwn=target_wwpns, target_lun=lun, initiator_target_map=init_target_map)) fczm_utils.add_fc_zone(conn_info) return conn_info
def _initialize_connection_fc(self, volume, connector): volume_name = self._make_volume_name(volume) infinidat_volume = self._get_infinidat_volume_by_name(volume_name) ports = [wwn.WWN(wwpn) for wwpn in connector['wwpns']] for port in ports: infinidat_host = self._get_or_create_host(port) mapping = self._get_or_create_mapping(infinidat_host, infinidat_volume) lun = mapping.get_lun() # Create initiator-target mapping. target_wwpns = list(self._get_online_fc_ports()) target_wwpns, init_target_map = self._build_initiator_target_map( connector, target_wwpns) conn_info = dict(driver_volume_type='fibre_channel', data=dict(target_discovered=False, target_wwn=target_wwpns, target_lun=lun, initiator_target_map=init_target_map)) fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Perform work so that an FC connection can be made. To be able to create a FC connection from a given host to a volume, we must: 1. Translate the given WWNN to a host name 2. Create new host on the storage system if it does not yet exist 3. Map the volume to the host if it is not already done 4. Return the connection information for relevant nodes (in the proper I/O group) """ LOG.debug( 'enter: initialize_connection: volume %(vol)s with ' 'connector %(conn)s.', { 'vol': volume, 'conn': connector }) vdisk_name = volume['name'] vdisk_id = volume['id'] vdisk_params = self._get_vdisk_params(volume['volume_type_id']) # TODO(edwin): might fix it after vdisk copy function is # ready in FlashSystem thin-provision layer. As this validation # is to check the vdisk which is in copying, at present in firmware # level vdisk doesn't allow to map host which it is copy. New # vdisk clone and snapshot function will cover it. After that the # _wait_vdisk_copy_completed need some modification. self._wait_vdisk_copy_completed(vdisk_name) self._driver_assert( self._is_vdisk_defined(vdisk_name), (_('initialize_connection: vdisk %s is not defined.') % vdisk_name)) lun_id = self._map_vdisk_to_host(vdisk_name, connector) properties = {} try: properties = self._get_vdisk_map_properties( connector, lun_id, vdisk_name, vdisk_id, vdisk_params) except exception.VolumeBackendAPIException: with excutils.save_and_reraise_exception(): self.terminate_connection(volume, connector) LOG.error( 'initialize_connection: Failed to collect ' 'return properties for volume %(vol)s and ' 'connector %(conn)s.', { 'vol': volume, 'conn': connector }) LOG.debug( 'leave: initialize_connection:\n volume: %(vol)s\n connector ' '%(conn)s\n properties: %(prop)s.', { 'vol': volume, 'conn': connector, 'prop': properties }) fczm_utils.add_fc_zone(properties) return properties
def initialize_connection(self, volume, connector): """Assigns the volume to a server. Assign any created volume to a compute node/host so that it can be used from that host. The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. Example return values: { 'driver_volume_type': 'fibre_channel' 'data': { 'encrypted': False, 'target_discovered': True, 'target_lun': 1, 'target_wwn': '1234567890123', } } or { 'driver_volume_type': 'fibre_channel' 'data': { 'encrypted': False, 'target_discovered': True, 'target_lun': 1, 'target_wwn': ['1234567890123', '0987654321321'], } } Steps to export a volume on 3PAR * Create a host on the 3par with the target wwn * Create a VLUN for that HOST with the volume we want to export. """ common = self._login() try: # we have to make sure we have a host host = self._create_host(common, volume, connector) target_wwns, init_targ_map, numPaths = \ self._build_initiator_target_map(common, connector) if not connector.get('multipath'): target_wwns = target_wwns[:1] initiator = connector.get('wwpns')[0] init_targ_map[initiator] = init_targ_map[initiator][:1] # check if a VLUN already exists for this host existing_vlun = common.find_existing_vlun(volume, host) vlun = None if existing_vlun is None: # now that we have a host, create the VLUN if self.lookup_service is not None and numPaths == 1: nsp = None active_fc_port_list = common.get_active_fc_target_ports() for port in active_fc_port_list: if port['portWWN'].lower() == target_wwns[0].lower(): nsp = port['nsp'] break vlun = common.create_vlun(volume, host, nsp) else: vlun = common.create_vlun(volume, host) else: vlun = existing_vlun info = { 'driver_volume_type': 'fibre_channel', 'data': { 'target_lun': vlun['lun'], 'target_discovered': True, 'target_wwn': target_wwns, 'initiator_target_map': init_targ_map } } encryption_key_id = volume.get('encryption_key_id', None) info['data']['encrypted'] = encryption_key_id is not None fczm_utils.add_fc_zone(info) return info finally: self._logout(common)
def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info.""" """ connector = {'ip': CONF.my_ip, 'host': CONF.host, 'initiator': self._initiator, 'wwnns': self._fc_wwnns, 'wwpns': self._fc_wwpns} """ dc_fc = {} dc_target = {} lsTargetWwpn = [] output = None properties = {} preferTargets = {} ret = 0 targetIdentifier = [] szwwpns = [] LOG.info( 'initialize_connection volume: %(volume)s, connector:' ' %(connector)s', { "volume": volume, "connector": connector }) # Get Storage Fiber channel controller dc_fc = self._get_fc_channel() # Get existed FC target list to decide target wwpn dc_target = self._get_targets() if len(dc_target) == 0: msg = _('Backend storage did not configure fiber channel ' 'target.') raise exception.VolumeBackendAPIException(data=msg) for keyFc in dc_fc: for targetuuid in dc_target: if dc_fc[keyFc]['hardware_address'] == \ dc_target[targetuuid]['targetAddr']: preferTargets[targetuuid] = dc_target[targetuuid] break # Confirm client wwpn is existed in sns table # Covert wwwpns to 'xx:xx:xx:xx:xx:xx:xx:xx' format for dwwpn in connector['wwpns']: szwwpn = self._convertHex2String(dwwpn) if len(szwwpn) == 0: msg = _('Invalid wwpns format %(wwpns)s') % \ {'wwpns': connector['wwpns']} raise exception.VolumeBackendAPIException(data=msg) szwwpns.append(szwwpn) if len(szwwpns): for targetUuid in preferTargets: targetWwpn = '' targetWwpn = preferTargets.get(targetUuid, {}).get('targetAddr', '') lsTargetWwpn.append(targetWwpn) # Use wwpns to assign volume. LOG.info('Prefer use target wwpn %(wwpn)s', {'wwpn': lsTargetWwpn}) # Start to create export in all FC target node. assignedTarget = [] for pTarget in lsTargetWwpn: try: ret = self._export_fc(volume['id'], str(pTarget), szwwpns, volume['name']) if ret: break else: assignedTarget.append(pTarget) except Exception as e: LOG.error('Failed to export fiber channel target ' 'due to %s', e) ret = errno.EFAULT break if ret == 0: ret, output = self.dpl.get_vdev(self._conver_uuid2hex( volume['id'])) nLun = -1 if ret == 0: try: for p in output['exports']['Network/FC']: # check initiator wwpn existed in target initiator list for initI in p.get('permissions', []): for szwpn in szwwpns: if initI.get(szwpn, None): nLun = initI[szwpn] break if nLun != -1: break if nLun != -1: targetIdentifier.append( str(p['target_identifier']).replace(':', '')) except Exception: msg = _('Invalid connection initialization response of ' 'volume %(name)s: ' '%(output)s') % { 'name': volume['name'], 'output': output } raise exception.VolumeBackendAPIException(data=msg) if nLun != -1: init_targ_map = self._build_initiator_target_map( connector, targetIdentifier) properties['target_discovered'] = True properties['target_wwn'] = targetIdentifier properties['target_lun'] = int(nLun) properties['volume_id'] = volume['id'] properties['initiator_target_map'] = init_targ_map LOG.info( '%(volume)s assign type fibre_channel, properties ' '%(properties)s', { 'volume': volume['id'], 'properties': properties }) else: msg = _('Invalid connection initialization response of ' 'volume %(name)s') % { 'name': volume['name'] } raise exception.VolumeBackendAPIException(data=msg) LOG.info( 'Connect initialization info: ' '{driver_volume_type: fibre_channel, ' 'data: %(properties)s', {'properties': properties}) conn_info = {'driver_volume_type': 'fibre_channel', 'data': properties} fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Perform necessary work to make a FC connection. To be able to create an FC connection from a given host to a volume, we must: 1. Translate the given WWNN to a host name 2. Create new host on the storage system if it does not yet exist 3. Map the volume to the host if it is not already done 4. Return the connection information for relevant nodes (in the proper I/O group) """ volume_name = self._get_target_vol(volume) # Check if a host object is defined for this host name host_name = self._assistant.get_host_from_connector(connector) if host_name is None: # Host does not exist - add a new host to InStorage/MCS host_name = self._assistant.create_host(connector) volume_attributes = self._assistant.get_vdisk_attributes(volume_name) if volume_attributes is None: msg = (_('initialize_connection: Failed to get attributes' ' for volume %s.') % volume_name) LOG.error(msg) raise exception.VolumeDriverException(message=msg) lun_id = self._assistant.map_vol_to_host(volume_name, host_name, True) try: preferred_node = volume_attributes['preferred_node_id'] IO_group = volume_attributes['IO_group_id'] except KeyError as e: LOG.error('Did not find expected column name in ' 'lsvdisk: %s.', e) raise exception.VolumeBackendAPIException( data=_('initialize_connection: Missing volume attribute for ' 'volume %s.') % volume_name) try: # Get preferred node and other nodes in I/O group preferred_node_entry = None io_group_nodes = [] for node in self._state['storage_nodes'].values(): if node['id'] == preferred_node: preferred_node_entry = node if node['IO_group'] == IO_group: io_group_nodes.append(node) if not len(io_group_nodes): msg = (_('initialize_connection: No node found in ' 'I/O group %(gid)s for volume %(vol)s.') % {'gid': IO_group, 'vol': volume_name}) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) if not preferred_node_entry: # Get 1st node in I/O group preferred_node_entry = io_group_nodes[0] LOG.warning('initialize_connection: Did not find a ' 'preferred node for volume %s.', volume_name) properties = {} properties['target_discovered'] = False properties['target_lun'] = lun_id properties['volume_id'] = volume.id conn_wwpns = self._assistant.get_conn_fc_wwpns(host_name) # If conn_wwpns is empty, then that means that there were # no target ports with visibility to any of the initiators # so we return all target ports. if len(conn_wwpns) == 0: for node in self._state['storage_nodes'].values(): conn_wwpns.extend(node['WWPN']) properties['target_wwn'] = conn_wwpns i_t_map = self.make_initiator_target_all2all_map( connector['wwpns'], conn_wwpns) properties['initiator_target_map'] = i_t_map except Exception: with excutils.save_and_reraise_exception(): self._do_terminate_connection(volume, connector) LOG.error('initialize_connection: Failed ' 'to collect return ' 'properties for volume %(vol)s and connector ' '%(conn)s.\n', {'vol': volume, 'conn': connector}) info = {'driver_volume_type': 'fibre_channel', 'data': properties, } fczm_utils.add_fc_zone(info) return info
def initialize_connection(self, volume, connector): """Perform necessary work to make a FC connection. To be able to create an FC connection from a given host to a volume, we must: 1. Translate the given WWNN to a host name 2. Create new host on the storage system if it does not yet exist 3. Map the volume to the host if it is not already done 4. Return the connection information for relevant nodes (in the proper I/O group) """ volume_name = self._get_target_vol(volume) # Check if a host object is defined for this host name host_name = self._assistant.get_host_from_connector(connector) if host_name is None: # Host does not exist - add a new host to InStorage/MCS host_name = self._assistant.create_host(connector) volume_attributes = self._assistant.get_vdisk_attributes(volume_name) if volume_attributes is None: msg = (_('initialize_connection: Failed to get attributes' ' for volume %s.') % volume_name) LOG.error(msg) raise exception.VolumeDriverException(message=msg) lun_id = self._assistant.map_vol_to_host(volume_name, host_name, True) try: preferred_node = volume_attributes['preferred_node_id'] IO_group = volume_attributes['IO_group_id'] except KeyError as e: LOG.error('Did not find expected column name in ' 'lsvdisk: %s.', e) raise exception.VolumeBackendAPIException( data=_('initialize_connection: Missing volume attribute for ' 'volume %s.') % volume_name) try: # Get preferred node and other nodes in I/O group preferred_node_entry = None io_group_nodes = [] for node in self._state['storage_nodes'].values(): if node['id'] == preferred_node: preferred_node_entry = node if node['IO_group'] == IO_group: io_group_nodes.append(node) if not len(io_group_nodes): msg = (_('initialize_connection: No node found in ' 'I/O group %(gid)s for volume %(vol)s.') % {'gid': IO_group, 'vol': volume_name}) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) if not preferred_node_entry: # Get 1st node in I/O group preferred_node_entry = io_group_nodes[0] LOG.warning('initialize_connection: Did not find a ' 'preferred node for volume %s.', volume_name) properties = {} properties['target_discovered'] = False properties['target_lun'] = lun_id properties['volume_id'] = volume.id conn_wwpns = self._assistant.get_conn_fc_wwpns(host_name) # If conn_wwpns is empty, then that means that there were # no target ports with visibility to any of the initiators # so we return all target ports. if len(conn_wwpns) == 0: for node in self._state['storage_nodes'].values(): conn_wwpns.extend(node['WWPN']) properties['target_wwn'] = conn_wwpns i_t_map = utils.make_initiator_target_all2all_map( connector['wwpns'], conn_wwpns) properties['initiator_target_map'] = i_t_map except Exception: with excutils.save_and_reraise_exception(): self._do_terminate_connection(volume, connector) LOG.error('initialize_connection: Failed ' 'to collect return ' 'properties for volume %(vol)s and connector ' '%(conn)s.\n', {'vol': volume, 'conn': connector}) info = {'driver_volume_type': 'fibre_channel', 'data': properties, } fczm_utils.add_fc_zone(info) return info
def initialize_connection(self, volume, connector): """Map the created volume.""" conn_info = self.proxy.initialize_connection(volume, connector) fczm_utils.add_fc_zone(conn_info) return conn_info
def _retype_hyperswap_volume(self, ctxt, volume, host, old_opts, new_opts, old_pool, new_pool, vdisk_changes, need_copy, new_type): if (old_opts['volume_topology'] != 'hyperswap' and new_opts['volume_topology'] == 'hyperswap'): LOG.debug( 'retype: Convert a normal volume %s to hyperswap ' 'volume.', volume.name) conn_info = {} if volume.previous_status == 'in-use': vdisk_info = self._helpers.ssh.lsvdiskhostmap(volume.name) peer_pool = new_opts['peer_pool'] iogrp_list = self._helpers.get_hyperswap_pool_io_grp( self._state, new_pool, peer_pool) for mapping_info in vdisk_info: host = mapping_info['host_name'] try: host_info = self._helpers.ssh.lshost(host) conn_info[host] = self._get_volume_connection_info( ctxt, volume, host_info, iogrp_list) host_site = self._get_volume_host_site_from_conf( volume, conn_info[host].get('connector')) self._update_host_site_for_hyperswap_volume( host, host_site) self._helpers.ssh.addhostiogrp(host, iogrp_list) except Exception as ex: msg = _('Error updating host %(host)s due to %(ex)s', { 'host': host, 'ex': ex }) raise exception.VolumeBackendAPIException(data=msg) self._helpers.convert_volume_to_hyperswap(volume.name, new_opts, self._state) if volume.previous_status == 'in-use': for host, info in conn_info.items(): try: fczm_utils.add_fc_zone(info) except Exception as ex: self._helpers.convert_hyperswap_volume_to_normal( volume.name, new_opts['peer_pool']) msg = _( 'Zoning failed for volume %(vol)s and host ' '%(host)s due to %(ex)s.', { 'vol': volume.name, 'host': host, 'ex': ex }) raise exception.VolumeBackendAPIException(data=msg) elif (old_opts['volume_topology'] == 'hyperswap' and new_opts['volume_topology'] != 'hyperswap'): LOG.debug( 'retype: Convert a hyperswap volume %s to normal ' 'volume.', volume.name) if new_pool == old_pool: self._helpers.convert_hyperswap_volume_to_normal( volume.name, old_opts['peer_pool']) elif new_pool == old_opts['peer_pool']: self._helpers.convert_hyperswap_volume_to_normal( volume.name, old_pool) if volume.previous_status == 'in-use': vdisk_info = self._helpers.ssh.lsvdiskhostmap(volume.name) for mapping_info in vdisk_info: res = self._helpers.check_host_mapped_vols( mapping_info['host_name']) if len(res) == 1: self._helpers.update_host(mapping_info['host_name'], None) else: rel_info = self._helpers.get_relationship_info(volume.name) aux_vdisk = rel_info['aux_vdisk_name'] if need_copy: self.add_vdisk_copy(aux_vdisk, old_opts['peer_pool'], new_type, auto_delete=True) elif vdisk_changes: self._helpers.change_vdisk_options(aux_vdisk, vdisk_changes, new_opts, self._state) if need_copy: self.add_vdisk_copy(volume.name, old_pool, new_type, auto_delete=True) elif vdisk_changes: self._helpers.change_vdisk_options(volume.name, vdisk_changes, new_opts, self._state)
def initialize_connection(self, volume, connector): conn_info = self.fc_initialize_connection(volume, connector) fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info.""" """ connector = {'ip': CONF.my_ip, 'host': CONF.host, 'initiator': self._initiator, 'wwnns': self._fc_wwnns, 'wwpns': self._fc_wwpns} """ dc_fc = {} dc_target = {} lsTargetWwpn = [] output = None properties = {} preferTargets = {} ret = 0 targetIdentifier = [] szwwpns = [] LOG.info('initialize_connection volume: %(volume)s, connector:' ' %(connector)s', {"volume": volume, "connector": connector}) # Get Storage Fiber channel controller dc_fc = self._get_fc_channel() # Get existed FC target list to decide target wwpn dc_target = self._get_targets() if len(dc_target) == 0: msg = _('Backend storage did not configure fiber channel ' 'target.') raise exception.VolumeBackendAPIException(data=msg) for keyFc in dc_fc: for targetuuid in dc_target: if dc_fc[keyFc]['hardware_address'] == \ dc_target[targetuuid]['targetAddr']: preferTargets[targetuuid] = dc_target[targetuuid] break # Confirm client wwpn is existed in sns table # Covert wwwpns to 'xx:xx:xx:xx:xx:xx:xx:xx' format for dwwpn in connector['wwpns']: szwwpn = self._convertHex2String(dwwpn) if len(szwwpn) == 0: msg = _('Invalid wwpns format %(wwpns)s') % \ {'wwpns': connector['wwpns']} raise exception.VolumeBackendAPIException(data=msg) szwwpns.append(szwwpn) if len(szwwpns): for targetUuid in preferTargets: targetWwpn = '' targetWwpn = preferTargets.get(targetUuid, {}).get('targetAddr', '') lsTargetWwpn.append(targetWwpn) # Use wwpns to assign volume. LOG.info('Prefer use target wwpn %(wwpn)s', {'wwpn': lsTargetWwpn}) # Start to create export in all FC target node. assignedTarget = [] for pTarget in lsTargetWwpn: try: ret = self._export_fc(volume['id'], str(pTarget), szwwpns, volume['name']) if ret: break else: assignedTarget.append(pTarget) except Exception as e: LOG.error('Failed to export fiber channel target ' 'due to %s', e) ret = errno.EFAULT break if ret == 0: ret, output = self.dpl.get_vdev(self._conver_uuid2hex( volume['id'])) nLun = -1 if ret == 0: try: for p in output['exports']['Network/FC']: # check initiator wwpn existed in target initiator list for initI in p.get('permissions', []): for szwpn in szwwpns: if initI.get(szwpn, None): nLun = initI[szwpn] break if nLun != -1: break if nLun != -1: targetIdentifier.append( str(p['target_identifier']).replace(':', '')) except Exception: msg = _('Invalid connection initialization response of ' 'volume %(name)s: ' '%(output)s') % {'name': volume['name'], 'output': output} raise exception.VolumeBackendAPIException(data=msg) if nLun != -1: init_targ_map = self._build_initiator_target_map(connector, targetIdentifier) properties['target_discovered'] = True properties['target_wwn'] = targetIdentifier properties['target_lun'] = int(nLun) properties['volume_id'] = volume['id'] properties['initiator_target_map'] = init_targ_map LOG.info('%(volume)s assign type fibre_channel, properties ' '%(properties)s', {'volume': volume['id'], 'properties': properties}) else: msg = _('Invalid connection initialization response of ' 'volume %(name)s') % {'name': volume['name']} raise exception.VolumeBackendAPIException(data=msg) LOG.info('Connect initialization info: ' '{driver_volume_type: fibre_channel, ' 'data: %(properties)s', {'properties': properties}) conn_info = {'driver_volume_type': 'fibre_channel', 'data': properties} fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): lun_id, lun_type = self.get_lun_id_and_type(volume) wwns = connector['wwpns'] LOG.info( 'initialize_connection, initiator: %(wwpns)s,' ' LUN ID: %(lun_id)s.', {'wwpns': wwns, 'lun_id': lun_id},) portg_id = None host_id = self.client.add_host_with_check(connector['host']) if not self.fcsan: self.fcsan = fczm_utils.create_lookup_service() if self.fcsan: # Use FC switch. zone_helper = fc_zone_helper.FCZoneHelper(self.fcsan, self.client) try: (tgt_port_wwns, portg_id, init_targ_map) = ( zone_helper.build_ini_targ_map(wwns, host_id, lun_id, lun_type)) except Exception as err: self.remove_host_with_check(host_id) msg = _('build_ini_targ_map fails. %s') % err raise exception.VolumeBackendAPIException(data=msg) for ini in init_targ_map: self.client.ensure_fc_initiator_added(ini, host_id) else: # Not use FC switch. online_wwns_in_host = ( self.client.get_host_online_fc_initiators(host_id)) online_free_wwns = self.client.get_online_free_wwns() fc_initiators_on_array = self.client.get_fc_initiator_on_array() wwns = [i for i in wwns if i in fc_initiators_on_array] for wwn in wwns: if (wwn not in online_wwns_in_host and wwn not in online_free_wwns): wwns_in_host = ( self.client.get_host_fc_initiators(host_id)) iqns_in_host = ( self.client.get_host_iscsi_initiators(host_id)) if not (wwns_in_host or iqns_in_host or self.client.is_host_associated_to_hostgroup(host_id)): self.client.remove_host(host_id) msg = _('No FC initiator can be added to host.') LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) for wwn in wwns: if wwn in online_free_wwns: self.client.add_fc_port_to_host(host_id, wwn) (tgt_port_wwns, init_targ_map) = ( self.client.get_init_targ_map(wwns)) # Add host into hostgroup. hostgroup_id = self.client.add_host_to_hostgroup(host_id) metadata = huawei_utils.get_volume_private_data(volume) LOG.info("initialize_connection, metadata is: %s.", metadata) hypermetro_lun = metadata.get('hypermetro_id') is not None map_info = self.client.do_mapping(lun_id, hostgroup_id, host_id, portg_id, lun_type, hypermetro_lun) host_lun_id = self.client.get_host_lun_id(host_id, lun_id, lun_type) # Return FC properties. fc_info = {'driver_volume_type': 'fibre_channel', 'data': {'target_lun': int(host_lun_id), 'target_discovered': True, 'target_wwn': tgt_port_wwns, 'volume_id': volume.id, 'initiator_target_map': init_targ_map, 'map_info': map_info}, } # Deal with hypermetro connection. if hypermetro_lun: loc_tgt_wwn = fc_info['data']['target_wwn'] local_ini_tgt_map = fc_info['data']['initiator_target_map'] hyperm = hypermetro.HuaweiHyperMetro(self.client, self.rmt_client, self.configuration) rmt_fc_info = hyperm.connect_volume_fc(volume, connector) rmt_tgt_wwn = rmt_fc_info['data']['target_wwn'] rmt_ini_tgt_map = rmt_fc_info['data']['initiator_target_map'] fc_info['data']['target_wwn'] = (loc_tgt_wwn + rmt_tgt_wwn) wwns = connector['wwpns'] for wwn in wwns: if (wwn in local_ini_tgt_map and wwn in rmt_ini_tgt_map): fc_info['data']['initiator_target_map'][wwn].extend( rmt_ini_tgt_map[wwn]) elif (wwn not in local_ini_tgt_map and wwn in rmt_ini_tgt_map): fc_info['data']['initiator_target_map'][wwn] = ( rmt_ini_tgt_map[wwn]) # else, do nothing loc_map_info = fc_info['data']['map_info'] rmt_map_info = rmt_fc_info['data']['map_info'] same_host_id = self._get_same_hostid(loc_map_info, rmt_map_info) self.client.change_hostlun_id(loc_map_info, same_host_id) hyperm.rmt_client.change_hostlun_id(rmt_map_info, same_host_id) fc_info['data']['target_lun'] = same_host_id hyperm.rmt_client.logout() fczm_utils.add_fc_zone(fc_info) LOG.info("Return FC info is: %s.", fc_info) return fc_info
def _do_initialize_connection_locked(system_id, host): conn_info = self._do_initialize_connection(volume, connector) fczm_utils.add_fc_zone(conn_info) return conn_info
def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. Assign any created volume to a compute node/host so that it can be used from that host. The driver returns a driver_volume_type of 'fibre_channel'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. """ # We use id to name the volume name as it is a # known unique name. volume_name = volume.get('id') provider_id = volume.get('provider_id') islivevol = self._is_live_vol(volume) LOG.debug('Initialize connection: %s', volume_name) with self._client.open_connection() as api: try: wwpns = connector.get('wwpns') # Find the volume on the storage center. Note that if this # is live volume and we are swapped this will be the back # half of the live volume. scvolume = api.find_volume(volume_name, provider_id, islivevol) if scvolume: # Get the SSN it is on. ssn = scvolume['instanceId'].split('.')[0] # Find our server. scserver = self._find_server(api, wwpns, ssn) # No? Create it. if scserver is None: scserver = api.create_server( wwpns, self.configuration.dell_server_os, ssn) # We have a volume and a server. Map them. if scserver is not None: mapping = api.map_volume(scvolume, scserver) if mapping is not None: # Since we just mapped our volume we had # best update our sc volume object. scvolume = api.get_volume(scvolume['instanceId']) lun, targets, init_targ_map = api.find_wwns( scvolume, scserver) # Do we have extra live volume work? if islivevol: # Get our live volume. sclivevolume = api.get_live_volume(provider_id) # Do not map to a failed over volume. if (sclivevolume and not api.is_failed_over(provider_id, sclivevolume)): # Now map our secondary. lvlun, lvtargets, lvinit_targ_map = ( self.initialize_secondary(api, sclivevolume, wwpns)) # Unmapped. Add info to our list. targets += lvtargets init_targ_map.update(lvinit_targ_map) # Roll up our return data. if lun is not None and len(targets) > 0: data = {'driver_volume_type': 'fibre_channel', 'data': {'target_lun': lun, 'target_discovered': True, 'target_wwn': targets, 'initiator_target_map': init_targ_map, 'discard': True}} LOG.debug('Return FC data: %s', data) fczm_utils.add_fc_zone(data) return data LOG.error('Lun mapping returned null!') except Exception: with excutils.save_and_reraise_exception(): LOG.error('Failed to initialize connection.') # We get here because our mapping is none so blow up. raise exception.VolumeBackendAPIException( data=_('Unable to map volume.'))
def initialize_connection(self, volume, connector): """Map the created volume.""" conn_info = self.proxy.initialize_connection(volume, connector) fczm_utils.add_fc_zone(conn_info) return conn_info