diff options
author | Kevin L. Mitchell <kevin.mitchell@rackspace.com> | 2012-06-27 18:45:28 -0500 |
---|---|---|
committer | Kevin L. Mitchell <kevin.mitchell@rackspace.com> | 2012-06-29 12:21:19 -0500 |
commit | a11788515e800a95d5b83448c2a9403eed509bdf (patch) | |
tree | e4b1d211815f36284c155d14b1aee30842a77fc5 | |
parent | 08cf0bf95ef99a0e39122ef99eb559e2d739716d (diff) | |
download | python-novaclient-2.6.10.tar.gz |
Add hypervisor information extension.2.6.10
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
-rw-r--r-- | novaclient/v1_1/client.py | 2 | ||||
-rw-r--r-- | novaclient/v1_1/hypervisors.py | 58 | ||||
-rw-r--r-- | novaclient/v1_1/shell.py | 54 | ||||
-rw-r--r-- | tests/v1_1/fakes.py | 86 | ||||
-rw-r--r-- | tests/v1_1/test_hypervisors.py | 138 | ||||
-rw-r--r-- | tests/v1_1/test_shell.py | 16 |
6 files changed, 354 insertions, 0 deletions
diff --git a/novaclient/v1_1/client.py b/novaclient/v1_1/client.py index 15364089..ba3bf7ae 100644 --- a/novaclient/v1_1/client.py +++ b/novaclient/v1_1/client.py @@ -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: diff --git a/novaclient/v1_1/hypervisors.py b/novaclient/v1_1/hypervisors.py new file mode 100644 index 00000000..9f56ae05 --- /dev/null +++ b/novaclient/v1_1/hypervisors.py @@ -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") diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index 8d92e249..faf9d655 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -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 diff --git a/tests/v1_1/fakes.py b/tests/v1_1/fakes.py index f2112f23..4a7c3aa1 100644 --- a/tests/v1_1/fakes.py +++ b/tests/v1_1/fakes.py @@ -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}}) diff --git a/tests/v1_1/test_hypervisors.py b/tests/v1_1/test_hypervisors.py new file mode 100644 index 00000000..2febadae --- /dev/null +++ b/tests/v1_1/test_hypervisors.py @@ -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) diff --git a/tests/v1_1/test_shell.py b/tests/v1_1/test_shell.py index e790cc9e..b31070fb 100644 --- a/tests/v1_1/test_shell.py +++ b/tests/v1_1/test_shell.py @@ -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') |