]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Move MidonetInterfaceDriver and use mm-ctl
authorjoe@midokura.com <ih@ih.defaultdomain>
Fri, 25 Oct 2013 09:01:27 +0000 (09:01 +0000)
committerGerrit Code Review <review@openstack.org>
Fri, 22 Nov 2013 02:15:52 +0000 (02:15 +0000)
* Change the plug method in MidonetInterfaceDriver to use mm-ctl
* Move MidonetInterfaceDriver to interface.py
* adapt interface driver midonet unit tests to mm-ctl

Change-Id: Ib6cfbc212b793fa939cad17017c0b2b8b0a5b7fb
Closes-Bug: #1245797

etc/neutron/rootwrap.d/dhcp.filters
etc/neutron/rootwrap.d/lbaas-haproxy.filters
neutron/agent/linux/interface.py
neutron/plugins/midonet/agent/midonet_driver.py
neutron/tests/unit/midonet/test_midonet_driver.py
neutron/tests/unit/test_linux_interface.py

index 02e091375a10a1fb4abefcc4e68e444c0e13d9b3..88d61e8e30fdf53a6653b4a196f3ccd24991772c 100644 (file)
@@ -18,6 +18,7 @@ kill_dnsmasq_usr: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP
 
 ovs-vsctl: CommandFilter, ovs-vsctl, root
 ivs-ctl: CommandFilter, ivs-ctl, root
+mm-ctl: CommandFilter, mm-ctl, root
 dhcp_release: CommandFilter, dhcp_release, root
 
 # metadata proxy
index aaf6be399f8ee924f297bd97060bf5e5f8d55e7c..fb2641d2cea9bb9982bb06120a4e3b944b2cd519 100644 (file)
@@ -15,6 +15,7 @@ haproxy: CommandFilter, haproxy, root
 kill_haproxy_usr: KillFilter, root, /usr/sbin/haproxy, -9, -HUP
 
 ovs-vsctl: CommandFilter, ovs-vsctl, root
+mm-ctl: CommandFilter, mm-ctl, root
 
 # ip_lib
 ip: IpFilter, ip, root
index 42a1f82d15d9fcbe49865d859156bf3902818634..8bb62058a34f0dd84e40f56b7c67acbfa754f046 100644 (file)
@@ -219,6 +219,50 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
                       device_name)
 
 
+class MidonetInterfaceDriver(LinuxInterfaceDriver):
+
+    def plug(self, network_id, port_id, device_name, mac_address,
+             bridge=None, namespace=None, prefix=None):
+        """This method is called by the Dhcp agent or by the L3 agent
+        when a new network is created
+        """
+        if not ip_lib.device_exists(device_name,
+                                    self.root_helper,
+                                    namespace=namespace):
+            ip = ip_lib.IPWrapper(self.root_helper)
+            tap_name = device_name.replace(prefix or 'tap', 'tap')
+
+            # Create ns_dev in a namespace if one is configured.
+            root_dev, ns_dev = ip.add_veth(tap_name, device_name,
+                                           namespace2=namespace)
+
+            ns_dev.link.set_address(mac_address)
+
+            # Add an interface created by ovs to the namespace.
+            namespace_obj = ip.ensure_namespace(namespace)
+            namespace_obj.add_device_to_namespace(ns_dev)
+
+            ns_dev.link.set_up()
+            root_dev.link.set_up()
+
+            cmd = ['mm-ctl', '--bind-port', port_id, device_name]
+            utils.execute(cmd, self.root_helper)
+
+        else:
+            LOG.warn(_("Device %s already exists"), device_name)
+
+    def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
+        # the port will be deleted by the dhcp agent that will call the plugin
+        device = ip_lib.IPDevice(device_name,
+                                 self.root_helper,
+                                 namespace)
+        device.link.delete()
+        LOG.debug(_("Unplugged interface '%s'"), device_name)
+
+        ip_lib.IPWrapper(
+            self.root_helper, namespace).garbage_collect_namespace()
+
+
 class IVSInterfaceDriver(LinuxInterfaceDriver):
     """Driver for creating an internal interface on an IVS bridge."""
 
index ccdc4ade2ee82c895891e465e08d859215b761dd..2bbd573df2cafebcc1c9fee1c1a55d6ac0c4f59c 100644 (file)
 # @author: Tomoe Sugihara, Midokura Japan KK
 # @author: Ryu Ishimoto, Midokura Japan KK
 
-from midonetclient import api
-from oslo.config import cfg
-from webob import exc as w_exc
-
 from neutron.agent.linux import dhcp
-from neutron.agent.linux import interface
-from neutron.agent.linux import ip_lib
 from neutron.openstack.common import log as logging
 from neutron.plugins.midonet.common import config  # noqa
 
@@ -59,83 +53,3 @@ class DhcpNoOpDriver(dhcp.DhcpLocalProcess):
 
     def spawn_process(self):
         pass
-
-
-class MidonetInterfaceDriver(interface.LinuxInterfaceDriver):
-    def __init__(self, conf):
-        super(MidonetInterfaceDriver, self).__init__(conf)
-        # Read config values
-        midonet_conf = conf.MIDONET
-        midonet_uri = midonet_conf.midonet_uri
-        admin_user = midonet_conf.username
-        admin_pass = midonet_conf.password
-        admin_project_id = midonet_conf.project_id
-
-        self.mido_api = api.MidonetApi(midonet_uri, admin_user,
-                                       admin_pass,
-                                       project_id=admin_project_id)
-
-    def _get_host_uuid(self):
-        """Get MidoNet host id from host_uuid.properties file."""
-        f = open(cfg.CONF.MIDONET.midonet_host_uuid_path)
-        lines = f.readlines()
-        host_uuid = filter(lambda x: x.startswith('host_uuid='),
-                           lines)[0].strip()[len('host_uuid='):]
-        return host_uuid
-
-    def plug(self, network_id, port_id, device_name, mac_address,
-             bridge=None, namespace=None, prefix=None):
-        """This method is called by the Dhcp agent or by the L3 agent
-        when a new network is created
-        """
-        if not ip_lib.device_exists(device_name,
-                                    self.root_helper,
-                                    namespace=namespace):
-            ip = ip_lib.IPWrapper(self.root_helper)
-            tap_name = device_name.replace(prefix or 'tap', 'tap')
-
-            # Create ns_dev in a namespace if one is configured.
-            root_dev, ns_dev = ip.add_veth(tap_name,
-                                           device_name,
-                                           namespace2=namespace)
-
-            ns_dev.link.set_address(mac_address)
-
-            # Add an interface created by ovs to the namespace.
-            namespace_obj = ip.ensure_namespace(namespace)
-            namespace_obj.add_device_to_namespace(ns_dev)
-
-            ns_dev.link.set_up()
-            root_dev.link.set_up()
-
-            vport_id = port_id
-            host_dev_name = device_name
-
-            # create if-vport mapping.
-            host_uuid = self._get_host_uuid()
-            try:
-                host = self.mido_api.get_host(host_uuid)
-            except w_exc.HTTPError as e:
-                LOG.error(_('Failed to create a if-vport mapping on host=%s'),
-                          host_uuid)
-                raise e
-            try:
-                self.mido_api.add_host_interface_port(
-                    host, vport_id, host_dev_name)
-            except w_exc.HTTPError:
-                LOG.warn(_(
-                         'Faild binding vport=%(vport)s to device=%(device)s'),
-                         {"vport": vport_id, "device": host_dev_name})
-        else:
-            LOG.warn(_("Device %s already exists"), device_name)
-
-    def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
-        # the port will be deleted by the dhcp agent that will call the plugin
-        device = ip_lib.IPDevice(device_name,
-                                 self.root_helper,
-                                 namespace)
-        device.link.delete()
-        LOG.debug(_("Unplugged interface '%s'"), device_name)
-
-        ip_lib.IPWrapper(
-            self.root_helper, namespace).garbage_collect_namespace()
index a4662e163646deff62633f5554b431377bff651d..cc550cfbe9e6fdfa514846180eca889775f0e01d 100644 (file)
 # @author: Rossella Sblendido, Midokura Japan KK
 
 import mock
-from oslo.config import cfg
 import sys
 sys.modules["midonetclient"] = mock.Mock()
 
 from neutron.agent.common import config
 from neutron.agent.linux import dhcp
-from neutron.agent.linux import interface
-from neutron.agent.linux import ip_lib
 from neutron.common import config as base_config
-from neutron.openstack.common import uuidutils
 import neutron.plugins.midonet.agent.midonet_driver as driver
 from neutron.tests import base
 
 
-class MidoInterfaceDriverTestCase(base.BaseTestCase):
-    def setUp(self):
-        self.conf = config.setup_conf()
-        self.conf.register_opts(interface.OPTS)
-        config.register_root_helper(self.conf)
-        self.ip_dev_p = mock.patch.object(ip_lib, 'IPDevice')
-        self.ip_dev = self.ip_dev_p.start()
-        self.ip_p = mock.patch.object(ip_lib, 'IPWrapper')
-        self.ip = self.ip_p.start()
-        self.device_exists_p = mock.patch.object(ip_lib, 'device_exists')
-        self.device_exists = self.device_exists_p.start()
-        self.device_exists.return_value = False
-        self.addCleanup(mock.patch.stopall)
-        midonet_opts = [
-            cfg.StrOpt('midonet_uri',
-                       default='http://localhost:8080/midonet-api',
-                       help=_('MidoNet API server URI.')),
-            cfg.StrOpt('username', default='admin',
-                       help=_('MidoNet admin username.')),
-            cfg.StrOpt('password', default='passw0rd',
-                       secret=True,
-                       help=_('MidoNet admin password.')),
-            cfg.StrOpt('project_id',
-                       default='77777777-7777-7777-7777-777777777777',
-                       help=_('ID of the project that MidoNet admin user'
-                              'belongs to.'))
-        ]
-        self.conf.register_opts(midonet_opts, "MIDONET")
-        self.driver = driver.MidonetInterfaceDriver(self.conf)
-        self.root_dev = mock.Mock()
-        self.ns_dev = mock.Mock()
-        self.ip().add_veth = mock.Mock(return_value=(
-            self.root_dev, self.ns_dev))
-        self.driver._get_host_uuid = mock.Mock(
-            return_value=uuidutils.generate_uuid())
-        self.network_id = uuidutils.generate_uuid()
-        self.port_id = uuidutils.generate_uuid()
-        self.device_name = "tap0"
-        self.mac_address = "aa:bb:cc:dd:ee:ff"
-        self.bridge = "br-test"
-        self.namespace = "ns-test"
-        super(MidoInterfaceDriverTestCase, self).setUp()
-
-    def test_plug(self):
-        self.driver.plug(
-            self.network_id, self.port_id,
-            self.device_name, self.mac_address,
-            self.bridge, self.namespace)
-
-        expected = [mock.call(), mock.call('sudo'),
-                    mock.call().add_veth(self.device_name,
-                                         self.device_name,
-                                         namespace2=self.namespace),
-                    mock.call().ensure_namespace(self.namespace),
-                    mock.call().ensure_namespace().add_device_to_namespace(
-                        mock.ANY)]
-        self.ns_dev.assert_has_calls(
-            [mock.call.link.set_address(self.mac_address)])
-
-        self.root_dev.assert_has_calls([mock.call.link.set_up()])
-        self.ns_dev.assert_has_calls([mock.call.link.set_up()])
-        self.ip.assert_has_calls(expected, True)
-
-    def test_unplug(self):
-        self.driver.unplug(self.device_name, self.bridge, self.namespace)
-
-        self.ip_dev.assert_has_calls([
-            mock.call(self.device_name, self.driver.root_helper,
-                      self.namespace),
-            mock.call().link.delete()])
-        self.ip.assert_has_calls(mock.call().garbage_collect_namespace())
-
-
 class FakeNetwork:
     id = 'aaaabbbb-cccc-dddd-eeee-ffff00001111'
     namespace = 'qdhcp-ns'
index d5576439e47b3f2710f482bf5f0664c625c9a89a..a2609442998327d0c716818e6a3d511b7ef517c2 100644 (file)
@@ -23,6 +23,7 @@ from neutron.agent.linux import interface
 from neutron.agent.linux import ip_lib
 from neutron.agent.linux import utils
 from neutron.extensions.flavor import (FLAVOR_NETWORK)
+from neutron.openstack.common import uuidutils
 from neutron.tests import base
 
 
@@ -468,3 +469,59 @@ class TestIVSInterfaceDriver(TestBase):
             execute.assert_called_once_with(ivsctl_cmd, 'sudo')
             self.ip_dev.assert_has_calls([mock.call('ns-0', 'sudo', None),
                                           mock.call().link.delete()])
+
+
+class TestMidonetInterfaceDriver(TestBase):
+    def setUp(self):
+        self.conf = config.setup_conf()
+        self.conf.register_opts(interface.OPTS)
+        config.register_root_helper(self.conf)
+        self.device_exists_p = mock.patch.object(ip_lib, 'device_exists')
+        self.device_exists = self.device_exists_p.start()
+        self.addCleanup(mock.patch.stopall)
+        self.driver = interface.MidonetInterfaceDriver(self.conf)
+        self.network_id = uuidutils.generate_uuid()
+        self.port_id = uuidutils.generate_uuid()
+        self.device_name = "tap0"
+        self.mac_address = "aa:bb:cc:dd:ee:ff"
+        self.bridge = "br-test"
+        self.namespace = "ns-test"
+        super(TestMidonetInterfaceDriver, self).setUp()
+
+    def test_plug(self):
+        cmd = ['mm-ctl', '--bind-port', self.port_id, 'tap0']
+        self.device_exists.return_value = False
+
+        root_dev = mock.Mock()
+        ns_dev = mock.Mock()
+        self.ip().add_veth = mock.Mock(return_value=(root_dev, ns_dev))
+        with mock.patch.object(utils, 'execute') as execute:
+            self.driver.plug(
+                self.network_id, self.port_id,
+                self.device_name, self.mac_address,
+                self.bridge, self.namespace)
+            execute.assert_called_once_with(cmd, 'sudo')
+
+        expected = [mock.call(), mock.call('sudo'),
+                    mock.call().add_veth(self.device_name,
+                                         self.device_name,
+                                         namespace2=self.namespace),
+                    mock.call().ensure_namespace(self.namespace),
+                    mock.call().ensure_namespace().add_device_to_namespace(
+                        mock.ANY)]
+
+        ns_dev.assert_has_calls(
+            [mock.call.link.set_address(self.mac_address)])
+
+        root_dev.assert_has_calls([mock.call.link.set_up()])
+        ns_dev.assert_has_calls([mock.call.link.set_up()])
+        self.ip.assert_has_calls(expected, True)
+
+    def test_unplug(self):
+        self.driver.unplug(self.device_name, self.bridge, self.namespace)
+
+        self.ip_dev.assert_has_calls([
+            mock.call(self.device_name, self.driver.root_helper,
+                      self.namespace),
+            mock.call().link.delete()])
+        self.ip.assert_has_calls(mock.call().garbage_collect_namespace())