Coverage for gws-app/gws/server/control.py: 21%
84 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-16 22:59 +0200
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-16 22:59 +0200
1"""Server control.
3Following workflows are supported:
51) Server start. This is called only once upon the container start.
7 - (empty TMP_DIR completely in bin/gws)
8 - configure
9 - store the config
10 - write server configs
11 - (the actual invocation of the server start script takes place in bin/gws)
132) Server reconfigure. Can be called anytime, e.g. by the monitor
15 - configure
16 - store the config
17 - write server configs
18 - empty the TRANSIENT_DIR
19 - reload all backends
20 - reload nginx
223) Server reload. Can be called anytime, e.g. by the monitor
24 - write server configs
25 - empty the TRANSIENT_DIR
26 - reload all backends
27 - reload nginx
304) Configure (debugging)
32 - configure
33 - store the config
365) Configtest (debugging)
38 - configure
42"""
44import gws
45import gws.config
46import gws.lib.datetimex
47import gws.lib.osx
48import gws.lib.watcher
49import gws.lib.lock
51# see bin/gws
52_SERVER_START_SCRIPT = f'{gws.c.VAR_DIR}/server.sh'
54_PID_PATHS = {
55 'web': f'{gws.c.PIDS_DIR}/web.uwsgi.pid',
56 'spool': f'{gws.c.PIDS_DIR}/spool.uwsgi.pid',
57 'mapproxy': f'{gws.c.PIDS_DIR}/mapproxy.uwsgi.pid',
58 'nginx': f'{gws.c.PIDS_DIR}/nginx.pid',
59}
62def start(manifest_path='', config_path=''):
63 if app_is_running('web'):
64 gws.log.error(f'server already running')
65 gws.u.exit(1)
66 root = configure_and_store(manifest_path, config_path, is_starting=True)
67 root.app.serverMgr.create_server_configs(gws.c.SERVER_DIR, _SERVER_START_SCRIPT, _PID_PATHS)
70def reconfigure(manifest_path='', config_path=''):
71 if not app_is_running('web'):
72 gws.log.error(f'server not running')
73 gws.u.exit(1)
74 root = configure_and_store(manifest_path, config_path, is_starting=False)
75 root.app.serverMgr.create_server_configs(gws.c.SERVER_DIR, _SERVER_START_SCRIPT, _PID_PATHS)
76 reload_all()
79def configure_and_store(manifest_path='', config_path='', is_starting=False):
80 root = configure(manifest_path, config_path, is_starting)
81 gws.config.store(root)
82 return root
85def configure(manifest_path='', config_path='', is_starting=False):
86 def _pre_init(ld: gws.config.loader.Object):
87 autorun = gws.u.get(ld.config, 'server.autoRun')
88 if autorun:
89 gws.log.info(f'AUTORUN: {autorun!r}')
90 gws.lib.osx.run(autorun, echo=True)
92 hooks = []
93 if is_starting:
94 hooks.append(['preInitialize', _pre_init])
96 root = gws.config.configure(
97 manifest_path=manifest_path,
98 config_path=config_path,
99 fallback_config=_FALLBACK_CONFIG,
100 hooks=hooks,
101 )
102 if not root:
103 raise gws.ConfigurationError('configuration failed')
104 return root
107def config_test(
108 manifest_path='',
109 config_path='',
110 dirs_to_watch='',
111 with_parse_only=False,
112 with_watch=False
113):
115 def _check(*args):
116 gws.log.info('=' * 80)
117 gws.log.info(f'TESTING CONFIGURATION...')
118 gws.log.info('=' * 80)
119 if with_parse_only:
120 gws.config.parse(manifest_path, config_path)
121 else:
122 gws.config.configure(manifest_path, config_path)
124 _check()
126 if not with_watch:
127 return
129 w = gws.lib.watcher.new(_check)
130 dirs = gws.u.to_list(dirs_to_watch or '/data')
131 for d in dirs:
132 w.add_directory(d, recursive=True)
133 w.start()
135 while True:
136 gws.u.sleep(3)
140##
142def reload_all():
143 gws.lib.osx.run(['rm', '-fr', gws.c.TRANSIENT_DIR])
144 gws.u.ensure_system_dirs()
146 reload_app('spool')
147 reload_app('mapproxy')
148 reload_app('web')
150 reload_nginx()
151 return True
154def reload_app(srv):
155 if not app_is_running(srv):
156 gws.log.debug(f'reload: {srv=} not running')
157 return
158 gws.log.info(f'reloading {srv}...')
159 gws.lib.osx.run(['uwsgi', '--reload', _PID_PATHS[srv]])
162def reload_nginx():
163 gws.log.info(f'reloading nginx...')
164 gws.lib.osx.run(['nginx', '-c', gws.c.SERVER_DIR + '/nginx.conf', '-s', 'reload'])
167def app_is_running(srv):
168 try:
169 with open(_PID_PATHS[srv]) as fp:
170 pid = int(fp.read())
171 except (FileNotFoundError, ValueError):
172 pid = 0
173 if pid == 0:
174 return False
175 gws.log.debug(f'found {pid=} for {srv=}')
176 return pid in gws.lib.osx.running_pids()
179##
182_FALLBACK_CONFIG = gws.Config(
183 server=gws.Config(
184 timeZone="Europe/Berlin",
185 mapproxy=gws.Config(disabled=True),
186 monitor=gws.Config(disabled=True),
187 log=gws.Config(level='INFO'),
188 qgis=gws.Config(host='qgis', port=80),
189 spool=gws.Config(disabled=True),
190 web=gws.Config(disabled=False, workers=1, timeout=60, maxRequestLength=10),
191 )
192)