~ubuntu-branches/ubuntu/raring/quantum/raring-proposed

« back to all changes in this revision

Viewing changes to quantum/plugins/openvswitch/ovs_quantum_plugin.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, Yolanda Robla, James Page, Maru Newby
  • Date: 2013-01-11 09:14:35 UTC
  • mfrom: (2.1.17)
  • Revision ID: package-import@ubuntu.com-20130111091435-vaup7dwmtmajy5oe
Tags: 2013.1~g2-0ubuntu1
[ Chuck Short ]
* New upstream version. 
* debian/patches/fix-quantum-configuration.patch: Refreshed.

[ Yolanda Robla ]
* debian/quantum-l3-agent.quantum-metadata-agent.upstart: Add
  upstart configuration for Metadata Agent.
* debian/quantum-l3-agent.install: Added quantum-ns-metadata-proxy,
  quantum-metadata-agent and metadata_agent.ini.
* debian/patches/fix-quantum-configuration.patch: Update rootwrap
  configuration in metadata_agent.ini file.
* debian/changelog: Updated package version
* d/p/fix-quantum-configuration.patch: refresh patches

[ James Page ]
* d/*.install: Install entry points from bin directory instead
  of easy-install ones generated during the package build process
  (LP: #1085038).
* d/control: Drop BD on python-dev-all; its not required.
* d/rules: Install multiple upstart configurations for quantum-l3-agent.
* d/control: Tidy package descriptions.
* d/*.postrm: Drop as debhelper will generate update-rc.d calls in
  maintainer scripts if required.
* d/quantum-common.postinst: Tweak permissions setting so that /etc/quantum
  is not owned/writable by the quantum user, ensure that /etc/quantum/rootwrap*
  is owned by root:root.
* d/*agent*.postinst: Dropped as permissions now correctly set in
  quantum-common.
* d/patches/fix-quantum-configuration.patch: Re-add dropped fixes rootwrap and
  sqlite defaults for all plugins.
* d/control: Added new BD on alembic (>= 0.4.1~), version python-mock >= 1.0b1.

[ Maru Newby ]
* debian/control: Remove unnecessary openvswitch-vswitch dependency
  from quantum-plugin-openvswitch (LP: #1076747).

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
from quantum.db import db_base_plugin_v2
31
31
from quantum.db import dhcp_rpc_base
32
32
from quantum.db import l3_db
 
33
from quantum.db import l3_rpc_base
 
34
from quantum.db import quota_db
 
35
from quantum.extensions import portbindings
33
36
from quantum.extensions import providernet as provider
34
37
from quantum.openstack.common import cfg
35
38
from quantum.openstack.common import log as logging
44
47
LOG = logging.getLogger(__name__)
45
48
 
46
49
 
47
 
class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin):
 
50
class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin,
 
51
                      l3_rpc_base.L3RpcCallbackMixin):
48
52
 
49
53
    # Set RPC API version to 1.0 by default.
50
54
    RPC_API_VERSION = '1.0'
64
68
        """Agent requests device details"""
65
69
        agent_id = kwargs.get('agent_id')
66
70
        device = kwargs.get('device')
67
 
        LOG.debug("Device %s details requested from %s", device, agent_id)
 
71
        LOG.debug(_("Device %(device)s details requested from %(agent_id)s"),
 
72
                  locals())
68
73
        port = ovs_db_v2.get_port(device)
69
74
        if port:
70
75
            binding = ovs_db_v2.get_network_binding(None, port['network_id'])
79
84
            ovs_db_v2.set_port_status(port['id'], q_const.PORT_STATUS_ACTIVE)
80
85
        else:
81
86
            entry = {'device': device}
82
 
            LOG.debug("%s can not be found in database", device)
 
87
            LOG.debug(_("%s can not be found in database"), device)
83
88
        return entry
84
89
 
85
90
    def update_device_down(self, rpc_context, **kwargs):
87
92
        # (TODO) garyk - live migration and port status
88
93
        agent_id = kwargs.get('agent_id')
89
94
        device = kwargs.get('device')
90
 
        LOG.debug("Device %s no longer exists on %s", device, agent_id)
 
95
        LOG.debug(_("Device %(device)s no longer exists on %(agent_id)s"),
 
96
                  locals())
91
97
        port = ovs_db_v2.get_port(device)
92
98
        if port:
93
99
            entry = {'device': device,
97
103
        else:
98
104
            entry = {'device': device,
99
105
                     'exists': False}
100
 
            LOG.debug("%s can not be found in database", device)
 
106
            LOG.debug(_("%s can not be found in database"), device)
101
107
        return entry
102
108
 
103
109
    def tunnel_sync(self, rpc_context, **kwargs):
120
126
 
121
127
 
122
128
class AgentNotifierApi(proxy.RpcProxy):
123
 
    '''Agent side of the linux bridge rpc API.
 
129
    '''Agent side of the openvswitch rpc API.
124
130
 
125
131
    API version history:
126
132
        1.0 - Initial version.
180
186
    handled, by adding support for extended attributes to the
181
187
    QuantumDbPluginV2 base class. When that occurs, this class should
182
188
    be updated to take advantage of it.
 
189
 
 
190
    The port binding extension enables an external application relay
 
191
    information to and from the plugin.
183
192
    """
184
193
 
185
194
    # This attribute specifies whether the plugin supports or not
186
195
    # bulk operations. Name mangling is used in order to ensure it
187
196
    # is qualified by class
188
197
    __native_bulk_support = True
189
 
    supported_extension_aliases = ["provider", "router"]
 
198
    supported_extension_aliases = ["provider", "router", "binding", "quotas"]
 
199
 
 
200
    network_view = "extension:provider_network:view"
 
201
    network_set = "extension:provider_network:set"
 
202
    binding_view = "extension:port_binding:view"
 
203
    binding_set = "extension:port_binding:set"
190
204
 
191
205
    def __init__(self, configfile=None):
192
206
        ovs_db_v2.initialize()
197
211
                                            constants.TYPE_VLAN,
198
212
                                            constants.TYPE_GRE,
199
213
                                            constants.TYPE_NONE]:
200
 
            LOG.error("Invalid tenant_network_type: %s. "
201
 
                      "Agent terminated!",
 
214
            LOG.error(_("Invalid tenant_network_type: %s. "
 
215
                      "Agent terminated!"),
202
216
                      self.tenant_network_type)
203
217
            sys.exit(1)
204
218
        self.enable_tunneling = cfg.CONF.OVS.enable_tunneling
207
221
            self._parse_tunnel_id_ranges()
208
222
            ovs_db_v2.sync_tunnel_allocations(self.tunnel_id_ranges)
209
223
        elif self.tenant_network_type == constants.TYPE_GRE:
210
 
            LOG.error("Tunneling disabled but tenant_network_type is 'gre'. "
211
 
                      "Agent terminated!")
 
224
            LOG.error(_("Tunneling disabled but tenant_network_type is 'gre'. "
 
225
                      "Agent terminated!"))
212
226
            sys.exit(1)
213
227
        self.setup_rpc()
214
228
 
235
249
                                                 int(vlan_min),
236
250
                                                 int(vlan_max))
237
251
                except ValueError as ex:
238
 
                    LOG.error("Invalid network VLAN range: '%s' - %s. "
239
 
                              "Agent terminated!",
240
 
                              entry, ex)
 
252
                    LOG.error(_("Invalid network VLAN range: "
 
253
                                "'%(range)s' - %(e)s. Agent terminated!"),
 
254
                              {'range': entry, 'e': ex})
241
255
                    sys.exit(1)
242
256
            else:
243
257
                self._add_network(entry)
244
 
        LOG.info("Network VLAN ranges: %s", self.network_vlan_ranges)
 
258
        LOG.info(_("Network VLAN ranges: %s"), self.network_vlan_ranges)
245
259
 
246
260
    def _add_network_vlan_range(self, physical_network, vlan_min, vlan_max):
247
261
        self._add_network(physical_network)
258
272
                tun_min, tun_max = entry.split(':')
259
273
                self.tunnel_id_ranges.append((int(tun_min), int(tun_max)))
260
274
            except ValueError as ex:
261
 
                LOG.error("Invalid tunnel ID range: '%s' - %s. "
262
 
                          "Agent terminated!", entry, ex)
 
275
                LOG.error(_("Invalid tunnel ID range: "
 
276
                            "'%(range)s' - %(e)s. Agent terminated!"),
 
277
                          {'range': entry, 'e': ex})
263
278
                sys.exit(1)
264
 
        LOG.info("Tunnel ID ranges: %s", self.tunnel_id_ranges)
 
279
        LOG.info(_("Tunnel ID ranges: %s"), self.tunnel_id_ranges)
265
280
 
266
281
    # TODO(rkukura) Use core mechanism for attribute authorization
267
282
    # when available.
268
283
 
269
 
    def _check_provider_view_auth(self, context, network):
270
 
        return policy.check(context,
271
 
                            "extension:provider_network:view",
272
 
                            network)
 
284
    def _check_view_auth(self, context, resource, action):
 
285
        return policy.check(context, action, resource)
273
286
 
274
 
    def _enforce_provider_set_auth(self, context, network):
275
 
        return policy.enforce(context,
276
 
                              "extension:provider_network:set",
277
 
                              network)
 
287
    def _enforce_set_auth(self, context, resource, action):
 
288
        policy.enforce(context, action, resource)
278
289
 
279
290
    def _extend_network_dict_provider(self, context, network):
280
 
        if self._check_provider_view_auth(context, network):
 
291
        if self._check_view_auth(context, network, self.network_view):
281
292
            binding = ovs_db_v2.get_network_binding(context.session,
282
293
                                                    network['id'])
283
294
            network[provider.NETWORK_TYPE] = binding.network_type
308
319
            return (None, None, None)
309
320
 
310
321
        # Authorize before exposing plugin details to client
311
 
        self._enforce_provider_set_auth(context, attrs)
 
322
        self._enforce_set_auth(context, attrs, self.network_set)
312
323
 
313
324
        if not network_type_set:
314
325
            msg = _("provider:network_type required")
354
365
            else:
355
366
                segmentation_id = None
356
367
        else:
357
 
            msg = _("provider:network_type %s not supported" % network_type)
 
368
            msg = _("provider:network_type %s not supported") % network_type
358
369
            raise q_exc.InvalidInput(error_message=msg)
359
370
 
360
371
        if network_type in [constants.TYPE_VLAN, constants.TYPE_FLAT]:
361
372
            if physical_network_set:
362
373
                if physical_network not in self.network_vlan_ranges:
363
 
                    msg = _("unknown provider:physical_network %s" %
364
 
                            physical_network)
 
374
                    msg = _("Unknown provider:physical_network "
 
375
                            "%s") % physical_network
365
376
                    raise q_exc.InvalidInput(error_message=msg)
366
377
            elif 'default' in self.network_vlan_ranges:
367
378
                physical_network = 'default'
385
396
            return
386
397
 
387
398
        # Authorize before exposing plugin details to client
388
 
        self._enforce_provider_set_auth(context, attrs)
 
399
        self._enforce_set_auth(context, attrs, self.network_set)
389
400
 
390
401
        msg = _("plugin does not support updating provider attributes")
391
402
        raise q_exc.InvalidInput(error_message=msg)
425
436
            self._extend_network_dict_provider(context, net)
426
437
            self._extend_network_dict_l3(context, net)
427
438
            # note - exception will rollback entire transaction
428
 
        LOG.debug("Created network: %s", net['id'])
 
439
        LOG.debug(_("Created network: %s"), net['id'])
429
440
        return net
430
441
 
431
442
    def update_network(self, context, id, network):
458
469
        self.notifier.network_delete(context, id)
459
470
 
460
471
    def get_network(self, context, id, fields=None):
461
 
        net = super(OVSQuantumPluginV2, self).get_network(context, id, None)
462
 
        self._extend_network_dict_provider(context, net)
463
 
        self._extend_network_dict_l3(context, net)
 
472
        session = context.session
 
473
        with session.begin(subtransactions=True):
 
474
            net = super(OVSQuantumPluginV2, self).get_network(context,
 
475
                                                              id, None)
 
476
            self._extend_network_dict_provider(context, net)
 
477
            self._extend_network_dict_l3(context, net)
464
478
        return self._fields(net, fields)
465
479
 
466
480
    def get_networks(self, context, filters=None, fields=None):
467
 
        nets = super(OVSQuantumPluginV2, self).get_networks(context, filters,
468
 
                                                            None)
469
 
        for net in nets:
470
 
            self._extend_network_dict_provider(context, net)
471
 
            self._extend_network_dict_l3(context, net)
 
481
        session = context.session
 
482
        with session.begin(subtransactions=True):
 
483
            nets = super(OVSQuantumPluginV2, self).get_networks(context,
 
484
                                                                filters,
 
485
                                                                None)
 
486
            for net in nets:
 
487
                self._extend_network_dict_provider(context, net)
 
488
                self._extend_network_dict_l3(context, net)
472
489
 
473
 
        # TODO(rkukura): Filter on extended provider attributes.
474
 
        nets = self._filter_nets_l3(context, nets, filters)
 
490
            # TODO(rkukura): Filter on extended provider attributes.
 
491
            nets = self._filter_nets_l3(context, nets, filters)
475
492
 
476
493
        return [self._fields(net, fields) for net in nets]
477
494
 
 
495
    def _extend_port_dict_binding(self, context, port):
 
496
        if self._check_view_auth(context, port, self.binding_view):
 
497
            port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_OVS
 
498
        return port
 
499
 
 
500
    def create_port(self, context, port):
 
501
        port = super(OVSQuantumPluginV2, self).create_port(context, port)
 
502
        return self._extend_port_dict_binding(context, port)
 
503
 
 
504
    def get_port(self, context, id, fields=None):
 
505
        port = super(OVSQuantumPluginV2, self).get_port(context, id, fields)
 
506
        return self._fields(self._extend_port_dict_binding(context, port),
 
507
                            fields)
 
508
 
 
509
    def get_ports(self, context, filters=None, fields=None):
 
510
        ports = super(OVSQuantumPluginV2, self).get_ports(context, filters,
 
511
                                                          fields)
 
512
        return [self._fields(self._extend_port_dict_binding(context, port),
 
513
                             fields) for port in ports]
 
514
 
478
515
    def update_port(self, context, id, port):
479
516
        original_port = super(OVSQuantumPluginV2, self).get_port(context,
480
517
                                                                 id)
486
523
                                      binding.network_type,
487
524
                                      binding.segmentation_id,
488
525
                                      binding.physical_network)
489
 
        return port
 
526
        return self._extend_port_dict_binding(context, port)
490
527
 
491
528
    def delete_port(self, context, id, l3_port_check=True):
492
529