Exemplo n.º 1
0
 def test_get_not_in_snap(self):
     config_manager = MAASConfiguration(environ={})
     # use mocked dir instead of /etc/maas
     config_manager.DEFAULT_CONFIG_DIR = self.config_dir
     config = {
         factory.make_name('key'): factory.make_name('value'),
         factory.make_name('key'): factory.make_name('value')
     }
     self.write_config(config, 'regiond.conf')
     self.assertEqual(config_manager.get(), config)
Exemplo n.º 2
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'init' command must be run by root.")

        mode = options.run_mode
        current_mode = get_current_mode()
        if current_mode != "none":
            if not options.force:
                init_text = "initialize again"
                if mode == "none":
                    init_text = "de-initialize"
                else:
                    print_msg("Controller has already been initialized.")
                initialize = prompt_for_choices(
                    "Are you sure you want to %s "
                    "(yes/no) [default=no]? " % init_text,
                    ["yes", "no"],
                    default="no",
                )
                if initialize == "no":
                    sys.exit(0)

        rpc_secret = None
        if mode in ("region", "region+rack"):
            try:
                database_settings = get_database_settings(options)
            except DatabaseSettingsError as error:
                raise CommandError(str(error))
        else:
            database_settings = {}
        maas_url = options.maas_url
        if mode != "none" and not maas_url:
            maas_url = required_prompt(
                "MAAS URL",
                default=get_default_url(),
                help_text=ARGUMENTS["maas-url"]["help"],
            )
        if mode == "rack":
            rpc_secret = options.secret
            if not rpc_secret:
                rpc_secret = required_prompt(
                    "Secret", help_text=ARGUMENTS["secret"]["help"])

        if current_mode != "none":

            def stop_services():
                render_supervisord("none")
                sighup_supervisord()

            perform_work("Stopping services", stop_services)

        # Configure the settings.
        settings = {"maas_url": maas_url}
        settings.update(database_settings)

        MAASConfiguration().update(settings)
        set_rpc_secret(rpc_secret)

        # Finalize the Initialization.
        self._finalize_init(mode, options)
Exemplo n.º 3
0
def init_db():
    """Initialize the database."""
    config_data = MAASConfiguration().get()
    base_db_dir = get_base_db_dir()
    db_path = os.path.join(base_db_dir, 'data')
    if not os.path.exists(base_db_dir):
        os.mkdir(base_db_dir)
        # allow both root and non-root user to create/delete directories under
        # this one
        shutil.chown(base_db_dir, group=NON_ROOT_USER)
        os.chmod(base_db_dir, 0o770)
    if os.path.exists(db_path):
        run_with_drop_privileges(shutil.rmtree, db_path)
    os.mkdir(db_path)
    shutil.chown(db_path, user=NON_ROOT_USER, group=NON_ROOT_USER)
    log_path = os.path.join(
        os.environ['SNAP_COMMON'], 'log', 'postgresql-init.log')
    if not os.path.exists(log_path):
        open(log_path, 'a').close()
    shutil.chown(log_path, user=NON_ROOT_USER, group=NON_ROOT_USER)
    socket_path = os.path.join(get_base_db_dir(), 'sockets')
    if not os.path.exists(socket_path):
        os.mkdir(socket_path)
        os.chmod(socket_path, 0o775)
        shutil.chown(socket_path, user=NON_ROOT_USER)  # keep root as group

    def _init_db():
        subprocess.check_output([
            os.path.join(os.environ['SNAP'], 'bin', 'initdb'),
            '-D', os.path.join(get_base_db_dir(), 'data'),
            '-U', 'postgres', '-E', 'UTF8', '--locale=C'],
            stderr=subprocess.STDOUT)
        with with_postgresql():
            create_db(config_data)
    run_with_drop_privileges(_init_db)
Exemplo n.º 4
0
def print_config(parsable=False,
                 show_database_password=False,
                 show_secret=False):
    """Print the config output."""
    current_mode = get_current_mode()
    config = MAASConfiguration().get()
    if parsable:
        print_msg('mode=%s' % current_mode)
    else:
        print_msg('Mode: %s' % current_mode)
    if current_mode != 'none':
        if not parsable:
            print_msg('Settings:')
        print_config_value(config, 'maas_url')
        if current_mode in ['region+rack', 'region']:
            print_config_value(config, 'database_host')
            print_config_value(config, 'database_port')
            print_config_value(config, 'database_name')
            print_config_value(config, 'database_user')
            print_config_value(config,
                               'database_pass',
                               hidden=(not show_database_password))
        if current_mode == 'rack':
            secret = "(hidden)"
            if show_secret:
                secret = get_rpc_secret()
            print_msg('secret=%s' % secret)
        if current_mode != 'rack':
            if 'num_workers' in config:
                print_config_value(config, 'num_workers')
            if 'debug' in config:
                print_config_value(config, 'debug')
            if 'debug_queries' in config:
                print_config_value(config, 'debug_queries')
Exemplo n.º 5
0
def print_config(parsable=False,
                 show_database_password=False,
                 show_secret=False):
    """Print the config output."""
    current_mode = get_current_mode()
    config = MAASConfiguration().get()
    if parsable:
        print_msg("mode=%s" % current_mode)
    else:
        print_msg("Mode: %s" % current_mode)
    if current_mode != "none":
        if not parsable:
            print_msg("Settings:")
        print_config_value(config, "maas_url")
        if current_mode in ["region+rack", "region"]:
            print_config_value(config, "database_host")
            print_config_value(config, "database_port")
            print_config_value(config, "database_name")
            print_config_value(config, "database_user")
            print_config_value(config,
                               "database_pass",
                               hidden=(not show_database_password))
        if current_mode == "rack":
            secret = "(hidden)"
            if show_secret:
                secret = get_rpc_secret()
            print_msg("secret=%s" % secret)
        if current_mode != "rack":
            if "num_workers" in config:
                print_config_value(config, "num_workers")
            if "debug" in config:
                print_config_value(config, "debug")
            if "debug_queries" in config:
                print_config_value(config, "debug_queries")
Exemplo n.º 6
0
def init_maas(options):
    print_msg("Configuring authentication")
    configure_authentication(options)
    if not options.skip_admin:
        auth_config = get_current_auth_config()
        if auth_config["external_auth_url"]:
            maas_config = MAASConfiguration().get()
            create_account_external_auth(auth_config, maas_config)
        else:
            create_admin_account(options)
Exemplo n.º 7
0
def init_maas(options):
    if options.enable_candid:
        print_msg('Configuring authentication')
        configure_authentication(options)
    if not options.skip_admin:
        auth_config = get_current_auth_config()
        if auth_config['external_auth_url']:
            maas_config = MAASConfiguration().get()
            create_account_external_auth(auth_config, maas_config)
        else:
            create_admin_account(options)
Exemplo n.º 8
0
def init_db():
    """Initialize the database."""
    config_data = MAASConfiguration().get()
    base_db_dir = get_base_db_dir()
    db_path = os.path.join(base_db_dir, "data")
    if not os.path.exists(base_db_dir):
        os.mkdir(base_db_dir)
        # allow both root and non-root user to create/delete directories under
        # this one
        shutil.chown(base_db_dir, group=NON_ROOT_USER)
        os.chmod(base_db_dir, 0o770)
    if os.path.exists(db_path):
        run_with_drop_privileges(shutil.rmtree, db_path)
    os.mkdir(db_path)
    shutil.chown(db_path, user=NON_ROOT_USER, group=NON_ROOT_USER)
    log_path = os.path.join(os.environ["SNAP_COMMON"], "log",
                            "postgresql-init.log")
    if not os.path.exists(log_path):
        open(log_path, "a").close()
    shutil.chown(log_path, user=NON_ROOT_USER, group=NON_ROOT_USER)
    socket_path = os.path.join(get_base_db_dir(), "sockets")
    if not os.path.exists(socket_path):
        os.mkdir(socket_path)
        os.chmod(socket_path, 0o775)
        shutil.chown(socket_path, user=NON_ROOT_USER)  # keep root as group

    def _init_db():
        subprocess.check_output(
            [
                os.path.join(os.environ["SNAP"], "bin", "initdb"),
                "-D",
                os.path.join(get_base_db_dir(), "data"),
                "-U",
                "postgres",
                "-E",
                "UTF8",
                "--locale=C",
            ],
            stderr=subprocess.STDOUT,
        )
        with with_postgresql():
            create_db(config_data)

    run_with_drop_privileges(_init_db)
Exemplo n.º 9
0
def init_db():
    """Initialize the database."""
    config_data = MAASConfiguration().get()
    db_path = os.path.join(os.environ['SNAP_COMMON'], 'db')
    if os.path.exists(db_path):
        shutil.rmtree(db_path)
    os.mkdir(db_path)
    shutil.chown(db_path, user='******', group='nogroup')
    log_path = os.path.join(os.environ['SNAP_COMMON'], 'log', 'postgresql.log')
    if not os.path.exists(log_path):
        open(log_path, 'a').close()
    shutil.chown(log_path, user='******', group='nogroup')

    def _init_db():
        subprocess.check_output([
            os.path.join(os.environ['SNAP'], 'bin', 'initdb'),
            '-D', os.path.join(os.environ['SNAP_COMMON'], 'db'),
            '-U', 'postgres', '-E', 'UTF8', '--locale=C'],
            stderr=subprocess.STDOUT)
        with with_postgresql():
            create_db(config_data)
    run_with_drop_privileges(_init_db)
Exemplo n.º 10
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'config' command must be run by root.")

        config_manager = MAASConfiguration()

        # Hidden option only called by the run-supervisord script. Renders
        # the initial supervisord.conf based on the current mode.
        if options.render:
            render_supervisord(get_current_mode())
            return

        # In config mode if --show is passed or none of the following flags
        # have been passed.
        in_config_mode = options.show
        if not in_config_mode:
            in_config_mode = not any(
                (getattr(options, flag) is not None
                 and getattr(options, flag) is not False)
                for flag in (('mode', 'secret') + self.setting_flags +
                             tuple(self.optional_flags.keys())))

        # Config mode returns the current config of the snap.
        if in_config_mode:
            return print_config(options.parsable,
                                options.show_database_password,
                                options.show_secret)
        else:
            restart_required = False
            changed_to_all = False
            current_mode = get_current_mode()
            running_mode = current_mode
            if options.mode is not None:
                running_mode = options.mode

            # Validate the mode and flags.
            self._validate_mode(options)
            self._validate_flags(options, running_mode)

            # Changing the mode to from all requires --force.
            if options.mode is not None:
                if current_mode == 'all' and options.mode != 'all':
                    if not options.force:
                        print_msg(
                            "Changing mode from 'all' to '%s' will "
                            "disconnect the database and all data will "
                            "be lost. Use '--force' if your sure you want "
                            "to do this." % options.mode)
                        sys.exit(1)
                elif current_mode != 'all' and options.mode == 'all':
                    # Changing mode to all requires services to be stopped and
                    # a new database to be initialized.
                    changed_to_all = True

                    def stop_services():
                        render_supervisord('none')
                        sighup_supervisord()

                    perform_work('Stopping services', stop_services)

                    # Configure the new database settings.
                    options.database_host = os.path.join(
                        get_base_db_dir(), 'sockets')
                    options.database_name = 'maasdb'
                    options.database_user = '******'
                    options.database_pass = ''.join(
                        random.choice(string.ascii_uppercase + string.digits)
                        for _ in range(10))
                    MAASConfiguration().write_to_file(
                        {
                            'maas_url': options.maas_url,
                            'database_host': options.database_host,
                            'database_name': options.database_name,
                            'database_user': options.database_user,
                            'database_pass': options.database_pass
                        }, 'regiond.conf')

                    # Initialize the database before starting the services.
                    perform_work('Initializing database', init_db)
                if options.mode != current_mode:
                    render_supervisord(options.mode)
                    set_current_mode(options.mode)
                    restart_required = True

            current_config = config_manager.get()
            if current_mode != running_mode:
                # Update all the settings since the mode changed.
                for flag in self.setting_flags:
                    flag_value = getattr(options, flag)
                    if current_config.get(flag) != flag_value:
                        config_manager.update({flag: flag_value})
                        restart_required = True
                set_rpc_secret(options.secret)
            else:
                # Only update the passed settings.
                for flag in self.setting_flags:
                    flag_value = getattr(options, flag)
                    should_update = (flag_value is not None and
                                     current_config.get(flag) != flag_value)
                    if should_update:
                        config_manager.update({flag: flag_value})
                        restart_required = True
                if options.secret is not None:
                    set_rpc_secret(options.secret)

            # fetch config again, as it might have changed
            current_config = config_manager.get()

            # Update any optional settings.
            for flag, flag_info in self.optional_flags.items():
                flag_value = getattr(options, flag)
                if flag_info['type'] != 'store_true':
                    flag_key = flag_info['config']
                    should_update = (
                        flag_value is not None
                        and current_config.get(flag_key) != flag_value)
                    if should_update:
                        config_manager.update({flag_key: flag_value})
                        restart_required = True
                elif flag_value:
                    flag_key = flag_info['config']
                    flag_value = flag_info['set_value']
                    if current_config.get(flag_key) != flag_value:
                        config_manager.update({flag_key: flag_value})
                        restart_required = True

            # Restart the supervisor as its required.
            if restart_required:
                perform_work(
                    'Restarting services' if running_mode != 'none' else
                    'Stopping services', sighup_supervisord)
                clear_line()

            # Perform migrations when switching to all.
            if changed_to_all:
                perform_work('Waiting for postgresql', wait_for_postgresql)
                perform_work("Performing database migrations",
                             migrate_db,
                             capture=sys.stdout.isatty())
                clear_line()
Exemplo n.º 11
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'init' command must be run by root.")

        mode = options.mode
        current_mode = get_current_mode()
        if current_mode != 'none':
            if not options.force:
                init_text = 'initialize again'
                if mode == 'none':
                    init_text = 'de-initialize'
                else:
                    print_msg('Controller has already been initialized.')
                initialize = prompt_for_choices('Are you sure you want to %s '
                                                '(yes/no) [default=no]? ' %
                                                init_text, ['yes', 'no'],
                                                default='no')
                if initialize == 'no':
                    sys.exit(0)

        if not mode:
            mode = prompt_for_choices(
                "Mode ({choices}) [default={default}]? ".format(
                    choices='/'.join(ARGUMENTS['mode']['choices']),
                    default=DEFAULT_OPERATION_MODE),
                ARGUMENTS['mode']['choices'],
                default=DEFAULT_OPERATION_MODE,
                help_text=OPERATION_MODES)
        if current_mode == 'all' and mode != 'all' and not options.force:
            print_msg(
                'This will disconnect your MAAS from the running database.')
            disconnect = prompt_for_choices(
                'Are you sure you want to disconnect the database '
                '(yes/no) [default=no]? ', ['yes', 'no'],
                default='no')
            if disconnect == 'no':
                return 0
        elif current_mode == 'all' and mode == 'all' and not options.force:
            print_msg('This will re-initialize your entire database and all '
                      'current data will be lost.')
            reinit_db = prompt_for_choices(
                'Are you sure you want to re-initialize the database '
                '(yes/no) [default=no]? ', ['yes', 'no'],
                default='no')
            if reinit_db == 'no':
                return 0

        maas_url = options.maas_url
        if mode != 'none' and not maas_url:
            maas_url = prompt_for_maas_url()
        database_host = database_name = None
        database_user = database_pass = None
        rpc_secret = None
        if mode == 'all':
            database_host = os.path.join(get_base_db_dir(), 'sockets')
            database_name = 'maasdb'
            database_user = '******'
            database_pass = ''.join(
                random.choice(string.ascii_uppercase + string.digits)
                for _ in range(10))
        if mode in ['region', 'region+rack']:
            database_host = options.database_host
            if not database_host:
                database_host = required_prompt(
                    "Database host: ",
                    help_text=ARGUMENTS['database-host']['help'])
            database_name = options.database_name
            if not database_name:
                database_name = required_prompt(
                    "Database name: ",
                    help_text=ARGUMENTS['database-name']['help'])
            database_user = options.database_user
            if not database_user:
                database_user = required_prompt(
                    "Database user: "******"Database password: "******"Secret: ", help_text=ARGUMENTS['secret']['help'])

        # Stop all services if in another mode.
        if current_mode != 'none':

            def stop_services():
                render_supervisord('none')
                sighup_supervisord()

            perform_work('Stopping services', stop_services)

        # Configure the settings.
        settings = {
            'maas_url': maas_url,
            'database_host': database_host,
            'database_name': database_name,
            'database_user': database_user,
            'database_pass': database_pass
        }

        # Add the port to the configuration if exists. By default
        # MAAS handles picking the port automatically in the backend
        # if none provided.
        if options.database_port:
            settings['database_port'] = options.database_port

        MAASConfiguration().update(settings)
        set_rpc_secret(rpc_secret)

        # Finalize the Initialization.
        self._finalize_init(mode, options)
Exemplo n.º 12
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'init' command must be run by root.")

        mode = options.mode
        current_mode = get_current_mode()
        if current_mode != "none":
            if not options.force:
                init_text = "initialize again"
                if mode == "none":
                    init_text = "de-initialize"
                else:
                    print_msg("Controller has already been initialized.")
                initialize = prompt_for_choices(
                    "Are you sure you want to %s "
                    "(yes/no) [default=no]? " % init_text,
                    ["yes", "no"],
                    default="no",
                )
                if initialize == "no":
                    sys.exit(0)

        if not mode:
            print_msg(
                dedent("""
            Select the mode the snap should operate in.

            When installing region or rack+region modes, MAAS needs a
            PostgreSQL database to connect to.

            If you want to set up PostgreSQL on this machine, and configure it
            for use with MAAS, you can run the following command:

            /snap/maas/current/helpers/maas-database-setup

            """))
            mode = prompt_for_choices(
                "Mode ({choices}) [default={default}]? ".format(
                    choices="/".join(ARGUMENTS["mode"]["choices"]),
                    default=DEFAULT_OPERATION_MODE,
                ),
                ARGUMENTS["mode"]["choices"],
                default=DEFAULT_OPERATION_MODE,
                help_text=OPERATION_MODES,
            )
        if current_mode == "all" and not options.force:
            print_msg(
                "This will disconnect your MAAS from the running database.")
            disconnect = prompt_for_choices(
                "Are you sure you want to disconnect the database "
                "(yes/no) [default=no]? ",
                ["yes", "no"],
                default="no",
            )
            if disconnect == "no":
                return 0

        maas_url = options.maas_url
        if mode != "none" and not maas_url:
            maas_url = prompt_for_maas_url()
        database_host = database_name = None
        database_user = database_pass = None
        rpc_secret = None
        if mode in ["region", "region+rack"]:
            database_host = options.database_host
            if not database_host:
                database_host = required_prompt(
                    "Database host: ",
                    help_text=ARGUMENTS["database-host"]["help"],
                )
            database_name = options.database_name
            if not database_name:
                database_name = required_prompt(
                    "Database name: ",
                    help_text=ARGUMENTS["database-name"]["help"],
                )
            database_user = options.database_user
            if not database_user:
                database_user = required_prompt(
                    "Database user: "******"database-user"]["help"],
                )
            database_pass = options.database_pass
            if not database_pass:
                database_pass = required_prompt(
                    "Database password: "******"database-pass"]["help"],
                )
        if mode == "rack":
            rpc_secret = options.secret
            if not rpc_secret:
                rpc_secret = required_prompt(
                    "Secret: ", help_text=ARGUMENTS["secret"]["help"])

        # Stop all services if in another mode.
        if current_mode != "none":

            def stop_services():
                render_supervisord("none")
                sighup_supervisord()

            perform_work("Stopping services", stop_services)

        # Configure the settings.
        settings = {
            "maas_url": maas_url,
            "database_host": database_host,
            "database_name": database_name,
            "database_user": database_user,
            "database_pass": database_pass,
        }

        # Add the port to the configuration if exists. By default
        # MAAS handles picking the port automatically in the backend
        # if none provided.
        if options.database_port:
            settings["database_port"] = options.database_port

        MAASConfiguration().update(settings)
        set_rpc_secret(rpc_secret)

        # Finalize the Initialization.
        self._finalize_init(mode, options)
Exemplo n.º 13
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'config' command must be run by root.")

        config_manager = MAASConfiguration()

        # Hidden option only called by the run-supervisord script. Renders
        # the initial supervisord.conf based on the current mode.
        if options.render:
            render_supervisord(get_current_mode())
            return

        # In config mode if --show is passed or none of the following flags
        # have been passed.
        in_config_mode = options.show
        if not in_config_mode:
            in_config_mode = not any(
                (getattr(options, flag) is not None
                 and getattr(options, flag) is not False)
                for flag in (("mode", "secret") + self.setting_flags +
                             tuple(self.optional_flags.keys())))

        # Config mode returns the current config of the snap.
        if in_config_mode:
            return print_config(
                options.parsable,
                options.show_database_password,
                options.show_secret,
            )
        else:
            restart_required = False
            current_mode = get_current_mode()
            running_mode = current_mode
            if options.mode is not None:
                running_mode = options.mode

            # Validate the mode and flags.
            self._validate_mode(options)
            self._validate_flags(options, running_mode)

            # Changing the mode from all requires --force.
            if options.mode is not None:
                if current_mode == "all":
                    if not options.force:
                        print_msg(
                            "Changing mode from 'all' to '%s' will "
                            "disconnect the database and all data will "
                            "be lost. Use '--force' if your sure you want "
                            "to do this." % options.mode)
                        sys.exit(1)
                if options.mode != current_mode:
                    render_supervisord(options.mode)
                    set_current_mode(options.mode)
                    restart_required = True

            current_config = config_manager.get()
            if current_mode != running_mode:
                # Update all the settings since the mode changed.
                for flag in self.setting_flags:
                    flag_value = getattr(options, flag)
                    if current_config.get(flag) != flag_value:
                        config_manager.update({flag: flag_value})
                        restart_required = True
                set_rpc_secret(options.secret)
            else:
                # Only update the passed settings.
                for flag in self.setting_flags:
                    flag_value = getattr(options, flag)
                    should_update = (flag_value is not None and
                                     current_config.get(flag) != flag_value)
                    if should_update:
                        config_manager.update({flag: flag_value})
                        restart_required = True
                if options.secret is not None:
                    set_rpc_secret(options.secret)

            # fetch config again, as it might have changed
            current_config = config_manager.get()

            # Update any optional settings.
            for flag, flag_info in self.optional_flags.items():
                flag_value = getattr(options, flag)
                if flag_info["type"] != "store_true":
                    flag_key = flag_info["config"]
                    should_update = (
                        flag_value is not None
                        and current_config.get(flag_key) != flag_value)
                    if should_update:
                        config_manager.update({flag_key: flag_value})
                        restart_required = True
                elif flag_value:
                    flag_key = flag_info["config"]
                    flag_value = flag_info["set_value"]
                    if current_config.get(flag_key) != flag_value:
                        config_manager.update({flag_key: flag_value})
                        restart_required = True

            # Restart the supervisor as its required.
            if restart_required:
                perform_work(
                    "Restarting services"
                    if running_mode != "none" else "Stopping services",
                    sighup_supervisord,
                )
                clear_line()
Exemplo n.º 14
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'config' command must be run by root.")

        config_manager = MAASConfiguration()

        # Hidden option only called by the run-supervisord script. Renders
        # the initial supervisord.conf based on the current mode.
        if options.render:
            render_supervisord(get_current_mode())
            return

        # In config mode if --show is passed or none of the following flags
        # have been passed.
        in_config_mode = options.show
        if not in_config_mode:
            in_config_mode = not any(
                (getattr(options, flag) is not None
                 and getattr(options, flag) is not False)
                for flag in (("secret", ) + self.setting_flags +
                             tuple(self.optional_flags.keys())))

        # Config mode returns the current config of the snap.
        if in_config_mode:
            return print_config(
                options.parsable,
                options.show_database_password,
                options.show_secret,
            )
        else:
            restart_required = False
            running_mode = get_current_mode()

            # Validate the mode and flags.
            self._validate_flags(options, running_mode)

            current_config = config_manager.get()
            # Only update the passed settings.
            for flag in self.setting_flags:
                flag_value = getattr(options, flag)
                should_update = (flag_value is not None
                                 and current_config.get(flag) != flag_value)
                if should_update:
                    config_manager.update({flag: flag_value})
                    restart_required = True
            if options.secret is not None:
                set_rpc_secret(options.secret)

            # fetch config again, as it might have changed
            current_config = config_manager.get()

            # Update any optional settings.
            for flag, flag_info in self.optional_flags.items():
                flag_value = getattr(options, flag)
                if flag_info["type"] != "store_true":
                    flag_key = flag_info["config"]
                    should_update = (
                        flag_value is not None
                        and current_config.get(flag_key) != flag_value)
                    if should_update:
                        config_manager.update({flag_key: flag_value})
                        restart_required = True
                elif flag_value:
                    flag_key = flag_info["config"]
                    flag_value = flag_info["set_value"]
                    if current_config.get(flag_key) != flag_value:
                        config_manager.update({flag_key: flag_value})
                        restart_required = True

            # Restart the supervisor as its required.
            if restart_required:
                perform_work(
                    "Restarting services"
                    if running_mode != "none" else "Stopping services",
                    sighup_supervisord,
                )
Exemplo n.º 15
0
class TestMAASConfiguration(MAASTestCase):
    def setUp(self):
        super().setUp()
        self.config_dir = Path(self.make_dir())
        self.environ = {"SNAP_DATA": self.config_dir}
        self.config_manager = MAASConfiguration(environ=self.environ)

    def write_config(self, config, filename):
        config_file = self.config_dir / filename
        config_file.write_text(yaml.safe_dump(config))

    def read_config(self, filename):
        config_file = self.config_dir / filename
        if not config_file.exists():
            return None
        return yaml.safe_load(config_file.read_text())

    def test_get_not_in_snap(self):
        config_manager = MAASConfiguration(environ={})
        # use mocked dir instead of /etc/maas
        config_manager.DEFAULT_CONFIG_DIR = self.config_dir
        config = {
            factory.make_name("key"): factory.make_name("value"),
            factory.make_name("key"): factory.make_name("value"),
        }
        self.write_config(config, "regiond.conf")
        self.assertEqual(config_manager.get(), config)

    def test_get(self):
        config = {
            factory.make_name("key"): factory.make_name("value"),
            factory.make_name("key"): factory.make_name("value"),
        }
        self.write_config(config, "regiond.conf")
        self.assertEqual(self.config_manager.get(), config)

    def test_get_empty(self):
        self.assertEqual(self.config_manager.get(), {})

    def test_write_to_file(self):
        config = {
            factory.make_name("key"): factory.make_name("value"),
            factory.make_name("key"): factory.make_name("value"),
        }
        filename = factory.make_name("file")
        self.config_manager.write_to_file(config, filename)
        self.assertEqual(self.read_config(filename), config)

    def test_update_updates(self):
        config1 = {"foo": "bar"}
        config2 = {"foo": "baz"}
        self.config_manager.update(config1)
        self.config_manager.update(config2)
        self.assertEqual(self.read_config("regiond.conf"), config2)

    def test_update_from_empty_file(self):
        config = {factory.make_name("key"): factory.make_name("value")}
        (self.config_dir / "regiond.conf").touch()
        self.config_manager.update(config)
        self.assertEqual(self.read_config("regiond.conf"), config)

    def test_update_sets(self):
        config = {
            factory.make_name("key"): factory.make_name("value"),
            factory.make_name("key"): factory.make_name("value"),
        }
        self.config_manager.update(config)
        self.assertEqual(self.read_config("regiond.conf"), config)
        # no rackd config is written
        self.assertIsNone(self.read_config("rackd.conf"))

    def test_update_extends(self):
        config1 = {"foo": "bar"}
        config2 = {"baz": "bza"}
        self.config_manager.update(config1)
        self.config_manager.update(config2)
        full_config = {}
        full_config.update(config1)
        full_config.update(config2)
        self.assertEqual(self.read_config("regiond.conf"), full_config)

    def test_update_removes_empty(self):
        config = {"foo": "bar", "baz": "bza"}
        self.config_manager.update(config)
        self.config_manager.update({"foo": None})
        self.assertEqual(self.read_config("regiond.conf"), {"baz": "bza"})

    def test_update_with_maas_url(self):
        url = factory.make_name("url")
        self.config_manager.update({"maas_url": url})
        expected = {"maas_url": url}
        self.assertEqual(self.read_config("regiond.conf"), expected)
        # MAAS url is set in rackd config as well
        self.assertEqual(self.read_config("rackd.conf"), expected)

    def test_unset_maas_url(self):
        config = {"maas_url": factory.make_name("url")}
        self.write_config(config, "regiond.conf")
        self.write_config(config, "rackd.conf")
        self.config_manager.update({"maas_url": None})
        self.assertEqual(self.read_config("regiond.conf"), {})
        self.assertEqual(self.read_config("rackd.conf"), {})
Exemplo n.º 16
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'init' command must be run by root.")

        mode = options.run_mode
        if options.deprecated_mode:
            mode = options.deprecated_mode
        current_mode = get_current_mode()
        if current_mode != "none":
            if not options.force:
                init_text = "initialize again"
                if mode == "none":
                    init_text = "de-initialize"
                else:
                    print_msg("Controller has already been initialized.")
                initialize = prompt_for_choices(
                    "Are you sure you want to %s "
                    "(yes/no) [default=no]? " % init_text,
                    ["yes", "no"],
                    default="no",
                )
                if initialize == "no":
                    sys.exit(0)

        if current_mode == "all" and mode != "all" and not options.force:
            print_msg(
                "This will disconnect your MAAS from the running database.")
            disconnect = prompt_for_choices(
                "Are you sure you want to disconnect the database "
                "(yes/no) [default=no]? ",
                ["yes", "no"],
                default="no",
            )
            if disconnect == "no":
                return 0
        elif current_mode == "all" and mode == "all" and not options.force:
            print_msg("This will re-initialize your entire database and all "
                      "current data will be lost.")
            reinit_db = prompt_for_choices(
                "Are you sure you want to re-initialize the database "
                "(yes/no) [default=no]? ",
                ["yes", "no"],
                default="no",
            )
            if reinit_db == "no":
                return 0

        rpc_secret = None
        if mode == "all":
            database_settings = {
                "database_host":
                os.path.join(get_base_db_dir(), "sockets"),
                "database_name":
                "maasdb",
                "database_user":
                "******",
                "database_pass":
                "".join(
                    random.choice(string.ascii_uppercase + string.digits)
                    for _ in range(10)),
            }
        elif mode in ["region", "region+rack"]:
            try:
                database_settings = get_database_settings(options)
            except DatabaseSettingsError as error:
                raise CommandError(str(error))
        else:
            database_settings = {}
        maas_url = options.maas_url
        if mode != "none" and not maas_url:
            maas_url = required_prompt(
                "MAAS URL",
                default=get_default_url(),
                help_text=ARGUMENTS["maas-url"]["help"],
            )
        if mode == "rack":
            rpc_secret = options.secret
            if not rpc_secret:
                rpc_secret = required_prompt(
                    "Secret", help_text=ARGUMENTS["secret"]["help"])

        # Stop all services if in another mode.
        if current_mode != "none":

            def stop_services():
                render_supervisord("none")
                sighup_supervisord()

            perform_work("Stopping services", stop_services)

        # Configure the settings.
        settings = {"maas_url": maas_url}
        settings.update(database_settings)

        MAASConfiguration().update(settings)
        set_rpc_secret(rpc_secret)

        # Finalize the Initialization.
        self._finalize_init(mode, options)
Exemplo n.º 17
0
 def setUp(self):
     super().setUp()
     self.config_dir = Path(self.make_dir())
     self.environ = {'SNAP_DATA': self.config_dir}
     self.config_manager = MAASConfiguration(environ=self.environ)
Exemplo n.º 18
0
class TestMAASConfiguration(MAASTestCase):
    def setUp(self):
        super().setUp()
        self.config_dir = Path(self.make_dir())
        self.environ = {'SNAP_DATA': self.config_dir}
        self.config_manager = MAASConfiguration(environ=self.environ)

    def write_config(self, config, filename):
        config_file = self.config_dir / filename
        config_file.write_text(yaml.safe_dump(config))

    def read_config(self, filename):
        config_file = self.config_dir / filename
        if not config_file.exists():
            return None
        return yaml.safe_load(config_file.read_text())

    def test_get_not_in_snap(self):
        config_manager = MAASConfiguration(environ={})
        # use mocked dir instead of /etc/maas
        config_manager.DEFAULT_CONFIG_DIR = self.config_dir
        config = {
            factory.make_name('key'): factory.make_name('value'),
            factory.make_name('key'): factory.make_name('value')
        }
        self.write_config(config, 'regiond.conf')
        self.assertEqual(config_manager.get(), config)

    def test_get(self):
        config = {
            factory.make_name('key'): factory.make_name('value'),
            factory.make_name('key'): factory.make_name('value')
        }
        self.write_config(config, 'regiond.conf')
        self.assertEqual(self.config_manager.get(), config)

    def test_get_empty(self):
        self.assertEqual(self.config_manager.get(), {})

    def test_write_to_file(self):
        config = {
            factory.make_name('key'): factory.make_name('value'),
            factory.make_name('key'): factory.make_name('value')
        }
        filename = factory.make_name('file')
        self.config_manager.write_to_file(config, filename)
        self.assertEqual(self.read_config(filename), config)

    def test_update_updates(self):
        config1 = {'foo': 'bar'}
        config2 = {'foo': 'baz'}
        self.config_manager.update(config1)
        self.config_manager.update(config2)
        self.assertEqual(self.read_config('regiond.conf'), config2)

    def test_update_from_empty_file(self):
        config = {factory.make_name('key'): factory.make_name('value')}
        (self.config_dir / 'regiond.conf').touch()
        self.config_manager.update(config)
        self.assertEqual(self.read_config('regiond.conf'), config)

    def test_update_sets(self):
        config = {
            factory.make_name('key'): factory.make_name('value'),
            factory.make_name('key'): factory.make_name('value')
        }
        self.config_manager.update(config)
        self.assertEqual(self.read_config('regiond.conf'), config)
        # no rackd config is written
        self.assertIsNone(self.read_config('rackd.conf'))

    def test_update_extends(self):
        config1 = {'foo': 'bar'}
        config2 = {'baz': 'bza'}
        self.config_manager.update(config1)
        self.config_manager.update(config2)
        full_config = {}
        full_config.update(config1)
        full_config.update(config2)
        self.assertEqual(self.read_config('regiond.conf'), full_config)

    def test_update_removes_empty(self):
        config = {'foo': 'bar', 'baz': 'bza'}
        self.config_manager.update(config)
        self.config_manager.update({'foo': None})
        self.assertEqual(self.read_config('regiond.conf'), {'baz': 'bza'})

    def test_update_with_maas_url(self):
        url = factory.make_name('url')
        self.config_manager.update({'maas_url': url})
        expected = {'maas_url': url}
        self.assertEqual(self.read_config('regiond.conf'), expected)
        # MAAS url is set in rackd config as well
        self.assertEqual(self.read_config('rackd.conf'), expected)

    def test_unset_maas_url(self):
        config = {'maas_url': factory.make_name('url')}
        self.write_config(config, 'regiond.conf')
        self.write_config(config, 'rackd.conf')
        self.config_manager.update({'maas_url': None})
        self.assertEqual(self.read_config('regiond.conf'), {})
        self.assertEqual(self.read_config('rackd.conf'), {})
Exemplo n.º 19
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'init' command must be run by root.")

        mode = options.mode
        current_mode = get_current_mode()
        if current_mode != "none":
            if not options.force:
                init_text = "initialize again"
                if mode == "none":
                    init_text = "de-initialize"
                else:
                    print_msg("Controller has already been initialized.")
                initialize = prompt_for_choices(
                    "Are you sure you want to %s "
                    "(yes/no) [default=no]? " % init_text,
                    ["yes", "no"],
                    default="no",
                )
                if initialize == "no":
                    sys.exit(0)

        if not mode:
            mode = prompt_for_choices(
                "Mode ({choices}) [default={default}]? ".format(
                    choices="/".join(ARGUMENTS["mode"]["choices"]),
                    default=DEFAULT_OPERATION_MODE,
                ),
                ARGUMENTS["mode"]["choices"],
                default=DEFAULT_OPERATION_MODE,
                help_text=OPERATION_MODES,
            )
        if current_mode == "all" and mode != "all" and not options.force:
            print_msg(
                "This will disconnect your MAAS from the running database.")
            disconnect = prompt_for_choices(
                "Are you sure you want to disconnect the database "
                "(yes/no) [default=no]? ",
                ["yes", "no"],
                default="no",
            )
            if disconnect == "no":
                return 0
        elif current_mode == "all" and mode == "all" and not options.force:
            print_msg("This will re-initialize your entire database and all "
                      "current data will be lost.")
            reinit_db = prompt_for_choices(
                "Are you sure you want to re-initialize the database "
                "(yes/no) [default=no]? ",
                ["yes", "no"],
                default="no",
            )
            if reinit_db == "no":
                return 0

        maas_url = options.maas_url
        if mode != "none" and not maas_url:
            maas_url = prompt_for_maas_url()
        database_host = database_name = None
        database_user = database_pass = None
        rpc_secret = None
        if mode == "all":
            database_host = os.path.join(get_base_db_dir(), "sockets")
            database_name = "maasdb"
            database_user = "******"
            database_pass = "".join(
                random.choice(string.ascii_uppercase + string.digits)
                for _ in range(10))
        if mode in ["region", "region+rack"]:
            database_host = options.database_host
            if not database_host:
                database_host = required_prompt(
                    "Database host: ",
                    help_text=ARGUMENTS["database-host"]["help"],
                )
            database_name = options.database_name
            if not database_name:
                database_name = required_prompt(
                    "Database name: ",
                    help_text=ARGUMENTS["database-name"]["help"],
                )
            database_user = options.database_user
            if not database_user:
                database_user = required_prompt(
                    "Database user: "******"database-user"]["help"],
                )
            database_pass = options.database_pass
            if not database_pass:
                database_pass = required_prompt(
                    "Database password: "******"database-pass"]["help"],
                )
        if mode == "rack":
            rpc_secret = options.secret
            if not rpc_secret:
                rpc_secret = required_prompt(
                    "Secret: ", help_text=ARGUMENTS["secret"]["help"])

        # Stop all services if in another mode.
        if current_mode != "none":

            def stop_services():
                render_supervisord("none")
                sighup_supervisord()

            perform_work("Stopping services", stop_services)

        # Configure the settings.
        settings = {
            "maas_url": maas_url,
            "database_host": database_host,
            "database_name": database_name,
            "database_user": database_user,
            "database_pass": database_pass,
        }

        # Add the port to the configuration if exists. By default
        # MAAS handles picking the port automatically in the backend
        # if none provided.
        if options.database_port:
            settings["database_port"] = options.database_port

        MAASConfiguration().update(settings)
        set_rpc_secret(rpc_secret)

        # Finalize the Initialization.
        self._finalize_init(mode, options)