diff --git a/tools/policy/poltool.py b/tools/policy/poltool.py index 570781b5..bcfd847d 100755 --- a/tools/policy/poltool.py +++ b/tools/policy/poltool.py @@ -51,7 +51,7 @@ requests.packages.urllib3.disable_warnings(InsecureRequestWarning) path.append(os.path.abspath("../../")) -OPERATIONS = ("create", "update", "delete", "get") +OPERATIONS = ("create", "update", "delete", "get", "state") RESOURCES = ("domain", "service", "icmp_service", "group", "tier1", "segment", "tier1_segment", "segment_port") @@ -163,6 +163,21 @@ def delete_resource(lib, resource_type, resource_id): api.delete(*ids) +def get_realized_state_for_resource(lib, resource_type, resource_id): + from vmware_nsxlib.v3 import exceptions as exc + + api = get_resource_api(lib, resource_type) + + ids = build_ids(resource_id) + try: + result = api.get_realization_info(*ids) + except exc.ResourceNotFound: + print("Resource of type %s %s not found" % (resource_type, ids)) + sys.exit(2) + + return result + + def main(argv=sys.argv): from vmware_nsxlib import v3 @@ -235,6 +250,10 @@ def main(argv=sys.argv): delete_resource(nsxlib, resource_type, resource_id) elif op == 'update': update_resource(nsxlib, resource_type, resource_id, resource_args) + elif op == 'state': + result = get_realized_state_for_resource( + nsxlib, resource_type, resource_id) + print(json.dumps(result, indent=4)) else: custom_operation(nsxlib, op, resource_type, resource_id, resource_args) diff --git a/vmware_nsxlib/tests/unit/v3/test_policy_resources.py b/vmware_nsxlib/tests/unit/v3/test_policy_resources.py index b357ccd9..2f469648 100644 --- a/vmware_nsxlib/tests/unit/v3/test_policy_resources.py +++ b/vmware_nsxlib/tests/unit/v3/test_policy_resources.py @@ -399,18 +399,31 @@ class TestPolicyGroup(NsxPolicyLibTestCase): def test_get_realized(self): domain_id = 'd1' - id = 'g1' - ep_id = 'ef1' - result = {'state': policy_constants.STATE_REALIZED} + group_id = 'g1' + result = [{'state': policy_constants.STATE_REALIZED}] with mock.patch.object( - self.policy_api, "get_by_path", + self.policy_api, "get_realized_entities", return_value=result) as api_get: state = self.resourceApi.get_realized_state( - domain_id, id, ep_id, tenant=TEST_TENANT) + domain_id, group_id, tenant=TEST_TENANT) self.assertEqual(policy_constants.STATE_REALIZED, state) - expected_path = policy_defs.REALIZED_STATE_GROUP % ( - TEST_TENANT, ep_id, domain_id, id) - api_get.assert_called_once_with(expected_path) + path = "/%s/domains/%s/groups/%s" % ( + TEST_TENANT, domain_id, group_id) + api_get.assert_called_once_with(path) + + def test_get_realized_id(self): + domain_id = 'd1' + group_id = 'g1' + result = [{'state': policy_constants.STATE_REALIZED}] + with mock.patch.object( + self.policy_api, "get_realized_entities", + return_value=result) as api_get: + state = self.resourceApi.get_realized_state( + domain_id, group_id, tenant=TEST_TENANT) + self.assertEqual(policy_constants.STATE_REALIZED, state) + path = "/%s/domains/%s/groups/%s" % ( + TEST_TENANT, domain_id, group_id) + api_get.assert_called_once_with(path) class TestPolicyService(NsxPolicyLibTestCase): @@ -1242,17 +1255,16 @@ class TestPolicyCommunicationMap(NsxPolicyLibTestCase): def test_get_realized(self): domain_id = 'd1' map_id = '111' - ep_id = 'ef1' - result = {'state': policy_constants.STATE_REALIZED} + result = [{'state': policy_constants.STATE_REALIZED}] with mock.patch.object( - self.policy_api, "get_by_path", + self.policy_api, "get_realized_entities", return_value=result) as api_get: state = self.resourceApi.get_realized_state( - domain_id, map_id, ep_id, tenant=TEST_TENANT) + domain_id, map_id, tenant=TEST_TENANT) self.assertEqual(policy_constants.STATE_REALIZED, state) - expected_path = policy_defs.REALIZED_STATE_COMM_MAP % ( - TEST_TENANT, ep_id, domain_id, map_id) - api_get.assert_called_once_with(expected_path) + path = "/%s/domains/%s/security-policies/%s" % ( + TEST_TENANT, domain_id, map_id) + api_get.assert_called_once_with(path) class TestPolicyEnforcementPoint(NsxPolicyLibTestCase): @@ -1367,16 +1379,16 @@ class TestPolicyEnforcementPoint(NsxPolicyLibTestCase): def test_get_realized(self): ep_id = 'ef1' - result = {'state': policy_constants.STATE_REALIZED} + result = [{'state': policy_constants.STATE_REALIZED}] with mock.patch.object( - self.policy_api, "get_by_path", + self.policy_api, "get_realized_entities", return_value=result) as api_get: state = self.resourceApi.get_realized_state( ep_id, tenant=TEST_TENANT) self.assertEqual(policy_constants.STATE_REALIZED, state) - expected_path = policy_defs.REALIZED_STATE_EF % ( + path = "/%s/sites/default/enforcement-points/%s" % ( TEST_TENANT, ep_id) - api_get.assert_called_once_with(expected_path) + api_get.assert_called_once_with(path) class TestPolicyDeploymentMap(NsxPolicyLibTestCase): diff --git a/vmware_nsxlib/v3/policy_defs.py b/vmware_nsxlib/v3/policy_defs.py index dbc9e6e3..df682f8c 100644 --- a/vmware_nsxlib/v3/policy_defs.py +++ b/vmware_nsxlib/v3/policy_defs.py @@ -30,12 +30,8 @@ SERVICES_PATH_PATTERN = TENANTS_PATH_PATTERN + "services/" ENFORCEMENT_POINT_PATTERN = (TENANTS_PATH_PATTERN + "sites/default/enforcement-points/") TRANSPORT_ZONE_PATTERN = ENFORCEMENT_POINT_PATTERN + "%s/transport-zones/" -REALIZED_STATE_EF = (TENANTS_PATH_PATTERN + - "realized-state/enforcement-points/%s/") -REALIZED_STATE_GROUP = REALIZED_STATE_EF + "groups/nsgroups/DOMAIN-%s-%s" -REALIZED_STATE_COMM_MAP = (REALIZED_STATE_EF + - "firewalls/firewall-sections/%s.%s") -REALIZED_STATE_SERVICE = REALIZED_STATE_EF + "services/nsservices/services:%s" + +REALIZATION_PATH = "infra/realized-state/realized-entities?intent_path=%s" @six.add_metaclass(abc.ABCMeta) @@ -496,11 +492,6 @@ class GroupDef(ResourceDef): del kwargs['conditions'] super(GroupDef, self).update_attributes_in_body(body=body, **kwargs) - def get_realized_state_path(self, ep_id): - return REALIZED_STATE_GROUP % (self.get_tenant(), ep_id, - self.get_attr('domain_id'), - self.get_id()) - class ServiceDef(ResourceDef): def __init__(self, **kwargs): @@ -531,10 +522,6 @@ class ServiceDef(ResourceDef): def sub_entries_path(): return ServiceEntryDef().get_last_section_dict_key - def get_realized_state_path(self, ep_id): - return REALIZED_STATE_SERVICE % (self.get_tenant(), ep_id, - self.get_id()) - class ServiceEntryDef(ResourceDef): @@ -608,11 +595,6 @@ class CommunicationMapDef(ResourceDef): def resource_type(): return 'SecurityPolicy' - def get_realized_state_path(self, ep_id): - return REALIZED_STATE_COMM_MAP % (self.get_tenant(), ep_id, - self.get_attr('domain_id'), - self.get_id()) - def get_obj_dict(self): body = super(CommunicationMapDef, self).get_obj_dict() for attr in ('category', 'precedence'): @@ -748,9 +730,6 @@ class EnforcementPointDef(ResourceDef): return body - def get_realized_state_path(self): - return REALIZED_STATE_EF % (self.get_tenant(), self.get_id()) - class TransportZoneDef(ResourceDef): @@ -858,5 +837,17 @@ class NsxPolicyApi(object): path = resource_def.get_section_path() return self.client.list(path) - def get_by_path(self, path): - return self.client.get(path) + def get_realized_entities(self, path): + return self.client.list(REALIZATION_PATH % path)['results'] + + def get_realized_entity(self, path): + # Return first realization entity if exists + # Useful for resources with single realization entity + entities = self.get_realized_entities(path) + if entities: + return entities[0] + + def get_realized_state(self, path): + entity = self.get_realized_entity(path) + if entity: + return entity['state'] diff --git a/vmware_nsxlib/v3/policy_resources.py b/vmware_nsxlib/v3/policy_resources.py index 58c0d201..aaf48d62 100644 --- a/vmware_nsxlib/v3/policy_resources.py +++ b/vmware_nsxlib/v3/policy_resources.py @@ -133,15 +133,24 @@ class NsxPolicyResourceBase(object): if obj.get('display_name') == name: return obj - def _get_realized_state(self, path): + def _get_realization_info(self, resource_def): try: - result = self.policy_api.get_by_path(path) - if result and result.get('state'): - return result['state'] + path = resource_def.get_resource_full_path() + return self.policy_api.get_realized_entity(path) except exceptions.ResourceNotFound: # resource not deployed yet LOG.warning("No realized state found for %s", path) + def _get_realized_state(self, resource_def): + info = self._get_realization_info(resource_def) + if info and info.get('state'): + return info['state'] + + def _get_realized_id(self, resource_def): + info = self._get_realization_info(resource_def) + if info and info.get('realization_specific_identifier'): + return info['realization_specific_identifier'] + def _list(self, obj_def): return self.policy_api.list(obj_def).get('results', []) @@ -309,13 +318,26 @@ class NsxPolicyGroupApi(NsxPolicyResourceBase): tags=tags, tenant=tenant) - def get_realized_state(self, domain_id, group_id, ep_id, + def get_realized_state(self, domain_id, group_id, tenant=policy_constants.POLICY_INFRA_TENANT): group_def = policy_defs.GroupDef(domain_id=domain_id, group_id=group_id, tenant=tenant) - path = group_def.get_realized_state_path(ep_id) - return self._get_realized_state(path) + return self._get_realized_state(group_def) + + def get_realized_id(self, domain_id, group_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + group_def = policy_defs.GroupDef(domain_id=domain_id, + group_id=group_id, + tenant=tenant) + return self._get_realized_id(group_def) + + def get_realization_info(self, domain_id, group_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + group_def = policy_defs.GroupDef(domain_id=domain_id, + group_id=group_id, + tenant=tenant) + return self._get_realization_info(group_def) class NsxPolicyServiceBase(NsxPolicyResourceBase): @@ -346,12 +368,23 @@ class NsxPolicyServiceBase(NsxPolicyResourceBase): service_def = policy_defs.ServiceDef(tenant=tenant) return self._list(service_def) - def get_realized_state(self, service_id, ep_id, + def get_realized_state(self, service_id, tenant=policy_constants.POLICY_INFRA_TENANT): service_def = policy_defs.ServiceDef(service_id=service_id, tenant=tenant) - path = service_def.get_realized_state_path(ep_id) - return self._get_realized_state(path) + return self._get_realized_state(service_def) + + def get_realized_id(self, service_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + service_def = policy_defs.ServiceDef(service_id=service_id, + tenant=tenant) + return self._get_realized_id(service_def) + + def get_realization_info(self, service_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + service_def = policy_defs.ServiceDef(service_id=service_id, + tenant=tenant) + return self._get_realization_info(service_def) class NsxPolicyL4ServiceApi(NsxPolicyServiceBase): @@ -795,6 +828,21 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): tags=tags, tenant=tenant) + def get_realized_state(self, segment_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + segment_def = self.entry_def(segment_id=segment_id, tenant=tenant) + return self._get_realized_state(segment_def) + + def get_realized_id(self, segment_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + segment_def = self.entry_def(segment_id=segment_id, tenant=tenant) + return self._get_realized_id(segment_def) + + def get_realization_info(self, segment_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + segment_def = self.entry_def(segment_id=segment_id, tenant=tenant) + return self._get_realization_info(segment_def) + class NsxPolicySegmentPortApi(NsxPolicyResourceBase): """NSX Segment Port API """ @@ -901,6 +949,27 @@ class NsxPolicySegmentPortApi(NsxPolicyResourceBase): self.policy_api.create_or_update(port_def) + def get_realized_state(self, segment_id, port_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + port_def = self.entry_def(segment_id=segment_id, + port_id=port_id, + tenant=tenant) + return self._get_realized_state(port_def) + + def get_realized_id(self, segment_id, port_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + port_def = self.entry_def(segment_id=segment_id, + port_id=port_id, + tenant=tenant) + return self._get_realized_id(port_def) + + def get_realization_info(self, segment_id, port_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + port_def = self.entry_def(segment_id=segment_id, + port_id=port_id, + tenant=tenant) + return self._get_realization_info(port_def) + class NsxPolicyCommunicationMapApi(NsxPolicyResourceBase): """NSX Policy CommunicationMap (Under a Domain).""" @@ -1181,13 +1250,26 @@ class NsxPolicyCommunicationMapApi(NsxPolicyResourceBase): _update() - def get_realized_state(self, domain_id, map_id, ep_id, + def get_realized_state(self, domain_id, map_id, tenant=policy_constants.POLICY_INFRA_TENANT): map_def = policy_defs.CommunicationMapDef(map_id=map_id, domain_id=domain_id, tenant=tenant) - path = map_def.get_realized_state_path(ep_id) - return self._get_realized_state(path) + return self._get_realized_state(map_def) + + def get_realized_id(self, domain_id, map_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + map_def = policy_defs.CommunicationMapDef(map_id=map_id, + domain_id=domain_id, + tenant=tenant) + return self._get_realized_id(map_def) + + def get_realization_info(self, domain_id, map_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + map_def = policy_defs.CommunicationMapDef(map_id=map_id, + domain_id=domain_id, + tenant=tenant) + return self._get_realization_info(map_def) class NsxPolicyEnforcementPointApi(NsxPolicyResourceBase): @@ -1269,8 +1351,12 @@ class NsxPolicyEnforcementPointApi(NsxPolicyResourceBase): def get_realized_state(self, ep_id, tenant=policy_constants.POLICY_INFRA_TENANT): ep_def = policy_defs.EnforcementPointDef(ep_id=ep_id, tenant=tenant) - path = ep_def.get_realized_state_path() - return self._get_realized_state(path) + return self._get_realized_state(ep_def) + + def get_realization_info(self, ep_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + ep_def = policy_defs.EnforcementPointDef(ep_id=ep_id, tenant=tenant) + return self._get_realization_info(ep_def) class NsxPolicyTransportZoneApi(NsxPolicyResourceBase):