Handle neutron-client conflict
When user tries to add stateless and stateful security groups on same port, neutron raises SecurityGroupConflict (409), but nova doesnot handle it and raises InternalServerError (500). As it appears to be invalid operation from user, so user should get the message that they are doing wrong. This changes catches SecurityGroupConflict from neutron client and raises newly added nova exception SecurityGroupConnectionStateConflict with 409 error code. Closes-Bug: #2056195 Change-Id: Ifad28fdd536ff0a4b30e786b2fcbc5a55987a13a
This commit is contained in:
@@ -441,7 +441,8 @@ class SecurityGroupActionController(wsgi.Controller):
|
||||
except (exception.SecurityGroupNotFound,
|
||||
exception.InstanceNotFound) as exp:
|
||||
raise exc.HTTPNotFound(explanation=exp.format_message())
|
||||
except exception.NoUniqueMatch as exp:
|
||||
except (exception.NoUniqueMatch,
|
||||
exception.SecurityGroupConnectionStateConflict) as exp:
|
||||
raise exc.HTTPConflict(explanation=exp.format_message())
|
||||
except exception.SecurityGroupCannotBeApplied as exp:
|
||||
raise exc.HTTPBadRequest(explanation=exp.format_message())
|
||||
|
@@ -1056,6 +1056,12 @@ class SecurityGroupCannotBeApplied(Invalid):
|
||||
" in order to apply security groups.")
|
||||
|
||||
|
||||
class SecurityGroupConnectionStateConflict(Invalid):
|
||||
code = 409
|
||||
msg_fmt = _("Cannot apply both stateful and stateless security groups on "
|
||||
"the same port.")
|
||||
|
||||
|
||||
class NoUniqueMatch(NovaException):
|
||||
msg_fmt = _("No Unique Match Found.")
|
||||
code = 409
|
||||
|
@@ -649,6 +649,8 @@ def add_to_instance(context, instance, security_group_name):
|
||||
except n_exc.NeutronClientException as e:
|
||||
if e.status_code == 400:
|
||||
raise exception.SecurityGroupCannotBeApplied(str(e))
|
||||
elif e.status_code == 409:
|
||||
raise exception.SecurityGroupConnectionStateConflict(str(e))
|
||||
else:
|
||||
raise e
|
||||
except Exception:
|
||||
|
@@ -373,6 +373,38 @@ class TestNeutronDriver(test.NoDBTestCase):
|
||||
self.mocked_client.update_port.assert_called_once_with(
|
||||
port_id, {'port': {'security_groups': [sg_id]}})
|
||||
|
||||
def test_add_to_instance_with_conflicting_sg(self):
|
||||
sg1_name = 'sg-stateful'
|
||||
sg1_id = '85cc3048-abc3-43cc-89b3-377341426ac5'
|
||||
port_id = 1
|
||||
port_list = {'ports': [{'id': port_id, 'device_id': uuids.instance,
|
||||
'fixed_ips': [{'ip_address': '10.0.0.1'}],
|
||||
'port_security_enabled': True, 'security_groups': []}]}
|
||||
self.mocked_client.list_ports.return_value = port_list
|
||||
with mock.patch.object(neutronv20, 'find_resourceid_by_name_or_id',
|
||||
return_value=sg1_id):
|
||||
sg_api.add_to_instance(
|
||||
self.context, objects.Instance(uuid=uuids.instance), sg1_name)
|
||||
self.mocked_client.list_ports.assert_called_once_with(
|
||||
device_id=uuids.instance)
|
||||
self.mocked_client.update_port.assert_called_once_with(
|
||||
port_id, {'port': {'security_groups': [sg1_id]}})
|
||||
|
||||
sg2_name = 'sg-stateless'
|
||||
sg2_id = '85cc3048-abc3-43cc-89b3-377341426ac5'
|
||||
port_id = 1
|
||||
port_list = {'ports': [{'id': port_id, 'device_id': uuids.instance,
|
||||
'fixed_ips': [{'ip_address': '10.0.0.1'}],
|
||||
'port_security_enabled': True, 'security_groups': []}]}
|
||||
self.mocked_client.list_ports.return_value = port_list
|
||||
self.mocked_client.update_port.side_effect = (
|
||||
n_exc.Conflict(message='error'))
|
||||
with mock.patch.object(neutronv20, 'find_resourceid_by_name_or_id',
|
||||
return_value=sg2_id):
|
||||
self.assertRaises(exception.SecurityGroupConnectionStateConflict,
|
||||
sg_api.add_to_instance, self.context,
|
||||
objects.Instance(uuid=uuids.instance), sg2_name)
|
||||
|
||||
def test_add_to_instance_duplicate_sg_name(self):
|
||||
sg_name = 'web_server'
|
||||
with mock.patch.object(neutronv20, 'find_resourceid_by_name_or_id',
|
||||
|
Reference in New Issue
Block a user