Browse Source

Command for managing DVPGs on vCenter server.

Adds "ovsvapp-mange-dvpg", a cli command to
manage Distributed Virtual Port Groups on a
vCenter server.

Change-Id: Ifb9f6c615462ef5b1d3661e66a328c07f2496698
Adolfo Duarte 1 year ago
parent
commit
e33b775bb3

+ 168
- 0
networking_vsphere/tests/unit/utils/test_vim_objects.py View File

@@ -245,3 +245,171 @@ class TestDistributedVirtualSwitch(TestBase):
245 245
         self.assertIsNotNone(self.sut.datacenter)
246 246
         mocked_get_mob_by_name.assert_called_with('Datacenter',
247 247
                                                   self.sut.datacenter_name)
248
+
249
+
250
+class TestDVSPortGroup(TestBase):
251
+    def setUp(self):
252
+        super(TestDVSPortGroup, self).setUp()
253
+        self.sut = vim_objects.DVSPortGroup('test_dvs_pg',
254
+                                            vlan_type=None,
255
+                                            vlan_id=None,
256
+                                            vlan_range_start=0,
257
+                                            vlan_range_end=4094,
258
+                                            dvs_name=None,
259
+                                            nic_teaming=None,
260
+                                            description=None,
261
+                                            allow_promiscuous=False,
262
+                                            forged_transmits=False,
263
+                                            auto_expand=True
264
+                                            )
265
+
266
+    @mock.patch.object(networking_vsphere.utils.vim_objects.VcenterProxy,
267
+                       'get_type')
268
+    def test_config_spec(self, mocked_get_type):
269
+        mocked_result = MagicMock()
270
+        mocked_get_type.return_value = mocked_result
271
+        self.assertEqual(self.sut.config_spec, mocked_result)
272
+        for _type in [
273
+            'DVPortgroupConfigSpec',
274
+            'DistributedVirtualPortgroupPortgroupType',
275
+            'VMwareDVSPortSetting',
276
+            'DVSSecurityPolicy',
277
+            'BoolPolicy',
278
+            'VmwareUplinkPortTeamingPolicy',
279
+            'DVSFailureCriteria',
280
+            'VMwareUplinkPortOrderPolicy'
281
+        ]:
282
+            mocked_get_type.assert_any_call(_type)
283
+
284
+    @mock.patch.object(networking_vsphere.utils.vim_objects.VcenterProxy,
285
+                       'get_type')
286
+    def test_dvs_port_settings(self, mocked_get_type):
287
+        mocked_result = MagicMock()
288
+        mocked_get_type.return_value = mocked_result
289
+        self.assertEqual(self.sut.dvs_port_settings, mocked_result)
290
+        for _type in [
291
+            'VMwareDVSPortSetting',
292
+            'DVSSecurityPolicy',
293
+            'BoolPolicy',
294
+            'VmwareUplinkPortTeamingPolicy',
295
+            'DVSFailureCriteria',
296
+            'VMwareUplinkPortOrderPolicy'
297
+        ]:
298
+            mocked_get_type.assert_any_call(_type)
299
+
300
+    @mock.patch.object(networking_vsphere.utils.vim_objects.VcenterProxy,
301
+                       'get_type')
302
+    def test_vlan_spec(self, mocked_get_type):
303
+        mocked_result = MagicMock()
304
+        mocked_result.__len__.return_value = 1
305
+        mocked_get_type.return_value = mocked_result
306
+
307
+        self.sut.vlan_type = None
308
+        self.assertEqual(len(self.sut.vlan_spec), 1)
309
+        mocked_get_type.assert_called_with(
310
+            'VmwareDistributedVirtualSwitchVlanIdSpec')
311
+
312
+        self.sut.vlan_type = 'vlan'
313
+        self.assertEqual(len(self.sut.vlan_spec), 1)
314
+        mocked_get_type.assert_called_with(
315
+            'VmwareDistributedVirtualSwitchVlanIdSpec')
316
+
317
+        self.sut.vlan_type = 'trunk'
318
+        self.assertEqual(len(self.sut.vlan_spec), 1)
319
+        mocked_get_type.assert_called_with(
320
+            'VmwareDistributedVirtualSwitchTrunkVlanSpec')
321
+
322
+    @mock.patch.object(networking_vsphere.utils.vim_objects.VcenterProxy,
323
+                       'get_type')
324
+    def test_vlan_spec_id(self, mocked_get_type):
325
+        mocked_result = MagicMock()
326
+        mocked_get_type.return_value = mocked_result
327
+
328
+        self.sut.vlan_type = None
329
+        self.sut.vlanid = None
330
+        self.assertEqual(self.sut.vlan_spec_id, 0)
331
+        mocked_get_type.assert_not_called()
332
+        mocked_get_type.reset_mock()
333
+
334
+        self.sut.vlan_type = 'vlan'
335
+        self.sut.vlan_id = None
336
+        self.assertEqual(self.sut.vlan_spec_id, 0)
337
+        mocked_get_type.assert_not_called()
338
+        mocked_get_type.reset_mock()
339
+
340
+        self.sut.vlan_type = 'trunk'
341
+        self.sut.vlan_id = None
342
+        results = self.sut.vlan_spec_id
343
+        mocked_get_type.assert_called_with('NumericRange')
344
+        self.assertEqual(results.start,
345
+                         self.sut.vlan_range_start)
346
+        self.assertEqual(results.end,
347
+                         self.sut.vlan_range_end)
348
+        mocked_get_type.reset_mock()
349
+
350
+        self.sut.vlan_type = None
351
+        self.sut.vlan_id = 1
352
+        self.assertEqual(self.sut.vlan_spec_id, 1)
353
+        mocked_get_type.assert_not_called()
354
+        mocked_get_type.reset_mock()
355
+
356
+        self.sut.vlan_type = 'vlan'
357
+        self.sut.vlan_id = 1
358
+        self.assertEqual(self.sut.vlan_spec_id, 1)
359
+        mocked_get_type.assert_not_called()
360
+        mocked_get_type.reset_mock()
361
+
362
+        self.sut.vlan_type = 'trunk'
363
+        self.sut.vlan_id = 1
364
+        results = self.sut.vlan_spec_id
365
+        mocked_get_type.assert_called_with('NumericRange')
366
+        self.assertEqual(results.start,
367
+                         self.sut.vlan_range_start)
368
+        self.assertEqual(results.end,
369
+                         self.sut.vlan_range_end)
370
+        mocked_get_type.reset_mock()
371
+
372
+    @mock.patch.object(networking_vsphere.utils.vim_objects.VcenterProxy,
373
+                       'get_type')
374
+    def test_security_policy(self, mocked_get_type):
375
+        mocked_result = MagicMock()
376
+        mocked_get_type.return_value = mocked_result
377
+        results = self.sut.security_policy
378
+        self.assertEqual(results, mocked_result)
379
+        for _type in [
380
+            'DVSSecurityPolicy',
381
+            'BoolPolicy'
382
+        ]:
383
+            mocked_get_type.assert_any_call(_type)
384
+
385
+        self.assertEqual(results.allowPromiscuous.value,
386
+                         self.sut.allow_promiscuous)
387
+        self.assertEqual(results.forgedTransmits.value,
388
+                         self.sut.forged_transmits)
389
+
390
+    @mock.patch.object(networking_vsphere.utils.vim_objects.VcenterProxy,
391
+                       'get_type')
392
+    def test_uplink_teaming_policy(self, mocked_get_type):
393
+        mocked_result = MagicMock()
394
+        mocked_get_type.return_value = mocked_result
395
+        self.assertEqual(len(self.sut.uplink_teaming_policy.
396
+                             uplinkPortOrder.activeUplinkPort), 0)
397
+
398
+        self.sut.nic_teaming['active_nics'] = ['vmnic1', 'vmnic2']
399
+        results = self.sut.uplink_teaming_policy
400
+        self.assertEqual(results, mocked_result)
401
+        for _type in [
402
+            'VmwareUplinkPortTeamingPolicy',
403
+            'BoolPolicy',
404
+            'DVSFailureCriteria',
405
+            'VMwareUplinkPortOrderPolicy'
406
+        ]:
407
+            mocked_get_type.assert_any_call(_type)
408
+
409
+        self.assertEqual(len(results.uplinkPortOrder.activeUplinkPort), 2)
410
+        self.assertEqual(results.policy.value,
411
+                         self.sut.nic_teaming['load_balancing'])
412
+        self.assertEqual(results.failureCriteria.checkBeacon.value,
413
+                         self.sut.nic_teaming['network_failover_detection'])
414
+        self.assertEqual(results.notifySwitches.value,
415
+                         self.sut.nic_teaming['notify_switches'])

+ 141
- 0
networking_vsphere/utils/ovsvapp_manage_vcenter.py View File

@@ -115,3 +115,144 @@ def dvs():
115 115
     if args.v:
116 116
         print("DVS Configuration: ")
117 117
         print(_dvs)
118
+
119
+
120
+def vlan_id_type(vid):
121
+    _id = int(vid)
122
+    if _id < 0 or _id > 4094:
123
+        raise argparse.ArgumentTypeError("Vlan id must be a value between "
124
+                                         "0 and 4094")
125
+    return _id
126
+
127
+
128
+def dvpg():
129
+    parser = argparse.ArgumentParser()
130
+
131
+    parser.add_argument("dvpg_name", type=str,
132
+                        help="Name to use for creating the"
133
+                             "Distributed Virtual Port Group (DVPG)")
134
+
135
+    parser.add_argument("vcenter_user", type=str,
136
+                        help="Username to be used for connecting to vCenter")
137
+
138
+    parser.add_argument("vcenter_password", type=str,
139
+                        help="Password to be used for connecting to vCenter")
140
+
141
+    parser.add_argument("vcenter_ip", type=str,
142
+                        help="IP address to be used for connecting to vCenter")
143
+
144
+    parser.add_argument("--tcp", type=int, dest='vcenter_port',
145
+                        metavar='tcp_port',
146
+                        help="TCP port to be used for connecting to vCenter",
147
+                        default=443)
148
+
149
+    parser.add_argument("dvs_name", type=str,
150
+                        help="Name of the Distributed Virtual Switch (DVS) "
151
+                             " to create the DVPG in")
152
+
153
+    parser.add_argument("--vlan_type", type=str, dest='vlan_type',
154
+                        metavar='vlan_type',
155
+                        help="Vlan type to use for the DVPG",
156
+                        choices=['vlan', 'trunk'],
157
+                        default='vlan')
158
+
159
+    parser.add_argument("--vlan_id", type=vlan_id_type, dest='vlan_id',
160
+                        metavar='vlan_id',
161
+                        help="Vlan id to use for vlan_type='vlan'",
162
+                        default=443)
163
+
164
+    parser.add_argument("--vlan_range_start", type=vlan_id_type,
165
+                        dest='vlan_range_start',
166
+                        metavar='vlan_range_start',
167
+                        help="Start of vlan id range for vlan_type='trunk'",
168
+                        default=0)
169
+
170
+    parser.add_argument("--vlan_range_stop", type=vlan_id_type,
171
+                        dest='vlan_range_stop',
172
+                        metavar='vlan_range_stop',
173
+                        help="End of vlan id range for vlan_type='trunk'",
174
+                        default=4094)
175
+
176
+    parser.add_argument("--description", type=str, dest='description',
177
+                        metavar='description',
178
+                        help="DVPG description",
179
+                        default="")
180
+
181
+    parser.add_argument("--allow_promiscuous", action='store_true',
182
+                        help="Sets promiscuous mode of DVPG")
183
+
184
+    parser.add_argument("--allow_forged_transmits", action='store_true',
185
+                        help="Sets forge transmit mode of DVPG")
186
+
187
+    parser.add_argument("--notify_switches", action='store_true',
188
+                        help="Set nic teaming 'notify switches' to True. ")
189
+
190
+    parser.add_argument("--network_failover_detection", action='store_true',
191
+                        help="Set nic teaming 'network failover detection' to "
192
+                             "True")
193
+
194
+    parser.add_argument("--load_balancing", type=str,
195
+                        choices=['loadbalance_srcid',
196
+                                 'loadbalance_ip',
197
+                                 'loadbalance_srcmac',
198
+                                 'loadbalance_loadbased',
199
+                                 'failover_explicit'],
200
+                        default='loadbalance_srcid',
201
+
202
+                        help="Set nic teaming load balancing algorithm. "
203
+                             "Default=loadbalance_srcid")
204
+
205
+    parser.add_argument("--create", action='store_true',
206
+                        help="Create DVPG on vCenter")
207
+
208
+    parser.add_argument("--display_spec", action='store_true',
209
+                        help="Send DVPG's create spec to OUTPUT"
210
+                        )
211
+
212
+    parser.add_argument("--active_nics", nargs='+',
213
+                        help="Space separated list of active nics to use in "
214
+                             "DVPG nic teaming"
215
+                        )
216
+
217
+    parser.add_argument("-v", action='store_true',
218
+                        help="Verbose output")
219
+
220
+    args = parser.parse_args()
221
+
222
+    nic_teaming = {'notify_switches': args.notify_switches,
223
+                   'network_failover_detection':
224
+                       args.network_failover_detection,
225
+                   'load_balancing': args.load_balancing,
226
+                   'active_nics': args.active_nics}
227
+
228
+    _dvpg = vim_objects.DVSPortGroup(
229
+        args.dvpg_name,
230
+        dvs_name=args.dvs_name,
231
+        vcenter_user=args.vcenter_user,
232
+        vcenter_password=args.vcenter_password,
233
+        vcenter_ip=args.vcenter_ip,
234
+        vcenter_port=args.vcenter_port,
235
+        vlan_type=args.vlan_type,
236
+        vlan_id=args.vlan_id,
237
+        vlan_range_start=args.vlan_range_start,
238
+        nic_teaming=nic_teaming,
239
+        description=args.description,
240
+        allow_promiscuous=args.allow_promiscuous,
241
+        forged_transmits=args.allow_forged_transmits,
242
+        auto_expand=True
243
+    )
244
+
245
+    if args.display_spec or args.create:
246
+        _dvpg.connect_to_vcenter()
247
+
248
+    if args.display_spec:
249
+        print(_dvpg.create_spec)
250
+
251
+    if args.create:
252
+        print("Attempting to create switch...")
253
+        _dvpg.create_on_vcenter()
254
+        print("Success")
255
+
256
+    if args.v:
257
+        print("DVPG Configuration: ")
258
+        print(_dvpg)

+ 123
- 0
networking_vsphere/utils/vim_objects.py View File

@@ -287,3 +287,126 @@ class DistributedVirtualSwitch(VcenterProxy):
287 287
                                        spec=self.create_spec)
288 288
 
289 289
         self.session.wait_for_task(task)
290
+
291
+
292
+class DVSPortGroup(VcenterProxy):
293
+
294
+    def __init__(self, name,
295
+                 vlan_type=None,
296
+                 vlan_id=None,
297
+                 vlan_range_start=0,
298
+                 vlan_range_end=4094,
299
+                 dvs_name=None,
300
+                 nic_teaming=None,
301
+                 description=None,
302
+                 allow_promiscuous=False,
303
+                 forged_transmits=False,
304
+                 auto_expand=True,
305
+                 **kwargs):
306
+        super(DVSPortGroup, self).__init__(name, **kwargs)
307
+        self.vlan_type = vlan_type
308
+        self.vlan_id = vlan_id
309
+        self.vlan_range_start = vlan_range_start
310
+        self.vlan_range_end = vlan_range_end
311
+        self.dvs_name = dvs_name
312
+        self.nic_teaming = nic_teaming
313
+        self.description = description
314
+        self.allow_promiscuous = allow_promiscuous
315
+        self.forged_transmits = forged_transmits
316
+        self.auto_expand = auto_expand
317
+        if self.nic_teaming is None:
318
+            self.nic_teaming = {'notify_switches': True,
319
+                                'network_failover_detection': True,
320
+                                'load_balancing': 'loadbalance_srcid',
321
+                                'active_nics': []}
322
+
323
+    def __str__(self):
324
+
325
+        return '\n'.join(["{} = '{}'".format(key, self.__dict__[key])
326
+                          for key in self.__dict__])
327
+
328
+    @property
329
+    def config_spec(self):
330
+        spec = self.get_type('DVPortgroupConfigSpec')
331
+        spec.name = self.name
332
+        spec.description = self.description
333
+        spec.autoExpand = True
334
+        spec.type = self.get_type(
335
+            'DistributedVirtualPortgroupPortgroupType').earlyBinding
336
+        spec.defaultPortConfig = self.dvs_port_settings
337
+        return spec
338
+
339
+    @property
340
+    def dvs_port_settings(self):
341
+        port_settings = self.get_type('VMwareDVSPortSetting')
342
+        port_settings.vlan = self.vlan_spec
343
+        port_settings.vlan.vlanId = self.vlan_spec_id
344
+        port_settings.vlan.inherited = False
345
+        port_settings.securityPolicy = self.security_policy
346
+        port_settings.uplinkTeamingPolicy = self.uplink_teaming_policy
347
+        return port_settings
348
+
349
+    @property
350
+    def vlan_spec(self):
351
+        if self.vlan_type == const.VLAN_TYPE_TRUNK:
352
+            return self.get_type('VmwareDistributedVirtualSwitchTrunkVlanSpec')
353
+        return self.get_type('VmwareDistributedVirtualSwitchVlanIdSpec')
354
+
355
+    @property
356
+    def vlan_spec_id(self):
357
+        if str(self.vlan_type).lower() == str(const.VLAN_TYPE_TRUNK).lower():
358
+            vlan_range = self.get_type('NumericRange')
359
+            vlan_range.start = self.vlan_range_start
360
+            vlan_range.end = self.vlan_range_end
361
+            return vlan_range
362
+
363
+        if self.vlan_id is None:
364
+            return 0
365
+        return self.vlan_id
366
+
367
+    @property
368
+    def security_policy(self):
369
+        policy = self.get_type('DVSSecurityPolicy')
370
+        policy.inherited = False
371
+        policy.allowPromiscuous = self.get_type('BoolPolicy')
372
+        policy.allowPromiscuous.inherited = False
373
+        policy.allowPromiscuous.value = self.allow_promiscuous
374
+        policy.forgedTransmits = self.get_type('BoolPolicy')
375
+        policy.forgedTransmits.inherited = False
376
+        policy.forgedTransmits.value = self.forged_transmits
377
+        return policy
378
+
379
+    @property
380
+    def uplink_teaming_policy(self):
381
+        policy = self.get_type('VmwareUplinkPortTeamingPolicy')
382
+        policy.inherited = False
383
+
384
+        policy.notifySwitches = self.get_type('BoolPolicy')
385
+        policy.notifySwitches.inherited = False
386
+        policy.notifySwitches.value = self.nic_teaming['notify_switches']
387
+
388
+        policy.failureCriteria = self.get_type('DVSFailureCriteria')
389
+        policy.failureCriteria.inherited = False
390
+        policy.failureCriteria.checkBeacon = self.get_type('BoolPolicy')
391
+        policy.failureCriteria.checkBeacon.inherited = False
392
+        policy.failureCriteria.checkBeacon.value = self.nic_teaming[
393
+            'network_failover_detection']
394
+
395
+        policy.policy.inherited = False
396
+        policy.policy.value = self.nic_teaming['load_balancing']
397
+
398
+        policy.uplinkPortOrder = self.get_type('VMwareUplinkPortOrderPolicy')
399
+        policy.uplinkPortOrder.activeUplinkPort = self.nic_teaming[
400
+            'active_nics']
401
+
402
+        return policy
403
+
404
+    def create_on_vcenter(self):
405
+        dvs = self.get_mob_by_name('DistributedVirtualSwitch',
406
+                                   self.dvs_name)
407
+        task = self.session.invoke_api(self.session.vim,
408
+                                       'AddDVPortgroup_Task',
409
+                                       dvs.obj,
410
+                                       spec=self.config_spec)
411
+
412
+        self.session.wait_for_task(task)

+ 1
- 0
setup.cfg View File

@@ -40,6 +40,7 @@ console_scripts =
40 40
     neutron-ovsvapp-agent-monitor = networking_vsphere.monitor.monitor:main
41 41
     neutron-dvs-agent = networking_vsphere.agent.dvs_neutron_agent:main
42 42
     ovsvapp-manage-dvs = networking_vsphere.utils.ovsvapp_manage_vcenter:dvs
43
+    ovsvapp-manage-dvpg = networking_vsphere.utils.ovsvapp_manage_vcenter:dvpg
43 44
 neutron.ml2.mechanism_drivers =
44 45
     ovsvapp = networking_vsphere.ml2.ovsvapp_mech_driver:OVSvAppAgentMechanismDriver
45 46
     vmware_dvs = networking_vsphere.ml2.dvs_mechanism_driver:VMwareDVSMechanismDriver

Loading…
Cancel
Save