-
Notifications
You must be signed in to change notification settings - Fork 1
/
unbound-cluster-ctl.py
128 lines (93 loc) · 3.04 KB
/
unbound-cluster-ctl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/python3
# Batteries
import os
import signal
import time
from argparse import ArgumentParser
# Own Imports
from config import Config, InvalidConfiguration
from master import UnboundClusterMaster
def stop():
"""
Stops the master process.
"""
# Check for pidfile
if not os.path.isfile(Config.getpath('pidfile')):
print('Could not find pidfile. Is the process running?')
return
# Read Supervisor PID from pidfile
with open(Config.getpath('pidfile'), 'r') as pidfile:
pid = int(pidfile.readline())
# Check for running pid
if not os.path.isdir(f'/proc/{pid}'):
# Remove pidfile
os.unlink(Config.getpath('pidfile'))
# Also remove socket file if existent
if os.path.isfile(Config.getpath('socket')):
os.unlink(Config.getpath('socket'))
print('Process is not running. Removed stale pidfile and socket.')
return
# Send SIGTERM to process
os.kill(pid, signal.SIGINT)
# Wait for process to end
attempts = 0
while os.path.isdir(f'/proc/{pid}'):
print('Waiting for Unbound Cluster to stop...')
# Send SIGTERM to process every 5 seconds
if attempts % 5 == 0:
os.kill(pid, signal.SIGINT)
# Increment attempts
attempts += 1
# Rest for a while
time.sleep(1)
def start():
"""
Starts the master process.
"""
# Check for pidfile existence
if os.path.isfile(Config.getpath('pidfile')):
# Check for stale PID file
with open(Config.getpath('pidfile'), 'r') as pidfile:
pid = pidfile.read()
# Check if process with PID is running
if os.path.isdir(f'/proc/{pid}'):
print(f'Unable to start. Process already running with pid {pid}.')
exit(0)
# Remove stale PID file
print(f'Found stale pid file at {Config.get("pidfile")}. Removing...')
os.unlink(Config.getpath('pidfile'))
# Remove stale socket if existent
if os.path.isfile(Config.getpath('socket')):
os.unlink(Config.getpath('socket'))
# Create and start the master process
UnboundClusterMaster().start()
def restart():
"""
Restarts the master process.
"""
stop()
start()
# Available operations
OPERATIONS = {
'stop': stop,
'start': start,
'restart': restart
}
# Main
if __name__ == '__main__':
# Create argument parser
parser = ArgumentParser(description='Unbound Cluster Controller')
parser.add_argument('operation', type=str, choices=OPERATIONS.keys(),
help=f'The operation to execute. Possible values: {", ".join(OPERATIONS.keys())}')
# Parse Arguments
args = parser.parse_args()
# Execute requested operation
try:
# Execute Operation
OPERATIONS[args.operation]()
except InvalidConfiguration as e:
print(f'Invalid Configuration: {str(e)}')
exit(1)
except Exception as e:
print(f'Unknown error occurred: {str(e)}')
exit(1)