فهرست منبع

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 
  - Allow "web handler" (the handler which receives http requests from 
    browsers visiting the web UI of supervisor) to deal with POST requests.
    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
 3.0a3
 
 
   - Supervisorctl now reports a better error message when the main
   - 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
         startall.rpcinterface = self
         return startall # deferred
         return startall # deferred
 
 
-    def stopProcess(self, name):
+    def stopProcess(self, name, wait=True):
         """ Stop a process named by name
         """ Stop a process named by name
 
 
         @param string name  The name of the process to stop (or 'group: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
         @return boolean result     Always return True unless error
         """
         """
         self._update('stopProcess')
         self._update('stopProcess')
@@ -318,7 +319,7 @@ class SupervisorNamespaceRPCInterface:
 
 
         if process is None:
         if process is None:
             group_name, process_name = split_namespec(name)
             group_name, process_name = split_namespec(name)
-            return self.stopProcessGroup(group_name)
+            return self.stopProcessGroup(group_name, wait)
 
 
         stopped = []
         stopped = []
         called  = []
         called  = []
@@ -335,7 +336,11 @@ class SupervisorNamespaceRPCInterface:
                 if msg is not None:
                 if msg is not None:
                     raise RPCError(Faults.FAILED, msg)
                     raise RPCError(Faults.FAILED, msg)
                 stopped.append(1)
                 stopped.append(1)
-                return NOT_DONE_YET
+                
+                if wait:
+                    return NOT_DONE_YET
+                else:
+                    return True
             
             
             if process.get_state() not in (ProcessStates.STOPPED,
             if process.get_state() not in (ProcessStates.STOPPED,
                                            ProcessStates.EXITED):
                                            ProcessStates.EXITED):
@@ -347,10 +352,11 @@ class SupervisorNamespaceRPCInterface:
         killit.rpcinterface = self
         killit.rpcinterface = self
         return killit # deferred
         return killit # deferred
 
 
-    def stopProcessGroup(self, name):
+    def stopProcessGroup(self, name, wait=True):
         """ Stop all processes in the process group named 'name'
         """ Stop all processes in the process group named 'name'
 
 
         @param string name  The group 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.
         @return boolean result Always return true unless error.
         """
         """
         self._update('stopProcessGroup')
         self._update('stopProcessGroup')
@@ -364,22 +370,25 @@ class SupervisorNamespaceRPCInterface:
         processes.sort()
         processes.sort()
         processes = [ (group, process) for process in processes ]
         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.delay = 0.05
         killall.rpcinterface = self
         killall.rpcinterface = self
         return killall # deferred
         return killall # deferred
 
 
-    def stopAllProcesses(self):
+    def stopAllProcesses(self, wait=True):
         """ Stop all processes in the process list
         """ 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.
         @return boolean result Always return true unless error.
         """
         """
         self._update('stopAllProcesses')
         self._update('stopAllProcesses')
         
         
         processes = self._getAllProcesses()
         processes = self._getAllProcesses()
 
 
-        killall = make_allfunc(processes, isRunning, self.stopProcess)
+        killall = make_allfunc(processes, isRunning, self.stopProcess,
+                               wait=wait)
 
 
         killall.delay = 0.05
         killall.delay = 0.05
         killall.rpcinterface = self
         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(len(supervisord.process_groups['foo'].processes), 1)
         self.assertEqual(interface.update_text, 'stopProcess')
         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):
     def test_stopProcessGroup(self):
         options = DummyOptions()
         options = DummyOptions()
         pconfig1 = DummyPConfig(options, 'process1', '/bin/foo')
         pconfig1 = DummyPConfig(options, 'process1', '/bin/foo')
@@ -622,6 +635,37 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         process2 = supervisord.process_groups['foo'].processes['process2']
         process2 = supervisord.process_groups['foo'].processes['process2']
         self.assertEqual(process2.stop_called, True)
         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):
     def test_stopProcessGroup_badname(self):
         from supervisor import xmlrpc
         from supervisor import xmlrpc
         supervisord = DummySupervisor()
         supervisord = DummySupervisor()
@@ -673,6 +717,37 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         process2 = supervisord.process_groups['foo'].processes['process2']
         process2 = supervisord.process_groups['foo'].processes['process2']
         self.assertEqual(process2.stop_called, True)
         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):
     def test__interpretProcessInfo(self):
         supervisord = DummySupervisor()
         supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)
         interface = self._makeOne(supervisord)