From 9e4f33500d21cee6faa266076ae0ee99d8e8b093 Mon Sep 17 00:00:00 2001 From: asarfaty Date: Tue, 14 Jan 2020 11:14:04 +0200 Subject: [PATCH] Support policy segment & port admin state Change-Id: I1254d4bccec44c1b7fa65c106a1261e00c57f2f2 --- .../tests/unit/v3/policy/test_resources.py | 70 +++++++++++++++++-- vmware_nsxlib/v3/nsx_constants.py | 1 + vmware_nsxlib/v3/policy/__init__.py | 3 +- vmware_nsxlib/v3/policy/core_defs.py | 56 ++++++++++++++- vmware_nsxlib/v3/policy/core_resources.py | 28 ++++++-- 5 files changed, 144 insertions(+), 14 deletions(-) diff --git a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py index c9f893dd..b931a52b 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py +++ b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py @@ -3613,7 +3613,8 @@ class TestPolicySegment(NsxPolicyLibTestCase): super(TestPolicySegment, self).setUp() self.resourceApi = self.policy_lib.segment - def _test_create(self, tier1_id=None, mdproxy=None, dhcp_server=None): + def _test_create(self, tier1_id=None, mdproxy=None, dhcp_server=None, + admin_state=None): name = 'test' description = 'desc' tier1_id = '111' @@ -3625,18 +3626,20 @@ class TestPolicySegment(NsxPolicyLibTestCase): if tier1_id: kwargs['tier1_id'] = tier1_id - if mdproxy: kwargs['metadata_proxy_id'] = mdproxy - if dhcp_server: kwargs['dhcp_server_config_id'] = dhcp_server + if admin_state: + kwargs['admin_state'] = admin_state with mock.patch.object(self.policy_api, "create_or_update") as api_call: result = self.resourceApi.create_or_overwrite( name, **kwargs) + if admin_state: + kwargs['admin_state'] = admin_state if 'UP' else 'DOWN' expected_def = core_defs.SegmentDef( nsx_version='3.0.0', segment_id=mock.ANY, @@ -3655,6 +3658,12 @@ class TestPolicySegment(NsxPolicyLibTestCase): def test_create_with_dhcp_server_config(self): self._test_create(dhcp_server='dhcp1') + def test_create_with_admin_state_up(self): + self._test_create(admin_state=True) + + def test_create_with_admin_state_down(self): + self._test_create(admin_state=False) + def test_delete(self): segment_id = '111' with mock.patch.object(self.policy_api, "delete") as api_call: @@ -3684,14 +3693,18 @@ class TestPolicySegment(NsxPolicyLibTestCase): def test_update(self): segment_id = '111' name = 'new name' + admin_state = False with self.mock_get(segment_id, name), \ self.mock_create_update() as update_call: self.resourceApi.update(segment_id, name=name, + admin_state=admin_state, tenant=TEST_TENANT) - expected_def = core_defs.SegmentDef(segment_id=segment_id, + expected_def = core_defs.SegmentDef(nsx_version='3.0.0', + segment_id=segment_id, name=name, + admin_state=admin_state, tenant=TEST_TENANT) self.assert_called_with_def(update_call, expected_def) @@ -4091,6 +4104,7 @@ class TestPolicySegmentPort(NsxPolicyLibTestCase): traffic_tag = 10 allocate_addresses = "BOTH" tags = [{'scope': 'a', 'tag': 'b'}] + admin_state = True with mock.patch.object(self.policy_api, "create_or_update") as api_call: @@ -4099,10 +4113,56 @@ class TestPolicySegmentPort(NsxPolicyLibTestCase): address_bindings=address_bindings, attachment_type=attachment_type, vif_id=vif_id, app_id=app_id, context_id=context_id, traffic_tag=traffic_tag, - allocate_addresses=allocate_addresses, tags=tags, + allocate_addresses=allocate_addresses, + admin_state=admin_state, tags=tags, tenant=TEST_TENANT) expected_def = core_defs.SegmentPortDef( + nsx_version='3.0.0', + segment_id=segment_id, + port_id=mock.ANY, + name=name, + description=description, + address_bindings=address_bindings, + attachment_type=attachment_type, + vif_id=vif_id, + app_id=app_id, + context_id=context_id, + traffic_tag=traffic_tag, + allocate_addresses=allocate_addresses, + admin_state=admin_state, + tags=tags, + tenant=TEST_TENANT) + + self.assert_called_with_def(api_call, expected_def) + self.assertIsNotNone(result) + + def test_create_with_unsupported_attribute(self): + name = 'test' + description = 'desc' + segment_id = "segment" + address_bindings = [] + attachment_type = "CHILD" + vif_id = "vif" + app_id = "app" + context_id = "context" + traffic_tag = 10 + allocate_addresses = "BOTH" + tags = [{'scope': 'a', 'tag': 'b'}] + admin_state = False + + with mock.patch.object( + self.policy_api, "create_or_update") as api_call, \ + mock.patch.object(self.resourceApi, 'version', '0.0.0'): + result = self.resourceApi.create_or_overwrite( + name, segment_id, description=description, + address_bindings=address_bindings, + attachment_type=attachment_type, vif_id=vif_id, app_id=app_id, + context_id=context_id, traffic_tag=traffic_tag, + allocate_addresses=allocate_addresses, tags=tags, + tenant=TEST_TENANT, admin_state=admin_state) + expected_def = core_defs.SegmentPortDef( + nsx_version=self.policy_lib.get_version(), segment_id=segment_id, port_id=mock.ANY, name=name, diff --git a/vmware_nsxlib/v3/nsx_constants.py b/vmware_nsxlib/v3/nsx_constants.py index 1810ab68..7a20eba1 100644 --- a/vmware_nsxlib/v3/nsx_constants.py +++ b/vmware_nsxlib/v3/nsx_constants.py @@ -177,6 +177,7 @@ FEATURE_NSX_POLICY_NETWORKING = 'NSX Policy Networking' FEATURE_NSX_POLICY_MDPROXY = 'NSX Policy Metadata Proxy' FEATURE_NSX_POLICY_DHCP = 'NSX Policy DHCP' FEATURE_NSX_POLICY_GLOBAL_CONFIG = 'NSX Policy Global Config' +FEATURE_NSX_POLICY_ADMIN_STATE = 'NSX Policy Segment admin state' # 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 a2081c12..b5bc4f04 100644 --- a/vmware_nsxlib/v3/policy/__init__.py +++ b/vmware_nsxlib/v3/policy/__init__.py @@ -37,7 +37,6 @@ class NsxPolicyLib(lib.NsxLibBase): def init_api(self): # Initialize the policy client - # TODO(annak): move the API class to separate file self.policy_api = core_defs.NsxPolicyApi(self.client) # NSX manager api will be used as a pass-through for apis which are @@ -178,6 +177,8 @@ class NsxPolicyLib(lib.NsxLibBase): return True if feature == nsx_constants.FEATURE_NSX_POLICY_GLOBAL_CONFIG: return True + if feature == nsx_constants.FEATURE_NSX_POLICY_ADMIN_STATE: + 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 a9d7214d..62c5bcab 100644 --- a/vmware_nsxlib/v3/policy/core_defs.py +++ b/vmware_nsxlib/v3/policy/core_defs.py @@ -824,9 +824,9 @@ class SegmentDef(BaseSegmentDef): 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 - if attr == 'dhcp_server_config_id': + if attr in ('metadata_proxy_id', + 'dhcp_server_config_id', + 'admin_state'): return True else: LOG.warning( @@ -889,6 +889,15 @@ class SegmentDef(BaseSegmentDef): body_attr='dhcp_config_path', value=path) + if (self.has_attr('admin_state') and + self._version_dependant_attr_supported('admin_state')): + if self.get_attr('admin_state'): + admin_state = nsx_constants.ADMIN_STATE_UP + else: + admin_state = nsx_constants.ADMIN_STATE_DOWN + self._set_attr_if_specified(body, 'admin_state', + value=admin_state) + return body @@ -939,6 +948,15 @@ class DhcpV6StaticBindingConfig(DhcpV4StaticBindingConfig): 'ip_addresses', 'sntp_servers', 'preferred_time']) + if (self.has_attr('admin_state') and + self._version_dependant_attr_supported('admin_state')): + if self.get_attr('admin_state'): + admin_state = nsx_constants.ADMIN_STATE_UP + else: + admin_state = nsx_constants.ADMIN_STATE_DOWN + self._set_attr_if_specified(body, 'admin_state', + value=admin_state) + return body @@ -1003,8 +1021,40 @@ class SegmentPortDef(ResourceDef): 'allocate_addresses']) body['attachment'] = attachment + if (self.has_attr('admin_state') and + self._version_dependant_attr_supported('admin_state')): + if self.get_attr('admin_state'): + admin_state = nsx_constants.ADMIN_STATE_UP + else: + admin_state = nsx_constants.ADMIN_STATE_DOWN + self._set_attr_if_specified(body, 'admin_state', + value=admin_state) + return body + def _version_dependant_attr_supported(self, attr): + if (version.LooseVersion(self.nsx_version) >= + version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): + if attr == 'admin_state': + return True + + 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 + + +class SegmentBindingMapDefBase(ResourceDef): + + @property + def path_ids(self): + return ('tenant', 'segment_id', 'map_id') + + def path_defs(self): + return (TenantDef, SegmentDef) + class SegmentPortBindingMapDefBase(ResourceDef): diff --git a/vmware_nsxlib/v3/policy/core_resources.py b/vmware_nsxlib/v3/policy/core_resources.py index 12f521ae..40d5685b 100644 --- a/vmware_nsxlib/v3/policy/core_resources.py +++ b/vmware_nsxlib/v3/policy/core_resources.py @@ -15,6 +15,7 @@ # import abc +from distutils import version import sys import decorator @@ -1812,6 +1813,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): transport_zone_id=IGNORE, metadata_proxy_id=IGNORE, dhcp_server_config_id=IGNORE, + admin_state=IGNORE, tags=IGNORE, tenant=constants.POLICY_INFRA_TENANT): @@ -1834,6 +1836,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): transport_zone_id=transport_zone_id, metadata_proxy_id=metadata_proxy_id, dhcp_server_config_id=dhcp_server_config_id, + admin_state=admin_state, tags=tags, tenant=tenant) self._create_or_store(segment_def) @@ -1864,9 +1867,9 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): def update(self, segment_id, name=IGNORE, description=IGNORE, tier1_id=IGNORE, subnets=IGNORE, dns_domain_name=IGNORE, - vlan_ids=IGNORE, tags=IGNORE, metadata_proxy_id=IGNORE, - dhcp_server_config_id=IGNORE, - tenant=constants.POLICY_INFRA_TENANT): + vlan_ids=IGNORE, metadata_proxy_id=IGNORE, + dhcp_server_config_id=IGNORE, admin_state=IGNORE, + tags=IGNORE, tenant=constants.POLICY_INFRA_TENANT): if (metadata_proxy_id != IGNORE and not self.nsxpolicy.feature_supported( @@ -1883,6 +1886,7 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): vlan_ids=vlan_ids, metadata_proxy_id=metadata_proxy_id, dhcp_server_config_id=dhcp_server_config_id, + admin_state=admin_state, tags=tags, tenant=tenant) @@ -1953,7 +1957,12 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): @check_allowed_passthrough def set_admin_state(self, segment_id, admin_state, tenant=constants.POLICY_INFRA_TENANT): - """Set the segment admin state using the passthrough api""" + """Set the segment admin state using the passthrough/policy api""" + if (version.LooseVersion(self.version) >= + version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): + return self.update(segment_id, admin_state=admin_state, + tenant=tenant) + realization_info = self.wait_until_realized( segment_id, entity_type='RealizedLogicalSwitch', tenant=tenant) @@ -1994,6 +2003,7 @@ class NsxPolicySegmentPortApi(NsxPolicyResourceBase): context_id=IGNORE, traffic_tag=IGNORE, allocate_addresses=IGNORE, + admin_state=IGNORE, tags=IGNORE, tenant=constants.POLICY_INFRA_TENANT): @@ -2009,6 +2019,7 @@ class NsxPolicySegmentPortApi(NsxPolicyResourceBase): context_id=context_id, traffic_tag=traffic_tag, allocate_addresses=allocate_addresses, + admin_state=admin_state, tags=tags, tenant=tenant) self._create_or_store(port_def) @@ -2037,6 +2048,7 @@ class NsxPolicySegmentPortApi(NsxPolicyResourceBase): name=IGNORE, description=IGNORE, address_bindings=IGNORE, + admin_state=IGNORE, tags=IGNORE, tenant=constants.POLICY_INFRA_TENANT): @@ -2045,6 +2057,7 @@ class NsxPolicySegmentPortApi(NsxPolicyResourceBase): name=name, description=description, address_bindings=address_bindings, + admin_state=admin_state, tags=tags, tenant=tenant) @@ -2119,7 +2132,12 @@ class NsxPolicySegmentPortApi(NsxPolicyResourceBase): @check_allowed_passthrough def set_admin_state(self, segment_id, port_id, admin_state, tenant=constants.POLICY_INFRA_TENANT): - """Set the segment port admin state using the passthrough api""" + """Set the segment port admin state using the passthrough/policy api""" + if (version.LooseVersion(self.version) >= + version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): + return self.update(segment_id, port_id, admin_state=admin_state, + tenant=tenant) + realization_info = self.wait_until_realized( segment_id, port_id, entity_type='RealizedLogicalPort', tenant=tenant)