From 62ce69c1c63df818a2a6f1be6cdad33cbe6ef796 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 27 Jun 2011 20:21:45 -0700 Subject: getting started --- nova/rpc.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nova/rpc.py b/nova/rpc.py index 2e78a31e7..d4ac19c20 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -45,6 +45,8 @@ from nova import flags from nova import log as logging from nova import utils +from nova.notifier import api as notifier + LOG = logging.getLogger('nova.rpc') @@ -312,6 +314,7 @@ class ConsumerSet(object): if not it: break while True: + ex = None try: it.next() except StopIteration: @@ -319,7 +322,17 @@ class ConsumerSet(object): except greenlet.GreenletExit: running = False break + except exception.NovaException, e: + if not e.notification_level: + ex = e + # We have an exception we can + # tell the Notification system about. + # Pass it on. + except Exception as e: + ex = e + + if ex: LOG.exception(_("Exception while processing consumer")) self.reconnect() # Break to outer loop -- cgit From 4c98425ba7a53c8b966317444abe2d4f7b6556d8 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 28 Jun 2011 05:51:40 -0700 Subject: refactoring to compute from scheduler --- nova/notifier/api.py | 39 +++++++++++++++++++++++++++++++++++++++ nova/rpc.py | 9 ++------- nova/scheduler/driver.py | 10 ++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/nova/notifier/api.py b/nova/notifier/api.py index d49517c8b..027aa7cc3 100644 --- a/nova/notifier/api.py +++ b/nova/notifier/api.py @@ -37,6 +37,45 @@ class BadPriorityException(Exception): pass +def publisher_id(service, host=None): + if not host: + host = FLAGS.host + return "%s.%s" % (service, host) + + +def msgkeys(event_type, instance_id, level, publisher_id): + return dict(event_type=event_type, instance_id=instance_id, + notification_level=level, publisher_id=publisher_id) + + +def safe_notify(publisher_id, event_type, priority, payload): + try: + notify(publisher_id, event_type, notification_level, payload) + exception Exception, e: + LOG.exception(_("Problem '%(e)' attempting to " + "send to notification system." % locals())) + + +def instance_safe_notify(publisher_id, event_type, priority, instance_id, + extra_payload=None): + payload = dict(instance_id = instance_id) + if extra_payload: + payload.extend(extra_payload) + safe_notify(publisher_id, event_type, priority, payload) + + +def exception_to_notification(self, ex): + required = ['instance_id', 'publisher_id', 'notification_level', + 'event_type'] + for key in required: + if not (hasattr(ex, key) and ex.key): + return # Doesn't have everything we need. Skip it. + instance_id = ex.instance_id + publisher_id = ex.publisher_id + notification_level = ex.notification_level + event_type = ex.event_type + instance_safe_notify(publisher_id, event_type, priority, instance_id) + def notify(publisher_id, event_type, priority, payload): """ Sends a notification using the specified driver diff --git a/nova/rpc.py b/nova/rpc.py index d4ac19c20..47d63769a 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -44,7 +44,6 @@ from nova import fakerabbit from nova import flags from nova import log as logging from nova import utils - from nova.notifier import api as notifier @@ -323,12 +322,8 @@ class ConsumerSet(object): running = False break except exception.NovaException, e: - if not e.notification_level: - ex = e - # We have an exception we can - # tell the Notification system about. - # Pass it on. - + ex = e + notifier.exception_to_notification(e) except Exception as e: ex = e diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index 0b257c5d8..7e5a15c7f 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -27,6 +27,7 @@ from nova import db from nova import exception from nova import flags from nova import log as logging +from nova import notifier from nova import rpc from nova import utils from nova.compute import power_state @@ -47,6 +48,15 @@ class WillNotSchedule(exception.Error): pass +def publisher_id(host=None): + return notifier.publisher_id("scheduler", host) + + +def notifier(instance_id, event_type, level, host=None): + return dict(instance_id=instance_id, event_type=event_type, + notification_level=level, host=publisher_id(host)) + + class Scheduler(object): """The base class that all Scheduler clases should inherit from.""" -- cgit From a0f968235332e5400d507bbafa99bc0728aa8479 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 28 Jun 2011 21:04:50 -0700 Subject: moved to wrap_exception decorator --- nova/compute/manager.py | 7 ++++++- nova/exception.py | 8 +++++++- nova/notifier/api.py | 26 -------------------------- nova/rpc.py | 8 -------- 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 5aed2c677..86d375b9e 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -54,6 +54,7 @@ from nova import utils from nova import volume from nova.compute import power_state from nova.compute.utils import terminate_volumes +from nova.notifier import api as notifier from nova.virt import driver @@ -111,6 +112,10 @@ def checks_instance_lock(function): return decorated_function +def publisher_id(host=None): + return notifier.publisher_id("compute", host) + + class ComputeManager(manager.SchedulerDependentManager): """Manages the running instances from creation to destruction.""" @@ -1158,7 +1163,7 @@ class ComputeManager(manager.SchedulerDependentManager): {"method": "pre_live_migration", "args": {'instance_id': instance_id}}) - except Exception: + except Exception, e: msg = _("Pre live migration for %(i_name)s failed at %(dest)s") LOG.error(msg % locals()) self.recover_live_migration(context, instance_ref) diff --git a/nova/exception.py b/nova/exception.py index f3a452228..4b625dd04 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -81,11 +81,17 @@ def wrap_db_error(f): _wrap.func_name = f.func_name -def wrap_exception(f): +def wrap_exception(f, notifier=None, publisher_id=None, level=None): def _wrap(*args, **kw): try: return f(*args, **kw) except Exception, e: + if notifier != None and 'safe_notify' in notifier.dir(): + event_type = f.__name__ + payload = dict(args=args, exception=e) + payload.update(kw) + notifier.safe_notify(publisher_id, event_type, level, payload) + if not isinstance(e, Error): #exc_type, exc_value, exc_traceback = sys.exc_info() LOG.exception(_('Uncaught exception')) diff --git a/nova/notifier/api.py b/nova/notifier/api.py index 027aa7cc3..89527be16 100644 --- a/nova/notifier/api.py +++ b/nova/notifier/api.py @@ -43,11 +43,6 @@ def publisher_id(service, host=None): return "%s.%s" % (service, host) -def msgkeys(event_type, instance_id, level, publisher_id): - return dict(event_type=event_type, instance_id=instance_id, - notification_level=level, publisher_id=publisher_id) - - def safe_notify(publisher_id, event_type, priority, payload): try: notify(publisher_id, event_type, notification_level, payload) @@ -55,27 +50,6 @@ def safe_notify(publisher_id, event_type, priority, payload): LOG.exception(_("Problem '%(e)' attempting to " "send to notification system." % locals())) - -def instance_safe_notify(publisher_id, event_type, priority, instance_id, - extra_payload=None): - payload = dict(instance_id = instance_id) - if extra_payload: - payload.extend(extra_payload) - safe_notify(publisher_id, event_type, priority, payload) - - -def exception_to_notification(self, ex): - required = ['instance_id', 'publisher_id', 'notification_level', - 'event_type'] - for key in required: - if not (hasattr(ex, key) and ex.key): - return # Doesn't have everything we need. Skip it. - instance_id = ex.instance_id - publisher_id = ex.publisher_id - notification_level = ex.notification_level - event_type = ex.event_type - instance_safe_notify(publisher_id, event_type, priority, instance_id) - def notify(publisher_id, event_type, priority, payload): """ Sends a notification using the specified driver diff --git a/nova/rpc.py b/nova/rpc.py index 47d63769a..2e78a31e7 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -44,7 +44,6 @@ from nova import fakerabbit from nova import flags from nova import log as logging from nova import utils -from nova.notifier import api as notifier LOG = logging.getLogger('nova.rpc') @@ -313,7 +312,6 @@ class ConsumerSet(object): if not it: break while True: - ex = None try: it.next() except StopIteration: @@ -321,13 +319,7 @@ class ConsumerSet(object): except greenlet.GreenletExit: running = False break - except exception.NovaException, e: - ex = e - notifier.exception_to_notification(e) except Exception as e: - ex = e - - if ex: LOG.exception(_("Exception while processing consumer")) self.reconnect() # Break to outer loop -- cgit From 8bd200505ada97780d3a63927cfadcded456b30d Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 29 Jun 2011 08:14:43 -0700 Subject: moved to wrap_exception approach --- nova/compute/manager.py | 20 ++++++++++---------- nova/exception.py | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 86d375b9e..f8ec3c861 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -200,7 +200,7 @@ class ComputeManager(manager.SchedulerDependentManager): def get_console_pool_info(self, context, console_type): return self.driver.get_console_pool_info(console_type) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) def refresh_security_group_rules(self, context, security_group_id, **kwargs): """Tell the virtualization driver to refresh security group rules. @@ -210,7 +210,7 @@ class ComputeManager(manager.SchedulerDependentManager): """ return self.driver.refresh_security_group_rules(security_group_id) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) def refresh_security_group_members(self, context, security_group_id, **kwargs): """Tell the virtualization driver to refresh security group members. @@ -220,7 +220,7 @@ class ComputeManager(manager.SchedulerDependentManager): """ return self.driver.refresh_security_group_members(security_group_id) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) def refresh_provider_fw_rules(self, context, **_kwargs): """This call passes straight through to the virtualization driver.""" return self.driver.refresh_provider_fw_rules() @@ -355,11 +355,11 @@ class ComputeManager(manager.SchedulerDependentManager): # be fixed once we have no-db-messaging pass - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) def run_instance(self, context, instance_id, **kwargs): self._run_instance(context, instance_id, **kwargs) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) @checks_instance_lock def start_instance(self, context, instance_id): """Starting an instance on this host.""" @@ -421,7 +421,7 @@ class ComputeManager(manager.SchedulerDependentManager): if action_str == 'Terminating': terminate_volumes(self.db, context, instance_id) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) @checks_instance_lock def terminate_instance(self, context, instance_id): """Terminate an instance on this host.""" @@ -430,14 +430,14 @@ class ComputeManager(manager.SchedulerDependentManager): # TODO(ja): should we keep it in a terminated state for a bit? self.db.instance_destroy(context, instance_id) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) @checks_instance_lock def stop_instance(self, context, instance_id): """Stopping an instance on this host.""" self._shutdown_instance(context, instance_id, 'Stopping') # instance state will be updated to stopped by _poll_instance_states() - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) @checks_instance_lock def rebuild_instance(self, context, instance_id, **kwargs): """Destroy and re-make this instance. @@ -466,7 +466,7 @@ class ComputeManager(manager.SchedulerDependentManager): self._update_launched_at(context, instance_id) self._update_state(context, instance_id) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) @checks_instance_lock def reboot_instance(self, context, instance_id): """Reboot an instance on this host.""" @@ -491,7 +491,7 @@ class ComputeManager(manager.SchedulerDependentManager): self.driver.reboot(instance_ref) self._update_state(context, instance_id) - @exception.wrap_exception + @exception.wrap_exception(publisher_id()) def snapshot_instance(self, context, instance_id, image_id): """Snapshot an instance on this host.""" context = context.elevated() diff --git a/nova/exception.py b/nova/exception.py index 4b625dd04..fb2094c04 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -25,6 +25,7 @@ SHOULD include dedicated exception logging. """ from nova import log as logging +from nova.notifier import api as notifier LOG = logging.getLogger('nova.exception') @@ -81,13 +82,12 @@ def wrap_db_error(f): _wrap.func_name = f.func_name -def wrap_exception(f, notifier=None, publisher_id=None, level=None): +def wrap_exception(f, event_type=None, publisher_id=None, level=notifier.ERROR): def _wrap(*args, **kw): try: return f(*args, **kw) except Exception, e: - if notifier != None and 'safe_notify' in notifier.dir(): - event_type = f.__name__ + if event_type and publisher_id: payload = dict(args=args, exception=e) payload.update(kw) notifier.safe_notify(publisher_id, event_type, level, payload) -- cgit From 799919fe59d4a4faed1ce4effd9705173671e4da Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 29 Jun 2011 19:10:11 -0700 Subject: done and done --- nova/exception.py | 3 ++- nova/tests/test_exception.py | 58 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/nova/exception.py b/nova/exception.py index c6d2bbc3d..ea590199c 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -82,7 +82,8 @@ def wrap_db_error(f): _wrap.func_name = f.func_name -def wrap_exception(notifier=None, publisher_id=None, event_type=None, level=None): +def wrap_exception(notifier=None, publisher_id=None, event_type=None, + level=None): """This decorator wraps a method to catch any exceptions that may get thrown. It logs the exception as well as optionally sending it to the notification system. diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index 4d3b9cc73..7e30d150f 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -32,3 +32,61 @@ class ApiErrorTestCase(test.TestCase): self.assertEqual(err.__str__(), 'blah code: fake error') self.assertEqual(err.code, 'blah code') self.assertEqual(err.msg, 'fake error') + + +class FakeNotifier(object): + """Acts like the nova.notifier.api module.""" + ERROR = 88 + + def __init__(self): + self.provided_publisher = None + self.provided_event = None + self.provided_priority = None + self.provided_payload = None + + def safe_notify(self, publisher, event, priority, payload): + self.provided_publisher = publisher + self.provided_event = event + self.provided_priority = priority + self.provided_payload = payload + + +def good_function(): + return 99 + + +def bad_function_error(): + raise exception.Error() + + +def bad_function_exception(): + raise Exception() + + +class WrapExceptionTestCase(test.TestCase): + def test_wrap_exception(self): + wrapped = exception.wrap_exception() + self.assertEquals(99, wrapped(good_function)()) + self.assertRaises(exception.Error, wrapped(bad_function_error)) + + # Note that Exception is converted to Error ... + self.assertRaises(exception.Error, wrapped(bad_function_exception)) + + def test_wrap_exception_with_notifier(self): + notifier = FakeNotifier() + wrapped = exception.wrap_exception(notifier, "publisher", "event", + "level") + self.assertRaises(exception.Error, wrapped(bad_function_exception)) + self.assertEquals(notifier.provided_publisher, "publisher") + self.assertEquals(notifier.provided_event, "event") + self.assertEquals(notifier.provided_priority, "level") + for key in ['exception', 'args']: + self.assertTrue(key in notifier.provided_payload.keys()) + + def test_wrap_exception_with_notifier_defaults(self): + notifier = FakeNotifier() + wrapped = exception.wrap_exception(notifier) + self.assertRaises(exception.Error, wrapped(bad_function_exception)) + self.assertEquals(notifier.provided_publisher, None) + self.assertEquals(notifier.provided_event, "bad_function_exception") + self.assertEquals(notifier.provided_priority, notifier.ERROR) -- cgit From 002b389aa90059c1c1986d4c1a3fbcd38527b4b4 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 29 Jun 2011 19:11:27 -0700 Subject: pep8 --- nova/tests/test_exception.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index 7e30d150f..63c807a84 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -49,7 +49,7 @@ class FakeNotifier(object): self.provided_event = event self.provided_priority = priority self.provided_payload = payload - + def good_function(): return 99 -- cgit From d17171b4277337388b372459571d9f3904798bca Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 29 Jun 2011 19:19:40 -0700 Subject: pep8 --- nova/tests/test_exception.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index 63c807a84..16e273f89 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -71,7 +71,7 @@ class WrapExceptionTestCase(test.TestCase): # Note that Exception is converted to Error ... self.assertRaises(exception.Error, wrapped(bad_function_exception)) - + def test_wrap_exception_with_notifier(self): notifier = FakeNotifier() wrapped = exception.wrap_exception(notifier, "publisher", "event", -- cgit From fbe296a7ab3bf1b9ee2bf765d13b5675ff4d6295 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 29 Jun 2011 20:02:30 -0700 Subject: clean up --- nova/api/openstack/wsgi.py | 1 - nova/compute/manager.py | 1 - nova/scheduler/driver.py | 5 ----- 3 files changed, 7 deletions(-) diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 836a13b62..5b6e3cb1d 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -394,5 +394,4 @@ class Resource(wsgi.Application): """Find action-spefic method on controller and call it.""" controller_method = getattr(self.controller, action) - print "DISPATCHING", self.controller, action return controller_method(req=request, **action_args) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 78c98cf42..d5530c296 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1183,7 +1183,6 @@ class ComputeManager(manager.SchedulerDependentManager): :returns: See driver.update_available_resource() """ - print "UPDATE AVAILABLE" return self.driver.update_available_resource(context, self.host) def pre_live_migration(self, context, instance_id, time=None): diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index db392a607..ec2c9ef78 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -30,7 +30,6 @@ from nova import log as logging from nova import rpc from nova import utils from nova.compute import power_state -from nova.notifier import api as notifier_api FLAGS = flags.FLAGS @@ -49,10 +48,6 @@ class WillNotSchedule(exception.Error): pass -def publisher_id(host=None): - return notifier_api.publisher_id("scheduler", host) - - class Scheduler(object): """The base class that all Scheduler clases should inherit from.""" -- cgit From e789dd29c48ee8ad2b10eeb9ff24725f0e696bed Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 1 Jul 2011 07:31:17 -0700 Subject: review fixes --- nova/exception.py | 4 ++-- nova/notifier/api.py | 14 +++++--------- nova/tests/test_exception.py | 7 ++++++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/nova/exception.py b/nova/exception.py index ea590199c..6e277b68d 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -113,8 +113,8 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, # propagated. temp_type = f.__name__ - notifier.safe_notify(publisher_id, temp_type, temp_level, - payload) + notifier.notify(publisher_id, temp_type, temp_level, + payload) if not isinstance(e, Error): #exc_type, exc_value, exc_traceback = sys.exc_info() diff --git a/nova/notifier/api.py b/nova/notifier/api.py index d388eda96..98969fd3e 100644 --- a/nova/notifier/api.py +++ b/nova/notifier/api.py @@ -45,14 +45,6 @@ def publisher_id(service, host=None): return "%s.%s" % (service, host) -def safe_notify(publisher_id, event_type, priority, payload): - try: - notify(publisher_id, event_type, notification_level, payload) - except Exception, e: - LOG.exception(_("Problem '%(e)s' attempting to " - "send to notification system." % locals())) - - def notify(publisher_id, event_type, priority, payload): """ Sends a notification using the specified driver @@ -95,4 +87,8 @@ def notify(publisher_id, event_type, priority, payload): priority=priority, payload=payload, timestamp=str(utils.utcnow())) - driver.notify(msg) + try: + driver.notify(msg) + except Exception, e: + LOG.exception(_("Problem '%(e)s' attempting to " + "send to notification system." % locals())) diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index 16e273f89..692b714e5 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -64,11 +64,16 @@ def bad_function_exception(): class WrapExceptionTestCase(test.TestCase): - def test_wrap_exception(self): + def test_wrap_exception_good_return(self): wrapped = exception.wrap_exception() self.assertEquals(99, wrapped(good_function)()) + + def test_wrap_exception_throws_error(self): + wrapped = exception.wrap_exception() self.assertRaises(exception.Error, wrapped(bad_function_error)) + def test_wrap_exception_throws_exception(self): + wrapped = exception.wrap_exception() # Note that Exception is converted to Error ... self.assertRaises(exception.Error, wrapped(bad_function_exception)) -- cgit From 81716e8142fac86e779514997335999df4375a34 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 1 Jul 2011 07:38:17 -0700 Subject: tweak --- nova/tests/test_exception.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index 692b714e5..cd74f8871 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -44,7 +44,7 @@ class FakeNotifier(object): self.provided_priority = None self.provided_payload = None - def safe_notify(self, publisher, event, priority, payload): + def notify(self, publisher, event, priority, payload): self.provided_publisher = publisher self.provided_event = event self.provided_priority = priority -- cgit From 72bdbc314ac311e8c831410bc4f9c8935bf9d5e8 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 1 Jul 2011 08:09:19 -0700 Subject: trunk merge --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 016915d2f..cf42a39aa 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -842,7 +842,7 @@ class ComputeManager(manager.SchedulerDependentManager): self.inject_network_info(context, instance_id) self.reset_network(context, instance_id) - @exception.wrap_exception + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @checks_instance_lock def pause_instance(self, context, instance_id): """Pause an instance on this host.""" -- cgit