From 445940543a0469fe0476d0a1d6b5f4846e7349b8 Mon Sep 17 00:00:00 2001 From: jmoore Date: Tue, 27 May 2008 14:11:41 +0000 Subject: [PATCH] OmeroShell : Fixes after first deployments * Disabling ICE_CONFIG * Passing rest of os.environ on to all subprocess.Popen calls * Hopefully clarified `missing registry` commands * Now deploying etc/grid/default.xml by default * Removed `` from default.xml to prevent `patch failed` warnings * Fixed error messages on `admin start` and `node stop` * Added tail_lines from ASPN cookbook * Added `NonZeroReturnCode` exception git-svn-id: file:///home/svn/omero/trunk@2426 05709c45-44f0-0310-885b-81a1db45b4a6 --- src/omero/cli.py | 109 +++++++++++++++++++++++-------------- src/omero/plugins/admin.py | 40 +++++++++----- src/omero/plugins/node.py | 50 +++++++++++++++-- 3 files changed, 138 insertions(+), 61 deletions(-) diff --git a/src/omero/cli.py b/src/omero/cli.py index 6503c9348..8afd5651a 100755 --- a/src/omero/cli.py +++ b/src/omero/cli.py @@ -63,6 +63,16 @@ # allowing users to do something of the form: on_success or on_fail +##################################################### +# +# Exceptions +# +class NonZeroReturnCode(Exc): + def __init__(self, rv, *args): + self.rv = rv + Exc.__init__(self, *args) + + ##################################################### # class Arguments: @@ -284,21 +294,22 @@ def _icedata(self, property): """ try: nodepath = self._properties()[property] - except KeyError, ke: - self.ctx.err(property + " is not configured") - self.ctx.die(4, ke) - if RELFILE.match(nodepath): - nodedata = OMERODIR / path(nodepath) - else: - nodedata = path(nodepath) + if RELFILE.match(nodepath): + nodedata = OMERODIR / path(nodepath) + else: + nodedata = path(nodepath) - created = False - if not nodedata.exists(): - self.ctx.out("Creating "+nodedata) - nodedata.makedirs() - created = True - return (nodedata, created) + created = False + if not nodedata.exists(): + self.ctx.out("Creating "+nodedata) + nodedata.makedirs() + created = True + return (nodedata, created) + + except KeyError, ke: + self.ctx.err(property + " is not configured") + self.ctx.die(4, str(ke)) def _nodedata(self): """ @@ -324,9 +335,14 @@ def _regdata(self): if created: self.ctx.out(""" Warning: - IceGrid.Registry.Data directory not present (%s). - You need to run "admin deploy" after this command - or no servers will be started. + %s, + the IceGrid.Registry.Data directory is not present. + This is the first time you've started OmeroGrid. + + No servers have been deployed yet. To do so, you + will need to run "admin deploy" after the following + initialization. See the files under etc/grid/ for + example application descriptors. This warning will not be shown again. """ % data) @@ -382,8 +398,7 @@ def _properties(self, prefix=""): try: self._props.load(str(cfg)) except Exc, exc: - self.ctx.err("Could not find file: "+cfg) - self.ctx.die(3, exc) + self.ctx.die(3, "Could not find file: "+cfg + "\nDid you specify the proper node?") return self._props.getPropertiesForPrefix(prefix) ############################################### @@ -542,7 +557,9 @@ def onecmd(self, line): self.err(str(ae)) if DEBUG: traceback.print_exc() - return False # Continue + except NonZeroReturnCode, nzrc: + self.rv = nzrc.rv + return False # Continue def postcmd(self, stop, line): return self.interrupt_loop @@ -599,9 +616,11 @@ def exit(self, args): self.out(args) self.interrupt_loop = True - def die(self, rc, args): - self.err(args) + def die(self, rc, text): + self.err(text) + self.rv = rc self.interrupt_loop = True + raise NonZeroReturnCode(rc, "die called") def pub(self, args): """ @@ -624,9 +643,9 @@ def popen(self, args, strict = True): """ Calls the string in a subprocess and dies if the return value is not 0 """ - rv = subprocess.call(args) + rv = subprocess.call(args, env = os.environ) if strict and not rv == 0: - self.die(rv, "Error during:\"%s\"" % str(args) ) + raise NonZeroReturnCode(rv, "%s => %d" % (" ".join(args), rv)) return rv def conn(self, properties={}, profile=None): @@ -686,6 +705,8 @@ def do_method(self, *args): try: self._setup() return self.control.__call__(*args) + except NonZeroReturnCode, nzrc: + raise except Exc, exc: if DEBUG: traceback.print_exc() @@ -741,20 +762,28 @@ def argv(args=pysys.argv): Finally, the cli enters a command loop reading from standard in. """ - # Modifying the args list if the name of the file - # has arguments encoded in it - if args[0].find("-") >= 0: - parts = args[0].split("-") - for arg in args[1:]: - parts.append(arg) - args = parts - - cli = CLI() - cli.loadplugins() - - if len(args) > 1: - cli.invoke(args[1:]) - return cli.rv - else: - cli.invokeloop() - return cli.rv + # Modiying the run-time environment + old_ice_config = os.getenv("ICE_CONFIG") + os.unsetenv("ICE_CONFIG") + try: + + # Modifying the args list if the name of the file + # has arguments encoded in it + if args[0].find("-") >= 0: + parts = args[0].split("-") + for arg in args[1:]: + parts.append(arg) + args = parts + + cli = CLI() + cli.loadplugins() + + if len(args) > 1: + cli.invoke(args[1:]) + return cli.rv + else: + cli.invokeloop() + return cli.rv + finally: + if old_ice_config: + os.putenv("ICE_CONFIG", old_ice_config) diff --git a/src/omero/plugins/admin.py b/src/omero/plugins/admin.py index 37ae71e6e..d64f9a1bb 100644 --- a/src/omero/plugins/admin.py +++ b/src/omero/plugins/admin.py @@ -17,6 +17,7 @@ from omero.cli import Arguments from omero.cli import BaseControl +from omero.cli import NonZeroReturnCode from omero_ext import pysys class AdminControl(BaseControl): @@ -27,12 +28,16 @@ def help(self, args = None): : No argument opens a command shell - adduser login first last : Add user - check : Run various checks on the installation. Done automatically for some commands. deploy filename [ targets ] : Deploy the given deployment descriptor. See etc/grid/*.xml + : If the first argument is not a file path, etc/grid/default.xml + : will be deployed by default. + start : Start server daemon and return immediately. + stop : Send server stop command and return immediately. + status : Status of server + ice [arg1 arg2 ...] : Drop user into icegridadmin console or execute arguments """) @@ -84,7 +89,7 @@ def start(self, args): then registers the action: "node HOST start" """ props = self._properties() - # Do the check + # Do a check to see if we've started before. self._regdata() self.check([]) self.ctx.pub(["node", self._node(), "start"]) @@ -106,18 +111,21 @@ def deploy(self, args): command = self._cmd() first,other = args.firstOther() - if first == None or len(first) == 0: - self.ctx.err("No file given") - else: + descrpt = None + targets = " ".join(other) + + if first != None and len(first) > 0: # Relative to cwd descrpt = path(first) - targets = " ".join(other) - if not descrpt.exists(): - self.ctx.err("%s does not exist" % str(path)) - else: - command = command + ["-e","application add %s %s" % (descrpt, targets) ] - self.ctx.popen(command) + if descrpt == None or not descrpt.exists(): + # If descript is not a file, then it must be a target + targets = " ".join([str(descrpt), targets]) + descrpt = self.dir / "etc" / "grid" / "default.xml" + self.ctx.err("No descriptor given. Using etc/grid/default.xml") + + command = command + ["-e","application add %s %s" % (descrpt, targets) ] + self.ctx.popen(command) def status(self, args): args = Arguments(args) @@ -141,9 +149,11 @@ def status(self, args): def stop(self, args): command = self._cmd("-e","node shutdown master") - self.ctx.popen(command) - # Was: - # self.ctx.pub(["node", self._node(), "stop"]) + try: + self.ctx.popen(command) + except NonZeroReturnCode, nzrc: + self.ctx.rv = nzrv.rv + self.ctx.out("Was the server already stopped?") def check(self, args): # print "Check db. Have a way to load the db control" diff --git a/src/omero/plugins/node.py b/src/omero/plugins/node.py index d4f5d6e64..31a2f9533 100644 --- a/src/omero/plugins/node.py +++ b/src/omero/plugins/node.py @@ -19,6 +19,39 @@ RE=re.compile("^\s*(\S*)\s*(start|stop|restart|status)\s*(\S*)\s*$") +#From: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/157035 +def tail_lines(filename,linesback=10,returnlist=0): + """Does what "tail -10 filename" would have done + Parameters: + filename file to read + linesback Number of lines to read from end of file + returnlist Return a list containing the lines instead of a string + + """ + avgcharsperline=75 + + file = open(filename,'r') + while 1: + try: file.seek(-1 * avgcharsperline * linesback,2) + except IOError: file.seek(0) + if file.tell() == 0: atstart=1 + else: atstart=0 + + lines=file.read().split("\n") + if (len(lines) > (linesback+1)) or atstart: break + #The lines are bigger than we thought + avgcharsperline=avgcharsperline * 1.3 #Inc avg for retry + file.close() + + if len(lines) > linesback: start=len(lines)-linesback -1 + else: start=0 + if returnlist: return lines[start:len(lines)-1] + + out="" + for l in lines[start:len(lines)-1]: out=out + l + "\n" + return out + + class NodeControl(BaseControl): def help(self, args = None): @@ -73,12 +106,11 @@ def __call__(self, *args): for act in acts: c = getattr(self, act) c(name, sync) + finally: + pass - except Exc, ex: - import traceback - traceback.print_exc() - self.ctx.dbg(str(ex)) - self.ctx.die(100, "Bad argument: "+ str(first) + ", " + ", ".join(other)) + #self.ctx.dbg(str(ex)) + #self.ctx.die(100, "Bad argument: "+ str(first) + ", " + ", ".join(other)) ############################################## # @@ -102,7 +134,13 @@ def start(self, name = None, sync = False): props = self._properties() command = ["icegridnode", self._icecfg()] command = command + ["--daemon", "--pidfile", str(self._pid()),"--nochdir"] - self.ctx.popen(command) + try: + self.ctx.popen(command) + except NonZeroReturnCode, nzrc: + self.ctx.rv = nzrc.rv + myoutput = path(props["Ice.StdErr"]) + print "from %s:" % str(myoutput) + print tail_lines(str(myoutput),2) def status(self, name = None):