summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmando Migliaccio <armando.migliaccio@eu.citrix.com>2012-02-14 22:56:42 +0000
committerArmando Migliaccio <armando.migliaccio@eu.citrix.com>2012-02-17 18:37:10 +0000
commitddc1b2c083323781334fdca7467b4914e823e0d6 (patch)
tree31b4ddab0f974a029628fcbb50d4fbb6b0d0391f
parentbca5acddafcf0cc7864022db92ae47ee1c61b29f (diff)
downloadpython-novaclient-ddc1b2c083323781334fdca7467b4914e823e0d6.tar.gz
bug 932408: python-novaclient miss OSAPI host operations
add client bindings for host-related actions. Change-Id: I98b3c11ec189029bafe73f499070ab132de640af
-rw-r--r--AUTHORS1
-rw-r--r--README.rst2
-rw-r--r--novaclient/base.py7
-rw-r--r--novaclient/v1_1/hosts.py27
-rw-r--r--novaclient/v1_1/shell.py30
-rw-r--r--tests/v1_1/fakes.py33
-rw-r--r--tests/v1_1/test_hosts.py40
-rw-r--r--tests/v1_1/test_shell.py28
8 files changed, 163 insertions, 5 deletions
diff --git a/AUTHORS b/AUTHORS
index a34e18e6..ba7d4085 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,6 +3,7 @@ Andrey Brindeyev <abrindeyev@griddynamics.com>
Andy Smith <github@anarkystic.com>
Anthony Young <sleepsonthefloor@gmail.com>
Antony Messerli <amesserl@rackspace.com>
+Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
Brian Lamar <brian.lamar@rackspace.com>
Brian Waldon <brian.waldon@rackspace.com>
Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
diff --git a/README.rst b/README.rst
index 9861f2f5..974a2699 100644
--- a/README.rst
+++ b/README.rst
@@ -107,6 +107,8 @@ You'll find complete documentation on the shell by running
get-vnc-console Get a vnc console for a server
help Display help about this program or one of its
subcommands.
+ host-update Update the host status or maintenance mode
+ host-action Perform a power action on the host
image-create Create a new image by taking a snapshot of a running
server.
image-delete Delete an image.
diff --git a/novaclient/base.py b/novaclient/base.py
index a24825f7..30ea73ec 100644
--- a/novaclient/base.py
+++ b/novaclient/base.py
@@ -135,9 +135,12 @@ class Manager(utils.HookableMixin):
if hasattr(self, '_uuid_cache'):
self._uuid_cache.write("%s\n" % uuid)
- def _get(self, url, response_key):
+ def _get(self, url, response_key=None):
resp, body = self.api.client.get(url)
- return self.resource_class(self, body[response_key])
+ if response_key:
+ return self.resource_class(self, body[response_key])
+ else:
+ return self.resource_class(self, body)
def _create(self, url, body, response_key, return_raw=False, **kwargs):
self.run_hooks('modify_body_for_create', body, **kwargs)
diff --git a/novaclient/v1_1/hosts.py b/novaclient/v1_1/hosts.py
index bb595038..172b08b7 100644
--- a/novaclient/v1_1/hosts.py
+++ b/novaclient/v1_1/hosts.py
@@ -24,11 +24,22 @@ class Host(base.Resource):
return "<Host: %s>" % self.host
def _add_details(self, info):
- dico = 'resource' in info and \
- info['resource'] or info
+ dico = 'resource' in info and info['resource'] or info
for (k, v) in dico.items():
setattr(self, k, v)
+ def update(self, values):
+ return self.manager.update(self.host, values)
+
+ def startup(self):
+ return self.manager.host_action(self.host, 'startup')
+
+ def shutdown(self):
+ return self.manager.host_action(self.host, 'shutdown')
+
+ def reboot(self):
+ return self.manager.host_action(self.host, 'reboot')
+
class HostManager(base.ManagerWithFind):
resource_class = Host
@@ -39,4 +50,14 @@ class HostManager(base.ManagerWithFind):
:param host: destination host name.
"""
- return self._list("/os-hosts/%s" % (host), "host")
+ return self._list("/os-hosts/%s" % host, "host")
+
+ def update(self, host, values):
+ """Update status or maintenance mode for the host."""
+ result = self._update("/os-hosts/%s" % host, values)
+ return self.resource_class(self, result)
+
+ def host_action(self, host, action):
+ """Performs an action on a host."""
+ url = "/os-hosts/%s/%s" % (host, action)
+ return self._get(url)
diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py
index f0dd81be..1e63c3f0 100644
--- a/novaclient/v1_1/shell.py
+++ b/novaclient/v1_1/shell.py
@@ -1408,6 +1408,36 @@ def do_describe_resource(cs, args):
utils.print_list(result, columns)
+@utils.arg('host', metavar='<hostname>', help='Name of host.')
+@utils.arg('--status', metavar='<status>', default=None, dest='status',
+ help='Either enable or disable a host.')
+@utils.arg('--maintenance', metavar='<maintenance_mode>', default=None,
+ dest='maintenance',
+ help='Either put or resume host to/from maintenance.')
+def do_host_update(cs, args):
+ """Update host settings."""
+ updates = {}
+ columns = ["HOST"]
+ if args.status:
+ updates['status'] = args.status
+ columns.append("status")
+ if args.maintenance:
+ updates['maintenance_mode'] = args.maintenance
+ columns.append("maintenance_mode")
+ result = cs.hosts.update(args.host, updates)
+ utils.print_list([result], columns)
+
+
+@utils.arg('host', metavar='<hostname>', help='Name of host.')
+@utils.arg('--action', metavar='<action>', dest='action',
+ choices=['startup', 'shutdown', 'reboot'],
+ help='A power action: startup, reboot, or shutdown.')
+def do_host_action(cs, args):
+ """Perform a power action on a host."""
+ result = cs.hosts.host_action(args.host, args.action)
+ utils.print_list([result], ['HOST', 'power_action'])
+
+
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 c2880018..e9127157 100644
--- a/tests/v1_1/fakes.py
+++ b/tests/v1_1/fakes.py
@@ -720,3 +720,36 @@ class FakeHTTPClient(base_client.HTTPClient):
'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}},
{'resource': {'project': 'admin', 'host': 'dummy',
'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}]})
+
+ def get_os_hosts_sample_host(self, *kw):
+ return (200, {'host': [{'resource': {'host': 'sample_host'}}], })
+
+ def put_os_hosts_sample_host_1(self, body, **kw):
+ return (200, {'host': 'sample-host_1',
+ 'status': 'enabled'})
+
+ def put_os_hosts_sample_host_2(self, body, **kw):
+ return (200, {'host': 'sample-host_2',
+ 'maintenance_mode': 'on_maintenance'})
+
+ def put_os_hosts_sample_host_3(self, body, **kw):
+ return (200, {'host': 'sample-host_3',
+ 'status': 'enabled',
+ 'maintenance_mode': 'on_maintenance'})
+
+ def get_os_hosts_sample_host_startup(self, **kw):
+ return (200, {'host': 'sample_host',
+ 'power_action': 'startup'})
+
+ def get_os_hosts_sample_host_reboot(self, **kw):
+ return (200, {'host': 'sample_host',
+ 'power_action': 'reboot'})
+
+ def get_os_hosts_sample_host_shutdown(self, **kw):
+ return (200, {'host': 'sample_host',
+ 'power_action': 'shutdown'})
+
+ def put_os_hosts_sample_host(self, body, **kw):
+ result = {'host': 'dummy'}
+ result.update(body)
+ return (200, result)
diff --git a/tests/v1_1/test_hosts.py b/tests/v1_1/test_hosts.py
index 5151c283..a6e8b5c7 100644
--- a/tests/v1_1/test_hosts.py
+++ b/tests/v1_1/test_hosts.py
@@ -12,3 +12,43 @@ class HostsTest(utils.TestCase):
hs = cs.hosts.get('host')
cs.assert_called('GET', '/os-hosts/host')
[self.assertTrue(isinstance(h, hosts.Host)) for h in hs]
+
+ def test_update_enable(self):
+ host = cs.hosts.get('sample_host')[0]
+ values = {"status": "enabled"}
+ result = host.update(values)
+ cs.assert_called('PUT', '/os-hosts/sample_host', values)
+ self.assertTrue(isinstance(result, hosts.Host))
+
+ def test_update_maintenance(self):
+ host = cs.hosts.get('sample_host')[0]
+ values = {"maintenance_mode": "enable"}
+ result = host.update(values)
+ cs.assert_called('PUT', '/os-hosts/sample_host', values)
+ self.assertTrue(isinstance(result, hosts.Host))
+
+ def test_update_both(self):
+ host = cs.hosts.get('sample_host')[0]
+ values = {"status": "enabled",
+ "maintenance_mode": "enable"}
+ result = host.update(values)
+ cs.assert_called('PUT', '/os-hosts/sample_host', values)
+ self.assertTrue(isinstance(result, hosts.Host))
+
+ def test_host_startup(self):
+ host = cs.hosts.get('sample_host')[0]
+ result = host.startup()
+ cs.assert_called('GET', '/os-hosts/sample_host/startup')
+ self.assertTrue(isinstance(result, hosts.Host))
+
+ def test_host_reboot(self):
+ host = cs.hosts.get('sample_host')[0]
+ result = host.reboot()
+ cs.assert_called('GET', '/os-hosts/sample_host/reboot')
+ self.assertTrue(isinstance(result, hosts.Host))
+
+ def test_host_shutdown(self):
+ host = cs.hosts.get('sample_host')[0]
+ result = host.shutdown()
+ cs.assert_called('GET', '/os-hosts/sample_host/shutdown')
+ self.assertTrue(isinstance(result, hosts.Host))
diff --git a/tests/v1_1/test_shell.py b/tests/v1_1/test_shell.py
index 31123414..ed138d98 100644
--- a/tests/v1_1/test_shell.py
+++ b/tests/v1_1/test_shell.py
@@ -385,3 +385,31 @@ class ShellTest(utils.TestCase):
{'os-migrateLive': {'host': 'hostname',
'block_migration': True,
'disk_over_commit': True}})
+
+ def test_host_update_status(self):
+ self.run_command('host-update sample-host_1 --status enabled')
+ body = {'status': 'enabled'}
+ self.assert_called('PUT', '/os-hosts/sample-host_1', body)
+
+ def test_host_update_maintenance(self):
+ self.run_command('host-update sample-host_2 --maintenance enable')
+ body = {'maintenance_mode': 'enable'}
+ self.assert_called('PUT', '/os-hosts/sample-host_2', body)
+
+ def test_host_update_multiple_settings(self):
+ self.run_command('host-update sample-host_3 '
+ '--status disabled --maintenance enable')
+ body = {'status': 'disabled', 'maintenance_mode': 'enable'}
+ self.assert_called('PUT', '/os-hosts/sample-host_3', body)
+
+ def test_host_startup(self):
+ self.run_command('host-action sample-host --action startup')
+ self.assert_called('GET', '/os-hosts/sample-host/startup')
+
+ def test_host_shutdown(self):
+ self.run_command('host-action sample-host --action shutdown')
+ self.assert_called('GET', '/os-hosts/sample-host/shutdown')
+
+ def test_host_reboot(self):
+ self.run_command('host-action sample-host --action reboot')
+ self.assert_called('GET', '/os-hosts/sample-host/reboot')