~ubuntu-branches/ubuntu/utopic/neutron/utopic-updates

« back to all changes in this revision

Viewing changes to neutron/plugins/ml2/drivers/mech_bigswitch/driver.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-10-03 18:45:23 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20141003184523-4mt6dy1q3j8n30c9
Tags: 1:2014.2~rc1-0ubuntu1
* New upstream release candidate:
  - d/p/*: Refreshed.
  - d/control: Add python-requests-mock to BD's.
  - d/control: Align versioned requirements with upstream.
* Transition linuxbridge and openvswitch plugin users to modular
  layer 2 plugin (LP: #1323729):
  - d/control: Mark removed plugin packages as transitional, depend
    on neutron-plugin-ml2, mark oldlibs/extra.
  - d/neutron-plugin-{linuxbridge,openvswitch}.install: Drop.
  - d/control: Depend on neutron-plugin-ml2 for linuxbridge
    agent package.
  - d/neutron-plugin-linuxbridge-agent.upstart: Use ml2 plugin
    configuration files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
13
#    License for the specific language governing permissions and limitations
14
14
#    under the License.
15
 
#
16
 
# @author: Sumit Naiksatam, sumitnaiksatam@gmail.com, Big Switch Networks, Inc.
17
 
# @author: Kevin Benton, Big Switch Networks, Inc.
18
15
import copy
 
16
import datetime
19
17
import httplib
20
18
 
21
19
import eventlet
25
23
from neutron.extensions import portbindings
26
24
from neutron.openstack.common import excutils
27
25
from neutron.openstack.common import log
 
26
from neutron.openstack.common import timeutils
28
27
from neutron.plugins.bigswitch import config as pl_config
29
28
from neutron.plugins.bigswitch import plugin
30
29
from neutron.plugins.bigswitch import servermanager
 
30
from neutron.plugins.common import constants as pconst
31
31
from neutron.plugins.ml2 import driver_api as api
32
32
 
33
33
 
 
34
EXTERNAL_PORT_OWNER = 'neutron:external_port'
34
35
LOG = log.getLogger(__name__)
 
36
put_context_in_serverpool = plugin.put_context_in_serverpool
 
37
 
 
38
# time in seconds to maintain existence of vswitch response
 
39
CACHE_VSWITCH_TIME = 60
35
40
 
36
41
 
37
42
class BigSwitchMechanismDriver(plugin.NeutronRestProxyV2Base,
59
64
                                               'get_floating_ips': False,
60
65
                                               'get_routers': False}
61
66
        self.segmentation_types = ', '.join(cfg.CONF.ml2.type_drivers)
 
67
        # Track hosts running IVS to avoid excessive calls to the backend
 
68
        self.ivs_host_cache = {}
 
69
 
62
70
        LOG.debug(_("Initialization done"))
63
71
 
 
72
    @put_context_in_serverpool
64
73
    def create_network_postcommit(self, context):
65
74
        # create network on the network controller
66
75
        self._send_create_network(context.current)
67
76
 
 
77
    @put_context_in_serverpool
68
78
    def update_network_postcommit(self, context):
69
79
        # update network on the network controller
70
80
        self._send_update_network(context.current)
71
81
 
 
82
    @put_context_in_serverpool
72
83
    def delete_network_postcommit(self, context):
73
84
        # delete network on the network controller
74
85
        self._send_delete_network(context.current)
75
86
 
 
87
    @put_context_in_serverpool
76
88
    def create_port_postcommit(self, context):
77
89
        # create port on the network controller
78
90
        port = self._prepare_port_for_controller(context)
80
92
            self.async_port_create(port["network"]["tenant_id"],
81
93
                                   port["network"]["id"], port)
82
94
 
 
95
    @put_context_in_serverpool
83
96
    def update_port_postcommit(self, context):
84
97
        # update port on the network controller
85
98
        port = self._prepare_port_for_controller(context)
103
116
                            triggered_by_tenant=port["network"]["tenant_id"]
104
117
                        )
105
118
 
 
119
    @put_context_in_serverpool
106
120
    def delete_port_postcommit(self, context):
107
121
        # delete port on the network controller
108
122
        port = context.current
126
140
            # the host_id set
127
141
            return False
128
142
        return prepped_port
 
143
 
 
144
    def bind_port(self, context):
 
145
        """Marks ports as bound.
 
146
 
 
147
        Binds external ports and IVS ports.
 
148
        Fabric configuration will occur on the subsequent port update.
 
149
        Currently only vlan segments are supported.
 
150
        """
 
151
        if context.current['device_owner'] == EXTERNAL_PORT_OWNER:
 
152
            # TODO(kevinbenton): check controller to see if the port exists
 
153
            # so this driver can be run in parallel with others that add
 
154
            # support for external port bindings
 
155
            for segment in context.network.network_segments:
 
156
                if segment[api.NETWORK_TYPE] == pconst.TYPE_VLAN:
 
157
                    context.set_binding(
 
158
                        segment[api.ID], portbindings.VIF_TYPE_BRIDGE,
 
159
                        {portbindings.CAP_PORT_FILTER: False,
 
160
                         portbindings.OVS_HYBRID_PLUG: False})
 
161
                    return
 
162
 
 
163
        # IVS hosts will have a vswitch with the same name as the hostname
 
164
        if self.does_vswitch_exist(context.host):
 
165
            for segment in context.network.network_segments:
 
166
                if segment[api.NETWORK_TYPE] == pconst.TYPE_VLAN:
 
167
                    context.set_binding(
 
168
                        segment[api.ID], portbindings.VIF_TYPE_IVS,
 
169
                        {portbindings.CAP_PORT_FILTER: True,
 
170
                        portbindings.OVS_HYBRID_PLUG: False})
 
171
 
 
172
    def does_vswitch_exist(self, host):
 
173
        """Check if Indigo vswitch exists with the given hostname.
 
174
 
 
175
        Returns True if switch exists on backend.
 
176
        Returns False if switch does not exist.
 
177
        Returns None if backend could not be reached.
 
178
        Caches response from backend.
 
179
        """
 
180
        try:
 
181
            return self._get_cached_vswitch_existence(host)
 
182
        except ValueError:
 
183
            # cache was empty for that switch or expired
 
184
            pass
 
185
 
 
186
        try:
 
187
            self.servers.rest_get_switch(host)
 
188
            exists = True
 
189
        except servermanager.RemoteRestError as e:
 
190
            if e.status == 404:
 
191
                exists = False
 
192
            else:
 
193
                # Another error, return without caching to try again on
 
194
                # next binding
 
195
                return
 
196
        self.ivs_host_cache[host] = {
 
197
            'timestamp': datetime.datetime.now(),
 
198
            'exists': exists
 
199
        }
 
200
        return exists
 
201
 
 
202
    def _get_cached_vswitch_existence(self, host):
 
203
        """Returns cached existence. Old and non-cached raise ValueError."""
 
204
        entry = self.ivs_host_cache.get(host)
 
205
        if not entry:
 
206
            raise ValueError(_('No cache entry for host %s') % host)
 
207
        diff = timeutils.delta_seconds(entry['timestamp'],
 
208
                                       datetime.datetime.now())
 
209
        if diff > CACHE_VSWITCH_TIME:
 
210
            self.ivs_host_cache.pop(host)
 
211
            raise ValueError(_('Expired cache entry for host %s') % host)
 
212
        return entry['exists']