+def MakeParamsDict(opts, params):
+ """Makes params dictionary out of a option set.
+
+ This function returns a dictionary needed for hv or be parameters. But only
+ those fields which provided in the option set. Takes parameters frozensets
+ from constants.
+
+ @type opts: dict
+ @param opts: selected options
+ @type params: frozenset
+ @param params: subset of options
+ @rtype: dict
+ @return: dictionary of options, filtered by given subset.
+
+ """
+ result = {}
+
+ for p in params:
+ try:
+ value = opts[p]
+ except KeyError:
+ continue
+ result[p] = value
+
+ return result
+
+
+def FillOpcode(opcls, body, static, rename=None):
+ """Fills an opcode with body parameters.
+
+ Parameter types are checked.
+
+ @type opcls: L{opcodes.OpCode}
+ @param opcls: Opcode class
+ @type body: dict
+ @param body: Body parameters as received from client
+ @type static: dict
+ @param static: Static parameters which can't be modified by client
+ @type rename: dict
+ @param rename: Renamed parameters, key as old name, value as new name
+ @return: Opcode object
+
+ """
+ CheckType(body, dict, "Body contents")
+
+ # Make copy to be modified
+ params = body.copy()
+
+ if rename:
+ for old, new in rename.items():
+ if new in params and old in params:
+ raise http.HttpBadRequest("Parameter '%s' was renamed to '%s', but"
+ " both are specified" %
+ (old, new))
+ if old in params:
+ assert new not in params
+ params[new] = params.pop(old)
+
+ if static:
+ overwritten = set(params.keys()) & set(static.keys())
+ if overwritten:
+ raise http.HttpBadRequest("Can't overwrite static parameters %r" %
+ overwritten)
+
+ params.update(static)
+
+ # Convert keys to strings (simplejson decodes them as unicode)
+ params = dict((str(key), value) for (key, value) in params.items())
+
+ try:
+ op = opcls(**params) # pylint: disable=W0142
+ op.Validate(False)
+ except (errors.OpPrereqError, TypeError), err:
+ raise http.HttpBadRequest("Invalid body parameters: %s" % err)
+
+ return op
+
+
+def SubmitJob(op, cl=None):
+ """Generic wrapper for submit job, for better http compatibility.
+
+ @type op: list
+ @param op: the list of opcodes for the job
+ @type cl: None or luxi.Client
+ @param cl: optional luxi client to use
+ @rtype: string
+ @return: the job ID
+
+ """
+ try:
+ if cl is None:
+ cl = GetClient()
+ return cl.SubmitJob(op)
+ except errors.JobQueueFull:
+ raise http.HttpServiceUnavailable("Job queue is full, needs archiving")
+ except errors.JobQueueDrainError:
+ raise http.HttpServiceUnavailable("Job queue is drained, cannot submit")
+ except luxi.NoMasterError, err:
+ raise http.HttpBadGateway("Master seems to be unreachable: %s" % str(err))
+ except luxi.PermissionError:
+ raise http.HttpInternalServerError("Internal error: no permission to"
+ " connect to the master daemon")
+ except luxi.TimeoutError, err:
+ raise http.HttpGatewayTimeout("Timeout while talking to the master"
+ " daemon. Error: %s" % str(err))
+
+
+def HandleItemQueryErrors(fn, *args, **kwargs):
+ """Converts errors when querying a single item.
+
+ """
+ try:
+ return fn(*args, **kwargs)
+ except errors.OpPrereqError, err:
+ if len(err.args) == 2 and err.args[1] == errors.ECODE_NOENT:
+ raise http.HttpNotFound()
+
+ raise
+
+
+def GetClient():
+ """Geric wrapper for luxi.Client(), for better http compatiblity.
+
+ """
+ try:
+ return luxi.Client()
+ except luxi.NoMasterError, err:
+ raise http.HttpBadGateway("Master seems to unreachable: %s" % str(err))
+ except luxi.PermissionError:
+ raise http.HttpInternalServerError("Internal error: no permission to"
+ " connect to the master daemon")
+
+
+def FeedbackFn(msg):
+ """Feedback logging function for jobs.
+
+ We don't have a stdout for printing log messages, so log them to the
+ http log at least.
+
+ @param msg: the message
+
+ """
+ (_, log_type, log_msg) = msg
+ logging.info("%s: %s", log_type, log_msg)
+
+
+def CheckType(value, exptype, descr):
+ """Abort request if value type doesn't match expected type.
+
+ @param value: Value
+ @type exptype: type
+ @param exptype: Expected type
+ @type descr: string
+ @param descr: Description of value
+ @return: Value (allows inline usage)
+
+ """
+ if not isinstance(value, exptype):
+ raise http.HttpBadRequest("%s: Type is '%s', but '%s' is expected" %
+ (descr, type(value).__name__, exptype.__name__))
+
+ return value
+
+
+def CheckParameter(data, name, default=_DEFAULT, exptype=_DEFAULT):
+ """Check and return the value for a given parameter.
+
+ If no default value was given and the parameter doesn't exist in the input
+ data, an error is raise.
+
+ @type data: dict
+ @param data: Dictionary containing input data
+ @type name: string
+ @param name: Parameter name
+ @param default: Default value (can be None)
+ @param exptype: Expected type (can be None)
+
+ """
+ try:
+ value = data[name]
+ except KeyError:
+ if default is not _DEFAULT:
+ return default
+
+ raise http.HttpBadRequest("Required parameter '%s' is missing" %
+ name)
+
+ if exptype is _DEFAULT:
+ return value
+
+ return CheckType(value, exptype, "'%s' parameter" % name)
+
+