~ubuntu-branches/ubuntu/vivid/neutron/vivid-updates

« back to all changes in this revision

Viewing changes to neutron/plugins/vmware/api_client/eventlet_client.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-03-30 11:17:19 UTC
  • mfrom: (1.1.21)
  • Revision ID: package-import@ubuntu.com-20150330111719-h0gx7233p4jkkgfh
Tags: 1:2015.1~b3-0ubuntu1
* New upstream milestone release:
  - d/control: Align version requirements with upstream.
  - d/control: Add new dependency on oslo-log.
  - d/p/*: Rebase.
  - d/control,d/neutron-plugin-hyperv*: Dropped, decomposed into
    separate project upstream.
  - d/control,d/neutron-plugin-openflow*: Dropped, decomposed into
    separate project upstream.
  - d/neutron-common.install: Add neutron-rootwrap-daemon and 
    neutron-keepalived-state-change binaries.
  - d/rules: Ignore neutron-hyperv-agent when installing; only for Windows.
  - d/neutron-plugin-cisco.install: Drop neutron-cisco-cfg-agent as
    decomposed into separate project upstream.
  - d/neutron-plugin-vmware.install: Drop neutron-check-nsx-config and
    neutron-nsx-manage as decomposed into separate project upstream.
  - d/control: Add dependency on python-neutron-fwaas to neutron-l3-agent.
* d/pydist-overrides: Add overrides for oslo packages.
* d/control: Fixup type in package description (LP: #1263539).
* d/p/fixup-driver-test-execution.patch: Cherry pick fix from upstream VCS
  to support unit test exection in out-of-tree vendor drivers.
* d/neutron-common.postinst: Allow general access to /etc/neutron but limit
  access to root/neutron to /etc/neutron/neutron.conf to support execution
  of unit tests in decomposed vendor drivers.
* d/control: Add dependency on python-neutron-fwaas to neutron-l3-agent
  package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2012 VMware, Inc.
2
 
#
3
 
# All Rights Reserved
4
 
#
5
 
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6
 
# not use this file except in compliance with the License. You may obtain
7
 
# a copy of the License at
8
 
#
9
 
# http://www.apache.org/licenses/LICENSE-2.0
10
 
#
11
 
# Unless required by applicable law or agreed to in writing, software
12
 
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
 
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
 
# License for the specific language governing permissions and limitations
15
 
# under the License.
16
 
#
17
 
 
18
 
import time
19
 
 
20
 
import eventlet
21
 
eventlet.monkey_patch()
22
 
 
23
 
from neutron.i18n import _LE
24
 
from neutron.openstack.common import log as logging
25
 
from neutron.plugins.vmware.api_client import base
26
 
from neutron.plugins.vmware.api_client import eventlet_request
27
 
 
28
 
LOG = logging.getLogger(__name__)
29
 
 
30
 
 
31
 
class EventletApiClient(base.ApiClientBase):
32
 
    """Eventlet-based implementation of NSX ApiClient ABC."""
33
 
 
34
 
    def __init__(self, api_providers, user, password,
35
 
                 concurrent_connections=base.DEFAULT_CONCURRENT_CONNECTIONS,
36
 
                 gen_timeout=base.GENERATION_ID_TIMEOUT,
37
 
                 use_https=True,
38
 
                 connect_timeout=base.DEFAULT_CONNECT_TIMEOUT):
39
 
        '''Constructor
40
 
 
41
 
        :param api_providers: a list of tuples of the form: (host, port,
42
 
            is_ssl).
43
 
        :param user: login username.
44
 
        :param password: login password.
45
 
        :param concurrent_connections: total number of concurrent connections.
46
 
        :param use_https: whether or not to use https for requests.
47
 
        :param connect_timeout: connection timeout in seconds.
48
 
        :param gen_timeout controls how long the generation id is kept
49
 
            if set to -1 the generation id is never timed out
50
 
        '''
51
 
        if not api_providers:
52
 
            api_providers = []
53
 
        self._api_providers = set([tuple(p) for p in api_providers])
54
 
        self._api_provider_data = {}  # tuple(semaphore, session_cookie)
55
 
        for p in self._api_providers:
56
 
            self._set_provider_data(p, (eventlet.semaphore.Semaphore(1), None))
57
 
        self._user = user
58
 
        self._password = password
59
 
        self._concurrent_connections = concurrent_connections
60
 
        self._use_https = use_https
61
 
        self._connect_timeout = connect_timeout
62
 
        self._config_gen = None
63
 
        self._config_gen_ts = None
64
 
        self._gen_timeout = gen_timeout
65
 
 
66
 
        # Connection pool is a list of queues.
67
 
        self._conn_pool = eventlet.queue.PriorityQueue()
68
 
        self._next_conn_priority = 1
69
 
        for host, port, is_ssl in api_providers:
70
 
            for _ in range(concurrent_connections):
71
 
                conn = self._create_connection(host, port, is_ssl)
72
 
                self._conn_pool.put((self._next_conn_priority, conn))
73
 
                self._next_conn_priority += 1
74
 
 
75
 
    def acquire_redirect_connection(self, conn_params, auto_login=True,
76
 
                                    headers=None):
77
 
        """Check out or create connection to redirected NSX API server.
78
 
 
79
 
        Args:
80
 
            conn_params: tuple specifying target of redirect, see
81
 
                self._conn_params()
82
 
            auto_login: returned connection should have valid session cookie
83
 
            headers: headers to pass on if auto_login
84
 
 
85
 
        Returns: An available HTTPConnection instance corresponding to the
86
 
                 specified conn_params. If a connection did not previously
87
 
                 exist, new connections are created with the highest prioity
88
 
                 in the connection pool and one of these new connections
89
 
                 returned.
90
 
        """
91
 
        result_conn = None
92
 
        data = self._get_provider_data(conn_params)
93
 
        if data:
94
 
            # redirect target already exists in provider data and connections
95
 
            # to the provider have been added to the connection pool. Try to
96
 
            # obtain a connection from the pool, note that it's possible that
97
 
            # all connection to the provider are currently in use.
98
 
            conns = []
99
 
            while not self._conn_pool.empty():
100
 
                priority, conn = self._conn_pool.get_nowait()
101
 
                if not result_conn and self._conn_params(conn) == conn_params:
102
 
                    conn.priority = priority
103
 
                    result_conn = conn
104
 
                else:
105
 
                    conns.append((priority, conn))
106
 
            for priority, conn in conns:
107
 
                self._conn_pool.put((priority, conn))
108
 
            # hack: if no free connections available, create new connection
109
 
            # and stash "no_release" attribute (so that we only exceed
110
 
            # self._concurrent_connections temporarily)
111
 
            if not result_conn:
112
 
                conn = self._create_connection(*conn_params)
113
 
                conn.priority = 0  # redirect connections have highest priority
114
 
                conn.no_release = True
115
 
                result_conn = conn
116
 
        else:
117
 
            #redirect target not already known, setup provider lists
118
 
            self._api_providers.update([conn_params])
119
 
            self._set_provider_data(conn_params,
120
 
                                    (eventlet.semaphore.Semaphore(1), None))
121
 
            # redirects occur during cluster upgrades, i.e. results to old
122
 
            # redirects to new, so give redirect targets highest priority
123
 
            priority = 0
124
 
            for i in range(self._concurrent_connections):
125
 
                conn = self._create_connection(*conn_params)
126
 
                conn.priority = priority
127
 
                if i == self._concurrent_connections - 1:
128
 
                    break
129
 
                self._conn_pool.put((priority, conn))
130
 
            result_conn = conn
131
 
        if result_conn:
132
 
            result_conn.last_used = time.time()
133
 
            if auto_login and self.auth_cookie(conn) is None:
134
 
                self._wait_for_login(result_conn, headers)
135
 
        return result_conn
136
 
 
137
 
    def _login(self, conn=None, headers=None):
138
 
        '''Issue login request and update authentication cookie.'''
139
 
        cookie = None
140
 
        g = eventlet_request.LoginRequestEventlet(
141
 
            self, self._user, self._password, conn, headers)
142
 
        g.start()
143
 
        ret = g.join()
144
 
        if ret:
145
 
            if isinstance(ret, Exception):
146
 
                LOG.error(_LE('Login error "%s"'), ret)
147
 
                raise ret
148
 
 
149
 
            cookie = ret.getheader("Set-Cookie")
150
 
            if cookie:
151
 
                LOG.debug("Saving new authentication cookie '%s'", cookie)
152
 
 
153
 
        return cookie
154
 
 
155
 
# Register as subclass.
156
 
base.ApiClientBase.register(EventletApiClient)