diff --git a/circle/common/models.py b/circle/common/models.py index 64f3fd5..6904b3c 100644 --- a/circle/common/models.py +++ b/circle/common/models.py @@ -488,7 +488,7 @@ class HumanReadableException(HumanReadableObject, Exception): "Level should be the name of an attribute of django." "contrib.messages (and it should be callable with " "(request, message)). Like 'error', 'warning'.") - else: + elif not hasattr(self, "level"): self.level = "error" def send_message(self, request, level=None): diff --git a/circle/manager/scheduler.py b/circle/manager/scheduler.py index 2468e59..f21fd99 100644 --- a/circle/manager/scheduler.py +++ b/circle/manager/scheduler.py @@ -18,26 +18,37 @@ from logging import getLogger from django.db.models import Sum +from django.utils.translation import ugettext_noop + +from common.models import HumanReadableException logger = getLogger(__name__) -class NotEnoughMemoryException(Exception): +class SchedulerError(HumanReadableException): + admin_message = None - def __init__(self, message=None): - if message is None: - message = "No node has enough memory to accomodate the guest." + def __init__(self, params=None, level=None, **kwargs): + kwargs.update(params or {}) + super(SchedulerError, self).__init__( + level, self.message, self.admin_message or self.message, + kwargs) - Exception.__init__(self, message) +class NotEnoughMemoryException(SchedulerError): + message = ugettext_noop( + "The resources required for launching the virtual machine are not " + "available currently. Please try again later.") -class TraitsUnsatisfiableException(Exception): + admin_message = ugettext_noop( + "The required free memory for launching the virtual machine is not " + "available on any usable node currently. Please try again later.") - def __init__(self, message=None): - if message is None: - message = "No node can satisfy all required traits of the guest." - Exception.__init__(self, message) +class TraitsUnsatisfiableException(SchedulerError): + message = ugettext_noop( + "No node can satisfy the required traits of the " + "new vitual machine currently.") def select_node(instance, nodes): diff --git a/circle/vm/operations.py b/circle/vm/operations.py index b14895c..65b3361 100644 --- a/circle/vm/operations.py +++ b/circle/vm/operations.py @@ -620,6 +620,17 @@ class ShutdownOperation(InstanceOperation): self.instance.yield_node() self.instance.yield_vnc_port() + def on_abort(self, activity, error): + if isinstance(error, TimeLimitExceeded): + activity.result = humanize_exception(ugettext_noop( + "The virtual machine did not switch off in the provided time " + "limit. Most of the time this is caused by incorrect ACPI " + "settings. You can also try to power off the machine from the " + "operating system manually."), error) + activity.resultant_state = None + else: + super(ShutdownOperation, self).on_abort(activity, error) + register_operation(ShutdownOperation)