Merge "Fixes Hyper-V agent port disconnect issue" into stable/juno

This commit is contained in:
Jenkins 2015-05-21 17:44:33 +00:00 committed by Gerrit Code Review
commit 61044f835b
5 changed files with 89 additions and 16 deletions

View File

@ -310,7 +310,7 @@ class HyperVNeutronAgent(n_rpc.RpcCallback):
self._utils.enable_port_metrics_collection(port_id)
self._port_metric_retries[port_id] = CONF.AGENT.metrics_max_retries
def _port_unbound(self, port_id):
def _port_unbound(self, port_id, vnic_deleted=False):
(net_uuid, map) = self._get_network_vswitch_map_by_port_id(port_id)
if net_uuid not in self._network_vswitch_map:
LOG.info(_('Network %s is not avalailable on this agent'),
@ -318,7 +318,8 @@ class HyperVNeutronAgent(n_rpc.RpcCallback):
return
LOG.debug(_("Unbinding port %s"), port_id)
self._utils.disconnect_switch_port(map['vswitch_name'], port_id, True)
self._utils.disconnect_switch_port(map['vswitch_name'], port_id,
vnic_deleted, True)
if not map['ports']:
self._reclaim_local_network(net_uuid)
@ -417,7 +418,7 @@ class HyperVNeutronAgent(n_rpc.RpcCallback):
dict(device=device, e=e))
resync = True
continue
self._port_unbound(device)
self._port_unbound(device, vnic_deleted=True)
return resync
def _process_network_ports(self, port_info):

View File

@ -173,7 +173,7 @@ class HyperVUtils(object):
pass
def disconnect_switch_port(
self, vswitch_name, switch_port_name, delete_port):
self, vswitch_name, switch_port_name, vnic_deleted, delete_port):
"""Disconnects the switch port."""
switch_svc = self._conn.Msvm_VirtualSwitchManagementService()[0]
switch_port_path = self._get_switch_port_path_by_name(
@ -182,16 +182,17 @@ class HyperVUtils(object):
# Port not found. It happens when the VM was already deleted.
return
(ret_val, ) = switch_svc.DisconnectSwitchPort(
SwitchPort=switch_port_path)
if ret_val != 0:
data = {'switch_port_name': switch_port_name,
'vswitch_name': vswitch_name,
'ret_val': ret_val}
raise HyperVException(
msg=_('Failed to disconnect port %(switch_port_name)s '
'from switch %(vswitch_name)s '
'with error %(ret_val)s') % data)
if not vnic_deleted:
(ret_val, ) = switch_svc.DisconnectSwitchPort(
SwitchPort=switch_port_path)
if ret_val != 0:
data = {'switch_port_name': switch_port_name,
'vswitch_name': vswitch_name,
'ret_val': ret_val}
raise HyperVException(
msg=_('Failed to disconnect port %(switch_port_name)s '
'from switch %(vswitch_name)s '
'with error %(ret_val)s') % data)
if delete_port:
(ret_val, ) = switch_svc.DeleteSwitchPort(
SwitchPort=switch_port_path)

View File

@ -113,7 +113,7 @@ class HyperVUtilsV2(utils.HyperVUtils):
self._check_job_status(ret_val, job_path)
def disconnect_switch_port(
self, vswitch_name, switch_port_name, delete_port):
self, vswitch_name, switch_port_name, vnic_deleted, delete_port):
"""Disconnects the switch port."""
sw_port, found = self._get_switch_port_allocation(switch_port_name)
if not sw_port:

View File

@ -34,6 +34,77 @@ class HyperVUtilsTestCase(base.BaseTestCase):
self.utils = utils.HyperVUtils()
self.utils._wmi_conn = mock.MagicMock()
@mock.patch.object(utils.HyperVUtils, "_get_switch_port_path_by_name")
def test_disconnect_switch_port_not_found(self, mock_get_swp_path):
mock_svc = self.utils._conn.Msvm_VirtualSwitchManagementService()[0]
mock_get_swp_path.return_value = None
self.utils.disconnect_switch_port(mock.sentinel.FAKE_VSWITCH_NAME,
mock.sentinel.FAKE_PORT_NAME,
True, True)
self.assertFalse(mock_svc.DisconnectSwitchPort.called)
self.assertFalse(mock_svc.DeleteSwitchPort.called)
@mock.patch.object(utils.HyperVUtils, "_get_switch_port_path_by_name")
def test_disconnect_switch_port(self, mock_get_swp_path):
mock_svc = self.utils._conn.Msvm_VirtualSwitchManagementService()[0]
mock_svc.DisconnectSwitchPort.return_value = (0, )
mock_svc.DeleteSwitchPort.return_value = (0, )
mock_get_swp_path.return_value = mock.sentinel.FAKE_PATH
self.utils.disconnect_switch_port(mock.sentinel.FAKE_VSWITCH_NAME,
mock.sentinel.FAKE_PORT_NAME,
False, True)
mock_svc.DisconnectSwitchPort.assert_called_once_with(
SwitchPort=mock.sentinel.FAKE_PATH)
mock_svc.DeleteSwitchPort.assert_called_once_with(
SwitchPort=mock.sentinel.FAKE_PATH)
@mock.patch.object(utils.HyperVUtils, "_get_switch_port_path_by_name")
def test_disconnect_switch_port_disconnected(self, mock_get_swp_path):
mock_svc = self.utils._conn.Msvm_VirtualSwitchManagementService()[0]
mock_svc.DeleteSwitchPort.return_value = (0, )
mock_get_swp_path.return_value = mock.sentinel.FAKE_PATH
self.utils.disconnect_switch_port(mock.sentinel.FAKE_VSWITCH_NAME,
mock.sentinel.FAKE_PORT_NAME,
True, True)
self.assertFalse(mock_svc.DisconnectSwitchPort.called)
mock_svc.DeleteSwitchPort.assert_called_once_with(
SwitchPort=mock.sentinel.FAKE_PATH)
@mock.patch.object(utils.HyperVUtils, "_get_switch_port_path_by_name")
def test_disconnect_switch_port_disconnect_ex(self, mock_get_swp_path):
mock_svc = self.utils._conn.Msvm_VirtualSwitchManagementService()[0]
mock_svc.DisconnectSwitchPort.return_value = (
mock.sentinel.FAKE_VAL, )
mock_get_swp_path.return_value = mock.sentinel.FAKE_PATH
self.assertRaises(utils.HyperVException,
self.utils.disconnect_switch_port,
mock.sentinel.FAKE_VSWITCH_NAME,
mock.sentinel.FAKE_PORT_NAME,
False, True)
mock_svc.DisconnectSwitchPort.assert_called_once_with(
SwitchPort=mock.sentinel.FAKE_PATH)
@mock.patch.object(utils.HyperVUtils, "_get_switch_port_path_by_name")
def test_disconnect_switch_port_delete_ex(self, mock_get_swp_path):
mock_svc = self.utils._conn.Msvm_VirtualSwitchManagementService()[0]
mock_svc.DeleteSwitchPort.return_value = (mock.sentinel.FAKE_VAL, )
mock_get_swp_path.return_value = mock.sentinel.FAKE_PATH
self.assertRaises(utils.HyperVException,
self.utils.disconnect_switch_port,
mock.sentinel.FAKE_VSWITCH_NAME,
mock.sentinel.FAKE_PORT_NAME,
True, True)
mock_svc.DeleteSwitchPort.assert_called_once_with(
SwitchPort=mock.sentinel.FAKE_PATH)
def test_get_vswitch_external_port(self):
ext_port = mock.MagicMock()
self.utils._conn.Msvm_ExternalEthernetPort.return_value = [ext_port]

View File

@ -161,7 +161,7 @@ class TestHyperVUtilsV2(base.BaseTestCase):
self._utils.disconnect_switch_port(self._FAKE_VSWITCH_NAME,
self._FAKE_PORT_NAME,
delete_port)
True, delete_port)
if delete_port:
self._utils._remove_virt_resource.assert_called_with(mock_sw_port)