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