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

« back to all changes in this revision

Viewing changes to neutron/plugins/openvswitch/agent/ovs_neutron_agent.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:
23
23
eventlet.monkey_patch()
24
24
 
25
25
import netaddr
26
 
from neutron.plugins.openvswitch.agent import ovs_dvr_neutron_agent
27
 
from oslo.config import cfg
28
 
from oslo import messaging
 
26
from oslo_config import cfg
 
27
from oslo_log import log as logging
 
28
import oslo_messaging
29
29
from six import moves
30
30
 
 
31
from neutron.agent.common import config
31
32
from neutron.agent import l2population_rpc
32
33
from neutron.agent.linux import ip_lib
33
34
from neutron.agent.linux import ovs_lib
43
44
from neutron.common import utils as q_utils
44
45
from neutron import context
45
46
from neutron.i18n import _LE, _LI, _LW
46
 
from neutron.openstack.common import log as logging
47
47
from neutron.openstack.common import loopingcall
48
48
from neutron.plugins.common import constants as p_const
 
49
from neutron.plugins.openvswitch.agent import ovs_dvr_neutron_agent
49
50
from neutron.plugins.openvswitch.common import constants
50
51
 
51
52
 
119
120
    #   1.0 Initial version
120
121
    #   1.1 Support Security Group RPC
121
122
    #   1.2 Support DVR (Distributed Virtual Router) RPC
122
 
    target = messaging.Target(version='1.2')
 
123
    target = oslo_messaging.Target(version='1.2')
123
124
 
124
125
    def __init__(self, integ_br, tun_br, local_ip,
125
 
                 bridge_mappings, root_helper,
126
 
                 polling_interval, tunnel_types=None,
 
126
                 bridge_mappings, polling_interval, tunnel_types=None,
127
127
                 veth_mtu=None, l2_population=False,
128
128
                 enable_distributed_routing=False,
129
129
                 minimize_polling=False,
138
138
        :param tun_br: name of the tunnel bridge.
139
139
        :param local_ip: local IP address of this hypervisor.
140
140
        :param bridge_mappings: mappings from physical network name to bridge.
141
 
        :param root_helper: utility to use when running shell cmds.
142
141
        :param polling_interval: interval (secs) to poll DB.
143
142
        :param tunnel_types: A list of tunnel types to enable support for in
144
143
               the agent. If set, will automatically set enable_tunneling to
160
159
        super(OVSNeutronAgent, self).__init__()
161
160
        self.use_veth_interconnection = use_veth_interconnection
162
161
        self.veth_mtu = veth_mtu
163
 
        self.root_helper = root_helper
164
162
        self.available_local_vlans = set(moves.xrange(q_const.MIN_VLAN_TAG,
165
163
                                                      q_const.MAX_VLAN_TAG))
166
164
        self.use_call = True
188
186
        # Keep track of int_br's device count for use by _report_state()
189
187
        self.int_br_device_count = 0
190
188
 
191
 
        self.int_br = ovs_lib.OVSBridge(integ_br, self.root_helper)
 
189
        self.int_br = ovs_lib.OVSBridge(integ_br)
192
190
        self.setup_integration_br()
193
191
        # Stores port update notifications for processing in main rpc loop
194
192
        self.updated_ports = set()
253
251
 
254
252
        # Security group agent support
255
253
        self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context,
256
 
                self.sg_plugin_rpc, root_helper, defer_refresh_firewall=True)
 
254
                self.sg_plugin_rpc, defer_refresh_firewall=True)
257
255
 
258
256
        # Initialize iteration counter
259
257
        self.iter_num = 0
294
292
        self.endpoints = [self]
295
293
        # Define the listening consumers for the agent
296
294
        consumers = [[topics.PORT, topics.UPDATE],
 
295
                     [topics.PORT, topics.DELETE],
297
296
                     [topics.NETWORK, topics.DELETE],
298
297
                     [constants.TUNNEL, topics.UPDATE],
 
298
                     [constants.TUNNEL, topics.DELETE],
299
299
                     [topics.SECURITY_GROUP, topics.UPDATE],
300
300
                     [topics.DVR, topics.UPDATE]]
301
301
        if self.l2_pop:
331
331
        self.updated_ports.add(port['id'])
332
332
        LOG.debug("port_update message processed for port %s", port['id'])
333
333
 
 
334
    def port_delete(self, context, **kwargs):
 
335
        port_id = kwargs.get('port_id')
 
336
        port = self.int_br.get_vif_port_by_id(port_id)
 
337
        # If port exists, delete it
 
338
        if port:
 
339
            self.int_br.delete_port(port.port_name)
 
340
 
334
341
    def tunnel_update(self, context, **kwargs):
335
342
        LOG.debug("tunnel_update received")
336
343
        if not self.enable_tunneling:
354
361
            self._setup_tunnel_port(self.tun_br, tun_name, tunnel_ip,
355
362
                                    tunnel_type)
356
363
 
 
364
    def tunnel_delete(self, context, **kwargs):
 
365
        LOG.debug("tunnel_delete received")
 
366
        if not self.enable_tunneling:
 
367
            return
 
368
        tunnel_ip = kwargs.get('tunnel_ip')
 
369
        if not tunnel_ip:
 
370
            LOG.error(_LE("No tunnel_ip specified, cannot delete tunnels"))
 
371
            return
 
372
        tunnel_type = kwargs.get('tunnel_type')
 
373
        if not tunnel_type:
 
374
            LOG.error(_LE("No tunnel_type specified, cannot delete tunnels"))
 
375
            return
 
376
        if tunnel_type not in self.tunnel_types:
 
377
            LOG.error(_LE("tunnel_type %s not supported by agent"),
 
378
                      tunnel_type)
 
379
            return
 
380
        ofport = self.tun_br_ofports[tunnel_type].get(tunnel_ip)
 
381
        self.cleanup_tunnel_port(self.tun_br, ofport, tunnel_type)
 
382
 
 
383
    def _tunnel_port_lookup(self, network_type, remote_ip):
 
384
        return self.tun_br_ofports[network_type].get(remote_ip)
 
385
 
357
386
    def fdb_add(self, context, fdb_entries):
358
387
        LOG.debug("fdb_add received")
359
388
        for lvm, agent_ports in self.get_agent_ports(fdb_entries,
363
392
                if not self.enable_distributed_routing:
364
393
                    with self.tun_br.deferred() as deferred_br:
365
394
                        self.fdb_add_tun(context, deferred_br, lvm,
366
 
                                         agent_ports, self.tun_br_ofports)
 
395
                                         agent_ports, self._tunnel_port_lookup)
367
396
                else:
368
397
                    self.fdb_add_tun(context, self.tun_br, lvm,
369
 
                                     agent_ports, self.tun_br_ofports)
 
398
                                     agent_ports, self._tunnel_port_lookup)
370
399
 
371
400
    def fdb_remove(self, context, fdb_entries):
372
401
        LOG.debug("fdb_remove received")
377
406
                if not self.enable_distributed_routing:
378
407
                    with self.tun_br.deferred() as deferred_br:
379
408
                        self.fdb_remove_tun(context, deferred_br, lvm,
380
 
                                            agent_ports, self.tun_br_ofports)
 
409
                                            agent_ports,
 
410
                                            self._tunnel_port_lookup)
381
411
                else:
382
412
                    self.fdb_remove_tun(context, self.tun_br, lvm,
383
 
                                        agent_ports, self.tun_br_ofports)
 
413
                                        agent_ports, self._tunnel_port_lookup)
384
414
 
385
415
    def add_fdb_flow(self, br, port_info, remote_ip, lvm, ofport):
386
416
        if port_info == q_const.FLOODING_ENTRY:
403
433
 
404
434
    def del_fdb_flow(self, br, port_info, remote_ip, lvm, ofport):
405
435
        if port_info == q_const.FLOODING_ENTRY:
 
436
            if ofport not in lvm.tun_ofports:
 
437
                LOG.debug("attempt to remove a non-existent port %s", ofport)
 
438
                return
406
439
            lvm.tun_ofports.remove(ofport)
407
440
            if len(lvm.tun_ofports) > 0:
408
441
                ofports = _ofport_set_to_str(lvm.tun_ofports)
580
613
        '''Reclaim a local VLAN.
581
614
 
582
615
        :param net_uuid: the network uuid associated with this vlan.
583
 
        :param lvm: a LocalVLANMapping object that tracks (vlan, lsw_id,
584
 
            vif_ids) mapping.
585
616
        '''
586
617
        lvm = self.local_vlan_map.pop(net_uuid, None)
587
618
        if lvm is None:
713
744
    def setup_integration_br(self):
714
745
        '''Setup the integration bridge.
715
746
 
716
 
        Create patch ports and remove all existing flows.
717
 
 
718
 
        :param bridge_name: the name of the integration bridge.
719
 
        :returns: the integration bridge
 
747
        Delete patch ports and remove all existing flows.
720
748
        '''
721
749
        # Ensure the integration bridge is created.
722
750
        # ovs_lib.OVSBridge.create() will run
735
763
 
736
764
    def setup_ancillary_bridges(self, integ_br, tun_br):
737
765
        '''Setup ancillary bridges - for example br-ex.'''
738
 
        ovs = ovs_lib.BaseOVS(self.root_helper)
 
766
        ovs = ovs_lib.BaseOVS()
739
767
        ovs_bridges = set(ovs.get_bridges())
740
768
        # Remove all known bridges
741
769
        ovs_bridges.remove(integ_br)
754
782
        ovs_bridges.difference_update(br_names)
755
783
        ancillary_bridges = []
756
784
        for bridge in ovs_bridges:
757
 
            br = ovs_lib.OVSBridge(bridge, self.root_helper)
 
785
            br = ovs_lib.OVSBridge(bridge)
758
786
            LOG.info(_LI('Adding %s to list of bridges.'), bridge)
759
787
            ancillary_bridges.append(br)
760
788
        return ancillary_bridges
768
796
        :param tun_br_name: the name of the tunnel bridge.
769
797
        '''
770
798
        if not self.tun_br:
771
 
            self.tun_br = ovs_lib.OVSBridge(tun_br_name, self.root_helper)
 
799
            self.tun_br = ovs_lib.OVSBridge(tun_br_name)
772
800
 
773
 
        self.tun_br.reset_bridge()
 
801
        self.tun_br.reset_bridge(secure_mode=True)
774
802
        self.patch_tun_ofport = self.int_br.add_patch_port(
775
803
            cfg.CONF.OVS.int_peer_patch_port, cfg.CONF.OVS.tun_peer_patch_port)
776
804
        self.patch_int_ofport = self.tun_br.add_patch_port(
887
915
        '''Setup the physical network bridges.
888
916
 
889
917
        Creates physical network bridges and links them to the
890
 
        integration bridge using veths.
 
918
        integration bridge using veths or patch ports.
891
919
 
892
920
        :param bridge_mappings: map physical network names to bridge names.
893
921
        '''
894
922
        self.phys_brs = {}
895
923
        self.int_ofports = {}
896
924
        self.phys_ofports = {}
897
 
        ip_wrapper = ip_lib.IPWrapper(self.root_helper)
898
 
        ovs = ovs_lib.BaseOVS(self.root_helper)
 
925
        ip_wrapper = ip_lib.IPWrapper()
 
926
        ovs = ovs_lib.BaseOVS()
899
927
        ovs_bridges = ovs.get_bridges()
900
928
        for physical_network, bridge in bridge_mappings.iteritems():
901
929
            LOG.info(_LI("Mapping physical network %(physical_network)s to "
910
938
                          {'physical_network': physical_network,
911
939
                           'bridge': bridge})
912
940
                sys.exit(1)
913
 
            br = ovs_lib.OVSBridge(bridge, self.root_helper)
 
941
            br = ovs_lib.OVSBridge(bridge)
914
942
            br.remove_all_flows()
915
943
            br.add_flow(priority=1, actions="normal")
916
944
            self.phys_brs[physical_network] = br
923
951
            self.int_br.delete_port(int_if_name)
924
952
            br.delete_port(phys_if_name)
925
953
            if self.use_veth_interconnection:
926
 
                if ip_lib.device_exists(int_if_name, self.root_helper):
927
 
                    ip_lib.IPDevice(int_if_name,
928
 
                                    self.root_helper).link.delete()
 
954
                if ip_lib.device_exists(int_if_name):
 
955
                    ip_lib.IPDevice(int_if_name).link.delete()
929
956
                    # Give udev a chance to process its rules here, to avoid
930
957
                    # race conditions between commands launched by udev rules
931
958
                    # and the subsequent call to ip_wrapper.add_veth
1309
1336
        try:
1310
1337
            return '%08x' % netaddr.IPAddress(ip_address, version=4)
1311
1338
        except Exception:
1312
 
            LOG.warn(_LW("Unable to create tunnel port. "
1313
 
                         "Invalid remote IP: %s"), ip_address)
 
1339
            LOG.warn(_LW("Invalid remote IP: %s"), ip_address)
1314
1340
            return
1315
1341
 
1316
1342
    def tunnel_sync(self):
1318
1344
            for tunnel_type in self.tunnel_types:
1319
1345
                details = self.plugin_rpc.tunnel_sync(self.context,
1320
1346
                                                      self.local_ip,
1321
 
                                                      tunnel_type)
 
1347
                                                      tunnel_type,
 
1348
                                                      cfg.CONF.host)
1322
1349
                if not self.l2_pop:
1323
1350
                    tunnels = details['tunnels']
1324
1351
                    for tunnel in tunnels:
1513
1540
    def daemon_loop(self):
1514
1541
        with polling.get_polling_manager(
1515
1542
            self.minimize_polling,
1516
 
            self.root_helper,
1517
1543
            self.ovsdb_monitor_respawn_interval) as pm:
1518
1544
 
1519
1545
            self.rpc_loop(polling_manager=pm)
1550
1576
        tun_br=config.OVS.tunnel_bridge,
1551
1577
        local_ip=config.OVS.local_ip,
1552
1578
        bridge_mappings=bridge_mappings,
1553
 
        root_helper=config.AGENT.root_helper,
1554
1579
        polling_interval=config.AGENT.polling_interval,
1555
1580
        minimize_polling=config.AGENT.minimize_polling,
1556
1581
        tunnel_types=config.AGENT.tunnel_types,
1576
1601
 
1577
1602
def main():
1578
1603
    cfg.CONF.register_opts(ip_lib.OPTS)
 
1604
    config.register_root_helper(cfg.CONF)
1579
1605
    common_config.init(sys.argv[1:])
1580
1606
    common_config.setup_logging()
1581
1607
    q_utils.log_opt_values(LOG)
1586
1612
        LOG.error(_LE('%s Agent terminated!'), e)
1587
1613
        sys.exit(1)
1588
1614
 
1589
 
    is_xen_compute_host = 'rootwrap-xen-dom0' in agent_config['root_helper']
 
1615
    is_xen_compute_host = 'rootwrap-xen-dom0' in cfg.CONF.AGENT.root_helper
1590
1616
    if is_xen_compute_host:
1591
1617
        # Force ip_lib to always use the root helper to ensure that ip
1592
1618
        # commands target xen dom0 rather than domU.
1593
1619
        cfg.CONF.set_default('ip_lib_force_root', True)
1594
1620
 
1595
 
    agent = OVSNeutronAgent(**agent_config)
 
1621
    try:
 
1622
        agent = OVSNeutronAgent(**agent_config)
 
1623
    except RuntimeError as e:
 
1624
        LOG.error(_LE("%s Agent terminated!"), e)
 
1625
        sys.exit(1)
1596
1626
    signal.signal(signal.SIGTERM, agent._handle_sigterm)
1597
1627
 
1598
1628
    # Start everything.