From f5bafe0ff4f69e4f6f39426cd2b69750aa6c9ce1 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Wed, 19 Dec 2018 09:59:02 +0200 Subject: [PATCH] Add support for removing subnets from a policy segment Removing the subnets of a segment should be done via PUT and not PATCH as the NSX backend does nto support it. Change-Id: Ib0ab3baacc65437aa1d822a133bdec2ebf566bd5 --- .../tests/unit/v3/test_policy_resources.py | 78 +++++++++++++++++++ vmware_nsxlib/v3/policy_defs.py | 11 ++- vmware_nsxlib/v3/policy_resources.py | 17 ++++ 3 files changed, 103 insertions(+), 3 deletions(-) diff --git a/vmware_nsxlib/tests/unit/v3/test_policy_resources.py b/vmware_nsxlib/tests/unit/v3/test_policy_resources.py index b41ead84..60f2d098 100644 --- a/vmware_nsxlib/tests/unit/v3/test_policy_resources.py +++ b/vmware_nsxlib/tests/unit/v3/test_policy_resources.py @@ -2130,6 +2130,84 @@ class TestPolicyTier0(NsxPolicyLibTestCase): tier1_id, tenant=TEST_TENANT) +class TestPolicySegment(NsxPolicyLibTestCase): + + def setUp(self, *args, **kwargs): + super(TestPolicySegment, self).setUp() + self.resourceApi = self.policy_lib.segment + + def test_create(self): + name = 'test' + description = 'desc' + tier1_id = '111' + subnets = [policy_defs.Subnet(gateway_address="2.2.2.0/24")] + + with mock.patch.object(self.policy_api, + "create_or_update") as api_call: + self.resourceApi.create_or_overwrite( + name, description=description, + tier1_id=tier1_id, + subnets=subnets, + tenant=TEST_TENANT) + + expected_def = policy_defs.SegmentDef( + segment_id=mock.ANY, + name=name, + description=description, + tier1_id=tier1_id, + subnets=subnets, + tenant=TEST_TENANT) + + self.assert_called_with_def(api_call, expected_def) + + def test_delete(self): + segment_id = '111' + with mock.patch.object(self.policy_api, "delete") as api_call: + self.resourceApi.delete(segment_id, tenant=TEST_TENANT) + expected_def = policy_defs.SegmentDef(segment_id=segment_id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + def test_get(self): + segment_id = '111' + with mock.patch.object(self.policy_api, "get") as api_call: + self.resourceApi.get(segment_id, tenant=TEST_TENANT) + expected_def = policy_defs.SegmentDef(segment_id=segment_id, + tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + 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.SegmentDef(tenant=TEST_TENANT) + self.assert_called_with_def(api_call, expected_def) + + def test_update(self): + segment_id = '111' + name = 'new name' + with mock.patch.object(self.policy_api, + "create_or_update") as update_call: + self.resourceApi.update(segment_id, + name=name, + tenant=TEST_TENANT) + expected_def = policy_defs.SegmentDef(segment_id=segment_id, + name=name, + tenant=TEST_TENANT) + self.assert_called_with_def(update_call, expected_def) + + def test_remove_connectivity_and_subnets(self): + segment_id = '111' + with mock.patch.object(self.policy_api, "get", + return_value={'id': segment_id}) as api_get,\ + mock.patch.object(self.policy_api.client, "update") as api_put: + self.resourceApi.remove_connectivity_and_subnets( + segment_id, tenant=TEST_TENANT) + api_get.assert_called_once() + api_put.assert_called_once_with( + '%s/segments/%s' % (TEST_TENANT, segment_id), + {'id': segment_id, 'connectivity_path': None, 'subnets': None}) + + class TestPolicySegmentProfileBase(NsxPolicyLibTestCase): def setUp(self, resource_api_name='segment_security_profile', diff --git a/vmware_nsxlib/v3/policy_defs.py b/vmware_nsxlib/v3/policy_defs.py index 7e365b69..c92aa052 100644 --- a/vmware_nsxlib/v3/policy_defs.py +++ b/vmware_nsxlib/v3/policy_defs.py @@ -498,8 +498,13 @@ class BaseSegmentDef(ResourceDef): def get_obj_dict(self): body = super(BaseSegmentDef, self).get_obj_dict() if self.has_attr('subnets'): - body['subnets'] = [subnet.get_obj_dict() - for subnet in self.get_attr('subnets')] + # Note(asarfaty): removing subnets through PATCH api is not + # supported + if self.get_attr('subnets'): + subnets = [subnet.get_obj_dict() + for subnet in self.get_attr('subnets')] + self._set_attr_if_specified(body, 'subnets', + value=subnets) self._set_attrs_if_specified(body, ['domain_name', 'vlan_ids']) return body @@ -543,7 +548,7 @@ class SegmentDef(BaseSegmentDef): def get_obj_dict(self): body = super(SegmentDef, self).get_obj_dict() if self.has_attr('tier1_id'): - path = None + path = "" if self.get_attr('tier1_id'): tier1 = Tier1Def(tier1_id=self.get_attr('tier1_id'), tenant=self.get_tenant()) diff --git a/vmware_nsxlib/v3/policy_resources.py b/vmware_nsxlib/v3/policy_resources.py index 965775c9..5ea7891c 100644 --- a/vmware_nsxlib/v3/policy_resources.py +++ b/vmware_nsxlib/v3/policy_resources.py @@ -1193,6 +1193,23 @@ class NsxPolicySegmentApi(NsxPolicyResourceBase): tags=tags, tenant=tenant) + def remove_connectivity_and_subnets( + self, segment_id, + tenant=policy_constants.POLICY_INFRA_TENANT): + """Disconnect a segment from a router and remove its subnets. + + PATCH does not support this action so PUT is used for this + """ + # Get the current segment and update it + segment = self.get(segment_id) + segment['subnets'] = None + segment['connectivity_path'] = None + + segment_def = self.entry_def(segment_id=segment_id, tenant=tenant) + path = segment_def.get_resource_path() + + self.policy_api.client.update(path, segment) + def get_realized_state(self, segment_id, entity_type=None, tenant=policy_constants.POLICY_INFRA_TENANT, realization_info=None):