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
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
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."""
# @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
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()
# @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'
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
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())