You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by de...@apache.org on 2018/08/15 12:05:15 UTC
svn commit: r1838082 [1/3] - in /uima/uima-ducc/trunk: src/main/admin/
src/main/admin/cron/
uima-ducc-database/src/main/java/org/apache/uima/ducc/database/lifetime/
uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/
Author: degenaro
Date: Wed Aug 15 12:05:15 2018
New Revision: 1838082
URL: http://svn.apache.org/viewvc?rev=1838082&view=rev
Log:
UIMA-5742 Reliable DUCC - New versions of start_ducc, stop_ducc, and check_ducc that use DB instead of PID files
- New python script db_autostart_delete to remove an autostart table entry
- New python script db_autostart_query to query autostart table entries
- New autostart python script to be run as crontab on each DUCC host to keep daemons alive
- New crontab example for launching autostart script
- New DB package to support autostart CRUD operations
- Revised DuccBook documenting above
Added:
uima/uima-ducc/trunk/src/main/admin/2.2_check_ducc
uima/uima-ducc/trunk/src/main/admin/2.2_start_ducc
uima/uima-ducc/trunk/src/main/admin/2.2_stop_ducc
uima/uima-ducc/trunk/src/main/admin/autostart.py (with props)
uima/uima-ducc/trunk/src/main/admin/cron/db_autostart.crontab.example
uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py (with props)
uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py (with props)
uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/lifetime/
uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/lifetime/DbDaemonLifetime.java (with props)
uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/lifetime/DbDaemonLifetimeCommon.java (with props)
uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/lifetime/DbDaemonLifetimeUI.java (with props)
uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/lifetime/IDbDaemonLifetime.java (with props)
Modified:
uima/uima-ducc/trunk/src/main/admin/check_ducc
uima/uima-ducc/trunk/src/main/admin/ducc_util.py
uima/uima-ducc/trunk/src/main/admin/start_ducc
uima/uima-ducc/trunk/src/main/admin/stop_ducc
uima/uima-ducc/trunk/uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/admin-commands.tex
Added: uima/uima-ducc/trunk/src/main/admin/2.2_check_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/2.2_check_ducc?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/2.2_check_ducc (added)
+++ uima/uima-ducc/trunk/src/main/admin/2.2_check_ducc Wed Aug 15 12:05:15 2018
@@ -0,0 +1,428 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+
+import os
+import sys
+from time import time
+import getopt
+import signal
+
+from ducc_util import DuccUtil
+from properties import Properties
+from local_hooks import verify_slave_node
+from local_hooks import verify_master_node
+
+#from ducc_util import ThreadWorker
+from ducc_util import ThreadPool
+
+class CheckDucc(DuccUtil):
+
+ def __init__(self):
+ DuccUtil.__init__(self)
+ self.badnodes = []
+
+ def validate(self, checkdate):
+ verify_slave_node(checkdate, self.ducc_properties)
+ self.check_clock_skew(checkdate)
+ self.verify_jvm()
+ self.verify_limits()
+ (viable, elevated, safe) = self.verify_duccling()
+ self.duccling_ok(viable, elevated, safe)
+ if ( not safe or not viable ):
+ print 'NOTOK ducc_ling is not installed correctly.'
+
+ return
+
+ def verify_database(self):
+ if ( self.db_bypass == True ):
+ return True
+
+ ret = self.db_alive(1)
+ if ( ret ):
+ print 'The database is running'
+ else:
+ print 'The database is not running'
+
+ def verify_activemq(self):
+ if ( self.is_amq_active() ):
+ print 'ActiveMQ is found listening at', self.broker_protocol + "://" + self.broker_host + ':' + self.broker_port
+ return True
+ return False
+
+ def check_node(self, args):
+
+ messages = []
+ spacer = ' '
+ node = args[0]
+
+ messages.append((' '))
+ messages.append(('Checking', node, '...'))
+
+ if(self.ssh_operational(node)):
+ text = "ssh is operational to "+node
+ #print text
+ else:
+ text = "ssh is NOT operational to "+node
+ print text
+ messages.append((spacer, text))
+ return messages
+
+ response = self.find_ducc_process(node) # a tuple, (True|False, proclist)
+ if ( not response[0] ):
+ messages.append((spacer, "No response."))
+ return messages
+
+ proclist = response[1] # a list of tuples, tuple is (component, pid, user)
+ if ( len(proclist) > 0 ):
+ for proc in proclist:
+ component = proc[0]
+ pid = proc[1]
+ found_user = proc[2]
+
+ signal = self.kill_signal
+
+ if(self.is_reliable_backup()):
+ if ( component == 'agent' ):
+ continue
+
+ if ( component == 'orchestrator' ):
+ component = 'or'
+
+ if ( component == 'database' ):
+ if ( signal != None ):
+ if ( self.kill_db9 == False ):
+ signal = '-QUIT'
+
+ process_id = found_user + ' ' + component + '@' + node + ' PID ' + pid
+ if ( signal != None ) :
+ if ( self.user != found_user ):
+ messages.append((spacer, "Not killing someone else's process.", process_id))
+ elif ( component == 'unknown-java' ):
+ messages.append((spacer, 'Not killing non-ducc process', process_id))
+ else:
+ messages.append((spacer, 'Killing (' + signal + ')', process_id))
+ self.kill_process(node, proc, signal)
+ if ( component == 'agent' ):
+ self.pids_agents.delete(pid)
+ else:
+ self.pids_daemons.delete(pid)
+ process_changes = True
+
+ else:
+ messages.append((spacer, 'Found', process_id))
+ full_name = component + '@' + node
+ if ( component == 'agent' ):
+ self.pids_agents.put(full_name, pid)
+ else:
+ if ( component in self.default_components ):
+ self.pids_daemons.put(full_name, pid)
+ self.pids_daemons.put(component, full_name)
+ else:
+ messages.append((spacer, 'no processes found.'))
+
+ if ( self.kill_signal == None ):
+ response = "Node health checks return."
+ lines = self.ssh(node, True, self.DUCC_HOME + "/admin/check_ducc", "-x", str(int(time())))
+ while 1:
+ line = lines.readline()
+ if ( 'signal' in line ):
+ response = "Node health did not complete: " + line
+ self.badnodes.append(node)
+ # these next two filter junk if 'mesg' is running in a shell rc
+ if ( 'stdin: is not a tty' in line ):
+ continue
+ if ( 'mesg' in line ):
+ continue
+
+ if ( not line ):
+ break
+ line = line.strip()
+ messages.append((spacer, line))
+ #messages.append((spacer, '[]', line))
+ messages.append((spacer, response))
+
+ return messages
+
+ def signalHandler(self, signum, frame):
+ print "-------- Caught signal", signum, "--------"
+ if ( len(self.badnodes) != 0 ):
+ print "Health checks on these nodes did not return:"
+ for n in self.badnodes:
+ print n,
+ print ''
+ sys.exit(1)
+
+ def usage(self, msg):
+ if ( msg != None ):
+ print msg
+ print "Usage:"
+ print " check_ducc [options]"
+ print " If no options are given this is the equivalent of:"
+ print ""
+ print " check_ducc -n ../resources/ducc.nodes"
+ print ""
+ print " For reliable DUCC agents will not be killed from backup head node. "
+ print ""
+ print " Broker will not be killed when ducc.broker.automanage = false. "
+ print " Database will not be killed when ducc.database.automanage = false. "
+ print ""
+ print "Options:"
+ print " -n --nodelist nodefile"
+ print " Check for agents on the nodes in nodefile. This option may be specified multiple time"
+ print " for multiple nodefiles. The 'local' node is always checked"
+ print ""
+ print " -c --configuration"
+ print " Do basic sanity checking on the configuration only. Note that configuration checking is always"
+ print " performed with most options. The [-c, --configuration] option does ONLY configuration checking."
+ print ""
+ print " -k --kill"
+ print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
+ print " uses kill -KILL (-9) for all daemons, except database which uses -QUIT (3),"
+ print " and only kills processes owned by the invoking user."
+ print ""
+ print " --db-9"
+ print " Use signal -KILL (-9) to kill database, rather than the default -QUIT (-3)"
+ print ""
+ print " -i --int"
+ print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
+ print " uses kill -INT (-2) and only kills processes owned by the invoking user."
+ print ""
+ print " -q --quit"
+ print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
+ print " uses kill -QUIT (-3) and only kills processes owned by the invoking user."
+ print ""
+ print " -p --pids"
+ print " Rewrite the PID file. The PID file is always rewritten if any changes to processes are made. Sometimes"
+ print " the PID file needs rebuilding. This option causes the file to be rebuilt regardless of"
+ print " changes."
+ print ""
+ print " -x localdate"
+ print " Validate the local installation, called via ssh usually. The date is the date on the calling machine."
+ print ""
+ print " --nothreading"
+ print " Disable multithreaded operation if it would otherwise be used"
+ print ""
+ print " -v --verbose"
+ print " If specified, print the validated configuration to the console."
+ print ""
+ print " -? prints this message."
+ sys.exit(1)
+
+ def main(self, argv):
+
+ try:
+ opts, args = getopt.getopt(argv, 'cikn:opqx:h?v', ['configuration', 'nodelist=', 'int', 'quit', 'kill', 'db-9', 'pids', 'verbose', 'nothreading', ])
+ except:
+ self.usage("Invalid arguments " + ' '.join(argv))
+
+ nodefiles = []
+ self.user = os.environ['LOGNAME']
+ self.kill_signal = None
+ self.kill_db9 = False
+ redo_pids = False
+ process_changes = False
+ do_validate = False
+ checkdate = 0
+ config_only = False
+ verbose = False
+
+ for ( o, a ) in opts:
+ if o in ('-c', '--configuration'):
+ config_only = True
+ elif o in ('-n', '--nodelist'):
+ nodefiles.append(a)
+ elif o in ('-i', '--int'):
+ if ( self.kill_signal != None ):
+ print 'Conflicting kill signals: -INT and', self.kill_signal
+ return
+ self.kill_signal = '-INT'
+ elif o in ('-q', '--quit'):
+ if ( self.kill_signal != None ):
+ print 'Conflicting kill signals: -QUIT and', self.kill_signal
+ return
+ self.kill_signal = '-QUIT'
+ elif o in ('-k', '--kill'):
+ if ( self.kill_signal != None ):
+ print 'Conflicting kill signals: -KILL and', self.kill_signal
+ return
+ self.kill_signal = '-KILL'
+ elif o in ('--db-9'):
+ self.kill_db9 = True
+ elif o in ( '--nothreading' ):
+ self.disable_threading()
+ elif o in ('-p', '--pids'):
+ redo_pids = True
+ elif o in ('-x'):
+ # intended to be called recursively from check_ducc, NOT from the command line
+ do_validate = True
+ checkdate = float(a)
+ elif o in ('-v', '--verbose'):
+ verbose = True
+ elif o in ('-h', '-?', '--help'):
+ self.usage(None)
+ else:
+ print 'badarg', a
+ usage('bad arg: ' + a)
+
+
+ if not self.installed():
+ print "Head node is not initialized. Have you run ducc_post_install?"
+ return
+
+ self.check_properties()
+
+ if ( do_validate ):
+ # if validating, ONLY validate, called via ssh usually
+ self.validate(checkdate)
+ return
+
+ # When called directly must be from the head node
+ self.verify_head()
+
+ self.set_duccling_version()
+
+ os.system('cat ' + self.DUCC_HOME + '/state/duccling.version')
+ # not -x option, do this only on local node
+ env = self.show_ducc_environment()
+ for e in env:
+ print e
+
+
+ jvm = self.ducc_properties.get('ducc.jvm')
+ if ( jvm == None ):
+ print 'WARN: ducc.jvm is not specified in ducc.properties. Default is simply "java" which may not work on all nodes.'
+
+ if ( not verify_master_node(self.ducc_properties) ):
+ print 'FAIL: Cannot verify master mode'
+ return
+
+ if ( not self.verify_activemq() ):
+ print 'ActiveMQ broker is not running on', self.broker_protocol + "://" + self.broker_host + ':' + self.broker_port
+
+ self.verify_database()
+
+ # init the PID file
+ if(not self.is_reliable_backup()):
+ self.pids_agents = Properties()
+ self.pids_agents.load_if_exists(self.pid_file_agents)
+ self.pids_daemons = Properties()
+ self.pids_daemons.load_if_exists(self.pid_file_daemons)
+
+ # read the nodelists
+ if ( len(nodefiles) == 0 ):
+ nodefiles = self.default_nodefiles
+ check_nodepools = True
+ else:
+ # if using other than the fully configured set of nodes we can't reliably check nodepools
+ # because anything other than the full set of nodes may be missing something
+ check_nodepools = False
+
+ nodes = {}
+ n_nodes = 0
+ for nf in nodefiles:
+ n_nodes, nodes = self.read_nodefile(nf, nodes)
+
+ #
+ # add in the local host if needed, and the webserver node
+ #
+ localnodes = []
+ if ( not self.localhost in nodes ):
+ localnodes.append(self.localhost)
+
+ if ( not (self.webserver_node in ['localhost', self.localhost, None]) ):
+ localnodes.append(self.webserver_node)
+
+ if ( len(localnodes) > 0 ):
+ nodes['local'] = localnodes
+
+ self.verify_jvm()
+
+
+ if ( config_only ):
+ if ( nodefiles != self.default_nodefiles):
+ print "NOTOK: Config check only works with full, default nodefile:", self.default_nodefiles
+ return
+ if self.verify_class_configuration(nodefiles[0], verbose):
+ print "OK: Class configuration checked"
+ else:
+ print "NOTOK: Errors in class or node configuration."
+
+ return
+
+ # checking starts here
+ print "Checking", n_nodes, "nodes"
+ self.threadpool = ThreadPool(n_nodes + 5) # more for the head processes
+ checked = {}
+
+ signal.signal(signal.SIGINT, self.signalHandler)
+
+ try:
+ for (nodefile, nodelist) in nodes.items():
+ if ( nodelist == None ):
+ # loading the nodes prints the necessary message
+ continue
+ for node in nodelist:
+ if ( checked.has_key(node) ):
+ continue
+
+ checked[node] = node
+ self.threadpool.invoke(self.check_node, node)
+ # check backup head node(s)
+ for node in self.get_head_node_list():
+ if(not node in checked):
+ checked[node] = node
+ self.threadpool.invoke(self.check_node, node)
+ except:
+ self.threadpool.quit()
+ print sys.exc_info()[0], "Exiting."
+ sys.exit(1)
+
+ self.threadpool.quit()
+
+ if ( self.kill_signal != None ):
+ if(self.automanage_broker):
+ print 'Stopping broker'
+ self.stop_broker()
+ else:
+ print 'Not stopping broker - not automanaged'
+ if(self.automanage_database):
+ print 'Stopping database'
+ self.db_stop()
+ else:
+ print 'Not stopping database - not automanaged'
+
+ if(not self.is_reliable_backup()):
+ if ( len(self.pids_agents) == 0):
+ if ( os.path.exists(self.pid_file_agents) ):
+ os.remove(self.pid_file_agents)
+ elif (process_changes or redo_pids):
+ self.pids_agents.write(self.pid_file_agents)
+
+ if ( len(self.pids_daemons) == 0):
+ if ( os.path.exists(self.pid_file_daemons) ):
+ os.remove(self.pid_file_daemons)
+ elif (process_changes or redo_pids):
+ self.pids_daemons.write(self.pid_file_daemons)
+
+if __name__ == "__main__":
+ checker = CheckDucc()
+ checker.main(sys.argv[1:])
+
Added: uima/uima-ducc/trunk/src/main/admin/2.2_start_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/2.2_start_ducc?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/2.2_start_ducc (added)
+++ uima/uima-ducc/trunk/src/main/admin/2.2_start_ducc Wed Aug 15 12:05:15 2018
@@ -0,0 +1,431 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+
+import os
+import sys
+import time
+import getopt
+import threading
+import traceback
+
+from ducc_util import DuccUtil
+from properties import Properties
+from local_hooks import verify_slave_node
+from local_hooks import verify_master_node
+from ducc import Ducc
+from ducc_util import ThreadPool
+from ducc_base import find_ducc_home
+
+class StartDucc(DuccUtil):
+
+ def __init__(self):
+ DuccUtil.__init__(self, True)
+
+ def start_broker(self):
+
+ broker_host = self.localhost
+ print 'Starting broker on', broker_host
+ lines = self.ssh(broker_host, True, "'", self.DUCC_HOME + '/admin/ducc.py', '-c', 'broker', "'")
+ while 1:
+ line = lines.readline().strip()
+ if ( not line ):
+ break
+ #print '[] ' + line
+ if ( line.startswith('PID') ):
+ toks = line.split(' ') # get the PID
+ print "Broker on", broker_host, 'PID', toks[1]
+ self.pids_daemons.put('broker@' + broker_host, toks[1])
+ lines.close()
+ break
+
+ for i in range(0, 9):
+ if ( self.is_amq_active() ):
+ return
+ print 'Waiting for broker .....', str(i)
+ time.sleep(1)
+
+ def start_component(self, args):
+
+ ducc, component, or_parms = args
+ msgs = []
+
+ node = self.ducc_properties.get('ducc.head')
+
+ com = component
+ if ( com.find('@') >= 0 ):
+ com, node = com.split('@')
+
+ if (com in self.local_components):
+ node = self.localhost
+
+ if ((com in self.default_components) or ( com == 'agent')) :
+ msgs.append((node, 'Starting', com))
+ else:
+ msgs.append(('Unrecognized component', component))
+ return msgs
+
+
+ if ( or_parms == None ):
+ or_parms = '--or_parms='
+ else:
+ or_parms = '--or_parms=' + or_parms
+
+ if ( node == 'local' ):
+ node = self.localhost
+
+ lines = self.ssh(node, True, "'", self.DUCC_HOME + '/admin/ducc.py', '-c', com, '-b', or_parms, '-d', str(time.time()), '--nodup', "'")
+
+ # we'll capture anything that the python shell spews because it may be useful, and then drop the
+ # pipe when we see a PID message
+ while 1:
+ line = lines.readline().strip()
+ if ( not line ):
+ break
+ #msgs.append(('[]', line))
+ if ( line.startswith('PID') ):
+ toks = line.split(' ') # get the PID
+ msgs.append((' PID', toks[1]))
+ self.pids_daemons.put(com + '@' + node, toks[1])
+ lines.close()
+ break
+ if ( line.startswith('WARN') ):
+ msgs.append((' ', line))
+
+ if ( com in self.default_components ): # tracks where the management processes are
+ self.pidlock.acquire()
+ self.pids_daemons.put(com, com + '@' + node)
+ self.pidlock.release()
+
+ return msgs
+
+ def start_one_agent(self, args):
+
+ host = args[0]
+ msgs = []
+ spacer = ' '
+ msgs.append((host, ""))
+ lines = self.ssh(host, True, "'", self.DUCC_HOME + '/admin/ducc.py', '-c' 'agent', '-b', '-d', str(time.time()), '--nodup', "'")
+ for line in lines:
+ line = line.strip()
+ # print '[]', host, line
+ # msgs.append(('[l]', line))
+ if ( line.startswith('PID') ):
+ toks = line.split(' ')
+ pid = toks[1]
+ self.pidlock.acquire()
+ self.pids_agents.put('agent@' + host, pid)
+ self.pidlock.release()
+
+ lines.close()
+ msgs.append((spacer, 'DUCC Agent started PID', pid))
+ break
+
+ if ( 'tty' in line ):
+ # ssh junk if mesg is set
+ continue
+
+ toks = line.split()
+
+ sshmsgs = self.ssh_ok(host, line )
+ if ( sshmsgs != None ):
+ for m in sshmsgs:
+ print '[S]', m
+
+ if ( toks[0] == 'NOTOK' ):
+ msgs.append((spacer, 'NOTOK Not started:', ' '.join(toks[1:])))
+ else:
+ msgs.append((spacer, line))
+
+ return msgs
+
+ def verify_required_directories(self):
+ for dir in ('history', 'state', 'logs'):
+ d = self.DUCC_HOME + '/' + dir
+ if ( not os.path.exists(d) ):
+ print "Initializing", d
+ os.mkdir(d)
+
+ def usage(self, *msg):
+ if ( msg[0] != None ):
+ print ' '.join(msg)
+
+ print "Usage:"
+ print " start_ducc [options]"
+ print " If no options are given, all DUCC processes are started, using the default"
+ print " nodelist, DUCC_HOME/resources/ducc.nodes. "
+ print ""
+ print " For reliable DUCC agents will not be started from backup head node. "
+ print ""
+ print " Broker will not be started when ducc.broker.automanage = false. "
+ print " Database will not be started when ducc.database.automanage = false. "
+ print ""
+ print "Options:"
+ print " -n --nodelist nodefile"
+ print " Start agents on the nodes in the nodefile. Multiple nodefiles may be specified:"
+ print ""
+ print " start_ducc -n foo.nodes -n bar.nodes -n baz.nodes"
+ print ""
+ print " -c, --component component"
+ print " Start a specific DUCC component, optionally on a specific node. If the component name"
+ print " is qualified with a nodename, the component is started on that node. To qualify a"
+ print " component name with a destination node, use the notation component@nodename."
+ print " Multiple components may be specified:"
+ print ""
+ print " start_ducc -c sm -c pm -c rm@node1 -c or@node2 -c agent@remote1 -c agent@remote2"
+ print ""
+ print " Components include:"
+ print " rm - resource manager"
+ print " or - orchestrator"
+ print " pm - process manager"
+ print " sm - services manager"
+ print " ws - web server"
+ print " agent - node agent"
+ print ' head = { or, pm, rm, sm, ws, db, broker }'
+ print ""
+ print " --nothreading"
+ print " Disable multithreaded operation if it would otherwise be used"
+ print ""
+ print " Choose none or one of the following two options, which is only effective when the orchestrator (or) component is started."
+ print " When specified here it supersedes that specified for ducc.orchestrator.start.type in ducc.properties."
+ print " When not specified here or in ducc.properties, the default is --warm."
+ print ""
+ print " --warm"
+ print " Do NOT force active Jobs, Services, and Reservations to Completed state."
+ print ""
+ print " --cold"
+ print " Force active Jobs, Services, and Reservations to Completed state."
+ print ""
+ print "Examples:"
+ print " Start all DUCC processes, using custom nodelists:"
+ print " start_ducc -n foo.nodes -n bar.nodes"
+ print ""
+ print " Start just agents on a specific set of nodes:"
+ print " start_ducc -n foo.nodes -n bar.nodes"
+ print ""
+ print " Start the webserver on node 'bingle':"
+ print " start_ducc -c ws@bingle"
+ sys.exit(1)
+
+ def invalid(self, *msg):
+ if ( msg[0] != None ):
+ print
+ print ' '.join(msg)
+ print
+ print "For usage run"
+ print " start_ducc -h"
+ print 'or'
+ print ' start_ducc --help'
+ sys.exit(1)
+
+ def main(self, argv):
+
+ self.verify_head()
+
+ self.check_properties()
+
+ if ( not self.verify_jvm() ):
+ sys.exit(1);
+
+ self.set_duccling_version()
+
+ nodefiles = []
+ components = []
+ or_parms = self.ducc_properties.get('ducc.orchestrator.start.type')
+ if(not self.is_reliable_backup()):
+ self.pids_agents = Properties()
+ self.pids_agents.load_if_exists(self.pid_file_agents)
+ self.pids_daemons = Properties()
+ self.pids_daemons.load_if_exists(self.pid_file_daemons)
+
+ try:
+ opts, args = getopt.getopt(argv, 'c:mn:sh?v', ['component=', 'help', 'nodelist=', 'cold', 'warm', 'nothreading'])
+ except:
+ self.invalid('Invalid arguments', ' '.join(argv))
+
+ if (len(args) > 0):
+ self.invalid('Invalid extra args: ', ' '.join(args))
+
+ for ( o, a ) in opts:
+ if o in ( '-c', '--component' ):
+ if (a.strip() == 'head'):
+ components.append('or')
+ components.append('pm')
+ components.append('rm')
+ components.append('sm')
+ components.append('ws')
+ components.append('db')
+ components.append('broker')
+ else:
+ components.append(a)
+ elif o in ( '-n', '--nodelist' ):
+ nodefiles.append(a)
+ elif o in ( '--nothreading' ):
+ self.disable_threading()
+ elif o in ( '--cold', '--warm' ):
+ or_parms = o[2:] # (strip the leading --)
+ elif ( o == '-v'):
+ print self.version()
+ sys.exit(0)
+ elif o in ( '-h', '--help' ):
+ self.usage(None)
+ elif ( o == '-?'):
+ self.usage(None)
+ else:
+ self.invalid('bad arg: ', o, 'in:', ' '.join(argv))
+
+ if not self.installed():
+ print "Head node is not initialized. Have you run ducc_post_install?"
+ return
+
+ environ = self.show_ducc_environment()
+ for e in environ:
+ print e
+
+ # no args, or just -s - make equivalent of -management and -nodefile=DUCC.HOME/resources/ducc.nodes
+ if ( (len(components) == 0) and (len(nodefiles) == 0 ) ) :
+ nodefiles = self.default_nodefiles
+ components = self.default_components
+
+ self.verify_required_directories()
+
+ if ( not verify_master_node(self.ducc_properties) ):
+ print 'FAIL: Cannot run javac to run java verification'
+ return
+
+ # make sure all the nodefiles exist and are readable
+ ok = True
+ nodes = {}
+ n_nodes = 0
+ for n in nodefiles:
+ n_nodes, nodes = self.read_nodefile(n, nodes)
+
+ for ( nf, nl ) in nodes.items():
+ if ( nl == None ):
+ print "Can't read nodefile", nf
+ ok = False
+
+ if ok and (nodefiles == self.default_nodefiles):
+ if self.verify_class_configuration(nodefiles[0], False):
+ print "OK: Class configuration checked"
+ else:
+ print "NOTOK: Bad configuration, cannot start."
+ ok = False
+
+ if ( not ok ):
+ sys.exit(1)
+
+ if ( not self.verify_limits() ):
+ print "Limits too low to run DUCC"
+ sys.exit(1)
+
+ # activeMQ needs to be started externally before starting any DUCC processes
+ if ( self.automanage_broker and ('broker' in components) ):
+ if ( self.is_amq_active() ):
+ print 'ActiveMQ broker is already running on host and port:', self.broker_host + ':' + self.broker_port, 'NOT restarting'
+ else:
+ try:
+ self.start_broker()
+ except:
+ print sys.exc_info()[0], "DUCC may not be started correctly."
+ sys.exit(1)
+
+ if ( self.automanage_database and ('db' in components) ):
+ try:
+ if ( not self.db_start() ):
+ print "Failed to start or connect to the database."
+ sys.exit(1)
+ except Exception (e):
+ # print e
+ print sys.exc_info()[0], "Can't start the database."
+ sys.exit(1)
+
+ if ( self.is_amq_active() ):
+ print 'ActiveMQ broker is found on configured host and port:', self.broker_host + ':' + self.broker_port
+ else:
+ print 'ActiveMQ broker is required but cannot be found on', self.broker_host + ':' + self.broker_port
+ sys.exit(1)
+
+ ducc = Ducc()
+
+ self.threadpool = ThreadPool(n_nodes + 5) # a few more for the head processes
+ self.pidlock = threading.Lock()
+
+ #start 'or' first to field system log requests
+ if ( len(components) != 0 ):
+ for com in components:
+ if ( com in ('or') ):
+ try:
+ self.threadpool.invoke(self.start_component, ducc, com, or_parms)
+ #self.start_component(ducc, com, or_parms)
+ except:
+ self.threadpool.quit()
+ print sys.exc_info()[0], "DUCC may not be started correctly."
+ sys.exit(1)
+ # give 'or' a small head start
+ time.sleep(2)
+
+ if(self.is_reliable_backup()):
+ print '********** "backup" head node -> not starting agents'
+ else:
+ print "Starting", n_nodes, "agents"
+ for (nodefile, nodelist) in nodes.items():
+ print '********** Starting agents from file', nodefile
+ try:
+ for node in nodelist:
+ self.threadpool.invoke(self.start_one_agent, node)
+ except:
+ self.threadpool.quit()
+ print sys.exc_info()[0], "DUCC may not be started correctly."
+ sys.exit(1)
+
+ if ( len(components) != 0 ):
+ print 'Starting', or_parms
+
+ for com in components:
+ if ( com in ('broker', 'db', 'or') ):
+ pass # already started
+ else:
+ try:
+ self.threadpool.invoke(self.start_component, ducc, com, or_parms)
+ #self.start_component(ducc, com, or_parms)
+ except:
+ self.threadpool.quit()
+ print sys.exc_info()[0], "DUCC may not be started correctly."
+ sys.exit(1)
+
+ self.threadpool.quit()
+
+ if(not self.is_reliable_backup()):
+ if ( len(self.pids_agents) > 0 ):
+ self.pids_agents.write(self.pid_file_agents)
+ if ( len(self.pids_daemons) > 0 ):
+ self.pids_daemons.write(self.pid_file_daemons)
+ return
+
+if __name__ == "__main__":
+ # First check if ducc_post_install has been run
+ DUCC_HOME = find_ducc_home()
+ propsfile = DUCC_HOME + '/resources/site.ducc.properties'
+ if ( not os.path.exists(propsfile) ):
+ print "\n>> ERROR >> Missing site.ducc.properties -- please run ducc_post_install\n"
+ sys.exit(99)
+ starter = StartDucc()
+ starter.main(sys.argv[1:])
Added: uima/uima-ducc/trunk/src/main/admin/2.2_stop_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/2.2_stop_ducc?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/2.2_stop_ducc (added)
+++ uima/uima-ducc/trunk/src/main/admin/2.2_stop_ducc Wed Aug 15 12:05:15 2018
@@ -0,0 +1,386 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+
+import os
+import sys
+import time
+import getopt
+import glob
+
+from ducc_util import DuccUtil
+from properties import *
+from ducc import Ducc
+
+class StopDucc(DuccUtil):
+
+ def stop_component(self, component, force):
+
+ if ( (component == 'broker') and self.automanage_broker ):
+ print 'Stopping broker'
+ self.stop_broker()
+ return
+ if ( (component == 'db') and self.automanage_database ):
+ print 'Stopping database'
+ self.db_stop()
+ return
+
+ #
+ # If it's an unqualified management component, we need to get it's qualified name
+ #
+ if ( component in self.default_components ):
+ if( component == 'agent' ):
+ if ( self.pids_agents.has_key(component) ):
+ component = self.pids_agents.get(component)
+ else:
+ print 'Skipping', component, 'not in pids file.'
+ return
+ else:
+ if ( self.pids_daemons.has_key(component) ):
+ component = self.pids_daemons.get(component)
+ else:
+ print 'Skipping', component, 'not in pids file.'
+ return
+
+ #
+ # If the name is not qualified we've got a problem, everything in the pids file is qualified
+ #
+ if ( component.find('@') >= 0 ):
+ com, target_node = component.split('@')
+ else:
+ self.invalid("Must specify hostname when stopping", component)
+
+ #
+ # If despite all that we can't find the pid, we need to run check_ducc
+ #
+ if( com == 'agent' ):
+ if ( not self.pids_agents.has_key(component) ):
+ print "Cannot find PID for component", component, ". Run check_ducc -p to refresh PIDS and then rerun stop_ducc."
+ return
+ else:
+ pid = self.pids_agents.get(component)
+ else:
+ if ( not self.pids_daemons.has_key(component) ):
+ print "Cannot find PID for component", component, ". Run check_ducc -p to refresh PIDS and then rerun stop_ducc."
+ return
+ else:
+ pid = self.pids_daemons.get(component)
+
+
+ if ( force ):
+ print 'Stopping component', com, 'on node', target_node, 'with PID', pid, 'forcibly (kill -9)'
+ self.nohup(['ssh', target_node, 'kill', '-KILL', pid], False)
+
+ pass
+ else:
+ print 'Stopping component', com, 'on node', target_node, 'with PID', pid
+ self.nohup(['ssh', target_node, 'kill', '-INT', pid], False)
+
+ # clear the short name if it exists, and the long name
+ if( com == 'agent' ):
+ self.pids_agents.delete(com)
+ self.pids_agents.delete(component)
+ else:
+ self.pids_daemons.delete(com)
+ self.pids_daemons.delete(component)
+
+ def quiesce_agents(self, components, nodes):
+ allnodes = []
+ for ( nf, nl ) in nodes.items():
+ allnodes = allnodes + nl
+
+ for c in components:
+ if ( c.find('@') >= 0 ):
+ com, target_node = c.split('@')
+ allnodes.append(target_node)
+ else:
+ self.invalid("Must specify hostname when stopping", component)
+
+ qparm = ','.join(allnodes)
+ print 'Quiescing', qparm
+ DUCC_JVM_OPTS = ' -Dducc.deploy.configuration=' + self.DUCC_HOME + "/resources/ducc.properties "
+ DUCC_JVM_OPTS = DUCC_JVM_OPTS + ' -DDUCC_HOME=' + self.DUCC_HOME
+ DUCC_JVM_OPTS = DUCC_JVM_OPTS + ' -Dducc.head=' + self.ducc_properties.get('ducc.head')
+ self.spawn(self.java(), DUCC_JVM_OPTS, 'org.apache.uima.ducc.common.main.DuccAdmin', '--quiesceAgents', qparm)
+
+ # NOTE: quiesce does not actually cause agents to terminate so we don't update the PIDs file
+ return
+
+ def stop_agent(self, node, force):
+ self.stop_component('agent@' + node.strip(), force)
+
+ def usage(self, msg):
+ if ( msg != None ):
+ print msg
+
+ print 'stop_ducc [options]'
+ print ' If no options are given, this help screen is shown.'
+ print ''
+ print ' For reliable DUCC agents will not be stopped from backup head node. '
+ print ''
+ print ' Broker will not be stopped when ducc.broker.automanage = false. '
+ print ' Database will not be stopped when ducc.database.automanage = false. '
+ print ''
+ print 'Options:'
+ print ' -a --all'
+ print ' Stop all the DUCC processes, including agents and management processes.'
+ print ''
+ print ' -n --nodelist nodefile'
+ print ' Stop agents on the nodes in the nodefile. Multiple nodefiles may be specified:'
+ print ''
+ print ' stop_ducc -n foo.nodes -n bar.nodes -n baz.nodes'
+ print ''
+ print ' -c --component component'
+ print ' Stop a specific component. The component may be qualified with the node name'
+ print ' using the @ symbol: component@node.'
+ print ''
+ print ' stop_ducc -c rm@foonode'
+ print ' stop_ducc -c agent@barnode -c or'
+ print ''
+ print ' Components include:'
+ print ' agent - node agent'
+ print ' broker - AMQ broker'
+ print ' db - database'
+ print ' or - orchestrator'
+ print ' pm - process manager'
+ print ' rm - resource manager'
+ print ' sm - services manager'
+ print ' ws - web server'
+ print ' head = { or, pm, rm, sm, ws, db, broker }'
+ print ''
+ print ' -w --wait'
+ print ' Time to wait for everything to come down, in seconds. Default is 60.'
+ print ''
+ print ' -k --kill'
+ print ' Stop the component forcibly and immediately using kill -9. Use this only if a'
+ print ' normal stop does not work (e.g. the process may be hung).'
+ print ''
+ print ' --nothreading'
+ print ' Disable multithreaded operation if it would otherwise be used'
+ print ''
+
+ sys.exit(1)
+
+ def invalid(self, *msg):
+ if ( msg[0] != None ):
+ print ' '.join(msg)
+
+ print "For usage run"
+ print " stop_ducc -h"
+ print 'or'
+ print ' stop_ducc --help'
+ sys.exit(1)
+
+
+ def main(self, argv):
+
+ self.verify_head()
+
+ self.check_properties()
+
+ if ( len(argv) == 0 ):
+ self.usage(None)
+
+ components = []
+ nodefiles = []
+ do_agents = False
+ do_components = False
+ force = False
+ quiesce = False
+ all = False
+ wait_time = 60
+
+ try:
+ opts, args = getopt.getopt(argv, 'ac:n:kn:w:qh?v', ['all', 'component=', 'help', 'nodelist=', 'kill', 'quiesce', 'nothreading', 'wait'])
+ except:
+ self.invalid('Invalid arguments ' + ' '.join(argv))
+
+ if (len(args) > 0):
+ self.invalid('Invalid extra args: ', ' '.join(args))
+
+ for ( o, a ) in opts:
+ if o in ('-c', '--component' ):
+ if (a.strip() == 'head'):
+ components.append('or')
+ components.append('pm')
+ components.append('rm')
+ components.append('sm')
+ components.append('ws')
+ components.append('db')
+ components.append('broker')
+ else:
+ components.append(a)
+ do_components = True
+ elif o in ( '-a', '--all' ):
+ all = True
+ components = self.default_components
+ elif o in ( '-n', '--nodelist' ):
+ nodefiles.append(a)
+ do_agents = True
+ elif o in ( '-k', '--kill' ):
+ force = True
+ elif o in ( '-q', '--quiesce' ):
+ quiesce = True
+ elif o in ( '-w', '--wait' ):
+ wait_time = int(a)
+ elif o in ( '--nothreading' ):
+ self.disable_threading()
+ elif ( o == '-v' ) :
+ print self.version()
+ sys.exit(0)
+ elif o in ( '-h', '--help' ):
+ self.usage(None)
+ elif ( o == '-?'):
+ self.usage(None)
+ else:
+ self.invalid('bad arg: ' + o)
+
+ if ( quiesce ):
+ if ( all ):
+ self.invalid("May not quiesce 'all'.");
+ if ( force ):
+ self.invalid("May not both quiesce and force.");
+ for c in components:
+ if ( not c.startswith('agent') ):
+ self.invalid("Only agents may be quiesced.")
+
+
+
+ # avoid confusion by insuring that if 'all', then nothing else is specified
+ if ( all and ( do_components ) ):
+ self.invalid("The --all option is mutually exclusive with --component")
+
+ # 'all' means everything. we use broadcast. should use check_ducc to make sure
+ # it actually worked, and find the stragglers.
+ if ( all ):
+ if ( not force ) :
+ self.clean_shutdown()
+
+ # Agents may wait up to 60 secs for processes to quiesce
+ print "Waiting " + str(wait_time) + " seconds to broadcast agent shutdown."
+ time.sleep(wait_time)
+
+ if ( self.automanage_broker ):
+ print "Stopping broker"
+ self.stop_broker()
+
+ if ( self.automanage_database ):
+ print "Stopping database"
+ self.db_stop()
+
+ if ( os.path.exists(self.pid_file_agents) ):
+ os.remove(self.pid_file_agents)
+ if ( os.path.exists(self.pid_file_daemons) ):
+ os.remove(self.pid_file_daemons)
+ return
+ else:
+ if ( len(nodefiles) == 0 ):
+ nodefiles = self.default_nodefiles
+
+
+ self.pids_agents = Properties()
+ self.pids_daemons = Properties()
+ sc = set(components)
+ sb = set(['broker', 'db'])
+ read_pids = True
+ if ( sc.issubset(sb) ):
+ read_pids = False
+
+ # The broker and db do not set the pid file
+ if ( read_pids ):
+ try:
+ if(not self.is_reliable_backup()):
+ self.pids_agents.load(self.pid_file_agents)
+ self.pids_daemons.load(self.pid_file_daemons)
+ except PropertiesException, (inst):
+ print inst.msg
+ print ''
+ print 'Run check_ducc -p to refresh the PIDs file, or check_ducc -k to search for and',
+ print 'kill all DUCC processes.'
+ print ''
+ sys.exit(1)
+
+ #
+ # if not 'all', we use nodefiles and component names
+ #
+
+ # make sure all the nodefiles exist and are readable
+ ok = True
+ nodes = {}
+ n_nodes = 0
+ for n in nodefiles:
+ n_nodes, nodes = self.read_nodefile(n, nodes)
+
+ for ( nf, nl ) in nodes.items():
+ if ( nl == None ): # die early if the parameters are wrong
+ print "Can't read nodefile", nf
+ ok = False
+
+ if ( not ok ):
+ sys.exit(1)
+
+ if ( quiesce ):
+ if(self.is_reliable_backup()):
+ print '********** "backup" head node -> not quiescing agents'
+ else:
+ self.quiesce_agents(components, nodes)
+ else:
+ if(self.is_reliable_backup()):
+ print '********** "backup" head node -> not stopping agents'
+ else:
+ for (nf, nl) in nodes.items():
+ for n in nl:
+ self.stop_agent(n, force)
+ host = self.localhost.split('.')[0]
+ for c in components:
+ c = c.strip()
+ if(c in ('pm','rm','sm','ws')):
+ c = c+'@'+host
+ self.stop_component(c, force)
+ time.sleep(2)
+ for c in components:
+ c = c.strip()
+ if(c in ('or')):
+ c = c+'@'+host
+ self.stop_component(c, force)
+ time.sleep(2)
+ for c in components:
+ c = c.strip()
+ if(c in ('db','broker')):
+ self.stop_component(c, force)
+
+ if ( read_pids ):
+ if(not self.is_reliable_backup()):
+ if ( len(self.pids_agents) > 0 ):
+ self.pids_agents.write(self.pid_file_agents)
+ else:
+ os.remove(self.pid_file_agents)
+ if ( len(self.pids_daemons) > 0 ):
+ self.pids_daemons.write(self.pid_file_daemons)
+ else:
+ os.remove(self.pid_file_daemons)
+
+ return
+
+if __name__ == "__main__":
+ stopper = StopDucc()
+ stopper.main(sys.argv[1:])
+
+
Added: uima/uima-ducc/trunk/src/main/admin/autostart.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/autostart.py?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/autostart.py (added)
+++ uima/uima-ducc/trunk/src/main/admin/autostart.py Wed Aug 15 12:05:15 2018
@@ -0,0 +1,296 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+import sys
+
+version_min = [2, 7]
+version_info = sys.version_info
+version_error = False
+if(version_info[0] < version_min[0]):
+ version_error = True
+elif(version_info[0] == version_min[0]):
+ if(version_info[1] < version_min[1]):
+ version_error = True
+if(version_error):
+ print('Python minimum requirement is version '+str(version_min[0])+'.'+str(version_min[1]))
+ sys.exit(1)
+
+import argparse
+import datetime
+import logging
+import os
+import shlex
+import socket
+import subprocess
+import time
+import traceback
+
+from ducc_util import DuccUtil
+
+# produce a time stamp
+def get_timestamp():
+ tod = time.time()
+ timestamp = datetime.datetime.fromtimestamp(tod).strftime('%Y-%m-%d %H:%M:%S')
+ return timestamp
+
+# embedded class to log to file
+# default level is info level,
+# controlled by environment variable LOGLEVEL = { info, debug, trace }
+class Logger():
+
+ flag_info = True
+ flag_debug = False
+ flag_trace = False
+
+ flag_error = True
+ flag_warn = True
+
+ def __init__(self,filename,level='info'):
+ self.filename = filename
+ if(level == 'debug'):
+ self.flag_debug = True
+ elif(level == 'trace'):
+ self.flag_debug = True
+ self.flag_trace = True
+
+ # write to file
+ def output(self,type,mn,text):
+ message = get_timestamp()+' '+type+' '+mn+' '+text
+ with open(self.filename, 'a') as logfile:
+ logfile.write(message+'\n')
+
+ # record info message
+ def info(self,mn,text):
+ if(self.flag_info):
+ self.output('I',mn,text)
+
+ # record debug message
+ def debug(self,mn,text):
+ if(self.flag_debug):
+ self.output('D',mn,text)
+
+ # record trace message
+ def trace(self,mn,text):
+ if(self.flag_trace):
+ self.output('T',mn,text)
+
+ # record error message
+ def error(self,mn,text):
+ if(self.flag_error):
+ self.output('E',mn,text)
+
+ # record warn message
+ def warn(self,mn,text):
+ if(self.flag_warn):
+ self.output('W',mn,text)
+
+# class to automagically start DUCC daemons
+class AutoStart(DuccUtil):
+
+ components = [ 'agent', 'broker', 'orchestrator', 'pm', 'rm', 'sm', 'ws' ]
+ map = { 'ag':'agent',
+ 'br':'broker',
+ 'or':'or',
+ 'pm':'pm',
+ 'rm':'rm',
+ 'sm':'sm',
+ 'ws':'ws',
+ }
+
+ # return file name
+ def _fn(self):
+ fpath = __file__.split('/')
+ flen = len(fpath)
+ return fpath[flen-1]
+
+ # return class name
+ def _cn(self):
+ return self.__class__.__name__
+
+ # return method name
+ def _mn(self):
+ return traceback.extract_stack(None,2)[0][2]
+
+ description = 'Start daemon(s) on the present node when listed in the autostart database table but not already running.'
+
+ def get_args(self):
+ parser = argparse.ArgumentParser(description=self.description)
+ self.args = parser.parse_args()
+
+ # setup logging to file for autostart script
+ def setup_logging(self,NAME):
+ LOGDIR = self.DUCC_HOME+'/logs/'+NAME
+ self.makedirs(LOGDIR)
+ self.LOCAL_HOST = socket.getfqdn()
+ FN = self.LOCAL_HOST.split('.')[0]+'.'+NAME+'.log'
+ LOGFILE = LOGDIR+'/'+FN
+ LOGLEVEL = os.environ.get('LOGLEVEL','info')
+ self.logger = Logger(LOGFILE,LOGLEVEL)
+
+
+ # check if host names with domain match
+ def is_host_match_with_domain(self,h1,h2):
+ retVal = False
+ if(h1 == h2):
+ retVal = True
+ text = str(h1)+' '+str(h2)+' '+str(retVal)
+ self.logger.debug(self._mn(),text)
+ return retVal
+
+ # check if host names without domain match
+ def is_host_match_without_domain(self,h1,h2):
+ retVal = False
+ h10 = h1.split('.')[0]
+ h20 = h2.split('.')[0]
+ if(h10 == h20):
+ retVal = True
+ text = str(h10)+' '+str(h20)+' '+str(retVal)
+ self.logger.debug(self._mn(),text)
+ return retVal
+
+ #check if host names match with/without domain
+ def is_host_match(self,h1,h2):
+ retVal = False
+ if(h1 != None):
+ if(h2 != None):
+ if(self.is_host_match_with_domain(h1,h2)):
+ retVal = True
+ elif(self.is_host_match_without_domain(h1,h2)):
+ retVal = True
+ text = str(h1)+' '+str(h2)+' '+str(retVal)
+ self.logger.debug(self._mn(),text)
+ return retVal
+
+ def parse_line(self,line):
+ retVal = '', '', ''
+ try:
+ if(line != None):
+ text = line
+ self.logger.debug(self._mn(),text)
+ tokens = line.split()
+ if(len(tokens) == 1):
+ host = line.split('.')[0]
+ remainder = line.split('.')[1]
+ name = remainder.split('=')[0]
+ state = remainder.split('=')[1]
+ retVal = host, name, state
+ except:
+ pass
+ return retVal
+
+ # get daemons started (from DB)
+ def get_daemons_started(self):
+ daemons = []
+ jclass = 'org.apache.uima.ducc.database.lifetime.DbDaemonLifetimeUI'
+ option = '--query'
+ cmd = [self.jvm, '-DDUCC_HOME='+self.DUCC_HOME, jclass, option]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ lines = out.split('\n')
+ for line in lines:
+ host, daemon, state = self.parse_line(line)
+ if(self.is_host_match(self.LOCAL_HOST, host)):
+ if(state == 'Start'):
+ daemons.append(daemon)
+ text = 'add'+' '+host+' '+daemon
+ self.logger.debug(self._mn(),text)
+ else:
+ text = 'skip'+' '+host+' '+daemon
+ self.logger.debug(self._mn(),text)
+ else:
+ text = 'skip'+' '+host+' '+daemon
+ self.logger.debug(self._mn(),text)
+ text = 'daemons'+' '+str(daemons)
+ self.logger.debug(self._mn(),text)
+ return daemons
+
+ def normalize_component(self,component):
+ daemon = component[:2]
+ return daemon
+
+ # get daemons running (from system)
+ def get_daemons_running(self):
+ daemons = []
+ result = self.find_ducc_process(self.LOCAL_HOST)
+ find_status = result[0]
+ text = 'find_status:'+str(find_status)
+ self.logger.debug(self._mn(),text)
+ tuples = result[1]
+ text = 'tuples:'+str(tuples)
+ self.logger.debug(self._mn(),text)
+ for tuple in tuples:
+ component = tuple[0]
+ pid = tuple[1]
+ user = tuple[2]
+ if(user == self.ducc_uid):
+ if(component in self.components):
+ text = 'keep:'+str(tuple)
+ self.logger.debug(self._mn(),text)
+ daemon = self.normalize_component(component)
+ daemons.append(daemon)
+ else:
+ text = 'skip:'+str(tuple)
+ self.logger.debug(self._mn(),text)
+ else:
+ text = 'skip:'+str(tuple)+' '+str(self.ducc_uid)
+ self.logger.debug(self._mn(),text)
+ text = 'daemons:'+str(daemons)
+ self.logger.debug(self._mn(),text)
+ return daemons
+
+ def start(self,daemon):
+ component = self.map[daemon]
+ text = str(component)
+ self.logger.warn(self._mn(),text)
+ if(daemon == 'ag'):
+ python_script = os.path.join(self.DUCC_HOME,'admin','ducc.py')
+ cmd = [ python_script, '-c', component, '-b', '-d', str(time.time()), '--nodup' ]
+ else:
+ python_script = os.path.join(self.DUCC_HOME,'admin','start_ducc',)
+ cmd = [ python_script, '-c', component ]
+ text = str(cmd)
+ self.logger.info(self._mn(),text)
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ text = str(out)
+ self.logger.info(self._mn(),text)
+
+ # autostart: start head or agent daemons, as required
+ def main(self, argv):
+ NAME = 'autostart'
+ self.setup_logging(NAME)
+ self.get_args()
+ try:
+ daemons_started = self.get_daemons_started()
+ daemons_running = self.get_daemons_running()
+ for daemon in daemons_started:
+ if(not daemon in daemons_running):
+ self.start(daemon)
+
+ except Exception,e:
+ lines = traceback.format_exc().splitlines()
+ for line in lines:
+ text = line
+ self.logger.debug(self._mn(),text)
+
+if __name__ == '__main__':
+ instance = AutoStart()
+ instance.main(sys.argv[1:])
+
\ No newline at end of file
Propchange: uima/uima-ducc/trunk/src/main/admin/autostart.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: uima/uima-ducc/trunk/src/main/admin/autostart.py
------------------------------------------------------------------------------
svn:executable = *
Modified: uima/uima-ducc/trunk/src/main/admin/check_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/check_ducc?rev=1838082&r1=1838081&r2=1838082&view=diff
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/check_ducc (original)
+++ uima/uima-ducc/trunk/src/main/admin/check_ducc Wed Aug 15 12:05:15 2018
@@ -128,13 +128,13 @@ class CheckDucc(DuccUtil):
else:
messages.append((spacer, 'Found', process_id))
- full_name = component + '@' + node
- if ( component == 'agent' ):
- self.pids_agents.put(full_name, pid)
- else:
- if ( component in self.default_components ):
- self.pids_daemons.put(full_name, pid)
- self.pids_daemons.put(component, full_name)
+ #full_name = component + '@' + node
+ #if ( component == 'agent' ):
+ # self.pids_agents.put(full_name, pid)
+ #else:
+ # if ( component in self.default_components ):
+ # self.pids_daemons.put(full_name, pid)
+ # self.pids_daemons.put(component, full_name)
else:
messages.append((spacer, 'no processes found.'))
@@ -179,11 +179,11 @@ class CheckDucc(DuccUtil):
print ""
print " check_ducc -n ../resources/ducc.nodes"
print ""
- print " For reliable DUCC agents will not be killed from backup head node. "
- print ""
- print " Broker will not be killed when ducc.broker.automanage = false. "
- print " Database will not be killed when ducc.database.automanage = false. "
- print ""
+ #print " For reliable DUCC agents will not be killed from backup head node. "
+ #print ""
+ #print " Broker will not be killed when ducc.broker.automanage = false. "
+ #print " Database will not be killed when ducc.database.automanage = false. "
+ #print ""
print "Options:"
print " -n --nodelist nodefile"
print " Check for agents on the nodes in nodefile. This option may be specified multiple time"
@@ -193,27 +193,27 @@ class CheckDucc(DuccUtil):
print " Do basic sanity checking on the configuration only. Note that configuration checking is always"
print " performed with most options. The [-c, --configuration] option does ONLY configuration checking."
print ""
- print " -k --kill"
- print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
- print " uses kill -KILL (-9) for all daemons, except database which uses -QUIT (3),"
- print " and only kills processes owned by the invoking user."
- print ""
- print " --db-9"
- print " Use signal -KILL (-9) to kill database, rather than the default -QUIT (-3)"
- print ""
- print " -i --int"
- print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
- print " uses kill -INT (-2) and only kills processes owned by the invoking user."
- print ""
- print " -q --quit"
- print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
- print " uses kill -QUIT (-3) and only kills processes owned by the invoking user."
- print ""
- print " -p --pids"
- print " Rewrite the PID file. The PID file is always rewritten if any changes to processes are made. Sometimes"
- print " the PID file needs rebuilding. This option causes the file to be rebuilt regardless of"
- print " changes."
- print ""
+ #print " -k --kill"
+ #print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
+ #print " uses kill -KILL (-9) for all daemons, except database which uses -QUIT (3),"
+ #print " and only kills processes owned by the invoking user."
+ #print ""
+ #print " --db-9"
+ #print " Use signal -KILL (-9) to kill database, rather than the default -QUIT (-3)"
+ #print ""
+ #print " -i --int"
+ #print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
+ #print " uses kill -INT (-2) and only kills processes owned by the invoking user."
+ #print ""
+ #print " -q --quit"
+ #print " Force-kill any DUCC process you find on a node (if normal stop_ducc isn't working. This"
+ #print " uses kill -QUIT (-3) and only kills processes owned by the invoking user."
+ #print ""
+ #print " -p --pids"
+ #print " Rewrite the PID file. The PID file is always rewritten if any changes to processes are made. Sometimes"
+ #print " the PID file needs rebuilding. This option causes the file to be rebuilt regardless of"
+ #print " changes."
+ #print ""
print " -x localdate"
print " Validate the local installation, called via ssh usually. The date is the date on the calling machine."
print ""
@@ -229,7 +229,8 @@ class CheckDucc(DuccUtil):
def main(self, argv):
try:
- opts, args = getopt.getopt(argv, 'cikn:opqx:h?v', ['configuration', 'nodelist=', 'int', 'quit', 'kill', 'db-9', 'pids', 'verbose', 'nothreading', ])
+ opts, args = getopt.getopt(argv, 'cn:x:h?v', ['configuration', 'nodelist=', 'verbose', 'nothreading', ])
+ #opts, args = getopt.getopt(argv, 'cikn:opqx:h?v', ['configuration', 'nodelist=', 'int', 'quit', 'kill', 'db-9', 'pids', 'verbose', 'nothreading', ])
except:
self.usage("Invalid arguments " + ' '.join(argv))
@@ -249,27 +250,27 @@ class CheckDucc(DuccUtil):
config_only = True
elif o in ('-n', '--nodelist'):
nodefiles.append(a)
- elif o in ('-i', '--int'):
- if ( self.kill_signal != None ):
- print 'Conflicting kill signals: -INT and', self.kill_signal
- return
- self.kill_signal = '-INT'
- elif o in ('-q', '--quit'):
- if ( self.kill_signal != None ):
- print 'Conflicting kill signals: -QUIT and', self.kill_signal
- return
- self.kill_signal = '-QUIT'
- elif o in ('-k', '--kill'):
- if ( self.kill_signal != None ):
- print 'Conflicting kill signals: -KILL and', self.kill_signal
- return
- self.kill_signal = '-KILL'
- elif o in ('--db-9'):
- self.kill_db9 = True
+ #elif o in ('-i', '--int'):
+ # if ( self.kill_signal != None ):
+ # print 'Conflicting kill signals: -INT and', self.kill_signal
+ # return
+ # self.kill_signal = '-INT'
+ #elif o in ('-q', '--quit'):
+ # if ( self.kill_signal != None ):
+ # print 'Conflicting kill signals: -QUIT and', self.kill_signal
+ # return
+ # self.kill_signal = '-QUIT'
+ #elif o in ('-k', '--kill'):
+ # if ( self.kill_signal != None ):
+ # print 'Conflicting kill signals: -KILL and', self.kill_signal
+ # return
+ # self.kill_signal = '-KILL'
+ #elif o in ('--db-9'):
+ # self.kill_db9 = True
elif o in ( '--nothreading' ):
self.disable_threading()
- elif o in ('-p', '--pids'):
- redo_pids = True
+ #elif o in ('-p', '--pids'):
+ # redo_pids = True
elif o in ('-x'):
# intended to be called recursively from check_ducc, NOT from the command line
do_validate = True
@@ -320,11 +321,11 @@ class CheckDucc(DuccUtil):
self.verify_database()
# init the PID file
- if(not self.is_reliable_backup()):
- self.pids_agents = Properties()
- self.pids_agents.load_if_exists(self.pid_file_agents)
- self.pids_daemons = Properties()
- self.pids_daemons.load_if_exists(self.pid_file_daemons)
+ #if(not self.is_reliable_backup()):
+ # self.pids_agents = Properties()
+ # self.pids_agents.load_if_exists(self.pid_file_agents)
+ #self.pids_daemons = Properties()
+ #self.pids_daemons.load_if_exists(self.pid_file_daemons)
# read the nodelists
if ( len(nodefiles) == 0 ):
@@ -397,30 +398,30 @@ class CheckDucc(DuccUtil):
self.threadpool.quit()
- if ( self.kill_signal != None ):
- if(self.automanage_broker):
- print 'Stopping broker'
- self.stop_broker()
- else:
- print 'Not stopping broker - not automanaged'
- if(self.automanage_database):
- print 'Stopping database'
- self.db_stop()
- else:
- print 'Not stopping database - not automanaged'
+ #if ( self.kill_signal != None ):
+ # if(self.automanage_broker):
+ # print 'Stopping broker'
+ # self.stop_broker()
+ # else:
+ # print 'Not stopping broker - not automanaged'
+ # if(self.automanage_database):
+ # print 'Stopping database'
+ # self.db_stop()
+ # else:
+ # print 'Not stopping database - not automanaged'
- if(not self.is_reliable_backup()):
- if ( len(self.pids_agents) == 0):
- if ( os.path.exists(self.pid_file_agents) ):
- os.remove(self.pid_file_agents)
- elif (process_changes or redo_pids):
- self.pids_agents.write(self.pid_file_agents)
+ #if(not self.is_reliable_backup()):
+ # if ( len(self.pids_agents) == 0):
+ # if ( os.path.exists(self.pid_file_agents) ):
+ # os.remove(self.pid_file_agents)
+ # elif (process_changes or redo_pids):
+ # self.pids_agents.write(self.pid_file_agents)
- if ( len(self.pids_daemons) == 0):
- if ( os.path.exists(self.pid_file_daemons) ):
- os.remove(self.pid_file_daemons)
- elif (process_changes or redo_pids):
- self.pids_daemons.write(self.pid_file_daemons)
+ #if ( len(self.pids_daemons) == 0):
+ # if ( os.path.exists(self.pid_file_daemons) ):
+ # os.remove(self.pid_file_daemons)
+ #elif (process_changes or redo_pids):
+ # self.pids_daemons.write(self.pid_file_daemons)
if __name__ == "__main__":
checker = CheckDucc()
Added: uima/uima-ducc/trunk/src/main/admin/cron/db_autostart.crontab.example
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/cron/db_autostart.crontab.example?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/cron/db_autostart.crontab.example (added)
+++ uima/uima-ducc/trunk/src/main/admin/cron/db_autostart.crontab.example Wed Aug 15 12:05:15 2018
@@ -0,0 +1,25 @@
+
+# Example crontab to autostart DUCC daemons
+
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+# every 10 minutes: re-start any DUCC daemons that are down on this node
+
+10 * * * * /share/Python-2.7.8/bin/python2.7 /home/ducc/ducc_runtime/admin/autostart.py 2>&1
Added: uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py (added)
+++ uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py Wed Aug 15 12:05:15 2018
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+import sys
+
+version_min = [2, 7]
+version_info = sys.version_info
+version_error = False
+if(version_info[0] < version_min[0]):
+ version_error = True
+elif(version_info[0] == version_min[0]):
+ if(version_info[1] < version_min[1]):
+ version_error = True
+if(version_error):
+ print('Python minimum requirement is version '+str(version_min[0])+'.'+str(version_min[1]))
+ sys.exit(1)
+
+import argparse
+import os
+import subprocess
+
+from ducc_util import DuccUtil
+
+# command to delete from the autostart database table the specified host & daemon
+
+class AutostartDelete(DuccUtil):
+
+ valid_names = [ 'ag', 'br', 'or', 'pm', 'rm', 'sm', 'ws' ]
+ jclass = 'org.apache.uima.ducc.database.lifetime.DbDaemonLifetimeUI'
+
+ description = 'Delete an entry from the autostart database table.'
+
+ def get_args(self):
+ parser = argparse.ArgumentParser(description=self.description)
+ parser.add_argument('--host', action='store', required=True, help='the DUCC daemon host')
+ parser.add_argument('--name', action='store', required=True, choices=self.valid_names, help='the DUCC daemon name')
+ self.args = parser.parse_args()
+
+ def find(self):
+ retVal = False
+ option = '--query'
+ cmd = [self.jvm, '-DDUCC_HOME='+self.DUCC_HOME, self.jclass, option]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ lines = out.split('\n')
+ for line in lines:
+ tokens = line.split('.')
+ if(len(tokens) == 2):
+ host = tokens[0]
+ name = tokens[1].split('=')[0]
+ if(host == self.args.host):
+ if(name == self.args.name):
+ retVal = True
+ return retVal
+
+ def delete(self):
+ option = '--delete'
+ cmd = [self.jvm, '-DDUCC_HOME='+self.DUCC_HOME, self.jclass, option, self.args.host, self.args.name]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+
+ def main(self, argv):
+ self.get_args()
+ if(self.find()):
+ self.delete()
+ if(self.find()):
+ print 'not deleted'
+ else:
+ print 'deleted'
+ else:
+ print 'not found'
+
+if __name__ == "__main__":
+
+ instance = AutostartDelete()
+ instance.main(sys.argv[1:])
Propchange: uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: uima/uima-ducc/trunk/src/main/admin/db_autostart_delete.py
------------------------------------------------------------------------------
svn:executable = *
Added: uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py?rev=1838082&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py (added)
+++ uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py Wed Aug 15 12:05:15 2018
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# -----------------------------------------------------------------------
+
+import sys
+
+version_min = [2, 7]
+version_info = sys.version_info
+version_error = False
+if(version_info[0] < version_min[0]):
+ version_error = True
+elif(version_info[0] == version_min[0]):
+ if(version_info[1] < version_min[1]):
+ version_error = True
+if(version_error):
+ print('Python minimum requirement is version '+str(version_min[0])+'.'+str(version_min[1]))
+ sys.exit(1)
+
+import argparse
+import os
+import subprocess
+
+from ducc_util import DuccUtil
+
+# command to query the database for all started daemons (i.e. what the autostart.py command sees)
+
+class AutostartQuery(DuccUtil):
+
+ description = 'List the entries from the autostart database table.'
+
+ def get_args(self):
+ parser = argparse.ArgumentParser(description=self.description)
+ self.args = parser.parse_args()
+
+ def main(self, argv):
+ self.get_args()
+ jclass = 'org.apache.uima.ducc.database.lifetime.DbDaemonLifetimeUI'
+ option = '--query'
+ cmd = [self.jvm, '-DDUCC_HOME='+self.DUCC_HOME, jclass, option]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ #print out
+ lines = out.split('\n')
+ counter = 0
+ for line in lines:
+ if('.db' in line):
+ print line
+ counter = counter + 1
+ elif('.br' in line):
+ print line
+ counter = counter + 1
+ elif('.or' in line):
+ print line
+ counter = counter + 1
+ elif('.pm' in line):
+ print line
+ counter = counter + 1
+ elif('.rm' in line):
+ print line
+ counter = counter + 1
+ elif('.sm' in line):
+ print line
+ counter = counter + 1
+ elif('.ws' in line):
+ print line
+ counter = counter + 1
+ elif('.ag' in line):
+ print line
+ counter = counter + 1
+ if(counter == 0):
+ print 'no daemon(s) registered as started in database'
+
+if __name__ == "__main__":
+
+ instance = AutostartQuery()
+ instance.main(sys.argv[1:])
Propchange: uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: uima/uima-ducc/trunk/src/main/admin/db_autostart_query.py
------------------------------------------------------------------------------
svn:executable = *