Author: justi9
Date: 2009-08-31 15:23:48 -0400 (Mon, 31 Aug 2009)
New Revision: 3602
Added:
mgmt/trunk/mint/bin/mint-admin
mgmt/trunk/mint/bin/mint-admin-test
mgmt/trunk/mint/bin/mint-demo
mgmt/trunk/mint/python/mint/demo.py
Removed:
mgmt/trunk/cumin/bin/cumin-load-demo-data
Modified:
mgmt/trunk/bin/reschema
mgmt/trunk/cumin/python/cumin/tools.py
mgmt/trunk/mint/python/mint/database.py
mgmt/trunk/mint/python/mint/tools.py
mgmt/trunk/mint/python/mint/util.py
mgmt/trunk/parsley/python/parsley/command.py
Log:
* Move data model admin functions from cumin to mint
* Make CommandException compatible with newer pythons
* Complain, but don't fail, if we try to drop an already dropped
schema
* On mint-admin (was cumin-admin) rename create-schema to
load-schema, and introduce reload-schema as a convenience
* Introduce a command mint-demo for demo-oriented utility subcommands
* Make the sql file selection internal to loadSchema; it should know
where they are
Modified: mgmt/trunk/bin/reschema
===================================================================
--- mgmt/trunk/bin/reschema 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/bin/reschema 2009-08-31 19:23:48 UTC (rev 3602)
@@ -1,7 +1,3 @@
#!/bin/bash -ex
-cumin-admin drop-schema --force || :
-cumin-admin create-schema
-cumin-admin add-user guest guest
-cumin-admin assign guest admin
-cumin-load-demo-data
+exec mint-demo reload
Deleted: mgmt/trunk/cumin/bin/cumin-load-demo-data
===================================================================
--- mgmt/trunk/cumin/bin/cumin-load-demo-data 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/cumin/bin/cumin-load-demo-data 2009-08-31 19:23:48 UTC (rev 3602)
@@ -1,42 +0,0 @@
-#!/usr/bin/python
-
-import sys, os
-from sqlobject import connectionForURI
-from traceback import print_exc
-from getpass import getpass
-from random import sample
-from crypt import crypt
-from mint import MintDatabase
-from psycopg2 import IntegrityError
-
-from cumin import *
-from cumin.util import *
-from cumin.demo import *
-
-def main():
- config = CuminConfig()
-
- if "-h" in sys.argv or "--help" in sys.argv:
- config.print_usage("cumin-load-demo-data")
- sys.exit(0)
-
- config.init()
-
- if config.debug:
- config.prt()
-
- cumin = Cumin(config)
- cumin.check()
- cumin.init()
-
- data = DemoData()
- data.load()
-
-if __name__ == "__main__":
- try:
- main()
- except SystemExit, e:
- raise e
- except:
- print_exc()
- sys.exit(1)
Modified: mgmt/trunk/cumin/python/cumin/tools.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/tools.py 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/cumin/python/cumin/tools.py 2009-08-31 19:23:48 UTC (rev 3602)
@@ -3,11 +3,6 @@
from parsley.config import *
from parsley.command import *
from wooly.devel import *
-from mint import *
-from mint.tools import MintServerTool
-from getpass import getpass
-from psycopg2 import IntegrityError
-from subprocess import Popen
from time import sleep
from util import *
@@ -16,20 +11,6 @@
from cumin.server import CuminServer
from test import *
-def prompt_password():
- password = None
-
- while password is None:
- once = getpass("Enter new password: ")
- twice = getpass("Confirm new password: ")
-
- if once == twice:
- password = once
- else:
- print "Passwords don't match; try again"
-
- return password
-
class BaseCuminTool(Command):
def __init__(self, name):
super(BaseCuminTool, self).__init__(None, name)
@@ -69,19 +50,19 @@
if os.getuid() == 0:
os.setuid(os.stat(__file__).st_uid)
- self.config.init()
-
try:
import psyco
psyco.full()
except ImportError:
pass
+ self.config.init()
+
def run(self):
try:
opts, args = self.parse(sys.argv)
except CommandException, e:
- print "Error: %s" % e.message
+ print "Error: %s" % e
e.command.print_help()
sys.exit(1)
@@ -89,6 +70,11 @@
self.print_help()
sys.exit(0)
+ self.config.load_dict(opts)
+
+ if self.config.debug:
+ self.config.prt()
+
self.do_run(opts, args)
def do_run(self, opts, args):
@@ -99,365 +85,6 @@
self.init()
self.run()
-class CuminAdminTool(BaseCuminTool):
- def __init__(self, name):
- super(CuminAdminTool, self).__init__(name)
-
- self.description = "Cumin administration commands"
- self.database = None # Set in init
-
- command = self.CreateSchema(self, "create-schema")
- command.description = "Create the database schema"
-
- command = self.DropSchema(self, "drop-schema")
- command.description = "Drop the database schema; requires --force"
-
- opt = CommandOption(command, "force")
- opt.description = "Don't complain and just do it"
-
- command = self.AddQmfServer(self, "add-qmf-server")
- command.arguments = ("NAME", "URL")
- command.description = "Add a new QMF server called NAME at URL"
-
- command = self.RemoveQmfServer(self, "remove-qmf-server")
- command.arguments = ("URL",)
- command.description = "Remove QMF server called NAME; requires
--force"
-
- opt = CommandOption(command, "force")
- opt.description = "Don't complain and just do it"
-
- command = self.ListQmfServers(self, "list-qmf-servers")
- command.description = "List existing QMF servers"
-
- command = self.AddUser(self, "add-user")
- command.arguments = ("NAME", "[PASSWORD]")
- command.description = "Add a new user called NAME"
-
- command = self.RemoveUser(self, "remove-user")
- command.arguments = ("NAME",)
- command.description = "Remove user called NAME; requires --force"
-
- opt = CommandOption(command, "force")
- opt.description = "Don't complain and just do it"
-
- command = self.ListUsers(self, "list-users")
- command.description = "List existing users"
-
- command = self.ListRoles(self, "list-roles")
- command.description = "List existing roles"
-
- command = self.Assign(self, "assign")
- command.description = "Add USER to ROLE"
- command.arguments = ("USER", "ROLE")
-
- command = self.Unassign(self, "unassign")
- command.description = "Remove USER from ROLE"
- command.arguments = ("USER", "ROLE")
-
- command = self.ChangePassword(self, "change-password")
- command.description = "Change password of USER"
- command.arguments = ("USER",)
-
- def init(self):
- super(CuminAdminTool, self).init()
-
- config = MintConfig()
- config.init({"data": self.config.data})
-
- app = Mint(config)
- app.updateEnabled = False
- app.pollEnabled = False
- app.expireEnabled = False
-
- self.database = MintDatabase(app)
- self.database.check()
- self.database.init()
-
- def run(self):
- if self.config.debug:
- self.config.prt()
-
- try:
- opts, remaining = self.parse_options(sys.argv[1:])
- except CommandException, e:
- print "Error: %s" % e.message
- e.command.print_help()
- sys.exit(1)
-
- if "help" in opts:
- self.print_help()
- return
-
- try:
- scommand = remaining[0]
- except IndexError:
- self.print_help()
- sys.exit(1)
-
- try:
- command = self.commands_by_name[scommand]
- except KeyError:
- print "Error: Command '%s' is unrecognized" % scommand
- self.print_help()
- sys.exit(1)
-
- try:
- opts, args = command.parse(remaining)
- except CommandException, e:
- print "Error: %s" % e.message
- e.command.print_help()
- sys.exit(1)
-
- if "help" in opts:
- command.print_help()
- return
-
- try:
- command.run(opts, args)
- except CommandException, e:
- print "Error: %s" % e.message
- e.command.print_help()
- sys.exit(1)
-
- class CreateSchema(Command):
- def run(self, opts, args):
- main = os.path.join(self.parent.config.home, "sql",
"schema.sql")
- indexes = os.path.join(self.parent.config.home, "sql",
"indexes.sql")
- triggers = os.path.join(self.parent.config.home, "sql",
"triggers.sql")
-
- self.parent.database.createSchema((main, indexes, triggers))
-
- class DropSchema(Command):
- def run(self, opts, args):
- if "force" in opts:
- self.parent.database.dropSchema()
- print "The schema is dropped"
- else:
- raise CommandException \
- (self, "Command create-schema requires --force")
-
- class CheckSchema(Command):
- def run(self, opts, args):
- self.parent.database.checkSchema()
-
- class AddQmfServer(Command):
- def run(self, opts, args):
- try:
- name, url = args[1:]
- except IndexError:
- raise CommandException(self, "NAME and URL are required")
- except ValueError:
- raise CommandException(self, "NAME and URL are required")
-
- for reg in BrokerRegistration.selectBy(name=name):
- print "Error: a broker called '%s' already exists" %
name
- sys.exit(1)
-
- for reg in BrokerRegistration.selectBy(url=url):
- print "Error: a broker at %s already exists" % url
- sys.exit(1)
-
- url = url.strip()
-
- expr = re.compile("^amqps?://")
-
- if not expr.match(url):
- url = "amqp://%s" % url
-
- expr = re.compile(":[0-9]+$")
-
- if not expr.match(url):
- url = "%s:5672" % url
-
- reg = BrokerRegistration(name=name, url=url)
- reg.syncUpdate()
-
- class RemoveQmfServer(Command):
- def run(self, opts, args):
- try:
- name = args[1]
- except IndexError:
- raise CommandException(self, "NAME is required")
-
- for reg in BrokerRegistration.selectBy(name=name):
- break
-
- if reg:
- reg.destroySelf()
- reg.syncUpdate()
- else:
- raise CommandException \
- (self, "Broker '%s' is unknown", reg.name)
-
- class ListQmfServers(Command):
- def run(self, opts, args):
- regs = BrokerRegistration.select()
-
- print " ID Name URL"
- print "---- --------------------
---------------------------------"
-
- for reg in regs:
- print "%4i %-20s %-20s" % (reg.id, reg.name, reg.url)
-
- count = regs.count()
-
- print "(%i server%s found)" % (count, ess(count))
-
- class AddUser(Command):
- def run(self, opts, args):
- try:
- name = args[1]
- except IndexError:
- raise CommandException(self, "NAME is required")
-
- if Subject.selectBy(name=name).count():
- print "Error: a user called '%s' already exists" %
name
- sys.exit(1)
-
- try:
- password = args[2]
- except IndexError:
- password = prompt_password()
-
- crypted = crypt_password(password)
-
- try:
- subject = Subject(name=name, password=crypted)
-
- for role in Role.selectBy(name="user"):
- subject.addRole(role)
- break
-
- assert role
-
- subject.syncUpdate()
- except IntegrityError:
- print "Error: a user called '%s' already exists" %
name
- sys.exit(1)
-
- print "User '%s' is added" % name
-
- class RemoveUser(Command):
- def run(self, opts, args):
- if "force" in opts:
- if len(args) != 2:
- print "Error: no user name given"
- sys.exit(1)
-
- name = args[1]
- subjects = Subject.selectBy(name=name)
-
- if subjects.count():
- for subject in subjects:
- subject.destroySelf()
- break
- else:
- raise CommandException(self, "User '%s' is unknown"
% name)
-
- print "User '%s' is removed" % name
- else:
- raise CommandException \
- (self, "Command remove-user requires --force yes")
-
- class ListUsers(Command):
- def run(self, opts, args):
- subjects = Subject.select(orderBy='name')
-
- print " ID Name Roles"
- print "---- -------------------- --------------------"
-
- for subject in subjects:
- roles = ", ".join([x.name for x in list(subject.roles)])
-
- print "%4i %-20s %-20s" % (subject.id, subject.name, roles)
-
- count = subjects.count()
- print "(%i user%s found)" % (count, ess(count))
-
- class ListRoles(Command):
- def run(self, opts, args):
- roles = Role.select(orderBy='name')
-
- print " ID Name"
- print "---- --------------------"
-
- for role in roles:
- print "%4i %s" % (role.id, role.name)
-
- count = roles.count()
- print "(%i role%s found)" % (count, ess(count))
-
- class Assign(Command):
- def run(self, opts, args):
- if len(args) != 3:
- raise CommandException(self, "USER and ROLE are required")
-
- subject = Subject.getByName(args[1])
-
- if not subject:
- raise CommandException \
- (self, "User '%s' is unknown" % subject.name)
-
- role = Role.getByName(args[2])
-
- if not role:
- raise CommandException \
- (self, "Role '%s' is unknown" % role.name)
-
- try:
- subject.addRole(role)
- subject.syncUpdate()
-
- print "User '%s' is added to role '%s'" % \
- (subject.name, role.name)
- except IntegrityError:
- msg = "User '%s' is already assigned to role
'%s'" % \
- (subject.name, role.name)
- raise CommandException(self, msg)
-
- class Unassign(Command):
- def run(self, opts, args):
- if len(args) != 3:
- raise CommandException(self, "USER and ROLE are required")
-
- subject = Subject.getByName(args[1])
-
- if not subject:
- raise CommandException \
- (self, "User '%s' is unknown" % subject.name)
-
- role = Role.getByName(args[2])
-
- if not role:
- raise CommandException \
- (self, "Role '%s' is unknown" % role.name)
-
- subject.removeRole(role)
- subject.syncUpdate()
-
- print "User '%s' is removed from role '%s'" % \
- (subject.name, role.name)
-
- class ChangePassword(Command):
- def run(self, opts, args):
- try:
- ssubject = args[1]
- except IndexError:
- raise CommandException(self, "USER is required")
-
- subject = Subject.getByName(ssubject)
-
- if not subject:
- raise CommandException\
- (self, "User '%s' is unknown" % subject.name)
-
- crypted = crypt_password(prompt_password())
-
- subject.password = crypted
- subject.syncUpdate()
-
- print "Password of user '%s' is changed" % subject.name
-
class CuminServerTool(BaseCuminTool):
def __init__(self, name):
super(CuminServerTool, self).__init__(name)
@@ -485,13 +112,6 @@
opt.description = "Serve web pages using SSL"
def do_run(self, opts, args):
- self.config.load_dict(opts)
-
- self.config.ssl = "ssl" in opts
-
- if self.config.debug:
- self.config.prt()
-
app = Cumin(self.config)
try:
@@ -541,18 +161,12 @@
opt.description = "Use existing broker at ADDR"
def do_run(self, opts, args):
- self.config.load_dict(opts)
-
- if self.config.debug:
- self.config.prt()
-
app = Cumin(self.config)
try:
app.check()
except Exception, e:
- if hasattr(e, "message"):
- print e.message
+ print e
sys.exit(1)
@@ -598,18 +212,12 @@
opt.description = "Check that page output is well-formed xml"
def do_run(self, opts, args):
- self.config.load_dict(opts)
-
- if self.config.debug:
- self.config.prt()
-
app = Cumin(self.config)
try:
app.check()
except Exception, e:
- if hasattr(e, "message"):
- print e.message
+ print e
sys.exit(1)
Added: mgmt/trunk/mint/bin/mint-admin
===================================================================
--- mgmt/trunk/mint/bin/mint-admin (rev 0)
+++ mgmt/trunk/mint/bin/mint-admin 2009-08-31 19:23:48 UTC (rev 3602)
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+from mint.tools import MintAdminTool
+
+if __name__ == "__main__":
+ try:
+ tool = MintAdminTool("mint-admin")
+ tool.main()
+ except KeyboardInterrupt:
+ pass
Property changes on: mgmt/trunk/mint/bin/mint-admin
___________________________________________________________________
Name: svn:executable
+ *
Added: mgmt/trunk/mint/bin/mint-admin-test
===================================================================
--- mgmt/trunk/mint/bin/mint-admin-test (rev 0)
+++ mgmt/trunk/mint/bin/mint-admin-test 2009-08-31 19:23:48 UTC (rev 3602)
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+id="$RANDOM"
+code=0
+tmpdir=$(mktemp -d)
+trap "rm -rf ${tmpdir}" EXIT
+
+while read command; do
+ echo -n "Testing command '$command'..."
+
+ $command &> "${tmpdir}/output"
+
+ if [[ $? == 0 ]]; then
+ echo " OK"
+ else
+ echo
+ echo "Command failed with exit code $?"
+ echo "Output:"
+ cat "${tmpdir}/output"
+ code=1
+ fi
+done <<EOF
+mint-admin --help
+mint-admin add-user "$id" changeme
+mint-admin assign "$id" admin
+mint-admin unassign "$id" admin
+mint-admin list-users
+mint-admin remove-user "$id" --force
+mint-admin list-roles
+EOF
+
+exit "$code"
Property changes on: mgmt/trunk/mint/bin/mint-admin-test
___________________________________________________________________
Name: svn:executable
+ *
Added: mgmt/trunk/mint/bin/mint-demo
===================================================================
--- mgmt/trunk/mint/bin/mint-demo (rev 0)
+++ mgmt/trunk/mint/bin/mint-demo 2009-08-31 19:23:48 UTC (rev 3602)
@@ -0,0 +1,27 @@
+#!/bin/bash -e
+
+function check {
+ which psql > /dev/null
+ psql -d cumin -U cumin -h localhost -c '\q' || {
+ echo "The database is not ready; use mint-database to prepare it"
+ exit 1
+ }
+}
+
+case "$1" in
+ reload)
+ check
+ mint-admin reload-schema --force || :
+ mint-admin add-user guest guest
+ mint-admin assign guest admin
+ python -m mint.demo
+ ;;
+ *)
+ echo "Utilities for mint demos"
+ echo "Usage: mint-demo COMMAND"
+ echo "Commands:"
+ echo " reload Reload the schema and load a guest user"
+ echo " and demo data"
+ exit 1
+ ;;
+esac
Property changes on: mgmt/trunk/mint/bin/mint-demo
___________________________________________________________________
Name: svn:executable
+ *
Modified: mgmt/trunk/mint/python/mint/database.py
===================================================================
--- mgmt/trunk/mint/python/mint/database.py 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/mint/python/mint/database.py 2009-08-31 19:23:48 UTC (rev 3602)
@@ -1,3 +1,7 @@
+import logging
+import os.path
+
+from psycopg2 import ProgrammingError
from sqlobject import connectionForURI, sqlhub
from model import MintInfo, Role
@@ -2,2 +6,4 @@
+log = logging.getLogger("mint.database")
+
class MintDatabase(object):
@@ -33,7 +39,10 @@
try:
cursor = conn.cursor()
- cursor.execute("drop schema public cascade")
+ try:
+ cursor.execute("drop schema public cascade")
+ except ProgrammingError:
+ log.warn("The schema is already dropped")
conn.commit()
finally:
@@ -68,18 +77,25 @@
result.append(tmpStmt.lstrip())
return result
- def createSchema(self, file_paths):
- conn = self.getConnection()
+ def loadSchema(self):
+ paths = list()
+ paths.append(os.path.join(self.app.config.home, "sql",
"schema.sql"))
+ paths.append(os.path.join(self.app.config.home, "sql",
"indexes.sql"))
+ paths.append(os.path.join(self.app.config.home, "sql",
"triggers.sql"))
+
scripts = list()
- for path in file_paths:
+ for path in paths:
file = open(path, "r")
+
try:
scripts.append((path, file.read()))
finally:
file.close()
+ conn = self.getConnection()
+
try:
cursor = conn.cursor()
Added: mgmt/trunk/mint/python/mint/demo.py
===================================================================
--- mgmt/trunk/mint/python/mint/demo.py (rev 0)
+++ mgmt/trunk/mint/python/mint/demo.py 2009-08-31 19:23:48 UTC (rev 3602)
@@ -0,0 +1,18 @@
+from mint import *
+
+class DemoData(object):
+ def load(self):
+ for name in ("Engineering", "Marketing", "Sales"):
+ group = BrokerGroup(name=name)
+ group.syncUpdate()
+
+if __name__ == "__main__":
+ config = MintConfig()
+ config.init()
+
+ app = Mint(config)
+ app.check()
+ app.init()
+
+ data = DemoData()
+ data.load()
Modified: mgmt/trunk/mint/python/mint/tools.py
===================================================================
--- mgmt/trunk/mint/python/mint/tools.py 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/mint/python/mint/tools.py 2009-08-31 19:23:48 UTC (rev 3602)
@@ -54,11 +54,13 @@
except ImportError:
pass
+ self.config.init()
+
def run(self):
try:
opts, args = self.parse(sys.argv)
except CommandException, e:
- print "Error: %s" % e.message
+ print "Error: %s" % e
e.command.print_help()
sys.exit(1)
@@ -66,8 +68,11 @@
self.print_help()
sys.exit(0)
- self.config.init(opts)
+ self.config.load_dict(opts)
+ if self.config.debug:
+ self.config.prt()
+
self.do_run(opts, args)
def do_run(self, opts, args):
@@ -78,6 +83,298 @@
self.init()
self.run()
+class MintAdminTool(BaseMintTool):
+ def __init__(self, name):
+ super(MintAdminTool, self).__init__(name)
+
+ self.description = "Mint administration commands"
+ self.database = None # Set in init
+
+ command = self.LoadSchema(self, "load-schema")
+ command.description = "Load the database schema"
+
+ command = self.DropSchema(self, "drop-schema")
+ command.description = "Drop the database schema; requires --force"
+
+ opt = CommandOption(command, "force")
+ opt.description = "Don't complain and just do it"
+
+ command = self.ReloadSchema(self, "reload-schema")
+ command.description = "Drop and reload the database schema; " + \
+ "requires --force"
+
+ opt = CommandOption(command, "force")
+ opt.description = "Don't complain and just do it"
+
+ command = self.AddUser(self, "add-user")
+ command.arguments = ("NAME", "[PASSWORD]")
+ command.description = "Add a new user called NAME"
+
+ command = self.RemoveUser(self, "remove-user")
+ command.arguments = ("NAME",)
+ command.description = "Remove user called NAME; requires --force"
+
+ opt = CommandOption(command, "force")
+ opt.description = "Don't complain and just do it"
+
+ command = self.ListUsers(self, "list-users")
+ command.description = "List existing users"
+
+ command = self.ListRoles(self, "list-roles")
+ command.description = "List existing roles"
+
+ command = self.Assign(self, "assign")
+ command.description = "Add USER to ROLE"
+ command.arguments = ("USER", "ROLE")
+
+ command = self.Unassign(self, "unassign")
+ command.description = "Remove USER from ROLE"
+ command.arguments = ("USER", "ROLE")
+
+ command = self.ChangePassword(self, "change-password")
+ command.description = "Change password of USER"
+ command.arguments = ("USER",)
+
+ def run(self):
+ try:
+ opts, remaining = self.parse_options(sys.argv[1:])
+ except CommandException, e:
+ print "Error: %s" % e
+ e.command.print_help()
+ sys.exit(1)
+
+ if "help" in opts:
+ self.print_help()
+ return
+
+ self.config.load_dict(opts)
+
+ if self.config.debug:
+ self.config.prt()
+
+ app = Mint(self.config)
+ app.updateEnabled = False
+ app.pollEnabled = False
+ app.expireEnabled = False
+
+ self.database = MintDatabase(app)
+ self.database.check()
+ self.database.init()
+
+ try:
+ scommand = remaining[0]
+ except IndexError:
+ self.print_help()
+ sys.exit(1)
+
+ try:
+ command = self.commands_by_name[scommand]
+ except KeyError:
+ print "Error: Command '%s' is unrecognized" % scommand
+ self.print_help()
+ sys.exit(1)
+
+ try:
+ opts, args = command.parse(remaining)
+ except CommandException, e:
+ print "Error: %s" % e
+ e.command.print_help()
+ sys.exit(1)
+
+ if "help" in opts:
+ command.print_help()
+ return
+
+ try:
+ command.run(opts, args)
+ except CommandException, e:
+ print "Error: %s" % e
+ e.command.print_help()
+ sys.exit(1)
+
+ class LoadSchema(Command):
+ def run(self, opts, args):
+ self.parent.database.loadSchema()
+ print "The schema is loaded"
+
+ class DropSchema(Command):
+ def run(self, opts, args):
+ if "force" in opts:
+ self.parent.database.dropSchema()
+ print "The schema is dropped"
+ else:
+ raise CommandException \
+ (self, "Command drop-schema requires --force")
+
+ class ReloadSchema(Command):
+ def run(self, opts, args):
+ if "force" in opts:
+ self.parent.database.dropSchema()
+ self.parent.database.loadSchema()
+ print "The schema is reloaded"
+ else:
+ raise CommandException \
+ (self, "Command reload-schema requires --force")
+
+ class CheckSchema(Command):
+ def run(self, opts, args):
+ self.parent.database.checkSchema()
+
+ class AddUser(Command):
+ def run(self, opts, args):
+ try:
+ name = args[1]
+ except IndexError:
+ raise CommandException(self, "NAME is required")
+
+ if Subject.selectBy(name=name).count():
+ print "Error: a user called '%s' already exists" %
name
+ sys.exit(1)
+
+ try:
+ password = args[2]
+ except IndexError:
+ password = prompt_password()
+
+ crypted = crypt_password(password)
+
+ try:
+ subject = Subject(name=name, password=crypted)
+
+ for role in Role.selectBy(name="user"):
+ subject.addRole(role)
+ break
+
+ assert role
+
+ subject.syncUpdate()
+ except IntegrityError:
+ print "Error: a user called '%s' already exists" %
name
+ sys.exit(1)
+
+ print "User '%s' is added" % name
+
+ class RemoveUser(Command):
+ def run(self, opts, args):
+ if "force" in opts:
+ if len(args) != 2:
+ print "Error: no user name given"
+ sys.exit(1)
+
+ name = args[1]
+ subjects = Subject.selectBy(name=name)
+
+ if subjects.count():
+ for subject in subjects:
+ subject.destroySelf()
+ break
+ else:
+ raise CommandException(self, "User '%s' is unknown"
% name)
+
+ print "User '%s' is removed" % name
+ else:
+ raise CommandException \
+ (self, "Command remove-user requires --force yes")
+
+ class ListUsers(Command):
+ def run(self, opts, args):
+ subjects = Subject.select(orderBy='name')
+
+ print " ID Name Roles"
+ print "---- -------------------- --------------------"
+
+ for subject in subjects:
+ roles = ", ".join([x.name for x in list(subject.roles)])
+
+ print "%4i %-20s %-20s" % (subject.id, subject.name, roles)
+
+ count = subjects.count()
+ print "(%i user%s found)" % (count, ess(count))
+
+ class ListRoles(Command):
+ def run(self, opts, args):
+ roles = Role.select(orderBy='name')
+
+ print " ID Name"
+ print "---- --------------------"
+
+ for role in roles:
+ print "%4i %s" % (role.id, role.name)
+
+ count = roles.count()
+ print "(%i role%s found)" % (count, ess(count))
+
+ class Assign(Command):
+ def run(self, opts, args):
+ if len(args) != 3:
+ raise CommandException(self, "USER and ROLE are required")
+
+ subject = Subject.getByName(args[1])
+
+ if not subject:
+ raise CommandException \
+ (self, "User '%s' is unknown" % subject.name)
+
+ role = Role.getByName(args[2])
+
+ if not role:
+ raise CommandException \
+ (self, "Role '%s' is unknown" % role.name)
+
+ try:
+ subject.addRole(role)
+ subject.syncUpdate()
+
+ print "User '%s' is added to role '%s'" % \
+ (subject.name, role.name)
+ except IntegrityError:
+ msg = "User '%s' is already assigned to role
'%s'" % \
+ (subject.name, role.name)
+ raise CommandException(self, msg)
+
+ class Unassign(Command):
+ def run(self, opts, args):
+ if len(args) != 3:
+ raise CommandException(self, "USER and ROLE are required")
+
+ subject = Subject.getByName(args[1])
+
+ if not subject:
+ raise CommandException \
+ (self, "User '%s' is unknown" % args[1])
+
+ role = Role.getByName(args[2])
+
+ if not role:
+ raise CommandException \
+ (self, "Role '%s' is unknown" % args[2])
+
+ subject.removeRole(role)
+ subject.syncUpdate()
+
+ print "User '%s' is removed from role '%s'" % \
+ (subject.name, role.name)
+
+ class ChangePassword(Command):
+ def run(self, opts, args):
+ try:
+ ssubject = args[1]
+ except IndexError:
+ raise CommandException(self, "USER is required")
+
+ subject = Subject.getByName(ssubject)
+
+ if not subject:
+ raise CommandException \
+ (self, "User '%s' is unknown" % ssubject)
+
+ crypted = crypt_password(prompt_password())
+
+ subject.password = crypted
+ subject.syncUpdate()
+
+ print "Password of user '%s' is changed" % subject.name
+
class MintServerTool(BaseMintTool):
def __init__(self, name):
super(MintServerTool, self).__init__(name)
Modified: mgmt/trunk/mint/python/mint/util.py
===================================================================
--- mgmt/trunk/mint/python/mint/util.py 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/mint/python/mint/util.py 2009-08-31 19:23:48 UTC (rev 3602)
@@ -1,8 +1,11 @@
import sys, os, logging
+from crypt import crypt
+from getpass import getpass
+from random import sample
from threading import Thread
-log = logging.getLogger("mint")
+log = logging.getLogger("mint.util")
class MintDaemonThread(Thread):
def __init__(self, app):
@@ -20,3 +23,28 @@
def stop(self):
assert self.stopRequested is False
self.stopRequested = True
+
+def prompt_password():
+ password = None
+
+ while password is None:
+ once = getpass("Enter new password: ")
+ twice = getpass("Confirm new password: ")
+
+ if once == twice:
+ password = once
+ else:
+ print "Passwords don't match; try again"
+
+ return password
+
+password_chars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+
+def crypt_password(password, salt=None):
+ if not salt:
+ salt = "".join(sample(password_chars, 2))
+
+ return crypt(password, salt)
+
+def ess(num, ending="s"):
+ return num != 1 and ending or ""
Modified: mgmt/trunk/parsley/python/parsley/command.py
===================================================================
--- mgmt/trunk/parsley/python/parsley/command.py 2009-08-31 17:13:12 UTC (rev 3601)
+++ mgmt/trunk/parsley/python/parsley/command.py 2009-08-31 19:23:48 UTC (rev 3602)
@@ -159,5 +159,6 @@
class CommandException(Exception):
def __init__(self, command, message):
+ super(CommandException, self).__init__(message)
+
self.command = command
- self.message = message