Пример #1
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)
Пример #2
0
    def _finalize_init(self, mode, options):
        # Configure mode.
        def start_services():
            render_supervisord(mode)
            set_current_mode(mode)
            sighup_supervisord()

        perform_work(
            "Starting services" if mode != "none" else "Stopping services",
            start_services,
        )

        if mode in ("region", "region+rack") and db_need_init():
            # When in 'region' or 'region+rack' the migrations for the database
            # must be at the same level as this controller.
            perform_work(
                "Performing database migrations",
                migrate_db,
                capture=sys.stdout.isatty(),
            )
            print_msg(
                dedent("""\
                    MAAS has been set up.

                    If you want to configure external authentication or use
                    MAAS with Canonical RBAC, please run

                      sudo maas configauth

                    To create admins when not using external authentication, run

                      sudo maas createadmin
                    """))
Пример #3
0
def print_config_value(config_name, hidden=False):
    """Print the configuration value to stdout."""
    if hidden:
        print_msg("%s=(hidden)" % config_name)
    else:
        config_value = get_config_value(config_name)
        print_msg("%s=%s" % (config_name, config_value))
Пример #4
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'migrate' command must be run by root.")

        # Hidden parameter that is only called from the configure hook. Updates
        # the database when running in all mode.
        if options.configure:
            current_mode = get_current_mode()
            if current_mode == 'all':
                wait_for_postgresql()
                sys.exit(migrate_db())
            elif current_mode in ['region', 'region+rack']:
                sys.exit(migrate_db())
            else:
                # In 'rack' or 'none' mode, nothing to do.
                sys.exit(0)

        mode = get_current_mode()
        if mode == 'none':
            print_msg('MAAS is not configured')
            sys.exit(1)
        elif mode == 'rack':
            print_msg("Mode 'rack' is not connected to a database. "
                      "No migrations to perform.")
            sys.exit(1)
        else:
            sys.exit(migrate_db())
Пример #5
0
def required_prompt(prompt, help_text=None):
    """Prompt for required input."""
    value = None
    while not value or value == "help":
        value = read_input(prompt)
        if value == "help":
            if help_text:
                print_msg(help_text)
    return value
Пример #6
0
 def _write_msg(evnt):
     idx = 0
     while not evnt.is_set():
         # Print the message with a spinner until the work is complete.
         print_msg("\r[%s] %s" % (spinner[idx], msg), newline=False)
         idx += 1
         if idx == 8:
             idx = 0
         time.sleep(0.25)
     # Clear the line so previous message is not show if the next message
     # is not as long as this message.
     print_msg('\r' + ' ' * (len(msg) + 4), newline=False)
Пример #7
0
def prompt_for_maas_url():
    """Prompt for the MAAS URL."""
    default_url = get_default_url()
    url = None
    while not url or url == "help":
        url = read_input("MAAS URL [default=%s]: " % default_url)
        if not url:
            url = default_url
        if url == "help":
            print_msg(
                'URL that MAAS should use for communicate from the nodes '
                'to MAAS and other controllers of MAAS.')
    return url
Пример #8
0
 def _validate_flags(self, options, running_mode):
     """
     Validate the flags are correct for the current mode or the new mode.
     """
     invalid_flags = []
     for flag in self.setting_flags + ('secret', ):
         if (flag not in self.required_options[running_mode]
                 and getattr(options, flag)):
             invalid_flags.append('--%s' % flag.replace('_', '-'))
     if len(invalid_flags) > 0:
         print_msg("Following flags are not supported in '%s' mode: %s" %
                   (running_mode, ', '.join(invalid_flags)))
         sys.exit(1)
Пример #9
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'status' command must be run by root.")

        if get_current_mode() == "none":
            print_msg("MAAS is not configured")
            sys.exit(1)
        else:
            process = subprocess.Popen(
                [
                    os.path.join(os.environ["SNAP"], "bin",
                                 "run-supervisorctl"),
                    "status",
                ],
                stdout=subprocess.PIPE,
            )
            ret = process.wait()
            output = process.stdout.read().decode("utf-8")
            if ret == 0:
                print_msg(output, newline=False)
            else:
                if "error:" in output:
                    print_msg("MAAS supervisor is currently restarting. "
                              "Please wait and try again.")
                    sys.exit(-1)
                else:
                    print_msg(output, newline=False)
                    sys.exit(ret)
Пример #10
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')
Пример #11
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")
Пример #12
0
 def _validate_mode(self, options):
     """Validate the parameters are correct for changing the mode."""
     if options.mode is not None:
         if options.mode != get_current_mode():
             # Changing the mode, ensure that the required parameters
             # are passed for this mode.
             missing_flags = []
             for flag in self.required_options[options.mode]:
                 if not getattr(options, flag):
                     missing_flags.append('--%s' % flag.replace('_', '-'))
             if len(missing_flags) > 0:
                 print_msg("Changing mode to '%s' requires parameters: %s" %
                           (options.mode, ', '.join(missing_flags)))
                 sys.exit(1)
Пример #13
0
def perform_work(msg, cmd, *args, **kwargs):
    """Perform work.

    Executes the `cmd` and while its running it prints a nice message.
    """
    # When not running in a terminal, just print the message once and perform
    # the operation.
    if not sys.stdout.isatty():
        print_msg(msg)
        return cmd(*args, **kwargs)

    spinner = {
        0: '/',
        1: '-',
        2: '\\',
        3: '|',
        4: '/',
        5: '-',
        6: '\\',
        7: '|',
    }

    def _write_msg(evnt):
        idx = 0
        while not evnt.is_set():
            # Print the message with a spinner until the work is complete.
            print_msg(
                "\r[%s] %s" % (spinner[idx], msg), newline=False)
            idx += 1
            if idx == 8:
                idx = 0
            time.sleep(0.25)
        # Clear the line so previous message is not show if the next message
        # is not as long as this message.
        print_msg('\r' + ' ' * (len(msg) + 4), newline=False)

    # Spawn a thread to print the message, while performing the work in the
    # current execution thread.
    evnt = threading.Event()
    t = threading.Thread(target=_write_msg, args=(evnt,))
    t.start()
    try:
        ret = cmd(*args, **kwargs)
    finally:
        evnt.set()
        t.join()
    return ret
Пример #14
0
def required_prompt(title, help_text=None, default=None):
    """Prompt for required input."""
    value = None
    if default is not None:
        default_text = f" [default={default}]"
    else:
        default_text = ""
    prompt = f"{title}{default_text}: "
    while not value or value == "help":
        value = read_input(prompt)
        if not value and default is not None:
            value = default

        if value == "help":
            if help_text:
                print_msg(help_text)
    return value
Пример #15
0
 def _parse_known_args(arg_strings, namespace):
     mode_parser = argparse.ArgumentParser(add_help=False)
     add_deprecated_mode_argument(mode_parser)
     options, rest = mode_parser.parse_known_args(arg_strings)
     if options.deprecated_mode is not None:
         if options.deprecated_mode == "all":
             print_msg(
                 "\nWARNING: Passing --mode=all is deprecated and "
                 "will be removed in the 2.9 release.\n"
                 "See https://maas.io/deprecations/MD1 for more details.\n",
                 stderr=True,
             )
         sub_command = ("region+rack" if options.deprecated_mode
                        in ["all", "none"] else options.deprecated_mode)
         arg_strings = [
             f"--mode={options.deprecated_mode}",
             sub_command,
         ] + rest
     return real_parse_known_args(arg_strings, namespace)
Пример #16
0
def migrate_db(capture=False):
    """Migrate the database."""
    if capture:
        process = subprocess.Popen(
            [
                os.path.join(os.environ["SNAP"], "bin", "maas-region"),
                "dbupgrade",
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
        )
        ret = process.wait()
        output = process.stdout.read().decode("utf-8")
        if ret != 0:
            clear_line()
            print_msg("Failed to perfom migrations:")
            print_msg(output)
            print_msg("")
            sys.exit(ret)
    else:
        subprocess.check_call(
            [
                os.path.join(os.environ["SNAP"], "bin", "maas-region"),
                "dbupgrade",
            ]
        )
Пример #17
0
    def handle(self, options):
        if os.getuid() != 0:
            raise SystemExit("The 'migrate' command must be run by root.")

        current_mode = get_current_mode()
        if options.configure:
            if current_mode == "all":
                wait_for_postgresql()
                sys.exit(migrate_db())
            elif current_mode in ["region", "region+rack"]:
                sys.exit(migrate_db())
            else:
                # In 'rack' or 'none' mode, nothing to do.
                sys.exit(0)

        if current_mode == "none":
            print_msg("MAAS is not configured")
            sys.exit(1)
        elif current_mode == "rack":
            print_msg("Mode 'rack' is not connected to a database. "
                      "No migrations to perform.")
            sys.exit(1)
        else:
            sys.exit(migrate_db())
Пример #18
0
 def handle(self, options):
     if get_current_mode() == 'none':
         print_msg('MAAS is not configured')
         sys.exit(1)
     else:
         process = subprocess.Popen([
             os.path.join(os.environ['SNAP'], 'bin', 'run-supervisorctl'),
             'status'
         ],
                                    stdout=subprocess.PIPE)
         ret = process.wait()
         output = process.stdout.read().decode('utf-8')
         if ret == 0:
             print_msg(output, newline=False)
         else:
             if 'error:' in output:
                 print_msg('MAAS supervisor is currently restarting. '
                           'Please wait and try again.')
                 sys.exit(-1)
             else:
                 print_msg(output, newline=False)
                 sys.exit(ret)
Пример #19
0
def migrate_db(capture=False):
    """Migrate the database."""
    if capture:
        process = subprocess.Popen([
            os.path.join(os.environ['SNAP'], 'bin', 'maas-region'), 'dbupgrade'
        ],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT)
        ret = process.wait()
        output = process.stdout.read().decode('utf-8')
        if ret != 0:
            clear_line()
            print_msg('Failed to perfom migrations:')
            print_msg(output)
            print_msg('')
            sys.exit(ret)
    else:
        subprocess.check_call([
            os.path.join(os.environ['SNAP'], 'bin', 'maas-region'), 'dbupgrade'
        ])
Пример #20
0
 def test_print_msg_empty_message(self):
     init.print_msg()
     self.mock_print.assert_called_with('', end='\n', flush=True)
Пример #21
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()
Пример #22
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)
Пример #23
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()
Пример #24
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)
Пример #25
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)
Пример #26
0
def prompt_for_choices(prompt, choices, default=None, help_text=None):
    """Prompt requires specific choice answeres.

    If `help_text` is provided the 'help' is added as a choice.
    """
    invalid_msg = 'Invalid input, try again'
    if help_text:
        invalid_msg += " or type 'help'"
    invalid_msg += '.'
    value = None
    while True:
        value = read_input(prompt)
        if not value:
            if default:
                return default
            else:
                print_msg(invalid_msg)
                print_msg()
        elif value == 'help' and help_text:
            print_msg(help_text)
            print_msg()
        elif value not in choices:
            print_msg(invalid_msg)
            print_msg()
        else:
            return value
Пример #27
0
def clear_line():
    """Resets the current line when in a terminal."""
    if sys.stdout.isatty():
        print_msg('\r' + ' ' * int(os.environ.get('COLUMNS', 0)),
                  newline=False)
Пример #28
0
def clear_line():
    """Resets the current line when in a terminal."""
    if sys.stdout.isatty():
        print_msg("\r" + " " * int(os.environ.get("COLUMNS", 0)),
                  newline=False)
Пример #29
0
def print_config_value(config, key, hidden=False):
    """Print the configuration value to stdout."""
    template = '{key}=(hidden)' if hidden else '{key}={value}'
    print_msg(template.format(key=key, value=config.get(key)))
Пример #30
0
 def test_print_msg_empty_message(self):
     init.print_msg()
     self.mock_print.assert_called_with("",
                                        end="\n",
                                        file=sys.stdout,
                                        flush=True)