def handle(self, *args, **options): context = { "site_dir": get_site_dir(), "orchestra_beat": run("which orchestra-beat").stdout.decode("utf8"), "venv": os.environ.get("VIRTUAL_ENV", ""), } content = run("crontab -l || true").stdout.decode("utf8") if "orchestra-beat" not in content: if context["venv"]: content += ( "\n* * * * * . %(venv)s/bin/activate && %(orchestra_beat)s %(site_dir)s/manage.py; deactivate" % context ) else: content += "\n* * * * * %(orchestra_beat)s %(site_dir)s/manage.py" % context context["content"] = content run("cat << EOF | crontab\n%(content)s\nEOF" % context, display=True) # Configrue settings to use threaded task backend (default) changes = {} if Setting.settings["TASKS_BACKEND"].value == "celery": changes["TASKS_BACKEND"] = settings_parser.Remove() if "celeryd" in Setting.settings["ORCHESTRA_START_SERVICES"].value: changes["ORCHESTRA_START_SERVICES"] = settings_parser.Remove() if "celeryd" in Setting.settings["ORCHESTRA_RESTART_SERVICES"].value: changes["ORCHESTRA_RESTART_SERVICES"] = settings_parser.Remove() if "celeryd" in Setting.settings["ORCHESTRA_STOP_SERVICES"].value: changes["ORCHESTRA_STOP_SERVICES"] = settings_parser.Remove() if changes: settings_parser.apply(changes)
def handle(self, *args, **options): context = { 'site_dir': get_site_dir(), 'orchestra_beat': run('which orchestra-beat').stdout.decode('utf8'), 'venv': os.environ.get('VIRTUAL_ENV', ''), } content = run('crontab -l || true').stdout.decode('utf8') if 'orchestra-beat' not in content: if context['venv']: content += "\n* * * * * . %(venv)s/bin/activate && %(orchestra_beat)s %(site_dir)s/manage.py; deactivate" % context else: content += "\n* * * * * %(orchestra_beat)s %(site_dir)s/manage.py" % context context['content'] = content run("cat << EOF | crontab\n%(content)s\nEOF" % context, display=True) # Configrue settings to use threaded task backend (default) changes = {} if Setting.settings['TASKS_BACKEND'].value == 'celery': changes['TASKS_BACKEND'] = settings_parser.Remove() if 'celeryd' in Setting.settings['ORCHESTRA_START_SERVICES'].value: changes['ORCHESTRA_START_SERVICES'] = settings_parser.Remove() if 'celeryd' in Setting.settings['ORCHESTRA_RESTART_SERVICES'].value: changes['ORCHESTRA_RESTART_SERVICES'] = settings_parser.Remove() if 'celeryd' in Setting.settings['ORCHESTRA_STOP_SERVICES'].value: changes['ORCHESTRA_STOP_SERVICES'] = settings_parser.Remove() if changes: settings_parser.apply(changes)
def handle(self, *args, **options): context = { 'project_name': paths.get_project_name(), 'site_dir': paths.get_site_dir(), } banner = "%(project_name)s status" % context self.stdout.write(banner) self.stdout.write('-' * len(banner)) self.stdout.write(' Orchestra version: ' + get_version()) if djsettings.DEBUG: self.stdout.write(" debug enabled") else: self.stdout.write(" debug disabled") ps = run('ps aux').stdout.decode().replace('\n', ' ') for service in flatten(settings.ORCHESTRA_START_SERVICES): context['service'] = service if self.is_running(context, ps): self.stdout.write(" %(service)s online" % context) else: self.stdout.write(" %(service)s offline" % context) if service == 'nginx': try: config_path = '/etc/nginx/sites-enabled/%(project_name)s.conf' % context with open(config_path, 'r') as handler: config = handler.read().replace('\n', ' ') except FileNotFoundError: self.stdout.write(" * %s not found" % config_path) else: regex = r'location\s+([^\s]+)\s+{.*uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;.*' % context location = re.findall(regex, config) if location: ip = run( "ip a | grep 'inet ' | awk {'print $2'} | grep -v '^127.0.' | head -n 1 | cut -d'/' -f1" ).stdout.decode() if not ip: ip = '127.0.0.1' location = 'http://%s%s' % (ip, location[0]) self.stdout.write(" * location %s" % location) else: self.stdout.write(" * location not found") elif service == 'postgresql': db_conn = connections['default'] try: c = db_conn.cursor() except OperationalError: self.stdout.write(" * DB connection failed") else: self.stdout.write(" * DB connection succeeded") elif service == 'uwsgi': uwsgi_config = '/etc/uwsgi/apps-enabled/%(project_name)s.ini' % context if os.path.isfile(uwsgi_config): self.stdout.write(" * %s exists" % uwsgi_config) else: self.stdout.write(" * %s does not exist" % uwsgi_config) cronbeat = 'crontab -l | grep "^.*/orchestra-beat %(site_dir)s/manage.py"' % context if run(cronbeat, valid_codes=(0, 1)).exit_code == 0: self.stdout.write(" cronbeat installed") else: self.stdout.write(" cronbeat not installed")
def handle(self, *args, **options): self.database_files = [] try: if os.getcwd() == get_site_dir(): self.generate_database_files() super(Command, self).handle(*args, **options) finally: self.remove_database_files()
def __init__(self, *args, **kwargs): super(Command, self).__init__(*args, **kwargs) self.option_list = BaseCommand.option_list + ( make_option('--cert', dest='cert', default='', help='Nginx SSL certificate, one will be created by default.'), make_option('--cert-key', dest='cert_key', default='', help='Nginx SSL certificate key.'), make_option('--cert-path', dest='cert_path', default=os.path.join(paths.get_site_dir(), 'ssl', 'orchestra.crt'), help='Nginx SSL certificate, one will be created by default.'), make_option('--cert-key-path', dest='cert_key_path', default=os.path.join(paths.get_site_dir(), 'ssl', 'orchestra.key'), help='Nginx SSL certificate key.'), # Cert options make_option('--cert-override', dest='cert_override', action='store_true', default=False, help='Force override cert and keys if exists.'), make_option('--cert-country', dest='cert_country', default='ES', help='Certificate Distinguished Name Country.'), make_option('--cert-state', dest='cert_state', default='Spain', help='Certificate Distinguished Name STATE.'), make_option('--cert-locality', dest='cert_locality', default='Barcelona', help='Certificate Distinguished Name Country.'), make_option('--cert-org_name', dest='cert_org_name', default='Orchestra', help='Certificate Distinguished Name Organization Name.'), make_option('--cert-org_unit', dest='cert_org_unit', default='DevOps', help='Certificate Distinguished Name Organization Unity.'), make_option('--cert-email', dest='cert_email', default='*****@*****.**', help='Certificate Distinguished Name Email Address.'), make_option('--cert-common_name', dest='cert_common_name', default=None, help='Certificate Distinguished Name Common Name.'), make_option('--server-name', dest='server_name', default='', help='Nginx SSL certificate key.'), make_option('--user', dest='user', default='', help='uWSGI daemon user.'), make_option('--group', dest='group', default='', help='uWSGI daemon group.'), make_option('--processes', dest='processes', default=4, help='uWSGI number of processes.'), make_option('--noinput', action='store_false', dest='interactive', default=True, help='Tells Django to NOT prompt the user for input of any kind. ' 'You must use --username with --noinput, and must contain the ' 'cleeryd process owner, which is the user how will perform tincd updates'), )
def handle(self, *args, **options): context = { 'project_name': paths.get_project_name(), 'site_dir': paths.get_site_dir(), } banner = "%(project_name)s status" % context self.stdout.write(banner) self.stdout.write('-'*len(banner)) self.stdout.write(' Orchestra version: ' + get_version()) if djsettings.DEBUG: self.stdout.write(" debug enabled") else: self.stdout.write(" debug disabled") ps = run('ps aux').stdout.decode().replace('\n', ' ') for service in flatten(settings.ORCHESTRA_START_SERVICES): context['service'] = service if self.is_running(context, ps): self.stdout.write(" %(service)s online" % context) else: self.stdout.write(" %(service)s offline" % context) if service == 'nginx': try: config_path = '/etc/nginx/sites-enabled/%(project_name)s.conf' % context with open(config_path, 'r') as handler: config = handler.read().replace('\n', ' ') except FileNotFoundError: self.stdout.write(" * %s not found" % config_path) else: regex = r'location\s+([^\s]+)\s+{.*uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;.*' % context location = re.findall(regex, config) if location: ip = run("ip a | grep 'inet ' | awk {'print $2'} | grep -v '^127.0.' | head -n 1 | cut -d'/' -f1").stdout.decode() if not ip: ip = '127.0.0.1' location = 'http://%s%s' % (ip, location[0]) self.stdout.write(" * location %s" % location) else: self.stdout.write(" * location not found") elif service == 'postgresql': db_conn = connections['default'] try: c = db_conn.cursor() except OperationalError: self.stdout.write(" * DB connection failed") else: self.stdout.write(" * DB connection succeeded") elif service == 'uwsgi': uwsgi_config = '/etc/uwsgi/apps-enabled/%(project_name)s.ini' % context if os.path.isfile(uwsgi_config): self.stdout.write(" * %s exists" % uwsgi_config) else: self.stdout.write(" * %s does not exist" % uwsgi_config) cronbeat = 'crontab -l | grep "^.*/orchestra-beat %(site_dir)s/manage.py"' % context if run(cronbeat, valid_codes=(0, 1)).exit_code == 0: self.stdout.write(" cronbeat installed") else: self.stdout.write(" cronbeat not installed")
def validate_allowed_domain(value): context = {'site_dir': paths.get_site_dir()} fname = domains.settings.DOMAINS_FORBIDDEN if fname: fname = fname % context with open(fname, 'r') as forbidden: for domain in forbidden.readlines(): if re.match(r'^(.*\.)*%s$' % domain.strip(), value): raise ValidationError(_("This domain name is not allowed"))
def validate_allowed_domain(value): context = { 'site_dir': paths.get_site_dir() } fname = domains.settings.DOMAINS_FORBIDDEN if fname: fname = fname % context with open(fname, 'r') as forbidden: for domain in forbidden.readlines(): if re.match(r'^(.*\.)*%s$' % domain.strip(), value): raise ValidationError(_("This domain name is not allowed"))
def handle(self, *args, **options): version = options.get('version') upgrade_notes = [] if version: version_re = re.compile(r'^\s*(\d+)\.(\d+)\.(\d+).*') minor_release = version_re.search(version) if minor_release is not None: major, major2, minor = version_re.search(version).groups() else: version_re = re.compile(r'^\s*(\d+)\.(\d+).*') major, major2 = version_re.search(version).groups() minor = 0 # Represent version as two digits per number: 1.2.2 -> 10202 version = int( str(major) + "%02d" % int(major2) + "%02d" % int(minor)) # Pre version specific upgrade operations if version < '001': pass if not options.get('specifics_only'): # Common stuff orchestra_admin = os.path.join(os.path.dirname(__file__), '../../bin/') orchestra_admin = os.path.join(orchestra_admin, 'orchestra-admin') run('chmod +x %s' % orchestra_admin) run("%s install_requirements" % orchestra_admin) manage_path = os.path.join(get_site_dir(), 'manage.py') run("python %s collectstatic --noinput" % manage_path) run("python %s migrate --noinput accounts" % manage_path) run("python %s migrate --noinput" % manage_path) if options.get('restart'): run("python %s restartservices" % manage_path) if not version: self.stderr.write( '\n' 'Next time you migth want to provide a --from argument in order ' 'to run version specific upgrade operations\n') return # Post version specific operations if version <= '001': pass if upgrade_notes and options.get('print_upgrade_notes'): self.stdout.write('\n\033[1m\n' ' ===================\n' ' ** UPGRADE NOTES **\n' ' ===================\n\n' + '\n'.join(upgrade_notes) + '\033[m\n')
def handle(self, *args, **options): context = { 'site_dir': get_site_dir(), 'orchestra_beat': run('which orchestra-beat').stdout.decode('utf8'), 'venv': os.environ.get('VIRTUAL_ENV', ''), } content = run('crontab -l || true').stdout.decode('utf8') if 'orchestra-beat' not in content: if context['venv']: content += "\n* * * * * . %(venv)s/bin/activate && %(orchestra_beat)s %(site_dir)s/manage.py; deactivate" % context else: content += "\n* * * * * %(orchestra_beat)s %(site_dir)s/manage.py" % context context['content'] = content run("cat << EOF | crontab\n%(content)s\nEOF" % context, display=True)
def handle(self, *args, **options): version = options.get('version') upgrade_notes = [] if version: version_re = re.compile(r'^\s*(\d+)\.(\d+)\.(\d+).*') minor_release = version_re.search(version) if minor_release is not None: major, major2, minor = version_re.search(version).groups() else: version_re = re.compile(r'^\s*(\d+)\.(\d+).*') major, major2 = version_re.search(version).groups() minor = 0 # Represent version as two digits per number: 1.2.2 -> 10202 version = int(str(major) + "%02d" % int(major2) + "%02d" % int(minor)) # Pre version specific upgrade operations if version < '001': pass if not options.get('specifics_only'): # Common stuff orchestra_admin = os.path.join(os.path.dirname(__file__), '../../bin/') orchestra_admin = os.path.join(orchestra_admin, 'orchestra-admin') run('chmod +x %s' % orchestra_admin) run("%s install_requirements" % orchestra_admin) manage_path = os.path.join(get_site_dir(), 'manage.py') run("python %s collectstatic --noinput" % manage_path) run("python %s migrate --noinput accounts" % manage_path) run("python %s migrate --noinput" % manage_path) if options.get('restart'): run("python %s restartservices" % manage_path) if not version: self.stderr.write('\n' 'Next time you migth want to provide a --from argument in order ' 'to run version specific upgrade operations\n') return # Post version specific operations if version <= '001': pass if upgrade_notes and options.get('print_upgrade_notes'): self.stdout.write('\n\033[1m\n' ' ===================\n' ' ** UPGRADE NOTES **\n' ' ===================\n\n' + '\n'.join(upgrade_notes) + '\033[m\n')
def handle(self, *args, **options): user = options.get('user') if not user: raise CommandError("System user for running uwsgi must be provided.") cert_path, key_path = self.generate_certificate(**options) server_name = options.get('server_name') context = { 'cert_path': cert_path, 'key_path': key_path, 'project_name': paths.get_project_name(), 'project_dir': paths.get_project_dir(), 'site_dir': paths.get_site_dir(), 'static_root': settings.STATIC_ROOT, 'static_url': (settings.STATIC_URL or '/static').rstrip('/'), 'user': user, 'group': options.get('group') or user, 'home': expanduser("~%s" % options.get('user')), 'processes': int(options.get('processes')), 'server_name': 'server_name %s' % server_name if server_name else '' } nginx_conf = textwrap.dedent("""\ server { listen 80; listen [::]:80 ipv6only=on; return 301 https://$host$request_uri; } server { listen 443 ssl; # listen [::]:443 ssl; # add SSL support to IPv6 address %(server_name)s ssl_certificate %(cert_path)s; ssl_certificate_key %(key_path)s; rewrite ^/$ /admin/; client_max_body_size 16m; location / { uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket; include uwsgi_params; } location %(static_url)s { alias %(static_root)s; expires 30d; } } """ ) % context uwsgi_conf = textwrap.dedent("""\ [uwsgi] plugins = python3 chdir = %(site_dir)s module = %(project_name)s.wsgi master = true workers = %(processes)d chmod-socket = 664 stats = /run/uwsgi/%%(deb-confnamespace)/%%(deb-confname)/statsocket uid = %(user)s gid = %(group)s env = HOME=%(home)s touch-reload = %(project_dir)s/wsgi.py vacuum = true # Remove socket stop enable-threads = true # Initializes the GIL max-requests = 500 # Mitigates memory leaks lazy-apps = true # Don't share database connections """ ) % context nginx_file = '/etc/nginx/sites-available/%(project_name)s.conf' % context if server_name: context['server_name'] = server_name nginx_file = '/etc/nginx/sites-available/%(server_name)s.conf' % context nginx = { 'file': nginx_file, 'conf': nginx_conf } uwsgi = { 'file': '/etc/uwsgi/apps-available/%(project_name)s.ini' % context, 'conf': uwsgi_conf } interactive = options.get('interactive') for extra_context in (nginx, uwsgi): context.update(extra_context) diff = run("cat << 'EOF' | diff - %(file)s\n%(conf)s\nEOF" % context, valid_codes=(0,1,2)) if diff.exit_code == 2: # File does not exist run("cat << 'EOF' > %(file)s\n%(conf)s\nEOF" % context, display=True) elif diff.exit_code == 1: # File is different, save the old one if interactive: if not confirm("\n\nFile %(file)s be updated, do you like to overide " "it? (yes/no): " % context): return run(textwrap.dedent("""\ cp %(file)s %(file)s.save cat << 'EOF' > %(file)s %(conf)s EOF""") % context, display=True ) self.stdout.write("\033[1;31mA new version of %(file)s has been installed.\n " "The old version has been placed at %(file)s.save\033[m" % context) if server_name: run('ln -s /etc/nginx/sites-available/%(server_name)s.conf /etc/nginx/sites-enabled/' % context, valid_codes=[0,1], display=True) else: run('rm -f /etc/nginx/sites-enabled/default') run('ln -s /etc/nginx/sites-available/%(project_name)s.conf /etc/nginx/sites-enabled/' % context, valid_codes=[0,1], display=True) run('ln -s /etc/uwsgi/apps-available/%(project_name)s.ini /etc/uwsgi/apps-enabled/' % context, valid_codes=[0,1], display=True) rotate = textwrap.dedent("""\ /var/log/nginx/*.log { daily missingok rotate 30 compress delaycompress notifempty create 640 root adm sharedscripts postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript }""" ) run("echo '%s' > /etc/logrotate.d/nginx" % rotate, display=True) # Allow nginx to write to uwsgi socket run('adduser www-data %(group)s' % context, display=True)
def handle(self, *args, **options): context = { 'site_dir': get_site_dir(), 'username': options.get('username'), 'bin_path': path.join(get_orchestra_dir(), 'bin'), 'processes': options.get('processes'), 'settings': path.join(get_project_dir(), 'settings.py') } celery_config = textwrap.dedent("""\ # Name of nodes to start, here we have a single node CELERYD_NODES="w1" # Where to chdir at start. CELERYD_CHDIR="%(site_dir)s" # How to call "manage.py celeryd_multi" CELERYD_MULTI="python3 $CELERYD_CHDIR/manage.py celeryd_multi" # Extra arguments to celeryd CELERYD_OPTS="-P:w1 processes -c:w1 %(processes)s -Q:w1 celery" # Name of the celery config module. CELERY_CONFIG_MODULE="celeryconfig" # %%n will be replaced with the nodename. CELERYD_LOG_FILE="/var/log/celery/%%n.log" CELERYD_PID_FILE="/var/run/celery/%%n.pid" CELERY_CREATE_DIRS=1 # Full path to the celeryd logfile. CELERYEV_LOG_FILE="/var/log/celery/celeryev.log" CELERYEV_PID_FILE="/var/run/celery/celeryev.pid" # Workers should run as an unprivileged user. CELERYD_USER="******" CELERYD_GROUP="$CELERYD_USER" # Persistent revokes CELERYD_STATE_DB="$CELERYD_CHDIR/persistent_revokes" # Celeryev CELERYEV="python3 $CELERYD_CHDIR/manage.py" CELERYEV_CAM="djcelery.snapshot.Camera" CELERYEV_USER="******" CELERYEV_GROUP="$CELERYD_USER" CELERYEV_OPTS="celerycam" # Celerybeat CELERYBEAT="python3 ${CELERYD_CHDIR}/manage.py celerybeat" CELERYBEAT_USER="******" CELERYBEAT_GROUP="$CELERYD_USER" CELERYBEAT_CHDIR="$CELERYD_CHDIR" CELERYBEAT_OPTS="--schedule=/var/run/celerybeat-schedule --scheduler=djcelery.schedulers.DatabaseScheduler" """ % context) run("echo '%s' > /etc/default/celeryd" % celery_config) # https://raw.github.com/celery/celery/master/extra/generic-init.d/ for script in ['celeryevcam', 'celeryd', 'celerybeat']: context['script'] = script run('cp %(bin_path)s/%(script)s /etc/init.d/%(script)s' % context) run('chmod +x /etc/init.d/%(script)s' % context) run('update-rc.d %(script)s defaults' % context) rotate = textwrap.dedent("""\ /var/log/celery/*.log { weekly missingok rotate 10 compress delaycompress notifempty copytruncate }""") run("echo '%s' > /etc/logrotate.d/celeryd" % rotate) changes = {} if Setting.settings['TASKS_BACKEND'].value != 'celery': changes['TASKS_BACKEND'] = 'celery' if Setting.settings[ 'ORCHESTRA_START_SERVICES'].value == Setting.settings[ 'ORCHESTRA_START_SERVICES'].default: changes['ORCHESTRA_START_SERVICES'] = ( 'postgresql', 'celeryevcam', 'celeryd', 'celerybeat', ('uwsgi', 'nginx'), ) if Setting.settings[ 'ORCHESTRA_RESTART_SERVICES'].value == Setting.settings[ 'ORCHESTRA_RESTART_SERVICES'].default: changes['ORCHESTRA_RESTART_SERVICES'] = ( 'celeryd', 'celerybeat', 'uwsgi', ) if Setting.settings[ 'ORCHESTRA_STOP_SERVICES'].value == Setting.settings[ 'ORCHESTRA_STOP_SERVICES'].default: changes['ORCHESTRA_STOP_SERVICES'] = (('uwsgi', 'nginx'), 'celerybeat', 'celeryd', 'celeryevcam', 'postgresql') if changes: settings_parser.apply(changes)
def handle(self, *args, **options): interactive = options.get('interactive') context = { 'site_dir': get_site_dir(), 'settings_path': os.path.join(get_project_dir(), 'settings.py'), 'project_name': get_project_name(), 'log_dir': os.path.join(get_site_dir(), 'log'), 'log_path': os.path.join(get_site_dir(), 'log', 'orchestra.log') } has_logging = not run( 'grep "^LOGGING\s*=" %(settings_path)s' % context, valid_codes=(0, 1)).exit_code if has_logging: if not interactive: self.stderr.write( "Project settings already defines LOGGING setting, doing nothing." ) return msg = ( "\n\nYour project settings file already defines a LOGGING setting.\n" "Do you want to override it? (yes/no): ") if not confirm(msg): return settings_parser.save({ 'LOGGING': settings_parser.Remove(), }) setuplogrotate = textwrap.dedent("""\ mkdir %(log_dir)s && chown --reference=%(site_dir)s %(log_dir)s touch %(log_path)s chown --reference=%(log_dir)s %(log_path)s echo '%(log_dir)s/*.log { copytruncate daily rotate 5 compress delaycompress missingok notifempty }' > /etc/logrotate.d/orchestra.%(project_name)s cat << 'EOF' >> %(settings_path)s LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'simple': { 'format': '%%(asctime)s %%(name)s %%(levelname)s %%(message)s' }, }, 'handlers': { 'file': { 'class': 'logging.FileHandler', 'filename': '%(log_path)s', 'formatter': 'simple' }, }, 'loggers': { 'orchestra': { 'handlers': ['file'], 'level': 'INFO', 'propagate': True, }, 'orm': { 'handlers': ['file'], 'level': 'INFO', 'propagate': True, }, }, } EOF""") % context run(setuplogrotate, display=True)
def handle(self, *args, **options): context = { 'site_dir': get_site_dir(), 'username': options.get('username'), 'bin_path': path.join(get_orchestra_dir(), 'bin'), 'processes': options.get('processes'), } celery_config = textwrap.dedent("""\ # Name of nodes to start, here we have a single node CELERYD_NODES="w1" # Where to chdir at start. CELERYD_CHDIR="%(site_dir)s" # How to call "manage.py celeryd_multi" CELERYD_MULTI="python3 $CELERYD_CHDIR/manage.py celeryd_multi" # Extra arguments to celeryd CELERYD_OPTS="-P:w1 processes -c:w1 %(processes)s -Q:w1 celery" # Name of the celery config module. CELERY_CONFIG_MODULE="celeryconfig" # %%n will be replaced with the nodename. CELERYD_LOG_FILE="/var/log/celery/%%n.log" CELERYD_PID_FILE="/var/run/celery/%%n.pid" CELERY_CREATE_DIRS=1 # Full path to the celeryd logfile. CELERYEV_LOG_FILE="/var/log/celery/celeryev.log" CELERYEV_PID_FILE="/var/run/celery/celeryev.pid" # Workers should run as an unprivileged user. CELERYD_USER="******" CELERYD_GROUP="$CELERYD_USER" # Persistent revokes CELERYD_STATE_DB="$CELERYD_CHDIR/persistent_revokes" # Celeryev CELERYEV="python3 $CELERYD_CHDIR/manage.py" CELERYEV_CAM="djcelery.snapshot.Camera" CELERYEV_USER="******" CELERYEV_GROUP="$CELERYD_USER" CELERYEV_OPTS="celerycam" # Celerybeat CELERYBEAT="python3 ${CELERYD_CHDIR}/manage.py celerybeat" CELERYBEAT_USER="******" CELERYBEAT_GROUP="$CELERYD_USER" CELERYBEAT_CHDIR="$CELERYD_CHDIR" CELERYBEAT_OPTS="--schedule=/var/run/celerybeat-schedule --scheduler=djcelery.schedulers.DatabaseScheduler" """ % context ) run("echo '%s' > /etc/default/celeryd" % celery_config) # https://raw.github.com/celery/celery/master/extra/generic-init.d/ for script in ['celeryevcam', 'celeryd', 'celerybeat']: context['script'] = script run('cp %(bin_path)s/%(script)s /etc/init.d/%(script)s' % context) run('chmod +x /etc/init.d/%(script)s' % context) run('update-rc.d %(script)s defaults' % context) rotate = textwrap.dedent("""\ /var/log/celery/*.log { weekly missingok rotate 10 compress delaycompress notifempty copytruncate }""" ) run("echo '%s' > /etc/logrotate.d/celeryd" % rotate)
def handle(self, *args, **options): interactive = options.get("interactive") context = { "site_dir": get_site_dir(), "settings_path": os.path.join(get_project_dir(), "settings.py"), "project_name": get_project_name(), "log_dir": os.path.join(get_site_dir(), "log"), "log_path": os.path.join(get_site_dir(), "log", "orchestra.log"), } has_logging = not run('grep "^LOGGING\s*=" %(settings_path)s' % context, valid_codes=(0, 1)).exit_code if has_logging: if not interactive: self.stderr.write("Project settings already defines LOGGING setting, doing nothing.") return msg = ( "\n\nYour project settings file already defines a LOGGING setting.\n" "Do you want to override it? (yes/no): " ) if not confirm(msg): return settings_parser.save({"LOGGING": settings_parser.Remove()}) setuplogrotate = ( textwrap.dedent( """\ mkdir %(log_dir)s && chown --reference=%(site_dir)s %(log_dir)s touch %(log_path)s chown --reference=%(log_dir)s %(log_path)s echo '%(log_dir)s/*.log { copytruncate daily rotate 5 compress delaycompress missingok notifempty }' > /etc/logrotate.d/orchestra.%(project_name)s cat << 'EOF' >> %(settings_path)s LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'simple': { 'format': '%%(asctime)s %%(name)s %%(levelname)s %%(message)s' }, }, 'handlers': { 'file': { 'class': 'logging.FileHandler', 'filename': '%(log_path)s', 'formatter': 'simple' }, }, 'loggers': { 'orchestra': { 'handlers': ['file'], 'level': 'INFO', 'propagate': True, }, 'orm': { 'handlers': ['file'], 'level': 'INFO', 'propagate': True, }, }, } EOF""" ) % context ) run(setuplogrotate, display=True)
def handle(self, *filenames, **options): flake = run('flake8 {%s,%s} | grep -v "W293\|E501"' % (get_orchestra_dir(), get_site_dir())) self.stdout.write(flake.stdout.decode('utf8'))