Author: tmckay
Date: 2012-09-26 21:06:23 +0000 (Wed, 26 Sep 2012)
New Revision: 5480
Modified:
trunk/cumin/python/cumin/grid/job.py
trunk/cumin/python/cumin/model.py
Log:
Submission membership checks on job control actions
BZ837047
Modified: trunk/cumin/python/cumin/grid/job.py
===================================================================
--- trunk/cumin/python/cumin/grid/job.py 2012-09-26 20:56:34 UTC (rev 5479)
+++ trunk/cumin/python/cumin/grid/job.py 2012-09-26 21:06:23 UTC (rev 5480)
@@ -104,43 +104,58 @@
return (self.parent,
"Logged in user does not own the specified submission")
- def do_process(self, session):
- super(JobFrame, self).do_process(session)
+ def get_job_ad(self, session, id=None, job_id=None):
+ if id is None:
+ id = self.id.get(session)
+ if job_id is None:
+ job_id = self.job_id.get(session)
+ submission, job_server, sched = self.get_trifecta(session, id)
+ results = self.app.remote.get_job_ad(job_server, job_id,
+ sched.Name, submission,
+ default={'JobAd': {}})
+ return results
- # Make sure that the job belongs to the designated submission.
- id = self.id.get(session)
- submission, js, sched = self.get_trifecta(session, id)
+ def check_submission_membership(self, session, sub_id, job_id):
+ frame = None
+ message = ""
+ submission, js, sched = self.get_trifecta(session, sub_id)
summaries = self.app.model.get_submission_job_summaries(submission,
sched.Name)
- okay = False
- frame = None
- message = ""
- if summaries.data is None:
+
+ # Make sure that the job belongs to the designated submission.
+ # None = no data
+ # True/False indicates job is a member of the submission
+ okay = summaries.check_submission_membership(job_id)
+
+ if okay is None:
# Well, someone is requesting a particular job but we have no
# data yet so we don't know if it is legit or not. Redirect
# to the parent frame, but without a notice. Normally data should
# be present because the trail through Cumin goes to the submission
# job list first, with a link to a particular job.
frame = self.parent
- else:
- job_id = self.job_id.get(session)
- for summary in summaries.data:
- if str(summary["ClusterId"]) + "." + \
- str(summary["ProcId"]) == job_id:
- okay = True
- break
+ elif not okay:
+ frame = self.parent
+ message = "Job %s is not part "\
+ "of the specified submission" % job_id
- if not okay:
- frame = self.parent
- message = "The specified job is not part "\
- "of the specified submission"
+ return okay, frame, message
+ def do_process(self, session):
+ super(JobFrame, self).do_process(session)
+
+ # Make sure that the job belongs to the designated submission.
+ sub_id = self.id.get(session)
+ job_id = self.job_id.get(session)
+ okay, frame, message = self.check_submission_membership(session,
+ sub_id, job_id)
# If the check failed and there is not yet a redirect
# value, set the redirect. Add the notice in either case.
- if not self.get_redirect(session) and frame:
- self.set_redirect(session, frame, message)
- elif message:
- session.add_notice(Notice(message))
+ if not okay:
+ if not self.get_redirect(session) and frame:
+ self.set_redirect(session, frame, message)
+ elif message:
+ session.add_notice(Notice(message))
class JobAdModes(ModeSet):
def __init__(self, app, name, check_viewable):
@@ -453,15 +468,14 @@
return ": ".join(reason)
def process_submit(self, session):
- self.validate(session)
+ selection = self.selection.get(session)
+ submission, scheduler = self.get_submission_sched(session)
+ self.validate(session, selection, submission, scheduler)
+
errors = self.errors.get(session)
if not errors:
- selection = self.selection.get(session)
reason = self.get_reason(session, self.verb)
-
- submission, scheduler = self.get_submission_sched(session)
-
self.task.invoke(session, selection, scheduler, reason, submission)
self.task.exit_with_redirect(session)
@@ -482,24 +496,45 @@
reason = self.reason.render(session)
return "<table
class=\"FormFieldSet\"><tbody>%s</tbody></table>%s" %
(reason, content)
- def validate(self, session):
+ def validate(self, session,
+ selection=None, submission=None, sched=None):
super(JobObjectSelectorTaskForm, self).validate(session)
if not self.errors.get(session) and \
self.app.authorizator.is_enforcing():
+
+ if selection is None:
+ selection = self.get_selection(session)
+ if submission is None or sched is None:
+ submission, sched = self.get_submission_sched(session)
+
# Check here to make sure the logged in user owns
# the submission or is an admin
login = session.client_session.attributes["login_session"]
if "admin" not in login.group:
user = login.user.name
- submission_id = self.submission_id.get(session)
- cls = self.app.model.com_redhat_grid.Submission
- submission = cls.get_object_by_id(session.cursor,
- submission_id)
if hasattr(submission, "Owner") and submission.Owner != user:
f = FormError("The logged in user does not "\
"own this submission.")
self.errors.add(session, f)
-
+
+ # Check that the job is a member of the submission
+ summaries = self.app.model.get_submission_job_summaries(submission,
+ sched.Name)
+
+ # Make sure that the job belongs to the designated submission.
+ # None = no data
+ # True/False indicates job is a member of the submission
+ for sel in selection:
+ okay = summaries.check_submission_membership(sel)
+ if okay is None:
+ f = FormError("Unable to verify job %s" \
+ " is a member of the submission" % sel)
+ self.errors.add(session, f)
+ elif not okay:
+ f = FormError("Job %s is not part of" \
+ " the specified submission" % sel)
+ self.errors.add(session, f)
+
class JobAdsSet(PropertySet):
types = {0: "expression",
1: "integer",
@@ -518,13 +553,8 @@
self.do_check_viewable = False
def get_job_ad(self, session):
- id = self.frame.id.get(session)
- submission, job_server, sched = self.frame.get_trifecta(session, id)
- job_id = self.frame.job_id.get(session)
- results = self.app.remote.get_job_ad(job_server, job_id,
- sched.Name, submission,
- default={'JobAd': {}})
- return results
+ # defer to the frame because it's got all the data
+ return self.frame.get_job_ad(session)
def check_job_owner(self, session, ad):
error = None
@@ -543,7 +573,7 @@
results = self.get_job_ad(session)
error = None
if results.error:
- error = results.error
+ error = results.error
elif self.do_check_viewable:
error = self.check_job_owner(session, results.data['JobAd'])
@@ -628,13 +658,12 @@
if not ad_list and not error:
ad_list = list()
- id = self.frame.id.get(session)
- submission, job_server, sched = self.frame.get_trifecta(session, id)
- job_id = self.frame.job_id.get(session)
- results = self.app.remote.get_job_ad(job_server, job_id,
- sched.Name, submission,
- default={'JobAd': {}})
- error = results.error
+ error = None
+ results = self.get_job_ad(session)
+ if results.error:
+ error = results.error
+ elif self.do_check_viewable:
+ error = self.check_job_owner(session, results.data['JobAd'])
self.qmf_error.set(session, error)
ads = results.data['JobAd']
cls = self.app.model.job_meta_data
@@ -1266,18 +1295,31 @@
super(JobActionForm, self).validate(session)
if not self.errors.get(session) and \
self.app.authorizator.is_enforcing():
+ id = self.id.get(session)
+
+ # Make sure that the job belongs to the designated submission.
+ job_id = self.job_id.get(session)
+ okay, frame, message = \
+ self.task.frame.check_submission_membership(session, id, job_id)
+ if not okay:
+ if not message:
+ message = "Unable to verify this job" \
+ " is a member of the submission"
+ f = FormError(message)
+ self.errors.add(session, f)
+ return
+
# Check here to make sure the logged in user owns
- # the job or is an admin
+ # the submission and job or is an admin
login = session.client_session.attributes["login_session"]
if "admin" not in login.group:
user = login.user.name
- id = self.id.get(session)
submission = self.task.frame.get_submission(session, id)
if hasattr(submission, "Owner") and submission.Owner != user:
f = FormError("The logged in user does not "\
"own this submission.")
self.errors.add(session, f)
-
+
class ReasonField(NoXMLStringField):
def render_title(self, session):
return "Reason"
Modified: trunk/cumin/python/cumin/model.py
===================================================================
--- trunk/cumin/python/cumin/model.py 2012-09-26 20:56:34 UTC (rev 5479)
+++ trunk/cumin/python/cumin/model.py 2012-09-26 21:06:23 UTC (rev 5480)
@@ -809,6 +809,19 @@
super(SubmissionJobSummaryStore, self).delete()
+ def check_submission_membership(self, job_id):
+
+ # Make sure that the job belongs to the designated submission.
+ okay = None
+ if self.data is not None:
+ okay = False
+ for summary in self.data:
+ if str(summary["ClusterId"]) + "." + \
+ str(summary["ProcId"]) == job_id:
+ okay = True
+ break
+ return okay
+
class NegotiatorGroupNamesStore(ObjectStore):
def __init__(self, model, negotiator):
super(NegotiatorGroupNamesStore, self).__init__(model)