From af67fb5ab9e1704316efe38b69fd2e9a7e903599 Mon Sep 17 00:00:00 2001 From: lxiaopei Date: Mon, 15 Nov 2021 18:24:57 +0800 Subject: [PATCH] Add all_results param in get_ip_subnet_realization_info Since there are two realized entities for subnet in API policy/api/v1/infra/realized-state/realized-entities?intent_path=/infra/ip-pools/pool-1/ip-subnets/subnet-1, sometimes we want to check the realization state for all entities. Add all_results param in get_ip_subnet_realization_info func to check all the entities realization state, and return all the realized entities if no entity_type param set. The default value for all_results is False. Change-Id: I5a48c8f7e711090b38ea31d5f732f022bc7bd4bc (cherry picked from commit a62e5ad1113c80a02f75d0d10b450b46a3f88108) --- .../tests/unit/v3/policy/test_resources.py | 64 +++++++++++++++++++ vmware_nsxlib/v3/policy/core_resources.py | 43 ++++++++++--- 2 files changed, 97 insertions(+), 10 deletions(-) diff --git a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py index 58d4d2ef..e3415d4b 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py +++ b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py @@ -5083,6 +5083,70 @@ class TestPolicyIpPool(NsxPolicyLibTestCase): wait=True, subnet_type=constants.IPPOOL_STATIC_SUBNET) api_get.assert_called_once() + def test_get_ip_subnet_realization_info_timeout(self): + ip_pool_id = '111' + ip_subnet_id = 'subnet-id' + subnet_id = 'realized_111' + pool_id = 'realized_222' + info = [{'state': constants.STATE_UNREALIZED, + 'realization_specific_identifier': subnet_id, + 'entity_type': 'IpBlockSubnet'}, + {'state': constants.STATE_REALIZED, + 'realization_specific_identifier': pool_id, + 'entity_type': 'IpPool'}] + with mock.patch.object(self.resourceApi, "_get_realization_info", + return_value=info): + self.assertRaises(nsxlib_exc.RealizationTimeoutError, + self.resourceApi.get_ip_subnet_realization_info, + ip_pool_id, ip_subnet_id, tenant=TEST_TENANT, + wait=True, all_results=True) + + def test_get_ip_subnet_realization_info_error(self): + ip_pool_id = '111' + ip_subnet_id = 'subnet-id' + subnet_id = 'realized_111' + info = [{'state': constants.STATE_REALIZED, + 'realization_specific_identifier': subnet_id, + 'entity_type': 'IpBlockSubnet'}, + {'state': constants.STATE_ERROR, + 'alarms': [{'message': 'dummy', + 'error_details': { + 'error_code': 5109}}], + 'entity_type': 'IpPool'}] + with mock.patch.object(self.resourceApi, "_get_realization_info", + return_value=info): + self.assertRaises(nsxlib_exc.RealizationErrorStateError, + self.resourceApi.get_ip_subnet_realization_info, + ip_pool_id, ip_subnet_id, tenant=TEST_TENANT, + wait=True, all_results=True) + with mock.patch.object(self.resourceApi, "_get_realization_info", + return_value=info): + with self.assertRaises(nsxlib_exc.RealizationErrorStateError) as e: + self.resourceApi.get_ip_subnet_realization_info( + ip_pool_id, ip_subnet_id, tenant=TEST_TENANT, + wait=True, all_results=True) + self.assertTrue(e.exception.msg.endswith('dummy')) + self.assertEqual(e.exception.error_code, 5109) + self.assertEqual(e.exception.related_error_codes, []) + + def test_get_ip_subnet_realization_info_succeed(self): + ip_pool_id = '111' + ip_subnet_id = 'subnet-id' + subnet_id = 'realized_111' + pool_id = 'realized_222' + info = [{'state': constants.STATE_REALIZED, + 'realization_specific_identifier': subnet_id, + 'entity_type': 'IpBlockSubnet'}, + {'state': constants.STATE_REALIZED, + 'realization_specific_identifier': pool_id, + 'entity_type': 'IpPool'}] + with mock.patch.object(self.resourceApi, "_get_realization_info", + return_value=info) as api_get: + self.resourceApi.get_ip_subnet_realization_info( + ip_pool_id, ip_subnet_id, tenant=TEST_TENANT, + wait=True, all_results=True) + api_get.assert_called_once() + def test_wait_until_realized_fail(self): ip_pool_id = 'p1' info = {'state': constants.STATE_UNREALIZED, diff --git a/vmware_nsxlib/v3/policy/core_resources.py b/vmware_nsxlib/v3/policy/core_resources.py index 0d779fd9..9c3ece50 100644 --- a/vmware_nsxlib/v3/policy/core_resources.py +++ b/vmware_nsxlib/v3/policy/core_resources.py @@ -264,7 +264,8 @@ class NsxPolicyResourceBase(object, metaclass=abc.ABCMeta): return error_msg, error_code, related_error_codes def _wait_until_realized(self, resource_def, entity_type=None, - sleep=None, max_attempts=None): + sleep=None, max_attempts=None, + all_results=False): """Wait until the resource has been realized Return the realization info, or raise an error @@ -278,13 +279,34 @@ class NsxPolicyResourceBase(object, metaclass=abc.ABCMeta): @utils.retry_upon_none_result(max_attempts, delay=sleep, random=True) def get_info(): info = self._get_realization_info( - resource_def, entity_type=entity_type, silent=True) + resource_def, entity_type=entity_type, + silent=True, all_results=all_results) + error_entity = None if info: - if info['state'] == constants.STATE_REALIZED: - return info - if info['state'] == constants.STATE_ERROR: + # the state can be 'REALIZED'/'UNREALIZED'/'ERROR' + if isinstance(info, list): + # check all the realization entry + i = 0 + for entity in info: + if entity['state'] == constants.STATE_REALIZED: + i += 1 + continue + if entity['state'] == constants.STATE_ERROR: + error_entity = entity + break + # all the entities are in "REALIZED" state + if i == len(info): + # return all the realization entities + return info + else: + if info['state'] == constants.STATE_REALIZED: + return info + if info['state'] == constants.STATE_ERROR: + error_entity = info + if error_entity: error_msg, error_code, related_error_codes = \ - self._get_realization_error_message_and_code(info) + self._get_realization_error_message_and_code( + error_entity) # There could be a delay between setting NSX-T # Error realization state and updating the realization # entity with alarms. Retry should be perform upon None @@ -3510,7 +3532,7 @@ class NsxPolicyIpPoolApi(NsxPolicyResourceBase): tenant=constants.POLICY_INFRA_TENANT, wait=False, sleep=None, max_attempts=None, - subnet_type=constants.IPPOOL_BLOCK_SUBNET): + subnet_type=constants.IPPOOL_BLOCK_SUBNET, all_results=False): if subnet_type == constants.IPPOOL_BLOCK_SUBNET: ip_subnet_def = core_defs.IpPoolBlockSubnetDef( ip_pool_id=ip_pool_id, @@ -3524,9 +3546,10 @@ class NsxPolicyIpPoolApi(NsxPolicyResourceBase): if wait: return self._wait_until_realized( ip_subnet_def, entity_type=entity_type, - sleep=sleep, max_attempts=max_attempts) - return self._get_realization_info(ip_subnet_def, - entity_type=entity_type) + sleep=sleep, max_attempts=max_attempts, + all_results=all_results) + return self._get_realization_info( + ip_subnet_def, entity_type=entity_type, all_results=all_results) def get_ip_alloc_realization_info(self, ip_pool_id, ip_allocation_id, entity_type=None,