Author: eallen
Date: 2010-06-30 16:28:45 -0400 (Wed, 30 Jun 2010)
New Revision: 4059
Added:
mgmt/newdata/cumin/model/qmf.xml
mgmt/newdata/cumin/python/cumin/qmfadapter.py
Modified:
mgmt/newdata/cumin/model/rosemary.xml
mgmt/newdata/cumin/python/cumin/grid/job.py
mgmt/newdata/cumin/python/cumin/grid/job.strings
mgmt/newdata/cumin/python/cumin/grid/submission.py
mgmt/newdata/cumin/python/cumin/inventory/system.py
mgmt/newdata/cumin/python/cumin/main.py
mgmt/newdata/cumin/python/cumin/model.py
mgmt/newdata/cumin/python/cumin/objectframe.py
mgmt/newdata/cumin/python/cumin/objectselector.py
mgmt/newdata/cumin/python/cumin/objecttask.py
mgmt/newdata/cumin/python/cumin/parameters.py
Log:
Moving jobs under submissions and using new schema methods
Added: mgmt/newdata/cumin/model/qmf.xml
===================================================================
--- mgmt/newdata/cumin/model/qmf.xml (rev 0)
+++ mgmt/newdata/cumin/model/qmf.xml 2010-06-30 20:28:45 UTC (rev 4059)
@@ -0,0 +1,13 @@
+<schema package="qmf.response" type="transient">
+ <class name="GetJobSummaries">
+ <property name="ProcId" type="sstr"/>
+ <property name="Args" type="sstr"/>
+ <property name="QDate" type="absTime"/>
+ <property name="Cmd" type="sstr"/>
+ <property name="ClusterId" type="sstr"/>
+ <property name="JobStatus" type="sstr"/>
+ <property name="EnteredCurrentStatus" type="absTime"/>
+ <property name="GlobalJobId" type="sstr"/>
+ </class>
+
+</schema>
Modified: mgmt/newdata/cumin/model/rosemary.xml
===================================================================
--- mgmt/newdata/cumin/model/rosemary.xml 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/model/rosemary.xml 2010-06-30 20:28:45 UTC (rev 4059)
@@ -1,4 +1,21 @@
<model>
+ <package name="qmf.response">
+ <class name="GetJobSummaries">
+ <property name="GlobalJobId">
+ <title>Job Id</title>
+ </property>
+
+ <property name="Cmd">
+ <title>Command</title>
+ </property>
+
+ <property name="JobStatus">
+ <title>Job Status</title>
+ </property>
+
+ </class>
+ </package>
+
<package name="org.apache.qpid.broker">
<class name="Binding">
<property name="bindingKey">
Modified: mgmt/newdata/cumin/python/cumin/grid/job.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/job.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/grid/job.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -7,446 +7,208 @@
from wooly.tables import *
from time import time
from cumin.widgets import *
+from cumin.model import FetchJobAd, FetchJobOutput
+from cumin.objecttask import *
from cumin.parameters import *
from cumin.stat import *
from cumin.formats import *
from cumin.util import *
-from cumin.model import FetchJobAd, FetchJobOutput
+from cumin.qmfadapter import *
+
import main
strings = StringCatalog(__file__)
log = logging.getLogger("cumin.job")
-class JobSet(CuminQMFSelectionTable):
+class JobFrame(ObjectFrame):
def __init__(self, app, name, submission):
- item = JobParameter(app, "item")
- super(JobSet, self).__init__(app, name, item)
+ cls = app.model.com_redhat_grid.Submission
- self.submission = submission
+ super(JobFrame, self).__init__(app, name, cls)
- self.defer_enabled = True
- self.update_enabled = True
+ self.view = JobView(app, "view", self.object)
+ self.replace_child(self.view)
- col = self.CustomIdColumn(app, "name")
- self.add_column(col)
- self.set_default_column(col)
+ # view or edit
+ self.ads = JobAdModes(app, "ads")
+ self.view.add_tab(self.ads)
- col = self.CommandColumn(app, "Cmd")
- self.add_column(col)
+ self.view.add_tab(JobOutput(app, "output"))
- col = self.StatusColumn(app, "JobStatus")
- self.add_column(col)
+ self.job_id = Parameter(app, "job_id")
+ self.add_parameter(self.job_id)
- col = self.ArgsColumn(app, "Args")
- col.align = "right"
- self.add_column(col)
+ JobHold(app, self)
+ JobRelease(app, self)
+ JobRemove(app, self)
- self.phase = JobStatusSwitch(app, "phase")
- self.filters.add_child(self.phase)
+ # task not visible on page. used for edit submit
+ self.set_ad_task = JobSetAttribute(app, self)
- multi_param = self.SubmissionJob(app, "subjob", self.selection,
submission)
+ def get_title(self, session):
+ job_id = self.job_id.get(session)
+ return "Job %s" % job_id
- task = main.module.job_set_hold
- button = TaskButton(app, "hold", task, multi_param)
- self.buttons.add_child(button)
+ def show_ads_edit(self, session):
+ self.ads.editor.show(session)
- task = main.module.job_set_release
- button = TaskButton(app, "release", task, multi_param)
- self.buttons.add_child(button)
+ def show_ads_view(self, session):
+ self.ads.viewer.show(session)
- task = main.module.job_set_remove
- button = TaskButton(app, "remove", task, multi_param)
- self.buttons.add_child(button)
+ def get_submission(self, session, id):
+ return self.get_object(session, id)
- def do_get_items(self, session, *args):
- submission = self.submission.get(session)
+ def get_job_server(self, session, id):
+ submission = self.get_submission(session, id)
- jobs = self.app.model.get_submission_jobs(submission)
+ cls = self.app.model.com_redhat_grid.JobServer
+ return cls.get_object(session.cursor, _id=submission._jobserverRef_id)
- if jobs is None:
- return ()
+ def get_scheduler(self, session, id):
+ job_server = self.get_job_server(session, id)
- return jobs
+ pool = job_server.Pool
+ machine = job_server.Machine
- def filter_item(self, session, item):
- state = self.phase.get(session)
+ cls = self.app.model.com_redhat_grid.Scheduler
+ return cls.get_object(session.cursor, Pool=pool, Machine=machine)
- if state == "All":
- return True
+ def get_href(self, session, id, job_id):
+ branch = session.branch()
- item_state = item["JobStatus"]["VALUE"]
- item_state = JobStatusInfo.get_status_string(int(item_state))
+ self.id.set(branch, id)
+ self.job_id.set(branch, job_id)
+ self.view.show(branch)
- return state == item_state
+ return branch.marshal()
- def render_deferred_content(self, session, *args):
- return "Loading..."
+class JobView(ObjectView):
+ def add_details_tab(self):
+ pass
- def get_phase_title(self, session):
- state = self.phase.get(session)
- return self.phase.get_title(state)
+ def render_title(self, session):
+ return self.frame.get_title(session)
- class ArgsColumn(ItemTableColumn):
- def render_title(self, session):
- return "Arguments"
+class JobSummariesAdapter(ObjectQmfAdapter):
+ def get_data(self, values, options):
+ submission = values["obj"]
+ results = self.app.model.get_submission_job_summaries(submission)
+ rows = self.process_results(results)
+ return rows
- class CustomIdColumn(ItemTableColumn):
- def render_title(self, session):
- return "ID"
+ def get_count(self, values):
+ submission = values["obj"]
+ results = self.app.model.get_submission_job_summaries(submission)
+ return results and len(results) or 0
- def render_content(self, session, data):
- id = data[self.name]
+class JobSelector(ObjectSelector):
+ def __init__(self, app, name, submission):
+ cls = app.model.qmf_response.GetJobSummaries
+ adapter = JobSummariesAdapter(app, cls)
+ super(JobSelector, self).__init__(app, name, cls, adapter)
- if id:
- job = Identifiable(data["id"])
- scheduler = self.parent.submission.get(session).scheduler
- href = self.page.main.grid.pool.job.get_href(session, job, scheduler)
- job_id, hash, num = id.rpartition('#')
- return fmt_link(href, job_id, link_title=id)
+ self.submission = submission
+ frame = "main.grid.pool.submission.job"
+ self.job_id_col = self.JobIdColumn(app, "job", cls.GlobalJobId,
cls._id, frame)
+ self.add_column(self.job_id_col)
- class StatusColumn(ItemTableColumn):
- def render_title(self, session):
- return "Status"
+ status_column = self.Status(app, "status", cls.JobStatus)
+ self.add_column(status_column)
- def render_content(self, session, data):
- stat = data[self.name]
- return JobStatusInfo.get_status_string(int(stat))
+ self.add_attribute_column(cls.Cmd)
- class CommandColumn(ItemTableColumn):
- def render_title(self, session):
- return "Command"
+ # CluserId.ProdId is the string needed to get the job ad from the jobserver
+ self.proc_id_column = ObjectAttributeColumn(app, cls.ProcId.name, cls.ProcId)
+ self.proc_id_column.visible = False
+ self.add_column(self.proc_id_column)
- def render_content(self, session, data):
- return fmt_shorten(escape_entity(data[self.name]), 0, 16)
+ self.cluster_id_column = ObjectAttributeColumn(app, cls.ClusterId.name,
cls.ClusterId)
+ self.cluster_id_column.visible = False
+ self.add_column(self.cluster_id_column)
- class SubmissionJob(object):
- def __init__(self, app, name, job, submission):
- self.job = job
- self.submission = submission
-
- def get(self, session):
- return (self.job.get(session), self.submission.get(session))
-
-class JobTab(JobSet):
- def __init__(self, app, name, pool):
- super(JobTab, self).__init__(app, name, pool)
-
- self.job_search = self.JobSearch(app, "job_search")
- self.add_child(self.job_search)
-
- def render_title(self, session, *args):
+ def render_title(self, session):
return "Jobs"
- def find_job(self, session):
- search_term = self.job_search.get(session)
+ def get_data_values(self, session):
+ values = super(JobSelector, self).get_data_values(session)
- if search_term:
- object = self.frame.get_object(session)
- rows = self.find_item(session, object)
+ submission = self.submission.get(session)
- if rows:
- try:
- first = rows[0]
- job = Identifiable(first["id"])
- href = self.page.main.grid.pool.job.get_href(session, job)
- self.page.redirect.set(session, href)
- except:
- self.job_search.set_not_found(session, search_term)
- else:
- self.job_search.set_not_found(session, search_term)
+ if submission:
+ values['obj'] = submission
+ values['args'] = ()
+ return values
- self.job_search.set(session, None)
+ class JobIdColumn(ObjectLinkColumn):
+ def render_cell_href(self, session, record):
+ index = self.parent.cluster_id_column.field.index
+ cluster_id = record[index]
+ index = self.parent.proc_id_column.field.index
+ proc_id = record[index]
+ job_id = "%d.%d" % (cluster_id, proc_id)
+ frame = self.page.page_widgets_by_path[self.frame_path]
- def render_find_sql_where(self, session, *args):
- return "j.custom_id = %(custom_id)s"
+ submission = self.parent.submission.get(session)
+ return frame.get_href(session, submission._id, job_id)
- def get_find_sql_values(self, session, pool):
- return {"custom_id": self.job_search.get(session)}
- #return {"custom_id": self.job_search.get(session), "pool":
pool.id}
+ class Status(ObjectAttributeColumn):
+ def render_cell_content(self, session, record):
+ status = self.field.get_content(session, record)
+ return JobStatusInfo.get_status_string(status)
- def get_full_item_count(self, session, *args):
- # request item count with phase=="a"
- return self.get_item_count(session, 'a')
-
- def get_visible_columns(self, session):
- return self.get_request_visible_columns(session, ["custom_group",
"scheduler", "submitter"])
-
- def render_count(self, session, *args):
- count = self.get_item_count(session, *args)
- phase = self.get_phase_title(session)
- if phase == "All":
- phase = ""
- return "%i %s %s" % (count, phase, count == 1 and "Job" or
"Jobs")
-
- class JobSearch(StringInput):
- """ displays the input box and button used to search for job id
"""
-
- def __init__(self, app, name):
- super(JobTab.JobSearch, self).__init__(app, name)
-
- self.__go = self.JobSearchButton(app, "go")
- self.add_child(self.__go)
-
- self.not_found = Attribute(app, "error")
- self.add_attribute(self.not_found)
-
- def set_not_found(self, session, value):
- self.not_found.set(session, value)
-
- def render_search_prompt(self, session):
- not_found = self.not_found.get(session)
- return not_found and "%s Not Found" % escape_entity(not_found) or
self.render_search_default_prompt(session)
-
- def render_search_default_prompt(self, session):
- return "Enter Job ID"
-
- def render_search_class(self, session):
- return self.not_found.get(session) and "search_error" or "
"
-
- def find_job(self, session):
- self.parent.find_job(session)
-
- class JobSearchButton(FormButton):
- def process_submit(self, session):
- self.parent.find_job(session)
-
- def render_content(self, session):
- return "Go"
-
-class JobGroupFrame(CuminFrame):
- def __init__(self, app, name, pool):
- super(JobGroupFrame, self).__init__(app, name)
-
- self.object = JobGroupParameter(app, "id")
- self.add_parameter(self.object)
-
- self.view = JobGroupView(app, "view", pool)
- self.add_mode(self.view)
-
- # XXX link instead
- #self.system = SystemFrame(app, "system")
- #self.add_mode(self.system)
-
-class JobGroupView(CuminView):
- def __init__(self, app, name, pool):
- super(JobGroupView, self).__init__(app, name, pool)
-
- self.tabs = TabbedModeSet(app, "tabs")
- self.add_child(self.tabs)
-
- self.tabs.add_tab(JobGroupStats(app, "stats"))
- self.tabs.add_tab(JobGroupJobSet(app, "jobs", pool))
- #self.tabs.add_tab(JobGroupSystemSet(app, "systems"))
- #self.tabs.add_tab(CuminDetails(app, "details"))
-
-class JobGroupStats(Widget):
+class JobAdModes(ModeSet):
def __init__(self, app, name):
- super(JobGroupStats, self).__init__(app, name)
+ super(JobAdModes, self).__init__(app, name)
- #stats = JobGroupStatSet(app, "general", "general")
- #self.add_child(stats)
+ self.viewer = JobAdsViewer(app, "viewer")
+ self.add_mode(self.viewer)
- def render_title(self, session):
- return "Statistics"
+ self.editor = JobAdsEditor(app, "editor")
+ self.add_mode(self.editor)
-"""
-class JobGroupStatSet(StatSet):
- def __init__(self, app, name, category):
- super(JobGroupStatSet, self).__init__(app, name, category)
-
- self.jobs = Attribute(app, "jobs")
- self.add_attribute(self.jobs)
-
- def process(self, session):
- group = self.frame.get_args(session)[0]
- if group:
- where_group = "custom_group = '%s'" % group.get_id()
- value = Job.select(where_group).count()
- self.jobs.set(session, value)
- super(JobGroupStatSet, self).process(session)
-
- def render_rate_text(self, session, args):
- return "Percentage"
-
- def render_item_name(self, session, args):
- stat, object = args
- return stat.name
-
- def render_item_value(self, session, args):
- stat, group = args
- if stat.name == "Jobs":
- return self.jobs.get(session)
- else:
- state = stat.name
- value = self.get_value(group, state)
- return value
-
- def get_value(self, group, state):
- where_group = "custom_group = '%s' \
- and job_status = %i" % (group.get_id(),
- JobStatusInfo.get_status_int(state))
- return Job.select(where_group).count()
-
- def render_item_rate(self, session, args):
- stat, group = args
- jobs = self.jobs.get(session)
- state = stat.name
- if stat.name == "Jobs":
- value = jobs
- else:
- value = self.get_value(group, state)
- percent = (value*1.0) / (jobs*1.0) * 100.0
- return jobs and "%2.1f" % percent or "-"
-"""
-
-class JobGroupJobSet(JobTab):
- def __init__(self, app, name, pool):
- super(JobGroupJobSet, self).__init__(app, name, pool)
-
- def get_visible_columns(self, session):
- return self.get_request_visible_columns(session, ["scheduler",
"submitter"])
-
def render_title(self, session):
- group = self.frame.object.get(session)
- where_group = "custom_group = '%s'" % group.get_id()
- return "Jobs %s" % fmt_count(Job.select(where_group).count())
+ return "Attributes"
- def render_sql_where(self, session):
- group = self.frame.object.get(session)
- phase_sql = self.get_phase_sql(session)
- group_sql = "j.custom_group = '%s'" % group.get_id()
- return "where %s" % " and ".join([phase_sql, group_sql])
-
- def render_count(self, session):
- group = self.frame.object.get(session)
- str = super(JobGroupJobSet, self).render_count(session)
- return "%s in Job Group '%s'" % (str, group.get_id())
-
-# class JobGroupSystemSet(SystemSet):
-# def render_sql_where(self, session):
-# subquery = """
-# select 1
-# from slot as l
-# join job as j on j.custom_id = l.job_id
-# where j.custom_group = %(id)s and l.system = s.node_name
-# """
-
-# return "where exists (%s)" % subquery
-
-# def get_sql_values(self, session):
-# group = self.frame.object.get(session)
-# return {"id": group.id}
-
-class JobFrame(CuminFrame):
- def __init__(self, app, name):
- super(JobFrame, self).__init__(app, name)
-
- self.object = JobParameter(app, "id")
- self.add_parameter(self.object)
-
- self.scheduler = SchedulerParameter(app, "scheduler")
- self.add_parameter(self.scheduler)
-
- self.view = JobView(app, "view", self.object)
- self.add_mode(self.view)
-
- self.__edit_ads = JobAdsEditor(app, "editads", self.object)
- self.add_mode(self.__edit_ads)
-
- def show_ads_edit(self, session):
- self.page.set_frame(session, self.__edit_ads)
- return self.__edit_ads.show(session)
-
- def show_job_group(self, session, jobgroup):
- self.__job.set_object(session, jobgroup)
- self.page.set_frame(session, self.__job)
- self.__job.set_switch(session, "group")
- return self.__job.show(session)
-
- def get_href(self, session, job, scheduler):
- branch = session.branch()
- self.show_object(branch, job)
- self.scheduler.set(session, scheduler)
- return branch.marshal()
-
-class JobView(CuminView):
- def __init__(self, app, name, job):
- super(JobView, self).__init__(app, name, job)
-
- self.tabs = TabbedModeSet(app, "tabs")
- self.add_child(self.tabs)
-
- self.tabs.add_tab(JobAdsViewer(app, "jobads", job))
- self.tabs.add_tab(JobOutput(app, "output", job))
- #self.tabs.add_tab(JobSystemSet(app, "systems", job))
- #self.tabs.add_tab(CuminDetails(app, "details", job))
-
-# class JobSystemSet(SystemSet):
-# def __init__(self, app, name, job):
-# super(JobSystemSet, self).__init__(app, name)
-
-# self.job = job
-
-# def render_sql_where(self, session):
-# return """
-# where exists
-# (select 1
-# from slot
-# where system = s.node_name and job_id = %(id)s)
-# """
-
-# def get_sql_values(self, session):
-# job = self.job.get(session)
-# return {"id": "%i.%i" % (job.ClusterId, job.ProcId)}
-
class JobAdsSet(PropertySet):
types = {0: "expression",
1: "integer",
2: "float",
3: "string"}
-
- def __init__(self, app, name, job):
+ def __init__(self, app, name):
super(JobAdsSet, self).__init__(app, name)
- self.job = job
+ self.items = Attribute(app, "cached_items")
+ self.add_attribute(self.items)
def do_get_items(self, session):
- job = self.job.get(session)
- cls = self.app.model.get_class_by_object(job)
+ ad_list = self.items.get(session)
- # XXX
- job_ads = self.get_raw_ads(session, job, None)
+ if not ad_list:
+ ad_list = list()
+ id = self.frame.id.get(session)
+ job_server = self.frame.get_job_server(session, id)
+ job_id = self.frame.job_id.get(session)
- return [self.gen_item(x, job_ads[x]["VALUE"], cls,
- dtype=self.types[job_ads[x]["TYPE"]])
- for x in job_ads]
+ action = QmfCall(self.app, {'JobAd': {}})
+ ads = action.execute(job_server, "GetJobAd",
job_id).data['JobAd']
+ cls = self.app.model.job_meta_data
+ ad_list = [self.gen_item(x, ads[x], cls, dtype=self.get_type(ads[x])) for x
in ads]
- def get_raw_ads(self, session, job, scheduler):
- if not scheduler:
- schedulers = Scheduler.select()
- for sched in schedulers:
- if sched.statsCurr:
- if sched.statsCurr.TotalRunningJobs:
- scheduler = sched
- break
+ self.items.set(session, ad_list)
- if scheduler:
- action = FetchJobAd(self.app)
- return action.execute(scheduler, job.id).data['JobAd']
+ return ad_list
+
+ def get_type(self, value):
+ if isinstance(value, (int, long)):
+ type = "integer"
+ elif isinstance(value, float):
+ type = "float"
+ elif isinstance(value, dict):
+ type = "dict"
else:
- return () # XXX
+ type = "string"
+ return type
- def gen_items(self, session, job, scheduler):
- job_ads = self.get_raw_ads(session, job, scheduler)
-
- cls = self.app.model.job
- return [self.gen_item(x, job_ads[x]["VALUE"], cls,
dtype=self.types[job_ads[x]["TYPE"]]) for x in job_ads]
- # list of dictionaries
- # each disctionary has:
- # name:, value:, type: [, error:] [, property:] [,path:]
- #return [self.gen_item(x, job_ads[x], cls) for x in job_ads]
-#
-
def gen_item(self, name, value, cls, path=None, dtype=None,
error=None, orig=None):
""" Generate a dict with name, value, type, error, path,
@@ -497,8 +259,11 @@
property = item["property"]
if property.renderer:
value = property.renderer(session, value)
- ret = escape_entity(str(value))
- return self.insert_breaks(ret)
+ if item["type"] == "dict":
+ return value
+ else:
+ ret = escape_entity(str(value))
+ return self.insert_breaks(ret)
def insert_breaks(self, value):
subwords = list()
@@ -517,26 +282,22 @@
return property.description
class JobAdsGroups(Widget):
- def __init__(self, app, name, job):
+ def __init__(self, app, name):
super(JobAdsGroups, self).__init__(app, name)
- self.job = job
-
self.group_tmpl = WidgetTemplate(self, "group_html")
def render_groups(self, session):
- job = self.job.get(session)
- groups = self.app.model.get_ad_groups()
writer = Writer()
- for group in groups:
- self.group_tmpl.render(writer, session, (job, group))
+ for group in self.app.model.get_ad_groups():
+ self.group_tmpl.render(writer, session, group)
return writer.to_string()
- def render_group_name(self, session, args):
- return args[1]
+ def render_group_name(self, session, group):
+ return group
- def render_properties(self, session, *args):
- items = self.parent.do_get_items(session, *args)
+ def render_properties(self, session, group):
+ items = self.parent.get_group_items(session, group)
writer = Writer()
for item in items:
@@ -545,12 +306,12 @@
return writer.to_string()
class JobAdsViewer(JobAdsSet):
- def __init__(self, app, name, job):
- super(JobAdsViewer, self).__init__(app, name, job)
+ def __init__(self, app, name):
+ super(JobAdsViewer, self).__init__(app, name)
self.item_renderer = JobPropertyRenderer(self, "property_html")
- self.groups = JobAdsGroups(app, "groups", job);
+ self.groups = JobAdsGroups(app, "groups");
self.add_child(self.groups)
self.wait = Wait(app, "wait")
@@ -566,12 +327,11 @@
self.frame.show_ads_edit(branch)
return branch.marshal()
- def do_get_items(self, session, args):
- group = args[1]
+ def get_group_items(self, session, group):
group_items = list()
- all_items = super(JobAdsViewer, self).do_get_items(session)
- for item in all_items:
+ items = self.do_get_items(session)
+ for item in items:
if "property" in item:
property = item["property"]
item_group = property.group
@@ -583,8 +343,8 @@
return group_items
class JobAdsEditor(JobAdsViewer, CuminForm):
- def __init__(self, app, name, job):
- super(JobAdsEditor, self).__init__(app, name, job)
+ def __init__(self, app, name):
+ super(JobAdsEditor, self).__init__(app, name)
# the parameter that will hold all the field values
self.ads = DictParameter(app, "params")
@@ -592,39 +352,25 @@
self.item_renderer = EditablePropertyRenderer(self, "property_html")
- def get_args(self, session):
- return tuple()
-
- def do_get_items(self, session, args):
- job = args[0]
- group = args[1]
- cls = self.app.model.job
+ def do_get_items(self, session):
ads = self.ads.get(session)
if len(ads):
+ # we just returned from a submit
+ cls = self.app.model.job_meta_data
return [self.gen_item(x, ads[x]["value"], cls, path=self.ads.path,
dtype=ads[x]["type"], error=ads[x],
- orig=ads[x]["orig"]) for x in ads
- if self.is_group(x, cls, group)]
- else:
- scheduler = self.frame.scheduler.get(session)
- items = super(JobAdsEditor, self).do_get_items(session, args)
- for item in items:
- item["path"] = self.ads.path
- return items
+ orig=ads[x]["orig"]) for x in ads]
- def is_group(self, name, cls, group):
- if name in cls.ad_properties_by_name:
- property = cls.ad_properties_by_name[name]
- item_group = property.group
- else:
- item_group = "Other"
- return item_group == group
+ items = super(JobAdsEditor, self).do_get_items(session)
+ for item in items:
+ item["path"] = self.ads.path
+ return items
def process_cancel(self, session):
branch = session.branch()
self.ads.set(branch, None) # otherwise url is too long
- self.frame.view.show(branch)
+ self.frame.show_ads_view(branch)
self.page.redirect.set(session, branch.marshal())
def process_submit(self, session):
@@ -651,10 +397,9 @@
except:
ads[field]["error"] = "Floating point value
expected"
errors = True
- elif ftype == "string":
- fval = "\"%s\"" % fval
else:
fval = unicode(fval)
+
if "orig" in ads[field]:
orig = ads[field]["orig"]
if ftype == "integer":
@@ -662,14 +407,20 @@
elif ftype == "float":
orig = float(orig)
if fval != orig:
+ if ftype == "string":
+ quoted = "\"%s\"" % fval
+ if quoted == orig:
+ continue
just_ads[unicode(field)] = fval
if not errors:
- scheduler = self.frame.scheduler.get(session)
- job = self.frame.get_object(session)
- task = main.module.job_setattribute
+ id = self.frame.id.get(session)
+ scheduler = self.frame.get_scheduler(session, id)
+ job_id = self.frame.job_id.get(session)
+
+ task = self.frame.set_ad_task
for field in just_ads:
- task.invoke(session, job.id, field, just_ads[field], scheduler)
+ task.invoke(session, scheduler, job_id, field, str(just_ads[field]))
self.process_cancel(session)
class OutputFile(Widget):
@@ -683,12 +434,15 @@
self.defer_enabled = True
def render_content(self, session):
- scheduler = self.frame.scheduler.get(session)
- job = self.frame.get_object(session)
+ id = self.frame.id.get(session)
+ job_server = self.frame.get_job_server(session, id)
+ job_id = self.frame.job_id.get(session)
file, start, end = self.get_file_args(session)
if file:
- action = FetchJobOutput(self.app)
- result = action.execute(scheduler, job.id, file, start, end)
+ action = QmfCall(self.app, {'Data': ""})
+ result = action.execute(job_server, "FetchJobData", job_id, file,
start, end)
+ if result.error:
+ return result.status
return escape_entity(result.data['Data'])
return self.err_msg
@@ -707,12 +461,10 @@
file = self.which_file.get_current_file_name(session)
return file and "loading..." or self.err_msg
-class JobOutput(Form):
- def __init__(self, app, name, job):
+class JobOutput(JobAdsSet, Form):
+ def __init__(self, app, name):
super(JobOutput, self).__init__(app, name)
- self.job = job
-
self.which_file = self.FileSwitch(app, "file")
self.add_child(self.which_file)
@@ -725,8 +477,6 @@
self.output = OutputFile(app, "job_output", self.which_file,
self.first_last)
self.add_child(self.output)
- self.ads = JobAdsSet(app, "ads", self.job)
-
def render_title(self, session):
return "Output"
@@ -739,14 +489,13 @@
return fmt_datetime(now, sec=True)
def do_process(self, session):
- job = self.job.get(session)
-
out_file = None
user_file = None
err_file = None
- scheduler = self.frame.scheduler.get(session)
- ads = self.ads.do_get_items(session)
+ id = self.frame.id.get(session)
+ scheduler = self.frame.get_scheduler(session, id)
+ ads = self.do_get_items(session)
for ad in ads:
if ad['name'] == "Out":
out_file = ad['value']
@@ -855,172 +604,92 @@
self.add_state("t", "Tail", "Display end of
file")
self.add_state("h", "Head", "Display beginning of
file")
-class JobGroupSet(CuminTable):
- def __init__(self, app, name, pool):
- super(JobGroupSet, self).__init__(app, name)
+class JobAction(ObjectTask):
+ def __init__(self, app, frame, verb):
+ super(JobAction, self).__init__(app, frame)
- self.pool = pool
+ self.form = JobActionForm(app, self.name, self, verb)
- col = self.GroupColumn(app, "job_group")
- self.add_column(col)
+ def do_enter(self, session, osession):
+ job_id = self.frame.job_id.get(osession)
+ self.form.job_id.set(session, job_id)
- col = self.JobsCountColumn(app, "jobs")
- col.align = "right"
- self.add_column(col)
-
- class GroupColumn(SqlTableColumn):
- def render_title(self, session):
- return "Job Group"
-
- def render_content(self, session, data):
- name = data[self.name]
-
- if name:
- group = Identifiable(name)
- href = self.page.main.grid.pool.job_group.get_href \
- (session, group)
- return fmt_link(href, fmt_shorten(name))
-
- class JobsCountColumn(SqlTableColumn):
- def render_title(self, session):
- return "Jobs"
-
-class JobsAndGroupsTab(TabbedModeSet):
- def __init__(self, app, name, pool):
- super(JobsAndGroupsTab, self).__init__(app, name)
-
- self.jobs_tab = JobTab(app, "jobtab", pool)
- self.add_tab(self.jobs_tab)
- self.add_tab(JobGroupTab(app, "jobgrouptab", pool))
-
- def render_title(self, session, *args):
- return "Jobs %s" % fmt_count(self.jobs_tab.get_full_item_count(session,
*args))
-
- def render_phase(self, session, *args):
- return self.mode.get(session) == self.jobs_tab and
self.jobs_tab.phase.render(session) or ""
-
-class JobGroupTab(JobGroupSet, Form):
- def __init__(self, app, name, pool):
- super(JobGroupTab, self).__init__(app, name, pool)
-
- self.set_default_column_name("job_group")
-
- def render_title(self, session, *args):
- return "Job Groups"
-
-class JobReasonForm(FieldSubmitForm):
+class JobActionForm(ObjectTaskForm):
def __init__(self, app, name, task, verb):
- super(JobReasonForm, self).__init__(app, name)
+ super(JobActionForm, self).__init__(app, name, task)
- self.task = task
- self.verb = verb
- self.object = None
-
self.reason = self.ReasonField(app, "reason")
self.add_field(self.reason)
- self.scheduler = SchedulerParameter(app, "scheduler")
- self.add_parameter(self.scheduler)
+ self.job_id = Parameter(app, "job_id")
+ self.add_parameter(self.job_id)
- def init(self):
- assert self.object
- super(JobReasonForm, self).init()
+ self.verb = verb
- def render_submit_content(self, session):
- return self.verb
-
- def render_cancel_content(self, session):
- return "Cancel"
-
- def process_submit(self, session):
- job = self.object.get(session)
- reason = self.get_reason(session, self.verb)
- scheduler = self.scheduler.get(session)
-
- if not reason:
- error = FormError("Reason is required")
- self.errors.add(session, error)
-
- if not self.errors.get(session):
- self.task.invoke(session, job, reason, scheduler)
- self.task.exit_with_redirect(session, job)
-
def get_reason(self, session, verb):
""" returns <verb> by username[: <user input reason>]
"""
reason = self.reason.get(session)
if reason:
reason = [reason]
- verb_by = "%s by %s" % (verb, session.user_session.subject.name)
+ user = session.client_session.attributes["login_session"].user
+
+ verb_by = "%s by %s" % (verb, user.name)
reason.insert(0, verb_by)
return ": ".join(reason)
+ def process_submit(self, session):
+ self.validate(session)
+
+ if not self.errors.get(session):
+ id = self.id.get(session)
+ scheduler = self.task.frame.get_scheduler(session, id)
+ reason = self.get_reason(session, self.verb)
+ job_id = self.job_id.get(session)
+
+ self.task.invoke(session, scheduler, job_id, reason)
+ self.task.exit_with_redirect(session)
+
class ReasonField(StringField):
def render_title(self, session):
return "Reason"
-class JobTaskForm(JobReasonForm):
- def __init__(self, app, name, task, verb):
- super(JobTaskForm, self).__init__(app, name, task, verb)
+class JobHold(JobAction):
+ def __init__(self, app, frame):
+ super(JobHold, self).__init__(app, frame, "held")
- self.object = JobParameter(app, "job")
- self.add_parameter(self.object)
+ def get_title(self, session):
+ return "Hold Job"
- def render_title(self, session):
- job = self.object.get(session)
- return "%s Job '%s'" % (self.verb, str(job.id))
+ def do_invoke(self, invoc, scheduler, job_id, reason):
+ self.qmf_call(invoc, scheduler, "HoldJob", job_id, reason)
-class JobSetTaskForm(JobReasonForm):
- def __init__(self, app, name, task, verb):
- super(JobSetTaskForm, self).__init__(app, name, task, verb)
+class JobRelease(JobAction):
+ def __init__(self, app, frame):
+ super(JobRelease, self).__init__(app, frame, "held")
- item = JobParameter(app, "item")
+ def get_title(self, session):
+ return "Release Job"
- self.object = ListParameter(app, "job", item)
- self.add_parameter(self.object)
+ def do_invoke(self, invoc, scheduler, job_id, reason):
+ self.qmf_call(invoc, scheduler, "ReleaseJob", job_id, reason)
- def render_title(self, session):
- jobs = self.object.get(session)
- return "%s %i Job%s" % (self.verb, len(jobs), len(jobs) > 1 and
"s" or "")
+class JobRemove(JobAction):
+ def __init__(self, app, frame):
+ super(JobRemove, self).__init__(app, frame, "removed")
-class JobStatusSwitch(StateSwitch):
- def __init__(self, app, name):
- super(JobStatusSwitch, self).__init__(app, name)
+ def get_title(self, session):
+ return "Remove Job"
- self.add_state("All", "All")
- self.add_state("Running", "Running")
- self.add_state("Idle", "Idle")
- self.add_state("Held", "Held")
- self.add_state("Completed", "Completed")
- self.add_state("Removed", "Removed")
+ def do_invoke(self, invoc, scheduler, job_id, reason):
+ self.qmf_call(invoc, scheduler, "RemoveJob", job_id, reason)
- def get_sql_constraint(self, session, phase=None):
- if not phase:
- phase = self.get(session)
+class JobSetAttribute(ObjectTask):
+ def get_title(self, session):
+ pass
- alive = "((j.qmf_update_time is null or " + \
- "j.qmf_update_time <= now() - interval '10 minutes')" +
\
- " and j.qmf_delete_time is null and j.job_status != %i)" %
JobStatusInfo.get_status_int("Removed")
+ def get_description(self, session):
+ return "Edit Ad"
- if phase == "a":
- sql = alive
- elif phase == "r":
- sql = "(j.job_status = %i" %
JobStatusInfo.get_status_int("Running") + \
- " and %s)" % alive
- elif phase == "i":
- sql = "(j.job_status = %i" %
JobStatusInfo.get_status_int("Idle") + \
- " and %s)" % alive
- elif phase == "h":
- sql = "(j.job_status = %i" %
JobStatusInfo.get_status_int("Held") + \
- " and %s)" % alive
- elif phase == "c":
- comotose = "(c.qmf_update_time is null or " + \
- "c.qmf_update_time <= now() - interval '10
minutes')"
- sql = "(j.job_status = %i" %
JobStatusInfo.get_status_int("Completed") + \
- " and %s)" % comotose
- else:
- not_completed = "(j.qmf_delete_time is not null and j.job_status
<> %i )" % JobStatusInfo.get_status_int("Completed")
- is_removed = "j.job_status = %i" %
JobStatusInfo.get_status_int("Removed")
- sql = " or ".join((not_completed, is_removed))
+ def do_invoke(self, invoc, scheduler, job_id, name, value):
+ self.qmf_call(invoc, scheduler, "SetJobAttribute", job_id, name,
value)
- return sql
-
Modified: mgmt/newdata/cumin/python/cumin/grid/job.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/job.strings 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/grid/job.strings 2010-06-30 20:28:45 UTC (rev 4059)
@@ -1,89 +1,3 @@
-[JobTab.css]
-input.search_input {
- color: #555;
- border: 1px solid #333;
- font-size: 0.9em;
- font-weight: normal;
- padding-left: 0.25em;
-}
-
-input.search_error {
- color: #CC0000 !important;
-}
-
-div.searchbox {
- padding-top: 2px;
-}
-
-[JobTab.javascript]
-function JobSearchFocus() {
- var val = this.value;
-
- if (val == job_search_prompt) {
- this.value = "";
- this.style.color = "#000";
- this.className = "search_input"; // remove search_error class
- }
-}
-
-function JobSearchBlur() {
- var val = this.value;
-
- if (val == "") {
- this.style.color = "#555";
- job_search_prompt = job_search_default_prompt;
- this.value = job_search_prompt;
- }
-}
-
-window.addEvent('domready', function () {
- var oInput = document.getElementById("job_search");
-
- if (oInput) {
- oInput.onfocus = JobSearchFocus;
- oInput.onblur = JobSearchBlur;
- }
-});
-
-
-[JobSearch.html]
-<div class="rfloat searchbox">
- <h2><label for="job_search">Go To Job:</label></h2>
- <input class="search_input {search_class}" type="text"
name="{name}" id="job_search" value="{search_prompt}" />
- {go}
-</div>
-<script type="text/javascript">
- var job_search_default_prompt = "{search_default_prompt}"
- var job_search_prompt = "{search_prompt}"
-</script>
-
-[JobGroupSet.sql]
-select
- j.custom_group as id,
- j.custom_group as job_group,
- count(*) as jobs
-from job as j
-{sql_where}
-group by j.custom_group
-{sql_orderby}
-{sql_limit}
-
-[JobGroupSet.count_sql]
-select count(1) from (select count(1) from job as j group by j.custom_group) as s;
-{sql_where}
-
-[JobGroupStats.html]
- <h2>General</h2>
- <div style="width:50%;">
- {general}
- </div>
-
-
-[JobsAndGroupsTab.html]
-<div style="float: right;">{phase}</div>
-<ul class="radiotabs tabs">{tabs}</ul>
-<div class="radiotabs mode">{content}</div>
-
[JobAdsViewer.html]
<div id="{id}">
<ul class="actions">
@@ -145,14 +59,15 @@
display: inline;
}
+[JobAdsEditor.css]
+table.Editable {
+ width: 100%;
+ border-collapse: collapse;
+}
+
[JobAdsEditor.html]
<form id="{id}" class="mform editform" method="post"
action="?">
- <div class="inline_help">
- <h2>Legend</h2>
- <span class="edit_number">Numeric input expected</span>
- <span class="edit_string">String input expected</span>
- </div>
- {help} {submit} {cancel}
+ <div style="float:left;">{submit} {cancel}</div><div
style="clear:both;"></div>
<table class="CuminDetails Editable">
<tbody>
<tr>
@@ -162,7 +77,7 @@
</tr>
</tbody>
</table>
- {help} {submit} {cancel}
+ <div style="float:left;">{submit} {cancel}</div><div
style="clear:both;"></div>
<div>{hidden_inputs}</div>
</form>
Modified: mgmt/newdata/cumin/python/cumin/grid/submission.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/submission.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/grid/submission.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -6,7 +6,7 @@
from cumin.objecttask import *
from cumin.widgets import *
from cumin.util import *
-from job import JobSet
+from job import JobSelector, JobFrame
strings = StringCatalog(__file__)
log = logging.getLogger("cumin.grid.submission")
@@ -17,6 +17,12 @@
super(SubmissionFrame, self).__init__(app, name, cls)
+ self.job = JobFrame(app, "job", self.object)
+ self.add_mode(self.job)
+
+ jobs = JobSelector(app, "jobs", self.object)
+ self.view.add_tab(jobs)
+
class SubmissionSelector(ObjectSelector):
def __init__(self, app, name):
cls = app.model.com_redhat_grid.Submission
@@ -31,10 +37,6 @@
self.add_attribute_column(cls.Running)
self.add_attribute_column(cls.Completed)
-class SubmissionJobSet(JobSet):
- def render_title(self, session):
- return "Jobs"
-
class SubmissionAdd(ObjectTask):
EXPR_TYPE, INTEGER_TYPE, FLOAT_TYPE, STRING_TYPE = 0, 1, 2, 3
UNIVERSE = {"VANILLA": 5,
Modified: mgmt/newdata/cumin/python/cumin/inventory/system.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/inventory/system.py 2010-06-30 19:10:29 UTC (rev
4058)
+++ mgmt/newdata/cumin/python/cumin/inventory/system.py 2010-06-30 20:28:45 UTC (rev
4059)
@@ -136,22 +136,6 @@
self.tabs.add_tab(SystemServices(app, "services", system))
self.tabs.add_tab(CuminDetails(app, "details", system))
-from cumin.grid.job import JobTab
-
-class SystemJobSet(JobTab):
- def render_title(self, session):
- return "Grid Jobs %s" % fmt_count(self.get_item_count(session))
-
- def render_sql_where(self, session):
- elems = list()
- elems.append("s.system = %(nodeName)s")
- elems.append(self.get_phase_sql(session))
- return "where %s" % " and ".join(elems)
-
- def get_sql_values(self, session):
- system = self.frame.get_object(session)
- return {"nodeName": system.nodeName}
-
class SystemServices(ItemSet):
def __init__(self, app, name, system):
super(SystemServices, self).__init__(app, name)
Modified: mgmt/newdata/cumin/python/cumin/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/main.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/main.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -19,6 +19,7 @@
from session import *
from sqladapter import *
from user import *
+from util import *
from widgets import *
from wooly import Session
Modified: mgmt/newdata/cumin/python/cumin/model.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/model.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/model.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -33,6 +33,8 @@
self.lock = Lock()
+ self.job_meta_data = JobMetaData("job")
+
def check(self):
log.info("Checking %s", self)
@@ -144,12 +146,11 @@
return value
-class AdProperty(CuminProperty):
+class AdProperty(object):
groups = ["Main", "Command Info", "Job Status Info",
"Condor Info", "Dates", "Other"]
def __init__(self, cls, name):
# don't call super since we don't want to call add_property
- self.model = cls.model
self.cumin_class = cls
self.name = name
@@ -167,10 +168,37 @@
self.cumin_class.add_ad_property(self)
+ def get_title(self, session):
+ if self.title:
+ return self.title
+ else:
+ return self.name
+
+ def value(self, session, object):
+ value = getattr(object, self.name, None)
+
+ if isinstance(value, datetime):
+ value = fmt_datetime(value)
+
+ if isinstance(value, dict):
+ value = fmt_dict(value, self.prefix)
+
+ return value
+
@classmethod
def get_ad_groups(cls):
return cls.groups
+class DictAdProperty(AdProperty):
+ def __init__(self, cls, name):
+ super(DictAdProperty, self).__init__(cls, name)
+
+ self.renderer = self.render_dict
+ self.group = "Other"
+
+ def render_dict(self, session, value):
+ return fmt_dict(value, self.prefix)
+
class DateAdProperty(AdProperty):
def __init__(self, cls, name):
super(DateAdProperty, self).__init__(cls, name)
@@ -547,6 +575,21 @@
except KeyError:
return value
+class MetaData(object):
+ def __init__(self, name):
+
+ self.name = name
+ self.ad_properties = list()
+ self.ad_properties_by_name = dict()
+
+ def init(self):
+ for ad_prop in self.ad_properties:
+ ad_prop.init()
+
+ def add_ad_property(self, prop):
+ self.ad_properties.append(prop)
+ self.ad_properties_by_name[prop.name] = prop
+
class CuminClass(object):
def __init__(self, model, name, mint_class):
self.model = model
@@ -1340,52 +1383,26 @@
title = self.get_title(session)
return "%s '%s'" % (title, limit)
-class CuminJobGroup(CuminClass):
- def __init__(self, model):
- super(CuminJobGroup, self).__init__ \
- (model, "job_group", JobGroup)
+class JobMetaData(MetaData):
+ def __init__(self, name):
+ super(JobMetaData, self).__init__(name)
- stat = CuminStat(self, "Running")
- stat.title = "Running Jobs"
-
- stat = CuminStat(self, "Completed")
- stat.title = "Completed Jobs"
-
- stat = CuminStat(self, "Idle")
- stat.title = "Idle Jobs"
-
- stat = CuminStat(self, "Held")
- stat.title = "Held Jobs"
-
- stat = CuminStat(self, "Jobs")
- stat.title = "Total Jobs"
-
- def init(self):
- super(CuminJobGroup, self).init()
-
- # XXX
- #self.frame = self.model.frame.grid.pool.job_group
-
- def get_object_title(self, session, group):
- title = self.get_title(session)
- name = group.get_id()
- return "%s '%s'" % (title, name)
-
- def get_title(self, session):
- return "Job Group"
-
- def get_icon_href(self, session):
- return "resource?name=group-36.png"
-
-class CuminJob(CuminClass):
- def __init__(self, model):
- super(CuminJob, self).__init__(model, "job", None)
-
### Main Group
prop = AdProperty(self, "Owner")
+ prop.group = "Main"
prop.description = "The submitter of the job"
prop.writable = False
+ prop = AdProperty(self, "GlobalJobId")
+ prop.group = "Main"
+ prop.description = "Unique job id"
+ prop.writable = False
+
+ prop = AdProperty(self, "Submission")
+ prop.group = "Main"
+ prop.description = "Submission name"
+ prop.writable = False
+
### Condor Info Group
prop = AdProperty(self, "CondorVersion")
prop.group = "Condor Info"
@@ -1395,6 +1412,10 @@
prop.group = "Condor Info"
prop.writable = False
+ prop = DictAdProperty(self, "!!descriptors")
+ prop.group = "Condor Info"
+ prop.writable = False
+
### Command Info Group
prop = AdProperty(self, "Args")
prop.description = "Arguments passed to job Cmd"
@@ -1403,20 +1424,27 @@
prop = AdProperty(self, "Cmd")
prop.description = "Command that will run the job"
prop.group = "Command Info"
- prop.title = "Command"
prop = AdProperty(self, "In")
prop.description = "The file where the job's standard input is
read"
prop.group = "Command Info"
+ prop = AdProperty(self, "Out")
+ prop.description = "The file where the job's standard output is
written"
+ prop.example = "'/dev/null' or '~/logs/'"
+ prop.group = "Command Info"
+
+ prop = AdProperty(self, "Err")
+ prop.description = "The file where the job's errors are written"
+ prop.group = "Command Info"
+
prop = AdProperty(self, "Iwd")
prop.description = "Command Input Working Directory"
prop.group = "Command Info"
prop.title = "Working Directory"
- prop = AdProperty(self, "Out")
- prop.description = "The file where the job's standard output is
written"
- prop.example = "'/dev/null' or '~/logs/'"
+ prop = AdProperty(self, "UserLog")
+ prop.description = "Log file"
prop.group = "Command Info"
######## Job Status Info
@@ -1432,19 +1460,26 @@
prop.title = "Hold Reason Code"
prop.writable = False
- prop = AdProperty(self, "ExitStatus")
+ prop = self.JobStatusProperty(self, "ExitStatus")
prop.description = "Status when job completes"
prop.group = "Job Status Info"
+ prop.renderer = prop.render_status
prop.title = "Exit Status"
prop.writable = False
+ prop = self.JobStatusProperty(self, "LastJobStatus")
+ prop.description = ""
+ prop.group = "Job Status Info"
+ prop.renderer = prop.render_status
+ prop.writable = False
+
+ ######## Other
prop = AdProperty(self, "ProcId")
prop.description = "The id of the job within its cluster. Proc Ids are
unique within a cluster."
- prop.group = "Job Status Info"
+ prop.group = "Other"
prop.title = "Proc Id"
prop.writable = False
- ######## Other
prop = AdProperty(self, "BufferBlockSize")
prop.example = "32768"
prop.group = "Other"
@@ -1455,6 +1490,7 @@
prop.title = "Cluster ID"
prop.writable = False
+ ###### Dates
prop = DateAdProperty(self, "QDate")
prop.description = "When the job was submitted"
prop.group = "Dates"
@@ -1500,83 +1536,10 @@
prop.group = "Dates"
prop.writable = False
- ######## Properties
- prop = CuminProperty(self, "CustomGroup")
- prop.title = "Job Group"
- prop.escape = False
+ prop = DateAdProperty(self, "ScheddBday")
+ prop.group = "Dates"
+ prop.writable = False
- prop = CuminProperty(self, "scheduler")
- prop.title = "Scheduler"
- prop.escape = False
-
- prop = CuminProperty(self, "submitter")
- prop.title = "Submitter"
- prop.escape = False
-
- prop = CuminProperty(self, "AccountingGroup")
- prop.title = "Accounting Group"
-
- prop = CuminProperty(self, "Args")
- prop.title = "Args"
-
- prop = CuminProperty(self, "ClusterId")
- prop.title = "Cluster ID"
-
- prop = CuminProperty(self, "Cmd")
- prop.title = "Command"
-
- prop = CuminProperty(self, "ConcurrencyLimits")
- prop.title = "Limits"
-
- prop = CuminProperty(self, "CustomId")
- prop.title = "Custom ID"
-
- prop = CuminProperty(self, "CustomPriority")
- prop.title = "Custom Priority"
-
- prop = CuminProperty(self, "GlobalJobId")
- prop.title = "Global Job ID"
-
- prop = CuminProperty(self, "JobStatus")
- prop.title = "Job Status"
-
- prop = CuminProperty(self, "Note")
- prop.title = "Note"
-
- prop = CuminProperty(self, "ProcId")
- prop.title = "Proc ID"
-
- prop = CuminProperty(self, "QDate")
- prop.title = "QDate"
-
- prop = CuminProperty(self, "Requirements")
- prop.title = "Requirements"
-
- prop = CuminProperty(self, "Title")
- prop.title = "Title"
-
- prop = CuminProperty(self, "UserLog")
- prop.title = "User Log"
-
- prop = CuminProperty(self, "HoldReason")
- prop.title = "Hold Reason"
-
- def init(self):
- super(CuminJob, self).init()
-
- #self.frame = self.model.frame.grid.pool.job
-
- def get_title(self, session):
- return "Job"
-
- if isinstance(job, basestring):
- return job
- else:
- return job.CustomId
-
- def get_icon_href(self, session):
- return "resource?name=job-36.png"
-
class JobStatusProperty(AdProperty):
def render_status(self, session, status):
return JobStatusInfo.get_status_string(status)
@@ -1625,10 +1588,10 @@
def done(self):
return self.got_data or self.error
- def execute(self, negotiator, method_name, *args):
+ def execute(self, obj, method_name, *args):
session = self.app.session
try:
- session.call_method(self.get_completion(), negotiator, method_name, args)
+ session.call_method(self.get_completion(), obj, method_name, args)
except Exception, e:
self.error = e
@@ -1934,13 +1897,6 @@
for negotiator in Negotiator.selectBy(Pool=self.id):
return negotiator
-class JobGroup(object):
- def __init__(self, id):
- self.id = id
-
- def get_id(self):
- return self.id
-
class ObjectStore(object):
def __init__(self, model):
self.model = model
Modified: mgmt/newdata/cumin/python/cumin/objectframe.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectframe.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/objectframe.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -15,7 +15,7 @@
super(ObjectFrame, self).__init__(app, name)
self.cls = cls
-
+
self.id = IntegerParameter(app, "id")
self.add_parameter(self.id)
@@ -179,10 +179,14 @@
self.add_child(self.body)
def init(self):
- self.add_tab(ObjectDetails(self.app, "details", self.object))
+ self.add_details_tab()
super(ObjectView, self).init()
+ def add_details_tab(self):
+ """ allow derived views to skip adding details tab
"""
+ self.add_tab(ObjectDetails(self.app, "details", self.object))
+
def add_tab(self, widget):
self.body.add_tab(widget)
Modified: mgmt/newdata/cumin/python/cumin/objectselector.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectselector.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/objectselector.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -6,6 +6,7 @@
from objectframe import *
from objecttask import *
from sqladapter import *
+from qmfadapter import *
from util import *
strings = StringCatalog(__file__)
@@ -17,7 +18,7 @@
if not adapter:
adapter = ObjectSqlAdapter(app, cls)
- assert isinstance(adapter, ObjectSqlAdapter), adapter
+ assert isinstance(adapter, DataAdapter), adapter
super(ObjectTable, self).__init__(app, name, adapter)
@@ -33,7 +34,7 @@
assert self.cls, self
assert self.adapter, self
- assert self.adapter.id_field, self
+ #assert self.adapter.id_field, self
def add_attribute_column(self, attr):
assert isinstance(attr, RosemaryAttribute), attr
@@ -120,7 +121,10 @@
try:
self.field = self.table.adapter.fields_by_attr[self.attr]
except KeyError:
- self.field = ObjectSqlField(self.table.adapter, self.attr)
+ if isinstance(self.table.adapter, ObjectQmfAdapter):
+ self.field = ObjectQmfField(self.table.adapter, self.attr)
+ else:
+ self.field = ObjectSqlField(self.table.adapter, self.attr)
class ObjectCheckboxColumn(ObjectAttributeColumn):
def __init__(self, app, name, attr, selection):
@@ -167,7 +171,10 @@
try:
self.id_field = self.table.adapter.fields_by_attr[self.id_attr]
except KeyError:
- self.id_field = ObjectSqlField(self.table.adapter, self.id_attr)
+ if isinstance(self.table.adapter, ObjectQmfAdapter):
+ self.id_field = ObjectQmfField(self.table.adapter, self.id_attr)
+ else:
+ self.id_field = ObjectSqlField(self.table.adapter, self.id_attr)
def render_cell_href(self, session, record):
id = record[self.id_field.index]
Modified: mgmt/newdata/cumin/python/cumin/objecttask.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objecttask.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/objecttask.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -130,11 +130,11 @@
self.form.return_url.set(nsession, session.marshal())
self.form.show(nsession)
- self.do_enter(nsession)
+ self.do_enter(nsession, session)
return nsession
- def do_enter(self, session):
+ def do_enter(self, session, osession):
pass
class TaskInvocation(object):
@@ -254,11 +254,11 @@
self.form.return_url.set(nsession, session.marshal())
self.form.show(nsession)
- self.do_enter(nsession)
+ self.do_enter(nsession, session)
return nsession
- def do_enter(self, session):
+ def do_enter(self, session, osession):
pass
def invoke(self, session, selection, *args):
Modified: mgmt/newdata/cumin/python/cumin/parameters.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/parameters.py 2010-06-30 19:10:29 UTC (rev 4058)
+++ mgmt/newdata/cumin/python/cumin/parameters.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -112,13 +112,6 @@
def do_marshal(self, job):
return str(job.id)
-class JobGroupParameter(Parameter):
- def do_unmarshal(self, string):
- return JobGroup(string)
-
- def do_marshal(self, job_group):
- return str(job_group.id)
-
class LinkParameter(Parameter):
def do_unmarshal(self, string):
return Link.get(int(string))
Added: mgmt/newdata/cumin/python/cumin/qmfadapter.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/qmfadapter.py (rev 0)
+++ mgmt/newdata/cumin/python/cumin/qmfadapter.py 2010-06-30 20:28:45 UTC (rev 4059)
@@ -0,0 +1,89 @@
+from rosemary.sqlquery import *
+from wooly.datatable import *
+
+from util import *
+
+class QmfAdapter(DataAdapter):
+ def __init__(self, app, method):
+ super(QmfAdapter, self).__init__()
+
+ self.app = app
+ self.method = method
+ self.default = dict()
+ self.columns = list()
+
+ def get_count(self, values):
+ obj = values['obj']
+ args = values['args']
+
+ action = QmfCall(self.app)
+ results = action.execute(obj, self.method, args)
+
+ return results and len(results) or 0
+
+ def get_data(self, values, options):
+ obj = values['obj']
+ args = values['args']
+
+ action = QmfCall(self.app)
+ results = action.execute(obj, self.method, args)
+
+ if results.error:
+ results.data = self.default
+
+ rows = self.process_results(results)
+ return rows
+
+ def process_results(self, results):
+ """ take the dict response from the qmf call and return a list of
lists """
+
+ records = list()
+
+ if results:
+ for key in results:
+ row = self.process_record(results[key])
+ records.append(row)
+
+ return records
+
+ def process_record(self, record):
+ field_data = list()
+ for column in self.columns:
+ try:
+ val = record[column.name]
+ except KeyError:
+ val = 0
+ field_data.append(val)
+ return field_data
+
+class ObjectQmfAdapter(QmfAdapter):
+ def __init__(self, app, cls):
+ super(ObjectQmfAdapter, self).__init__(app, cls._name)
+
+ self.cls = cls
+
+ self.fields_by_attr = dict()
+
+class QmfField(DataAdapterField):
+ def __init__(self, adapter, column):
+ python_type = column.type.python_type
+
+ super(QmfField, self).__init__(adapter, column.name, python_type)
+
+ self.column = column
+
+ self.adapter.columns.append(column)
+
+
+class ObjectQmfField(QmfField):
+ def __init__(self, adapter, attr):
+ assert isinstance(adapter, ObjectQmfAdapter), adapter
+
+ super(ObjectQmfField, self).__init__(adapter, attr.sql_column)
+
+ self.attr = attr
+
+ self.adapter.fields_by_attr[self.attr] = self
+
+ def get_title(self, session):
+ return self.attr.title or self.attr.name