Add hypervisor information extension.
Adds support for a new nova extension for getting information about hypervisors (as opposed to compute hosts), including a list of hypervisors matching a regular expression (database regular expression, i.e., %'s) and a list of hypervisors with the list of instances living on those hypervisors. Change-Id: I7353991ffbf484da175a0912ee46e80f623e230f
This commit is contained in:
parent
08cf0bf95e
commit
a11788515e
|
@ -7,6 +7,7 @@ from novaclient.v1_1 import floating_ip_dns
|
|||
from novaclient.v1_1 import floating_ips
|
||||
from novaclient.v1_1 import floating_ip_pools
|
||||
from novaclient.v1_1 import hosts
|
||||
from novaclient.v1_1 import hypervisors
|
||||
from novaclient.v1_1 import images
|
||||
from novaclient.v1_1 import keypairs
|
||||
from novaclient.v1_1 import limits
|
||||
|
@ -76,6 +77,7 @@ class Client(object):
|
|||
virtual_interfaces.VirtualInterfaceManager(self)
|
||||
self.aggregates = aggregates.AggregateManager(self)
|
||||
self.hosts = hosts.HostManager(self)
|
||||
self.hypervisors = hypervisors.HypervisorManager(self)
|
||||
|
||||
# Add in any extensions...
|
||||
if extensions:
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
# Copyright 2012 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Hypervisors interface (1.1 extension).
|
||||
"""
|
||||
|
||||
import urllib
|
||||
|
||||
from novaclient import base
|
||||
|
||||
|
||||
class Hypervisor(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Hypervisor: %s>" % self.id
|
||||
|
||||
|
||||
class HypervisorManager(base.Manager):
|
||||
resource_class = Hypervisor
|
||||
|
||||
def list(self, detailed=True):
|
||||
"""
|
||||
Get a list of hypervisors.
|
||||
"""
|
||||
detail = ""
|
||||
if detailed:
|
||||
detail = "/detail"
|
||||
return self._list('/os-hypervisors%s' % detail, 'hypervisors')
|
||||
|
||||
def search(self, hypervisor_match, servers=False):
|
||||
"""
|
||||
Get a list of matching hypervisors.
|
||||
|
||||
:param servers: If True, server information is also retrieved.
|
||||
"""
|
||||
target = 'servers' if servers else 'search'
|
||||
url = ('/os-hypervisors/%s/%s' %
|
||||
(urllib.quote(hypervisor_match, safe=''), target))
|
||||
return self._list(url, 'hypervisors')
|
||||
|
||||
def get(self, hypervisor):
|
||||
"""
|
||||
Get a specific hypervisor.
|
||||
"""
|
||||
return self._get("/os-hypervisors/%s" % base.getid(hypervisor),
|
||||
"hypervisor")
|
|
@ -1649,6 +1649,60 @@ def do_host_action(cs, args):
|
|||
utils.print_list([result], ['HOST', 'power_action'])
|
||||
|
||||
|
||||
@utils.arg('--matching', metavar='<hostname>', default=None,
|
||||
help='List hypervisors matching the given <hostname>.')
|
||||
def do_hypervisor_list(cs, args):
|
||||
"""List hypervisors."""
|
||||
columns = ['ID', 'Hypervisor hostname']
|
||||
if args.matching:
|
||||
utils.print_list(cs.hypervisors.search(args.matching), columns)
|
||||
else:
|
||||
# Since we're not outputting detail data, choose
|
||||
# detailed=False for server-side efficiency
|
||||
utils.print_list(cs.hypervisors.list(False), columns)
|
||||
|
||||
|
||||
@utils.arg('hostname', metavar='<hostname>',
|
||||
help='The hypervisor hostname (or pattern) to search for.')
|
||||
def do_hypervisor_servers(cs, args):
|
||||
"""List instances belonging to specific hypervisors."""
|
||||
hypers = cs.hypervisors.search(args.hostname, servers=True)
|
||||
|
||||
class InstanceOnHyper(object):
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
# Massage the result into a list to be displayed
|
||||
instances = []
|
||||
for hyper in hypers:
|
||||
hyper_host = hyper.hypervisor_hostname
|
||||
hyper_id = hyper.id
|
||||
instances.extend([InstanceOnHyper(id=serv['uuid'],
|
||||
name=serv['name'],
|
||||
hypervisor_hostname=hyper_host,
|
||||
hypervisor_id=hyper_id)
|
||||
for serv in hyper.servers])
|
||||
|
||||
# Output the data
|
||||
utils.print_list(instances, ['ID', 'Name', 'Hypervisor ID',
|
||||
'Hypervisor Hostname'])
|
||||
|
||||
|
||||
@utils.arg('hypervisor_id', metavar='<hypervisor_id>',
|
||||
help='The ID of the hypervisor to show the details of.')
|
||||
def do_hypervisor_show(cs, args):
|
||||
"""Display the details of the specified hypervisor."""
|
||||
hyper = utils.find_resource(cs.hypervisors, args.hypervisor_id)
|
||||
|
||||
# Build up the dict
|
||||
info = hyper._info.copy()
|
||||
info['service_id'] = info['service']['id']
|
||||
info['service_host'] = info['service']['host']
|
||||
del info['service']
|
||||
|
||||
utils.print_dict(info)
|
||||
|
||||
|
||||
def do_endpoints(cs, _args):
|
||||
"""Discover endpoints that get returned from the authenticate services"""
|
||||
catalog = cs.client.service_catalog.catalog
|
||||
|
|
|
@ -822,3 +822,89 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||
result = {'host': 'dummy'}
|
||||
result.update(body)
|
||||
return (200, result)
|
||||
|
||||
def get_os_hypervisors(self, **kw):
|
||||
return (200, {"hypervisors": [
|
||||
{'id': 1234, 'hypervisor_hostname': 'hyper1'},
|
||||
{'id': 5678, 'hypervisor_hostname': 'hyper2'},
|
||||
]})
|
||||
|
||||
def get_os_hypervisors_detail(self, **kw):
|
||||
return (200, {"hypervisors": [
|
||||
{'id': 1234,
|
||||
'service': {'id': 1, 'host': 'compute1'},
|
||||
'vcpus': 4,
|
||||
'memory_mb': 10 * 1024,
|
||||
'local_gb': 250,
|
||||
'vcpus_used': 2,
|
||||
'memory_mb_used': 5 * 1024,
|
||||
'local_gb_used': 125,
|
||||
'hypervisor_type': "xen",
|
||||
'hypervisor_version': 3,
|
||||
'hypervisor_hostname': "hyper1",
|
||||
'free_ram_mb': 5 * 1024,
|
||||
'free_disk_gb': 125,
|
||||
'current_workload': 2,
|
||||
'running_vms': 2,
|
||||
'cpu_info': 'cpu_info',
|
||||
'disk_available_least': 100},
|
||||
{'id': 2,
|
||||
'service': {'id': 2, 'host': "compute2"},
|
||||
'vcpus': 4,
|
||||
'memory_mb': 10 * 1024,
|
||||
'local_gb': 250,
|
||||
'vcpus_used': 2,
|
||||
'memory_mb_used': 5 * 1024,
|
||||
'local_gb_used': 125,
|
||||
'hypervisor_type': "xen",
|
||||
'hypervisor_version': 3,
|
||||
'hypervisor_hostname': "hyper2",
|
||||
'free_ram_mb': 5 * 1024,
|
||||
'free_disk_gb': 125,
|
||||
'current_workload': 2,
|
||||
'running_vms': 2,
|
||||
'cpu_info': 'cpu_info',
|
||||
'disk_available_least': 100}
|
||||
]})
|
||||
|
||||
def get_os_hypervisors_hyper_search(self, **kw):
|
||||
return (200, {'hypervisors': [
|
||||
{'id': 1234, 'hypervisor_hostname': 'hyper1'},
|
||||
{'id': 5678, 'hypervisor_hostname': 'hyper2'}
|
||||
]})
|
||||
|
||||
def get_os_hypervisors_hyper_servers(self, **kw):
|
||||
return (200, {'hypervisors': [
|
||||
{'id': 1234,
|
||||
'hypervisor_hostname': 'hyper1',
|
||||
'servers': [
|
||||
{'name': 'inst1', 'uuid': 'uuid1'},
|
||||
{'name': 'inst2', 'uuid': 'uuid2'}
|
||||
]},
|
||||
{'id': 5678,
|
||||
'hypervisor_hostname': 'hyper2',
|
||||
'servers': [
|
||||
{'name': 'inst3', 'uuid': 'uuid3'},
|
||||
{'name': 'inst4', 'uuid': 'uuid4'}
|
||||
]}
|
||||
]})
|
||||
|
||||
def get_os_hypervisors_1234(self, **kw):
|
||||
return (200, {'hypervisor':
|
||||
{'id': 1234,
|
||||
'service': {'id': 1, 'host': 'compute1'},
|
||||
'vcpus': 4,
|
||||
'memory_mb': 10 * 1024,
|
||||
'local_gb': 250,
|
||||
'vcpus_used': 2,
|
||||
'memory_mb_used': 5 * 1024,
|
||||
'local_gb_used': 125,
|
||||
'hypervisor_type': "xen",
|
||||
'hypervisor_version': 3,
|
||||
'hypervisor_hostname': "hyper1",
|
||||
'free_ram_mb': 5 * 1024,
|
||||
'free_disk_gb': 125,
|
||||
'current_workload': 2,
|
||||
'running_vms': 2,
|
||||
'cpu_info': 'cpu_info',
|
||||
'disk_available_least': 100}})
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
# Copyright 2012 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tests import utils
|
||||
from tests.v1_1 import fakes
|
||||
|
||||
|
||||
cs = fakes.FakeClient()
|
||||
|
||||
|
||||
class HypervisorsTest(utils.TestCase):
|
||||
def compare_to_expected(self, expected, hyper):
|
||||
for key, value in expected.items():
|
||||
self.assertEqual(getattr(hyper, key), value)
|
||||
|
||||
def test_hypervisor_index(self):
|
||||
expected = [
|
||||
dict(id=1234, hypervisor_hostname='hyper1'),
|
||||
dict(id=5678, hypervisor_hostname='hyper2'),
|
||||
]
|
||||
|
||||
result = cs.hypervisors.list(False)
|
||||
cs.assert_called('GET', '/os-hypervisors')
|
||||
|
||||
for idx, hyper in enumerate(result):
|
||||
self.compare_to_expected(expected[idx], hyper)
|
||||
|
||||
def test_hypervisor_detail(self):
|
||||
expected = [
|
||||
dict(id=1234,
|
||||
service=dict(id=1, host='compute1'),
|
||||
vcpus=4,
|
||||
memory_mb=10 * 1024,
|
||||
local_gb=250,
|
||||
vcpus_used=2,
|
||||
memory_mb_used=5 * 1024,
|
||||
local_gb_used=125,
|
||||
hypervisor_type="xen",
|
||||
hypervisor_version=3,
|
||||
hypervisor_hostname="hyper1",
|
||||
free_ram_mb=5 * 1024,
|
||||
free_disk_gb=125,
|
||||
current_workload=2,
|
||||
running_vms=2,
|
||||
cpu_info='cpu_info',
|
||||
disk_available_least=100),
|
||||
dict(id=2,
|
||||
service=dict(id=2, host="compute2"),
|
||||
vcpus=4,
|
||||
memory_mb=10 * 1024,
|
||||
local_gb=250,
|
||||
vcpus_used=2,
|
||||
memory_mb_used=5 * 1024,
|
||||
local_gb_used=125,
|
||||
hypervisor_type="xen",
|
||||
hypervisor_version=3,
|
||||
hypervisor_hostname="hyper2",
|
||||
free_ram_mb=5 * 1024,
|
||||
free_disk_gb=125,
|
||||
current_workload=2,
|
||||
running_vms=2,
|
||||
cpu_info='cpu_info',
|
||||
disk_available_least=100)]
|
||||
|
||||
result = cs.hypervisors.list()
|
||||
cs.assert_called('GET', '/os-hypervisors/detail')
|
||||
|
||||
for idx, hyper in enumerate(result):
|
||||
self.compare_to_expected(expected[idx], hyper)
|
||||
|
||||
def test_hypervisor_search(self):
|
||||
expected = [
|
||||
dict(id=1234, hypervisor_hostname='hyper1'),
|
||||
dict(id=5678, hypervisor_hostname='hyper2'),
|
||||
]
|
||||
|
||||
result = cs.hypervisors.search('hyper')
|
||||
cs.assert_called('GET', '/os-hypervisors/hyper/search')
|
||||
|
||||
for idx, hyper in enumerate(result):
|
||||
self.compare_to_expected(expected[idx], hyper)
|
||||
|
||||
def test_hypervisor_servers(self):
|
||||
expected = [
|
||||
dict(id=1234,
|
||||
hypervisor_hostname='hyper1',
|
||||
servers=[
|
||||
dict(name='inst1', uuid='uuid1'),
|
||||
dict(name='inst2', uuid='uuid2')]),
|
||||
dict(id=5678,
|
||||
hypervisor_hostname='hyper2',
|
||||
servers=[
|
||||
dict(name='inst3', uuid='uuid3'),
|
||||
dict(name='inst4', uuid='uuid4')]),
|
||||
]
|
||||
|
||||
result = cs.hypervisors.search('hyper', True)
|
||||
cs.assert_called('GET', '/os-hypervisors/hyper/servers')
|
||||
|
||||
for idx, hyper in enumerate(result):
|
||||
self.compare_to_expected(expected[idx], hyper)
|
||||
|
||||
def test_hypervisor_get(self):
|
||||
expected = dict(
|
||||
id=1234,
|
||||
service=dict(id=1, host='compute1'),
|
||||
vcpus=4,
|
||||
memory_mb=10 * 1024,
|
||||
local_gb=250,
|
||||
vcpus_used=2,
|
||||
memory_mb_used=5 * 1024,
|
||||
local_gb_used=125,
|
||||
hypervisor_type="xen",
|
||||
hypervisor_version=3,
|
||||
hypervisor_hostname="hyper1",
|
||||
free_ram_mb=5 * 1024,
|
||||
free_disk_gb=125,
|
||||
current_workload=2,
|
||||
running_vms=2,
|
||||
cpu_info='cpu_info',
|
||||
disk_available_least=100)
|
||||
|
||||
result = cs.hypervisors.get(1234)
|
||||
cs.assert_called('GET', '/os-hypervisors/1234')
|
||||
|
||||
self.compare_to_expected(expected, result)
|
|
@ -476,6 +476,22 @@ class ShellTest(utils.TestCase):
|
|||
self.run_command('host-action sample-host --action reboot')
|
||||
self.assert_called('GET', '/os-hosts/sample-host/reboot')
|
||||
|
||||
def test_hypervisor_list(self):
|
||||
self.run_command('hypervisor-list')
|
||||
self.assert_called('GET', '/os-hypervisors')
|
||||
|
||||
def test_hypervisor_list_matching(self):
|
||||
self.run_command('hypervisor-list --matching hyper')
|
||||
self.assert_called('GET', '/os-hypervisors/hyper/search')
|
||||
|
||||
def test_hypervisor_servers(self):
|
||||
self.run_command('hypervisor-servers hyper')
|
||||
self.assert_called('GET', '/os-hypervisors/hyper/servers')
|
||||
|
||||
def test_hypervisor_show(self):
|
||||
self.run_command('hypervisor-show 1234')
|
||||
self.assert_called('GET', '/os-hypervisors/1234')
|
||||
|
||||
def test_quota_show(self):
|
||||
self.run_command('quota-show test')
|
||||
self.assert_called('GET', '/os-quota-sets/test')
|
||||
|
|
Loading…
Reference in New Issue