diff --git a/octavia/api/v2/controllers/member.py b/octavia/api/v2/controllers/member.py index 0f592492c6..d14d0a3119 100644 --- a/octavia/api/v2/controllers/member.py +++ b/octavia/api/v2/controllers/member.py @@ -293,6 +293,13 @@ class MembersController(MemberController): self._auth_validate_action(context, db_pool.project_id, constants.RBAC_DELETE) + # Validate member subnets + for member in members: + if member.subnet_id and not validate.subnet_exists( + member.subnet_id): + raise exceptions.NotFound(resource='Subnet', + id=member.subnet_id) + with db_api.get_lock_session() as lock_session: self._test_lb_and_listener_and_pool_statuses(lock_session) diff --git a/octavia/tests/functional/api/v2/test_member.py b/octavia/tests/functional/api/v2/test_member.py index 4cc805b733..7c1d599049 100644 --- a/octavia/tests/functional/api/v2/test_member.py +++ b/octavia/tests/functional/api/v2/test_member.py @@ -516,6 +516,24 @@ class TestMember(base.BaseAPITest): handler_args[1]) self.assertEqual(0, len(handler_args[2])) + def test_create_batch_members_with_bad_subnet(self): + subnet_id = uuidutils.generate_uuid() + member5 = {'address': '10.0.0.5', + 'protocol_port': 80, + 'subnet_id': subnet_id} + + req_dict = [member5] + body = {self.root_tag_list: req_dict} + path = self.MEMBERS_PATH.format(pool_id=self.pool_id) + + with mock.patch( + 'octavia.common.utils.get_network_driver') as net_mock: + net_mock.return_value.get_subnet = mock.Mock( + side_effect=network_base.SubnetNotFound('Subnet not found')) + response = self.put(path, body, status=400).json + err_msg = 'Subnet ' + subnet_id + ' not found.' + self.assertEqual(response.get('faultstring'), err_msg) + def test_update_batch_members(self): member1 = {'address': '192.0.2.1', 'protocol_port': 80} member2 = {'address': '192.0.2.2', 'protocol_port': 80}