fb-vmware 1.7.1__py3-none-any.whl → 1.8.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 +1 -1
- fb_vmware/app/__init__.py +285 -6
- fb_vmware/app/get_host_list.py +115 -100
- fb_vmware/app/get_network_list.py +176 -218
- fb_vmware/app/get_rpool_list.py +386 -0
- fb_vmware/app/get_storage_cluster_info.py +303 -0
- fb_vmware/app/get_storage_cluster_list.py +100 -107
- fb_vmware/app/get_storage_list.py +145 -112
- fb_vmware/app/get_vm_info.py +79 -17
- fb_vmware/app/get_vm_list.py +169 -95
- fb_vmware/app/search_storage.py +470 -0
- fb_vmware/argparse_actions.py +78 -0
- fb_vmware/base.py +28 -1
- fb_vmware/cluster.py +99 -7
- fb_vmware/connect.py +450 -20
- fb_vmware/datastore.py +195 -6
- fb_vmware/dc.py +19 -1
- fb_vmware/ds_cluster.py +215 -2
- fb_vmware/dvs.py +37 -1
- fb_vmware/errors.py +31 -10
- fb_vmware/host.py +40 -2
- fb_vmware/host_port_group.py +1 -2
- fb_vmware/network.py +17 -1
- fb_vmware/obj.py +30 -1
- fb_vmware/vm.py +19 -1
- fb_vmware/xlate.py +8 -13
- fb_vmware-1.8.1.data/data/share/locale/de/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.8.1.data/data/share/locale/en/LC_MESSAGES/fb_vmware.mo +0 -0
- {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/METADATA +2 -1
- fb_vmware-1.8.1.dist-info/RECORD +40 -0
- {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/entry_points.txt +3 -0
- fb_vmware-1.7.1.data/data/share/locale/de_DE/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.7.1.data/data/share/locale/en_US/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.7.1.dist-info/RECORD +0 -36
- {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/WHEEL +0 -0
- {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -24,6 +24,10 @@ from fb_tools.common import pp
|
|
|
24
24
|
from fb_tools.spinner import Spinner
|
|
25
25
|
from fb_tools.xlate import format_list
|
|
26
26
|
|
|
27
|
+
from rich import box
|
|
28
|
+
from rich.table import Table
|
|
29
|
+
from rich.text import Text
|
|
30
|
+
|
|
27
31
|
# Own modules
|
|
28
32
|
from . import BaseVmwareApplication
|
|
29
33
|
from . import VmwareAppError
|
|
@@ -32,7 +36,7 @@ from ..ds_cluster import VsphereDsClusterDict
|
|
|
32
36
|
from ..errors import VSphereExpectedError
|
|
33
37
|
from ..xlate import XLATOR
|
|
34
38
|
|
|
35
|
-
__version__ = "1.
|
|
39
|
+
__version__ = "1.5.0"
|
|
36
40
|
LOG = logging.getLogger(__name__)
|
|
37
41
|
|
|
38
42
|
_ = XLATOR.gettext
|
|
@@ -60,6 +64,8 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
60
64
|
)
|
|
61
65
|
default_sort_keys = ["vsphere_name", "cluster_name"]
|
|
62
66
|
|
|
67
|
+
show_simulate_option = False
|
|
68
|
+
|
|
63
69
|
# -------------------------------------------------------------------------
|
|
64
70
|
def __init__(
|
|
65
71
|
self,
|
|
@@ -120,8 +126,6 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
120
126
|
# -------------------------------------------------------------------------
|
|
121
127
|
def init_arg_parser(self):
|
|
122
128
|
"""Public available method to initiate the argument parser."""
|
|
123
|
-
super(GetStorageClusterListApp, self).init_arg_parser()
|
|
124
|
-
|
|
125
129
|
output_options = self.arg_parser.add_argument_group(_("Output options"))
|
|
126
130
|
|
|
127
131
|
output_options.add_argument(
|
|
@@ -148,6 +152,8 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
148
152
|
),
|
|
149
153
|
)
|
|
150
154
|
|
|
155
|
+
super(GetStorageClusterListApp, self).init_arg_parser()
|
|
156
|
+
|
|
151
157
|
# -------------------------------------------------------------------------
|
|
152
158
|
def perform_arg_parser(self):
|
|
153
159
|
"""Evaluate command line parameters."""
|
|
@@ -243,6 +249,8 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
243
249
|
cluster["vsphere_name"] = vsphere_name
|
|
244
250
|
cluster["dc"] = cl.dc_name
|
|
245
251
|
|
|
252
|
+
cluster["storage_type"] = cl.storage_type
|
|
253
|
+
|
|
246
254
|
cluster["capacity"] = cl.capacity_gb
|
|
247
255
|
cluster["capacity_gb"] = format_decimal(cl.capacity_gb, format="#,##0")
|
|
248
256
|
total_capacity += cl.capacity_gb
|
|
@@ -260,104 +268,50 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
260
268
|
cluster["usage_pc"] = usage_pc
|
|
261
269
|
cluster["usage_pc_out"] = format_decimal(usage_pc, format="0.0 %")
|
|
262
270
|
else:
|
|
271
|
+
cluster["usage_pc"] = None
|
|
263
272
|
cluster["usage_pc_out"] = "- %"
|
|
264
273
|
|
|
265
274
|
cluster_list.append(cluster)
|
|
266
275
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
276
|
+
total_used = total_capacity - total_free
|
|
277
|
+
total_used_pc = None
|
|
278
|
+
total_used_pc_out = "- %"
|
|
279
|
+
if total_capacity:
|
|
280
|
+
total_used_pc = total_used / total_capacity
|
|
281
|
+
total_used_pc_out = format_decimal(total_used_pc, format="0.0 %")
|
|
282
|
+
|
|
283
|
+
self.totals = {
|
|
284
|
+
"cluster_name": _("Total"),
|
|
285
|
+
"storage_type": "",
|
|
286
|
+
"vsphere_name": "",
|
|
287
|
+
"dc": "",
|
|
288
|
+
"is_total": True,
|
|
289
|
+
"capacity_gb": format_decimal(total_capacity, format="#,##0"),
|
|
290
|
+
"free_space_gb": format_decimal(total_free, format="#,##0"),
|
|
291
|
+
"usage_gb": format_decimal(total_used, format="#,##0"),
|
|
292
|
+
"usage_pc_out": total_used_pc_out,
|
|
293
|
+
}
|
|
294
|
+
if not self.quiet:
|
|
295
|
+
self.totals["cluster_name"] += ":"
|
|
287
296
|
|
|
288
297
|
return cluster_list
|
|
289
298
|
|
|
290
|
-
# -------------------------------------------------------------------------
|
|
291
|
-
def _get_cluster_fields_len(self, cluster_list, labels):
|
|
292
|
-
|
|
293
|
-
field_length = {}
|
|
294
|
-
|
|
295
|
-
for label in labels.keys():
|
|
296
|
-
field_length[label] = len(labels[label])
|
|
297
|
-
|
|
298
|
-
for cluster in cluster_list:
|
|
299
|
-
for label in labels.keys():
|
|
300
|
-
field = cluster[label]
|
|
301
|
-
if len(field) > field_length[label]:
|
|
302
|
-
field_length[label] = len(field)
|
|
303
|
-
|
|
304
|
-
if self.totals:
|
|
305
|
-
for label in labels.keys():
|
|
306
|
-
field = self.totals[label]
|
|
307
|
-
if len(field) > field_length[label]:
|
|
308
|
-
field_length[label] = len(field)
|
|
309
|
-
|
|
310
|
-
return field_length
|
|
311
|
-
|
|
312
299
|
# -------------------------------------------------------------------------
|
|
313
300
|
def print_clusters(self, clusters):
|
|
314
301
|
"""Print on STDOUT all information about all datastore clusters."""
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
"cluster_name",
|
|
327
|
-
"vsphere_name",
|
|
328
|
-
"dc",
|
|
329
|
-
"capacity_gb",
|
|
330
|
-
"usage_gb",
|
|
331
|
-
"usage_pc_out",
|
|
332
|
-
"free_space_gb",
|
|
333
|
-
)
|
|
302
|
+
show_footer = False
|
|
303
|
+
if self.print_total and not self.quiet:
|
|
304
|
+
show_footer = True
|
|
305
|
+
|
|
306
|
+
show_header = True
|
|
307
|
+
table_title = _("All datastore clusters") + "\n"
|
|
308
|
+
box_style = box.ROUNDED
|
|
309
|
+
if self.quiet:
|
|
310
|
+
show_header = False
|
|
311
|
+
table_title = None
|
|
312
|
+
box_style = None
|
|
334
313
|
|
|
335
314
|
cluster_list = self._get_cluster_list(clusters)
|
|
336
|
-
field_length = self._get_cluster_fields_len(cluster_list, labels)
|
|
337
|
-
|
|
338
|
-
max_len = 0
|
|
339
|
-
count = len(cluster_list)
|
|
340
|
-
|
|
341
|
-
for label in labels.keys():
|
|
342
|
-
if max_len:
|
|
343
|
-
max_len += 2
|
|
344
|
-
max_len += field_length[label]
|
|
345
|
-
|
|
346
|
-
if self.verbose > 2:
|
|
347
|
-
LOG.debug("Label length:\n" + pp(field_length))
|
|
348
|
-
LOG.debug("Max line length: {} chars".format(max_len))
|
|
349
|
-
LOG.debug("Datastore clusters:\n" + pp(cluster_list))
|
|
350
|
-
|
|
351
|
-
tpl = ""
|
|
352
|
-
for label in label_list:
|
|
353
|
-
if tpl != "":
|
|
354
|
-
tpl += " "
|
|
355
|
-
if label in ("cluster_name", "vsphere_name", "dc"):
|
|
356
|
-
tpl += "{{{la}:<{le}}}".format(la=label, le=field_length[label])
|
|
357
|
-
else:
|
|
358
|
-
tpl += "{{{la}:>{le}}}".format(la=label, le=field_length[label])
|
|
359
|
-
if self.verbose > 1:
|
|
360
|
-
LOG.debug(_("Line template: {}").format(tpl))
|
|
361
315
|
|
|
362
316
|
if self.sort_keys:
|
|
363
317
|
LOG.debug("Sorting keys: " + pp(self.sort_keys))
|
|
@@ -368,31 +322,70 @@ class GetStorageClusterListApp(BaseVmwareApplication):
|
|
|
368
322
|
else:
|
|
369
323
|
cluster_list.sort(key=itemgetter(key), reverse=True)
|
|
370
324
|
|
|
371
|
-
if
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
for cluster in cluster_list:
|
|
377
|
-
print(tpl.format(**cluster))
|
|
378
|
-
|
|
379
|
-
if self.totals:
|
|
380
|
-
if not self.quiet:
|
|
381
|
-
print("-" * max_len)
|
|
382
|
-
print(tpl.format(**self.totals))
|
|
383
|
-
|
|
384
|
-
if not self.quiet:
|
|
385
|
-
print()
|
|
325
|
+
if self.quiet:
|
|
326
|
+
caption = None
|
|
327
|
+
else:
|
|
328
|
+
count = len(cluster_list)
|
|
386
329
|
if count:
|
|
387
|
-
|
|
330
|
+
caption = "\n" + ngettext(
|
|
388
331
|
"Found one VMware storage cluster.",
|
|
389
332
|
"Found {} VMware storage clusters.",
|
|
390
333
|
count,
|
|
391
334
|
).format(count)
|
|
392
335
|
else:
|
|
393
|
-
|
|
336
|
+
caption = "\n" + _("No VMware storage clusters found.")
|
|
337
|
+
|
|
338
|
+
table = Table(
|
|
339
|
+
title=table_title,
|
|
340
|
+
title_style="bold cyan",
|
|
341
|
+
caption=caption,
|
|
342
|
+
caption_style="default on default",
|
|
343
|
+
caption_justify="left",
|
|
344
|
+
box=box_style,
|
|
345
|
+
show_header=show_header,
|
|
346
|
+
show_footer=show_footer,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
table.add_column(header="Cluster", footer=_("Total"))
|
|
350
|
+
table.add_column(header=_("Type"), justify="center", footer="")
|
|
351
|
+
table.add_column(header=_("vSphere"), footer="")
|
|
352
|
+
table.add_column(header=_("Data Center"), footer="")
|
|
353
|
+
table.add_column(
|
|
354
|
+
header=_("Capacity in GB"), footer=self.totals["capacity_gb"], justify="right"
|
|
355
|
+
)
|
|
356
|
+
table.add_column(
|
|
357
|
+
header=_("Calculated usage in GB"), footer=self.totals["usage_gb"], justify="right"
|
|
358
|
+
)
|
|
359
|
+
table.add_column(
|
|
360
|
+
header=_("Usage in percent"), footer=self.totals["usage_pc_out"], justify="right"
|
|
361
|
+
)
|
|
362
|
+
table.add_column(
|
|
363
|
+
header=_("Free space in GB"), footer=self.totals["free_space_gb"], justify="right"
|
|
364
|
+
)
|
|
394
365
|
|
|
395
|
-
|
|
366
|
+
for cluster in cluster_list:
|
|
367
|
+
used_pc_out = Text(cluster["usage_pc_out"])
|
|
368
|
+
if cluster["usage_pc"] is None:
|
|
369
|
+
used_pc_out.stylize("bold magenta")
|
|
370
|
+
elif cluster["usage_pc"] >= 0.9:
|
|
371
|
+
used_pc_out.stylize("bold red")
|
|
372
|
+
elif cluster["usage_pc"] >= 0.8:
|
|
373
|
+
used_pc_out.stylize("bold yellow")
|
|
374
|
+
|
|
375
|
+
table.add_row(
|
|
376
|
+
cluster["cluster_name"],
|
|
377
|
+
cluster["storage_type"],
|
|
378
|
+
cluster["vsphere_name"],
|
|
379
|
+
cluster["dc"],
|
|
380
|
+
cluster["capacity_gb"],
|
|
381
|
+
cluster["usage_gb"],
|
|
382
|
+
used_pc_out,
|
|
383
|
+
cluster["free_space_gb"],
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
self.rich_console.print(table)
|
|
387
|
+
|
|
388
|
+
if not self.quiet:
|
|
396
389
|
print()
|
|
397
390
|
|
|
398
391
|
|
|
@@ -24,6 +24,10 @@ from fb_tools.common import pp
|
|
|
24
24
|
from fb_tools.spinner import Spinner
|
|
25
25
|
from fb_tools.xlate import format_list
|
|
26
26
|
|
|
27
|
+
from rich import box
|
|
28
|
+
from rich.table import Table
|
|
29
|
+
from rich.text import Text
|
|
30
|
+
|
|
27
31
|
# Own modules
|
|
28
32
|
from . import BaseVmwareApplication
|
|
29
33
|
from . import VmwareAppError
|
|
@@ -32,7 +36,7 @@ from ..datastore import VsphereDatastoreDict
|
|
|
32
36
|
from ..errors import VSphereExpectedError
|
|
33
37
|
from ..xlate import XLATOR
|
|
34
38
|
|
|
35
|
-
__version__ = "1.0
|
|
39
|
+
__version__ = "1.3.0"
|
|
36
40
|
LOG = logging.getLogger(__name__)
|
|
37
41
|
|
|
38
42
|
_ = XLATOR.gettext
|
|
@@ -62,6 +66,8 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
62
66
|
)
|
|
63
67
|
default_sort_keys = ["vsphere_name", "dc", "ds_name"]
|
|
64
68
|
|
|
69
|
+
show_simulate_option = False
|
|
70
|
+
|
|
65
71
|
# -------------------------------------------------------------------------
|
|
66
72
|
def __init__(
|
|
67
73
|
self,
|
|
@@ -83,6 +89,7 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
83
89
|
self._print_total = True
|
|
84
90
|
self._no_local = False
|
|
85
91
|
self.totals = None
|
|
92
|
+
self._detailled = False
|
|
86
93
|
self.sort_keys = self.default_sort_keys
|
|
87
94
|
|
|
88
95
|
super(GetStorageListApp, self).__init__(
|
|
@@ -108,6 +115,12 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
108
115
|
"""Don't print out local datastores on the ESX hosts."""
|
|
109
116
|
return self._no_local
|
|
110
117
|
|
|
118
|
+
# -------------------------------------------------------------------------
|
|
119
|
+
@property
|
|
120
|
+
def detailled(self):
|
|
121
|
+
"""Print out a more detailled info about the datastores."""
|
|
122
|
+
return self._detailled
|
|
123
|
+
|
|
111
124
|
# -------------------------------------------------------------------------
|
|
112
125
|
def as_dict(self, short=True):
|
|
113
126
|
"""
|
|
@@ -120,6 +133,7 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
120
133
|
@rtype: dict
|
|
121
134
|
"""
|
|
122
135
|
res = super(GetStorageListApp, self).as_dict(short=short)
|
|
136
|
+
res["detailled"] = self.detailled
|
|
123
137
|
res["no_local"] = self.no_local
|
|
124
138
|
res["print_total"] = self.print_total
|
|
125
139
|
|
|
@@ -128,8 +142,6 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
128
142
|
# -------------------------------------------------------------------------
|
|
129
143
|
def init_arg_parser(self):
|
|
130
144
|
"""Public available method to initiate the argument parser."""
|
|
131
|
-
super(GetStorageListApp, self).init_arg_parser()
|
|
132
|
-
|
|
133
145
|
output_options = self.arg_parser.add_argument_group(_("Output options"))
|
|
134
146
|
|
|
135
147
|
output_options.add_argument(
|
|
@@ -148,6 +160,17 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
148
160
|
help=_("Don't print the totals of all datastores."),
|
|
149
161
|
)
|
|
150
162
|
|
|
163
|
+
output_options.add_argument(
|
|
164
|
+
"-D",
|
|
165
|
+
"--detailled",
|
|
166
|
+
action="store_true",
|
|
167
|
+
dest="detailled",
|
|
168
|
+
help=_(
|
|
169
|
+
"Print out a more detailled info about the datastores, e.g. the number of "
|
|
170
|
+
"connected hosts. Tooks significant more time to retrieve the data from vSphere."
|
|
171
|
+
),
|
|
172
|
+
)
|
|
173
|
+
|
|
151
174
|
output_options.add_argument(
|
|
152
175
|
"-S",
|
|
153
176
|
"--sort",
|
|
@@ -164,6 +187,8 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
164
187
|
),
|
|
165
188
|
)
|
|
166
189
|
|
|
190
|
+
super(GetStorageListApp, self).init_arg_parser()
|
|
191
|
+
|
|
167
192
|
# -------------------------------------------------------------------------
|
|
168
193
|
def perform_arg_parser(self):
|
|
169
194
|
"""Evaluate command line parameters."""
|
|
@@ -178,6 +203,9 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
178
203
|
if getattr(self.args, "no_local", False):
|
|
179
204
|
self._no_local = True
|
|
180
205
|
|
|
206
|
+
if getattr(self.args, "detailled", False):
|
|
207
|
+
self._detailled = True
|
|
208
|
+
|
|
181
209
|
# -------------------------------------------------------------------------
|
|
182
210
|
def _run(self):
|
|
183
211
|
|
|
@@ -201,7 +229,7 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
201
229
|
if self.no_local:
|
|
202
230
|
no_local_ds = True
|
|
203
231
|
try:
|
|
204
|
-
vsphere.get_datastores(no_local_ds=no_local_ds)
|
|
232
|
+
vsphere.get_datastores(no_local_ds=no_local_ds, detailled=self.detailled)
|
|
205
233
|
except VSphereExpectedError as e:
|
|
206
234
|
LOG.error(str(e))
|
|
207
235
|
self.exit(6)
|
|
@@ -253,15 +281,29 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
253
281
|
total_capacity = 0.0
|
|
254
282
|
total_free = 0.0
|
|
255
283
|
|
|
284
|
+
first = True
|
|
285
|
+
|
|
256
286
|
for vsphere_name in datastores.keys():
|
|
257
287
|
for ds_name in datastores[vsphere_name].keys():
|
|
258
288
|
|
|
259
289
|
ds = datastores[vsphere_name][ds_name]
|
|
290
|
+
|
|
291
|
+
if self.verbose == 2 and first:
|
|
292
|
+
LOG.debug("First found datastore:\n" + pp(ds.as_dict()))
|
|
293
|
+
first = False
|
|
294
|
+
|
|
260
295
|
datastore = {}
|
|
261
296
|
datastore["is_total"] = False
|
|
262
297
|
|
|
298
|
+
datastore["storage_type"] = ds.storage_type
|
|
299
|
+
|
|
263
300
|
datastore["ds_name"] = ds_name
|
|
264
301
|
|
|
302
|
+
if hasattr(ds, "hosts"):
|
|
303
|
+
datastore["hosts"] = str(len(ds.hosts))
|
|
304
|
+
else:
|
|
305
|
+
datastore["hosts"] = "~"
|
|
306
|
+
|
|
265
307
|
datastore["vsphere_name"] = vsphere_name
|
|
266
308
|
datastore["dc"] = ds.dc_name
|
|
267
309
|
datastore["cluster"] = "~"
|
|
@@ -285,107 +327,51 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
285
327
|
datastore["usage_pc"] = usage_pc
|
|
286
328
|
datastore["usage_pc_out"] = format_decimal(usage_pc, format="0.0 %")
|
|
287
329
|
else:
|
|
330
|
+
datastore["usage_pc"] = None
|
|
288
331
|
datastore["usage_pc_out"] = "- %"
|
|
289
332
|
|
|
290
333
|
datastore_list.append(datastore)
|
|
291
334
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
335
|
+
total_used = total_capacity - total_free
|
|
336
|
+
total_used_pc = None
|
|
337
|
+
total_used_pc_out = "- %"
|
|
338
|
+
if total_capacity:
|
|
339
|
+
total_used_pc = total_used / total_capacity
|
|
340
|
+
total_used_pc_out = format_decimal(total_used_pc, format="0.0 %")
|
|
341
|
+
|
|
342
|
+
self.totals = {
|
|
343
|
+
"ds_name": _("Total"),
|
|
344
|
+
"vsphere_name": "",
|
|
345
|
+
"hosts": "",
|
|
346
|
+
"dc": "",
|
|
347
|
+
"cluster": "",
|
|
348
|
+
"is_total": True,
|
|
349
|
+
"capacity_gb": format_decimal(total_capacity, format="#,##0"),
|
|
350
|
+
"free_space_gb": format_decimal(total_free, format="#,##0"),
|
|
351
|
+
"usage_gb": format_decimal(total_used, format="#,##0"),
|
|
352
|
+
"usage_pc_out": total_used_pc_out,
|
|
353
|
+
}
|
|
354
|
+
if not self.quiet:
|
|
355
|
+
self.totals["ds_name"] += ":"
|
|
313
356
|
|
|
314
357
|
return datastore_list
|
|
315
358
|
|
|
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
359
|
# -------------------------------------------------------------------------
|
|
339
360
|
def print_datastores(self, all_datastores):
|
|
340
361
|
"""Print on STDOUT all information about all datastore clusters."""
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
+
show_footer = False
|
|
363
|
+
if self.print_total and not self.quiet:
|
|
364
|
+
show_footer = True
|
|
365
|
+
|
|
366
|
+
show_header = True
|
|
367
|
+
table_title = _("All datastores") + "\n"
|
|
368
|
+
box_style = box.ROUNDED
|
|
369
|
+
if self.quiet:
|
|
370
|
+
show_header = False
|
|
371
|
+
table_title = None
|
|
372
|
+
box_style = None
|
|
362
373
|
|
|
363
374
|
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
375
|
|
|
390
376
|
if self.sort_keys:
|
|
391
377
|
LOG.debug("Sorting keys: " + pp(self.sort_keys))
|
|
@@ -396,31 +382,74 @@ class GetStorageListApp(BaseVmwareApplication):
|
|
|
396
382
|
else:
|
|
397
383
|
datastore_list.sort(key=itemgetter(key), reverse=True)
|
|
398
384
|
|
|
399
|
-
if
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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()
|
|
385
|
+
if self.quiet:
|
|
386
|
+
caption = None
|
|
387
|
+
else:
|
|
388
|
+
count = len(datastore_list)
|
|
414
389
|
if count:
|
|
415
|
-
|
|
390
|
+
caption = "\n" + ngettext(
|
|
416
391
|
"Found one VMware datastore.",
|
|
417
392
|
"Found {} VMware datastores.",
|
|
418
393
|
count,
|
|
419
394
|
).format(count)
|
|
420
395
|
else:
|
|
421
|
-
|
|
396
|
+
caption = "\n" + _("No VMware datastores found.")
|
|
397
|
+
|
|
398
|
+
ds_table = Table(
|
|
399
|
+
title=table_title,
|
|
400
|
+
title_style="bold cyan",
|
|
401
|
+
caption=caption,
|
|
402
|
+
caption_style="default on default",
|
|
403
|
+
caption_justify="left",
|
|
404
|
+
box=box_style,
|
|
405
|
+
show_header=show_header,
|
|
406
|
+
show_footer=show_footer,
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
ds_table.add_column(header=_("Datastore"), footer=_("Total"))
|
|
410
|
+
ds_table.add_column(header=_("Type"), footer="", justify="center")
|
|
411
|
+
ds_table.add_column(header=_("vSphere"), footer="")
|
|
412
|
+
ds_table.add_column(header=_("Data Center"), footer="")
|
|
413
|
+
ds_table.add_column(header=_("Cluster"), footer="")
|
|
414
|
+
ds_table.add_column(header=_("Connected Hosts"), footer="", justify="right")
|
|
415
|
+
ds_table.add_column(
|
|
416
|
+
header=_("Capacity in GB"), footer=self.totals["capacity_gb"], justify="right"
|
|
417
|
+
)
|
|
418
|
+
ds_table.add_column(
|
|
419
|
+
header=_("Calculated usage in GB"), footer=self.totals["usage_gb"], justify="right"
|
|
420
|
+
)
|
|
421
|
+
ds_table.add_column(
|
|
422
|
+
header=_("Usage in percent"), footer=self.totals["usage_pc_out"], justify="right"
|
|
423
|
+
)
|
|
424
|
+
ds_table.add_column(
|
|
425
|
+
header=_("Free space in GB"), footer=self.totals["free_space_gb"], justify="right"
|
|
426
|
+
)
|
|
422
427
|
|
|
423
|
-
|
|
428
|
+
for datastore in datastore_list:
|
|
429
|
+
used_pc_out = Text(datastore["usage_pc_out"])
|
|
430
|
+
if datastore["usage_pc"] is None:
|
|
431
|
+
used_pc_out.stylize("bold magenta")
|
|
432
|
+
elif datastore["usage_pc"] >= 0.9:
|
|
433
|
+
used_pc_out.stylize("bold red")
|
|
434
|
+
elif datastore["usage_pc"] >= 0.8:
|
|
435
|
+
used_pc_out.stylize("bold yellow")
|
|
436
|
+
|
|
437
|
+
ds_table.add_row(
|
|
438
|
+
datastore["ds_name"],
|
|
439
|
+
datastore["storage_type"],
|
|
440
|
+
datastore["vsphere_name"],
|
|
441
|
+
datastore["dc"],
|
|
442
|
+
datastore["cluster"],
|
|
443
|
+
datastore["hosts"],
|
|
444
|
+
datastore["capacity_gb"],
|
|
445
|
+
datastore["usage_gb"],
|
|
446
|
+
used_pc_out,
|
|
447
|
+
datastore["free_space_gb"],
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
self.rich_console.print(ds_table)
|
|
451
|
+
|
|
452
|
+
if not self.quiet:
|
|
424
453
|
print()
|
|
425
454
|
|
|
426
455
|
|
|
@@ -438,7 +467,11 @@ def main():
|
|
|
438
467
|
if app.verbose > 2:
|
|
439
468
|
print(_("{c}-Object:\n{a}").format(c=app.__class__.__name__, a=app), file=sys.stderr)
|
|
440
469
|
|
|
441
|
-
|
|
470
|
+
try:
|
|
471
|
+
app()
|
|
472
|
+
except KeyboardInterrupt:
|
|
473
|
+
print("\n" + app.colored(_("User interrupt."), "YELLOW"))
|
|
474
|
+
sys.exit(5)
|
|
442
475
|
|
|
443
476
|
return 0
|
|
444
477
|
|