예제 #1
0
    def acquire_connection(self, auto_login=True, headers=None, rid=-1):
        '''Check out an available HTTPConnection instance.

        Blocks until a connection is available.
        :auto_login: automatically logins before returning conn
        :headers: header to pass on to login attempt
        :param rid: request id passed in from request eventlet.
        :returns: An available HTTPConnection instance or None if no
                 api_providers are configured.
        '''
        if self._conn_pool.empty():
            LOG.debug("[%d] Waiting to acquire API client connection.", rid)
        priority, conn = self._conn_pool.get()
        now = time.time()
        if getattr(conn, 'last_used', now) < now - self.CONN_IDLE_TIMEOUT:
            LOG.info(_LI("[%(rid)d] Connection %(conn)s idle for "
                         "%(sec)0.2f seconds; reconnecting."),
                     {'rid': rid,
                      'conn': api_client.ctrl_conn_to_str(conn),
                      'sec': now - conn.last_used})
            conn = self._create_connection(*self._conn_params(conn))
            self.set_auth_cookie(conn, None)
        conn.last_used = now
        conn.priority = priority  # stash current priority for release
        qsize = self._conn_pool.qsize()
        LOG.debug("[%(rid)d] Acquired connection %(conn)s. %(qsize)d "
                  "connection(s) available.",
                  {'rid': rid, 'conn': api_client.ctrl_conn_to_str(conn),
                   'qsize': qsize})
        if auto_login and self.auth_cookie(conn) is None:
            self._wait_for_login(conn, headers)
        return conn
예제 #2
0
    def run(self):
        while True:
            try:
                if self._stopped:
                    # Gracefully terminate this thread if the _stopped
                    # attribute was set to true
                    LOG.info(_LI("Stopping TaskManager"))
                    break

                # get a task from queue, or timeout for periodic status check
                task = self._get_task()

                try:
                    #if constants.TaskStatus.ROLLBACK == task.status:
                    self._main_thread_exec_task = task
                    self._execute(task)
                finally:
                    self._main_thread_exec_task = None
                    if task.status in [
                            constants.TaskStatus.NONE,
                            constants.TaskStatus.ERROR,
                            constants.TaskStatus.COMPLETED
                    ]:
                        # The thread is killed during _execute(). To guarantee
                        # the task been aborted correctly, put it to the queue.
                        #self._enqueue(task)
                        self._dequeue(task)
                    else:
                        self._enqueue(task)
            except Exception:
                LOG.exception(
                    _LE("TaskManager terminating because "
                        "of an exception"))
                break
예제 #3
0
 def get_vifs_by_ids(self, port_ids):
     interface_info = self.get_ports_attributes(
         "Interface", columns=["name", "external_ids", "ofport"],
         if_exists=True)
     by_id = {}
     for x in interface_info:
         external_ids = self._format_attr(x['external_ids'])
         if x['name'] in consts.FTNT_PORTS and \
                 isinstance(external_ids.get('iface-id'), dict):
             if_ids = set(external_ids.get('iface-id'))
             by_id.update({if_id: x for if_id in if_ids})
         elif x['name'] not in consts.FTNT_PORTS:
             by_id.update({external_ids.get('iface-id'): x})
     result = {}
     for port_id in port_ids:
         result[port_id] = None
         if port_id not in by_id:
             LOG.info(_LI("Port %(port_id)s not present in bridge "
                          "%(br_name)s"),
                      {'port_id': port_id, 'br_name': self.br_name})
             continue
         pinfo = by_id[port_id]
         if not self._check_ofport(port_id, pinfo):
             continue
         mac = pinfo['external_ids'].get('attached-mac')
         result[port_id] = ovs_lib.VifPort(pinfo['name'], pinfo['ofport'],
                                   port_id, mac, self)
     return result
예제 #4
0
    def run(self):
        while True:
            try:
                if self._stopped:
                    # Gracefully terminate this thread if the _stopped
                    # attribute was set to true
                    LOG.info(_LI("Stopping TaskManager"))
                    break

                # get a task from queue, or timeout for periodic status check
                task = self._get_task()

                try:
                    #if constants.TaskStatus.ROLLBACK == task.status:
                    self._main_thread_exec_task = task
                    self._execute(task)
                finally:
                    self._main_thread_exec_task = None
                    if task.status in [constants.TaskStatus.NONE,
                                       constants.TaskStatus.ERROR,
                                       constants.TaskStatus.COMPLETED]:
                        # The thread is killed during _execute(). To guarantee
                        # the task been aborted correctly, put it to the queue.
                        #self._enqueue(task)
                        self._dequeue(task)
                    else:
                        self._enqueue(task)
            except Exception:
                LOG.exception(_LE("TaskManager terminating because "
                                "of an exception"))
                break
예제 #5
0
 def stop(self):
     if self._thread is None:
         return
     self._stopped = True
     self._thread.kill()
     self._thread = None
     # Stop looping call and abort running tasks
     self._monitor.stop()
     if self._monitor_busy:
         self._monitor.wait()
     self._abort()
     LOG.info(_LI("TaskManager terminated"))
예제 #6
0
 def stop(self):
     if self._thread is None:
         return
     self._stopped = True
     self._thread.kill()
     self._thread = None
     # Stop looping call and abort running tasks
     self._monitor.stop()
     if self._monitor_busy:
         self._monitor.wait()
     self._abort()
     LOG.info(_LI("TaskManager terminated"))
예제 #7
0
 def update_network_precommit(self, mech_context):
     """Noop now, it is left here for future."""
     cur_network = mech_context.current
     org_network = mech_context.original
     if cur_network["router:external"] != org_network["router:external"]:
         LOG.info(_LI("update_network_precommit failed: the external "
                      "attribute cannot be updated, instead of updating the"
                      " attribute, the external network only support "
                      "creation from scratch on the admin view. \nThe "
                      "org_network: %(org)s, \nthe cur_network %(cur)s"),
                  {'org': org_network, 'cur': cur_network})
         raise NotImplementedError("The external attribute cannot be "
                                   "updated")
     pass
예제 #8
0
 def update_network_precommit(self, mech_context):
     """Noop now, it is left here for future."""
     cur_network = mech_context.current
     org_network = mech_context.original
     if cur_network["router:external"] != org_network["router:external"]:
         LOG.info(_LI("update_network_precommit failed: the external "
                      "attribute cannot be updated, instead of updating the"
                      " attribute, the external network only support "
                      "creation from scratch on the admin view. \nThe "
                      "org_network: %(org)s, \nthe cur_network %(cur)s"),
                  {'org': org_network, 'cur': cur_network})
         raise NotImplementedError("The external attribute cannot be "
                                   "updated")
     pass
예제 #9
0
    def get_vif_port_by_id(self, port_id):
        ports = self.ovsdb.db_find(
            'Interface', ('external_ids', '=', {'iface-id': port_id}),
            ('external_ids', '!=', {'attached-mac': ''}),
            columns=['external_ids', 'name', 'ofport']).execute()
        for port in ports:
            if self.br_name != self.get_bridge_for_iface(port['name']):
                continue
            if not self._check_ofport(port_id, port):
                continue
            mac = port['external_ids'].get('attached-mac')
            return ovs_lib.VifPort(port['name'], port['ofport'],
                                   port_id, mac, self)

        #import ipdb;ipdb.set_trace()
        LOG.info(_LI("Port %(port_id)s not present in bridge %(br_name)s"),
                 {'port_id': port_id, 'br_name': self.br_name})
예제 #10
0
 def delete_network_postcommit(self, mech_context):
     """Delete network which translates to remove vlan interface
     and related vdom from the fortigate.
     """
     LOG.debug("delete_network_postcommit: called")
     network = mech_context.current
     context = mech_context._plugin_context
     tenant_id = network['tenant_id']
     with context.session.begin(subtransactions=True):
         try:
             utils.delete_vdom(self, context, tenant_id=tenant_id)
             LOG.info(_LI("delete network postcommit: tenant= %(tenant_id)s"
                        " network= %(network)s"),
                      {'tenant_id': tenant_id, 'network': network})
         except Exception as e:
             resources.Exinfo(e)
             raise ml2_exc.MechanismDriverError(
                 method=sys._getframe().f_code.co_name)
예제 #11
0
 def delete_network_postcommit(self, mech_context):
     """Delete network which translates to remove vlan interface
     and related vdom from the fortigate.
     """
     LOG.debug("delete_network_postcommit: called")
     network = mech_context.current
     context = mech_context._plugin_context
     tenant_id = network['tenant_id']
     with context.session.begin(subtransactions=True):
         try:
             utils.delete_vdom(self, context, tenant_id=tenant_id)
             LOG.info(_LI("delete network postcommit: tenant= %(tenant_id)s"
                        " network= %(network)s"),
                      {'tenant_id': tenant_id, 'network': network})
         except Exception as e:
             resources.Exinfo(e)
             raise ml2_exc.MechanismDriverError(
                 method=sys._getframe().f_code.co_name)
예제 #12
0
    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)
                if templates.RELOGIN in url:
                    url = jsonutils.loads(templates.LOGIN)['path']
                    conn.connect()
                    self._api_client._wait_for_login(conn, headers)
                    url = self._url

                cookie = self._api_client.auth_cookie(conn)

                if (self._url != jsonutils.loads(templates.LOGIN)['path'] and
                    cookie):
                    headers['Cookie'] = cookie['Cookie']
                    headers['X-CSRFTOKEN'] = cookie['X-CSRFTOKEN']

                try:
                    if self._body:
                        if (self._url ==
                                jsonutils.loads(templates.LOGIN)['path']):
                            body = urlparse.urlencode(self._body)
                        else:
                            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), "
                          "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,
                           'response.headers': response.headers,
                           'response.body': response.body})

                if response.status in (401, 302):
                    if (cookie is None and
                       self._url != jsonutils.loads(templates.LOGIN)['path']):
                        # 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.
                        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_cookie(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())