Exemple #1
0
 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):
     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):
     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)
Exemple #4
0
 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)
Exemple #5
0
 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):
     interactive = options.get('interactive')
     
     context = {
         'project_name': get_project_name(),
         'project_root': get_project_root(),
         'site_root': get_site_root(),
         'static_root': settings.STATIC_ROOT,
         'user': options.get('user'),
         'group': options.get('group') or options.get('user'),
         'home': expanduser("~%s" % options.get('user')),
         'processes': int(options.get('processes')),}
     
     nginx_conf = (
         'server {\n'
         '    listen 80;\n'
         '    listen [::]:80 ipv6only=on;\n'
         '    rewrite ^/$ /admin;\n'
         '    client_max_body_size 500m;\n'
         '    location / {\n'
         '        uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;\n'
         '        include uwsgi_params;\n'
         '    }\n'
         '    location /static {\n'
         '        alias %(static_root)s;\n'
         '        expires 30d;\n'
         '    }\n'
         '}\n') % context
     
     uwsgi_conf = (
         '[uwsgi]\n'
         'plugins      = python\n'
         'chdir        = %(site_root)s\n'
         'module       = %(project_name)s.wsgi\n'
         'master       = true\n'
         'processes    = %(processes)d\n'
         'chmod-socket = 664\n'
         'stats        = /run/uwsgi/%%(deb-confnamespace)/%%(deb-confname)/statsocket\n'
         'vacuum       = true\n'
         'uid          = %(user)s\n'
         'gid          = %(group)s\n'
         'env          = HOME=%(home)s\n') % context
     
     nginx = {
         'file': '/etc/nginx/conf.d/%(project_name)s.conf' % context,
         'conf': nginx_conf }
     uwsgi = {
         'file': '/etc/uwsgi/apps-available/%(project_name)s.ini' % context,
         'conf': uwsgi_conf }
     
     for extra_context in (nginx, uwsgi):
         context.update(extra_context)
         diff = run("echo '%(conf)s'|diff - %(file)s" % context, error_codes=[0,1,2])
         if diff.return_code == 2:
             # File does not exist
             run("echo '%(conf)s' > %(file)s" % context)
         elif diff.return_code == 1:
             # File is different, save the old one
             if interactive:
                 msg = ("\n\nFile %(file)s be updated, do you like to overide "
                        "it? (yes/no): " % context)
                 confirm = input(msg)
                 while 1:
                     if confirm not in ('yes', 'no'):
                         confirm = input('Please enter either "yes" or "no": ')
                         continue
                     if confirm == 'no':
                         return
                     break
             run("cp %(file)s %(file)s.save" % context)
             run("echo '%(conf)s' > %(file)s" % context)
             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)
     
     run('ln -s /etc/uwsgi/apps-available/%(project_name)s.ini /etc/uwsgi/apps-enabled/' % context, error_codes=[0,1])
     
     # nginx should start after tincd
     current = "\$local_fs \$remote_fs \$network \$syslog"
     run('sed -i "s/  %s$/  %s \$named/g" /etc/init.d/nginx' % (current, current))
     
     rotate = (
         '/var/log/nginx/*.log {\n'
         '    daily\n'
         '    missingok\n'
         '    rotate 30\n'
         '    compress\n'
         '    delaycompress\n'
         '    notifempty\n'
         '    create 640 root adm\n'
         '    sharedscripts\n'
         '    postrotate\n'
         '        [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`\n'
         '    endscript\n'
         '}\n')
     run("echo '%s' > /etc/logrotate.d/nginx" % rotate)
     
     # Allow nginx to write to uwsgi socket
     run('adduser www-data %(group)s' % context)