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.
Files changed (36) hide show
  1. fb_vmware/__init__.py +1 -1
  2. fb_vmware/app/__init__.py +285 -6
  3. fb_vmware/app/get_host_list.py +115 -100
  4. fb_vmware/app/get_network_list.py +176 -218
  5. fb_vmware/app/get_rpool_list.py +386 -0
  6. fb_vmware/app/get_storage_cluster_info.py +303 -0
  7. fb_vmware/app/get_storage_cluster_list.py +100 -107
  8. fb_vmware/app/get_storage_list.py +145 -112
  9. fb_vmware/app/get_vm_info.py +79 -17
  10. fb_vmware/app/get_vm_list.py +169 -95
  11. fb_vmware/app/search_storage.py +470 -0
  12. fb_vmware/argparse_actions.py +78 -0
  13. fb_vmware/base.py +28 -1
  14. fb_vmware/cluster.py +99 -7
  15. fb_vmware/connect.py +450 -20
  16. fb_vmware/datastore.py +195 -6
  17. fb_vmware/dc.py +19 -1
  18. fb_vmware/ds_cluster.py +215 -2
  19. fb_vmware/dvs.py +37 -1
  20. fb_vmware/errors.py +31 -10
  21. fb_vmware/host.py +40 -2
  22. fb_vmware/host_port_group.py +1 -2
  23. fb_vmware/network.py +17 -1
  24. fb_vmware/obj.py +30 -1
  25. fb_vmware/vm.py +19 -1
  26. fb_vmware/xlate.py +8 -13
  27. fb_vmware-1.8.1.data/data/share/locale/de/LC_MESSAGES/fb_vmware.mo +0 -0
  28. fb_vmware-1.8.1.data/data/share/locale/en/LC_MESSAGES/fb_vmware.mo +0 -0
  29. {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/METADATA +2 -1
  30. fb_vmware-1.8.1.dist-info/RECORD +40 -0
  31. {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/entry_points.txt +3 -0
  32. fb_vmware-1.7.1.data/data/share/locale/de_DE/LC_MESSAGES/fb_vmware.mo +0 -0
  33. fb_vmware-1.7.1.data/data/share/locale/en_US/LC_MESSAGES/fb_vmware.mo +0 -0
  34. fb_vmware-1.7.1.dist-info/RECORD +0 -36
  35. {fb_vmware-1.7.1.dist-info → fb_vmware-1.8.1.dist-info}/WHEEL +0 -0
  36. {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.3.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
- if self.print_total:
268
- total_used = total_capacity - total_free
269
- total_used_pc = None
270
- total_used_pc_out = "- %"
271
- if total_capacity:
272
- total_used_pc = total_used / total_capacity
273
- total_used_pc_out = format_decimal(total_used_pc, format="0.0 %")
274
-
275
- self.totals = {
276
- "cluster_name": _("Total"),
277
- "vsphere_name": "",
278
- "dc": "",
279
- "is_total": True,
280
- "capacity_gb": format_decimal(total_capacity, format="#,##0"),
281
- "free_space_gb": format_decimal(total_free, format="#,##0"),
282
- "usage_gb": format_decimal(total_used, format="#,##0"),
283
- "usage_pc_out": total_used_pc_out,
284
- }
285
- if not self.quiet:
286
- self.totals["cluster_name"] += ":"
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
- labels = {
316
- "cluster_name": "Cluster",
317
- "vsphere_name": "vSphere",
318
- "dc": _("Data Center"),
319
- "capacity_gb": _("Capacity in GB"),
320
- "free_space_gb": _("Free space in GB"),
321
- "usage_gb": _("Calculated usage in GB"),
322
- "usage_pc_out": _("Usage in percent"),
323
- }
324
-
325
- label_list = (
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 not self.quiet:
372
- print()
373
- print(tpl.format(**labels))
374
- print("-" * max_len)
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
- msg = ngettext(
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
- msg = _("No VMware storage clusters found.")
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
- print(msg)
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.2"
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
- 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"] += ":"
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
- 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
+ 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 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()
385
+ if self.quiet:
386
+ caption = None
387
+ else:
388
+ count = len(datastore_list)
414
389
  if count:
415
- msg = ngettext(
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
- msg = _("No VMware datastores found.")
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
- print(msg)
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
- app()
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