diff --git a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py index 0e992375..cc4e6cee 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py +++ b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py @@ -2466,6 +2466,41 @@ class TestPolicyEdgeCluster(NsxPolicyLibTestCase): self.assertEqual([node_id], result) +class TestPolicyMetadataProxy(NsxPolicyLibTestCase): + + def setUp(self, *args, **kwargs): + super(TestPolicyMetadataProxy, self).setUp() + self.resourceApi = self.policy_lib.md_proxy + + def test_get(self): + obj_id = '111' + with mock.patch.object(self.policy_api, "get", + return_value={'id': obj_id}) as api_call: + result = self.resourceApi.get(obj_id, tenant=TEST_TENANT) + expected_def = core_defs.MetadataProxyDef(mdproxy_id=obj_id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + self.assertEqual(obj_id, result['id']) + + 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 = core_defs.MetadataProxyDef(tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + def test_list(self): + with mock.patch.object(self.policy_api, "list", + return_value={'results': []}) as api_call: + result = self.resourceApi.list(tenant=TEST_TENANT) + expected_def = core_defs.MetadataProxyDef(tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + self.assertEqual([], result) + + class TestPolicyTier1(NsxPolicyLibTestCase): def setUp(self, *args, **kwargs): @@ -3573,7 +3608,7 @@ class TestPolicySegment(NsxPolicyLibTestCase): super(TestPolicySegment, self).setUp() self.resourceApi = self.policy_lib.segment - def _test_create(self, tier1_id=None, tier0_id=None): + def _test_create(self, tier1_id=None, tier0_id=None, mdproxy=None): name = 'test' description = 'desc' subnets = [core_defs.Subnet(gateway_address="2.2.2.0/24")] @@ -3587,11 +3622,15 @@ class TestPolicySegment(NsxPolicyLibTestCase): if tier0_id: kwargs['tier0_id'] = tier0_id + if mdproxy: + kwargs['metadata_proxy_id'] = mdproxy + with mock.patch.object(self.policy_api, "create_or_update") as api_call: result = self.resourceApi.create_or_overwrite(name, **kwargs) expected_def = core_defs.SegmentDef( + nsx_version='3.0.0', segment_id=mock.ANY, name=name, **kwargs) @@ -3610,6 +3649,9 @@ class TestPolicySegment(NsxPolicyLibTestCase): self.resourceApi.create_or_overwrite, 'seg-name', tier1_id='111', tier0_id='000') + def test_create_with_mdproxy(self): + self._test_create(mdproxy='md1') + def test_delete(self): segment_id = '111' with mock.patch.object(self.policy_api, "delete") as api_call: diff --git a/vmware_nsxlib/v3/nsx_constants.py b/vmware_nsxlib/v3/nsx_constants.py index 51ebda91..29b97465 100644 --- a/vmware_nsxlib/v3/nsx_constants.py +++ b/vmware_nsxlib/v3/nsx_constants.py @@ -176,6 +176,7 @@ FEATURE_SWITCH_HYPERBUS_MODE = 'Switch hyperbus mode with policy API' # Features available depending on the Policy Manager backend version FEATURE_NSX_POLICY = 'NSX Policy' FEATURE_NSX_POLICY_NETWORKING = 'NSX Policy Networking' +FEATURE_NSX_POLICY_MDPROXY = 'NSX Policy Metadata Proxy' # FEATURE available depending on Inventory service backend version FEATURE_CONTAINER_CLUSTER_INVENTORY = 'Container Cluster Inventory' diff --git a/vmware_nsxlib/v3/policy/__init__.py b/vmware_nsxlib/v3/policy/__init__.py index df81668b..c86e5725 100644 --- a/vmware_nsxlib/v3/policy/__init__.py +++ b/vmware_nsxlib/v3/policy/__init__.py @@ -118,6 +118,7 @@ class NsxPolicyLib(lib.NsxLibBase): self.ipv6_ndra_profile = ( core_resources.NsxIpv6NdraProfileApi(*args)) self.dhcp_relay_config = core_resources.NsxDhcpRelayConfigApi(*args) + self.md_proxy = core_resources.NsxPolicyMetadataProxyApi(*args) self.certificate = core_resources.NsxPolicyCertApi(*args) self.exclude_list = core_resources.NsxPolicyExcludeListApi(*args) self.load_balancer = lb_resources.NsxPolicyLoadBalancerApi(*args) @@ -174,6 +175,8 @@ class NsxPolicyLib(lib.NsxLibBase): return True if feature == nsx_constants.FEATURE_SWITCH_HYPERBUS_MODE: return True + if feature == nsx_constants.FEATURE_NSX_POLICY_MDPROXY: + return True return (feature == nsx_constants.FEATURE_NSX_POLICY) diff --git a/vmware_nsxlib/v3/policy/core_defs.py b/vmware_nsxlib/v3/policy/core_defs.py index ac652662..ed6dfb25 100644 --- a/vmware_nsxlib/v3/policy/core_defs.py +++ b/vmware_nsxlib/v3/policy/core_defs.py @@ -15,16 +15,16 @@ # import abc - from distutils import version from oslo_log import log as logging import six from vmware_nsxlib.v3 import nsx_constants +from vmware_nsxlib.v3.policy import constants from vmware_nsxlib.v3 import utils -from vmware_nsxlib.v3.policy import constants +LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__) @@ -61,6 +61,7 @@ EXCLUDE_LIST_PATH_PATTERN = (TENANTS_PATH_PATTERN + REALIZATION_PATH = "infra/realized-state/realized-entities?intent_path=%s" DHCP_REALY_PATTERN = TENANTS_PATH_PATTERN + "dhcp-relay-configs/" +MDPROXY_PATTERN = TENANTS_PATH_PATTERN + "metadata-proxies/" TIER0_LOCALE_SERVICES_PATH_PATTERN = (TIER0S_PATH_PATTERN + "%s/locale-services/") @@ -754,6 +755,21 @@ class SegmentDef(BaseSegmentDef): def path_defs(self): return (TenantDef,) + def _version_dependant_attr_supported(self, attr): + if (version.LooseVersion(self.nsx_version) >= + version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): + if attr == 'metadata_proxy_id': + return True + else: + LOG.warning( + "Ignoring %s for %s %s: this feature is not supported." + "Current NSX version: %s. Minimum supported version: %s", + attr, self.resource_type, self.attrs.get('name', ''), + self.nsx_version, nsx_constants.NSX_VERSION_3_0_0) + return False + + return False + def get_obj_dict(self): body = super(SegmentDef, self).get_obj_dict() if self.has_attr('tier1_id'): @@ -788,6 +804,18 @@ class SegmentDef(BaseSegmentDef): body_attr='transport_zone_path', value=path) + if (self.has_attr('metadata_proxy_id') and + self._version_dependant_attr_supported('metadata_proxy_id')): + paths = "" + if self.get_attr('metadata_proxy_id'): + mdproxy = MetadataProxyDef( + mdproxy_id=self.get_attr('metadata_proxy_id'), + tenant=self.get_tenant()) + paths = [mdproxy.get_resource_full_path()] + self._set_attr_if_specified(body, 'metadata_proxy_id', + body_attr='metadata_proxy_paths', + value=paths) + return body @@ -854,14 +882,12 @@ class SegmentPortDef(ResourceDef): version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): if attr == 'hyperbus_mode': return True - else: - LOG.warning( - "Ignoring %s for %s %s: this feature is not supported." - "Current NSX version: %s. Minimum supported version: %s", - attr, self.resource_type, self.attrs.get('name', ''), - self.nsx_version, nsx_constants.NSX_VERSION_3_0_0) - return False + LOG.warning( + "Ignoring %s for %s %s: this feature is not supported." + "Current NSX version: %s. Minimum supported version: %s", + attr, self.resource_type, self.attrs.get('name', ''), + self.nsx_version, nsx_constants.NSX_VERSION_3_0_0) return False @@ -1857,6 +1883,31 @@ class WAFProfileDef(ResourceDef): return body +class MetadataProxyDef(ResourceDef): + + @property + def path_pattern(self): + return MDPROXY_PATTERN + + @property + def path_ids(self): + return ('tenant', 'mdproxy_id') + + @staticmethod + def resource_type(): + return 'MetadataProxyConfig' + + def path_defs(self): + return (TenantDef,) + + def get_obj_dict(self): + body = super(MetadataProxyDef, self).get_obj_dict() + self._set_attrs_if_specified(body, ['edge_cluster_path', + 'enable_standby_relocation', + 'secret', 'server_address']) + return body + + class CertificateDef(ResourceDef): @property diff --git a/vmware_nsxlib/v3/policy/core_resources.py b/vmware_nsxlib/v3/policy/core_resources.py index a94175c7..02009ff0 100644 --- a/vmware_nsxlib/v3/policy/core_resources.py +++ b/vmware_nsxlib/v3/policy/core_resources.py @@ -1833,6 +1833,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): vlan_ids=IGNORE, transport_zone_id=IGNORE, ip_pool_id=IGNORE, + metadata_proxy_id=IGNORE, tags=IGNORE, tenant=constants.POLICY_INFRA_TENANT): @@ -1852,6 +1853,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): vlan_ids=vlan_ids, transport_zone_id=transport_zone_id, ip_pool_id=ip_pool_id, + metadata_proxy_id=metadata_proxy_id, tags=tags, tenant=tenant) self._create_or_store(segment_def) @@ -1882,8 +1884,9 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): def update(self, segment_id, name=IGNORE, description=IGNORE, tier1_id=IGNORE, tier0_id=IGNORE, subnets=IGNORE, dns_domain_name=IGNORE, - vlan_ids=IGNORE, tags=IGNORE, + vlan_ids=IGNORE, tags=IGNORE, metadata_proxy_id=IGNORE, tenant=constants.POLICY_INFRA_TENANT): + self._update(segment_id=segment_id, name=name, description=description, @@ -1892,6 +1895,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): subnets=subnets, dns_domain_name=dns_domain_name, vlan_ids=vlan_ids, + metadata_proxy_id=metadata_proxy_id, tags=tags, tenant=tenant) @@ -3529,6 +3533,49 @@ class NsxPolicyEdgeClusterApi(NsxPolicyResourceBase): return [node['id'] for node in nodes] +class NsxPolicyMetadataProxyApi(NsxPolicyResourceBase): + # Currently this is used as a ready only Api + @property + def entry_def(self): + return core_defs.MetadataProxyDef + + def get(self, mdproxy_id, + tenant=constants.POLICY_INFRA_TENANT, silent=False): + md_def = core_defs.MetadataProxyDef( + mdproxy_id=mdproxy_id, tenant=tenant) + return self.policy_api.get(md_def, silent=silent) + + def list(self, tenant=constants.POLICY_INFRA_TENANT): + md_def = core_defs.MetadataProxyDef(tenant=tenant) + return self._list(md_def) + + def get_by_name(self, name, + tenant=constants.POLICY_INFRA_TENANT): + return super(NsxPolicyMetadataProxyApi, self).get_by_name( + name, tenant=tenant) + + def create_or_overwrite(self, name, mdproxy_id=None, + tenant=constants.POLICY_INFRA_TENANT): + err_msg = (_("This action is not supported")) + raise exceptions.ManagerError(details=err_msg) + + def update(self, mdproxy_id, + tenant=constants.POLICY_INFRA_TENANT): + err_msg = (_("This action is not supported")) + raise exceptions.ManagerError(details=err_msg) + + def delete(self, mdproxy_id, + tenant=constants.POLICY_INFRA_TENANT): + err_msg = (_("This action is not supported")) + raise exceptions.ManagerError(details=err_msg) + + def get_path(self, mdproxy_id, + tenant=constants.POLICY_INFRA_TENANT): + md_def = core_defs.MetadataProxyDef( + mdproxy_id=mdproxy_id, tenant=tenant) + return md_def.get_resource_full_path() + + class NsxPolicyDeploymentMapApi(NsxPolicyResourceBase): """NSX Policy Deployment Map.""" @property