Merge "Silence patch output"
This commit is contained in:
commit
576cde7689
|
@ -1,72 +1,9 @@
|
|||
diff --git a/nova/tests/unit/virt/xenapi/test_vif.py b/nova/tests/unit/virt/xenapi/test_vif.py
|
||||
index ebd3a9a..320a92a 100644
|
||||
--- a/nova/tests/unit/virt/xenapi/test_vif.py
|
||||
+++ b/nova/tests/unit/virt/xenapi/test_vif.py
|
||||
@@ -22,6 +22,7 @@ from nova.tests.unit.virt.xenapi import stubs
|
||||
from nova.virt.xenapi import network_utils
|
||||
from nova.virt.xenapi import vif
|
||||
|
||||
+
|
||||
fake_vif = {
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
@@ -190,6 +191,10 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase):
|
||||
self.assertTrue(mock_create_vif.called)
|
||||
self.assertEqual('fake_vif_ref', ret_vif_ref)
|
||||
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_delete_linux_bridge')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_delete_linux_port')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_device_exists',
|
||||
+ return_value=True)
|
||||
@mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_br')
|
||||
@mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_port')
|
||||
@mock.patch.object(network_utils, 'find_network_with_name_label',
|
||||
@@ -198,7 +203,10 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase):
|
||||
def test_unplug(self, mock_super_unplug,
|
||||
mock_find_network_with_name_label,
|
||||
mock_ovs_del_port,
|
||||
- mock_ovs_del_br):
|
||||
+ mock_ovs_del_br,
|
||||
+ mock_device_exists,
|
||||
+ mock_delete_linux_port,
|
||||
+ mock_delete_linux_bridge):
|
||||
instance = {'name': "fake_instance"}
|
||||
vm_ref = "fake_vm_ref"
|
||||
|
||||
@@ -241,10 +249,12 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase):
|
||||
self.ovs_driver.unplug, instance, fake_vif,
|
||||
vm_ref)
|
||||
|
||||
- @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_add_patch_port')
|
||||
- @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_map_external_ids')
|
||||
- def test_post_start_actions(self, mock_ovs_map_external_ids,
|
||||
- mock_ovs_add_patch_port):
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_brctl_add_if')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_create_linux_bridge')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_add_port')
|
||||
+ def test_post_start_actions(self, mock_ovs_add_port,
|
||||
+ mock_create_linux_bridge,
|
||||
+ mock_brctl_add_if):
|
||||
vif_ref = "fake_vif_ref"
|
||||
instance = {'name': 'fake_instance_name'}
|
||||
fake_vif_rec = {'uuid': fake_vif['uuid'],
|
||||
@@ -267,8 +277,8 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase):
|
||||
self.assertTrue(mock_VIF_get_record.called)
|
||||
self.assertTrue(mock_network_get_bridge.called)
|
||||
self.assertTrue(mock_network_get_uuid.called)
|
||||
- self.assertEqual(mock_ovs_add_patch_port.call_count, 2)
|
||||
- self.assertTrue(mock_ovs_map_external_ids.called)
|
||||
+ self.assertEqual(mock_ovs_add_port.call_count, 1)
|
||||
+ self.assertTrue(mock_brctl_add_if.called)
|
||||
|
||||
@mock.patch.object(network_utils, 'find_network_with_name_label',
|
||||
return_value="exist_network_ref")
|
||||
diff --git a/nova/virt/xenapi/vif.py b/nova/virt/xenapi/vif.py
|
||||
index b9660be..a474d23 100644
|
||||
--- a/nova/virt/xenapi/vif.py
|
||||
+++ b/nova/virt/xenapi/vif.py
|
||||
@@ -230,11 +230,11 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
|
||||
|
||||
def unplug(self, instance, vif, vm_ref):
|
||||
"""unplug vif:
|
||||
- 1. unplug and destroy vif.
|
||||
|
@ -81,7 +18,7 @@ index b9660be..a474d23 100644
|
|||
+ 4. delete linux bridge qbr and related ports if exist
|
||||
"""
|
||||
super(XenAPIOpenVswitchDriver, self).unplug(instance, vif, vm_ref)
|
||||
|
||||
|
||||
@@ -253,12 +253,10 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
LOG.debug('destroying patch port pair for vif: vif_id=%(vif_id)s',
|
||||
{'vif_id': vif['id']})
|
||||
|
@ -118,7 +55,7 @@ index b9660be..a474d23 100644
|
|||
@@ -284,6 +294,88 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
raise exception.VirtualInterfaceUnplugException(
|
||||
reason=_("Failed to delete bridge"))
|
||||
|
||||
|
||||
+ def _get_qbr_name(self, iface_id):
|
||||
+ return ("qbr" + iface_id)[:network_model.NIC_NAME_LEN]
|
||||
+
|
||||
|
@ -218,7 +155,7 @@ index b9660be..a474d23 100644
|
|||
if bridge_name is None:
|
||||
raise exception.VirtualInterfacePlugException(
|
||||
_("Failed to find bridge for vif"))
|
||||
|
||||
|
||||
- self._ovs_add_patch_port(bridge_name, patch_port1, patch_port2)
|
||||
- self._ovs_add_patch_port(CONF.xenserver.ovs_integration_bridge,
|
||||
- patch_port2, patch_port1)
|
||||
|
@ -233,18 +170,18 @@ index b9660be..a474d23 100644
|
|||
+ self._brctl_add_if(linux_br_name, tap_name)
|
||||
+ # Add port to interim bridge
|
||||
+ self._ovs_add_port(bridge_name, patch_port1)
|
||||
|
||||
|
||||
def get_vif_interim_net_name(self, vif):
|
||||
return ("net-" + vif['id'])[:network_model.NIC_NAME_LEN]
|
||||
@@ -335,14 +433,13 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
return network_ref
|
||||
|
||||
|
||||
def _get_patch_port_pair_names(self, iface_id):
|
||||
- return (("pp1-%s" % iface_id)[:network_model.NIC_NAME_LEN],
|
||||
- ("pp2-%s" % iface_id)[:network_model.NIC_NAME_LEN])
|
||||
+ return (("vif%s" % iface_id)[:network_model.NIC_NAME_LEN],
|
||||
+ ("tap%s" % iface_id)[:network_model.NIC_NAME_LEN])
|
||||
|
||||
|
||||
- def _ovs_add_patch_port(self, bridge_name, port_name, peer_port_name):
|
||||
- cmd = 'ovs_add_patch_port'
|
||||
+ def _ovs_add_port(self, bridge_name, port_name):
|
||||
|
@ -255,11 +192,11 @@ index b9660be..a474d23 100644
|
|||
+ 'port_name': port_name
|
||||
}
|
||||
self._exec_dom0_cmd(cmd, args)
|
||||
|
||||
|
||||
@@ -378,6 +475,40 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
self._ovs_set_if_external_id(interface, 'xs-vif-uuid', vif_uuid)
|
||||
self._ovs_set_if_external_id(interface, 'iface-status', status)
|
||||
|
||||
|
||||
+ def _brctl_add_if(self, bridge_name, interface_name):
|
||||
+ cmd = 'brctl_add_if'
|
||||
+ args = {'bridge_name': bridge_name,
|
||||
|
@ -297,114 +234,3 @@ index b9660be..a474d23 100644
|
|||
def _exec_dom0_cmd(self, cmd, cmd_args):
|
||||
args = {'cmd': cmd,
|
||||
'args': cmd_args
|
||||
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost
|
||||
index ed0ff0f..045f362 100755
|
||||
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost
|
||||
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost
|
||||
@@ -252,12 +252,105 @@ def _ovs_set_if_external_id(args):
|
||||
return _run_command(cmd_args)
|
||||
|
||||
|
||||
+def _ovs_add_port(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ port_name = pluginlib.exists(args, 'port_name')
|
||||
+ cmd_args = ['ovs-vsctl', '--', '--if-exists', 'del-port', port_name,
|
||||
+ '--', 'add-port', bridge_name, port_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ip_link_get_dev(args):
|
||||
+ device_name = pluginlib.exists(args, 'device_name')
|
||||
+ cmd_args = ['ip', 'link', 'show', device_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ip_link_del_dev(args):
|
||||
+ device_name = pluginlib.exists(args, 'device_name')
|
||||
+ cmd_args = ['ip', 'link', 'delete', device_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+def _ip_link_add_veth_pair(args):
|
||||
+ dev1_name = pluginlib.exists(args, 'dev1_name')
|
||||
+ dev2_name = pluginlib.exists(args, 'dev2_name')
|
||||
+ cmd_args = ['ip', 'link', 'add', dev1_name, 'type', 'veth', 'peer',
|
||||
+ 'name', dev2_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ip_link_set_dev(args):
|
||||
+ device_name = pluginlib.exists(args, 'device_name')
|
||||
+ option = pluginlib.exists(args, 'option')
|
||||
+ cmd_args = ['ip', 'link', 'set', device_name, option]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ip_link_set_promisc(args):
|
||||
+ device_name = pluginlib.exists(args, 'device_name')
|
||||
+ option = pluginlib.exists(args, 'option')
|
||||
+ cmd_args = ['ip', 'link', 'set', device_name, 'promisc', option]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _brctl_add_br(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ cmd_args = ['brctl', 'addbr', bridge_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _brctl_del_br(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ cmd_args = ['brctl', 'delbr', bridge_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _brctl_set_fd(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ fd = pluginlib.exists(args, 'fd')
|
||||
+ cmd_args = ['brctl', 'setfd', bridge_name, fd]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _brctl_set_stp(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ option = pluginlib.exists(args, 'option')
|
||||
+ cmd_args = ['brctl', 'stp', bridge_name, option]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _brctl_add_if(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ if_name = pluginlib.exists(args, 'interface_name')
|
||||
+ cmd_args = ['brctl', 'addif', bridge_name, if_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _brctl_del_if(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ if_name = pluginlib.exists(args, 'interface_name')
|
||||
+ cmd_args = ['brctl', 'delif', bridge_name, if_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
ALLOWED_NETWORK_CMDS = {
|
||||
# allowed cmds to config OVS bridge
|
||||
'ovs_add_patch_port': _ovs_add_patch_port,
|
||||
+ 'ovs_add_port': _ovs_add_port,
|
||||
'ovs_del_port': _ovs_del_port,
|
||||
'ovs_del_br': _ovs_del_br,
|
||||
- 'ovs_set_if_external_id': _ovs_set_if_external_id
|
||||
+ 'ovs_set_if_external_id': _ovs_set_if_external_id,
|
||||
+ 'ip_link_add_veth_pair': _ip_link_add_veth_pair,
|
||||
+ 'ip_link_del_dev': _ip_link_del_dev,
|
||||
+ 'ip_link_get_dev': _ip_link_get_dev,
|
||||
+ 'ip_link_set_dev': _ip_link_set_dev,
|
||||
+ 'ip_link_set_promisc': _ip_link_set_promisc,
|
||||
+ 'brctl_add_br': _brctl_add_br,
|
||||
+ 'brctl_add_if': _brctl_add_if,
|
||||
+ 'brctl_del_br': _brctl_del_br,
|
||||
+ 'brctl_del_if': _brctl_del_if,
|
||||
+ 'brctl_set_fd': _brctl_set_fd,
|
||||
+ 'brctl_set_stp': _brctl_set_stp
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ index 40b82bf..f9cd12f 100644
|
|||
+++ b/nova/exception.py
|
||||
@@ -187,6 +187,11 @@ class VirtualInterfacePlugException(NovaException):
|
||||
msg_fmt = _("Virtual interface plugin failed")
|
||||
|
||||
|
||||
|
||||
|
||||
+class VirtualInterfaceUnplugException(NovaException):
|
||||
+ msg_fmt = _("Virtual interface unplugin failed: "
|
||||
+ "%(reason)s")
|
||||
|
@ -14,229 +14,14 @@ index 40b82bf..f9cd12f 100644
|
|||
class GlanceConnectionFailed(NovaException):
|
||||
msg_fmt = _("Connection to glance host %(server)s failed: "
|
||||
"%(reason)s")
|
||||
diff --git a/nova/tests/unit/virt/xenapi/client/test_objects.py b/nova/tests/unit/virt/xenapi/client/test_objects.py
|
||||
index efaf17a..6730745 100644
|
||||
--- a/nova/tests/unit/virt/xenapi/client/test_objects.py
|
||||
+++ b/nova/tests/unit/virt/xenapi/client/test_objects.py
|
||||
@@ -55,6 +55,11 @@ class ObjectsTestCase(stubs.XenAPITestBaseNoDB):
|
||||
vdi.get_X("ref")
|
||||
self.session.call_xenapi.assert_called_once_with("VDI.get_X", "ref")
|
||||
|
||||
+ def test_VIF(self):
|
||||
+ vdi = objects.VIF(self.session)
|
||||
+ vdi.get_X("ref")
|
||||
+ self.session.call_xenapi.assert_called_once_with("VIF.get_X", "ref")
|
||||
+
|
||||
def test_VBD(self):
|
||||
vbd = objects.VBD(self.session)
|
||||
vbd.get_X("ref")
|
||||
diff --git a/nova/tests/unit/virt/xenapi/client/test_session.py b/nova/tests/unit/virt/xenapi/client/test_session.py
|
||||
index 16c352f..f9b490e 100644
|
||||
--- a/nova/tests/unit/virt/xenapi/client/test_session.py
|
||||
+++ b/nova/tests/unit/virt/xenapi/client/test_session.py
|
||||
@@ -100,6 +100,10 @@ class ApplySessionHelpersTestCase(stubs.XenAPITestBaseNoDB):
|
||||
self.session.VDI.get_X("ref")
|
||||
self.session.call_xenapi.assert_called_once_with("VDI.get_X", "ref")
|
||||
|
||||
+ def test_apply_session_helpers_add_VIF(self):
|
||||
+ self.session.VIF.get_X("ref")
|
||||
+ self.session.call_xenapi.assert_called_once_with("VIF.get_X", "ref")
|
||||
+
|
||||
def test_apply_session_helpers_add_VBD(self):
|
||||
self.session.VBD.get_X("ref")
|
||||
self.session.call_xenapi.assert_called_once_with("VBD.get_X", "ref")
|
||||
diff --git a/nova/tests/unit/virt/xenapi/test_vif.py b/nova/tests/unit/virt/xenapi/test_vif.py
|
||||
index a41e506..ebd3a9a 100644
|
||||
--- a/nova/tests/unit/virt/xenapi/test_vif.py
|
||||
+++ b/nova/tests/unit/virt/xenapi/test_vif.py
|
||||
@@ -17,6 +17,7 @@ import mock
|
||||
|
||||
from nova import exception
|
||||
from nova.network import model
|
||||
+from nova import test
|
||||
from nova.tests.unit.virt.xenapi import stubs
|
||||
from nova.virt.xenapi import network_utils
|
||||
from nova.virt.xenapi import vif
|
||||
@@ -67,6 +68,22 @@ class XenVIFDriverTestBase(stubs.XenAPITestBaseNoDB):
|
||||
self._session = mock.Mock()
|
||||
self._session.call_xenapi.side_effect = fake_call_xenapi
|
||||
|
||||
+ def mock_patch_object(self, target, attribute, return_val=None,
|
||||
+ side_effect=None):
|
||||
+ """Utilility function to mock object's attribute at runtime:
|
||||
+ Some methods are dynamic, so standard mocking does not work
|
||||
+ and we need to mock them at runtime.
|
||||
+ e.g. self._session.VIF.get_record which is dynamically
|
||||
+ created via the override function of __getattr__.
|
||||
+ """
|
||||
+
|
||||
+ patcher = mock.patch.object(target, attribute,
|
||||
+ return_value=return_val,
|
||||
+ side_effect=side_effect)
|
||||
+ mock_one = patcher.start()
|
||||
+ self.addCleanup(patcher.stop)
|
||||
+ return mock_one
|
||||
+
|
||||
|
||||
class XenVIFDriverTestCase(XenVIFDriverTestBase):
|
||||
def setUp(self):
|
||||
@@ -149,41 +166,126 @@ class XenAPIBridgeDriverTestCase(XenVIFDriverTestBase, object):
|
||||
ret_vif_ref = self.bridge_driver.plug(instance, vif, vm_ref, device)
|
||||
self.assertEqual('fake_vif_ref', ret_vif_ref)
|
||||
|
||||
- @mock.patch.object(vif.XenVIFDriver, '_get_vif_ref',
|
||||
- return_value='fake_vif_ref')
|
||||
- def test_unplug(self, mock_get_vif_ref):
|
||||
- instance = {'name': "fake_instance"}
|
||||
- vm_ref = "fake_vm_ref"
|
||||
- self.bridge_driver.unplug(instance, fake_vif, vm_ref)
|
||||
-
|
||||
- expected = [mock.call('VIF.destroy', 'fake_vif_ref')]
|
||||
- self.assertEqual(expected, self._session.call_xenapi.call_args_list)
|
||||
-
|
||||
|
||||
class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase):
|
||||
def setUp(self):
|
||||
super(XenAPIOpenVswitchDriverTestCase, self).setUp()
|
||||
self.ovs_driver = vif.XenAPIOpenVswitchDriver(self._session)
|
||||
|
||||
- @mock.patch.object(network_utils, 'find_network_with_bridge',
|
||||
- return_value='fake_network_ref')
|
||||
@mock.patch.object(vif.XenVIFDriver, '_create_vif',
|
||||
return_value='fake_vif_ref')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver,
|
||||
+ 'create_vif_interim_network')
|
||||
@mock.patch.object(vif.XenVIFDriver, '_get_vif_ref', return_value=None)
|
||||
- def test_plug(self, mock_get_vif_ref, mock_create_vif,
|
||||
- mock_find_network_with_bridge):
|
||||
+ @mock.patch.object(vif.vm_utils, 'lookup', return_value='fake_vm_ref')
|
||||
+ def test_plug(self, mock_lookup, mock_get_vif_ref,
|
||||
+ mock_create_vif_interim_network,
|
||||
+ mock_create_vif):
|
||||
instance = {'name': "fake_instance_name"}
|
||||
- vm_ref = "fake_vm_ref"
|
||||
- device = 1
|
||||
- ret_vif_ref = self.ovs_driver.plug(instance, fake_vif, vm_ref, device)
|
||||
+ ret_vif_ref = self.ovs_driver.plug(
|
||||
+ instance, fake_vif, vm_ref=None, device=1)
|
||||
+ self.assertTrue(mock_lookup.called)
|
||||
+ self.assertTrue(mock_get_vif_ref.called)
|
||||
+ self.assertTrue(mock_create_vif_interim_network.called)
|
||||
+ self.assertTrue(mock_create_vif.called)
|
||||
self.assertEqual('fake_vif_ref', ret_vif_ref)
|
||||
|
||||
- @mock.patch.object(vif.XenVIFDriver, '_get_vif_ref',
|
||||
- return_value='fake_vif_ref')
|
||||
- def test_unplug(self, mock_get_vif_ref):
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_br')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_port')
|
||||
+ @mock.patch.object(network_utils, 'find_network_with_name_label',
|
||||
+ return_value='fake_network')
|
||||
+ @mock.patch.object(vif.XenVIFDriver, 'unplug')
|
||||
+ def test_unplug(self, mock_super_unplug,
|
||||
+ mock_find_network_with_name_label,
|
||||
+ mock_ovs_del_port,
|
||||
+ mock_ovs_del_br):
|
||||
instance = {'name': "fake_instance"}
|
||||
vm_ref = "fake_vm_ref"
|
||||
+
|
||||
+ mock_network_get_VIFs = self.mock_patch_object(
|
||||
+ self._session.network, 'get_VIFs', return_val=None)
|
||||
+ mock_network_get_bridge = self.mock_patch_object(
|
||||
+ self._session.network, 'get_bridge', return_val='fake_bridge')
|
||||
+ mock_network_destroy = self.mock_patch_object(
|
||||
+ self._session.network, 'destroy')
|
||||
self.ovs_driver.unplug(instance, fake_vif, vm_ref)
|
||||
|
||||
- expected = [mock.call('VIF.destroy', 'fake_vif_ref')]
|
||||
- self.assertEqual(expected, self._session.call_xenapi.call_args_list)
|
||||
+ self.assertTrue(mock_super_unplug.called)
|
||||
+ self.assertTrue(mock_find_network_with_name_label.called)
|
||||
+ self.assertTrue(mock_network_get_VIFs.called)
|
||||
+ self.assertTrue(mock_network_get_bridge.called)
|
||||
+ self.assertEqual(mock_ovs_del_port.call_count, 2)
|
||||
+ self.assertTrue(mock_network_destroy.called)
|
||||
+
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_br')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_port')
|
||||
+ @mock.patch.object(network_utils, 'find_network_with_name_label',
|
||||
+ return_value='fake_network')
|
||||
+ @mock.patch.object(vif.XenVIFDriver, 'unplug')
|
||||
+ def test_unplug_exception(self, mock_super_unplug,
|
||||
+ mock_find_network_with_name_label,
|
||||
+ mock_ovs_del_port,
|
||||
+ mock_ovs_del_br):
|
||||
+ instance = {'name': "fake_instance"}
|
||||
+ vm_ref = "fake_vm_ref"
|
||||
+
|
||||
+ self.mock_patch_object(
|
||||
+ self._session.network, 'get_VIFs', return_val=None)
|
||||
+ self.mock_patch_object(
|
||||
+ self._session.network, 'get_bridge', return_val='fake_bridge')
|
||||
+ self.mock_patch_object(
|
||||
+ self._session.network, 'destroy',
|
||||
+ side_effect=test.TestingException)
|
||||
+
|
||||
+ self.assertRaises(exception.VirtualInterfaceUnplugException,
|
||||
+ self.ovs_driver.unplug, instance, fake_vif,
|
||||
+ vm_ref)
|
||||
+
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_add_patch_port')
|
||||
+ @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_map_external_ids')
|
||||
+ def test_post_start_actions(self, mock_ovs_map_external_ids,
|
||||
+ mock_ovs_add_patch_port):
|
||||
+ vif_ref = "fake_vif_ref"
|
||||
+ instance = {'name': 'fake_instance_name'}
|
||||
+ fake_vif_rec = {'uuid': fake_vif['uuid'],
|
||||
+ 'MAC': fake_vif['address'],
|
||||
+ 'network': 'fake_network',
|
||||
+ 'other_config': {
|
||||
+ 'nicira-iface-id': 'fake-nicira-iface-id'}
|
||||
+ }
|
||||
+ mock_VIF_get_record = self.mock_patch_object(
|
||||
+ self._session.VIF, 'get_record', return_val=fake_vif_rec)
|
||||
+ mock_network_get_bridge = self.mock_patch_object(
|
||||
+ self._session.network, 'get_bridge',
|
||||
+ return_val='fake_bridge_name')
|
||||
+ mock_network_get_uuid = self.mock_patch_object(
|
||||
+ self._session.network, 'get_uuid',
|
||||
+ return_val='fake_network_uuid')
|
||||
+
|
||||
+ self.ovs_driver.post_start_actions(instance, vif_ref)
|
||||
+
|
||||
+ self.assertTrue(mock_VIF_get_record.called)
|
||||
+ self.assertTrue(mock_network_get_bridge.called)
|
||||
+ self.assertTrue(mock_network_get_uuid.called)
|
||||
+ self.assertEqual(mock_ovs_add_patch_port.call_count, 2)
|
||||
+ self.assertTrue(mock_ovs_map_external_ids.called)
|
||||
+
|
||||
+ @mock.patch.object(network_utils, 'find_network_with_name_label',
|
||||
+ return_value="exist_network_ref")
|
||||
+ def test_create_vif_interim_network_exist(self,
|
||||
+ mock_find_network_with_name_label):
|
||||
+ mock_network_create = self.mock_patch_object(
|
||||
+ self._session.network, 'create', return_val='new_network_ref')
|
||||
+ network_ref = self.ovs_driver.create_vif_interim_network(fake_vif)
|
||||
+ self.assertFalse(mock_network_create.called)
|
||||
+ self.assertEqual(network_ref, 'exist_network_ref')
|
||||
+
|
||||
+ @mock.patch.object(network_utils, 'find_network_with_name_label',
|
||||
+ return_value=None)
|
||||
+ def test_create_vif_interim_network_new(self,
|
||||
+ mock_find_network_with_name_label):
|
||||
+ mock_network_create = self.mock_patch_object(
|
||||
+ self._session.network, 'create', return_val='new_network_ref')
|
||||
+ network_ref = self.ovs_driver.create_vif_interim_network(fake_vif)
|
||||
+ self.assertTrue(mock_network_create.called)
|
||||
+ self.assertEqual(network_ref, 'new_network_ref')
|
||||
diff --git a/nova/virt/xenapi/client/objects.py b/nova/virt/xenapi/client/objects.py
|
||||
index 5cc91eb..7f7215c 100644
|
||||
--- a/nova/virt/xenapi/client/objects.py
|
||||
+++ b/nova/virt/xenapi/client/objects.py
|
||||
@@ -100,6 +100,12 @@ class VDI(XenAPISessionObject):
|
||||
super(VDI, self).__init__(session, "VDI")
|
||||
|
||||
|
||||
|
||||
|
||||
+class VIF(XenAPISessionObject):
|
||||
+ """Virtual Network Interface."""
|
||||
+ def __init__(self, session):
|
||||
|
@ -269,30 +54,30 @@ index 5c7a350..b9660be 100644
|
|||
+from nova.network import model as network_model
|
||||
from nova.virt.xenapi import network_utils
|
||||
from nova.virt.xenapi import vm_utils
|
||||
|
||||
|
||||
@@ -185,11 +186,18 @@ class XenAPIBridgeDriver(XenVIFDriver):
|
||||
def unplug(self, instance, vif, vm_ref):
|
||||
super(XenAPIBridgeDriver, self).unplug(instance, vif, vm_ref)
|
||||
|
||||
|
||||
+ def post_start_actions(self, instance, vif_ref):
|
||||
+ """no further actions needed for this driver type"""
|
||||
+ pass
|
||||
+
|
||||
|
||||
|
||||
class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
"""VIF driver for Open vSwitch with XenAPI."""
|
||||
|
||||
|
||||
def plug(self, instance, vif, vm_ref=None, device=None):
|
||||
+ """create an interim network for this vif; and build
|
||||
+ the vif_rec which will be used by xapi to create VM vif
|
||||
+ """
|
||||
if not vm_ref:
|
||||
vm_ref = vm_utils.lookup(self._session, instance['name'])
|
||||
|
||||
|
||||
@@ -203,10 +211,10 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
if not device:
|
||||
device = 0
|
||||
|
||||
|
||||
- # with OVS model, always plug into an OVS integration bridge
|
||||
- # that is already created
|
||||
- network_ref = network_utils.find_network_with_bridge(
|
||||
|
@ -306,7 +91,7 @@ index 5c7a350..b9660be 100644
|
|||
vif_rec['network'] = network_ref
|
||||
@@ -221,4 +229,157 @@ class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||
return self._create_vif(vif, vif_rec, vm_ref)
|
||||
|
||||
|
||||
def unplug(self, instance, vif, vm_ref):
|
||||
+ """unplug vif:
|
||||
+ 1. unplug and destroy vif.
|
||||
|
@ -469,7 +254,7 @@ index ab9368c..51d9627 100644
|
|||
@@ -348,6 +348,18 @@ class VMOps(object):
|
||||
if bad_volumes_callback and bad_devices:
|
||||
bad_volumes_callback(bad_devices)
|
||||
|
||||
|
||||
+ # Do some operations which have to be done after start:
|
||||
+ # e.g. The vif's interim bridge won't be created until VM starts.
|
||||
+ # So the operations on the interim bridge have be done after
|
||||
|
@ -487,13 +272,13 @@ index ab9368c..51d9627 100644
|
|||
"""Create or connect to all virtual disks for this instance."""
|
||||
@@ -1935,13 +1947,20 @@ class VMOps(object):
|
||||
"""Creates vifs for an instance."""
|
||||
|
||||
|
||||
LOG.debug("Creating vifs", instance=instance)
|
||||
+ vif_refs = []
|
||||
|
||||
|
||||
# this function raises if vm_ref is not a vm_opaque_ref
|
||||
self._session.call_xenapi("VM.get_domid", vm_ref)
|
||||
|
||||
|
||||
for device, vif in enumerate(network_info):
|
||||
LOG.debug('Create VIF %s', vif, instance=instance)
|
||||
- self.vif_driver.plug(instance, vif, vm_ref=vm_ref, device=device)
|
||||
|
@ -504,91 +289,6 @@ index ab9368c..51d9627 100644
|
|||
+ LOG.debug('Created the vif_refs: %(vifs)s for VM name: %(name)s',
|
||||
+ {'vifs': vif_refs, 'name': instance['name']},
|
||||
+ instance=instance)
|
||||
|
||||
|
||||
def plug_vifs(self, instance, network_info):
|
||||
"""Set up VIF networking on the host."""
|
||||
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost
|
||||
index 7417a3c..ed0ff0f 100755
|
||||
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost
|
||||
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost
|
||||
@@ -217,6 +217,65 @@ def iptables_config(session, args):
|
||||
raise pluginlib.PluginError(_("Invalid iptables command"))
|
||||
|
||||
|
||||
+def _ovs_add_patch_port(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ port_name = pluginlib.exists(args, 'port_name')
|
||||
+ peer_port_name = pluginlib.exists(args, 'peer_port_name')
|
||||
+ cmd_args = ['ovs-vsctl', '--', '--if-exists', 'del-port',
|
||||
+ port_name, '--', 'add-port', bridge_name, port_name,
|
||||
+ '--', 'set', 'interface', port_name,
|
||||
+ 'type=patch', 'options:peer=%s' % peer_port_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ovs_del_port(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ port_name = pluginlib.exists(args, 'port_name')
|
||||
+ cmd_args = ['ovs-vsctl', '--', '--if-exists', 'del-port',
|
||||
+ bridge_name, port_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ovs_del_br(args):
|
||||
+ bridge_name = pluginlib.exists(args, 'bridge_name')
|
||||
+ cmd_args = ['ovs-vsctl', '--', '--if-exists',
|
||||
+ 'del-br', bridge_name]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+def _ovs_set_if_external_id(args):
|
||||
+ interface = pluginlib.exists(args, 'interface')
|
||||
+ extneral_id = pluginlib.exists(args, 'extneral_id')
|
||||
+ value = pluginlib.exists(args, 'value')
|
||||
+ cmd_args = ['ovs-vsctl', 'set', 'Interface', interface,
|
||||
+ 'external-ids:%s=%s' % (extneral_id, value)]
|
||||
+ return _run_command(cmd_args)
|
||||
+
|
||||
+
|
||||
+ALLOWED_NETWORK_CMDS = {
|
||||
+ # allowed cmds to config OVS bridge
|
||||
+ 'ovs_add_patch_port': _ovs_add_patch_port,
|
||||
+ 'ovs_del_port': _ovs_del_port,
|
||||
+ 'ovs_del_br': _ovs_del_br,
|
||||
+ 'ovs_set_if_external_id': _ovs_set_if_external_id
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+def network_config(session, args):
|
||||
+ """network config functions"""
|
||||
+ cmd = pluginlib.exists(args, 'cmd')
|
||||
+ if not isinstance(cmd, basestring):
|
||||
+ msg = _("invalid command '%s'") % str(cmd)
|
||||
+ raise pluginlib.PluginError(msg)
|
||||
+ return
|
||||
+ if cmd not in ALLOWED_NETWORK_CMDS:
|
||||
+ msg = _("Dom0 execution of '%s' is not permitted") % cmd
|
||||
+ raise pluginlib.PluginError(msg)
|
||||
+ return
|
||||
+ cmd_args = pluginlib.exists(args, 'args')
|
||||
+ return ALLOWED_NETWORK_CMDS[cmd](cmd_args)
|
||||
+
|
||||
+
|
||||
def _power_action(action, arg_dict):
|
||||
# Host must be disabled first
|
||||
host_uuid = arg_dict['host_uuid']
|
||||
@@ -453,10 +512,12 @@ def get_pci_type(session, pci_device):
|
||||
if __name__ == "__main__":
|
||||
# Support both serialized and non-serialized plugin approaches
|
||||
_, methodname = xmlrpclib.loads(sys.argv[1])
|
||||
- if methodname in ['query_gc', 'get_pci_device_details', 'get_pci_type']:
|
||||
+ if methodname in ['query_gc', 'get_pci_device_details', 'get_pci_type',
|
||||
+ 'network_config']:
|
||||
utils.register_plugin_calls(query_gc,
|
||||
get_pci_device_details,
|
||||
- get_pci_type)
|
||||
+ get_pci_type,
|
||||
+ network_config)
|
||||
|
||||
XenAPIPlugin.dispatch(
|
||||
{"host_data": host_data,
|
||||
|
|
|
@ -1,16 +1,3 @@
|
|||
diff --git a/nova/tests/unit/virt/xenapi/test_vm_utils.py b/nova/tests/unit/virt/xenapi/test_vm_utils.py
|
||||
index 174b5cf..d65385e 100644
|
||||
--- a/nova/tests/unit/virt/xenapi/test_vm_utils.py
|
||||
+++ b/nova/tests/unit/virt/xenapi/test_vm_utils.py
|
||||
@@ -190,7 +190,7 @@ class GenerateConfigDriveTestCase(VMUtilsTestBase):
|
||||
'-publisher', mox.IgnoreArg(), '-quiet',
|
||||
'-J', '-r', '-V', 'config-2', mox.IgnoreArg(),
|
||||
attempts=1, run_as_root=False).AndReturn(None)
|
||||
- utils.execute('dd', mox.IgnoreArg(), mox.IgnoreArg(),
|
||||
+ utils.execute('dd', mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(),
|
||||
mox.IgnoreArg(), run_as_root=True).AndReturn(None)
|
||||
|
||||
self.mox.StubOutWithMock(vm_utils, 'create_vbd')
|
||||
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
|
||||
index f88cb3a..982ad37 100644
|
||||
--- a/nova/virt/xenapi/vm_utils.py
|
||||
|
@ -20,7 +7,7 @@ index f88cb3a..982ad37 100644
|
|||
MAX_VDI_CHAIN_SIZE = 16
|
||||
PROGRESS_INTERVAL_SECONDS = 300
|
||||
+DD_BLOCKSIZE = 65536
|
||||
|
||||
|
||||
# Fudge factor to allow for the VHD chain to be slightly larger than
|
||||
# the partitioned space. Otherwise, legitimate images near their
|
||||
@@ -1159,6 +1160,7 @@ def generate_configdrive(session, instance, vm_ref, userdevice,
|
||||
|
@ -30,7 +17,7 @@ index f88cb3a..982ad37 100644
|
|||
+ 'bs=%d' % DD_BLOCKSIZE,
|
||||
'oflag=direct,sync',
|
||||
run_as_root=True)
|
||||
|
||||
|
||||
@@ -2426,6 +2428,7 @@ def _copy_partition(session, src_ref, dst_ref, partition, virtual_size):
|
||||
utils.execute('dd',
|
||||
'if=%s' % src_path,
|
||||
|
|
|
@ -1,54 +1,3 @@
|
|||
diff --git a/nova/tests/unit/virt/xenapi/test_vm_utils.py b/nova/tests/unit/virt/xenapi/test_vm_utils.py
|
||||
index 1305d05..174b5cf 100644
|
||||
--- a/nova/tests/unit/virt/xenapi/test_vm_utils.py
|
||||
+++ b/nova/tests/unit/virt/xenapi/test_vm_utils.py
|
||||
@@ -1455,6 +1455,46 @@ class CreateKernelRamdiskTestCase(VMUtilsTestBase):
|
||||
self.session, self.instance, self.name_label)
|
||||
self.assertEqual(("k", None), result)
|
||||
|
||||
+ def _test_create_kernel_image(self, cache_images):
|
||||
+ kernel_id = "kernel"
|
||||
+ self.instance["kernel_id"] = kernel_id
|
||||
+
|
||||
+ args_kernel = {}
|
||||
+ args_kernel['cached-image'] = kernel_id
|
||||
+ args_kernel['new-image-uuid'] = "fake_uuid1"
|
||||
+ self.flags(cache_images=cache_images, group='xenserver')
|
||||
+
|
||||
+ if cache_images == 'all':
|
||||
+ uuid.uuid4().AndReturn("fake_uuid1")
|
||||
+ self.session.call_plugin('kernel', 'create_kernel_ramdisk',
|
||||
+ args_kernel).AndReturn("cached_image")
|
||||
+ else:
|
||||
+ kernel = {"kernel": {"file": "new_image", "uuid": None}}
|
||||
+ vm_utils._fetch_disk_image(self.context, self.session,
|
||||
+ self.instance, self.name_label,
|
||||
+ kernel_id, 0).AndReturn(kernel)
|
||||
+
|
||||
+ self.mox.ReplayAll()
|
||||
+
|
||||
+ result = vm_utils._create_kernel_image(self.context,
|
||||
+ self.session,
|
||||
+ self.instance,
|
||||
+ self.name_label,
|
||||
+ kernel_id, 0)
|
||||
+
|
||||
+ if cache_images == 'all':
|
||||
+ self.assertEqual(result, {"kernel":
|
||||
+ {"file": "cached_image", "uuid": None}})
|
||||
+ else:
|
||||
+ self.assertEqual(result, {"kernel":
|
||||
+ {"file": "new_image", "uuid": None}})
|
||||
+
|
||||
+ def test_create_kernel_image_cached_config(self):
|
||||
+ self._test_create_kernel_image('all')
|
||||
+
|
||||
+ def test_create_kernel_image_uncached_config(self):
|
||||
+ self._test_create_kernel_image('none')
|
||||
+
|
||||
|
||||
class ScanSrTestCase(VMUtilsTestBase):
|
||||
@mock.patch.object(vm_utils, "_scan_sr")
|
||||
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
|
||||
index 583a913..f88cb3a 100644
|
||||
--- a/nova/virt/xenapi/vm_utils.py
|
||||
|
@ -63,11 +12,11 @@ index 583a913..f88cb3a 100644
|
|||
args['cached-image'] = image_id
|
||||
args['new-image-uuid'] = str(uuid.uuid4())
|
||||
@@ -1569,7 +1569,7 @@ def _fetch_disk_image(context, session, instance, name_label, image_id,
|
||||
|
||||
|
||||
# Let the plugin copy the correct number of bytes.
|
||||
args['image-size'] = str(vdi_size)
|
||||
- if CONF.xenserver.cache_images:
|
||||
+ if CONF.xenserver.cache_images != 'none':
|
||||
args['cached-image'] = image_id
|
||||
filename = session.call_plugin('kernel', 'copy_vdi', args)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue