ominfra 0.0.0.dev130__py3-none-any.whl → 0.0.0.dev131__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ominfra/deploy/_executor.py +2 -2
- ominfra/deploy/poly/_main.py +2 -2
- ominfra/pyremote/_runcommands.py +2 -2
- ominfra/scripts/journald2aws.py +6 -6
- ominfra/scripts/supervisor.py +94 -96
- ominfra/supervisor/configs.py +17 -17
- ominfra/supervisor/dispatchersimpl.py +8 -8
- ominfra/supervisor/pipes.py +2 -2
- ominfra/supervisor/privileges.py +4 -6
- ominfra/supervisor/processimpl.py +30 -30
- ominfra/supervisor/setupimpl.py +16 -16
- ominfra/supervisor/spawningimpl.py +1 -1
- ominfra/supervisor/supervisor.py +1 -1
- ominfra/supervisor/utils/os.py +1 -1
- ominfra/supervisor/utils/strings.py +2 -2
- {ominfra-0.0.0.dev130.dist-info → ominfra-0.0.0.dev131.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev130.dist-info → ominfra-0.0.0.dev131.dist-info}/RECORD +21 -21
- {ominfra-0.0.0.dev130.dist-info → ominfra-0.0.0.dev131.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev130.dist-info → ominfra-0.0.0.dev131.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev130.dist-info → ominfra-0.0.0.dev131.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev130.dist-info → ominfra-0.0.0.dev131.dist-info}/top_level.txt +0 -0
ominfra/deploy/_executor.py
CHANGED
@@ -82,10 +82,10 @@ if sys.version_info < (3, 8):
|
|
82
82
|
########################################
|
83
83
|
|
84
84
|
|
85
|
-
#
|
85
|
+
# ../../../omlish/lite/cached.py
|
86
86
|
T = ta.TypeVar('T')
|
87
87
|
|
88
|
-
#
|
88
|
+
# ../../../omlish/lite/check.py
|
89
89
|
SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
|
90
90
|
|
91
91
|
|
ominfra/deploy/poly/_main.py
CHANGED
@@ -33,10 +33,10 @@ if sys.version_info < (3, 8):
|
|
33
33
|
########################################
|
34
34
|
|
35
35
|
|
36
|
-
#
|
36
|
+
# ../../../omlish/lite/cached.py
|
37
37
|
T = ta.TypeVar('T')
|
38
38
|
|
39
|
-
#
|
39
|
+
# base.py
|
40
40
|
ConcernT = ta.TypeVar('ConcernT')
|
41
41
|
ConfigT = ta.TypeVar('ConfigT')
|
42
42
|
SiteConcernT = ta.TypeVar('SiteConcernT', bound='SiteConcern')
|
ominfra/pyremote/_runcommands.py
CHANGED
@@ -41,10 +41,10 @@ if sys.version_info < (3, 8):
|
|
41
41
|
########################################
|
42
42
|
|
43
43
|
|
44
|
-
#
|
44
|
+
# ../../omlish/lite/cached.py
|
45
45
|
T = ta.TypeVar('T')
|
46
46
|
|
47
|
-
#
|
47
|
+
# ../../omlish/lite/check.py
|
48
48
|
SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
|
49
49
|
|
50
50
|
|
ominfra/scripts/journald2aws.py
CHANGED
@@ -51,24 +51,24 @@ if sys.version_info < (3, 8):
|
|
51
51
|
########################################
|
52
52
|
|
53
53
|
|
54
|
-
#
|
54
|
+
# ../../../../omdev/toml/parser.py
|
55
55
|
TomlParseFloat = ta.Callable[[str], ta.Any]
|
56
56
|
TomlKey = ta.Tuple[str, ...]
|
57
57
|
TomlPos = int # ta.TypeAlias
|
58
58
|
|
59
|
-
#
|
59
|
+
# ../../../../omlish/lite/cached.py
|
60
60
|
T = ta.TypeVar('T')
|
61
61
|
|
62
|
-
#
|
62
|
+
# ../../../../omlish/lite/check.py
|
63
63
|
SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
|
64
64
|
|
65
|
-
#
|
65
|
+
# ../../../../omlish/lite/contextmanagers.py
|
66
66
|
ExitStackedT = ta.TypeVar('ExitStackedT', bound='ExitStacked')
|
67
67
|
|
68
|
-
#
|
68
|
+
# ../../../configs.py
|
69
69
|
ConfigMapping = ta.Mapping[str, ta.Any]
|
70
70
|
|
71
|
-
#
|
71
|
+
# ../../../threadworkers.py
|
72
72
|
ThreadWorkerT = ta.TypeVar('ThreadWorkerT', bound='ThreadWorker')
|
73
73
|
|
74
74
|
|
ominfra/scripts/supervisor.py
CHANGED
@@ -90,50 +90,50 @@ if sys.version_info < (3, 8):
|
|
90
90
|
########################################
|
91
91
|
|
92
92
|
|
93
|
-
#
|
93
|
+
# ../../omdev/toml/parser.py
|
94
94
|
TomlParseFloat = ta.Callable[[str], ta.Any]
|
95
95
|
TomlKey = ta.Tuple[str, ...]
|
96
96
|
TomlPos = int # ta.TypeAlias
|
97
97
|
|
98
|
-
#
|
98
|
+
# utils/collections.py
|
99
99
|
K = ta.TypeVar('K')
|
100
100
|
V = ta.TypeVar('V')
|
101
101
|
|
102
|
-
#
|
102
|
+
# ../../omlish/lite/cached.py
|
103
103
|
T = ta.TypeVar('T')
|
104
104
|
|
105
|
-
#
|
105
|
+
# ../../omlish/lite/check.py
|
106
106
|
SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
|
107
107
|
|
108
|
-
#
|
108
|
+
# ../../omlish/lite/socket.py
|
109
109
|
SocketAddress = ta.Any
|
110
110
|
SocketHandlerFactory = ta.Callable[[SocketAddress, ta.BinaryIO, ta.BinaryIO], 'SocketHandler']
|
111
111
|
|
112
|
-
#
|
112
|
+
# ../../omlish/lite/typing.py
|
113
113
|
A0 = ta.TypeVar('A0')
|
114
114
|
A1 = ta.TypeVar('A1')
|
115
115
|
A2 = ta.TypeVar('A2')
|
116
116
|
|
117
|
-
#
|
117
|
+
# events.py
|
118
118
|
EventCallback = ta.Callable[['Event'], None]
|
119
119
|
|
120
|
-
#
|
120
|
+
# ../../omlish/lite/http/parsing.py
|
121
121
|
HttpHeaders = http.client.HTTPMessage # ta.TypeAlias
|
122
122
|
|
123
|
-
#
|
123
|
+
# ../../omlish/lite/inject.py
|
124
124
|
U = ta.TypeVar('U')
|
125
125
|
InjectorKeyCls = ta.Union[type, ta.NewType]
|
126
126
|
InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
|
127
127
|
InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
|
128
128
|
InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
|
129
129
|
|
130
|
-
#
|
130
|
+
# ../configs.py
|
131
131
|
ConfigMapping = ta.Mapping[str, ta.Any]
|
132
132
|
|
133
|
-
#
|
133
|
+
# ../../omlish/lite/http/handlers.py
|
134
134
|
HttpHandler = ta.Callable[['HttpHandlerRequest'], 'HttpHandlerResponse']
|
135
135
|
|
136
|
-
#
|
136
|
+
# ../../omlish/lite/http/coroserver.py
|
137
137
|
CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer']
|
138
138
|
|
139
139
|
|
@@ -991,9 +991,8 @@ class NoPermissionError(ProcessError):
|
|
991
991
|
|
992
992
|
def drop_privileges(user: ta.Union[int, str, None]) -> ta.Optional[str]:
|
993
993
|
"""
|
994
|
-
Drop privileges to become the specified user, which may be a username or uid.
|
995
|
-
|
996
|
-
dropped.
|
994
|
+
Drop privileges to become the specified user, which may be a username or uid. Called for supervisord startup and
|
995
|
+
when spawning subprocesses. Returns None on success or a string error message if privileges could not be dropped.
|
997
996
|
"""
|
998
997
|
|
999
998
|
if user is None:
|
@@ -1017,9 +1016,8 @@ def drop_privileges(user: ta.Union[int, str, None]) -> ta.Optional[str]:
|
|
1017
1016
|
current_uid = os.getuid()
|
1018
1017
|
|
1019
1018
|
if current_uid == uid:
|
1020
|
-
# do nothing and return successfully if the uid is already the current one.
|
1021
|
-
#
|
1022
|
-
# it.
|
1019
|
+
# do nothing and return successfully if the uid is already the current one. this allows a supervisord running as
|
1020
|
+
# an unprivileged user "foo" to start a process where the config has "user=foo" (same user) in it.
|
1023
1021
|
return None
|
1024
1022
|
|
1025
1023
|
if current_uid != 0:
|
@@ -1373,8 +1371,8 @@ def strip_escapes(s: bytes) -> bytes:
|
|
1373
1371
|
|
1374
1372
|
|
1375
1373
|
class SuffixMultiplier:
|
1376
|
-
# d is a dictionary of suffixes to integer multipliers.
|
1377
|
-
#
|
1374
|
+
# d is a dictionary of suffixes to integer multipliers. If no suffixes match, default is the multiplier. Matches are
|
1375
|
+
# case insensitive. Return values are in the fundamental unit.
|
1378
1376
|
def __init__(self, d, default=1):
|
1379
1377
|
super().__init__()
|
1380
1378
|
self._d = d
|
@@ -2430,7 +2428,7 @@ def decode_wait_status(sts: int) -> ta.Tuple[Rc, str]:
|
|
2430
2428
|
Decode the status returned by wait() or waitpid().
|
2431
2429
|
|
2432
2430
|
Return a tuple (exitstatus, message) where exitstatus is the exit status, or -1 if the process was killed by a
|
2433
|
-
signal; and message is a message telling what happened.
|
2431
|
+
signal; and message is a message telling what happened. It is the caller's responsibility to display the message.
|
2434
2432
|
"""
|
2435
2433
|
|
2436
2434
|
if os.WIFEXITED(sts):
|
@@ -5068,8 +5066,8 @@ class ProcessPipes:
|
|
5068
5066
|
|
5069
5067
|
def make_process_pipes(stderr=True) -> ProcessPipes:
|
5070
5068
|
"""
|
5071
|
-
Create pipes for parent to child stdin/stdout/stderr communications.
|
5072
|
-
|
5069
|
+
Create pipes for parent to child stdin/stdout/stderr communications. Open fd in non-blocking mode so we can read
|
5070
|
+
them in the mainloop without blocking. If stderr is False, don't create a pipe for stderr.
|
5073
5071
|
"""
|
5074
5072
|
|
5075
5073
|
pipes: ta.Dict[str, ta.Optional[Fd]] = {
|
@@ -5219,32 +5217,32 @@ class ProcessConfig:
|
|
5219
5217
|
umask: ta.Optional[int] = None
|
5220
5218
|
priority: int = 999
|
5221
5219
|
|
5222
|
-
|
5223
|
-
|
5220
|
+
auto_start: bool = True
|
5221
|
+
auto_restart: str = 'unexpected'
|
5224
5222
|
|
5225
|
-
|
5226
|
-
|
5223
|
+
start_secs: int = 1
|
5224
|
+
start_retries: int = 3
|
5227
5225
|
|
5228
|
-
|
5229
|
-
|
5226
|
+
num_procs: int = 1
|
5227
|
+
num_procs_start: int = 0
|
5230
5228
|
|
5231
5229
|
@dc.dataclass(frozen=True)
|
5232
5230
|
class Log:
|
5233
5231
|
file: ta.Optional[str] = None
|
5234
|
-
|
5232
|
+
capture_max_bytes: ta.Optional[int] = None
|
5235
5233
|
events_enabled: bool = False
|
5236
5234
|
syslog: bool = False
|
5237
5235
|
backups: ta.Optional[int] = None
|
5238
|
-
|
5236
|
+
max_bytes: ta.Optional[int] = None
|
5239
5237
|
|
5240
5238
|
stdout: Log = Log()
|
5241
5239
|
stderr: Log = Log()
|
5242
5240
|
|
5243
|
-
|
5244
|
-
|
5245
|
-
|
5241
|
+
stop_signal: int = signal.SIGTERM
|
5242
|
+
stop_wait_secs: int = 10
|
5243
|
+
stop_as_group: bool = False
|
5246
5244
|
|
5247
|
-
|
5245
|
+
kill_as_group: bool = False
|
5248
5246
|
|
5249
5247
|
exitcodes: ta.Sequence[int] = (0,)
|
5250
5248
|
|
@@ -5269,14 +5267,14 @@ class ServerConfig:
|
|
5269
5267
|
umask: int = 0o22
|
5270
5268
|
directory: ta.Optional[str] = None
|
5271
5269
|
logfile: str = 'supervisord.log'
|
5272
|
-
|
5270
|
+
logfile_max_bytes: int = 50 * 1024 * 1024
|
5273
5271
|
logfile_backups: int = 10
|
5274
5272
|
loglevel: int = logging.INFO
|
5275
5273
|
pidfile: str = 'supervisord.pid'
|
5276
5274
|
identifier: str = 'supervisor'
|
5277
5275
|
child_logdir: str = '/dev/null'
|
5278
|
-
|
5279
|
-
|
5276
|
+
min_fds: int = 1024
|
5277
|
+
min_procs: int = 200
|
5280
5278
|
nocleanup: bool = False
|
5281
5279
|
strip_ansi: bool = False
|
5282
5280
|
silent: bool = False
|
@@ -5289,7 +5287,7 @@ class ServerConfig:
|
|
5289
5287
|
umask: ta.Union[int, str] = 0o22,
|
5290
5288
|
directory: ta.Optional[str] = None,
|
5291
5289
|
logfile: str = 'supervisord.log',
|
5292
|
-
|
5290
|
+
logfile_max_bytes: ta.Union[int, str] = 50 * 1024 * 1024,
|
5293
5291
|
loglevel: ta.Union[int, str] = logging.INFO,
|
5294
5292
|
pidfile: str = 'supervisord.pid',
|
5295
5293
|
child_logdir: ta.Optional[str] = None,
|
@@ -5299,7 +5297,7 @@ class ServerConfig:
|
|
5299
5297
|
umask=parse_octal(umask),
|
5300
5298
|
directory=check_existing_dir(directory) if directory is not None else None,
|
5301
5299
|
logfile=check_path_with_existing_dir(logfile),
|
5302
|
-
|
5300
|
+
logfile_max_bytes=parse_bytes_size(logfile_max_bytes),
|
5303
5301
|
loglevel=parse_logging_level(loglevel),
|
5304
5302
|
pidfile=check_path_with_existing_dir(pidfile),
|
5305
5303
|
child_logdir=child_logdir if child_logdir else tempfile.gettempdir(),
|
@@ -6360,7 +6358,7 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
6360
6358
|
channel = self._channel # noqa
|
6361
6359
|
|
6362
6360
|
logfile = self._lc.file
|
6363
|
-
|
6361
|
+
max_bytes = self._lc.max_bytes # noqa
|
6364
6362
|
backups = self._lc.backups # noqa
|
6365
6363
|
to_syslog = self._lc.syslog
|
6366
6364
|
|
@@ -6372,8 +6370,8 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
6372
6370
|
# self.normal_log,
|
6373
6371
|
# filename=logfile,
|
6374
6372
|
# fmt='%(message)s',
|
6375
|
-
# rotating=bool(
|
6376
|
-
#
|
6373
|
+
# rotating=bool(max_bytes), # optimization
|
6374
|
+
# max_bytes=max_bytes,
|
6377
6375
|
# backups=backups,
|
6378
6376
|
# )
|
6379
6377
|
|
@@ -6385,17 +6383,17 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
6385
6383
|
|
6386
6384
|
def _init_capture_log(self) -> None:
|
6387
6385
|
"""
|
6388
|
-
Configure the capture log for this process.
|
6386
|
+
Configure the capture log for this process. This log is used to temporarily capture output when special output
|
6389
6387
|
is detected. Sets self.capture_log if capturing is enabled.
|
6390
6388
|
"""
|
6391
6389
|
|
6392
|
-
|
6393
|
-
if
|
6390
|
+
capture_max_bytes = self._lc.capture_max_bytes
|
6391
|
+
if capture_max_bytes:
|
6394
6392
|
self._capture_log = logging.getLogger(__name__)
|
6395
6393
|
# loggers.handle_boundIO(
|
6396
6394
|
# self._capture_log,
|
6397
6395
|
# fmt='%(message)s',
|
6398
|
-
#
|
6396
|
+
# max_bytes=capture_max_bytes,
|
6399
6397
|
# )
|
6400
6398
|
|
6401
6399
|
def remove_logs(self) -> None:
|
@@ -6508,7 +6506,7 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
6508
6506
|
self._output_buffer += data
|
6509
6507
|
self.record_output()
|
6510
6508
|
if not data:
|
6511
|
-
# if we get no data back from the pipe, it means that the child process has ended.
|
6509
|
+
# if we get no data back from the pipe, it means that the child process has ended. See
|
6512
6510
|
# mail.python.org/pipermail/python-dev/2004-August/046850.html
|
6513
6511
|
self.close()
|
6514
6512
|
|
@@ -6717,21 +6715,21 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
6717
6715
|
def _cleanup_fds(self) -> None:
|
6718
6716
|
# try to close any leaked file descriptors (for reload)
|
6719
6717
|
start = 5
|
6720
|
-
os.closerange(start, self._config.
|
6718
|
+
os.closerange(start, self._config.min_fds)
|
6721
6719
|
|
6722
6720
|
#
|
6723
6721
|
|
6724
6722
|
def _set_uid_or_exit(self) -> None:
|
6725
6723
|
"""
|
6726
|
-
Set the uid of the supervisord process.
|
6724
|
+
Set the uid of the supervisord process. Called during supervisord startup only. No return value. Exits the
|
6727
6725
|
process via usage() if privileges could not be dropped.
|
6728
6726
|
"""
|
6729
6727
|
|
6730
6728
|
if self._user is None:
|
6731
6729
|
if os.getuid() == 0:
|
6732
6730
|
warnings.warn(
|
6733
|
-
'Supervisor is running as root.
|
6734
|
-
'config file.
|
6731
|
+
'Supervisor is running as root. Privileges were not dropped because no user is specified in the '
|
6732
|
+
'config file. If you intend to run as root, you can set user=root in the config file to avoid '
|
6735
6733
|
'this message.',
|
6736
6734
|
)
|
6737
6735
|
else:
|
@@ -6745,8 +6743,8 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
6745
6743
|
|
6746
6744
|
def _set_rlimits_or_exit(self) -> None:
|
6747
6745
|
"""
|
6748
|
-
Set the rlimits of the supervisord process.
|
6749
|
-
|
6746
|
+
Set the rlimits of the supervisord process. Called during supervisord startup only. No return value. Exits the
|
6747
|
+
process via usage() if any rlimits could not be set.
|
6750
6748
|
"""
|
6751
6749
|
|
6752
6750
|
limits = []
|
@@ -6755,12 +6753,12 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
6755
6753
|
limits.append({
|
6756
6754
|
'msg': (
|
6757
6755
|
'The minimum number of file descriptors required to run this process is %(min_limit)s as per the '
|
6758
|
-
'"
|
6759
|
-
'you to open %(hard)s file descriptors.
|
6760
|
-
'your environment (see README.rst) or lower the
|
6756
|
+
'"min_fds" command-line argument or config file setting. The current environment will only allow '
|
6757
|
+
'you to open %(hard)s file descriptors. Either raise the number of usable file descriptors in '
|
6758
|
+
'your environment (see README.rst) or lower the min_fds setting in the config file to allow the '
|
6761
6759
|
'process to start.'
|
6762
6760
|
),
|
6763
|
-
'min': self._config.
|
6761
|
+
'min': self._config.min_fds,
|
6764
6762
|
'resource': resource.RLIMIT_NOFILE,
|
6765
6763
|
'name': 'RLIMIT_NOFILE',
|
6766
6764
|
})
|
@@ -6770,11 +6768,11 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
6770
6768
|
'msg': (
|
6771
6769
|
'The minimum number of available processes required to run this program is %(min_limit)s as per '
|
6772
6770
|
'the "minprocs" command-line argument or config file setting. The current environment will only '
|
6773
|
-
'allow you to open %(hard)s processes.
|
6771
|
+
'allow you to open %(hard)s processes. Either raise the number of usable processes in your '
|
6774
6772
|
'environment (see README.rst) or lower the minprocs setting in the config file to allow the '
|
6775
6773
|
'program to start.'
|
6776
6774
|
),
|
6777
|
-
'min': self._config.
|
6775
|
+
'min': self._config.min_procs,
|
6778
6776
|
'resource': resource.RLIMIT_NPROC,
|
6779
6777
|
'name': 'RLIMIT_NPROC',
|
6780
6778
|
})
|
@@ -6860,11 +6858,11 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
6860
6858
|
dl.after_daemonize()
|
6861
6859
|
|
6862
6860
|
def _do_daemonize(self) -> None:
|
6863
|
-
# To daemonize, we need to become the leader of our own session (process) group.
|
6864
|
-
# our parent process will also be sent to us.
|
6861
|
+
# To daemonize, we need to become the leader of our own session (process) group. If we do not, signals sent to
|
6862
|
+
# our parent process will also be sent to us. This might be bad because signals such as SIGINT can be sent to
|
6865
6863
|
# our parent process during normal (uninteresting) operations such as when we press Ctrl-C in the parent
|
6866
6864
|
# terminal window to escape from a logtail command. To disassociate ourselves from our parent's session group we
|
6867
|
-
# use os.setsid.
|
6865
|
+
# use os.setsid. It means "set session id", which has the effect of disassociating a process from is current
|
6868
6866
|
# session and process group and setting itself up as a new session leader.
|
6869
6867
|
#
|
6870
6868
|
# Unfortunately we cannot call setsid if we're already a session group leader, so we use "fork" to make a copy
|
@@ -6896,7 +6894,7 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
6896
6894
|
os.dup2(2, os.open('/dev/null', os.O_WRONLY))
|
6897
6895
|
|
6898
6896
|
# XXX Stevens, in his Advanced Unix book, section 13.3 (page 417) recommends calling umask(0) and closing unused
|
6899
|
-
# file descriptors.
|
6897
|
+
# file descriptors. In his Network Programming book, he additionally recommends ignoring SIGHUP and forking
|
6900
6898
|
# again after the setsid() call, for obscure SVR4 reasons.
|
6901
6899
|
os.setsid()
|
6902
6900
|
os.umask(self._config.umask)
|
@@ -7275,7 +7273,7 @@ class ProcessImpl(Process):
|
|
7275
7273
|
|
7276
7274
|
self._killing = False # true if we are trying to kill this process
|
7277
7275
|
|
7278
|
-
self._backoff = 0 # backoff counter (to
|
7276
|
+
self._backoff = 0 # backoff counter (to start_retries)
|
7279
7277
|
|
7280
7278
|
self._exitstatus: ta.Optional[Rc] = None # status attached to dead process by finish()
|
7281
7279
|
self._spawn_err: ta.Optional[str] = None # error message attached by spawn() if any
|
@@ -7352,7 +7350,7 @@ class ProcessImpl(Process):
|
|
7352
7350
|
self._pipes = sp.pipes
|
7353
7351
|
self._dispatchers = sp.dispatchers
|
7354
7352
|
|
7355
|
-
self._delay = time.time() + self.config.
|
7353
|
+
self._delay = time.time() + self.config.start_secs
|
7356
7354
|
|
7357
7355
|
return sp.pid
|
7358
7356
|
|
@@ -7410,17 +7408,17 @@ class ProcessImpl(Process):
|
|
7410
7408
|
|
7411
7409
|
if self._state == ProcessState.STARTING:
|
7412
7410
|
self._last_start = min(test_time, self._last_start)
|
7413
|
-
if self._delay > 0 and test_time < (self._delay - self._config.
|
7414
|
-
self._delay = test_time + self._config.
|
7411
|
+
if self._delay > 0 and test_time < (self._delay - self._config.start_secs):
|
7412
|
+
self._delay = test_time + self._config.start_secs
|
7415
7413
|
|
7416
7414
|
elif self._state == ProcessState.RUNNING:
|
7417
|
-
if test_time > self._last_start and test_time < (self._last_start + self._config.
|
7418
|
-
self._last_start = test_time - self._config.
|
7415
|
+
if test_time > self._last_start and test_time < (self._last_start + self._config.start_secs):
|
7416
|
+
self._last_start = test_time - self._config.start_secs
|
7419
7417
|
|
7420
7418
|
elif self._state == ProcessState.STOPPING:
|
7421
7419
|
self._last_stop_report = min(test_time, self._last_stop_report)
|
7422
|
-
if self._delay > 0 and test_time < (self._delay - self._config.
|
7423
|
-
self._delay = test_time + self._config.
|
7420
|
+
if self._delay > 0 and test_time < (self._delay - self._config.stop_wait_secs):
|
7421
|
+
self._delay = test_time + self._config.stop_wait_secs
|
7424
7422
|
|
7425
7423
|
elif self._state == ProcessState.BACKOFF:
|
7426
7424
|
if self._delay > 0 and test_time < (self._delay - self._backoff):
|
@@ -7429,7 +7427,7 @@ class ProcessImpl(Process):
|
|
7429
7427
|
def stop(self) -> ta.Optional[str]:
|
7430
7428
|
self._administrative_stop = True
|
7431
7429
|
self._last_stop_report = 0
|
7432
|
-
return self.kill(self._config.
|
7430
|
+
return self.kill(self._config.stop_signal)
|
7433
7431
|
|
7434
7432
|
def stop_report(self) -> None:
|
7435
7433
|
"""Log a 'waiting for x to stop' message with throttling."""
|
@@ -7452,7 +7450,7 @@ class ProcessImpl(Process):
|
|
7452
7450
|
|
7453
7451
|
def kill(self, sig: int) -> ta.Optional[str]:
|
7454
7452
|
"""
|
7455
|
-
Send a signal to the subprocess with the intention to kill it (to make it exit).
|
7453
|
+
Send a signal to the subprocess with the intention to kill it (to make it exit). This may or may not actually
|
7456
7454
|
kill it.
|
7457
7455
|
|
7458
7456
|
Return None if the signal was sent, or an error message string if an error occurred or if the subprocess is not
|
@@ -7460,8 +7458,8 @@ class ProcessImpl(Process):
|
|
7460
7458
|
"""
|
7461
7459
|
now = time.time()
|
7462
7460
|
|
7463
|
-
# If the process is in BACKOFF and we want to stop or kill it, then BACKOFF -> STOPPED.
|
7464
|
-
# if
|
7461
|
+
# If the process is in BACKOFF and we want to stop or kill it, then BACKOFF -> STOPPED. This is needed because
|
7462
|
+
# if start_retries is a large number and the process isn't starting successfully, the stop request would be
|
7465
7463
|
# blocked for a long time waiting for the retries.
|
7466
7464
|
if self._state == ProcessState.BACKOFF:
|
7467
7465
|
log.debug('Attempted to kill %s, which is in BACKOFF state.', self.name)
|
@@ -7476,25 +7474,25 @@ class ProcessImpl(Process):
|
|
7476
7474
|
|
7477
7475
|
# If we're in the stopping state, then we've already sent the stop signal and this is the kill signal
|
7478
7476
|
if self._state == ProcessState.STOPPING:
|
7479
|
-
|
7477
|
+
kill_as_group = self._config.kill_as_group
|
7480
7478
|
else:
|
7481
|
-
|
7479
|
+
kill_as_group = self._config.stop_as_group
|
7482
7480
|
|
7483
7481
|
as_group = ''
|
7484
|
-
if
|
7482
|
+
if kill_as_group:
|
7485
7483
|
as_group = 'process group '
|
7486
7484
|
|
7487
7485
|
log.debug('killing %s (pid %s) %s with signal %s', self.name, self.pid, as_group, sig_name(sig))
|
7488
7486
|
|
7489
7487
|
# RUNNING/STARTING/STOPPING -> STOPPING
|
7490
7488
|
self._killing = True
|
7491
|
-
self._delay = now + self._config.
|
7492
|
-
# we will already be in the STOPPING state if we're doing a SIGKILL as a result of overrunning
|
7489
|
+
self._delay = now + self._config.stop_wait_secs
|
7490
|
+
# we will already be in the STOPPING state if we're doing a SIGKILL as a result of overrunning stop_wait_secs
|
7493
7491
|
self.check_in_state(ProcessState.RUNNING, ProcessState.STARTING, ProcessState.STOPPING)
|
7494
7492
|
self.change_state(ProcessState.STOPPING)
|
7495
7493
|
|
7496
7494
|
kpid = int(self.pid)
|
7497
|
-
if
|
7495
|
+
if kill_as_group:
|
7498
7496
|
# send to the whole process group instead
|
7499
7497
|
kpid = -kpid
|
7500
7498
|
|
@@ -7504,7 +7502,7 @@ class ProcessImpl(Process):
|
|
7504
7502
|
except OSError as exc:
|
7505
7503
|
if exc.errno == errno.ESRCH:
|
7506
7504
|
log.debug('unable to signal %s (pid %s), it probably just exited on its own: %s', self.name, self.pid, str(exc)) # noqa
|
7507
|
-
# we could change the state here but we intentionally do not.
|
7505
|
+
# we could change the state here but we intentionally do not. we will do it during normal SIGCHLD
|
7508
7506
|
# processing.
|
7509
7507
|
return None
|
7510
7508
|
raise
|
@@ -7547,7 +7545,7 @@ class ProcessImpl(Process):
|
|
7547
7545
|
self.pid,
|
7548
7546
|
str(exc),
|
7549
7547
|
)
|
7550
|
-
# we could change the state here but we intentionally do not.
|
7548
|
+
# we could change the state here but we intentionally do not. we will do it during normal SIGCHLD
|
7551
7549
|
# processing.
|
7552
7550
|
return None
|
7553
7551
|
raise
|
@@ -7575,7 +7573,7 @@ class ProcessImpl(Process):
|
|
7575
7573
|
|
7576
7574
|
if now > self._last_start:
|
7577
7575
|
log.info(f'{now - self._last_start=}') # noqa
|
7578
|
-
too_quickly = now - self._last_start < self._config.
|
7576
|
+
too_quickly = now - self._last_start < self._config.start_secs
|
7579
7577
|
else:
|
7580
7578
|
too_quickly = False
|
7581
7579
|
log.warning(
|
@@ -7647,8 +7645,8 @@ class ProcessImpl(Process):
|
|
7647
7645
|
if self._supervisor_states.state > SupervisorState.RESTARTING:
|
7648
7646
|
# dont start any processes if supervisor is shutting down
|
7649
7647
|
if state == ProcessState.EXITED:
|
7650
|
-
if self._config.
|
7651
|
-
if self._config.
|
7648
|
+
if self._config.auto_restart:
|
7649
|
+
if self._config.auto_restart is RestartUnconditionally:
|
7652
7650
|
# EXITED -> STARTING
|
7653
7651
|
self.spawn()
|
7654
7652
|
elif self._exitstatus not in self._config.exitcodes:
|
@@ -7656,29 +7654,29 @@ class ProcessImpl(Process):
|
|
7656
7654
|
self.spawn()
|
7657
7655
|
|
7658
7656
|
elif state == ProcessState.STOPPED and not self._last_start:
|
7659
|
-
if self._config.
|
7657
|
+
if self._config.auto_start:
|
7660
7658
|
# STOPPED -> STARTING
|
7661
7659
|
self.spawn()
|
7662
7660
|
|
7663
7661
|
elif state == ProcessState.BACKOFF:
|
7664
|
-
if self._backoff <= self._config.
|
7662
|
+
if self._backoff <= self._config.start_retries:
|
7665
7663
|
if now > self._delay:
|
7666
7664
|
# BACKOFF -> STARTING
|
7667
7665
|
self.spawn()
|
7668
7666
|
|
7669
7667
|
if state == ProcessState.STARTING:
|
7670
|
-
if now - self._last_start > self._config.
|
7668
|
+
if now - self._last_start > self._config.start_secs:
|
7671
7669
|
# STARTING -> RUNNING if the proc has started successfully and it has stayed up for at least
|
7672
|
-
# proc.config.
|
7670
|
+
# proc.config.start_secs,
|
7673
7671
|
self._delay = 0
|
7674
7672
|
self._backoff = 0
|
7675
7673
|
self.check_in_state(ProcessState.STARTING)
|
7676
7674
|
self.change_state(ProcessState.RUNNING)
|
7677
|
-
msg = ('entered RUNNING state, process has stayed up for > than %s seconds (
|
7675
|
+
msg = ('entered RUNNING state, process has stayed up for > than %s seconds (start_secs)' % self._config.start_secs) # noqa
|
7678
7676
|
log.info('success: %s %s', self.name, msg)
|
7679
7677
|
|
7680
7678
|
if state == ProcessState.BACKOFF:
|
7681
|
-
if self._backoff > self._config.
|
7679
|
+
if self._backoff > self._config.start_retries:
|
7682
7680
|
# BACKOFF -> FATAL if the proc has exceeded its number of retries
|
7683
7681
|
self.give_up()
|
7684
7682
|
msg = ('entered FATAL state, too many start retries too quickly')
|
@@ -7687,7 +7685,7 @@ class ProcessImpl(Process):
|
|
7687
7685
|
elif state == ProcessState.STOPPING:
|
7688
7686
|
time_left = self._delay - now
|
7689
7687
|
if time_left <= 0:
|
7690
|
-
# kill processes which are taking too long to stop with a final sigkill.
|
7688
|
+
# kill processes which are taking too long to stop with a final sigkill. if this doesn't kill it, the
|
7691
7689
|
# process will be stuck in the STOPPING state forever.
|
7692
7690
|
log.warning('killing \'%s\' (%s) with SIGKILL', self.name, self.pid)
|
7693
7691
|
self.kill(signal.SIGKILL)
|
@@ -8039,7 +8037,7 @@ class ProcessSpawningImpl(ProcessSpawning):
|
|
8039
8037
|
else:
|
8040
8038
|
os.dup2(check_not_none(pipes.child_stderr), 2)
|
8041
8039
|
|
8042
|
-
for i in range(3, self._server_config.
|
8040
|
+
for i in range(3, self._server_config.min_fds):
|
8043
8041
|
if i in self._inherited_fds:
|
8044
8042
|
continue
|
8045
8043
|
close_fd(Fd(i))
|
@@ -8329,7 +8327,7 @@ class WaitedPid(ta.NamedTuple):
|
|
8329
8327
|
|
8330
8328
|
|
8331
8329
|
def waitpid() -> ta.Optional[WaitedPid]:
|
8332
|
-
# Need pthread_sigmask here to avoid concurrent sigchld, but Python doesn't offer in Python < 3.4.
|
8330
|
+
# Need pthread_sigmask here to avoid concurrent sigchld, but Python doesn't offer in Python < 3.4. There is
|
8333
8331
|
# still a race condition here; we can get a sigchld while we're sitting in the waitpid call. However, AFAICT, if
|
8334
8332
|
# waitpid is interrupted by SIGCHLD, as long as we call waitpid again (which happens every so often during the
|
8335
8333
|
# normal course in the mainloop), we'll eventually reap the child that we tried to reap during the interrupted
|
ominfra/supervisor/configs.py
CHANGED
@@ -37,32 +37,32 @@ class ProcessConfig:
|
|
37
37
|
umask: ta.Optional[int] = None
|
38
38
|
priority: int = 999
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
auto_start: bool = True
|
41
|
+
auto_restart: str = 'unexpected'
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
start_secs: int = 1
|
44
|
+
start_retries: int = 3
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
num_procs: int = 1
|
47
|
+
num_procs_start: int = 0
|
48
48
|
|
49
49
|
@dc.dataclass(frozen=True)
|
50
50
|
class Log:
|
51
51
|
file: ta.Optional[str] = None
|
52
|
-
|
52
|
+
capture_max_bytes: ta.Optional[int] = None
|
53
53
|
events_enabled: bool = False
|
54
54
|
syslog: bool = False
|
55
55
|
backups: ta.Optional[int] = None
|
56
|
-
|
56
|
+
max_bytes: ta.Optional[int] = None
|
57
57
|
|
58
58
|
stdout: Log = Log()
|
59
59
|
stderr: Log = Log()
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
stop_signal: int = signal.SIGTERM
|
62
|
+
stop_wait_secs: int = 10
|
63
|
+
stop_as_group: bool = False
|
64
64
|
|
65
|
-
|
65
|
+
kill_as_group: bool = False
|
66
66
|
|
67
67
|
exitcodes: ta.Sequence[int] = (0,)
|
68
68
|
|
@@ -87,14 +87,14 @@ class ServerConfig:
|
|
87
87
|
umask: int = 0o22
|
88
88
|
directory: ta.Optional[str] = None
|
89
89
|
logfile: str = 'supervisord.log'
|
90
|
-
|
90
|
+
logfile_max_bytes: int = 50 * 1024 * 1024
|
91
91
|
logfile_backups: int = 10
|
92
92
|
loglevel: int = logging.INFO
|
93
93
|
pidfile: str = 'supervisord.pid'
|
94
94
|
identifier: str = 'supervisor'
|
95
95
|
child_logdir: str = '/dev/null'
|
96
|
-
|
97
|
-
|
96
|
+
min_fds: int = 1024
|
97
|
+
min_procs: int = 200
|
98
98
|
nocleanup: bool = False
|
99
99
|
strip_ansi: bool = False
|
100
100
|
silent: bool = False
|
@@ -107,7 +107,7 @@ class ServerConfig:
|
|
107
107
|
umask: ta.Union[int, str] = 0o22,
|
108
108
|
directory: ta.Optional[str] = None,
|
109
109
|
logfile: str = 'supervisord.log',
|
110
|
-
|
110
|
+
logfile_max_bytes: ta.Union[int, str] = 50 * 1024 * 1024,
|
111
111
|
loglevel: ta.Union[int, str] = logging.INFO,
|
112
112
|
pidfile: str = 'supervisord.pid',
|
113
113
|
child_logdir: ta.Optional[str] = None,
|
@@ -117,7 +117,7 @@ class ServerConfig:
|
|
117
117
|
umask=parse_octal(umask),
|
118
118
|
directory=check_existing_dir(directory) if directory is not None else None,
|
119
119
|
logfile=check_path_with_existing_dir(logfile),
|
120
|
-
|
120
|
+
logfile_max_bytes=parse_bytes_size(logfile_max_bytes),
|
121
121
|
loglevel=parse_logging_level(loglevel),
|
122
122
|
pidfile=check_path_with_existing_dir(pidfile),
|
123
123
|
child_logdir=child_logdir if child_logdir else tempfile.gettempdir(),
|
@@ -147,7 +147,7 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
147
147
|
channel = self._channel # noqa
|
148
148
|
|
149
149
|
logfile = self._lc.file
|
150
|
-
|
150
|
+
max_bytes = self._lc.max_bytes # noqa
|
151
151
|
backups = self._lc.backups # noqa
|
152
152
|
to_syslog = self._lc.syslog
|
153
153
|
|
@@ -159,8 +159,8 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
159
159
|
# self.normal_log,
|
160
160
|
# filename=logfile,
|
161
161
|
# fmt='%(message)s',
|
162
|
-
# rotating=bool(
|
163
|
-
#
|
162
|
+
# rotating=bool(max_bytes), # optimization
|
163
|
+
# max_bytes=max_bytes,
|
164
164
|
# backups=backups,
|
165
165
|
# )
|
166
166
|
|
@@ -172,17 +172,17 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
172
172
|
|
173
173
|
def _init_capture_log(self) -> None:
|
174
174
|
"""
|
175
|
-
Configure the capture log for this process.
|
175
|
+
Configure the capture log for this process. This log is used to temporarily capture output when special output
|
176
176
|
is detected. Sets self.capture_log if capturing is enabled.
|
177
177
|
"""
|
178
178
|
|
179
|
-
|
180
|
-
if
|
179
|
+
capture_max_bytes = self._lc.capture_max_bytes
|
180
|
+
if capture_max_bytes:
|
181
181
|
self._capture_log = logging.getLogger(__name__)
|
182
182
|
# loggers.handle_boundIO(
|
183
183
|
# self._capture_log,
|
184
184
|
# fmt='%(message)s',
|
185
|
-
#
|
185
|
+
# max_bytes=capture_max_bytes,
|
186
186
|
# )
|
187
187
|
|
188
188
|
def remove_logs(self) -> None:
|
@@ -295,7 +295,7 @@ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispat
|
|
295
295
|
self._output_buffer += data
|
296
296
|
self.record_output()
|
297
297
|
if not data:
|
298
|
-
# if we get no data back from the pipe, it means that the child process has ended.
|
298
|
+
# if we get no data back from the pipe, it means that the child process has ended. See
|
299
299
|
# mail.python.org/pipermail/python-dev/2004-August/046850.html
|
300
300
|
self.close()
|
301
301
|
|
ominfra/supervisor/pipes.py
CHANGED
@@ -29,8 +29,8 @@ class ProcessPipes:
|
|
29
29
|
|
30
30
|
def make_process_pipes(stderr=True) -> ProcessPipes:
|
31
31
|
"""
|
32
|
-
Create pipes for parent to child stdin/stdout/stderr communications.
|
33
|
-
|
32
|
+
Create pipes for parent to child stdin/stdout/stderr communications. Open fd in non-blocking mode so we can read
|
33
|
+
them in the mainloop without blocking. If stderr is False, don't create a pipe for stderr.
|
34
34
|
"""
|
35
35
|
|
36
36
|
pipes: ta.Dict[str, ta.Optional[Fd]] = {
|
ominfra/supervisor/privileges.py
CHANGED
@@ -7,9 +7,8 @@ import typing as ta
|
|
7
7
|
|
8
8
|
def drop_privileges(user: ta.Union[int, str, None]) -> ta.Optional[str]:
|
9
9
|
"""
|
10
|
-
Drop privileges to become the specified user, which may be a username or uid.
|
11
|
-
|
12
|
-
dropped.
|
10
|
+
Drop privileges to become the specified user, which may be a username or uid. Called for supervisord startup and
|
11
|
+
when spawning subprocesses. Returns None on success or a string error message if privileges could not be dropped.
|
13
12
|
"""
|
14
13
|
|
15
14
|
if user is None:
|
@@ -33,9 +32,8 @@ def drop_privileges(user: ta.Union[int, str, None]) -> ta.Optional[str]:
|
|
33
32
|
current_uid = os.getuid()
|
34
33
|
|
35
34
|
if current_uid == uid:
|
36
|
-
# do nothing and return successfully if the uid is already the current one.
|
37
|
-
#
|
38
|
-
# it.
|
35
|
+
# do nothing and return successfully if the uid is already the current one. this allows a supervisord running as
|
36
|
+
# an unprivileged user "foo" to start a process where the config has "user=foo" (same user) in it.
|
39
37
|
return None
|
40
38
|
|
41
39
|
if current_uid != 0:
|
@@ -79,7 +79,7 @@ class ProcessImpl(Process):
|
|
79
79
|
|
80
80
|
self._killing = False # true if we are trying to kill this process
|
81
81
|
|
82
|
-
self._backoff = 0 # backoff counter (to
|
82
|
+
self._backoff = 0 # backoff counter (to start_retries)
|
83
83
|
|
84
84
|
self._exitstatus: ta.Optional[Rc] = None # status attached to dead process by finish()
|
85
85
|
self._spawn_err: ta.Optional[str] = None # error message attached by spawn() if any
|
@@ -156,7 +156,7 @@ class ProcessImpl(Process):
|
|
156
156
|
self._pipes = sp.pipes
|
157
157
|
self._dispatchers = sp.dispatchers
|
158
158
|
|
159
|
-
self._delay = time.time() + self.config.
|
159
|
+
self._delay = time.time() + self.config.start_secs
|
160
160
|
|
161
161
|
return sp.pid
|
162
162
|
|
@@ -214,17 +214,17 @@ class ProcessImpl(Process):
|
|
214
214
|
|
215
215
|
if self._state == ProcessState.STARTING:
|
216
216
|
self._last_start = min(test_time, self._last_start)
|
217
|
-
if self._delay > 0 and test_time < (self._delay - self._config.
|
218
|
-
self._delay = test_time + self._config.
|
217
|
+
if self._delay > 0 and test_time < (self._delay - self._config.start_secs):
|
218
|
+
self._delay = test_time + self._config.start_secs
|
219
219
|
|
220
220
|
elif self._state == ProcessState.RUNNING:
|
221
|
-
if test_time > self._last_start and test_time < (self._last_start + self._config.
|
222
|
-
self._last_start = test_time - self._config.
|
221
|
+
if test_time > self._last_start and test_time < (self._last_start + self._config.start_secs):
|
222
|
+
self._last_start = test_time - self._config.start_secs
|
223
223
|
|
224
224
|
elif self._state == ProcessState.STOPPING:
|
225
225
|
self._last_stop_report = min(test_time, self._last_stop_report)
|
226
|
-
if self._delay > 0 and test_time < (self._delay - self._config.
|
227
|
-
self._delay = test_time + self._config.
|
226
|
+
if self._delay > 0 and test_time < (self._delay - self._config.stop_wait_secs):
|
227
|
+
self._delay = test_time + self._config.stop_wait_secs
|
228
228
|
|
229
229
|
elif self._state == ProcessState.BACKOFF:
|
230
230
|
if self._delay > 0 and test_time < (self._delay - self._backoff):
|
@@ -233,7 +233,7 @@ class ProcessImpl(Process):
|
|
233
233
|
def stop(self) -> ta.Optional[str]:
|
234
234
|
self._administrative_stop = True
|
235
235
|
self._last_stop_report = 0
|
236
|
-
return self.kill(self._config.
|
236
|
+
return self.kill(self._config.stop_signal)
|
237
237
|
|
238
238
|
def stop_report(self) -> None:
|
239
239
|
"""Log a 'waiting for x to stop' message with throttling."""
|
@@ -256,7 +256,7 @@ class ProcessImpl(Process):
|
|
256
256
|
|
257
257
|
def kill(self, sig: int) -> ta.Optional[str]:
|
258
258
|
"""
|
259
|
-
Send a signal to the subprocess with the intention to kill it (to make it exit).
|
259
|
+
Send a signal to the subprocess with the intention to kill it (to make it exit). This may or may not actually
|
260
260
|
kill it.
|
261
261
|
|
262
262
|
Return None if the signal was sent, or an error message string if an error occurred or if the subprocess is not
|
@@ -264,8 +264,8 @@ class ProcessImpl(Process):
|
|
264
264
|
"""
|
265
265
|
now = time.time()
|
266
266
|
|
267
|
-
# If the process is in BACKOFF and we want to stop or kill it, then BACKOFF -> STOPPED.
|
268
|
-
# if
|
267
|
+
# If the process is in BACKOFF and we want to stop or kill it, then BACKOFF -> STOPPED. This is needed because
|
268
|
+
# if start_retries is a large number and the process isn't starting successfully, the stop request would be
|
269
269
|
# blocked for a long time waiting for the retries.
|
270
270
|
if self._state == ProcessState.BACKOFF:
|
271
271
|
log.debug('Attempted to kill %s, which is in BACKOFF state.', self.name)
|
@@ -280,25 +280,25 @@ class ProcessImpl(Process):
|
|
280
280
|
|
281
281
|
# If we're in the stopping state, then we've already sent the stop signal and this is the kill signal
|
282
282
|
if self._state == ProcessState.STOPPING:
|
283
|
-
|
283
|
+
kill_as_group = self._config.kill_as_group
|
284
284
|
else:
|
285
|
-
|
285
|
+
kill_as_group = self._config.stop_as_group
|
286
286
|
|
287
287
|
as_group = ''
|
288
|
-
if
|
288
|
+
if kill_as_group:
|
289
289
|
as_group = 'process group '
|
290
290
|
|
291
291
|
log.debug('killing %s (pid %s) %s with signal %s', self.name, self.pid, as_group, sig_name(sig))
|
292
292
|
|
293
293
|
# RUNNING/STARTING/STOPPING -> STOPPING
|
294
294
|
self._killing = True
|
295
|
-
self._delay = now + self._config.
|
296
|
-
# we will already be in the STOPPING state if we're doing a SIGKILL as a result of overrunning
|
295
|
+
self._delay = now + self._config.stop_wait_secs
|
296
|
+
# we will already be in the STOPPING state if we're doing a SIGKILL as a result of overrunning stop_wait_secs
|
297
297
|
self.check_in_state(ProcessState.RUNNING, ProcessState.STARTING, ProcessState.STOPPING)
|
298
298
|
self.change_state(ProcessState.STOPPING)
|
299
299
|
|
300
300
|
kpid = int(self.pid)
|
301
|
-
if
|
301
|
+
if kill_as_group:
|
302
302
|
# send to the whole process group instead
|
303
303
|
kpid = -kpid
|
304
304
|
|
@@ -308,7 +308,7 @@ class ProcessImpl(Process):
|
|
308
308
|
except OSError as exc:
|
309
309
|
if exc.errno == errno.ESRCH:
|
310
310
|
log.debug('unable to signal %s (pid %s), it probably just exited on its own: %s', self.name, self.pid, str(exc)) # noqa
|
311
|
-
# we could change the state here but we intentionally do not.
|
311
|
+
# we could change the state here but we intentionally do not. we will do it during normal SIGCHLD
|
312
312
|
# processing.
|
313
313
|
return None
|
314
314
|
raise
|
@@ -351,7 +351,7 @@ class ProcessImpl(Process):
|
|
351
351
|
self.pid,
|
352
352
|
str(exc),
|
353
353
|
)
|
354
|
-
# we could change the state here but we intentionally do not.
|
354
|
+
# we could change the state here but we intentionally do not. we will do it during normal SIGCHLD
|
355
355
|
# processing.
|
356
356
|
return None
|
357
357
|
raise
|
@@ -379,7 +379,7 @@ class ProcessImpl(Process):
|
|
379
379
|
|
380
380
|
if now > self._last_start:
|
381
381
|
log.info(f'{now - self._last_start=}') # noqa
|
382
|
-
too_quickly = now - self._last_start < self._config.
|
382
|
+
too_quickly = now - self._last_start < self._config.start_secs
|
383
383
|
else:
|
384
384
|
too_quickly = False
|
385
385
|
log.warning(
|
@@ -451,8 +451,8 @@ class ProcessImpl(Process):
|
|
451
451
|
if self._supervisor_states.state > SupervisorState.RESTARTING:
|
452
452
|
# dont start any processes if supervisor is shutting down
|
453
453
|
if state == ProcessState.EXITED:
|
454
|
-
if self._config.
|
455
|
-
if self._config.
|
454
|
+
if self._config.auto_restart:
|
455
|
+
if self._config.auto_restart is RestartUnconditionally:
|
456
456
|
# EXITED -> STARTING
|
457
457
|
self.spawn()
|
458
458
|
elif self._exitstatus not in self._config.exitcodes:
|
@@ -460,29 +460,29 @@ class ProcessImpl(Process):
|
|
460
460
|
self.spawn()
|
461
461
|
|
462
462
|
elif state == ProcessState.STOPPED and not self._last_start:
|
463
|
-
if self._config.
|
463
|
+
if self._config.auto_start:
|
464
464
|
# STOPPED -> STARTING
|
465
465
|
self.spawn()
|
466
466
|
|
467
467
|
elif state == ProcessState.BACKOFF:
|
468
|
-
if self._backoff <= self._config.
|
468
|
+
if self._backoff <= self._config.start_retries:
|
469
469
|
if now > self._delay:
|
470
470
|
# BACKOFF -> STARTING
|
471
471
|
self.spawn()
|
472
472
|
|
473
473
|
if state == ProcessState.STARTING:
|
474
|
-
if now - self._last_start > self._config.
|
474
|
+
if now - self._last_start > self._config.start_secs:
|
475
475
|
# STARTING -> RUNNING if the proc has started successfully and it has stayed up for at least
|
476
|
-
# proc.config.
|
476
|
+
# proc.config.start_secs,
|
477
477
|
self._delay = 0
|
478
478
|
self._backoff = 0
|
479
479
|
self.check_in_state(ProcessState.STARTING)
|
480
480
|
self.change_state(ProcessState.RUNNING)
|
481
|
-
msg = ('entered RUNNING state, process has stayed up for > than %s seconds (
|
481
|
+
msg = ('entered RUNNING state, process has stayed up for > than %s seconds (start_secs)' % self._config.start_secs) # noqa
|
482
482
|
log.info('success: %s %s', self.name, msg)
|
483
483
|
|
484
484
|
if state == ProcessState.BACKOFF:
|
485
|
-
if self._backoff > self._config.
|
485
|
+
if self._backoff > self._config.start_retries:
|
486
486
|
# BACKOFF -> FATAL if the proc has exceeded its number of retries
|
487
487
|
self.give_up()
|
488
488
|
msg = ('entered FATAL state, too many start retries too quickly')
|
@@ -491,7 +491,7 @@ class ProcessImpl(Process):
|
|
491
491
|
elif state == ProcessState.STOPPING:
|
492
492
|
time_left = self._delay - now
|
493
493
|
if time_left <= 0:
|
494
|
-
# kill processes which are taking too long to stop with a final sigkill.
|
494
|
+
# kill processes which are taking too long to stop with a final sigkill. if this doesn't kill it, the
|
495
495
|
# process will be stuck in the STOPPING state forever.
|
496
496
|
log.warning('killing \'%s\' (%s) with SIGKILL', self.name, self.pid)
|
497
497
|
self.kill(signal.SIGKILL)
|
ominfra/supervisor/setupimpl.py
CHANGED
@@ -77,21 +77,21 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
77
77
|
def _cleanup_fds(self) -> None:
|
78
78
|
# try to close any leaked file descriptors (for reload)
|
79
79
|
start = 5
|
80
|
-
os.closerange(start, self._config.
|
80
|
+
os.closerange(start, self._config.min_fds)
|
81
81
|
|
82
82
|
#
|
83
83
|
|
84
84
|
def _set_uid_or_exit(self) -> None:
|
85
85
|
"""
|
86
|
-
Set the uid of the supervisord process.
|
86
|
+
Set the uid of the supervisord process. Called during supervisord startup only. No return value. Exits the
|
87
87
|
process via usage() if privileges could not be dropped.
|
88
88
|
"""
|
89
89
|
|
90
90
|
if self._user is None:
|
91
91
|
if os.getuid() == 0:
|
92
92
|
warnings.warn(
|
93
|
-
'Supervisor is running as root.
|
94
|
-
'config file.
|
93
|
+
'Supervisor is running as root. Privileges were not dropped because no user is specified in the '
|
94
|
+
'config file. If you intend to run as root, you can set user=root in the config file to avoid '
|
95
95
|
'this message.',
|
96
96
|
)
|
97
97
|
else:
|
@@ -105,8 +105,8 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
105
105
|
|
106
106
|
def _set_rlimits_or_exit(self) -> None:
|
107
107
|
"""
|
108
|
-
Set the rlimits of the supervisord process.
|
109
|
-
|
108
|
+
Set the rlimits of the supervisord process. Called during supervisord startup only. No return value. Exits the
|
109
|
+
process via usage() if any rlimits could not be set.
|
110
110
|
"""
|
111
111
|
|
112
112
|
limits = []
|
@@ -115,12 +115,12 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
115
115
|
limits.append({
|
116
116
|
'msg': (
|
117
117
|
'The minimum number of file descriptors required to run this process is %(min_limit)s as per the '
|
118
|
-
'"
|
119
|
-
'you to open %(hard)s file descriptors.
|
120
|
-
'your environment (see README.rst) or lower the
|
118
|
+
'"min_fds" command-line argument or config file setting. The current environment will only allow '
|
119
|
+
'you to open %(hard)s file descriptors. Either raise the number of usable file descriptors in '
|
120
|
+
'your environment (see README.rst) or lower the min_fds setting in the config file to allow the '
|
121
121
|
'process to start.'
|
122
122
|
),
|
123
|
-
'min': self._config.
|
123
|
+
'min': self._config.min_fds,
|
124
124
|
'resource': resource.RLIMIT_NOFILE,
|
125
125
|
'name': 'RLIMIT_NOFILE',
|
126
126
|
})
|
@@ -130,11 +130,11 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
130
130
|
'msg': (
|
131
131
|
'The minimum number of available processes required to run this program is %(min_limit)s as per '
|
132
132
|
'the "minprocs" command-line argument or config file setting. The current environment will only '
|
133
|
-
'allow you to open %(hard)s processes.
|
133
|
+
'allow you to open %(hard)s processes. Either raise the number of usable processes in your '
|
134
134
|
'environment (see README.rst) or lower the minprocs setting in the config file to allow the '
|
135
135
|
'program to start.'
|
136
136
|
),
|
137
|
-
'min': self._config.
|
137
|
+
'min': self._config.min_procs,
|
138
138
|
'resource': resource.RLIMIT_NPROC,
|
139
139
|
'name': 'RLIMIT_NPROC',
|
140
140
|
})
|
@@ -220,11 +220,11 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
220
220
|
dl.after_daemonize()
|
221
221
|
|
222
222
|
def _do_daemonize(self) -> None:
|
223
|
-
# To daemonize, we need to become the leader of our own session (process) group.
|
224
|
-
# our parent process will also be sent to us.
|
223
|
+
# To daemonize, we need to become the leader of our own session (process) group. If we do not, signals sent to
|
224
|
+
# our parent process will also be sent to us. This might be bad because signals such as SIGINT can be sent to
|
225
225
|
# our parent process during normal (uninteresting) operations such as when we press Ctrl-C in the parent
|
226
226
|
# terminal window to escape from a logtail command. To disassociate ourselves from our parent's session group we
|
227
|
-
# use os.setsid.
|
227
|
+
# use os.setsid. It means "set session id", which has the effect of disassociating a process from is current
|
228
228
|
# session and process group and setting itself up as a new session leader.
|
229
229
|
#
|
230
230
|
# Unfortunately we cannot call setsid if we're already a session group leader, so we use "fork" to make a copy
|
@@ -256,7 +256,7 @@ class SupervisorSetupImpl(SupervisorSetup):
|
|
256
256
|
os.dup2(2, os.open('/dev/null', os.O_WRONLY))
|
257
257
|
|
258
258
|
# XXX Stevens, in his Advanced Unix book, section 13.3 (page 417) recommends calling umask(0) and closing unused
|
259
|
-
# file descriptors.
|
259
|
+
# file descriptors. In his Network Programming book, he additionally recommends ignoring SIGHUP and forking
|
260
260
|
# again after the setsid() call, for obscure SVR4 reasons.
|
261
261
|
os.setsid()
|
262
262
|
os.umask(self._config.umask)
|
@@ -316,7 +316,7 @@ class ProcessSpawningImpl(ProcessSpawning):
|
|
316
316
|
else:
|
317
317
|
os.dup2(check_not_none(pipes.child_stderr), 2)
|
318
318
|
|
319
|
-
for i in range(3, self._server_config.
|
319
|
+
for i in range(3, self._server_config.min_fds):
|
320
320
|
if i in self._inherited_fds:
|
321
321
|
continue
|
322
322
|
close_fd(Fd(i))
|
ominfra/supervisor/supervisor.py
CHANGED
@@ -282,7 +282,7 @@ class WaitedPid(ta.NamedTuple):
|
|
282
282
|
|
283
283
|
|
284
284
|
def waitpid() -> ta.Optional[WaitedPid]:
|
285
|
-
# Need pthread_sigmask here to avoid concurrent sigchld, but Python doesn't offer in Python < 3.4.
|
285
|
+
# Need pthread_sigmask here to avoid concurrent sigchld, but Python doesn't offer in Python < 3.4. There is
|
286
286
|
# still a race condition here; we can get a sigchld while we're sitting in the waitpid call. However, AFAICT, if
|
287
287
|
# waitpid is interrupted by SIGCHLD, as long as we call waitpid again (which happens every so often during the
|
288
288
|
# normal course in the mainloop), we'll eventually reap the child that we tried to reap during the interrupted
|
ominfra/supervisor/utils/os.py
CHANGED
@@ -21,7 +21,7 @@ def decode_wait_status(sts: int) -> ta.Tuple[Rc, str]:
|
|
21
21
|
Decode the status returned by wait() or waitpid().
|
22
22
|
|
23
23
|
Return a tuple (exitstatus, message) where exitstatus is the exit status, or -1 if the process was killed by a
|
24
|
-
signal; and message is a message telling what happened.
|
24
|
+
signal; and message is a message telling what happened. It is the caller's responsibility to display the message.
|
25
25
|
"""
|
26
26
|
|
27
27
|
if os.WIFEXITED(sts):
|
@@ -62,8 +62,8 @@ def strip_escapes(s: bytes) -> bytes:
|
|
62
62
|
|
63
63
|
|
64
64
|
class SuffixMultiplier:
|
65
|
-
# d is a dictionary of suffixes to integer multipliers.
|
66
|
-
#
|
65
|
+
# d is a dictionary of suffixes to integer multipliers. If no suffixes match, default is the multiplier. Matches are
|
66
|
+
# case insensitive. Return values are in the fundamental unit.
|
67
67
|
def __init__(self, d, default=1):
|
68
68
|
super().__init__()
|
69
69
|
self._d = d
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ominfra
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev131
|
4
4
|
Summary: ominfra
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omdev==0.0.0.
|
16
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omdev==0.0.0.dev131
|
16
|
+
Requires-Dist: omlish==0.0.0.dev131
|
17
17
|
Provides-Extra: all
|
18
18
|
Requires-Dist: paramiko~=3.5; extra == "all"
|
19
19
|
Requires-Dist: asyncssh~=2.18; extra == "all"
|
@@ -22,7 +22,7 @@ ominfra/clouds/aws/journald2aws/poster.py,sha256=hz1XuctW8GtLmfjhRvCFY6py52D4BzX
|
|
22
22
|
ominfra/clouds/gcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
23
|
ominfra/clouds/gcp/auth.py,sha256=3PyfRJNgajjMqJFem3SKui0CqGeHEsZlvbRhuxFcZG8,1348
|
24
24
|
ominfra/deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
ominfra/deploy/_executor.py,sha256=
|
25
|
+
ominfra/deploy/_executor.py,sha256=4i5JP4tiF-MJQHxwstja4tRoYprnAMyzGd9f_az3r98,35355
|
26
26
|
ominfra/deploy/configs.py,sha256=qi0kwT7G2NH7dXLOQic-u6R3yeadup_QtvrjwWIggbM,435
|
27
27
|
ominfra/deploy/remote.py,sha256=6ACmpXU1uBdyGs3Xsp97ktKFq30cJlzN9LRWNUWlGY4,2144
|
28
28
|
ominfra/deploy/executor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
@@ -37,7 +37,7 @@ ominfra/deploy/executor/concerns/systemd.py,sha256=MtsSEToEa1HNouern_JukcYTnypw_
|
|
37
37
|
ominfra/deploy/executor/concerns/user.py,sha256=j5LDfQXquIp-eEM7t6aShsrYoQrM_ILXZycTmTcRVxA,686
|
38
38
|
ominfra/deploy/executor/concerns/venv.py,sha256=jbRriqJHO4r9Zyo5Hfl_qVmcU6Qm6UgrouBroKcPn2g,775
|
39
39
|
ominfra/deploy/poly/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
40
|
-
ominfra/deploy/poly/_main.py,sha256=
|
40
|
+
ominfra/deploy/poly/_main.py,sha256=fqlcDbbfY6gmebcO9BMWD9sz6V6_gxFTQr194xi69N4,24174
|
41
41
|
ominfra/deploy/poly/base.py,sha256=1dGuzWxi2Z6Hm6-YlkVxPk9r3In2aCJ0p8lGR-QQI_s,4166
|
42
42
|
ominfra/deploy/poly/configs.py,sha256=9bzWdbxhOk_Q4KokDjmRz254KHnUU71Vl1frLlhQyU4,584
|
43
43
|
ominfra/deploy/poly/deploy.py,sha256=tMYKslXLjstcv86siRt5j37USsS0Wd6lsfeGRE26zio,544
|
@@ -56,18 +56,18 @@ ominfra/journald/tailer.py,sha256=5abcFMfgi7fnY9ZEQe2ZVobaJxjQkeu6d9Kagw33a1w,33
|
|
56
56
|
ominfra/manage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
57
|
ominfra/manage/manage.py,sha256=BttL8LFEknHZE_h2Pt5dAqbfUkv6qy43WI0raXBZ1a8,151
|
58
58
|
ominfra/pyremote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
|
-
ominfra/pyremote/_runcommands.py,sha256=
|
59
|
+
ominfra/pyremote/_runcommands.py,sha256=RKNvaHje-QGpvwwmFQ6OfEn3eEJ2c6zVUBYnDo2RV9U,29188
|
60
60
|
ominfra/pyremote/bootstrap.py,sha256=RvMO3YGaN1E4sgUi1JEtiPak8cjvqtc_vRCq1yqbeZg,3370
|
61
61
|
ominfra/pyremote/runcommands.py,sha256=bviS0_TDIoZVAe4h-_iavbvJtVSFu8lnk7fQ5iasCWE,1571
|
62
62
|
ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
|
-
ominfra/scripts/journald2aws.py,sha256=
|
64
|
-
ominfra/scripts/supervisor.py,sha256=
|
63
|
+
ominfra/scripts/journald2aws.py,sha256=qNGdiXxng21BBO5kqOQvnOf1Ftc3rTJZXpCu8MO-Kvc,131387
|
64
|
+
ominfra/scripts/supervisor.py,sha256=a0oz88cW-9y0P_LNFXuDBKLgDywv3RIUxxXuZ8VezCE,242615
|
65
65
|
ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
|
66
66
|
ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
67
67
|
ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
|
68
|
-
ominfra/supervisor/configs.py,sha256=
|
68
|
+
ominfra/supervisor/configs.py,sha256=OPtiL5_SjBYQ9xDqMgZvjoXgpleTxv4d3C4fD1X2Dz0,3966
|
69
69
|
ominfra/supervisor/dispatchers.py,sha256=dfjog5PyVAJaFzgFI0tpy38ZgDiFrewMjVi21ksrlAg,1007
|
70
|
-
ominfra/supervisor/dispatchersimpl.py,sha256=
|
70
|
+
ominfra/supervisor/dispatchersimpl.py,sha256=dZpfG7Z2_AcRpfa2RaZ-xolsbM5iKkifdQpON7w7Upo,11257
|
71
71
|
ominfra/supervisor/events.py,sha256=w3HQFrq-SuroYWoQfNFYeU1phnTvHTgsAqA6TGtAafI,6593
|
72
72
|
ominfra/supervisor/exceptions.py,sha256=Qbu211H3CLlSmi9LsSikOwrcL5HgJP9ugvcKWlGTAoI,750
|
73
73
|
ominfra/supervisor/groups.py,sha256=MBbsbt8Zh_WEYkGOr1KXa82gnPVw9wPB2lAnqhugXSc,2457
|
@@ -76,36 +76,36 @@ ominfra/supervisor/http.py,sha256=y0tos6zbb4k-WvNQXlgAeK1qi5mKXkyXO9bVJt4OXew,32
|
|
76
76
|
ominfra/supervisor/inject.py,sha256=onKUudx5eBbNuXwEqeiaVIIA3ZbpUSDiEAKg9GBiWG8,4514
|
77
77
|
ominfra/supervisor/io.py,sha256=2NO4BYC-PznIrJpTFxN8UEAhd_codfNm_HI424gYQ3c,3294
|
78
78
|
ominfra/supervisor/main.py,sha256=ebe7skFPfwXV2meMVRndhuLZmz-LiuHH1x1CgiarR0o,4132
|
79
|
-
ominfra/supervisor/pipes.py,sha256=
|
80
|
-
ominfra/supervisor/privileges.py,sha256=
|
79
|
+
ominfra/supervisor/pipes.py,sha256=2ZihNTnRNjnIPOtPbm3_pyqO15f7BNs7WnNtO5V8ahM,2231
|
80
|
+
ominfra/supervisor/privileges.py,sha256=kaRTHI7XjqzxEWCeHp3_0J0Vc4gSPugRbXEwxuw6MYE,2054
|
81
81
|
ominfra/supervisor/process.py,sha256=UaubVxsxVqDnbuWVpTH0DTGbJGLO0vGJ9mNcvy2kCXM,217
|
82
|
-
ominfra/supervisor/processimpl.py,sha256=
|
82
|
+
ominfra/supervisor/processimpl.py,sha256=YRHIVYdPXighBXAVNmW3ur7IhoSxhkxFYCQI1B8CpDo,18748
|
83
83
|
ominfra/supervisor/setup.py,sha256=7HwwwI-WT_Z0WjZ9_l5Orr4K298nKKhQ1f_ZgGsi9TU,622
|
84
|
-
ominfra/supervisor/setupimpl.py,sha256=
|
84
|
+
ominfra/supervisor/setupimpl.py,sha256=88h3oYsdJ0LAo7sZZZGRQti14oQay3b-0Vd_h3Cl108,9638
|
85
85
|
ominfra/supervisor/signals.py,sha256=jY52naUifcAjd6nICTP1ZW3IQSPsHB4cvbsJo8_QV_U,2196
|
86
86
|
ominfra/supervisor/spawning.py,sha256=i1k3tmqWyU-KIN7kel-JVxTVGnLiTIVmZzlstJSZpjM,622
|
87
|
-
ominfra/supervisor/spawningimpl.py,sha256=
|
87
|
+
ominfra/supervisor/spawningimpl.py,sha256=Pkp6mefJhOGCCj5T2I1jXEsVp15g9KMKbANYgoX-ws8,11162
|
88
88
|
ominfra/supervisor/states.py,sha256=9yoNOSwalRcKEnCP9zG6tVS0oivo5tCeuH6AaaW7Jpc,890
|
89
|
-
ominfra/supervisor/supervisor.py,sha256=
|
89
|
+
ominfra/supervisor/supervisor.py,sha256=Ryvs80cDOe4pvBdZazLLaOCR1We0aj44Y1Hw4l3FUnk,9514
|
90
90
|
ominfra/supervisor/types.py,sha256=RamAYEF3fISfKwlIMRleLOFuKVWrxjQJGI6p76jK03c,3959
|
91
91
|
ominfra/supervisor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
92
|
ominfra/supervisor/utils/collections.py,sha256=vcfmVYS4QngMdtEI1DvdRIcubmy55Wj40NCzW27_rIY,1361
|
93
93
|
ominfra/supervisor/utils/diag.py,sha256=ujz4gkW7p3wmbaKFM8Hz5eHEwpoUkbB8JeDvcHilCz0,705
|
94
94
|
ominfra/supervisor/utils/fds.py,sha256=lz8DWXzGYvu93dqhWK0WrhXrrJVQ_psoom4Nj_o8g2g,849
|
95
95
|
ominfra/supervisor/utils/fs.py,sha256=ABbNcsCpzSXAvq_ZZSCj61mj5kGnVuC4spUmoWenlqw,1155
|
96
|
-
ominfra/supervisor/utils/os.py,sha256=
|
96
|
+
ominfra/supervisor/utils/os.py,sha256=IZJ9mBV23CAI0hSBVQiyCNcf-sWqHAmjAW9bbsvKFao,1095
|
97
97
|
ominfra/supervisor/utils/ostypes.py,sha256=B7VjwbzVesz9we9MztoSk8bH8sTxMIWtILy_Qde0G7w,164
|
98
98
|
ominfra/supervisor/utils/signals.py,sha256=uZkTvissbtq7TlJD4MkTiL3F-zyWmAFUuWQtFjsf0MI,1474
|
99
|
-
ominfra/supervisor/utils/strings.py,sha256=
|
99
|
+
ominfra/supervisor/utils/strings.py,sha256=gZOYiFI3ZQEMrXq6VlK2WadK12JPO6zYjPenq_OPcYU,2475
|
100
100
|
ominfra/supervisor/utils/users.py,sha256=PRUhWy74WQCxix4BLNYcWW1i2mF1IyAxj1RzElnP4iM,1345
|
101
101
|
ominfra/tailscale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
102
102
|
ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
|
103
103
|
ominfra/tailscale/cli.py,sha256=DSGp4hn5xwOW-l_u_InKlSF6kIobxtUtVssf_73STs0,3567
|
104
104
|
ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
105
105
|
ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
|
106
|
-
ominfra-0.0.0.
|
107
|
-
ominfra-0.0.0.
|
108
|
-
ominfra-0.0.0.
|
109
|
-
ominfra-0.0.0.
|
110
|
-
ominfra-0.0.0.
|
111
|
-
ominfra-0.0.0.
|
106
|
+
ominfra-0.0.0.dev131.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
107
|
+
ominfra-0.0.0.dev131.dist-info/METADATA,sha256=tX48aF4l92ov4-dQc50yn6pbYrXTAz3j73ZJS7H9p04,731
|
108
|
+
ominfra-0.0.0.dev131.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
109
|
+
ominfra-0.0.0.dev131.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
|
110
|
+
ominfra-0.0.0.dev131.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
|
111
|
+
ominfra-0.0.0.dev131.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|