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
fb_vmware/app/get_vm_info.py
CHANGED
|
@@ -16,6 +16,9 @@ import pathlib
|
|
|
16
16
|
import sys
|
|
17
17
|
from operator import attrgetter
|
|
18
18
|
|
|
19
|
+
# Third party modules
|
|
20
|
+
from fb_tools.spinner import Spinner
|
|
21
|
+
|
|
19
22
|
# Own modules
|
|
20
23
|
from . import BaseVmwareApplication, VmwareAppError
|
|
21
24
|
from .. import __version__ as GLOBAL_VERSION
|
|
@@ -24,7 +27,7 @@ from ..errors import VSphereExpectedError
|
|
|
24
27
|
from ..ether import VsphereEthernetcard
|
|
25
28
|
from ..xlate import XLATOR
|
|
26
29
|
|
|
27
|
-
__version__ = "1.
|
|
30
|
+
__version__ = "1.10.0"
|
|
28
31
|
LOG = logging.getLogger(__name__)
|
|
29
32
|
|
|
30
33
|
_ = XLATOR.gettext
|
|
@@ -132,11 +135,23 @@ class GetVmApplication(BaseVmwareApplication):
|
|
|
132
135
|
# -------------------------------------------------------------------------
|
|
133
136
|
def show_vm(self, vm_name):
|
|
134
137
|
"""Show a particular VM on STDOUT."""
|
|
135
|
-
print(
|
|
138
|
+
print()
|
|
139
|
+
msg_tpl = _("Getting data of VM {} ... ")
|
|
136
140
|
if self.verbose:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
141
|
+
msg = msg_tpl.format(self.colored(vm_name, "CYAN"))
|
|
142
|
+
print(msg)
|
|
143
|
+
vm = self._get_vm_data(vm_name)
|
|
144
|
+
else:
|
|
145
|
+
msg_len = len(msg_tpl.format(vm_name))
|
|
146
|
+
spin_prompt = msg_tpl.format(self.colored(vm_name, "CYAN"))
|
|
147
|
+
spinner_name = self.get_random_spinner_name()
|
|
148
|
+
with Spinner(spin_prompt, spinner_name):
|
|
149
|
+
vm = self._get_vm_data(vm_name)
|
|
150
|
+
sys.stdout.write(" " * msg_len)
|
|
151
|
+
sys.stdout.write("\r")
|
|
152
|
+
sys.stdout.flush()
|
|
153
|
+
|
|
154
|
+
print("{}: ".format(vm_name), end="")
|
|
140
155
|
if not vm:
|
|
141
156
|
print(self.colored(_("NOT FOUND"), "RED"))
|
|
142
157
|
return False
|
|
@@ -190,6 +205,24 @@ class GetVmApplication(BaseVmwareApplication):
|
|
|
190
205
|
# -------------------------------------------------------------------------
|
|
191
206
|
def _print_ctrlrs(self, vm):
|
|
192
207
|
|
|
208
|
+
ctrl_lbl = _("Controller") + ":"
|
|
209
|
+
len_ctrl_lbl = len(ctrl_lbl)
|
|
210
|
+
|
|
211
|
+
len_no_disk = 1
|
|
212
|
+
len_ctrl_no = 1
|
|
213
|
+
for ctrlr in filter(lambda x: x.scsi_ctrl_nr is not None, vm.controllers):
|
|
214
|
+
nr_disks = len(ctrlr.devices)
|
|
215
|
+
no_disk = ngettext("{nr:>2} disk ", "{nr:>2} disks", nr_disks).format(nr=nr_disks)
|
|
216
|
+
if len(no_disk) > len_no_disk:
|
|
217
|
+
len_no_disk = len(no_disk)
|
|
218
|
+
if len(str(ctrlr.bus_nr)) > len_ctrl_no:
|
|
219
|
+
len_ctrl_no = len(str(ctrlr.bus_nr))
|
|
220
|
+
|
|
221
|
+
line_template = (
|
|
222
|
+
f" {{la:<{len_ctrl_lbl}}} {{nr:>{len_ctrl_no}}} - {{di:<{len_no_disk}}} - {{ty}}"
|
|
223
|
+
)
|
|
224
|
+
# LOG.debug(f"Line template: {line_template!r}")
|
|
225
|
+
|
|
193
226
|
first = True
|
|
194
227
|
for ctrlr in sorted(
|
|
195
228
|
filter(lambda x: x.scsi_ctrl_nr is not None, vm.controllers), key=attrgetter("bus_nr")
|
|
@@ -198,28 +231,46 @@ class GetVmApplication(BaseVmwareApplication):
|
|
|
198
231
|
continue
|
|
199
232
|
label = ""
|
|
200
233
|
if first:
|
|
201
|
-
label =
|
|
234
|
+
label = ctrl_lbl
|
|
202
235
|
first = False
|
|
203
236
|
ctype = _("Unknown")
|
|
204
237
|
nr_disks = len(ctrlr.devices)
|
|
205
238
|
if ctrlr.ctrl_type in VsphereDiskController.type_names.keys():
|
|
206
239
|
ctype = VsphereDiskController.type_names[ctrlr.ctrl_type]
|
|
207
240
|
no_disk = ngettext("{nr:>2} disk ", "{nr:>2} disks", nr_disks).format(nr=nr_disks)
|
|
208
|
-
|
|
209
|
-
# if len(ctrlr.devices) == 1:
|
|
210
|
-
# no_disk = _(" 1 disk ")
|
|
211
|
-
msg = " {la:<15} {nr:>2} - {di} - {ty}".format(
|
|
212
|
-
la=label, nr=ctrlr.bus_nr, di=no_disk, ty=ctype
|
|
213
|
-
)
|
|
241
|
+
msg = line_template.format(la=label, nr=ctrlr.bus_nr, di=no_disk, ty=ctype)
|
|
214
242
|
print(msg)
|
|
215
243
|
|
|
216
244
|
# -------------------------------------------------------------------------
|
|
217
245
|
def _print_disks(self, vm):
|
|
218
246
|
|
|
219
247
|
if not vm.disks:
|
|
220
|
-
print(" Disks:
|
|
248
|
+
print(" " + _("Disks") + ": " + _("None"))
|
|
221
249
|
return
|
|
222
250
|
|
|
251
|
+
ctrl_lbl = _("Controller")
|
|
252
|
+
file_lbl = _("File")
|
|
253
|
+
len_disk_lbl = 1
|
|
254
|
+
len_ctrl_lbl = len(ctrl_lbl)
|
|
255
|
+
len_ctrlr_nr = 1
|
|
256
|
+
|
|
257
|
+
for disk in vm.disks:
|
|
258
|
+
if len(disk.label) > len_disk_lbl:
|
|
259
|
+
len_disk_lbl = len(disk.label)
|
|
260
|
+
ctrlr_nr = -1
|
|
261
|
+
for ctrlr in vm.controllers:
|
|
262
|
+
if disk.key in ctrlr.devices:
|
|
263
|
+
ctrlr_nr = ctrlr.bus_nr
|
|
264
|
+
break
|
|
265
|
+
if len(str(ctrlr_nr)) > len_ctrlr_nr:
|
|
266
|
+
len_ctrlr_nr = len(str(ctrlr_nr))
|
|
267
|
+
|
|
268
|
+
line_template = f" {{la}} {{n:<{len_disk_lbl}}}"
|
|
269
|
+
line_template += f" - {{s:7.1f}} GiB - {{ctrl_lbl:<{len_ctrl_lbl}}}"
|
|
270
|
+
line_template += f" {{c:>{len_ctrlr_nr}}}"
|
|
271
|
+
line_template += " - {file_lbl} {f}"
|
|
272
|
+
# LOG.debug(f"Line template: {line_template!r}")
|
|
273
|
+
|
|
223
274
|
total_gb = 0.0
|
|
224
275
|
first = True
|
|
225
276
|
for disk in vm.disks:
|
|
@@ -233,8 +284,14 @@ class GetVmApplication(BaseVmwareApplication):
|
|
|
233
284
|
if disk.key in ctrlr.devices:
|
|
234
285
|
ctrlr_nr = ctrlr.bus_nr
|
|
235
286
|
break
|
|
236
|
-
msg =
|
|
237
|
-
la=label,
|
|
287
|
+
msg = line_template.format(
|
|
288
|
+
la=label,
|
|
289
|
+
n=disk.label,
|
|
290
|
+
s=disk.size_gb,
|
|
291
|
+
ctrl_lbl=ctrl_lbl,
|
|
292
|
+
c=ctrlr_nr,
|
|
293
|
+
file_lbl=file_lbl,
|
|
294
|
+
f=disk.file_name,
|
|
238
295
|
)
|
|
239
296
|
print(msg)
|
|
240
297
|
if len(vm.disks) > 1:
|
|
@@ -303,7 +360,8 @@ class GetVmApplication(BaseVmwareApplication):
|
|
|
303
360
|
vm=self.colored(vm_name, "CYAN"), vs=self.colored(vsphere_name, "CYAN")
|
|
304
361
|
)
|
|
305
362
|
)
|
|
306
|
-
vm = vsphere.
|
|
363
|
+
vm = vsphere.get_vm_direct(vm_name, vsphere_name=vsphere_name, no_error=True)
|
|
364
|
+
# vm = vsphere.get_vm(vm_name, vsphere_name=vsphere_name, no_error=True)
|
|
307
365
|
if not vm:
|
|
308
366
|
continue
|
|
309
367
|
|
|
@@ -337,7 +395,11 @@ def main():
|
|
|
337
395
|
if app.verbose > 2:
|
|
338
396
|
print(_("{c}-Object:\n{a}").format(c=app.__class__.__name__, a=app), file=sys.stderr)
|
|
339
397
|
|
|
340
|
-
|
|
398
|
+
try:
|
|
399
|
+
app()
|
|
400
|
+
except KeyboardInterrupt:
|
|
401
|
+
print("\n" + app.colored(_("User interrupt."), "YELLOW"))
|
|
402
|
+
sys.exit(5)
|
|
341
403
|
|
|
342
404
|
sys.exit(0)
|
|
343
405
|
|
fb_vmware/app/get_vm_list.py
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
from __future__ import absolute_import, print_function
|
|
11
11
|
|
|
12
12
|
# Standard modules
|
|
13
|
+
import argparse
|
|
13
14
|
import locale
|
|
14
15
|
import logging
|
|
15
16
|
import pathlib
|
|
@@ -19,10 +20,16 @@ from operator import attrgetter, itemgetter
|
|
|
19
20
|
|
|
20
21
|
# Third party modules
|
|
21
22
|
from fb_tools.argparse_actions import RegexOptionAction
|
|
22
|
-
from fb_tools.common import
|
|
23
|
+
from fb_tools.common import is_sequence
|
|
24
|
+
from fb_tools.common import pp
|
|
25
|
+
from fb_tools.common import to_bool
|
|
23
26
|
from fb_tools.spinner import Spinner
|
|
24
27
|
from fb_tools.xlate import format_list
|
|
25
28
|
|
|
29
|
+
from rich import box
|
|
30
|
+
from rich.table import Table
|
|
31
|
+
from rich.text import Text
|
|
32
|
+
|
|
26
33
|
# Own modules
|
|
27
34
|
from . import BaseVmwareApplication, VmwareAppError
|
|
28
35
|
from .. import __version__ as GLOBAL_VERSION
|
|
@@ -30,7 +37,7 @@ from ..errors import VSphereExpectedError
|
|
|
30
37
|
from ..vm import VsphereVm
|
|
31
38
|
from ..xlate import XLATOR
|
|
32
39
|
|
|
33
|
-
__version__ = "1.
|
|
40
|
+
__version__ = "1.12.1"
|
|
34
41
|
LOG = logging.getLogger(__name__)
|
|
35
42
|
|
|
36
43
|
_ = XLATOR.gettext
|
|
@@ -44,6 +51,51 @@ class GetVmListAppError(VmwareAppError):
|
|
|
44
51
|
pass
|
|
45
52
|
|
|
46
53
|
|
|
54
|
+
# =============================================================================
|
|
55
|
+
class RegexListOptionAction(argparse.Action):
|
|
56
|
+
"""An argparse action for regular expressions."""
|
|
57
|
+
|
|
58
|
+
# -------------------------------------------------------------------------
|
|
59
|
+
def __init__(self, option_strings, topic, re_options=None, *args, **kwargs):
|
|
60
|
+
"""Initialise a RegexListOptionAction object."""
|
|
61
|
+
self._topic = topic
|
|
62
|
+
self._re_options = None
|
|
63
|
+
if re_options is not None:
|
|
64
|
+
self._re_options = re_options
|
|
65
|
+
|
|
66
|
+
super(RegexListOptionAction, self).__init__(*args, option_strings=option_strings, **kwargs)
|
|
67
|
+
|
|
68
|
+
# -------------------------------------------------------------------------
|
|
69
|
+
def __call__(self, parser, namespace, pattern, option_string=None):
|
|
70
|
+
"""Parse the regular expression option."""
|
|
71
|
+
try:
|
|
72
|
+
if is_sequence(pattern):
|
|
73
|
+
if len(pattern) > 1:
|
|
74
|
+
used_pattern = []
|
|
75
|
+
for pat in pattern:
|
|
76
|
+
used_pattern.append("(" + pat + ")")
|
|
77
|
+
pattern_all = "|".join(used_pattern)
|
|
78
|
+
elif len(pattern) == 1:
|
|
79
|
+
pattern_all = pattern[0]
|
|
80
|
+
else:
|
|
81
|
+
pattern_all = None
|
|
82
|
+
else:
|
|
83
|
+
pattern_all = pattern
|
|
84
|
+
|
|
85
|
+
if pattern_all is not None:
|
|
86
|
+
if self._re_options is None:
|
|
87
|
+
re_test = re.compile(pattern_all) # noqa
|
|
88
|
+
else:
|
|
89
|
+
re_test = re.compile(pattern_all, self._re_options) # noqa
|
|
90
|
+
except Exception as e:
|
|
91
|
+
msg = _("Got a {c} for pattern {p!r}: {e}").format(
|
|
92
|
+
c=e.__class__.__name__, p=pattern_all, e=e
|
|
93
|
+
)
|
|
94
|
+
raise argparse.ArgumentError(self, msg)
|
|
95
|
+
|
|
96
|
+
setattr(namespace, self.dest, pattern_all)
|
|
97
|
+
|
|
98
|
+
|
|
47
99
|
# =============================================================================
|
|
48
100
|
class GetVmListApplication(BaseVmwareApplication):
|
|
49
101
|
"""Class for the application objects."""
|
|
@@ -83,6 +135,7 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
83
135
|
|
|
84
136
|
self._vm_pattern = self.default_vm_pattern
|
|
85
137
|
self._details = False
|
|
138
|
+
self.count_templates = None
|
|
86
139
|
|
|
87
140
|
self.sort_keys = self.default_sort_keys
|
|
88
141
|
|
|
@@ -156,12 +209,10 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
156
209
|
filter_group = self.arg_parser.add_argument_group(_("Filter options"))
|
|
157
210
|
|
|
158
211
|
filter_group.add_argument(
|
|
159
|
-
"-p",
|
|
160
|
-
"--pattern",
|
|
161
|
-
"--search-pattern",
|
|
162
212
|
dest="vm_pattern",
|
|
213
|
+
nargs="*",
|
|
163
214
|
metavar="REGEX",
|
|
164
|
-
action=
|
|
215
|
+
action=RegexListOptionAction,
|
|
165
216
|
topic=_("for names of VMs"),
|
|
166
217
|
re_options=re.IGNORECASE,
|
|
167
218
|
help=_(
|
|
@@ -295,7 +346,7 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
295
346
|
else:
|
|
296
347
|
LOG.warn(
|
|
297
348
|
_(
|
|
298
|
-
"Sorting key {!r} not usable, if not detailed output
|
|
349
|
+
"Sorting key {!r} not usable, if not detailed output was given."
|
|
299
350
|
).format(key)
|
|
300
351
|
)
|
|
301
352
|
if not self.sort_keys:
|
|
@@ -335,10 +386,10 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
335
386
|
|
|
336
387
|
re_name = re.compile(self.vm_pattern, re.IGNORECASE)
|
|
337
388
|
|
|
338
|
-
if self.verbose:
|
|
389
|
+
if self.verbose or self.quiet:
|
|
339
390
|
for vsphere_name in self.vsphere:
|
|
340
391
|
all_vms += self.get_vms(vsphere_name, re_name)
|
|
341
|
-
|
|
392
|
+
else:
|
|
342
393
|
spin_prompt = _("Getting all vSphere VMs ...") + " "
|
|
343
394
|
spinner_name = self.get_random_spinner_name()
|
|
344
395
|
with Spinner(spin_prompt, spinner_name):
|
|
@@ -351,99 +402,101 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
351
402
|
if self.verbose > 1:
|
|
352
403
|
LOG.debug(_("Using sorting keys:") + " " + format_list(self.sort_keys, do_repr=True))
|
|
353
404
|
|
|
354
|
-
|
|
355
|
-
self.print_vms_detailed(all_vms)
|
|
356
|
-
else:
|
|
357
|
-
self.print_vms(all_vms)
|
|
405
|
+
self.print_virtual_machines(all_vms)
|
|
358
406
|
|
|
359
407
|
return ret
|
|
360
408
|
|
|
361
409
|
# -------------------------------------------------------------------------
|
|
362
|
-
def
|
|
410
|
+
def print_virtual_machines(self, all_vms):
|
|
363
411
|
"""Print out on STDOUT the list of found VMs."""
|
|
364
|
-
label_list = ("name", "vsphere", "dc", "path")
|
|
365
|
-
labels = {
|
|
366
|
-
"name": _("Host"),
|
|
367
|
-
"vsphere": "vSphere",
|
|
368
|
-
"dc": _("Data Center"),
|
|
369
|
-
"path": _("Path"),
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
self._print_vms(all_vms, label_list, labels)
|
|
373
|
-
|
|
374
|
-
# -------------------------------------------------------------------------
|
|
375
|
-
def print_vms_detailed(self, all_vms):
|
|
376
|
-
"""Print out on STDOUT the list of found VMs in a detailled way."""
|
|
377
|
-
label_list = self.avail_sort_keys
|
|
378
|
-
labels = {
|
|
379
|
-
"name": "VM/Template",
|
|
380
|
-
"vsphere": "vSphere",
|
|
381
|
-
"dc": _("Data Center"),
|
|
382
|
-
"cluster": _("Cluster"),
|
|
383
|
-
"path": _("Path"),
|
|
384
|
-
"type": _("Type"),
|
|
385
|
-
"onl_str": _("Online Status"),
|
|
386
|
-
"cfg_ver": _("Config Version"),
|
|
387
|
-
"os": _("Operating System"),
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
self._print_vms(all_vms, label_list, labels)
|
|
391
|
-
|
|
392
|
-
# -------------------------------------------------------------------------
|
|
393
|
-
def _print_vms(self, all_vms, label_list, labels):
|
|
394
|
-
|
|
395
|
-
str_lengths = {}
|
|
396
|
-
for label in labels.keys():
|
|
397
|
-
str_lengths[label] = len(labels[label])
|
|
398
|
-
|
|
399
|
-
max_len = 0
|
|
400
|
-
count = 0
|
|
401
|
-
for cdata in all_vms:
|
|
402
|
-
for field in ("cluster", "path", "type", "cfg_ver", "os"):
|
|
403
|
-
if field in labels and cdata[field] is None:
|
|
404
|
-
cdata[field] = "~"
|
|
405
|
-
for label in labels.keys():
|
|
406
|
-
val = cdata[label]
|
|
407
|
-
if len(val) > str_lengths[label]:
|
|
408
|
-
str_lengths[label] = len(val)
|
|
409
|
-
|
|
410
|
-
for label in labels.keys():
|
|
411
|
-
if max_len:
|
|
412
|
-
max_len += 2
|
|
413
|
-
max_len += str_lengths[label]
|
|
414
|
-
|
|
415
412
|
if self.verbose > 1:
|
|
416
|
-
LOG.debug("
|
|
417
|
-
LOG.debug("Max line length: {} chars".format(max_len))
|
|
418
|
-
|
|
419
|
-
tpl = ""
|
|
420
|
-
for label in label_list:
|
|
421
|
-
if tpl != "":
|
|
422
|
-
tpl += " "
|
|
423
|
-
tpl += "{{{la}:<{le}}}".format(la=label, le=str_lengths[label])
|
|
424
|
-
if self.verbose > 1:
|
|
425
|
-
LOG.debug(_("Line template: {}").format(tpl))
|
|
426
|
-
|
|
427
|
-
if not self.quiet:
|
|
428
|
-
print()
|
|
429
|
-
print(tpl.format(**labels))
|
|
430
|
-
print("-" * max_len)
|
|
413
|
+
LOG.debug("Print out VM list: " + pp(all_vms))
|
|
431
414
|
|
|
432
415
|
all_vms.sort(key=itemgetter(*self.sort_keys))
|
|
433
416
|
|
|
434
|
-
|
|
435
|
-
|
|
417
|
+
show_header = True
|
|
418
|
+
title = _("Virtual Machines")
|
|
419
|
+
title += "\n" + ("=" * len(title))
|
|
420
|
+
box_style = box.ROUNDED
|
|
421
|
+
if self.quiet:
|
|
422
|
+
show_header = False
|
|
423
|
+
title = None
|
|
424
|
+
box_style = None
|
|
425
|
+
|
|
426
|
+
if self.quiet:
|
|
427
|
+
caption = None
|
|
428
|
+
else:
|
|
429
|
+
count = len(all_vms)
|
|
430
|
+
if count:
|
|
431
|
+
caption = "\n" + ngettext(
|
|
432
|
+
"Found one virtual machine.",
|
|
433
|
+
"Found {} virtual machines.",
|
|
434
|
+
count,
|
|
435
|
+
).format(count)
|
|
436
|
+
else:
|
|
437
|
+
caption = "\n" + _("No virtual machines found.")
|
|
438
|
+
|
|
439
|
+
if self.count_templates is not None:
|
|
440
|
+
if self.count_templates:
|
|
441
|
+
caption += "\n" + ngettext(
|
|
442
|
+
"One VM of them is a template.",
|
|
443
|
+
"{} VMs of them are templates.",
|
|
444
|
+
self.count_templates,
|
|
445
|
+
).format(self.count_templates)
|
|
446
|
+
caption += "\n"
|
|
447
|
+
|
|
448
|
+
table = Table(
|
|
449
|
+
title=title,
|
|
450
|
+
title_style="bold cyan",
|
|
451
|
+
caption=caption,
|
|
452
|
+
caption_style="default on default",
|
|
453
|
+
caption_justify="left",
|
|
454
|
+
box=box_style,
|
|
455
|
+
show_header=show_header,
|
|
456
|
+
show_footer=False,
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
table.add_column(header="VM/Template")
|
|
460
|
+
table.add_column(header="vSphere")
|
|
461
|
+
table.add_column(header=_("Data Center"))
|
|
462
|
+
if self.details:
|
|
463
|
+
table.add_column(header=_("Cluster"))
|
|
464
|
+
table.add_column(header=_("Path"))
|
|
465
|
+
if self.details:
|
|
466
|
+
table.add_column(header=_("Type"))
|
|
467
|
+
table.add_column(header=_("Online Status"))
|
|
468
|
+
table.add_column(header=_("Config Version"))
|
|
469
|
+
table.add_column(header=_("Operating System"))
|
|
436
470
|
|
|
437
|
-
|
|
471
|
+
for vm in all_vms:
|
|
438
472
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
473
|
+
if self.details:
|
|
474
|
+
online_status = Text(vm["onl_str"], style="bold green")
|
|
475
|
+
if vm["is_template"]:
|
|
476
|
+
online_status = Text(vm["onl_str"], style="bold cyan")
|
|
477
|
+
elif not vm["is_online"]:
|
|
478
|
+
online_status = Text(vm["onl_str"], style="bold red")
|
|
479
|
+
|
|
480
|
+
table.add_row(
|
|
481
|
+
vm["name"],
|
|
482
|
+
vm["vsphere"],
|
|
483
|
+
vm["dc"],
|
|
484
|
+
vm["cluster"],
|
|
485
|
+
vm["path"],
|
|
486
|
+
vm["type"],
|
|
487
|
+
online_status,
|
|
488
|
+
vm["cfg_ver"],
|
|
489
|
+
vm["os"],
|
|
490
|
+
)
|
|
443
491
|
else:
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
492
|
+
table.add_row(
|
|
493
|
+
vm["name"],
|
|
494
|
+
vm["vsphere"],
|
|
495
|
+
vm["dc"],
|
|
496
|
+
vm["path"],
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
self.rich_console.print(table)
|
|
447
500
|
|
|
448
501
|
# -------------------------------------------------------------------------
|
|
449
502
|
def get_vms(self, vsphere_name, re_name=None):
|
|
@@ -455,10 +508,16 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
455
508
|
re_name = re.compile(self.vm_pattern, re.IGNORECASE)
|
|
456
509
|
|
|
457
510
|
if self.details:
|
|
458
|
-
vm_list = vsphere.get_vms(re_name, vsphere_name=vsphere_name, as_obj=True)
|
|
511
|
+
# vm_list = vsphere.get_vms(re_name, vsphere_name=vsphere_name, as_obj=True)
|
|
512
|
+
vm_list = vsphere.get_vm_list(
|
|
513
|
+
re_name, vsphere_name=vsphere_name, name_only=False, disconnect=True
|
|
514
|
+
)
|
|
459
515
|
vms = self.mangle_vmlist_details(vm_list, vsphere_name)
|
|
460
516
|
else:
|
|
461
|
-
vm_list = vsphere.get_vms(re_name, vsphere_name=vsphere_name, name_only=True)
|
|
517
|
+
# vm_list = vsphere.get_vms(re_name, vsphere_name=vsphere_name, name_only=True)
|
|
518
|
+
vm_list = vsphere.get_vm_list(
|
|
519
|
+
re_name, vsphere_name=vsphere_name, name_only=True, disconnect=True
|
|
520
|
+
)
|
|
462
521
|
vms = self.mangle_vmlist_no_details(vm_list, vsphere_name)
|
|
463
522
|
|
|
464
523
|
return vms
|
|
@@ -466,6 +525,8 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
466
525
|
# -------------------------------------------------------------------------
|
|
467
526
|
def mangle_vmlist_no_details(self, vm_list, vsphere_name):
|
|
468
527
|
"""Prepare the non-detailled data about found VMs for output."""
|
|
528
|
+
if self.verbose > 1:
|
|
529
|
+
LOG.debug(_("Performing VM list ..."))
|
|
469
530
|
if self.verbose > 3:
|
|
470
531
|
LOG.debug("Mangling VM list:\n" + pp(vm_list))
|
|
471
532
|
|
|
@@ -485,7 +546,7 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
485
546
|
}
|
|
486
547
|
|
|
487
548
|
if cdata["path"]:
|
|
488
|
-
cdata["path"] =
|
|
549
|
+
cdata["path"] = cdata["path"]
|
|
489
550
|
else:
|
|
490
551
|
cdata["path"] = "/"
|
|
491
552
|
|
|
@@ -501,8 +562,12 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
501
562
|
# -------------------------------------------------------------------------
|
|
502
563
|
def mangle_vmlist_details(self, vm_list, vsphere_name):
|
|
503
564
|
"""Prepare the detailled data about found VMs for output."""
|
|
565
|
+
if self.verbose > 1:
|
|
566
|
+
LOG.debug(_("Performing detailled VM list ..."))
|
|
504
567
|
vms = []
|
|
505
568
|
|
|
569
|
+
self.count_templates = 0
|
|
570
|
+
|
|
506
571
|
first = True
|
|
507
572
|
for vm in sorted(vm_list, key=attrgetter("name", "path")):
|
|
508
573
|
|
|
@@ -571,10 +636,12 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
571
636
|
"onl_str": "Online",
|
|
572
637
|
"cfg_ver": vm.config_version,
|
|
573
638
|
"os": vm.guest_id,
|
|
639
|
+
"is_online": True,
|
|
640
|
+
"is_template": False,
|
|
574
641
|
}
|
|
575
642
|
|
|
576
643
|
if cdata["path"]:
|
|
577
|
-
cdata["path"] =
|
|
644
|
+
cdata["path"] = cdata["path"]
|
|
578
645
|
else:
|
|
579
646
|
cdata["path"] = "/"
|
|
580
647
|
|
|
@@ -586,9 +653,12 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
586
653
|
|
|
587
654
|
if not vm.online:
|
|
588
655
|
cdata["onl_str"] = "Offline"
|
|
656
|
+
cdata["is_online"] = False
|
|
589
657
|
|
|
590
658
|
if vm.template:
|
|
591
659
|
cdata["type"] = "VMware Template"
|
|
660
|
+
cdata["is_template"] = True
|
|
661
|
+
self.count_templates += 1
|
|
592
662
|
|
|
593
663
|
return cdata
|
|
594
664
|
|
|
@@ -607,7 +677,11 @@ def main():
|
|
|
607
677
|
if app.verbose > 2:
|
|
608
678
|
print(_("{c}-Object:\n{a}").format(c=app.__class__.__name__, a=app), file=sys.stderr)
|
|
609
679
|
|
|
610
|
-
|
|
680
|
+
try:
|
|
681
|
+
app()
|
|
682
|
+
except KeyboardInterrupt:
|
|
683
|
+
print("\n" + app.colored(_("User interrupt."), "YELLOW"))
|
|
684
|
+
sys.exit(5)
|
|
611
685
|
|
|
612
686
|
sys.exit(0)
|
|
613
687
|
|