[rhmessaging-commits] rhmessaging commits: r3886 - in mgmt/newdata: cumin/python/cumin/account and 11 other directories.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Wed Mar 31 13:45:45 EDT 2010


Author: justi9
Date: 2010-03-31 13:45:43 -0400 (Wed, 31 Mar 2010)
New Revision: 3886

Added:
   mgmt/newdata/cumin/python/cumin/objecttask.strings
Removed:
   mgmt/newdata/cumin/python/cumin/objectform.py
Modified:
   mgmt/newdata/cumin/python/cumin/account/main.py
   mgmt/newdata/cumin/python/cumin/account/model.py
   mgmt/newdata/cumin/python/cumin/account/widgets.py
   mgmt/newdata/cumin/python/cumin/grid/job.py
   mgmt/newdata/cumin/python/cumin/grid/main.py
   mgmt/newdata/cumin/python/cumin/grid/model.py
   mgmt/newdata/cumin/python/cumin/grid/negotiator.py
   mgmt/newdata/cumin/python/cumin/grid/scheduler.py
   mgmt/newdata/cumin/python/cumin/inventory/main.py
   mgmt/newdata/cumin/python/cumin/main.py
   mgmt/newdata/cumin/python/cumin/messaging/binding.py
   mgmt/newdata/cumin/python/cumin/messaging/broker.py
   mgmt/newdata/cumin/python/cumin/messaging/brokergroup.py
   mgmt/newdata/cumin/python/cumin/messaging/brokergroup.strings
   mgmt/newdata/cumin/python/cumin/messaging/brokerlink.py
   mgmt/newdata/cumin/python/cumin/messaging/connection.py
   mgmt/newdata/cumin/python/cumin/messaging/connection.strings
   mgmt/newdata/cumin/python/cumin/messaging/exchange.py
   mgmt/newdata/cumin/python/cumin/messaging/exchange.strings
   mgmt/newdata/cumin/python/cumin/messaging/main.py
   mgmt/newdata/cumin/python/cumin/messaging/model.py
   mgmt/newdata/cumin/python/cumin/messaging/queue.py
   mgmt/newdata/cumin/python/cumin/messaging/queue.strings
   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/objectselector.strings
   mgmt/newdata/cumin/python/cumin/objecttask.py
   mgmt/newdata/cumin/python/cumin/parameters.py
   mgmt/newdata/cumin/python/cumin/table.py
   mgmt/newdata/cumin/python/cumin/usergrid/main.py
   mgmt/newdata/cumin/python/cumin/usergrid/widgets.py
   mgmt/newdata/cumin/python/cumin/util.py
   mgmt/newdata/cumin/python/cumin/widgets.py
   mgmt/newdata/cumin/python/cumin/widgets.strings
   mgmt/newdata/cumin/resources/app.css
   mgmt/newdata/mint/python/mint/demo.py
   mgmt/newdata/mint/python/mint/model.py
   mgmt/newdata/mint/python/mint/newupdate.py
   mgmt/newdata/mint/python/mint/tools.py
   mgmt/newdata/mint/sql/rosemary.sql
   mgmt/newdata/misc/boneyard.py
   mgmt/newdata/rosemary/python/rosemary/model.py
   mgmt/newdata/rosemary/python/rosemary/sqlmodel.py
   mgmt/newdata/rosemary/python/rosemary/sqloperation.py
   mgmt/newdata/rosemary/xml/cumin.xml
   mgmt/newdata/wooly/python/wooly/__init__.py
   mgmt/newdata/wooly/python/wooly/forms.py
   mgmt/newdata/wooly/python/wooly/forms.strings
   mgmt/newdata/wooly/python/wooly/sql.py
   mgmt/newdata/wooly/python/wooly/table.py
   mgmt/newdata/wooly/python/wooly/table.strings
Log:
 * Part one of overhauling tasks for the new data; selection tasks
   don't work yet

 * Refactor modules, including a more convenient means to access task
   metadata

 * Add User and Role metadata to cumin.xml

 * Move login UI components to the account module

 * Fix checkbox restoration on ObjectSelector

 * Stop using the 'returning' syntax in rosemary since postgresql 8.1
   doesn't have it; as an alternative query a sequence on
   create_object

 * Drop the primary key column from samples

 * Include _qmf_session_id in the qmf id unique constraint

 * Fix value quoting in queries

 * Maintain a _sync_time attribute on data object, to indicate when
   and whether it's been committed to storage

 * Remove lots of obsolete classes and strings


Modified: mgmt/newdata/cumin/python/cumin/account/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/account/main.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/account/main.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -2,11 +2,22 @@
 from cumin.util import *
 
 from model import *
+from widgets import *
 
-class AccountModule(CuminModule):
-    def init(self, app):
-        subject = app.model.subject
+class Module(CuminModule):
+    def __init__(self, app, name):
+        super(Module, self).__init__(app, name)
+        
+        cls = app.rosemary.com_redhat_cumin.User
 
-        self.change_password = ChangePasswordTask(app, subject)
+        ChangePassword(self, cls)
 
-module = AccountModule()
+        self.app.login_page = LoginPage(self.app, "login.html")
+        self.app.add_page(self.app.login_page)
+
+        self.app.account_page = AccountPage(self.app, "account.html")
+        self.app.add_page(self.app.account_page)
+
+        self.app.login_page.protected = False
+        self.app.login_page.css_page.protected = False
+        self.app.login_page.javascript_page.protected = False

Modified: mgmt/newdata/cumin/python/cumin/account/model.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/account/model.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/account/model.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,3 +1,4 @@
+from cumin.objecttask import *
 from cumin.model import *
 from cumin.util import *
 
@@ -3,24 +4,18 @@
 from widgets import *
 
-class ChangePasswordTask(Task):
-    def __init__(self, app, cls):
-        super(ChangePasswordTask, self).__init__(app, cls)
+class ChangePassword(ObjectTask):
+    def __init__(self, module, cls):
+        super(ChangePassword, self).__init__(module, cls)
 
-        self.form = ChangePasswordForm(self.app, "change_password", self)
+        self.form = ChangePasswordForm(module.app, self.name, self)
 
-    def get_title(self, session):
+    def get_title(self, session, user):
         return "Change password"
 
-    def get_description(self, session, subject):
-        return "Change password of user '%s'" % subject.name
+    def do_enter(self, session, user):
+        pass
 
-    def do_invoke(self, session, subject, password):
-        subject.password = crypt_password(password)
-        subject.syncUpdate()
-
-class LoginSession(object):
-    def __init__(self, app, user):
-        self.app = app
-        self.user = user
-
-        self.created = datetime.now()
+    def do_invoke(self, invoc, user, password):
+        # XXX
+        user.password = crypt_password(password)
+        user.syncUpdate()

Modified: mgmt/newdata/cumin/python/cumin/account/widgets.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/account/widgets.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/account/widgets.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,10 +1,9 @@
-import logging
-
 from wooly import *
 from wooly.widgets import *
 from wooly.resources import *
 
 from cumin import *
+from cumin.objecttask import *
 from cumin.widgets import *
 from cumin.util import *
 
@@ -48,9 +47,8 @@
 class SettingsView(Widget):
     def init(self):
         # XXX deferring this, but I don't like it
-        task = main.module.change_password
-        link = TaskLink(self.app, "change_password", task, None)
-        link.html_class = "action"
+        task = self.app.account.ChangePassword
+        link = ObjectTaskLink(self.app, "change_password", task, None)
         self.add_child(link)
 
         super(SettingsView, self).init()
@@ -112,9 +110,21 @@
             self.validate(session)
 
             if not self.errors.get(session):
+                cls = self.app.rosemary.com_redhat_cumin.User
+                name_literal = "'%s'" % name
+                user = None
+            
+                conn = self.app.model.get_sql_connection()
+                cursor = conn.cursor()
+
                 try:
-                    user = Subject.selectBy(name=name)[0]
-                except IndexError:
+                    for obj in cls.get_selection(cursor, name=name_literal):
+                        user = obj
+                        break
+                finally:
+                    cursor.close()
+
+                if not user:
                     self.login_invalid.set(session, True)
                     return
 
@@ -148,12 +158,10 @@
         def render_content(self, session):
             return "Submit"
 
-class ChangePasswordForm(FieldSubmitForm):
+class ChangePasswordForm(ObjectTaskForm):
     def __init__(self, app, name, task):
-        super(ChangePasswordForm, self).__init__(app, name)
+        super(ChangePasswordForm, self).__init__(app, name, task)
 
-        self.task = task
-
         self.current = self.Current(app, "current")
         self.current.required = True
         self.current.input.size = 20
@@ -197,9 +205,6 @@
             self.task.invoke(session, user, password)
             self.task.exit_with_redirect(session, user)
 
-    def render_title(self, session):
-        return "Change password"
-
     class Current(PasswordField):
         def render_title(self, session):
             return "Current password"

Modified: mgmt/newdata/cumin/python/cumin/grid/job.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/job.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/grid/job.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -213,8 +213,6 @@
             def render_content(self, session):
                 return "Go"
 
-from cumin.inventory.system import SystemFrame
-
 class JobGroupFrame(CuminFrame):
     def __init__(self, app, name, pool):
         super(JobGroupFrame, self).__init__(app, name)
@@ -225,8 +223,9 @@
         self.view = JobGroupView(app, "view", pool)
         self.add_mode(self.view)
 
-        self.system = SystemFrame(app, "system")
-        self.add_mode(self.system)
+        # XXX link instead
+        #self.system = SystemFrame(app, "system")
+        #self.add_mode(self.system)
 
 class JobGroupView(CuminView):
     def __init__(self, app, name, pool):

Modified: mgmt/newdata/cumin/python/cumin/grid/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/main.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/grid/main.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,7 +1,8 @@
 from wooly import *
 from wooly.widgets import *
 from wooly.resources import *
-from cumin.widgets import *
+
+from cumin import *
 from cumin.util import *
 
 from model import *
@@ -10,62 +11,66 @@
 
 strings = StringCatalog(__file__)
 
-class GridModule(CuminModule):
-    def init(self, app):
-        self.see_pools = SeePoolsTask(app, None)
+class Module(CuminModule):
+    def __init__(self, app, name):
+        super(Module, self).__init__(app, name)
 
-        pool = app.model.pool
-        self.submission_add = SubmissionAddTask(app, pool)
+        cls = app.rosemary.mrg_grid.Submission
 
-        job = app.model.job
-        self.job_hold = JobHoldTask(app, job)
-        self.job_set_hold = JobSetHoldTask(app, job)
-        self.job_release = JobReleaseTask(app, job)
-        self.job_set_release = JobSetReleaseTask(app, job)
-        self.job_remove = JobRemoveTask(app, job)
-        self.job_set_remove = JobSetRemoveTask(app, job)
-        self.job_setattribute = JobSetattributeTask(app, job)
+        SubmissionAdd(self, cls)
 
-        scheduler = app.model.scheduler
-        self.scheduler_start = SchedulerStartTask(app, scheduler)
-        self.scheduler_stop = SchedulerStopTask(app, scheduler)
-        self.scheduler_set_start = SchedulerSetStartTask(app, scheduler)
-        self.scheduler_set_stop = SchedulerSetStopTask(app, scheduler)
+        # cls = app.rosemary.mrg_grid.Job
 
-        collector = app.model.collector
-        self.collector_start = CollectorStartTask(app, collector)
-        self.collector_stop = CollectorStopTask(app, collector)
-        self.collector_set_start = CollectorSetStartTask(app, collector)
-        self.collector_set_stop = CollectorSetStopTask(app, collector)
+        # JobHold(self, cls)
+        # JobRelease(self, cls)
+        # JobRemove(self, cls)
+        # JobSetAttribute(self, cls)
 
-        negotiator = app.model.negotiator
-        self.negotiator_start = NegotiatorStartTask(app, negotiator)
-        self.negotiator_stop = NegotiatorStopTask(app, negotiator)
-        self.negotiator_set_start = NegotiatorSetStartTask(app, negotiator)
-        self.negotiator_set_stop = NegotiatorSetStopTask(app, negotiator)
-        self.negotiator_edit_dynamic_quota = NegotiatorEditDynamicQuotaTask(app, negotiator)
-        self.negotiator_edit_static_quota = NegotiatorEditStaticQuotaTask(app, negotiator)
-        self.negotiator_edit_prio_factor = NegotiatorEditPrioFactorTask(app, negotiator)
-        self.negotiator_user_prio_factor = NegotiatorUserPrioFactorTask(app, negotiator)
-        self.negotiator_edit_regroup = NegotiatorEditRegroupTask(app, negotiator)
-        self.negotiator_user_regroup = NegotiatorUserRegroupTask(app, negotiator)
-        self.negotiator_add_group = NegotiatorAddGroupTask(app, negotiator)
+        cls = app.rosemary.mrg_grid.Scheduler
+        
+        start = SchedulerStart(self, cls)
+        stop = SchedulerStop(self, cls)
 
-        self.frame = GridFrame(app, "grid")
-        app.main_page.main.grid = self.frame
-        app.main_page.main.add_tab(self.frame)
+        SelectionTask(start)
+        SelectionTask(stop)
 
-        self.pool_slots_page = PoolSlotMapPage(app, "poolslots.vis")
-        app.add_page(self.pool_slots_page)
+        cls = app.rosemary.mrg_grid.Collector
 
-        self.pool_slots_fullpage = PoolSlotFullPage(app, "poolslotsfull.vis")
-        app.add_page(self.pool_slots_fullpage)
+        start = CollectorStart(self, cls)
+        stop = CollectorStop(self, cls)
 
+        SelectionTask(start)
+        SelectionTask(stop)
+
+        # cls = app.rosemary.mrg_grid.Negotiator
+
+        # NegotiatorStart(self, cls)
+        # NegotiatorStop(self, cls)
+        # NegotiatorEditDynamicQuota(self, cls)
+        # NegotiatorEditStaticQuota(self, cls)
+        # NegotiatorEditPrioFactor(self, cls)
+        # NegotiatorUserPrioFactor(self, cls)
+        # NegotiatorEditRegroup(self, cls)
+        # NegotiatorUserRegroup(self, cls)
+        # NegotiatorAddGroup(self, cls)
+
+    def init(self):
+        super(Module, self).init()
+
+        self.frame = GridFrame(self.app, "grid")
+        self.app.main_page.main.grid = self.frame
+        self.app.main_page.main.add_tab(self.frame)
+
+        self.pool_slots_page = PoolSlotMapPage(self.app, "poolslots.vis")
+        self.app.add_page(self.pool_slots_page)
+
+        self.pool_slots_fullpage = PoolSlotFullPage \
+            (self.app, "poolslotsfull.vis")
+        self.app.add_page(self.pool_slots_fullpage)
+
     def init_test(self, test):
         GridTest("grid", test)
 
-module = GridModule()
-
 class GridFrame(CuminFrame):
     def __init__(self, app, name):
         super(GridFrame, self).__init__(app, name)

Modified: mgmt/newdata/cumin/python/cumin/grid/model.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/model.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/grid/model.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,6 +1,7 @@
 from wooly import Session
 
 from cumin.model import *
+from cumin.objecttask import *
 from cumin.util import *
 
 from job import *
@@ -9,16 +10,16 @@
 from collector import *
 from negotiator import *
 
-from cumin.model import Pool
+#from cumin.model import Pool
 
-class SeePoolsTask(Task):
-    def get_title(self, session):
-        return "See all pools"
+# class SeePoolsTask(Task):
+#     def get_title(self, session):
+#         return "See all pools"
 
-    def do_enter(self, session, scheduler):
-        self.app.main_page.grid.view.show(branch)
+#     def do_enter(self, session, scheduler):
+#         self.app.main_page.grid.view.show(branch)
 
-class SubmissionAddTask(QmfTask):
+class SubmissionAdd(ObjectTask):
     EXPR_TYPE, INTEGER_TYPE, FLOAT_TYPE, STRING_TYPE = 0, 1, 2, 3
     UNIVERSE = {"VANILLA": 5,
                 "SCHEDULER": 7,
@@ -28,26 +29,17 @@
                 "LOCAL": 12,
                 "VM": 13}
 
-    def __init__(self, app, cls):
-        super(SubmissionAddTask, self).__init__(app, cls)
+    def __init__(self, module, cls):
+        super(SubmissionAdd, self).__init__(module, cls)
 
-        self.form = SubmissionAddForm(app, "submission_add", self)
+        self.form = SubmissionAddForm(module.app, "submission_add", self)
 
-    def get_title(self, session):
+    def get_title(self, session, scheduler):
         return "Create submission"
 
-    def get_description(self, session, pool):
-        return "Create submission"
-        #return "Create submission to pool '%s'" % pool.name
-
-    def do_enter(self, session, pool):
-        if pool:
-            assert isinstance(pool, Pool)
-
-            self.form.pool.set(session, pool)
-
-    def do_invoke(self, completion, session,
-                  scheduler, description, executable,
+    def do_invoke(self, invoc, scheduler,
+                  description,
+                  executable,
                   args=None,
                   iwd="/tmp",
                   stdin=None,
@@ -55,8 +47,7 @@
                   stderr=None,
                   requirements="TRUE",
                   universe="VANILLA"):
-        login = session.client_session.attributes["login_session"]
-        user_name = login.user.name
+        user_name = invoc.user.name
 
         ad = {
             "Submission":   {"TYPE": self.STRING_TYPE,
@@ -65,7 +56,8 @@
                              "VALUE": condor_string(executable)},
             "Args":         {"TYPE": self.STRING_TYPE,
                              "VALUE": condor_string(args)},
-            "Requirements": {"TYPE": self.EXPR_TYPE, "VALUE": requirements},
+            "Requirements": {"TYPE": self.EXPR_TYPE,
+                             "VALUE": requirements},
             "JobUniverse":  {"TYPE": self.INTEGER_TYPE,
                              "VALUE": str(self.UNIVERSE[universe])},
             "Iwd":          {"TYPE": self.STRING_TYPE,
@@ -83,82 +75,40 @@
     return string
     # XXX return "\"%s\"" % string
 
-class NegotiatorStartTask(QmfTask):
-    def __init__(self, app, cls):
-        super(NegotiatorStartTask, self).__init__(app, cls)
-
-        self.form = NegotiatorStartForm(app, "negotiator_start", self)
-
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
-
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.negotiator.view.show(session)
-
-    def get_title(self, session):
+class NegotiatorStart(ObjectTask):
+    def get_title(self, session, negotiator):
         return "Start"
 
-    def do_invoke(self, completion, session, negotiator):
-        assert isinstance(negotiator, Negotiator)
-
+    def do_invoke(self, invoc, negotiator):
         system_name = negotiator.System
+
         try:
             master = Master.select("System = '%s'" % system_name)[0]
         except IndexError:
             raise Exception("Master daemon not running")
+
         master.Start(completion, "NEGOTIATOR")
 
-class NegotiatorSetStartTask(SetTask):
-    def __init__(self, app, cls):
-        super(NegotiatorSetStartTask, self).__init__(app, cls)
-
-        self.form = NegotiatorSetTaskForm(app, "negotiator_set_start", self)
-        self.item_task = NegotiatorStartTask(app, cls)
-
-    def do_enter(self, session, objects):
-        self.form.object.set(session, objects)
-
-class NegotiatorStopTask(QmfTask):
-    def __init__(self, app, cls):
-        super(NegotiatorStopTask, self).__init__(app, cls)
-
-        self.form = NegotiatorStopForm(app, "negotiator_stop", self)
-
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
-
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.negotiator.view.show(session)
-
-    def get_title(self, session):
+class NegotiatorStop(ObjectTask):
+    def get_title(self, session, negotiator):
         return "Stop"
 
-    def do_invoke(self, completion, session, negotiator):
-        assert isinstance(negotiator, Negotiator)
-
+    def do_invoke(self, invoc, negotiator):
         system_name = negotiator.System
+
         try:
             master = Master.select("System = '%s'" % system_name)[0]
         except IndexError:
             raise Exception("Master daemon not running")
+
         master.Stop(completion, "NEGOTIATOR")
 
-class NegotiatorSetStopTask(SetTask):
-    def __init__(self, app, cls):
-        super(NegotiatorSetStopTask, self).__init__(app, cls)
+class NegotiatorLimitSet(ObjectTask):
+    def __init__(self, module, cls):
+        super(NegotiatorLimitSet, self).__init__(module, cls)
 
-        self.form = NegotiatorSetTaskForm(app, "negotiator_set_stop", self)
-        self.item_task = NegotiatorStopTask(app, cls)
+        self.form = NegotiatorLimitSetForm(module.app, self.name, self)
 
-    def do_enter(self, session, objects):
-        self.form.object.set(session, objects)
-
-class NegotiatorLimitSetTask(QmfTask):
-    def __init__(self, app, cls):
-        super(NegotiatorLimitSetTask, self).__init__(app, cls)
-
-        self.form = NegotiatorLimitSetForm(app, "negotiator_limit_set", self)
-
     def do_enter(self, session, limit):
         self.form.negotiator.set(session, limit[0])
         self.form.limit_name.set(session, limit[1])
@@ -166,258 +116,175 @@
     def get_title(self, session):
         return "Set limit"
 
-    def do_invoke(self, completion, session, negotiator, name, max):
+    def do_invoke(self, invoc, negotiator, name, max):
         assert isinstance(negotiator, Negotiator)
 
         negotiator.SetLimit(completion, name, max)
 
+        # XXX 
         def completion():
             pass
 
         negotiator.Reconfig(completion)
         
-class CollectorStartTask(QmfTask):
-    def __init__(self, app, cls):
-        super(CollectorStartTask, self).__init__(app, cls)
-
-        self.form = CollectorStartForm(app, "collector_start", self)
-
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
-
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.collector.view.show(session)
-
+class CollectorStart(ObjectTask):
     def get_title(self, session):
         return "Start"
 
-    def do_invoke(self, completion, session, collector):
+    def do_invoke(self, invoc, collector):
         assert isinstance(collector, Collector)
 
         system_name = collector.System
+
         try:
             master = Master.select("System = '%s'" % system_name)[0]
         except IndexError:
             raise Exception("Master daemon not running")
+
         master.Start(completion, "COLLECTOR")
 
-class CollectorSetStartTask(SetTask):
-    def __init__(self, app, cls):
-        super(CollectorSetStartTask, self).__init__(app, cls)
-
-        self.form = CollectorSetTaskForm(app, "collector_set_start", self)
-        self.item_task = CollectorStartTask(app, cls)
-
-    def do_enter(self, session, objects):
-        self.form.object.set(session, objects)
-
-class CollectorStopTask(QmfTask):
-    def __init__(self, app, cls):
-        super(CollectorStopTask, self).__init__(app, cls)
-
-        self.form = CollectorStopForm(app, "collector_stop", self)
-
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
-
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.collector.view.show(session)
-
+class CollectorStop(ObjectTask):
     def get_title(self, session):
         return "Stop"
 
-    def do_invoke(self, completion, session, collector):
+    def do_invoke(self, invoc, collector):
         assert isinstance(collector, Collector)
 
         system_name = collector.System
+
         try:
             master = Master.select("System = '%s'" % system_name)[0]
         except IndexError:
             raise Exception("Master daemon not running")
+
         master.Stop(completion, "COLLECTOR")
 
-class CollectorSetStopTask(SetTask):
-    def __init__(self, app, cls):
-        super(CollectorSetStopTask, self).__init__(app, cls)
-
-        self.form = CollectorSetTaskForm(app, "collector_set_stop", self)
-        self.item_task = CollectorStopTask(app, cls)
-
-    def do_enter(self, session, objects):
-        self.form.object.set(session, objects)
-
-class SchedulerStartTask(QmfTask):
-    def __init__(self, app, cls):
-        super(SchedulerStartTask, self).__init__(app, cls)
-
-        self.form = SchedulerStartForm(app, "scheduler_start", self)
-
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
-
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.scheduler.view.show(session)
-
-    def get_title(self, session):
+class SchedulerStart(ObjectTask):
+    def get_title(self, session, scheduler):
         return "Start"
 
-    def do_invoke(self, completion, session, scheduler):
+    def do_invoke(self, invoc, scheduler):
         assert isinstance(scheduler, Scheduler)
 
         system_name = scheduler.System
+
         try:
             master = Master.select("System = '%s'" % system_name)[0]
         except IndexError:
             raise Exception("Master daemon not running")
+
         master.Start(completion, "SCHEDD")
 
-class SchedulerSetStartTask(SetTask):
-    def __init__(self, app, cls):
-        super(SchedulerSetStartTask, self).__init__(app, cls)
-
-        self.form = SchedulerSetTaskForm(app, "scheduler_set_start", self)
-        self.item_task = SchedulerStartTask(app, cls)
-
-    def do_enter(self, session, objects):
-        self.form.object.set(session, objects)
-
-class SchedulerStopTask(QmfTask):
-    def __init__(self, app, cls):
-        super(SchedulerStopTask, self).__init__(app, cls)
-
-        self.form = SchedulerStopForm(app, "scheduler_stop", self)
-
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
-
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.scheduler.view.show(session)
-
-    def get_title(self, session):
+class SchedulerStop(ObjectTask):
+    def get_title(self, session, sheduler):
         return "Stop"
 
-    def do_invoke(self, completion, session, scheduler):
+    def do_invoke(self, invoc, scheduler):
         assert isinstance(scheduler, Scheduler)
 
         system_name = scheduler.System
+
         try:
             master = Master.select("System = '%s'" % system_name)[0]
         except IndexError:
             raise Exception("Master daemon not running")
+
         master.Stop(completion, "SCHEDD")
 
-class SchedulerSetStopTask(SetTask):
-    def __init__(self, app, cls):
-        super(SchedulerSetStopTask, self).__init__(app, cls)
+# class JobBaseTask(QmfTask):
+#     def __init__(self, app, cls, form, verb):
+#         super(JobBaseTask, self).__init__(app, cls)
 
-        self.form = SchedulerSetTaskForm(app, "scheduler_set_stop", self)
-        self.item_task = SchedulerStopTask(app, cls)
+#         self.form = form
+#         self.verb = verb
 
-    def do_enter(self, session, objects):
-        self.form.object.set(session, objects)
+#     def get_href(self, session, object):
+#         fsession = self.enter(session, object)
+#         #XXX fix this. what happens if this is called from the overview or inventory tab?
+#         scheduler = self.cls.frame.scheduler.get(session)
+#         self.form.scheduler.set(fsession, scheduler)
+#         return fsession.marshal()
 
-class JobBaseTask(QmfTask):
-    def __init__(self, app, cls, form, verb):
-        super(JobBaseTask, self).__init__(app, cls)
+#     def do_enter(self, session, job):
+#         self.form.object.set(session, job)
 
-        self.form = form
-        self.verb = verb
+#     def do_exit(self, session, job):
+#         self.app.main_page.main.grid.pool.job.view.show(session)
 
-    def get_href(self, session, object):
-        fsession = self.enter(session, object)
-        #XXX fix this. what happens if this is called from the overview or inventory tab?
-        scheduler = self.cls.frame.scheduler.get(session)
-        self.form.scheduler.set(fsession, scheduler)
-        return fsession.marshal()
+#     def get_title(self, session):
+#         return self.verb
 
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
+# class JobSetBaseTask(SetTask):
+#     def get_href(self, session, object):
+#         job, submission = object
+#         fsession = self.enter(session, job)
+#         self.form.scheduler.set(fsession, submission.scheduler)
+#         return fsession.marshal()
 
-    def do_exit(self, session, job):
-        self.app.main_page.main.grid.pool.job.view.show(session)
+#     def do_enter(self, session, job):
+#         self.form.object.set(session, job)
 
-    def get_title(self, session):
-        return self.verb
+# class JobHoldTask(JobBaseTask):
+#     def __init__(self, app, cls):
+#         form = JobTaskForm(app, "job_hold", self, "Hold")
+#         super(JobHoldTask, self).__init__(app, cls, form, "Hold")
 
-class JobSetBaseTask(SetTask):
-    def get_href(self, session, object):
-        job, submission = object
-        fsession = self.enter(session, job)
-        self.form.scheduler.set(fsession, submission.scheduler)
-        return fsession.marshal()
+#     def do_invoke(self, completion, session, job, reason, scheduler):
+#         assert isinstance(scheduler, Scheduler)
+#         scheduler.Hold(completion, job, reason)
 
-    def do_enter(self, session, job):
-        self.form.object.set(session, job)
+# class JobSetHoldTask(JobSetBaseTask):
+#     def __init__(self, app, cls):
+#         super(JobSetHoldTask, self).__init__(app, cls)
 
-class JobHoldTask(JobBaseTask):
-    def __init__(self, app, cls):
-        form = JobTaskForm(app, "job_hold", self, "Hold")
-        super(JobHoldTask, self).__init__(app, cls, form, "Hold")
+#         self.form = JobSetTaskForm(app, "job_set_hold", self, "Hold")
+#         self.item_task = JobHoldTask(app, cls)
 
-    def do_invoke(self, completion, session, job, reason, scheduler):
-        assert isinstance(scheduler, Scheduler)
-        scheduler.Hold(completion, job, reason)
+# class JobReleaseTask(JobBaseTask):
+#     def __init__(self, app, cls):
+#         form = JobTaskForm(app, "job_release", self, "Release")
+#         super(JobReleaseTask, self).__init__(app, cls, form, "Release")
 
-class JobSetHoldTask(JobSetBaseTask):
-    def __init__(self, app, cls):
-        super(JobSetHoldTask, self).__init__(app, cls)
+#     def do_invoke(self, completion, session, job, reason, scheduler):
+#         assert isinstance(scheduler, Scheduler)
+#         scheduler.Release(completion, job, reason)
 
-        self.form = JobSetTaskForm(app, "job_set_hold", self, "Hold")
-        self.item_task = JobHoldTask(app, cls)
+# class JobSetReleaseTask(JobSetBaseTask):
+#     def __init__(self, app, cls):
+#         super(JobSetReleaseTask, self).__init__(app, cls)
 
-class JobReleaseTask(JobBaseTask):
-    def __init__(self, app, cls):
-        form = JobTaskForm(app, "job_release", self, "Release")
-        super(JobReleaseTask, self).__init__(app, cls, form, "Release")
+#         self.form = JobSetTaskForm(app, "job_set_release", self, "Release")
+#         self.item_task = JobReleaseTask(app, cls)
 
-    def do_invoke(self, completion, session, job, reason, scheduler):
-        assert isinstance(scheduler, Scheduler)
-        scheduler.Release(completion, job, reason)
+# class JobRemoveTask(JobBaseTask):
+#     def __init__(self, app, cls):
+#         form = JobTaskForm(app, "job_remove", self, "Remove")
+#         super(JobRemoveTask, self).__init__(app, cls, form, "Remove")
 
-class JobSetReleaseTask(JobSetBaseTask):
-    def __init__(self, app, cls):
-        super(JobSetReleaseTask, self).__init__(app, cls)
+#     def do_invoke(self, completion, session, job, reason, scheduler):
+#         assert isinstance(scheduler, Scheduler)
+#         scheduler.Remove(completion, job, reason)
 
-        self.form = JobSetTaskForm(app, "job_set_release", self, "Release")
-        self.item_task = JobReleaseTask(app, cls)
+# class JobSetRemoveTask(JobSetBaseTask):
+#     def __init__(self, app, cls):
+#         super(JobSetRemoveTask, self).__init__(app, cls)
 
-class JobRemoveTask(JobBaseTask):
-    def __init__(self, app, cls):
-        form = JobTaskForm(app, "job_remove", self, "Remove")
-        super(JobRemoveTask, self).__init__(app, cls, form, "Remove")
+#         self.form = JobSetTaskForm(app, "job_set_remove", self, "Remove")
+#         self.item_task = JobRemoveTask(app, cls)
 
-    def do_invoke(self, completion, session, job, reason, scheduler):
-        assert isinstance(scheduler, Scheduler)
-        scheduler.Remove(completion, job, reason)
+# class JobSetattributeTask(QmfTask):
+#     def __init__(self, app, cls):
+#         super(JobSetattributeTask, self).__init__(app, cls)
+#         self.navigable = False
 
-class JobSetRemoveTask(JobSetBaseTask):
-    def __init__(self, app, cls):
-        super(JobSetRemoveTask, self).__init__(app, cls)
+#     def do_invoke(self, completion, session, job, name, value, scheduler):
+#         assert isinstance(scheduler, Scheduler)
+#         scheduler.SetAttribute(completion, job, name, str(value))
 
-        self.form = JobSetTaskForm(app, "job_set_remove", self, "Remove")
-        self.item_task = JobRemoveTask(app, cls)
+#     def get_title(self, session):
+#         return "Set Job Attribute"
 
-class JobSetattributeTask(QmfTask):
-    def __init__(self, app, cls):
-        super(JobSetattributeTask, self).__init__(app, cls)
-        self.navigable = False
-
-    def do_invoke(self, completion, session, job, name, value, scheduler):
-        assert isinstance(scheduler, Scheduler)
-        scheduler.SetAttribute(completion, job, name, str(value))
-
-    def get_title(self, session):
-        return "Set Job Attribute"
-
-class NegotiatorGroupTask(QmfTask):
-    def __init__(self, app, cls):
-        super(NegotiatorGroupTask, self).__init__(app, cls)
-
-        self.navigable = False
-
-    def do_enter(self, session, negotiator):
-        self.form.object.set(session, negotiator)
-
+class NegotiatorGroupTask(ObjectTask):
     def do_exit(self, session, negotiator):
         self.app.main_page.main.grid.pool.negotiator.view.show(session)
 
@@ -429,50 +296,50 @@
         else:
             negotiator.SetRawConfig(completion, group, value)
 
-class NegotiatorAddGroupTask(NegotiatorGroupTask):
-    def __init__(self, app, cls):
-        super(NegotiatorAddGroupTask, self).__init__(app, cls)
+class NegotiatorAddGroup(NegotiatorGroupTask):
+    def __init__(self, module, cls):
+        super(NegotiatorAddGroupTask, self).__init__(module, cls)
 
-        self.form = AddGroupForm(self.app, "negotiator_add_group", self)
+        self.form = AddGroupForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Add Group"
+    def get_title(self, session, obj):
+        return "Add group"
 
-class NegotiatorEditRegroupTask(NegotiatorGroupTask):
-    def __init__(self, app, cls):
-        super(NegotiatorEditRegroupTask, self).__init__(app, cls)
+class NegotiatorEditRegroup(NegotiatorGroupTask):
+    def __init__(self, module, cls):
+        super(NegotiatorEditRegroupTask, self).__init__(module, cls)
 
-        self.form = EditRegroupForm(self.app, "negotiator_edit_regroup", self)
+        self.form = EditRegroupForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Edit Autoregroup"
+    def get_title(self, session, obj):
+        return "Edit autoregroup"
 
-class NegotiatorEditPrioFactorTask(NegotiatorGroupTask):
-    def __init__(self, app, cls):
-        super(NegotiatorEditPrioFactorTask, self).__init__(app, cls)
+class NegotiatorEditPrioFactor(NegotiatorGroupTask):
+    def __init__(self, module, cls):
+        super(NegotiatorEditPrioFactorTask, self).__init__(module, cls)
 
-        self.form = EditPrioFactorForm(self.app, "negotiator_edit_prio_factor", self)
+        self.form = EditPrioFactorForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Edit Priority Factor"
+    def get_title(self, session, obj):
+        return "Edit priority factor"
 
-class NegotiatorEditDynamicQuotaTask(NegotiatorGroupTask):
-    def __init__(self, app, cls):
-        super(NegotiatorEditDynamicQuotaTask, self).__init__(app, cls)
+class NegotiatorEditDynamicQuota(NegotiatorGroupTask):
+    def __init__(self, module, cls):
+        super(NegotiatorEditDynamicQuotaTask, self).__init__(module, cls)
 
-        self.form = EditDynamicQuotaForm(self.app, "negotiator_edit_dynamic_quota", self)
+        self.form = EditDynamicQuotaForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Edit Dynamic Quota"
+    def get_title(self, session, obj):
+        return "Edit dynamic quota"
 
-class NegotiatorEditStaticQuotaTask(NegotiatorGroupTask):
-    def __init__(self, app, cls):
-        super(NegotiatorEditStaticQuotaTask, self).__init__(app, cls)
+class NegotiatorEditStaticQuota(NegotiatorGroupTask):
+    def __init__(self, module, cls):
+        super(NegotiatorEditStaticQuotaTask, self).__init__(module, cls)
 
-        self.form = EditStaticQuotaForm(self.app, "negotiator_edit_static_quota", self)
+        self.form = EditStaticQuotaForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Edit Static Quota"
+    def get_title(self, session, obj):
+        return "Edit static quota"
 
 class NegotiatorUserTask(NegotiatorGroupTask):
     def do_enter(self, session, ng):
@@ -483,20 +350,20 @@
         super(NegotiatorUserTask, self).do_enter(session, negotiator)
         self.form.group.set(session, group)
 
-class NegotiatorUserPrioFactorTask(NegotiatorUserTask):
-    def __init__(self, app, cls):
-        super(NegotiatorUserPrioFactorTask, self).__init__(app, cls)
+class NegotiatorUserPrioFactor(NegotiatorUserTask):
+    def __init__(self, module, cls):
+        super(NegotiatorUserPrioFactorTask, self).__init__(module, cls)
 
-        self.form = UserPrioFactorForm(self.app, "negotiator_user_prio_factor", self)
+        self.form = UserPrioFactorForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Edit Priority Factor"
+    def get_title(self, session, obj):
+        return "Edit priority factor"
 
-class NegotiatorUserRegroupTask(NegotiatorUserTask):
-    def __init__(self, app, cls):
-        super(NegotiatorUserRegroupTask, self).__init__(app, cls)
+class NegotiatorUserRegroup(NegotiatorUserTask):
+    def __init__(self, module, cls):
+        super(NegotiatorUserRegroupTask, self).__init__(module, cls)
 
-        self.form = UserRegroupForm(self.app, "negotiator_user_regroup", self)
+        self.form = UserRegroupForm(self.app, self.name, self)
 
-    def get_title(self, session):
-        return "Edit Autoregroup"
+    def get_title(self, session, obj):
+        return "Edit autoregroup"

Modified: mgmt/newdata/cumin/python/cumin/grid/negotiator.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/negotiator.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/grid/negotiator.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -36,8 +36,8 @@
         self.add_attribute_column(cls.Machine)
         self.add_attribute_column(cls.System)
 
-        self.add_selection_task(main.module.negotiator_set_start)
-        self.add_selection_task(main.module.negotiator_set_stop)
+        # self.add_selection_task(main.module.negotiator_set_start)
+        # self.add_selection_task(main.module.negotiator_set_stop)
 
 class NegotiatorFrame(ObjectFrame):
     def __init__(self, app, name):

Modified: mgmt/newdata/cumin/python/cumin/grid/scheduler.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/scheduler.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/grid/scheduler.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -42,8 +42,8 @@
         self.add_attribute_column(cls.TotalRunningJobs)
         self.add_attribute_column(cls.TotalHeldJobs)
 
-        self.add_selection_task(main.module.scheduler_set_start)
-        self.add_selection_task(main.module.scheduler_set_stop)
+        #self.add_selection_task(main.module.scheduler_set_start)
+        #self.add_selection_task(main.module.scheduler_set_stop)
 
 class SchedulerFrame(ObjectFrame):
     def __init__(self, app, name, pool):

Modified: mgmt/newdata/cumin/python/cumin/inventory/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/inventory/main.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/inventory/main.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,6 +1,8 @@
 from wooly import *
 from wooly.widgets import *
 from wooly.resources import *
+
+from cumin import *
 from cumin.widgets import *
 from cumin.util import *
 
@@ -8,8 +10,10 @@
 
 strings = StringCatalog(__file__)
 
-class InventoryModule(CuminModule):
-    def init(self, app):
+class Module(CuminModule):
+    def __init__(self, app, name):
+        super(Module, self).__init__(app, name)
+
         self.frame = InventoryFrame(app, "inventory")
         app.main_page.main.inventory = self.frame
         app.main_page.main.add_tab(self.frame)
@@ -17,8 +21,6 @@
         self.system_slots_page = SystemSlotMapPage(app, "systemslots.png")
         app.add_page(self.system_slots_page)
 
-module = InventoryModule()
-
 class InventoryFrame(CuminFrame):
     def __init__(self, app, name):
         super(InventoryFrame, self).__init__(app, name)

Modified: mgmt/newdata/cumin/python/cumin/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/main.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/main.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -14,6 +14,7 @@
 
 from config import *
 from model import *
+from objecttask import *
 from sqladapter import *
 from table import *
 from user import *
@@ -21,16 +22,7 @@
 
 from wooly import Session
 
-# Modules
-
-import account
-import messaging
-import grid
-import inventory
-import usergrid
-
 strings = StringCatalog(__file__)
-
 log = logging.getLogger("cumin")
 
 class Cumin(Application):
@@ -44,6 +36,7 @@
         self.devel_enabled = self.config.debug
 
         self.modules = list()
+        self.modules_by_name = dict()
 
         self.home = self.config.home
 
@@ -66,22 +59,12 @@
         self.form_page = CuminFormPage(self, "form.html")
         self.add_page(self.form_page)
 
-        self.login_page = account.LoginPage(self, "login.html")
-        self.add_page(self.login_page)
-
-        # XXX move this to the account module
-        self.account_page = account.AccountPage(self, "account.html")
-        self.add_page(self.account_page)
-
         self.add_page(CallPage(self, "call.xml"))
         self.add_page(StatChartPage(self, "stats.png"))
         self.add_page(StatStackedPage(self, "stacked.png"))
         self.add_page(StatFlashPage(self, "chart.json"))
         self.add_page(FlashFullPage(self, "flashpage.html"))
 
-        self.login_page.protected = False
-        self.login_page.css_page.protected = False
-        self.login_page.javascript_page.protected = False
         self.resource_page.protected = False
 
     def check(self):
@@ -93,14 +76,20 @@
         self.model.check()
 
     def do_init(self):
-        self.modules.append(account.module)
-        self.modules.append(messaging.module)
-        self.modules.append(grid.module)
-        self.modules.append(inventory.module)
-        self.modules.append(usergrid.module)
+        import account
+        import messaging
+        import grid
+        import inventory
+        import usergrid
 
+        account.Module(self, "account")
+        messaging.Module(self, "messaging")
+        grid.Module(self, "grid")
+        inventory.Module(self, "inventory")
+        usergrid.Module(self, "usergrid")
+
         for module in self.modules:
-            module.init(self)
+            module.init()
 
         self.model.init()
 
@@ -112,6 +101,25 @@
     def do_stop(self):
         self.model.stop()
 
+class CuminModule(object):
+    def __init__(self, app, name):
+        self.app = app
+        self.name = name
+
+        self.tasks = list()
+
+        assert not hasattr(app, self.name), self.name
+
+        self.app.modules.append(self)
+        setattr(self.app, self.name, self)
+
+    def init(self):
+        for task in self.tasks:
+            task.init()
+
+    def init_test(self, test):
+        pass
+
 class MainPage(CuminPage, ModeSet):
     def __init__(self, app, name):
         super(MainPage, self).__init__(app, name)
@@ -160,15 +168,17 @@
     def __init__(self, app, name):
         super(OverviewView, self).__init__(app, name)
 
-        queues = messaging.queue.TopQueueSet(app, "queues")
-        self.add_child(queues)
+        # XXX
 
-        submissions = grid.submission.TopSubmissionSet(app, "submissions")
-        self.add_child(submissions)
+        #queues = messaging.queue.TopQueueSet(app, "queues")
+        #self.add_child(queues)
 
-        systems = inventory.system.TopSystemSet(app, "systems")
-        self.add_child(systems)
+        #submissions = grid.submission.TopSubmissionSet(app, "submissions")
+        #self.add_child(submissions)
 
+        #systems = inventory.system.TopSystemSet(app, "systems")
+        #self.add_child(systems)
+
     class Heading(CuminHeading):
         def render_title(self, session):
             return "Overview"

Modified: mgmt/newdata/cumin/python/cumin/messaging/binding.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/binding.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/binding.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -49,7 +49,7 @@
         self.add_attribute_column(binding.origin)
         self.add_attribute_column(binding.msgMatched)
 
-        self.add_selection_task(main.module.binding_set_remove)
+        #self.add_selection_task(main.module.binding_set_remove)
 
     class Exchange(ObjectLinkColumn):
         def render_header_content(self, session):
@@ -348,12 +348,10 @@
         cursor = conn.cursor()
 
         try:
-            exchanges = cls.select_objects(cursor, _vhostRef_id=vhost._id)
+            exchanges = cls.get_selection(cursor, _vhostRef_id=vhost._id)
         finally:
             cursor.close()
 
-        print "XXX", exchanges
-
         # render each exchange we support
         writer = Writer()
 
@@ -487,13 +485,4 @@
 
         return form_binding_info
 
-class BindingSetTaskForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(BindingSetTaskForm, self).__init__(app, name, task)
-
-        item = BindingParameter(app, "item")
-
-        self.object = ListParameter(app, "binding", item)
-        self.add_parameter(self.object)
-
 from exchange import ExchangeInfo

Modified: mgmt/newdata/cumin/python/cumin/messaging/broker.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/broker.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/broker.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -61,8 +61,7 @@
 
         super(BrokerSelector, self).__init__(app, name, broker, data)
 
-        self.group = BrokerGroupParameter(app, "group")
-        self.add_parameter(self.group)
+        self.group = SessionAttribute(self, "group")
 
         frame = "main.messaging.broker"
         col = ObjectLinkColumn(app, "name", system.nodeName, broker._id, frame)
@@ -71,7 +70,7 @@
         self.add_attribute_column(broker.port)
         self.add_attribute_column(cluster.clusterName)
 
-        self.add_selection_task(main.module.broker_set_engroup)
+        #self.add_selection_task(app.messaging.BrokerEngroup)
 
     def get_data_values(self, session):
         values = super(BrokerSelector, self).get_data_values(session)
@@ -79,7 +78,7 @@
         group = self.group.get(session)
 
         if group:
-            values["group_id"] = group.id
+            values["group_id"] = group._id
 
         return values
 
@@ -122,8 +121,8 @@
         self.view.add_tab(BrokerLinkSelector(app, "brokerlinks", self.vhost))
 
         self.add_summary_attribute(cls.port)
-        self.add_summary_task(main.module.exchange_add)
-        self.add_summary_task(main.module.queue_add)
+        self.add_summary_task(app.messaging.ExchangeAdd)
+        self.add_summary_task(app.messaging.QueueAdd)
 
 class ModuleNotEnabled(Widget):
     def do_render(self, session):
@@ -256,6 +255,8 @@
 
         return fmt_link(href, name, class_)
 
+# XXX
+
 from brokergroup import BrokerGroupInputSet
 class BrokerSetEngroupForm(CuminTaskForm):
     def __init__(self, app, name, task):

Modified: mgmt/newdata/cumin/python/cumin/messaging/brokergroup.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/brokergroup.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/brokergroup.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -28,8 +28,8 @@
 
         self.add_attribute_column(cls.description)
 
-        self.add_task(main.module.broker_group_add, None)
-        self.add_selection_task(main.module.broker_group_set_remove)
+        self.add_task(app.messaging.BrokerGroupAdd, None)
+        self.add_selection_task(app.messaging.BrokerGroupRemove)
 
 class BrokerGroupInputSet(CheckboxInputSet):
     def __init__(self, app, name):
@@ -58,20 +58,11 @@
 
         super(BrokerGroupFrame, self).__init__(app, name, cls)
 
-class BrokerGroupView(CuminView):
-    def __init__(self, app, name, group):
-        super(BrokerGroupView, self).__init__(app, name, group)
-
-        self.tabs = TabbedModeSet(app, "tabs")
-        self.add_child(self.tabs)
-
         data = BrokerData(app)
         brokers = BrokerSelector(app, "brokers", data)
-        brokers.group = group
-        self.tabs.add_tab(brokers)
+        brokers.group = self.object
+        self.view.add_tab(brokers)
 
-        self.tabs.add_tab(CuminDetails(app, "details", group))
-
 class BrokerGroupForm(FieldSubmitForm):
     def __init__(self, app, name, task):
         super(BrokerGroupForm, self).__init__(app, name)
@@ -87,12 +78,13 @@
 
         if not self.errors.get(session):
             name = self.group_name.get(session)
+            description = ""
 
-            self.task.invoke(session, None, name)
+            self.task.invoke(session, None, name, description)
             self.task.exit_with_redirect(session, None)
 
     def render_title(self, session):
-        return self.task.get_title(session)
+        return self.task.get_title(session, None)
 
 class BrokerGroupEditForm(BrokerGroupForm):
     def __init__(self, app, name, task):
@@ -118,19 +110,3 @@
     def render_title(self, session):
         group = self.group.get(session)
         return self.task.get_description(session, group)
-
-class BrokerGroupRemoveForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(BrokerGroupRemoveForm, self).__init__(app, name, task)
-
-        self.object = NewBrokerGroupParameter(app, "group")
-        self.add_parameter(self.object)
-
-class BrokerGroupSetTaskForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(BrokerGroupSetTaskForm, self).__init__(app, name, task)
-
-        item = BrokerGroupParameter(app, "item")
-
-        self.object = ListParameter(app, "brokergroup", item)
-        self.add_parameter(self.object)

Modified: mgmt/newdata/cumin/python/cumin/messaging/brokergroup.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/brokergroup.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/brokergroup.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,15 +1,5 @@
-[BrokerGroupSet.sql]
-select bg.id, bg.name
-from broker_group as bg
-{sql_orderby}
-{sql_limit}
-
-[BrokerGroupSet.count_sql]
-select count(*) from broker_group
-
 [BrokerGroupInputSet.item_html]
 <div class="field">
   <input type="checkbox" id="{id}.{item_value}" name="{name}" value="{item_value}" tabindex="{tab_index}" {item_checked_attr}/>
   <label for="{id}.{item_value}">{item_content}</label>
 </div>
-

Modified: mgmt/newdata/cumin/python/cumin/messaging/brokerlink.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/brokerlink.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/brokerlink.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -34,8 +34,8 @@
         self.add_attribute_column(cls.transport)
         self.add_attribute_column(cls.durable)
 
-        self.add_task(main.module.link_add, self.vhost)
-        self.add_selection_task(main.module.link_set_remove)
+        self.add_task(app.messaging.BrokerLinkAdd, self.vhost)
+        self.add_selection_task(app.messaging.BrokerLinkRemove)
 
     # Address column XXX
 
@@ -64,27 +64,11 @@
         self.add_attribute_column(cls.tag)
         self.add_attribute_column(cls.excludes)
 
-        self.add_task(main.module.route_add, self.link)
-        self.add_selection_task(main.module.route_set_remove)
+        self.add_task(app.messaging.RouteAdd, self.link)
+        self.add_selection_task(app.messaging.RouteRemove)
 
 # XXX RouteFrame
 
-class LinkRemoveForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(LinkRemoveForm, self).__init__(app, name, task)
-
-        self.object = LinkParameter(app, "link")
-        self.add_parameter(self.object)
-
-class LinkSetRemoveForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(LinkSetRemoveForm, self).__init__(app, name, task)
-
-        item = LinkParameter(app, "item")
-
-        self.object = ListParameter(app, "link", item)
-        self.add_parameter(self.object)
-
 class LinkView(CuminView):
     def __init__(self, app, name, link):
         super(LinkView, self).__init__(app, name, link)
@@ -284,45 +268,57 @@
         self.object = ListParameter(app, "route", item)
         self.add_parameter(self.object)
 
-class LinkForm(FieldSubmitForm):
-    def __init__(self, app, name):
-        super(LinkForm, self).__init__(app, name)
+class BrokerLinkAddForm(ObjectTaskForm):
+    def __init__(self, app, name, task):
+        super(BrokerLinkAddForm, self).__init__(app, name, task)
 
         self.host = self.Host(app, "host")
         self.add_field(self.host)
 
-        self.more = self.ShowButton(app, "more")
-        self.add_field(self.more)
-
         self.port = self.PortField(app, "port")
-        self.more.add_field(self.port)
+        self.add_extra_field(self.port)
 
         self.username = self.UsernameField(app, "username")
-        self.more.add_field(self.username)
+        self.add_extra_field(self.username)
 
         self.password = self.PassField(app, "password")
-        self.more.add_field(self.password)
+        self.add_extra_field(self.password)
 
         self.durable = self.DurableField(app, "durable")
-        self.more.add_field(self.durable)
+        self.add_extra_field(self.durable)
 
         self.transport = self.TransportField(app, "transport")
-        self.more.add_field(self.transport)
+        self.add_extra_field(self.transport)
 
-    class ShowButton(MoreFieldSet):
-        def render_more_text(self, session):
-            return "Show Optional Inputs..."
+    def process_submit(self, session):
+        self.validate(session)
 
-        def render_less_text(self, session):
-            return "Hide Optional Inputs..."
+        if not self.errors.get(session):
+            vhost = self.object.get(session)
 
+            host = self.host.get(session)
+            port = self.port.get(session) or 5672
+            username = self.username.get(session) or "anonymous"
+            password = self.password.get(session)
+            durable = self.durable.get(session) == "yes"
+            transport = self.transport.get(session)
+
+            # XXX PortField should enforce this
+
+            if port:
+                port = int(port)
+
+            self.task.invoke(session, vhost, host, port,
+                             durable, username, password, transport)
+            self.task.exit_with_redirect(session, vhost)
+
     class Host(NameField):
         def render_title(self, session):
             return "Address"
 
     class PortField(IntegerField):
         def __init__(self, app, name):
-            super(LinkForm.PortField, self).__init__(app, name)
+            super(BrokerLinkAddForm.PortField, self).__init__(app, name)
 
             self.input.size = 5
             self.css_class = "compact first"
@@ -346,7 +342,8 @@
 
     class TransportField(RadioField):
         def __init__(self, app, name):
-            super(LinkForm.TransportField, self).__init__(app, name, None)
+            super(BrokerLinkAddForm.TransportField, self).__init__ \
+                (app, name, None)
 
             self.param = Parameter(app, "param")
             self.param.default = "tcp"
@@ -391,36 +388,3 @@
 
         def render_title_2(self, session):
             return "No, do not restore if broker restarts"
-
-class LinkAddForm(LinkForm):
-    def __init__(self, app, name, task):
-        super(LinkAddForm, self).__init__(app, name)
-
-        self.task = task
-
-        self.vhost = VhostParameter(app, "vhost")
-        self.add_parameter(self.vhost)
-
-    def render_title(self, session):
-        vhost = self.vhost.get(session)
-        return self.task.get_description(session, vhost)
-
-    def process_submit(self, session):
-        self.validate(session)
-
-        if not self.errors.get(session):
-            vhost = self.vhost.get(session)
-
-            host = self.host.get(session)
-            port = self.port.get(session) or 5672
-            username = self.username.get(session) or "anonymous"
-            password = self.password.get(session)
-            durable = self.durable.get(session) == "yes"
-            transport = self.transport.get(session)
-
-            if port:
-                port = int(port)
-
-            self.task.invoke(session, vhost, host, port,
-                             durable, username, password, transport)
-            self.task.exit_with_redirect(session, vhost)

Modified: mgmt/newdata/cumin/python/cumin/messaging/connection.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/connection.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/connection.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -63,138 +63,6 @@
 
         super(ConnectionFrame, self).__init__(app, name, cls)
 
-class ConnectionSet(CuminSelectionTable):
-    def __init__(self, app, name, vhost):
-        item = ConnectionParameter(app, "item")
-        super(ConnectionSet, self).__init__(app, name, item)
-
-        self.vhost = vhost
-
-        col = self.AddressColumn(app, "addr")
-        self.add_column(col)
-        self.set_default_column(col)
-
-        col = self.SystemConnectionColumn(app, "sysconn")
-        self.add_column(col)
-
-        col = self.AuthIdentityColumn(app, "authid")
-        self.add_column(col)
-
-        col = self.FedLinkColumn(app, "fedlink")
-        self.add_column(col)
-
-        col = self.SentColumn(app, "sent")
-        col.align = "right"
-        self.add_column(col)
-
-        col = self.ReceivedColumn(app, "received")
-        col.align = "right"
-        self.add_column(col)
-
-        self.unit = StateSwitch(app, "unit")
-        self.unit.add_state("b", "Bytes")
-        self.unit.add_state("f", "Frames")
-        self.switches.add_child(self.unit)
-
-        self.phase = PhaseSwitch(app, "phase")
-        self.filters.add_child(self.phase)
-
-        task = main.module.connection_set_close
-        button = TaskButton(app, "close", task, self.selection)
-        self.add_child(button)
-
-    def get_unit_plural(self, session):
-        return self.unit.get(session) == "b" and "Bytes" or "Frames"
-
-    def render_title(self, session):
-        vhost = self.vhost.get(session)
-        return "Connections %s" % fmt_count(vhost.clientConnections.count())
-
-    def render_sql_where(self, session):
-        vhost = self.vhost.get(session)
-
-        constraints = list()
-        constraints.append("l.vhost_id = %(id)r")
-        constraints.append(self.phase.get_sql_constraint(session, vhost))
-
-        return "where %s" % " and ".join(constraints)
-
-    def get_sql_values(self, session):
-        vhost = self.vhost.get(session)
-        return {"id": vhost.id}
-
-    class AddressColumn(SqlTableColumn):
-        def render_title(self, session):
-            return "Address"
-
-        def render_content(self, session, data):
-            conn = Identifiable(data["id"])
-            href = self.frame.connection.get_href(session, conn)
-            return fmt_link(href, fmt_shorten(data["addr"]))
-
-    class SystemConnectionColumn(SqlTableColumn):
-        def render_title(self, session):
-            return "Connect Type"
-
-        def render_content(self, session, data):
-            if data['sysconn']:
-                return "System"
-            else:
-                return "Client"
-
-    class AuthIdentityColumn(SqlTableColumn):
-        def render_title(self, session):
-            return "Auth Id"
-
-    class FedLinkColumn(SqlTableColumn):
-
-        def render_title(self, session):
-            return "Fed Link"
-
-        def render_content(self, session, data):
-            if data['fedlink']:
-                return "Yes"
-            else:
-                return "No"
-
-    class SentColumn(NullSortColumn, FreshDataOnlyColumn):
-        def render_title(self, session):
-            return "%s Sent" % self.parent.get_unit_plural(session)
-
-        def get_column_key(self, session):
-            unit = self.parent.unit.get(session)
-            return unit == "b" and "bs" or "fs"
-
-        def render_value(self, session, value):
-            return fmt_rate(value, "", "sec")
-
-    class ReceivedColumn(NullSortColumn, FreshDataOnlyColumn):
-        def render_title(self, session):
-            return "%s Received" % self.parent.get_unit_plural(session)
-
-        def get_column_key(self, session):
-            unit = self.parent.unit.get(session)
-            return unit == "b" and "br" or "fr"
-
-        def render_value(self, session, value):
-            return fmt_rate(value, "", "sec")
-
-class ConnectionCloseForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(ConnectionCloseForm, self).__init__(app, name, task)
-
-        self.object = ConnectionParameter(app, "conn")
-        self.add_parameter(self.object)
-
-class ConnectionSetCloseForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(ConnectionSetCloseForm, self).__init__(app, name, task)
-
-        item = ConnectionParameter(app, "item")
-
-        self.object = ListParameter(app, "conn", item)
-        self.add_parameter(self.object)
-
 class ConnectionView(CuminView):
     def __init__(self, app, name, conn):
         super(ConnectionView, self).__init__(app, name, conn)
@@ -227,73 +95,3 @@
     class SendReceiveRateChart(StatFlashChart):
         def render_title(self, session):
             return "Bytes sent and received"
-
-class SessionSetTaskForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(SessionSetTaskForm, self).__init__(app, name, task)
-
-        item = SessionParameter(app, "item")
-
-        self.object = ListParameter(app, "session", item)
-        self.add_parameter(self.object)
-
-class SessionSet(CuminSelectionTable):
-    def __init__(self, app, name, conn):
-        item = SessionParameter(app, "item")
-        super(SessionSet, self).__init__(app, name, item)
-
-        self.conn = conn
-
-        col = self.NameColumn(app, "name")
-        self.add_column(col)
-        self.set_default_column(col)
-
-        col = self.ExpiresColumn(app, "expires")
-        self.add_column(col)
-
-        col = self.StatusColumn(app, "attached")
-        self.add_column(col)
-
-        self.__phase = PhaseSwitch(app, "phase")
-        self.add_child(self.__phase)
-
-        task = main.module.session_set_detach
-        self.buttons.add_child(TaskButton(app, "detach", task, self.selection))
-
-        task = main.module.session_set_close
-        self.buttons.add_child(TaskButton(app, "close", task, self.selection))
-
-    def render_title(self, session):
-        conn = self.conn.get(session)
-        return "Sessions %s" % fmt_count(conn.sessions.count())
-
-    def render_sql_where(self, session):
-        conn = self.conn.get(session)
-
-        elems = list()
-        elems.append("s.client_connection_id = %(id)r")
-        elems.append(self.__phase.get_sql_constraint(session, conn))
-
-        return "where %s" % " and ".join(elems)
-
-    def get_sql_values(self, session):
-        conn = self.conn.get(session)
-        return {"id": conn.id}
-
-    class NameColumn(SqlTableColumn):
-        def render_title(self, session):
-            return "Name"
-
-    class ExpiresColumn(SqlTableColumn):
-        def render_title(self, session):
-            return "Expires"
-
-        def render_value(self, session, value):
-            return fmt_datetime(value)
-
-    class StatusColumn(SqlTableColumn):
-        def render_title(self, session):
-            return "Attached?"
-
-        def render_content(self, session, data):
-            return fmt_predicate(data["attached"])

Modified: mgmt/newdata/cumin/python/cumin/messaging/connection.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/connection.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/connection.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,36 +1,3 @@
-[ConnectionSet.sql]
-select
-  l.id,
-  l.system_connection as sysconn,
-  l.auth_identity as authid,
-  l.federation_link as fedlink,
-  l.address as addr,
-  (c.bytes_from_client - p.bytes_from_client)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as bs,
-  case when p.bytes_from_client is null then true else false end as bs_is_null,
-  (c.frames_from_client - p.frames_from_client)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as fs,
-  case when p.frames_from_client is null then true else false end as fs_is_null,
-  (c.bytes_to_client - p.bytes_to_client)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as br,
-  case when p.bytes_to_client is null then true else false end as br_is_null,
-  (c.frames_to_client - p.frames_to_client)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as fr,
-  case when p.frames_to_client is null then true else false end as fr_is_null,
-  c.qmf_update_time
-from client_connection as l
-left outer join client_connection_stats as c on c.id = l.stats_curr_id
-left outer join client_connection_stats as p on p.id = l.stats_prev_id
-{sql_where}
-{sql_orderby}
-{sql_limit}
-
-[ConnectionSet.count_sql]
-select count(*)
-from client_connection as l
-left outer join client_connection_stats as c on c.id = l.stats_curr_id
-{sql_where}
-
 [ConnectionStats.html]
 <table class="twocol">
   <tbody>
@@ -48,18 +15,3 @@
   </tr>
   </tbody>
 </table>
-
-[SessionSet.sql]
-select s.id, s.name, s.expire_time as expires, s.attached
-from session as s
-left outer join session_stats as c on c.id = s.stats_curr_id
-left outer join session_stats as p on p.id = s.stats_prev_id
-{sql_where}
-{sql_orderby}
-{sql_limit}
-
-[SessionSet.count_sql]
-select count(*)
-from session as s
-left outer join session_stats as c on c.id = s.stats_curr_id
-{sql_where}

Modified: mgmt/newdata/cumin/python/cumin/messaging/exchange.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/exchange.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/exchange.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,15 +1,15 @@
-import logging
-
 from wooly import *
-from wooly.widgets import *
 from wooly.forms import *
 from wooly.resources import *
-from cumin.stat import *
+from wooly.widgets import *
+
+from cumin.formats import *
 from cumin.model import *
-from cumin.widgets import *
+from cumin.objecttask import *
 from cumin.parameters import *
-from cumin.formats import *
+from cumin.stat import *
 from cumin.util import *
+from cumin.widgets import *
 
 from binding import *
 
@@ -37,8 +37,8 @@
     
         self.add_reference_filter(vhost, cls.vhostRef)
 
-        self.add_task(main.module.exchange_add, self.vhost)
-        self.add_selection_task(main.module.exchange_set_remove)
+        self.add_task(app.messaging.ExchangeAdd, self.vhost)
+        self.add_selection_task(app.messaging.ExchangeRemove)
 
 class ExchangeFrame(ObjectFrame):
     def __init__(self, app, name):
@@ -96,22 +96,6 @@
     def render_item_checked_attr(self, session, exchange):
         return exchange is self.param.get(session) and "checked=\"checked\""
 
-class ExchangeRemoveForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(ExchangeRemoveForm, self).__init__(app, name, task)
-
-        self.object = ExchangeParameter(app, "exchange")
-        self.add_parameter(self.object)
-
-class ExchangeSetRemoveForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(ExchangeSetRemoveForm, self).__init__(app, name, task)
-
-        item = ExchangeParameter(app, "item")
-
-        self.object = ListParameter(app, "exchange", item)
-        self.add_parameter(self.object)
-
 class ExchangeTypeField(RadioItemSetField):
     def __init__(self, app, name):
         param = SymbolParameter(app, "param")
@@ -211,15 +195,10 @@
     def render_title(self, session):
         return "Advanced options"
 
-class ExchangeAddForm(FoldingFieldSubmitForm):
+class ExchangeAddForm(ObjectTaskForm):
     def __init__(self, app, name, task):
-        super(ExchangeAddForm, self).__init__(app, name)
+        super(ExchangeAddForm, self).__init__(app, name, task)
 
-        self.task = task
-
-        self.vhost = VhostParameter(app, "vhost")
-        self.add_parameter(self.vhost)
-
         self.exchange_name = ExchangeNameField(app, "exchange_name")
         self.main_fields.add_field(self.exchange_name)
 
@@ -236,7 +215,8 @@
         self.validate(session)
 
         if not self.errors.get(session):
-            vhost = self.vhost.get(session)
+            vhost = self.object.get(session)
+
             name = self.exchange_name.get(session)
             type = self.exchange_type.get(session)
             durable = self.durability.get(session)
@@ -249,10 +229,6 @@
                              durable, sequence_numbers, initial_value)
             self.task.exit_with_redirect(session, vhost)
 
-    def render_title(self, session):
-        vhost = self.vhost.get(session)
-        return self.task.get_description(session, vhost)
-
 class ExchangeOverview(Widget):
     def __init__(self, app, name, exchange):
         super(ExchangeOverview, self).__init__(app, name)

Modified: mgmt/newdata/cumin/python/cumin/messaging/exchange.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/exchange.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/exchange.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -4,40 +4,6 @@
   {item_content}
 </div>
 
-[ExchangeSet.sql]
-select
-  e.id,
-  e.name,
-  c.producer_count as producers,
-  c.binding_count as bindings,
-  (c.msg_receives - p.msg_receives)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as mreceived,
-  case when p.msg_receives is null then true else false end as mreceived_is_null,
-  (c.byte_receives - p.byte_receives)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as breceived,
-  case when p.byte_receives is null then true else false end as breceived_is_null,
-  (c.msg_routes - p.msg_routes)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as mrouted,
-  case when p.msg_routes is null then true else false end as mrouted_is_null,
-  (c.byte_routes - p.byte_routes)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as brouted,
-  case when p.byte_routes is null then true else false end as brouted_is_null,
-  c.msg_drops as mdropped,
-  c.byte_drops as bdropped,
-  c.qmf_update_time
-from exchange as e
-left outer join exchange_stats as c on c.id = e.stats_curr_id
-left outer join exchange_stats as p on p.id = e.stats_prev_id
-{sql_where}
-{sql_orderby}
-{sql_limit}
-
-[ExchangeSet.count_sql]
-select count(*)
-from exchange as e
-left outer join exchange_stats as c on c.id = e.stats_curr_id
-{sql_where}
-
 [ExchangeStats.html]
 <table class="twocol">
   <tbody>

Modified: mgmt/newdata/cumin/python/cumin/messaging/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/main.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/main.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,7 +1,8 @@
 from wooly import *
 from wooly.widgets import *
 from wooly.resources import *
-from cumin.widgets import *
+
+from cumin import *
 from cumin.util import *
 
 from broker import *
@@ -11,71 +12,81 @@
 
 strings = StringCatalog(__file__)
 
-class MessagingModule(CuminModule):
-    def init(self, app):
-        broker = app.model.broker
+class Module(CuminModule):
+    def __init__(self, app, name):
+        super(Module, self).__init__(app, name)
 
-        self.broker_set_engroup = BrokerSetEngroupTask(app, broker)
-        self.exchange_add = ExchangeAddTask(app, broker)
-        self.link_add = LinkAddTask(app, broker)
-        self.queue_add = QueueAddTask(app, broker)
+        cls = app.rosemary.org_apache_qpid_broker.Broker
 
-        broker_group = app.model.broker_group
+        BrokerEngroup(self, cls)
+        ExchangeAdd(self, cls)
+        BrokerLinkAdd(self, cls)
+        QueueAdd(self, cls)
 
-        self.broker_group_add = BrokerGroupAddTask(app, broker_group)
-        self.broker_group_edit = BrokerGroupEditTask(app, broker_group)
-        self.broker_group_remove = BrokerGroupRemoveTask(app, broker_group)
-        self.broker_group_set_remove = BrokerGroupSetRemoveTask \
-            (app, broker_group)
+        cls = app.rosemary.com_redhat_cumin.BrokerGroup
 
-        queue = app.model.queue
+        BrokerGroupAdd(self, cls)
+        BrokerGroupEdit(self, cls)
 
-        self.queue_remove = QueueRemoveTask(app, queue)
-        self.queue_set_remove = QueueSetRemoveTask(app, queue)
-        self.queue_purge = QueuePurgeTask(app, queue)
-        self.queue_set_purge = QueueSetPurgeTask(app, queue)
-        self.binding_add = BindingAddTask(app, queue)
-        self.move_messages = MoveMessagesTask(app, queue)
+        task = BrokerGroupRemove(self, cls)
+        SelectionTask(task)
 
-        exchange = app.model.exchange
+        cls = app.rosemary.org_apache_qpid_broker.Queue
 
-        self.exchange_remove = ExchangeRemoveTask(app, exchange)
-        self.exchange_set_remove = ExchangeSetRemoveTask(app, exchange)
+        task = QueueRemove(self, cls)
+        SelectionTask(task)
 
-        binding = app.model.binding
+        task = QueuePurge(self, cls)
+        SelectionTask(task)
 
-        self.binding_remove = BindingRemoveTask(app, binding)
-        self.binding_set_remove = BindingSetRemoveTask(app, binding)
+        BindingAdd(self, cls)
+        MoveMessages(self, cls)
 
-        link = app.model.link
+        cls = app.rosemary.org_apache_qpid_broker.Exchange
 
-        self.link_remove = LinkRemoveTask(app, link)
-        self.link_set_remove = LinkSetRemoveTask(app, link)
-        self.route_add = RouteAddTask(app, link)
+        task = ExchangeRemove(self, cls)
+        SelectionTask(task)
 
-        route = app.model.route
+        cls = app.rosemary.org_apache_qpid_broker.Binding
 
-        self.route_set_remove = RouteSetRemoveTask(app, route)
+        task = BindingRemove(self, cls)
+        SelectionTask(task)
 
-        connection = app.model.connection
+        cls = app.rosemary.org_apache_qpid_broker.Link
 
-        self.connection_close = ConnectionCloseTask(app, connection)
-        self.connection_set_close = ConnectionSetCloseTask(app, connection)
+        task = BrokerLinkRemove(self, cls)
+        SelectionTask(task)
 
-        session = app.model.session
+        RouteAdd(self, cls)
 
-        self.session_set_detach = SessionSetDetachTask(app, session)
-        self.session_set_close = SessionSetCloseTask(app, session)
+        cls = app.rosemary.org_apache_qpid_broker.Bridge
 
-        self.frame = MessagingFrame(app, "messaging")
-        app.main_page.main.messaging = self.frame
-        app.main_page.main.add_tab(self.frame)
+        task = RouteRemove(self, cls)
+        SelectionTask(task)
 
+        cls = app.rosemary.org_apache_qpid_broker.Connection
+
+        task = ConnectionClose(self, cls)
+        SelectionTask(task)
+
+        cls = app.rosemary.org_apache_qpid_broker.Session
+
+        task = SessionDetach(self, cls)
+        SelectionTask(task)
+
+        task = SessionClose(self, cls)
+        SelectionTask(task)
+
+    def init(self):
+        super(Module, self).init()
+
+        self.frame = MessagingFrame(self.app, "messaging")
+        self.app.main_page.main.messaging = self.frame
+        self.app.main_page.main.add_tab(self.frame)
+
     def init_test(self, test):
         MessagingTest("messaging", test)
 
-module = MessagingModule()
-
 class MessagingFrame(CuminFrame):
     def __init__(self, app, name):
         super(MessagingFrame, self).__init__(app, name)

Modified: mgmt/newdata/cumin/python/cumin/messaging/model.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/model.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/model.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,6 +1,7 @@
 from wooly import Session
 
 from cumin.model import *
+from cumin.objecttask import *
 from cumin.util import *
 
 from broker import *
@@ -9,19 +10,11 @@
 from queue import *
 from exchange import *
 
-class ConnectionCloseTask(Task):
-    def __init__(self, app, cls):
-        super(ConnectionCloseTask, self).__init__(app, cls)
-
-        self.form = ConnectionCloseForm(app, "connection_close", self)
-
-    def get_title(self, session):
+class ConnectionClose(ObjectTask):
+    def get_title(self, session, conn):
         return "Close"
 
-    def do_enter(self, session, conn):
-        self.form.object.set(session, conn)
-
-    def do_invoke(self, completion, session, conn):
+    def do_invoke(self, invoc, conn):
         # XXX generalize this check and use it for other closes
 
         session_ids = set()
@@ -34,174 +27,81 @@
                 raise Exception \
                     ("Cannot close management connection %s" % conn.address)
 
-        conn.close(completion)
+        print "XXX conn.close", conn
 
-class ConnectionSetCloseTask(SetTask):
-    def __init__(self, app, cls):
-        super(ConnectionSetCloseTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = ConnectionSetCloseForm(app, "connection_set_close", self)
-        self.item_task = ConnectionCloseTask(app, cls)
-
-    def get_title(self, session):
-        return "Close"
-
-    def do_enter(self, session, conns):
-        self.form.object.set(session, conns)
-
-class SessionDetachTask(QmfTask):
-    def get_title(self, session):
+class SessionDetach(ObjectTask):
+    def get_title(self, session, sess):
         return "Detach"
 
-    def do_invoke(self, completion, session, sess):
-        sess.detach(completion)
+    def do_invoke(self, invoc, sess):
+        self.qmf_call(invoc, sess, "detach")
 
-class SessionSetDetachTask(SetTask):
-    def __init__(self, app, cls):
-        super(SessionSetDetachTask, self).__init__(app, cls)
-
-        self.form = SessionSetTaskForm(app, "session_set_detach", self)
-        self.item_task = SessionDetachTask(app, cls)
-
-    def do_enter(self, session, sessions):
-        self.form.object.set(session, sessions)
-
-class SessionCloseTask(QmfTask):
-    def get_title(self, session):
+class SessionClose(ObjectTask):
+    def get_title(self, session, sess):
         return "Close"
 
-    def do_invoke(self, completion, session, sess):
-        sess.close(completion)
+    def do_invoke(self, invoc, sess):
+        self.qmf_call(invoc, sess, "close")
 
-class SessionSetCloseTask(SetTask):
-    def __init__(self, app, cls):
-        super(SessionSetCloseTask, self).__init__(app, cls)
+class QueueAdd(ObjectTask):
+    def __init__(self, module, cls):
+        super(QueueAdd, self).__init__(module, cls)
 
-        self.form = SessionSetTaskForm(app, "session_set_close", self)
-        self.item_task = SessionCloseTask(app, cls)
+        self.form = QueueAddForm(self.app, self.name, self)
 
-    def do_enter(self, session, sessions):
-        self.form.object.set(session, sessions)
-
-class QueueAddTask(Task):
-    def __init__(self, app, cls):
-        super(QueueAddTask, self).__init__(app, cls)
-
-        self.form = QueueAddForm(app, "queue_add", self)
-
-    def get_title(self, session):
+    def get_title(self, session, vhost):
         return "Add queue"
 
-    def get_description(self, session, vhost):
-        cls = self.app.rosemary.org_apache_qpid_broker.Broker
-
-        conn = self.app.model.get_sql_connection()
-        cursor = conn.cursor()
-
-        try:
-            broker = cls.get_object(cursor, vhost._brokerRef_id)
-        finally:
-            cursor.close()
-
-        return "Add queue to broker '%s'" % broker.get_title()
-
-    def do_enter(self, session, vhost):
-        self.form.vhost.set(session, vhost)
-
-    # XXX need to move logic here
-
-class QueueRemoveTask(Task):
-    def __init__(self, app, cls):
-        super(QueueRemoveTask, self).__init__(app, cls)
-
-        self.form = QueueRemoveForm(app, "queue_remove", self)
-
-    def get_title(self, session):
+class QueueRemove(ObjectTask):
+    def get_title(self, session, queue):
         return "Remove"
 
-    def do_enter(self, session, queue):
-        self.form.object.set(session, queue)
-
     def do_exit(self, session, queue):
         self.app.main_page.main.messaging.broker.view.show(session)
 
-    def do_invoke(self, session, queue):
+    def do_invoke(self, invoc, queue):
         session = self.app.model.get_session_by_object(queue)
         session.queue_delete(queue=queue.name)
         session.sync()
 
-class QueueSetRemoveTask(SetTask):
-    def __init__(self, app, cls):
-        super(QueueSetRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = QueueSetTaskForm(app, "queue_set_remove", self)
-        self.item_task = QueueRemoveTask(app, cls)
+class QueuePurge(ObjectTask):
+    def __init__(self, module, cls):
+        super(QueuePurge, self).__init__(module, cls)
 
-    def do_enter(self, session, selection):
-        self.form.selection.set(session, selection)
+        self.form = QueuePurgeForm(self.app, self.name, self)
 
-class QueuePurgeTask(QmfTask):
-    def __init__(self, app, cls):
-        super(QueuePurgeTask, self).__init__(app, cls)
-
-        self.form = QueuePurgeForm(app, "queue_purge", self)
-
-    def get_title(self, session):
+    def get_title(self, session, queue):
         return "Purge"
 
-    def do_enter(self, session, queue):
-        self.form.queue.set(session, queue)
+    def do_invoke(self, invoc, queue, count=0):
+        self.qmf_call(invoc, queue, "purge", count)
 
-    def do_invoke(self, completion, session, obj, count=0):
-        """A count of 0 purges all"""
+class BindingAdd(ObjectTask):
+    def __init__(self, module, cls):
+        super(BindingAdd, self).__init__(module, cls)
 
-        agent = self.app.model.mint.model.agents[obj._qmf_agent_id]
-        agent.call_method(obj, "purge", completion, (count,))
+        self.form = BindingAddForm(self.app, self.name, self)
 
-class QueueSetPurgeTask(SetTask):
-    def __init__(self, app, cls):
-        super(QueueSetPurgeTask, self).__init__(app, cls)
-
-        self.form = QueueSetTaskForm(app, "queue_set_purge", self)
-        self.item_task = QueuePurgeTask(app, cls)
-
-    def do_enter(self, session, ids):
-        self.form.selection.set(session, ids)
-
-class BindingAddTask(Task):
-    def __init__(self, app, cls):
-        super(BindingAddTask, self).__init__(app, cls)
-
-        self.form = BindingAddForm(app, "binding_add", self)
-
-    def get_title(self, session):
+    def get_title(self, session, vhost):
         return "Add binding"
 
-    def get_description(self, session, queue):
-        return "Add binding to queue '%s'" % queue.name
-
-    def do_enter(self, session, queue):
-        self.form.queue.set(session, queue)
-
-    def do_invoke(self, session, queue, exchange, binding_key, arguments):
-        session = self.app.model.get_session_by_object(queue)
+    def do_invoke(self, invoc, vhost, queue, exchange, binding_key, args):
+        session = self.app.model.get_session_by_object(vhost)
         session.exchange_bind(queue=queue.name, exchange=exchange.name,
-                              binding_key=binding_key, arguments=arguments)
+                              binding_key=binding_key, arguments=args)
         session.sync()
 
-class BindingRemoveTask(Task):
-    def __init__(self, app, cls):
-        super(BindingRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = BindingRemoveForm(app, "binding_remove", self)
-
-    def get_title(self, session):
+class BindingRemove(ObjectTask):
+    def get_title(self, session, binding):
         return "Remove"
 
-    def do_enter(self, session, binding):
-        self.form.binding.set(session, binding)
-
-    def do_invoke(self, session, binding):
+    def do_invoke(self, invoc, binding):
         assert isinstance(binding, Binding)
 
         session = self.app.model.get_session_by_object(binding)
@@ -210,51 +110,34 @@
                                 binding_key=binding.bindingKey)
         session.sync()
 
-class BindingSetRemoveTask(SetTask):
-    def __init__(self, app, cls):
-        super(BindingSetRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = BindingSetTaskForm(app, "binding_set_remove", self)
-        self.item_task = BindingRemoveTask(app, cls)
+class MoveMessages(ObjectTask):
+    def __init__(self, module, cls):
+        super(MoveMessages, self).__init__(module, cls)
 
-    def do_enter(self, session, bindings):
-        self.form.object.set(session, bindings)
+        self.form = MoveMessagesForm(self.app, self.name, self)
 
-class MoveMessagesTask(QmfTask):
-    def __init__(self, app, cls):
-        super(MoveMessagesTask, self).__init__(app, cls)
-
-        self.form = MoveMessagesForm(app, "move_messages", self)
-
-    def get_title(self, session):
+    def get_title(self, session, vhost):
         return "Move messages"
 
-    def do_enter(self, session, queue):
-        self.form.queue.set(session, queue)
+    def do_invoke(self, invoc, vhost, src, dst, count):
+        broker = vhost.broker
+        broker.queueMoveMessages(completion, src.name, dst.name, count)
 
-    def do_invoke(self, completion, session, queue, dest_queue, count):
-        broker = queue.vhost.broker
-        broker.queueMoveMessages \
-            (completion, queue.name, dest_queue.name, count)
-
-class ExchangeAddTask(Task):
+class ExchangeAdd(ObjectTask):
     MSG_SEQUENCE = "qpid.msg_sequence"
     IVE = "qpid.ive"
 
-    def __init__(self, app, cls):
-        super(ExchangeAddTask, self).__init__(app, cls)
+    def __init__(self, module, cls):
+        super(ExchangeAdd, self).__init__(module, cls)
 
-        self.form = ExchangeAddForm(app, "exchange_add", self)
+        self.form = ExchangeAddForm(self.app, self.name, self)
 
-    def get_title(self, session):
+    def get_title(self, session, vhost):
         return "Add exchange"
 
-    def do_enter(self, session, vhost):
-        self.form.vhost.set(session, vhost)
-
-    def do_invoke(self, session, vhost, name, type, durable, sequence, ive):
-        assert isinstance(vhost, Vhost)
-
+    def do_invoke(self, invoc, vhost, name, type, durable, sequence, ive):
         args = dict()
 
         if sequence:
@@ -268,157 +151,97 @@
             (exchange=name, type=type, durable=durable, arguments=args)
         session.sync()
 
-class ExchangeRemoveTask(Task):
-    def __init__(self, app, cls):
-        super(ExchangeRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = ExchangeRemoveForm(app, "exchange_remove", self)
-
-    def get_title(self, session):
+class ExchangeRemove(ObjectTask):
+    def get_title(self, session, exchange):
         return "Remove"
 
-    def do_enter(self, session, exchange):
-        self.form.object.set(session, exchange)
-
     def do_exit(self, session, exchange):
         self.app.main_page.main.messaging.broker.view.show(session)
 
-    def do_invoke(self, session, exchange):
-        assert isinstance(exchange, Exchange)
-
+    def do_invoke(self, invoc, exchange):
         session = self.app.model.get_session_by_object(exchange)
         session.exchange_delete(exchange=exchange.name)
         session.sync()
 
-class ExchangeSetRemoveTask(SetTask):
-    def __init__(self, app, cls):
-        super(ExchangeSetRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = ExchangeSetRemoveForm(app, "exchange_set_remove", self)
-        self.item_task = ExchangeRemoveTask(app, cls)
+class BrokerLinkAdd(ObjectTask):
+    def __init__(self, module, cls):
+        super(BrokerLinkAdd, self).__init__(module, cls)
 
-    def get_description(self, session, exchanges):
-        count = len(exchanges)
-        return "Remove %i exchange%s" % (count, ess(count))
+        self.form = BrokerLinkAddForm(self.app, self.name, self)
 
-    def do_enter(self, session, exchanges):
-        self.form.object.set(session, exchanges)
-
-class LinkAddTask(QmfTask):
-    def __init__(self, app, cls):
-        super(LinkAddTask, self).__init__(app, cls)
-
-        self.form = LinkAddForm(app, "link_add", self)
-
-    def get_title(self, session):
+    def get_title(self, session, vhost):
         return "Add broker link"
 
-    def get_description(self, session, vhost):
-        return "Add broker link to vhost '%s'" % get_vhost_name(vhost)
+    def do_invoke(self, invoc, vhost, host, port, durable, username,
+                    password, transport):
+        broker = vhost.broker # XXX
 
-    def do_enter(self, session, vhost):
-        self.form.vhost.set(session, vhost)
-
-    def do_invoke(self, completion, session, vhost,
-                  host, port, durable, username, password, transport):
-        broker = vhost.broker
-
         if username == "anonymous":
             mech = "ANONYMOUS"
         else:
             mech = "PLAIN"
 
-        broker.connect(completion, host, port, durable, mech,
-                       username, password, transport)
+        self.qmf_call(invoc, broker, "connect",
+                      host, port, durable, mech, username, password, transport)
 
-class LinkRemoveTask(QmfTask):
-    def __init__(self, app, cls):
-        super(LinkRemoveTask, self).__init__(app, cls)
-
-        self.form = LinkRemoveForm(app, "link_remove", self)
-
-    def get_title(self, session):
+class BrokerLinkRemove(ObjectTask):
+    def get_title(self, session, link):
         return "Remove"
 
-    def do_enter(self, session, link):
-        self.form.object.set(session, link)
+    def do_exit(self, session, link):
+        self.app.main_page.main.messaging.broker.view.show(session)
 
-    def do_invoke(self, completion, session, link):
-        link.close(completion)
+    def do_invoke(self, invoc, link):
+        self.qmf_call(invoc, link, "remove")
 
-class LinkSetRemoveTask(SetTask):
-    def __init__(self, app, cls):
-        super(LinkSetRemoveTask, self).__init__(app, cls)
+class RouteAdd(ObjectTask):
+    def __init__(self, module, cls):
+        super(RouteAdd, self).__init__(module, cls)
 
-        self.form = LinkSetRemoveForm(app, "link_set_remove", self)
-        self.item_task = LinkRemoveTask(app, cls)
+        self.form = RouteAddForm(self.app, self.name, self)
 
-    def do_enter(self, session, links):
-        self.form.object.set(session, links)
-
-class RouteAddTask(QmfTask):
-    def __init__(self, app, cls):
-        super(RouteAddTask, self).__init__(app, cls)
-
-        self.form = RouteAddForm(app, "route_add", self)
-
-    def get_title(self, session):
+    def get_title(self, session, link):
         return "Add route"
 
-    def get_description(self, session, link):
-        return "Add route to link '%s:%i'" % (link.host, link.port)
+    def do_invoke(self, invoc, link, exchange, key, tag, dynamic, sync,
+                    excludes):
+        self.qmf_call(invoc, link, "bridge",
+                      link.durable, exchange.name, exchange.name,
+                      key, tag, excludes, False, False, dynamic, sync)
 
-    def do_enter(self, session, link):
-        self.form.link.set(session, link)
-
-    def do_invoke(self, completion, session, link, exchange, key, tag,
-                  dynamic, sync, excludes):
-        link.bridge(completion, link.durable, exchange.name, exchange.name,
-                    key, tag, excludes, False, False, dynamic, sync)
-
-class RouteRemoveTask(QmfTask):
-    def get_title(self, session):
+class RouteRemove(ObjectTask):
+    def get_title(self, session, route):
         return "Remove"
 
-    def do_invoke(self, completion, session, route):
-        route.close(completion)
+    def do_exit(self, session, route):
+        self.app.main_page.main.messaging.broker.view.show(session)
 
-class RouteSetRemoveTask(SetTask):
-    def __init__(self, app, cls):
-        super(RouteSetRemoveTask, self).__init__(app, cls)
+    def do_invoke(self, invoc, route):
+        self.qmf_call(invoc, "close")
 
-        self.form = RouteSetRemoveForm(app, "route_set_remove", self)
-        self.item_task = RouteRemoveTask(app, cls)
+class BrokerGroupAdd(ObjectTask):
+    def __init__(self, module, cls):
+        super(BrokerGroupAdd, self).__init__(module, cls)
 
-    def do_enter(self, session, routes):
-        self.form.object.set(session, routes)
+        self.form = BrokerGroupAddForm(self.app, self.name, self)
 
-class BrokerGroupAddTask(Task):
-    def __init__(self, app, cls):
-        super(BrokerGroupAddTask, self).__init__(app, cls)
-
-        self.form = BrokerGroupAddForm(app, "broker_group_add", self)
-
-    def get_title(self, session):
+    def get_title(self, session, obj):
         return "Add broker group"
 
-    def do_invoke(self, session, object, name):
-        cls = self.app.rosemary.com_redhat_cumin.BrokerGroup
+    def do_invoke(self, invoc, obj, name, description):
+        conn = self.app.model.get_sql_connection()
+        cursor = conn.cursor()
 
-        group = cls.create_object()
+        group = self.cls.create_object(cursor)
         group.name = name
-        group.description = "XXX"
+        group.description = description
 
-        # XXX ugh
-        group._qmf_agent_id = "cumin"
-        group._qmf_object_id = str(uuid4())
-        group._qmf_create_time = datetime.now()
-        group._qmf_update_time = datetime.now()
-        group._qmf_class_key = "cumin"
+        group.fake_qmf_values()
 
-        conn = self.app.model.get_sql_connection()
-        cursor = conn.cursor()
-
         try:
             group.save(cursor)
         finally:
@@ -426,21 +249,20 @@
 
         conn.commit()
 
+        invoc.end()
+
         return group
 
-class BrokerGroupEditTask(Task):
-    def __init__(self, app, cls):
-        super(BrokerGroupEditTask, self).__init__(app, cls)
+class BrokerGroupEdit(ObjectTask):
+    def __init__(self, module, cls):
+        super(BrokerGroupEdit, self).__init__(module, cls)
 
-        self.form = BrokerGroupEditForm(app, "broker_group_edit", self)
+        self.form = BrokerGroupEditForm(self.app, self.name, self)
 
-    def get_title(self, session):
+    def get_title(self, session, group):
         return "Edit"
 
-    def do_enter(self, session, group):
-        self.form.group.set(session, group)
-
-    def do_invoke(self, session, group, name):
+    def do_invoke(self, invoc, group, name, description):
         assert group
 
         group.name = name
@@ -455,24 +277,16 @@
 
         conn.commit()
 
-class BrokerGroupRemoveTask(Task):
-    def __init__(self, app, cls):
-        super(BrokerGroupRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = BrokerGroupRemoveForm(app, "broker_group_remove", self)
-
-    def get_title(self, session):
+class BrokerGroupRemove(ObjectTask):
+    def get_title(self, session, group):
         return "Remove"
 
-    def do_enter(self, session, group):
-        self.form.object.set(session, group)
-
     def do_exit(self, session, group):
         self.app.main_page.main.messaging.view.show(session)
 
-    def do_invoke(self, session, group):
-        assert group
-
+    def do_invoke(self, invoc, group):
         conn = self.app.model.get_sql_connection()
         cursor = conn.cursor()
 
@@ -483,21 +297,19 @@
 
         conn.commit()
 
-class BrokerGroupSetRemoveTask(SetTask):
-    def __init__(self, app, cls):
-        super(BrokerGroupSetRemoveTask, self).__init__(app, cls)
+        invoc.end()
 
-        self.form = BrokerGroupSetTaskForm(app, "broker_groups_remove", self)
-        self.item_task = BrokerGroupRemoveTask(app, cls)
+class BrokerEngroup(ObjectTask):
+    def get_title(self, session, broker):
+        return "Add to groups"
 
-    def do_enter(self, session, groups):
-        self.form.object.set(session, groups)
+    def do_invoke(self, invoc, broker, groups):
+        print "XXX engroup", broker, groups
 
-class BrokerEngroupTask(Task):
-    def get_title(self, session):
-        return "Add to groups"
+        invoc.end()
 
-    def do_invoke(self, session, broker, selected_groups):
+        return
+
         all_groups = BrokerGroup.select()
         selected_ids = [x.id for x in selected_groups]
         for group in all_groups:
@@ -513,26 +325,6 @@
                 if existing_mapping.count() == 0:
                     # add mapping if group is checked but there
                     # is not already a mapping
-                    new_mapping = BrokerGroupMapping(brokerID=broker.id, brokerGroupID=group.id)
+                    new_mapping = BrokerGroupMapping(brokerID=broker.id,
+                                                     brokerGroupID=group.id)
                     new_mapping.syncUpdate()
-
-class BrokerSetEngroupTask(SetTask):
-    def __init__(self, app, cls):
-        super(BrokerSetEngroupTask, self).__init__(app, cls)
-
-        self.form = BrokerSetEngroupForm(app, "brokers_engroup", self)
-        self.item_task = BrokerEngroupTask(app, cls)
-
-    def get_description(self, session, brokers):
-        count = len(brokers)
-        return "Place %i broker%s in broker groups" % (count, ess(count))
-
-    def do_enter(self, session, brokers):
-        self.form.object.set(session, brokers)
-
-def get_vhost_name(vhost):
-    broker = vhost.broker
-    name = broker.system.nodeName
-    port = broker.port
-
-    return "%s:%i" % (name, port)

Modified: mgmt/newdata/cumin/python/cumin/messaging/queue.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/queue.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/queue.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,29 +1,24 @@
-import logging
-
-from mint import Queue, Journal, Exchange
 from wooly import *
-from wooly.widgets import *
 from wooly.forms import *
 from wooly.resources import *
 from wooly.tables import *
-from datetime import datetime
-from sqlobject.sqlbuilder import LEFTJOINOn
-from cumin.objectselector import *
+from wooly.widgets import *
+
+from cumin.formats import *
 from cumin.objectform import *
+from cumin.objectselector import *
+from cumin.objecttask import *
+from cumin.parameters import *
 from cumin.sqladapter import *
 from cumin.stat import *
 from cumin.table import *
-from cumin.widgets import *
-from cumin.parameters import *
-from cumin.formats import *
 from cumin.util import *
+from cumin.widgets import *
 
 from binding import *
-from exchange import ExchangeInputSet
+from exchange import *
 from subscription import *
 
-import main
-
 strings = StringCatalog(__file__)
 log = logging.getLogger("cumin.messaging.queue")
 
@@ -46,9 +41,9 @@
 
         self.add_reference_filter(vhost, cls.vhostRef)
 
-        self.add_task(main.module.queue_add, self.vhost)
-        self.add_selection_task(main.module.queue_set_purge)
-        self.add_selection_task(main.module.queue_set_remove)
+        self.add_task(app.messaging.QueueAdd, self.vhost)
+        self.add_selection_task(app.messaging.QueuePurge)
+        self.add_selection_task(app.messaging.QueueRemove)
 
 class QueueFrame(ObjectFrame):
     def __init__(self, app, name):
@@ -78,56 +73,49 @@
 
         self.queue_column.visible = False
 
-class QueueAddForm(FieldSubmitForm):
+class QueueAddForm(ObjectTaskForm):
     def __init__(self, app, name, task):
-        super(QueueAddForm, self).__init__(app, name)
+        super(QueueAddForm, self).__init__(app, name, task)
 
-        self.task = task
-
-        cls = self.app.rosemary.org_apache_qpid_broker.Vhost
-
-        self.vhost = RosemaryObjectParameter(app, "vhost", cls)
-        self.add_parameter(self.vhost)
-
         self.namef = NameField(app, "name")
         self.add_field(self.namef)
 
         self.more = self.AdvancedOptions(app, "more")
         self.add_field(self.more)
 
+        self.bindings = ExchangeKeysField(app, "bindings", self.object)
+        self.add_field(self.bindings)
+
         self.durable = self.QueueDurabilityField(app, "durable")
-        self.more.add_field(self.durable)
+        self.add_extra_field(self.durable)
 
         self.cluster_durable = self.ClusterDurabilityField \
             (app, "cluster_durable")
-        self.more.add_field(self.cluster_durable)
+        self.add_extra_field(self.cluster_durable)
 
         self.lvq = self.LVQField(app, "lvq")
-        self.more.add_field(self.lvq)
+        self.add_extra_field(self.lvq)
 
         self.optimistic = self.OptimisticField(app, "optimistic")
-        self.more.add_field(self.optimistic)
+        self.add_extra_field(self.optimistic)
 
         self.file_count = self.FileCountField(app, "file_count")
         self.file_count.input.param.default = 8
-        self.more.add_field(self.file_count)
+        self.add_extra_field(self.file_count)
 
         self.file_size = self.FileSizeField(app, "file_size")
         self.file_size.input.param.default = 24
-        self.more.add_field(self.file_size)
+        self.add_extra_field(self.file_size)
 
         self.policy = self.PolicyField(app, "policy")
-        self.more.add_field(self.policy)
+        self.add_extra_field(self.policy)
 
         self.q_size = self.QSizeField(app, "q_size")
-        self.more.add_field(self.q_size)
+        self.add_extra_field(self.q_size)
 
         self.q_count = self.QCountField(app, "q_count")
-        self.more.add_field(self.q_count)
+        self.add_extra_field(self.q_count)
 
-        self.bindings = ExchangeKeysField(app, "bindings", self.vhost)
-        self.add_field(self.bindings)
-
     class AdvancedOptions(MoreFieldSet):
         def render_title(self, session):
             return "Advanced Options"
@@ -277,7 +265,8 @@
                 return "Ring Strict"
 
     def process_submit(self, session):
-        vhost = self.vhost.get(session)
+        vhost = self.object.get(session)
+
         name = self.namef.get(session)
         durable = self.durable.get(session)
         policy = self.policy.get(session)
@@ -336,44 +325,25 @@
                                            binding_key=binding_key,
                                            arguments=eargs)
 
-                self.task.end(invoc)
+                invoc.end()
             except Exception, e:
                 self.task.exception(invoc, e)
 
             self.process_return(session)
 
-    def render_title(self, session):
-        vhost = self.vhost.get(session)
-        return self.task.get_description(session, vhost)
-
-class QueueRemoveForm(CuminTaskForm):
+class QueuePurgeForm(ObjectTaskForm):
     def __init__(self, app, name, task):
-        super(QueueRemoveForm, self).__init__(app, name, task)
+        super(QueuePurgeForm, self).__init__(app, name, task)
 
-        self.object = QueueParameter(app, "queue")
-        self.add_parameter(self.object)
-
-class QueuePurgeForm(FieldSubmitForm):
-    def __init__(self, app, name, task):
-        super(QueuePurgeForm, self).__init__(app, name)
-
-        self.task = task
-
-        self.queue = QueueParameter(app, "queue")
-        self.add_parameter(self.queue)
-
         self.purge_request = MultiplicityField(app, "purge_request")
         self.add_field(self.purge_request)
 
-    def render_title(self, session):
-        queue = self.queue.get(session)
-        return self.task.get_description(session, queue)
-
     def process_submit(self, session):
         self.validate(session)
 
         if not self.errors.get(session):
-            queue = self.queue.get(session)
+            queue = self.object.get(session)
+
             request_amt = self.purge_request.get(session)
 
             if request_amt == "all":
@@ -388,12 +358,6 @@
             self.task.invoke(session, queue, count)
             self.task.exit_with_redirect(session, queue)
 
-class QueueSetTaskForm(SelectionTaskForm):
-    def __init__(self, app, name, task):
-        cls = app.rosemary.org_apache_qpid_broker.Queue
-
-        super(QueueSetTaskForm, self).__init__(app, name, cls, task)
-
 class BindSummaryPropertiesField(FormField):
     def __init__(self, app, name, queue):
         super(BindSummaryPropertiesField, self).__init__(app, name)
@@ -420,19 +384,14 @@
     def render_prop_items(self, session):
         return self.sum_props.render_items(session)
 
-class BindingAddForm(FieldSubmitForm):
+class BindingAddForm(ObjectTaskForm):
     def __init__(self, app, name, task):
-        super(BindingAddForm, self).__init__(app, name)
+        super(BindingAddForm, self).__init__(app, name, task)
 
-        self.task = task
-
-        self.queue = QueueParameter(app, "queue")
-        self.add_parameter(self.queue)
-
         self.vhost = self.VhostAttribute(app, "vhost")
         self.add_attribute(self.vhost)
 
-        self.props = BindSummaryPropertiesField(app, "props", self.queue)
+        self.props = BindSummaryPropertiesField(app, "props", self.object)
         self.add_field(self.props)
 
         self.bindings = self.ExchangeBindings(app, "bindings", self.vhost)
@@ -444,10 +403,11 @@
 
     class VhostAttribute(Attribute):
         def get(self, session):
-            return self.widget.queue.get(session).vhost
+            return self.widget.object.get(session).vhost
 
     def process_submit(self, session):
-        queue = self.queue.get(session)
+        queue = self.object.get(session)
+
         errors, form_binding_info = self.bindings.get_binding_errors \
             (session, queue.name)
 
@@ -463,17 +423,6 @@
             #self.task.invoke(session, queue, args)
             self.task.exit_with_redirect(session, queue)
 
-    def render_title(self, session):
-        queue = self.queue.get(session)
-        return self.task.get_description(session, queue)
-
-class BindingRemoveForm(CuminTaskForm):
-    def __init__(self, app, name, task):
-        super(BindingRemoveForm, self).__init__(app, name, task)
-
-        self.object = BindingParameter(app, "binding")
-        self.add_parameter(self.object)
-
 class QueueStats(RadioModeSet):
     def __init__(self, app, name, queue):
         super(QueueStats, self).__init__(app, name)

Modified: mgmt/newdata/cumin/python/cumin/messaging/queue.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/messaging/queue.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/messaging/queue.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,39 +1,3 @@
-[QueueSet.sql]
-select
-  q.id,
-  q.name,
-  c.consumer_count as consumers,
-  c.binding_count as bindings,
-  (c.msg_total_enqueues - p.msg_total_enqueues)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as menqueued,
-  case when p.msg_total_enqueues is null then true else false end as menqueued_is_null,
-  (c.byte_total_enqueues - p.byte_total_enqueues)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as benqueued,
-  case when p.byte_total_enqueues is null then true else false end as benqueued_is_null,
-  (c.msg_total_dequeues - p.msg_total_dequeues)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as mdequeued,
-  case when p.msg_total_dequeues is null then true else false end as mdequeued_is_null,
-  (c.byte_total_dequeues - p.byte_total_dequeues)
-   / (extract(epoch from (c.qmf_update_time - p.qmf_update_time)) + 0.0001) as bdequeued,
-  case when p.byte_total_dequeues is null then true else false end as bdequeued_is_null,
-  c.msg_depth as mdepth,
-  c.byte_depth as bdepth,
-  1 as mdepthaccel,
-  1 as bdepthaccel,
-  c.qmf_update_time
-from queue as q
-left outer join queue_stats as c on c.id = q.stats_curr_id
-left outer join queue_stats as p on p.id = q.stats_prev_id
-{sql_where}
-{sql_orderby}
-{sql_limit}
-
-[QueueSet.count_sql]
-select count(*)
-from queue as q
-left outer join queue_stats as c on c.id = q.stats_curr_id
-{sql_where}
-
 [TopQueueSet.sql]
 select
   q.id,

Modified: mgmt/newdata/cumin/python/cumin/model.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/model.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/model.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -57,8 +57,6 @@
         CuminBrokerAclModule(self)
         CuminBrokerClusterModule(self)
 
-        CuminBrokerGroup(self)
-
         # Grid
 
         CuminScheduler(self)
@@ -68,7 +66,6 @@
         CuminJobGroup(self)
         CuminLimit(self)
 
-        CuminPool(self)
         CuminCollector(self)
         CuminNegotiator(self)
 
@@ -961,8 +958,6 @@
     def init(self):
         super(CuminGrid, self).init()
 
-        self.frame = self.model.frame.grid.pool
-
     def get_title(self, session):
         return "Grid"
 
@@ -1093,8 +1088,6 @@
     def init(self):
         super(CuminSystem, self).init()
 
-        self.frame = self.model.frame.inventory.system
-
     def get_title(self, session):
         return "System"
 
@@ -1742,66 +1735,6 @@
         prop = CuminProperty(self, "members")
         prop.title = "Members"
 
-class CuminBrokerGroup(CuminClass):
-    def __init__(self, model):
-        super(CuminBrokerGroup, self).__init__ \
-            (model, "broker_group", BrokerGroup)
-
-    def init(self):
-        super(CuminBrokerGroup, self).init()
-
-        self.frame = self.model.frame.messaging.broker_group
-
-    def get_title(self, session):
-        return "Broker Group"
-
-    def get_icon_href(self, session):
-        return "resource?name=group-36.png"
-
-class CuminPool(CuminClass):
-    def __init__(self, model):
-        super(CuminPool, self).__init__(model, "pool", Pool)
-
-        prop = CuminProperty(self, "id")
-        prop.title = "Collector"
-        prop.summary = True
-
-    def init(self):
-        super(CuminPool, self).init()
-
-        self.frame = self.model.frame.grid.pool
-
-    def get_title(self, session):
-        return "Pool"
-
-    def get_object_name(self, pool):
-        coll = pool.get_collector()
-        return coll.Name
-
-    def get_object_title(self, session, pool):
-        coll = pool.get_collector()
-
-        if coll.Name == "main":
-            title = "Main Pool"
-        else:
-            title = super(CuminPool, self).get_object_title(session, pool)
-
-        return title
-
-    def get_icon_href(self, session):
-        return "resource?name=pool-36.png"
-
-    class StatusStat(CuminStat):
-        def value_text(self, record):
-            if record:
-                state = self.name
-                value = record[state]
-                return str(value)
-            return ""
-
-        def rate_text(self, record):
-            return ""
-
 class CuminLimit(CuminClass):
     def __init__(self, model):
         super(CuminLimit, self).__init__ \

Deleted: mgmt/newdata/cumin/python/cumin/objectform.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectform.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/objectform.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,97 +0,0 @@
-from wooly import *
-from wooly.forms import *
-from wooly.parameters import *
-
-from util import *
-
-class ObjectForm(SubmitForm, Frame):
-    def __init__(self, app, name, cls):
-        super(ObjectForm, self).__init__(app, name)
-
-        self.cls = cls
-
-        self.id = IntegerParameter(app, "id")
-        self.add_parameter(self.id)
-
-        self.object = Attribute(app, "object")
-
-    def init(self):
-        super(ObjectForm, self).init()
-
-        assert self.cls, self
-
-    def do_process(self, session):
-        conn = self.app.model.get_sql_connection()
-        cursor = conn.cursor()
-
-        try:
-            obj = self.cls.get_object(cursor, id)
-            self.object.set(session, obj)
-        finally:
-            cursor.close()
-
-        super(ObjectForm, self).do_process(session)
-
-class SelectionForm(SubmitForm, Frame):
-    def __init__(self, app, name, cls):
-        super(SelectionForm, self).__init__(app, name)
-
-        self.cls = cls
-
-        item = IntegerParameter(app, "item")
-
-        self.selection = ListParameter(app, "id", item)
-        self.add_parameter(self.selection)
-
-        self.objects = Attribute(app, "objects")
-
-    def init(self):
-        super(SelectionForm, self).init()
-
-        assert self.cls, self
-
-    def do_process(self, session):
-        objects = list()
-        
-        self.objects.set(session, objects)
-
-        conn = self.app.model.get_sql_connection()
-        cursor = conn.cursor()
-
-        try:
-            for id in self.selection.get(session):
-                obj = self.cls.get_object(cursor, id)
-                objects.append(obj)
-        finally:
-            cursor.close()
-
-        super(SelectionForm, self).do_process(session)
-
-class SelectionTaskForm(SelectionForm):
-    def __init__(self, app, name, cls, task):
-        super(SelectionTaskForm, self).__init__(app, name, cls)
-
-        self.cls = cls
-        self.task = task
-
-    def init(self):
-        super(SelectionForm, self).init()
-
-        assert self.task, self
-
-    def process_submit(self, session):
-        objects = self.objects.get(session)
-
-        self.task.invoke(session, objects)
-        self.task.exit_with_redirect(session, objects)
-
-    def render_submit_content(self, session):
-        return self.task.get_title(session)
-
-    def render_title(self, session):
-        return "Confirm"
-
-    def render_content(self, session):
-        objects = self.objects.get(session)
-
-        return "%s?" % self.task.get_description(session, objects)

Modified: mgmt/newdata/cumin/python/cumin/objectframe.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectframe.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/objectframe.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -2,6 +2,7 @@
 from wooly.resources import *
 from wooly.widgets import *
 
+from objecttask import *
 from formats import *
 from util import *
 from widgets import *
@@ -224,7 +225,7 @@
 
             for task in self.frame.summary_tasks:
                 name = task.__class__.__name__
-                link = TaskLink(self.app, name, task, self.object)
+                link = ObjectTaskLink(self.app, name, task, self.object)
 
                 self.add_child(link)
 

Modified: mgmt/newdata/cumin/python/cumin/objectselector.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectselector.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/objectselector.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -4,6 +4,7 @@
 from wooly.widgets import *
 
 from objectframe import *
+from objecttask import *
 from sqladapter import *
 from util import *
 
@@ -24,6 +25,8 @@
 
         self.cls = cls
 
+        self.update_enabled = True
+
         item = IntegerParameter(app, "item")
 
         self.selection = ListParameter(app, "selection", item)
@@ -61,45 +64,38 @@
         col = ObjectAttributeColumn(self.app, attr.name, attr)
         self.add_column(col)
 
-    def add_task(self, task, parameter):
-        link = TaskLink(self.app, task.__class__.__name__, task, parameter)
-
+    def add_task(self, task, attribute):
+        link = ObjectTaskLink(self.app, task.name, task, attribute)
         self.links.add_child(link)
 
-        return link
-
     def add_selection_task(self, task):
-        name = task.__class__.__name__
-        button = TaskButton(self.app, name, task, self.selection)
-
+        button = SelectionTaskButton(self.app, task.name, task, self.selection)
         self.buttons.add_child(button)
 
-        return button
-
-    def add_filter(self, object, this, that=None):
+    def add_filter(self, attribute, this, that=None):
         if not that:
             that = this
 
-        assert isinstance(object, Attribute), object
+        assert isinstance(attribute, Attribute), attribute
         assert isinstance(this, RosemaryAttribute), this
         assert isinstance(that, RosemaryAttribute), that
 
-        self.filter_specs.append((this, that, object))
+        self.filter_specs.append((this, that, attribute))
         self.adapter.add_value_filter(this)
 
-    def add_reference_filter(self, object, ref):
+    def add_reference_filter(self, attribute, ref):
         assert isinstance(ref, RosemaryReference), ref
 
         this = ref
         that = ref.that_cls._id
 
-        self.add_filter(object, this, that)
+        self.add_filter(attribute, this, that)
 
     def get_data_values(self, session):
         values = dict()
 
-        for this, that, object in self.filter_specs:
-            obj = object.get(session)
+        for this, that, fobj in self.filter_specs:
+            obj = fobj.get(session)
 
             values[this.name] = getattr(obj, that.name)
 
@@ -134,11 +130,21 @@
         self.cell = CheckboxColumnCell(app, "cell", selection)
         self.replace_child(self.cell)
 
+        self.cell.input = ObjectCheckboxColumnInput(app, "input", selection)
+        self.cell.replace_child(self.cell.input)
+
         self.width = "1%"
 
     def render_cell_value(self, session, record):
         return record[self.field.index]
 
+class ObjectCheckboxColumnInput(CheckboxColumnInput):
+    def render_onclick_attr(self, session, record):
+        value = "cumin.clickTableCheckbox(this, '%s')" % \
+            self.parent.parent.selection.path
+
+        return "onclick=\"%s\"" % value
+
 class ObjectLinkColumn(ObjectAttributeColumn, LinkColumn):
     def __init__(self, app, name, attr, id_attr, frame_path):
         super(ObjectLinkColumn, self).__init__(app, name, attr)

Modified: mgmt/newdata/cumin/python/cumin/objectselector.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectselector.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/objectselector.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,8 +1,4 @@
 [ObjectSelector.css]
-//div.ObjectSelector form {
-//    clear: both;
-//}
-
 div.ObjectSelectorControl ul {
     list-style: none;
     display: inline;
@@ -60,6 +56,10 @@
 
     <div>{hidden_inputs}</div>
   </form>
+
+  <script type="text/javascript">
+    cumin.restoreTableCheckboxes();
+  </script>
 </div>
 
 [ObjectSelectorControl.html]

Modified: mgmt/newdata/cumin/python/cumin/objecttask.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objecttask.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/objecttask.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,5 +1,365 @@
+from rosemary.model import *
+from wooly.forms import *
+from wooly.resources import *
+from wooly.widgets import *
+
+from main import *
 from util import *
 
-class ObjectTaskLink(object):
-    def __init__(self, app, cls):
+from wooly.widgets import Link
+
+log = logging.getLogger("cumin.objecttask")
+strings = StringCatalog(__file__)
+
+class Task(object):
+    def __init__(self, module, cls, name):
+        assert isinstance(cls, RosemaryClass), cls
+
+        self.app = module.app
+        self.module = module
         self.cls = cls
+        self.name = name
+
+        self.form = None
+
+        assert not hasattr(self.module, self.name), (self.module, self.name)
+
+        self.module.tasks.append(self)
+        setattr(self.module, self.name, self)
+
+    def init(self):
+        log.info("Initializing %s", self)
+
+        assert self.form, self.form
+
+        self.module.app.form_page.modes.add_mode(self.form)
+
+    def get_title(self, session, obj):
+        pass
+
+    def get_description(self, session, obj):
+        return self.get_title(session, obj)
+
+    def get_href(self, session, obj):
+        return self.enter(session, obj).marshal()
+
+    def enter(self, session, obj):
+        nsession = wooly.Session(self.module.app.form_page)
+
+        self.form.return_url.set(nsession, session.marshal())
+        self.form.show(nsession)
+
+        self.do_enter(nsession, obj)
+
+        return nsession
+
+    def exit(self, session, obj):
+        log.debug("Exiting %s", self)
+
+        url = self.form.return_url.get(session)
+        osession = wooly.Session.unmarshal(self.app, url)
+
+        self.do_exit(osession, obj)
+
+        log.info("Exited %s", self)
+
+        return osession
+
+    def do_exit(self, session, obj):
+        pass
+
+    def exit_with_redirect(self, session, obj):
+        osession = self.exit(session, obj)
+        self.form.page.redirect.set(session, osession.marshal())
+
+    def start(self, session, obj):
+        log.debug("Starting %s", self)
+
+        login = session.client_session.attributes["login_session"]
+
+        invoc = TaskInvocation(self, login.user, obj)
+
+        now = datetime.now()
+
+        invoc.start_time = now
+        invoc.last_change_time = now
+        invoc.status = invoc.PENDING
+
+        self.app.model.task_invocations.append(invoc)
+
+        log.info("Started %s", self)
+
+        return invoc
+
+    def do_invoke(self, invoc, obj, *args):
+        pass
+
+    def qmf_call(self, invoc, obj, meth, *args):
+        def completion(status_code, output_args):
+            invoc.status_code = status_code
+            invoc.output_args = output_args
+
+            invoc.end()
+
+        agent = self.app.model.mint.model.agents[obj._qmf_agent_id]
+        agent.call_method(completion, obj, meth, *args)
+
+    def exception(self, invoc, e):
+        now = datetime.now()
+
+        invoc.status = invoc.FAILED
+        invoc.end_time = now
+        invoc.last_change_time = now
+        invoc.exception = e
+
+        log.exception(e)
+
+    def __str__(self):
+        return "%s.%s" % (self.__module__, self.__class__.__name__)
+
+class TaskInvocation(object):
+    PENDING = "pending"
+    FAILED = "failed"
+    OK = "ok"
+
+    def __init__(self, task, user, obj):
+        self.task = task
+        self.user = user
+        self.object = obj
+        self.start_time = None
+        self.end_time = None
+        self.last_change_time = None
+        self.status = None
+        self.exception = None
+
+        self.status_code = None
+        self.output_args = None
+
+        self.results_by_item = dict()
+        self.outstanding_items = set()
+
+    def end(self):
+        log.debug("Ending %s", self.task)
+
+        if self.status_code in (None, 0, "OK"):
+            self.status = self.OK
+        else:
+            self.status = self.FAILED
+
+        now = datetime.now()
+
+        self.end_time = now
+        self.last_change_time = now
+
+        log.info("Ended %s", self.task)
+
+class TaskInvocationSet(ItemSet):
+    def __init__(self, app, name):
+        super(TaskInvocationSet, self).__init__(app, name)
+
+        self.html_class = TaskInvocationSet.__name__
+        self.update_enabled = True
+
+    def do_get_items(self, session):
+        now = secs(datetime.now())
+
+        invocs = sorted_by(self.app.model.task_invocations, "last_change_time")
+        invocs = [x for x in invocs if now - secs(x.last_change_time) < 10]
+
+        return invocs
+
+    def do_render(self, session):
+        items = self.get_items(session)
+
+        if items:
+            return super(TaskInvocationSet, self).do_render(session)
+
+    def render_item_content(self, session, item):
+        description = item.task.get_description(session, item.object)
+        description = xml_escape(description)
+
+        if not description:
+            description = ""
+
+        status = item.status
+        exc = str(item.exception)
+        code = str(item.status_code)
+        outs = str(item.output_args)
+
+        return ": ".join((description, status))
+
+# XXX
+def completion(status_code=0, output_args=()):
+    invoc.results_by_item[item] = (status_code, output_args)
+    invoc.outstanding_items.remove(item)
+
+    if not invoc.outstanding_items:
+        self.end(invoc)
+
+class ObjectTask(Task):
+    def __init__(self, module, cls):
+        name = self.__class__.__name__
+
+        super(ObjectTask, self).__init__(module, cls, name)
+
+        self.form = ObjectTaskForm(self.app, self.name, self)
+
+    def do_enter(self, session, obj):
+        if obj:
+            self.form.id.set(session, obj._id)
+
+    def invoke(self, session, obj, *args):
+        if obj:
+            assert isinstance(obj, RosemaryObject), obj
+
+        invoc = self.start(session, obj)
+
+        try:
+            self.do_invoke(invoc, obj, *args)
+        except Exception, e:
+            self.exception(invoc, e)
+
+class SelectionTask(Task):
+    def __init__(self, item_task):
+        module = item_task.module
+        cls = item_task.cls
+        name = "%s_selection" % item_task.name
+
+        super(SelectionTask, self).__init__(module, cls, name)
+
+        self.item_task = item_task
+        self.item_task.selection_task = self
+
+        self.form = SelectionTaskForm(self.module.app, self.name, self)
+
+    def do_enter(self, session, ids):
+        if ids:
+            self.form.ids.set(session, ids)
+
+    def invoke(self, session, selection, *args):
+        invoc = self.start(session, selection)
+
+        for item in selection:
+            invoc.outstanding_items.add(item)
+
+            self.item_task.do_invoke(invoc, item, *args)
+
+class TaskForm(FoldingFieldSubmitForm):
+    def __init__(self, app, name, task):
+        assert isinstance(task, Task)
+
+        super(TaskForm, self).__init__(app, name)
+
+        self.task = task
+
+class ObjectTaskForm(TaskForm):
+    def __init__(self, app, name, task):
+        super(ObjectTaskForm, self).__init__(app, name, task)
+
+        self.id = IntegerParameter(app, "id")
+        self.add_parameter(self.id)
+
+        self.object = SessionAttribute(self, "object")
+
+    def do_process(self, session):
+        id = self.id.get(session)
+
+        if id:
+            conn = self.app.model.get_sql_connection()
+            cursor = conn.cursor()
+
+            try:
+                obj = self.task.cls.get_object(cursor, id)
+            finally:
+                cursor.close()
+
+            self.object.set(session, obj)
+
+        super(ObjectTaskForm, self).do_process(session)
+
+    def process_submit(self, session):
+        obj = self.object.get(session)
+
+        self.task.invoke(session, obj)
+        self.task.exit_with_redirect(session, obj)
+
+    def render_title(self, session):
+        obj = self.object.get(session)
+        return self.task.get_title(session, obj)
+
+class SelectionTaskForm(TaskForm):
+    def __init__(self, app, name, task):
+        super(SelectionTaskForm, self).__init__(app, name, task)
+
+        item = IntegerParameter(app, "item")
+
+        self.ids = ListParameter(app, "id", item)
+        self.add_parameter(self.ids)
+
+        self.selection = SessionAttribute(self, "selection")
+
+    def do_process(self, session):
+        selection = list()
+        
+        self.selection.set(session, selection)
+
+        conn = self.app.model.get_sql_connection()
+        cursor = conn.cursor()
+
+        try:
+            for id in self.ids.get(session):
+                item = self.task.cls.get_object(cursor, id)
+                selection.append(item)
+        finally:
+            cursor.close()
+
+        super(SelectionTaskForm, self).do_process(session)
+    
+    def process_submit(self, session):
+        selection = self.selection.get(session)
+
+        self.task.invoke(session, selection)
+        self.task.exit_with_redirect(session, selection)
+
+class ObjectTaskLink(Link):
+    def __init__(self, app, name, task, attribute=None):
+        assert isinstance(task, ObjectTask), task
+
+        super(ObjectTaskLink, self).__init__(app, name)
+
+        self.task = task
+        self.attribute = attribute
+
+    def get_object(self, session):
+        if self.attribute:
+            return self.attribute.get(session)
+
+    def render_href(self, session):
+        return self.task.get_href(session, self.get_object(session))
+
+    def render_content(self, session):
+        return self.task.get_title(session, self.get_object(session))
+
+class SelectionTaskButton(FormButton):
+    def __init__(self, app, name, task, attribute=None):
+        assert isinstance(task, ObjectTask), task
+
+        super(SelectionTaskButton, self).__init__(app, name)
+
+        self.task = task
+        self.attribute = attribute
+
+    def get_selection(self, session):
+        if self.attribute:
+            return self.attribute.get(session)
+
+    def process_submit(self, session):
+        selection = self.get_selection(session)
+
+        href = self.task.selection_task.get_href(session, selection)
+
+        self.page.redirect.set(session, href)
+
+    def render_content(self, session):
+        selection = self.get_selection(session)
+        return self.task.get_title(session, selection)

Added: mgmt/newdata/cumin/python/cumin/objecttask.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/objecttask.strings	                        (rev 0)
+++ mgmt/newdata/cumin/python/cumin/objecttask.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -0,0 +1,9 @@
+[TaskInvocationSet.css]
+ul.TaskInvocationSet {
+    background-color: #fe0;
+    padding: 1em 2em;
+    -moz-border-radius: 0.5em;
+    -webkit-border-radius: 0.5em;
+    margin: 0.5em auto 1em auto;
+    width: 80%;
+}

Modified: mgmt/newdata/cumin/python/cumin/parameters.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/parameters.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/parameters.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -55,6 +55,24 @@
     def do_marshal(self, obj):
         return str(obj._id)
 
+class ObjectAttribute(SessionAttribute):
+    def __init__(self, widget, name, cls, id_parameter):
+        super(ObjectAttribute, self).__init__(widget, name)
+
+        self.cls = cls
+        self.id_parameter = id_parameter
+
+    def do_get(self, session):
+        id = self.id_parameter.get(session)
+
+        conn = self.widget.app.model.get_sql_connection()
+        cursor = conn.cursor()
+
+        try:
+            return self.cls.get_object(cursor, id)
+        finally:
+            cursor.close()
+
 class VhostParameter(RosemaryObjectParameter):
     def __init__(self, app, name):
         cls = app.rosemary.org_apache_qpid_broker.Vhost
@@ -111,13 +129,15 @@
         cursor = conn.cursor()
 
         try:
-            kwargs = {"_brokerRef_id": broker._id, "name": "'/'"}
+            kwargs = {"_brokerRef_id": broker._id, "name": "/"}
 
-            for obj in cls.select_objects(cursor, **kwargs):
-                return obj
+            for obj in cls.get_selection(cursor, **kwargs):
+                break
         finally:
             cursor.close()
 
+        return obj
+
 class ConnectionParameter(Parameter):
     def do_unmarshal(self, string):
         return ClientConnection.get(int(string))

Modified: mgmt/newdata/cumin/python/cumin/table.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/table.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/table.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -53,7 +53,7 @@
         return self.table.adapter.get_data(sort, ascending, limit, offset)
 
     def add_task(self, task):
-        link = TaskLink(self.app, task.__class__.__name__, task, None)
+        link = ObjectTaskLink(self.app, task.__class__.__name__, task)
         self.links.add_child(link)
 
     def add_selection_task(self, task):

Modified: mgmt/newdata/cumin/python/cumin/usergrid/main.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/usergrid/main.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/usergrid/main.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,19 +1,13 @@
-from wooly import *
-from wooly.widgets import *
-
-from cumin.widgets import *
+from cumin import *
 from cumin.util import *
-from cumin.grid.submission import *
 
-from wooly.widgets import Link
-
 from widgets import *
 
 strings = StringCatalog(__file__)
 
-class UserGridModule(CuminModule):
-    def init(self, app):
-        app.user_grid_page = MainPage(app, "usergrid.html")
-        app.add_page(app.user_grid_page)
+class Module(CuminModule):
+    def init(self):
+        super(Module, self).init()
 
-module = UserGridModule()
+        self.app.user_grid_page = MainPage(self.app, "usergrid.html")
+        self.app.add_page(self.app.user_grid_page)

Modified: mgmt/newdata/cumin/python/cumin/usergrid/widgets.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/usergrid/widgets.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/usergrid/widgets.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -65,8 +65,8 @@
     def __init__(self, app, name, user):
         super(SubmissionsFrame, self).__init__(app, name)
 
-        self.view = UserSubmissionSet(app, "view", user)
-        self.add_mode(self.view)
+        #self.view = UserSubmissionSet(app, "view", user)
+        #self.add_mode(self.view)
 
         self.submission = SubmissionFrame(app, "submission")
         self.add_mode(self.submission)
@@ -74,30 +74,30 @@
     def render_title(self, session):
         return "Submissions"
 
-class UserSubmissionSet(SubmissionSet):
-    def __init__(self, app, name, user):
-        super(UserSubmissionSet, self).__init__(app, name)
+# class UserSubmissionSet(SubmissionSet):
+#     def __init__(self, app, name, user):
+#         super(UserSubmissionSet, self).__init__(app, name)
 
-        self.user = user
+#         self.user = user
 
-        self.scheduler_col.visible = False
-        self.submitter_col.visible = False
+#         self.scheduler_col.visible = False
+#         self.submitter_col.visible = False
 
-        task = cumin.grid.module.submission_add
-        link = TaskLink(app, "add", task, None)
-        self.links.add_child(link)
+#         task = app.grid.SubmissionAdd
+#         link = TaskLink(app, "add", task, None)
+#         self.links.add_child(link)
 
-    def get_submission_href(self, session, id):
-        submission = Identifiable(id)
-        return self.page.main.submissions.submission.get_href \
-            (session, submission)
+#     def get_submission_href(self, session, id):
+#         submission = Identifiable(id)
+#         return self.page.main.submissions.submission.get_href \
+#             (session, submission)
 
-    def render_sql_where(self, session):
-        pass # XXX return "where m.name = %(name)s"
+#     def render_sql_where(self, session):
+#         pass # XXX return "where m.name = %(name)s"
 
-    def get_sql_values(self, session):
-        user = self.page.user.get(session)
-        return {"name": user.name}
+#     def get_sql_values(self, session):
+#         user = self.page.user.get(session)
+#         return {"name": user.name}
 
 class UserJobStatSet(NewStatSet):
     def __init__(self, app, name, user):

Modified: mgmt/newdata/cumin/python/cumin/util.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/util.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/util.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -9,8 +9,12 @@
 from random import sample
 from threading import Thread, Event
 from time import mktime, time, sleep
-from xml.sax.saxutils import escape as xml_escape
+from xml.sax.saxutils import escape as do_xml_escape
 
+def xml_escape(string):
+    if string:
+        return do_xml_escape(string)
+
 def short_id():
     return "%08x" % randint(0, sys.maxint)
 
@@ -192,10 +196,3 @@
         rows.append(row)
 
     return rows
-
-class CuminModule(object):
-    def init(self, app):
-        pass
-
-    def init_test(self, test):
-        pass

Modified: mgmt/newdata/cumin/python/cumin/widgets.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/widgets.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/widgets.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -8,6 +8,7 @@
 from mint.schema import *
 
 from action import *
+from objecttask import *
 from parameters import *
 from widgets import *
 from charts import *
@@ -116,7 +117,7 @@
         #    pages.append(self.app.main_page)
 
         pages.append(self.app.main_page)
-        pages.append(self.app.user_grid_page)
+        #pages.append(self.app.user_grid_page) XXX
         pages.append(self.app.account_page)
 
         return pages
@@ -1337,6 +1338,13 @@
 class Wait(Widget):
     pass
 
+class LoginSession(object):
+    def __init__(self, app, user):
+        self.app = app
+        self.user = user
+
+        self.created = datetime.now()
+
 class CuminPage(HtmlPage):
     def __init__(self, app, name):
         super(CuminPage, self).__init__(app, name)
@@ -1347,6 +1355,9 @@
         self.add_attribute(self.user)
 
     def do_process(self, session):
+        conn = self.app.model.get_sql_connection()
+        setattr(session, "cursor", conn.cursor())
+
         if self.authorized(session):
             super(CuminPage, self).do_process(session)
 
@@ -1364,10 +1375,18 @@
         elif self.app.config.user:
             user = Subject.getByName(self.app.config.user)
 
+            # cls = self.app.rosemary.com_redhat_cumin.User
+            # name_literal = "'%s'" % self.app.config.user
+            # user = None
+
+            # for obj in cls.get_selection(session.cursor, name=name_literal):
+            #     user = obj
+            #     break
+
             if user is None:
                 raise Exception("User '%s' not found" % self.app.config.user)
 
-            login = cumin.account.model.LoginSession(self.app, user)
+            login = LoginSession(self.app, user)
             session.client_session.attributes["login_session"] = login
 
             return True
@@ -1453,91 +1472,6 @@
         writer.write(data)
         writer.write("</data>")
 
-# XXX for later consideration
-class CuminClassTable(CuminSelectionTable):
-    def __init__(self, app, name, cumin_class):
-        super(CuminClassTable, self).__init__(app, name)
-
-        self.cumin_class = cumin_class
-
-        tasks = [x for x in self.cumin_class.tasks if x.aggregate]
-
-        for task in tasks:
-            button = TaskButton(app, action.name, task, self.selection)
-            self.buttons.add_child(button)
-
-    def render_title(self, session, *args):
-        title = self.cumin_class.get_plural_title(session)
-        count = fmt_count(self.cumin_class.mint_class.select().count())
-
-        return "%s %s" % (title, count)
-
-class TaskLink(Link):
-    def __init__(self, app, name, task, param):
-        super(TaskLink, self).__init__(app, name)
-
-        self.task = task
-        self.param = param
-
-    def get(self, session):
-        if self.param:
-            return self.param.get(session)
-
-    def render_href(self, session):
-        return self.task.get_href(session, self.get(session))
-
-    def render_content(self, session):
-        return self.task.get_title(session)
-
-class TaskButton(FormButton):
-    def __init__(self, app, name, task, set_param):
-        super(TaskButton, self).__init__(app, name)
-
-        self.task = task
-        self.set_param = set_param
-
-    def process_submit(self, session):
-        items = self.set_param.get(session)
-
-        href = self.task.get_href(session, items)
-        self.page.redirect.set(session, href)
-
-    def render_content(self, session):
-        return self.task.get_title(session)
-
-class TaskInvocationSet(ItemSet):
-    def __init__(self, app, name):
-        super(TaskInvocationSet, self).__init__(app, name)
-
-        self.html_class = TaskInvocationSet.__name__
-        self.update_enabled = True
-
-    def do_get_items(self, session):
-        now = secs(datetime.now())
-
-        invocs = sorted_by(self.app.model.task_invocations, "last_change_time")
-        invocs = [x for x in invocs if now - secs(x.last_change_time) < 10]
-
-        return invocs
-
-    def do_render(self, session):
-        items = self.get_items(session)
-
-        if items:
-            return super(TaskInvocationSet, self).do_render(session)
-
-    def render_item_content(self, session, item):
-        description = xml_escape \
-            (item.task.get_description(session, item.object))
-        status = item.status
-        exc = str(item.exception)
-        code = str(item.status_code)
-        outs = str(item.output_args)
-
-        return ": ".join((description, status))
-
-import cumin.account.model
-
 class IncrementalSearchInput(StringInput, ItemSet):
     def do_get_items(self, session):
         return ()

Modified: mgmt/newdata/cumin/python/cumin/widgets.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/widgets.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/python/cumin/widgets.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -843,57 +843,6 @@
     background-color: #fff;
 }
 
-[CuminClassTable.css]
-.CuminClassTable div.addlink {
-  margin: 0 0 1em 0;
-}
-
-.CuminClassTable ul.actions {
-  margin: 0;
-  display: inline;
-}
-
-.CuminClassTable ul.actions li {
-  display: inline;
-}
-
-[CuminClassTable.html]
-<form class="CuminClassTable" id="{id}" method="post" action="?">
-  <div class="addlink">{add_link}</div>
-
-  {switches}
-
-  {filters}
-
-  <div class="sactions">Act on Selected {plural_title}: {actions}</div>
-
-  <table class="mobjects">
-    {columns}
-    <thead>
-      <tr>
-        <th class="setnav" colspan="{column_count}">
-          <div class="rfloat">{page}</div>
-          {count}
-        </th>
-      </tr>
-      <tr>{headers}</tr>
-    </thead>
-    <tbody>{items}</tbody>
-  </table>
-
-  <div>{hidden_inputs}</div>
-</form>
-
-[TaskInvocationSet.css]
-ul.TaskInvocationSet {
-    background-color: #fe0;
-    padding: 1em 2em;
-    -moz-border-radius: 0.5em;
-    -webkit-border-radius: 0.5em;
-    margin: 0.5em auto 1em auto;
-    width: 80%;
-}
-
 [IncrementalSearchInput.css]
 div.IncrementalSearchInput ul {
     display: none;

Modified: mgmt/newdata/cumin/resources/app.css
===================================================================
--- mgmt/newdata/cumin/resources/app.css	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/cumin/resources/app.css	2010-03-31 17:45:43 UTC (rev 3886)
@@ -609,7 +609,7 @@
     font-size: 0.9em;
 }
 
-a.TaskLink.Cumin:before {
+a.ObjectTaskLink.Cumin:before {
     content: "\00BB \0020";
     font-weight: bold;
     color: #dc9f2e;

Modified: mgmt/newdata/mint/python/mint/demo.py
===================================================================
--- mgmt/newdata/mint/python/mint/demo.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/mint/python/mint/demo.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -12,15 +12,10 @@
 
         try:
             for name in ("Engineering", "Marketing", "Sales"):
-                group = cls.create_object()
+                group = cls.create_object(cursor)
                 group.name = name
 
-                # XXX ugh
-                group._qmf_agent_id = "cumin"
-                group._qmf_object_id = str(datetime.now())
-                group._qmf_create_time = datetime.now()
-                group._qmf_update_time = datetime.now()
-                group._qmf_class_key = "cumin"
+                group.fake_qmf_values()
 
                 group.save(cursor)
         finally:

Modified: mgmt/newdata/mint/python/mint/model.py
===================================================================
--- mgmt/newdata/mint/python/mint/model.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/mint/python/mint/model.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -23,6 +23,8 @@
         mint.schema.model = self
 
         self.rosemary = RosemaryModel()
+        self.rosemary.sql_logging_enabled = True
+
         self.qmf_session = None
         self.qmf_brokers = list()
 
@@ -99,7 +101,7 @@
         finally:
             self.model.lock.release()
 
-    def call_method(self, obj, name, callback, args):
+    def call_method(self, callback, obj, name, *args):
         assert isinstance(obj, RosemaryObject)
         
         class_key = ClassKey(obj._qmf_class_key)

Modified: mgmt/newdata/mint/python/mint/newupdate.py
===================================================================
--- mgmt/newdata/mint/python/mint/newupdate.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/mint/python/mint/newupdate.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -120,7 +120,7 @@
 
         update_time, create_time, delete_time = self.object.getTimestamps()
 
-        if obj._id:
+        if obj._sync_time:
             # This object is already in the database
 
             obj._qmf_update_time = self.update_time
@@ -135,6 +135,7 @@
             obj._qmf_update_time = self.update_time
             obj._qmf_create_time = self.create_time
 
+            columns.append(cls.sql_table._id)
             columns.append(cls.sql_table._qmf_agent_id)
             columns.append(cls.sql_table._qmf_object_id)
             columns.append(cls.sql_table._qmf_session_id)
@@ -178,18 +179,18 @@
         try:
             return self.agent.objects_by_id[object_id]
         except KeyError:
-            obj = cls.create_object()
+            conn = self.model.app.database.get_connection()
+            cursor = conn.cursor()
+
+            obj = RosemaryObject(cls, None)
             obj._qmf_agent_id = self.agent.id
             obj._qmf_object_id = object_id
 
-            conn = self.model.app.database.get_connection()
-            cursor = conn.cursor()
-
             try:
                 try:
-                    cls.load_object(cursor, obj)
+                    cls.load_object_by_qmf_id(cursor, obj)
                 except RosemaryNotFound:
-                    pass
+                    obj._id = cls.get_new_id(cursor)
             finally:
                 cursor.close()
 
@@ -220,7 +221,7 @@
                 that_id = str(QmfObjectId(value.first, value.second))
                 that = self.get_object(ref.that_cls, that_id)
 
-                if not that._id:
+                if not that._sync_time:
                     continue
 
                 value = that._id
@@ -303,7 +304,7 @@
         if not cls._statistics:
             stats.samples_dropped += 1; return
 
-        if not obj._id:
+        if not obj._sync_time:
             stats.samples_dropped += 1; return
 
         if stats.enqueued - stats.dequeued > 100:
@@ -323,7 +324,8 @@
         cursor = conn.cursor()
 
         try:
-            cls.sql_update.execute(cursor, update_columns, obj.__dict__)
+            obj.save(cursor, update_columns)
+
             cls.sql_samples_insert.execute \
                 (cursor, insert_columns, obj.__dict__)
         finally:

Modified: mgmt/newdata/mint/python/mint/tools.py
===================================================================
--- mgmt/newdata/mint/python/mint/tools.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/mint/python/mint/tools.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -85,6 +85,22 @@
         self.init()
         self.run()
 
+class DatabaseSubcommand(Command):
+    def run(self, opts, args):
+        conn = self.parent.database.get_connection()
+        cursor = conn.cursor()
+
+        try:
+            self.do_run(cursor, opts, args)
+
+            conn.commit()
+        finally:
+            cursor.close()
+            conn.close()
+
+    def do_run(self, cursor, opts, args):
+        raise Exception("Not implemented")
+
 class MintAdminTool(BaseMintTool):
     def __init__(self, name):
         super(MintAdminTool, self).__init__(name)
@@ -159,6 +175,8 @@
         app.update_enabled = False
         app.expire_enabled = False
 
+        #self.cumin = app.model.rosemary.com_redhat_cumin
+
         self.database = MintDatabase(app)
         self.database.check()
         self.database.init()
@@ -222,13 +240,16 @@
         def run(self, opts, args):
             self.parent.database.check_schema()
 
-    class AddUser(Command):
-        def run(self, opts, args):
+    class AddUser(DatabaseSubcommand):
+        def do_run(self, cursor, opts, args):
             try:
                 name = args[1]
             except IndexError:
                 raise CommandException(self, "NAME is required")
 
+            #objs = self.parent.cumin.User.get_selection(cursor, name=name)
+            #if objs:
+
             if Subject.selectBy(name=name).count():
                 print "Error: a user called '%s' already exists" % name
                 sys.exit(1)
@@ -245,11 +266,29 @@
 
                 for role in Role.selectBy(name="user"):
                     subject.addRole(role)
-                    break
 
                 assert role
 
                 subject.syncUpdate()
+
+                # user = self.parent.cumin.User.create_object(cursor)
+                # user.name = name
+                # user.password = crypted
+                # user.save(cursor)
+
+                # roles = self.parent.cumin.Role.get_selection \
+                #     (cursor, name="user")
+
+                # for role in roles:
+                #     mapping = self.parent.cumin.UserRoleMapping.create_object \
+                #         (cursor)
+                #     mapping.user = user
+                #     mapping.role = role
+                #     mapping.save(cursor)
+
+                #     break
+
+                assert role, self
             except IntegrityError:
                 print "Error: a user called '%s' already exists" % name
                 sys.exit(1)

Modified: mgmt/newdata/mint/sql/rosemary.sql
===================================================================
--- mgmt/newdata/mint/sql/rosemary.sql	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/mint/sql/rosemary.sql	2010-03-31 17:45:43 UTC (rev 3886)
@@ -1,6 +1,14 @@
+drop schema "org.apache.qpid.cluster" cascade;
+drop schema "org.apache.qpid.broker" cascade;
+drop schema "com.redhat.sesame" cascade;
+drop schema "org.apache.qpid.acl" cascade;
+drop schema "com.redhat.cumin" cascade;
+drop schema "com.redhat.rhm.store" cascade;
+drop schema "mrg.grid" cascade;
 create schema "org.apache.qpid.cluster"
+    create sequence "Cluster_id_seq"
     create table "Cluster" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -18,18 +26,29 @@
         "members" text not null,
         "memberIDs" text not null,
         constraint "Cluster_pk" primary key ("_id"),
-        constraint "Cluster_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Cluster_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Cluster_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "Cluster_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     ;
 create schema "org.apache.qpid.broker"
+    create sequence "System_id_seq"
+    create sequence "Broker_id_seq"
+    create sequence "Agent_id_seq"
+    create sequence "Vhost_id_seq"
+    create sequence "Queue_id_seq"
+    create sequence "Exchange_id_seq"
+    create sequence "Binding_id_seq"
+    create sequence "Subscription_id_seq"
+    create sequence "Connection_id_seq"
+    create sequence "Link_id_seq"
+    create sequence "Bridge_id_seq"
+    create sequence "Session_id_seq"
+    create sequence "ManagementSetupState_id_seq"
     create table "System" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -44,16 +63,14 @@
         "version" text not null,
         "machine" text not null,
         constraint "System_pk" primary key ("_id"),
-        constraint "System_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "System_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "System_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "System_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "Broker" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -72,17 +89,15 @@
         "dataDir" text,
         "uptime" numeric(19),
         constraint "Broker_pk" primary key ("_id"),
-        constraint "Broker_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Broker_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Broker_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
-        "uptime" numeric(19) not null,
-        constraint "Broker_samples_pk" primary key ("_id")
+        "uptime" numeric(19) not null
         )
     create table "Agent" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -97,16 +112,14 @@
         "brokerBank" int8 not null,
         "agentBank" int8 not null,
         constraint "Agent_pk" primary key ("_id"),
-        constraint "Agent_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Agent_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Agent_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "Agent_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "Vhost" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -118,16 +131,14 @@
         "name" text not null,
         "federationTag" text not null,
         constraint "Vhost_pk" primary key ("_id"),
-        constraint "Vhost_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Vhost_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Vhost_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "Vhost_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "Queue" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -161,10 +172,9 @@
         "unackedMessages" int8,
         "messageLatency" numeric(19),
         constraint "Queue_pk" primary key ("_id"),
-        constraint "Queue_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Queue_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Queue_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "msgTotalEnqueues" numeric(19) not null,
@@ -184,11 +194,10 @@
         "consumerCount" int8 not null,
         "bindingCount" int8 not null,
         "unackedMessages" int8 not null,
-        "messageLatency" numeric(19),
-        constraint "Queue_samples_pk" primary key ("_id")
+        "messageLatency" numeric(19)
         )
     create table "Exchange" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -212,10 +221,9 @@
         "byteDrops" numeric(19),
         "byteRoutes" numeric(19),
         constraint "Exchange_pk" primary key ("_id"),
-        constraint "Exchange_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Exchange_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Exchange_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "producerCount" int8 not null,
@@ -225,11 +233,10 @@
         "msgRoutes" numeric(19) not null,
         "byteReceives" numeric(19) not null,
         "byteDrops" numeric(19) not null,
-        "byteRoutes" numeric(19) not null,
-        constraint "Exchange_samples_pk" primary key ("_id")
+        "byteRoutes" numeric(19) not null
         )
     create table "Binding" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -244,17 +251,15 @@
         "origin" text,
         "msgMatched" numeric(19),
         constraint "Binding_pk" primary key ("_id"),
-        constraint "Binding_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Binding_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Binding_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
-        "msgMatched" numeric(19) not null,
-        constraint "Binding_samples_pk" primary key ("_id")
+        "msgMatched" numeric(19) not null
         )
     create table "Subscription" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -272,17 +277,15 @@
         "arguments" text not null,
         "delivered" numeric(19),
         constraint "Subscription_pk" primary key ("_id"),
-        constraint "Subscription_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Subscription_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Subscription_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
-        "delivered" numeric(19) not null,
-        constraint "Subscription_samples_pk" primary key ("_id")
+        "delivered" numeric(19) not null
         )
     create table "Connection" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -306,21 +309,19 @@
         "bytesFromClient" numeric(19),
         "bytesToClient" numeric(19),
         constraint "Connection_pk" primary key ("_id"),
-        constraint "Connection_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Connection_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Connection_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "closing" bool not null,
         "framesFromClient" numeric(19) not null,
         "framesToClient" numeric(19) not null,
         "bytesFromClient" numeric(19) not null,
-        "bytesToClient" numeric(19) not null,
-        constraint "Connection_samples_pk" primary key ("_id")
+        "bytesToClient" numeric(19) not null
         )
     create table "Link" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -336,18 +337,16 @@
         "state" text,
         "lastError" text,
         constraint "Link_pk" primary key ("_id"),
-        constraint "Link_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Link_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Link_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "state" text not null,
-        "lastError" text not null,
-        constraint "Link_samples_pk" primary key ("_id")
+        "lastError" text not null
         )
     create table "Bridge" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -368,16 +367,14 @@
         "dynamic" bool not null,
         "sync" int4 not null,
         constraint "Bridge_pk" primary key ("_id"),
-        constraint "Bridge_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Bridge_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Bridge_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "Bridge_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "Session" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -400,10 +397,9 @@
         "TxnCount" int8,
         "clientCredit" int8,
         constraint "Session_pk" primary key ("_id"),
-        constraint "Session_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Session_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Session_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "framesOutstanding" int8 not null,
@@ -411,11 +407,10 @@
         "TxnCommits" numeric(19) not null,
         "TxnRejects" numeric(19) not null,
         "TxnCount" int8 not null,
-        "clientCredit" int8 not null,
-        constraint "Session_samples_pk" primary key ("_id")
+        "clientCredit" int8 not null
         )
     create table "ManagementSetupState" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -426,18 +421,17 @@
         "objectNum" numeric(19) not null,
         "bootSequence" int4 not null,
         constraint "ManagementSetupState_pk" primary key ("_id"),
-        constraint "ManagementSetupState_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "ManagementSetupState_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "ManagementSetupState_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "ManagementSetupState_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     ;
 create schema "com.redhat.sesame"
+    create sequence "Sysimage_id_seq"
     create table "Sysimage" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -462,10 +456,9 @@
         "procTotal" int8,
         "procRunning" int8,
         constraint "Sysimage_pk" primary key ("_id"),
-        constraint "Sysimage_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Sysimage_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Sysimage_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "memFree" int8 not null,
@@ -474,13 +467,13 @@
         "loadAverage5Min" float4 not null,
         "loadAverage10Min" float4 not null,
         "procTotal" int8 not null,
-        "procRunning" int8 not null,
-        constraint "Sysimage_samples_pk" primary key ("_id")
+        "procRunning" int8 not null
         )
     ;
 create schema "org.apache.qpid.acl"
+    create sequence "Acl_id_seq"
     create table "Acl" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -495,19 +488,22 @@
         "lastAclLoad" timestamp not null,
         "aclDenyCount" numeric(19),
         constraint "Acl_pk" primary key ("_id"),
-        constraint "Acl_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Acl_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Acl_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
-        "aclDenyCount" numeric(19) not null,
-        constraint "Acl_samples_pk" primary key ("_id")
+        "aclDenyCount" numeric(19) not null
         )
     ;
 create schema "com.redhat.cumin"
+    create sequence "BrokerGroup_id_seq"
+    create sequence "BrokerGroupMapping_id_seq"
+    create sequence "User_id_seq"
+    create sequence "Role_id_seq"
+    create sequence "UserRoleMapping_id_seq"
     create table "BrokerGroup" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -518,16 +514,14 @@
         "name" text not null,
         "description" text,
         constraint "BrokerGroup_pk" primary key ("_id"),
-        constraint "BrokerGroup_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "BrokerGroup_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "BrokerGroup_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "BrokerGroup_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "BrokerGroupMapping" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -538,18 +532,70 @@
         "_broker_id" int8,
         "_group_id" int8,
         constraint "BrokerGroupMapping_pk" primary key ("_id"),
-        constraint "BrokerGroupMapping_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "BrokerGroupMapping_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "BrokerGroupMapping_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
+        "_qmf_update_time" timestamp not null
+        )
+    create table "User" (
+        "_id" int8 not null,
+        "_qmf_agent_id" text not null,
+        "_qmf_object_id" text not null,
+        "_qmf_session_id" text,
+        "_qmf_class_key" text not null,
+        "_qmf_create_time" timestamp not null,
         "_qmf_update_time" timestamp not null,
-        constraint "BrokerGroupMapping_samples_pk" primary key ("_id")
+        "_qmf_delete_time" timestamp,
+        "name" text not null,
+        constraint "User_pk" primary key ("_id"),
+        constraint "User_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
+    create table "User_samples" (
+        "_parent_id" int8 not null,
+        "_qmf_update_time" timestamp not null
+        )
+    create table "Role" (
+        "_id" int8 not null,
+        "_qmf_agent_id" text not null,
+        "_qmf_object_id" text not null,
+        "_qmf_session_id" text,
+        "_qmf_class_key" text not null,
+        "_qmf_create_time" timestamp not null,
+        "_qmf_update_time" timestamp not null,
+        "_qmf_delete_time" timestamp,
+        "name" text not null,
+        constraint "Role_pk" primary key ("_id"),
+        constraint "Role_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
+        )
+    create table "Role_samples" (
+        "_parent_id" int8 not null,
+        "_qmf_update_time" timestamp not null
+        )
+    create table "UserRoleMapping" (
+        "_id" int8 not null,
+        "_qmf_agent_id" text not null,
+        "_qmf_object_id" text not null,
+        "_qmf_session_id" text,
+        "_qmf_class_key" text not null,
+        "_qmf_create_time" timestamp not null,
+        "_qmf_update_time" timestamp not null,
+        "_qmf_delete_time" timestamp,
+        "_user_id" int8,
+        "_role_id" int8,
+        constraint "UserRoleMapping_pk" primary key ("_id"),
+        constraint "UserRoleMapping_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
+        )
+    create table "UserRoleMapping_samples" (
+        "_parent_id" int8 not null,
+        "_qmf_update_time" timestamp not null
+        )
     ;
 create schema "com.redhat.rhm.store"
+    create sequence "Store_id_seq"
+    create sequence "Journal_id_seq"
     create table "Store" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -574,21 +620,19 @@
         "tplTxnAborts" numeric(19),
         "tplOutstandingAIOs" int8,
         constraint "Store_pk" primary key ("_id"),
-        constraint "Store_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Store_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Store_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "tplTransactionDepth" int8 not null,
         "tplTxnPrepares" numeric(19) not null,
         "tplTxnCommits" numeric(19) not null,
         "tplTxnAborts" numeric(19) not null,
-        "tplOutstandingAIOs" int8 not null,
-        constraint "Store_samples_pk" primary key ("_id")
+        "tplOutstandingAIOs" int8 not null
         )
     create table "Journal" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -627,10 +671,9 @@
         "writePageCacheDepth" int8,
         "readPageCacheDepth" int8,
         constraint "Journal_pk" primary key ("_id"),
-        constraint "Journal_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Journal_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Journal_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "recordDepth" int8 not null,
@@ -649,13 +692,20 @@
         "readRecordCount" numeric(19) not null,
         "readBusyFailures" numeric(19) not null,
         "writePageCacheDepth" int8 not null,
-        "readPageCacheDepth" int8 not null,
-        constraint "Journal_samples_pk" primary key ("_id")
+        "readPageCacheDepth" int8 not null
         )
     ;
 create schema "mrg.grid"
+    create sequence "Slot_id_seq"
+    create sequence "Scheduler_id_seq"
+    create sequence "Submitter_id_seq"
+    create sequence "Negotiator_id_seq"
+    create sequence "Collector_id_seq"
+    create sequence "Master_id_seq"
+    create sequence "Grid_id_seq"
+    create sequence "Submission_id_seq"
     create table "Slot" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -745,10 +795,9 @@
         "TotalTimeUnclaimedBenchmarking" int8,
         "TotalTimeUnclaimedIdle" int8,
         constraint "Slot_pk" primary key ("_id"),
-        constraint "Slot_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Slot_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Slot_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "ClockDay" int8 not null,
@@ -773,11 +822,10 @@
         "TotalTimePreemptingKilling" int8 not null,
         "TotalTimePreemptingVacating" int8 not null,
         "TotalTimeUnclaimedBenchmarking" int8 not null,
-        "TotalTimeUnclaimedIdle" int8 not null,
-        constraint "Slot_samples_pk" primary key ("_id")
+        "TotalTimeUnclaimedIdle" int8 not null
         )
     create table "Scheduler" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -799,10 +847,9 @@
         "TotalRemovedJobs" int8,
         "TotalRunningJobs" int8,
         constraint "Scheduler_pk" primary key ("_id"),
-        constraint "Scheduler_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Scheduler_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Scheduler_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "NumUsers" int8 not null,
@@ -810,11 +857,10 @@
         "TotalIdleJobs" int8 not null,
         "TotalJobAds" int8 not null,
         "TotalRemovedJobs" int8 not null,
-        "TotalRunningJobs" int8 not null,
-        constraint "Scheduler_samples_pk" primary key ("_id")
+        "TotalRunningJobs" int8 not null
         )
     create table "Submitter" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -831,19 +877,17 @@
         "IdleJobs" int8,
         "RunningJobs" int8,
         constraint "Submitter_pk" primary key ("_id"),
-        constraint "Submitter_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Submitter_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Submitter_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "HeldJobs" int8 not null,
         "IdleJobs" int8 not null,
-        "RunningJobs" int8 not null,
-        constraint "Submitter_samples_pk" primary key ("_id")
+        "RunningJobs" int8 not null
         )
     create table "Negotiator" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -857,16 +901,14 @@
         "Machine" text not null,
         "MyAddress" text not null,
         constraint "Negotiator_pk" primary key ("_id"),
-        constraint "Negotiator_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Negotiator_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Negotiator_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "Negotiator_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "Collector" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -887,10 +929,9 @@
         "HostsUnclaimed" int8,
         "HostsOwner" int8,
         constraint "Collector_pk" primary key ("_id"),
-        constraint "Collector_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Collector_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Collector_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "RunningJobs" int8 not null,
@@ -898,11 +939,10 @@
         "HostsTotal" int8 not null,
         "HostsClaimed" int8 not null,
         "HostsUnclaimed" int8 not null,
-        "HostsOwner" int8 not null,
-        constraint "Collector_samples_pk" primary key ("_id")
+        "HostsOwner" int8 not null
         )
     create table "Master" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -917,16 +957,14 @@
         "MyAddress" text not null,
         "RealUid" int4 not null,
         constraint "Master_pk" primary key ("_id"),
-        constraint "Master_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Master_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Master_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
-        "_qmf_update_time" timestamp not null,
-        constraint "Master_samples_pk" primary key ("_id")
+        "_qmf_update_time" timestamp not null
         )
     create table "Grid" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -949,10 +987,9 @@
         "RunningJobs" int8,
         "IdleJobs" int8,
         constraint "Grid_pk" primary key ("_id"),
-        constraint "Grid_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Grid_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Grid_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "NumJobs" int8 not null,
@@ -961,11 +998,10 @@
         "SubmitsAllowed" int8 not null,
         "SubmitsWanted" int8 not null,
         "RunningJobs" int8 not null,
-        "IdleJobs" int8 not null,
-        constraint "Grid_samples_pk" primary key ("_id")
+        "IdleJobs" int8 not null
         )
     create table "Submission" (
-        "_id" serial8 not null,
+        "_id" int8 not null,
         "_qmf_agent_id" text not null,
         "_qmf_object_id" text not null,
         "_qmf_session_id" text,
@@ -982,18 +1018,16 @@
         "Completed" int8,
         "Held" int8,
         constraint "Submission_pk" primary key ("_id"),
-        constraint "Submission_qmf_ids_uq" unique ("_qmf_agent_id", "_qmf_object_id")
+        constraint "Submission_qmf_id_uq" unique ("_qmf_agent_id", "_qmf_object_id", "_qmf_session_id")
         )
     create table "Submission_samples" (
-        "_id" serial8 not null,
         "_parent_id" int8 not null,
         "_qmf_update_time" timestamp not null,
         "Idle" int8 not null,
         "Running" int8 not null,
         "Removed" int8 not null,
         "Completed" int8 not null,
-        "Held" int8 not null,
-        constraint "Submission_samples_pk" primary key ("_id")
+        "Held" int8 not null
         )
     ;
 alter table "org.apache.qpid.cluster"."Cluster"
@@ -1099,6 +1133,19 @@
 alter table "com.redhat.cumin"."BrokerGroupMapping_samples"
     add constraint "_parent_id_fk" foreign key ("_parent_id") references "com.redhat.cumin"."BrokerGroupMapping" ("_id") on update cascade on delete cascade
     ;
+alter table "com.redhat.cumin"."User_samples"
+    add constraint "_parent_id_fk" foreign key ("_parent_id") references "com.redhat.cumin"."User" ("_id") on update cascade on delete cascade
+    ;
+alter table "com.redhat.cumin"."Role_samples"
+    add constraint "_parent_id_fk" foreign key ("_parent_id") references "com.redhat.cumin"."Role" ("_id") on update cascade on delete cascade
+    ;
+alter table "com.redhat.cumin"."UserRoleMapping"
+    add constraint "_user_id_fk" foreign key ("_user_id") references "com.redhat.cumin"."User" ("_id") on update cascade on delete set null,
+    add constraint "_role_id_fk" foreign key ("_role_id") references "com.redhat.cumin"."Role" ("_id") on update cascade on delete set null
+    ;
+alter table "com.redhat.cumin"."UserRoleMapping_samples"
+    add constraint "_parent_id_fk" foreign key ("_parent_id") references "com.redhat.cumin"."UserRoleMapping" ("_id") on update cascade on delete cascade
+    ;
 alter table "com.redhat.rhm.store"."Store"
     add constraint "_brokerRef_id_fk" foreign key ("_brokerRef_id") references "org.apache.qpid.broker"."Broker" ("_id") on update cascade on delete set null
     ;

Modified: mgmt/newdata/misc/boneyard.py
===================================================================
--- mgmt/newdata/misc/boneyard.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/misc/boneyard.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -246,3 +246,64 @@
                 value = p.value
 
     return value
+
+class SessionSet(CuminSelectionTable):
+    def __init__(self, app, name, conn):
+        item = SessionParameter(app, "item")
+        super(SessionSet, self).__init__(app, name, item)
+
+        self.conn = conn
+
+        col = self.NameColumn(app, "name")
+        self.add_column(col)
+        self.set_default_column(col)
+
+        col = self.ExpiresColumn(app, "expires")
+        self.add_column(col)
+
+        col = self.StatusColumn(app, "attached")
+        self.add_column(col)
+
+        self.__phase = PhaseSwitch(app, "phase")
+        self.add_child(self.__phase)
+
+        task = main.module.session_set_detach
+        self.buttons.add_child(TaskButton(app, "detach", task, self.selection))
+
+        task = main.module.session_set_close
+        self.buttons.add_child(TaskButton(app, "close", task, self.selection))
+
+    def render_title(self, session):
+        conn = self.conn.get(session)
+        return "Sessions %s" % fmt_count(conn.sessions.count())
+
+    def render_sql_where(self, session):
+        conn = self.conn.get(session)
+
+        elems = list()
+        elems.append("s.client_connection_id = %(id)r")
+        elems.append(self.__phase.get_sql_constraint(session, conn))
+
+        return "where %s" % " and ".join(elems)
+
+    def get_sql_values(self, session):
+        conn = self.conn.get(session)
+        return {"id": conn.id}
+
+    class NameColumn(SqlTableColumn):
+        def render_title(self, session):
+            return "Name"
+
+    class ExpiresColumn(SqlTableColumn):
+        def render_title(self, session):
+            return "Expires"
+
+        def render_value(self, session, value):
+            return fmt_datetime(value)
+
+    class StatusColumn(SqlTableColumn):
+        def render_title(self, session):
+            return "Attached?"
+
+        def render_content(self, session, data):
+            return fmt_predicate(data["attached"])

Modified: mgmt/newdata/rosemary/python/rosemary/model.py
===================================================================
--- mgmt/newdata/rosemary/python/rosemary/model.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/rosemary/python/rosemary/model.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -149,14 +149,18 @@
     def add_sql(self):
         # Main table
 
+        name = "%s_id_seq" % self._name
+        self.sql_sequence = SqlSequence(self._package.sql_schema, name)
+
         self.sql_table = SqlTable(self._package.sql_schema, self._name)
 
-        id_col = SqlColumn(self.sql_table, "_id", sql_serial8)
+        id_col = SqlColumn(self.sql_table, "_id", sql_int8)
         self.sql_table.key_column = id_col
 
         name = "%s_pk" % self._name
         SqlPrimaryKeyConstraint(self.sql_table, name, (id_col,))
 
+        self.sql_get_new_id = SqlGetNewId(self.sql_table, self.sql_sequence)
         self.sql_select = SqlQuery(self.sql_table)
         self.sql_select_by_id = SqlSelectItem(self.sql_table)
         self.sql_select_by_qmf_id = SqlSelectItemByQmfId(self.sql_table)
@@ -170,12 +174,6 @@
         name = "%s_samples" % self._name
         self.sql_samples_table = SqlTable(self._package.sql_schema, name)
 
-        stats_id_col = SqlColumn(self.sql_samples_table, "_id", sql_serial8)
-        self.sql_samples_table.key_column = stats_id_col
-
-        name = "%s_pk" % self.sql_samples_table._name
-        SqlPrimaryKeyConstraint(self.sql_samples_table, name, (stats_id_col,))
-
         name = "_parent_id"
         parent_col = SqlColumn(self.sql_samples_table, name, sql_int8)
         parent_col.foreign_key_column = id_col
@@ -224,8 +222,10 @@
         self._qmf_delete_time.optional = True
 
     def add_constraints(self):
-        name = "%s_qmf_ids_uq" % self._name
-        cols = (self._qmf_agent_id.sql_column, self._qmf_object_id.sql_column)
+        name = "%s_qmf_id_uq" % self._name
+        cols = (self._qmf_agent_id.sql_column,
+                self._qmf_object_id.sql_column,
+                self._qmf_session_id.sql_column)
 
         SqlUniqueConstraint(self.sql_table, name, cols)
 
@@ -291,14 +291,26 @@
 
         self.add_constraints()
 
-    def select_objects(self, cursor, **kwargs):
-        objects = list()
+    def get_object(self, cursor, id):
+        assert id
 
+        obj = RosemaryObject(self, id)
+
+        self.load_object(cursor, obj)
+
+        return obj
+
+    def get_selection(self, cursor, **kwargs):
+        selection = list()
+
         columns = self.sql_table._columns
-
         options = SqlQueryOptions()
 
-        for name, value in kwargs.items():
+        for name in kwargs:
+            # XXX need to translate ref=obj args here
+            
+            value = "%%(%s)s" % name
+
             column = self.sql_table._columns_by_name[name]
             filter = SqlComparisonFilter(None, column, value)
             options.filters.append(filter)
@@ -310,33 +322,42 @@
 
             self.set_object_attributes(obj, columns, record)
 
-            objects.append(obj)
+            selection.append(obj)
 
-        return objects
+        return selection
 
-    def get_object(self, cursor, id):
-        assert id
+    def get_object_by_qmf_id(self, cursor, agent_id, object_id):
+        assert isinstance(obj, RosemaryObject)
 
-        object = RosemaryObject(self, id)
+        obj = RosemaryObject(self, None)
+        obj._qmf_agent_id = agent_id
+        obj._qmf_object_id = object_id
 
-        self.load_object(cursor, object)
+        self.load_object_qmf_id(cursor, obj)
 
-        return object
+        return obj
 
-    def create_object(self):
-        return RosemaryObject(self, None)
+    def get_new_id(self, cursor):
+        self.sql_get_new_id.execute(cursor, ())
 
+        values = cursor.fetchone()
+
+        assert values
+
+        return values[0]
+
+    def create_object(self, cursor):
+        id = self.get_new_id(cursor)
+
+        return RosemaryObject(self, id)
+
     def load_object(self, cursor, obj):
         assert isinstance(obj, RosemaryObject)
+        assert obj._id, obj
 
         columns = self.sql_table._columns
 
-        if obj._id:
-            self.sql_select_by_id.execute(cursor, columns, obj.__dict__)
-        elif obj._qmf_agent_id and obj._qmf_object_id:
-            self.sql_select_by_qmf_id.execute(cursor, columns, obj.__dict__)
-        else:
-            raise Exception("No id attributes are set")
+        self.sql_select_by_id.execute(cursor, columns, obj.__dict__)
 
         values = cursor.fetchone()
 
@@ -345,25 +366,43 @@
 
         self.set_object_attributes(obj, columns, values)
 
+    def load_object_by_qmf_id(self, cursor, obj):
+        assert isinstance(obj, RosemaryObject)
+        assert obj._qmf_agent_id, obj
+        assert obj._qmf_object_id, obj
+
+        columns = self.sql_table._columns
+
+        self.sql_select_by_qmf_id.execute(cursor, columns, obj.__dict__)
+
+        values = cursor.fetchone()
+
+        if not values:
+            raise RosemaryNotFound()
+
+        self.set_object_attributes(obj, columns, values)
+
     def set_object_attributes(self, obj, columns, values):
         assert isinstance(obj, RosemaryObject)
 
         for column, value in zip(columns, values):
             setattr(obj, column.name, value)
 
+        obj._sync_time = datetime.now()
+
     def save_object(self, cursor, obj, columns=None):
         assert isinstance(obj, RosemaryObject)
+        assert obj._id, obj
 
-        if not columns:
-            columns = list(self.sql_table._columns)
-            columns.remove(self.sql_table._id)
+        if columns is None:
+            columns = self.sql_table._columns
 
-        if obj._id is None:
+        if obj._sync_time:
+            self.sql_update.execute(cursor, columns, obj.__dict__)
+        else:
             self.sql_insert.execute(cursor, columns, obj.__dict__)
 
-            obj._id = cursor.fetchone()[0]
-        else:
-            self.sql_update.execute(cursor, columns, obj.__dict__)
+        obj._sync_time = datetime.now()
 
     def delete_object(self, cursor, obj):
         assert isinstance(obj, RosemaryObject)
@@ -570,6 +609,7 @@
 
         self._class = cls
         self._id = id
+        self._sync_time = None
 
     # XXX prefix these with _
     def load(self, cursor):
@@ -581,6 +621,13 @@
     def delete(self, cursor):
         self._class.delete_object(cursor, self)
 
+    def fake_qmf_values(self):
+        self._qmf_agent_id = "__rosemary__"
+        self._qmf_object_id = str(datetime.now())
+        self._qmf_create_time = datetime.now()
+        self._qmf_update_time = datetime.now()
+        self._qmf_class_key = "__rosemary__"
+
     def get_title(self):
         if self._class._object_title:
             return self._class._object_title % self.__dict__
@@ -589,5 +636,10 @@
             if hasattr(self, attr):
                 return getattr(self, attr)
 
+    def __repr__(self):
+        name = self.__class__.__name__
+        args = (name, self._class, self._id, self._sync_time)
+        return "%s(%s,%i,%s)" % args
+
 class RosemaryNotFound(Exception):
     pass

Modified: mgmt/newdata/rosemary/python/rosemary/sqlmodel.py
===================================================================
--- mgmt/newdata/rosemary/python/rosemary/sqlmodel.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/rosemary/python/rosemary/sqlmodel.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -37,6 +37,9 @@
         # XXX _ this one too
         self.identifier = "\"%s\"" % self._name
 
+        self._sequences = list()
+        self._sequences_by_name = dict()
+
         self._tables = list()
         self._tables_by_name = dict()
 
@@ -49,6 +52,9 @@
     def write_create_ddl(self, out):
         out.write("create schema %s\n" % self.identifier)
 
+        for seq in self._sequences:
+            seq.write_create_ddl(out)
+
         for table in self._tables:
             table.write_create_ddl(out)
 
@@ -67,6 +73,21 @@
         args = (self.__class__.__name__, self._name)
         return "%s(%s)" % args
 
+class SqlSequence(object):
+    def __init__(self, schema, name):
+        assert isinstance(schema, SqlSchema)
+
+        self.schema = schema
+        self.name = name
+
+        self.identifier = "%s.\"%s\"" % (self.schema.identifier, self.name)
+
+        self.schema._sequences.append(self)
+        self.schema._sequences_by_name[self.name] = self
+
+    def write_create_ddl(self, out):
+        out.write("    create sequence \"%s\"\n" % self.name)
+
 class SqlTable(object):
     def __init__(self, schema, name):
         assert isinstance(schema, SqlSchema)

Modified: mgmt/newdata/rosemary/python/rosemary/sqloperation.py
===================================================================
--- mgmt/newdata/rosemary/python/rosemary/sqloperation.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/rosemary/python/rosemary/sqloperation.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -5,7 +5,7 @@
 
 class SqlOperation(object):
     def __init__(self, table):
-        self.table = table
+        self.table = table # XXX consider making this "relation" or "object"
 
     def execute(self, cursor, columns, values=None, options=None):
         text = self.emit(columns, options)
@@ -13,9 +13,6 @@
         if values is None:
             values = {}
 
-        if self.table._schema._model._model.sql_logging_enabled:
-            self.log_sql(cursor, text, values)
-
         try:
             cursor.execute(text, values)
         except:
@@ -25,6 +22,9 @@
 
             raise
 
+        if self.table._schema._model._model.sql_logging_enabled:
+            self.log_sql(cursor, text, values)
+
     def log_sql(self, cursor, text, values):
         log.info("Sql text: %s", text)
         log.info("Sql values:")
@@ -32,11 +32,20 @@
         for item in sorted(values.items()):
             log.info("    %-34s  %r", *item)
 
-        # XXX log.info("Sql row count: %i", cursor.rowcount)
+        log.info("Sql row count: %i", cursor.rowcount)
 
     def __repr__(self):
         return "%s(%s)" % (self.__class__.__name__, self.table)
 
+class SqlGetNewId(SqlOperation):
+    def __init__(self, table, sequence):
+        super(SqlGetNewId, self).__init__(table)
+
+        self.sequence = sequence
+
+    def emit(self, columns, options=None):
+        return "select nextval('%s')" % self.sequence.identifier
+
 class SqlSelectItem(SqlOperation):
     def emit(self, columns, options=None):
         cols = ", ".join([x.identifier for x in columns])
@@ -65,7 +74,7 @@
 
         args = (table, cols, vals)
 
-        return "insert into %s (%s) values (%s) returning _id" % args
+        return "insert into %s (%s) values (%s)" % args
 
 class SqlInsertItemStats(SqlOperation):
     def emit(self, columns, options=None):
@@ -86,7 +95,9 @@
 class SqlUpdateItem(SqlOperation):
     def emit(self, columns, options=None):
         table = getattr(self.table, "identifier", self.table)
-        exprs = ["\"%s\" = %%(%s)s" % (x.name, x.name) for x in columns]
+        exprs = ["\"%s\" = %%(%s)s" % (x.name, x.name)
+                 for x in columns
+                 if x is not self.table.key_column]
         exprs = ", ".join(exprs)
 
         return "update %s set %s where _id = %%(_id)s" % (table, exprs)

Modified: mgmt/newdata/rosemary/xml/cumin.xml
===================================================================
--- mgmt/newdata/rosemary/xml/cumin.xml	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/rosemary/xml/cumin.xml	2010-03-31 17:45:43 UTC (rev 3886)
@@ -8,4 +8,17 @@
     <property name="broker" type="objId" references="org.apache.qpid.broker:Broker"/>
     <property name="group" type="objId" references="BrokerGroup"/>
   </class>
+
+  <class name="User">
+    <property name="name" type="sstr" index="y"/>
+  </class>
+
+  <class name="Role">
+    <property name="name" type="sstr" index="y"/>
+  </class>
+
+  <class name="UserRoleMapping">
+    <property name="user" references="User" index="y"/>
+    <property name="role" references="Role" index="y"/>
+  </class>
 </schema>

Modified: mgmt/newdata/wooly/python/wooly/__init__.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/__init__.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/wooly/python/wooly/__init__.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -203,9 +203,9 @@
 
     def add_child(self, child):
         assert not self.sealed, self
-        assert isinstance(child, Widget), "%s %s" % (self, child)
+        assert isinstance(child, Widget), (self, child)
         assert child is not self, self
-        assert child not in self.children, self
+        assert child not in self.children, (self, child, self.children)
 
         # XXX assert child.name not in self.children_by_name
         if child.name in self.children_by_name:
@@ -695,6 +695,36 @@
         return "%s(trunk=%s,app=%s,id=%i)" % \
             (self.__class__.__name__, self.trunk, self.app, id(self))
 
+class SessionAttribute(object):
+    def __init__(self, widget, name):
+        assert hasattr(widget, "app"), widget
+        
+        self.widget = widget
+        self.name = name
+        self.default = None
+
+        self.key = (self.widget, self.name)
+
+    def do_get(self, session):
+        return copy(self.default)
+
+    def get(self, session):
+        value = session.get(self.key)
+
+        if value is None:
+            value = self.do_get(session)
+
+            if value is not None:
+                self.set(session, value)
+
+        return value
+
+    def add(self, session, value):
+        self.set(session, value)
+
+    def set(self, session, value):
+        session.set(self.key, value)
+
 class ClientSession(object):
     def __init__(self):
         self.id = unique_id()

Modified: mgmt/newdata/wooly/python/wooly/forms.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/forms.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/wooly/python/wooly/forms.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -200,6 +200,9 @@
             self.param = VoidBooleanParameter(app, "param")
             self.add_parameter(self.param)
 
+    def render_onclick_attr(self, session, *args):
+        pass
+
     def render_checked_attr(self, session, *args):
         if self.get(session):
             return "checked=\"checked\""
@@ -657,6 +660,12 @@
         self.extra_fields = ShowableFieldSet(app, "extra")
         self.content.add_child(self.extra_fields)
 
+    def add_field(self, field):
+        self.main_fields.add_field(field)
+
+    def add_extra_field(self, field):
+        self.extra_fields.add_field(field)
+
     def validate(self, session):
         super(FoldingFieldSubmitForm, self).validate(session)
 

Modified: mgmt/newdata/wooly/python/wooly/forms.strings
===================================================================
--- mgmt/newdata/wooly/python/wooly/forms.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/wooly/python/wooly/forms.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -78,7 +78,7 @@
 <input type="password" name="{name}" value="{value}" tabindex="{tab_index}" {disabled_attr} size="{size}"/>
 
 [CheckboxInput.html]
-<input type="checkbox" name="{name}" value="{value}" tabindex="{tab_index}" {checked_attr} {disabled_attr}/>
+<input type="checkbox" name="{name}" value="{value}" tabindex="{tab_index}" {checked_attr} {disabled_attr} {onclick_attr}/>
 
 [HiddenInput.html]
 <input type="hidden" name="{name}" value="{value}" tabindex="{tab_index}"/>

Modified: mgmt/newdata/wooly/python/wooly/sql.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/sql.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/wooly/python/wooly/sql.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -3,38 +3,11 @@
 from resources import *
 from template import *
 from util import *
+from wooly import *
 
 strings = StringCatalog(__file__)
 log = logging.getLogger("wooly.sql")
 
-class SessionAttribute(object):
-    def __init__(self, object, name):
-        self.object = object
-        self.name = name
-        self.default = None
-
-        self.key = (self.object, self.name)
-
-    def get_default(self, session):
-        return copy(self.default)
-
-    def get(self, session):
-        value = session.get(self.key)
-
-        if value is None:
-            value = self.get_default(session)
-
-            if value is not None:
-                self.set(session, value)
-
-        return value
-
-    def add(self, session, value):
-        self.set(session, value)
-
-    def set(self, session, value):
-        session.set(self.key, value)
-
 class SqlOperation(object):
     def __init__(self, app):
         super(SqlOperation, self).__init__()

Modified: mgmt/newdata/wooly/python/wooly/table.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/table.py	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/wooly/python/wooly/table.py	2010-03-31 17:45:43 UTC (rev 3886)
@@ -230,9 +230,15 @@
         self.input = CheckboxColumnInput(app, "input", selection)
         self.add_child(self.input)
 
-    def render_input(self, session, record):
+    def render_content(self, session, record):
         return self.input.render(session, record)
 
 class CheckboxColumnInput(CheckboxInput):
+    def render_onclick_attr(self, session, record):
+        value = "wooly.clickTableCheckbox(this, '%s')" % \
+            self.parent.parent.selection.path
+
+        return "onclick=\"%s\"" % value
+
     def render_value(self, session, record):
         return self.parent.parent.render_cell_value(session, record)

Modified: mgmt/newdata/wooly/python/wooly/table.strings
===================================================================
--- mgmt/newdata/wooly/python/wooly/table.strings	2010-03-31 15:34:40 UTC (rev 3885)
+++ mgmt/newdata/wooly/python/wooly/table.strings	2010-03-31 17:45:43 UTC (rev 3886)
@@ -101,6 +101,3 @@
 <th class="{class}"><input id="{id}" type="checkbox"
    onclick="wooly.clickTableCheckboxes(this, '{name}')"
 /></th>
-
-[CheckboxColumnCell.html]
-<td class="{class}">{input}</td>



More information about the rhmessaging-commits mailing list