Browse Source

Merge "Add support for relax_scale_validation in LbService"

changes/99/681199/5
Zuul 1 week ago
parent
commit
6b6e881201

+ 35
- 7
vmware_nsxlib/tests/unit/v3/policy/test_lb_resources.py View File

@@ -628,6 +628,7 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
628 628
         obj_id = '111'
629 629
         size = 'SMALL'
630 630
         connectivity_path = 'path'
631
+        relax_scale_validation = True
631 632
         with self.mock_create_update() as api_call:
632 633
             result = self.resourceApi.create_or_overwrite(
633 634
                 name,
@@ -635,14 +636,17 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
635 636
                 description=description,
636 637
                 size=size,
637 638
                 connectivity_path=connectivity_path,
639
+                relax_scale_validation=relax_scale_validation,
638 640
                 tenant=TEST_TENANT)
639 641
             expected_def = (
640 642
                 lb_defs.LBServiceDef(
643
+                    nsx_version=self.policy_lib.get_version(),
641 644
                     lb_service_id=obj_id,
642 645
                     name=name,
643 646
                     description=description,
644 647
                     size=size,
645 648
                     connectivity_path=connectivity_path,
649
+                    relax_scale_validation=relax_scale_validation,
646 650
                     tenant=TEST_TENANT))
647 651
             self.assert_called_with_def(api_call, expected_def)
648 652
             self.assertEqual(obj_id, result)
@@ -662,6 +666,25 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
662 666
             self.assert_called_with_def(api_call, expected_def)
663 667
             self.assertIsNotNone(result)
664 668
 
669
+    def test_create_with_unsupported_attribute(self):
670
+        name = 'd1'
671
+        description = 'desc'
672
+        relax_scale_validation = True
673
+
674
+        with self.mock_create_update() as api_call, \
675
+                mock.patch.object(self.resourceApi, 'version', '0.0.0'):
676
+            result = self.resourceApi.create_or_overwrite(
677
+                name, description=description,
678
+                relax_scale_validation=relax_scale_validation,
679
+                tenant=TEST_TENANT)
680
+            expected_def = (
681
+                lb_defs.LBServiceDef(lb_service_id=mock.ANY,
682
+                                     name=name,
683
+                                     description=description,
684
+                                     tenant=TEST_TENANT))
685
+            self.assert_called_with_def(api_call, expected_def)
686
+            self.assertIsNotNone(result)
687
+
665 688
     def test_delete(self):
666 689
         obj_id = '111'
667 690
         with mock.patch.object(self.policy_api, "delete") as api_call:
@@ -708,21 +731,26 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
708 731
         description = 'new desc'
709 732
         size = 'SMALL'
710 733
         connectivity_path = 'path'
734
+        relax_scale_validation = True
711 735
         with self.mock_get(obj_id, name), \
712 736
             self.mock_create_update() as update_call:
713
-            self.resourceApi.update(obj_id,
714
-                                    name=name,
715
-                                    description=description,
716
-                                    tenant=TEST_TENANT,
717
-                                    size=size,
718
-                                    connectivity_path=connectivity_path)
737
+            self.resourceApi.update(
738
+                obj_id,
739
+                name=name,
740
+                description=description,
741
+                tenant=TEST_TENANT,
742
+                size=size,
743
+                connectivity_path=connectivity_path,
744
+                relax_scale_validation=relax_scale_validation)
719 745
             expected_def = lb_defs.LBServiceDef(
746
+                nsx_version=self.policy_lib.get_version(),
720 747
                 lb_service_id=obj_id,
721 748
                 name=name,
722 749
                 description=description,
723 750
                 tenant=TEST_TENANT,
724 751
                 size=size,
725
-                connectivity_path=connectivity_path)
752
+                connectivity_path=connectivity_path,
753
+                relax_scale_validation=relax_scale_validation)
726 754
             self.assert_called_with_def(update_call, expected_def)
727 755
 
728 756
     def test_get_status(self):

+ 2
- 1
vmware_nsxlib/tests/unit/v3/test_constants.py View File

@@ -348,7 +348,8 @@ FAKE_SERVICE = {
348 348
     "attachment": {
349 349
         "target_id": FAKE_ROUTER_UUID,
350 350
         "target_type": "LogicalRouter"
351
-    }
351
+    },
352
+    "relax_scale_validation": False
352 353
 }
353 354
 
354 355
 FAKE_TZ_UUID = uuidutils.generate_uuid()

+ 6
- 2
vmware_nsxlib/tests/unit/v3/test_load_balancer.py View File

@@ -498,13 +498,17 @@ class TestService(nsxlib_testcase.NsxClientTestCase):
498 498
             'description': fake_service['description'],
499 499
             'enabled': fake_service['enabled'],
500 500
             'attachment': fake_service['attachment'],
501
+            'relax_scale_validation': fake_service['relax_scale_validation'],
501 502
             'tags': consts.FAKE_TAGS
502 503
         }
503
-        with mock.patch.object(self.nsxlib.client, 'create') as create:
504
+        with mock.patch.object(self.nsxlib.client, 'create') as create, \
505
+                mock.patch.object(self.nsxlib, 'feature_supported') as support:
506
+            support.return_value = True
504 507
             self.nsxlib.load_balancer.service.create(
505 508
                 body['display_name'], body['description'],
506 509
                 consts.FAKE_TAGS, enabled=body['enabled'],
507
-                attachment=body['attachment'])
510
+                attachment=body['attachment'],
511
+                relax_scale_validation=body['relax_scale_validation'])
508 512
             create.assert_called_with('loadbalancer/services',
509 513
                                       body)
510 514
 

+ 10
- 4
vmware_nsxlib/v3/__init__.py View File

@@ -91,7 +91,7 @@ class NsxLib(lib.NsxLibBase):
91 91
         self.ip_pool = resources.IpPool(
92 92
             self.client, self.nsxlib_config, nsxlib=self)
93 93
         self.load_balancer = load_balancer.LoadBalancer(
94
-            self.client, self.nsxlib_config)
94
+            self.client, self.nsxlib_config, nsxlib=self)
95 95
         self.trust_management = trust_management.NsxLibTrustManagement(
96 96
             self.client, self.nsxlib_config)
97 97
         self.router = router.RouterLib(
@@ -168,7 +168,13 @@ class NsxLib(lib.NsxLibBase):
168 168
 
169 169
     def feature_supported(self, feature):
170 170
         if (version.LooseVersion(self.get_version()) >=
171
-                version.LooseVersion(nsx_constants.NSX_VERSION_2_5_0)):
171
+            version.LooseVersion(nsx_constants.NSX_VERSION_2_5_1)):
172
+            # features available since 2.5.1
173
+            if (feature == nsx_constants.FEATURE_RELAX_SCALE_VALIDATION):
174
+                return True
175
+
176
+        if (version.LooseVersion(self.get_version()) >=
177
+            version.LooseVersion(nsx_constants.NSX_VERSION_2_5_0)):
172 178
             # features available since 2.5
173 179
             if (feature == nsx_constants.FEATURE_CONTAINER_CLUSTER_INVENTORY):
174 180
                 return True
@@ -178,7 +184,7 @@ class NsxLib(lib.NsxLibBase):
178 184
                 return True
179 185
 
180 186
         if (version.LooseVersion(self.get_version()) >=
181
-                version.LooseVersion(nsx_constants.NSX_VERSION_2_4_0)):
187
+            version.LooseVersion(nsx_constants.NSX_VERSION_2_4_0)):
182 188
             # Features available since 2.4
183 189
             if (feature == nsx_constants.FEATURE_ENS_WITH_SEC):
184 190
                 return True
@@ -188,7 +194,7 @@ class NsxLib(lib.NsxLibBase):
188 194
                 return True
189 195
 
190 196
         if (version.LooseVersion(self.get_version()) >=
191
-                version.LooseVersion(nsx_constants.NSX_VERSION_2_3_0)):
197
+            version.LooseVersion(nsx_constants.NSX_VERSION_2_3_0)):
192 198
             # Features available since 2.3
193 199
             if (feature == nsx_constants.FEATURE_ROUTER_ALLOCATION_PROFILE):
194 200
                 return True

+ 24
- 2
vmware_nsxlib/v3/load_balancer.py View File

@@ -16,6 +16,7 @@
16 16
 from oslo_log import log as logging
17 17
 
18 18
 from vmware_nsxlib.v3 import exceptions as nsxlib_exc
19
+from vmware_nsxlib.v3 import nsx_constants
19 20
 from vmware_nsxlib.v3 import utils
20 21
 
21 22
 LOG = logging.getLogger(__name__)
@@ -411,6 +412,27 @@ class VirtualServer(LoadBalancerBase):
411 412
 class Service(LoadBalancerBase):
412 413
     resource = 'loadbalancer/services'
413 414
 
415
+    def _build_args(self, body, display_name=None, description=None,
416
+                    tags=None, resource_type=None, **kwargs):
417
+        if display_name:
418
+            body['display_name'] = display_name
419
+        if description:
420
+            body['description'] = description
421
+        if tags:
422
+            body['tags'] = tags
423
+        if resource_type:
424
+            body['resource_type'] = resource_type
425
+
426
+        if ('relax_scale_validation' in kwargs and
427
+            not self.nsxlib.feature_supported(
428
+                nsx_constants.FEATURE_RELAX_SCALE_VALIDATION)):
429
+            kwargs.pop('relax_scale_validation')
430
+            LOG.warning("Ignoring relax_scale_validation for new "
431
+                        "lb service %s: this feature is not supported.",
432
+                        display_name)
433
+        body.update(kwargs)
434
+        return body
435
+
414 436
     def update_service_with_virtual_servers(self, service_id,
415 437
                                             virtual_server_ids):
416 438
         # Using internal method so we can access max_attempts in the decorator
@@ -475,8 +497,8 @@ class Service(LoadBalancerBase):
475 497
 class LoadBalancer(object):
476 498
     """This is the class that have all load balancer resource clients"""
477 499
 
478
-    def __init__(self, client, nsxlib_config=None):
479
-        self.service = Service(client, nsxlib_config)
500
+    def __init__(self, client, nsxlib_config=None, nsxlib=None):
501
+        self.service = Service(client, nsxlib_config, nsxlib)
480 502
         self.virtual_server = VirtualServer(client, nsxlib_config)
481 503
         self.pool = Pool(client, nsxlib_config)
482 504
         self.monitor = Monitor(client, nsxlib_config)

+ 2
- 0
vmware_nsxlib/v3/nsx_constants.py View File

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

+ 7
- 0
vmware_nsxlib/v3/policy/__init__.py View File

@@ -161,8 +161,15 @@ class NsxPolicyLib(lib.NsxLibBase):
161 161
             if (feature == nsx_constants.FEATURE_ENS_WITH_QOS):
162 162
                 return True
163 163
 
164
+        if (version.LooseVersion(self.get_version()) >=
165
+            version.LooseVersion(nsx_constants.NSX_VERSION_2_5_1)):
166
+            # features available since 2.5.1
167
+            if (feature == nsx_constants.FEATURE_RELAX_SCALE_VALIDATION):
168
+                return True
169
+
164 170
         if (version.LooseVersion(self.get_version()) >=
165 171
             version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
172
+            # features available since 3.0.0
166 173
             if feature == nsx_constants.FEATURE_PARTIAL_UPDATES:
167 174
                 return True
168 175
 

+ 40
- 1
vmware_nsxlib/v3/policy/core_defs.py View File

@@ -64,9 +64,13 @@ TIER1_LOCALE_SERVICES_PATH_PATTERN = (TIER1S_PATH_PATTERN +
64 64
 
65 65
 @six.add_metaclass(abc.ABCMeta)
66 66
 class ResourceDef(object):
67
-    def __init__(self, **kwargs):
67
+    def __init__(self, nsx_version=None, **kwargs):
68 68
         self.attrs = kwargs
69 69
 
70
+        # nsx_version should be passed in on init if the resource has
71
+        # version-dependant attributes. Otherwise this is ignored
72
+        self.nsx_version = nsx_version
73
+
70 74
         # init default tenant
71 75
         self.attrs['tenant'] = self.get_tenant()
72 76
 
@@ -191,6 +195,41 @@ class ResourceDef(object):
191 195
         for attr in attr_list:
192 196
             self._set_attr_if_specified(body, attr)
193 197
 
198
+    # Helper to set attr in body if user specified it
199
+    # and current nsx version supports it
200
+    # Body name must match attr name
201
+    def _set_attr_if_supported(self, body, attr, value=None):
202
+        if self.has_attr(attr) and self._version_dependant_attr_supported(
203
+                attr):
204
+            value = value if value is not None else self.get_attr(attr)
205
+            body[attr] = value
206
+
207
+    # Helper to set attrs in body if user specified them
208
+    # and current nsx version supports it
209
+    # Body name must match attr name
210
+    def _set_attrs_if_supported(self, body, attr_list):
211
+        for attr in attr_list:
212
+            self._set_attr_if_supported(body, attr)
213
+
214
+    def _version_dependant_attr_supported(self, attr):
215
+        """Check if a version dependent attr is supported on current NSX
216
+
217
+        For each resource def, there could be some attributes which only exist
218
+        on NSX after certain versions. This abstract method provides a skeleton
219
+        to define version requirements of version-dependent attributes.
220
+
221
+        By design, Devs should use _set_attr_if_supported() to add any attrs
222
+        that are only known to NSX after a certain version. This method works
223
+        as a registry for _set_attrs_if_supported() to know the baseline
224
+        version of each version dependent attr.
225
+
226
+        Non-version-dependent attributes should be added to the request body
227
+        by using _set_attr_if_specified(). This method defaults to false since
228
+        any version dependent attr unknown to this lib should be excluded
229
+        for security and safety reasons.
230
+        """
231
+        return False
232
+
194 233
     @classmethod
195 234
     def get_single_entry(cls, obj_body):
196 235
         """Return the single sub-entry from the object body.

+ 2
- 2
vmware_nsxlib/v3/policy/core_resources.py View File

@@ -125,7 +125,7 @@ class NsxPolicyResourceBase(object):
125 125
     def _init_def(self, **kwargs):
126 126
         """Helper for update function - ignore attrs without explicit value"""
127 127
         args = self._get_user_args(**kwargs)
128
-        return self.entry_def(**args)
128
+        return self.entry_def(nsx_version=self.version, **args)
129 129
 
130 130
     def _init_parent_def(self, **kwargs):
131 131
         """Helper for update function - ignore attrs without explicit value"""
@@ -135,7 +135,7 @@ class NsxPolicyResourceBase(object):
135 135
     def _get_and_update_def(self, **kwargs):
136 136
         """Helper for update function - ignore attrs without explicit value"""
137 137
         args = self._get_user_args(**kwargs)
138
-        resource_def = self.entry_def(**args)
138
+        resource_def = self.entry_def(nsx_version=self.version, **args)
139 139
         body = self.policy_api.get(resource_def)
140 140
         if body:
141 141
             resource_def.set_obj_dict(body)

+ 22
- 0
vmware_nsxlib/v3/policy/lb_defs.py View File

@@ -14,9 +14,15 @@
14 14
 #    under the License.
15 15
 #
16 16
 
17
+from distutils import version
18
+
19
+from oslo_log import log as logging
20
+from vmware_nsxlib.v3 import nsx_constants
17 21
 from vmware_nsxlib.v3.policy import constants
18 22
 from vmware_nsxlib.v3.policy.core_defs import ResourceDef
19 23
 
24
+LOG = logging.getLogger(__name__)
25
+
20 26
 TENANTS_PATH_PATTERN = "%s/"
21 27
 LB_VIRTUAL_SERVERS_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-virtual-servers/"
22 28
 LB_SERVICES_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-services/"
@@ -379,8 +385,24 @@ class LBServiceDef(ResourceDef):
379 385
     def get_obj_dict(self):
380 386
         body = super(LBServiceDef, self).get_obj_dict()
381 387
         self._set_attrs_if_specified(body, ['size', 'connectivity_path'])
388
+        self._set_attrs_if_supported(body, ['relax_scale_validation'])
382 389
         return body
383 390
 
391
+    def _version_dependant_attr_supported(self, attr):
392
+        if (version.LooseVersion(self.nsx_version) >=
393
+            version.LooseVersion(nsx_constants.NSX_VERSION_2_5_1)):
394
+            if attr == 'relax_scale_validation':
395
+                return True
396
+            else:
397
+                LOG.warning(
398
+                    "Ignoring %s for %s %s: this feature is not supported."
399
+                    "Current NSX version: %s. Minimum supported version: %s",
400
+                    attr, self.resource_type, self.attrs.get('name', ''),
401
+                    self.nsx_version, nsx_constants.NSX_VERSION_2_5_1)
402
+                return False
403
+
404
+        return False
405
+
384 406
 
385 407
 class LBServiceStatisticsDef(ResourceDef):
386 408
 

+ 14
- 7
vmware_nsxlib/v3/policy/lb_resources.py View File

@@ -577,6 +577,7 @@ class NsxPolicyLoadBalancerPoolApi(NsxPolicyResourceBase):
577 577
 
578 578
 class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
579 579
     """NSX Policy LBService."""
580
+
580 581
     @property
581 582
     def entry_def(self):
582 583
         return lb_defs.LBServiceDef
@@ -586,6 +587,7 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
586 587
                             tags=IGNORE,
587 588
                             size=IGNORE,
588 589
                             connectivity_path=IGNORE,
590
+                            relax_scale_validation=IGNORE,
589 591
                             tenant=constants.POLICY_INFRA_TENANT):
590 592
         lb_service_id = self._init_obj_uuid(lb_service_id)
591 593
         lb_service_def = self._init_def(
@@ -595,6 +597,7 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
595 597
             tags=tags,
596 598
             size=size,
597 599
             connectivity_path=connectivity_path,
600
+            relax_scale_validation=relax_scale_validation,
598 601
             tenant=tenant)
599 602
 
600 603
         self._create_or_store(lb_service_def)
@@ -618,14 +621,18 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
618 621
     def update(self, lb_service_id, name=IGNORE,
619 622
                description=IGNORE, tags=IGNORE,
620 623
                size=IGNORE, connectivity_path=IGNORE,
624
+               relax_scale_validation=IGNORE,
621 625
                tenant=constants.POLICY_INFRA_TENANT):
622
-        self._update(lb_service_id=lb_service_id,
623
-                     name=name,
624
-                     description=description,
625
-                     tags=tags,
626
-                     size=size,
627
-                     connectivity_path=connectivity_path,
628
-                     tenant=tenant)
626
+
627
+        self._update(
628
+            lb_service_id=lb_service_id,
629
+            name=name,
630
+            description=description,
631
+            tags=tags,
632
+            size=size,
633
+            connectivity_path=connectivity_path,
634
+            relax_scale_validation=relax_scale_validation,
635
+            tenant=tenant)
629 636
 
630 637
     def get_statistics(self, lb_service_id,
631 638
                        tenant=constants.POLICY_INFRA_TENANT):

Loading…
Cancel
Save