Fix lint errors
[ganeti-local] / lib / opcodes.py
index d0f6208..bfe45a7 100644 (file)
@@ -35,8 +35,8 @@ opcodes.
 
 import logging
 import re
-import operator
 
+from ganeti import compat
 from ganeti import constants
 from ganeti import errors
 from ganeti import ht
@@ -125,13 +125,17 @@ _PNoRemember = ("no_remember", False, ht.TBool,
 _PMigrationTargetNode = ("target_node", None, ht.TMaybeString,
                          "Target node for shared-storage instances")
 
+_PStartupPaused = ("startup_paused", False, ht.TBool,
+                   "Pause instance at startup")
+
+
 #: OP_ID conversion regular expression
 _OPID_RE = re.compile("([a-z])([A-Z])")
 
 #: Utility function for L{OpClusterSetParams}
 _TestClusterOsList = ht.TOr(ht.TNone,
   ht.TListOf(ht.TAnd(ht.TList, ht.TIsLength(2),
-    ht.TMap(ht.WithDesc("GetFirstItem")(operator.itemgetter(0)),
+    ht.TMap(ht.WithDesc("GetFirstItem")(compat.fst),
             ht.TElemOf(constants.DDMS_VALUES)))))
 
 
@@ -147,6 +151,12 @@ _SUMMARY_PREFIX = {
   "INSTANCE_": "I_",
   }
 
+#: Attribute name for dependencies
+DEPEND_ATTR = "depends"
+
+#: Attribute name for comment
+COMMENT_ATTR = "comment"
+
 
 def _NameToId(name):
   """Convert an opcode class name to an OP_ID.
@@ -386,6 +396,33 @@ class BaseOpCode(object):
                                      errors.ECODE_INVAL)
 
 
+def _BuildJobDepCheck(relative):
+  """Builds check for job dependencies (L{DEPEND_ATTR}).
+
+  @type relative: bool
+  @param relative: Whether to accept relative job IDs (negative)
+  @rtype: callable
+
+  """
+  if relative:
+    job_id = ht.TOr(ht.TJobId, ht.TRelativeJobId)
+  else:
+    job_id = ht.TJobId
+
+  job_dep = \
+    ht.TAnd(ht.TIsLength(2),
+            ht.TItems([job_id,
+                       ht.TListOf(ht.TElemOf(constants.JOBS_FINALIZED))]))
+
+  return ht.TOr(ht.TNone, ht.TListOf(job_dep))
+
+
+TNoRelativeJobDependencies = _BuildJobDepCheck(False)
+
+#: List of submission status and job ID as returned by C{SubmitManyJobs}
+TJobIdList = ht.TListOf(ht.TItems([ht.TBool, ht.TOr(ht.TString, ht.TJobId)]))
+
+
 class OpCode(BaseOpCode):
   """Abstract OpCode.
 
@@ -399,6 +436,7 @@ class OpCode(BaseOpCode):
                       method for details).
   @cvar OP_PARAMS: List of opcode attributes, the default values they should
                    get if not already defined, and types they must match.
+  @cvar OP_RESULT: Callable to verify opcode result
   @cvar WITH_LU: Boolean that specifies whether this should be included in
       mcpu's dispatch table
   @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just
@@ -414,7 +452,13 @@ class OpCode(BaseOpCode):
     ("debug_level", None, ht.TOr(ht.TNone, ht.TPositiveInt), "Debug level"),
     ("priority", constants.OP_PRIO_DEFAULT,
      ht.TElemOf(constants.OP_PRIO_SUBMIT_VALID), "Opcode priority"),
+    (DEPEND_ATTR, None, _BuildJobDepCheck(True),
+     "Job dependencies; if used through ``SubmitManyJobs`` relative (negative)"
+     " job IDs can be used"),
+    (COMMENT_ATTR, None, ht.TMaybeString,
+     "Comment describing the purpose of the opcode"),
     ]
+  OP_RESULT = None
 
   def __getstate__(self):
     """Specialized getstate for opcodes.
@@ -555,11 +599,17 @@ class OpClusterVerifyGroup(OpCode):
 class OpClusterVerifyDisks(OpCode):
   """Verify the cluster disks.
 
-  Parameters: none
+  """
+  OP_RESULT = ht.TStrictDict(True, True, {
+    constants.JOB_IDS_KEY: TJobIdList,
+    })
+
+
+class OpGroupVerifyDisks(OpCode):
+  """Verifies the status of all disks in a node group.
 
-  Result: a tuple of four elements:
-    - list of node names with bad data returned (unreachable, etc.)
-    - dict of node names with broken volume groups (values: error msg)
+  Result: a tuple of three elements:
+    - dict of node names with issues (values: error msg)
     - list of instances with degraded disks (that should be activated)
     - dict of instances with missing logical volumes (values: (node, vol)
       pairs with details about the missing volumes)
@@ -573,6 +623,15 @@ class OpClusterVerifyDisks(OpCode):
   consideration. This might need to be revisited in the future.
 
   """
+  OP_DSC_FIELD = "group_name"
+  OP_PARAMS = [
+    _PGroupName,
+    ]
+  OP_RESULT = \
+    ht.TAnd(ht.TIsLength(3),
+            ht.TItems([ht.TDictOf(ht.TString, ht.TString),
+                       ht.TListOf(ht.TString),
+                       ht.TDictOf(ht.TString, ht.TListOf(ht.TString))]))
 
 
 class OpClusterRepairDiskSizes(OpCode):
@@ -1018,6 +1077,7 @@ class OpInstanceStartup(OpCode):
      "Temporary hypervisor parameters, hypervisor-dependent"),
     ("beparams", ht.EmptyDict, ht.TDict, "Temporary backend parameters"),
     _PNoRemember,
+    _PStartupPaused,
     ]
 
 
@@ -1279,6 +1339,18 @@ class OpGroupRename(OpCode):
     ]
 
 
+class OpGroupEvacuate(OpCode):
+  """Evacuate a node group in the cluster."""
+  OP_DSC_FIELD = "group_name"
+  OP_PARAMS = [
+    _PGroupName,
+    _PEarlyRelease,
+    ("iallocator", None, ht.TMaybeString, "Iallocator for computing solution"),
+    ("target_groups", None, ht.TOr(ht.TNone, ht.TListOf(ht.TNonEmptyString)),
+     "Destination group names or UUIDs"),
+    ]
+
+
 # OS opcodes
 class OpOsDiagnose(OpCode):
   """Compute the list of guest operating systems."""
@@ -1422,7 +1494,7 @@ class OpTestDelay(OpCode):
   """
   OP_DSC_FIELD = "duration"
   OP_PARAMS = [
-    ("duration", ht.NoDefault, ht.TFloat, None),
+    ("duration", ht.NoDefault, ht.TNumber, None),
     ("on_master", True, ht.TBool, None),
     ("on_nodes", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), None),
     ("repeat", 0, ht.TPositiveInt, None),