fb-vmware 1.8.0__tar.gz → 1.8.1__tar.gz
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-1.8.0 → fb_vmware-1.8.1}/PKG-INFO +1 -1
- fb_vmware-1.8.1/data/share/locale/de/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.8.1/data/share/locale/en/LC_MESSAGES/fb_vmware.mo +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/pyproject.toml +1 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/__init__.py +1 -1
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/__init__.py +1 -1
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_host_list.py +6 -8
- fb_vmware-1.8.1/src/fb_vmware/app/get_rpool_list.py +386 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_vm_list.py +3 -3
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/argparse_actions.py +5 -2
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/cluster.py +67 -4
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/connect.py +18 -5
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/host.py +1 -1
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/host_port_group.py +1 -2
- fb_vmware-1.8.0/data/share/locale/de/LC_MESSAGES/fb_vmware.mo +0 -0
- fb_vmware-1.8.0/data/share/locale/en/LC_MESSAGES/fb_vmware.mo +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/LICENSE +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/README.md +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/about.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_network_list.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_storage_cluster_info.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_storage_cluster_list.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_storage_list.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/get_vm_info.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/app/search_storage.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/base.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/config/__init__.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/controller.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/datastore.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/dc.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/disk.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/ds_cluster.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/dvs.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/errors.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/ether.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/iface.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/network.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/obj.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/typed_dict.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/vm.py +0 -0
- {fb_vmware-1.8.0 → fb_vmware-1.8.1}/src/fb_vmware/xlate.py +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -48,6 +48,7 @@ name = "fb_vmware"
|
|
|
48
48
|
directory = "data"
|
|
49
49
|
|
|
50
50
|
[project.scripts]
|
|
51
|
+
get-vsphere-cluster-list = "fb_vmware.app.get_rpool_list:main"
|
|
51
52
|
get-vsphere-host-list = "fb_vmware.app.get_host_list:main"
|
|
52
53
|
get-vsphere-network-list = "fb_vmware.app.get_network_list:main"
|
|
53
54
|
get-vsphere-storage-cluster-info = "fb_vmware.app.get_storage_cluster_info:main"
|
|
@@ -163,7 +163,7 @@ class BaseVmwareApplication(FbConfigApplication):
|
|
|
163
163
|
# -------------------------------------------------------------------------
|
|
164
164
|
def __del__(self):
|
|
165
165
|
"""Clean up in emergency case."""
|
|
166
|
-
if self.vsphere.keys():
|
|
166
|
+
if hasattr(self, "vsphere") and self.vsphere.keys():
|
|
167
167
|
self.cleaning_up()
|
|
168
168
|
|
|
169
169
|
# -------------------------------------------------------------------------
|
|
@@ -36,7 +36,7 @@ from ..errors import VSphereExpectedError
|
|
|
36
36
|
from ..host import VsphereHost
|
|
37
37
|
from ..xlate import XLATOR
|
|
38
38
|
|
|
39
|
-
__version__ = "1.5.
|
|
39
|
+
__version__ = "1.5.6"
|
|
40
40
|
LOG = logging.getLogger(__name__)
|
|
41
41
|
|
|
42
42
|
_ = XLATOR.gettext
|
|
@@ -73,9 +73,7 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
73
73
|
env_prefix=None,
|
|
74
74
|
):
|
|
75
75
|
"""Initialize a GetHostsListApplication object."""
|
|
76
|
-
desc = _(
|
|
77
|
-
"Tries to get a list of all physical hosts in " "VMware vSphere and print it out."
|
|
78
|
-
)
|
|
76
|
+
desc = _("Tries to get a list of all physical hosts in VMware vSphere and print it out.")
|
|
79
77
|
|
|
80
78
|
self._host_pattern = self.default_host_pattern
|
|
81
79
|
self.sort_keys = self.default_sort_keys
|
|
@@ -119,8 +117,6 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
119
117
|
# -------------------------------------------------------------------------
|
|
120
118
|
def init_arg_parser(self):
|
|
121
119
|
"""Public available method to initiate the argument parser."""
|
|
122
|
-
super(GetHostsListApplication, self).init_arg_parser()
|
|
123
|
-
|
|
124
120
|
filter_group = self.arg_parser.add_argument_group(_("Filter options"))
|
|
125
121
|
|
|
126
122
|
filter_group.add_argument(
|
|
@@ -172,6 +168,8 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
172
168
|
),
|
|
173
169
|
)
|
|
174
170
|
|
|
171
|
+
super(GetHostsListApplication, self).init_arg_parser()
|
|
172
|
+
|
|
175
173
|
# -------------------------------------------------------------------------
|
|
176
174
|
def perform_arg_parser(self):
|
|
177
175
|
"""Evaluate command line parameters."""
|
|
@@ -213,10 +211,10 @@ class GetHostsListApplication(BaseVmwareApplication):
|
|
|
213
211
|
ret = 0
|
|
214
212
|
all_hosts = []
|
|
215
213
|
|
|
216
|
-
if self.verbose:
|
|
214
|
+
if self.verbose or self.quiet:
|
|
217
215
|
for vsphere_name in self.vsphere:
|
|
218
216
|
all_hosts += self.get_hosts(vsphere_name)
|
|
219
|
-
|
|
217
|
+
else:
|
|
220
218
|
spin_prompt = _("Getting all vSphere hosts ...") + " "
|
|
221
219
|
spinner_name = self.get_random_spinner_name()
|
|
222
220
|
with Spinner(spin_prompt, spinner_name):
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
@summary: Print a list of all resouce pools in a VMware vSphere.
|
|
5
|
+
|
|
6
|
+
@author: Frank Brehm
|
|
7
|
+
@contact: frank@brehm-online.com
|
|
8
|
+
@copyright: © 2026 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 attrgetter
|
|
18
|
+
|
|
19
|
+
# Third party modules
|
|
20
|
+
from babel.numbers import format_decimal
|
|
21
|
+
|
|
22
|
+
from fb_tools.common import pp
|
|
23
|
+
from fb_tools.spinner import Spinner
|
|
24
|
+
from fb_tools.xlate import format_list
|
|
25
|
+
|
|
26
|
+
from rich import box
|
|
27
|
+
from rich.table import Table
|
|
28
|
+
from rich.text import Text
|
|
29
|
+
|
|
30
|
+
# Own modules
|
|
31
|
+
from . import BaseVmwareApplication, VmwareAppError
|
|
32
|
+
from .. import __version__ as GLOBAL_VERSION
|
|
33
|
+
from ..errors import VSphereExpectedError
|
|
34
|
+
from ..xlate import XLATOR
|
|
35
|
+
|
|
36
|
+
__version__ = "1.1.1"
|
|
37
|
+
LOG = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
_ = XLATOR.gettext
|
|
40
|
+
ngettext = XLATOR.ngettext
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# =============================================================================
|
|
44
|
+
class GetResPoolAppError(VmwareAppError):
|
|
45
|
+
"""Base exception class for all exceptions in this application."""
|
|
46
|
+
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# =============================================================================
|
|
51
|
+
class GetResPoolListApplication(BaseVmwareApplication):
|
|
52
|
+
"""Class for the application object."""
|
|
53
|
+
|
|
54
|
+
avail_sort_keys = ("name", "vsphere", "dc_name")
|
|
55
|
+
default_sort_keys = ["vsphere", "dc_name", "name"]
|
|
56
|
+
|
|
57
|
+
# -------------------------------------------------------------------------
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
appname=None,
|
|
61
|
+
verbose=0,
|
|
62
|
+
version=GLOBAL_VERSION,
|
|
63
|
+
base_dir=None,
|
|
64
|
+
initialized=False,
|
|
65
|
+
usage=None,
|
|
66
|
+
description=None,
|
|
67
|
+
argparse_epilog=None,
|
|
68
|
+
argparse_prefix_chars="-",
|
|
69
|
+
env_prefix=None,
|
|
70
|
+
):
|
|
71
|
+
"""Initialize a GetResPoolListApplication object."""
|
|
72
|
+
desc = _(
|
|
73
|
+
"Tries to get a list of all resource pools (a.k.a. computing resource and cluster "
|
|
74
|
+
"computing resource) in VMware vSphere and print it out."
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
self.sort_keys = self.default_sort_keys
|
|
78
|
+
|
|
79
|
+
super(GetResPoolListApplication, self).__init__(
|
|
80
|
+
appname=appname,
|
|
81
|
+
verbose=verbose,
|
|
82
|
+
version=version,
|
|
83
|
+
base_dir=base_dir,
|
|
84
|
+
description=desc,
|
|
85
|
+
initialized=False,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
self.initialized = True
|
|
89
|
+
|
|
90
|
+
# -------------------------------------------------------------------------
|
|
91
|
+
def init_arg_parser(self):
|
|
92
|
+
"""Public available method to initiate the argument parser."""
|
|
93
|
+
output_options = self.arg_parser.add_argument_group(_("Output options"))
|
|
94
|
+
|
|
95
|
+
output_options.add_argument(
|
|
96
|
+
"-S",
|
|
97
|
+
"--sort",
|
|
98
|
+
metavar="KEY",
|
|
99
|
+
nargs="+",
|
|
100
|
+
dest="sort_keys",
|
|
101
|
+
choices=self.avail_sort_keys,
|
|
102
|
+
help=_(
|
|
103
|
+
"The keys for sorting the output. Available keys are: {avail}. "
|
|
104
|
+
"The default sorting keys are: {default}."
|
|
105
|
+
).format(
|
|
106
|
+
avail=format_list(self.avail_sort_keys, do_repr=True),
|
|
107
|
+
default=format_list(self.default_sort_keys, do_repr=True),
|
|
108
|
+
),
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
super(GetResPoolListApplication, self).init_arg_parser()
|
|
112
|
+
|
|
113
|
+
# -------------------------------------------------------------------------
|
|
114
|
+
def perform_arg_parser(self):
|
|
115
|
+
"""Evaluate command line parameters."""
|
|
116
|
+
super(GetResPoolListApplication, self).perform_arg_parser()
|
|
117
|
+
|
|
118
|
+
if self.args.sort_keys:
|
|
119
|
+
self.sort_keys = self.args.sort_keys
|
|
120
|
+
|
|
121
|
+
# -------------------------------------------------------------------------
|
|
122
|
+
def _run(self):
|
|
123
|
+
|
|
124
|
+
LOG.debug(_("Starting {a!r}, version {v!r} ...").format(a=self.appname, v=self.version))
|
|
125
|
+
|
|
126
|
+
ret = 0
|
|
127
|
+
try:
|
|
128
|
+
ret = self.get_all_resource_pools()
|
|
129
|
+
except VSphereExpectedError as e:
|
|
130
|
+
LOG.error(str(e))
|
|
131
|
+
self.exit(6)
|
|
132
|
+
finally:
|
|
133
|
+
self.cleaning_up()
|
|
134
|
+
|
|
135
|
+
self.exit(ret)
|
|
136
|
+
|
|
137
|
+
# -------------------------------------------------------------------------
|
|
138
|
+
def get_all_resource_pools(self):
|
|
139
|
+
"""Collect all resource pools, a.k.a. (cluster) computing resources."""
|
|
140
|
+
ret = 0
|
|
141
|
+
all_rpools = []
|
|
142
|
+
|
|
143
|
+
if self.verbose or self.quiet:
|
|
144
|
+
for vsphere_name in self.vsphere:
|
|
145
|
+
all_rpools += self.get_resource_pools(vsphere_name)
|
|
146
|
+
else:
|
|
147
|
+
spin_prompt = _("Getting all vSphere hosts ...") + " "
|
|
148
|
+
spinner_name = self.get_random_spinner_name()
|
|
149
|
+
with Spinner(spin_prompt, spinner_name):
|
|
150
|
+
for vsphere_name in self.vsphere:
|
|
151
|
+
all_rpools += self.get_resource_pools(vsphere_name)
|
|
152
|
+
sys.stdout.write(" " * len(spin_prompt))
|
|
153
|
+
sys.stdout.write("\r")
|
|
154
|
+
sys.stdout.flush()
|
|
155
|
+
|
|
156
|
+
all_rpools.sort(key=attrgetter(*self.sort_keys))
|
|
157
|
+
|
|
158
|
+
if len(all_rpools):
|
|
159
|
+
out_list = []
|
|
160
|
+
out = ""
|
|
161
|
+
if self.verbose == 2:
|
|
162
|
+
LOG.debug(_("First computing resource:") + "\n" + pp(all_rpools[0].as_dict()))
|
|
163
|
+
for rpool in all_rpools:
|
|
164
|
+
out_list.append(
|
|
165
|
+
f" * Vsphere {rpool.vsphere:<10} - DC {rpool.dc_name:<12} - {rpool.name}"
|
|
166
|
+
)
|
|
167
|
+
out = "\n".join(out_list)
|
|
168
|
+
elif self.verbose > 2:
|
|
169
|
+
for rpool in all_rpools:
|
|
170
|
+
out_list.append(rpool.as_dict())
|
|
171
|
+
out = pp(out_list)
|
|
172
|
+
if self.verbose >= 2:
|
|
173
|
+
LOG.debug("All computing resources:\n{}".format(out))
|
|
174
|
+
|
|
175
|
+
self.print_rpools(all_rpools)
|
|
176
|
+
else:
|
|
177
|
+
LOG.error(_("Did not found any resource pools or cluster resource pools."))
|
|
178
|
+
if not self.quiet:
|
|
179
|
+
print()
|
|
180
|
+
ret = 3
|
|
181
|
+
|
|
182
|
+
return ret
|
|
183
|
+
|
|
184
|
+
# -------------------------------------------------------------------------
|
|
185
|
+
def get_resource_pools(self, vsphere_name):
|
|
186
|
+
"""Get all host of all (cluster) computing resources in a VMware vSphere."""
|
|
187
|
+
clusters = []
|
|
188
|
+
|
|
189
|
+
vsphere = self.vsphere[vsphere_name]
|
|
190
|
+
|
|
191
|
+
vsphere.get_clusters(vsphere_name=vsphere_name)
|
|
192
|
+
|
|
193
|
+
for cluster in sorted(vsphere.clusters):
|
|
194
|
+
clusters.append(cluster)
|
|
195
|
+
|
|
196
|
+
return clusters
|
|
197
|
+
|
|
198
|
+
# -------------------------------------------------------------------------
|
|
199
|
+
def print_rpools(self, rpools):
|
|
200
|
+
"""Print on STDOUT all information about cluster) computing resources."""
|
|
201
|
+
show_header = True
|
|
202
|
+
show_footer = True
|
|
203
|
+
table_title = _("All compute resources and cluster compute resources") + "\n"
|
|
204
|
+
box_style = box.ROUNDED
|
|
205
|
+
|
|
206
|
+
if self.quiet:
|
|
207
|
+
show_header = False
|
|
208
|
+
show_footer = False
|
|
209
|
+
table_title = None
|
|
210
|
+
box_style = None
|
|
211
|
+
|
|
212
|
+
if self.quiet:
|
|
213
|
+
caption = None
|
|
214
|
+
else:
|
|
215
|
+
count = len(rpools)
|
|
216
|
+
if count:
|
|
217
|
+
caption = "\n" + ngettext(
|
|
218
|
+
"Found one compute resource.",
|
|
219
|
+
"Found {} compute resources.",
|
|
220
|
+
count,
|
|
221
|
+
).format(count)
|
|
222
|
+
else:
|
|
223
|
+
caption = "\n" + _("Found no compute resources.")
|
|
224
|
+
|
|
225
|
+
totals = self._get_totals(rpools)
|
|
226
|
+
|
|
227
|
+
table = Table(
|
|
228
|
+
title=table_title,
|
|
229
|
+
title_style="bold cyan",
|
|
230
|
+
caption=caption,
|
|
231
|
+
caption_style="default on default",
|
|
232
|
+
caption_justify="left",
|
|
233
|
+
box=box_style,
|
|
234
|
+
show_header=show_header,
|
|
235
|
+
show_footer=show_footer,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
table.add_column(header=_("vSphere"), footer=_("Total:"))
|
|
239
|
+
table.add_column(header=_("Data Center"), footer="")
|
|
240
|
+
table.add_column(header=_("Name"), footer="")
|
|
241
|
+
table.add_column(header=_("Cluster"), footer="")
|
|
242
|
+
table.add_column(header=_("Pool name"), footer="")
|
|
243
|
+
table.add_column(
|
|
244
|
+
header=_("Hosts total"),
|
|
245
|
+
justify="right",
|
|
246
|
+
footer=self._prepare_number(totals["hosts_total"], warn_on_value1=True),
|
|
247
|
+
)
|
|
248
|
+
table.add_column(
|
|
249
|
+
header=_("Hosts available"),
|
|
250
|
+
justify="right",
|
|
251
|
+
footer=self._prepare_number(
|
|
252
|
+
totals["hosts_avail"],
|
|
253
|
+
warn_on_value1=True,
|
|
254
|
+
compare_val=totals["hosts_total"],
|
|
255
|
+
),
|
|
256
|
+
)
|
|
257
|
+
table.add_column(
|
|
258
|
+
header=_("CPU cores"),
|
|
259
|
+
justify="right",
|
|
260
|
+
footer=self._prepare_number(totals["cpu_cores"]),
|
|
261
|
+
)
|
|
262
|
+
table.add_column(
|
|
263
|
+
header=_("CPU threads"),
|
|
264
|
+
justify="right",
|
|
265
|
+
footer=self._prepare_number(totals["cpu_threads"]),
|
|
266
|
+
)
|
|
267
|
+
table.add_column(
|
|
268
|
+
header=_("Memory total"),
|
|
269
|
+
justify="right",
|
|
270
|
+
footer=self._prepare_number(totals["mem_total"]),
|
|
271
|
+
)
|
|
272
|
+
table.add_column(
|
|
273
|
+
header=_("Memory available"),
|
|
274
|
+
justify="right",
|
|
275
|
+
footer=self._prepare_number(totals["mem_avail"], compare_val=totals["mem_total"]),
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
for rpool in rpools:
|
|
279
|
+
row = []
|
|
280
|
+
row.append(rpool.vsphere)
|
|
281
|
+
row.append(rpool.dc_name)
|
|
282
|
+
row.append(rpool.name)
|
|
283
|
+
|
|
284
|
+
is_cluster = Text(_("Yes"), style="bold green")
|
|
285
|
+
if rpool.standalone:
|
|
286
|
+
is_cluster = Text(_("No"), style="green")
|
|
287
|
+
|
|
288
|
+
row.append(is_cluster)
|
|
289
|
+
row.append(rpool.base_resource_pool_name)
|
|
290
|
+
row.append(self._prepare_number(rpool.hosts_total, warn_on_value1=True))
|
|
291
|
+
row.append(
|
|
292
|
+
self._prepare_number(
|
|
293
|
+
rpool.hosts_effective,
|
|
294
|
+
warn_on_value1=True,
|
|
295
|
+
compare_val=rpool.hosts_total,
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
row.append(self._prepare_number(rpool.cpu_cores))
|
|
299
|
+
row.append(self._prepare_number(rpool.cpu_threads))
|
|
300
|
+
row.append(self._prepare_number(rpool.mem_mb_total))
|
|
301
|
+
row.append(
|
|
302
|
+
self._prepare_number(rpool.mem_mb_effective, compare_val=rpool.mem_mb_total)
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
table.add_row(*row)
|
|
306
|
+
|
|
307
|
+
self.rich_console.print(table)
|
|
308
|
+
|
|
309
|
+
if not self.quiet:
|
|
310
|
+
print()
|
|
311
|
+
|
|
312
|
+
# -------------------------------------------------------------------------
|
|
313
|
+
def _get_totals(self, rpools):
|
|
314
|
+
|
|
315
|
+
totals = {
|
|
316
|
+
"hosts_total": 0,
|
|
317
|
+
"hosts_avail": 0,
|
|
318
|
+
"cpu_cores": 0,
|
|
319
|
+
"cpu_threads": 0,
|
|
320
|
+
"mem_total": 0,
|
|
321
|
+
"mem_avail": 0,
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
for rpool in rpools:
|
|
325
|
+
totals["hosts_total"] += rpool.hosts_total
|
|
326
|
+
totals["hosts_avail"] += rpool.hosts_effective
|
|
327
|
+
totals["cpu_cores"] += rpool.cpu_cores
|
|
328
|
+
totals["cpu_threads"] += rpool.cpu_threads
|
|
329
|
+
totals["mem_total"] += rpool.mem_mb_total
|
|
330
|
+
totals["mem_avail"] += rpool.mem_mb_effective
|
|
331
|
+
|
|
332
|
+
return totals
|
|
333
|
+
|
|
334
|
+
# -------------------------------------------------------------------------
|
|
335
|
+
def _prepare_number(self, value, may_zero=False, warn_on_value1=False, compare_val=None):
|
|
336
|
+
|
|
337
|
+
if value is None:
|
|
338
|
+
return ""
|
|
339
|
+
|
|
340
|
+
try:
|
|
341
|
+
int_val = int(value)
|
|
342
|
+
except ValueError:
|
|
343
|
+
return value
|
|
344
|
+
|
|
345
|
+
val_str = format_decimal(int_val, format="#,##0")
|
|
346
|
+
if not may_zero and int_val == 0:
|
|
347
|
+
val_str = Text(val_str, style="bold red")
|
|
348
|
+
elif warn_on_value1 and int_val == 1:
|
|
349
|
+
val_str = Text(val_str, style="bold yellow")
|
|
350
|
+
elif compare_val is not None and int_val < compare_val:
|
|
351
|
+
val_str = Text(val_str, style="bold yellow")
|
|
352
|
+
|
|
353
|
+
return val_str
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
# =============================================================================
|
|
357
|
+
def main():
|
|
358
|
+
"""Entrypoint for get-vsphere-cluster-list."""
|
|
359
|
+
my_path = pathlib.Path(__file__)
|
|
360
|
+
appname = my_path.name
|
|
361
|
+
|
|
362
|
+
locale.setlocale(locale.LC_ALL, "")
|
|
363
|
+
|
|
364
|
+
app = GetResPoolListApplication(appname=appname)
|
|
365
|
+
app.initialized = True
|
|
366
|
+
|
|
367
|
+
if app.verbose > 2:
|
|
368
|
+
print(_("{c}-Object:\n{a}").format(c=app.__class__.__name__, a=app), file=sys.stderr)
|
|
369
|
+
|
|
370
|
+
try:
|
|
371
|
+
app()
|
|
372
|
+
except KeyboardInterrupt:
|
|
373
|
+
print("\n" + app.colored(_("User interrupt."), "YELLOW"))
|
|
374
|
+
sys.exit(5)
|
|
375
|
+
|
|
376
|
+
sys.exit(0)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
# =============================================================================
|
|
380
|
+
if __name__ == "__main__":
|
|
381
|
+
|
|
382
|
+
pass
|
|
383
|
+
|
|
384
|
+
# =============================================================================
|
|
385
|
+
|
|
386
|
+
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list
|
|
@@ -37,7 +37,7 @@ from ..errors import VSphereExpectedError
|
|
|
37
37
|
from ..vm import VsphereVm
|
|
38
38
|
from ..xlate import XLATOR
|
|
39
39
|
|
|
40
|
-
__version__ = "1.12.
|
|
40
|
+
__version__ = "1.12.1"
|
|
41
41
|
LOG = logging.getLogger(__name__)
|
|
42
42
|
|
|
43
43
|
_ = XLATOR.gettext
|
|
@@ -386,10 +386,10 @@ class GetVmListApplication(BaseVmwareApplication):
|
|
|
386
386
|
|
|
387
387
|
re_name = re.compile(self.vm_pattern, re.IGNORECASE)
|
|
388
388
|
|
|
389
|
-
if self.verbose:
|
|
389
|
+
if self.verbose or self.quiet:
|
|
390
390
|
for vsphere_name in self.vsphere:
|
|
391
391
|
all_vms += self.get_vms(vsphere_name, re_name)
|
|
392
|
-
|
|
392
|
+
else:
|
|
393
393
|
spin_prompt = _("Getting all vSphere VMs ...") + " "
|
|
394
394
|
spinner_name = self.get_random_spinner_name()
|
|
395
395
|
with Spinner(spin_prompt, spinner_name):
|
|
@@ -11,6 +11,7 @@ from __future__ import absolute_import
|
|
|
11
11
|
# Standard modules
|
|
12
12
|
import argparse
|
|
13
13
|
import logging
|
|
14
|
+
|
|
14
15
|
# import os
|
|
15
16
|
# from pathlib import Path
|
|
16
17
|
|
|
@@ -20,7 +21,7 @@ import logging
|
|
|
20
21
|
# Own modules
|
|
21
22
|
from .xlate import XLATOR
|
|
22
23
|
|
|
23
|
-
__version__ = "0.1.
|
|
24
|
+
__version__ = "0.1.2"
|
|
24
25
|
LOG = logging.getLogger(__name__)
|
|
25
26
|
|
|
26
27
|
_ = XLATOR.gettext
|
|
@@ -40,7 +41,9 @@ class NonNegativeIntegerOptionAction(argparse.Action):
|
|
|
40
41
|
self.may_zero = bool(may_zero)
|
|
41
42
|
|
|
42
43
|
super(NonNegativeIntegerOptionAction, self).__init__(
|
|
43
|
-
*args,
|
|
44
|
+
*args,
|
|
45
|
+
**kwargs,
|
|
46
|
+
option_strings=option_strings,
|
|
44
47
|
)
|
|
45
48
|
|
|
46
49
|
# -------------------------------------------------------------------------
|
|
@@ -19,12 +19,13 @@ from fb_tools.xlate import format_list
|
|
|
19
19
|
from pyVmomi import vim
|
|
20
20
|
|
|
21
21
|
# Own modules
|
|
22
|
+
from .errors import VSphereHandlerError
|
|
22
23
|
from .errors import VSphereNameError
|
|
23
24
|
from .obj import DEFAULT_OBJ_STATUS
|
|
24
25
|
from .obj import VsphereObject
|
|
25
26
|
from .xlate import XLATOR
|
|
26
27
|
|
|
27
|
-
__version__ = "1.
|
|
28
|
+
__version__ = "1.9.2"
|
|
28
29
|
LOG = logging.getLogger(__name__)
|
|
29
30
|
|
|
30
31
|
|
|
@@ -35,6 +36,8 @@ _ = XLATOR.gettext
|
|
|
35
36
|
class VsphereCluster(VsphereObject):
|
|
36
37
|
"""An object for encapsulating a vSphere calculation cluster object."""
|
|
37
38
|
|
|
39
|
+
default_resource_pool_name = "Resources"
|
|
40
|
+
|
|
38
41
|
# -------------------------------------------------------------------------
|
|
39
42
|
def __init__(
|
|
40
43
|
self,
|
|
@@ -43,9 +46,11 @@ class VsphereCluster(VsphereObject):
|
|
|
43
46
|
version=__version__,
|
|
44
47
|
base_dir=None,
|
|
45
48
|
initialized=None,
|
|
49
|
+
vsphere=None,
|
|
46
50
|
dc_name=None,
|
|
47
51
|
name=None,
|
|
48
52
|
status=DEFAULT_OBJ_STATUS,
|
|
53
|
+
resource_pool_name=None,
|
|
49
54
|
cpu_cores=0,
|
|
50
55
|
cpu_threads=0,
|
|
51
56
|
config_status=DEFAULT_OBJ_STATUS,
|
|
@@ -80,7 +85,9 @@ class VsphereCluster(VsphereObject):
|
|
|
80
85
|
self._mem_mb_effective = None
|
|
81
86
|
self._mem_total = None
|
|
82
87
|
self._standalone = False
|
|
88
|
+
self._vsphere = None
|
|
83
89
|
self._dc_name = None
|
|
90
|
+
self._resource_pool_name = self.default_resource_pool_name
|
|
84
91
|
self.networks = []
|
|
85
92
|
self.datastores = []
|
|
86
93
|
self.resource_pool = None
|
|
@@ -98,6 +105,8 @@ class VsphereCluster(VsphereObject):
|
|
|
98
105
|
)
|
|
99
106
|
|
|
100
107
|
self.dc_name = dc_name
|
|
108
|
+
if vsphere is not None:
|
|
109
|
+
self.vsphere = vsphere
|
|
101
110
|
self.cpu_cores = cpu_cores
|
|
102
111
|
self.cpu_threads = cpu_threads
|
|
103
112
|
self.hosts_effective = hosts_effective
|
|
@@ -106,9 +115,31 @@ class VsphereCluster(VsphereObject):
|
|
|
106
115
|
self.mem_total = mem_total
|
|
107
116
|
self.standalone = standalone
|
|
108
117
|
|
|
118
|
+
if resource_pool_name is not None and str(resource_pool_name).strip() != "":
|
|
119
|
+
self._resource_pool_name = str(resource_pool_name).strip()
|
|
120
|
+
|
|
109
121
|
if initialized is not None:
|
|
110
122
|
self.initialized = initialized
|
|
111
123
|
|
|
124
|
+
# -----------------------------------------------------------
|
|
125
|
+
@property
|
|
126
|
+
def vsphere(self):
|
|
127
|
+
"""Return the name of the vSphere from configuration of the cluster."""
|
|
128
|
+
return self._vsphere
|
|
129
|
+
|
|
130
|
+
@vsphere.setter
|
|
131
|
+
def vsphere(self, value):
|
|
132
|
+
if value is None:
|
|
133
|
+
self._vsphere = None
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
val = str(value).strip()
|
|
137
|
+
if val == "":
|
|
138
|
+
msg = _("The name of the vSphere may not be empty.")
|
|
139
|
+
raise VSphereHandlerError(msg)
|
|
140
|
+
|
|
141
|
+
self._vsphere = val
|
|
142
|
+
|
|
112
143
|
# -----------------------------------------------------------
|
|
113
144
|
@property
|
|
114
145
|
def dc_name(self):
|
|
@@ -128,11 +159,17 @@ class VsphereCluster(VsphereObject):
|
|
|
128
159
|
|
|
129
160
|
self._dc_name = val
|
|
130
161
|
|
|
162
|
+
# -----------------------------------------------------------
|
|
163
|
+
@property
|
|
164
|
+
def base_resource_pool_name(self):
|
|
165
|
+
"""Return the base name of the default resource pool of this cluster."""
|
|
166
|
+
return self._resource_pool_name
|
|
167
|
+
|
|
131
168
|
# -----------------------------------------------------------
|
|
132
169
|
@property
|
|
133
170
|
def resource_pool_name(self):
|
|
134
171
|
"""Return the name of the default resource pool of this cluster."""
|
|
135
|
-
return self.name
|
|
172
|
+
return f"{self.name}/{self.base_resource_pool_name}"
|
|
136
173
|
|
|
137
174
|
# -----------------------------------------------------------
|
|
138
175
|
@property
|
|
@@ -306,7 +343,9 @@ class VsphereCluster(VsphereObject):
|
|
|
306
343
|
"""
|
|
307
344
|
res = super(VsphereCluster, self).as_dict(short=short)
|
|
308
345
|
|
|
346
|
+
res["vsphere"] = self.vsphere
|
|
309
347
|
res["dc_name"] = self.dc_name
|
|
348
|
+
res["base_resource_pool_name"] = self.base_resource_pool_name
|
|
310
349
|
res["resource_pool_name"] = self.resource_pool_name
|
|
311
350
|
res["resource_pool_var"] = self.resource_pool_var
|
|
312
351
|
res["cpu_cores"] = self.cpu_cores
|
|
@@ -339,7 +378,9 @@ class VsphereCluster(VsphereObject):
|
|
|
339
378
|
base_dir=self.base_dir,
|
|
340
379
|
initialized=self.initialized,
|
|
341
380
|
name=self.name,
|
|
381
|
+
vsphere=self.vsphere,
|
|
342
382
|
dc_name=self.dc_name,
|
|
383
|
+
resource_pool_name=self.base_resource_pool_name,
|
|
343
384
|
standalone=self.standalone,
|
|
344
385
|
status=self.status,
|
|
345
386
|
cpu_cores=self.cpu_cores,
|
|
@@ -359,9 +400,10 @@ class VsphereCluster(VsphereObject):
|
|
|
359
400
|
if not isinstance(other, VsphereCluster):
|
|
360
401
|
return False
|
|
361
402
|
|
|
403
|
+
if self.vsphere != other.vsphere:
|
|
404
|
+
return False
|
|
362
405
|
if self.dc_name != other.dc_name:
|
|
363
406
|
return False
|
|
364
|
-
|
|
365
407
|
if self.name != other.name:
|
|
366
408
|
return False
|
|
367
409
|
|
|
@@ -370,7 +412,14 @@ class VsphereCluster(VsphereObject):
|
|
|
370
412
|
# -------------------------------------------------------------------------
|
|
371
413
|
@classmethod
|
|
372
414
|
def from_summary(
|
|
373
|
-
cls,
|
|
415
|
+
cls,
|
|
416
|
+
data,
|
|
417
|
+
vsphere=None,
|
|
418
|
+
dc_name=None,
|
|
419
|
+
appname=None,
|
|
420
|
+
verbose=0,
|
|
421
|
+
base_dir=None,
|
|
422
|
+
test_mode=False,
|
|
374
423
|
):
|
|
375
424
|
"""Create a new VsphereCluster object based on the appropriate data from pyvomi."""
|
|
376
425
|
if test_mode:
|
|
@@ -387,7 +436,9 @@ class VsphereCluster(VsphereObject):
|
|
|
387
436
|
"verbose": verbose,
|
|
388
437
|
"base_dir": base_dir,
|
|
389
438
|
"initialized": True,
|
|
439
|
+
"vsphere": vsphere,
|
|
390
440
|
"dc_name": dc_name,
|
|
441
|
+
"resource_pool_name": cls.default_resource_pool_name,
|
|
391
442
|
"name": data.name,
|
|
392
443
|
"status": data.overallStatus,
|
|
393
444
|
"config_status": data.configStatus,
|
|
@@ -402,6 +453,18 @@ class VsphereCluster(VsphereObject):
|
|
|
402
453
|
if isinstance(data, vim.ClusterComputeResource):
|
|
403
454
|
params["standalone"] = False
|
|
404
455
|
|
|
456
|
+
if hasattr(data, "resourcePool"):
|
|
457
|
+
rname = data.resourcePool.summary.name
|
|
458
|
+
if verbose > 0:
|
|
459
|
+
LOG.debug(f"Name of resource pool of {data.name!r}: {rname!r}")
|
|
460
|
+
params["resource_pool_name"] = rname
|
|
461
|
+
else:
|
|
462
|
+
msg = _(
|
|
463
|
+
"Could not access to resource pool of compute resource {cc!r} in vSphere {vs!r}, "
|
|
464
|
+
"datacenter {dc!r}."
|
|
465
|
+
).format(cc=data.name, vs=vsphere, dc=dc_name)
|
|
466
|
+
LOG.warn(msg)
|
|
467
|
+
|
|
405
468
|
if verbose > 2:
|
|
406
469
|
LOG.debug(_("Creating {} object from:").format(cls.__name__) + "\n" + pp(params))
|
|
407
470
|
|
|
@@ -55,7 +55,7 @@ from .network import VsphereNetwork, VsphereNetworkDict
|
|
|
55
55
|
from .vm import VsphereVm, VsphereVmList
|
|
56
56
|
from .xlate import XLATOR
|
|
57
57
|
|
|
58
|
-
__version__ = "2.11.
|
|
58
|
+
__version__ = "2.11.3"
|
|
59
59
|
LOG = logging.getLogger(__name__)
|
|
60
60
|
|
|
61
61
|
DEFAULT_OS_VERSION = "rhel9_64Guest"
|
|
@@ -279,12 +279,15 @@ class VsphereConnection(BaseVsphereHandler):
|
|
|
279
279
|
return
|
|
280
280
|
|
|
281
281
|
# -------------------------------------------------------------------------
|
|
282
|
-
def get_clusters(self, search_in_dc=None, disconnect=False):
|
|
282
|
+
def get_clusters(self, vsphere_name=None, search_in_dc=None, disconnect=False):
|
|
283
283
|
"""Get all computing clusters from vSphere as VsphereCluster objects."""
|
|
284
284
|
LOG.debug(_("Trying to get all clusters from vSphere ..."))
|
|
285
285
|
|
|
286
286
|
self.clusters = []
|
|
287
287
|
|
|
288
|
+
if vsphere_name is None:
|
|
289
|
+
vsphere_name = self.name
|
|
290
|
+
|
|
288
291
|
try:
|
|
289
292
|
|
|
290
293
|
if not self.service_instance:
|
|
@@ -302,7 +305,7 @@ class VsphereConnection(BaseVsphereHandler):
|
|
|
302
305
|
dc = self.get_obj(content, [vim.Datacenter], dc_name)
|
|
303
306
|
|
|
304
307
|
for child in dc.hostFolder.childEntity:
|
|
305
|
-
self._get_clusters(child, dc_name=dc_name)
|
|
308
|
+
self._get_clusters(child, vsphere_name=vsphere_name, dc_name=dc_name)
|
|
306
309
|
|
|
307
310
|
finally:
|
|
308
311
|
if disconnect:
|
|
@@ -320,13 +323,21 @@ class VsphereConnection(BaseVsphereHandler):
|
|
|
320
323
|
LOG.debug(_("Found clusters:") + "\n" + pp(out))
|
|
321
324
|
|
|
322
325
|
# -------------------------------------------------------------------------
|
|
323
|
-
def _get_clusters(self, child, dc_name=None, depth=1):
|
|
326
|
+
def _get_clusters(self, child, vsphere_name=None, dc_name=None, depth=1):
|
|
327
|
+
|
|
328
|
+
if vsphere_name is None:
|
|
329
|
+
vsphere_name = self.name
|
|
324
330
|
|
|
325
331
|
if hasattr(child, "childEntity"):
|
|
326
332
|
if depth > self.max_search_depth:
|
|
327
333
|
return
|
|
328
334
|
for sub_child in child.childEntity:
|
|
329
|
-
self._get_clusters(
|
|
335
|
+
self._get_clusters(
|
|
336
|
+
sub_child,
|
|
337
|
+
vsphere_name=vsphere_name,
|
|
338
|
+
dc_name=dc_name,
|
|
339
|
+
depth=(depth + 1),
|
|
340
|
+
)
|
|
330
341
|
return
|
|
331
342
|
|
|
332
343
|
if isinstance(child, (vim.ClusterComputeResource, vim.ComputeResource)):
|
|
@@ -335,6 +346,7 @@ class VsphereConnection(BaseVsphereHandler):
|
|
|
335
346
|
appname=self.appname,
|
|
336
347
|
verbose=self.verbose,
|
|
337
348
|
base_dir=self.base_dir,
|
|
349
|
+
vsphere=vsphere_name,
|
|
338
350
|
dc_name=dc_name,
|
|
339
351
|
)
|
|
340
352
|
if self.verbose > 1:
|
|
@@ -891,6 +903,7 @@ class VsphereConnection(BaseVsphereHandler):
|
|
|
891
903
|
if isinstance(child, (vim.ClusterComputeResource, vim.ComputeResource)):
|
|
892
904
|
cluster = VsphereCluster.from_summary(
|
|
893
905
|
child,
|
|
906
|
+
vsphere=vsphere_name,
|
|
894
907
|
dc_name=dc_name,
|
|
895
908
|
appname=self.appname,
|
|
896
909
|
verbose=self.verbose,
|
|
@@ -394,7 +394,7 @@ class VsphereHost(VsphereObject):
|
|
|
394
394
|
# -----------------------------------------------------------
|
|
395
395
|
@property
|
|
396
396
|
def vsphere(self):
|
|
397
|
-
"""Return the name of the vSphere from configuration
|
|
397
|
+
"""Return the name of the vSphere from configuration of the host."""
|
|
398
398
|
return self._vsphere
|
|
399
399
|
|
|
400
400
|
@vsphere.setter
|
|
@@ -20,7 +20,6 @@ except ImportError:
|
|
|
20
20
|
|
|
21
21
|
# Third party modules
|
|
22
22
|
from fb_tools.common import pp
|
|
23
|
-
# from fb_tools.common import to_bool
|
|
24
23
|
from fb_tools.obj import FbBaseObject
|
|
25
24
|
from fb_tools.xlate import format_list
|
|
26
25
|
|
|
@@ -29,7 +28,7 @@ from pyVmomi import vim
|
|
|
29
28
|
# Own modules
|
|
30
29
|
from .xlate import XLATOR
|
|
31
30
|
|
|
32
|
-
__version__ = "1.0.
|
|
31
|
+
__version__ = "1.0.3"
|
|
33
32
|
LOG = logging.getLogger(__name__)
|
|
34
33
|
|
|
35
34
|
_ = XLATOR.gettext
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|