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:
Kevin L. Mitchell 2012-06-27 18:45:28 -05:00
parent 08cf0bf95e
commit a11788515e
6 changed files with 354 additions and 0 deletions

View File

@ -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:

View File

@ -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")

View File

@ -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

View File

@ -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}})

View File

@ -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)

View File

@ -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')