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 CHANGED
@@ -56,7 +56,7 @@ from .vm import VsphereVmList
56
56
  from .xlate import XLATOR
57
57
 
58
58
 
59
- __version__ = "1.6.0"
59
+ __version__ = "1.7.0"
60
60
 
61
61
  LOG = logging.getLogger(__name__)
62
62
 
@@ -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.3.0"
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.6.0"
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.2.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.".format(count),
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