소스 검색

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 17 년 전
부모
커밋
a038641c41
3개의 변경된 파일95개의 추가작업 그리고 7개의 파일을 삭제
  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)