@@ -40,6 +40,8 @@ def detect_provider():
40
40
print (os .path .realpath (cmd ))
41
41
if b'systemd' in os .path .realpath (cmd ):
42
42
return Systemd
43
+ if b'supervisor' in os .path .realpath (cmd ):
44
+ return Supervisor
43
45
return Upstart
44
46
45
47
@@ -228,3 +230,78 @@ def _fill_template(self, template):
228
230
self .interpreter .file (f )
229
231
return self .interpreter .output .getvalue ()
230
232
self .set_job_path ()
233
+
234
+
235
+ class Supervisor (Generic ):
236
+ """ The Supervisor implementation places the user-specified files in ``/etc/ros/DISTRO/NAME.d``,
237
+ and creates an systemd job configuration in ``/lib/systemd/system/NAME.d``. Two additional
238
+ helper scripts are created for starting and stopping the job, places in
239
+ ``/usr/sbin``.
240
+ To detect which system you're using run: ps -p1 | grep systemd && echo systemd || echo upstart
241
+ """
242
+
243
+ def generate_install (self ):
244
+ # Default is /etc/ros/DISTRO/JOBNAME.d
245
+ self ._set_job_path ()
246
+
247
+ # User-specified launch files.
248
+ self ._add_job_files ()
249
+
250
+ # This is optional to support the old --augment flag where a "job" only adds
251
+ # launch files to an existing configuration.
252
+ if self .job .generate_system_files :
253
+ # Share a single instance of the EmPy interpreter.
254
+ self .interpreter = em .Interpreter (globals = self .job .__dict__ .copy ())
255
+
256
+ self .installation_files [os .path .join (self .root , "etc/supervisor/conf.d" , self .job .name + ".conf" )] = {
257
+ "content" : self ._fill_template ("templates/supervisor_job.conf.em" ), "mode" : 0o644 }
258
+ self .installation_files [os .path .join (self .root , "usr/sbin" , self .job .name + "-start" )] = {
259
+ "content" : self ._fill_template ("templates/job-start.em" ), "mode" : 0o755 }
260
+ self .installation_files [os .path .join (self .root , "usr/sbin" , self .job .name + "-stop" )] = {
261
+ "content" : self ._fill_template ("templates/job-stop.em" ), "mode" : 0o755 }
262
+ self .interpreter .shutdown ()
263
+
264
+ # Add an annotation file listing what has been installed. This is a union of what's being
265
+ # installed now with what has been installed previously, so that an uninstall should remove
266
+ # all of it. A more sophisticated future implementation could track contents or hashes and
267
+ # thereby warn users when a new installation is stomping a change they have made.
268
+ self ._load_installed_files_set ()
269
+ self .installed_files_set .update (list (self .installation_files .keys ()))
270
+
271
+ # Remove the job directory. This will fail if it is not empty, and notify the user.
272
+ self .installed_files_set .add (self .job .job_path )
273
+
274
+ # Remove the annotation file itself.
275
+ self .installed_files_set .add (self .installed_files_set_location )
276
+
277
+ self .installation_files [self .installed_files_set_location ] = {
278
+ "content" : "\n " .join (self .installed_files_set )}
279
+
280
+ return self .installation_files
281
+
282
+ def post_install (self ):
283
+ print ("** To complete installation please run the following command:" )
284
+ print (" sudo supervisorctl reload" +
285
+ " && sudo supervisorctl status" +
286
+ " ; browse https://localhost:9001" )
287
+
288
+ def generate_uninstall (self ):
289
+ self ._set_job_path ()
290
+ self ._load_installed_files_set ()
291
+
292
+ for filename in self .installed_files_set :
293
+ self .installation_files [filename ] = {"remove" : True }
294
+
295
+ return self .installation_files
296
+
297
+ def _set_job_path (self ):
298
+ self .job .job_path = os .path .join (
299
+ self .root , "etc/ros" , self .job .rosdistro , self .job .name + ".d" )
300
+
301
+ def _fill_template (self , template ):
302
+ self .interpreter .output = io .StringIO ()
303
+ self .interpreter .reset ()
304
+ with open (find_in_workspaces (project = "robot_upstart" , path = template )[0 ]) as f :
305
+ self .interpreter .file (f )
306
+ return self .interpreter .output .getvalue ()
307
+ self .set_job_path ()
0 commit comments