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

« back to all changes in this revision

Viewing changes to quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.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:
32
32
from quantum.agent.linux import ip_lib
33
33
from quantum.agent.linux import utils
34
34
from quantum.agent import rpc as agent_rpc
 
35
from quantum.agent import securitygroups_rpc as sg_rpc
35
36
from quantum.common import config as logging_config
36
37
from quantum.common import topics
37
38
from quantum.common import utils as q_utils
78
79
 
79
80
    def get_bridge_name(self, network_id):
80
81
        if not network_id:
81
 
            LOG.warning("Invalid Network ID, will lead to incorrect bridge"
82
 
                        "name")
 
82
            LOG.warning(_("Invalid Network ID, will lead to incorrect bridge"
 
83
                          "name"))
83
84
        bridge_name = BRIDGE_NAME_PREFIX + network_id[0:11]
84
85
        return bridge_name
85
86
 
86
87
    def get_subinterface_name(self, physical_interface, vlan_id):
87
88
        if not vlan_id:
88
 
            LOG.warning("Invalid VLAN ID, will lead to incorrect "
89
 
                        "subinterface name")
 
89
            LOG.warning(_("Invalid VLAN ID, will lead to incorrect "
 
90
                          "subinterface name"))
90
91
        subinterface_name = '%s.%s' % (physical_interface, vlan_id)
91
92
        return subinterface_name
92
93
 
93
94
    def get_tap_device_name(self, interface_id):
94
95
        if not interface_id:
95
 
            LOG.warning("Invalid Interface ID, will lead to incorrect "
96
 
                        "tap device name")
 
96
            LOG.warning(_("Invalid Interface ID, will lead to incorrect "
 
97
                          "tap device name"))
97
98
        tap_device_name = TAP_INTERFACE_PREFIX + interface_id[0:11]
98
99
        return tap_device_name
99
100
 
187
188
        """Create a vlan unless it already exists."""
188
189
        interface = self.get_subinterface_name(physical_interface, vlan_id)
189
190
        if not self.device_exists(interface):
190
 
            LOG.debug("Creating subinterface %s for VLAN %s on interface %s" %
191
 
                      (interface, vlan_id, physical_interface))
 
191
            LOG.debug(_("Creating subinterface %(interface)s for "
 
192
                        "VLAN %(vlan_id)s on interface "
 
193
                        "%(physical_interface)s"),
 
194
                      locals())
192
195
            if utils.execute(['ip', 'link', 'add', 'link',
193
196
                              physical_interface,
194
197
                              'name', interface, 'type', 'vlan', 'id',
197
200
            if utils.execute(['ip', 'link', 'set',
198
201
                              interface, 'up'], root_helper=self.root_helper):
199
202
                return
200
 
            LOG.debug("Done creating subinterface %s" % interface)
 
203
            LOG.debug(_("Done creating subinterface %s"), interface)
201
204
        return interface
202
205
 
203
206
    def update_interface_ip_details(self, destination, source, ips,
234
237
        Create a bridge unless it already exists.
235
238
        """
236
239
        if not self.device_exists(bridge_name):
237
 
            LOG.debug("Starting bridge %s for subinterface %s" % (bridge_name,
238
 
                                                                  interface))
 
240
            LOG.debug(_("Starting bridge %(bridge_name)s for subinterface "
 
241
                        "%(interface)s"), locals())
239
242
            if utils.execute(['brctl', 'addbr', bridge_name],
240
243
                             root_helper=self.root_helper):
241
244
                return
248
251
            if utils.execute(['ip', 'link', 'set', bridge_name,
249
252
                              'up'], root_helper=self.root_helper):
250
253
                return
251
 
            LOG.debug("Done starting bridge %s for subinterface %s" %
252
 
                      (bridge_name, interface))
 
254
            LOG.debug(_("Done starting bridge %(bridge_name)s for "
 
255
                        "subinterface %(interface)s"),
 
256
                      locals())
253
257
 
254
258
        if not interface:
255
259
            return
263
267
                utils.execute(['brctl', 'addif', bridge_name, interface],
264
268
                              root_helper=self.root_helper)
265
269
            except Exception as e:
266
 
                LOG.error("Unable to add %s to %s! Exception: %s", interface,
267
 
                          bridge_name, e)
 
270
                LOG.error(_("Unable to add %(interface)s to %(bridge_name)s! "
 
271
                            "Exception: %(e)s"), locals())
268
272
                return
269
273
 
270
274
    def ensure_physical_in_bridge(self, network_id,
272
276
                                  vlan_id):
273
277
        physical_interface = self.interface_mappings.get(physical_network)
274
278
        if not physical_interface:
275
 
            LOG.error("No mapping for physical network %s" %
 
279
            LOG.error(_("No mapping for physical network %s"),
276
280
                      physical_network)
277
281
            return False
278
282
 
291
295
        """
292
296
        if not self.device_exists(tap_device_name):
293
297
            LOG.debug(_("Tap device: %s does not exist on "
294
 
                        "this host, skipped" % tap_device_name))
 
298
                        "this host, skipped"), tap_device_name)
295
299
            return False
296
300
 
297
301
        bridge_name = self.get_bridge_name(network_id)
343
347
                        if interface.startswith(physical_interface):
344
348
                            self.delete_vlan(interface)
345
349
 
346
 
            LOG.debug("Deleting bridge %s" % bridge_name)
 
350
            LOG.debug(_("Deleting bridge %s"), bridge_name)
347
351
            if utils.execute(['ip', 'link', 'set', bridge_name, 'down'],
348
352
                             root_helper=self.root_helper):
349
353
                return
350
354
            if utils.execute(['brctl', 'delbr', bridge_name],
351
355
                             root_helper=self.root_helper):
352
356
                return
353
 
            LOG.debug("Done deleting bridge %s" % bridge_name)
 
357
            LOG.debug(_("Done deleting bridge %s"), bridge_name)
354
358
 
355
359
        else:
356
 
            LOG.error("Cannot delete bridge %s, does not exist" % bridge_name)
 
360
            LOG.error(_("Cannot delete bridge %s, does not exist"),
 
361
                      bridge_name)
357
362
 
358
363
    def remove_interface(self, bridge_name, interface_name):
359
364
        if self.device_exists(bridge_name):
360
365
            if not self.is_device_on_bridge(interface_name):
361
366
                return True
362
 
            LOG.debug("Removing device %s from bridge %s" %
363
 
                      (interface_name, bridge_name))
 
367
            LOG.debug(_("Removing device %(interface_name)s from bridge "
 
368
                        "%(bridge_name)s"), locals())
364
369
            if utils.execute(['brctl', 'delif', bridge_name, interface_name],
365
370
                             root_helper=self.root_helper):
366
371
                return False
367
 
            LOG.debug("Done removing device %s from bridge %s" %
368
 
                      (interface_name, bridge_name))
 
372
            LOG.debug(_("Done removing device %(interface_name)s from bridge "
 
373
                        "%(bridge_name)s"), locals())
369
374
            return True
370
375
        else:
371
 
            LOG.debug("Cannot remove device %s, bridge %s does not exist" %
372
 
                      (interface_name, bridge_name))
 
376
            LOG.debug(_("Cannot remove device %(interface_name)s bridge "
 
377
                        "%(bridge_name)s does not exist"), locals())
373
378
            return False
374
379
 
375
380
    def delete_vlan(self, interface):
376
381
        if self.device_exists(interface):
377
 
            LOG.debug("Deleting subinterface %s for vlan" % interface)
 
382
            LOG.debug(_("Deleting subinterface %s for vlan"), interface)
378
383
            if utils.execute(['ip', 'link', 'set', interface, 'down'],
379
384
                             root_helper=self.root_helper):
380
385
                return
381
386
            if utils.execute(['ip', 'link', 'delete', interface],
382
387
                             root_helper=self.root_helper):
383
388
                return
384
 
            LOG.debug("Done deleting subinterface %s" % interface)
385
 
 
386
 
 
387
 
class LinuxBridgeRpcCallbacks():
 
389
            LOG.debug(_("Done deleting subinterface %s"), interface)
 
390
 
 
391
 
 
392
class LinuxBridgeRpcCallbacks(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
388
393
 
389
394
    # Set RPC API version to 1.0 by default.
390
 
    RPC_API_VERSION = '1.0'
 
395
    # history
 
396
    #   1.1 Support Security Group RPC
 
397
    RPC_API_VERSION = '1.1'
391
398
 
392
 
    def __init__(self, context, linux_br):
 
399
    def __init__(self, context, agent):
393
400
        self.context = context
394
 
        self.linux_br = linux_br
 
401
        self.agent = agent
 
402
        self.linux_br = agent.linux_br
395
403
 
396
404
    def network_delete(self, context, **kwargs):
397
 
        LOG.debug("network_delete received")
 
405
        LOG.debug(_("network_delete received"))
398
406
        network_id = kwargs.get('network_id')
399
407
        bridge_name = self.linux_br.get_bridge_name(network_id)
400
 
        LOG.debug("Delete %s", bridge_name)
 
408
        LOG.debug(_("Delete %s"), bridge_name)
401
409
        self.linux_br.delete_vlan_bridge(bridge_name)
402
410
 
403
411
    def port_update(self, context, **kwargs):
404
 
        LOG.debug("port_update received")
 
412
        LOG.debug(_("port_update received"))
405
413
        port = kwargs.get('port')
 
414
        if 'security_groups' in port:
 
415
            self.agent.refresh_firewall()
 
416
 
406
417
        if port['admin_state_up']:
407
418
            vlan_id = kwargs.get('vlan_id')
408
419
            physical_network = kwargs.get('physical_network')
425
436
        return dispatcher.RpcDispatcher([self])
426
437
 
427
438
 
428
 
class LinuxBridgeQuantumAgentRPC:
 
439
class LinuxBridgePluginApi(agent_rpc.PluginApi,
 
440
                           sg_rpc.SecurityGroupServerRpcApiMixin):
 
441
    pass
 
442
 
 
443
 
 
444
class LinuxBridgeQuantumAgentRPC(sg_rpc.SecurityGroupAgentRpcMixin):
429
445
 
430
446
    def __init__(self, interface_mappings, polling_interval,
431
447
                 root_helper):
433
449
        self.root_helper = root_helper
434
450
        self.setup_linux_bridge(interface_mappings)
435
451
        self.setup_rpc(interface_mappings.values())
 
452
        self.init_firewall()
436
453
 
437
454
    def setup_rpc(self, physical_interfaces):
438
455
        if physical_interfaces:
442
459
            if devices:
443
460
                mac = utils.get_interface_mac(devices[0].name)
444
461
            else:
445
 
                LOG.error("Unable to obtain MAC address for unique ID. "
446
 
                          "Agent terminated!")
 
462
                LOG.error(_("Unable to obtain MAC address for unique ID. "
 
463
                          "Agent terminated!"))
447
464
                exit(1)
448
465
        self.agent_id = '%s%s' % ('lb', (mac.replace(":", "")))
449
 
        LOG.info("RPC agent_id: %s" % self.agent_id)
 
466
        LOG.info(_("RPC agent_id: %s"), self.agent_id)
450
467
 
451
468
        self.topic = topics.AGENT
452
 
        self.plugin_rpc = agent_rpc.PluginApi(topics.PLUGIN)
 
469
        self.plugin_rpc = LinuxBridgePluginApi(topics.PLUGIN)
453
470
 
454
471
        # RPC network init
455
472
        self.context = context.get_admin_context_without_session()
456
473
        # Handle updates from service
457
474
        self.callbacks = LinuxBridgeRpcCallbacks(self.context,
458
 
                                                 self.linux_br)
 
475
                                                 self)
459
476
        self.dispatcher = self.callbacks.create_rpc_dispatcher()
460
477
        # Define the listening consumers for the agent
461
478
        consumers = [[topics.PORT, topics.UPDATE],
462
 
                     [topics.NETWORK, topics.DELETE]]
 
479
                     [topics.NETWORK, topics.DELETE],
 
480
                     [topics.SECURITY_GROUP, topics.UPDATE]]
463
481
        self.connection = agent_rpc.create_consumers(self.dispatcher,
464
482
                                                     self.topic,
465
483
                                                     consumers)
511
529
 
512
530
    def treat_devices_added(self, devices):
513
531
        resync = False
 
532
        self.prepare_devices_filter(devices)
514
533
        for device in devices:
515
 
            LOG.debug("Port %s added", device)
 
534
            LOG.debug(_("Port %s added"), device)
516
535
            try:
517
536
                details = self.plugin_rpc.get_device_details(self.context,
518
537
                                                             device,
519
538
                                                             self.agent_id)
520
539
            except Exception as e:
521
 
                LOG.debug("Unable to get port details for %s: %s", device, e)
 
540
                LOG.debug(_("Unable to get port details for "
 
541
                            "%(device)s: %(e)s"), locals())
522
542
                resync = True
523
543
                continue
524
544
            if 'port_id' in details:
525
 
                LOG.info("Port %s updated. Details: %s", device, details)
 
545
                LOG.info(_("Port %(device)s updated. Details: %(details)s"),
 
546
                         locals())
526
547
                if details['admin_state_up']:
527
548
                    # create the networking for the port
528
549
                    self.linux_br.add_interface(details['network_id'],
533
554
                    self.remove_port_binding(details['network_id'],
534
555
                                             details['port_id'])
535
556
            else:
536
 
                LOG.info("Device %s not defined on plugin", device)
 
557
                LOG.info(_("Device %s not defined on plugin"), device)
537
558
        return resync
538
559
 
539
560
    def treat_devices_removed(self, devices):
540
561
        resync = False
 
562
        self.remove_devices_filter(devices)
541
563
        for device in devices:
542
 
            LOG.info("Attachment %s removed", device)
 
564
            LOG.info(_("Attachment %s removed"), device)
543
565
            try:
544
566
                details = self.plugin_rpc.update_device_down(self.context,
545
567
                                                             device,
546
568
                                                             self.agent_id)
547
569
            except Exception as e:
548
 
                LOG.debug("port_removed failed for %s: %s", device, e)
 
570
                LOG.debug(_("port_removed failed for %(device)s: %(e)s"),
 
571
                          locals())
549
572
                resync = True
550
573
            if details['exists']:
551
 
                LOG.info("Port %s updated.", device)
 
574
                LOG.info(_("Port %s updated."), device)
552
575
                # Nothing to do regarding local networking
553
576
            else:
554
 
                LOG.debug("Device %s not defined on plugin", device)
 
577
                LOG.debug(_("Device %s not defined on plugin"), device)
555
578
        return resync
556
579
 
557
580
    def daemon_loop(self):
558
581
        sync = True
559
582
        devices = set()
560
583
 
561
 
        LOG.info("LinuxBridge Agent RPC Daemon Started!")
 
584
        LOG.info(_("LinuxBridge Agent RPC Daemon Started!"))
562
585
 
563
586
        while True:
564
587
            start = time.time()
565
588
            if sync:
566
 
                LOG.info("Agent out of sync with plugin!")
 
589
                LOG.info(_("Agent out of sync with plugin!"))
567
590
                devices.clear()
568
591
                sync = False
569
592
 
571
594
 
572
595
            # notify plugin about device deltas
573
596
            if device_info:
574
 
                LOG.debug("Agent loop has new devices!")
 
597
                LOG.debug(_("Agent loop has new devices!"))
575
598
                # If treat devices fails - indicates must resync with plugin
576
599
                sync = self.process_network_devices(device_info)
577
600
                devices = device_info['current']
581
604
            if (elapsed < self.polling_interval):
582
605
                time.sleep(self.polling_interval - elapsed)
583
606
            else:
584
 
                LOG.debug("Loop iteration exceeded interval (%s vs. %s)!",
585
 
                          self.polling_interval, elapsed)
 
607
                LOG.debug(_("Loop iteration exceeded interval "
 
608
                            "(%(polling_interval)s vs. %(elapsed)s)!"),
 
609
                          {'polling_interval': self.polling_interval,
 
610
                           'elapsed': elapsed})
586
611
 
587
612
 
588
613
def main():
589
614
    eventlet.monkey_patch()
590
615
    cfg.CONF(args=sys.argv, project='quantum')
591
 
 
592
 
    # (TODO) gary - swap with common logging
593
616
    logging_config.setup_logging(cfg.CONF)
594
 
 
595
617
    try:
596
618
        interface_mappings = q_utils.parse_mappings(
597
619
            cfg.CONF.LINUX_BRIDGE.physical_interface_mappings)