summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rwxr-xr-xcli/job.py45
-rwxr-xr-xcli/job_unittest.py191
-rwxr-xr-xcli/topic_common.py1
3 files changed, 229 insertions, 8 deletions
diff --git a/cli/job.py b/cli/job.py
index 8d8d61cf..276f9b10 100755
--- a/cli/job.py
+++ b/cli/job.py
@@ -150,14 +150,33 @@ class job_stat(job_list_stat):
self.parser.add_option('-f', '--control-file',
help='Display the control file',
action='store_true', default=False)
+ self.parser.add_option('-N', '--list-hosts',
+ help='Display only a list of hosts',
+ action='store_true')
+ self.parser.add_option('-s', '--list-hosts-status',
+ help='Display only the hosts in these statuses '
+ 'for a job.', action='store')
def parse(self):
- options, leftover = super(job_stat, self).parse(req_items='jobs')
+ status_list = topic_common.item_parse_info(
+ attribute_name='status_list',
+ inline_option='list_hosts_status')
+ options, leftover = super(job_stat, self).parse([status_list],
+ req_items='jobs')
+
if not self.jobs:
self.invalid_syntax('Must specify at least one job.')
self.show_control_file = options.control_file
+ self.list_hosts = options.list_hosts
+
+ if self.list_hosts and self.status_list:
+ self.invalid_syntax('--list-hosts is implicit when using '
+ '--list-hosts-status.')
+ if len(self.jobs) > 1 and (self.list_hosts or self.status_list):
+ self.invalid_syntax('--list-hosts and --list-hosts-status should '
+ 'only be used on a single job.')
return options, leftover
@@ -176,11 +195,23 @@ class job_stat(job_list_stat):
job_id = job['id']
if hosts_status.has_key(job_id):
this_job = hosts_status[job_id]
- host_per_status = ['%s=%s' %(status, ','.join(host))
+ job['hosts'] = ' '.join(' '.join(host) for host in
+ this_job.itervalues())
+ host_per_status = ['%s="%s"' %(status, ' '.join(host))
for status, host in this_job.iteritems()]
job['hosts_status'] = ', '.join(host_per_status)
+ if self.status_list:
+ statuses = set(s.lower() for s in self.status_list)
+ all_hosts = [s for s in host_per_status if s.split('=',
+ 1)[0].lower() in statuses]
+ job['hosts_selected_status'] = '\n'.join(all_hosts)
else:
job['hosts_status'] = ''
+
+ if not job.get('hosts'):
+ self.generic_error('Job has unassigned meta-hosts, '
+ 'try again shortly.')
+
return summary
@@ -199,7 +230,11 @@ class job_stat(job_list_stat):
def output(self, results):
- if not self.verbose:
+ if self.list_hosts:
+ keys = ['hosts']
+ elif self.status_list:
+ keys = ['hosts_selected_status']
+ elif not self.verbose:
keys = ['id', 'name', 'priority', 'status_counts', 'hosts_status']
else:
keys = ['id', 'name', 'priority', 'status_counts', 'hosts_status',
@@ -433,10 +468,6 @@ class job_create(job_create_or_clone):
self.generic_error('Unable to read from specified '
'control-file: %s' % options.control_file)
if options.kernel:
- if options.server:
- self.invalid_syntax(
- 'A control file and a kernel may only be specified'
- ' together on client side jobs.')
# execute() will pass this to the AFE server to wrap this
# control file up to include the kernel installation steps.
self.ctrl_file_data['client_control_file'] = control_file_data
diff --git a/cli/job_unittest.py b/cli/job_unittest.py
index 4e572cd6..90072587 100755
--- a/cli/job_unittest.py
+++ b/cli/job_unittest.py
@@ -254,6 +254,195 @@ class job_stat_unittest(job_unittest):
'Aborted'])
+
+ def test_job_stat_list_unassigned_host(self):
+ self.run_cmd(argv=['atest', 'job', 'stat', '6761',
+ '--list-hosts', '--ignore_site_file'],
+ rpcs=[('get_jobs_summary', {'id__in': ['6761']}, True,
+ [{u'status_counts': {u'Queued': 1},
+ u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test_on_meta_hosts',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761}]),
+ ('get_host_queue_entries', {'job__in': ['6761']},
+ True,
+ [{u'status': u'Queued',
+ u'complete': 0,
+ u'deleted': 0,
+ u'host': None,
+ u'priority': 1,
+ u'meta_host': u'Xeon',
+ u'job': {u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test_on_meta_hosts',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761},
+ u'active': 0,
+ u'id': 193166} ])],
+ err_words_ok=['unassigned', 'meta-hosts'],
+ out_words_no=['Xeon'])
+
+
+ def test_job_stat_list_hosts(self):
+ self.run_cmd(argv=['atest', 'job', 'stat', '6761',
+ '--list-hosts', '--ignore_site_file'],
+ rpcs=[('get_jobs_summary', {'id__in': ['6761']}, True,
+ [{u'status_counts': {u'Queued': 1},
+ u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test_on_meta_hosts',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761}]),
+ ('get_host_queue_entries', {'job__in': ['6761']},
+ True,
+ [{u'status': u'Queued',
+ u'complete': 0,
+ u'deleted': 0,
+ u'host': {u'status': u'Running',
+ u'lock_time': None,
+ u'hostname': u'host41',
+ u'locked': False,
+ u'locked_by': None,
+ u'invalid': False,
+ u'id': 4833,
+ u'protection': u'Repair filesystem only',
+ u'synch_id': None},
+ u'priority': 1,
+ u'meta_host': u'Xeon',
+ u'job': {u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test_on_meta_hosts',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761},
+ u'active': 0,
+ u'id': 193166},
+ {u'status': u'Running',
+ u'complete': 0,
+ u'deleted': 0,
+ u'host': {u'status': u'Running',
+ u'lock_time': None,
+ u'hostname': u'host42',
+ u'locked': False,
+ u'locked_by': None,
+ u'invalid': False,
+ u'id': 4833,
+ u'protection': u'Repair filesystem only',
+ u'synch_id': None},
+ u'priority': 1,
+ u'meta_host': u'Xeon',
+ u'job': {u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test_on_meta_hosts',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761},
+ u'active': 0,
+ u'id': 193166} ])],
+ out_words_ok=['host41', 'host42'],
+ out_words_no=['Xeon', 'Running', 'Queued'],
+ err_words_no=['unassigned'])
+
+
+ def test_job_stat_list_hosts_status(self):
+ self.run_cmd(argv=['atest', 'job', 'stat', '6761',
+ '--list-hosts-status', 'Running,Queued',
+ '--ignore_site_file'],
+ rpcs=[('get_jobs_summary', {'id__in': ['6761']}, True,
+ [{u'status_counts': {u'Queued': 1, u'Running': 1},
+ u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761}]),
+ ('get_host_queue_entries', {'job__in': ['6761']},
+ True,
+ [{u'status': u'Queued',
+ u'complete': 0,
+ u'deleted': 0,
+ u'host': {u'status': u'Queued',
+ u'lock_time': None,
+ u'hostname': u'host41',
+ u'locked': False,
+ u'locked_by': None,
+ u'invalid': False,
+ u'id': 4833,
+ u'protection': u'Repair filesystem only',
+ u'synch_id': None},
+ u'priority': 1,
+ u'meta_host': None,
+ u'job': {u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761},
+ u'active': 0,
+ u'id': 193166},
+ {u'status': u'Running',
+ u'complete': 0,
+ u'deleted': 0,
+ u'host': {u'status': u'Running',
+ u'lock_time': None,
+ u'hostname': u'host42',
+ u'locked': False,
+ u'locked_by': None,
+ u'invalid': False,
+ u'id': 4833,
+ u'protection': u'Repair filesystem only',
+ u'synch_id': None},
+ u'priority': 1,
+ u'meta_host': None,
+ u'job': {u'control_file': u'def step_init():\n job.next_step(\'step0\')\n\ndef step0():\n AUTHOR = "mbligh@google.com (Martin Bligh)"\n NAME = "Kernbench"\n TIME = "SHORT"\n TEST_CLASS = "Kernel"\n TEST_CATEGORY = "Benchmark"\n TEST_TYPE = "client"\n \n DOC = """\n A standard CPU benchmark. Runs a kernel compile and measures the performance.\n """\n \n job.run_test(\'kernbench\')',
+ u'name': u'test',
+ u'control_type': u'Client',
+ u'run_verify': 1,
+ u'priority': u'Medium',
+ u'owner': u'user0',
+ u'created_on': u'2008-07-30 22:15:43',
+ u'timeout': 144,
+ u'synch_count': 1,
+ u'id': 6761},
+ u'active': 0,
+ u'id': 193166} ])],
+ out_words_ok=['Queued', 'Running', 'host41', 'host42'],
+ out_words_no=['Xeon'],
+ err_words_no=['unassigned'])
+
+
def test_job_stat_job_multiple_hosts(self):
self.run_cmd(argv=['atest', 'job', 'stat', '6761',
'--ignore_site_file'],
@@ -398,7 +587,7 @@ class job_stat_unittest(job_unittest):
u'id': 180},
u'active': 0,
u'id': 101084}])],
- out_words_ok=['test_job0', 'Aborted'])
+ err_words_ok=['unassigned', 'meta-hosts'])
def test_job_stat_multi_jobs(self):
diff --git a/cli/topic_common.py b/cli/topic_common.py
index 6ef2a9cc..c6529ea4 100755
--- a/cli/topic_common.py
+++ b/cli/topic_common.py
@@ -86,6 +86,7 @@ KEYS_TO_NAMES_EN = {'hostname': 'Host',
'owner': 'Owner',
'status_counts': 'Status Counts',
'hosts_status': 'Host Status',
+ 'hosts_selected_status': 'Hosts filtered by Status',
'priority': 'Priority',
'control_type': 'Control Type',
'created_on': 'Created On',