import os
import argparse
import platform
+from pwd import getpwnam
+from grp import getgrnam
sysvinit_script = """#!/bin/sh
-
### BEGIN INIT INFO
-# Provides: {project_name}
+# Provides: %s
# Required-Start: docker
# Required-Stop: docker
# Default-Start: 2 3 4 5
set -e
-PROJECT_NAME={project_name}
-OPTS="{compose_opts}"
-UPOPTS="-d --no-recreate --no-build --no-deps"
+PROJECT_NAME=%s
+YAMLFILE=%s
+OPTS="-f $YAMLFILE -p $PROJECT_NAME"
+UPOPTS="-d --no-build --no-deps"
. /lib/lsb/init-functions
;;
*)
- log_action_msg "Usage: /etc/init.d/$PROJECT_NAME {{start|stop|reload|force-reload|restart|try-restart|status}}" || true
+ log_action_msg "Usage: /etc/init.d/$PROJECT_NAME {start|stop|reload|force-reload|restart|try-restart|status}" || true
exit 1
;;
esac
systemd_service = """
[Unit]
-Description={project_name} composition
+Description=%s composition
Requires=docker.service
After=docker.service
-{ConditionPathExists}
+ConditionPathExists=%s
[Service]
-ExecStart={docker_compose} {compose_opts} up -d
-ExecStop={docker_compose} {compose_opts} %s stop
+ExecStart=%s -f %s up -d
+ExecStop=%s -f %s stop
[Install]
WantedBy=local.target
"""
-
class DockerCompositionInstaller(object):
docker = '/etc/init.d/docker'
docker_compose = '/usr/local/bin/docker-compose'
+ cron_rule = "0 */6 * * * %s %s"
- def __init__(self, config='docker-compose.yml', init_type='sysvinit', dry_run=False):
+ def __init__(self, config='docker-compose.yml', init_type='sysvinit', cron=False):
self.init_type = init_type
- self.dry_run = dry_run
- self.path = os.getcwd()
- self.config = [os.path.realpath(yml_file)
- for yml_file in config]
- self.check_path()
- self.name = self.config[0].split(os.sep)[-2].lower()
- opts = ' '.join(['-f %s' % yml_file for yml_file in self.config])
- opts += ' -p %s' % self.name
- self.docker_compose_opts = opts
-
- def check_path(self):
- for yml_file in self.config:
- if not os.path.exists(yml_file):
- raise ValueError('The YAML docker composition %s was not found, please type "install.py -h" for more infos.' % yml_file)
+ self.path = os.path.dirname(os.path.realpath(__file__))
+ self.config = config
+ self.root = self.get_root()
+ self.config = os.path.abspath(self.root + os.sep + self.config)
+ self.name = self.config.split(os.sep)[-2].lower()
+ self.cron = cron
+
+ def get_root(self):
+ path = self.path
+ while not self.config in os.listdir(path):
+ path = os.sep.join(path.split(os.sep)[:-1])
+ if not path:
+ raise ValueError('The YAML docker composition was not found, please type "install.py -h" for more infos.')
+ return path
def install_docker(self):
if not os.path.exists(self.docker):
def install_daemon_sysvinit(self):
script = '/etc/init.d/' + self.name
print 'Writing sysvinit script in ' + script
- data = sysvinit_script.format(project_name=self.name,
- compose_opts=self.docker_compose_opts)
- if self.dry_run:
- print data
- return
+ data = sysvinit_script % (self.name, self.name, self.config)
f = open(script, 'w')
f.write(data)
f.close()
def install_daemon_systemd(self):
service = '/lib/systemd/system/' + self.name + '.service'
print 'Writing systemd service in ' + service
- conditions = '\n'.join(['ConditionPathExists=%s' % yml_file
- for yml_file in self.config])
- data = systemd_service.format(project_name=self.name,
- ConditionPathExists=conditions,
- docker_compose=self.docker_compose,
- compose_opts=self.docker_compose_opts)
- if self.dry_run:
- print data
- return
+ data = systemd_service % (self.name, self.config, self.docker_compose,
+ self.config, self.docker_compose, self.config)
f = open(service, 'w')
f.write(data)
f.close()
os.system('systemctl enable ' + service)
os.system('systemctl daemon-reload')
- def install(self):
- print 'Installing ' + self.name + ' composition as a daemon...'
- self.install_docker()
- if self.init_type == 'sysvinit':
- self.install_daemon_sysvinit()
- elif self.init_type == 'systemd':
- self.install_daemon_systemd()
- print 'Done'
+ def install_cron(self):
+ cron_path = os.sep.join([self.root, 'etc', 'cron.d', 'app'])
+ log_path = os.sep.join([self.root, 'var', 'log', 'cron'])
+ if not os.path.exists(log_path) :
+ os.makedirs(log_path, 0o755)
+ os.symlink(cron_path, '/etc/cron.d/' + self.name)
+ uid = int(getpwnam('root').pw_uid)
+ guid = int(getgrnam('root').gr_gid)
+ fd_cron_path = os.open(cron_path, os.O_RDONLY)
+ os.fchown(fd_cron_path, 0, 0)
def uninstall_daemon_sysvinit(self):
script = '/etc/init.d/' + self.name
os.system('systemctl daemon-reload')
os.system('rm ' + service)
+ def uninstall_cron(self):
+ os.system('rm /etc/cron.d/' + self.name)
+
def uninstall(self):
print 'Uninstalling ' + self.name + ' composition as a daemon...'
if self.init_type == 'sysvinit':
self.uninstall_daemon_sysvinit()
elif self.init_type == 'systemd':
self.uninstall_daemon_systemd()
+ if self.cron:
+ self.uninstall_cron()
+ print 'Done'
+
+ def install(self):
+ print 'Installing ' + self.name + ' composition as a daemon...'
+ self.install_docker()
+ if self.init_type == 'sysvinit':
+ self.install_daemon_sysvinit()
+ elif self.init_type == 'systemd':
+ self.install_daemon_systemd()
+ if self.cron:
+ self.install_cron()
print 'Done'
description ="""Install this docker composition program as a daemon with boot init (sysvinit by default)."""
parser = argparse.ArgumentParser(description=description)
parser.add_argument('--uninstall', help='uninstall the daemon', action='store_true')
+ parser.add_argument('--cron', help='install cron backup rule', action='store_true')
parser.add_argument('--systemd', help='use systemd', action='store_true')
- parser.add_argument('--dry-run', help='dry run, do not install the daemon but print the service file', action='store_true')
- parser.add_argument('composition_file', nargs='*', help='the path of the YAML composition file to use (optional)')
+ parser.add_argument('composition_file', nargs='?', help='the path of the YAML composition file to use (optional)')
- config = ['docker-compose.yml']
+ config = 'docker-compose.yml'
init_type = 'sysvinit'
- dry_run = False
args = vars(parser.parse_args())
if args['systemd']:
init_type = 'systemd'
if args['composition_file']:
config = args['composition_file']
- if args['dry_run']:
- dry_run = args['dry_run']
- installer = DockerCompositionInstaller(config, init_type, dry_run=dry_run)
+ installer = DockerCompositionInstaller(config, init_type, args['cron'])
if args['uninstall']:
installer.uninstall()
else: