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
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"
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
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
220
221 if has_win32:
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
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
254 self.ctx.die(666, "Could not import win32service and/or win32evtlogutil")
255
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)
264 output = popen.communicate()[0]
265 if 0 <= output.find("1060"):
266 return "DOESNOTEXIST"
267 else:
268 return output
269
270
271
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
293 if args.file != None:
294
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
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
350
351
352 @with_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
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
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
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])
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])
403
404
405 if 0 <= output.find("RUNNING"):
406 self.ctx.die(201, "%s is already running. Use stop first" % svc_name)
407
408
409 output = self.ctx.popen(["sc","start",svc_name]).communicate()[0]
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):
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
435
436
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")
443 self.ctx.rv = self.ctx.popen(command).wait()
444
445
446
447
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)
460 except omero.WrappedCreateSessionException, wcse:
461
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
477
478 @with_config
482
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
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
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])
536 self.ctx.out(self.ctx.popen(["sc","delete",svc_name]).communicate()[0])
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):
550
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
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"))
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))
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
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
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
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
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
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
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
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
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"):
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)
933 self.ctx.rv = p.wait()
934
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
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
958
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