diff --git a/vmware_nsxlib/tests/unit/v3/policy/policy_testcase.py b/vmware_nsxlib/tests/unit/v3/policy/policy_testcase.py index 73b05e88..b9606edf 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/policy_testcase.py +++ b/vmware_nsxlib/tests/unit/v3/policy/policy_testcase.py @@ -29,7 +29,7 @@ class TestPolicyApi(nsxlib_testcase.NsxClientTestCase): super(TestPolicyApi, self).setUp() - def assert_json_call(self, method, client, url, data=None): + def assert_json_call(self, method, client, url, data=None, headers=None): url = BASE_POLICY_URI + url return super(TestPolicyApi, self).assert_json_call( - method, client, url, data=data) + method, client, url, data=data, headers=headers) diff --git a/vmware_nsxlib/tests/unit/v3/policy/test_lb_resources.py b/vmware_nsxlib/tests/unit/v3/policy/test_lb_resources.py index 80c46044..8b489be3 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/test_lb_resources.py +++ b/vmware_nsxlib/tests/unit/v3/policy/test_lb_resources.py @@ -913,7 +913,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): expected_def = lb_defs.LBVirtualServerDef( virtual_server_id=vs_obj_id, - name=vs_name, rules=[lb_rule]) self.assert_called_with_def(update_call, expected_def) @@ -941,7 +940,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): expected_def = lb_defs.LBVirtualServerDef( virtual_server_id=vs_obj_id, - name=vs_name, rules=[lb_rule, {'display_name': 'xx'}, {'display_name': 'yy'}]) @@ -969,7 +967,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): expected_def = lb_defs.LBVirtualServerDef( virtual_server_id=vs_obj_id, - name=vs_name, rules=[{'display_name': 'xx'}, {'display_name': 'yy'}, lb_rule]) @@ -998,7 +995,7 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): rule_match_strategy, rule_phase) expected_def = lb_defs.LBVirtualServerDef( - virtual_server_id=vs_obj_id, name=vs_name, + virtual_server_id=vs_obj_id, rules=[{'display_name': 'xx'}, {'display_name': 'yy'}, lb_rule]) @@ -1026,7 +1023,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): rule_match_strategy, rule_phase) expected_def = lb_defs.LBVirtualServerDef( - name=vs_name, virtual_server_id=vs_obj_id, rules=[{'display_name': 'xx'}, lb_rule, @@ -1044,7 +1040,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): self.resourceApi.update_lb_rule(vs_obj_id, 'xx', actions='22') expected_def = lb_defs.LBVirtualServerDef( - name=vs_name, virtual_server_id=vs_obj_id, rules=[{'display_name': 'xx', 'actions': '22'}, {'display_name': 'yy'}]) @@ -1063,7 +1058,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): expected_def = lb_defs.LBVirtualServerDef( virtual_server_id=vs_obj_id, - name=vs_name, rules=[{'display_name': 'yy'}, {'display_name': 'xx', 'actions': '22'}]) self.assert_called_with_def(update_call, expected_def) @@ -1079,7 +1073,6 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase): expected_def = lb_defs.LBVirtualServerDef( virtual_server_id=vs_obj_id, - name=vs_name, rules=[{'display_name': 'yy'}]) self.assert_called_with_def(update_call, expected_def) diff --git a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py index 44d4a92d..5e334f52 100644 --- a/vmware_nsxlib/tests/unit/v3/policy/test_resources.py +++ b/vmware_nsxlib/tests/unit/v3/policy/test_resources.py @@ -18,6 +18,7 @@ import mock from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase from vmware_nsxlib.tests.unit.v3.policy import policy_testcase +from vmware_nsxlib.tests.unit.v3 import test_client from vmware_nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsxlib.v3 import nsx_constants from vmware_nsxlib.v3 import policy @@ -39,7 +40,7 @@ class NsxPolicyLibTestCase(policy_testcase.TestPolicyApi): # Mock the nsx-lib for the passthrough api # TODO(annak): move version forward with backend releases with mock.patch("vmware_nsxlib.v3.NsxLib") as mock_lib: - mock_lib.return_value.get_version.return_value = "2.5.0" + mock_lib.return_value.get_version.return_value = "3.0.0" self.policy_lib = policy.NsxPolicyLib(nsxlib_config) self.policy_api = self.policy_lib.policy_api @@ -216,7 +217,8 @@ class TestPolicyDomain(NsxPolicyLibTestCase): self.assert_json_call('PATCH', self.client, '%s/domains/%s' % (TEST_TENANT, domain_id), - data=expected_body) + data=expected_body, + headers=test_client.PARTIAL_UPDATE_HEADERS) class TestPolicyGroup(NsxPolicyLibTestCase): @@ -595,7 +597,8 @@ class TestPolicyGroup(NsxPolicyLibTestCase): '%s/domains/%s/groups/%s' % (TEST_TENANT, domain_id, group_id), - data=expected_body) + data=expected_body, + headers=test_client.PARTIAL_UPDATE_HEADERS) def test_get_realized(self): domain_id = 'd1' @@ -2407,6 +2410,7 @@ class TestPolicyTier1(NsxPolicyLibTestCase): def setUp(self, *args, **kwargs): super(TestPolicyTier1, self).setUp(*args, **kwargs) self.resourceApi = self.policy_lib.tier1 + self.partial_updates = True def test_create(self): name = 'test' @@ -2575,9 +2579,10 @@ class TestPolicyTier1(NsxPolicyLibTestCase): expected_def = core_defs.Tier1Def( tier1_id=obj_id, - name=rtr_name, route_advertisement=new_adv, tenant=TEST_TENANT) + if not self.partial_updates: + expected_def.attrs['name'] = rtr_name self.assert_called_with_def( update_call, expected_def) @@ -2607,10 +2612,11 @@ class TestPolicyTier1(NsxPolicyLibTestCase): expected_def = core_defs.Tier1Def( tier1_id=obj_id, - name=rtr_name, route_advertisement=new_adv, tier0=tier0, tenant=TEST_TENANT) + if not self.partial_updates: + expected_def.attrs['name'] = rtr_name self.assert_called_with_def( update_call, expected_def) @@ -3000,6 +3006,8 @@ class TestPolicyTier1NoPassthrough(TestPolicyTier1): def setUp(self, *args, **kwargs): super(TestPolicyTier1NoPassthrough, self).setUp( allow_passthrough=False) + # No passthrough also means no partial updates + self.partial_updates = False def test_update_transport_zone(self): # Will not work without passthrough api diff --git a/vmware_nsxlib/tests/unit/v3/test_client.py b/vmware_nsxlib/tests/unit/v3/test_client.py index 02e71329..1d14578b 100644 --- a/vmware_nsxlib/tests/unit/v3/test_client.py +++ b/vmware_nsxlib/tests/unit/v3/test_client.py @@ -39,6 +39,13 @@ JSON_DFT_ACCEPT_HEADERS = { 'Cookie': 'JSESSIONID=%s;' % nsxlib_testcase.JSESSIONID } +PARTIAL_UPDATE_HEADERS = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Cookie': 'JSESSIONID=%s;' % nsxlib_testcase.JSESSIONID, + 'nsx-enable-partial-patch': 'true' +} + def _headers(**kwargs): headers = copy.copy(DFT_ACCEPT_HEADERS) diff --git a/vmware_nsxlib/v3/policy/__init__.py b/vmware_nsxlib/v3/policy/__init__.py index 2e06143c..4e352ffa 100644 --- a/vmware_nsxlib/v3/policy/__init__.py +++ b/vmware_nsxlib/v3/policy/__init__.py @@ -161,11 +161,10 @@ class NsxPolicyLib(lib.NsxLibBase): if (feature == nsx_constants.FEATURE_ENS_WITH_QOS): return True - # TODO(asarfaty): Uncomment this once partial updates are supported - # if (version.LooseVersion(self.get_version()) >= - # version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): - # if feature == nsx_constants.FEATURE_PARTIAL_UPDATES: - # return True + if (version.LooseVersion(self.get_version()) >= + version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)): + if feature == nsx_constants.FEATURE_PARTIAL_UPDATES: + 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 953b3272..f4930f49 100644 --- a/vmware_nsxlib/v3/policy/core_defs.py +++ b/vmware_nsxlib/v3/policy/core_defs.py @@ -1852,7 +1852,7 @@ class NsxPolicyApi(object): def partial_updates_supported(self): return self.partial_updates - def create_or_update(self, resource_def): + def create_or_update(self, resource_def, partial_updates=False): """Create or update a policy object. This api will update an existing object, or create a new one if it @@ -1864,7 +1864,10 @@ class NsxPolicyApi(object): self.cache.remove(path) body = resource_def.get_obj_dict() - self.client.patch(path, body) + headers = None + if partial_updates: + headers = {'nsx-enable-partial-patch': 'true'} + self.client.patch(path, body, headers=headers) def create_with_parent(self, parent_def, resource_def): path = parent_def.get_resource_path() diff --git a/vmware_nsxlib/v3/policy/core_resources.py b/vmware_nsxlib/v3/policy/core_resources.py index 1e9fd22b..204edabb 100644 --- a/vmware_nsxlib/v3/policy/core_resources.py +++ b/vmware_nsxlib/v3/policy/core_resources.py @@ -147,14 +147,16 @@ class NsxPolicyResourceBase(object): if self.policy_api.partial_updates_supported(): policy_def = self._init_def(**kwargs) + partial_updates = True else: policy_def = self._get_and_update_def(**kwargs) + partial_updates = False if policy_def.bodyless(): # Nothing to update - only keys provided in kwargs return - - self.policy_api.create_or_update(policy_def) + self.policy_api.create_or_update( + policy_def, partial_updates=partial_updates) @staticmethod def _init_obj_uuid(obj_uuid): @@ -969,8 +971,7 @@ class NsxPolicyTier1Api(NsxPolicyResourceBase): self.update(tier1_id, route_advertisement=route_adv, tier0=tier0, - tenant=tenant, - current_body=tier1_dict) + tenant=tenant) def add_advertisement_rule( self, tier1_id, name, action=None, prefix_operator=None,