#!/usr/bin/env python # -*- coding: utf-8 -*- """ openslides.main ~~~~~~~~~~~~~~~ Main script to start and set up OpenSlides. :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. :license: GNU GPL, see LICENSE for more details. """ # for python 2.5 support from __future__ import with_statement import os import sys import optparse import socket import time import threading import webbrowser from contextlib import nested import django.conf from django.core.management import execute_from_command_line from django.utils.crypto import get_random_string import openslides def main(argv = None): if argv is None: argv = sys.argv[1:] parser = optparse.OptionParser(description = "Run openslides using " "django's builtin webserver") parser.add_option("-a", "--address", help = "IP Address to listen on") parser.add_option("-p", "--port", type = "int", help = "Port to listen on") parser.add_option("--nothread", action = "store_true", help = "Do not use threading") parser.add_option("--syncdb", action = "store_true", help = "Update/create database before starting the server") parser.add_option("--reset-admin", action = "store_true", help = "Make sure the user 'admin' exists and uses 'admin' as password") opts, args = parser.parse_args(argv) if args: sys.stderr.write("This command does not take arguments!\n\n") parser.print_help() sys.exit(1) addr, port = detect_listen_opts(opts.address, opts.port) if port == 80: url = "http://%s" % (addr, ) else: url = "http://%s:%d" % (addr, port) if not prepare_openslides(url, opts.syncdb): sys.exit(1) if opts.reset_admin: create_or_reset_admin_user() # NOTE: --insecure is needed so static files will be served if # DEBUG is set to False argv = ["", "runserver", "--noreload", "--insecure"] if opts.nothread: argv.append("--nothread") argv.append("%s:%d" % (addr, port)) start_browser(url) execute_from_command_line(argv) def detect_listen_opts(address, port): if address is None: try: address = socket.gethostbyname(socket.gethostname()) except socket.error: address = "127.0.0.1" if port is None: # test if we can use port 80 s = socket.socket() port = 80 try: s.bind((address, port)) s.listen(-1) except socket.error: port = 8000 finally: s.close() return address, port def start_browser(url): browser = webbrowser.get() def f(): time.sleep(1) browser.open(url) t = threading.Thread(target = f) t.start() def prepare_openslides(url, always_syncdb = False): settings_module = os.environ.get(django.conf.ENVIRONMENT_VARIABLE) if not settings_module: os.environ[django.conf.ENVIRONMENT_VARIABLE] = "openslides.settings" settings_module = "openslides.settings" try: # settings is a lazy object, force the settings module # to be imported getattr(django.conf.settings, "DATABASES", None) except ImportError: pass else: if not check_database(url) and always_syncdb: run_syncdb(url) return True # import worked, settings are already configured if settings_module != "openslides.settings": sys.stderr.write("Settings module '%s' cannot be imported.\n" % (django.conf.ENVIRONMENT_VARIABLE, )) return False openslides_dir = os.path.dirname(openslides.__file__) src_fp = os.path.join(openslides_dir, "default.settings.py") dest_fp = os.path.join(openslides_dir, "settings.py") with nested(open(dest_fp, "w"), open(src_fp, "r")) as (dest, src): for l in src: if l.startswith("SECRET_KEY ="): l = "SECRET_KEY = '%s'\n" % (generate_secret_key(), ) dest.write(l) run_syncdb(url) create_or_reset_admin_user() return True def run_syncdb(url): # now initialize the database argv = ["", "syncdb", "--noinput"] execute_from_command_line(argv) set_system_url(url) def check_database(url): """Detect if database was deleted and recreate if necessary""" # can't be imported in global scope as they already require # the settings module during import from django.db import DatabaseError from django.contrib.auth.models import User try: User.objects.count() except DatabaseError: run_syncdb(url) create_or_reset_admin_user() return True return False def create_or_reset_admin_user(): # can't be imported in global scope as it already requires # the settings module during import from django.contrib.auth.models import User from openslides.config.models import config try: obj = User.objects.get(username = "admin") except User.DoesNotExist: User.objects.create_superuser( username="admin", password="admin", email="admin@example.com") config['admin_password'] = "admin" print("Created default admin user") return print("Password for user admin was reset to 'admin'") obj.set_password("admin") obj.save() def set_system_url(url): # can't be imported in global scope as it already requires # the settings module during import from openslides.config.models import config key = "participant_pdf_system_url" if key in config: return config[key] = url def generate_secret_key(): # same chars/ length as used in djangos startproject command chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)" return get_random_string(50, chars) if __name__ == "__main__": main()