Skip to content

Commit e708ddc

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Moved hypervisor to the SDK"
2 parents 06afa9b + 006e355 commit e708ddc

4 files changed

Lines changed: 303 additions & 201 deletions

File tree

openstackclient/compute/v2/hypervisor.py

Lines changed: 99 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import json
1919
import re
2020

21-
from novaclient import api_versions
2221
from novaclient import exceptions as nova_exceptions
22+
from openstack import utils as sdk_utils
2323
from osc_lib.cli import format_columns
2424
from osc_lib.command import command
2525
from osc_lib import exceptions
@@ -28,11 +28,44 @@
2828
from openstackclient.i18n import _
2929

3030

31+
def _get_hypervisor_columns(item, client):
32+
column_map = {'name': 'hypervisor_hostname'}
33+
hidden_columns = ['location', 'servers']
34+
35+
if sdk_utils.supports_microversion(client, '2.88'):
36+
hidden_columns.extend([
37+
'current_workload',
38+
'disk_available',
39+
'local_disk_free',
40+
'local_disk_size',
41+
'local_disk_used',
42+
'memory_free',
43+
'memory_size',
44+
'memory_used',
45+
'running_vms',
46+
'vcpus_used',
47+
'vcpus',
48+
])
49+
else:
50+
column_map.update({
51+
'disk_available': 'disk_available_least',
52+
'local_disk_free': 'free_disk_gb',
53+
'local_disk_size': 'local_gb',
54+
'local_disk_used': 'local_gb_used',
55+
'memory_free': 'free_ram_mb',
56+
'memory_used': 'memory_mb_used',
57+
'memory_size': 'memory_mb',
58+
})
59+
60+
return utils.get_osc_show_columns_for_sdk_resource(
61+
item, column_map, hidden_columns)
62+
63+
3164
class ListHypervisor(command.Lister):
3265
_description = _("List hypervisors")
3366

3467
def get_parser(self, prog_name):
35-
parser = super(ListHypervisor, self).get_parser(prog_name)
68+
parser = super().get_parser(prog_name)
3669
parser.add_argument(
3770
'--matching',
3871
metavar='<hostname>',
@@ -67,7 +100,7 @@ def get_parser(self, prog_name):
67100
return parser
68101

69102
def take_action(self, parsed_args):
70-
compute_client = self.app.client_manager.compute
103+
compute_client = self.app.client_manager.sdk_connection.compute
71104

72105
list_opts = {}
73106

@@ -78,7 +111,7 @@ def take_action(self, parsed_args):
78111
raise exceptions.CommandError(msg)
79112

80113
if parsed_args.marker:
81-
if compute_client.api_version < api_versions.APIVersion('2.33'):
114+
if not sdk_utils.supports_microversion(compute_client, '2.33'):
82115
msg = _(
83116
'--os-compute-api-version 2.33 or greater is required to '
84117
'support the --marker option'
@@ -87,31 +120,51 @@ def take_action(self, parsed_args):
87120
list_opts['marker'] = parsed_args.marker
88121

89122
if parsed_args.limit:
90-
if compute_client.api_version < api_versions.APIVersion('2.33'):
123+
if not sdk_utils.supports_microversion(compute_client, '2.33'):
91124
msg = _(
92125
'--os-compute-api-version 2.33 or greater is required to '
93126
'support the --limit option'
94127
)
95128
raise exceptions.CommandError(msg)
96129
list_opts['limit'] = parsed_args.limit
97130

98-
columns = (
131+
column_headers = (
99132
"ID",
100133
"Hypervisor Hostname",
101134
"Hypervisor Type",
102135
"Host IP",
103136
"State"
104137
)
138+
columns = (
139+
'id',
140+
'name',
141+
'hypervisor_type',
142+
'host_ip',
143+
'state'
144+
)
105145
if parsed_args.long:
106-
columns += ("vCPUs Used", "vCPUs", "Memory MB Used", "Memory MB")
146+
if not sdk_utils.supports_microversion(compute_client, '2.88'):
147+
column_headers += (
148+
'vCPUs Used',
149+
'vCPUs',
150+
'Memory MB Used',
151+
'Memory MB'
152+
)
153+
columns += (
154+
'vcpus_used',
155+
'vcpus',
156+
'memory_used',
157+
'memory_size'
158+
)
107159

108160
if parsed_args.matching:
109-
data = compute_client.hypervisors.search(parsed_args.matching)
161+
data = compute_client.find_hypervisor(
162+
parsed_args.matching, ignore_missing=False)
110163
else:
111-
data = compute_client.hypervisors.list(**list_opts)
164+
data = compute_client.hypervisors(**list_opts, details=True)
112165

113166
return (
114-
columns,
167+
column_headers,
115168
(utils.get_item_properties(s, columns) for s in data),
116169
)
117170

@@ -120,7 +173,7 @@ class ShowHypervisor(command.ShowOne):
120173
_description = _("Display hypervisor details")
121174

122175
def get_parser(self, prog_name):
123-
parser = super(ShowHypervisor, self).get_parser(prog_name)
176+
parser = super().get_parser(prog_name)
124177
parser.add_argument(
125178
"hypervisor",
126179
metavar="<hypervisor>",
@@ -129,20 +182,25 @@ def get_parser(self, prog_name):
129182
return parser
130183

131184
def take_action(self, parsed_args):
132-
compute_client = self.app.client_manager.compute
133-
hypervisor = utils.find_resource(compute_client.hypervisors,
134-
parsed_args.hypervisor)._info.copy()
185+
compute_client = self.app.client_manager.sdk_connection.compute
186+
hypervisor = compute_client.find_hypervisor(
187+
parsed_args.hypervisor, ignore_missing=False).copy()
188+
189+
# Some of the properties in the hypervisor object need to be processed
190+
# before they get reported to the user. We spend this section
191+
# extracting the relevant details to be reported by modifying our
192+
# copy of the hypervisor object.
193+
aggregates = compute_client.aggregates()
194+
hypervisor['aggregates'] = list()
195+
service_details = hypervisor['service_details']
135196

136-
aggregates = compute_client.aggregates.list()
137-
hypervisor["aggregates"] = list()
138197
if aggregates:
139198
# Hypervisors in nova cells are prefixed by "<cell>@"
140-
if "@" in hypervisor['service']['host']:
141-
cell, service_host = hypervisor['service']['host'].split(
142-
'@', 1)
199+
if "@" in service_details['host']:
200+
cell, service_host = service_details['host'].split('@', 1)
143201
else:
144202
cell = None
145-
service_host = hypervisor['service']['host']
203+
service_host = service_details['host']
146204

147205
if cell:
148206
# The host aggregates are also prefixed by "<cell>@"
@@ -154,42 +212,45 @@ def take_action(self, parsed_args):
154212
member_of = [aggregate.name
155213
for aggregate in aggregates
156214
if service_host in aggregate.hosts]
157-
hypervisor["aggregates"] = member_of
215+
hypervisor['aggregates'] = member_of
158216

159217
try:
160-
uptime = compute_client.hypervisors.uptime(hypervisor['id'])._info
218+
if sdk_utils.supports_microversion(compute_client, '2.88'):
219+
uptime = hypervisor['uptime'] or ''
220+
del hypervisor['uptime']
221+
else:
222+
del hypervisor['uptime']
223+
uptime = compute_client.get_hypervisor_uptime(
224+
hypervisor['id'])['uptime']
161225
# Extract data from uptime value
162226
# format: 0 up 0, 0 users, load average: 0, 0, 0
163227
# example: 17:37:14 up 2:33, 3 users,
164228
# load average: 0.33, 0.36, 0.34
165229
m = re.match(
166230
r"\s*(.+)\sup\s+(.+),\s+(.+)\susers?,\s+load average:\s(.+)",
167-
uptime['uptime'])
231+
uptime)
168232
if m:
169-
hypervisor["host_time"] = m.group(1)
170-
hypervisor["uptime"] = m.group(2)
171-
hypervisor["users"] = m.group(3)
172-
hypervisor["load_average"] = m.group(4)
233+
hypervisor['host_time'] = m.group(1)
234+
hypervisor['uptime'] = m.group(2)
235+
hypervisor['users'] = m.group(3)
236+
hypervisor['load_average'] = m.group(4)
173237
except nova_exceptions.HTTPNotImplemented:
174238
pass
175239

176-
hypervisor["service_id"] = hypervisor["service"]["id"]
177-
hypervisor["service_host"] = hypervisor["service"]["host"]
178-
del hypervisor["service"]
240+
hypervisor['service_id'] = service_details['id']
241+
hypervisor['service_host'] = service_details['host']
242+
del hypervisor['service_details']
179243

180-
if compute_client.api_version < api_versions.APIVersion('2.28'):
244+
if not sdk_utils.supports_microversion(compute_client, '2.28'):
181245
# microversion 2.28 transformed this to a JSON blob rather than a
182246
# string; on earlier fields, do this manually
183-
if hypervisor['cpu_info']:
184-
hypervisor['cpu_info'] = json.loads(hypervisor['cpu_info'])
185-
else:
186-
hypervisor['cpu_info'] = {}
187-
188-
columns = tuple(sorted(hypervisor))
247+
hypervisor['cpu_info'] = json.loads(hypervisor['cpu_info'] or '{}')
248+
display_columns, columns = _get_hypervisor_columns(
249+
hypervisor, compute_client)
189250
data = utils.get_dict_properties(
190251
hypervisor, columns,
191252
formatters={
192253
'cpu_info': format_columns.DictColumn,
193254
})
194255

195-
return (columns, data)
256+
return display_columns, data

openstackclient/tests/unit/compute/v2/fakes.py

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from novaclient import api_versions
2222
from openstack.compute.v2 import flavor as _flavor
23+
from openstack.compute.v2 import hypervisor as _hypervisor
2324
from openstack.compute.v2 import server
2425
from openstack.compute.v2 import server_group as _server_group
2526
from openstack.compute.v2 import server_interface as _server_interface
@@ -340,75 +341,6 @@ def create_one_extension(attrs=None):
340341
return extension
341342

342343

343-
class FakeHypervisor(object):
344-
"""Fake one or more hypervisor."""
345-
346-
@staticmethod
347-
def create_one_hypervisor(attrs=None):
348-
"""Create a fake hypervisor.
349-
350-
:param dict attrs:
351-
A dictionary with all attributes
352-
:return:
353-
A FakeResource object, with id, hypervisor_hostname, and so on
354-
"""
355-
attrs = attrs or {}
356-
357-
# Set default attributes.
358-
hypervisor_info = {
359-
'id': 'hypervisor-id-' + uuid.uuid4().hex,
360-
'hypervisor_hostname': 'hypervisor-hostname-' + uuid.uuid4().hex,
361-
'status': 'enabled',
362-
'host_ip': '192.168.0.10',
363-
'cpu_info': {
364-
'aaa': 'aaa',
365-
},
366-
'free_disk_gb': 50,
367-
'hypervisor_version': 2004001,
368-
'disk_available_least': 50,
369-
'local_gb': 50,
370-
'free_ram_mb': 1024,
371-
'service': {
372-
'host': 'aaa',
373-
'disabled_reason': None,
374-
'id': 1,
375-
},
376-
'vcpus_used': 0,
377-
'hypervisor_type': 'QEMU',
378-
'local_gb_used': 0,
379-
'vcpus': 4,
380-
'memory_mb_used': 512,
381-
'memory_mb': 1024,
382-
'current_workload': 0,
383-
'state': 'up',
384-
'running_vms': 0,
385-
}
386-
387-
# Overwrite default attributes.
388-
hypervisor_info.update(attrs)
389-
390-
hypervisor = fakes.FakeResource(info=copy.deepcopy(hypervisor_info),
391-
loaded=True)
392-
return hypervisor
393-
394-
@staticmethod
395-
def create_hypervisors(attrs=None, count=2):
396-
"""Create multiple fake hypervisors.
397-
398-
:param dict attrs:
399-
A dictionary with all attributes
400-
:param int count:
401-
The number of hypervisors to fake
402-
:return:
403-
A list of FakeResource objects faking the hypervisors
404-
"""
405-
hypervisors = []
406-
for i in range(0, count):
407-
hypervisors.append(FakeHypervisor.create_one_hypervisor(attrs))
408-
409-
return hypervisors
410-
411-
412344
class FakeHypervisorStats(object):
413345
"""Fake one or more hypervisor stats."""
414346

@@ -1795,6 +1727,70 @@ def create_sdk_volume_attachments(attrs=None, methods=None, count=2):
17951727
return volume_attachments
17961728

17971729

1730+
def create_one_hypervisor(attrs=None):
1731+
"""Create a fake hypervisor.
1732+
1733+
:param dict attrs:
1734+
A dictionary with all attributes
1735+
:return:
1736+
A FakeResource object, with id, hypervisor_hostname, and so on
1737+
"""
1738+
attrs = attrs or {}
1739+
1740+
# Set default attributes.
1741+
hypervisor_info = {
1742+
'id': 'hypervisor-id-' + uuid.uuid4().hex,
1743+
'hypervisor_hostname': 'hypervisor-hostname-' + uuid.uuid4().hex,
1744+
'status': 'enabled',
1745+
'host_ip': '192.168.0.10',
1746+
'cpu_info': {
1747+
'aaa': 'aaa',
1748+
},
1749+
'free_disk_gb': 50,
1750+
'hypervisor_version': 2004001,
1751+
'disk_available_least': 50,
1752+
'local_gb': 50,
1753+
'free_ram_mb': 1024,
1754+
'service': {
1755+
'host': 'aaa',
1756+
'disabled_reason': None,
1757+
'id': 1,
1758+
},
1759+
'vcpus_used': 0,
1760+
'hypervisor_type': 'QEMU',
1761+
'local_gb_used': 0,
1762+
'vcpus': 4,
1763+
'memory_mb_used': 512,
1764+
'memory_mb': 1024,
1765+
'current_workload': 0,
1766+
'state': 'up',
1767+
'running_vms': 0,
1768+
}
1769+
1770+
# Overwrite default attributes.
1771+
hypervisor_info.update(attrs)
1772+
1773+
hypervisor = _hypervisor.Hypervisor(**hypervisor_info, loaded=True)
1774+
return hypervisor
1775+
1776+
1777+
def create_hypervisors(attrs=None, count=2):
1778+
"""Create multiple fake hypervisors.
1779+
1780+
:param dict attrs:
1781+
A dictionary with all attributes
1782+
:param int count:
1783+
The number of hypervisors to fake
1784+
:return:
1785+
A list of FakeResource objects faking the hypervisors
1786+
"""
1787+
hypervisors = []
1788+
for i in range(0, count):
1789+
hypervisors.append(create_one_hypervisor(attrs))
1790+
1791+
return hypervisors
1792+
1793+
17981794
def create_one_server_group(attrs=None):
17991795
"""Create a fake server group
18001796

0 commit comments

Comments
 (0)