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/04/17 17:24:52 UTC

svn commit: r1829373 - in /uima/uima-ducc/branches/reliable-ducc: src/main/admin/ src/main/scripts/ uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/

Author: degenaro
Date: Tue Apr 17 17:24:51 2018
New Revision: 1829373

URL: http://svn.apache.org/viewvc?rev=1829373&view=rev
Log:
UIMA-5742 Reliable DUCC

- start/stop/kill broker only when ducc.broker.autostart = true
- start/stop/kill database only when ducc.database.autostart = true
- do not start/stop agents from backup head node

Modified:
    uima/uima-ducc/branches/reliable-ducc/src/main/admin/check_ducc
    uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_head_mode.py
    uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_util.py
    uima/uima-ducc/branches/reliable-ducc/src/main/admin/start_ducc
    uima/uima-ducc/branches/reliable-ducc/src/main/admin/stop_ducc
    uima/uima-ducc/branches/reliable-ducc/src/main/scripts/properties.py
    uima/uima-ducc/branches/reliable-ducc/uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/admin-commands.tex

Modified: uima/uima-ducc/branches/reliable-ducc/src/main/admin/check_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/src/main/admin/check_ducc?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/src/main/admin/check_ducc (original)
+++ uima/uima-ducc/branches/reliable-ducc/src/main/admin/check_ducc Tue Apr 17 17:24:51 2018
@@ -99,6 +99,10 @@ class CheckDucc(DuccUtil):
 
                 signal = self.kill_signal
                 
+                if(self.is_reliable_backup()):
+                    if ( component == 'agent' ):
+                        continue
+                    
                 if ( component == 'orchestrator' ):
                     component = 'or'
                     
@@ -116,18 +120,21 @@ class CheckDucc(DuccUtil):
                     else:
                         messages.append((spacer, 'Killing (' +  signal + ')', process_id))
                         self.kill_process(node, proc, signal)
-                        self.pids.delete(pid)
+                        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.put(full_name, pid)
-
-                    if ( component in self.default_components ):
-                        self.pids.put(full_name, pid)
-                        self.pids.put(component, full_name)
+                        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.'))
 
@@ -172,6 +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 "Options:"
         print "    -n --nodelist nodefile"
         print "        Check for agents on the nodes in nodefile.  This option may be specified multiple time"
@@ -203,7 +215,7 @@ class CheckDucc(DuccUtil):
         print "       changes."
         print ""
         print "    -x localdate"
-        print "       Validate the local installation, called via ssh usually. The date is the dat on the calling machine."
+        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"
@@ -306,9 +318,12 @@ class CheckDucc(DuccUtil):
         self.verify_database() 
 
         # init the PID file
-        self.pids = Properties()
-        self.pids.load_if_exists(self.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
@@ -376,17 +391,30 @@ class CheckDucc(DuccUtil):
         self.threadpool.quit()
 
         if ( self.kill_signal != None ):
-            print 'Stopping broker'
-            self.stop_broker()
-            print 'Stopping database'
-            self.db_stop()
-                
-        if ( len(self.pids) == 0):
-            if ( os.path.exists(self.pid_file) ):
-                os.remove(self.pid_file)
+            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.write(self.pid_file)
-    
+            self.pids_daemons.write(self.pid_file_daemons)
+            
 if __name__ == "__main__":
     checker = CheckDucc()
     checker.main(sys.argv[1:])

Modified: uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_head_mode.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_head_mode.py?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_head_mode.py (original)
+++ uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_head_mode.py Tue Apr 17 17:24:51 2018
@@ -31,47 +31,9 @@ class DuccHeadMode(DuccUtil):
     # operation:  look in ducc.properties for relevant keywords
     #             and employ linux commands to determine if system
     #             has matching configured virtual ip address
-
-    debug_flag = False
     
-    def debug(self,text):
-        if(self.debug_flag):
-            print(text)
-    
-    keepalivd_conf = '/etc/keepalived/keepalived.conf'
-    
-    # eligible when keepalived config comprises the ip
-    def is_reliable_eligible(self, ip):
-        retVal = False
-        if ( os.path.exists(self.keepalivd_conf) ):
-            with open(self.keepalivd_conf) as f:
-                for line in f:
-                    if ip in line:
-                        retVal = True
-                        break
-        return retVal
-    
-    # master when current node keepalived answers for head node ip
-    # backup when current node keepalived does not answer for head ip, but is capable in config
-    # unspecified otherwise
     def main(self):
-    	result = 'unspecified'
-    	try:
-            ducc_head = self.ducc_properties.get('ducc.head')
-            head_ip = self.get_ip_address(ducc_head)
-            if(self.is_reliable_eligible(head_ip)):
-    	    	text = 'cmd: ', '/sbin/ip', 'addr', 'list'
-                self.debug(text)
-    	    	p = subprocess.Popen(['/sbin/ip', 'addr', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-            	output, err = p.communicate()
-            	text = "output: "+output
-                self.debug(text)
-            	if(head_ip in output):
-            		result = 'master'
-            	else:
-            		result = 'backup'
-    	except Exception as e:
-    		print e
+    	result = self.get_reliable_state()
     	print result
         
 if __name__ == '__main__':

Modified: uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_util.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_util.py?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_util.py (original)
+++ uima/uima-ducc/branches/reliable-ducc/src/main/admin/ducc_util.py Tue Apr 17 17:24:51 2018
@@ -583,6 +583,7 @@ class DuccUtil(DuccBase):
     
     # transform hostname into ip address
     def get_ip_address(self,hostname):
+        label = 'get_ip_address'
         result = None
         try:
             p = subprocess.Popen(['/usr/bin/nslookup', hostname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -602,7 +603,7 @@ class DuccUtil(DuccBase):
                         name = t1
         except Exception as e:
             print e
-        debug('ip_address: ', str(result))
+        debug(label, str(result))
         return result
     
     # get all possible hostnames & ip addresses for a head node
@@ -1192,6 +1193,46 @@ class DuccUtil(DuccBase):
             return False
         return True
 
+    keepalivd_conf = '/etc/keepalived/keepalived.conf'
+
+    # eligible when keepalived config comprises the ip
+    def is_reliable_eligible(self, ip):
+        retVal = False
+        if ( os.path.exists(self.keepalivd_conf) ):
+            with open(self.keepalivd_conf) as f:
+                for line in f:
+                    if ip in line:
+                        retVal = True
+                        break
+        return retVal
+        
+    # master when current node keepalived answers for head node ip
+    # backup when current node keepalived does not answer for head ip, but is capable in config
+    # unspecified otherwise
+    def get_reliable_state(self):
+        label = 'get_reliable_state'
+        result = 'unspecified'
+        try:
+            ducc_head = self.ducc_properties.get('ducc.head')
+            head_ip = self.get_ip_address(ducc_head)
+            if(self.is_reliable_eligible(head_ip)):
+                text = 'cmd: ', '/sbin/ip', 'addr', 'list'
+                debug(label, text)
+                p = subprocess.Popen(['/sbin/ip', 'addr', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                output, err = p.communicate()
+                text = "output: "+output
+                debug(label, text)
+                if(head_ip in output):
+                    result = 'master'
+                else:
+                    result = 'backup'
+        except Exception as e:
+            print e
+        return result
+    
+    def is_reliable_backup(self):
+        return self.get_reliable_state() == 'backup'
+    
     def __init__(self, merge=False):
         global use_threading
         DuccBase.__init__(self, merge)
@@ -1209,7 +1250,7 @@ class DuccUtil(DuccBase):
         if ( self.localhost == self.ducc_properties.get("ducc.head")):
             self.is_ducc_head = True
 
-        os.environ['DUCC_NODENAME'] = self.localhost    # to match java code's implicit propery so script and java match
+        os.environ['DUCC_NODENAME'] = self.localhost    # to match java code's implicit property so script and java match
 
         dbhost = self.ducc_properties.get('ducc.database.host')
         if ( dbhost == None ):
@@ -1225,7 +1266,8 @@ class DuccUtil(DuccBase):
         self.db_pidfile = dir_db_state+ '/cassandra.pid'
         self.db_logfile = dir_db_logs + '/cassandra.console'
         
-        self.pid_file  = self.DUCC_HOME + '/state/ducc.pids'
+        self.pid_file_agents  = self.DUCC_HOME + '/state/agents/ducc.pids'
+        self.pid_file_daemons  = self.DUCC_HOME + '/state/daemons/'+self.get_node_name()+'/ducc.pids'
         self.set_classpath()
         self.os_pagesize = self.get_os_pagesize()
         self.update_properties()

Modified: uima/uima-ducc/branches/reliable-ducc/src/main/admin/start_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/src/main/admin/start_ducc?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/src/main/admin/start_ducc (original)
+++ uima/uima-ducc/branches/reliable-ducc/src/main/admin/start_ducc Tue Apr 17 17:24:51 2018
@@ -52,7 +52,7 @@ class StartDucc(DuccUtil):
             if ( line.startswith('PID') ):
                 toks = line.split(' ')    # get the PID
                 print "Broker on", broker_host, 'PID', toks[1]
-                self.pids.put('broker@' + broker_host, toks[1])
+                self.pids_daemons.put('broker@' + broker_host, toks[1])
                 lines.close()
                 break
 
@@ -103,7 +103,7 @@ class StartDucc(DuccUtil):
             if ( line.startswith('PID') ):
                 toks = line.split(' ')    # get the PID
                 msgs.append(('     PID', toks[1]))
-                self.pids.put(com + '@' + node, toks[1])
+                self.pids_daemons.put(com + '@' + node, toks[1])
                 lines.close()
                 break
             if ( line.startswith('WARN') ):
@@ -111,7 +111,7 @@ class StartDucc(DuccUtil):
             
         if ( com in self.default_components ):           # tracks where the management processes are
             self.pidlock.acquire()
-            self.pids.put(com, com + '@' + node)
+            self.pids_daemons.put(com, com + '@' + node)
             self.pidlock.release()
 
         return msgs
@@ -131,7 +131,7 @@ class StartDucc(DuccUtil):
                 toks = line.split(' ')
                 pid = toks[1]
                 self.pidlock.acquire()
-                self.pids.put('agent@' + host, pid)
+                self.pids_agents.put('agent@' + host, pid)
                 self.pidlock.release()
 
                 lines.close()
@@ -172,6 +172,11 @@ class StartDucc(DuccUtil):
         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:"
@@ -242,8 +247,11 @@ class StartDucc(DuccUtil):
         nodefiles = []
         components = []
         or_parms = self.ducc_properties.get('ducc.orchestrator.start.type')
-        self.pids = Properties()
-        self.pids.load_if_exists(self.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)
         
         try:
             opts, args = getopt.getopt(argv, 'c:mn:sh?v', ['component=', 'help', 'nodelist=', 'cold', 'warm', 'nothreading'])
@@ -372,16 +380,17 @@ class StartDucc(DuccUtil):
                         sys.exit(1)
                     # give 'or' a small head start
                     time.sleep(2)
-                    
-        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(not self.is_reliable_backup()):
+            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
@@ -400,8 +409,11 @@ class StartDucc(DuccUtil):
 
         self.threadpool.quit()
 
-        if ( len(self.pids) > 0 ):
-            self.pids.write(self.pid_file)
+        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__":

Modified: uima/uima-ducc/branches/reliable-ducc/src/main/admin/stop_ducc
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/src/main/admin/stop_ducc?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/src/main/admin/stop_ducc (original)
+++ uima/uima-ducc/branches/reliable-ducc/src/main/admin/stop_ducc Tue Apr 17 17:24:51 2018
@@ -46,11 +46,18 @@ class StopDucc(DuccUtil):
         # If it's an unqualified management component, we need to get it's qualified name
         #
         if ( component in self.default_components ):
-            if ( self.pids.has_key(component) ):
-                component = self.pids.get(component)
+            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:
-                print 'Skipping', component, 'not in pids file.'
-                return
+                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
@@ -63,11 +70,19 @@ class StopDucc(DuccUtil):
         #
         # If despite all that we can't find the pid, we need to run check_ducc
         #        
-        if ( not self.pids.has_key(component) ):
-            print "Cannot find PID for component", component, ". Run check_ducc -p to refresh PIDS and then rerun stop_ducc."
-            return
-
-        pid = self.pids.get(component)
+        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)'
@@ -79,8 +94,12 @@ class StopDucc(DuccUtil):
             self.nohup(['ssh', target_node, 'kill', '-INT', pid], False)
 
         # clear the short name if it exists, and the long name
-        self.pids.delete(com)
-        self.pids.delete(component)
+        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):
@@ -106,7 +125,8 @@ class StopDucc(DuccUtil):
         return
 
     def stop_agents(self, node, force):
-        self.stop_component('agent@' + node.strip(), force)
+        if(not self.is_reliable_backup()):
+            self.stop_component('agent@' + node.strip(), force)
     
     def usage(self, msg):
         if ( msg != None ):
@@ -115,6 +135,11 @@ class StopDucc(DuccUtil):
         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.'
@@ -260,27 +285,30 @@ class StopDucc(DuccUtil):
                 	print "Stopping database"
                 	self.db_stop()
 
-                if ( os.path.exists(self.pid_file) ):
-                    os.remove(self.pid_file)
+                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 = Properties()
+        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:
-                self.pids.load(self.pid_file)
-                pass
+                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 ''
@@ -333,10 +361,15 @@ class StopDucc(DuccUtil):
                     self.stop_component(c, force)         
 
         if ( read_pids ):
-            if ( len(self.pids) > 0 ):
-                self.pids.write(self.pid_file)
+            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)
+                os.remove(self.pid_file_daemons)
 
         return
 

Modified: uima/uima-ducc/branches/reliable-ducc/src/main/scripts/properties.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/src/main/scripts/properties.py?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/src/main/scripts/properties.py (original)
+++ uima/uima-ducc/branches/reliable-ducc/src/main/scripts/properties.py Tue Apr 17 17:24:51 2018
@@ -213,11 +213,22 @@ class Properties:
         if ( self.props.has_key(key) ):
             del self.props[key]
             self.keys.remove(key)
-
+        
+    #
+    # make directories, if need be
+    #
+    def _makedirs(self, path):
+        try:
+            dir_path = path.rsplit('/',1)[0]
+            os.makedirs(dir_path)
+        except:
+            pass
+        
     #
     # Write the has as a Java-like properties file
     #
     def write(self, propsfile):
+        self._makedirs(propsfile)
         f = open(propsfile, 'w')
         for k in self.keys:
             p = self.props[k]

Modified: uima/uima-ducc/branches/reliable-ducc/uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/admin-commands.tex
URL: http://svn.apache.org/viewvc/uima/uima-ducc/branches/reliable-ducc/uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/admin-commands.tex?rev=1829373&r1=1829372&r2=1829373&view=diff
==============================================================================
--- uima/uima-ducc/branches/reliable-ducc/uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/admin-commands.tex (original)
+++ uima/uima-ducc/branches/reliable-ducc/uima-ducc-duccdocs/src/site/tex/duccbook/part4/admin/admin-commands.tex Tue Apr 17 17:24:51 2018
@@ -42,6 +42,13 @@
       Services Manager, and Web Server on the local node.
       \item Starts an agent process on every node named in the default node list. 
     \end{itemize}
+    
+    Exceptions:
+    \begin{itemize}
+      \item When running reliable DUCC, agents are not started from any backup node.
+      \item When ducc.broker.autostart = false, the ActiveMQ server will not be started.
+      \item When ducc.database.autostart = false, the database will not be started.
+    \end{itemize}
 
     \subsubsection{{\em Usage}}
 
@@ -144,13 +151,19 @@ start_ducc -c sm -c pm -c rm -c or@bj22
     When {\em -a} is specified, the following actions are taken:
     \begin{itemize}
        \item Uses the ActiveMQ broker to broadcast a shutdown request to all
-        DUCC compoments, other than the ActiveMQ broker itself, and the database.
+        DUCC components, other than the ActiveMQ broker itself, and the database.
       \item Waits a bit, for all daemons to stop.
       \item Stops the database.
       \item Stops the ActiveMQ broker.
     \end{itemize}
 
-
+    Exceptions:
+    \begin{itemize}
+      \item When running reliable DUCC, agents are not stopped from any backup node.
+      \item When ducc.broker.autostart = false, the ActiveMQ server will not be stopped.
+      \item When ducc.database.autostart = false, the database will not be stopped.
+    \end{itemize}
+    
     \subsubsection{\em Usage:}
 
     \begin{description}
@@ -250,6 +263,13 @@ start_ducc -c rm
     to do so. The difference is that stop\_ducc generally tries more gracefully stop processes. 
     check\_ducc is used as a last resort, or if a fast but graceless shutdown is desired. 
     
+    Exceptions:
+    \begin{itemize}
+      \item When running reliable DUCC, agents are not killed from any backup node.
+      \item When ducc.broker.autostart = false, the ActiveMQ server will not be killed.
+      \item When ducc.database.autostart = false, the database will not be killed.
+    \end{itemize}
+    
     \subsubsection{\em{Usage: }}
 
         \begin{description}