def test_generate_password(self): password = volume_utils.generate_password() self.assertTrue(any(c for c in password if c in "23456789")) self.assertTrue(any(c for c in password if c in "abcdefghijkmnopqrstuvwxyz")) self.assertTrue(any(c for c in password if c in "ABCDEFGHJKLMNPQRSTUVWXYZ")) self.assertEqual(16, len(password)) self.assertEqual(10, len(volume_utils.generate_password(10)))
def test_generate_password(self): password = volume_utils.generate_password() self.assertTrue(any(c for c in password if c in '23456789')) self.assertTrue( any(c for c in password if c in 'abcdefghijkmnopqrstuvwxyz')) self.assertTrue( any(c for c in password if c in 'ABCDEFGHJKLMNPQRSTUVWXYZ')) self.assertEqual(16, len(password)) self.assertEqual(10, len(volume_utils.generate_password(10)))
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_target, lun = self._get_target_and_lun(context, volume) if self.target_name is None: iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) else: iscsi_name = self.target_name if self.chap_username and self.chap_password: chap_auth = (self.chap_username, self.chap_password) else: chap_auth = self._get_target_chap_auth(context, iscsi_name) if not chap_auth: chap_auth = (vutils.generate_username(), vutils.generate_password()) tid = self.create_iscsi_target(iscsi_name, volume['id'], iscsi_target, lun, volume_path, chap_auth) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', *chap_auth) return data
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_target, lun = self._get_target_and_lun(context, volume) if self.target_name is None: iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) else: iscsi_name = self.target_name if self.chap_username and self.chap_password: chap_username = self.chap_username chap_password = self.chap_password else: chap_username = vutils.generate_username() chap_password = vutils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) tid = self.create_iscsi_target(iscsi_name, volume['id'], iscsi_target, lun, volume_path, chap_auth) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', chap_username, chap_password) return data
def create_export(self, context, volume, connector): """Driver entry point to get the export info for a new volume.""" target_name = self._get_target_name(volume) updates = {} if not self._tgt_utils.iscsi_target_exists(target_name): self._tgt_utils.create_iscsi_target(target_name) updates['provider_location'] = target_name if self.configuration.use_chap_auth: chap_username = (self.configuration.chap_username or utils.generate_username()) chap_password = (self.configuration.chap_password or utils.generate_password()) self._tgt_utils.set_chap_credentials(target_name, chap_username, chap_password) updates['provider_auth'] = ' '.join(('CHAP', chap_username, chap_password)) # This operation is idempotent self._tgt_utils.add_disk_to_target(volume['name'], target_name) return updates
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) # Verify we haven't setup a CHAP creds file already # if DNE no big deal, we'll just create it current_chap_auth = self._get_target_chap_auth(iscsi_name) if current_chap_auth: (chap_username, chap_password) = current_chap_auth else: chap_username = vutils.generate_username() chap_password = vutils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future iscsi_write_cache = self.configuration.get('iscsi_write_cache', 'on') tid = self.create_iscsi_target(iscsi_name, iscsi_target, 0, volume_path, chap_auth, iscsi_write_cache=iscsi_write_cache) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication('CHAP', chap_username, chap_password) return data
def test_generate_password(self): password = volume_utils.generate_password() self.assertTrue([c for c in password if c in '0123456789']) self.assertTrue([c for c in password if c in 'abcdefghijklmnopqrstuvwxyz']) self.assertTrue([c for c in password if c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'])
def create_export(self, context, volume, connector): """Driver entry point to get the export info for a new volume.""" target_name = self._get_target_name(volume) updates = {} if not self._tgt_utils.iscsi_target_exists(target_name): self._tgt_utils.create_iscsi_target(target_name) updates['provider_location'] = target_name if self.configuration.use_chap_auth: chap_username = (self.configuration.chap_username or utils.generate_username()) chap_password = (self.configuration.chap_password or utils.generate_password()) self._tgt_utils.set_chap_credentials(target_name, chap_username, chap_password) updates['provider_auth'] = ' '.join( ('CHAP', chap_username, chap_password)) # This operation is idempotent self._tgt_utils.add_disk_to_target(volume.name, target_name) return updates
def _create_server(self, connector, client): server_info = None chap_enabled = self.configuration.hplefthand_iscsi_chap_enabled try: server_info = client.getServerByName(connector['host']) chap_secret = server_info['chapTargetSecret'] if not chap_enabled and chap_secret: LOG.warning(_LW('CHAP secret exists for host %s but CHAP is ' 'disabled'), connector['host']) if chap_enabled and chap_secret is None: LOG.warning(_LW('CHAP is enabled, but server secret not ' 'configured on server %s'), connector['host']) return server_info except hpexceptions.HTTPNotFound: # server does not exist, so create one pass optional = None if chap_enabled: chap_secret = utils.generate_password() optional = {'chapName': connector['initiator'], 'chapTargetSecret': chap_secret, 'chapAuthenticationRequired': True } server_info = client.createServer(connector['host'], connector['initiator'], optional) return server_info
def _create_server(self, connector, client): server_info = None chap_enabled = self.configuration.hplefthand_iscsi_chap_enabled try: server_info = client.getServerByName(connector["host"]) chap_secret = server_info["chapTargetSecret"] if not chap_enabled and chap_secret: LOG.warning(_LW("CHAP secret exists for host %s but CHAP is " "disabled"), connector["host"]) if chap_enabled and chap_secret is None: LOG.warning(_LW("CHAP is enabled, but server secret not " "configured on server %s"), connector["host"]) return server_info except hpexceptions.HTTPNotFound: # server does not exist, so create one pass optional = None if chap_enabled: chap_secret = utils.generate_password() optional = { "chapName": connector["initiator"], "chapTargetSecret": chap_secret, "chapAuthenticationRequired": True, } server_info = client.createServer(connector["host"], connector["initiator"], optional) return server_info
def test_generate_password(self): password = volume_utils.generate_password() self.assertTrue([c for c in password if c in '0123456789']) self.assertTrue( [c for c in password if c in 'abcdefghijklmnopqrstuvwxyz']) self.assertTrue( [c for c in password if c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'])
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" # 'iscsi_name': 'iqn.2010-10.org.openstack:volume-00000001' iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) # Verify we haven't setup a CHAP creds file already # if DNE no big deal, we'll just create it chap_auth = self._get_target_chap_auth(context, volume) if not chap_auth: chap_auth = (vutils.generate_username(), vutils.generate_password()) # Get portals ips and port portals_config = self._get_portals_config() # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.create_iscsi_target(iscsi_name, iscsi_target, lun, volume_path, chap_auth, **portals_config) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun, self.configuration.iscsi_secondary_ip_addresses) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication('CHAP', *chap_auth) return data
def create_export(self, context, volume, volume_path, conf): """Creates an export for a logical volume.""" iscsi_name = "%s%s" % (conf.iscsi_target_prefix, volume['name']) max_targets = conf.safe_get('iscsi_num_targets') (iscsi_target, lun) = self._get_target_and_lun(context, volume, max_targets) current_chap_auth = self._get_target_chap_auth(iscsi_name) if current_chap_auth: (chap_username, chap_password) = current_chap_auth else: chap_username = utils.generate_username() chap_password = utils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.create_iscsi_target(iscsi_name, iscsi_target, 0, volume_path, chap_auth, write_cache= conf.iscsi_write_cache) data = {} data['location'] = self._iscsi_location( conf.iscsi_ip_address, tid, iscsi_name, conf.iscsi_port, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', chap_username, chap_password) return data
def create_export(self, context, volume, volume_path, conf): """Creates an export for a logical volume.""" iscsi_name = "%s%s" % (conf.iscsi_target_prefix, volume['name']) max_targets = conf.safe_get('iscsi_num_targets') (iscsi_target, lun) = self._get_target_and_lun(context, volume, max_targets) chap_username = utils.generate_username() chap_password = utils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.create_iscsi_target(iscsi_name, iscsi_target, 0, volume_path, chap_auth, write_cache= conf.iscsi_write_cache) data = {} data['location'] = self._iscsi_location( conf.iscsi_ip_address, tid, iscsi_name, conf.iscsi_port, lun) data['auth'] = self._iscsi_authentication( 'CHAP', chap_username, chap_password) return data
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) # Verify we haven't setup a CHAP creds file already # if DNE no big deal, we'll just create it current_chap_auth = self._get_target_chap_auth(iscsi_name) if current_chap_auth: (chap_username, chap_password) = current_chap_auth else: chap_username = vutils.generate_username() chap_password = vutils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future iscsi_write_cache = self.configuration.get('iscsi_write_cache', 'on') tid = self.create_iscsi_target(iscsi_name, iscsi_target, 0, volume_path, chap_auth, iscsi_write_cache=iscsi_write_cache) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun, self.configuration.iscsi_secondary_ip_addresses) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', chap_username, chap_password) return data
def create_export(self, context, volume, connector): """Driver entry point to get the export info for a new volume.""" # Since the iSCSI targets are not reused, being deleted when the # volume is detached, we should clean up existing targets before # creating a new one. self.remove_export(context, volume) target_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) updates = {'provider_location': target_name} self.utils.create_iscsi_target(target_name) if self.configuration.use_chap_auth: chap_username = (self.configuration.chap_username or utils.generate_username()) chap_password = (self.configuration.chap_password or utils.generate_password()) self.utils.set_chap_credentials(target_name, chap_username, chap_password) updates['provider_auth'] = ' '.join( ('CHAP', chap_username, chap_password)) # Get the disk to add vol_name = volume['name'] self.utils.add_disk_to_target(vol_name, target_name) return updates
def create_export(self, context, volume, connector): """Driver entry point to get the export info for a new volume.""" # Since the iSCSI targets are not reused, being deleted when the # volume is detached, we should clean up existing targets before # creating a new one. self.remove_export(context, volume) target_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) updates = {'provider_location': target_name} self.utils.create_iscsi_target(target_name) if self.configuration.use_chap_auth: chap_username = (self.configuration.chap_username or utils.generate_username()) chap_password = (self.configuration.chap_password or utils.generate_password()) self.utils.set_chap_credentials(target_name, chap_username, chap_password) updates['provider_auth'] = ' '.join(('CHAP', chap_username, chap_password)) # Get the disk to add vol_name = volume['name'] self.utils.add_disk_to_target(vol_name, target_name) return updates
def _create_server(self, connector): server_info = None chap_enabled = self.configuration.hplefthand_iscsi_chap_enabled try: server_info = self.client.getServerByName(connector['host']) chap_secret = server_info['chapTargetSecret'] if not chap_enabled and chap_secret: LOG.warning( _('CHAP secret exists for host %s but CHAP is ' 'disabled') % connector['host']) if chap_enabled and chap_secret is None: LOG.warning( _('CHAP is enabled, but server secret not ' 'configured on server %s') % connector['host']) return server_info except hpexceptions.HTTPNotFound: # server does not exist, so create one pass optional = None if chap_enabled: chap_secret = utils.generate_password() optional = { 'chapName': connector['initiator'], 'chapTargetSecret': chap_secret, 'chapAuthenticationRequired': True } server_info = self.client.createServer(connector['host'], connector['initiator'], optional) return server_info
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" # 'iscsi_name': 'iqn.2010-10.org.openstack:volume-00000001' iscsi_name = "%s%s" % (self.configuration.target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) # Verify we haven't setup a CHAP creds file already # if DNE no big deal, we'll just create it chap_auth = self._get_target_chap_auth(context, volume) if not chap_auth: chap_auth = (vutils.generate_username(), vutils.generate_password()) # Get portals ips and port portals_config = self._get_portals_config() # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.create_iscsi_target(iscsi_name, iscsi_target, lun, volume_path, chap_auth, **portals_config) data = {} data['location'] = self._iscsi_location( self.configuration.target_ip_address, tid, iscsi_name, lun, self.configuration.iscsi_secondary_ip_addresses) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', *chap_auth) return data
def _configure_chap(self, initiator_name): password = volume_utils.generate_password(na_utils.CHAP_SECRET_LENGTH) username = na_utils.DEFAULT_CHAP_USER_NAME self.zapi_client.set_iscsi_chap_authentication(initiator_name, username, password) LOG.debug("Set iSCSI CHAP authentication.") return username, password
def create_nvmeof_target(self, volume_id, subsystem_name, target_ip, target_port, transport_type, nvmet_port_id, ns_id, volume_path): LOG.debug('SPDK create target') nqn = self._get_nqn_with_volume_name(volume_id) if nqn is None: node = self._get_first_free_node() nqn = '%s:cnode%s' % (subsystem_name, node) choice = string.ascii_uppercase + string.digits serial = ''.join( utils.generate_password(length=12, symbolgroups=choice)) params = { 'nqn': nqn, 'allow_any_host': True, 'serial_number': serial, } self._rpc_call('nvmf_subsystem_create', params) listen_address = { 'trtype': transport_type, 'traddr': target_ip, 'trsvcid': str(target_port), } params = { 'nqn': nqn, 'listen_address': listen_address, } self._rpc_call('nvmf_subsystem_add_listener', params) ns = { 'bdev_name': self._get_spdk_volume_name(volume_id), 'nsid': ns_id, } params = { 'nqn': nqn, 'namespace': ns, } self._rpc_call('nvmf_subsystem_add_ns', params) location = self.get_nvmeof_location( nqn, target_ip, target_port, transport_type, ns_id) return {'location': location, 'auth': '', 'provider_id': nqn}
def _create_export(self, context, volume): """Creates an export for a logical volume.""" if volume['name'] is None: return None # devmeg=zfscm.DEVList() # devname=devmeg.get_devname_by_volumename(volume['name']) # volume_path = "/dev/%s" % devname volume_path="/dev/" + self.poolname + "/" + volume['name'] #data = self.target_helper.create_export(context, # volume, # volume_path, # self.configuration) conf=self.configuration iscsi_name = "%s%s" % (conf.iscsi_target_prefix, volume['name']) max_targets = conf.safe_get('iscsi_num_targets') (iscsi_target, lun) = self.target_helper._get_target_and_lun(context, volume, max_targets) try: current_chap_auth = self.target_helper._get_target_chap_auth(context,iscsi_name) except: current_chap_auth = self._getzfs_target_chap_auth(context,iscsi_name) pass if current_chap_auth: (chap_username, chap_password) = current_chap_auth else: chap_username = cutils.generate_username() chap_password = cutils.generate_password() chap_auth = self.target_helper._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.targetbase.create_iscsi_target(iscsi_name,iscsi_target, 0, volume_path, chap_auth, write_cache=conf.iscsi_write_cache) data = {} data['location'] = self.target_helper._iscsi_location( conf.iscsi_ip_address, tid, iscsi_name, conf.iscsi_port, lun) data['auth'] = self.target_helper._iscsi_authentication( 'CHAP', chap_username, chap_password) return { 'provider_location': data['location'], 'provider_auth': data['auth'], }
def initialize_connection(self, volume, connector, **kwargs): """Attach volume to initiator/host. Creates a profile for the initiator, and adds the new profile to the target ACL. """ # generate a CHAP secret here -- there is no way to retrieve an # existing CHAP secret over the Blockbridge API, so it must be # supplied by the volume driver. export_params = { 'chap_user': (kwargs.get('user', volume_utils.generate_username(16))), 'chap_secret': (kwargs.get('password', volume_utils.generate_password(32))), } LOG.debug("Configuring export for %(initiator)s", connector, resource=volume) rsp = self._create_export(volume['id'], connector['initiator'], export_params, user_id=volume['user_id'], project_id=volume['project_id']) # combine locally generated chap credentials with target iqn/lun to # present the attach properties. target_portal = "%s:%s" % (rsp['target_ip'], rsp['target_port']) properties = { 'target_discovered': False, 'target_portal': target_portal, 'target_iqn': rsp['target_iqn'], 'target_lun': rsp['target_lun'], 'volume_id': volume['id'], 'auth_method': 'CHAP', 'auth_username': rsp['initiator_login'], 'auth_password': export_params['chap_secret'], } LOG.debug("Attach properties: %(properties)s", {'properties': properties}) return { 'driver_volume_type': 'iscsi', 'data': properties, }
def initialize_connection(self, volume, connector, **kwargs): """Attach volume to initiator/host. Creates a profile for the initiator, and adds the new profile to the target ACL. """ # generate a CHAP secret here -- there is no way to retrieve an # existing CHAP secret over the Blockbridge API, so it must be # supplied by the volume driver. export_params = { 'chap_user': ( kwargs.get('user', volume_utils.generate_username(16))), 'chap_secret': ( kwargs.get('password', volume_utils.generate_password(32))), } LOG.debug("Configuring export for %(initiator)s", connector, resource=volume) rsp = self._create_export(volume['id'], connector['initiator'], export_params, user_id=volume['user_id'], project_id=volume['project_id']) # combine locally generated chap credentials with target iqn/lun to # present the attach properties. target_portal = "%s:%s" % (rsp['target_ip'], rsp['target_port']) properties = { 'target_discovered': False, 'target_portal': target_portal, 'target_iqn': rsp['target_iqn'], 'target_lun': rsp['target_lun'], 'volume_id': volume['id'], 'auth_method': 'CHAP', 'auth_username': rsp['initiator_login'], 'auth_password': export_params['chap_secret'], } LOG.debug("Attach properties: %(properties)s", {'properties': properties}) return { 'driver_volume_type': 'iscsi', 'data': properties, }
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" # 'iscsi_name': 'iqn.2010-10.org.openstack:volume-00000001' iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) # Verify we haven't setup a CHAP creds file already # if DNE no big deal, we'll just create it chap_auth = self._get_target_chap_auth(context, volume) if not chap_auth: auth = volume['provider_auth'] if auth: (auth_method, auth_username, auth_secret) = auth.split() if auth_method == 'CHAP': chap_auth = (auth_username, auth_secret) else: LOG.error("Failed create_export. " "Invalid auth_method: %(a)s for volume: %(v)s", {"a": auth_method, "v": volume['id']}) return else: chap_auth = (vutils.generate_username(), vutils.generate_password()) # Get portals ips and port portals_config = self._get_portals_config() # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future LOG.info(("Creating volume export for %(uuid)s target:%(target)s " "lun:%(lun)s path:%(volume_path)s"), {"uuid": volume['id'], "target": iscsi_target, "lun": lun, "volume_path": volume_path}) tid = self.create_iscsi_target(iscsi_name, iscsi_target, lun, volume_path, chap_auth, **portals_config) LOG.info("Volume export for %s created", volume['id']) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun, self.configuration.iscsi_secondary_ip_addresses) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', *chap_auth) return data
def _target_create(self, identifier): if not identifier: err = _('Param [identifier] is invalid.') raise exception.InvalidParameterValue(err=err) # 0 for no auth, 1 for single chap, 2 for mutual chap auth_type = 0 chap_username = '' chap_password = '' provider_auth = '' if self.config.safe_get('use_chap_auth') and self.config.use_chap_auth: auth_type = 1 chap_username = (self.config.safe_get('chap_username') or volutils.generate_username(12)) chap_password = (self.config.safe_get('chap_password') or volutils.generate_password()) provider_auth = ' '.join(('CHAP', chap_username, chap_password)) trg_prefix = self.config.safe_get('iscsi_target_prefix') trg_name = (self.TARGET_NAME_PREFIX + '%s') % identifier iqn = trg_prefix + trg_name try: out = self.exec_webapi('SYNO.Core.ISCSI.Target', 'create', 1, name=trg_name, iqn=iqn, auth_type=auth_type, user=chap_username, password=chap_password, max_sessions=0) self.check_response(out) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE('Failed to _target_create. [%s]'), identifier) if not self.check_value_valid(out, ['data', 'target_id']): msg = _('Failed to get target_id of target [%s]') % trg_name raise exception.VolumeDriverException(message=msg) trg_id = out['data']['target_id'] return iqn, trg_id, provider_auth
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) chap_username = vutils.generate_username() chap_password = vutils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.create_iscsi_target(iscsi_name, iscsi_target, 0, volume_path, chap_auth) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication('CHAP', chap_username, chap_password) return data
def _initialize_connection_iscsi(self, volume, connector): volume_name = self._make_volume_name(volume) infinidat_volume = self._get_infinidat_volume_by_name(volume_name) port = iqn.IQN(connector['initiator']) infinidat_host = self._get_or_create_host(port) if self.configuration.use_chap_auth: chap_username = (self.configuration.chap_username or vol_utils.generate_username()) chap_password = (self.configuration.chap_password or vol_utils.generate_password()) infinidat_host.update_fields( security_method='CHAP', security_chap_inbound_username=chap_username, security_chap_inbound_secret=chap_password) mapping = self._get_or_create_mapping(infinidat_host, infinidat_volume) lun = mapping.get_lun() netspace_names = self.configuration.infinidat_iscsi_netspaces target_portals = [] target_iqns = [] target_luns = [] for netspace_name in netspace_names: netspace = self._get_iscsi_network_space(netspace_name) target_portals.append(self._get_iscsi_portal(netspace)) target_iqns.append(netspace.get_properties().iscsi_iqn) target_luns.append(lun) result_data = dict(target_discovered=True, target_portal=target_portals[0], target_iqn=target_iqns[0], target_lun=target_luns[0]) if len(target_portals) > 1: # multiple network spaces defined result_data.update( dict(target_portals=target_portals, target_iqns=target_iqns, target_luns=target_luns)) if self.configuration.use_chap_auth: result_data.update( dict(auth_method='CHAP', auth_username=chap_username, auth_password=chap_password)) return dict(driver_volume_type='iscsi', data=result_data)
def _initialize_connection_iscsi(self, volume, connector): volume_name = self._make_volume_name(volume) infinidat_volume = self._get_infinidat_volume_by_name(volume_name) port = iqn.IQN(connector['initiator']) infinidat_host = self._get_or_create_host(port) if self.configuration.use_chap_auth: chap_username = (self.configuration.chap_username or vol_utils.generate_username()) chap_password = (self.configuration.chap_password or vol_utils.generate_password()) infinidat_host.update_fields( security_method='CHAP', security_chap_inbound_username=chap_username, security_chap_inbound_secret=chap_password) mapping = self._get_or_create_mapping(infinidat_host, infinidat_volume) lun = mapping.get_lun() netspace_names = self.configuration.infinidat_iscsi_netspaces target_portals = [] target_iqns = [] target_luns = [] for netspace_name in netspace_names: netspace = self._get_iscsi_network_space(netspace_name) target_portals.append(self._get_iscsi_portal(netspace)) target_iqns.append(netspace.get_properties().iscsi_iqn) target_luns.append(lun) result_data = dict(target_discovered=True, target_portal=target_portals[0], target_iqn=target_iqns[0], target_lun=target_luns[0]) if len(target_portals) > 1: # multiple network spaces defined result_data.update(dict(target_portals=target_portals, target_iqns=target_iqns, target_luns=target_luns)) if self.configuration.use_chap_auth: result_data.update(dict(auth_method='CHAP', auth_username=chap_username, auth_password=chap_password)) return dict(driver_volume_type='iscsi', data=result_data)
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_target, lun = self._get_target_and_lun(context, volume) iscsi_name = self._get_iscsi_name(volume) if self.chap_username and self.chap_password: chap_auth = (self.chap_username, self.chap_password) else: chap_auth = self._get_target_chap_auth(context, volume) if not chap_auth: chap_auth = (vutils.generate_username(), vutils.generate_password()) tid = self.create_iscsi_target(iscsi_name, volume['id'], iscsi_target, lun, volume_path, chap_auth) data = {} data['location'] = self._iscsi_location( self.configuration.target_ip_address, tid, iscsi_name, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication('CHAP', *chap_auth) return data
def create_export(self, context, volume, volume_path): """Creates an export for a logical volume.""" iscsi_name = "%s%s" % (self.configuration.iscsi_target_prefix, volume['name']) iscsi_target, lun = self._get_target_and_lun(context, volume) chap_username = vutils.generate_username() chap_password = vutils.generate_password() chap_auth = self._iscsi_authentication('IncomingUser', chap_username, chap_password) # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need # should clean this all up at some point in the future tid = self.create_iscsi_target(iscsi_name, iscsi_target, 0, volume_path, chap_auth) data = {} data['location'] = self._iscsi_location( self.configuration.iscsi_ip_address, tid, iscsi_name, lun) LOG.debug('Set provider_location to: %s', data['location']) data['auth'] = self._iscsi_authentication( 'CHAP', chap_username, chap_password) return data
def _generate_chap_secret(): return volume_utils.generate_password()
def _get_service_target(self, volume): """Get the available service parameters Get the available service parameters for a given volume using its type. :param volume: dictionary volume reference """ hdp = self._get_service(volume) info = _loc_info(volume['provider_location']) (arid, lun_name) = info['id_lu'] evsid = self.bend.get_evs(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], hdp) svc_label = utils.extract_host(volume['host'], level='pool') svc = self.config['services'][svc_label] LOG.info(_LI("_get_service_target hdp: %s."), hdp) LOG.info(_LI("config[services]: %s."), self.config['services']) mapped, lunid, tgt = self.bend.check_lu(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], lun_name, hdp) LOG.info(_LI("Target is %(map)s! Targetlist = %(tgtl)s."), {'map': "mapped" if mapped else "not mapped", 'tgtl': tgt}) # The volume is already mapped to a LUN, so no need to create any # targets if mapped: service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], hdp, tgt['alias'], tgt['secret']) return service # Each EVS can have up to 32 targets. Each target can have up to 32 # LUNs attached and have the name format 'evs<id>-tgt<0-N>'. We run # from the first 'evs1-tgt0' until we find a target that is not already # created in the BE or is created but have slots to place new targets. found_tgt = False for i in range(0, MAX_HNAS_ISCSI_TARGETS): tgt_alias = 'evs' + evsid + '-tgt' + six.text_type(i) # TODO(erlon): we need to go to the BE 32 times here tgt_exist, tgt = self.bend.check_target(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], hdp, tgt_alias) if tgt_exist and len(tgt['luns']) < 32 or not tgt_exist: # Target exists and has free space or, target does not exist # yet. Proceed and use the target or create a target using this # name. found_tgt = True break # If we've got here and found_tgt is not True, we run out of targets, # raise and go away. if not found_tgt: LOG.error(_LE("No more targets avaliable.")) raise exception.NoMoreTargets(param=tgt_alias) LOG.info(_LI("Using target label: %s."), tgt_alias) # Check if we have a secret stored for this target so we don't have to # go to BE on every query if 'targets' not in self.config.keys(): self.config['targets'] = {} if tgt_alias not in self.config['targets'].keys(): self.config['targets'][tgt_alias] = {} tgt_info = self.config['targets'][tgt_alias] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled'] == 'True': # It may not exist, create and set secret. if 'iscsi_secret' not in tgt_info.keys(): LOG.info(_LI("Retrieving secret for service: %s."), tgt_alias) out = self.bend.get_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp) tgt_info['iscsi_secret'] = out if tgt_info['iscsi_secret'] == "": randon_secret = utils.generate_password()[0:15] tgt_info['iscsi_secret'] = randon_secret self.bend.set_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp, tgt_info['iscsi_secret']) LOG.info(_LI("Set tgt CHAP secret for service: %s."), tgt_alias) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exists in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in tgt_info.keys(): # Warns in the first time LOG.info(_LI("CHAP authentication disabled.")) tgt_info['iscsi_secret'] = "" if 'tgt_iqn' not in tgt_info: LOG.info(_LI("Retrieving target for service: %s."), tgt_alias) out = self.bend.get_targetiqn(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp, tgt_info['iscsi_secret']) tgt_info['tgt_iqn'] = out self.config['targets'][tgt_alias] = tgt_info service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], hdp, tgt_alias, tgt_info['iscsi_secret']) return service
def _generate_hex_key(self, **kwargs): key_length = kwargs.get('key_length', 256) # hex digit => 4 bits hex_encoded = utils.generate_password(length=key_length // 4, symbolgroups='0123456789ABCDEF') return hex_encoded
def _get_service_target(self, volume): """Gets the available service parameters Gets the available service parameters for a given volume using its type. :param volume: dictionary volume reference :returns: service target information or raises error :raises: NoMoreTargets """ fs_label = self._get_service(volume) evs_id = self.backend.get_evs(fs_label) svc_label = utils.extract_host(volume.host, level='pool') svc = self.config['services'][svc_label] lu_info = self.backend.check_lu(volume.name, fs_label) # The volume is already mapped to a LU, so no need to create any # targets if lu_info['mapped']: service = (svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'], fs_label, lu_info['tgt']['alias'], lu_info['tgt']['secret']) LOG.info( _LI("Volume %(vol_name)s already mapped on target " "%(tgt)s to LUN %(lunid)s."), { 'vol_name': volume.name, 'tgt': lu_info['tgt']['alias'], 'lunid': lu_info['id'] }) return service # Each EVS can have up to 32 targets. Each target can have up to 32 # LUs attached and have the name format 'evs<id>-tgt<0-N>'. We run # from the first 'evs1-tgt0' until we find a target that is not already # created in the BE or is created but have slots to place new LUs. tgt_alias = '' for i in range(0, MAX_HNAS_ISCSI_TARGETS): tgt_alias = 'evs' + evs_id + '-tgt' + six.text_type(i) tgt = self.backend.check_target(fs_label, tgt_alias) if (tgt['found'] and len(tgt['tgt']['lus']) < MAX_HNAS_LUS_PER_TARGET or not tgt['found']): # Target exists and has free space or, target does not exist # yet. Proceed and use the target or create a target using this # name. break else: # If we've got here, we run out of targets, raise and go away. LOG.error(_LE("No more targets available.")) raise exception.NoMoreTargets(param=tgt_alias) LOG.info(_LI("Using target label: %(tgt)s."), {'tgt': tgt_alias}) # Check if we have a secret stored for this target so we don't have to # go to BE on every query if 'targets' not in self.config.keys(): self.config['targets'] = {} if tgt_alias not in self.config['targets'].keys(): self.config['targets'][tgt_alias] = {} tgt_info = self.config['targets'][tgt_alias] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled']: # CHAP support is enabled. Tries to get the target secret. if 'iscsi_secret' not in tgt_info.keys(): LOG.info(_LI("Retrieving secret for service: %(tgt)s."), {'tgt': tgt_alias}) out = self.backend.get_target_secret(tgt_alias, fs_label) tgt_info['iscsi_secret'] = out # CHAP supported and the target has no secret yet. So, the # secret is created for the target if tgt_info['iscsi_secret'] == "": random_secret = utils.generate_password()[0:15] tgt_info['iscsi_secret'] = random_secret LOG.info(_LI("Set tgt CHAP secret for service: %(tgt)s."), {'tgt': tgt_alias}) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exist in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in tgt_info.keys(): # Warns in the first time LOG.info(_LI("CHAP authentication disabled.")) tgt_info['iscsi_secret'] = "''" # If the target does not exist, it should be created if not tgt['found']: self.backend.create_target(tgt_alias, fs_label, tgt_info['iscsi_secret']) elif (tgt['tgt']['secret'] == "" and self.config['chap_enabled']): # The target exists, has no secret and chap is enabled self.backend.set_target_secret(tgt_alias, fs_label, tgt_info['iscsi_secret']) if 'tgt_iqn' not in tgt_info: LOG.info(_LI("Retrieving IQN for service: %(tgt)s."), {'tgt': tgt_alias}) out = self.backend.get_target_iqn(tgt_alias, fs_label) tgt_info['tgt_iqn'] = out self.config['targets'][tgt_alias] = tgt_info service = (svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'], fs_label, tgt_alias, tgt_info['iscsi_secret']) return service
def add_chap_secret_to_host(self, host_name): """Generate and store a randomly-generated CHAP secret for the host.""" chap_secret = utils.generate_password() self.ssh.add_chap_secret(chap_secret, host_name) return chap_secret
def _do_export(self, common, volume): """Gets the associated account, generates CHAP info and updates.""" model_update = {} if not common._client_conf['hpe3par_iscsi_chap_enabled']: model_update['provider_auth'] = None return model_update # CHAP username will be the hostname chap_username = volume['host'].split('@')[0] chap_password = None try: # Get all active VLUNs for the host vluns = common.client.getHostVLUNs(chap_username) # Host has active VLUNs... is CHAP enabled on host? host_info = common.client.getHost(chap_username) if not host_info['initiatorChapEnabled']: LOG.warning("Host has no CHAP key, but CHAP is enabled.") except hpeexceptions.HTTPNotFound: chap_password = volume_utils.generate_password(16) LOG.warning("No host or VLUNs exist. Generating new " "CHAP key.") else: # Get a list of all iSCSI VLUNs and see if there is already a CHAP # key assigned to one of them. Use that CHAP key if present, # otherwise create a new one. Skip any VLUNs that are missing # CHAP credentials in metadata. chap_exists = False active_vluns = 0 for vlun in vluns: if not vlun['active']: continue active_vluns += 1 # iSCSI connections start with 'iqn'. if ('remoteName' in vlun and re.match('iqn.*', vlun['remoteName'])): try: chap_password = common.client.getVolumeMetaData( vlun['volumeName'], CHAP_PASS_KEY)['value'] chap_exists = True break except hpeexceptions.HTTPNotFound: LOG.debug( "The VLUN %s is missing CHAP credentials " "but CHAP is enabled. Skipping.", vlun['remoteName']) else: LOG.warning("Non-iSCSI VLUN detected.") if not chap_exists: chap_password = volume_utils.generate_password(16) LOG.warning("No VLUN contained CHAP credentials. " "Generating new CHAP key.") # Add CHAP credentials to the volume metadata vol_name = common._get_3par_vol_name(volume['id']) common.client.setVolumeMetaData(vol_name, CHAP_USER_KEY, chap_username) common.client.setVolumeMetaData(vol_name, CHAP_PASS_KEY, chap_password) model_update['provider_auth'] = ('CHAP %s %s' % (chap_username, chap_password)) return model_update
def _get_service_target(self, volume): """Get the available service parameters Get the available service parameters for a given volume using its type. :param volume: dictionary volume reference """ hdp = self._get_service(volume) info = _loc_info(volume['provider_location']) (arid, lun_name) = info['id_lu'] evsid = self.bend.get_evs(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], hdp) svc_label = utils.extract_host(volume['host'], level='pool') svc = self.config['services'][svc_label] LOG.info(_LI("_get_service_target hdp: %s."), hdp) LOG.info(_LI("config[services]: %s."), self.config['services']) mapped, lunid, tgt = self.bend.check_lu(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], lun_name, hdp) LOG.info(_LI("Target is %(map)s! Targetlist = %(tgtl)s."), { 'map': "mapped" if mapped else "not mapped", 'tgtl': tgt }) # The volume is already mapped to a LUN, so no need to create any # targets if mapped: service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], hdp, tgt['alias'], tgt['secret']) return service # Each EVS can have up to 32 targets. Each target can have up to 32 # LUNs attached and have the name format 'evs<id>-tgt<0-N>'. We run # from the first 'evs1-tgt0' until we find a target that is not already # created in the BE or is created but have slots to place new targets. found_tgt = False for i in range(0, MAX_HNAS_ISCSI_TARGETS): tgt_alias = 'evs' + evsid + '-tgt' + six.text_type(i) # TODO(erlon): we need to go to the BE 32 times here tgt_exist, tgt = self.bend.check_target(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], hdp, tgt_alias) if tgt_exist and len(tgt['luns']) < 32 or not tgt_exist: # Target exists and has free space or, target does not exist # yet. Proceed and use the target or create a target using this # name. found_tgt = True break # If we've got here and found_tgt is not True, we run out of targets, # raise and go away. if not found_tgt: LOG.error(_LE("No more targets avaliable.")) raise exception.NoMoreTargets(param=tgt_alias) LOG.info(_LI("Using target label: %s."), tgt_alias) # Check if we have a secret stored for this target so we don't have to # go to BE on every query if 'targets' not in self.config.keys(): self.config['targets'] = {} if tgt_alias not in self.config['targets'].keys(): self.config['targets'][tgt_alias] = {} tgt_info = self.config['targets'][tgt_alias] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled'] == 'True': # It may not exist, create and set secret. if 'iscsi_secret' not in tgt_info.keys(): LOG.info(_LI("Retrieving secret for service: %s."), tgt_alias) out = self.bend.get_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp) tgt_info['iscsi_secret'] = out if tgt_info['iscsi_secret'] == "": randon_secret = utils.generate_password()[0:15] tgt_info['iscsi_secret'] = randon_secret self.bend.set_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp, tgt_info['iscsi_secret']) LOG.info(_LI("Set tgt CHAP secret for service: %s."), tgt_alias) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exists in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in tgt_info.keys(): # Warns in the first time LOG.info(_LI("CHAP authentication disabled.")) tgt_info['iscsi_secret'] = "" if 'tgt_iqn' not in tgt_info: LOG.info(_LI("Retrieving target for service: %s."), tgt_alias) out = self.bend.get_targetiqn(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp, tgt_info['iscsi_secret']) tgt_info['tgt_iqn'] = out self.config['targets'][tgt_alias] = tgt_info service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], hdp, tgt_alias, tgt_info['iscsi_secret']) return service
def _get_service_target(self, volume): """Gets the available service parameters Gets the available service parameters for a given volume using its type. :param volume: dictionary volume reference :returns: service target information or raises error :raises: NoMoreTargets """ fs_label = self._get_service(volume) evs_id = self.backend.get_evs(fs_label) svc_label = utils.extract_host(volume.host, level='pool') svc = self.config['services'][svc_label] lu_info = self.backend.check_lu(volume.name, fs_label) # The volume is already mapped to a LU, so no need to create any # targets if lu_info['mapped']: service = ( svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'], fs_label, lu_info['tgt']['alias'], lu_info['tgt']['secret']) return service # Each EVS can have up to 32 targets. Each target can have up to 32 # LUs attached and have the name format 'evs<id>-tgt<0-N>'. We run # from the first 'evs1-tgt0' until we find a target that is not already # created in the BE or is created but have slots to place new LUs. tgt_alias = '' for i in range(0, MAX_HNAS_ISCSI_TARGETS): tgt_alias = 'evs' + evs_id + '-tgt' + six.text_type(i) tgt = self.backend.check_target(fs_label, tgt_alias) if (tgt['found'] and len(tgt['tgt']['lus']) < MAX_HNAS_LUS_PER_TARGET or not tgt['found']): # Target exists and has free space or, target does not exist # yet. Proceed and use the target or create a target using this # name. break else: # If we've got here, we run out of targets, raise and go away. LOG.error(_LE("No more targets available.")) raise exception.NoMoreTargets(param=tgt_alias) LOG.info(_LI("Using target label: %(tgt)s."), {'tgt': tgt_alias}) # Check if we have a secret stored for this target so we don't have to # go to BE on every query if 'targets' not in self.config.keys(): self.config['targets'] = {} if tgt_alias not in self.config['targets'].keys(): self.config['targets'][tgt_alias] = {} tgt_info = self.config['targets'][tgt_alias] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled']: # CHAP support is enabled. Tries to get the target secret. if 'iscsi_secret' not in tgt_info.keys(): LOG.info(_LI("Retrieving secret for service: %(tgt)s."), {'tgt': tgt_alias}) out = self.backend.get_target_secret(tgt_alias, fs_label) tgt_info['iscsi_secret'] = out # CHAP supported and the target has no secret yet. So, the # secret is created for the target if tgt_info['iscsi_secret'] == "": random_secret = utils.generate_password()[0:15] tgt_info['iscsi_secret'] = random_secret LOG.info(_LI("Set tgt CHAP secret for service: %(tgt)s."), {'tgt': tgt_alias}) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exist in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in tgt_info.keys(): # Warns in the first time LOG.info(_LI("CHAP authentication disabled.")) tgt_info['iscsi_secret'] = "''" # If the target does not exist, it should be created if not tgt['found']: self.backend.create_target(tgt_alias, fs_label, tgt_info['iscsi_secret']) elif (tgt['tgt']['secret'] == "" and self.config['chap_enabled']): # The target exists, has no secret and chap is enabled self.backend.set_target_secret(tgt_alias, fs_label, tgt_info['iscsi_secret']) if 'tgt_iqn' not in tgt_info: LOG.info(_LI("Retrieving IQN for service: %(tgt)s."), {'tgt': tgt_alias}) out = self.backend.get_target_iqn(tgt_alias, fs_label) tgt_info['tgt_iqn'] = out self.config['targets'][tgt_alias] = tgt_info service = (svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'], fs_label, tgt_alias, tgt_info['iscsi_secret']) return service
def _do_export(self, common, volume): """Gets the associated account, generates CHAP info and updates.""" model_update = {} if not self.configuration.hp3par_iscsi_chap_enabled: model_update['provider_auth'] = None return model_update # CHAP username will be the hostname chap_username = volume['host'].split('@')[0] chap_password = None try: # Get all active VLUNs for the host vluns = common.client.getHostVLUNs(chap_username) # Host has active VLUNs... is CHAP enabled on host? host_info = common.client.getHost(chap_username) if not host_info['initiatorChapEnabled']: LOG.warning(_LW("Host has no CHAP key, but CHAP is enabled.")) except hpexceptions.HTTPNotFound: chap_password = volume_utils.generate_password(16) LOG.warning(_LW("No host or VLUNs exist. Generating new " "CHAP key.")) else: # Get a list of all iSCSI VLUNs and see if there is already a CHAP # key assigned to one of them. Use that CHAP key if present, # otherwise create a new one. Skip any VLUNs that are missing # CHAP credentials in metadata. chap_exists = False active_vluns = 0 for vlun in vluns: if not vlun['active']: continue active_vluns += 1 # iSCSI connections start with 'iqn'. if ('remoteName' in vlun and re.match('iqn.*', vlun['remoteName'])): try: chap_password = common.client.getVolumeMetaData( vlun['volumeName'], CHAP_PASS_KEY)['value'] chap_exists = True break except hpexceptions.HTTPNotFound: LOG.debug("The VLUN %s is missing CHAP credentials " "but CHAP is enabled. Skipping.", vlun['remoteName']) else: LOG.warning(_LW("Non-iSCSI VLUN detected.")) if not chap_exists: chap_password = volume_utils.generate_password(16) LOG.warning(_LW("No VLUN contained CHAP credentials. " "Generating new CHAP key.")) # Add CHAP credentials to the volume metadata vol_name = common._get_3par_vol_name(volume['id']) common.client.setVolumeMetaData( vol_name, CHAP_USER_KEY, chap_username) common.client.setVolumeMetaData( vol_name, CHAP_PASS_KEY, chap_password) model_update['provider_auth'] = ('CHAP %s %s' % (chap_username, chap_password)) return model_update
def _get_service(self, volume): """Get available service parameters. Get the available service parameters for a given volume using its type. :param volume: dictionary volume reference """ label = utils.extract_host(volume['host'], level='pool') LOG.info(_LI("Using service label: %s"), label) if label in self.config['services'].keys(): svc = self.config['services'][label] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled'] == 'True': # it may not exist, create and set secret if 'iscsi_secret' not in svc: LOG.info(_LI("Retrieving secret for service: %s"), label) out = self.bend.get_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], 'cinder-' + label, svc['hdp']) svc['iscsi_secret'] = out if svc['iscsi_secret'] == "": svc['iscsi_secret'] = utils.generate_password()[0:15] self.bend.set_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], 'cinder-' + label, svc['hdp'], svc['iscsi_secret']) LOG.info(_LI("Set tgt CHAP secret for service: %s"), label) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exists in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in svc: # Warns in the first time LOG.info(_LI("CHAP authentication disabled")) svc['iscsi_secret'] = "" if 'iscsi_target' not in svc: LOG.info(_LI("Retrieving target for service: %s"), label) out = self.bend.get_targetiqn(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], 'cinder-' + label, svc['hdp'], svc['iscsi_secret']) svc['iscsi_target'] = out self.config['services'][label] = svc service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], svc['hdp'], svc['iscsi_target'], svc['iscsi_secret']) else: LOG.info(_LI("Available services: %s"), self.config['services'].keys()) LOG.error(_LE("No configuration found for service: %s"), label) raise exception.ParameterNotFound(param=label) return service
def _setup_iscsi_chap_authentication(self, targets, initiator): iscsi_chap_enabled = self.configuration.datacore_iscsi_chap_enabled self._check_iscsi_chap_configuration(iscsi_chap_enabled, targets) server_group = self._get_our_server_group() update_access_token = False access_token = None chap_secret = None if iscsi_chap_enabled: authentication = 'CHAP' chap_secret = self._password_storage.get_password( server_group.Id, initiator.PortName) update_access_token = False if not chap_secret: chap_secret = volume_utils.generate_password(length=15) self._password_storage.set_password( server_group.Id, initiator.PortName, chap_secret) update_access_token = True access_token = self._api.build_access_token( initiator.PortName, None, None, False, initiator.PortName, chap_secret) else: authentication = 'None' if self._password_storage: self._password_storage.delete_password(server_group.Id, initiator.PortName) changed_targets = {} try: for target in targets: if iscsi_chap_enabled: target_iscsi_nodes = getattr(target.iSCSINodes, 'Node', []) iscsi_node = datacore_utils.get_first_or_default( lambda node: node.Name == initiator.PortName, target_iscsi_nodes, None) if (not iscsi_node or not iscsi_node.AccessToken.TargetUsername or update_access_token): self._api.set_access_token(target.Id, access_token) properties = target.ServerPortProperties if properties.Authentication != authentication: changed_targets[target] = properties.Authentication properties.Authentication = authentication self._api.set_server_port_properties( target.Id, properties) except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Configuring of iSCSI CHAP authentication for " "initiator %(initiator)s failed.", {'initiator': initiator.PortName}) try: for target in changed_targets: properties = target.ServerPortProperties properties.Authentication = changed_targets[target] self._api.set_server_port_properties( target.Id, properties) except datacore_exception.DataCoreException as e: LOG.warning("An error occurred on a cleanup after failed " "configuration of iSCSI CHAP authentication " "on initiator %(initiator)s: %(error)s.", {'initiator': initiator.PortName, 'error': e}) if iscsi_chap_enabled: return initiator.PortName, chap_secret