From 1cb3fabe7570b884575fc4865e749d602bd40133 Mon Sep 17 00:00:00 2001 From: asarfaty Date: Sun, 19 Jul 2020 18:03:21 +0200 Subject: [PATCH] Add api for waiting for success consolidated status for gateway policy Change-Id: Ie6516d9d574bf4777f451d44439dc512a89245a7 --- .../tests/unit/v3/policy/test_resources.py | 51 +++++++++++++++++++ vmware_nsxlib/v3/policy/core_defs.py | 21 +++++++- vmware_nsxlib/v3/policy/core_resources.py | 46 +++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py index 8f47d788..86be8c69 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py +++ b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py @@ -2279,6 +2279,57 @@ class TestPolicyGatewayPolicy(TestPolicyCommunicationMap): service_ids=[service_id], scope=policy_id, dest_groups=[dest_group], plain_groups=True) + def test_get_realized(self): + domain_id = 'd1' + map_id = '111' + result = [{'state': constants.STATE_REALIZED, + 'entity_type': 'RealizedFirewallSection'}] + with mock.patch.object( + self.policy_api, "get_realized_entities", + return_value=result) as api_get: + state = self.resourceApi.get_realized_state( + domain_id, map_id, tenant=TEST_TENANT) + self.assertEqual(constants.STATE_REALIZED, state) + path = "/%s/domains/%s/%s/%s" % ( + TEST_TENANT, domain_id, self.path_name, map_id) + api_get.assert_called_once_with(path, silent=False) + + def test_wait_until_realized_failed(self): + domain_id = 'd1' + map_id = '111' + gw_section_id = 'realized_111' + info = {'state': constants.STATE_UNREALIZED, + 'realization_specific_identifier': gw_section_id} + with mock.patch.object(self.resourceApi, "_get_realization_info", + return_value=info): + self.assertRaises(nsxlib_exc.RealizationTimeoutError, + self.resourceApi.wait_until_realized, + domain_id, map_id, tenant=TEST_TENANT, + max_attempts=5, sleep=0.1) + + def test_wait_until_state_sucessful_with_error(self): + domain_id = 'd1' + map_id = '111' + info = {'consolidated_status': {'consolidated_status': 'ERROR'}} + with mock.patch.object(self.resourceApi.policy_api, + "get_intent_consolidated_status", + return_value=info): + self.assertRaises(nsxlib_exc.RealizationErrorStateError, + self.resourceApi.wait_until_state_sucessful, + domain_id, map_id, tenant=TEST_TENANT, + max_attempts=5, sleep=0.1) + + def test_wait_until_state_sucessful(self): + domain_id = 'd1' + map_id = '111' + info = {'consolidated_status': {'consolidated_status': 'SUCCESS'}} + with mock.patch.object(self.resourceApi.policy_api, + "get_intent_consolidated_status", + return_value=info): + self.resourceApi.wait_until_state_sucessful( + domain_id, map_id, tenant=TEST_TENANT, + max_attempts=5, sleep=0.1) + class TestPolicyEnforcementPoint(NsxPolicyLibTestCase): diff --git a/vmware_nsxlib/v3/policy/core_defs.py b/vmware_nsxlib/v3/policy/core_defs.py index 6a200607..05d8755a 100644 --- a/vmware_nsxlib/v3/policy/core_defs.py +++ b/vmware_nsxlib/v3/policy/core_defs.py @@ -18,6 +18,7 @@ import abc from distutils import version from oslo_log import log as logging +import requests import six from vmware_nsxlib.v3 import exceptions @@ -58,8 +59,14 @@ WAF_PROFILES_PATH_PATTERN = (TENANTS_PATH_PATTERN + CERTIFICATE_PATH_PATTERN = TENANTS_PATH_PATTERN + "certificates/" EXCLUDE_LIST_PATH_PATTERN = (TENANTS_PATH_PATTERN + "settings/firewall/security/exclude-list") - -REALIZATION_PATH = "infra/realized-state/realized-entities?intent_path=%s" +REALIZATION_PATH_PREFIX = "infra/realized-state/" +REALIZATION_PATH_SUFFIX = "?intent_path=%s" +REALIZATION_PATH = (REALIZATION_PATH_PREFIX + "realized-entities" + + REALIZATION_PATH_SUFFIX) +REALIZATION_REFRESH_PATH = (REALIZATION_PATH_PREFIX + "realized-entity" + + REALIZATION_PATH_SUFFIX + "&action=refresh") +REALIZATION_STATUS_PATH = (REALIZATION_PATH_PREFIX + "status" + + REALIZATION_PATH_SUFFIX) DHCP_REALY_PATTERN = TENANTS_PATH_PATTERN + "dhcp-relay-configs/" DHCP_SERVER_PATTERN = TENANTS_PATH_PATTERN + "dhcp-server-configs/" MDPROXY_PATTERN = TENANTS_PATH_PATTERN + "metadata-proxies/" @@ -2525,6 +2532,16 @@ class NsxPolicyApi(object): if entity: return entity['state'] + def refresh_realized_state(self, path): + # Using POST, excepting 204 + expected_results = [requests.codes.no_content] + return self.client.create(REALIZATION_REFRESH_PATH % path, + expected_results=expected_results) + + def get_intent_consolidated_status(self, path, silent=False): + return self.client.get(REALIZATION_STATUS_PATH % path, + silent=silent) + class RouteMapEntry(object): def __init__(self, action, community_list_matches=None, diff --git a/vmware_nsxlib/v3/policy/core_resources.py b/vmware_nsxlib/v3/policy/core_resources.py index 43cee300..7ebd05c7 100644 --- a/vmware_nsxlib/v3/policy/core_resources.py +++ b/vmware_nsxlib/v3/policy/core_resources.py @@ -3696,6 +3696,52 @@ class NsxPolicySecurityPolicyBaseApi(NsxPolicyResourceBase): sleep=sleep, max_attempts=max_attempts) + def wait_until_state_sucessful(self, domain_id, map_id, + tenant=constants.POLICY_INFRA_TENANT, + sleep=None, max_attempts=None, + with_refresh=False): + map_def = self.parent_entry_def(map_id=map_id, + domain_id=domain_id, + tenant=tenant) + map_path = map_def.get_resource_full_path() + + if sleep is None: + sleep = self.nsxlib_config.realization_wait_sec + if max_attempts is None: + max_attempts = self.nsxlib_config.realization_max_attempts + + @utils.retry_upon_none_result(max_attempts, delay=sleep, random=True) + def get_state(): + state = self.policy_api.get_intent_consolidated_status( + map_path, silent=True) + if state and state.get('consolidated_status'): + con_state = state['consolidated_status'].get( + 'consolidated_status') + if con_state == 'SUCCESS': + return True + if con_state == 'ERROR': + raise exceptions.RealizationErrorStateError( + resource_type=map_def.resource_type(), + resource_id=map_def.get_id(), + error="Unknown") + if with_refresh: + # Refresh the consolidated state for the next time + # (if not, it will be refreshed at the policy level after a + # refresh cycle) + self.policy_api.refresh_realized_state(map_path) + + try: + return get_state() + except exceptions.RealizationError as e: + raise e + except Exception: + # max retries reached + raise exceptions.RealizationTimeoutError( + resource_type=map_def.resource_type(), + resource_id=map_def.get_id(), + attempts=max_attempts, + sleep=sleep) + class NsxPolicyCommunicationMapApi(NsxPolicySecurityPolicyBaseApi): """NSX Policy CommunicationMap (Under a Domain). AKA Security"""