31 |
31 |
import ganeti.cli
|
32 |
32 |
|
33 |
33 |
from ganeti import constants
|
|
34 |
from ganeti import luxi
|
34 |
35 |
from ganeti import utils
|
35 |
36 |
from ganeti.rapi import httperror
|
36 |
37 |
|
... | ... | |
39 |
40 |
_CONNECTOR = {}
|
40 |
41 |
|
41 |
42 |
|
42 |
|
def BuildUriList(names, uri_format):
|
|
43 |
def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
|
43 |
44 |
"""Builds a URI list as used by index resources.
|
44 |
45 |
|
45 |
46 |
Args:
|
46 |
|
- names: List of names as strings
|
|
47 |
- ids: List of ids as strings
|
47 |
48 |
- uri_format: Format to be applied for URI
|
|
49 |
- uri_fields: Optional parameter for field ids
|
48 |
50 |
|
49 |
51 |
"""
|
50 |
|
def _MapName(name):
|
51 |
|
return { "name": name, "uri": uri_format % name, }
|
|
52 |
(field_id, field_uri) = uri_fields
|
|
53 |
|
|
54 |
def _MapId(m_id):
|
|
55 |
return { field_id: m_id, field_uri: uri_format % m_id, }
|
52 |
56 |
|
53 |
57 |
# Make sure the result is sorted, makes it nicer to look at and simplifies
|
54 |
58 |
# unittests.
|
55 |
|
names.sort()
|
|
59 |
ids.sort()
|
56 |
60 |
|
57 |
|
return map(_MapName, names)
|
|
61 |
return map(_MapId, ids)
|
58 |
62 |
|
59 |
63 |
|
60 |
64 |
def ExtractField(sequence, index):
|
... | ... | |
523 |
527 |
return [row[0] for row in diagnose_data if row[1]]
|
524 |
528 |
|
525 |
529 |
|
|
530 |
class R_2_jobs(R_Generic):
|
|
531 |
"""/2/jobs resource.
|
|
532 |
|
|
533 |
"""
|
|
534 |
DOC_URI = "/2/jobs"
|
|
535 |
|
|
536 |
def GET(self):
|
|
537 |
"""Returns a dictionary of jobs.
|
|
538 |
|
|
539 |
Returns:
|
|
540 |
A dictionary with jobs id and uri.
|
|
541 |
|
|
542 |
"""
|
|
543 |
fields = ["id"]
|
|
544 |
# Convert the list of lists to the list of ids
|
|
545 |
result = [job_id for [job_id] in luxi.Client().QueryJobs(None, fields)]
|
|
546 |
return BuildUriList(result, "/2/jobs/%s", uri_fields=("id", "uri"))
|
|
547 |
|
|
548 |
|
|
549 |
class R_2_jobs_id(R_Generic):
|
|
550 |
"""/2/jobs/[job_id] resource.
|
|
551 |
|
|
552 |
"""
|
|
553 |
DOC_URI = "/2/jobs/[job_id]"
|
|
554 |
|
|
555 |
def GET(self):
|
|
556 |
"""Returns a job status.
|
|
557 |
|
|
558 |
Returns:
|
|
559 |
A dictionary with job parameters.
|
|
560 |
|
|
561 |
The result includes:
|
|
562 |
id - job ID as a number
|
|
563 |
status - current job status as a string
|
|
564 |
ops - involved OpCodes as a list of dictionaries for each opcodes in
|
|
565 |
the job
|
|
566 |
opstatus - OpCodes status as a list
|
|
567 |
opresult - OpCodes results as a list of lists
|
|
568 |
|
|
569 |
"""
|
|
570 |
fields = ["id", "ops", "status", "opstatus", "opresult"]
|
|
571 |
job_id = self.items[0]
|
|
572 |
result = luxi.Client().QueryJobs([job_id,], fields)[0]
|
|
573 |
return MapFields(fields, result)
|
|
574 |
|
|
575 |
|
526 |
576 |
_CONNECTOR.update({
|
527 |
577 |
"/": R_root,
|
528 |
578 |
|
... | ... | |
540 |
590 |
re.compile(r'^/instances/([\w\._-]+)/tags$'): R_instances_name_tags,
|
541 |
591 |
|
542 |
592 |
"/os": R_os,
|
|
593 |
|
|
594 |
"/2/jobs": R_2_jobs,
|
|
595 |
re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): R_2_jobs_id,
|
543 |
596 |
})
|