def _validate_required_options(self, tenant_name, tenant_id, project_name, project_id, token, service_catalog_url, auth_url): if token and not service_catalog_url: raise exc.CommandError( "bypass_url missing: When specifying a token the bypass_url " "must be set via --bypass-url or env[OS_MANILA_BYPASS_URL]") if service_catalog_url and not token: raise exc.CommandError( "Token missing: When specifying a bypass_url a token must be " "set via --os-token or env[OS_TOKEN]") if token and service_catalog_url: return if not (tenant_name or tenant_id or project_name or project_id): raise exc.CommandError( "You must provide a tenant_name, tenant_id, " "project_id or project_name (with " "project_domain_name or project_domain_id) via " "--os-tenant-name or env[OS_TENANT_NAME], " "--os-tenant-id or env[OS_TENANT_ID], " "--os-project-id or env[OS_PROJECT_ID], " "--os-project-name or env[OS_PROJECT_NAME], " "--os-project-domain-id or env[OS_PROJECT_DOMAIN_ID] and " "--os-project-domain-name or env[OS_PROJECT_DOMAIN_NAME]." ) if not auth_url: raise exc.CommandError( "You must provide an auth url " "via either --os-auth-url or env[OS_AUTH_URL]")
def _validate_access(self, access_type, access, valid_access_types=None, enable_ipv6=False): if not valid_access_types: valid_access_types = ('ip', 'user', 'cert') if access_type in valid_access_types: if access_type == 'ip': try: if enable_ipv6: ipaddress.ip_network(str(access)) else: ipaddress.IPv4Network(str(access)) except ValueError as error: raise exceptions.CommandError(str(error)) elif access_type == 'user': self._validate_username(access) elif access_type == 'cert': # 'access' is used as the certificate's CN (common name) # to which access is allowed or denied by the backend. # The standard allows for just about any string in the # common name. The meaning of a string depends on its # interpretation and is limited to 64 characters. self._validate_common_name(access.strip()) elif access_type == 'cephx': self._validate_cephx_id(access.strip()) else: msg = ('Only following access types are supported: %s' % ', '.join(valid_access_types)) raise exceptions.CommandError(msg)
def _validate_required_options(self, os_tenant_name, os_tenant_id, os_project_name, os_project_id, os_auth_url): if not (os_tenant_name or os_tenant_id or os_project_name or os_project_id): raise exc.CommandError( "You must provide a tenant_name, tenant_id, " "project_id or project_name (with " "project_domain_name or project_domain_id) via " "--os-tenant-name (env[OS_TENANT_NAME]), " "--os-tenant-id (env[OS_TENANT_ID]), " "--os-project-id (env[OS_PROJECT_ID]), " "--os-project-name (env[OS_PROJECT_NAME]), " "--os-project-domain-id (env[OS_PROJECT_DOMAIN_ID]) and " "--os-project-domain-name (env[OS_PROJECT_DOMAIN_NAME])." ) if not os_auth_url: raise exc.CommandError( "You must provide an auth url " "via either --os-auth-url or env[OS_AUTH_URL]")
def extract_properties(properties): result_dict = {} for item in properties: try: (key, value) = item.split('=', 1) if key in result_dict: raise exceptions.CommandError( "Argument '%s' is specified twice." % key) else: result_dict[key] = value except ValueError: raise exceptions.CommandError( "Parsing error, expected format 'key=value' for " + item) return result_dict
def _validate_username(access): sole_periods_spaces_re = r'[\s|\.]+$' valid_username_re = r'.[^\"\/\\\[\]\:\;\|\=\,\+\*\?\<\>]{3,254}$' username = access if re.match(sole_periods_spaces_re, username): exc_str = ('Invalid user or group name,cannot consist solely ' 'of periods or spaces.') raise exceptions.CommandError(exc_str) if not re.match(valid_username_re, username): exc_str = ('Invalid user or group name. Must be 4-255 characters ' 'and consist of alphanumeric characters and ' 'exclude special characters "/\\[]:;|=,+*?<>') raise exceptions.CommandError(exc_str)
def _validate_cephx_id(cephx_id): if not cephx_id: raise exceptions.CommandError('Ceph IDs may not be empty.') # This restriction may be lifted in Ceph in the future: # http://tracker.ceph.com/issues/14626 if not set(cephx_id) <= set(string.printable): raise exceptions.CommandError( 'Ceph IDs must consist of ASCII printable characters.') # Periods are technically permitted, but we restrict them here # to avoid confusion where users are unsure whether they should # include the "client." prefix: otherwise they could accidentally # create "client.client.foobar". if '.' in cephx_id: raise exceptions.CommandError('Ceph IDs may not contain periods.')
def _handle_spec_driver_handles_share_servers( self, extra_specs, spec_driver_handles_share_servers): """Validation and default for DHSS extra spec.""" if spec_driver_handles_share_servers is not None: if 'driver_handles_share_servers' in extra_specs: msg = ("'driver_handles_share_servers' is already set via " "positional argument.") raise exceptions.CommandError(msg) else: extra_specs['driver_handles_share_servers'] = ( spec_driver_handles_share_servers) else: msg = ("'driver_handles_share_servers' is not set via " "positional argument.") raise exceptions.CommandError(msg)
def update(self, share_network, neutron_net_id=None, neutron_subnet_id=None, name=None, description=None): """Updates a share network. :param share_network: share network to update. :rtype: :class:`ShareNetwork` """ values = {} if neutron_net_id is not None: values['neutron_net_id'] = neutron_net_id if neutron_subnet_id is not None: values['neutron_subnet_id'] = neutron_subnet_id if name is not None: values['name'] = name if description is not None: values['description'] = description for k, v in values.items(): if v == '': values[k] = None if not values: msg = "Must specify fields to be updated" raise exceptions.CommandError(msg) body = {RESOURCE_NAME: values} return self._update(RESOURCE_PATH % common_base.getid(share_network), body, RESOURCE_NAME)
def _validate_username(access): valid_username_re = '[\w\$\.\-_\`;\'\{\}\[\]\\\\]{4,255}$' username = access if not re.match(valid_username_re, username): exc_str = ('Invalid user or group name. Must be 4-255 characters ' 'and consist of alphanumeric characters and ' 'special characters $]{.-_\'`;}[\\') raise exceptions.CommandError(exc_str)
def extract_extra_specs(extra_specs, specs_to_add): for item in specs_to_add: (key, value) = item.split('=', 1) if key in extra_specs: msg = ("Argument '%s' value specified twice." % key) raise exceptions.CommandError(msg) elif key in constants.BOOL_SPECS: if strutils.is_valid_boolstr(value): extra_specs[key] = value.capitalize() else: msg = ("Argument '%s' is of boolean " "type and has invalid value: %s" % (key, six.text_type(value))) raise exceptions.CommandError(msg) else: extra_specs[key] = value return extra_specs
def _validate_access(self, access_type, access): if access_type == 'ip': self._validate_ip_range(access) elif access_type == 'passwd': self._validate_username(access) else: raise exceptions.CommandError( 'Only ip and passwd type are supported')
def update(self, security_service, dns_ip=None, ou=None, server=None, domain=None, password=None, user=None, name=None, description=None): """Updates a security service. :param security_service: security service to update. :param dns_ip: dns ip address used inside tenant's network :param ou: security service organizational unit :param server: security service server ip address or hostname :param domain: security service domain :param user: security identifier used by tenant :param password: password used by user :param name: security service name :param description: security service description :rtype: :class:`SecurityService` """ values = {} if dns_ip is not None: values['dns_ip'] = dns_ip if ou is not None: values['ou'] = ou if server is not None: values['server'] = server if domain is not None: values['domain'] = domain if user is not None: values['user'] = user if password is not None: values['password'] = password if name is not None: values['name'] = name if description is not None: values['description'] = description for k, v in values.items(): if v == '': values[k] = None if not values: msg = "Must specify fields to be updated" raise exceptions.CommandError(msg) body = {RESOURCE_NAME: values} return self._update( RESOURCE_PATH % common_base.getid(security_service), body, RESOURCE_NAME, )
def _validate_ip_range(ip_range): ip_range = ip_range.split('/') exc_str = ('Supported ip format examples:\n' '\t10.0.0.2, 10.0.0.*, 10.0.0.0/24') if len(ip_range) > 2: raise exceptions.CommandError(exc_str) allow_asterisk = (len(ip_range) == 1) ip_range = ip_range[0].split('.') if len(ip_range) != 4: raise exceptions.CommandError(exc_str) for item in ip_range: try: if 0 <= int(item) <= 255: continue raise ValueError() except ValueError: if not (allow_asterisk and item == '*'): raise exceptions.CommandError(exc_str)
def do_help(self, args): """Display help about this program or one of its subcommands.""" if args.command: if args.command in self.subcommands: self.subcommands[args.command].print_help() else: raise exc.CommandError("'%s' is not a valid subcommand" % args.command) else: self.parser.print_help()
def find_resource(manager, name_or_id): """Helper for the _find_* methods.""" # first try to get entity as integer id try: if isinstance(name_or_id, int) or name_or_id.isdigit(): return manager.get(int(name_or_id)) except exceptions.NotFound: pass # now try to get entity as uuid try: uuid.UUID(strutils.safe_decode(name_or_id)) return manager.get(name_or_id) except (ValueError, exceptions.NotFound): pass try: try: return manager.find(human_id=name_or_id) except exceptions.NotFound: pass # finally try to find entity by name try: return manager.find(name=name_or_id) except exceptions.NotFound: try: return manager.find(display_name=name_or_id) except (UnicodeDecodeError, exceptions.NotFound): try: # Volumes does not have name, but display_name return manager.find(display_name=name_or_id) except exceptions.NotFound: msg = "No %s with a name or ID of '%s' exists." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exceptions.CommandError(msg) except exceptions.NoUniqueMatch: msg = ("Multiple %s matches found for '%s', use an ID to be more" " specific." % (manager.resource_class.__name__.lower(), name_or_id)) raise exceptions.CommandError(msg)
def _handle_spec_snapshot_support(self, extra_specs, spec_snapshot_support, set_default=False): """Validation and default for snapshot extra spec.""" if spec_snapshot_support is not None: if 'snapshot_support' in extra_specs: msg = "'snapshot_support' extra spec is provided twice." raise exceptions.CommandError(msg) else: extra_specs['snapshot_support'] = spec_snapshot_support elif 'snapshot_support' not in extra_specs and set_default: extra_specs['snapshot_support'] = True
def _get_keystone_client(self): # First create a Keystone session if self.insecure: verify = False else: verify = self.cacert or True ks_session = session.Session(verify=verify, cert=self.cert) # Discover the supported keystone versions using the given url ks_discover = discover.Discover(session=ks_session, auth_url=self.auth_url) # Inspect the auth_url to see the supported version. If both v3 and v2 # are supported, then use the highest version if possible. v2_auth_url = ks_discover.url_for('v2.0') v3_auth_url = ks_discover.url_for('v3.0') if v3_auth_url: keystone_client = ks_client.Client( session=ks_session, version=(3, 0), auth_url=v3_auth_url, username=self.username, password=self.password, user_id=self.user_id, user_domain_name=self.user_domain_name, user_domain_id=self.user_domain_id, project_id=self.project_id or self.tenant_id, project_name=self.project_name, project_domain_name=self.project_domain_name, project_domain_id=self.project_domain_id, region_name=self.region_name) elif v2_auth_url: keystone_client = ks_client.Client( session=ks_session, version=(2, 0), auth_url=v2_auth_url, username=self.username, password=self.password, tenant_id=self.tenant_id, tenant_name=self.tenant_name, region_name=self.region_name, cert=self.cert, use_keyring=self.use_keyring, force_new_token=self.force_new_token, stale_duration=self.cached_token_lifetime) else: raise exceptions.CommandError( 'Unable to determine the Keystone version to authenticate ' 'with using the given auth_url.') keystone_client.authenticate() return keystone_client
def extract_extra_specs(extra_specs, specs_to_add, bool_specs=constants.BOOL_SPECS): try: for item in specs_to_add: (key, value) = item.split('=', 1) if key in extra_specs: msg = ("Argument '%s' value specified twice." % key) raise exceptions.CommandError(msg) elif key in bool_specs: if strutils.is_valid_boolstr(value): extra_specs[key] = value.capitalize() else: msg = ("Argument '%s' is of boolean " "type and has invalid value: %s" % (key, str(value))) raise exceptions.CommandError(msg) else: extra_specs[key] = value except ValueError: msg = LOG.error(_("Wrong format: specs should be key=value pairs.")) raise exceptions.CommandError(msg) return extra_specs
def _validate_ip_range(ip_range): ip_range = ip_range.split('/') exc_str = ('Supported ip format examples:\n' '\t10.0.0.2, 10.0.0.0/24') if len(ip_range) > 2: raise exceptions.CommandError(exc_str) if len(ip_range) == 2: try: prefix = int(ip_range[1]) if prefix < 0 or prefix > 32: raise ValueError() except ValueError: msg = 'IP prefix should be in range from 0 to 32' raise exceptions.CommandError(msg) ip_range = ip_range[0].split('.') if len(ip_range) != 4: raise exceptions.CommandError(exc_str) for item in ip_range: try: if 0 <= int(item) <= 255: continue raise ValueError() except ValueError: raise exceptions.CommandError(exc_str)
def _validate_access(self, access_type, access): if access_type == 'ip': self._validate_ip_range(access) elif access_type == 'user': self._validate_username(access) elif access_type == 'cert': # 'access' is used as the certificate's CN (common name) # to which access is allowed or denied by the backend. # The standard allows for just about any string in the # common name. The meaning of a string depends on its # interpretation and is limited to 64 characters. self._validate_common_name(access.strip()) else: raise exceptions.CommandError( 'Only ip, user, and cert types are supported')
def extract_key_value_options(pairs): result_dict = {} duplicate_options = [] pairs = pairs or {} for attr, value in pairs.items(): if attr not in result_dict: result_dict[attr] = value else: duplicate_options.append(attr) if pairs and len(duplicate_options) > 0: duplicate_str = ', '.join(duplicate_options) msg = "Following options were duplicated: %s" % duplicate_str raise exceptions.CommandError(msg) return result_dict
def main(self, argv): # Parse args once to find version and debug settings parser = self.get_base_parser() (options, args) = parser.parse_known_args(argv) self.setup_debugging(options.debug) # build available subcommands based on version self.extensions = self._discover_extensions( options.os_share_api_version) self._run_extension_hooks('__pre_parse_args__') subcommand_parser = self.get_subcommand_parser( options.os_share_api_version) self.parser = subcommand_parser if options.help or not argv: subcommand_parser.print_help() return 0 args = subcommand_parser.parse_args(argv) self._run_extension_hooks('__post_parse_args__', args) # Short-circuit and deal with help right away. if args.func == self.do_help: self.do_help(args) return 0 elif args.func == self.do_bash_completion: self.do_bash_completion(args) return 0 (os_username, os_password, os_tenant_name, os_auth_url, os_region_name, os_tenant_id, endpoint_type, insecure, service_type, service_name, share_service_name, username, apikey, projectid, url, region_name, cacert) = (args.os_username, args.os_password, args.os_tenant_name, args.os_auth_url, args.os_region_name, args.os_tenant_id, args.endpoint_type, args.insecure, args.service_type, args.service_name, args.share_service_name, args.username, args.apikey, args.projectid, args.url, args.region_name, args.os_cacert) if not endpoint_type: endpoint_type = DEFAULT_MANILA_ENDPOINT_TYPE if not service_type: service_type = DEFAULT_MANILA_SERVICE_TYPE service_type = utils.get_service_type(args.func) or service_type #FIXME(usrleon): Here should be restrict for project id same as # for os_username or os_password but for compatibility it is not. if not utils.isunauthenticated(args.func): if not os_username: if not username: raise exc.CommandError( "You must provide a username " "via either --os-username or env[OS_USERNAME]") else: os_username = username if not os_password: if not apikey: raise exc.CommandError("You must provide a password " "via either --os-password or via " "env[OS_PASSWORD]") else: os_password = apikey if not (os_tenant_name or os_tenant_id): if not projectid: raise exc.CommandError("You must provide a tenant_id " "via either --os-tenant-id or " "env[OS_TENANT_ID]") else: os_tenant_name = projectid if not os_auth_url: if not url: raise exc.CommandError( "You must provide an auth url " "via either --os-auth-url or env[OS_AUTH_URL]") else: os_auth_url = url if not os_region_name and region_name: os_region_name = region_name if not (os_tenant_name or os_tenant_id): raise exc.CommandError( "You must provide a tenant_id " "via either --os-tenant-id or env[OS_TENANT_ID]") if not os_auth_url: raise exc.CommandError( "You must provide an auth url " "via either --os-auth-url or env[OS_AUTH_URL]") self.cs = client.Client(options.os_share_api_version, os_username, os_password, os_tenant_name, os_auth_url, insecure, region_name=os_region_name, tenant_id=os_tenant_id, endpoint_type=endpoint_type, extensions=self.extensions, service_type=service_type, service_name=service_name, share_service_name=share_service_name, retries=options.retries, http_log_debug=args.debug, cacert=cacert) try: if not utils.isunauthenticated(args.func): self.cs.authenticate() except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Manila credentials.") except exc.AuthorizationFailure: raise exc.CommandError("Unable to authorize user") args.func(self.cs, args)
def _validate_username(access): valid_useraname_re = '\w{4,32}' username = access if not re.match(valid_useraname_re, username): exc_str = _('Invalid user name. Must be alphanum 4-32 chars long') raise exceptions.CommandError(exc_str)
def _validate_common_name(access): if len(access) == 0 or len(access) > 64: exc_str = ('Invalid CN (common name). Must be 1-64 chars long.') raise exceptions.CommandError(exc_str)