1
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"
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
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
215
216 if has_win32:
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
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
249 self.ctx.die(666, "Could not import win32service and/or win32evtlogutil")
250
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)
259 output = popen.communicate()[0]
260 if 0 <= output.find("1060"):
261 return "DOESNOTEXIST"
262 else:
263 return output
264
265
266
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
288 if args.file != None:
289
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
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
345
346
347 @with_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
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
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
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])
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])
398
399
400 if 0 <= output.find("RUNNING"):
401 self.ctx.die(201, "%s is already running. Use stop first" % svc_name)
402
403
404 output = self.ctx.popen(["sc","start",svc_name]).communicate()[0]
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):
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
430
431
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")
438 self.ctx.rv = self.ctx.popen(command).wait()
439
440
441
442
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)
455 except omero.WrappedCreateSessionException, wcse:
456
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
472
473 @with_config
477
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
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
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])
531 self.ctx.out(self.ctx.popen(["sc","delete",svc_name]).communicate()[0])
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):
545
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
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"))
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))
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
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
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
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
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
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
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
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
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"):
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)
926 self.ctx.rv = p.wait()
927
935
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