コード例 #1
0
ファイル: request.py プロジェクト: ggpaue/api_client
    def _redirect_params(self, conn, headers, allow_release_conn=False):
        """Process redirect response, create new connection if necessary.

        Args:
            conn: connection that returned the redirect response
            headers: response headers of the redirect response
            allow_release_conn: if redirecting to a different server,
                release existing connection back to connection pool.

        Returns: Return tuple(conn, url) where conn is a connection object
            to the redirect target and url is the path of the API request
        """
        url = None
        for name, value in headers:
            if name.lower() == "location":
                url = value
                break
        if not url:
            LOG.warning(_LW("[%d] Received redirect status without location "
                            "header field"), self._rid())
            return (conn, None)
        # Accept location with the following format:
        # 1. /path, redirect to same node
        # 2. scheme://hostname:[port]/path where scheme is https or http
        # Reject others
        # 3. e.g. relative paths, unsupported scheme, unspecified host
        result = urlparse.urlparse(url)
        if not result.scheme and not result.hostname and result.path:
            if result.path[0] == "/":
                if result.query:
                    url = "%s?%s" % (result.path, result.query)
                else:
                    url = result.path
                return (conn, url)      # case 1
            else:
                LOG.warning(_LW("[%(rid)d] Received invalid redirect location:"
                                "'%(url)s'"), {'rid': self._rid(), 'url': url})
                return (conn, None)     # case 3
        elif result.scheme not in ["http", "https"] or not result.hostname:
            LOG.warning(_LW("[%(rid)d] Received malformed redirect "
                            "location: %(url)s"),
                        {'rid': self._rid(), 'url': url})
            return (conn, None)  # case 3
        # case 2, redirect location includes a scheme
        # so setup a new connection and authenticate
        if allow_release_conn:
            self._api_client.release_connection(conn)
        conn_params = (result.hostname, result.port, result.scheme == "https")
        conn = self._api_client.acquire_redirect_connection(conn_params, True,
                                                            self._headers)
        if result.query:
            url = "%s?%s" % (result.path, result.query)
        else:
            url = result.path
        return (conn, url)
コード例 #2
0
    def get_traffic_counters(self, chain, wrap=True, zero=False):
        """Return the sum of the traffic counters of all rules of a chain."""
        cmd_tables = self._get_traffic_counters_cmd_tables(chain, wrap)
        if not cmd_tables:
            LOG.warning(
                _LW('Attempted to get traffic counters of chain %s '
                    'which does not exist'), chain)
            return

        name = get_chain_name(chain, wrap)
        acc = {'pkts': 0, 'bytes': 0}

        for cmd, table in cmd_tables:
            args = [cmd, '-t', table, '-L', name, '-n', '-v', '-x']
            if zero:
                args.append('-Z')
            if self.namespace:
                args = ['ip', 'netns', 'exec', self.namespace] + args
            current_table = self.execute(args, run_as_root=True)
            current_lines = current_table.split('\n')

            for line in current_lines[2:]:
                if not line:
                    break
                data = line.split()
                if (len(data) < 2 or not data[0].isdigit()
                        or not data[1].isdigit()):
                    break

                acc['pkts'] += int(data[0])
                acc['bytes'] += int(data[1])

        return acc
コード例 #3
0
    def get_traffic_counters(self, chain, wrap=True, zero=False):
        """Return the sum of the traffic counters of all rules of a chain."""
        cmd_tables = self._get_traffic_counters_cmd_tables(chain, wrap)
        if not cmd_tables:
            LOG.warning(_LW('Attempted to get traffic counters of chain %s '
                            'which does not exist'), chain)
            return

        name = get_chain_name(chain, wrap)
        acc = {'pkts': 0, 'bytes': 0}

        for cmd, table in cmd_tables:
            args = [cmd, '-t', table, '-L', name, '-n', '-v', '-x']
            if zero:
                args.append('-Z')
            if self.namespace:
                args = ['ip', 'netns', 'exec', self.namespace] + args
            current_table = self.execute(args, run_as_root=True)
            current_lines = current_table.split('\n')

            for line in current_lines[2:]:
                if not line:
                    break
                data = line.split()
                if (len(data) < 2 or
                        not data[0].isdigit() or
                        not data[1].isdigit()):
                    break

                acc['pkts'] += int(data[0])
                acc['bytes'] += int(data[1])

        return acc
コード例 #4
0
    def plug_new(self, network_id, port_id, device_name, mac_address,
                 bridge=None, namespace=None, prefix=None, mtu=None):
        """Plug in the interface."""
        ip = ip_lib.IPWrapper()
        tap_name = self._get_tap_name(device_name, prefix)

        root_dev, ns_dev = ip.add_veth(tap_name, device_name)
        root_dev.disable_ipv6()

        self._ivs_add_port(tap_name, port_id, mac_address)

        ns_dev = ip.device(device_name)
        ns_dev.link.set_address(mac_address)

        mtu = self.conf.network_device_mtu or mtu
        if mtu:
            ns_dev.link.set_mtu(mtu)
            root_dev.link.set_mtu(mtu)
        else:
            LOG.warning(_LW("No MTU configured for port %s"), port_id)

        if namespace:
            namespace_obj = ip.ensure_namespace(namespace)
            namespace_obj.add_device_to_namespace(ns_dev)

        ns_dev.link.set_up()
        root_dev.link.set_up()
コード例 #5
0
    def remove_rule(self, chain, rule, wrap=True, top=False, comment=None):
        """Remove a rule from a chain.

        Note: The rule must be exactly identical to the one that was added.
        You cannot switch arguments around like you can with the iptables
        CLI tool.

        """
        chain = get_chain_name(chain, wrap)
        try:
            if '$' in rule:
                rule = ' '.join(
                    self._wrap_target_chain(e, wrap) for e in rule.split(' '))

            self.rules.remove(IptablesRule(chain, rule, wrap, top,
                                           self.wrap_name,
                                           comment=comment))
            if not wrap:
                self.remove_rules.append(str(IptablesRule(chain, rule, wrap,
                                                          top, self.wrap_name,
                                                          comment=comment)))
        except ValueError:
            LOG.warning(_LW('Tried to remove rule that was not there:'
                            ' %(chain)r %(rule)r %(wrap)r %(top)r'),
                        {'chain': chain, 'rule': rule,
                         'top': top, 'wrap': wrap})
コード例 #6
0
    def api_providers(self):
        """Parse api_providers from response.

        Returns: api_providers in [(host, port, is_ssl), ...] format
        """
        def _provider_from_listen_addr(addr):
            # (pssl|ptcp):<ip>:<port> => (host, port, is_ssl)
            parts = addr.split(':')
            return (parts[1], int(parts[2]), parts[0] == 'pssl')

        try:
            if self.successful():
                ret = []
                body = jsonutils.loads(self.value.body)
                for node in body.get('results', []):
                    for role in node.get('roles', []):
                        if role.get('role') == 'api_provider':
                            addr = role.get('listen_addr')
                            if addr:
                                ret.append(_provider_from_listen_addr(addr))
                return ret
        except Exception as e:
            LOG.warning(_LW("[%(rid)d] Failed to parse API provider: %(e)s"), {
                'rid': self._rid(),
                'e': e
            })
            # intentionally fall through
        return None
コード例 #7
0
 def _weed_out_duplicates(line):
     if line in seen_lines:
         thing = 'chain' if line.startswith(':') else 'rule'
         LOG.warning(_LW("Duplicate iptables %(thing)s detected. This "
                         "may indicate a bug in the the iptables "
                         "%(thing)s generation code. Line: %(line)s"),
                     {'thing': thing, 'line': line})
         return False
     seen_lines.add(line)
     # Leave it alone
     return True
コード例 #8
0
 def _weed_out_duplicates(line):
     if line in seen_lines:
         thing = 'chain' if line.startswith(':') else 'rule'
         LOG.warning(
             _LW("Duplicate iptables %(thing)s detected. This "
                 "may indicate a bug in the the iptables "
                 "%(thing)s generation code. Line: %(line)s"), {
                     'thing': thing,
                     'line': line
                 })
         return False
     seen_lines.add(line)
     # Leave it alone
     return True
コード例 #9
0
 def plug(self, network_id, port_id, device_name, mac_address,
          bridge=None, namespace=None, prefix=None, mtu=None):
     if not ip_lib.device_exists(device_name,
                                 namespace=namespace):
         try:
             self.plug_new(network_id, port_id, device_name, mac_address,
                           bridge, namespace, prefix, mtu)
         except TypeError:
             versionutils.report_deprecated_feature(
                 LOG,
                 _LW('Interface driver does not support MTU parameter. '
                     'This may not work in future releases.'))
             self.plug_new(network_id, port_id, device_name, mac_address,
                           bridge, namespace, prefix)
     else:
         LOG.info(_LI("Device %s already exists"), device_name)
コード例 #10
0
ファイル: client.py プロジェクト: ggpaue/api_client
    def request_response(self, method, url, response):
        """
          response is a modified HTTPResponse object or None.
          response.read() will not work on response as the underlying library
          request_eventlet.ApiRequestEventlet has already called this
          method in order to extract the body and headers for processing.
          ApiRequestEventlet derived classes call .read() and
          .getheaders() on the HTTPResponse objects and store the results in
          the response object's .body and .headers data members for future
          access.
        """
        if response is None:
            # Timeout.
            LOG.error(_LE('Request timed out: %(method)s to %(url)s'),
                      {'method': method, 'url': url})
            raise exceptions.RequestTimeout()

        status = response.status
        LOG.debug("response.status = %(status)s", {'status': status})
        if status == 401:
            raise exceptions.UnAuthorizedRequest()
        # Fail-fast: Check for exception conditions and raise the
        # appropriate exceptions for known error codes.
        if status in [404]:
            LOG.warning(_LW("Resource not found. Response status: %(status)s, "
                            "response body: %(response.body)s"),
                        {'status': status, 'response.body': response.body})
            exceptions.ERROR_MAPPINGS[status](response)
        elif status in exceptions.ERROR_MAPPINGS:
            LOG.error(_LE("Received error code: %s"), status)
            LOG.error(_LE("Server Error Message: %s"), response.body)
            exceptions.ERROR_MAPPINGS[status](response)

        # Continue processing for non-error condition.
        if status != 200 and status != 201 and status != 204:
            LOG.error(_LE("%(method)s to %(url)s, unexpected response code: "
                          "%(status)d (content = '%(body)s')"),
                      {'method': method, 'url': url,
                       'status': response.status, 'body': response.body})
            return None
        return self.request_response_body(response)
コード例 #11
0
    def remove_rule(self, chain, rule, wrap=True, top=False, comment=None):
        """Remove a rule from a chain.

        Note: The rule must be exactly identical to the one that was added.
        You cannot switch arguments around like you can with the iptables
        CLI tool.

        """
        chain = get_chain_name(chain, wrap)
        try:
            if '$' in rule:
                rule = ' '.join(
                    self._wrap_target_chain(e, wrap) for e in rule.split(' '))

            self.rules.remove(
                IptablesRule(chain,
                             rule,
                             wrap,
                             top,
                             self.wrap_name,
                             comment=comment))
            if not wrap:
                self.remove_rules.append(
                    str(
                        IptablesRule(chain,
                                     rule,
                                     wrap,
                                     top,
                                     self.wrap_name,
                                     comment=comment)))
        except ValueError:
            LOG.warning(
                _LW('Tried to remove rule that was not there:'
                    ' %(chain)r %(rule)r %(wrap)r %(top)r'), {
                        'chain': chain,
                        'rule': rule,
                        'top': top,
                        'wrap': wrap
                    })
コード例 #12
0
    def plug_new(self, network_id, port_id, device_name, mac_address,
                 bridge=None, namespace=None, prefix=None, mtu=None):
        """Plugin the interface."""
        ip = ip_lib.IPWrapper()

        # Enable agent to define the prefix
        tap_name = device_name.replace(prefix or self.DEV_NAME_PREFIX,
                                       common.TAP_DEVICE_PREFIX)
        # Create ns_veth in a namespace if one is configured.
        root_veth, ns_veth = ip.add_veth(tap_name, device_name,
                                         namespace2=namespace)
        root_veth.disable_ipv6()
        ns_veth.link.set_address(mac_address)

        mtu = self.conf.network_device_mtu or mtu
        if mtu:
            root_veth.link.set_mtu(mtu)
            ns_veth.link.set_mtu(mtu)
        else:
            LOG.warning(_LW("No MTU configured for port %s"), port_id)

        root_veth.link.set_up()
        ns_veth.link.set_up()
コード例 #13
0
ファイル: base.py プロジェクト: ggpaue/api_client
    def release_connection(self, http_conn, bad_state=False,
                           service_unavail=False, rid=-1):
        '''Mark HTTPConnection instance as available for check-out.

        :param http_conn: An HTTPConnection instance obtained from this
            instance.
        :param bad_state: True if http_conn is known to be in a bad state
                (e.g. connection fault.)
        :service_unavail: True if http_conn returned 503 response.
        :param rid: request id passed in from request eventlet.
        '''
        conn_params = self._conn_params(http_conn)
        if self._conn_params(http_conn) not in self._api_providers:
            LOG.debug("[%(rid)d] Released connection %(conn)s is not an "
                      "API provider for the cluster",
                      {'rid': rid,
                       'conn': utils.ctrl_conn_to_str(http_conn)})
            return
        elif hasattr(http_conn, "no_release"):
            return

        if bad_state:
            # Reconnect to provider.
            LOG.warning(_LW("[%(rid)d] Connection returned in bad state, "
                            "reconnecting to %(conn)s"),
                        {'rid': rid,
                         'conn': utils.ctrl_conn_to_str(http_conn)})
            http_conn.close()
            http_conn = self._create_connection(*self._conn_params(http_conn))
            conns = []
            while not self._conn_pool.empty():
                priority, conn = self._conn_pool.get()
                if self._conn_params(conn) == conn_params:
                    conn.close()
                    continue
                conns.append((priority, conn))
            for priority, conn in conns:
                self._conn_pool.put((priority, conn))
            priority = self._next_conn_priority
            self._next_conn_priority += 1

        elif service_unavail:
            # http_conn returned a service unaviable response, put other
            # connections to the same controller at end of priority queue,
            conns = []
            while not self._conn_pool.empty():
                priority, conn = self._conn_pool.get()
                if self._conn_params(conn) == conn_params:
                    priority = self._next_conn_priority
                    self._next_conn_priority += 1
                conns.append((priority, conn))
            for priority, conn in conns:
                self._conn_pool.put((priority, conn))
            priority = self._next_conn_priority
            self._next_conn_priority += 1
        else:
            priority = http_conn.priority

        self._conn_pool.put((priority, http_conn))
        LOG.debug("[%(rid)d] Released connection %(conn)s. %(qsize)d "
                  "connection(s) available.",
                  {'rid': rid, 'conn': utils.ctrl_conn_to_str(http_conn),
                   'qsize': self._conn_pool.qsize()})
コード例 #14
0
ファイル: usage_i18n.py プロジェクト: ronaldbradford/oslo.log
    #
    # These variables default to respectively:
    #
    #  import oslo_log
    #  oslo_log._options.DEFAULT_LOG_LEVELS
    #  oslo_log._options.log_opts[0].default
    #

    extra_log_level_defaults = [
        'dogpile=INFO',
        'routes=INFO'
        ]

    logging.set_defaults(
        default_log_levels=logging.get_default_log_levels() +
        extra_log_level_defaults)

    # Required setup based on configuration and domain
    logging.setup(CONF, DOMAIN)


if __name__ == '__main__':
    prepare()
    # NOTE: These examples use Oslo i18n marker functions

    LOG.info(_LI("Welcome to Oslo Logging"))
    LOG.debug("A debugging message")  # Debug messages are not translated
    LOG.warning(_LW("A warning occured"))
    LOG.error(_LE("An error occured"))
    LOG.exception(_("An Exception occured"))
コード例 #15
0
 def _respawn_action(self, service_id):
     LOG.warning(_LW("Respawning %(service)s for uuid %(uuid)s"), {
         'service': service_id.service,
         'uuid': service_id.uuid
     })
     self._monitored_processes[service_id].enable()
コード例 #16
0
    #
    # These variables default to respectively:
    #
    #  import oslo_log
    #  oslo_log._options.DEFAULT_LOG_LEVELS
    #  oslo_log._options.log_opts[0].default
    #

    extra_log_level_defaults = [
        'dogpile=INFO',
        'routes=INFO'
        ]

    logging.set_defaults(
        default_log_levels=logging.get_default_log_levels() +
        extra_log_level_defaults)

    # Required setup based on configuration and domain
    logging.setup(CONF, DOMAIN)


if __name__ == '__main__':
    prepare()
    # NOTE: These examples use Oslo i18n marker functions

    LOG.info(_LI("Welcome to Oslo Logging"))
    LOG.debug("A debugging message")  # Debug messages are not translated
    LOG.warning(_LW("A warning occurred"))
    LOG.error(_LE("An error occurred"))
    LOG.exception(_("An Exception occurred"))
コード例 #17
0
ファイル: request.py プロジェクト: ggpaue/api_client
    def _issue_request(self):
        '''Issue a request to a provider.'''
        conn = self.get_conn()
        if conn is None:
            error = Exception(_("No API connections available"))
            self._request_error = error
            return error

        url = self._url
        LOG.debug("[%(rid)d] Issuing - request url: %(conn)s, body: %(body)s",
                  {'rid': self._rid(), 'conn': self._request_str(conn, url),
                   'body': self._body})
        issued_time = time.time()
        is_conn_error = False
        is_conn_service_unavail = False
        response = None
        try:
            redirects = 0
            while redirects <= self._redirects:
                # Update connection with user specified request timeout,
                # the connect timeout is usually smaller so we only set
                # the request timeout after a connection is established
                if conn.sock is None:
                    conn.connect()
                    conn.sock.settimeout(self._http_timeout)
                elif conn.sock.gettimeout() != self._http_timeout:
                    conn.sock.settimeout(self._http_timeout)

                headers = copy.copy(self._headers)
                auth = self._api_client.auth_data(conn)
                headers.update(auth)
                try:
                    if self._body:
                        body = jsonutils.dumps(self._body)
                    else:
                        body = None
                    LOG.debug("Issuing request: self._method = [%(method)s], "
                              "url= %(url)s, body=%(body)s, "
                              "headers=%(headers)s",
                              {'method': self._method, "url": url,
                               "body": body, "headers": headers})
                    conn.request(self._method, url, body, headers)
                except Exception as e:
                    with excutils.save_and_reraise_exception():
                        LOG.warning(
                            _LW("[%(rid)d] Exception issuing request: %(e)s"),
                            {'rid': self._rid(), 'e': e})

                response = conn.getresponse()
                response.body = response.read()
                response.headers = response.getheaders()
                elapsed_time = time.time() - issued_time
                LOG.debug("@@@@@@ [ _issue_request ] [%(rid)d] "
                          "Completed request '%(conn)s': "
                          "%(status)s (%(elapsed)s seconds), "
                          "request.url: %(url)s, "
                          "request.method: %(method)s, "
                          "request.headers: %(headers)s, "
                          "request.body %(body)s,"
                          "response.headers: %(response.headers)s, "
                          "response.body: %(response.body)s",
                          {'rid': self._rid(),
                           'conn': self._request_str(conn, url),
                           'status': response.status,
                           'elapsed': elapsed_time,
                           'method': self._method, "url": url,
                           'headers': headers, 'body': body,
                           'response.headers': response.headers,
                           'response.body': response.body})

                if response.status in (401, 302):
                    # if response.headers:
                    login_msg = self._api_client.login_msg()
                    if auth is None and login_msg:
                        # The connection still has no valid cookie despite
                        # attempts to authenticate and the request has failed
                        # with unauthorized status code. If this isn't a
                        # a request to authenticate, we should abort the
                        # request since there is no point in retrying.
                        if self._url != jsonutils.loads(login_msg)['path']:
                            self._abort = True

                    # If request is unauthorized, clear the session cookie
                    # for the current provider so that subsequent requests
                    # to the same provider triggers re-authentication.
                    self._api_client.set_auth_data(conn, None)

                elif 503 == response.status:
                    is_conn_service_unavail = True

                if response.status not in [301, 307]:
                    break
                elif redirects >= self._redirects:
                    LOG.info(_LI("[%d] Maximum redirects exceeded, aborting "
                                 "request"), self._rid())
                    break
                redirects += 1
                conn, url = self._redirect_params(conn, response.headers,
                                                  self._client_conn is None)
                if url is None:
                    response.status = 500
                    break
                LOG.info(_LI("[%(rid)d] Redirecting request to: %(conn)s"),
                         {'rid': self._rid(),
                          'conn': self._request_str(conn, url)})
                # yield here, just in case we are not out of the loop yet
                eventlet.greenthread.sleep(0)
            # If we receive any of these responses, then
            # our server did not process our request and may be in an
            # errored state. Raise an exception, which will cause the
            # the conn to be released with is_conn_error == True
            # which puts the conn on the back of the client's priority
            # queue.
            if 500 == response.status or 501 < response.status:
                LOG.warning(_LW("[%(rid)d] Request '%(method)s %(url)s' "
                                "received: %(status)s"),
                            {'rid': self._rid(), 'method': self._method,
                             'url': self._url, 'status': response.status})
                raise Exception(_('Server error return: %s'), response.status)
            return response

        except Exception as e:
            if isinstance(e, httpclient.BadStatusLine):
                msg = "Invalid server response"
            else:
                msg = str(e)
            if response is None:
                elapsed_time = time.time() - issued_time
            LOG.warning(_LW("[%(rid)d] Failed request '%(conn)s': '%(msg)s' "
                            "(%(elapsed)s seconds)"),
                        {'rid': self._rid(),
                         'conn': self._request_str(conn, url),
                         'msg': msg, 'elapsed': elapsed_time})
            self._request_error = e
            is_conn_error = True
            return e

        finally:
            # Make sure we release the original connection provided by the
            # acquire_connection() call above.
            if self._client_conn is None:
                self._api_client.release_connection(conn, is_conn_error,
                                                    is_conn_service_unavail,
                                                    rid=self._rid())
コード例 #18
0
 def _respawn_action(self, service_id):
     LOG.warning(_LW("Respawning %(service)s for uuid %(uuid)s"),
                 {'service': service_id.service,
                  'uuid': service_id.uuid})
     self._monitored_processes[service_id].enable()