def get_parser(self, prog_name): parser = super(ListStrategy, self).get_parser(prog_name) parser.add_argument('--goal', metavar='<goal>', dest='goal', help=_('UUID or name of the goal')) parser.add_argument( '--detail', dest='detail', action='store_true', default=False, help=_("Show detailed information about each strategy.")) parser.add_argument( '--limit', metavar='<limit>', type=int, help=_('Maximum number of strategies to return per request, ' '0 for no limit. Default is the maximum number used ' 'by the Watcher API Service.')) parser.add_argument( '--sort-key', metavar='<field>', help=_('Goal field that will be used for sorting.')) parser.add_argument( '--sort-dir', metavar='<direction>', choices=['asc', 'desc'], help='Sort direction: "asc" (the default) or "desc".') return parser
def get_parser(self, prog_name): parser = super(ListActionPlan, self).get_parser(prog_name) parser.add_argument('--audit', metavar='<audit>', help=_('UUID of an audit used for filtering.')) parser.add_argument( '--detail', dest='detail', action='store_true', default=False, help=_("Show detailed information about action plans.")) parser.add_argument( '--limit', metavar='<limit>', type=int, help=_('Maximum number of action plans to return per request, ' '0 for no limit. Default is the maximum number used ' 'by the Watcher API Service.')) parser.add_argument( '--sort-key', metavar='<field>', help=_('Action Plan field that will be used for sorting.')) parser.add_argument( '--sort-dir', metavar='<direction>', choices=['asc', 'desc'], help=_('Sort direction: "asc" (the default) or "desc".')) return parser
def get_parser(self, prog_name): parser = super(ListGoal, self).get_parser(prog_name) parser.add_argument( '--detail', dest='detail', action='store_true', default=False, help=_("Show detailed information about each goal.")) parser.add_argument( '--limit', metavar='<limit>', type=int, help=_('Maximum number of goals to return per request, ' '0 for no limit. Default is the maximum number used ' 'by the Watcher API Service.')) parser.add_argument( '--sort-key', metavar='<field>', help=_('Goal field that will be used for sorting.')) parser.add_argument( '--sort-dir', metavar='<direction>', choices=['asc', 'desc'], help=_('Sort direction: "asc" (the default) or "desc".')) parser.add_argument('--marker', dest='marker', metavar='<marker>', default=None, help=_( 'UUID of the last goal in the previous page; ' 'displays list of goals after "marker".')) return parser
def get_parser(self, prog_name): parser = super(ListScoringEngine, self).get_parser(prog_name) parser.add_argument( '--detail', dest='detail', action='store_true', default=False, help=_("Show detailed information about scoring engines.")) parser.add_argument( '--limit', metavar='<limit>', type=int, help=_('Maximum number of actions to return per request, ' '0 for no limit. Default is the maximum number used ' 'by the Watcher API Service.')) parser.add_argument( '--sort-key', metavar='<field>', help=_('Action field that will be used for sorting.')) parser.add_argument( '--sort-dir', metavar='<direction>', choices=['asc', 'desc'], help=_('Sort direction: "asc" (the default) or "desc".')) return parser
def negotiate_version(self, conn, resp): """Negotiate the server version Assumption: Called after receiving a 406 error when doing a request. param conn: A connection object param resp: The response object from http request """ if self.api_version_select_state not in API_VERSION_SELECTED_STATES: raise RuntimeError( _('Error: self.api_version_select_state should be one of the ' 'values in: "%(valid)s" but had the value: "%(value)s"') % { 'valid': ', '.join(API_VERSION_SELECTED_STATES), 'value': self.api_version_select_state }) min_ver, max_ver = self._parse_version_headers(resp) # If the user requested an explicit version or we have negotiated a # version and still failing then error now. The server could # support the version requested but the requested operation may not # be supported by the requested version. if self.api_version_select_state == 'user': raise exceptions.UnsupportedVersion( textwrap.fill( _("Requested API version %(req)s is not supported by the " "server or the requested operation is not supported by the " "requested version. Supported version range is %(min)s to " "%(max)s") % { 'req': self.os_infra_optim_api_version, 'min': min_ver, 'max': max_ver })) if self.api_version_select_state == 'negotiated': raise exceptions.UnsupportedVersion( textwrap.fill( _("No API version was specified and the requested operation " "was not supported by the client's negotiated API version " "%(req)s. Supported version range is: %(min)s to %(max)s" ) % { 'req': self.os_infra_optim_api_version, 'min': min_ver, 'max': max_ver })) negotiated_ver = str( min(version.StrictVersion(self.os_infra_optim_api_version), version.StrictVersion(max_ver))) if negotiated_ver < min_ver: negotiated_ver = min_ver # server handles microversions, but doesn't support # the requested version, so try a negotiated version self.api_version_select_state = 'negotiated' self.os_infra_optim_api_version = negotiated_ver LOG.debug('Negotiated API version is %s', negotiated_ver) return negotiated_ver
class ServiceUnavailable(HttpServerError): """HTTP 503 - Service Unavailable. The server is currently unavailable. """ http_status = 503 message = _("Service Unavailable")
def matches(self, min_version, max_version): """Matches the version object. Returns whether the version object represents a version greater than or equal to the minimum version and less than or equal to the maximum version. :param min_version: Minimum acceptable version. :param max_version: Maximum acceptable version. :returns: boolean If min_version is null then there is no minimum limit. If max_version is null then there is no maximum limit. If self is null then raise ValueError """ if self.is_null(): raise ValueError(_("Null APIVersion doesn't support 'matches'.")) if max_version.is_null() and min_version.is_null(): return True elif max_version.is_null(): return min_version <= self elif min_version.is_null(): return self <= max_version else: return min_version <= self <= max_version
def __init__(self, endpoint, **kwargs): self.endpoint = endpoint self.endpoint_trimmed = _trim_endpoint_api_version(endpoint) self.auth_token = kwargs.get('token') self.auth_ref = kwargs.get('auth_ref') self.os_watcher_api_version = kwargs.get('os_watcher_api_version', DEFAULT_VER) self.api_version_select_state = kwargs.get('api_version_select_state', 'default') self.conflict_max_retries = kwargs.pop('max_retries', DEFAULT_MAX_RETRIES) self.conflict_retry_interval = kwargs.pop('retry_interval', DEFAULT_RETRY_INTERVAL) self.session = requests.Session() parts = urlparse.urlparse(endpoint) if parts.scheme not in SUPPORTED_ENDPOINT_SCHEME: msg = _('Unsupported scheme: %s') % parts.scheme raise exceptions.EndpointException(msg) if parts.scheme == 'https': if kwargs.get('insecure') is True: self.session.verify = False elif kwargs.get('ca_file'): self.session.verify = kwargs['ca_file'] self.session.cert = (kwargs.get('cert_file'), kwargs.get('key_file'))
def get_parser(self, prog_name): parser = super(CancelActionPlan, self).get_parser(prog_name) parser.add_argument('action_plan', metavar='<action-plan>', help=_("UUID of the action_plan.")) return parser
def __init__(self, version_str=None): """Create an API version object. :param version_str: String representation of APIVersionRequest. Correct format is 'X.Y', where 'X' and 'Y' are int values. None value should be used to create Null APIVersionRequest, which is equal to 0.0 """ self.ver_major = 0 self.ver_minor = 0 if version_str is not None: match = re.match(r"^([1-9]\d*)\.([1-9]\d*|0|latest)$", version_str) if match: self.ver_major = int(match.group(1)) if match.group(2) == "latest": # NOTE(andreykurilin): Infinity allows to easily determine # latest version and doesn't require any additional checks # in comparison methods. self.ver_minor = float("inf") else: self.ver_minor = int(match.group(2)) else: msg = _("Invalid format of client version '%s'. " "Expected format 'X.Y', where X is a major part and Y " "is a minor part of version.") % version_str raise exceptions.UnsupportedVersion(msg)
class RequestUriTooLong(HTTPClientError): """HTTP 414 - Request-URI Too Long. The URI provided was too long for the server to process. """ http_status = 414 message = _("Request-URI Too Long")
def print_dict(dct, dict_property="Property", wrap=0): """Print a `dict` as a table of two columns. :param dct: `dict` to print :param dict_property: name of the first column :param wrap: wrapping for the second column """ pt = prettytable.PrettyTable([dict_property, 'Value']) pt.align = 'l' for k, v in dct.items(): # convert dict to str to check length if isinstance(v, dict): v = six.text_type(v) if wrap > 0: v = textwrap.fill(six.text_type(v), wrap) elif wrap < 0: raise ValueError(_("Wrap argument should be a positive integer")) # if value has a newline, add in multiple rows # e.g. fault with stacktrace if v and isinstance(v, six.string_types) and r'\n' in v: lines = v.strip().split(r'\n') col1 = k for line in lines: pt.add_row([col1, line]) col1 = '' else: if v is None: v = '-' pt.add_row([k, v]) if six.PY3: print(encodeutils.safe_encode(pt.get_string()).decode()) else: print(encodeutils.safe_encode(pt.get_string()))
class ProxyAuthenticationRequired(HTTPClientError): """HTTP 407 - Proxy Authentication Required. The client must first authenticate itself with the proxy. """ http_status = 407 message = _("Proxy Authentication Required")
class RequestTimeout(HTTPClientError): """HTTP 408 - Request Timeout. The server timed out waiting for the request. """ http_status = 408 message = _("Request Timeout")
class PaymentRequired(HTTPClientError): """HTTP 402 - Payment Required. Reserved for future use. """ http_status = 402 message = _("Payment Required")
class BadRequest(HTTPClientError): """HTTP 400 - Bad Request. The request cannot be fulfilled due to bad syntax. """ http_status = 400 message = _("Bad Request")
class HttpServerError(HttpError): """Server-side HTTP error. Exception for cases in which the server is aware that it has erred or is incapable of performing the request. """ message = _("HTTP Server Error")
class HttpVersionNotSupported(HttpServerError): """HTTP 505 - HttpVersion Not Supported. The server does not support the HTTP protocol version used in the request. """ http_status = 505 message = _("HTTP Version Not Supported")
def find(self, base_url=None, **kwargs): """Find a single item with attributes matching ``**kwargs``. :param base_url: if provided, the generated URL will be appended to it """ kwargs = self._filter_kwargs(kwargs) rl = self._list( '%(base_url)s%(query)s' % { 'base_url': self.build_url(base_url=base_url, **kwargs), 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', }, self.collection_key) num = len(rl) if num == 0: msg = _("No %(name)s matching %(args)s.") % { 'name': self.resource_class.__name__, 'args': kwargs } raise exceptions.NotFound(404, msg) elif num > 1: raise exceptions.NoUniqueMatch else: return rl[0]
def __init__(self, endpoint=None, *args, **kwargs): """Initialize a new client for the Watcher v1 API.""" if kwargs.get('os_infra_optim_api_version'): kwargs['api_version_select_state'] = "user" else: if not endpoint: raise exceptions.EndpointException( _("Must provide 'endpoint' if os_infra_optim_api_version " "isn't specified")) # If the user didn't specify a version, use a cached version if # one has been stored host, netport = httpclient.get_server(endpoint) kwargs['api_version_select_state'] = "default" kwargs['os_infra_optim_api_version'] = httpclient.DEFAULT_VER self.http_client = httpclient._construct_http_client( endpoint, *args, **kwargs) self.audit = v1.AuditManager(self.http_client) self.audit_template = v1.AuditTemplateManager(self.http_client) self.action = v1.ActionManager(self.http_client) self.action_plan = v1.ActionPlanManager(self.http_client) self.goal = v1.GoalManager(self.http_client) self.scoring_engine = v1.ScoringEngineManager(self.http_client) self.service = v1.ServiceManager(self.http_client) self.strategy = v1.StrategyManager(self.http_client)
def __init__(self, endpoint, **kwargs): self.endpoint = endpoint self.endpoint_trimmed = _trim_endpoint_api_version(endpoint) self.auth_token = kwargs.get('token') self.auth_ref = kwargs.get('auth_ref') self.os_infra_optim_api_version = kwargs.get( 'os_infra_optim_api_version', DEFAULT_VER) self.api_version_select_state = kwargs.get( 'api_version_select_state', 'default') self.conflict_max_retries = kwargs.pop('max_retries', DEFAULT_MAX_RETRIES) self.conflict_retry_interval = kwargs.pop('retry_interval', DEFAULT_RETRY_INTERVAL) self.session = requests.Session() parts = urlparse.urlparse(endpoint) if parts.scheme not in SUPPORTED_ENDPOINT_SCHEME: msg = _('Unsupported scheme: %s') % parts.scheme raise exceptions.EndpointException(msg) if parts.scheme == 'https': if kwargs.get('insecure') is True: self.session.verify = False elif kwargs.get('ca_file'): self.session.verify = kwargs['ca_file'] self.session.cert = (kwargs.get('cert_file'), kwargs.get('key_file'))
class InternalServerError(HttpServerError): """HTTP 500 - Internal Server Error. A generic error message, given when no more specific message is suitable. """ http_status = 500 message = _("Internal Server Error")
class ExpectationFailed(HTTPClientError): """HTTP 417 - Expectation Failed. The server cannot meet the requirements of the Expect request-header field. """ http_status = 417 message = _("Expectation Failed")
def __init__(self, endpoint=None, *args, **kwargs): """Initialize a new client for the Watcher v1 API.""" if kwargs.get('os_watcher_api_version'): kwargs['api_version_select_state'] = "user" else: if not endpoint: raise exceptions.EndpointException( _("Must provide 'endpoint' if os_watcher_api_version " "isn't specified")) # If the user didn't specify a version, use a cached version if # one has been stored host, netport = httpclient.get_server(endpoint) kwargs['api_version_select_state'] = "default" kwargs['os_watcher_api_version'] = httpclient.DEFAULT_VER self.http_client = httpclient._construct_http_client( endpoint, *args, **kwargs) self.audit = v1.AuditManager(self.http_client) self.audit_template = v1.AuditTemplateManager(self.http_client) self.action = v1.ActionManager(self.http_client) self.action_plan = v1.ActionPlanManager(self.http_client) self.goal = v1.GoalManager(self.http_client) self.scoring_engine = v1.ScoringEngineManager(self.http_client) self.service = v1.ServiceManager(self.http_client) self.strategy = v1.StrategyManager(self.http_client)
def negotiate_version(self, conn, resp): """Negotiate the server version Assumption: Called after receiving a 406 error when doing a request. param conn: A connection object param resp: The response object from http request """ if self.api_version_select_state not in API_VERSION_SELECTED_STATES: raise RuntimeError( _('Error: self.api_version_select_state should be one of the ' 'values in: "%(valid)s" but had the value: "%(value)s"') % {'valid': ', '.join(API_VERSION_SELECTED_STATES), 'value': self.api_version_select_state}) min_ver, max_ver = self._parse_version_headers(resp) # If the user requested an explicit version or we have negotiated a # version and still failing then error now. The server could # support the version requested but the requested operation may not # be supported by the requested version. if self.api_version_select_state == 'user': raise exceptions.UnsupportedVersion(textwrap.fill( _("Requested API version %(req)s is not supported by the " "server or the requested operation is not supported by the " "requested version. Supported version range is %(min)s to " "%(max)s") % {'req': self.os_infra_optim_api_version, 'min': min_ver, 'max': max_ver})) if self.api_version_select_state == 'negotiated': raise exceptions.UnsupportedVersion(textwrap.fill( _("No API version was specified and the requested operation " "was not supported by the client's negotiated API version " "%(req)s. Supported version range is: %(min)s to %(max)s") % {'req': self.os_infra_optim_api_version, 'min': min_ver, 'max': max_ver})) negotiated_ver = str( min(version.StrictVersion(self.os_infra_optim_api_version), version.StrictVersion(max_ver))) if negotiated_ver < min_ver: negotiated_ver = min_ver # server handles microversions, but doesn't support # the requested version, so try a negotiated version self.api_version_select_state = 'negotiated' self.os_infra_optim_api_version = negotiated_ver LOG.debug('Negotiated API version is %s', negotiated_ver) return negotiated_ver
class BadGateway(HttpServerError): """HTTP 502 - Bad Gateway. The server was acting as a gateway or proxy and received an invalid response from the upstream server. """ http_status = 502 message = _("Bad Gateway")
def get_parser(self, prog_name): parser = super(ShowAudit, self).get_parser(prog_name) parser.add_argument( 'audit', metavar='<audit>', help=_('UUID or name of the audit'), ) return parser
def get_parser(self, prog_name): parser = super(ShowGoal, self).get_parser(prog_name) parser.add_argument( 'goal', metavar='<goal>', help=_('UUID or name of the goal'), ) return parser
class GatewayTimeout(HttpServerError): """HTTP 504 - Gateway Timeout. The server was acting as a gateway or proxy and did not receive a timely response from the upstream server. """ http_status = 504 message = _("Gateway Timeout")
def get_parser(self, prog_name): parser = super(CreateActionPlan, self).get_parser(prog_name) parser.add_argument( '-a', '--audit-template', required=True, dest='audit_template_uuid', metavar='<audit_template>', help=_('ActionPlan template used for this audit (name or uuid).')) parser.add_argument('-t', '--audit_type', dest='audit_type', metavar='<audit_type>', default='ONESHOT', help=_("ActionPlan type.")) return parser
def get_parser(self, prog_name): parser = super(StateStrategy, self).get_parser(prog_name) parser.add_argument( 'strategy', metavar='<strategy>', help=_('Name of the strategy'), ) return parser
def get_parser(self, prog_name): parser = super(ShowAuditTemplate, self).get_parser(prog_name) parser.add_argument( 'audit_template', metavar='<audit-template>', help=_('UUID or name of the audit template'), ) return parser
def get_parser(self, prog_name): parser = super(ShowActionPlan, self).get_parser(prog_name) parser.add_argument( 'action_plan', metavar='<action-plan>', help=_('UUID of the action plan'), ) return parser
def get_parser(self, prog_name): parser = super(ShowScoringEngine, self).get_parser(prog_name) parser.add_argument( 'scoring_engine', metavar='<scoring_engine>', help=_('Name of the scoring engine'), ) return parser
def get_parser(self, prog_name): parser = super(ShowService, self).get_parser(prog_name) parser.add_argument( 'service', metavar='<service>', help=_('ID or name of the service'), ) return parser
class HttpNotImplemented(HttpServerError): """HTTP 501 - Not Implemented. The server either does not recognize the request method, or it lacks the ability to fulfill the request. """ http_status = 501 message = _("Not Implemented")
def get_parser(self, prog_name): parser = super(CancelActionPlan, self).get_parser(prog_name) parser.add_argument( 'action_plan', metavar='<action-plan>', help=_("UUID of the action_plan.")) return parser
class UnprocessableEntity(HTTPClientError): """HTTP 422 - Unprocessable Entity. The request was well-formed but was unable to be followed due to semantic errors. """ http_status = 422 message = _("Unprocessable Entity")
def common_params_for_list(args, fields, field_labels): """Generate 'params' dict that is common for every 'list' command. :param args: arguments from command line. :param fields: possible fields for sorting. :param field_labels: possible field labels for sorting. :returns: a dict with params to pass to the client method. """ params = {} if args.limit is not None: if args.limit < 0: raise exc.CommandError( _('Expected non-negative --limit, got %s') % args.limit) params['limit'] = args.limit if args.sort_key is not None: # Support using both heading and field name for sort_key fields_map = dict(zip(field_labels, fields)) fields_map.update(zip(fields, fields)) try: sort_key = fields_map[args.sort_key] except KeyError: raise exc.CommandError( _("%(sort_key)s is an invalid field for sorting, " "valid values for --sort-key are: %(valid)s") % {'sort_key': args.sort_key, 'valid': list(fields_map)}) params['sort_key'] = sort_key if args.sort_dir is not None: if args.sort_dir not in ('asc', 'desc'): raise exc.CommandError( _("%s is an invalid value for sort direction, " "valid values for --sort-dir are: 'asc', 'desc'") % args.sort_dir) params['sort_dir'] = args.sort_dir marker = getattr(args, 'marker', None) if marker is not None: params['marker'] = marker params['detail'] = args.detail return params
def check_major_version(api_version): """Checks major part of ``APIVersion`` obj is supported. :raises watcherclient.exceptions.UnsupportedVersion: if major part is not supported """ available_versions = get_available_major_versions() if (not api_version.is_null() and str(api_version.ver_major) not in available_versions): if len(available_versions) == 1: msg = _("Invalid client version '%(version)s'. " "Major part should be '%(major)s'") % { "version": api_version.get_string(), "major": available_versions[0]} else: msg = _("Invalid client version '%(version)s'. " "Major part must be one of: '%(major)s'") % { "version": api_version.get_string(), "major": ", ".join(available_versions)} raise exceptions.UnsupportedVersion(msg)
def get_parser(self, prog_name): parser = super(UpdateActionPlan, self).get_parser(prog_name) parser.add_argument( 'action_plan', metavar='<action-plan>', help=_("UUID of the action_plan.")) parser.add_argument( 'op', metavar='<op>', choices=['add', 'replace', 'remove'], help=_("Operation: 'add', 'replace', or 'remove'.")) parser.add_argument( 'attributes', metavar='<path=value>', nargs='+', action='append', default=[], help=_("Attribute to add, replace, or remove. Can be specified " "multiple times. For 'remove', only <path> is necessary.")) return parser
def get_string(self): """Version string representation. Converts object to string representation which if used to create an APIVersion object results in the same version. """ if self.is_null(): raise ValueError( _("Null APIVersion cannot be converted to string.")) elif self.is_latest(): return "%s.%s" % (self.ver_major, "latest") return "%s.%s" % (self.ver_major, self.ver_minor)
def get_parser(self, prog_name): parser = super(ListActionPlan, self).get_parser(prog_name) parser.add_argument( '--audit', metavar='<audit>', help=_('UUID of an audit used for filtering.')) parser.add_argument( '--detail', dest='detail', action='store_true', default=False, help=_("Show detailed information about action plans.")) parser.add_argument( '--limit', metavar='<limit>', type=int, help=_('Maximum number of action plans to return per request, ' '0 for no limit. Default is the maximum number used ' 'by the Watcher API Service.')) parser.add_argument( '--marker', metavar='<actionplan>', help=_('The last actionplan UUID of the previous page; ' 'displays list of actionplans after "marker".')) parser.add_argument( '--sort-key', metavar='<field>', help=_('Action Plan field that will be used for sorting.')) parser.add_argument( '--sort-dir', metavar='<direction>', choices=['asc', 'desc'], help=_('Sort direction: "asc" (the default) or "desc".')) return parser
def print_list(objs, fields, formatters=None, sortby_index=0, mixed_case_fields=None, field_labels=None): """Print a list or objects as a table, one row per object. :param objs: iterable of :class:`Resource` :param fields: attributes that correspond to columns, in order :param formatters: `dict` of callables for field formatting :param sortby_index: index of the field for sorting table rows :param mixed_case_fields: fields corresponding to object attributes that have mixed case names (e.g., 'serverId') :param field_labels: Labels to use in the heading of the table, default to fields. """ formatters = formatters or {} mixed_case_fields = mixed_case_fields or [] field_labels = field_labels or fields if len(field_labels) != len(fields): raise ValueError(_("Field labels list %(labels)s has different number " "of elements than fields list %(fields)s"), {'labels': field_labels, 'fields': fields}) if sortby_index is None: kwargs = {} else: kwargs = {'sortby': field_labels[sortby_index]} pt = prettytable.PrettyTable(field_labels) pt.align = 'l' for o in objs: row = [] for field in fields: data = '-' if field in formatters: data = formatters[field](o) else: if field in mixed_case_fields: field_name = field.replace(' ', '_') else: field_name = field.lower().replace(' ', '_') data = getattr(o, field_name, '') if data is None: data = '-' row.append(data) pt.add_row(row) if six.PY3: print(encodeutils.safe_encode(pt.get_string(**kwargs)).decode()) else: print(encodeutils.safe_encode(pt.get_string(**kwargs)))
def args_array_to_patch(op, attributes, exclude_fields=[]): patch = [] for attr in attributes: # Sanitize if not attr.startswith('/'): attr = '/' + attr if op in ['add', 'replace']: path, value = split_and_deserialize(attr, exclude_fields=exclude_fields) patch.append({'op': op, 'path': path, 'value': value}) elif op == "remove": # For remove only the key is needed patch.append({'op': op, 'path': attr}) else: raise exc.CommandError(_('Unknown PATCH operation: %s') % op) return patch
def find(self, **kwargs): """Find a single item with attributes matching ``**kwargs``. This isn't very efficient: it loads the entire list then filters on the Python side. """ matches = self.findall(**kwargs) num_matches = len(matches) if num_matches == 0: msg = _("No %(name)s matching %(args)s.") % { 'name': self.resource_class.__name__, 'args': kwargs } raise exceptions.NotFound(msg) elif num_matches > 1: raise exceptions.NoUniqueMatch() else: return matches[0]
def split_and_deserialize(string, exclude_fields=[]): """Split and try to JSON deserialize a string. Gets a string with the KEY=VALUE format, split it (using '=' as the separator) and try to JSON deserialize the VALUE. :returns: A tuple of (key, value). """ try: key, value = string.split("=", 1) except ValueError: raise exc.CommandError(_('Attributes must be a list of ' 'PATH=VALUE not "%s"') % string) if key not in exclude_fields: try: value = jsonutils.loads(value) except ValueError: pass return (key, value)
def _http_request(self, url, method, **kwargs): """Send an http request with the specified characteristics. Wrapper around request.Session.request to handle tasks such as setting headers and error handling. """ # Copy the kwargs so we can reuse the original in case of redirects kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {})) kwargs['headers'].setdefault('User-Agent', USER_AGENT) if self.os_infra_optim_api_version: api_version = api_versioning.get_api_version( self.os_infra_optim_api_version) if api_version.is_latest(): api_version = api_versioning.get_api_version( LATEST_VERSION) kwargs['headers'].setdefault( 'OpenStack-API-Version', ' '.join(['infra-optim', api_version.get_string()])) if self.auth_token: kwargs['headers'].setdefault('X-Auth-Token', self.auth_token) self.log_curl_request(method, url, kwargs) # NOTE(aarefiev): This is for backwards compatibility, request # expected body in 'data' field, previously we used httplib, # which expected 'body' field. body = kwargs.pop('body', None) if body: kwargs['data'] = body conn_url = self._make_connection_url(url) try: resp = self.session.request(method, conn_url, **kwargs) # TODO(deva): implement graceful client downgrade when connecting # to servers that did not support microversions. Details here: # http://specs.openstack.org/openstack/watcher-specs/specs/kilo/api-microversions.html#use-case-3b-new-client-communicating-with-a-old-watcher-user-specified # noqa if resp.status_code == http_client.NOT_ACCEPTABLE: negotiated_ver = self.negotiate_version(self.session, resp) kwargs['headers']['OpenStack-API-Version'] = ( ' '.join(['infra-optim', negotiated_ver])) return self._http_request(url, method, **kwargs) except requests.exceptions.RequestException as e: message = (_("Error has occurred while handling " "request for %(url)s: %(e)s") % dict(url=conn_url, e=e)) # NOTE(aarefiev): not valid request(invalid url, missing schema, # and so on), retrying is not needed. if isinstance(e, ValueError): raise exceptions.ValidationError(message) raise exceptions.ConnectionRefused(message) body_iter = resp.iter_content(chunk_size=CHUNKSIZE) # Read body into string if it isn't obviously image data body_str = None if resp.headers.get('Content-Type') != 'application/octet-stream': # decoding byte to string is necessary for Python 3 compatibility # this issues has not been found with Python 3 unit tests # because the test creates a fake http response of type str # the if statement satisfies test (str) and real (bytes) behavior body_list = [ chunk.decode("utf-8") if isinstance(chunk, bytes) else chunk for chunk in body_iter ] body_str = ''.join(body_list) self.log_http_response(resp, body_str) body_iter = six.StringIO(body_str) else: self.log_http_response(resp) if resp.status_code >= http_client.BAD_REQUEST: error_json = _extract_error_json(body_str) raise exceptions.from_response( resp, error_json.get('faultstring'), error_json.get('debuginfo'), method, url) elif resp.status_code in (http_client.MOVED_PERMANENTLY, http_client.FOUND, http_client.USE_PROXY): # Redirected. Reissue the request to the new location. return self._http_request(resp['location'], method, **kwargs) elif resp.status_code == http_client.MULTIPLE_CHOICES: raise exceptions.from_response(resp, method=method, url=url) return resp, body_iter
def get_parser(self, prog_name): class SmartFormatter(argparse.HelpFormatter): def _split_lines(self, text, width): if '\n' in text: return text.splitlines() else: return argparse.HelpFormatter._split_lines( self, text, width) parser = super(CreateAuditTemplate, self).get_parser( prog_name, formatter_class=SmartFormatter) parser.add_argument( 'name', metavar='<name>', help=_('Name for this audit template.')) parser.add_argument( 'goal', metavar='<goal>', help=_('Goal UUID or name associated to this audit template.')) parser.add_argument( '-s', '--strategy', dest='strategy', metavar='<strategy>', help=_('Strategy UUID or name associated to this audit template.')) parser.add_argument( '-d', '--description', metavar='<description>', help=_('Description of the audit template.')) parser.add_argument( '--scope', metavar='<path>', help=_("Part of the cluster on which an audit will be done.\n" "Can be provided either in yaml or json file.\n" "YAML example:\n" "---\n" " - compute:\n" " - host_aggregates:\n" " - id: 1\n" " - id: 2\n" " - id: 3\n" " - availability_zones:\n" " - name: AZ1\n" " - name: AZ2\n" " - exclude:\n" " - instances:\n" " - uuid: UUID1\n" " - uuid: UUID2\n" " - compute_nodes:\n" " - name: compute1\n" " - storage: \n" " - availability_zones:\n" " - name: AZ1\n" " - name: AZ2\n" " - volume_types:\n" " - name: lvm1\n" " - name: lvm2\n" " - exclude:\n" " - storage_pools:\n" " - name: host0@backend0#pool0\n" " - name: host1@backend1#pool1\n" " - volumes:\n" " - uuid: UUID1\n" " - uuid: UUID2\n" " - projects:\n" " - uuid: UUID1\n" " - uuid: UUID2\n" "\n" "JSON example:\n" "[\n" " {\"compute\":\n" " [{\"host_aggregates\": [\n" " {\"id\": 1},\n" " {\"id\": 2},\n" " {\"id\": 3}]},\n" " {\"availability_zones\": [\n" " {\"name\": \"AZ1\"},\n" " {\"name\": \"AZ2\"}]},\n" " {\"exclude\": [\n" " {\"instances\": [\n" " {\"uuid\": \"UUID1\"},\n" " {\"uuid\": \"UUID2\"}\n" " ]},\n" " {\"compute_nodes\": [\n" " {\"name\": \"compute1\"}\n" " ]}\n" " ]}]\n" " },\n" " {\"storage\":\n" " [{\"availability_zones\": [\n" " {\"name\": \"AZ1\"},\n" " {\"name\": \"AZ2\"}]},\n" " {\"volume_types\": [\n" " {\"name\": \"lvm1\"},\n" " {\"name\": \"lvm2\"}]},\n" " {\"exclude\": [\n" " {\"storage_pools\": [\n" " {\"name\": \"host0@backend0#pool0\"},\n" " {\"name\": \"host1@backend1#pool1\"}\n" " ]},\n" " {\"volumes\": [\n" " {\"uuid\": \"UUID1\"},\n" " {\"uuid\": \"UUID2\"}\n" " ]},\n" " {\"projects\": [\n" " {\"uuid\": \"UUID1\"},\n" " {\"uuid\": \"UUID2\"}\n" " ]},\n" " ]}]\n" " }\n" " ]\n" ) ) return parser
from oslo_utils import strutils from watcherclient._i18n import _ from watcherclient import exceptions LOG = logging.getLogger(__name__) if not LOG.handlers: LOG.addHandler(logging.StreamHandler()) MINOR_1_START_END_TIMING = '1.1' HEADER_NAME = "OpenStack-API-Version" # key is a deprecated version and value is an alternative version. DEPRECATED_VERSIONS = {} _type_error_msg = _("'%(other)s' should be an instance of '%(cls)s'") def allow_start_end_audit_time(requested_version): """Check if we should support optional start/end attributes for Audit. Version 1.1 of the API added support for start and end time of continuous audits. """ return (APIVersion(requested_version) >= APIVersion(MINOR_1_START_END_TIMING)) class APIVersion(object): """This class represents an API Version Request.
def __init__(self, endpoints=None): super(AmbiguousEndpoints, self).__init__( _("AmbiguousEndpoints: %r") % endpoints) self.endpoints = endpoints
def __init__(self, opt_names): super(AuthPluginOptionsMissing, self).__init__( _("Authentication failed. Missing options: %s") % ", ".join(opt_names)) self.opt_names = opt_names
def __init__(self, auth_system): super(AuthSystemNotFound, self).__init__( _("AuthSystemNotFound: %r") % auth_system) self.auth_system = auth_system
def __init__(self, missing): self.missing = missing msg = _("Missing arguments: %s") % ", ".join(missing) super(MissingArgs, self).__init__(msg)