Commit bac5ffc3 authored by Oleksiy Mishchenko's avatar Oleksiy Mishchenko
Browse files

Implement jobs resource in RAPI

Reviewed-by: imsnah
parent 8075ce7e
......@@ -28,7 +28,7 @@ PROTOCOL_VERSION = 13
RELEASE_VERSION = _autoconf.PACKAGE_VERSION
OS_API_VERSION = 5
EXPORT_VERSION = 0
RAPI_VERSION = 1
RAPI_VERSION = 2
# Format for CONFIG_VERSION:
......@@ -254,6 +254,8 @@ JOB_QUEUE_LOCK_FILE = QUEUE_DIR + "/lock"
JOB_QUEUE_VERSION_FILE = QUEUE_DIR + "/version"
JOB_QUEUE_SERIAL_FILE = QUEUE_DIR + "/serial"
JOB_ID_TEMPLATE = r"\d+"
# Job status
JOB_STATUS_QUEUED = "queued"
JOB_STATUS_RUNNING = "running"
......
......@@ -264,7 +264,7 @@ class _JobQueueWorkerPool(workerpool.WorkerPool):
class JobStorage(object):
_RE_JOB_FILE = re.compile(r"^job-(\d+)$")
_RE_JOB_FILE = re.compile(r"^job-(%s)$" % constants.JOB_ID_TEMPLATE)
def __init__(self):
self._lock = threading.Lock()
......
......@@ -31,6 +31,7 @@ import ganeti.errors
import ganeti.cli
from ganeti import constants
from ganeti import luxi
from ganeti import utils
from ganeti.rapi import httperror
......@@ -39,22 +40,25 @@ from ganeti.rapi import httperror
_CONNECTOR = {}
def BuildUriList(names, uri_format):
def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
"""Builds a URI list as used by index resources.
Args:
- names: List of names as strings
- ids: List of ids as strings
- uri_format: Format to be applied for URI
- uri_fields: Optional parameter for field ids
"""
def _MapName(name):
return { "name": name, "uri": uri_format % name, }
(field_id, field_uri) = uri_fields
def _MapId(m_id):
return { field_id: m_id, field_uri: uri_format % m_id, }
# Make sure the result is sorted, makes it nicer to look at and simplifies
# unittests.
names.sort()
ids.sort()
return map(_MapName, names)
return map(_MapId, ids)
def ExtractField(sequence, index):
......@@ -523,6 +527,52 @@ class R_os(R_Generic):
return [row[0] for row in diagnose_data if row[1]]
class R_2_jobs(R_Generic):
"""/2/jobs resource.
"""
DOC_URI = "/2/jobs"
def GET(self):
"""Returns a dictionary of jobs.
Returns:
A dictionary with jobs id and uri.
"""
fields = ["id"]
# Convert the list of lists to the list of ids
result = [job_id for [job_id] in luxi.Client().QueryJobs(None, fields)]
return BuildUriList(result, "/2/jobs/%s", uri_fields=("id", "uri"))
class R_2_jobs_id(R_Generic):
"""/2/jobs/[job_id] resource.
"""
DOC_URI = "/2/jobs/[job_id]"
def GET(self):
"""Returns a job status.
Returns:
A dictionary with job parameters.
The result includes:
id - job ID as a number
status - current job status as a string
ops - involved OpCodes as a list of dictionaries for each opcodes in
the job
opstatus - OpCodes status as a list
opresult - OpCodes results as a list of lists
"""
fields = ["id", "ops", "status", "opstatus", "opresult"]
job_id = self.items[0]
result = luxi.Client().QueryJobs([job_id,], fields)[0]
return MapFields(fields, result)
_CONNECTOR.update({
"/": R_root,
......@@ -540,4 +590,7 @@ _CONNECTOR.update({
re.compile(r'^/instances/([\w\._-]+)/tags$'): R_instances_name_tags,
"/os": R_os,
"/2/jobs": R_2_jobs,
re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): R_2_jobs_id,
})
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment