def _verify_configuration(self): allowed_driver_methods = [m for m in dir(self) if m[0] != '_'] allowed_driver_methods.extend([ "_setup_server", "_teardown_server", "_get_pools_info", "_update_share_stats", ]) disallowed_driver_methods = ( "get_admin_network_allocations_number", "get_network_allocations_number", "get_share_server_pools", ) for k, v in self.configuration.safe_get( "dummy_driver_driver_methods_delays").items(): if k not in allowed_driver_methods: raise exception.BadConfigurationException( reason=("Dummy driver does not have '%s' method." % k)) elif k in disallowed_driver_methods: raise exception.BadConfigurationException( reason=("Method '%s' does not support delaying." % k)) try: float(v) except (TypeError, ValueError): raise exception.BadConfigurationException(reason=( "Wrong value (%(v)s) for '%(k)s' dummy driver method time " "delay is set in 'dummy_driver_driver_methods_delays' " "config option." % { "k": k, "v": v }))
def __init__(self, *args, **kwargs): """Do initialization.""" LOG.debug('Initializing Nexenta driver.') super(NexentaNasDriver, self).__init__((True, False), *args, **kwargs) self.configuration = kwargs.get('configuration') if self.configuration: self.configuration.append_config_values( options.nexenta_connection_opts) self.configuration.append_config_values(options.nexenta_nfs_opts) self.configuration.append_config_values( options.nexenta_dataset_opts) else: raise exception.BadConfigurationException( reason=_('Nexenta configuration missing.')) required_params = ['nas_host', 'user', 'password', 'pool', 'folder'] for param in required_params: if not getattr(self.configuration, 'nexenta_%s' % param): msg = 'Required parameter nexenta_%s is not provided.' % param raise exception.NexentaException(msg) self.nef = None self.verify_ssl = self.configuration.nexenta_ssl_cert_verify self.nef_host = self.configuration.nexenta_rest_address self.nas_host = self.configuration.nexenta_nas_host self.nef_port = self.configuration.nexenta_rest_port self.nef_user = self.configuration.nexenta_user self.nef_password = self.configuration.nexenta_password self.pool_name = self.configuration.nexenta_pool self.parent_fs = self.configuration.nexenta_folder self.nfs_mount_point_base = self.configuration.nexenta_mount_point_base self.dataset_compression = ( self.configuration.nexenta_dataset_compression) self.provisioned_capacity = 0
def get_backend_configuration(backend_name): config_stanzas = CONF.list_all_sections() if backend_name not in config_stanzas: msg = _("Could not find backend stanza %(backend_name)s in " "configuration which is required for replication or migration " "workflows with the source backend. Available stanzas are " "%(stanzas)s") params = { "stanzas": config_stanzas, "backend_name": backend_name, } raise exception.BadConfigurationException(reason=msg % params) config = configuration.Configuration(driver.share_opts, config_group=backend_name) if config.driver_handles_share_servers: # NOTE(dviroel): avoid using a pre-create vserver on DHSS == True mode # when retrieving remote backend configuration. config.netapp_vserver = None config.append_config_values(na_opts.netapp_cluster_opts) config.append_config_values(na_opts.netapp_connection_opts) config.append_config_values(na_opts.netapp_basicauth_opts) config.append_config_values(na_opts.netapp_transport_opts) config.append_config_values(na_opts.netapp_support_opts) config.append_config_values(na_opts.netapp_provisioning_opts) config.append_config_values(na_opts.netapp_data_motion_opts) return config
def _get_managed_ports(self, port_conf, sp): # Get the real ports from the backend storage real_ports = set([port.id for port in self.client.get_ip_ports(sp)]) if not port_conf: LOG.debug("No ports are specified, so all ports in storage " "system will be managed.") return real_ports matched_ports, unmanaged_ports = unity_utils.do_match( real_ports, port_conf) if not matched_ports: msg = (_("All the specified storage ports to be managed " "do not exist. Please check your configuration " "emc_interface_ports in manila.conf. " "The available ports in the backend are %s") % ",".join(real_ports)) raise exception.BadConfigurationException(reason=msg) if unmanaged_ports: LOG.info( _LI("The following specified ports " "are not managed by the backend: " "%(un_managed)s. This host will only manage " "the storage ports: %(exist)s"), { 'un_managed': ",".join(unmanaged_ports), 'exist': ",".join(matched_ports) }) else: LOG.debug("Ports: %s will be managed.", ",".join(matched_ports)) return matched_ports
def _get_managed_pools(self, pool_conf): # Get the real pools from the backend storage real_pools = set(pool.name for pool in self.client.get_pool()) if not pool_conf: LOG.debug("No storage pool is specified, so all pools in storage " "system will be managed.") return real_pools matched_pools, unmanaged_pools = unity_utils.do_match( real_pools, pool_conf) if not matched_pools: msg = (_("All the specified storage pools to be managed " "do not exist. Please check your configuration " "emc_nas_pool_names in manila.conf. " "The available pools in the backend are %s") % ",".join(real_pools)) raise exception.BadConfigurationException(reason=msg) if unmanaged_pools: LOG.info( "The following specified storage pools " "are not managed by the backend: " "%(un_managed)s. This host will only manage " "the storage pools: %(exist)s", { 'un_managed': ",".join(unmanaged_pools), 'exist': ",".join(matched_pools) }) else: LOG.debug("Storage pools: %s will be managed.", ",".join(matched_pools)) return matched_pools
def connect(self, emc_share_driver, context): """Connect to Unity storage.""" config = emc_share_driver.configuration storage_ip = enas_utils.convert_ipv6_format_if_needed( config.emc_nas_server) username = config.emc_nas_login password = config.emc_nas_password self.client = client.UnityClient(storage_ip, username, password) pool_conf = config.safe_get('unity_share_data_pools') self.pool_set = self._get_managed_pools(pool_conf) self.reserved_percentage = config.safe_get('reserved_share_percentage') if self.reserved_percentage is None: self.reserved_percentage = 0 self.max_over_subscription_ratio = config.safe_get( 'max_over_subscription_ratio') self.port_ids_conf = config.safe_get('unity_ethernet_ports') self.unity_share_server = config.safe_get('unity_share_server') self.driver_handles_share_servers = config.safe_get( 'driver_handles_share_servers') if (not self.driver_handles_share_servers) and ( not self.unity_share_server): msg = ("Make sure there is NAS server name " "configured for share creation when driver " "is in DHSS=False mode.") raise exception.BadConfigurationException(reason=msg) self.validate_port_configuration(self.port_ids_conf) pool_name = config.unity_server_meta_pool self._config_pool(pool_name)
def validate_port_configuration(self, port_ids_conf): """Initializes the SP and ports based on the port option.""" ports = self.client.get_file_ports() sp_ports_map, unmanaged_port_ids = unity_utils.match_ports( ports, port_ids_conf) if not sp_ports_map: msg = (_("All the specified storage ports to be managed " "do not exist. Please check your configuration " "unity_ethernet_ports in manila.conf. " "The available ports in the backend are %s.") % ",".join([port.get_id() for port in ports])) raise exception.BadConfigurationException(reason=msg) if unmanaged_port_ids: LOG.info( "The following specified ports are not managed by " "the backend: %(unmanaged)s. This host will only " "manage the storage ports: %(exist)s", { 'unmanaged': ",".join(unmanaged_port_ids), 'exist': ",".join(map(",".join, sp_ports_map.values())) }) else: LOG.debug("Ports: %s will be managed.", ",".join(map(",".join, sp_ports_map.values()))) if len(sp_ports_map) == 1: LOG.info( "Only ports of %s are configured. Configure ports " "of both SPA and SPB to use both of the SPs.", list(sp_ports_map)[0]) return sp_ports_map
def __init__(self, *args, **kwargs): """Do initialization.""" LOG.debug('Initializing Nexenta driver.') super(NexentaNasDriver, self).__init__(False, *args, **kwargs) self.configuration = kwargs.get('configuration') if self.configuration: self.configuration.append_config_values( options.nexenta_connection_opts) self.configuration.append_config_values( options.nexenta_nfs_opts) self.configuration.append_config_values( options.nexenta_dataset_opts) else: raise exception.BadConfigurationException( reason=_('Nexenta configuration missing.')) self.nef = None self.nef_protocol = self.configuration.nexenta_rest_protocol self.nef_host = self.configuration.nexenta_host self.nef_port = self.configuration.nexenta_rest_port self.nef_user = self.configuration.nexenta_user self.nef_password = self.configuration.nexenta_password self.pool_name = self.configuration.nexenta_pool self.fs_prefix = self.configuration.nexenta_nfs_share self.storage_protocol = 'NFS' self.nfs_mount_point_base = self.configuration.nexenta_mount_point_base self.dataset_compression = ( self.configuration.nexenta_dataset_compression) self.provisioned_capacity = 0
def _nas_product(self, xml_root): text = xml_root.findtext('Storage/Product') if not text: msg = _("Storage product is not configured.") LOG.error(msg) raise exception.BadConfigurationException(reason=msg) if text not in constants.VALID_PRODUCTS: msg = _("Invalid storage product %(text)s, must be " "in %(valid)s." ) % {'text': text, 'valid': constants.VALID_PRODUCTS} LOG.error(msg) raise exception.BadConfigurationException(reason=msg) setattr(self.config, 'nas_product', text)
def _config_pool(self, pool_name): try: self.nas_server_pool = self.client.get_pool(pool_name) except storops_ex.UnityResourceNotFoundError: message = (_("The storage pools %s to store NAS server " "configuration do not exist.") % pool_name) LOG.exception(message) raise exception.BadConfigurationException(reason=message)
def _nas_user(self, xml_root): text = xml_root.findtext('Storage/UserName') if not text: msg = _("UserName is not configured.") LOG.error(msg) raise exception.BadConfigurationException(reason=msg) setattr(self.config, 'nas_user', text.strip())
def _safe_get_from_config_or_fail(self, config_parameter): config_value = self.configuration.safe_get(config_parameter) if not config_value: # None or empty string reason = (_("%(config_parameter)s configuration parameter " "must be specified") % {'config_parameter': config_parameter}) LOG.error(reason) raise exception.BadConfigurationException(reason=reason) return config_value
def _config_sp(self, sp_name): self.storage_processor = self.client.get_storage_processor( sp_name.lower()) if self.storage_processor is None: message = (_LE("The storage processor %s does not exist or " "is unavailable. Please reconfigure it in " "manila.conf.") % sp_name) LOG.error(message) raise exception.BadConfigurationException(reason=message)
def _nas_address(self, xml_root): text = xml_root.findtext('Storage/RestURL') if not text: msg = _("RestURL is not configured.") LOG.error(msg) raise exception.BadConfigurationException(reason=msg) addrs = set([x.strip() for x in text.split(';') if x.strip()]) setattr(self.config, 'nas_address', list(addrs))
def _storage_pools(self, xml_root): text = xml_root.findtext('Filesystem/StoragePool') if not text: msg = _('StoragePool must be configured.') LOG.error(msg) raise exception.BadConfigurationException(reason=msg) pools = set() for pool in text.split(';'): if pool.strip(): pools.add(pool.strip()) if not pools: msg = _('No valid storage pool configured.') LOG.error(msg) raise exception.BadConfigurationException(reason=msg) setattr(self.config, 'storage_pools', list(pools))
def _safe_get_from_config_or_fail(self, config_parameter): config_value = self.configuration.safe_get(config_parameter) if not config_value: reason = _("%(config_parameter)s configuration parameter " "must be specified") % { "config_parameter": config_parameter } LOG.exception(reason) raise exception.BadConfigurationException(reason=reason) return config_value
def _load_auth_plugin(self): if self.admin_auth: return self.admin_auth self.auth_plugin = ks_loading.load_auth_from_conf_options( CONF, self.group) if self.auth_plugin: return self.auth_plugin msg = _('Cannot load auth plugin for %s') % self.group raise exception.BadConfigurationException(reason=msg)
def get_share(self, name, share_proto): # Validate the share protocol proto = share_proto.upper() if proto == 'CIFS': return self.system.get_cifs_share(name=name) elif proto == 'NFS': return self.system.get_nfs_share(name=name) else: raise exception.BadConfigurationException( reason=_('Invalid NAS protocol supplied: %s.') % share_proto)
def _timeout(self, xml_root): timeout = constants.DEFAULT_TIMEOUT text = xml_root.findtext('Filesystem/Timeout') if text: timeout = int(text.strip()) if timeout <= 0: msg = _("Invalid Timeout config %s, must be " "a positive digit.") % text LOG.error(msg) raise exception.BadConfigurationException(reason=msg) setattr(self.config, 'timeout', timeout)
def _wait_interval(self, xml_root): interval = constants.DEFAULT_WAIT_INTERVAL text = xml_root.findtext('Filesystem/WaitInterval') if text: interval = int(text.strip()) if interval <= 0: msg = _("Invalid WaitInterval config %s, " "must be a positive digit.") % text LOG.error(msg) raise exception.BadConfigurationException(reason=msg) setattr(self.config, 'wait_interval', interval)
def __init__(self, *args, **kwargs): """Do initialization.""" LOG.debug('Initializing Nexenta driver.') super(NexentaNasDriver, self).__init__(False, *args, **kwargs) self.configuration = kwargs.get('configuration') if self.configuration: self.configuration.append_config_values( options.nexenta_connection_opts) self.configuration.append_config_values(options.nexenta_nfs_opts) self.configuration.append_config_values( options.nexenta_dataset_opts) self.helper = nexenta_nfs_helper.NFSHelper(self.configuration) else: raise exception.BadConfigurationException( reason=_('Nexenta configuration missing.'))
def __init__(self, *args, **kwargs): super(CephFSDriver, self).__init__(False, *args, **kwargs) self.backend_name = self.configuration.safe_get( 'share_backend_name') or 'CephFS' self._volume_client = None self.configuration.append_config_values(cephfs_opts) try: self._cephfs_volume_mode = int( self.configuration.cephfs_volume_mode, 8) except ValueError: msg = _("Invalid CephFS volume mode %s") raise exception.BadConfigurationException( msg % self.configuration.cephfs_volume_mode)
def get_backend_configuration(backend_name): config_stanzas = CONF.list_all_sections() if backend_name not in config_stanzas: msg = _("Could not find backend stanza %(backend_name)s in " "configuration which is required for share replication and " "migration. Available stanzas are %(stanzas)s") params = { "stanzas": config_stanzas, "backend_name": backend_name, } raise exception.BadConfigurationException(reason=msg % params) config = configuration.Configuration(driver.share_opts, config_group=backend_name) config.append_config_values(dummy_opts) config.append_config_values(share_manager_opts) config.append_config_values(driver.ssh_opts) return config
def setup_tracing(trace_flags_string, api_trace_pattern=API_TRACE_PATTERN): global TRACE_METHOD global TRACE_API global API_TRACE_PATTERN TRACE_METHOD = False TRACE_API = False API_TRACE_PATTERN = api_trace_pattern if trace_flags_string: flags = trace_flags_string.split(',') flags = [flag.strip() for flag in flags] for invalid_flag in list(set(flags) - set(VALID_TRACE_FLAGS)): LOG.warning('Invalid trace flag: %s', invalid_flag) try: re.compile(api_trace_pattern) except re.error: msg = _('Cannot parse the API trace pattern. %s is not a ' 'valid python regular expression.') % api_trace_pattern raise exception.BadConfigurationException(reason=msg) TRACE_METHOD = 'method' in flags TRACE_API = 'api' in flags
def get_managed_ports(self): # Get the real ports(devices) list from the backend storage real_ports = self._get_physical_devices(self.mover_name) if not self.port_conf: LOG.debug("No ports are specified, so any of the ports on the " "Data Mover can be used.") return real_ports matched_ports, unmanaged_ports = vnx_utils.do_match_any( real_ports, self.port_conf) if not matched_ports: msg = (_("None of the specified network ports exist. " "Please check your configuration vnx_ethernet_ports " "in manila.conf. The available ports on the Data Mover " "are %s.") % ",".join(real_ports)) raise exception.BadConfigurationException(reason=msg) LOG.debug("Ports: %s can be used.", ",".join(matched_ports)) return list(matched_ports)
def __init__(self, *args, **kwargs): super(CephFSDriver, self).__init__(False, *args, **kwargs) self.backend_name = self.configuration.safe_get( 'share_backend_name') or 'CephFS' setup_rados() setup_json_command() self._rados_client = None # name of the filesystem/volume used by the driver self._volname = None self._ceph_mon_version = None self.configuration.append_config_values(cephfs_opts) try: int(self.configuration.cephfs_volume_mode, 8) except ValueError: msg = _("Invalid CephFS volume mode %s") raise exception.BadConfigurationException( msg % self.configuration.cephfs_volume_mode) self._cephfs_volume_mode = self.configuration.cephfs_volume_mode self.ipv6_implemented = True
def get_backend_configuration(backend_name): config_stanzas = CONF.list_all_sections() if backend_name not in config_stanzas: msg = _("Could not find backend stanza %(backend_name)s in " "configuration which is required for replication with " "the backend. Available stanzas are %(stanzas)s") params = { "stanzas": config_stanzas, "backend_name": backend_name, } raise exception.BadConfigurationException(reason=msg % params) config = configuration.Configuration(driver.share_opts, config_group=backend_name) config.append_config_values(na_opts.netapp_cluster_opts) config.append_config_values(na_opts.netapp_connection_opts) config.append_config_values(na_opts.netapp_basicauth_opts) config.append_config_values(na_opts.netapp_transport_opts) config.append_config_values(na_opts.netapp_support_opts) config.append_config_values(na_opts.netapp_provisioning_opts) config.append_config_values(na_opts.netapp_replication_opts) return config
def manage_existing(self, share, driver_options, share_server=None): """Manages a share that exists on backend. :param share: Share that will be managed. :param driver_options: Driver-specific options provided by admin. :param share_server: Share server name provided by admin in DHSS=True. :returns: Returns a dict with share size and export location. """ export_locations = share['export_locations'] if not export_locations: message = ("Failed to manage existing share: %s, missing " "export locations." % share['id']) raise exception.ManageInvalidShare(reason=message) try: share_size = int(driver_options.get("size", 0)) except (ValueError, TypeError): msg = _("The driver options' size to manage the share " "%(share_id)s, should be an integer, in format " "driver-options size=<SIZE>. Value specified: " "%(size)s.") % { 'share_id': share['id'], 'size': driver_options.get("size") } raise exception.ManageInvalidShare(reason=msg) if not share_size: msg = _("Share %(share_id)s has no specified size. " "Using default value 1, set size in driver options if you " "want.") % { 'share_id': share['id'] } LOG.warning(msg) share_size = 1 share_id = unity_utils.get_share_backend_id(share) backend_share = self.client.get_share(share_id, share['share_proto']) if not backend_share: message = ("Could not find the share in backend, please make sure " "the export location is right.") raise exception.ManageInvalidShare(reason=message) # Check the share server when in DHSS=true mode if share_server: backend_share_server = self._get_server_name(share_server) if not backend_share_server: message = ("Could not find the backend share server: %s, " "please make sure that share server with the " "specified name exists in the backend.", share_server) raise exception.BadConfigurationException(message) LOG.info( "Share %(shr_path)s is being managed with ID " "%(shr_id)s.", { 'shr_path': share['export_locations'][0]['path'], 'shr_id': share['id'] }) # export_locations was not changed, return original value return { "size": share_size, 'export_locations': { 'path': share['export_locations'][0]['path'] } }