r5033 - in branches/lucidity/cumin: bin python/cumin python/cumin/account
by tmckay@fedoraproject.org
Author: tmckay
Date: 2011-09-30 16:29:36 +0000 (Fri, 30 Sep 2011)
New Revision: 5033
Removed:
branches/lucidity/cumin/python/cumin/authenticator.py
Modified:
branches/lucidity/cumin/bin/cumin-admin
branches/lucidity/cumin/bin/cumin-web
branches/lucidity/cumin/python/cumin/account/widgets.py
branches/lucidity/cumin/python/cumin/config.py
branches/lucidity/cumin/python/cumin/main.py
Log:
Back out external authentication changes inherited from trunk.
Retain changes to cumin/python/cumin/admin.py (exception handling)
Retain addition of "def confirm" in cumin-admin
svn merge -c -4971 svn+ssh://svn.fedorahosted.org/svn/cumin/trunk
svn merge -c -4945 svn+ssh://svn.fedorahosted.org/svn/cumin/trunk
Modified: branches/lucidity/cumin/bin/cumin-admin
===================================================================
--- branches/lucidity/cumin/bin/cumin-admin 2011-09-30 15:45:25 UTC (rev 5032)
+++ branches/lucidity/cumin/bin/cumin-admin 2011-09-30 16:29:36 UTC (rev 5033)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
import os
import sys
@@ -65,9 +65,8 @@
sys.exit(1)
broker_uris = [x.strip() for x in opts.brokers.split(",")]
- authmech = [x.strip() for x in values.common.auth.split(";")]
- app = Cumin(config.get_home(), broker_uris, opts.database, authmech=authmech)
+ app = Cumin(config.get_home(), broker_uris, opts.database)
app.check()
app.init()
@@ -97,9 +96,6 @@
lines.append("User commands:")
lines.append("")
lines.append(" add-user USER [PASSWORD] Add USER")
- lines.append(" external-user USER Add USER with external authentication")
- lines.append(" external-sync AUTH [VERBOSE] Batch import users with external authentication")
- lines.append(" AUTH is the name of a mechanism like 'ldap' or 'script'")
lines.append(" remove-user USER Remove USER")
lines.append(" add-assignment USER ROLE Add USER to ROLE")
lines.append(" remove-assignment USER ROLE Remove USER from ROLE")
@@ -108,8 +104,6 @@
lines.append(" list-roles List roles")
lines.append(" export-users FILE Export user list to file")
lines.append(" import-users FILE Import user list from file")
- lines.append(" expunge-users Remove all users. Use with caution")
- lines.append(" You may want to run export-users first")
lines.append("")
lines.append("Schema commands:")
lines.append("")
@@ -121,7 +115,6 @@
lines.append(" the expected version if necessary")
return "\n".join(lines)
-
def confirm(prompt, resp=False):
if resp:
prompt = '%s [%s]|%s: ' % (prompt, 'yes', 'no')
@@ -288,79 +281,24 @@
def handle_list_users(app, cursor, opts, args):
- print " ID Name Roles"
- print "---- -------------------- --------------------"
+ print " ID Name Roles"
+ print "---- -------------------- --------------------"
users, roles_by_user_id = get_users(app, cursor)
- externals = 0
+
for user in users:
try:
roles = ", ".join(roles_by_user_id[user._id])
except KeyError:
roles = ""
- if len(user.password) == 0:
- ex = "*"
- externals += 1
- else:
- ex = " "
- print "%4i %s %-20s %-20s" % (user._id, ex, user.name, roles)
+ print "%4i %-20s %-20s" % (user._id, user.name, roles)
+
count = len(users)
print
print "(%i user%s found)" % (count, ess(count))
- if externals > 0:
- print "(%i external user%s, indicated by *)" % (externals, ess(externals))
-def handle_external_user(app, cursor, opts, args):
- try:
- name = args[0]
- except IndexError:
- error("USER is required")
- role = app.admin.get_role(cursor, "user")
- try:
- user = app.admin.add_user(cursor, name, "")
- except IntegrityError:
- error("A user called '%s' already exists" % name)
-
- app.admin.add_assignment(cursor, user, role)
- print "External user '%s' is added" % name
-
-def handle_external_sync(app, cursor, opts, args):
- try:
- authenticatorname = args[0]
- except IndexError:
- error("AUTHENTICATOR name is required")
-
- output_on = False
- if len(args) > 1:
- output_on = args[1].lower() in ("t", "true", "1")
-
- users, conflicts, errors = \
- app.authenticator.batch_import(authenticatorname, output_on)
-
- print("Successfully imported %s users, %s conflicts" % (users, conflicts))
- if errors:
- print("Errors reported, check logs for details.")
-
-def handle_expunge_users(app, cursor, opts, args):
-
- print("This will remove all users from Cumin's database.")
- print("Hint: you may want to backup Cumin's user database "\
- "with export-users first.\n")
- try:
- go = confirm( "Are you sure you want to do this?", resp=False)
- except KeyboardInterrupt:
- go = False
-
- if go:
- cls = app.model.com_redhat_cumin.User
- cls.delete_selection(cursor)
- print("\nAll users removed.")
- else:
- print("\nNo users removed.")
-
-
def handle_add_user(app, cursor, opts, args):
try:
name = args[0]
@@ -376,14 +314,18 @@
password = args[1]
except IndexError:
password = prompt_password()
+
crypted = crypt_password(password)
+
role = app.admin.get_role(cursor, "user")
+
try:
user = app.admin.add_user(cursor, name, crypted)
except IntegrityError:
error("A user called '%s' already exists" % name)
app.admin.add_assignment(cursor, user, role)
+
print "User '%s' is added" % name
def handle_export_users(app, cursor, opts, args):
@@ -423,19 +365,15 @@
for info in user_data:
line += 1
- count = 0
for field in info:
# Don't suppose it's possible for data to be anything other than
# strings from csv, but this is where such type checking goes
if type(field) != str:
error("Data error, line %u, fields must be strings" % line)
+ if len(field) == 0:
+ error("Data error, line %u, importer "\
+ "does not allow empty fields" % line)
- # Empty password field is external auth indicator, allow it
- if len(field) == 0 and count != 1:
- error("Data error, line %u, field %u, importer "\
- "does not allow empty field" % (line, field+1))
- count += 1
-
if len(info) < 2:
error("Data error, line %u, not enough fields. "\
" User and password are required" % (line))
@@ -450,7 +388,7 @@
# before we get an integrity error
warn("A user called '%s' already exists, skipping" % info[0])
continue
-
+
try:
user = app.admin.add_user(cursor, info[0], info[1])
except IntegrityError:
@@ -538,11 +476,10 @@
if not user:
error("User '%s' is not found" % user_name)
- if user.password == "":
- error("User '%s' is an external user, password cannot be changed "\
- "through this mechanism" % user_name)
+
user.password = crypt_password(prompt_password())
user.save(cursor)
+
print "Password of user '%s' is changed" % user.name
def handle_load_demo_data(app, cursor, opts, args):
Modified: branches/lucidity/cumin/bin/cumin-web
===================================================================
--- branches/lucidity/cumin/bin/cumin-web 2011-09-30 15:45:25 UTC (rev 5032)
+++ branches/lucidity/cumin/bin/cumin-web 2011-09-30 16:29:36 UTC (rev 5033)
@@ -103,9 +103,8 @@
values.log_max_archives)
broker_uris = [x.strip() for x in opts.brokers.split(",")]
- authmech = [x.strip() for x in values.auth.split(";")]
cumin = Cumin(config.get_home(), broker_uris, opts.database,
- opts.host, opts.port, values.persona, authmech)
+ opts.host, opts.port, values.persona)
if type(values.sasl_mech_list) == str:
cumin.sasl_mech_list = values.sasl_mech_list.upper()
Modified: branches/lucidity/cumin/python/cumin/account/widgets.py
===================================================================
--- branches/lucidity/cumin/python/cumin/account/widgets.py 2011-09-30 15:45:25 UTC (rev 5032)
+++ branches/lucidity/cumin/python/cumin/account/widgets.py 2011-09-30 16:29:36 UTC (rev 5033)
@@ -61,6 +61,7 @@
def render_content(self, sessino):
return "Change password"
+
class LoginPage(HtmlPage):
def __init__(self, app, name):
super(LoginPage, self).__init__(app, name)
@@ -127,11 +128,14 @@
self.login_invalid.set(session, True)
return
- authenticated = self.app.authenticator.authenticate(name,password)
- if authenticated:
+ crypted = user.password
+
+ if crypted and crypt(password, crypted) == crypted:
# You're in!
+
login = LoginSession(self.app, user)
session.client_session.attributes["login_session"] = login
+
url = self.page.origin.get(session)
self.page.redirect.set(session, url)
@@ -174,51 +178,53 @@
self.add_field(self.new1)
def validate(self, session):
+ super(ChangePasswordForm, self).validate(session)
+
+ current = self.current.get(session)
+ new0 = self.new0.get(session)
+ new1 = self.new1.get(session)
+
user = session.client_session.attributes["login_session"].user
+
# In case a different login session for this user has made
# changes, refresh the user object
+
user.load(session.cursor)
-
- new0 = self.new0.get(session)
- new1 = self.new1.get(session)
+ crypted = user.password
+
+ if crypt_password(current, crypted) != crypted:
+ error = FormError("The password is incorrect")
+ self.errors.add(session, error)
+
if new0 != new1:
error = FormError("The new passwords do not match")
self.errors.add(session, error)
- return
- super(ChangePasswordForm, self).validate(session)
-
- # authenticator.update_password does authentication
- # before allowing the password change, no need to authenticate here
-
def process_submit(self, session):
self.validate(session)
if not self.errors.get(session):
- newpassword = self.new0.get(session)
- oldpassword = self.current.get(session)
- user = session.client_session.attributes["login_session"].user
+ password = self.new0.get(session)
+
+ conn = self.app.database.get_connection()
+
try:
- status, message = self.app.authenticator.update_password(user.name,
- oldpassword,
- newpassword)
- if not status:
- if not message:
- message = "Update failed."
- error = FormError(message)
- self.errors.add(session, error)
+ cursor = conn.cursor()
- except Exception,e:
- log.debug("Error in external authenticator: %s" , e )
- error = FormError("Password change error. Please contact your site administrator.")
- self.errors.add(session,error)
+ user = session.client_session.attributes["login_session"].user
+ user.password = crypt_password(password)
+ user.save(cursor)
- if not self.errors.get(session):
+ conn.commit()
+ finally:
+ conn.close()
+
task = ObjectTask(self.app)
invoc = task.start(session, None)
invoc.description = "Password changed"
invoc.end()
+
url = self.return_url.get(session)
self.page.redirect.set(session, url)
Deleted: branches/lucidity/cumin/python/cumin/authenticator.py
===================================================================
--- branches/lucidity/cumin/python/cumin/authenticator.py 2011-09-30 15:45:25 UTC (rev 5032)
+++ branches/lucidity/cumin/python/cumin/authenticator.py 2011-09-30 16:29:36 UTC (rev 5033)
@@ -1,347 +0,0 @@
-from util import *
-try:
- import ldap
- import ldapurl
- have_ldap = True
-except:
- have_ldap = False
-
-import subprocess
-from subprocess import PIPE
-from psycopg2 import IntegrityError
-import syslog
-
-# Send sensitive authentication logs to syslog
-# but use this for other stuff. We want to keep
-# all user and password information out of the
-# publically readable log file.
-log = logging.getLogger("cumin.authenticator")
-
-
-class _syslog(object):
- log_auth = False
- @classmethod
- def log(cls, msg):
- if _syslog.log_auth:
- syslog.syslog(msg)
-
-class CuminAuthenticatorLDAP(object):
- def __init__(self, url):
- log.info("Initializing %s", self)
- myurl = url.split("=",1)[1]
- try:
- self.url = ldapurl.LDAPUrl(myurl)
- log.info("Authenticator: parsed LDAP url successfully.")
- except Exception,e:
- log.error("Authenticator: cannot parse LDAP url %s", e)
-
- def __prep_con(self):
- try:
- conn = ldap.initialize(self.url.urlscheme + "://" +self.url.hostport)
- except Exception,e:
- log.error("Authenticator: cannot contact ldap server %s",e)
- return False
-
- if self.url.who and self.url.cred:
- try:
- conn.simple_bind_s(self.url.who,self.url.cred)
- except:
- log.error("Authenticator: cannot authenticate as service %s",
- self.url.who)
- return False
- return conn
-
- def change_pw(self,user,oldpass,newpass):
- conn = self.__prep_con()
- if not conn:
- return False
- filter = self.url.filterstr % user
- try:
- res = conn.search_s(self.url.dn, self.url.scope, filter)
- except Exception, e:
- log.error("Authenticator: update password, "\
- "query returned exception %s", e)
- res = []
- if not res:
- log.info("Authenticator: update password, "\
- "query returned no results in %s", self.__class__.__name__)
- else:
- dn,ent = res[0]
- conn.simple_bind_s(dn,oldpass)
- conn.passwd_s(dn,oldpass,newpass)
- log.info("Authenticator: update password succeeded in %s",
- self.__class__.__name__)
- _syslog.log("cumin: updated password via LDAP for user %s" % dn)
- return True
- return False
-
- def batch_import(self):
- log.debug("Authenticator: batch import in %s", self.__class__.__name__)
- userlist = res = []
- conn = self.__prep_con()
- error = not conn
- if not error:
- filter = self.url.filterstr % '*'
- try:
- res = conn.search_s(self.url.dn, self.url.scope, filter)
- except Exception, e:
- log.error("Authenticator:, batch import, "\
- "query returned exception %s", e)
- error = True
- if not res:
- log.info("Authenticator: batch import failed, "\
- "query returned no results in %s", self.__class__.__name__)
- else:
- for dn,ent in res:
- dn_arr = ldap.dn.explode_rdn(dn)
- naming_attr = dn_arr[0].split('=')[0]
- userlist.append(ent[naming_attr][0])
- return userlist, error
-
- def authenticate(self, username, password):
- log.debug("Authenticating against %s", self.__class__.__name__)
- conn = self.__prep_con()
- if not conn:
- return False
- filter = self.url.filterstr % username
- try:
- res = conn.search_s(self.url.dn, self.url.scope, filter)
- except Exception, e:
- log.error("Authenticator: authenticate, "\
- "query returned exception %s", e)
- res = []
- if not res:
- log.info("Authenticator: authentication failed, "\
- "query returned no results in %s", self.__class__.__name__)
- else:
- for dn,ent in res:
- try:
- conn.simple_bind_s(dn,password)
- _syslog.log("cumin: authenticated user %s via LDAP" % dn)
- return True
- except Exception, e:
- log.info("Authenticator: LDAP authentication "\
- "returned exception %s" % e)
- _syslog.log("cumin: authentication via LDAP failed "\
- "for user" % dn)
- return False
-
-class CuminAuthenticatorScript(object):
- def __init__(self, commandline):
- self.params = {}
- self.cap = []
- me = self.__class__.__name__
- for a in commandline.split(','):
- param,val = a.split('=')
- self.params[param] = val
-
- if self.params.has_key('script') and \
- os.access(self.params['script'], os.X_OK):
- if self.params.has_key('auth'):
- log.debug("Authenticator: adding auth capability to %s", me)
- self.cap.append('a')
- if self.params.has_key('change'):
- log.debug("Authenticator: adding change capability to %s", me)
- self.cap.append('c')
- if self.params.has_key('list'):
- log.debug("Authenticator: adding list capability to %s", me)
- self.cap.append('l')
- else:
- log.error('Authenticator: script parameter missing or target file '\
- 'not executable in %s', me)
-
- def authenticate(self, username, password):
- me = self.__class__.__name__
- if 'a' in self.cap:
- log.debug("Authenticator: executing %s in %s",
- self.params['script'], me)
- # Use nameless pipes to pass parameters.
- # If they are passed as arguments they show up in the output
- # of ps, etc. This way is secure.
- # Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input="%s %s %s" % \
- (self.params['auth'], username, password))
- log.debug("Authenticator: authenticate, script returned "\
- "%s, %s, exitcode %s", out, err, res.returncode)
- if res.returncode == 0:
- _syslog.log("cumin: authenticated user %s via script" % username)
- return True
- _syslog.log("cumin: authentication via script failed for user %s" % username)
- return False
-
- def batch_import(self):
- if 'l' in self.cap:
- log.debug("Authenticator: batch import in %s",
- self.__class__.__name__)
- # Use nameless pipes to pass parameters.
- # If they are passed as arguments they show up in the output
- # of ps, etc. This way is secure.
- # Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input=self.params['list'])
- log.debug("Authenticator: batch import, script returned "\
- "%s, %s, exitcode %s", out, err, res.returncode)
- return out.split(','), False
- return [], False
-
- def change_pw(self, user, newpass, oldpass):
- if 'c' in self.cap:
- me = self.__class__.__name__
- log.debug("Authenticator: change password in %s", me)
-
- # Use nameless pipes to pass parameters.
- # If they are passed as arguments they show up in the output
- # of ps, etc. This way is secure.
- # Note, the call to communicate causes an EOF on stdin
- cmd = [self.params['script']]
- try:
- res = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- out, err = res.communicate(input="%s %s %s %s" % \
- (self.params['change'], user, newpass, oldpass))
- log.debug("Authenticator: update password, script returned "\
- "%s, %s, exitcode %s", out, err, res.returncode)
- except Exception, e:
- import traceback
- traceback.print_exc()
- res.returncode = -1
-
- if res.returncode == 0:
- _syslog.log("cumin: updated password via script for user %s" % user)
- return True
- return False
-
-if have_ldap:
- authen_map = {'ldap': CuminAuthenticatorLDAP,
- 'script': CuminAuthenticatorScript}
-else:
- authen_map = {'script': CuminAuthenticatorScript}
-
-class CuminAuthenticator(object):
- def __init__(self, app, log_authentication=True):
- self.authenticators=[]
- self.app = app
- _syslog.log_auth = log_authentication
- log.info("Initializing %s", self)
- if not have_ldap:
- log.info("Authenticator: import of ldap modules failed, "\
- "ldap mechanism not available")
- for authmech in app.authmech:
- if authmech != "internal":
- try:
- mechname = authmech.split('=')[0]
- log.info("Authenticator: adding auth mechanism %s", mechname)
- classname = authen_map[mechname]
- except KeyError:
- log.error("Authenticator: unsupported authenticator type %s",
- mechname)
- continue
- self.authenticators.append(classname(authmech))
-
- def batch_import(self, backend, output_on=False):
- numusers = 0
- numconflicts = 0
- errors = False
- import_list = []
- log.debug("Authenticator: calling batch import")
- try:
- classname = authen_map[backend]
- except KeyError:
- log.error("Authenticator: batch import, unsupported authenticator "\
- "type '%s'", backend)
- errors = True
-
- if not errors:
- try:
- idx = [x.__class__.__name__ for x in self.authenticators]
- idx = idx.index(classname.__name__)
- except ValueError:
- log.error("Authenticator: batch import, authenticator "\
- "not configured '%s'", backend)
- errors = True
-
- if not errors:
- users, errors = self.authenticators[idx].batch_import()
- for imp in users:
- import_list.append(imp)
-
- if len(import_list) > 0:
- try:
- conn = self.app.database.get_connection()
- cursor = conn.cursor()
- role = self.app.admin.get_role(cursor, "user")
- for importuser in import_list:
- try:
- user = self.app.admin.add_user(cursor, importuser, "")
- if output_on:
- print("Importing user %s" % importuser)
- self.app.admin.add_assignment(cursor, user, role)
- conn.commit()
- numusers += 1
- except IntegrityError:
- if output_on:
- print("Import failed, a user called '%s' "\
- "already exists" % importuser)
- numconflicts += 1
- conn.rollback()
- finally:
- conn.close()
- return numusers, numconflicts, errors
-
- def authenticate(self, username, password):
- log.debug("Authenticator: calling authenticate")
- cursor = self.app.database.get_read_cursor()
- cls = self.app.model.com_redhat_cumin.User
- user = cls.get_object(cursor, name=username)
- external = len(user.password) == 0
- log.info("Authenticator: authenticating external user %s" % external)
- if not external:
- res = crypt(password, user.password) == user.password
- if res:
- msg = "cumin: authenticated user %s" % username
- else:
- msg = "cumin: authentication failed for user %s" % username
- _syslog.log(msg)
- return res
- else:
- for authenticator in self.authenticators:
- log.debug("Authenticator: authenticate, try %s", authenticator)
- if authenticator.authenticate(username, password):
- return True
- return False
-
- def update_password(self, username, oldpassword, newpassword):
- status = False
- message = ""
- log.debug("Authenticator: calling update_password")
- conn = self.app.database.get_connection()
- try:
- cursor = conn.cursor()
- cls = self.app.model.com_redhat_cumin.User
- user = cls.get_object(cursor, name=username)
- if user.password == "":
- for authenticator in self.authenticators:
- status = authenticator.authenticate(username, oldpassword)
- if status:
- status = authenticator.change_pw(username,
- oldpassword, newpassword)
- if not status:
- message = "Could not change password"
- break
-
- if not status and message == "":
- message = "The password is incorrect"
- else:
- status = crypt(oldpassword, user.password) == user.password
- if status:
- user.password = crypt_password(newpassword)
- user.save(cursor)
- conn.commit()
- _syslog.log("cumin: updated password for user %s" % username)
- else:
- message = "The password is incorrect"
- finally:
- conn.close()
- return status, message
Modified: branches/lucidity/cumin/python/cumin/config.py
===================================================================
--- branches/lucidity/cumin/python/cumin/config.py 2011-09-30 15:45:25 UTC (rev 5032)
+++ branches/lucidity/cumin/python/cumin/config.py 2011-09-30 16:29:36 UTC (rev 5033)
@@ -145,9 +145,6 @@
param = ConfigParameter(self, "brokers", str)
param.default = "amqp://localhost"
- param = ConfigParameter(self, "auth", str)
- param.default = 'internal'
-
# Leave default set to None, which is equivalent to
# previous behavior
param = ConfigParameter(self, "sasl-mech-list", str)
Modified: branches/lucidity/cumin/python/cumin/main.py
===================================================================
--- branches/lucidity/cumin/python/cumin/main.py 2011-09-30 15:45:25 UTC (rev 5032)
+++ branches/lucidity/cumin/python/cumin/main.py 2011-09-30 16:29:36 UTC (rev 5033)
@@ -21,7 +21,6 @@
from user import *
from util import *
from widgets import *
-from authenticator import *
from sage.catalog import Catalog
from sage.qmf.qmfoperations import QmfOperations
from sage.wallaby.wallabyoperations import WallabyOperations
@@ -34,12 +33,10 @@
class Cumin(Application):
def __init__(self, home, broker_uris, database_dsn,
- host="localhost", port=45672, persona="default",
- authmech=["internal"]):
+ host="localhost", port=45672, persona="default"):
super(Cumin, self).__init__()
self.home = home
- self.authmech = authmech
model_dir = os.path.join(self.home, "model")
@@ -49,7 +46,6 @@
self.database = CuminDatabase(self, database_dsn)
self.server = CuminServer(self, host, port)
self.admin = CuminAdmin(self)
- self.authenticator = CuminAuthenticator(self)
self.add_resource_dir(os.path.join(self.home, "resources-wooly"))
self.add_resource_dir(os.path.join(self.home, "resources"))
@@ -670,7 +666,6 @@
if qdate is None:
return 0
- import time
return fmt_duration(time.time() - secs(qdate))
def render_text_align(self, session):
12 years, 7 months
r5032 - branches
by tmckay@fedoraproject.org
Author: tmckay
Date: 2011-09-30 15:45:25 +0000 (Fri, 30 Sep 2011)
New Revision: 5032
Added:
branches/lucidity/
Log:
Create a new branch from trunk
12 years, 7 months
r5031 - in trunk/cumin: model model/upgrades python/cumin python/cumin/grid
by tmckay@fedoraproject.org
Author: tmckay
Date: 2011-09-30 14:45:15 +0000 (Fri, 30 Sep 2011)
New Revision: 5031
Modified:
trunk/cumin/model/condor.xml
trunk/cumin/model/rosemary.xml
trunk/cumin/model/upgrades/1.0_to_1.1
trunk/cumin/python/cumin/grid/pool.py
trunk/cumin/python/cumin/grid/submission.py
trunk/cumin/python/cumin/main.py
trunk/cumin/python/cumin/objectframe.py
trunk/cumin/python/cumin/objectframe.strings
Log:
Add QDate column to submission table in Postgres, add qdate column to submissions under admin tab,
remove scheduler column from same and add a scheduler link to the SubmissionFrame.
BZ639383
Modified: trunk/cumin/model/condor.xml
===================================================================
--- trunk/cumin/model/condor.xml 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/model/condor.xml 2011-09-30 14:45:15 UTC (rev 5031)
@@ -810,6 +810,8 @@
<property name="Name" type="sstr" index="y"/>
<property name="Owner" type="sstr" index="y"/>
+ <property name="QDate" type="absTime" optional="y"
+ desc="Oldest QDate of member jobs"/>
<statistic name="Idle" type="count32"/>
<statistic name="Running" type="count32"/>
Modified: trunk/cumin/model/rosemary.xml
===================================================================
--- trunk/cumin/model/rosemary.xml 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/model/rosemary.xml 2011-09-30 14:45:15 UTC (rev 5031)
@@ -502,6 +502,9 @@
<property name="Name">
<title>Description</title>
</property>
+ <property name="QDate">
+ <title>Enqueued</title>
+ </property>
</class>
<class name="Negotiator">
Modified: trunk/cumin/model/upgrades/1.0_to_1.1
===================================================================
--- trunk/cumin/model/upgrades/1.0_to_1.1 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/model/upgrades/1.0_to_1.1 2011-09-30 14:45:15 UTC (rev 5031)
@@ -1,2 +1,3 @@
#!/bin/bash
echo create index \"Submission_Name_idx\" on \"com.redhat.grid\".\"Submission\"\(\"Name\"\) | psql -d cumin -U cumin -h localhost
+echo alter table \"com.redhat.grid\".\"Submission\" add column \"QDate\" timestamp | psql -d cumin -U cumin -h localhost
Modified: trunk/cumin/python/cumin/grid/pool.py
===================================================================
--- trunk/cumin/python/cumin/grid/pool.py 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/python/cumin/grid/pool.py 2011-09-30 14:45:15 UTC (rev 5031)
@@ -9,7 +9,7 @@
from cumin.grid.dashboard import PoolDashboard
from cumin.grid.tags import TagsNodeEditTask, TagsFrame, TagInventory
-from submission import SubmissionFrame, PoolSubmissionJoinSelector
+from submission import PoolSubmissionFrame, PoolSubmissionJoinSelector
from slot import SlotFrame
from scheduler import SchedulerFrame, SchedulerSelector
from negotiator import NegotiatorFrame, NegotiatorSelector,\
@@ -61,7 +61,7 @@
self.mode.default = self.view
- self.submission = SubmissionFrame(app, "submission")
+ self.submission = PoolSubmissionFrame(app, "submission")
self.add_mode(self.submission)
self.slot = SlotFrame(app, "slot")
Modified: trunk/cumin/python/cumin/grid/submission.py
===================================================================
--- trunk/cumin/python/cumin/grid/submission.py 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/python/cumin/grid/submission.py 2011-09-30 14:45:15 UTC (rev 5031)
@@ -4,7 +4,7 @@
import os
from job import JobSelector, JobFrame
-from cumin.objectframe import ObjectFrame
+from cumin.objectframe import ObjectFrame, ObjectView, ObjectViewSummary, ObjectViewContext
from cumin.sqladapter import ObjectSqlAdapter
from cumin.objectselector import ObjectSelector, ObjectLinkColumn,\
ObjectTableColumn, ObjectTable
@@ -33,6 +33,35 @@
jobs = JobSelector(app, "jobs", self.object)
self.view.add_tab(jobs)
+class PoolSubmissionFrame(SubmissionFrame):
+ # Use an ObjectView derivation here so that
+ # SubmissionFrame can use a different summary class later on...
+ def get_view(self, app, name, obj):
+ return self.MyObjectView(app, name, obj)
+
+ class MyObjectView(ObjectView):
+ def get_summary(self, app, name, obj):
+ return PoolSubmissionFrame.MyObjectViewSummary(app, name, obj)
+
+ class MyObjectViewSummary(ObjectViewSummary):
+ def get_scheduler(self, session):
+ # Find out submission
+ subm = self.frame.get_object(session,
+ self.frame.id.get(session))
+
+ # Get a scheduler...
+ js = self.app.model.get_jobserver_from_submission(session, subm)
+ return self.app.model.get_scheduler_from_jobserver(session, js)
+
+ def render_auxlink(self, session):
+ sch = self.get_scheduler(session)
+ frame = self.page.page_widgets_by_path["main.grid.scheduler"]
+ return frame.get_href(session, sch._id)
+
+ def render_auxtitle(self, session):
+ sch = self.get_scheduler(session)
+ return "Scheduler '%s'" % sch.Name
+
class SubmissionData(ObjectSqlAdapter):
def __init__(self, app):
submission = app.model.com_redhat_grid.Submission
@@ -70,6 +99,9 @@
self.table.adapter = SubmissionData(app)
+ col = self.QDateColumn(app, cls.QDate.name, cls.QDate)
+ self.add_column(col)
+
self.add_attribute_column(cls.Idle)
self.add_attribute_column(cls.Running)
self.add_attribute_column(cls.Completed)
@@ -79,6 +111,14 @@
# avoid the checkboxes
return ObjectTable(app, name, cls)
+ class QDateColumn(ObjectTableColumn):
+ def render_cell_content(self, session, data):
+ date = super(SubmissionSelector.QDateColumn, self).\
+ render_cell_content(session, data)
+ if date is None:
+ date = "unknown"
+ return date
+
class PoolSubmissionSelector(SubmissionSelector):
def __init__(self, app, name, frame="main.grid.submission"):
super(PoolSubmissionSelector, self).__init__(app, name)
@@ -119,9 +159,9 @@
self.SchedulerJoin(app, self.table.adapter.query, self.cls.sql_table,
self.cls.jobserverRef.sql_column, "jid")
- frame = "main.grid.scheduler"
- col = self.SchedulerColumn(app, "Scheduler", scheduler.Name, scheduler._id, frame)
- self.insert_column(2, col)
+ #frame = "main.grid.scheduler"
+ #col = self.SchedulerColumn(app, "Scheduler", scheduler.Name, scheduler._id, frame)
+ #self.insert_column(2, col)
self.enable_csv_export()
Modified: trunk/cumin/python/cumin/main.py
===================================================================
--- trunk/cumin/python/cumin/main.py 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/python/cumin/main.py 2011-09-30 14:45:15 UTC (rev 5031)
@@ -598,8 +598,10 @@
col = self.NameColumn(app, cls.Name.name, cls.Name, cls._id, None)
self.add_column(col)
- col = self.DurationColumn(app, cls._qmf_create_time.name,
- cls._qmf_create_time)
+# col = self.DurationColumn(app, cls._qmf_create_time.name,
+# cls._qmf_create_time)
+
+ col = self.DurationColumn(app, cls.QDate.name, cls.QDate)
self.add_column(col)
self.set_default_sort_column(col)
@@ -664,9 +666,12 @@
return "Duration"
def render_cell_content(self, session, record):
- created = self.field.get_content(session, record)
+ qdate = self.field.get_content(session, record)
+ if qdate is None:
+ return 0
+
import time
- return fmt_duration(time.time() - secs(created))
+ return fmt_duration(time.time() - secs(qdate))
def render_text_align(self, session):
return "right"
Modified: trunk/cumin/python/cumin/objectframe.py
===================================================================
--- trunk/cumin/python/cumin/objectframe.py 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/python/cumin/objectframe.py 2011-09-30 14:45:15 UTC (rev 5031)
@@ -27,7 +27,8 @@
self.object = Attribute(app, "object")
self.add_attribute(self.object)
- self.view = ObjectView(app, "view", self.object)
+ self.view = self.get_view(app, "view", self.object)
+ #self.view = ObjectView(app, "view", self.object)
self.add_child(self.view)
self.icon_href = "resource?name=action-36.png"
@@ -71,6 +72,9 @@
def get_object(self, session, id):
return self.cls.get_object_by_id(session.cursor, id)
+ def get_view(self, app, name, obj):
+ return ObjectView(app, name, obj)
+
class ObjectAttributes(Widget):
def __init__(self, app, name, object):
super(ObjectAttributes, self).__init__(app, name)
@@ -195,7 +199,8 @@
self.heading = ObjectViewHeading(app, "heading", self.object)
self.add_child(self.heading)
- self.summary = ObjectViewSummary(app, "summary", self.object)
+ self.summary = self.get_summary(app, "summary", self.object)
+# self.summary = ObjectViewSummary(app, "summary", self.object)
self.add_child(self.summary)
self.body = TabbedModeSet(app, "body")
@@ -219,10 +224,14 @@
if obj is not None:
title = obj.get_title()
else:
- # useful in the case where we are dealing with non-database objects and the object title is passed in as the id
+ # useful in the case where we are dealing with
+ # non-database objects and the object title is passed in as the id
title = self.frame.id.get(session)
return title
+ def get_summary(self, app, name, obj):
+ return ObjectViewSummary(app, name, obj)
+
class ObjectViewChild(Widget):
def __init__(self, app, name, object):
super(ObjectViewChild, self).__init__(app, name)
@@ -290,7 +299,6 @@
retval = retval[:100] + "..."
return retval
-
class ObjectViewSummary(ObjectViewChild):
def __init__(self, app, name, object):
super(ObjectViewSummary, self).__init__(app, name, object)
@@ -298,11 +306,19 @@
tasks = SummaryTasks(app, "tasks", self.object)
self.add_child(tasks)
+ self.auxlink = None
+
def render_wide(self, session):
visible_tasks = [x for x in self.frame.tasks if x.visible]
if len(visible_tasks) > 6:
return "wide"
+ def render_auxlink(self, session):
+ pass
+
+ def render_auxtitle(self, session):
+ pass
+
class DetailsAttributes(ObjectAttributes):
pass
Modified: trunk/cumin/python/cumin/objectframe.strings
===================================================================
--- trunk/cumin/python/cumin/objectframe.strings 2011-09-30 14:25:25 UTC (rev 5030)
+++ trunk/cumin/python/cumin/objectframe.strings 2011-09-30 14:45:15 UTC (rev 5031)
@@ -126,13 +126,13 @@
[ObjectViewHeading.html]
<div class="{class}">
<img src="{icon_href}" alt="icon"/>
-
<h1>{title}</h1>
</div>
[ObjectViewSummary.html]
<div class="{class} {wide}">
{tasks}
+ <a href="{auxlink}">{auxtitle}</a>
</div>
[ObjectViewContext.html]
12 years, 7 months
r5030 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-30 14:25:25 +0000 (Fri, 30 Sep 2011)
New Revision: 5030
Modified:
trunk/cumin/python/cumin/grid/tags.py
Log:
Expanding the features column on the Grid::Configuration table.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-29 18:47:16 UTC (rev 5029)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-30 14:25:25 UTC (rev 5030)
@@ -337,7 +337,7 @@
'''
def render_cell_content(self, session, data):
feature_list = data[2]
- features = truncate_text(feature_list, 50, True)
+ features = truncate_text(feature_list, 70, True)
return features
def render_cell_title(self, session, data):
12 years, 7 months
r5029 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-29 18:47:16 +0000 (Thu, 29 Sep 2011)
New Revision: 5029
Modified:
trunk/cumin/python/cumin/grid/tags.py
Log:
Adding some defense against potentially null objects.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-28 19:44:35 UTC (rev 5028)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-29 18:47:16 UTC (rev 5029)
@@ -160,7 +160,10 @@
'''
def render_title(self, session):
obj = self.object.get(session)
- return obj.name
+ if obj is not None:
+ return obj.name
+ else:
+ return ""
def add_details_tab(self):
pass
@@ -926,7 +929,9 @@
given_tag = self.form.tags.input.param.get(session)
tag_object = self.app.wallaby.get_tag_by_name(given_tag)
- selected_features = tag_object.features
+ selected_features = list()
+ if tag_object is not None:
+ selected_features = tag_object.features
for i, feature in enumerate(items):
selected = ""
@@ -972,10 +977,13 @@
def render_inputs(self, session, *args):
tag = self.form.tags.get(session)
- value = ", ".join(self.app.wallaby.get_tag_by_name(tag).features)
- if not value or value == "":
- value = "No features currently selected"
- value = truncate_text(value, 50, True)
+ value = ""
+ tag_obj = self.app.wallaby.get_tag_by_name(tag)
+ if tag_obj is not None:
+ value = ", ".join(tag_obj.features)
+ if not value or value == "":
+ value = "No features currently selected"
+ value = truncate_text(value, 50, True)
return value
def render_title(self, session):
@@ -1131,7 +1139,10 @@
tag_id = osession.values_by_path["main.grid.tag.id"]
self.form.tags.set(session, tag_id)
features = "No features currently assigned"
- feature_list = self.app.wallaby.get_tag_by_name(tag_id).features
+ tag = self.app.wallaby.get_tag_by_name(tag_id)
+ feature_list = list()
+ if tag is not None:
+ feature_list = tag.features
if len(feature_list) > 0:
features = ", ".join(feature_list)
self.form.feature_name.set(session, features)
12 years, 7 months
r5028 - trunk/cumin/python/cumin/inventory
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-28 19:44:35 +0000 (Wed, 28 Sep 2011)
New Revision: 5028
Modified:
trunk/cumin/python/cumin/inventory/system.py
Log:
Adding a cell title to the tags column in the system inventory table.
Modified: trunk/cumin/python/cumin/inventory/system.py
===================================================================
--- trunk/cumin/python/cumin/inventory/system.py 2011-09-28 19:37:59 UTC (rev 5027)
+++ trunk/cumin/python/cumin/inventory/system.py 2011-09-28 19:44:35 UTC (rev 5028)
@@ -359,7 +359,7 @@
value = truncate_text(value, 30, True)
except Exception, e:
pass
- return value
+ return value
def get_title(self, session):
return "Tags"
@@ -375,7 +375,10 @@
def get_field(self):
field = TagsField(self.table.adapter, self.name)
- return field
+ return field
+
+ def render_cell_title(self, session, record):
+ return record[self.field.index]
def render_text_align(self, session):
return "right"
12 years, 7 months
r5027 - in trunk: cumin/python/cumin/grid wooly/python/wooly
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-28 19:37:59 +0000 (Wed, 28 Sep 2011)
New Revision: 5027
Modified:
trunk/cumin/python/cumin/grid/tags.py
trunk/wooly/python/wooly/datatable.py
trunk/wooly/python/wooly/table.py
trunk/wooly/python/wooly/table.strings
Log:
Adding a title attribute to the features column under Grid::Configuration that will show all the features (not just the abbreviated list). Also provided the plumbing to add a cell_title to any table cell.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-28 17:44:27 UTC (rev 5026)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-28 19:37:59 UTC (rev 5027)
@@ -335,8 +335,11 @@
def render_cell_content(self, session, data):
feature_list = data[2]
features = truncate_text(feature_list, 50, True)
- return features
+ return features
+ def render_cell_title(self, session, data):
+ return data[2]
+
class HostCountColumn(ObjectTableColumn):
def render_cell_content(self, session, data):
tags = super(TagInventory.HostCountColumn, self).render_cell_content(session, data)
Modified: trunk/wooly/python/wooly/datatable.py
===================================================================
--- trunk/wooly/python/wooly/datatable.py 2011-09-28 17:44:27 UTC (rev 5026)
+++ trunk/wooly/python/wooly/datatable.py 2011-09-28 19:37:59 UTC (rev 5027)
@@ -186,6 +186,9 @@
def render_cell_content(self, session, record):
return self.field.get_content(session, record)
+
+ def render_cell_title(self, session, record):
+ return ""
class DataTableHeader(TableHeader):
def __init__(self, app, name):
Modified: trunk/wooly/python/wooly/table.py
===================================================================
--- trunk/wooly/python/wooly/table.py 2011-09-28 17:44:27 UTC (rev 5026)
+++ trunk/wooly/python/wooly/table.py 2011-09-28 19:37:59 UTC (rev 5027)
@@ -243,6 +243,10 @@
def render_content(self, session, record):
return self.parent.render_cell_content(session, record)
+
+ def render_cell_title(self, session, record):
+ #gives us the title="" attribute for each table cell
+ return self.parent.render_cell_title(session, record)
class TableHeader(TableChild):
def render_colspan(self, session):
Modified: trunk/wooly/python/wooly/table.strings
===================================================================
--- trunk/wooly/python/wooly/table.strings 2011-09-28 17:44:27 UTC (rev 5026)
+++ trunk/wooly/python/wooly/table.strings 2011-09-28 19:37:59 UTC (rev 5027)
@@ -59,7 +59,7 @@
<th class="{class}">{content}</th>
[TableColumnCell.html]
-<td class="{class}">{content}</td>
+<td class="{class}" title="{cell_title}">{content}</td>
[TableRow.html]
<tr>{cells}</tr>
12 years, 7 months
r5026 - trunk/cumin/python/cumin/inventory
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-28 17:44:27 +0000 (Wed, 28 Sep 2011)
New Revision: 5026
Modified:
trunk/cumin/python/cumin/inventory/system.py
Log:
Correcting the text of the breadcrumb when drilling into a System object.
Modified: trunk/cumin/python/cumin/inventory/system.py
===================================================================
--- trunk/cumin/python/cumin/inventory/system.py 2011-09-28 17:40:49 UTC (rev 5025)
+++ trunk/cumin/python/cumin/inventory/system.py 2011-09-28 17:44:27 UTC (rev 5026)
@@ -90,7 +90,7 @@
if obj is not None:
title = "%s '%s'" % (obj._class._title, obj.get_title())
else:
- title = self.id.get(session)
+ title = "System '%s'" % self.id.get(session)
return title
class SystemGeneralStatSet(StatSet):
12 years, 7 months
r5025 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-28 17:40:49 +0000 (Wed, 28 Sep 2011)
New Revision: 5025
Modified:
trunk/cumin/python/cumin/grid/tags.py
Log:
Correcting the text of the breadcrumb when drilling into a tag object.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-28 17:22:06 UTC (rev 5024)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-28 17:40:49 UTC (rev 5025)
@@ -275,7 +275,7 @@
def get_title(self, session):
retval = ""
try:
- retval = self.object.get(session).name
+ retval = "Tag '%s'" % self.object.get(session).name
except Exception, e:
pass
return retval
12 years, 7 months
r5024 - trunk/cumin/python/cumin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2011-09-28 17:22:06 +0000 (Wed, 28 Sep 2011)
New Revision: 5024
Modified:
trunk/cumin/python/cumin/authenticator.py
Log:
Make failed import of ldap modules non-fatal, add log message
that ldap authentication mechanism is not available if imports fail
Modified: trunk/cumin/python/cumin/authenticator.py
===================================================================
--- trunk/cumin/python/cumin/authenticator.py 2011-09-28 14:52:08 UTC (rev 5023)
+++ trunk/cumin/python/cumin/authenticator.py 2011-09-28 17:22:06 UTC (rev 5024)
@@ -1,6 +1,11 @@
from util import *
-import ldap
-import ldapurl
+try:
+ import ldap
+ import ldapurl
+ have_ldap = True
+except:
+ have_ldap = False
+
import subprocess
from subprocess import PIPE
from psycopg2 import IntegrityError
@@ -208,8 +213,11 @@
return True
return False
-authen_map = { 'ldap': CuminAuthenticatorLDAP,
- 'script': CuminAuthenticatorScript }
+if have_ldap:
+ authen_map = {'ldap': CuminAuthenticatorLDAP,
+ 'script': CuminAuthenticatorScript}
+else:
+ authen_map = {'script': CuminAuthenticatorScript}
class CuminAuthenticator(object):
def __init__(self, app, log_authentication=True):
@@ -217,16 +225,20 @@
self.app = app
_syslog.log_auth = log_authentication
log.info("Initializing %s", self)
+ if not have_ldap:
+ log.info("Authenticator: import of ldap modules failed, "\
+ "ldap mechanism not available")
for authmech in app.authmech:
- try:
- mechname = authmech.split('=')[0]
- log.info("Authenticator: adding auth mechanism %s", mechname)
- classname = authen_map[mechname]
- except KeyError:
- log.error("Authenticator: unsupported authenticator type %s",
- mechname)
- continue
- self.authenticators.append(classname(authmech))
+ if authmech != "internal":
+ try:
+ mechname = authmech.split('=')[0]
+ log.info("Authenticator: adding auth mechanism %s", mechname)
+ classname = authen_map[mechname]
+ except KeyError:
+ log.error("Authenticator: unsupported authenticator type %s",
+ mechname)
+ continue
+ self.authenticators.append(classname(authmech))
def batch_import(self, backend, output_on=False):
numusers = 0
12 years, 7 months