Implement BuildHooksEnv for NoHooksLU
[ganeti-local] / lib / errors.py
index 7bcd564..2040cae 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#
 #
 
 # Copyright (C) 2006, 2007 Google Inc.
 #
 
 # Copyright (C) 2006, 2007 Google Inc.
@@ -104,8 +104,9 @@ class InvalidOS(GenericError):
   This is raised when an OS exists on the master (or is otherwise
   requested to the code) but not on the target node.
 
   This is raised when an OS exists on the master (or is otherwise
   requested to the code) but not on the target node.
 
-  This exception has two arguments:
+  This exception has three arguments:
     - the name of the os
     - the name of the os
+    - the source directory, if any
     - the reason why we consider this an invalid OS (text of error message)
 
   """
     - the reason why we consider this an invalid OS (text of error message)
 
   """
@@ -129,11 +130,19 @@ class OpPrereqError(GenericError):
 
   """
 
 
   """
 
+
 class OpExecError(GenericError):
   """Error during OpCode execution.
 
   """
 
 class OpExecError(GenericError):
   """Error during OpCode execution.
 
   """
 
+
+class OpRetryError(OpExecError):
+  """Error during OpCode execution, action can be retried.
+
+  """
+
+
 class OpCodeUnknown(GenericError):
   """Unknown opcode submitted.
 
 class OpCodeUnknown(GenericError):
   """Unknown opcode submitted.
 
@@ -142,6 +151,29 @@ class OpCodeUnknown(GenericError):
 
   """
 
 
   """
 
+
+class JobLost(GenericError):
+  """Submitted job lost.
+
+  The job was submitted but it cannot be found in the current job
+  list.
+
+  """
+
+
+class ResolverError(GenericError):
+  """Host name cannot be resolved.
+
+  This is not a normal situation for Ganeti, as we rely on having a
+  working resolver.
+
+  The non-resolvable hostname is available as the first element of the
+  args tuple; the other two elements of the tuple are the first two
+  args of the socket.gaierror exception (error code and description).
+
+  """
+
+
 class HooksFailure(GenericError):
   """A generic hook failure.
 
 class HooksFailure(GenericError):
   """A generic hook failure.
 
@@ -149,6 +181,7 @@ class HooksFailure(GenericError):
 
   """
 
 
   """
 
+
 class HooksAbort(HooksFailure):
   """A required hook has failed.
 
 class HooksAbort(HooksFailure):
   """A required hook has failed.
 
@@ -159,12 +192,128 @@ class HooksAbort(HooksFailure):
 
   """
 
 
   """
 
+
 class UnitParseError(GenericError):
   """Unable to parse size unit.
 
   """
 
 class UnitParseError(GenericError):
   """Unable to parse size unit.
 
   """
 
+class TypeEnforcementError(GenericError):
+  """Unable to enforce data type.
+
+  """
 
 class SshKeyError(GenericError):
   """Invalid SSH key.
 
 class SshKeyError(GenericError):
   """Invalid SSH key.
+
+  """
+
+
+class TagError(GenericError):
+  """Generic tag error.
+
+  The argument to this exception will show the exact error.
+
+  """
+
+
+class CommandError(GenericError):
+  """External command error.
+
+  """
+
+
+class QuitGanetiException(Exception):
+  """Signal that Ganeti that it must quit.
+
+  This is not necessarily an error (and thus not a subclass of GenericError),
+  but it's an exceptional circumstance and it is thus treated. This instance
+  should be instantiated with two values. The first one will specify whether an
+  error should returned to the caller, and the second one will be the returned
+  result (either as an error or as a normal result).
+
+  Examples::
+
+    # Return a result of "True" to the caller, but quit ganeti afterwards
+    raise QuitGanetiException(False, True)
+    # Send an error to the caller, and quit ganeti
+    raise QuitGanetiException(True, "Fatal safety violation, shutting down")
+
+  """
+
+
+class JobQueueError(GenericError):
+  """Job queue error.
+
+  """
+
+
+class JobQueueDrainError(JobQueueError):
+  """Job queue is marked for drain error.
+
+  This is raised when a job submission attempt is made but the queue
+  is marked for drain.
+
+  """
+
+
+class JobQueueFull(JobQueueError):
+  """Job queue full error.
+
+  Raised when job queue size reached its hard limit.
+
+  """
+
+
+# errors should be added above
+
+
+def GetErrorClass(name):
+  """Return the class of an exception.
+
+  Given the class name, return the class itself.
+
+  @type name: str
+  @param name: the exception name
+  @rtype: class
+  @return: the actual class, or None if not found
+
+  """
+  item = globals().get(name, None)
+  if item is not None:
+    if not (isinstance(item, type(Exception)) and
+            issubclass(item, GenericError)):
+      item = None
+  return item
+
+
+def EncodeException(err):
+  """Encodes an exception into a format that L{MaybeRaise} will recognise.
+
+  The passed L{err} argument will be formatted as a tuple (exception
+  name, arguments) that the MaybeRaise function will recognise.
+
+  @type err: GenericError child
+  @param err: usually a child of GenericError (but any exception
+      will be accepted)
+  @rtype: tuple
+  @return: tuple of (exception name, exception arguments)
+
+  """
+  return (err.__class__.__name__, err.args)
+
+
+def MaybeRaise(result):
+  """If this looks like an encoded Ganeti exception, raise it.
+
+  This function tries to parse the passed argument and if it looks
+  like an encoding done by EncodeException, it will re-raise it.
+
   """
   """
+  tlt = (tuple, list)
+  if (isinstance(result, tlt) and len(result) == 2 and
+      isinstance(result[1], tlt)):
+    # custom ganeti errors
+    err_class = GetErrorClass(result[0])
+    if err_class is not None:
+      raise err_class, tuple(result[1])