fb-vmware 1.4.1__py3-none-any.whl → 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fb_vmware/__init__.py CHANGED
@@ -35,6 +35,8 @@ from .dc import VsphereDatacenter
35
35
  from .disk import VsphereDisk, VsphereDiskList
36
36
  from .ds_cluster import VsphereDsCluster
37
37
  from .ds_cluster import VsphereDsClusterDict
38
+ from .dvs import VsphereDVS
39
+ from .dvs import VsphereDvPortGroup
38
40
  from .ether import VsphereEthernetcard
39
41
  from .ether import VsphereEthernetcardList
40
42
  from .host import VsphereHost
@@ -43,16 +45,18 @@ from .host import VsphereHostList
43
45
  from .host_port_group import VsphereHostPortgroup
44
46
  from .host_port_group import VsphereHostPortgroupList
45
47
  from .iface import VsphereVmInterface
48
+ from .network import GeneralNetworksDict
46
49
  from .network import VsphereNetwork
47
50
  from .network import VsphereNetworkDict
48
51
  from .obj import DEFAULT_OBJ_STATUS
49
52
  from .obj import VsphereObject
53
+ from .typed_dict import TypedDict
50
54
  from .vm import VsphereVm
51
55
  from .vm import VsphereVmList
52
56
  from .xlate import XLATOR
53
57
 
54
58
 
55
- __version__ = '1.4.1'
59
+ __version__ = '1.5.1'
56
60
 
57
61
  LOG = logging.getLogger(__name__)
58
62
 
@@ -0,0 +1,509 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ @summary: The module for the application object of the get-vsphere-network-list application.
5
+
6
+ @author: Frank Brehm
7
+ @contact: frank@brehm-online.com
8
+ @copyright: © 2025 by Frank Brehm, Berlin
9
+ """
10
+ from __future__ import absolute_import, print_function
11
+
12
+ # Standard modules
13
+ import logging
14
+ import sys
15
+ from operator import itemgetter
16
+
17
+ # from fb_tools.argparse_actions import RegexOptionAction
18
+ from fb_tools.common import pp
19
+ from fb_tools.spinner import Spinner
20
+
21
+ # Own modules
22
+ from . import BaseVmwareApplication, VmwareAppError
23
+ from .. import __version__ as GLOBAL_VERSION
24
+ from ..errors import VSphereExpectedError
25
+ from ..network import GeneralNetworksDict
26
+ from ..network import VsphereNetwork
27
+ from ..xlate import XLATOR
28
+
29
+ __version__ = '1.5.2'
30
+ LOG = logging.getLogger(__name__)
31
+
32
+ _ = XLATOR.gettext
33
+ ngettext = XLATOR.ngettext
34
+
35
+ # =============================================================================
36
+ class GetVmNetworkAppError(VmwareAppError):
37
+ """Base exception class for all exceptions in this application."""
38
+
39
+ pass
40
+
41
+
42
+ # =============================================================================
43
+ class GetNetworkListApp(BaseVmwareApplication):
44
+ """Class for the application object."""
45
+
46
+ # -------------------------------------------------------------------------
47
+ def __init__(
48
+ self, appname=None, verbose=0, version=GLOBAL_VERSION, base_dir=None,
49
+ initialized=False, usage=None, description=None,
50
+ argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None):
51
+ """Initialize a GetNetworkListApp object."""
52
+ desc = _(
53
+ 'Tries to get a list of all networks in '
54
+ 'VMWare VSphere and print it out.')
55
+
56
+ self.all_dvpgs = GeneralNetworksDict()
57
+ self.all_networks = GeneralNetworksDict()
58
+
59
+ super(GetNetworkListApp, self).__init__(
60
+ appname=appname, verbose=verbose, version=version, base_dir=base_dir,
61
+ description=desc, initialized=False,
62
+ )
63
+
64
+ self.initialized = True
65
+
66
+ # -------------------------------------------------------------------------
67
+ def as_dict(self, short=True):
68
+ """
69
+ Transform the elements of the object into a dict.
70
+
71
+ @param short: don't include local properties in resulting dict.
72
+ @type short: bool
73
+
74
+ @return: structure as dict
75
+ @rtype: dict
76
+ """
77
+ res = super(GetNetworkListApp, self).as_dict(short=short)
78
+
79
+ return res
80
+
81
+ # -------------------------------------------------------------------------
82
+ def _run(self):
83
+
84
+ LOG.debug(_('Starting {a!r}, version {v!r} ...').format(
85
+ a=self.appname, v=self.version))
86
+
87
+ VsphereNetwork.warn_unassigned_net = False
88
+
89
+ ret = 0
90
+ try:
91
+ ret = self.get_all_networks()
92
+ self.print_virtual_switches()
93
+ self.print_dv_portgroups()
94
+ self.print_networks()
95
+ finally:
96
+ self.cleaning_up()
97
+
98
+ self.exit(ret)
99
+
100
+ # -------------------------------------------------------------------------
101
+ def get_networks(self, vsphere_name):
102
+ """Get all networks in a VMWare VSPhere."""
103
+ networks = []
104
+
105
+ vsphere = self.vsphere[vsphere_name]
106
+ try:
107
+ vsphere.get_networks()
108
+
109
+ except VSphereExpectedError as e:
110
+ LOG.error(str(e))
111
+ self.exit(6)
112
+
113
+ for network in vsphere.networks:
114
+ networks.append(vsphere.networks[network])
115
+
116
+ return networks
117
+
118
+ # -------------------------------------------------------------------------
119
+ def _get_all_networks(self):
120
+
121
+ for vsphere_name in self.vsphere:
122
+ vsphere = self.vsphere[vsphere_name]
123
+ LOG.debug(_('Get all network-like objects from VSPhere {!r} ...').format(vsphere_name))
124
+
125
+ try:
126
+ vsphere.get_networks()
127
+ except VSphereExpectedError as e:
128
+ LOG.error(str(e))
129
+ self.exit(6)
130
+
131
+ self.all_dvpgs[vsphere_name] = vsphere.dv_portgroups
132
+ self.all_networks[vsphere_name] = vsphere.networks
133
+
134
+ # -------------------------------------------------------------------------
135
+ def get_all_networks(self):
136
+ """Collect all networks."""
137
+ ret = 0
138
+
139
+ if self.verbose or self.quiet:
140
+ self._get_all_networks()
141
+
142
+ else:
143
+ spin_prompt = _('Getting all VSPhere networks') + ' '
144
+ spinner_name = self.get_random_spinner_name()
145
+ with Spinner(spin_prompt, spinner_name):
146
+ self._get_all_networks()
147
+ sys.stdout.write(' ' * len(spin_prompt))
148
+ sys.stdout.write('\r')
149
+ sys.stdout.flush()
150
+
151
+ if self.verbose > 2:
152
+ dvs = {}
153
+ for vsphere_name in self.vsphere:
154
+ dvs[vsphere_name] = {}
155
+ for uuid in self.vsphere[vsphere_name].dvs.keys():
156
+ dvs[vsphere_name][uuid] = self.vsphere[vsphere_name].dvs[uuid].as_dict()
157
+
158
+ msg = _('Found Distributed Virtual Switches:') + '\n' + pp(dvs)
159
+ LOG.debug(msg)
160
+
161
+ if self.verbose > 2:
162
+ networks = {}
163
+ dv_port_groups = {}
164
+ if self.verbose > 3:
165
+ dv_port_groups = self.all_dvpgs.as_dict()
166
+ networks = self.all_networks.as_dict()
167
+ else:
168
+ dv_port_group_lists = self.all_dvpgs.as_lists()
169
+ networks_lists = self.all_networks.as_lists()
170
+ for vsphere_name in self.vsphere:
171
+ dv_port_groups[vsphere_name] = []
172
+ networks[vsphere_name] = []
173
+ if len(dv_port_group_lists[vsphere_name]):
174
+ dv_port_groups[vsphere_name] = [dv_port_group_lists[vsphere_name][0]]
175
+ if len(networks_lists[vsphere_name]):
176
+ networks[vsphere_name] = [networks_lists[vsphere_name][0]]
177
+
178
+ msg = _('Found Distributed Virtual Portgroups:') + pp(dv_port_groups)
179
+ LOG.debug(msg)
180
+ msg = _('Found Virtual Networks:') + pp(networks)
181
+ LOG.debug(msg)
182
+
183
+ return ret
184
+
185
+ # -------------------------------------------------------------------------
186
+ def print_virtual_switches(self):
187
+ """Print on STDOUT all information about Distributed Virtual Switches."""
188
+ all_dvs = []
189
+
190
+ print()
191
+ title = _('Distributed Virtual Switches')
192
+ print(self.colored(title, 'cyan'))
193
+ print(self.colored('=' * len(title), 'cyan'))
194
+
195
+ # -----------------------------
196
+ def get_contact(dvs):
197
+ """Generate and return a contact string for this DVS."""
198
+ contact_name = None
199
+ contact_info = None
200
+ contact = '~'
201
+ if dvs.contact_name is not None:
202
+ contact_name = dvs.contact_name.strip()
203
+ if dvs.contact_info is not None:
204
+ contact_info = dvs.contact_info.strip()
205
+ if contact_name:
206
+ if contact_info:
207
+ contact = '{n} ({i})'.format(n=contact_name, i=contact_info)
208
+ else:
209
+ contact = contact_name
210
+ elif contact_info:
211
+ contact = contact_info
212
+
213
+ return contact
214
+
215
+ for vsphere_name in self.vsphere:
216
+ for uuid in self.vsphere[vsphere_name].dvs.keys():
217
+ this_dvs = self.vsphere[vsphere_name].dvs[uuid]
218
+
219
+ dvs = {
220
+ 'vsphere': vsphere_name,
221
+ 'name': this_dvs.name,
222
+ 'contact': get_contact(this_dvs),
223
+ 'create_time': this_dvs.create_time.isoformat(sep=' ', timespec='seconds'),
224
+ 'description': this_dvs.description,
225
+ 'hosts': '{:,}'.format(this_dvs.num_hosts),
226
+ 'ports': '{:,}'.format(this_dvs.num_ports),
227
+ 'standalone_ports': '{:,}'.format(this_dvs.num_standalone_ports),
228
+ 'ratio_reservation': '{:d} %'.format(this_dvs.pnic_cap_ratio_reservation),
229
+ }
230
+ all_dvs.append(dvs)
231
+
232
+ if len(all_dvs):
233
+ self._print_virtual_switches(all_dvs)
234
+ return
235
+
236
+ print()
237
+ print(_('No Distributed Virtual Switches found.'))
238
+
239
+ # -------------------------------------------------------------------------
240
+ def _print_virtual_switches(self, all_dvs):
241
+
242
+ labels = {
243
+ 'vsphere': 'VSPhere',
244
+ 'name': _('Name'),
245
+ 'contact': _('Contact'),
246
+ 'create_time': _('Creation time'),
247
+ 'description': _('Description'),
248
+ 'hosts': _('Hosts'),
249
+ 'ports': _('Ports'),
250
+ 'standalone_ports': _('Standalone Ports'),
251
+ 'ratio_reservation': _('Ratio reservation'),
252
+ }
253
+ label_list = (
254
+ 'name', 'vsphere', 'create_time', 'hosts', 'ports', 'standalone_ports',
255
+ 'ratio_reservation', 'contact', 'description',
256
+ )
257
+
258
+ str_lengths = {}
259
+ for label in labels:
260
+ str_lengths[label] = len(labels[label])
261
+
262
+ max_len = 0
263
+ count = 0
264
+ for dvs in all_dvs:
265
+ for label in labels.keys():
266
+ val = dvs[label]
267
+ if val is None:
268
+ val = '-'
269
+ dvs[label] = val
270
+ if len(val) > str_lengths[label]:
271
+ str_lengths[label] = len(val)
272
+
273
+ for label in labels.keys():
274
+ if max_len:
275
+ max_len += 2
276
+ max_len += str_lengths[label]
277
+
278
+ if self.verbose > 1:
279
+ LOG.debug('Label length:\n' + pp(str_lengths))
280
+ LOG.debug('Max line length: {} chars'.format(max_len))
281
+
282
+ tpl = ''
283
+ for label in label_list:
284
+ if tpl != '':
285
+ tpl += ' '
286
+ if label in ('hosts', 'ports', 'standalone_ports', 'ratio_reservation'):
287
+ tpl += '{{{la}:>{le}}}'.format(la=label, le=str_lengths[label])
288
+ else:
289
+ tpl += '{{{la}:<{le}}}'.format(la=label, le=str_lengths[label])
290
+ if self.verbose > 1:
291
+ LOG.debug(_('Line template: {}').format(tpl))
292
+
293
+ if not self.quiet:
294
+ print()
295
+ print(tpl.format(**labels))
296
+ print('-' * max_len)
297
+
298
+ sort_keys = ['vsphere', 'name']
299
+ all_dvs.sort(key=itemgetter(*sort_keys))
300
+ for dvs in all_dvs:
301
+ count += 1
302
+ print(tpl.format(**dvs))
303
+
304
+ # -------------------------------------------------------------------------
305
+ def print_dv_portgroups(self):
306
+ """Print on STDOUT all information about Distributed Virtual Port Groups."""
307
+ all_dvpgs = []
308
+
309
+ print()
310
+ title = _('Distributed Virtual Port Groups')
311
+ print(self.colored(title, 'cyan'))
312
+ print(self.colored('=' * len(title), 'cyan'))
313
+
314
+ for vsphere_name in self.vsphere:
315
+ for name in self.vsphere[vsphere_name].dv_portgroups.keys():
316
+ this_dvpg = self.vsphere[vsphere_name].dv_portgroups[name]
317
+ dvs_name = '~'
318
+ dvs_uuid = this_dvpg.dvs_uuid
319
+ if dvs_uuid in self.vsphere[vsphere_name].dvs:
320
+ dvs_name = self.vsphere[vsphere_name].dvs[dvs_uuid].name
321
+ network = '~'
322
+ if this_dvpg.network:
323
+ network = str(this_dvpg.network)
324
+ uplink = _('No')
325
+ if this_dvpg.uplink:
326
+ uplink = _('Yes')
327
+ accessible = 'No'
328
+ if this_dvpg.accessible:
329
+ accessible = _('Yes')
330
+
331
+ dvpg = {
332
+ 'vsphere': vsphere_name,
333
+ 'name': name,
334
+ 'dvs': dvs_name,
335
+ 'network': network,
336
+ 'accessible': accessible,
337
+ 'num_ports': '{:,}'.format(this_dvpg.num_ports),
338
+ 'type': this_dvpg.pg_type,
339
+ 'uplink': uplink,
340
+ 'description': this_dvpg.description,
341
+ }
342
+ all_dvpgs.append(dvpg)
343
+
344
+ if len(all_dvpgs):
345
+ self._print_dv_portgroups(all_dvpgs)
346
+ return
347
+
348
+ print()
349
+ print(_('No Distributed Virtual Port Groups found.'))
350
+
351
+ # -------------------------------------------------------------------------
352
+ def _print_dv_portgroups(self, all_dvpgs):
353
+
354
+ labels = {
355
+ 'vsphere': 'VSPhere',
356
+ 'name': _('Name'),
357
+ 'dvs': 'DV Switch',
358
+ 'network': _('Network'),
359
+ 'accessible': _('Accessible'),
360
+ 'num_ports': _('Ports'),
361
+ 'type': _('Type'),
362
+ 'uplink': _('Uplink'),
363
+ 'description': _('Description'),
364
+ }
365
+ label_list = (
366
+ 'name', 'vsphere', 'dvs', 'network', 'accessible', 'type',
367
+ 'num_ports', 'uplink', 'description'
368
+ )
369
+
370
+ str_lengths = {}
371
+ for label in labels:
372
+ str_lengths[label] = len(labels[label])
373
+
374
+ max_len = 0
375
+ count = 0
376
+ for dvpg in all_dvpgs:
377
+ for label in labels.keys():
378
+ val = dvpg[label]
379
+ if val is None:
380
+ val = '-'
381
+ dvpg[label] = val
382
+ if len(val) > str_lengths[label]:
383
+ str_lengths[label] = len(val)
384
+
385
+ for label in labels.keys():
386
+ if max_len:
387
+ max_len += 2
388
+ max_len += str_lengths[label]
389
+
390
+ if self.verbose > 1:
391
+ LOG.debug('Label length:\n' + pp(str_lengths))
392
+ LOG.debug('Max line length: {} chars'.format(max_len))
393
+
394
+ tpl = ''
395
+ for label in label_list:
396
+ if tpl != '':
397
+ tpl += ' '
398
+ if label in ('num_ports',):
399
+ tpl += '{{{la}:>{le}}}'.format(la=label, le=str_lengths[label])
400
+ else:
401
+ tpl += '{{{la}:<{le}}}'.format(la=label, le=str_lengths[label])
402
+ if self.verbose > 1:
403
+ LOG.debug(_('Line template: {}').format(tpl))
404
+
405
+ if not self.quiet:
406
+ print()
407
+ print(tpl.format(**labels))
408
+ print('-' * max_len)
409
+
410
+ for dvpg in all_dvpgs:
411
+ count += 1
412
+ print(tpl.format(**dvpg))
413
+
414
+ # -------------------------------------------------------------------------
415
+ def print_networks(self):
416
+ """Print on STDOUT all information about Virtual Networks."""
417
+ all_networks = []
418
+
419
+ print()
420
+ title = _('Virtual Networks')
421
+ print(self.colored(title, 'cyan'))
422
+ print(self.colored('=' * len(title), 'cyan'))
423
+
424
+ for vsphere_name in self.vsphere:
425
+ for name in self.vsphere[vsphere_name].networks.keys():
426
+ this_network = self.vsphere[vsphere_name].networks[name]
427
+ network = '~'
428
+ if this_network.network:
429
+ network = str(this_network.network)
430
+ accessible = 'No'
431
+ if this_network.accessible:
432
+ accessible = _('Yes')
433
+
434
+ net = {
435
+ 'vsphere': vsphere_name,
436
+ 'name': name,
437
+ 'network': network,
438
+ 'accessible': accessible,
439
+ }
440
+ all_networks.append(net)
441
+
442
+ if len(all_networks):
443
+ self._print_networks(all_networks)
444
+ return
445
+
446
+ print()
447
+ print(_('No Virtual Networks found.'))
448
+
449
+ # -------------------------------------------------------------------------
450
+ def _print_networks(self, all_networks):
451
+
452
+ labels = {
453
+ 'vsphere': 'VSPhere',
454
+ 'name': _('Name'),
455
+ 'network': _('Network'),
456
+ 'accessible': _('Accessible'),
457
+ }
458
+ label_list = ('name', 'vsphere', 'network', 'accessible')
459
+
460
+ str_lengths = {}
461
+ for label in labels:
462
+ str_lengths[label] = len(labels[label])
463
+
464
+ max_len = 0
465
+ count = 0
466
+ for net in all_networks:
467
+ for label in labels.keys():
468
+ val = net[label]
469
+ if val is None:
470
+ val = '-'
471
+ net[label] = val
472
+ if len(val) > str_lengths[label]:
473
+ str_lengths[label] = len(val)
474
+
475
+ for label in labels.keys():
476
+ if max_len:
477
+ max_len += 2
478
+ max_len += str_lengths[label]
479
+
480
+ if self.verbose > 1:
481
+ LOG.debug('Label length:\n' + pp(str_lengths))
482
+ LOG.debug('Max line length: {} chars'.format(max_len))
483
+
484
+ tpl = ''
485
+ for label in label_list:
486
+ if tpl != '':
487
+ tpl += ' '
488
+ tpl += '{{{la}:<{le}}}'.format(la=label, le=str_lengths[label])
489
+ if self.verbose > 1:
490
+ LOG.debug(_('Line template: {}').format(tpl))
491
+
492
+ if not self.quiet:
493
+ print()
494
+ print(tpl.format(**labels))
495
+ print('-' * max_len)
496
+
497
+ for net in all_networks:
498
+ count += 1
499
+ print(tpl.format(**net))
500
+
501
+
502
+ # =============================================================================
503
+ if __name__ == '__main__':
504
+
505
+ pass
506
+
507
+ # =============================================================================
508
+
509
+ # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list