Esempio n. 1
0
    def call(self, ctxt, method, **kwargs):
        """Invoke a method and wait for a reply. See RPCClient.call()."""
        if self.target.fanout:
            raise exceptions.InvalidTarget('A call cannot be used with fanout',
                                           self.target)

        msg = self._make_message(ctxt, method, kwargs)
        msg_ctxt = self.serializer.serialize_context(ctxt)

        span_host = tomograph.getHost()

        ser_name = "%s[%s]" % ("RPC_call", self.target.topic)
        tomograph.start(ser_name, self.target.topic, span_host, 0)
        trace_info = tomograph.get_trace_info()
        msg_ctxt["trace_id"] = trace_info[0]
        msg_ctxt["span_id"] = trace_info[1]

        timeout = self.timeout
        if self.timeout is None:
            timeout = self.conf.rpc_response_timeout

        if self.version_cap:
            self._check_version_cap(msg.get('version'))

        try:
            result = self.transport._send(self.target, msg_ctxt, msg,
                                          wait_for_reply=True, timeout=timeout,
                                          retry=self.retry)

            tomograph.stop(self.target.topic)
        except driver_base.TransportDriverError as ex:
            raise ClientSendError(self.target, ex)
        return self.serializer.deserialize_entity(ctxt, result)
Esempio n. 2
0
    def call(self, ctxt, method, **kwargs):
        """Invoke a method and wait for a reply. See RPCClient.call()."""
        if self.target.fanout:
            raise exceptions.InvalidTarget("A call cannot be used with fanout", self.target)

        msg = self._make_message(ctxt, method, kwargs)
        msg_ctxt = self.serializer.serialize_context(ctxt)

        span_host = tomograph.getHost()

        ser_name = "%s[%s]" % ("RPC_call", self.target.topic)
        tomograph.start(ser_name, self.target.topic, span_host, 0)
        trace_info = tomograph.get_trace_info()
        msg_ctxt["trace_id"] = trace_info[0]
        msg_ctxt["span_id"] = trace_info[1]

        timeout = self.timeout
        if self.timeout is None:
            timeout = self.conf.rpc_response_timeout

        if self.version_cap:
            self._check_version_cap(msg.get("version"))

        try:
            result = self.transport._send(
                self.target, msg_ctxt, msg, wait_for_reply=True, timeout=timeout, retry=self.retry
            )

            tomograph.stop(self.target.topic)
        except driver_base.TransportDriverError as ex:
            raise ClientSendError(self.target, ex)
        return self.serializer.deserialize_entity(ctxt, result)
Esempio n. 3
0
    def request(self, url, method, **kwargs):
        endpoint_filter = kwargs.setdefault('endpoint_filter', {})
        self._set_endpoint_filter_kwargs(endpoint_filter)

        if self.endpoint_override:
            kwargs.setdefault('endpoint_override', self.endpoint_override)

        if self.auth:
            kwargs.setdefault('auth', self.auth)
        if self.user_agent:
            kwargs.setdefault('user_agent', self.user_agent)
        if self.connect_retries is not None:
            kwargs.setdefault('connect_retries', self.connect_retries)
        if self.logger:
            kwargs.setdefault('logger', self.logger)

        if isinstance(self.session, Session):
            if self.user_agent:
                span_service_name = self.user_agent
            else:
                span_service_name = "unknown user_agent"
            if self.service_type:
                span_name = self.service_type
            else: 
                span_name = "unknown sevice_type"
            span_host = tomograph.getHost()
            ser_name = "%s[%s]" % (span_service_name, span_name)
            tomograph.start_http_h(ser_name, span_name, kwargs["headers"], span_host, 0)
            tomograph.add_trace_info_header(kwargs["headers"])
            ret = self.session.request(url, method, **kwargs)
            tomograph.stop(span_name)
            return ret
        else:
            return self.session.request(url, method, **kwargs)
Esempio n. 4
0
    def request(self, url, method, **kwargs):
        endpoint_filter = kwargs.setdefault('endpoint_filter', {})
        self._set_endpoint_filter_kwargs(endpoint_filter)

        if self.endpoint_override:
            kwargs.setdefault('endpoint_override', self.endpoint_override)

        if self.auth:
            kwargs.setdefault('auth', self.auth)
        if self.user_agent:
            kwargs.setdefault('user_agent', self.user_agent)
        if self.connect_retries is not None:
            kwargs.setdefault('connect_retries', self.connect_retries)
        if self.logger:
            kwargs.setdefault('logger', self.logger)

        if isinstance(self.session, Session):
            if self.user_agent:
                span_service_name = self.user_agent
            else:
                span_service_name = "unknown user_agent"
            if self.service_type:
                span_name = self.service_type
            else:
                span_name = "unknown sevice_type"
            span_host = tomograph.getHost()
            ser_name = "%s[%s]" % (span_service_name, span_name)
            tomograph.start_http_h(ser_name, span_name, kwargs["headers"],
                                   span_host, 0)
            tomograph.add_trace_info_header(kwargs["headers"])
            ret = self.session.request(url, method, **kwargs)
            tomograph.stop(span_name)
            return ret
        else:
            return self.session.request(url, method, **kwargs)
Esempio n. 5
0
File: wsgi.py Progetto: hbkqh/patch
    def dispatch(self, obj, action, *args, **kwargs):
        """Find action-specific method on self and call it."""
        try:
            method = getattr(obj, action)
            if isinstance(args[0], Request):
                ser_name = "%s[%s]" % (method.__module__, method.__name__)
                tomograph.start_http(ser_name, method.__name__, args[0])
                tomograph.stop(method.__name__)
        except AttributeError:
            method = getattr(obj, 'default')

        return method(*args, **kwargs)
Esempio n. 6
0
    def dispatch(self, obj, action, *args, **kwargs):
        """Find action-specific method on self and call it."""
        try:
            method = getattr(obj, action)
            if isinstance(args[0], Request):
                ser_name = "%s[%s]" % (method.__module__, method.__name__)
                tomograph.start_http(ser_name, method.__name__, args[0])
                tomograph.stop(method.__name__)
        except AttributeError:
            method = getattr(obj, 'default')

        return method(*args, **kwargs)
Esempio n. 7
0
    def process_request(self, request):
        """Process request.

        Evaluate the headers in a request and attempt to authenticate the
        request against the identity server. If authenticated then additional
        headers are added to the request for use by applications. If not
        authenticated the request will be rejected or marked unauthenticated
        depending on configuration.
        """
        # pdb.set_trace()
        tomograph.start_http(
            "keystonemiddleware.auth_token.AuthProtocol[process_request]",
            "process_request", request)
        tomograph.add_trace_info_header(request.headers)

        self._token_cache.initialize(request.environ)

        resp = super(AuthProtocol, self).process_request(request)

        tomograph.stop("process_request")

        if resp:
            return resp

        if not request.user_token:
            # if no user token is present then that's an invalid request
            request.user_token_valid = False

        # NOTE(jamielennox): The service status is allowed to be missing if a
        # service token is not passed. If the service status is missing that's
        # a valid request. We should find a better way to expose this from the
        # request object.
        user_status = request.user_token and request.user_token_valid
        service_status = request.headers.get('X-Service-Identity-Status',
                                             'Confirmed')

        if not (user_status and service_status == 'Confirmed'):
            if self._delay_auth_decision:
                self.log.info(_LI('Deferring reject downstream'))
            else:
                self.log.info(_LI('Rejecting request'))
                self._reject_request()

        if request.user_token_valid:
            request.set_user_headers(request.token_auth._user_auth_ref,
                                     self._include_service_catalog)

        if request.service_token and request.service_token_valid:
            request.set_service_headers(request.token_auth._serv_auth_ref)

        if self.log.isEnabledFor(logging.DEBUG):
            self.log.debug('Received request from %s',
                           request.token_auth._log_format)
Esempio n. 8
0
 def dec(request, *args, **kwargs):
     if dashboard:
         request.horizon['dashboard'] = dashboard
     if panel:
         request.horizon['panel'] = panel
     if not tomograph.tracing_started():
         span_host = tomograph.getHost()
         ser_name = "%s[%s]" % (view_func.__module__, view_func.__name__)
         tomograph.start(ser_name, view_func.__name__, span_host, 0)
         ret = view_func(request, *args, **kwargs)
         tomograph.stop(view_func.__name__)
         return ret
     return view_func(request, *args, **kwargs)
Esempio n. 9
0
 def dec(request, *args, **kwargs):
     if dashboard:
         request.horizon['dashboard'] = dashboard
     if panel:
         request.horizon['panel'] = panel
     if not tomograph.tracing_started():
         span_host = tomograph.getHost()
         ser_name = "%s[%s]" % (view_func.__module__, view_func.__name__)
         tomograph.start(ser_name, view_func.__name__, span_host, 0)
         ret = view_func(request, *args, **kwargs)
         tomograph.stop(view_func.__name__)
         return ret
     return view_func(request, *args, **kwargs)
Esempio n. 10
0
    def process_request(self, request):
        """Process request.

        Evaluate the headers in a request and attempt to authenticate the
        request against the identity server. If authenticated then additional
        headers are added to the request for use by applications. If not
        authenticated the request will be rejected or marked unauthenticated
        depending on configuration.
        """
        # pdb.set_trace()
        tomograph.start_http("keystonemiddleware.auth_token.AuthProtocol[process_request]", "process_request", request)
        tomograph.add_trace_info_header(request.headers)

        self._token_cache.initialize(request.environ)

        resp = super(AuthProtocol, self).process_request(request)

        tomograph.stop("process_request")

        if resp:
            return resp

        if not request.user_token:
            # if no user token is present then that's an invalid request
            request.user_token_valid = False

        # NOTE(jamielennox): The service status is allowed to be missing if a
        # service token is not passed. If the service status is missing that's
        # a valid request. We should find a better way to expose this from the
        # request object.
        user_status = request.user_token and request.user_token_valid
        service_status = request.headers.get("X-Service-Identity-Status", "Confirmed")

        if not (user_status and service_status == "Confirmed"):
            if self._delay_auth_decision:
                self.log.info(_LI("Deferring reject downstream"))
            else:
                self.log.info(_LI("Rejecting request"))
                self._reject_request()

        if request.user_token_valid:
            request.set_user_headers(request.token_auth._user_auth_ref, self._include_service_catalog)

        if request.service_token and request.service_token_valid:
            request.set_service_headers(request.token_auth._serv_auth_ref)

        if self.log.isEnabledFor(logging.DEBUG):
            self.log.debug("Received request from %s", request.token_auth._log_format)
Esempio n. 11
0
 def inner(*args, **kwargs):
     try:
         span_host = tomograph.getHost()
         ser_name = "%s[%s]" % (func.__module__, func.__name__)
         tomograph.start(ser_name, func.__name__, span_host, 0)
         ret = func(*args, **kwargs)
         tomograph.stop(func.__name__)
         return ret
     # Take advantage of the fact that we can catch
     # multiple exception types using a tuple of
     # exception classes, with subclass detection
     # for free. Any exception that is not in or
     # derived from the args passed to us will be
     # ignored and thrown as normal.
     except exceptions:
         tomograph.stop(func.__name__)
         raise rpc_dispatcher.ExpectedException()
Esempio n. 12
0
    def cast(self, ctxt, method, **kwargs):
        """Invoke a method and return immediately. See RPCClient.cast()."""
        msg = self._make_message(ctxt, method, kwargs)
        msg_ctxt = self.serializer.serialize_context(ctxt)

        span_host = tomograph.getHost()
        ser_name = "%s[%s]" % ("RPC_cast", self.target.topic)
        tomograph.start(ser_name, self.target.topic, span_host, 0)
        trace_info = tomograph.get_trace_info()
        msg_ctxt["trace_id"] = trace_info[0]
        msg_ctxt["span_id"] = trace_info[1]

        if self.version_cap:
            self._check_version_cap(msg.get("version"))
        try:
            self.transport._send(self.target, msg_ctxt, msg, retry=self.retry)
            tomograph.stop(self.target.topic)
        except driver_base.TransportDriverError as ex:
            raise ClientSendError(self.target, ex)
Esempio n. 13
0
    def cast(self, ctxt, method, **kwargs):
        """Invoke a method and return immediately. See RPCClient.cast()."""
        msg = self._make_message(ctxt, method, kwargs)
        msg_ctxt = self.serializer.serialize_context(ctxt)

        span_host = tomograph.getHost()
        ser_name = "%s[%s]" % ("RPC_cast", self.target.topic)
        tomograph.start(ser_name, self.target.topic, span_host, 0)
        trace_info = tomograph.get_trace_info()
        msg_ctxt["trace_id"] = trace_info[0]
        msg_ctxt["span_id"] = trace_info[1]

        if self.version_cap:
            self._check_version_cap(msg.get('version'))
        try:
            self.transport._send(self.target, msg_ctxt, msg, retry=self.retry)
            tomograph.stop(self.target.topic)
        except driver_base.TransportDriverError as ex:
            raise ClientSendError(self.target, ex)
Esempio n. 14
0
    def __init__(self, endpoint, **kwargs):
        self.endpoint = endpoint
        self.identity_headers = kwargs.get('identity_headers')
        self.auth_token = kwargs.get('token')
        if self.identity_headers:
            if self.identity_headers.get('X-Auth-Token'):
                self.auth_token = self.identity_headers.get('X-Auth-Token')
                del self.identity_headers['X-Auth-Token']

        self.session = requests.Session()
        self.session.headers["User-Agent"] = USER_AGENT

        if self.auth_token:
            self.session.headers["X-Auth-Token"] = self.auth_token

        self.timeout = float(kwargs.get('timeout', 600))

        if self.endpoint.startswith("https"):
            compression = kwargs.get('ssl_compression', True)

            if compression is False:
                # Note: This is not seen by default. (python must be
                # run with -Wd)
                warnings.warn(
                    'The "ssl_compression" argument has been '
                    'deprecated.', DeprecationWarning)

            if kwargs.get('insecure', False) is True:
                self.session.verify = False
            else:
                if kwargs.get('cacert', None) is not '':
                    self.session.verify = kwargs.get('cacert', True)

            self.session.cert = (kwargs.get('cert_file'),
                                 kwargs.get('key_file'))
        span_host = tomograph.getHost()
        span_name = "HTTPClient"
        ser_name = "%s[%s]" % (USER_AGENT, span_name)
        tomograph.start_http_h(ser_name, span_name, self.session.headers,
                               span_host, 0)
        tomograph.add_trace_info_header(self.session.headers)
        tomograph.stop(span_name)
Esempio n. 15
0
File: http.py Progetto: hbkqh/patch
    def __init__(self, endpoint, **kwargs):
        self.endpoint = endpoint
        self.identity_headers = kwargs.get("identity_headers")
        self.auth_token = kwargs.get("token")
        if self.identity_headers:
            if self.identity_headers.get("X-Auth-Token"):
                self.auth_token = self.identity_headers.get("X-Auth-Token")
                del self.identity_headers["X-Auth-Token"]

        self.session = requests.Session()
        self.session.headers["User-Agent"] = USER_AGENT

        if self.auth_token:
            self.session.headers["X-Auth-Token"] = self.auth_token

        self.timeout = float(kwargs.get("timeout", 600))

        if self.endpoint.startswith("https"):
            compression = kwargs.get("ssl_compression", True)

            if compression is False:
                # Note: This is not seen by default. (python must be
                # run with -Wd)
                warnings.warn('The "ssl_compression" argument has been ' "deprecated.", DeprecationWarning)

            if kwargs.get("insecure", False) is True:
                self.session.verify = False
            else:
                if kwargs.get("cacert", None) is not "":
                    self.session.verify = kwargs.get("cacert", True)

            self.session.cert = (kwargs.get("cert_file"), kwargs.get("key_file"))
        span_host = tomograph.getHost()
        span_name = "HTTPClient"
        ser_name = "%s[%s]" % (USER_AGENT, span_name)
        tomograph.start_http_h(ser_name, span_name, self.session.headers, span_host, 0)
        tomograph.add_trace_info_header(self.session.headers)
        tomograph.stop(span_name)
Esempio n. 16
0
    def _do_dispatch(self, endpoint, method, ctxt, args, executor_callback):

        #pdb.set_trace()

        trace_info = None
        if ctxt.__contains__("trace_id"):
            trace_info = ctxt.pop("trace_id"), ctxt.pop("span_id")

        ctxt = self.serializer.deserialize_context(ctxt)
        new_args = dict()
        for argname, arg in six.iteritems(args):
            new_args[argname] = self.serializer.deserialize_entity(ctxt, arg)
        func = getattr(endpoint, method)

        span_host = tomograph.getHost()
        ser_name = "%s[%s]" % (func.__module__, func.__name__)
        tomograph.start(ser_name, func.__name__, span_host, 0, trace_info)

        if executor_callback:
            result = executor_callback(func, ctxt, **new_args)
        else:
            result = func(ctxt, **new_args)
        tomograph.stop(func.__name__)
        return self.serializer.serialize_entity(ctxt, result)
Esempio n. 17
0
    def _do_dispatch(self, endpoint, method, ctxt, args, executor_callback):

        #pdb.set_trace()

        trace_info = None
        if ctxt.__contains__("trace_id"):
            trace_info = ctxt.pop("trace_id"), ctxt.pop("span_id")

        ctxt = self.serializer.deserialize_context(ctxt)
        new_args = dict()
        for argname, arg in six.iteritems(args):
            new_args[argname] = self.serializer.deserialize_entity(ctxt, arg)
        func = getattr(endpoint, method)

        span_host = tomograph.getHost()
        ser_name = "%s[%s]" % (func.__module__, func.__name__)
        tomograph.start(ser_name, func.__name__, span_host, 0, trace_info)

        if executor_callback:
            result = executor_callback(func, ctxt, **new_args)
        else:
            result = func(ctxt, **new_args)
        tomograph.stop(func.__name__)
        return self.serializer.serialize_entity(ctxt, result)
Esempio n. 18
0
File: wsgi.py Progetto: hbkqh/patch
    def __call__(self, req):
        arg_dict = req.environ['wsgiorg.routing_args'][1]
        action = arg_dict.pop('action')
        del arg_dict['controller']

        # allow middleware up the stack to provide context, params and headers.
        context = req.environ.get(CONTEXT_ENV, {})
        context['query_string'] = dict(req.params.items())
        context['headers'] = dict(req.headers.items())
        context['path'] = req.environ['PATH_INFO']
        scheme = (None if not CONF.secure_proxy_ssl_header else
                  req.environ.get(CONF.secure_proxy_ssl_header))
        if scheme:
            # NOTE(andrey-mp): "wsgi.url_scheme" contains the protocol used
            # before the proxy removed it ('https' usually). So if
            # the webob.Request instance is modified in order to use this
            # scheme instead of the one defined by API, the call to
            # webob.Request.relative_url() will return a URL with the correct
            # scheme.
            req.environ['wsgi.url_scheme'] = scheme
        context['host_url'] = req.host_url
        params = req.environ.get(PARAMS_ENV, {})
        # authentication and authorization attributes are set as environment
        # values by the container and processed by the pipeline.  the complete
        # set is not yet know.
        context['environment'] = req.environ
        context['accept_header'] = req.accept
        req.environ = None

        params.update(arg_dict)

        context.setdefault('is_admin', False)

        # TODO(termie): do some basic normalization on methods
        method = getattr(self, action)

        # NOTE(morganfainberg): use the request method to normalize the
        # response code between GET and HEAD requests. The HTTP status should
        # be the same.
        LOG.info(
            '%(req_method)s %(uri)s', {
                'req_method': req.environ['REQUEST_METHOD'].upper(),
                'uri': wsgiref.util.request_uri(req.environ),
            })

        params = self._normalize_dict(params)

        try:
            ser_name = "%s[%s]" % (method.__module__, method.__name__)
            tomograph.start_http(ser_name, method.__name__, req)
            result = method(context, **params)
            tomograph.stop(method.__name__)
        except exception.Unauthorized as e:
            LOG.warning(
                _LW("Authorization failed. %(exception)s from "
                    "%(remote_addr)s"), {
                        'exception': e,
                        'remote_addr': req.environ['REMOTE_ADDR']
                    })
            return render_exception(e,
                                    context=context,
                                    user_locale=best_match_language(req))
        except exception.Error as e:
            LOG.warning(six.text_type(e))
            return render_exception(e,
                                    context=context,
                                    user_locale=best_match_language(req))
        except TypeError as e:
            LOG.exception(six.text_type(e))
            return render_exception(exception.ValidationError(e),
                                    context=context,
                                    user_locale=best_match_language(req))
        except Exception as e:
            LOG.exception(six.text_type(e))
            return render_exception(exception.UnexpectedError(exception=e),
                                    context=context,
                                    user_locale=best_match_language(req))
        if result is None:
            return render_response(status=(204, 'No Content'))
        elif isinstance(result, six.string_types):
            return result
        elif isinstance(result, webob.Response):
            return result
        elif isinstance(result, webob.exc.WSGIHTTPException):
            return result

        response_code = self._get_response_code(req)
        return render_response(body=result,
                               status=response_code,
                               method=req.environ['REQUEST_METHOD'])
Esempio n. 19
0
File: shell.py Progetto: hbkqh/patch
    def main(self, argv):
        # Parse args once to find version
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(argv)

        # build available subcommands based on version
        api_version = options.os_identity_api_version
        subcommand_parser = self.get_subcommand_parser(api_version)
        self.parser = subcommand_parser

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if not argv or options.help:
            self.do_help(options)
            return 0

        # Parse args again and call whatever callback was selected
        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help command 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

        if args.debug:
            logging_level = logging.DEBUG
            iso_logger = logging.getLogger('iso8601')
            iso_logger.setLevel('WARN')
        else:
            logging_level = logging.WARNING

        logging.basicConfig(level=logging_level)

        # TODO(heckj): supporting backwards compatibility with environment
        # variables. To be removed after DEVSTACK is updated, ideally in
        # the Grizzly release cycle.
        args.os_token = args.os_token or env('SERVICE_TOKEN')
        args.os_endpoint = args.os_endpoint or env('SERVICE_ENDPOINT')

        if utils.isunauthenticated(args.func):
            self.cs = shell_generic.CLIENT_CLASS(endpoint=args.os_auth_url,
                                                 cacert=args.os_cacert,
                                                 key=args.os_key,
                                                 cert=args.os_cert,
                                                 insecure=args.insecure,
                                                 timeout=args.timeout)
        else:
            self.auth_check(args)
            token = None
            if args.os_token and args.os_endpoint:
                token = args.os_token
            api_version = options.os_identity_api_version
            self.cs = self.get_api_class(api_version)(
                username=args.os_username,
                tenant_name=args.os_tenant_name,
                tenant_id=args.os_tenant_id,
                token=token,
                endpoint=args.os_endpoint,
                password=args.os_password,
                auth_url=args.os_auth_url,
                region_name=args.os_region_name,
                cacert=args.os_cacert,
                key=args.os_key,
                cert=args.os_cert,
                insecure=args.insecure,
                debug=args.debug,
                use_keyring=args.os_cache,
                force_new_token=args.force_new_token,
                stale_duration=args.stale_duration,
                timeout=args.timeout)

        try:
            span_host = tomograph.getHost()
            span_name = ' '.join(sys.argv)
            tomograph.start("keystoneclient-shell", span_name, span_host, 0)
            args.func(self.cs, args)
            tomograph.stop(span_name)
        except exc.Unauthorized:
            tomograph.tag("Exception", "Unauthorized")
            tomograph.stop(span_name)
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        except exc.AuthorizationFailure:
            tomograph.tag("Exception", "AuthorizationFailure")
            tomograph.stop(span_name)
            raise exc.CommandError("Unable to authorize user")
Esempio n. 20
0
File: wsgi.py Progetto: hbkqh/patch
    def _process_stack(self, request, action, action_args,
                       content_type, body, accept):
        """Implement the processing stack."""

        # Get the implementing method
        try:
            meth, extensions = self.get_method(request, action,
                                               content_type, body)
        except (AttributeError, TypeError):
            return Fault(webob.exc.HTTPNotFound())
        except KeyError as ex:
            msg = _("There is no such action: %s") % ex.args[0]
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))
        except exception.MalformedRequestBody:
            msg = _("Malformed request body")
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        ser_name = "%s[%s]" % (meth.__module__, meth.__name__)
        tomograph.start_http(ser_name, meth.__name__, request)

        if body:
            msg = _("Action: '%(action)s', calling method: %(meth)s, body: "
                    "%(body)s") % {'action': action,
                                   'body': six.text_type(body, 'utf-8'),
                                   'meth': str(meth)}
            LOG.debug(strutils.mask_password(msg))
        else:
            LOG.debug("Calling method '%(meth)s'",
                      {'meth': str(meth)})

        # Now, deserialize the request body...
        try:
            contents = {}
            if self._should_have_body(request):
                # allow empty body with PUT and POST
                if request.content_length == 0:
                    contents = {'body': None}
                else:
                    contents = self.deserialize(meth, content_type, body)
        except exception.InvalidContentType:
            msg = _("Unsupported Content-Type")
            tomograph.tag("Exception", "Unsupported Content-Type")
            tomograph.stop(meth.__name__)
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))
        except exception.MalformedRequestBody:
            msg = _("Malformed request body")
            tomograph.tag("Exception", "Malformed request body")
            tomograph.stop(meth.__name__)
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Update the action args
        action_args.update(contents)

        project_id = action_args.pop("project_id", None)
        context = request.environ.get('nova.context')
        if (context and project_id and (project_id != context.project_id)):
            msg = _("Malformed request URL: URL's project_id '%(project_id)s'"
                    " doesn't match Context's project_id"
                    " '%(context_project_id)s'") % \
                    {'project_id': project_id,
                     'context_project_id': context.project_id}
            tomograph.tag("Exception", "HTTPBadRequest")
            tomograph.stop(meth.__name__)
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Run pre-processing extensions
        response, post = self.pre_process_extensions(extensions,
                                                     request, action_args)

        if not response:
            try:
                with ResourceExceptionHandler():
                    action_result = self.dispatch(meth, request, action_args)
            except Fault as ex:
                response = ex

        if not response:
            # No exceptions; convert action_result into a
            # ResponseObject
            resp_obj = None
            if type(action_result) is dict or action_result is None:
                resp_obj = ResponseObject(action_result)
            elif isinstance(action_result, ResponseObject):
                resp_obj = action_result
            else:
                response = action_result

            # Run post-processing extensions
            if resp_obj:
                # Do a preserialize to set up the response object
                serializers = getattr(meth, 'wsgi_serializers', {})
                resp_obj._bind_method_serializers(serializers)
                if hasattr(meth, 'wsgi_code'):
                    resp_obj._default_code = meth.wsgi_code
                resp_obj.preserialize(accept, self.default_serializers)

                # Process post-processing extensions
                response = self.post_process_extensions(post, resp_obj,
                                                        request, action_args)

            if resp_obj and not response:
                response = resp_obj.serialize(request, accept,
                                              self.default_serializers)

        if hasattr(response, 'headers'):

            for hdr, val in response.headers.items():
                # Headers must be utf-8 strings
                response.headers[hdr] = utils.utf8(str(val))

            if not request.api_version_request.is_null():
                response.headers[API_VERSION_REQUEST_HEADER] = \
                    request.api_version_request.get_string()
                response.headers['Vary'] = API_VERSION_REQUEST_HEADER

        tomograph.stop(meth.__name__)

        return response
Esempio n. 21
0
File: shell.py Progetto: hbkqh/patch
    def main(self, argv):
        # Parse args once to find version

        # NOTE(flepied) Under Python3, parsed arguments are removed
        # from the list so make a copy for the first parsing
        base_argv = copy.deepcopy(argv)
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(base_argv)

        span_host = tomograph.getHost()
        span_name = ' '.join(sys.argv)
        tomograph.start("glanceclient-shell", span_name, span_host, 0)

        try:
            # NOTE(flaper87): Try to get the version from the
            # image-url first. If no version was specified, fallback
            # to the api-image-version arg. If both of these fail then
            # fallback to the minimum supported one and let keystone
            # do the magic.
            endpoint = self._get_image_url(options)
            endpoint, url_version = utils.strip_version(endpoint)
        except ValueError:
            # NOTE(flaper87): ValueError is raised if no endpoint is povided
            url_version = None

        # build available subcommands based on version
        try:
            api_version = int(options.os_image_api_version or url_version or 2)
            if api_version not in SUPPORTED_VERSIONS:
                raise ValueError
        except ValueError:
            msg = ("Invalid API version parameter. "
                   "Supported values are %s" % SUPPORTED_VERSIONS)
            utils.exit(msg=msg)

        if api_version == 2:
            switch_version = self._cache_schemas(options)
            if switch_version:
                print('WARNING: The client is falling back to v1 because'
                      ' the accessing to v2 failed. This behavior will'
                      ' be removed in future versions')
                api_version = 1

        try:
            subcommand_parser = self.get_subcommand_parser(api_version)
        except ImportError as e:
            if options.debug:
                traceback.print_exc()
            if not str(e):
                # Add a generic import error message if the raised ImportError
                # has none.
                raise ImportError('Unable to import module. Re-run '
                                  'with --debug for more info.')
            raise
        except Exception:
            if options.debug:
                traceback.print_exc()
            raise

        self.parser = subcommand_parser

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if options.help or not argv:
            self.do_help(options)
            return 0

        # Parse args again and call whatever callback was selected
        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help command 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

        LOG = logging.getLogger('glanceclient')
        LOG.addHandler(logging.StreamHandler())
        LOG.setLevel(logging.DEBUG if args.debug else logging.INFO)

        profile = osprofiler_profiler and options.profile
        if profile:
            osprofiler_profiler.init(options.profile)

        client = self._get_versioned_client(api_version, args,
                                            force_auth=False)

        try:
            # pdb.set_trace()
            args.func(client, args)
        except exc.Unauthorized:
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        except Exception:
            # NOTE(kragniz) Print any exceptions raised to stderr if the
            # --debug flag is set
            if args.debug:
                traceback.print_exc()
            raise
        finally:
            tomograph.stop(span_name)
            if profile:
                trace_id = osprofiler_profiler.get().get_base_id()
                print("Profiling trace ID: %s" % trace_id)
                print("To display trace use next command:\n"
                      "osprofiler trace show --html %s " % trace_id)
Esempio n. 22
0
File: shell.py Progetto: hbkqh/patch
    def main(self, argv):
        # Parse args once to find version
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(argv)

        # build available subcommands based on version
        api_version = options.os_identity_api_version
        subcommand_parser = self.get_subcommand_parser(api_version)
        self.parser = subcommand_parser

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if not argv or options.help:
            self.do_help(options)
            return 0

        # Parse args again and call whatever callback was selected
        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help command 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

        if args.debug:
            logging_level = logging.DEBUG
            iso_logger = logging.getLogger('iso8601')
            iso_logger.setLevel('WARN')
        else:
            logging_level = logging.WARNING

        logging.basicConfig(level=logging_level)

        # TODO(heckj): supporting backwards compatibility with environment
        # variables. To be removed after DEVSTACK is updated, ideally in
        # the Grizzly release cycle.
        args.os_token = args.os_token or env('SERVICE_TOKEN')
        args.os_endpoint = args.os_endpoint or env('SERVICE_ENDPOINT')

        if utils.isunauthenticated(args.func):
            self.cs = shell_generic.CLIENT_CLASS(endpoint=args.os_auth_url,
                                                 cacert=args.os_cacert,
                                                 key=args.os_key,
                                                 cert=args.os_cert,
                                                 insecure=args.insecure,
                                                 timeout=args.timeout)
        else:
            self.auth_check(args)
            token = None
            if args.os_token and args.os_endpoint:
                token = args.os_token
            api_version = options.os_identity_api_version
            self.cs = self.get_api_class(api_version)(
                username=args.os_username,
                tenant_name=args.os_tenant_name,
                tenant_id=args.os_tenant_id,
                token=token,
                endpoint=args.os_endpoint,
                password=args.os_password,
                auth_url=args.os_auth_url,
                region_name=args.os_region_name,
                cacert=args.os_cacert,
                key=args.os_key,
                cert=args.os_cert,
                insecure=args.insecure,
                debug=args.debug,
                use_keyring=args.os_cache,
                force_new_token=args.force_new_token,
                stale_duration=args.stale_duration,
                timeout=args.timeout)

        try:
            span_host = tomograph.getHost()
            span_name = ' '.join(sys.argv)
            tomograph.start("keystoneclient-shell", span_name, span_host, 0)
            args.func(self.cs, args)
            tomograph.stop(span_name)
        except exc.Unauthorized:
            tomograph.tag("Exception", "Unauthorized")
            tomograph.stop(span_name)
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        except exc.AuthorizationFailure:
            tomograph.tag("Exception", "AuthorizationFailure")
            tomograph.stop(span_name)
            raise exc.CommandError("Unable to authorize user")
Esempio n. 23
0
File: shell.py Progetto: hbkqh/patch
    def main(self, argv):
        # Parse args once to find version

        # NOTE(flepied) Under Python3, parsed arguments are removed
        # from the list so make a copy for the first parsing
        base_argv = copy.deepcopy(argv)
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(base_argv)

        span_host = tomograph.getHost()
        span_name = ' '.join(sys.argv)
        tomograph.start("glanceclient-shell", span_name, span_host, 0)

        try:
            # NOTE(flaper87): Try to get the version from the
            # image-url first. If no version was specified, fallback
            # to the api-image-version arg. If both of these fail then
            # fallback to the minimum supported one and let keystone
            # do the magic.
            endpoint = self._get_image_url(options)
            endpoint, url_version = utils.strip_version(endpoint)
        except ValueError:
            # NOTE(flaper87): ValueError is raised if no endpoint is povided
            url_version = None

        # build available subcommands based on version
        try:
            api_version = int(options.os_image_api_version or url_version or 2)
            if api_version not in SUPPORTED_VERSIONS:
                raise ValueError
        except ValueError:
            msg = ("Invalid API version parameter. "
                   "Supported values are %s" % SUPPORTED_VERSIONS)
            utils.exit(msg=msg)

        if api_version == 2:
            switch_version = self._cache_schemas(options)
            if switch_version:
                print('WARNING: The client is falling back to v1 because'
                      ' the accessing to v2 failed. This behavior will'
                      ' be removed in future versions')
                api_version = 1

        try:
            subcommand_parser = self.get_subcommand_parser(api_version)
        except ImportError as e:
            if options.debug:
                traceback.print_exc()
            if not str(e):
                # Add a generic import error message if the raised ImportError
                # has none.
                raise ImportError('Unable to import module. Re-run '
                                  'with --debug for more info.')
            raise
        except Exception:
            if options.debug:
                traceback.print_exc()
            raise

        self.parser = subcommand_parser

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if options.help or not argv:
            self.do_help(options)
            return 0

        # Parse args again and call whatever callback was selected
        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help command 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

        LOG = logging.getLogger('glanceclient')
        LOG.addHandler(logging.StreamHandler())
        LOG.setLevel(logging.DEBUG if args.debug else logging.INFO)

        profile = osprofiler_profiler and options.profile
        if profile:
            osprofiler_profiler.init(options.profile)

        client = self._get_versioned_client(api_version,
                                            args,
                                            force_auth=False)

        try:
            # pdb.set_trace()
            args.func(client, args)
        except exc.Unauthorized:
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        except Exception:
            # NOTE(kragniz) Print any exceptions raised to stderr if the
            # --debug flag is set
            if args.debug:
                traceback.print_exc()
            raise
        finally:
            tomograph.stop(span_name)
            if profile:
                trace_id = osprofiler_profiler.get().get_base_id()
                print("Profiling trace ID: %s" % trace_id)
                print("To display trace use next command:\n"
                      "osprofiler trace show --html %s " % trace_id)
Esempio n. 24
0
File: shell.py Progetto: hbkqh/patch
    def main(self, argv):
        # Parse args once to find version and debug settings
        parser = self.get_base_parser()

        # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.



        if '--endpoint_type' in argv:
            spot = argv.index('--endpoint_type')
            argv[spot] = '--endpoint-type'

        (args, args_list) = parser.parse_known_args(argv)

        self.setup_debugging(args.debug)
        self.extensions = []
        do_help = ('help' in argv) or not argv

        # Discover available auth plugins
        #tomograph.annotate("Discover available auth plugins", "novaclient-shell")
        novaclient.auth_plugin.discover_auth_systems()

        if not args.os_compute_api_version:
            api_version = api_versions.get_api_version(
                DEFAULT_MAJOR_OS_COMPUTE_API_VERSION)
        else:
            api_version = api_versions.get_api_version(
                args.os_compute_api_version)

        os_username = args.os_username
        os_user_id = args.os_user_id
        os_password = None  # Fetched and set later as needed
        os_tenant_name = args.os_tenant_name
        os_tenant_id = args.os_tenant_id
        os_auth_url = args.os_auth_url
        os_region_name = args.os_region_name
        os_auth_system = args.os_auth_system
        endpoint_type = args.endpoint_type
        insecure = args.insecure
        service_type = args.service_type
        service_name = args.service_name
        volume_service_name = args.volume_service_name
        bypass_url = args.bypass_url
        os_cache = args.os_cache
        cacert = args.os_cacert
        timeout = args.timeout

        keystone_session = None
        keystone_auth = None

        # We may have either, both or none of these.
        # If we have both, we don't need USERNAME, PASSWORD etc.
        # Fill in the blanks from the SecretsHelper if possible.
        # Finally, authenticate unless we have both.
        # Note if we don't auth we probably don't have a tenant ID so we can't
        # cache the token.
        auth_token = args.os_auth_token if args.os_auth_token else None
        management_url = bypass_url if bypass_url else None

        if os_auth_system and os_auth_system != "keystone":
            auth_plugin = novaclient.auth_plugin.load_plugin(os_auth_system)
        else:
            auth_plugin = None

        if not endpoint_type:
            endpoint_type = DEFAULT_NOVA_ENDPOINT_TYPE

        # This allow users to use endpoint_type as (internal, public or admin)
        # just like other openstack clients (glance, cinder etc)
        if endpoint_type in ['internal', 'public', 'admin']:
            endpoint_type += 'URL'

        if not service_type:
            # Note(alex_xu): We need discover version first, so if there isn't
            # service type specified, we use default nova service type.
            service_type = DEFAULT_NOVA_SERVICE_TYPE

        # If we have an auth token but no management_url, we must auth anyway.
        # Expired tokens are handled by client.py:_cs_request
        must_auth = not (auth_token and management_url)

        # Do not use Keystone session for cases with no session support. The
        # presence of auth_plugin means os_auth_system is present and is not
        # keystone.
        use_session = True
        if auth_plugin or bypass_url or os_cache or volume_service_name:
            use_session = False

        # FIXME(usrleon): Here should be restrict for project id same as
        # for os_username or os_password but for compatibility it is not.
        if must_auth and not do_help:
            if auth_plugin:
                auth_plugin.parse_opts(args)

            if not auth_plugin or not auth_plugin.opts:
                if not os_username and not os_user_id:
                    raise exc.CommandError(
                        _("You must provide a username "
                          "or user id via --os-username, --os-user-id, "
                          "env[OS_USERNAME] or env[OS_USER_ID]"))

            if not any([args.os_tenant_name, args.os_tenant_id,
                        args.os_project_id, args.os_project_name]):
                raise exc.CommandError(_("You must provide a project name or"
                                         " project id via --os-project-name,"
                                         " --os-project-id, env[OS_PROJECT_ID]"
                                         " or env[OS_PROJECT_NAME]. You may"
                                         " use os-project and os-tenant"
                                         " interchangeably."))

            if not os_auth_url:
                if os_auth_system and os_auth_system != 'keystone':
                    os_auth_url = auth_plugin.get_auth_url()

            if not os_auth_url:
                    raise exc.CommandError(
                        _("You must provide an auth url "
                          "via either --os-auth-url or env[OS_AUTH_URL] "
                          "or specify an auth_system which defines a "
                          "default url with --os-auth-system "
                          "or env[OS_AUTH_SYSTEM]"))

            project_id = args.os_project_id or args.os_tenant_id
            project_name = args.os_project_name or args.os_tenant_name
            if use_session:
                # Not using Nova auth plugin, so use keystone
                with utils.record_time(self.times, args.timings,
                                       'auth_url', args.os_auth_url):
                    keystone_session = (ksession.Session
                                        .load_from_cli_options(args))
                    keystone_auth = self._get_keystone_auth(
                        keystone_session,
                        args.os_auth_url,
                        username=args.os_username,
                        user_id=args.os_user_id,
                        user_domain_id=args.os_user_domain_id,
                        user_domain_name=args.os_user_domain_name,
                        password=args.os_password,
                        auth_token=args.os_auth_token,
                        project_id=project_id,
                        project_name=project_name,
                        project_domain_id=args.os_project_domain_id,
                        project_domain_name=args.os_project_domain_name)

        if not do_help and not any([args.os_tenant_id, args.os_tenant_name,
                                    args.os_project_id, args.os_project_name]):
            raise exc.CommandError(_("You must provide a project name or"
                                     " project id via --os-project-name,"
                                     " --os-project-id, env[OS_PROJECT_ID]"
                                     " or env[OS_PROJECT_NAME]. You may"
                                     " use os-project and os-tenant"
                                     " interchangeably."))

        if not os_auth_url and not do_help:
            raise exc.CommandError(
                _("You must provide an auth url "
                  "via either --os-auth-url or env[OS_AUTH_URL]"))

        # This client is just used to discover api version. Version API needn't
        # microversion, so we just pass version 2 at here.
        #tomograph.annotate("Discover api version", "novaclient-shell")
        self.cs = client.Client(
            api_versions.APIVersion("2.0"),
            os_username, os_password, os_tenant_name,
            tenant_id=os_tenant_id, user_id=os_user_id,
            auth_url=os_auth_url, insecure=insecure,
            region_name=os_region_name, endpoint_type=endpoint_type,
            extensions=self.extensions, service_type=service_type,
            service_name=service_name, auth_system=os_auth_system,
            auth_plugin=auth_plugin, auth_token=auth_token,
            volume_service_name=volume_service_name,
            timings=args.timings, bypass_url=bypass_url,
            os_cache=os_cache, http_log_debug=args.debug,
            cacert=cacert, timeout=timeout,
            session=keystone_session, auth=keystone_auth)

        if not do_help:
            if not api_version.is_latest():
                if api_version > api_versions.APIVersion("2.0"):
                    if not api_version.matches(novaclient.API_MIN_VERSION,
                                               novaclient.API_MAX_VERSION):
                        raise exc.CommandError(
                            _("The specified version isn't supported by "
                              "client. The valid version range is '%(min)s' "
                              "to '%(max)s'") % {
                                "min": novaclient.API_MIN_VERSION.get_string(),
                                "max": novaclient.API_MAX_VERSION.get_string()}
                        )
            api_version = api_versions.discover_version(self.cs, api_version)

        # build available subcommands based on version
        self.extensions = client.discover_extensions(api_version)
        self._run_extension_hooks('__pre_parse_args__')

        subcommand_parser = self.get_subcommand_parser(
            api_version, do_help=do_help)
        self.parser = subcommand_parser

        if args.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

        if not args.service_type:
            service_type = (cliutils.get_service_type(args.func) or
                            DEFAULT_NOVA_SERVICE_TYPE)

        if cliutils.isunauthenticated(args.func):
            # NOTE(alex_xu): We need authentication for discover microversion.
            # But the subcommands may needn't it. If the subcommand needn't,
            # we clear the session arguements.
            keystone_session = None
            keystone_auth = None

        # Recreate client object with discovered version.
        self.cs = client.Client(
            api_version,
            os_username, os_password, os_tenant_name,
            tenant_id=os_tenant_id, user_id=os_user_id,
            auth_url=os_auth_url, insecure=insecure,
            region_name=os_region_name, endpoint_type=endpoint_type,
            extensions=self.extensions, service_type=service_type,
            service_name=service_name, auth_system=os_auth_system,
            auth_plugin=auth_plugin, auth_token=auth_token,
            volume_service_name=volume_service_name,
            timings=args.timings, bypass_url=bypass_url,
            os_cache=os_cache, http_log_debug=args.debug,
            cacert=cacert, timeout=timeout,
            session=keystone_session, auth=keystone_auth)

        # Now check for the password/token of which pieces of the
        # identifying keyring key can come from the underlying client
        span_host = tomograph.getHost()
        span_name = ' '.join(sys.argv)
        # for arg in argv:
        #     if arg[0] is not '-':
        #         span_name = span_name + ' ' + arg
        tomograph.start("novaclient-shell", span_name, span_host, 0)

        if must_auth:
            helper = SecretsHelper(args, self.cs.client)
            self.cs.client.keyring_saver = helper
            if (auth_plugin and auth_plugin.opts and
                    "os_password" not in auth_plugin.opts):
                use_pw = False
            else:
                use_pw = True

            tenant_id = helper.tenant_id
            # Allow commandline to override cache
            if not auth_token:
                auth_token = helper.auth_token
            if not management_url:
                management_url = helper.management_url
            if tenant_id and auth_token and management_url:
                self.cs.client.tenant_id = tenant_id
                self.cs.client.auth_token = auth_token
                self.cs.client.management_url = management_url
                self.cs.client.password_func = lambda: helper.password
            elif use_pw:
                # We're missing something, so auth with user/pass and save
                # the result in our helper.
                self.cs.client.password = helper.password

        try:
            # This does a couple of bits which are useful even if we've
            # got the token + service URL already. It exits fast in that case.
            if not cliutils.isunauthenticated(args.func):
                if not use_session:
                    # Only call authenticate() if Nova auth plugin is used.
                    # If keystone is used, authentication is handled as part
                    # of session.
                    self.cs.authenticate()
        except exc.Unauthorized:
            tomograph.tag("Exception", "Unauthorized")
            tomograph.stop(span_name)
            raise exc.CommandError(_("Invalid OpenStack Nova credentials."))
        except exc.AuthorizationFailure:
            tomograph.tag("Exception", "AuthorizationFailure")
            tomograph.stop(span_name)
            raise exc.CommandError(_("Unable to authorize user"))

        args.func(self.cs, args)

        if args.timings:
            self._dump_timings(self.times + self.cs.get_timings())

        tomograph.stop(span_name)
Esempio n. 25
0
    def _process_stack(self, request, action, action_args, content_type, body,
                       accept):
        """Implement the processing stack."""

        # Get the implementing method
        try:
            meth, extensions = self.get_method(request, action, content_type,
                                               body)
        except (AttributeError, TypeError):
            return Fault(webob.exc.HTTPNotFound())
        except KeyError as ex:
            msg = _("There is no such action: %s") % ex.args[0]
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))
        except exception.MalformedRequestBody:
            msg = _("Malformed request body")
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        ser_name = "%s[%s]" % (meth.__module__, meth.__name__)
        tomograph.start_http(ser_name, meth.__name__, request)

        if body:
            msg = _("Action: '%(action)s', calling method: %(meth)s, body: "
                    "%(body)s") % {
                        'action': action,
                        'body': six.text_type(body, 'utf-8'),
                        'meth': str(meth)
                    }
            LOG.debug(strutils.mask_password(msg))
        else:
            LOG.debug("Calling method '%(meth)s'", {'meth': str(meth)})

        # Now, deserialize the request body...
        try:
            contents = {}
            if self._should_have_body(request):
                # allow empty body with PUT and POST
                if request.content_length == 0:
                    contents = {'body': None}
                else:
                    contents = self.deserialize(meth, content_type, body)
        except exception.InvalidContentType:
            msg = _("Unsupported Content-Type")
            tomograph.tag("Exception", "Unsupported Content-Type")
            tomograph.stop(meth.__name__)
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))
        except exception.MalformedRequestBody:
            msg = _("Malformed request body")
            tomograph.tag("Exception", "Malformed request body")
            tomograph.stop(meth.__name__)
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Update the action args
        action_args.update(contents)

        project_id = action_args.pop("project_id", None)
        context = request.environ.get('nova.context')
        if (context and project_id and (project_id != context.project_id)):
            msg = _("Malformed request URL: URL's project_id '%(project_id)s'"
                    " doesn't match Context's project_id"
                    " '%(context_project_id)s'") % \
                    {'project_id': project_id,
                     'context_project_id': context.project_id}
            tomograph.tag("Exception", "HTTPBadRequest")
            tomograph.stop(meth.__name__)
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Run pre-processing extensions
        response, post = self.pre_process_extensions(extensions, request,
                                                     action_args)

        if not response:
            try:
                with ResourceExceptionHandler():
                    action_result = self.dispatch(meth, request, action_args)
            except Fault as ex:
                response = ex

        if not response:
            # No exceptions; convert action_result into a
            # ResponseObject
            resp_obj = None
            if type(action_result) is dict or action_result is None:
                resp_obj = ResponseObject(action_result)
            elif isinstance(action_result, ResponseObject):
                resp_obj = action_result
            else:
                response = action_result

            # Run post-processing extensions
            if resp_obj:
                # Do a preserialize to set up the response object
                serializers = getattr(meth, 'wsgi_serializers', {})
                resp_obj._bind_method_serializers(serializers)
                if hasattr(meth, 'wsgi_code'):
                    resp_obj._default_code = meth.wsgi_code
                resp_obj.preserialize(accept, self.default_serializers)

                # Process post-processing extensions
                response = self.post_process_extensions(
                    post, resp_obj, request, action_args)

            if resp_obj and not response:
                response = resp_obj.serialize(request, accept,
                                              self.default_serializers)

        if hasattr(response, 'headers'):

            for hdr, val in response.headers.items():
                # Headers must be utf-8 strings
                response.headers[hdr] = utils.utf8(str(val))

            if not request.api_version_request.is_null():
                response.headers[API_VERSION_REQUEST_HEADER] = \
                    request.api_version_request.get_string()
                response.headers['Vary'] = API_VERSION_REQUEST_HEADER

        tomograph.stop(meth.__name__)

        return response
Esempio n. 26
0
    def main(self, argv):
        # Parse args once to find version and debug settings
        parser = self.get_base_parser()

        # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.

        if '--endpoint_type' in argv:
            spot = argv.index('--endpoint_type')
            argv[spot] = '--endpoint-type'

        (args, args_list) = parser.parse_known_args(argv)

        self.setup_debugging(args.debug)
        self.extensions = []
        do_help = ('help' in argv) or not argv

        # Discover available auth plugins
        #tomograph.annotate("Discover available auth plugins", "novaclient-shell")
        novaclient.auth_plugin.discover_auth_systems()

        if not args.os_compute_api_version:
            api_version = api_versions.get_api_version(
                DEFAULT_MAJOR_OS_COMPUTE_API_VERSION)
        else:
            api_version = api_versions.get_api_version(
                args.os_compute_api_version)

        os_username = args.os_username
        os_user_id = args.os_user_id
        os_password = None  # Fetched and set later as needed
        os_tenant_name = args.os_tenant_name
        os_tenant_id = args.os_tenant_id
        os_auth_url = args.os_auth_url
        os_region_name = args.os_region_name
        os_auth_system = args.os_auth_system
        endpoint_type = args.endpoint_type
        insecure = args.insecure
        service_type = args.service_type
        service_name = args.service_name
        volume_service_name = args.volume_service_name
        bypass_url = args.bypass_url
        os_cache = args.os_cache
        cacert = args.os_cacert
        timeout = args.timeout

        keystone_session = None
        keystone_auth = None

        # We may have either, both or none of these.
        # If we have both, we don't need USERNAME, PASSWORD etc.
        # Fill in the blanks from the SecretsHelper if possible.
        # Finally, authenticate unless we have both.
        # Note if we don't auth we probably don't have a tenant ID so we can't
        # cache the token.
        auth_token = args.os_auth_token if args.os_auth_token else None
        management_url = bypass_url if bypass_url else None

        if os_auth_system and os_auth_system != "keystone":
            auth_plugin = novaclient.auth_plugin.load_plugin(os_auth_system)
        else:
            auth_plugin = None

        if not endpoint_type:
            endpoint_type = DEFAULT_NOVA_ENDPOINT_TYPE

        # This allow users to use endpoint_type as (internal, public or admin)
        # just like other openstack clients (glance, cinder etc)
        if endpoint_type in ['internal', 'public', 'admin']:
            endpoint_type += 'URL'

        if not service_type:
            # Note(alex_xu): We need discover version first, so if there isn't
            # service type specified, we use default nova service type.
            service_type = DEFAULT_NOVA_SERVICE_TYPE

        # If we have an auth token but no management_url, we must auth anyway.
        # Expired tokens are handled by client.py:_cs_request
        must_auth = not (auth_token and management_url)

        # Do not use Keystone session for cases with no session support. The
        # presence of auth_plugin means os_auth_system is present and is not
        # keystone.
        use_session = True
        if auth_plugin or bypass_url or os_cache or volume_service_name:
            use_session = False

        # FIXME(usrleon): Here should be restrict for project id same as
        # for os_username or os_password but for compatibility it is not.
        if must_auth and not do_help:
            if auth_plugin:
                auth_plugin.parse_opts(args)

            if not auth_plugin or not auth_plugin.opts:
                if not os_username and not os_user_id:
                    raise exc.CommandError(
                        _("You must provide a username "
                          "or user id via --os-username, --os-user-id, "
                          "env[OS_USERNAME] or env[OS_USER_ID]"))

            if not any([
                    args.os_tenant_name, args.os_tenant_id, args.os_project_id,
                    args.os_project_name
            ]):
                raise exc.CommandError(
                    _("You must provide a project name or"
                      " project id via --os-project-name,"
                      " --os-project-id, env[OS_PROJECT_ID]"
                      " or env[OS_PROJECT_NAME]. You may"
                      " use os-project and os-tenant"
                      " interchangeably."))

            if not os_auth_url:
                if os_auth_system and os_auth_system != 'keystone':
                    os_auth_url = auth_plugin.get_auth_url()

            if not os_auth_url:
                raise exc.CommandError(
                    _("You must provide an auth url "
                      "via either --os-auth-url or env[OS_AUTH_URL] "
                      "or specify an auth_system which defines a "
                      "default url with --os-auth-system "
                      "or env[OS_AUTH_SYSTEM]"))

            project_id = args.os_project_id or args.os_tenant_id
            project_name = args.os_project_name or args.os_tenant_name
            if use_session:
                # Not using Nova auth plugin, so use keystone
                with utils.record_time(self.times, args.timings, 'auth_url',
                                       args.os_auth_url):
                    keystone_session = (
                        ksession.Session.load_from_cli_options(args))
                    keystone_auth = self._get_keystone_auth(
                        keystone_session,
                        args.os_auth_url,
                        username=args.os_username,
                        user_id=args.os_user_id,
                        user_domain_id=args.os_user_domain_id,
                        user_domain_name=args.os_user_domain_name,
                        password=args.os_password,
                        auth_token=args.os_auth_token,
                        project_id=project_id,
                        project_name=project_name,
                        project_domain_id=args.os_project_domain_id,
                        project_domain_name=args.os_project_domain_name)

        if not do_help and not any([
                args.os_tenant_id, args.os_tenant_name, args.os_project_id,
                args.os_project_name
        ]):
            raise exc.CommandError(
                _("You must provide a project name or"
                  " project id via --os-project-name,"
                  " --os-project-id, env[OS_PROJECT_ID]"
                  " or env[OS_PROJECT_NAME]. You may"
                  " use os-project and os-tenant"
                  " interchangeably."))

        if not os_auth_url and not do_help:
            raise exc.CommandError(
                _("You must provide an auth url "
                  "via either --os-auth-url or env[OS_AUTH_URL]"))

        # This client is just used to discover api version. Version API needn't
        # microversion, so we just pass version 2 at here.
        #tomograph.annotate("Discover api version", "novaclient-shell")
        self.cs = client.Client(api_versions.APIVersion("2.0"),
                                os_username,
                                os_password,
                                os_tenant_name,
                                tenant_id=os_tenant_id,
                                user_id=os_user_id,
                                auth_url=os_auth_url,
                                insecure=insecure,
                                region_name=os_region_name,
                                endpoint_type=endpoint_type,
                                extensions=self.extensions,
                                service_type=service_type,
                                service_name=service_name,
                                auth_system=os_auth_system,
                                auth_plugin=auth_plugin,
                                auth_token=auth_token,
                                volume_service_name=volume_service_name,
                                timings=args.timings,
                                bypass_url=bypass_url,
                                os_cache=os_cache,
                                http_log_debug=args.debug,
                                cacert=cacert,
                                timeout=timeout,
                                session=keystone_session,
                                auth=keystone_auth)

        if not do_help:
            if not api_version.is_latest():
                if api_version > api_versions.APIVersion("2.0"):
                    if not api_version.matches(novaclient.API_MIN_VERSION,
                                               novaclient.API_MAX_VERSION):
                        raise exc.CommandError(
                            _("The specified version isn't supported by "
                              "client. The valid version range is '%(min)s' "
                              "to '%(max)s'") %
                            {
                                "min": novaclient.API_MIN_VERSION.get_string(),
                                "max": novaclient.API_MAX_VERSION.get_string()
                            })
            api_version = api_versions.discover_version(self.cs, api_version)

        # build available subcommands based on version
        self.extensions = client.discover_extensions(api_version)
        self._run_extension_hooks('__pre_parse_args__')

        subcommand_parser = self.get_subcommand_parser(api_version,
                                                       do_help=do_help)
        self.parser = subcommand_parser

        if args.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

        if not args.service_type:
            service_type = (cliutils.get_service_type(args.func)
                            or DEFAULT_NOVA_SERVICE_TYPE)

        if cliutils.isunauthenticated(args.func):
            # NOTE(alex_xu): We need authentication for discover microversion.
            # But the subcommands may needn't it. If the subcommand needn't,
            # we clear the session arguements.
            keystone_session = None
            keystone_auth = None

        # Recreate client object with discovered version.
        self.cs = client.Client(api_version,
                                os_username,
                                os_password,
                                os_tenant_name,
                                tenant_id=os_tenant_id,
                                user_id=os_user_id,
                                auth_url=os_auth_url,
                                insecure=insecure,
                                region_name=os_region_name,
                                endpoint_type=endpoint_type,
                                extensions=self.extensions,
                                service_type=service_type,
                                service_name=service_name,
                                auth_system=os_auth_system,
                                auth_plugin=auth_plugin,
                                auth_token=auth_token,
                                volume_service_name=volume_service_name,
                                timings=args.timings,
                                bypass_url=bypass_url,
                                os_cache=os_cache,
                                http_log_debug=args.debug,
                                cacert=cacert,
                                timeout=timeout,
                                session=keystone_session,
                                auth=keystone_auth)

        # Now check for the password/token of which pieces of the
        # identifying keyring key can come from the underlying client
        span_host = tomograph.getHost()
        span_name = ' '.join(sys.argv)
        # for arg in argv:
        #     if arg[0] is not '-':
        #         span_name = span_name + ' ' + arg
        tomograph.start("novaclient-shell", span_name, span_host, 0)

        if must_auth:
            helper = SecretsHelper(args, self.cs.client)
            self.cs.client.keyring_saver = helper
            if (auth_plugin and auth_plugin.opts
                    and "os_password" not in auth_plugin.opts):
                use_pw = False
            else:
                use_pw = True

            tenant_id = helper.tenant_id
            # Allow commandline to override cache
            if not auth_token:
                auth_token = helper.auth_token
            if not management_url:
                management_url = helper.management_url
            if tenant_id and auth_token and management_url:
                self.cs.client.tenant_id = tenant_id
                self.cs.client.auth_token = auth_token
                self.cs.client.management_url = management_url
                self.cs.client.password_func = lambda: helper.password
            elif use_pw:
                # We're missing something, so auth with user/pass and save
                # the result in our helper.
                self.cs.client.password = helper.password

        try:
            # This does a couple of bits which are useful even if we've
            # got the token + service URL already. It exits fast in that case.
            if not cliutils.isunauthenticated(args.func):
                if not use_session:
                    # Only call authenticate() if Nova auth plugin is used.
                    # If keystone is used, authentication is handled as part
                    # of session.
                    self.cs.authenticate()
        except exc.Unauthorized:
            tomograph.tag("Exception", "Unauthorized")
            tomograph.stop(span_name)
            raise exc.CommandError(_("Invalid OpenStack Nova credentials."))
        except exc.AuthorizationFailure:
            tomograph.tag("Exception", "AuthorizationFailure")
            tomograph.stop(span_name)
            raise exc.CommandError(_("Unable to authorize user"))

        args.func(self.cs, args)

        if args.timings:
            self._dump_timings(self.times + self.cs.get_timings())

        tomograph.stop(span_name)
Esempio n. 27
0
File: wsgi.py Progetto: hbkqh/patch
    def __call__(self, req):
        arg_dict = req.environ['wsgiorg.routing_args'][1]
        action = arg_dict.pop('action')
        del arg_dict['controller']

        # allow middleware up the stack to provide context, params and headers.
        context = req.environ.get(CONTEXT_ENV, {})
        context['query_string'] = dict(req.params.items())
        context['headers'] = dict(req.headers.items())
        context['path'] = req.environ['PATH_INFO']
        scheme = (None if not CONF.secure_proxy_ssl_header
                  else req.environ.get(CONF.secure_proxy_ssl_header))
        if scheme:
            # NOTE(andrey-mp): "wsgi.url_scheme" contains the protocol used
            # before the proxy removed it ('https' usually). So if
            # the webob.Request instance is modified in order to use this
            # scheme instead of the one defined by API, the call to
            # webob.Request.relative_url() will return a URL with the correct
            # scheme.
            req.environ['wsgi.url_scheme'] = scheme
        context['host_url'] = req.host_url
        params = req.environ.get(PARAMS_ENV, {})
        # authentication and authorization attributes are set as environment
        # values by the container and processed by the pipeline.  the complete
        # set is not yet know.
        context['environment'] = req.environ
        context['accept_header'] = req.accept
        req.environ = None

        params.update(arg_dict)

        context.setdefault('is_admin', False)

        # TODO(termie): do some basic normalization on methods
        method = getattr(self, action)

        # NOTE(morganfainberg): use the request method to normalize the
        # response code between GET and HEAD requests. The HTTP status should
        # be the same.
        LOG.info('%(req_method)s %(uri)s', {
            'req_method': req.environ['REQUEST_METHOD'].upper(),
            'uri': wsgiref.util.request_uri(req.environ),
        })

        params = self._normalize_dict(params)

        try:
            ser_name = "%s[%s]" % (method.__module__, method.__name__)
            tomograph.start_http(ser_name, method.__name__, req)
            result = method(context, **params)
            tomograph.stop(method.__name__)
        except exception.Unauthorized as e:
            LOG.warning(
                _LW("Authorization failed. %(exception)s from "
                    "%(remote_addr)s"),
                {'exception': e, 'remote_addr': req.environ['REMOTE_ADDR']})
            return render_exception(e, context=context,
                                    user_locale=best_match_language(req))
        except exception.Error as e:
            LOG.warning(six.text_type(e))
            return render_exception(e, context=context,
                                    user_locale=best_match_language(req))
        except TypeError as e:
            LOG.exception(six.text_type(e))
            return render_exception(exception.ValidationError(e),
                                    context=context,
                                    user_locale=best_match_language(req))
        except Exception as e:
            LOG.exception(six.text_type(e))
            return render_exception(exception.UnexpectedError(exception=e),
                                    context=context,
                                    user_locale=best_match_language(req))
        if result is None:
            return render_response(status=(204, 'No Content'))
        elif isinstance(result, six.string_types):
            return result
        elif isinstance(result, webob.Response):
            return result
        elif isinstance(result, webob.exc.WSGIHTTPException):
            return result

        response_code = self._get_response_code(req)
        return render_response(body=result, status=response_code,
                               method=req.environ['REQUEST_METHOD'])