Ver Fonte

RPC interface methods stopProcess(), stopProcessGroup(), and
stopAllProcesses() now take an optional "wait" argument that defaults
to True for parity with the start methods.

Mike Naberezny há 17 anos atrás
pai
commit
a038641c41
3 ficheiros alterados com 95 adições e 7 exclusões
  1. 4 0
      CHANGES.txt
  2. 16 7
      src/supervisor/rpcinterface.py
  3. 75 0
      src/supervisor/tests/test_rpcinterfaces.py

+ 4 - 0
CHANGES.txt

@@ -187,6 +187,10 @@ Next Release
  - Allow "web handler" (the handler which receives http requests from 
    browsers visiting the web UI of supervisor) to deal with POST requests.
 
+ - RPC interface methods stopProcess(), stopProcessGroup(), and
+   stopAllProcesses() now take an optional "wait" argument that defaults
+   to True for parity with the start methods.  
+
 3.0a3
 
   - Supervisorctl now reports a better error message when the main

+ 16 - 7
src/supervisor/rpcinterface.py

@@ -306,10 +306,11 @@ class SupervisorNamespaceRPCInterface:
         startall.rpcinterface = self
         return startall # deferred
 
-    def stopProcess(self, name):
+    def stopProcess(self, name, wait=True):
         """ Stop a process named by name
 
         @param string name  The name of the process to stop (or 'group:name')
+        @param boolean wait        Wait for the process to be fully stopped
         @return boolean result     Always return True unless error
         """
         self._update('stopProcess')
@@ -318,7 +319,7 @@ class SupervisorNamespaceRPCInterface:
 
         if process is None:
             group_name, process_name = split_namespec(name)
-            return self.stopProcessGroup(group_name)
+            return self.stopProcessGroup(group_name, wait)
 
         stopped = []
         called  = []
@@ -335,7 +336,11 @@ class SupervisorNamespaceRPCInterface:
                 if msg is not None:
                     raise RPCError(Faults.FAILED, msg)
                 stopped.append(1)
-                return NOT_DONE_YET
+                
+                if wait:
+                    return NOT_DONE_YET
+                else:
+                    return True
             
             if process.get_state() not in (ProcessStates.STOPPED,
                                            ProcessStates.EXITED):
@@ -347,10 +352,11 @@ class SupervisorNamespaceRPCInterface:
         killit.rpcinterface = self
         return killit # deferred
 
-    def stopProcessGroup(self, name):
+    def stopProcessGroup(self, name, wait=True):
         """ Stop all processes in the process group named 'name'
 
         @param string name  The group name
+        @param boolean wait    Wait for each process to be fully stopped
         @return boolean result Always return true unless error.
         """
         self._update('stopProcessGroup')
@@ -364,22 +370,25 @@ class SupervisorNamespaceRPCInterface:
         processes.sort()
         processes = [ (group, process) for process in processes ]
 
-        killall = make_allfunc(processes, isRunning, self.stopProcess)
+        killall = make_allfunc(processes, isRunning, self.stopProcess,
+                               wait=wait)
             
         killall.delay = 0.05
         killall.rpcinterface = self
         return killall # deferred
 
-    def stopAllProcesses(self):
+    def stopAllProcesses(self, wait=True):
         """ Stop all processes in the process list
 
+        @param boolean wait    Wait for each process to be fully stopped
         @return boolean result Always return true unless error.
         """
         self._update('stopAllProcesses')
         
         processes = self._getAllProcesses()
 
-        killall = make_allfunc(processes, isRunning, self.stopProcess)
+        killall = make_allfunc(processes, isRunning, self.stopProcess,
+                               wait=wait)
 
         killall.delay = 0.05
         killall.rpcinterface = self

+ 75 - 0
src/supervisor/tests/test_rpcinterfaces.py

@@ -594,6 +594,19 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         self.assertEqual(len(supervisord.process_groups['foo'].processes), 1)
         self.assertEqual(interface.update_text, 'stopProcess')
 
+    def test_stopProcess_nowait(self):
+        options = DummyOptions()
+        pconfig = DummyPConfig(options, 'foo', __file__)
+        from supervisor.process import ProcessStates
+        supervisord = PopulatedDummySupervisor(options, 'foo', pconfig)
+        supervisord.set_procattr('foo', 'state', ProcessStates.RUNNING)
+        interface = self._makeOne(supervisord)
+        callback = interface.stopProcess('foo', wait=False)
+        self.assertEqual(callback(), True)
+        process = supervisord.process_groups['foo'].processes['foo']
+        self.assertEqual(process.stop_called, True)
+        self.assertEqual(interface.update_text, 'stopProcess')
+
     def test_stopProcessGroup(self):
         options = DummyOptions()
         pconfig1 = DummyPConfig(options, 'process1', '/bin/foo')
@@ -622,6 +635,37 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         process2 = supervisord.process_groups['foo'].processes['process2']
         self.assertEqual(process2.stop_called, True)
 
+    def test_stopProcessGroup_nowait(self):
+        options = DummyOptions()
+        pconfig1 = DummyPConfig(options, 'process1', __file__)
+        pconfig2 = DummyPConfig(options, 'process2', __file__)
+        supervisord = PopulatedDummySupervisor(options, 'foo', pconfig1,
+                                               pconfig2)
+        from supervisor.process import ProcessStates
+        supervisord.set_procattr('process1', 'state', ProcessStates.RUNNING)
+        supervisord.set_procattr('process2', 'state', ProcessStates.RUNNING)
+        interface = self._makeOne(supervisord)
+        callback = interface.stopProcessGroup('foo', wait=False)
+        from supervisor.http import NOT_DONE_YET
+        from supervisor.xmlrpc import Faults
+
+        # create callbacks in killall()
+        self.assertEqual(callback(), NOT_DONE_YET)
+
+        # get a result
+        result = callback()
+
+        self.assertEqual(len(result), 2)
+        self.assertEqual(result[0]['name'], 'process1')
+        self.assertEqual(result[0]['group'], 'foo')
+        self.assertEqual(result[0]['status'],  Faults.SUCCESS)
+        self.assertEqual(result[0]['description'], 'OK')
+
+        self.assertEqual(result[1]['name'], 'process2')
+        self.assertEqual(result[1]['group'], 'foo')
+        self.assertEqual(result[1]['status'],  Faults.SUCCESS)
+        self.assertEqual(result[1]['description'], 'OK')
+
     def test_stopProcessGroup_badname(self):
         from supervisor import xmlrpc
         supervisord = DummySupervisor()
@@ -673,6 +717,37 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         process2 = supervisord.process_groups['foo'].processes['process2']
         self.assertEqual(process2.stop_called, True)
 
+    def test_stopAllProcesses_nowait(self):
+        options = DummyOptions()
+        pconfig1 = DummyPConfig(options, 'process1', __file__)
+        pconfig2 = DummyPConfig(options, 'process2', __file__)
+        supervisord = PopulatedDummySupervisor(options, 'foo', pconfig1,
+                                               pconfig2)
+        from supervisor.process import ProcessStates
+        supervisord.set_procattr('process1', 'state', ProcessStates.RUNNING)
+        supervisord.set_procattr('process2', 'state', ProcessStates.RUNNING)
+        interface = self._makeOne(supervisord)
+        callback = interface.stopAllProcesses(wait=False)
+        from supervisor.http import NOT_DONE_YET
+        from supervisor.xmlrpc import Faults
+
+        # create callbacks in killall()
+        self.assertEqual(callback(), NOT_DONE_YET)
+
+        # get a result
+        result = callback()
+
+        self.assertEqual(len(result), 2)
+        self.assertEqual(result[0]['name'], 'process1')
+        self.assertEqual(result[0]['group'], 'foo')
+        self.assertEqual(result[0]['status'],  Faults.SUCCESS)
+        self.assertEqual(result[0]['description'], 'OK')
+
+        self.assertEqual(result[1]['name'], 'process2')
+        self.assertEqual(result[1]['group'], 'foo')
+        self.assertEqual(result[1]['status'],  Faults.SUCCESS)
+        self.assertEqual(result[1]['description'], 'OK')
+
     def test__interpretProcessInfo(self):
         supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)