fb-vmware 1.6.0__py3-none-any.whl → 1.7.0__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 +1 -1
- fb_vmware/app/get_host_list.py +5 -2
- fb_vmware/app/get_network_list.py +32 -5
- fb_vmware/app/get_storage_cluster_list.py +8 -5
- fb_vmware/app/get_storage_list.py +453 -0
- fb_vmware/app/get_vm_info.py +16 -5
- fb_vmware/app/get_vm_list.py +32 -14
- fb_vmware/cluster.py +34 -2
- fb_vmware/connect.py +333 -79
- fb_vmware/datastore.py +117 -20
- fb_vmware/ds_cluster.py +85 -15
- fb_vmware/dvs.py +103 -48
- fb_vmware/host.py +32 -2
- fb_vmware/network.py +62 -3
- fb_vmware/vm.py +42 -4
- fb_vmware-1.7.0.data/data/.gitkeep +0 -0
- fb_vmware-1.7.0.data/data/share/locale/de_DE/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.7.0.data/data/share/locale/en_US/LC_MESSAGES/fb_vmware.mo +0 -0
- {fb_vmware-1.6.0.dist-info → fb_vmware-1.7.0.dist-info}/METADATA +1 -1
- fb_vmware-1.7.0.dist-info/RECORD +37 -0
- {fb_vmware-1.6.0.dist-info → fb_vmware-1.7.0.dist-info}/entry_points.txt +1 -0
- fb_vmware-1.6.0.data/data/share/locale/de_DE/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.6.0.data/data/share/locale/en_US/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.6.0.dist-info/RECORD +0 -35
- {fb_vmware-1.6.0.dist-info → fb_vmware-1.7.0.dist-info}/WHEEL +0 -0
- {fb_vmware-1.6.0.dist-info → fb_vmware-1.7.0.dist-info}/licenses/LICENSE +0 -0
fb_vmware/__init__.py
CHANGED
fb_vmware/app/get_host_list.py
CHANGED
|
@@ -29,7 +29,7 @@ from .. import __version__ as GLOBAL_VERSION
|
|
|
29
29
|
from ..errors import VSphereExpectedError
|
|
30
30
|
from ..xlate import XLATOR
|
|
31
31
|
|
|
32
|
-
__version__ = "1.
|
|
32
|
+
__version__ = "1.4.0"
|
|
33
33
|
LOG = logging.getLogger(__name__)
|
|
34
34
|
|
|
35
35
|
_ = XLATOR.gettext
|
|
@@ -251,6 +251,7 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
251
251
|
summary = {}
|
|
252
252
|
|
|
253
253
|
summary["vsphere"] = host.vsphere
|
|
254
|
+
summary["dc"] = host.dc_name
|
|
254
255
|
summary["cluster"] = host.cluster_name
|
|
255
256
|
summary["name"] = host.name
|
|
256
257
|
summary["connection_state"] = host.connection_state
|
|
@@ -279,6 +280,7 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
279
280
|
"""Print on STDOUT all information about all hosts in a human readable format."""
|
|
280
281
|
labels = {
|
|
281
282
|
"vsphere": "vSphere",
|
|
283
|
+
"dc": "DC",
|
|
282
284
|
"cluster": "Cluster",
|
|
283
285
|
"name": "Host",
|
|
284
286
|
"connection_state": _("Connect state"),
|
|
@@ -297,6 +299,7 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
297
299
|
|
|
298
300
|
label_list = (
|
|
299
301
|
"name",
|
|
302
|
+
"dc",
|
|
300
303
|
"vsphere",
|
|
301
304
|
"cluster",
|
|
302
305
|
"vendor",
|
|
@@ -384,7 +387,7 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
384
387
|
hosts = []
|
|
385
388
|
|
|
386
389
|
vsphere = self.vsphere[vsphere_name]
|
|
387
|
-
vsphere.get_datacenter()
|
|
390
|
+
# vsphere.get_datacenter()
|
|
388
391
|
|
|
389
392
|
re_name = None
|
|
390
393
|
if self.host_pattern is not None:
|
|
@@ -28,7 +28,7 @@ from ..network import GeneralNetworksDict
|
|
|
28
28
|
from ..network import VsphereNetwork
|
|
29
29
|
from ..xlate import XLATOR
|
|
30
30
|
|
|
31
|
-
__version__ = "1.
|
|
31
|
+
__version__ = "1.7.0"
|
|
32
32
|
LOG = logging.getLogger(__name__)
|
|
33
33
|
|
|
34
34
|
_ = XLATOR.gettext
|
|
@@ -117,7 +117,7 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
117
117
|
|
|
118
118
|
vsphere = self.vsphere[vsphere_name]
|
|
119
119
|
try:
|
|
120
|
-
vsphere.get_networks()
|
|
120
|
+
vsphere.get_networks(vsphere_name=vsphere_name)
|
|
121
121
|
|
|
122
122
|
except VSphereExpectedError as e:
|
|
123
123
|
LOG.error(str(e))
|
|
@@ -136,7 +136,7 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
136
136
|
LOG.debug(_("Get all network-like objects from vSphere {!r} ...").format(vsphere_name))
|
|
137
137
|
|
|
138
138
|
try:
|
|
139
|
-
vsphere.get_networks()
|
|
139
|
+
vsphere.get_networks(vsphere_name=vsphere_name)
|
|
140
140
|
except VSphereExpectedError as e:
|
|
141
141
|
LOG.error(str(e))
|
|
142
142
|
self.exit(6)
|
|
@@ -229,8 +229,13 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
229
229
|
for uuid in self.vsphere[vsphere_name].dvs.keys():
|
|
230
230
|
this_dvs = self.vsphere[vsphere_name].dvs[uuid]
|
|
231
231
|
|
|
232
|
+
dc_name = "~"
|
|
233
|
+
if this_dvs.dc_name:
|
|
234
|
+
dc_name = this_dvs.dc_name
|
|
235
|
+
|
|
232
236
|
dvs = {
|
|
233
237
|
"vsphere": vsphere_name,
|
|
238
|
+
"dc": dc_name,
|
|
234
239
|
"name": this_dvs.name,
|
|
235
240
|
"contact": get_contact(this_dvs),
|
|
236
241
|
"create_time": this_dvs.create_time.isoformat(sep=" ", timespec="seconds"),
|
|
@@ -254,6 +259,7 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
254
259
|
|
|
255
260
|
labels = {
|
|
256
261
|
"vsphere": "vSphere",
|
|
262
|
+
"dc": _("Data Center"),
|
|
257
263
|
"name": _("Name"),
|
|
258
264
|
"contact": _("Contact"),
|
|
259
265
|
"create_time": _("Creation time"),
|
|
@@ -266,6 +272,7 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
266
272
|
label_list = (
|
|
267
273
|
"name",
|
|
268
274
|
"vsphere",
|
|
275
|
+
"dc",
|
|
269
276
|
"create_time",
|
|
270
277
|
"hosts",
|
|
271
278
|
"ports",
|
|
@@ -348,10 +355,20 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
348
355
|
if this_dvpg.accessible:
|
|
349
356
|
accessible = _("Yes")
|
|
350
357
|
|
|
358
|
+
dc_name = "~"
|
|
359
|
+
if this_dvpg.dc_name:
|
|
360
|
+
dc_name = this_dvpg.dc_name
|
|
361
|
+
|
|
362
|
+
vlan_id = "~"
|
|
363
|
+
if this_dvpg.vlan_id:
|
|
364
|
+
vlan_id = this_dvpg.vlan_id
|
|
365
|
+
|
|
351
366
|
dvpg = {
|
|
352
367
|
"vsphere": vsphere_name,
|
|
368
|
+
"dc": dc_name,
|
|
353
369
|
"name": name,
|
|
354
370
|
"dvs": dvs_name,
|
|
371
|
+
"vlan_id": vlan_id,
|
|
355
372
|
"network": network,
|
|
356
373
|
"accessible": accessible,
|
|
357
374
|
"num_ports": "{:,}".format(this_dvpg.num_ports),
|
|
@@ -373,8 +390,10 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
373
390
|
|
|
374
391
|
labels = {
|
|
375
392
|
"vsphere": "vSphere",
|
|
393
|
+
"dc": "DC",
|
|
376
394
|
"name": _("Name"),
|
|
377
395
|
"dvs": "DV Switch",
|
|
396
|
+
"vlan_id": "VLAN ID",
|
|
378
397
|
"network": _("Network"),
|
|
379
398
|
"accessible": _("Accessible"),
|
|
380
399
|
"num_ports": _("Ports"),
|
|
@@ -385,7 +404,9 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
385
404
|
label_list = (
|
|
386
405
|
"name",
|
|
387
406
|
"vsphere",
|
|
407
|
+
"dc",
|
|
388
408
|
"dvs",
|
|
409
|
+
"vlan_id",
|
|
389
410
|
"network",
|
|
390
411
|
"accessible",
|
|
391
412
|
"type",
|
|
@@ -422,7 +443,7 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
422
443
|
for label in label_list:
|
|
423
444
|
if tpl != "":
|
|
424
445
|
tpl += " "
|
|
425
|
-
if label in ("num_ports",):
|
|
446
|
+
if label in ("num_ports", "vlan_id"):
|
|
426
447
|
tpl += "{{{la}:>{le}}}".format(la=label, le=str_lengths[label])
|
|
427
448
|
else:
|
|
428
449
|
tpl += "{{{la}:<{le}}}".format(la=label, le=str_lengths[label])
|
|
@@ -458,8 +479,13 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
458
479
|
if this_network.accessible:
|
|
459
480
|
accessible = _("Yes")
|
|
460
481
|
|
|
482
|
+
dc_name = "~"
|
|
483
|
+
if this_network.dc_name:
|
|
484
|
+
dc_name = this_network.dc_name
|
|
485
|
+
|
|
461
486
|
net = {
|
|
462
487
|
"vsphere": vsphere_name,
|
|
488
|
+
"dc": dc_name,
|
|
463
489
|
"name": name,
|
|
464
490
|
"network": network,
|
|
465
491
|
"accessible": accessible,
|
|
@@ -478,11 +504,12 @@ class GetNetworkListApp(BaseVmwareApplication):
|
|
|
478
504
|
|
|
479
505
|
labels = {
|
|
480
506
|
"vsphere": "vSphere",
|
|
507
|
+
"dc": _("Data Center"),
|
|
481
508
|
"name": _("Name"),
|
|
482
509
|
"network": _("Network"),
|
|
483
510
|
"accessible": _("Accessible"),
|
|
484
511
|
}
|
|
485
|
-
label_list = ("name", "vsphere", "network", "accessible")
|
|
512
|
+
label_list = ("name", "vsphere", "dc", "network", "accessible")
|
|
486
513
|
|
|
487
514
|
str_lengths = {}
|
|
488
515
|
for label in labels:
|
|
@@ -28,12 +28,11 @@ from fb_tools.xlate import format_list
|
|
|
28
28
|
from . import BaseVmwareApplication
|
|
29
29
|
from . import VmwareAppError
|
|
30
30
|
from .. import __version__ as GLOBAL_VERSION
|
|
31
|
-
# from ..ds_cluster import VsphereDsCluster
|
|
32
31
|
from ..ds_cluster import VsphereDsClusterDict
|
|
33
32
|
from ..errors import VSphereExpectedError
|
|
34
33
|
from ..xlate import XLATOR
|
|
35
34
|
|
|
36
|
-
__version__ = "1.
|
|
35
|
+
__version__ = "1.3.1"
|
|
37
36
|
LOG = logging.getLogger(__name__)
|
|
38
37
|
|
|
39
38
|
_ = XLATOR.gettext
|
|
@@ -242,6 +241,7 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
242
241
|
cluster["cluster_name"] = cluster_name
|
|
243
242
|
|
|
244
243
|
cluster["vsphere_name"] = vsphere_name
|
|
244
|
+
cluster["dc"] = cl.dc_name
|
|
245
245
|
|
|
246
246
|
cluster["capacity"] = cl.capacity_gb
|
|
247
247
|
cluster["capacity_gb"] = format_decimal(cl.capacity_gb, format="#,##0")
|
|
@@ -275,6 +275,7 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
275
275
|
self.totals = {
|
|
276
276
|
"cluster_name": _("Total"),
|
|
277
277
|
"vsphere_name": "",
|
|
278
|
+
"dc": "",
|
|
278
279
|
"is_total": True,
|
|
279
280
|
"capacity_gb": format_decimal(total_capacity, format="#,##0"),
|
|
280
281
|
"free_space_gb": format_decimal(total_free, format="#,##0"),
|
|
@@ -314,6 +315,7 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
314
315
|
labels = {
|
|
315
316
|
"cluster_name": "Cluster",
|
|
316
317
|
"vsphere_name": "vSphere",
|
|
318
|
+
"dc": _("Data Center"),
|
|
317
319
|
"capacity_gb": _("Capacity in GB"),
|
|
318
320
|
"free_space_gb": _("Free space in GB"),
|
|
319
321
|
"usage_gb": _("Calculated usage in GB"),
|
|
@@ -323,6 +325,7 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
323
325
|
label_list = (
|
|
324
326
|
"cluster_name",
|
|
325
327
|
"vsphere_name",
|
|
328
|
+
"dc",
|
|
326
329
|
"capacity_gb",
|
|
327
330
|
"usage_gb",
|
|
328
331
|
"usage_pc_out",
|
|
@@ -349,7 +352,7 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
349
352
|
for label in label_list:
|
|
350
353
|
if tpl != "":
|
|
351
354
|
tpl += " "
|
|
352
|
-
if label in ("cluster_name", "vsphere_name"):
|
|
355
|
+
if label in ("cluster_name", "vsphere_name", "dc"):
|
|
353
356
|
tpl += "{{{la}:<{le}}}".format(la=label, le=field_length[label])
|
|
354
357
|
else:
|
|
355
358
|
tpl += "{{{la}:>{le}}}".format(la=label, le=field_length[label])
|
|
@@ -383,9 +386,9 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
383
386
|
if count:
|
|
384
387
|
msg = ngettext(
|
|
385
388
|
"Found one VMware storage cluster.",
|
|
386
|
-
"Found {} VMware storage clusters."
|
|
389
|
+
"Found {} VMware storage clusters.",
|
|
387
390
|
count,
|
|
388
|
-
)
|
|
391
|
+
).format(count)
|
|
389
392
|
else:
|
|
390
393
|
msg = _("No VMware storage clusters found.")
|
|
391
394
|
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
@summary: Print a list of all datastores (Storages) in a VMware vSphere.
|
|
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 locale
|
|
14
|
+
import logging
|
|
15
|
+
import pathlib
|
|
16
|
+
import sys
|
|
17
|
+
from operator import itemgetter
|
|
18
|
+
|
|
19
|
+
# Third party modules
|
|
20
|
+
from babel.numbers import format_decimal
|
|
21
|
+
|
|
22
|
+
# from fb_tools.argparse_actions import RegexOptionAction
|
|
23
|
+
from fb_tools.common import pp
|
|
24
|
+
from fb_tools.spinner import Spinner
|
|
25
|
+
from fb_tools.xlate import format_list
|
|
26
|
+
|
|
27
|
+
# Own modules
|
|
28
|
+
from . import BaseVmwareApplication
|
|
29
|
+
from . import VmwareAppError
|
|
30
|
+
from .. import __version__ as GLOBAL_VERSION
|
|
31
|
+
from ..datastore import VsphereDatastoreDict
|
|
32
|
+
from ..errors import VSphereExpectedError
|
|
33
|
+
from ..xlate import XLATOR
|
|
34
|
+
|
|
35
|
+
__version__ = "1.0.2"
|
|
36
|
+
LOG = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
_ = XLATOR.gettext
|
|
39
|
+
ngettext = XLATOR.ngettext
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# =============================================================================
|
|
43
|
+
class GetVmStoragesAppError(VmwareAppError):
|
|
44
|
+
"""Base exception class for all exceptions in this application."""
|
|
45
|
+
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# =============================================================================
|
|
50
|
+
class GetStorageListApp(BaseVmwareApplication):
|
|
51
|
+
"""Class for the application object."""
|
|
52
|
+
|
|
53
|
+
avail_sort_keys = (
|
|
54
|
+
"ds_name",
|
|
55
|
+
"vsphere_name",
|
|
56
|
+
"dc",
|
|
57
|
+
"ecluster",
|
|
58
|
+
"capacity",
|
|
59
|
+
"free_space",
|
|
60
|
+
"usage",
|
|
61
|
+
"usage_pc",
|
|
62
|
+
)
|
|
63
|
+
default_sort_keys = ["vsphere_name", "dc", "ds_name"]
|
|
64
|
+
|
|
65
|
+
# -------------------------------------------------------------------------
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
appname=None,
|
|
69
|
+
verbose=0,
|
|
70
|
+
version=GLOBAL_VERSION,
|
|
71
|
+
base_dir=None,
|
|
72
|
+
initialized=False,
|
|
73
|
+
usage=None,
|
|
74
|
+
description=None,
|
|
75
|
+
argparse_epilog=None,
|
|
76
|
+
argparse_prefix_chars="-",
|
|
77
|
+
env_prefix=None,
|
|
78
|
+
):
|
|
79
|
+
"""Initialize a GetStorageListApp object."""
|
|
80
|
+
desc = _("Tries to get a list of all datastores in VMware vSphere and print it out.")
|
|
81
|
+
|
|
82
|
+
self.datastores = []
|
|
83
|
+
self._print_total = True
|
|
84
|
+
self._no_local = False
|
|
85
|
+
self.totals = None
|
|
86
|
+
self.sort_keys = self.default_sort_keys
|
|
87
|
+
|
|
88
|
+
super(GetStorageListApp, self).__init__(
|
|
89
|
+
appname=appname,
|
|
90
|
+
verbose=verbose,
|
|
91
|
+
version=version,
|
|
92
|
+
base_dir=base_dir,
|
|
93
|
+
description=desc,
|
|
94
|
+
initialized=False,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
self.initialized = True
|
|
98
|
+
|
|
99
|
+
# -------------------------------------------------------------------------
|
|
100
|
+
@property
|
|
101
|
+
def print_total(self):
|
|
102
|
+
"""Print out a line with the total capacity."""
|
|
103
|
+
return self._print_total
|
|
104
|
+
|
|
105
|
+
# -------------------------------------------------------------------------
|
|
106
|
+
@property
|
|
107
|
+
def no_local(self):
|
|
108
|
+
"""Don't print out local datastores on the ESX hosts."""
|
|
109
|
+
return self._no_local
|
|
110
|
+
|
|
111
|
+
# -------------------------------------------------------------------------
|
|
112
|
+
def as_dict(self, short=True):
|
|
113
|
+
"""
|
|
114
|
+
Transform the elements of the object into a dict.
|
|
115
|
+
|
|
116
|
+
@param short: don't include local properties in resulting dict.
|
|
117
|
+
@type short: bool
|
|
118
|
+
|
|
119
|
+
@return: structure as dict
|
|
120
|
+
@rtype: dict
|
|
121
|
+
"""
|
|
122
|
+
res = super(GetStorageListApp, self).as_dict(short=short)
|
|
123
|
+
res["no_local"] = self.no_local
|
|
124
|
+
res["print_total"] = self.print_total
|
|
125
|
+
|
|
126
|
+
return res
|
|
127
|
+
|
|
128
|
+
# -------------------------------------------------------------------------
|
|
129
|
+
def init_arg_parser(self):
|
|
130
|
+
"""Public available method to initiate the argument parser."""
|
|
131
|
+
super(GetStorageListApp, self).init_arg_parser()
|
|
132
|
+
|
|
133
|
+
output_options = self.arg_parser.add_argument_group(_("Output options"))
|
|
134
|
+
|
|
135
|
+
output_options.add_argument(
|
|
136
|
+
"-L",
|
|
137
|
+
"--no-local",
|
|
138
|
+
action="store_true",
|
|
139
|
+
dest="no_local",
|
|
140
|
+
help=_("Don't print local datastores on the ESX hosts."),
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
output_options.add_argument(
|
|
144
|
+
"-N",
|
|
145
|
+
"--no-totals",
|
|
146
|
+
action="store_true",
|
|
147
|
+
dest="no_totals",
|
|
148
|
+
help=_("Don't print the totals of all datastores."),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
output_options.add_argument(
|
|
152
|
+
"-S",
|
|
153
|
+
"--sort",
|
|
154
|
+
metavar="KEY",
|
|
155
|
+
nargs="+",
|
|
156
|
+
dest="sort_keys",
|
|
157
|
+
choices=self.avail_sort_keys,
|
|
158
|
+
help=_(
|
|
159
|
+
"The keys for sorting the output. Available keys are: {avail}. "
|
|
160
|
+
"The default sorting keys are: {default}."
|
|
161
|
+
).format(
|
|
162
|
+
avail=format_list(self.avail_sort_keys, do_repr=True),
|
|
163
|
+
default=format_list(self.default_sort_keys, do_repr=True),
|
|
164
|
+
),
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# -------------------------------------------------------------------------
|
|
168
|
+
def perform_arg_parser(self):
|
|
169
|
+
"""Evaluate command line parameters."""
|
|
170
|
+
super(GetStorageListApp, self).perform_arg_parser()
|
|
171
|
+
|
|
172
|
+
if self.args.sort_keys:
|
|
173
|
+
self.sort_keys = self.args.sort_keys
|
|
174
|
+
|
|
175
|
+
if getattr(self.args, "no_totals", False):
|
|
176
|
+
self._print_total = False
|
|
177
|
+
|
|
178
|
+
if getattr(self.args, "no_local", False):
|
|
179
|
+
self._no_local = True
|
|
180
|
+
|
|
181
|
+
# -------------------------------------------------------------------------
|
|
182
|
+
def _run(self):
|
|
183
|
+
|
|
184
|
+
LOG.debug(_("Starting {a!r}, version {v!r} ...").format(a=self.appname, v=self.version))
|
|
185
|
+
|
|
186
|
+
ret = 0
|
|
187
|
+
try:
|
|
188
|
+
ret = self.get_all_datastores()
|
|
189
|
+
finally:
|
|
190
|
+
self.cleaning_up()
|
|
191
|
+
|
|
192
|
+
self.exit(ret)
|
|
193
|
+
|
|
194
|
+
# -------------------------------------------------------------------------
|
|
195
|
+
def get_datastores(self, vsphere_name):
|
|
196
|
+
"""Get all datastore clusters in a VMware vSphere."""
|
|
197
|
+
datastores = []
|
|
198
|
+
|
|
199
|
+
vsphere = self.vsphere[vsphere_name]
|
|
200
|
+
no_local_ds = False
|
|
201
|
+
if self.no_local:
|
|
202
|
+
no_local_ds = True
|
|
203
|
+
try:
|
|
204
|
+
vsphere.get_datastores(no_local_ds=no_local_ds)
|
|
205
|
+
except VSphereExpectedError as e:
|
|
206
|
+
LOG.error(str(e))
|
|
207
|
+
self.exit(6)
|
|
208
|
+
|
|
209
|
+
for datastore in vsphere.datastores:
|
|
210
|
+
datastores.append(vsphere.datastores[datastore])
|
|
211
|
+
|
|
212
|
+
return datastores
|
|
213
|
+
|
|
214
|
+
# -------------------------------------------------------------------------
|
|
215
|
+
def get_all_datastores(self):
|
|
216
|
+
"""Collect all datastores."""
|
|
217
|
+
ret = 0
|
|
218
|
+
all_datastores = {}
|
|
219
|
+
|
|
220
|
+
# ----------
|
|
221
|
+
def _get_all_datastores():
|
|
222
|
+
|
|
223
|
+
for vsphere_name in self.vsphere:
|
|
224
|
+
if vsphere_name not in all_datastores:
|
|
225
|
+
all_datastores[vsphere_name] = VsphereDatastoreDict()
|
|
226
|
+
for datastore in self.get_datastores(vsphere_name):
|
|
227
|
+
all_datastores[vsphere_name].append(datastore)
|
|
228
|
+
|
|
229
|
+
if self.verbose or self.quiet:
|
|
230
|
+
_get_all_datastores()
|
|
231
|
+
|
|
232
|
+
else:
|
|
233
|
+
spin_prompt = _("Getting all vSphere datastores ...")
|
|
234
|
+
spinner_name = self.get_random_spinner_name()
|
|
235
|
+
with Spinner(spin_prompt, spinner_name):
|
|
236
|
+
_get_all_datastores()
|
|
237
|
+
sys.stdout.write(" " * len(spin_prompt))
|
|
238
|
+
sys.stdout.write("\r")
|
|
239
|
+
sys.stdout.flush()
|
|
240
|
+
|
|
241
|
+
if self.verbose > 2:
|
|
242
|
+
LOG.debug(_("Found datastores:") + "\n" + pp(all_datastores))
|
|
243
|
+
|
|
244
|
+
self.print_datastores(all_datastores)
|
|
245
|
+
|
|
246
|
+
return ret
|
|
247
|
+
|
|
248
|
+
# -------------------------------------------------------------------------
|
|
249
|
+
def _get_datastore_list(self, datastores):
|
|
250
|
+
|
|
251
|
+
datastore_list = []
|
|
252
|
+
|
|
253
|
+
total_capacity = 0.0
|
|
254
|
+
total_free = 0.0
|
|
255
|
+
|
|
256
|
+
for vsphere_name in datastores.keys():
|
|
257
|
+
for ds_name in datastores[vsphere_name].keys():
|
|
258
|
+
|
|
259
|
+
ds = datastores[vsphere_name][ds_name]
|
|
260
|
+
datastore = {}
|
|
261
|
+
datastore["is_total"] = False
|
|
262
|
+
|
|
263
|
+
datastore["ds_name"] = ds_name
|
|
264
|
+
|
|
265
|
+
datastore["vsphere_name"] = vsphere_name
|
|
266
|
+
datastore["dc"] = ds.dc_name
|
|
267
|
+
datastore["cluster"] = "~"
|
|
268
|
+
if ds.cluster:
|
|
269
|
+
datastore["cluster"] = ds.cluster
|
|
270
|
+
|
|
271
|
+
datastore["capacity"] = ds.capacity_gb
|
|
272
|
+
datastore["capacity_gb"] = format_decimal(ds.capacity_gb, format="#,##0")
|
|
273
|
+
total_capacity += ds.capacity_gb
|
|
274
|
+
|
|
275
|
+
datastore["free_space"] = ds.free_space_gb
|
|
276
|
+
datastore["free_space_gb"] = format_decimal(ds.free_space_gb, format="#,##0")
|
|
277
|
+
total_free += ds.free_space_gb
|
|
278
|
+
|
|
279
|
+
used = ds.capacity_gb - ds.free_space_gb
|
|
280
|
+
datastore["usage"] = used
|
|
281
|
+
datastore["usage_gb"] = format_decimal(used, format="#,##0")
|
|
282
|
+
|
|
283
|
+
if ds.capacity_gb:
|
|
284
|
+
usage_pc = used / ds.capacity_gb
|
|
285
|
+
datastore["usage_pc"] = usage_pc
|
|
286
|
+
datastore["usage_pc_out"] = format_decimal(usage_pc, format="0.0 %")
|
|
287
|
+
else:
|
|
288
|
+
datastore["usage_pc_out"] = "- %"
|
|
289
|
+
|
|
290
|
+
datastore_list.append(datastore)
|
|
291
|
+
|
|
292
|
+
if self.print_total:
|
|
293
|
+
total_used = total_capacity - total_free
|
|
294
|
+
total_used_pc = None
|
|
295
|
+
total_used_pc_out = "- %"
|
|
296
|
+
if total_capacity:
|
|
297
|
+
total_used_pc = total_used / total_capacity
|
|
298
|
+
total_used_pc_out = format_decimal(total_used_pc, format="0.0 %")
|
|
299
|
+
|
|
300
|
+
self.totals = {
|
|
301
|
+
"ds_name": _("Total"),
|
|
302
|
+
"vsphere_name": "",
|
|
303
|
+
"dc": "",
|
|
304
|
+
"cluster": "",
|
|
305
|
+
"is_total": True,
|
|
306
|
+
"capacity_gb": format_decimal(total_capacity, format="#,##0"),
|
|
307
|
+
"free_space_gb": format_decimal(total_free, format="#,##0"),
|
|
308
|
+
"usage_gb": format_decimal(total_used, format="#,##0"),
|
|
309
|
+
"usage_pc_out": total_used_pc_out,
|
|
310
|
+
}
|
|
311
|
+
if not self.quiet:
|
|
312
|
+
self.totals["ds_name"] += ":"
|
|
313
|
+
|
|
314
|
+
return datastore_list
|
|
315
|
+
|
|
316
|
+
# -------------------------------------------------------------------------
|
|
317
|
+
def _get_ds_fields_len(self, datastore_list, labels):
|
|
318
|
+
|
|
319
|
+
field_length = {}
|
|
320
|
+
|
|
321
|
+
for label in labels.keys():
|
|
322
|
+
field_length[label] = len(labels[label])
|
|
323
|
+
|
|
324
|
+
for ds in datastore_list:
|
|
325
|
+
for label in labels.keys():
|
|
326
|
+
field = ds[label]
|
|
327
|
+
if len(field) > field_length[label]:
|
|
328
|
+
field_length[label] = len(field)
|
|
329
|
+
|
|
330
|
+
if self.totals:
|
|
331
|
+
for label in labels.keys():
|
|
332
|
+
field = self.totals[label]
|
|
333
|
+
if len(field) > field_length[label]:
|
|
334
|
+
field_length[label] = len(field)
|
|
335
|
+
|
|
336
|
+
return field_length
|
|
337
|
+
|
|
338
|
+
# -------------------------------------------------------------------------
|
|
339
|
+
def print_datastores(self, all_datastores):
|
|
340
|
+
"""Print on STDOUT all information about all datastore clusters."""
|
|
341
|
+
labels = {
|
|
342
|
+
"ds_name": _("Datastore"),
|
|
343
|
+
"vsphere_name": "vSphere",
|
|
344
|
+
"dc": _("Data Center"),
|
|
345
|
+
"cluster": _("Cluster"),
|
|
346
|
+
"capacity_gb": _("Capacity in GB"),
|
|
347
|
+
"free_space_gb": _("Free space in GB"),
|
|
348
|
+
"usage_gb": _("Calculated usage in GB"),
|
|
349
|
+
"usage_pc_out": _("Usage in percent"),
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
label_list = (
|
|
353
|
+
"ds_name",
|
|
354
|
+
"vsphere_name",
|
|
355
|
+
"dc",
|
|
356
|
+
"cluster",
|
|
357
|
+
"capacity_gb",
|
|
358
|
+
"usage_gb",
|
|
359
|
+
"usage_pc_out",
|
|
360
|
+
"free_space_gb",
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
datastore_list = self._get_datastore_list(all_datastores)
|
|
364
|
+
field_length = self._get_ds_fields_len(datastore_list, labels)
|
|
365
|
+
|
|
366
|
+
max_len = 0
|
|
367
|
+
count = len(datastore_list)
|
|
368
|
+
|
|
369
|
+
for label in labels.keys():
|
|
370
|
+
if max_len:
|
|
371
|
+
max_len += 2
|
|
372
|
+
max_len += field_length[label]
|
|
373
|
+
|
|
374
|
+
if self.verbose > 2:
|
|
375
|
+
LOG.debug("Label length:\n" + pp(field_length))
|
|
376
|
+
LOG.debug("Max line length: {} chars".format(max_len))
|
|
377
|
+
LOG.debug("Datastore clusters:\n" + pp(datastore_list))
|
|
378
|
+
|
|
379
|
+
tpl = ""
|
|
380
|
+
for label in label_list:
|
|
381
|
+
if tpl != "":
|
|
382
|
+
tpl += " "
|
|
383
|
+
if label in ("ds_name", "vsphere_name", "dc", "cluster"):
|
|
384
|
+
tpl += "{{{la}:<{le}}}".format(la=label, le=field_length[label])
|
|
385
|
+
else:
|
|
386
|
+
tpl += "{{{la}:>{le}}}".format(la=label, le=field_length[label])
|
|
387
|
+
if self.verbose > 1:
|
|
388
|
+
LOG.debug(_("Line template: {}").format(tpl))
|
|
389
|
+
|
|
390
|
+
if self.sort_keys:
|
|
391
|
+
LOG.debug("Sorting keys: " + pp(self.sort_keys))
|
|
392
|
+
self.sort_keys.reverse()
|
|
393
|
+
for key in self.sort_keys:
|
|
394
|
+
if key in ("ds_name", "vsphere_name", "dc", "cluster"):
|
|
395
|
+
datastore_list.sort(key=itemgetter(key))
|
|
396
|
+
else:
|
|
397
|
+
datastore_list.sort(key=itemgetter(key), reverse=True)
|
|
398
|
+
|
|
399
|
+
if not self.quiet:
|
|
400
|
+
print()
|
|
401
|
+
print(tpl.format(**labels))
|
|
402
|
+
print("-" * max_len)
|
|
403
|
+
|
|
404
|
+
for datastore in datastore_list:
|
|
405
|
+
print(tpl.format(**datastore))
|
|
406
|
+
|
|
407
|
+
if self.totals:
|
|
408
|
+
if not self.quiet:
|
|
409
|
+
print("-" * max_len)
|
|
410
|
+
print(tpl.format(**self.totals))
|
|
411
|
+
|
|
412
|
+
if not self.quiet:
|
|
413
|
+
print()
|
|
414
|
+
if count:
|
|
415
|
+
msg = ngettext(
|
|
416
|
+
"Found one VMware datastore.",
|
|
417
|
+
"Found {} VMware datastores.",
|
|
418
|
+
count,
|
|
419
|
+
).format(count)
|
|
420
|
+
else:
|
|
421
|
+
msg = _("No VMware datastores found.")
|
|
422
|
+
|
|
423
|
+
print(msg)
|
|
424
|
+
print()
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
# =============================================================================
|
|
428
|
+
def main():
|
|
429
|
+
"""Entrypoint for get-vsphere-storage-list."""
|
|
430
|
+
my_path = pathlib.Path(__file__)
|
|
431
|
+
appname = my_path.name
|
|
432
|
+
|
|
433
|
+
locale.setlocale(locale.LC_ALL, "")
|
|
434
|
+
|
|
435
|
+
app = GetStorageListApp(appname=appname)
|
|
436
|
+
app.initialized = True
|
|
437
|
+
|
|
438
|
+
if app.verbose > 2:
|
|
439
|
+
print(_("{c}-Object:\n{a}").format(c=app.__class__.__name__, a=app), file=sys.stderr)
|
|
440
|
+
|
|
441
|
+
app()
|
|
442
|
+
|
|
443
|
+
return 0
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
# =============================================================================
|
|
447
|
+
if __name__ == "__main__":
|
|
448
|
+
|
|
449
|
+
pass
|
|
450
|
+
|
|
451
|
+
# =============================================================================
|
|
452
|
+
|
|
453
|
+
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list
|