Package omero :: Package plugins :: Module admin
[hide private]
[frames] | no frames]

Source Code for Module omero.plugins.admin

  1  #!/usr/bin/env python 
  2  """ 
  3   :author: Josh Moore, josh at glencoesoftware.com 
  4   
  5   OMERO Grid admin controller 
  6   
  7   This is a python wrapper around icegridregistry/icegridnode for master 
  8   and various other tools needed for administration. 
  9   
 10   Copyright 2008 Glencoe Software, Inc.  All Rights Reserved. 
 11   Use is subject to license terms supplied in LICENSE.txt 
 12   
 13  """ 
 14   
 15  import re 
 16  import os 
 17  import sys 
 18  import stat 
 19  import platform 
 20  import exceptions 
 21  import portalocker 
 22   
 23  from path import path 
 24   
 25  import omero 
 26  import omero.config 
 27   
 28  from omero.cli import CLI 
 29  from omero.cli import BaseControl 
 30  from omero.cli import DirectoryType 
 31  from omero.cli import NonZeroReturnCode 
 32  from omero.cli import VERSION 
 33   
 34  from omero.plugins.prefs import with_config 
 35   
 36  from omero_ext.which import whichall 
 37   
 38  try: 
 39      import win32service 
 40      import win32evtlogutil 
 41      has_win32 = True 
 42  except ImportError: 
 43      has_win32 = False 
 44   
 45  HELP="""Administrative tools including starting/stopping OMERO. 
 46   
 47  Environment variables: 
 48   OMERO_MASTER 
 49   OMERO_NODE 
 50   
 51  Configuration properties: 
 52   omero.windows.user 
 53   omero.windows.pass 
 54   
 55  """ + "\n" + "="*50 + "\n" 
56 57 58 -class AdminControl(BaseControl):
59
60 - def _complete(self, text, line, begidx, endidx):
61 """ 62 Returns a file after "deploy", "start", or "startasync" 63 and otherwise delegates to the BaseControl 64 """ 65 for s in (" deploy ", " start ", " startasync "): 66 l = len(s) 67 i = line.find(s) 68 if i >= 0: 69 f = line[i+l:] 70 return self._complete_file(f) 71 return BaseControl._complete(self, text, line, begidx, endidx)
72
73 - def _configure(self, parser):
74 sub = parser.sub() 75 self.actions = {} 76 77 class Action(object): 78 def __init__(this, name, help): 79 this.parser = sub.add_parser(name, help=help, description=help) 80 this.parser.set_defaults(func=getattr(self, name)) 81 self.actions[name] = this.parser
82 83 Action("start", """Start icegridnode daemon and waits for required components to come up, i.e. status == 0 84 85 If the first argument can be found as a file, it will 86 be deployed as the application descriptor rather than 87 etc/grid/default.xml. All other arguments will be used 88 as targets to enable optional sections of the descriptor""") 89 90 Action("startasync", """The same as start but returns immediately.""",) 91 92 Action("restart", """stop && start""",) 93 94 Action("restartasync", """The same as restart but returns as soon as starting has begun.""",) 95 96 Action("status", """Status of server. 97 Returns with 0 status if a node ping is successful 98 and if some SessionManager returns an OMERO-specific exception on 99 a bad login. This can be used in shell scripts, e.g.: 100 101 omero admin status && echo "server started" 102 """) 103 104 Action("stop", """Initiates node shutdown and waits for status to return a non-0 value""") 105 106 Action("stopasync", """The same as stop but returns immediately.""") 107 108 Action("deploy", """Deploy the given deployment descriptor. See etc/grid/*.xml 109 If the first argument is not a file path, etc/grid/default.xml 110 will be deployed by default. Same functionality as start, but 111 requires that the node already be running. This may automatically 112 restart some server components.""") 113 114 Action("ice", """Drop user into icegridadmin console or execute arguments""") 115 116 Action("diagnostics", """Run a set of checks on the current, preferably active server""") 117 118 Action("waitup", """Used by start after calling startasync to wait on status==0""") 119 120 Action("waitdown", """Used by stop after calling stopasync to wait on status!=0""") 121 122 reindex = Action("reindex", """Re-index the Lucene index 123 124 Command-line tool for re-index the database. This command must be run on the machine where 125 /OMERO/FullText is located. 126 127 Examples: 128 bin/omero admin reindex --full # All objects 129 bin/omero admin reindex --reindex ome.model.core.Image # Only images 130 JAVA_OPTS="-Dlog4j.configuration=stderr.xml" bin/omero admin reindex --full # Passing arguments to Java 131 132 133 LIMITATION: omero.db.pass values do not currently get passed to the Java process. You will 134 need to all passwordless login to PostgreSQL. In fact, only the following properties 135 are passed: 136 137 omero.data.dir 138 omero.search.* 139 omero.db.* (excluding pass) 140 141 """).parser 142 reindex.add_argument("--jdwp", help = "Activate remote debugging") 143 group = reindex.add_mutually_exclusive_group() 144 group.add_argument("--full", action="store_true", help = "Reindexes all non-excluded tables sequentially") 145 group.add_argument("--events", action="store_true", help = "Reindexes all non-excluded event logs chronologically") 146 group.add_argument("--class", nargs="+", help = "Reindexes the given classes sequentially") 147 148 ports = Action("ports", """Allows modifying the ports from a standard OMERO install 149 150 To have two OMERO's running on the same machine, several ports must be modified from their default values. 151 Internally, this command uses the omero.install.change_ports module. Changing the ports on a running server 152 is usually not what you want and will be prevented. Use --skipcheck to change the ports anyway. 153 154 Examples: 155 156 %(prog)s --prefix=1 # sets ports to: 14061, 14063, 14064 157 %(prog)s --prefix=1 --revert # sets ports back to: 4061, 4063, 4064 158 %(prog)s --registry=4444 --tcp=5555 --ssl=6666 # sets ports to: 4444 5555 6666 159 160 """).parser 161 ports.add_argument("--prefix", help = "Adds a prefix to each port ON TOP OF any other settings") 162 ports.add_argument("--registry", help = "Registry port. (default: %(default)s)", default = "4061") 163 ports.add_argument("--tcp", help = "The tcp port to be used by Glacier2 (default: %(default)s)", default = "4063") 164 ports.add_argument("--ssl", help = "The ssl port to be used by Glacier2 (default: %(default)s", default = "4064") 165 ports.add_argument("--revert", action="store_true", help = "Used to rollback from the given settings to the defaults") 166 ports.add_argument("--skipcheck", action="store_true", help = "Skips the check if the server is already running") 167 168 sessionlist = Action("sessionlist", """List currently running sessions""").parser 169 170 cleanse = Action("cleanse", """Remove binary data files from OMERO. 171 172 Deleting an object from OMERO currently does not remove the binary data. Use this 173 command either manually or in a cron job periodically to remove Pixels and other data. 174 175 This is done by checking that for all the files in the given directory, a matching entry 176 exists on the server. THE /OMERO DIRECTORY MUST MATCH THE DATABASE YOU ARE RUNNING AGAINST. 177 178 This command must be run on the machine where, for example, /OMERO/ is located. 179 180 Examples: 181 bin/omero admin cleanse --dry-run /OMERO # Lists files that will be deleted 182 bin/omero admin cleanse /OMERO # Actually delete them. 183 bin/omero admin cleanse /volumes/data/OMERO # Delete from a standard location. 184 185 """).parser 186 cleanse.add_argument("--dry-run", action = "store_true", help = "Print out which files would be deleted") 187 cleanse.add_argument("data_dir", type=DirectoryType(), help = "omero.data.dir directory value (e.g. /OMERO") 188 189 Action("checkwindows", """Run simple check of the local installation (Windows-only)""") 190 191 Action("events", """Print event log (Windows-only)""") 192 193 self.actions["ice"].add_argument("argument", nargs="*", help="""Arguments joined together to make an Ice command. 194 If not present, the user will enter a console""") 195 196 self.actions["status"].add_argument("node", nargs="?", default="master") 197 self.actions["status"].add_argument("--nodeonly", action="store_true", 198 help="""If set, then only tests if the icegridnode is running""") 199 200 for name in ("start", "startasync"): 201 self.actions[name].add_argument("-u","--user", help=""" 202 User argument which should be logged in. If none is provided, the configuration 203 value for omero.windows.user will be taken. (Windows-only) 204 """) 205 206 for k in ("start", "startasync", "deploy", "restart", "restartasync"): 207 self.actions[k].add_argument("file", nargs="?", 208 help="""Application descriptor. If not provided, a default will be used""") 209 self.actions[k].add_argument("targets", nargs="*", 210 help="""Targets within the application descriptor which should be activated. 211 Common values are: "debug", "trace" """) 212 213 DISABLED = """ see: http://www.zeroc.com/forums/bug-reports/4237-sporadic-freeze-errors-concurrent-icegridnode-access.html 214 restart [filename] [targets] : Calls stop followed by start args 215 restartasync [filename] [targets] : Calls stop followed by startasync args 216 """ 217 218 # 219 # Windows utility methods 220 # 221 if has_win32:
222 - def _query_service(unused, svc_name):
223 hscm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS) 224 try: 225 try: 226 hs = win32service.OpenService(hscm, svc_name, win32service.SERVICE_ALL_ACCESS) 227 except: 228 return "DOESNOTEXIST" 229 try: 230 q = win32service.QueryServiceStatus(hs) 231 type, state, ctrl, err, svcerr, svccp, svcwh = q 232 if state == win32service.SERVICE_STOPPED: 233 return "STOPPED" 234 else: 235 return "unknown" 236 finally: 237 win32service.CloseServiceHandle(hs) 238 finally: 239 win32service.CloseServiceHandle(hscm)
240
241 - def events(self, svc_name):
242 def DumpRecord(record): 243 if str(record.SourceName) == svc_name: 244 self.ctx.out("Time: %s" % record.TimeWritten) 245 self.ctx.out("Rec: %s" % record.RecordNumber) 246 for si in record.StringInserts: 247 self.ctx.out(si) 248 self.ctx.out("="*20)
249 win32evtlogutil.FeedEventLogRecords(DumpRecord) 250 251 else: 252
253 - def events(self, svc_name):
254 self.ctx.die(666, "Could not import win32service and/or win32evtlogutil")
255
256 - def _query_service(self, svc_name):
257 """ 258 Query the service 259 Required to check the stdout since 260 rcode is not non-0 261 """ 262 command = ["sc", "query", svc_name] 263 popen = self.ctx.popen(command) # popen 264 output = popen.communicate()[0] 265 if 0 <= output.find("1060"): 266 return "DOESNOTEXIST" 267 else: 268 return output
269 270 # 271 # End Windows Methods 272 # 273
274 - def _node(self, omero_node = None):
275 """ Overrides the regular node() logic to return the value of OMERO_MASTER or "master" """ 276 if omero_node != None: 277 os.environ["OMERO_MASTER"] = omero_node 278 279 if os.environ.has_key("OMERO_MASTER"): 280 return os.environ["OMERO_MASTER"] 281 else: 282 return "master"
283
284 - def _cmd(self, *command_arguments):
285 """ 286 Used to generate an icegridadmin command line argument list 287 """ 288 command = ["icegridadmin", self._intcfg() ] 289 command.extend(command_arguments) 290 return command
291
292 - def _descript(self, args):
293 if args.file != None: 294 # Relative to cwd 295 descript = path(args.file).abspath() 296 if not descript.exists(): 297 self.ctx.dbg("No such file: %s -- Using as target" % descript) 298 args.targets.insert(0, args.file) 299 descript = None 300 else: 301 descript = None 302 303 if descript == None: 304 __d__ = "default.xml" 305 if self._isWindows(): 306 __d__ = "windefault.xml" 307 descript = self.ctx.dir / "etc" / "grid" / __d__ 308 self.ctx.err("No descriptor given. Using %s" % os.path.sep.join(["etc","grid",__d__])) 309 return descript
310
311 - def checkwindows(self, args):
312 """ 313 Checks that the templates file as defined in etc\Windows.cfg 314 can be found. 315 """ 316 self.check_access(os.R_OK) 317 if not self._isWindows(): 318 self.ctx.die(123, "Not Windows") 319 320 import Ice 321 key = "IceGrid.Node.Data" 322 properties = Ice.createProperties([self._icecfg()]) 323 nodedata = properties.getProperty(key) 324 if not nodedata: 325 self.ctx.die(300, "Bad configuration: No IceGrid.Node.Data property") 326 nodepath = path(nodedata) 327 pp = nodepath.parpath(self.ctx.dir) 328 if pp: 329 return 330 if nodepath == r"c:\omero_dist\var\master": 331 self.ctx.out("Found default value: %s" % nodepath) 332 self.ctx.out("Attempting to correct...") 333 from omero.install.win_set_path import win_set_path 334 count = win_set_path(dir = self.ctx.dir) 335 if count: 336 return 337 self.ctx.die(400, """ 338 339 %s is not in this directory. Aborting... 340 341 Please see the installation instructions on modifying 342 the files for your installation (%s) 343 with bin\winconfig.bat 344 345 """ % (nodedata, self.ctx.dir))
346 347 ############################################## 348 # 349 # Commands 350 # 351 352 @with_config
353 - def startasync(self, args, config):
354 """ 355 First checks for a valid installation, then checks the grid, 356 then registers the action: "node HOST start" 357 """ 358 359 self.check_access(config=config) 360 self.check_ice() 361 self.check_node(args) 362 if self._isWindows(): 363 self.checkwindows(args) 364 365 if 0 == self.status(args, node_only=True): 366 self.ctx.die(876, "Server already running") 367 368 self._initDir() 369 props = self._properties() 370 # Do a check to see if we've started before. 371 self._regdata() 372 self.check([]) 373 374 user = args.user 375 descript = self._descript(args) 376 377 if self._isWindows(): 378 svc_name = "OMERO.%s" % args.node 379 output = self._query_service(svc_name) 380 381 # Now check if the server exists 382 if 0 <= output.find("DOESNOTEXIST"): 383 command = [ 384 "sc", "create", svc_name, 385 "binPath=","""icegridnode.exe "%s" --deploy "%s" --service %s""" % (self._icecfg(), descript, svc_name), 386 "DisplayName=", svc_name, 387 "start=","auto"] 388 389 # By default: "NT Authority\LocalService" 390 if user: 391 user = self.ctx.input("User account:", False) 392 if not user: 393 user = self.ctx.initData().properties.getProperty("omero.windows.user") 394 if len(user) > 0: 395 command.append("obj=") 396 command.append(user) 397 self.ctx.out(self.ctx.popen(["ntrights","+r","SeServiceLogonRight","-u",user]).communicate()[0]) # popen 398 pasw = self.ctx.initData().properties.getProperty("omero.windows.pass") 399 pasw = self._ask_for_password(" for service user: %s" % user, pasw) 400 command.append("password=") 401 command.append(pasw) 402 self.ctx.out(self.ctx.popen(command).communicate()[0]) # popen 403 404 # Then check if the server is already running 405 if 0 <= output.find("RUNNING"): 406 self.ctx.die(201, "%s is already running. Use stop first" % svc_name) 407 408 # Finally start the service 409 output = self.ctx.popen(["sc","start",svc_name]).communicate()[0] # popen 410 self.ctx.out(output) 411 else: 412 command = ["icegridnode","--daemon","--pidfile",str(self._pid()),"--nochdir",self._icecfg(),"--deploy",str(descript)] + args.targets 413 self.ctx.call(command)
414 415 @with_config
416 - def start(self, args, config):
417 self.startasync(args, config) 418 try: 419 self.waitup(args) 420 except NonZeroReturnCode, nzrc: 421 # stop() may itself throw, 422 # if it does not, then we rethrow 423 # the original 424 self.ctx.err('Calling "stop" on remaining components') 425 self.stop(args, config) 426 raise nzrc
427 428 @with_config
429 - def deploy(self, args, config):
430 self.check_access() 431 self.check_ice() 432 descript = self._descript(args) 433 434 # TODO : Doesn't properly handle whitespace 435 # Though users can workaround with something like: 436 # bin/omero admin deploy etc/grid/a\\\\ b.xml 437 command = ["icegridadmin",self._intcfg(),"-e"," ".join(["application","update", str(descript)] + args.targets)] 438 self.ctx.call(command)
439
440 - def status(self, args, node_only = False):
441 self.check_node(args) 442 command = self._cmd("-e","node ping master") #3141, TODO should be configurable 443 self.ctx.rv = self.ctx.popen(command).wait() # popen 444 445 # node_only implies that "up" need not check for all 446 # of blitz to be accessible but just that if the node 447 # is running. 448 if not node_only: 449 node_only = getattr(args, "nodeonly", False) 450 451 if self.ctx.rv == 0 and not node_only: 452 try: 453 import Ice 454 import omero_ServerErrors_ice 455 ic = Ice.initialize([self._intcfg()]) 456 try: 457 sm = self.session_manager(ic) 458 try: 459 sm.create("####### STATUS CHECK ########", None) # Not adding "omero.client.uuid" 460 except omero.WrappedCreateSessionException, wcse: 461 # Only the server will throw one of these 462 self.ctx.dbg("Server reachable") 463 self.ctx.rv = 0 464 finally: 465 ic.destroy() 466 except exceptions.Exception, exc: 467 self.ctx.rv = 1 468 self.ctx.dbg("Server not reachable: "+str(exc)) 469 470 return self.ctx.rv
471 472 @with_config
473 - def restart(self, args, config):
474 if not self.stop(args, config): 475 self.ctx.die(54, "Failed to shutdown") 476 self.start(args, config)
477 478 @with_config
479 - def restartasync(self, args, config):
480 self.stop(args, config) 481 self.startasync(args, config)
482
483 - def waitup(self, args):
484 """ 485 Loops 30 times with 10 second pauses waiting for status() 486 to return 0. If it does not, then ctx.die() is called. 487 """ 488 self.check_access(os.R_OK) 489 self.ctx.out("Waiting on startup. Use CTRL-C to exit") 490 count = 30 491 while True: 492 count = count - 1 493 if count == 0: 494 self.ctx.die(43, "\nFailed to startup some components after 5 minutes") 495 elif 0 == self.status(args, node_only = False): 496 break 497 else: 498 self.ctx.out(".", newline = False) 499 self.ctx.sleep(10)
500
501 - def waitdown(self, args):
502 """ 503 Returns true if the server went down 504 """ 505 self.check_access(os.R_OK) 506 self.ctx.out("Waiting on shutdown. Use CTRL-C to exit") 507 count = 30 508 while True: 509 count = count - 1 510 if count == 0: 511 self.ctx.die(44, "\nFailed to shutdown some components after 5 minutes") 512 return False 513 elif 0 != self.status(args, node_only = True): 514 break 515 else: 516 self.ctx.out(".", newline = False) 517 self.ctx.sleep(10) 518 self.ctx.rv = 0 519 return True
520 521 @with_config
522 - def stopasync(self, args, config):
523 """ 524 Returns true if the server was already stopped 525 """ 526 self.check_node(args) 527 if 0 != self.status(args, node_only=True): 528 self.ctx.err("Server not running") 529 return True 530 elif self._isWindows(): 531 svc_name = "OMERO.%s" % args.node 532 output = self._query_service(svc_name) 533 if 0 <= output.find("DOESNOTEXIST"): 534 self.ctx.die(203, "%s does not exist. Use 'start' first." % svc_name) 535 self.ctx.out(self.ctx.popen(["sc","stop",svc_name]).communicate()[0]) # popen 536 self.ctx.out(self.ctx.popen(["sc","delete",svc_name]).communicate()[0]) # popen 537 else: 538 command = self._cmd("-e","node shutdown master") 539 try: 540 self.ctx.call(command) 541 except NonZeroReturnCode, nzrc: 542 self.ctx.rv = nzrc.rv 543 self.ctx.out("Was the server already stopped?")
544 545 @with_config
546 - def stop(self, args, config):
547 if not self.stopasync(args, config): 548 return self.waitdown(args) 549 return True
550
551 - def check(self, args):
552 # print "Check db. Have a way to load the db control" 553 pass
554
555 - def ice(self, args):
556 self.check_access() 557 command = self._cmd() 558 if len(args.argument) > 0: 559 command.extend(["-e", " ".join(args.argument)]) 560 return self.ctx.call(command) 561 else: 562 rv = self.ctx.call(command)
563 564 @with_config
565 - def diagnostics(self, args, config):
566 self.check_access() 567 config = config.as_map() 568 omero_data_dir = '/OMERO' 569 try: 570 omero_data_dir = config['omero.data.dir'] 571 except KeyError: 572 pass 573 self.ctx.out(""" 574 %s 575 OMERO Diagnostics %s 576 %s 577 """ % ("="*80, VERSION, "="*80)) 578 579 def sz_str(sz): 580 for x in ["KB", "MB", "GB"]: 581 sz /= 1000 582 if sz < 1000: 583 break 584 sz = "%.1f %s" % (sz, x) 585 return sz
586 587 def item(cat, msg): 588 cat = cat + ":" 589 cat = "%-12s" % cat 590 self.ctx.out(cat, False) 591 msg = "%-30s " % msg 592 self.ctx.out(msg, False) 593 594 def exists(p): 595 if p.isdir(): 596 if not p.exists(): 597 self.ctx.out("doesn't exist") 598 else: 599 self.ctx.out("exists") 600 else: 601 if not p.exists(): 602 self.ctx.out("n/a") 603 else: 604 warn = 0 605 err = 0 606 for l in p.lines(): 607 if l.find("ERROR") >= 0: 608 err += 1 609 elif l.find("WARN") >= 0: 610 warn += 1 611 msg = "" 612 if warn or err: 613 msg = " errors=%-4s warnings=%-4s" % (err, warn) 614 self.ctx.out("%-12s %s" % (sz_str(p.size), msg)) 615 616 def version(cmd): 617 """ 618 Returns a true response only 619 if a valid version was found. 620 """ 621 item("Commands","%s" % " ".join(cmd)) 622 try: 623 p = self.ctx.popen(cmd) 624 except OSError: 625 self.ctx.err("not found") 626 return False 627 628 rv = p.wait() 629 io = p.communicate() 630 try: 631 v = io[0].split() 632 v.extend(io[1].split()) 633 v = "".join(v) 634 m = re.match("^\D*(\d[.\d]+\d)\D?.*$", v) 635 v = "%-10s" % m.group(1) 636 self.ctx.out(v, False) 637 try: 638 where = whichall(cmd[0]) 639 sz = len(where) 640 if sz == 0: 641 where = "unknown" 642 else: 643 where = where[0] 644 if sz > 1: 645 where += " -- %s others" % sz 646 647 except: 648 where = "unknown" 649 self.ctx.out("(%s)" % where) 650 return True 651 except exceptions.Exception, e: 652 self.ctx.err("error:%s" % e) 653 return False 654 655 656 import logging 657 logging.basicConfig() 658 from omero.util.upgrade_check import UpgradeCheck 659 check = UpgradeCheck("diagnostics") 660 check.run() 661 if check.isUpgradeNeeded(): 662 self.ctx.out("") 663 664 version(["java", "-version"]) 665 version(["python", "-V"]) 666 version(["icegridnode", "--version"]) 667 iga = version(["icegridadmin", "--version"]) 668 version(["psql", "--version"]) 669 670 671 self.ctx.out("") 672 if not iga: 673 self.ctx.out("No icegridadmin available: Cannot check server list") 674 else: 675 item("Server", "icegridnode") 676 p = self.ctx.popen(self._cmd("-e", "server list")) # popen 677 rv = p.wait() 678 io = p.communicate() 679 if rv != 0: 680 self.ctx.out("not started") 681 self.ctx.dbg(""" 682 Stdout:\n%s 683 Stderr:\n%s 684 """ % io) 685 else: 686 self.ctx.out("running") 687 servers = io[0].split() 688 servers.sort() 689 for s in servers: 690 item("Server", "%s" % s) 691 p2 = self.ctx.popen(self._cmd("-e", "server state %s" % s)) # popen 692 rv2 = p2.wait() 693 io2 = p2.communicate() 694 if io2[1]: 695 self.ctx.err(io2[1].strip()) 696 elif io2[0]: 697 self.ctx.out(io2[0].strip()) 698 else: 699 self.ctx.err("UNKNOWN!") 700 701 def log_dir(log, cat, cat2, knownfiles): 702 self.ctx.out("") 703 item(cat, "%s" % log.abspath()) 704 exists(log) 705 self.ctx.out("") 706 707 if log.exists(): 708 files = log.files() 709 files = set([x.basename() for x in files]) 710 # Adding known names just in case 711 for x in knownfiles: 712 files.add(x) 713 files = list(files) 714 files.sort() 715 for x in files: 716 item(cat2, x) 717 exists(log / x) 718 item(cat2, "Total size") 719 sz = 0 720 for x in log.walkfiles(): 721 sz += x.size 722 self.ctx.out("%-.2f MB" % (float(sz)/1000000.0)) 723 724 log_dir(self.ctx.dir / "var" / "log", "Log dir", "Log files",\ 725 ["Blitz-0.log", "Tables-0.log", "Processor-0.log", "Indexer-0.log", "FileServer.log", "MonitorServer.log", "DropBox.log", "TestDropBox.log", "OMEROweb.log"]) 726 727 # Parsing well known issues 728 self.ctx.out("") 729 ready = re.compile(".*?ome.services.util.ServerVersionCheck.*OMERO.Version.*Ready..*?") 730 db_ready = re.compile(".*?Did.you.create.your.database[?].*?") 731 data_dir = re.compile(".*?Unable.to.initialize:.FullText.*?") 732 pg_password = re.compile(".*?org.postgresql.util.PSQLException:.FATAL:.password.*?authentication.failed.for.user.*?") 733 pg_user = re.compile(""".*?org.postgresql.util.PSQLException:.FATAL:.role.".*?".does.not.exist.*?""") 734 pg_conn = re.compile(""".*?org.postgresql.util.PSQLException:.Connection.refused.""") 735 736 737 issues = { 738 ready : "=> Server restarted <=", 739 db_ready : "Your database configuration is invalid", 740 data_dir : "Did you create your omero.data.dir? E.g. /OMERO", 741 pg_password : "Your postgres password seems to be invalid", 742 pg_user: "Your postgres user is invalid", 743 pg_conn: "Your postgres hostname and/or port is invalid" 744 } 745 746 try: 747 for file in ('Blitz-0.log',): 748 749 p = self.ctx.dir / "var" / "log" / file 750 import fileinput 751 for line in fileinput.input([str(p)]): 752 lno = fileinput.filelineno() 753 for k, v in issues.items(): 754 if k.match(line): 755 item('Parsing %s' % file, "[line:%s] %s" % (lno, v)) 756 self.ctx.out("") 757 break 758 except: 759 self.ctx.err("Error while parsing logs") 760 761 self.ctx.out("") 762 763 def env_val(val): 764 item("Environment","%s=%s" % (val, os.environ.get(val, "(unset)"))) 765 self.ctx.out("") 766 env_val("OMERO_HOME") 767 env_val("OMERO_NODE") 768 env_val("OMERO_MASTER") 769 env_val("PATH") 770 env_val("ICE_HOME") 771 env_val("LD_LIBRARY_PATH") 772 env_val("DYLD_LIBRARY_PATH") 773 774 self.ctx.out("") 775 exists = os.path.exists(omero_data_dir) 776 is_writable = os.access(omero_data_dir, os.R_OK|os.W_OK) 777 self.ctx.out("OMERO data dir: '%s'\tExists? %s\tIs writable? %s" % \ 778 (omero_data_dir, exists, is_writable)) 779 from omero.plugins.web import WebControl 780 WebControl().status(args) 781
782 - def session_manager(self, communicator):
783 import IceGrid, Glacier2 784 iq = communicator.stringToProxy("IceGrid/Query") 785 iq = IceGrid.QueryPrx.checkedCast(iq) 786 sm = iq.findAllObjectsByType("::Glacier2::SessionManager")[0] 787 sm = Glacier2.SessionManagerPrx.checkedCast(sm) 788 return sm
789
790 - def can_access(self, filepath, mask=os.R_OK|os.W_OK):
791 """ 792 Check that the given path belongs to 793 or is accessible by the current user 794 on Linux systems. 795 """ 796 797 if "Windows" == platform.system(): 798 return 799 800 pathobj = path(filepath) 801 802 if not pathobj.exists(): 803 self.ctx.die(8, "FATAL: OMERO directory does not exist: %s" % pathobj) 804 805 owner = os.stat(filepath)[stat.ST_UID] 806 if owner == 0: 807 msg = "" 808 msg += "FATAL: OMERO directory which needs to be writeable belongs to root: %s\n" % filepath 809 msg += "Please use \"chown -R NEWUSER %s\" and run as then run %s as NEWUSER" % (filepath, sys.argv[0]) 810 self.ctx.die(9, msg) 811 else: 812 if not os.access(filepath, mask): 813 self.ctx.die(10, "FATAL: Cannot access %s, a required file/directory for OMERO" % filepath)
814
815 - def check_access(self, mask=os.R_OK|os.W_OK, config=None):
816 """Check that 'var' is accessible by the current user.""" 817 818 var = self.ctx.dir / 'var' 819 if not os.path.exists(var): 820 print "Creating directory %s" % var 821 os.makedirs(var, 0700) 822 else: 823 self.can_access(var, mask) 824 825 if config is not None: 826 omero_data_dir = '/OMERO' 827 config = config.as_map() 828 try: 829 omero_data_dir = config['omero.data.dir'] 830 except KeyError: 831 pass 832 self.can_access(omero_data_dir) 833 for p in os.listdir(var): 834 subpath = os.path.join(var, p) 835 if os.path.isdir(subpath): 836 self.can_access(subpath, mask)
837
838 - def check_node(self, args):
839 """ 840 If the args argparse.Namespace argument has no "node" attribute, 841 then assign one. 842 """ 843 if not hasattr(args, "node"): 844 args.node = self._node()
845
846 - def check_ice(self):
847 """ 848 Checks for Ice version 3.3 849 850 See ticket:2514 851 """ 852 pattern = "3.3." 853 854 import Ice, sys, re 855 pat = "^3[.]3[.].*" 856 pattern = re.compile(pat) 857 vers = Ice.stringVersion() 858 if pattern.match(vers) is None: 859 self.ctx.die(164, "IcePy Version is not compatible with %s: %s" % (pat, vers)) 860 861 popen = self.ctx.popen(["icegridnode", "--version"]) 862 vers = popen.communicate()[1] 863 if pattern.match(vers) is None: 864 self.ctx.die(165, "icegridnode version is not compatible with %s: %s" % (pat, vers))
865
866 - def open_config(self, unused):
867 """ 868 Callers are responsible for closing the 869 returned ConfigXml object. 870 """ 871 cfg_xml = self.ctx.dir / "etc" / "grid" / "config.xml" 872 cfg_tmp = self.ctx.dir / "etc" / "grid" / "config.xml.tmp" 873 grid_dir = self.ctx.dir / "etc" / "grid" 874 if not cfg_xml.exists() and self.can_access(grid_dir): 875 if cfg_tmp.exists() and self.can_access(cfg_tmp): 876 self.ctx.dbg("Removing old config.xml.tmp") 877 cfg_tmp.remove() 878 config = omero.config.ConfigXml(str(cfg_tmp)) 879 try: 880 self.ctx.controls["config"].upgrade(None, config) 881 finally: 882 config.close() 883 self.ctx.err("Creating %s" % cfg_xml) 884 cfg_tmp.rename(str(cfg_xml)) 885 886 try: 887 config = omero.config.ConfigXml(str(cfg_xml)) 888 config.save() 889 except portalocker.LockException: 890 self.ctx.die(111, "Could not acquire lock on %s" % cfg_xml) 891 892 return config
893 894 @with_config
895 - def reindex(self, args, config):
896 self.check_access(config=config) 897 import omero.java 898 server_dir = self.ctx.dir / "lib" / "server" 899 log4j = "-Dlog4j.configuration=log4j-cli.properties" 900 classpath = [ file.abspath() for file in server_dir.files("*.jar") ] 901 xargs = [ log4j, "-Xmx1024M", "-cp", os.pathsep.join(classpath) ] 902 903 cfg = config.as_map() 904 for x in ("name", "user", "host", "port"): # NOT passing password on command-line 905 k = "omero.db.%s" % x 906 if k in cfg: 907 v = cfg[k] 908 xargs.append("-D%s=%s" % (k, v)) 909 if "omero.data.dir" in cfg: 910 xargs.append("-Domero.data.dir=%s" % cfg["omero.data.dir"]) 911 for k, v in cfg.items(): 912 if k.startswith("omero.search"): 913 xargs.append("-D%s=%s" % (k, cfg[k])) 914 915 cmd = ["ome.services.fulltext.Main"] 916 917 if args.full: 918 cmd.append("full") 919 elif args.events: 920 cmd.append("events") 921 elif getattr(args, "class"): 922 cmd.append("reindex") 923 cmd.extend(getattr(args, "class")) 924 else: 925 self.ctx.die(502, "No valid action: %s" % args) 926 927 debug = False 928 if getattr(args, "jdwp"): 929 debug = True 930 931 self.ctx.dbg("Launching Java: %s, debug=%s, xargs=%s" % (cmd, debug, xargs)) 932 p = omero.java.popen(cmd, debug=debug, xargs=xargs, stdout=sys.stdout, stderr=sys.stderr) # FIXME. Shouldn't use std{out,err} 933 self.ctx.rv = p.wait()
934
935 - def ports(self, args):
936 self.check_access() 937 from omero.install.change_ports import change_ports 938 if not args.skipcheck: 939 if 0 == self.status(args, node_only=True): 940 self.ctx.die(100, "Can't change ports while the server is running!") 941 942 # Resetting return value. 943 self.ctx.rv = 0 944 945 if args.prefix: 946 for x in ("registry", "tcp", "ssl"): 947 setattr(args, x, "%s%s" % (args.prefix, getattr(args, x))) 948 change_ports(args.ssl, args.tcp, args.registry, args.revert, dir=self.ctx.dir)
949
950 - def cleanse(self, args):
951 self.check_access() 952 from omero.util.cleanse import cleanse 953 client = self.ctx.conn(args) 954 key = client.getSessionId() 955 cleanse(data_dir=args.data_dir, dry_run=args.dry_run, \ 956 query_service=client.sf.getQueryService(), \ 957 config_service=client.sf.getConfigService())
958
959 - def sessionlist(self, args):
960 client = self.ctx.conn(args) 961 service = client.sf.getQueryService() 962 params = omero.sys.ParametersI() 963 query = "select s from Session s join fetch s.node n join fetch s.owner o where s.closed is null and n.id != 0" 964 results = service.findAllByQuery(query, params) 965 mapped = list() 966 for s in results: 967 rv = list() 968 mapped.append(rv) 969 if not s.isLoaded(): 970 rv.append("") 971 rv.append("id=%s" % s.id.val) 972 rv.append("") 973 rv.append("") 974 rv.append("") 975 rv.append("insufficient privileges") 976 else: 977 rv.append(s.node.id) 978 rv.append(s.uuid) 979 rv.append(s.started) 980 rv.append(s.owner.omeName) 981 if s.userAgent is None: 982 rv.append("") 983 else: 984 rv.append(s.userAgent) 985 if client.getSessionId() == s.uuid.val: 986 rv.append("current session") 987 else: 988 rv.append("") 989 self.ctx.controls["hql"].display(mapped, ("node", "session", "started", "owner", "agent", "notes"))
990 try: 991 register("admin", AdminControl, HELP) 992 except NameError: 993 if __name__ == "__main__": 994 cli = CLI() 995 cli.register("admin", AdminControl, HELP) 996 cli.invoke(sys.argv[1:]) 997