Skip to content

Commit 8538721

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "neutron: Unbind remaining ports after PortNotFound" into stable/xena
2 parents e812b6f + d322f8e commit 8538721

File tree

2 files changed

+64
-23
lines changed

2 files changed

+64
-23
lines changed

nova/network/neutron.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ def _unbind_ports(self, context, ports,
621621
# in case the caller forgot to filter the list.
622622
if port_id is None:
623623
continue
624+
624625
port_req_body: ty.Dict[str, ty.Any] = {
625626
'port': {
626627
'device_id': '',
@@ -635,7 +636,7 @@ def _unbind_ports(self, context, ports,
635636
except exception.PortNotFound:
636637
LOG.debug('Unable to show port %s as it no longer '
637638
'exists.', port_id)
638-
return
639+
continue
639640
except Exception:
640641
# NOTE: In case we can't retrieve the binding:profile or
641642
# network info assume that they are empty

nova/tests/unit/network/test_neutron.py

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5212,7 +5212,8 @@ def test_get_preexisting_port_ids(self, mock_get_nw_info):
52125212
self.assertEqual(['2', '3'], result, "Invalid preexisting ports")
52135213

52145214
@mock.patch('nova.network.neutron.API._show_port')
5215-
def _test_unbind_ports_get_client(self, mock_neutron, mock_show):
5215+
@mock.patch('nova.network.neutron.get_client')
5216+
def test_unbind_ports_get_client(self, mock_neutron, mock_show):
52165217
mock_ctx = mock.Mock(is_admin=False)
52175218
ports = ["1", "2", "3"]
52185219

@@ -5228,23 +5229,16 @@ def _test_unbind_ports_get_client(self, mock_neutron, mock_show):
52285229
self.assertEqual(1, mock_neutron.call_count)
52295230
mock_neutron.assert_has_calls(get_client_calls, True)
52305231

5231-
@mock.patch('nova.network.neutron.get_client')
5232-
def test_unbind_ports_get_client_binding_extension(self,
5233-
mock_neutron):
5234-
self._test_unbind_ports_get_client(mock_neutron)
5235-
5236-
@mock.patch('nova.network.neutron.get_client')
5237-
def test_unbind_ports_get_client(self, mock_neutron):
5238-
self._test_unbind_ports_get_client(mock_neutron)
5239-
52405232
@mock.patch('nova.network.neutron.API._show_port')
5241-
def _test_unbind_ports(self, mock_neutron, mock_show):
5233+
@mock.patch('nova.network.neutron.get_client')
5234+
def test_unbind_ports(self, mock_neutron, mock_show):
52425235
mock_client = mock.Mock()
52435236
mock_update_port = mock.Mock()
52445237
mock_client.update_port = mock_update_port
52455238
mock_ctx = mock.Mock(is_admin=False)
52465239
ports = ["1", "2", "3"]
52475240
mock_show.side_effect = [{"id": "1"}, {"id": "2"}, {"id": "3"}]
5241+
52485242
api = neutronapi.API()
52495243
api._unbind_ports(mock_ctx, ports, mock_neutron, mock_client)
52505244

@@ -5258,14 +5252,6 @@ def _test_unbind_ports(self, mock_neutron, mock_show):
52585252
self.assertEqual(3, mock_update_port.call_count)
52595253
mock_update_port.assert_has_calls(update_port_calls)
52605254

5261-
@mock.patch('nova.network.neutron.get_client')
5262-
def test_unbind_ports_binding_ext(self, mock_neutron):
5263-
self._test_unbind_ports(mock_neutron)
5264-
5265-
@mock.patch('nova.network.neutron.get_client')
5266-
def test_unbind_ports(self, mock_neutron):
5267-
self._test_unbind_ports(mock_neutron)
5268-
52695255
def test_unbind_ports_no_port_ids(self):
52705256
# Tests that None entries in the ports list are filtered out.
52715257
mock_client = mock.Mock()
@@ -6014,7 +6000,6 @@ def test_get_instance_id_by_floating_address_port_not_found(self,
60146000
def test_unbind_ports_port_show_portnotfound(self, mock_log, mock_show):
60156001
api = neutronapi.API()
60166002
neutron_client = mock.Mock()
6017-
mock_show.return_value = {'id': uuids.port}
60186003
api._unbind_ports(self.context, [uuids.port_id],
60196004
neutron_client, neutron_client)
60206005
mock_show.assert_called_once_with(
@@ -6023,6 +6008,59 @@ def test_unbind_ports_port_show_portnotfound(self, mock_log, mock_show):
60236008
neutron_client=mock.ANY)
60246009
mock_log.assert_not_called()
60256010

6011+
@mock.patch('nova.network.neutron.API._show_port')
6012+
@mock.patch.object(neutronapi, 'LOG')
6013+
def test_unbind_ports_port_show_portnotfound_multiple_ports(
6014+
self, mock_log, mock_show,
6015+
):
6016+
"""Ensure we continue unbinding ports even when one isn't found."""
6017+
mock_show.side_effect = [
6018+
exception.PortNotFound(port_id=uuids.port_a),
6019+
{'id': uuids.port_b},
6020+
]
6021+
api = neutronapi.API()
6022+
neutron_client = mock.Mock()
6023+
6024+
api._unbind_ports(
6025+
self.context,
6026+
[uuids.port_a, uuids.port_b],
6027+
neutron_client,
6028+
neutron_client,
6029+
)
6030+
6031+
mock_show.assert_has_calls(
6032+
[
6033+
mock.call(
6034+
self.context,
6035+
uuids.port_a,
6036+
fields=['binding:profile', 'network_id'],
6037+
neutron_client=neutron_client,
6038+
),
6039+
mock.call(
6040+
self.context,
6041+
uuids.port_b,
6042+
fields=['binding:profile', 'network_id'],
6043+
neutron_client=neutron_client,
6044+
),
6045+
]
6046+
)
6047+
# Only the port that exists should be updated
6048+
neutron_client.update_port.assert_called_once_with(
6049+
uuids.port_b,
6050+
{
6051+
'port': {
6052+
'device_id': '',
6053+
'device_owner': '',
6054+
'binding:profile': {},
6055+
'binding:host_id': None,
6056+
}
6057+
}
6058+
)
6059+
mock_log.exception.assert_not_called()
6060+
mock_log.debug.assert_called_with(
6061+
'Unable to show port %s as it no longer exists.', uuids.port_a,
6062+
)
6063+
60266064
@mock.patch('nova.network.neutron.API._show_port',
60276065
side_effect=Exception)
60286066
@mock.patch.object(neutronapi.LOG, 'exception')
@@ -6042,7 +6080,7 @@ def test_unbind_ports_port_show_unexpected_error(self,
60426080

60436081
@mock.patch('nova.network.neutron.API._show_port')
60446082
@mock.patch.object(neutronapi.LOG, 'exception')
6045-
def test_unbind_ports_portnotfound(self, mock_log, mock_show):
6083+
def test_unbind_ports_port_update_portnotfound(self, mock_log, mock_show):
60466084
api = neutronapi.API()
60476085
neutron_client = mock.Mock()
60486086
neutron_client.update_port = mock.Mock(
@@ -6058,7 +6096,9 @@ def test_unbind_ports_portnotfound(self, mock_log, mock_show):
60586096

60596097
@mock.patch('nova.network.neutron.API._show_port')
60606098
@mock.patch.object(neutronapi.LOG, 'exception')
6061-
def test_unbind_ports_unexpected_error(self, mock_log, mock_show):
6099+
def test_unbind_ports_port_update_unexpected_error(
6100+
self, mock_log, mock_show,
6101+
):
60626102
api = neutronapi.API()
60636103
neutron_client = mock.Mock()
60646104
neutron_client.update_port = mock.Mock(

0 commit comments

Comments
 (0)