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