From ee376de40ca691c5307e1e6866bd22bcbf13e889 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Thu, 23 Nov 2017 01:34:32 -0800 Subject: [PATCH] Support NSX tag limitations The NSX has various tag limitations. For example the maximum length of the tags and the maximum amount of tags per resource. This may increase with NSX versions. This patch enables the library to learn from the NSX the tag limits. Change-Id: Ie2eac9c51a36496908140018d7ca1d15ed0e9d58 --- vmware_nsxlib/tests/unit/v3/test_utils.py | 13 ++++++++++ vmware_nsxlib/v3/__init__.py | 20 ++++++++++++++++ vmware_nsxlib/v3/utils.py | 29 +++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/vmware_nsxlib/tests/unit/v3/test_utils.py b/vmware_nsxlib/tests/unit/v3/test_utils.py index 3be2fce4..04a1f774 100644 --- a/vmware_nsxlib/tests/unit/v3/test_utils.py +++ b/vmware_nsxlib/tests/unit/v3/test_utils.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import mock + from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase from vmware_nsxlib.v3 import exceptions from vmware_nsxlib.v3 import nsx_constants @@ -250,6 +252,17 @@ class TestNsxV3Utils(nsxlib_testcase.NsxClientTestCase): self.assertRaises(exceptions.NsxLibInvalidInput, func_to_fail, 99) self.assertEqual(max_retries, total_count['val']) + @mock.patch.object(utils, '_update_max_tags') + @mock.patch.object(utils, '_update_tag_length') + @mock.patch.object(utils, '_update_resource_length') + def test_update_limits(self, _update_resource_length, + _update_tag_length, _update_max_tags): + limits = utils.TagLimits(1, 2, 3) + utils.update_tag_limits(limits) + _update_resource_length.assert_called_with(1) + _update_tag_length.assert_called_with(2) + _update_max_tags.assert_called_with(3) + class NsxFeaturesTestCase(nsxlib_testcase.NsxLibTestCase): diff --git a/vmware_nsxlib/v3/__init__.py b/vmware_nsxlib/v3/__init__.py index 4d9ef592..03d198b6 100644 --- a/vmware_nsxlib/v3/__init__.py +++ b/vmware_nsxlib/v3/__init__.py @@ -194,6 +194,23 @@ class NsxLibBase(object): reason = _('Missing key:%s in tags') % str(e) raise exceptions.NsxSearchInvalidQuery(reason=reason) + def get_tag_limits(self): + try: + result = self.client.url_get('spec/vmware/types/Tag') + scope_length = result['properties']['scope']['maxLength'] + tag_length = result['properties']['tag']['maxLength'] + except Exception as e: + LOG.error("Unable to read tag limits. Reason: %s", e) + scope_length = utils.MAX_RESOURCE_TYPE_LEN + tag_length = utils.MAX_TAG_LEN + try: + result = self.client.url_get('spec/vmware/types/ManagedResource') + max_tags = result['properties']['tags']['maxItems'] + except Exception as e: + LOG.error("Unable to read maximum tags. Reason: %s", e) + max_tags = utils.MAX_TAGS + return utils.TagLimits(scope_length, tag_length, max_tags) + class NsxLib(NsxLibBase): @@ -255,6 +272,9 @@ class NsxLib(NsxLibBase): self.client, self.nsxlib_config, nsxlib=self) self.vif = core_resources.NsxLibFabricVirtualInterface( self.client, self.nsxlib_config, nsxlib=self) + # Update tag limits + self.tag_limits = self.get_tag_limits() + utils.update_tag_limits(self.tag_limits) @property def keepalive_section(self): diff --git a/vmware_nsxlib/v3/utils.py b/vmware_nsxlib/v3/utils.py index cd98390a..ae144f77 100644 --- a/vmware_nsxlib/v3/utils.py +++ b/vmware_nsxlib/v3/utils.py @@ -14,6 +14,7 @@ # under the License. import abc +import collections import inspect import re import time @@ -27,8 +28,15 @@ from vmware_nsxlib.v3 import exceptions as nsxlib_exceptions LOG = log.getLogger(__name__) +TagLimits = collections.namedtuple('TagLimits', + ['scope_length', 'tag_length', 'max_tags']) + +# The tag limits may change in the NSX. We set the default values to be those +# in NSX 2.0. If the NSX returns different values we update these globals. MAX_RESOURCE_TYPE_LEN = 20 MAX_TAG_LEN = 40 +MAX_TAGS = 15 + DEFAULT_MAX_ATTEMPTS = 10 DEFAULT_CACHE_AGE_SEC = 600 INJECT_HEADERS_CALLBACK = None @@ -51,6 +59,27 @@ def set_inject_headers_callback(callback): INJECT_HEADERS_CALLBACK = callback +def _update_resource_length(length): + global MAX_RESOURCE_TYPE_LEN + MAX_RESOURCE_TYPE_LEN = length + + +def _update_tag_length(length): + global MAX_TAG_LEN + MAX_TAG_LEN = length + + +def _update_max_tags(max_tags): + global MAX_TAGS + MAX_TAGS = max_tags + + +def update_tag_limits(limits): + _update_resource_length(limits.scope_length) + _update_tag_length(limits.tag_length) + _update_max_tags(limits.max_tags) + + def _validate_resource_type_length(resource_type): # Add in a validation to ensure that we catch this at build time if len(resource_type) > MAX_RESOURCE_TYPE_LEN: