From 7ebdb6428368bf5a32bb30e77846b8926004de21 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Mon, 29 Oct 2018 14:00:52 +0200 Subject: [PATCH] Readonly support for Policy transport zones Change-Id: I21c51576d1de4db6689335a0e5645d3b4e13ad26 --- .../tests/unit/v3/test_policy_api.py | 9 +++ .../tests/unit/v3/test_policy_resources.py | 69 +++++++++++++++++ vmware_nsxlib/v3/__init__.py | 2 + vmware_nsxlib/v3/core_resources.py | 8 +- vmware_nsxlib/v3/nsx_constants.py | 6 ++ vmware_nsxlib/v3/policy_constants.py | 1 + vmware_nsxlib/v3/policy_defs.py | 27 ++++++- vmware_nsxlib/v3/policy_resources.py | 77 +++++++++++++++++++ 8 files changed, 193 insertions(+), 6 deletions(-) diff --git a/vmware_nsxlib/tests/unit/v3/test_policy_api.py b/vmware_nsxlib/tests/unit/v3/test_policy_api.py index 2205732e..843df2af 100644 --- a/vmware_nsxlib/tests/unit/v3/test_policy_api.py +++ b/vmware_nsxlib/tests/unit/v3/test_policy_api.py @@ -301,6 +301,15 @@ class TestPolicyEnforcementPoint(TestPolicyApi): data=ep_def.get_obj_dict()) +class TestPolicyTransportZone(TestPolicyApi): + + def test_get(self): + tz_def = policy.TransportZoneDef(tz_id='tz1', ep_id='default') + self.policy_api.get(tz_def) + tz_path = tz_def.get_resource_path() + self.assert_json_call('GET', self.client, tz_path) + + class TestPolicyDeploymentMap(TestPolicyApi): def test_create(self): diff --git a/vmware_nsxlib/tests/unit/v3/test_policy_resources.py b/vmware_nsxlib/tests/unit/v3/test_policy_resources.py index 8d88d0c3..1b1a1924 100644 --- a/vmware_nsxlib/tests/unit/v3/test_policy_resources.py +++ b/vmware_nsxlib/tests/unit/v3/test_policy_resources.py @@ -1470,6 +1470,75 @@ class TestPolicyDeploymentMap(NsxPolicyLibTestCase): update_call, expected_def) +class TestPolicyTransportZone(NsxPolicyLibTestCase): + + def setUp(self, *args, **kwargs): + super(TestPolicyTransportZone, self).setUp() + self.resourceApi = self.policy_lib.transport_zone + + def test_get(self): + id = '111' + with mock.patch.object(self.policy_api, "get") as api_call: + self.resourceApi.get(id, tenant=TEST_TENANT) + expected_def = policy_defs.TransportZoneDef(tz_id=id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + def test_get_by_name(self): + name = 'tz1' + with mock.patch.object( + self.policy_api, "list", + return_value={'results': [{'display_name': name}]}) as api_call: + obj = self.resourceApi.get_by_name(name, tenant=TEST_TENANT) + self.assertIsNotNone(obj) + expected_def = policy_defs.TransportZoneDef(tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + def test_get_tz_type(self): + id = '111' + tz_type = self.resourceApi.TZ_TYPE_OVERLAY + with mock.patch.object(self.policy_api, "get", + return_value={'tz_type': tz_type}) as api_call: + actual_tz_type = self.resourceApi.get_tz_type( + id, tenant=TEST_TENANT) + expected_def = policy_defs.TransportZoneDef(tz_id=id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + self.assertEqual(tz_type, actual_tz_type) + + def test_get_transport_type(self): + id = '111' + tz_type = self.resourceApi.TZ_TYPE_OVERLAY + with mock.patch.object(self.policy_api, "get", + return_value={'tz_type': tz_type}) as api_call: + actual_tz_type = self.resourceApi.get_transport_type( + id, tenant=TEST_TENANT) + expected_def = policy_defs.TransportZoneDef(tz_id=id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + self.assertEqual(nsx_constants.TRANSPORT_TYPE_OVERLAY, + actual_tz_type) + + def test_get_switch_mode(self): + id = '111' + tz_type = self.resourceApi.TZ_TYPE_OVERLAY + with mock.patch.object(self.policy_api, "get", + return_value={'tz_type': tz_type}) as api_call: + actual_sm = self.resourceApi.get_host_switch_mode( + id, tenant=TEST_TENANT) + expected_def = policy_defs.TransportZoneDef(tz_id=id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + self.assertEqual(nsx_constants.HOST_SWITCH_MODE_STANDARD, + actual_sm) + + def test_list(self): + with mock.patch.object(self.policy_api, "list") as api_call: + self.resourceApi.list(tenant=TEST_TENANT) + expected_def = policy_defs.TransportZoneDef(tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + class TestPolicyTier1(NsxPolicyLibTestCase): def setUp(self, *args, **kwargs): diff --git a/vmware_nsxlib/v3/__init__.py b/vmware_nsxlib/v3/__init__.py index b3d87e7b..fef69470 100644 --- a/vmware_nsxlib/v3/__init__.py +++ b/vmware_nsxlib/v3/__init__.py @@ -400,6 +400,8 @@ class NsxPolicyLib(NsxLibBase): self.policy_api) self.enforcement_point = policy_resources.NsxPolicyEnforcementPointApi( self.policy_api) + self.transport_zone = policy_resources.NsxPolicyTransportZoneApi( + self.policy_api) self.deployment_map = policy_resources.NsxPolicyDeploymentMapApi( self.policy_api) diff --git a/vmware_nsxlib/v3/core_resources.py b/vmware_nsxlib/v3/core_resources.py index ab187e80..f1c9fd03 100644 --- a/vmware_nsxlib/v3/core_resources.py +++ b/vmware_nsxlib/v3/core_resources.py @@ -776,10 +776,10 @@ class NsxLibEdgeCluster(utils.NsxLibApiBase): class NsxLibTransportZone(utils.NsxLibApiBase): - TRANSPORT_TYPE_VLAN = 'VLAN' - TRANSPORT_TYPE_OVERLAY = 'OVERLAY' - HOST_SWITCH_MODE_ENS = 'ENS' - HOST_SWITCH_MODE_STANDARD = 'STANDARD' + TRANSPORT_TYPE_VLAN = nsx_constants.TRANSPORT_TYPE_VLAN + TRANSPORT_TYPE_OVERLAY = nsx_constants.TRANSPORT_TYPE_OVERLAY + HOST_SWITCH_MODE_ENS = nsx_constants.HOST_SWITCH_MODE_ENS + HOST_SWITCH_MODE_STANDARD = nsx_constants.HOST_SWITCH_MODE_STANDARD @property def uri_segment(self): diff --git a/vmware_nsxlib/v3/nsx_constants.py b/vmware_nsxlib/v3/nsx_constants.py index 4b68119d..8103246e 100644 --- a/vmware_nsxlib/v3/nsx_constants.py +++ b/vmware_nsxlib/v3/nsx_constants.py @@ -115,6 +115,12 @@ INGRESS = 'ingress' EGRESS_SHAPING = 'EgressRateShaper' INGRESS_SHAPING = 'IngressRateShaper' +# Transport zone constants +TRANSPORT_TYPE_VLAN = 'VLAN' +TRANSPORT_TYPE_OVERLAY = 'OVERLAY' +HOST_SWITCH_MODE_ENS = 'ENS' +HOST_SWITCH_MODE_STANDARD = 'STANDARD' + # Error codes returned by the backend ERR_CODE_OBJECT_NOT_FOUND = 202 ERR_CODE_IPAM_POOL_EXHAUSTED = 5109 diff --git a/vmware_nsxlib/v3/policy_constants.py b/vmware_nsxlib/v3/policy_constants.py index a9adc011..5dc89ab5 100644 --- a/vmware_nsxlib/v3/policy_constants.py +++ b/vmware_nsxlib/v3/policy_constants.py @@ -36,6 +36,7 @@ CONDITION_OP_OR = 'OR' DEFAULT_THUMBPRINT = 'abc' DEFAULT_DOMAIN = 'default' +DEFAULT_ENFORCEMENT_POINT = 'default' STATE_REALIZED = 'REALIZED' STATE_UNREALIZED = 'UNREALIZED' diff --git a/vmware_nsxlib/v3/policy_defs.py b/vmware_nsxlib/v3/policy_defs.py index d413f3f4..dbc9e6e3 100644 --- a/vmware_nsxlib/v3/policy_defs.py +++ b/vmware_nsxlib/v3/policy_defs.py @@ -27,6 +27,9 @@ PROVIDERS_PATH_PATTERN = TENANTS_PATH_PATTERN + "providers/" TIER0S_PATH_PATTERN = TENANTS_PATH_PATTERN + "tier-0s/" TIER1S_PATH_PATTERN = TENANTS_PATH_PATTERN + "tier-1s/" 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" @@ -354,6 +357,12 @@ class SegmentDef(BaseSegmentDef): tier1 = Tier1Def(tier1_id=self.get_attr('tier1_id'), tenant=self.get_tenant()) body['connectivity_path'] = tier1.get_resource_full_path() + if self.get_attr('transport_zone_id'): + tz = TransportZoneDef( + tz_id=self.get_attr('transport_zone_id'), + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=self.get_tenant()) + body['transport_zone_path'] = tz.get_resource_full_path() # TODO(annak): support also tier0 return body @@ -705,8 +714,7 @@ class EnforcementPointDef(ResourceDef): @property def path_pattern(self): - return (TENANTS_PATH_PATTERN + - 'sites/default/enforcement-points/') + return ENFORCEMENT_POINT_PATTERN @property def path_ids(self): @@ -744,6 +752,21 @@ class EnforcementPointDef(ResourceDef): return REALIZED_STATE_EF % (self.get_tenant(), self.get_id()) +class TransportZoneDef(ResourceDef): + + @property + def path_pattern(self): + return TRANSPORT_ZONE_PATTERN + + @property + def path_ids(self): + return ('tenant', 'ep_id', 'tz_id') + + @staticmethod + def resource_type(): + return 'PolicyTransportZone' + + # Currently assumes one deployment point per id class DeploymentMapDef(ResourceDef): diff --git a/vmware_nsxlib/v3/policy_resources.py b/vmware_nsxlib/v3/policy_resources.py index 2b276c6b..a40986a3 100644 --- a/vmware_nsxlib/v3/policy_resources.py +++ b/vmware_nsxlib/v3/policy_resources.py @@ -22,6 +22,7 @@ import six from vmware_nsxlib._i18n import _ from vmware_nsxlib.v3 import exceptions +from vmware_nsxlib.v3 import nsx_constants from vmware_nsxlib.v3 import policy_constants from vmware_nsxlib.v3 import policy_defs from vmware_nsxlib.v3 import utils @@ -746,6 +747,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): subnets=None, dns_domain_name=None, vlan_ids=None, + transport_zone_id=None, tags=None, tenant=policy_constants.POLICY_INFRA_TENANT): @@ -757,6 +759,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): subnets=subnets, dns_domain_name=dns_domain_name, vlan_ids=vlan_ids, + transport_zone_id=transport_zone_id, tags=tags, tenant=tenant) self.policy_api.create_or_update(segment_def) @@ -1269,6 +1272,80 @@ class NsxPolicyEnforcementPointApi(NsxPolicyResourceBase): return self._get_realized_state(path) +class NsxPolicyTransportZoneApi(NsxPolicyResourceBase): + """NSX Policy Enforcement Point.""" + + TZ_TYPE_OVERLAY = 'OVERLAY_STANDARD' + TZ_TYPE_ENS = 'OVERLAY_ENS' + TZ_TYPE_VLAN = 'VLAN_BACKED' + + @property + def entry_def(self): + return policy_defs.TransportZoneDef + + def get(self, tz_id, ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT, silent=False): + tz_def = policy_defs.TransportZoneDef( + ep_id=ep_id, tz_id=tz_id, tenant=tenant) + return self.policy_api.get(tz_def, silent=silent) + + def get_tz_type(self, tz_id, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + tz = self.get(tz_id, ep_id=ep_id, tenant=tenant) + return tz.get('tz_type') + + def get_transport_type(self, tz_id, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + """This api is consistent with the nsx manager resource api""" + tz_type = self.get_tz_type(tz_id, ep_id=ep_id, tenant=tenant) + if tz_type == self.TZ_TYPE_VLAN: + return nsx_constants.TRANSPORT_TYPE_VLAN + else: + return nsx_constants.TRANSPORT_TYPE_OVERLAY + + def get_host_switch_mode(self, tz_id, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + """This api is consistent with the nsx manager resource api""" + tz_type = self.get_tz_type(tz_id, ep_id=ep_id, tenant=tenant) + if tz_type == self.TZ_TYPE_ENS: + return nsx_constants.HOST_SWITCH_MODE_ENS + else: + return nsx_constants.HOST_SWITCH_MODE_STANDARD + + def list(self, ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + tz_def = policy_defs.TransportZoneDef(ep_id=ep_id, tenant=tenant) + return self._list(tz_def) + + def get_by_name(self, name, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + """Return first group matched by name""" + return super(NsxPolicyTransportZoneApi, self).get_by_name( + name, ep_id, tenant=tenant) + + def create_or_overwrite(self, name, tz_id=None, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + err_msg = (_("This action is not supported")) + raise exceptions.ManagerError(details=err_msg) + + def update(self, tz_id, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + err_msg = (_("This action is not supported")) + raise exceptions.ManagerError(details=err_msg) + + def delete(self, tz_id, + ep_id=policy_constants.DEFAULT_ENFORCEMENT_POINT, + tenant=policy_constants.POLICY_INFRA_TENANT): + err_msg = (_("This action is not supported")) + raise exceptions.ManagerError(details=err_msg) + + class NsxPolicyDeploymentMapApi(NsxPolicyResourceBase): """NSX Policy Deployment Map.""" @property