Пример #1
0
    def handle(self, *args, **options):
        if not options["interactive"]:
            options["username"] = options["username"] or getattr(settings, "INSTALL_ADMIN_USERNAME", None) or get_clean_default_username()
            options["hostname"] = options["hostname"] or get_host_name()

        sys.stdout.write("                                  \n")  # blank allows ansible scripts to dump errors cleanly.
        sys.stdout.write("  _   __  ___    _     _ _        \n")
        sys.stdout.write(" | | / / / _ \  | |   (_) |       \n")
        sys.stdout.write(" | |/ / / /_\ \ | |    _| |_ ___  \n")
        sys.stdout.write(" |    \ |  _  | | |   | | __/ _ \ \n")
        sys.stdout.write(" | |\  \| | | | | |___| | ||  __/ \n")
        sys.stdout.write(" \_| \_/\_| |_/ \_____/_|\__\___| \n")
        sys.stdout.write("                                  \n")
        sys.stdout.write("http://kalite.learningequality.org\n")
        sys.stdout.write("                                  \n")
        sys.stdout.write("         version %s\n" % VERSION)
        sys.stdout.write("                                  \n")

        if sys.version_info >= (2,8) or sys.version_info < (2,6):
            raise CommandError("You must have Python version 2.6.x or 2.7.x installed. Your version is: %s\n" % sys.version_info)

        if options["interactive"]:
            sys.stdout.write("--------------------------------------------------------------------------------\n")
            sys.stdout.write("\n")
            sys.stdout.write("This script will configure the database and prepare it for use.\n")
            sys.stdout.write("\n")
            sys.stdout.write("--------------------------------------------------------------------------------\n")
            sys.stdout.write("\n")
            raw_input("Press [enter] to continue...")
            sys.stdout.write("\n")

        # Tried not to be os-specific, but ... hey. :-/
        if not is_windows() and hasattr(os, "getuid") and os.getuid() == 502:
            sys.stdout.write("-------------------------------------------------------------------\n")
            sys.stdout.write("WARNING: You are installing KA-Lite as root user!\n")
            sys.stdout.write("\tInstalling as root may cause some permission problems while running\n")
            sys.stdout.write("\tas a normal user in the future.\n")
            sys.stdout.write("-------------------------------------------------------------------\n")
            if options["interactive"]:
                if not raw_input_yn("Do you wish to continue and install it as root?"):
                    raise CommandError("Aborting script.\n")
                sys.stdout.write("\n")

        # Check to see if the current user is the owner of the install directory
        if not os.access(BASE_DIR, os.W_OK):
            raise CommandError("You do not have permission to write to this directory!")

        install_clean = not kalite.is_installed()
        database_kind = settings.DATABASES["default"]["ENGINE"]
        database_file = ("sqlite" in database_kind and settings.DATABASES["default"]["NAME"]) or None

        if database_file and os.path.exists(database_file):
            # We found an existing database file.  By default,
            #   we will upgrade it; users really need to work hard
            #   to delete the file (but it's possible, which is nice).
            sys.stdout.write("-------------------------------------------------------------------\n")
            sys.stdout.write("WARNING: Database file already exists! \n")
            sys.stdout.write("-------------------------------------------------------------------\n")
            if not options["interactive"] \
               or raw_input_yn("Keep database file and upgrade to KA Lite version %s? " % VERSION) \
               or not raw_input_yn("Remove database file '%s' now? " % database_file) \
               or not raw_input_yn("WARNING: all data will be lost!  Are you sure? "):
                install_clean = False
                sys.stdout.write("Upgrading database to KA Lite version %s\n" % VERSION)
            else:
                install_clean = True
                sys.stdout.write("OK.  We will run a clean install; \n")
                sys.stdout.write("the database file will be moved to a deletable location.\n")  # After all, don't delete--just move.

        if not install_clean and not database_file and not kalite.is_installed():
            # Make sure that, for non-sqlite installs, the database exists.
            raise Exception("For databases not using SQLIte, you must set up your database before running setup.")

        # Do all input at once, at the beginning
        if install_clean and options["interactive"]:
            if not options["username"] or not options["password"]:
                sys.stdout.write("\n")
                sys.stdout.write("Please choose a username and password for the admin account on this device.\n")
                sys.stdout.write("\tYou must remember this login information, as you will need\n")
                sys.stdout.write("\tto enter it to administer this installation of KA Lite.\n")
                sys.stdout.write("\n")
            (username, password) = get_username_password(options["username"], options["password"])
            email = options["email"]
            (hostname, description) = get_hostname_and_description(options["hostname"], options["description"])
        else:
            username = options["username"] or getattr(settings, "INSTALL_ADMIN_USERNAME", None)
            password = options["password"] or getattr(settings, "INSTALL_ADMIN_PASSWORD", None)
            email = options["email"]  # default is non-empty
            hostname = options["hostname"]
            description = options["description"]

        if username and not validate_username(username):
            raise CommandError("Username must contain only letters, digits, and underscores, and start with a letter.\n")


        ########################
        # Now do stuff
        ########################

        # Move database file (if exists)
        if install_clean and database_file and os.path.exists(database_file):
            # This is an overwrite install; destroy the old db
            dest_file = tempfile.mkstemp()[1]
            sys.stdout.write("(Re)moving database file to temp location, starting clean install.  Recovery location: %s\n" % dest_file)
            shutil.move(database_file, dest_file)

        # Should clean_pyc for (clean) reinstall purposes
        call_command("clean_pyc", interactive=False, verbosity=options.get("verbosity"), path=os.path.join(settings.PROJECT_PATH, ".."))

        # Migrate the database
        call_command("syncdb", interactive=False, verbosity=options.get("verbosity"))
        call_command("migrate", merge=True, verbosity=options.get("verbosity"))

        # Install data
        if install_clean:
            # Create device, load on any zone data
            call_command("generatekeys", verbosity=options.get("verbosity"))
            call_command("initdevice", hostname, description, verbosity=options.get("verbosity"))
            Facility.initialize_default_facility()

        #else:
            # Device exists; load data if required.
            #
            # Hackish, as this duplicates code from initdevice.
            #
            #if os.path.exists(InitCommand.data_json_file):
            #    # This is a pathway to install zone-based data on a software upgrade.
            #    sys.stdout.write("Loading zone data from '%s'\n" % InitCommand.data_json_file)
            #    load_data_for_offline_install(in_file=InitCommand.data_json_file)

        #    confirm_or_generate_zone()

        # Create the admin user
        if password:  # blank password (non-interactive) means don't create a superuser
            admin = get_object_or_None(User, username=username)
            if not admin:
                call_command("createsuperuser", username=username, email=email, interactive=False, verbosity=options.get("verbosity"))
                admin = User.objects.get(username=username)
            admin.set_password(password)
            admin.save()

        # Now deploy the static files
        call_command("collectstatic", interactive=False)

        if not settings.CENTRAL_SERVER:
            # Move scripts
            for script_name in ["start", "stop", "run_command"]:
                script_file = script_name + system_script_extension()
                dest_dir = os.path.join(settings.PROJECT_PATH, "..")
                src_dir = os.path.join(dest_dir, "scripts")
                shutil.copyfile(os.path.join(src_dir, script_file), os.path.join(dest_dir, script_file))
                shutil.copystat(os.path.join(src_dir, script_file), os.path.join(dest_dir, script_file))

            start_script_path = os.path.realpath(os.path.join(settings.PROJECT_PATH, "..", "start%s" % system_script_extension()))

            # Run videoscan, on the distributed server.
            sys.stdout.write("Scanning for video files in the content directory (%s)\n" % settings.CONTENT_ROOT)
            call_command("videoscan")

            # done; notify the user.
            sys.stdout.write("\n")
            if install_clean:
                sys.stdout.write("CONGRATULATIONS! You've finished setting up the KA Lite server software.\n")
                sys.stdout.write("\tPlease run '%s' to start the server,\n" % start_script_path)
                sys.stdout.write("\tthen load one of the following addresses in your browser to complete the configuration:\n")
                for ip in get_ip_addresses():
                    sys.stdout.write("\t\thttp://%s:%d/\n" % (ip, settings.USER_FACING_PORT()))

            else:
                sys.stdout.write("CONGRATULATIONS! You've finished updating the KA Lite server software.\n")
                sys.stdout.write("\tPlease run '%s' to start the server.\n" % start_script_path)
            sys.stdout.write("\n")
Пример #2
0
    def handle(self, *args, **options):
        if not options["interactive"]:
            options["hostname"] = options["hostname"] or get_host_name()

        # blank allows ansible scripts to dump errors cleanly.
        print("                                  ")
        print("  _   __  ___    _     _ _        ")
        print(" | | / / / _ \  | |   (_) |       ")
        print(" | |/ / / /_\ \ | |    _| |_ ___  ")
        print(" |    \ |  _  | | |   | | __/ _ \ ")
        print(" | |\  \| | | | | |___| | ||  __/ ")
        print(" \_| \_/\_| |_/ \_____/_|\__\___| ")
        print("                                  ")
        print("http://kalite.learningequality.org")
        print("                                  ")
        print("         version %s" % VERSION)
        print("                                  ")

        if sys.version_info >= (2, 8) or sys.version_info < (2, 6):
            raise CommandError(
                "You must have Python version 2.6.x or 2.7.x installed. Your version is: %s\n" % str(sys.version_info))
        if sys.version_info < (2, 7, 9):
            logging.warning(
                "It's recommended that you install Python version 2.7.9. Your version is: %s\n" % str(sys.version_info))

        if options["interactive"]:
            print(
                "--------------------------------------------------------------------------------")
            print(
                "This script will configure the database and prepare it for use.")
            print(
                "--------------------------------------------------------------------------------")
            raw_input("Press [enter] to continue...")

        # Tried not to be os-specific, but ... hey. :-/
        # benjaoming: This doesn't work, why is 502 hard coded!? Root is normally
        # '0' And let's not care about stuff like this, people can be free to
        # run this as root if they want :)
        if not is_windows() and hasattr(os, "getuid") and os.getuid() == 502:
            print(
                "-------------------------------------------------------------------")
            print("WARNING: You are installing KA-Lite as root user!")
            print(
                "\tInstalling as root may cause some permission problems while running")
            print("\tas a normal user in the future.")
            print(
                "-------------------------------------------------------------------")
            if options["interactive"]:
                if not raw_input_yn("Do you wish to continue and install it as root?"):
                    raise CommandError("Aborting script.\n")

        git_migrate_path = options["git_migrate_path"]

        if git_migrate_path:
            call_command("gitmigrate", path=git_migrate_path)
        
        # TODO(benjaoming): This is used very loosely, what does it mean?
        # Does it mean that the installation path is clean or does it mean
        # that we should remove (clean) items from a previous installation?
        install_clean = not kalite.is_installed()
        
        database_kind = settings.DATABASES["default"]["ENGINE"]
        database_file = (
            "sqlite" in database_kind and settings.DATABASES["default"]["NAME"]) or None

        if database_file and os.path.exists(database_file):
            # We found an existing database file.  By default,
            #   we will upgrade it; users really need to work hard
            #   to delete the file (but it's possible, which is nice).
            print(
                "-------------------------------------------------------------------")
            print("WARNING: Database file already exists!")
            print(
                "-------------------------------------------------------------------")
            if not options["interactive"] \
               or raw_input_yn("Keep database file and upgrade to KA Lite version %s? " % VERSION) \
               or not raw_input_yn("Remove database file '%s' now? " % database_file) \
               or not raw_input_yn("WARNING: all data will be lost!  Are you sure? "):
                install_clean = False
                print("Upgrading database to KA Lite version %s" % VERSION)
            else:
                install_clean = True
                print("OK.  We will run a clean install; ")
                # After all, don't delete--just move.
                print(
                    "the database file will be moved to a deletable location.")

        if not install_clean and not database_file and not kalite.is_installed():
            # Make sure that, for non-sqlite installs, the database exists.
            raise Exception(
                "For databases not using SQLite, you must set up your database before running setup.")

        # Do all input at once, at the beginning
        if install_clean and options["interactive"]:
            if not options["username"] or not options["password"]:
                print(
                    "Please choose a username and password for the admin account on this device.")
                print(
                    "\tYou must remember this login information, as you will need")
                print(
                    "\tto enter it to administer this installation of KA Lite.")
            (username, password) = get_username_password(
                options["username"], options["password"])
            email = options["email"]
            (hostname, description) = get_hostname_and_description(
                options["hostname"], options["description"])
        else:
            username = options["username"] = options["username"] or \
                                             getattr(settings, "INSTALL_ADMIN_USERNAME", None) or \
                                             get_clean_default_username()
            password = options["password"] or getattr(settings, "INSTALL_ADMIN_PASSWORD", None)
            email = options["email"]  # default is non-empty
            hostname = options["hostname"]
            description = options["description"]

        if username and not validate_username(username):
            raise CommandError(
                "Username must contain only letters, digits, and underscores, and start with a letter.\n")

        ########################
        # Now do stuff
        ########################

        # Clean *pyc files if we are in a git repo
        if settings.IS_SOURCE:
            clean_pyc(settings.SOURCE_DIR)
        else:
            # Because we install dependencies as data_files, we run into problems,
            # namely that the pyc files are left dangling.
            distributed_packages = [
                os.path.join(kalite.ROOT_DATA_PATH, 'dist-packages'),
                os.path.join(kalite.ROOT_DATA_PATH, 'python-packages'),
            ]
            # Try locating django
            for dir_to_clean in distributed_packages:
                clean_pyc(dir_to_clean)
            
        # Move database file (if exists)
        if install_clean and database_file and os.path.exists(database_file):
            # This is an overwrite install; destroy the old db
            dest_file = tempfile.mkstemp()[1]
            print(
                "(Re)moving database file to temp location, starting clean install. Recovery location: %s" % dest_file)
            shutil.move(database_file, dest_file)

        # benjaoming: Commented out, this hits the wrong directories currently
        # and should not be necessary.
        # If we have problems with pyc files, we're doing something else wrong.
        # See https://github.com/learningequality/ka-lite/issues/3487

        # Should clean_pyc for (clean) reinstall purposes
        # call_command("clean_pyc", interactive=False, verbosity=options.get("verbosity"), path=os.path.join(settings.PROJECT_PATH, ".."))

        # Migrate the database
        call_command(
            "syncdb", interactive=False, verbosity=options.get("verbosity"))
        call_command("migrate", merge=True, verbosity=options.get("verbosity"))
        # Create *.json and friends database
        call_command("syncdb", interactive=False, verbosity=options.get(
            "verbosity"), database="assessment_items")

        # download assessment items
        # This can take a long time and lead to Travis stalling. None of this
        # is required for tests.

        # Outdated location of assessment items
        # TODO(benjaoming) for 0.15, remove this
        writable_assessment_items = os.access(
            settings.KHAN_ASSESSMENT_ITEM_ROOT, os.W_OK)

        def _move_to_new_location(old, new):
            if not writable_assessment_items:
                return
            if os.path.exists(old):
                if os.access(settings.KHAN_CONTENT_PATH, os.W_OK):
                    os.rename(old, new)
        _move_to_new_location(
            os.path.join(settings.KHAN_CONTENT_PATH, 'assessmentitems.sqlite'),
            settings.KHAN_ASSESSMENT_ITEM_DATABASE_PATH
        )
        _move_to_new_location(
            os.path.join(
                settings.KHAN_CONTENT_PATH, 'assessmentitems.version'),
            settings.KHAN_ASSESSMENT_ITEM_VERSION_PATH
        )
        _move_to_new_location(
            os.path.join(
                settings.USER_DATA_ROOT, "data", "khan", "assessmentitems.json"),
            settings.KHAN_ASSESSMENT_ITEM_JSON_PATH
        )
        if writable_assessment_items and options['force-assessment-item-dl']:
            call_command(
                "unpack_assessment_zip", settings.ASSESSMENT_ITEMS_ZIP_URL)
        elif options['force-assessment-item-dl']:
            raise RuntimeError(
                "Got force-assessment-item-dl but directory not writable")
        elif writable_assessment_items and not settings.RUNNING_IN_TRAVIS and options['interactive']:
            print(
                "\nStarting in version 0.13, you will need an assessment items package in order to access many of the available exercises.")
            print(
                "If you have an internet connection, you can download the needed package. Warning: this may take a long time!")
            print(
                "If you have already downloaded the assessment items package, you can specify the file in the next step.")
            print("Otherwise, we will download it from {url}.".format(
                url=settings.ASSESSMENT_ITEMS_ZIP_URL))

            if raw_input_yn("Do you wish to download the assessment items package now?"):
                ass_item_filename = settings.ASSESSMENT_ITEMS_ZIP_URL
            elif raw_input_yn("Have you already downloaded the assessment items package?"):
                ass_item_filename = get_assessment_items_filename()
            else:
                ass_item_filename = None

            if not ass_item_filename:
                logging.warning(
                    "No assessment items package file given. You will need to download and unpack it later.")
            else:
                call_command("unpack_assessment_zip", ass_item_filename)
        elif options['interactive']:
            logging.warning(
                "Assessment item directory not writable, skipping download.")
        else:
            logging.warning(
                "No assessment items package file given. You will need to download and unpack it later.")

        # Individually generate any prerequisite models/state that is missing
        if not Settings.get("private_key"):
            call_command("generatekeys", verbosity=options.get("verbosity"))
        if not Device.objects.count():
            call_command(
                "initdevice", hostname, description, verbosity=options.get("verbosity"))
        if not Facility.objects.count():
            Facility.initialize_default_facility()

        # Create the admin user
        # blank password (non-interactive) means don't create a superuser
        if password:
            admin = get_object_or_None(User, username=username)
            if not admin:
                call_command("createsuperuser", username=username, email=email,
                             interactive=False, verbosity=options.get("verbosity"))
                admin = User.objects.get(username=username)
            admin.set_password(password)
            admin.save()

        # Now deploy the static files
        logging.info("Copying static media...")
        call_command("collectstatic", interactive=False, verbosity=0)

        # This is not possible in a distributed env
        if not settings.CENTRAL_SERVER:

            kalite_executable = 'kalite'
            if not spawn.find_executable('kalite'):
                if os.name == 'posix':
                    start_script_path = os.path.realpath(
                        os.path.join(settings.PROJECT_PATH, "..", "bin", kalite_executable))
                else:
                    start_script_path = os.path.realpath(
                        os.path.join(settings.PROJECT_PATH, "..", "bin", "windows", "kalite.bat"))
            else:
                start_script_path = kalite_executable

            # Run videoscan, on the distributed server.
            print("Scanning for video files in the content directory (%s)" %
                  settings.CONTENT_ROOT)
            call_command("videoscan")

            # done; notify the user.
            print(
                "CONGRATULATIONS! You've finished setting up the KA Lite server software.")
            print(
                "You can now start KA Lite with the following command:\n\n\t%s start\n\n" % start_script_path)
Пример #3
0
    def handle(self, *args, **options):
        if not options["interactive"]:
            options["hostname"] = options["hostname"] or get_host_name()

        # blank allows ansible scripts to dump errors cleanly.
        print("                                     ")
        print("   _   __  ___    _     _ _          ")
        print("  | | / / / _ \  | |   (_) |         ")
        print("  | |/ / / /_\ \ | |    _| |_ ___    ")
        print("  |    \ |  _  | | |   | | __/ _ \   ")
        print("  | |\  \| | | | | |___| | ||  __/   ")
        print("  \_| \_/\_| |_/ \_____/_|\__\___|   ")
        print("                                     ")
        print("https://learningequality.org/ka-lite/")
        print("                                     ")
        print("         version %s" % VERSION)
        print("                                     ")

        if sys.version_info >= (2, 8) or sys.version_info < (2, 6):
            raise CommandError(
                "You must have Python version 2.6.x or 2.7.x installed. Your version is: %d.%d.%d\n"
                % sys.version_info[:3])
        if sys.version_info < (2, 7, 9):
            logging.warning(
                "It's recommended that you install Python version 2.7.9. Your version is: %d.%d.%d\n"
                % sys.version_info[:3])
            if sys.version_info < (2, 7):
                warnings.warn(
                    "Support for Python 2.6 will be discontinued in 0.16, please upgrade.",
                    RemovedInKALite_v016_Warning)

        if options["interactive"]:
            print(
                "--------------------------------------------------------------------------------"
            )
            print(
                "This script will configure the database and prepare it for use."
            )
            print(
                "--------------------------------------------------------------------------------"
            )
            raw_input("Press [enter] to continue...")

        # Tried not to be os-specific, but ... hey. :-/
        # benjaoming: This doesn't work, why is 502 hard coded!? Root is normally
        # '0' And let's not care about stuff like this, people can be free to
        # run this as root if they want :)
        if not is_windows() and hasattr(os, "getuid") and os.getuid() == 502:
            print(
                "-------------------------------------------------------------------"
            )
            print("WARNING: You are installing KA-Lite as root user!")
            print(
                "\tInstalling as root may cause some permission problems while running"
            )
            print("\tas a normal user in the future.")
            print(
                "-------------------------------------------------------------------"
            )
            if options["interactive"]:
                if not raw_input_yn(
                        "Do you wish to continue and install it as root?"):
                    raise CommandError("Aborting script.\n")

        git_migrate_path = options["git_migrate_path"]

        if git_migrate_path:
            call_command("gitmigrate",
                         path=git_migrate_path,
                         interactive=options["interactive"])

        # TODO(benjaoming): This is used very loosely, what does it mean?
        # Does it mean that the installation path is clean or does it mean
        # that we should remove (clean) items from a previous installation?
        install_clean = not kalite.is_installed()

        database_kind = settings.DATABASES["default"]["ENGINE"]
        database_file = ("sqlite" in database_kind
                         and settings.DATABASES["default"]["NAME"]) or None

        if database_file and os.path.exists(database_file):
            # We found an existing database file.  By default,
            #   we will upgrade it; users really need to work hard
            #   to delete the file (but it's possible, which is nice).
            print(
                "-------------------------------------------------------------------"
            )
            print("WARNING: Database file already exists!")
            print(
                "-------------------------------------------------------------------"
            )
            if not options["interactive"] \
               or raw_input_yn("Keep database file and upgrade to KA Lite version %s? " % VERSION) \
               or not raw_input_yn("Remove database file '%s' now? " % database_file) \
               or not raw_input_yn("WARNING: all data will be lost!  Are you sure? "):
                install_clean = False
                print("Upgrading database to KA Lite version %s" % VERSION)
            else:
                install_clean = True
                print("OK.  We will run a clean install; ")
                # After all, don't delete--just move.
                print(
                    "the database file will be moved to a deletable location.")

        if not install_clean and not database_file and not kalite.is_installed(
        ):
            # Make sure that, for non-sqlite installs, the database exists.
            raise Exception(
                "For databases not using SQLite, you must set up your database before running setup."
            )

        # Do all input at once, at the beginning
        if install_clean and options["interactive"]:
            if not options["username"] or not options["password"]:
                print(
                    "Please choose a username and password for the admin account on this device."
                )
                print(
                    "\tYou must remember this login information, as you will need"
                )
                print(
                    "\tto enter it to administer this installation of KA Lite."
                )
            (username,
             password) = get_username_password(options["username"],
                                               options["password"])
            email = options["email"]
            (hostname, description) = get_hostname_and_description(
                options["hostname"], options["description"])
        else:
            username = options["username"] = (options["username"] or getattr(
                settings, "INSTALL_ADMIN_USERNAME", None)
                                              or get_clean_default_username())
            password = options["password"] or getattr(
                settings, "INSTALL_ADMIN_PASSWORD", None)
            email = options["email"]  # default is non-empty
            hostname = options["hostname"]
            description = options["description"]

        if username and not validate_username(username):
            raise CommandError(
                "Username must contain only letters, digits, and underscores, and start with a letter.\n"
            )

        ########################
        # Now do stuff
        ########################

        # Clean *pyc files if we are in a git repo
        if settings.IS_SOURCE:
            clean_pyc(settings.SOURCE_DIR)
        else:
            # Because we install dependencies as data_files, we run into problems,
            # namely that the pyc files are left dangling.
            distributed_packages = [
                os.path.join(kalite.ROOT_DATA_PATH, 'dist-packages'),
                os.path.join(kalite.ROOT_DATA_PATH, 'python-packages'),
            ]
            # Try locating django
            for dir_to_clean in distributed_packages:
                clean_pyc(dir_to_clean)

        # Move database file (if exists)
        if install_clean and database_file and os.path.exists(database_file):
            # This is an overwrite install; destroy the old db
            dest_file = tempfile.mkstemp()[1]
            print(
                "(Re)moving database file to temp location, starting clean install. Recovery location: %s"
                % dest_file)
            shutil.move(database_file, dest_file)

        # benjaoming: Commented out, this hits the wrong directories currently
        # and should not be necessary.
        # If we have problems with pyc files, we're doing something else wrong.
        # See https://github.com/learningequality/ka-lite/issues/3487

        # Should clean_pyc for (clean) reinstall purposes
        # call_command("clean_pyc", interactive=False, verbosity=options.get("verbosity"), path=os.path.join(settings.PROJECT_PATH, ".."))

        # Migrate the database
        call_command("syncdb",
                     interactive=False,
                     verbosity=options.get("verbosity"))
        call_command("migrate", merge=True, verbosity=options.get("verbosity"))
        Settings.set("database_version", VERSION)

        # download assessment items
        # This can take a long time and lead to Travis stalling. None of this
        # is required for tests, and does not apply to the central server.
        if options.get("no-assessment-items", False):

            logging.warning(
                "Skipping assessment item downloading and configuration.")

        else:

            call_command("syncdb",
                         interactive=False,
                         verbosity=options.get("verbosity"),
                         database="assessment_items")

            # Outdated location of assessment items - move assessment items from their
            # old location (CONTENT_ROOT/khan where they were mixed with other content
            # items)

            # TODO(benjaoming) for 0.15, remove the "move assessment items"
            # mechanism
            writable_assessment_items = os.access(KHAN_ASSESSMENT_ITEM_ROOT,
                                                  os.W_OK)

            # Remove old assessment items
            if os.path.exists(OLD_ASSESSMENT_ITEMS_LOCATION) and os.access(
                    OLD_ASSESSMENT_ITEMS_LOCATION, os.W_OK):
                logging.info("Deleting old assessment items")
                shutil.rmtree(OLD_ASSESSMENT_ITEMS_LOCATION)

            if writable_assessment_items and options[
                    'force-assessment-item-dl']:
                call_command("unpack_assessment_zip", ASSESSMENT_ITEMS_ZIP_URL)
            elif options['force-assessment-item-dl']:
                raise RuntimeError(
                    "Got force-assessment-item-dl but directory not writable")
            elif not settings.ASSESSMENT_ITEMS_SYSTEM_WIDE and not settings.RUNNING_IN_TRAVIS and options[
                    'interactive']:
                print(
                    "\nStarting in version 0.13, you will need an assessment items package in order to access many of the available exercises."
                )
                print(
                    "If you have an internet connection, you can download the needed package. Warning: this may take a long time!"
                )
                print(
                    "If you have already downloaded the assessment items package, you can specify the file in the next step."
                )
                print("Otherwise, we will download it from {url}.".format(
                    url=ASSESSMENT_ITEMS_ZIP_URL))

                if raw_input_yn(
                        "Do you wish to download the assessment items package now?"
                ):
                    ass_item_filename = ASSESSMENT_ITEMS_ZIP_URL
                elif raw_input_yn(
                        "Have you already downloaded the assessment items package?"
                ):
                    ass_item_filename = get_assessment_items_filename()
                else:
                    ass_item_filename = None

                if not ass_item_filename:
                    logging.warning(
                        "No assessment items package file given. You will need to download and unpack it later."
                    )
                else:
                    call_command("unpack_assessment_zip", ass_item_filename)

            elif options[
                    'interactive'] and not settings.ASSESSMENT_ITEMS_SYSTEM_WIDE:
                logging.warning(
                    "Assessment item directory not writable, skipping download."
                )
            elif not settings.ASSESSMENT_ITEMS_SYSTEM_WIDE:
                logging.warning(
                    "No assessment items package file given. You will need to download and unpack it later."
                )
            else:
                print("Found bundled assessment items")

        # Individually generate any prerequisite models/state that is missing
        if not Settings.get("private_key"):
            call_command("generatekeys", verbosity=options.get("verbosity"))
        if not Device.objects.count():
            call_command("initdevice",
                         hostname,
                         description,
                         verbosity=options.get("verbosity"))
        if not Facility.objects.count():
            Facility.initialize_default_facility()

        # Create the admin user
        # blank password (non-interactive) means don't create a superuser
        if password:
            admin = get_object_or_None(User, username=username)
            if not admin:
                call_command("createsuperuser",
                             username=username,
                             email=email,
                             interactive=False,
                             verbosity=options.get("verbosity"))
                admin = User.objects.get(username=username)
            admin.set_password(password)
            admin.save()

        # Now deploy the static files
        logging.info("Copying static media...")
        call_command("collectstatic", interactive=False, verbosity=0)
        call_command("collectstatic_js_reverse", interactive=False)

        # This is not possible in a distributed env
        if not settings.CENTRAL_SERVER:

            kalite_executable = 'kalite'
            if not spawn.find_executable('kalite'):
                if os.name == 'posix':
                    start_script_path = os.path.realpath(
                        os.path.join(settings.PROJECT_PATH, "..", "bin",
                                     kalite_executable))
                else:
                    start_script_path = os.path.realpath(
                        os.path.join(settings.PROJECT_PATH, "..", "bin",
                                     "windows", "kalite.bat"))
            else:
                start_script_path = kalite_executable

            # Run videoscan, on the distributed server.
            print("Scanning for video files in the content directory (%s)" %
                  settings.CONTENT_ROOT)
            call_command("videoscan")

            # done; notify the user.
            print(
                "\nCONGRATULATIONS! You've finished setting up the KA Lite server software."
            )
            print(
                "You can now start KA Lite with the following command:\n\n\t%s start\n\n"
                % start_script_path)

            if options['interactive']:
                if raw_input_yn("Do you wish to start the server now?"):
                    print("Running {0} start".format(start_script_path))
                    p = subprocess.Popen([start_script_path, "start"],
                                         env=os.environ)
                    p.wait()
Пример #4
0
    def handle(self, *args, **options):
        if not options["interactive"]:
            options["username"] = options["username"] or getattr(settings, "INSTALL_ADMIN_USERNAME", None) or get_clean_default_username()
            options["hostname"] = options["hostname"] or get_host_name()

        print("                                  ")  # blank allows ansible scripts to dump errors cleanly.
        print("  _   __  ___    _     _ _        ")
        print(" | | / / / _ \  | |   (_) |       ")
        print(" | |/ / / /_\ \ | |    _| |_ ___  ")
        print(" |    \ |  _  | | |   | | __/ _ \ ")
        print(" | |\  \| | | | | |___| | ||  __/ ")
        print(" \_| \_/\_| |_/ \_____/_|\__\___| ")
        print("                                  ")
        print("http://kalite.learningequality.org")
        print("                                  ")
        print("         version %s" % VERSION)
        print("                                  ")

        if sys.version_info >= (2,8) or sys.version_info < (2,6):
            raise CommandError("You must have Python version 2.6.x or 2.7.x installed. Your version is: %s\n" % sys.version_info)

        if options["interactive"]:
            print("--------------------------------------------------------------------------------")
            print("This script will configure the database and prepare it for use.")
            print("--------------------------------------------------------------------------------")
            raw_input("Press [enter] to continue...")

        # Tried not to be os-specific, but ... hey. :-/
        # benjaoming: This doesn't work, why is 502 hard coded!? Root is normally
        # '0' And let's not care about stuff like this, people can be free to
        # run this as root if they want :)
        if not is_windows() and hasattr(os, "getuid") and os.getuid() == 502:
            print("-------------------------------------------------------------------")
            print("WARNING: You are installing KA-Lite as root user!")
            print("\tInstalling as root may cause some permission problems while running")
            print("\tas a normal user in the future.")
            print("-------------------------------------------------------------------")
            if options["interactive"]:
                if not raw_input_yn("Do you wish to continue and install it as root?"):
                    raise CommandError("Aborting script.\n")

        # Check to see if the current user is the owner of the install directory
        if not os.access(BASE_DIR, os.W_OK):
            raise CommandError("You do not have permission to write to this directory!")

        install_clean = not kalite.is_installed()
        database_kind = settings.DATABASES["default"]["ENGINE"]
        database_file = ("sqlite" in database_kind and settings.DATABASES["default"]["NAME"]) or None

        if database_file and os.path.exists(database_file):
            # We found an existing database file.  By default,
            #   we will upgrade it; users really need to work hard
            #   to delete the file (but it's possible, which is nice).
            print("-------------------------------------------------------------------")
            print("WARNING: Database file already exists!")
            print("-------------------------------------------------------------------")
            if not options["interactive"] \
               or raw_input_yn("Keep database file and upgrade to KA Lite version %s? " % VERSION) \
               or not raw_input_yn("Remove database file '%s' now? " % database_file) \
               or not raw_input_yn("WARNING: all data will be lost!  Are you sure? "):
                install_clean = False
                print("Upgrading database to KA Lite version %s" % VERSION)
            else:
                install_clean = True
                print("OK.  We will run a clean install; ")
                print("the database file will be moved to a deletable location.")  # After all, don't delete--just move.

        if not install_clean and not database_file and not kalite.is_installed():
            # Make sure that, for non-sqlite installs, the database exists.
            raise Exception("For databases not using SQLite, you must set up your database before running setup.")

        # Do all input at once, at the beginning
        if install_clean and options["interactive"]:
            if not options["username"] or not options["password"]:
                print("Please choose a username and password for the admin account on this device.")
                print("\tYou must remember this login information, as you will need")
                print("\tto enter it to administer this installation of KA Lite.")
            (username, password) = get_username_password(options["username"], options["password"])
            email = options["email"]
            (hostname, description) = get_hostname_and_description(options["hostname"], options["description"])
        else:
            username = options["username"] or getattr(settings, "INSTALL_ADMIN_USERNAME", None)
            password = options["password"] or getattr(settings, "INSTALL_ADMIN_PASSWORD", None)
            email = options["email"]  # default is non-empty
            hostname = options["hostname"]
            description = options["description"]

        if username and not validate_username(username):
            raise CommandError("Username must contain only letters, digits, and underscores, and start with a letter.\n")


        ########################
        # Now do stuff
        ########################

        # Move database file (if exists)
        if install_clean and database_file and os.path.exists(database_file):
            # This is an overwrite install; destroy the old db
            dest_file = tempfile.mkstemp()[1]
            print("(Re)moving database file to temp location, starting clean install.  Recovery location: %s" % dest_file)
            shutil.move(database_file, dest_file)

        # Should clean_pyc for (clean) reinstall purposes
        call_command("clean_pyc", interactive=False, verbosity=options.get("verbosity"), path=os.path.join(settings.PROJECT_PATH, ".."))

        # Migrate the database
        call_command("syncdb", interactive=False, verbosity=options.get("verbosity"))
        call_command("migrate", merge=True, verbosity=options.get("verbosity"))

        # download assessment items
        # This can take a long time and lead to Travis stalling. None of this is required for tests.
        if options['force-assessment-item-dl']:
            call_command("unpack_assessment_zip", settings.ASSESSMENT_ITEMS_ZIP_URL)
        elif not settings.RUNNING_IN_TRAVIS and options['interactive']:
            print("\nStarting in version 0.13, you will need an assessment items package in order to access many of the available exercises.")
            print("If you have an internet connection, you can download the needed package. Warning: this may take a long time!")
            print("If you have already downloaded the assessment items package, you can specify the file in the next step.")
            print("Otherwise, we will download it from {url}.".format(url=settings.ASSESSMENT_ITEMS_ZIP_URL))

            if raw_input_yn("Do you wish to download the assessment items package now?"):
                ass_item_filename = settings.ASSESSMENT_ITEMS_ZIP_URL
            elif raw_input_yn("Have you already downloaded the assessment items package?"):
                ass_item_filename = get_assessment_items_filename()
            else:
                ass_item_filename = None

            if not ass_item_filename:
                logging.warning("No assessment items package file given. You will need to download and unpack it later.")
            else:
                call_command("unpack_assessment_zip", ass_item_filename)
        else:
            logging.warning("No assessment items package file given. You will need to download and unpack it later.")


        # Individually generate any prerequisite models/state that is missing
        if not Settings.get("private_key"):
            call_command("generatekeys", verbosity=options.get("verbosity"))
        if not Device.objects.count():
            call_command("initdevice", hostname, description, verbosity=options.get("verbosity"))
        if not Facility.objects.count():
            Facility.initialize_default_facility()

        # Install data
        # if install_clean:
        #     # Create device, load on any zone data
        #     call_command("generatekeys", verbosity=options.get("verbosity"))
        #     call_command("initdevice", hostname, description, verbosity=options.get("verbosity"))
        #     Facility.initialize_default_facility()

        #else:
            # Device exists; load data if required.
            #
            # Hackish, as this duplicates code from initdevice.
            #
            #if os.path.exists(InitCommand.data_json_file):
            #    # This is a pathway to install zone-based data on a software upgrade.
            #    print("Loading zone data from '%s'\n" % InitCommand.data_json_file)
            #    load_data_for_offline_install(in_file=InitCommand.data_json_file)

        #    confirm_or_generate_zone()

        # Create the admin user
        if password:  # blank password (non-interactive) means don't create a superuser
            admin = get_object_or_None(User, username=username)
            if not admin:
                call_command("createsuperuser", username=username, email=email, interactive=False, verbosity=options.get("verbosity"))
                admin = User.objects.get(username=username)
            admin.set_password(password)
            admin.save()

        # Now deploy the static files
        call_command("collectstatic", interactive=False)

        if not settings.CENTRAL_SERVER:
            # Move scripts
            for script_name in ["start", "stop", "run_command"]:
                script_file = script_name + system_script_extension()
                dest_dir = os.path.join(settings.PROJECT_PATH, "..")
                src_dir = os.path.join(dest_dir, "scripts")
                shutil.copyfile(os.path.join(src_dir, script_file), os.path.join(dest_dir, script_file))
                try:
                    shutil.copystat(os.path.join(src_dir, script_file), os.path.join(dest_dir, script_file))
                except OSError:  # even if we have write permission, we might not have permission to change file mode
                    print("WARNING: Unable to set file permissions on %s! " % script_file)

            kalite_executable = 'kalite'
            if not spawn.find_executable('kalite'):
                if os.name == 'posix':
                    start_script_path = os.path.realpath(os.path.join(settings.PROJECT_PATH, "..", "bin", kalite_executable))
                else:
                    start_script_path = os.path.realpath(os.path.join(settings.PROJECT_PATH, "..", "bin", "windows", "kalite.bat"))
            else:
                start_script_path = kalite_executable

            # Run videoscan, on the distributed server.
            print("Scanning for video files in the content directory (%s)" % settings.CONTENT_ROOT)
            call_command("videoscan")

            # done; notify the user.
            print("CONGRATULATIONS! You've finished setting up the KA Lite server software.")
            print("You can now start KA Lite with the following command:\n\n\t%s start\n\n" % start_script_path)
Пример #5
0
    def handle(self, *args, **options):
        if not options["interactive"]:
            options["username"] = options["username"] or getattr(settings, "INSTALL_ADMIN_USERNAME", None) or get_clean_default_username()
            options["hostname"] = options["hostname"] or get_host_name()

        sys.stdout.write("                                  \n")  # blank allows ansible scripts to dump errors cleanly.
        sys.stdout.write("  _   __  ___    _     _ _        \n")
        sys.stdout.write(" | | / / / _ \  | |   (_) |       \n")
        sys.stdout.write(" | |/ / / /_\ \ | |    _| |_ ___  \n")
        sys.stdout.write(" |    \ |  _  | | |   | | __/ _ \ \n")
        sys.stdout.write(" | |\  \| | | | | |___| | ||  __/ \n")
        sys.stdout.write(" \_| \_/\_| |_/ \_____/_|\__\___| \n")
        sys.stdout.write("                                  \n")
        sys.stdout.write("http://kalite.learningequality.org\n")
        sys.stdout.write("                                  \n")
        sys.stdout.write("         version %s\n" % VERSION)
        sys.stdout.write("                                  \n")

        if sys.version_info >= (2,8) or sys.version_info < (2,6):
            raise CommandError("You must have Python version 2.6.x or 2.7.x installed. Your version is: %s\n" % sys.version_info)

        if options["interactive"]:
            sys.stdout.write("--------------------------------------------------------------------------------\n")
            sys.stdout.write("\n")
            sys.stdout.write("This script will configure the database and prepare it for use.\n")
            sys.stdout.write("\n")
            sys.stdout.write("--------------------------------------------------------------------------------\n")
            sys.stdout.write("\n")
            raw_input("Press [enter] to continue...")
            sys.stdout.write("\n")

        # Tried not to be os-specific, but ... hey. :-/
        if not is_windows() and hasattr(os, "getuid") and os.getuid() == 502:
            sys.stdout.write("-------------------------------------------------------------------\n")
            sys.stdout.write("WARNING: You are installing KA-Lite as root user!\n")
            sys.stdout.write("\tInstalling as root may cause some permission problems while running\n")
            sys.stdout.write("\tas a normal user in the future.\n")
            sys.stdout.write("-------------------------------------------------------------------\n")
            if options["interactive"]:
                if not raw_input_yn("Do you wish to continue and install it as root?"):
                    raise CommandError("Aborting script.\n")
                sys.stdout.write("\n")

        # Check to see if the current user is the owner of the install directory
        if not os.access(BASE_DIR, os.W_OK):
            raise CommandError("You do not have permission to write to this directory!")

        install_clean = not kalite.is_installed()
        database_kind = settings.DATABASES["default"]["ENGINE"]
        database_file = ("sqlite" in database_kind and settings.DATABASES["default"]["NAME"]) or None

        if database_file and os.path.exists(database_file):
            # We found an existing database file.  By default,
            #   we will upgrade it; users really need to work hard
            #   to delete the file (but it's possible, which is nice).
            sys.stdout.write("-------------------------------------------------------------------\n")
            sys.stdout.write("WARNING: Database file already exists! \n")
            sys.stdout.write("-------------------------------------------------------------------\n")
            if not options["interactive"] \
               or raw_input_yn("Keep database file and upgrade to KA Lite version %s? " % VERSION) \
               or not raw_input_yn("Remove database file '%s' now? " % database_file) \
               or not raw_input_yn("WARNING: all data will be lost!  Are you sure? "):
                install_clean = False
                sys.stdout.write("Upgrading database to KA Lite version %s\n" % VERSION)
            else:
                install_clean = True
                sys.stdout.write("OK.  We will run a clean install; \n")
                sys.stdout.write("the database file will be moved to a deletable location.\n")  # After all, don't delete--just move.

        if not install_clean and not database_file and not kalite.is_installed():
            # Make sure that, for non-sqlite installs, the database exists.
            raise Exception("For databases not using SQLite, you must set up your database before running setup.")

        # Do all input at once, at the beginning
        if install_clean and options["interactive"]:
            if not options["username"] or not options["password"]:
                sys.stdout.write("\n")
                sys.stdout.write("Please choose a username and password for the admin account on this device.\n")
                sys.stdout.write("\tYou must remember this login information, as you will need\n")
                sys.stdout.write("\tto enter it to administer this installation of KA Lite.\n")
                sys.stdout.write("\n")
            (username, password) = get_username_password(options["username"], options["password"])
            email = options["email"]
            (hostname, description) = get_hostname_and_description(options["hostname"], options["description"])
        else:
            username = options["username"] or getattr(settings, "INSTALL_ADMIN_USERNAME", None)
            password = options["password"] or getattr(settings, "INSTALL_ADMIN_PASSWORD", None)
            email = options["email"]  # default is non-empty
            hostname = options["hostname"]
            description = options["description"]

        if username and not validate_username(username):
            raise CommandError("Username must contain only letters, digits, and underscores, and start with a letter.\n")


        ########################
        # Now do stuff
        ########################

        # Move database file (if exists)
        if install_clean and database_file and os.path.exists(database_file):
            # This is an overwrite install; destroy the old db
            dest_file = tempfile.mkstemp()[1]
            sys.stdout.write("(Re)moving database file to temp location, starting clean install.  Recovery location: %s\n" % dest_file)
            shutil.move(database_file, dest_file)

        # Should clean_pyc for (clean) reinstall purposes
        call_command("clean_pyc", interactive=False, verbosity=options.get("verbosity"), path=os.path.join(settings.PROJECT_PATH, ".."))

        # Migrate the database
        call_command("syncdb", interactive=False, verbosity=options.get("verbosity"))
        call_command("migrate", merge=True, verbosity=options.get("verbosity"))

        # Individually generate any prerequisite models/state that is missing
        if not Settings.get("private_key"):
            call_command("generatekeys", verbosity=options.get("verbosity"))
        if not Device.objects.count():
            call_command("initdevice", hostname, description, verbosity=options.get("verbosity"))
        if not Facility.objects.count():
            Facility.initialize_default_facility()

        # Install data
        # if install_clean:
        #     # Create device, load on any zone data
        #     call_command("generatekeys", verbosity=options.get("verbosity"))
        #     call_command("initdevice", hostname, description, verbosity=options.get("verbosity"))
        #     Facility.initialize_default_facility()

        #else:
            # Device exists; load data if required.
            #
            # Hackish, as this duplicates code from initdevice.
            #
            #if os.path.exists(InitCommand.data_json_file):
            #    # This is a pathway to install zone-based data on a software upgrade.
            #    sys.stdout.write("Loading zone data from '%s'\n" % InitCommand.data_json_file)
            #    load_data_for_offline_install(in_file=InitCommand.data_json_file)

        #    confirm_or_generate_zone()

        # Create the admin user
        if password:  # blank password (non-interactive) means don't create a superuser
            admin = get_object_or_None(User, username=username)
            if not admin:
                call_command("createsuperuser", username=username, email=email, interactive=False, verbosity=options.get("verbosity"))
                admin = User.objects.get(username=username)
            admin.set_password(password)
            admin.save()

        # Now deploy the static files
        call_command("collectstatic", interactive=False)

        if not settings.CENTRAL_SERVER:
            # Move scripts
            for script_name in ["start", "stop", "run_command"]:
                script_file = script_name + system_script_extension()
                dest_dir = os.path.join(settings.PROJECT_PATH, "..")
                src_dir = os.path.join(dest_dir, "scripts")
                shutil.copyfile(os.path.join(src_dir, script_file), os.path.join(dest_dir, script_file))
                try:
                    shutil.copystat(os.path.join(src_dir, script_file), os.path.join(dest_dir, script_file))
                except OSError: # even if we have write permission, we might not have permission to change file mode
                    sys.stdout.write("WARNING: Unable to set file permissions on %s! \n" % script_file)

            start_script_path = os.path.realpath(os.path.join(settings.PROJECT_PATH, "..", "start%s" % system_script_extension()))

            # Run videoscan, on the distributed server.
            sys.stdout.write("Scanning for video files in the content directory (%s)\n" % settings.CONTENT_ROOT)
            call_command("videoscan")

            # done; notify the user.
            sys.stdout.write("\n")
            if install_clean:
                sys.stdout.write("CONGRATULATIONS! You've finished setting up the KA Lite server software.\n")
                sys.stdout.write("\tPlease run '%s' to start the server,\n" % start_script_path)
                sys.stdout.write("\tthen load one of the following addresses in your browser to complete the configuration:\n")
                for ip in get_ip_addresses():
                    sys.stdout.write("\t\thttp://%s:%d/\n" % (ip, settings.USER_FACING_PORT()))

            else:
                sys.stdout.write("CONGRATULATIONS! You've finished updating the KA Lite server software.\n")
                sys.stdout.write("\tPlease run '%s' to start the server.\n" % start_script_path)
            sys.stdout.write("\n")