+_PTags = ("tags", ht.NoDefault, ht.TListOf(ht.TNonEmptyString), None)
+
+_PForceVariant = ("force_variant", False, ht.TBool,
+ "Whether to force an unknown OS variant")
+
+_PWaitForSync = ("wait_for_sync", True, ht.TBool,
+ "Whether to wait for the disk to synchronize")
+
+_PIgnoreConsistency = ("ignore_consistency", False, ht.TBool,
+ "Whether to ignore disk consistency")
+
+_PStorageName = ("name", ht.NoDefault, ht.TMaybeString, "Storage name")
+
+_PUseLocking = ("use_locking", False, ht.TBool,
+ "Whether to use synchronization")
+
+_PNameCheck = ("name_check", True, ht.TBool, "Whether to check name")
+
+_PNodeGroupAllocPolicy = \
+ ("alloc_policy", None,
+ ht.TOr(ht.TNone, ht.TElemOf(constants.VALID_ALLOC_POLICIES)),
+ "Instance allocation policy")
+
+_PGroupNodeParams = ("ndparams", None, ht.TMaybeDict,
+ "Default node parameters for group")
+
+_PQueryWhat = ("what", ht.NoDefault, ht.TElemOf(constants.QR_VIA_OP),
+ "Resource(s) to query for")
+
+_PEarlyRelease = ("early_release", False, ht.TBool,
+ "Whether to release locks as soon as possible")
+
+_PIpCheckDoc = "Whether to ensure instance's IP address is inactive"
+
+#: Do not remember instance state changes
+_PNoRemember = ("no_remember", False, ht.TBool,
+ "Do not remember the state change")
+
+#: Target node for instance migration/failover
+_PMigrationTargetNode = ("target_node", None, ht.TMaybeString,
+ "Target node for shared-storage instances")
+
+_PStartupPaused = ("startup_paused", False, ht.TBool,
+ "Pause instance at startup")
+
+_PVerbose = ("verbose", False, ht.TBool, "Verbose mode")
+
+# Parameters for cluster verification
+_PDebugSimulateErrors = ("debug_simulate_errors", False, ht.TBool,
+ "Whether to simulate errors (useful for debugging)")
+_PErrorCodes = ("error_codes", False, ht.TBool, "Error codes")
+_PSkipChecks = ("skip_checks", ht.EmptyList,
+ ht.TListOf(ht.TElemOf(constants.VERIFY_OPTIONAL_CHECKS)),
+ "Which checks to skip")
+
+#: 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")(compat.fst),
+ ht.TElemOf(constants.DDMS_VALUES)))))
+
+
+# TODO: Generate check from constants.INIC_PARAMS_TYPES
+#: Utility function for testing NIC definitions
+_TestNicDef = ht.TDictOf(ht.TElemOf(constants.INIC_PARAMS),
+ ht.TOr(ht.TNone, ht.TNonEmptyString))
+
+_TSetParamsResultItemItems = [
+ ht.Comment("name of changed parameter")(ht.TNonEmptyString),
+ ht.TAny,
+ ]
+
+_TSetParamsResult = \
+ ht.TListOf(ht.TAnd(ht.TIsLength(len(_TSetParamsResultItemItems)),
+ ht.TItems(_TSetParamsResultItemItems)))
+
+_SUMMARY_PREFIX = {
+ "CLUSTER_": "C_",
+ "GROUP_": "G_",
+ "NODE_": "N_",
+ "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.
+
+ @type name: string
+ @param name: the class name, as OpXxxYyy
+ @rtype: string
+ @return: the name in the OP_XXXX_YYYY format
+
+ """
+ if not name.startswith("Op"):
+ return None
+ # Note: (?<=[a-z])(?=[A-Z]) would be ideal, since it wouldn't
+ # consume any input, and hence we would just have all the elements
+ # in the list, one by one; but it seems that split doesn't work on
+ # non-consuming input, hence we have to process the input string a
+ # bit
+ name = _OPID_RE.sub(r"\1,\2", name)
+ elems = name.split(",")
+ return "_".join(n.upper() for n in elems)