--- a/cwctl.py Wed Apr 28 10:06:01 2010 +0200
+++ b/cwctl.py Wed Apr 28 12:21:48 2010 +0200
@@ -26,6 +26,7 @@
# possible (for cubicweb-ctl reactivity, necessary for instance for usable bash
# completion). So import locally in command helpers.
import sys
+from warnings import warn
from os import remove, listdir, system, pathsep
try:
from os import kill, getpgid
@@ -98,7 +99,7 @@
Instance used by another one should appears first in the file (one
instance per line)
"""
- regdir = cwcfg.registry_dir()
+ regdir = cwcfg.instances_dir()
_allinstances = list_instances(regdir)
if isfile(join(regdir, 'startorder')):
allinstances = []
@@ -132,29 +133,33 @@
self.run_args(args, askconfirm)
def run_args(self, args, askconfirm):
+ status = 0
for appid in args:
if askconfirm:
print '*'*72
if not ASK.confirm('%s instance %r ?' % (self.name, appid)):
continue
- self.run_arg(appid)
+ status = max(status, self.run_arg(appid))
+ sys.exit(status)
def run_arg(self, appid):
cmdmeth = getattr(self, '%s_instance' % self.name)
try:
- cmdmeth(appid)
+ status = cmdmeth(appid)
except (KeyboardInterrupt, SystemExit):
print >> sys.stderr, '%s aborted' % self.name
- sys.exit(2) # specific error code
+ return 2 # specific error code
except (ExecutionError, ConfigurationError), ex:
print >> sys.stderr, 'instance %s not %s: %s' % (
appid, self.actionverb, ex)
+ status = 4
except Exception, ex:
import traceback
traceback.print_exc()
print >> sys.stderr, 'instance %s not %s: %s' % (
appid, self.actionverb, ex)
-
+ status = 8
+ return status
class InstanceCommandFork(InstanceCommand):
"""Same as `InstanceCommand`, but command is forked in a new environment
@@ -181,86 +186,6 @@
# base commands ###############################################################
-def version_strictly_lower(a, b):
- from logilab.common.changelog import Version
- if a:
- a = Version(a)
- if b:
- b = Version(b)
- return a < b
-
-def max_version(a, b):
- from logilab.common.changelog import Version
- return str(max(Version(a), Version(b)))
-
-class ConfigurationProblem(object):
- """Each cube has its own list of dependencies on other cubes/versions.
-
- The ConfigurationProblem is used to record the loaded cubes, then to detect
- inconsistencies in their dependencies.
-
- See configuration management on wikipedia for litterature.
- """
-
- def __init__(self):
- self.cubes = {}
-
- def add_cube(self, name, info):
- self.cubes[name] = info
-
- def solve(self):
- self.warnings = []
- self.errors = []
- self.read_constraints()
- for cube, versions in sorted(self.constraints.items()):
- oper, version = None, None
- # simplify constraints
- if versions:
- for constraint in versions:
- op, ver = constraint
- if oper is None:
- oper = op
- version = ver
- elif op == '>=' and oper == '>=':
- version = max_version(ver, version)
- else:
- print 'unable to handle this case', oper, version, op, ver
- # "solve" constraint satisfaction problem
- if cube not in self.cubes:
- self.errors.append( ('add', cube, version) )
- elif versions:
- lower_strict = version_strictly_lower(self.cubes[cube].version, version)
- if oper in ('>=','='):
- if lower_strict:
- self.errors.append( ('update', cube, version) )
- else:
- print 'unknown operator', oper
-
- def read_constraints(self):
- self.constraints = {}
- self.reverse_constraints = {}
- for cube, info in self.cubes.items():
- if hasattr(info,'__depends_cubes__'):
- use = info.__depends_cubes__
- if not isinstance(use, dict):
- use = dict((key, None) for key in use)
- self.warnings.append('cube %s should define __depends_cubes__ as a dict not a list')
- elif hasattr(info, '__use__'):
- self.warnings.append('cube %s should define __depends_cubes__' % cube)
- use = dict((key, None) for key in info.__use__)
- else:
- continue
- for name, constraint in use.items():
- self.constraints.setdefault(name,set())
- if constraint:
- try:
- oper, version = constraint.split()
- self.constraints[name].add( (oper, version) )
- except:
- self.warnings.append('cube %s depends on %s but constraint badly formatted: %s'
- % (cube, name, constraint))
- self.reverse_constraints.setdefault(name, set()).add(cube)
-
class ListCommand(Command):
"""List configurations, cubes and instances.
@@ -277,6 +202,7 @@
"""run the command with its specific arguments"""
if args:
raise BadCommandUsage('Too much arguments')
+ from cubicweb.migration import ConfigurationProblem
print 'CubicWeb %s (%s mode)' % (cwcfg.cubicweb_version(), cwcfg.mode)
print
print 'Available configurations:'
@@ -288,7 +214,7 @@
continue
print ' ', line
print
- cfgpb = ConfigurationProblem()
+ cfgpb = ConfigurationProblem(cwcfg)
try:
cubesdir = pathsep.join(cwcfg.cubes_search_path())
namesize = max(len(x) for x in cwcfg.available_cubes())
@@ -299,26 +225,31 @@
else:
print 'Available cubes (%s):' % cubesdir
for cube in cwcfg.available_cubes():
- if cube in ('CVS', '.svn', 'shared', '.hg'):
- continue
try:
tinfo = cwcfg.cube_pkginfo(cube)
tversion = tinfo.version
- cfgpb.add_cube(cube, tinfo)
+ cfgpb.add_cube(cube, tversion)
except ConfigurationError:
tinfo = None
tversion = '[missing cube information]'
print '* %s %s' % (cube.ljust(namesize), tversion)
if self.config.verbose:
- shortdesc = tinfo and (getattr(tinfo, 'short_desc', '')
- or tinfo.__doc__)
- if shortdesc:
- print ' '+ ' \n'.join(shortdesc.splitlines())
+ if tinfo:
+ descr = getattr(tinfo, 'description', '')
+ if not descr:
+ descr = getattr(tinfo, 'short_desc', '')
+ if descr:
+ warn('[3.8] short_desc is deprecated, update %s'
+ ' pkginfo' % cube, DeprecationWarning)
+ else:
+ descr = tinfo.__doc__
+ if descr:
+ print ' '+ ' \n'.join(descr.splitlines())
modes = detect_available_modes(cwcfg.cube_dir(cube))
print ' available modes: %s' % ', '.join(modes)
print
try:
- regdir = cwcfg.registry_dir()
+ regdir = cwcfg.instances_dir()
except ConfigurationError, ex:
print 'No instance available:', ex
print
@@ -423,7 +354,7 @@
helper.bootstrap(cubes, self.config.config_level)
# input for cubes specific options
for section in set(sect.lower() for sect, opt, optdict in config.all_options()
- if optdict.get('inputlevel') <= self.config.config_level):
+ if optdict.get('level') <= self.config.config_level):
if section not in ('main', 'email', 'pyro'):
print '\n' + underline_title('%s options' % section)
config.input_config(section, self.config.config_level)
@@ -626,7 +557,7 @@
actionverb = 'restarted'
def run_args(self, args, askconfirm):
- regdir = cwcfg.registry_dir()
+ regdir = cwcfg.instances_dir()
if not isfile(join(regdir, 'startorder')) or len(args) <= 1:
# no specific startorder
super(RestartInstanceCommand, self).run_args(args, askconfirm)
@@ -680,6 +611,7 @@
@staticmethod
def status_instance(appid):
"""print running status information for an instance"""
+ status = 0
for mode in cwcfg.possible_configurations(appid):
config = cwcfg.config_for(appid, mode)
print '[%s-%s]' % (appid, mode),
@@ -690,6 +622,7 @@
continue
if not exists(pidf):
print "doesn't seem to be running"
+ status = 1
continue
pid = int(open(pidf).read().strip())
# trick to guess whether or not the process is running
@@ -697,9 +630,10 @@
getpgid(pid)
except OSError:
print "should be running with pid %s but the process can not be found" % pid
+ status = 1
continue
print "running with pid %s" % (pid)
-
+ return status
class UpgradeInstanceCommand(InstanceCommandFork):
"""Upgrade an instance after cubicweb and/or component(s) upgrade.
@@ -968,7 +902,7 @@
def run(self, args):
"""run the command with its specific arguments"""
- regdir = cwcfg.registry_dir()
+ regdir = cwcfg.instances_dir()
for appid in sorted(listdir(regdir)):
print appid