-
Notifications
You must be signed in to change notification settings - Fork 22
/
mtda-service
executable file
·160 lines (135 loc) · 4.51 KB
/
mtda-service
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/bin/env python3
# ---------------------------------------------------------------------------
# MTDA Service
# ---------------------------------------------------------------------------
#
# This software is a part of MTDA.
# Copyright (C) 2024 Siemens Digital Industries Software
#
# ---------------------------------------------------------------------------
# SPDX-License-Identifier: MIT
# ---------------------------------------------------------------------------
# System imports
import argparse
import daemon
import lockfile
import os
import os.path
import signal
import sys
import zerorpc
import socket
import zeroconf
from systemd import daemon as sd
# Local imports
from mtda.main import MultiTenantDeviceAccess
import mtda.constants as CONSTS
class Application:
def __init__(self):
self.agent = None
self.remote = None
self.zeroconf = None
self.zerosrv = None
self.logfile = "/var/log/mtda.log"
self.pidfile = "/var/run/mtda.pid"
def daemonize(self):
context = daemon.DaemonContext(
working_directory=os.getcwd(),
stdout=open(self.logfile, 'w+'),
stderr=open(self.logfile, 'w+'),
umask=0o002,
pidfile=lockfile.FileLock(self.pidfile)
)
context.signal_map = {
signal.SIGTERM: self.stop,
signal.SIGHUP: 'terminate'
}
with context:
status = self.server()
return status
def _ip(self):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('192.0.2.0', 0))
ip = s.getsockname()[0]
s.close()
return ip
def server(self):
# Start our agent
status = self.agent.start()
if status is False:
return False
# Start our RPC server
uri = "tcp://*:%d" % (self.agent.ctrlport)
s = zerorpc.Server(self.agent, heartbeat=20)
s.bind(uri)
# Initialize ZeroConf
interfaces = zeroconf.InterfaceChoice.All
zc = zeroconf.Zeroconf(interfaces=interfaces)
props = {
'description': 'Multi-Tenant Device Access'
}
deviceType = CONSTS.MDNS.TYPE
name = self.agent.name
info = zeroconf.ServiceInfo(
type_=deviceType,
name=f'{name}.{deviceType}',
addresses=[socket.inet_aton(self._ip())],
port=int(self.agent.ctrlport),
properties=props,
server=f'{name}.local.')
try:
zc.register_service(info)
self.zeroconf = zc
self.zerosrv = info
except zeroconf.NonUniqueNameException:
pass
try:
sd.notify('READY=1')
s.run()
except KeyboardInterrupt:
self.stop()
return True
def stop(self, signum=0, frame=None):
if self.zerosrv is not None:
self.zeroconf.unregister_service(self.zerosrv)
if self.agent is not None:
self.agent.stop()
sys.exit(signum)
def print_version(self):
agent = MultiTenantDeviceAccess()
print(f"MTDA version: {agent.version}")
def main(self):
config = None
parser = argparse.ArgumentParser(
description='service process for MTDA')
parser.add_argument('-c', '--config',
nargs=1,
help='alternate configuration file')
parser.add_argument('-n', '--no-detach',
action='store_true',
help='do not detach from the calling process')
parser.add_argument('-v', '--version',
action='store_true',
help='print version of this program and exit')
args = parser.parse_args()
if args.version is True:
self.print_version()
sys.exit(0)
if args.config is not None:
config = args.config[0]
# Start our server
self.agent = MultiTenantDeviceAccess()
self.agent.load_config(None, True, config)
self.remote = self.agent.remote
if args.no_detach is False:
status = self.daemonize()
else:
signal.signal(signal.SIGTERM, self.stop)
status = self.server()
if status is False:
print('Failed to start the MTDA server!', file=sys.stderr)
return False
return True
if __name__ == '__main__':
app = Application()
app.main()