Преглед изворни кода

Keep track of supervisor "mood" on options object so we can access it from
elsewhere. Define a FATAL state (although it's unused right now).

Chris McDonough пре 18 година
родитељ
комит
1947b7ec67

+ 2 - 0
src/supervisor/options.py

@@ -57,6 +57,7 @@ from supervisor.datatypes import Automatic
 from supervisor.datatypes import auto_restart
 
 from supervisor import loggers
+from supervisor import states
 
 here = os.path.abspath(os.path.dirname(__file__))
 version_txt = os.path.join(here, 'version.txt')
@@ -332,6 +333,7 @@ class ServerOptions(Options):
     environment = None
     httpserver = None
     unlink_socketfile = True
+    mood = states.SupervisorStates.RUNNING
     
     ANSI_ESCAPE_BEGIN = '\x1b['
     ANSI_TERMINATORS = ('H', 'f', 'A', 'B', 'C', 'D', 'R', 's', 'u', 'J', 

+ 4 - 8
src/supervisor/rpcinterface.py

@@ -31,10 +31,7 @@ class SupervisorNamespaceRPCInterface:
 
     def _update(self, text):
         self.update_text = text # for unit tests, mainly
-
-        state = self.supervisord.get_state()
-
-        if state == SupervisorStates.SHUTDOWN:
+        if self.supervisord.options.mood < SupervisorStates.RUNNING:
             raise RPCError(Faults.SHUTDOWN_STATE)
 
     # RPC API methods
@@ -73,7 +70,7 @@ class SupervisorNamespaceRPCInterface:
         """
         self._update('getState')
 
-        state = self.supervisord.get_state()
+        state = self.supervisord.options.mood
         statename = getSupervisorStateDescription(state)
         data =  {
             'statecode':state,
@@ -132,8 +129,7 @@ class SupervisorNamespaceRPCInterface:
         @return boolean result always returns True unless error
         """
         self._update('shutdown')
-        
-        self.supervisord.mood = -1
+        self.supervisord.options.mood = SupervisorStates.SHUTDOWN
         return True
 
     def restart(self):
@@ -143,7 +139,7 @@ class SupervisorNamespaceRPCInterface:
         """
         self._update('restart')
         
-        self.supervisord.mood = 0
+        self.supervisord.options.mood = SupervisorStates.RESTARTING
         return True
 
     def _getAllProcesses(self, lexical=False):

+ 21 - 2
src/supervisor/states.py

@@ -1,3 +1,20 @@
+##############################################################################
+#
+# Copyright (c) 2007 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+# This modules must not depend on any other non-stdlib module to prevent
+# circular import problems.
+
 class ProcessStates:
     STOPPED = 0
     STARTING = 10
@@ -25,8 +42,10 @@ def getProcessStateDescription(code):
             return statename
 
 class SupervisorStates:
-    ACTIVE = 0
-    SHUTDOWN = 1
+    FATAL = 2
+    RUNNING = 1
+    RESTARTING = 0
+    SHUTDOWN = -1
 
 def getSupervisorStateDescription(code):
     for statename in SupervisorStates.__dict__:

+ 8 - 11
src/supervisor/supervisord.py

@@ -55,7 +55,6 @@ from supervisor.states import SupervisorStates
 from supervisor.states import getProcessStateDescription
 
 class Supervisor:
-    mood = 1 # 1: up, 0: restarting, -1: suicidal
     stopping = False # set after we detect that we are handling a stop request
     lastdelayreport = 0 # throttle for delayed process error reports at stop
     process_groups = None # map of process group name to process group object
@@ -173,10 +172,10 @@ class Supervisor:
             pgroups = self.process_groups.values()
             pgroups.sort()
 
-            if self.mood > 0:
+            if self.options.mood > SupervisorStates.RESTARTING:
                 [ group.start_necessary() for group in pgroups ]
 
-            elif self.mood < 1:
+            elif self.options.mood < SupervisorStates.RUNNING:
                 if not self.stopping:
                     # first time, set the stopping flag, do a
                     # notification and set stop_groups
@@ -239,7 +238,7 @@ class Supervisor:
             self.reap()
             self.handle_signal()
 
-            if self.mood < 1:
+            if self.options.mood < SupervisorStates.RUNNING:
                 self.ordered_stop_groups_phase_2()
 
             if test:
@@ -263,13 +262,13 @@ class Supervisor:
             if sig in (signal.SIGTERM, signal.SIGINT, signal.SIGQUIT):
                 self.options.logger.warn(
                     'received %s indicating exit request' % signame(sig))
-                self.mood = -1
+                self.options.mood = SupervisorStates.SHUTDOWN
             elif sig == signal.SIGHUP:
                 self.options.logger.warn(
                     'received %s indicating restart request' % signame(sig))
-                self.mood = 0
+                self.options.mood = SupervisorStates.RESTARTING
             elif sig == signal.SIGCHLD:
-                self.options.logger.info(
+                self.options.logger.debug(
                     'received %s indicating a child quit' % signame(sig))
             elif sig == signal.SIGUSR2:
                 self.options.logger.info(
@@ -282,9 +281,7 @@ class Supervisor:
                     'received %s indicating nothing' % signame(sig))
         
     def get_state(self):
-        if self.mood <= 0:
-            return SupervisorStates.SHUTDOWN
-        return SupervisorStates.ACTIVE
+        return self.options.mood
 
 # Main program
 def main(test=False):
@@ -302,7 +299,7 @@ def main(test=False):
         first = False
         if test:
             return d
-        if d.mood < 0:
+        if options.mood < SupervisorStates.RUNNING:
             break
         if d.options.httpserver:
             d.options.httpserver.close()

+ 2 - 5
src/supervisor/tests/base.py

@@ -262,17 +262,14 @@ class DummySupervisor:
             self.options = options
         if state is None:
             from supervisor.supervisord import SupervisorStates
-            self.state = SupervisorStates.ACTIVE
+            self.options.mood = SupervisorStates.RUNNING
         else:
-            self.state = state
+            self.options.mood = state
         if process_groups is None:
             self.process_groups = {}
         else:
             self.process_groups = process_groups
 
-    def get_state(self):
-        return self.state
-
 class DummyProcess:
     # Initial state; overridden by instance variables
     pid = 0 # Subprocess pid; 0 when not running

+ 5 - 5
src/supervisor/tests/test_rpcinterfaces.py

@@ -73,7 +73,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         interface = self._makeOne(supervisord)
         interface._update('foo')
         self.assertEqual(interface.update_text, 'foo')
-        supervisord.state = SupervisorStates.SHUTDOWN
+        supervisord.options.mood = SupervisorStates.SHUTDOWN
         self._assertRPCError(xmlrpc.Faults.SHUTDOWN_STATE, interface._update,
                              'foo')
 
@@ -111,7 +111,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)
         stateinfo = interface.getState()
-        statecode = supervisord.get_state()
+        statecode = supervisord.options.mood
         statename = getSupervisorStateDescription(statecode)
         self.assertEqual(stateinfo['statecode'], statecode)
         self.assertEqual(stateinfo['statename'], statename)
@@ -202,14 +202,14 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         interface = self._makeOne(supervisord)
         value = interface.shutdown()
         self.assertEqual(value, True)
-        self.assertEqual(supervisord.mood, -1)
+        self.assertEqual(supervisord.options.mood, -1)
 
     def test_restart(self):
         supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)
         value = interface.restart()
         self.assertEqual(value, True)
-        self.assertEqual(supervisord.mood, 0)
+        self.assertEqual(supervisord.options.mood, 0)
 
     def test_startProcess_already_started(self):
         from supervisor import xmlrpc
@@ -642,7 +642,7 @@ class SupervisorNamespaceXMLRPCInterfaceTests(TestBase):
         self.assertEqual(process2.stop_called, True)
 
     def test__interpretProcessInfo(self):
-        supervisord = DummySupervisor({})
+        supervisord = DummySupervisor()
         interface = self._makeOne(supervisord)
         start = _NOW -100
         stop  = _NOW -1

+ 11 - 19
src/supervisor/tests/test_supervisord.py

@@ -46,14 +46,6 @@ class SupervisordTests(unittest.TestCase):
         self.assertEqual(options.pidfile_written, True)
         self.assertEqual(options.cleaned_up, True)
 
-    def test_get_state(self):
-        from supervisor.supervisord import SupervisorStates
-        options = DummyOptions()
-        supervisord = self._makeOne(options)
-        self.assertEqual(supervisord.get_state(), SupervisorStates.ACTIVE)
-        supervisord.mood = -1
-        self.assertEqual(supervisord.get_state(), SupervisorStates.SHUTDOWN)
-
     def test_reap(self):
         options = DummyOptions()
         options.waitpid_return = 1, 1
@@ -74,7 +66,7 @@ class SupervisordTests(unittest.TestCase):
         options.signal = signal.SIGTERM
         supervisord = self._makeOne(options)
         supervisord.handle_signal()
-        self.assertEqual(supervisord.mood, -1)
+        self.assertEqual(supervisord.options.mood, -1)
         self.assertEqual(options.logger.data[0],
                          'received SIGTERM indicating exit request')
 
@@ -83,7 +75,7 @@ class SupervisordTests(unittest.TestCase):
         options.signal = signal.SIGINT
         supervisord = self._makeOne(options)
         supervisord.handle_signal()
-        self.assertEqual(supervisord.mood, -1)
+        self.assertEqual(supervisord.options.mood, -1)
         self.assertEqual(options.logger.data[0],
                          'received SIGINT indicating exit request')
 
@@ -92,7 +84,7 @@ class SupervisordTests(unittest.TestCase):
         options.signal = signal.SIGQUIT
         supervisord = self._makeOne(options)
         supervisord.handle_signal()
-        self.assertEqual(supervisord.mood, -1)
+        self.assertEqual(supervisord.options.mood, -1)
         self.assertEqual(options.logger.data[0],
                          'received SIGQUIT indicating exit request')
 
@@ -101,7 +93,7 @@ class SupervisordTests(unittest.TestCase):
         options.signal = signal.SIGHUP
         supervisord = self._makeOne(options)
         supervisord.handle_signal()
-        self.assertEqual(supervisord.mood, 0)
+        self.assertEqual(supervisord.options.mood, 0)
         self.assertEqual(options.logger.data[0],
                          'received SIGHUP indicating restart request')
 
@@ -118,7 +110,7 @@ class SupervisordTests(unittest.TestCase):
             options, 'foo',
             pconfigs=pconfigs)
         supervisord.handle_signal()
-        self.assertEqual(supervisord.mood, 1)
+        self.assertEqual(supervisord.options.mood, 1)
         self.assertEqual(options.logs_reopened, True)
         self.assertEqual(options.logger.data[0],
                          'received SIGUSR2 indicating log reopen request')
@@ -128,7 +120,7 @@ class SupervisordTests(unittest.TestCase):
         options.signal = signal.SIGUSR1
         supervisord = self._makeOne(options)
         supervisord.handle_signal()
-        self.assertEqual(supervisord.mood, 1)
+        self.assertEqual(supervisord.options.mood, 1)
         self.assertEqual(options.logger.data[0],
                          'received SIGUSR1 indicating nothing')
 
@@ -210,7 +202,7 @@ class SupervisordTests(unittest.TestCase):
         gconfig = DummyPGroupConfig(options)
         pgroup = DummyProcessGroup(gconfig)
         supervisord.process_groups = {'foo': pgroup}
-        supervisord.mood = -1
+        supervisord.options.mood = -1
         L = []
         def callback(event):
             L.append(event)
@@ -235,7 +227,7 @@ class SupervisordTests(unittest.TestCase):
         def callback():
             L.append(1)
         supervisord.process_groups = {'foo': pgroup}
-        supervisord.mood = 0
+        supervisord.options.mood = 0
         import asyncore
         self.assertRaises(asyncore.ExitNow, supervisord.runforever, test=True)
         self.assertEqual(pgroup.all_stopped, True)
@@ -252,7 +244,7 @@ class SupervisordTests(unittest.TestCase):
         def callback():
             L.append(1)
         supervisord.process_groups = {'foo': pgroup}
-        supervisord.mood = 0
+        supervisord.options.mood = 0
         import asyncore
         supervisord.runforever(test=True)
         self.assertNotEqual(supervisord.lastdelayreport, 0)
@@ -260,8 +252,8 @@ class SupervisordTests(unittest.TestCase):
     def test_getSupervisorStateDescription(self):
         from supervisor.states import getSupervisorStateDescription
         from supervisor.states import SupervisorStates
-        result = getSupervisorStateDescription(SupervisorStates.ACTIVE)
-        self.assertEqual(result, 'ACTIVE')
+        result = getSupervisorStateDescription(SupervisorStates.RUNNING)
+        self.assertEqual(result, 'RUNNING')
 
 def test_suite():
     return unittest.findTestCases(sys.modules[__name__])