Merge "Add support for relax_scale_validation in LbService"

This commit is contained in:
Zuul 2019-09-11 20:38:15 +00:00 committed by Gerrit Code Review
commit 6b6e881201
11 changed files with 164 additions and 26 deletions

View File

@ -628,6 +628,7 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
obj_id = '111'
size = 'SMALL'
connectivity_path = 'path'
relax_scale_validation = True
with self.mock_create_update() as api_call:
result = self.resourceApi.create_or_overwrite(
name,
@ -635,14 +636,17 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
description=description,
size=size,
connectivity_path=connectivity_path,
relax_scale_validation=relax_scale_validation,
tenant=TEST_TENANT)
expected_def = (
lb_defs.LBServiceDef(
nsx_version=self.policy_lib.get_version(),
lb_service_id=obj_id,
name=name,
description=description,
size=size,
connectivity_path=connectivity_path,
relax_scale_validation=relax_scale_validation,
tenant=TEST_TENANT))
self.assert_called_with_def(api_call, expected_def)
self.assertEqual(obj_id, result)
@ -662,6 +666,25 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
self.assert_called_with_def(api_call, expected_def)
self.assertIsNotNone(result)
def test_create_with_unsupported_attribute(self):
name = 'd1'
description = 'desc'
relax_scale_validation = True
with self.mock_create_update() as api_call, \
mock.patch.object(self.resourceApi, 'version', '0.0.0'):
result = self.resourceApi.create_or_overwrite(
name, description=description,
relax_scale_validation=relax_scale_validation,
tenant=TEST_TENANT)
expected_def = (
lb_defs.LBServiceDef(lb_service_id=mock.ANY,
name=name,
description=description,
tenant=TEST_TENANT))
self.assert_called_with_def(api_call, expected_def)
self.assertIsNotNone(result)
def test_delete(self):
obj_id = '111'
with mock.patch.object(self.policy_api, "delete") as api_call:
@ -708,21 +731,26 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
description = 'new desc'
size = 'SMALL'
connectivity_path = 'path'
relax_scale_validation = True
with self.mock_get(obj_id, name), \
self.mock_create_update() as update_call:
self.resourceApi.update(obj_id,
name=name,
description=description,
tenant=TEST_TENANT,
size=size,
connectivity_path=connectivity_path)
self.resourceApi.update(
obj_id,
name=name,
description=description,
tenant=TEST_TENANT,
size=size,
connectivity_path=connectivity_path,
relax_scale_validation=relax_scale_validation)
expected_def = lb_defs.LBServiceDef(
nsx_version=self.policy_lib.get_version(),
lb_service_id=obj_id,
name=name,
description=description,
tenant=TEST_TENANT,
size=size,
connectivity_path=connectivity_path)
connectivity_path=connectivity_path,
relax_scale_validation=relax_scale_validation)
self.assert_called_with_def(update_call, expected_def)
def test_get_status(self):

View File

@ -348,7 +348,8 @@ FAKE_SERVICE = {
"attachment": {
"target_id": FAKE_ROUTER_UUID,
"target_type": "LogicalRouter"
}
},
"relax_scale_validation": False
}
FAKE_TZ_UUID = uuidutils.generate_uuid()

View File

@ -498,13 +498,17 @@ class TestService(nsxlib_testcase.NsxClientTestCase):
'description': fake_service['description'],
'enabled': fake_service['enabled'],
'attachment': fake_service['attachment'],
'relax_scale_validation': fake_service['relax_scale_validation'],
'tags': consts.FAKE_TAGS
}
with mock.patch.object(self.nsxlib.client, 'create') as create:
with mock.patch.object(self.nsxlib.client, 'create') as create, \
mock.patch.object(self.nsxlib, 'feature_supported') as support:
support.return_value = True
self.nsxlib.load_balancer.service.create(
body['display_name'], body['description'],
consts.FAKE_TAGS, enabled=body['enabled'],
attachment=body['attachment'])
attachment=body['attachment'],
relax_scale_validation=body['relax_scale_validation'])
create.assert_called_with('loadbalancer/services',
body)

View File

@ -91,7 +91,7 @@ class NsxLib(lib.NsxLibBase):
self.ip_pool = resources.IpPool(
self.client, self.nsxlib_config, nsxlib=self)
self.load_balancer = load_balancer.LoadBalancer(
self.client, self.nsxlib_config)
self.client, self.nsxlib_config, nsxlib=self)
self.trust_management = trust_management.NsxLibTrustManagement(
self.client, self.nsxlib_config)
self.router = router.RouterLib(
@ -168,7 +168,13 @@ class NsxLib(lib.NsxLibBase):
def feature_supported(self, feature):
if (version.LooseVersion(self.get_version()) >=
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_0)):
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_1)):
# features available since 2.5.1
if (feature == nsx_constants.FEATURE_RELAX_SCALE_VALIDATION):
return True
if (version.LooseVersion(self.get_version()) >=
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_0)):
# features available since 2.5
if (feature == nsx_constants.FEATURE_CONTAINER_CLUSTER_INVENTORY):
return True
@ -178,7 +184,7 @@ class NsxLib(lib.NsxLibBase):
return True
if (version.LooseVersion(self.get_version()) >=
version.LooseVersion(nsx_constants.NSX_VERSION_2_4_0)):
version.LooseVersion(nsx_constants.NSX_VERSION_2_4_0)):
# Features available since 2.4
if (feature == nsx_constants.FEATURE_ENS_WITH_SEC):
return True
@ -188,7 +194,7 @@ class NsxLib(lib.NsxLibBase):
return True
if (version.LooseVersion(self.get_version()) >=
version.LooseVersion(nsx_constants.NSX_VERSION_2_3_0)):
version.LooseVersion(nsx_constants.NSX_VERSION_2_3_0)):
# Features available since 2.3
if (feature == nsx_constants.FEATURE_ROUTER_ALLOCATION_PROFILE):
return True

View File

@ -16,6 +16,7 @@
from oslo_log import log as logging
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsxlib.v3 import nsx_constants
from vmware_nsxlib.v3 import utils
LOG = logging.getLogger(__name__)
@ -411,6 +412,27 @@ class VirtualServer(LoadBalancerBase):
class Service(LoadBalancerBase):
resource = 'loadbalancer/services'
def _build_args(self, body, display_name=None, description=None,
tags=None, resource_type=None, **kwargs):
if display_name:
body['display_name'] = display_name
if description:
body['description'] = description
if tags:
body['tags'] = tags
if resource_type:
body['resource_type'] = resource_type
if ('relax_scale_validation' in kwargs and
not self.nsxlib.feature_supported(
nsx_constants.FEATURE_RELAX_SCALE_VALIDATION)):
kwargs.pop('relax_scale_validation')
LOG.warning("Ignoring relax_scale_validation for new "
"lb service %s: this feature is not supported.",
display_name)
body.update(kwargs)
return body
def update_service_with_virtual_servers(self, service_id,
virtual_server_ids):
# Using internal method so we can access max_attempts in the decorator
@ -475,8 +497,8 @@ class Service(LoadBalancerBase):
class LoadBalancer(object):
"""This is the class that have all load balancer resource clients"""
def __init__(self, client, nsxlib_config=None):
self.service = Service(client, nsxlib_config)
def __init__(self, client, nsxlib_config=None, nsxlib=None):
self.service = Service(client, nsxlib_config, nsxlib)
self.virtual_server = VirtualServer(client, nsxlib_config)
self.pool = Pool(client, nsxlib_config)
self.monitor = Monitor(client, nsxlib_config)

View File

@ -146,6 +146,7 @@ NSX_VERSION_2_2_0 = '2.2.0'
NSX_VERSION_2_3_0 = '2.3.0'
NSX_VERSION_2_4_0 = '2.4.0'
NSX_VERSION_2_5_0 = '2.5.0'
NSX_VERSION_2_5_1 = '2.5.1'
NSX_VERSION_3_0_0 = '3.0.0'
# Features available depending on the NSX Manager backend version
@ -169,6 +170,7 @@ FEATURE_ICMP_STRICT = 'Strict list of supported ICMP types and codes'
FEATURE_ROUTER_ALLOCATION_PROFILE = 'Router Allocation Profile'
FEATURE_ENABLE_STANDBY_RELOCATION = 'Router Enable standby relocation'
FEATURE_PARTIAL_UPDATES = 'Partial Update with PATCH'
FEATURE_RELAX_SCALE_VALIDATION = 'Relax Scale Validation for LbService'
# Features available depending on the Policy Manager backend version
FEATURE_NSX_POLICY = 'NSX Policy'

View File

@ -161,8 +161,15 @@ class NsxPolicyLib(lib.NsxLibBase):
if (feature == nsx_constants.FEATURE_ENS_WITH_QOS):
return True
if (version.LooseVersion(self.get_version()) >=
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_1)):
# features available since 2.5.1
if (feature == nsx_constants.FEATURE_RELAX_SCALE_VALIDATION):
return True
if (version.LooseVersion(self.get_version()) >=
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
# features available since 3.0.0
if feature == nsx_constants.FEATURE_PARTIAL_UPDATES:
return True

View File

@ -64,9 +64,13 @@ TIER1_LOCALE_SERVICES_PATH_PATTERN = (TIER1S_PATH_PATTERN +
@six.add_metaclass(abc.ABCMeta)
class ResourceDef(object):
def __init__(self, **kwargs):
def __init__(self, nsx_version=None, **kwargs):
self.attrs = kwargs
# nsx_version should be passed in on init if the resource has
# version-dependant attributes. Otherwise this is ignored
self.nsx_version = nsx_version
# init default tenant
self.attrs['tenant'] = self.get_tenant()
@ -191,6 +195,41 @@ class ResourceDef(object):
for attr in attr_list:
self._set_attr_if_specified(body, attr)
# Helper to set attr in body if user specified it
# and current nsx version supports it
# Body name must match attr name
def _set_attr_if_supported(self, body, attr, value=None):
if self.has_attr(attr) and self._version_dependant_attr_supported(
attr):
value = value if value is not None else self.get_attr(attr)
body[attr] = value
# Helper to set attrs in body if user specified them
# and current nsx version supports it
# Body name must match attr name
def _set_attrs_if_supported(self, body, attr_list):
for attr in attr_list:
self._set_attr_if_supported(body, attr)
def _version_dependant_attr_supported(self, attr):
"""Check if a version dependent attr is supported on current NSX
For each resource def, there could be some attributes which only exist
on NSX after certain versions. This abstract method provides a skeleton
to define version requirements of version-dependent attributes.
By design, Devs should use _set_attr_if_supported() to add any attrs
that are only known to NSX after a certain version. This method works
as a registry for _set_attrs_if_supported() to know the baseline
version of each version dependent attr.
Non-version-dependent attributes should be added to the request body
by using _set_attr_if_specified(). This method defaults to false since
any version dependent attr unknown to this lib should be excluded
for security and safety reasons.
"""
return False
@classmethod
def get_single_entry(cls, obj_body):
"""Return the single sub-entry from the object body.

View File

@ -125,7 +125,7 @@ class NsxPolicyResourceBase(object):
def _init_def(self, **kwargs):
"""Helper for update function - ignore attrs without explicit value"""
args = self._get_user_args(**kwargs)
return self.entry_def(**args)
return self.entry_def(nsx_version=self.version, **args)
def _init_parent_def(self, **kwargs):
"""Helper for update function - ignore attrs without explicit value"""
@ -135,7 +135,7 @@ class NsxPolicyResourceBase(object):
def _get_and_update_def(self, **kwargs):
"""Helper for update function - ignore attrs without explicit value"""
args = self._get_user_args(**kwargs)
resource_def = self.entry_def(**args)
resource_def = self.entry_def(nsx_version=self.version, **args)
body = self.policy_api.get(resource_def)
if body:
resource_def.set_obj_dict(body)

View File

@ -14,9 +14,15 @@
# under the License.
#
from distutils import version
from oslo_log import log as logging
from vmware_nsxlib.v3 import nsx_constants
from vmware_nsxlib.v3.policy import constants
from vmware_nsxlib.v3.policy.core_defs import ResourceDef
LOG = logging.getLogger(__name__)
TENANTS_PATH_PATTERN = "%s/"
LB_VIRTUAL_SERVERS_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-virtual-servers/"
LB_SERVICES_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-services/"
@ -379,8 +385,24 @@ class LBServiceDef(ResourceDef):
def get_obj_dict(self):
body = super(LBServiceDef, self).get_obj_dict()
self._set_attrs_if_specified(body, ['size', 'connectivity_path'])
self._set_attrs_if_supported(body, ['relax_scale_validation'])
return body
def _version_dependant_attr_supported(self, attr):
if (version.LooseVersion(self.nsx_version) >=
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_1)):
if attr == 'relax_scale_validation':
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_2_5_1)
return False
return False
class LBServiceStatisticsDef(ResourceDef):

View File

@ -577,6 +577,7 @@ class NsxPolicyLoadBalancerPoolApi(NsxPolicyResourceBase):
class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
"""NSX Policy LBService."""
@property
def entry_def(self):
return lb_defs.LBServiceDef
@ -586,6 +587,7 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
tags=IGNORE,
size=IGNORE,
connectivity_path=IGNORE,
relax_scale_validation=IGNORE,
tenant=constants.POLICY_INFRA_TENANT):
lb_service_id = self._init_obj_uuid(lb_service_id)
lb_service_def = self._init_def(
@ -595,6 +597,7 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
tags=tags,
size=size,
connectivity_path=connectivity_path,
relax_scale_validation=relax_scale_validation,
tenant=tenant)
self._create_or_store(lb_service_def)
@ -618,14 +621,18 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
def update(self, lb_service_id, name=IGNORE,
description=IGNORE, tags=IGNORE,
size=IGNORE, connectivity_path=IGNORE,
relax_scale_validation=IGNORE,
tenant=constants.POLICY_INFRA_TENANT):
self._update(lb_service_id=lb_service_id,
name=name,
description=description,
tags=tags,
size=size,
connectivity_path=connectivity_path,
tenant=tenant)
self._update(
lb_service_id=lb_service_id,
name=name,
description=description,
tags=tags,
size=size,
connectivity_path=connectivity_path,
relax_scale_validation=relax_scale_validation,
tenant=tenant)
def get_statistics(self, lb_service_id,
tenant=constants.POLICY_INFRA_TENANT):