Пример #1
0
 def test_set_and_get_tftp_port(self):
     config = ClusterConfiguration({})
     example_port = factory.pick_port()
     config.tftp_port = example_port
     self.assertEqual(example_port, config.tftp_port)
     # It's also stored in the configuration database.
     self.assertEqual({"tftp_port": example_port}, config.store)
Пример #2
0
 def test_set_and_get_cluster_uuid(self):
     example_uuid = uuid4()
     config = ClusterConfiguration({})
     config.cluster_uuid = example_uuid
     self.assertEqual(str(example_uuid), config.cluster_uuid)
     # It's also stored in the configuration database.
     self.assertEqual({"cluster_uuid": str(example_uuid)}, config.store)
Пример #3
0
 def test_set_maas_url_accepts_very_short_hostnames(self):
     config = ClusterConfiguration({})
     example_url = factory.make_simple_http_url(netloc=factory.make_string(
         size=1))
     config.maas_url = example_url
     self.assertEqual(example_url, config.maas_url)
     self.assertEqual({"maas_url": example_url}, config.store)
Пример #4
0
 def test_set_maas_url_accepts_ipv6_addresses_with_brackets(self):
     config = ClusterConfiguration({})
     example_url = factory.make_simple_http_url(netloc="[%s]" %
                                                factory.make_ipv6_address())
     config.maas_url = example_url
     self.assertEqual(example_url, config.maas_url)
     self.assertEqual({"maas_url": example_url}, config.store)
Пример #5
0
 def test_set_maas_url_rejects_bare_ipv6_addresses(self):
     config = ClusterConfiguration({})
     example_url = factory.make_simple_http_url(
         netloc=factory.make_ipv6_address()
     )
     with ExpectedException(formencode.api.Invalid):
         config.maas_url = example_url
Пример #6
0
 def test_set_and_get_maas_url(self):
     config = ClusterConfiguration({})
     example_url = factory.make_simple_http_url()
     config.maas_url = example_url
     self.assertEqual(example_url, config.maas_url)
     # It's also stored in the configuration database.
     self.assertEqual({"maas_url": example_url}, config.store)
Пример #7
0
 def test_config_set_maas_url_without_setting_does_nothing(self):
     with ClusterConfiguration.open() as config:
         expected = config.maas_url
     cluster_config_command.run(self.make_args(region_url=None))
     with ClusterConfiguration.open() as config:
         observed = config.maas_url
     self.assertEqual(expected, observed)
Пример #8
0
 def test_config_set_tftp_root_without_setting_does_nothing(self):
     with ClusterConfiguration.open() as config:
         expected = config.tftp_root
     cluster_config_command.run(self.make_args(tftp_root=None))
     with ClusterConfiguration.open() as config:
         observed = config.tftp_root
     self.assertEqual(expected, observed)
Пример #9
0
 def test_config_set_debug_without_setting_does_nothing(self):
     with ClusterConfiguration.open() as config:
         expected = config.debug
     cluster_config_command.run(self.make_args(debug=None))
     with ClusterConfiguration.open() as config:
         observed = config.debug
     self.assertEqual(expected, observed)
Пример #10
0
 def test_set_and_get_tftp_root(self):
     config = ClusterConfiguration({})
     example_dir = self.make_dir()
     config.tftp_root = example_dir
     self.assertEqual(example_dir, config.tftp_root)
     # It's also stored in the configuration database.
     self.assertEqual({"tftp_root": example_dir}, config.store)
Пример #11
0
    def test_config_init_when_already_configured_does_nothing(self):
        expected_previous_value = str(uuid.uuid4())
        with ClusterConfiguration.open_for_update() as config:
            config.cluster_uuid = expected_previous_value
        with ClusterConfiguration.open() as config:
            observed_previous_value = config.cluster_uuid
        self.assertEqual(expected_previous_value, observed_previous_value)

        cluster_config_command.run(self.make_args(init=True))

        parsed_observed, observed = self.get_parsed_uuid_from_config()
        self.assertEqual(parsed_observed, observed)
        self.assertEqual(parsed_observed, expected_previous_value)
Пример #12
0
 def get_xinstall_parameters(self, arch, subarch, release, label):
     """Returns the xinstall image name and type for given image."""
     filetypes = {
         "root-tgz": "tgz",
         "root-dd.tar": "dd-tar",
         "root-dd.raw": "dd-raw",
         "root-dd.tar.bz2": "dd-tbz",
         "root-dd": "dd-tgz",
         "root-dd.tar.xz": "dd-txz",
         "root-dd.bz2": "dd-bz2",
         "root-dd.gz": "dd-gz",
         "root-dd.xz": "dd-xz"
     }
     with ClusterConfiguration.open() as config:
         dd_path = os.path.join(config.tftp_root, 'ubuntu-core', arch,
                                subarch, release, label)
     filename, filetype = "", ""
     try:
         for fname in os.listdir(dd_path):
             if fname in filetypes.keys():
                 filename, filetype = fname, filetypes[fname]
                 break
     except FileNotFoundError:
         # In case the path does not exist
         pass
     return filename, filetype
Пример #13
0
 def test_calls_hooks(self):
     upgrade_hook = Mock()
     upgrade_hook.__name__ = "upgrade_hook"
     self.patch_upgrade_hooks([upgrade_hook])
     self.run_command()
     with ClusterConfiguration.open() as config:
         self.assertThat(upgrade_hook, MockCalledOnceWith(config.tftp_root))
Пример #14
0
def get_local_cluster_UUID():
    """Return the UUID of the local cluster (or None if it cannot be found)."""
    with ClusterConfiguration.open() as config:
        if config.cluster_uuid == UUID_NOT_SET:
            return None
        else:
            return config.cluster_uuid
Пример #15
0
def make_maas_own_boot_resources():
    """Upgrade hook: make the `maas` user the owner of the boot resources."""
    # This reduces the privileges required for importing and managing images.
    with ClusterConfiguration.open() as config:
        boot_resources_storage = config.tftp_root
    if os.path.isdir(boot_resources_storage):
        check_call(['chown', '-R', 'maas', boot_resources_storage])
Пример #16
0
    def makeService(self, options, clock=reactor):
        """Construct the MAAS Cluster service."""
        register_sigusr1_toggle_cprofile('rackd')
        register_sigusr2_thread_dump_handler()
        clean_prometheus_dir()
        add_patches_to_txtftp()
        add_patches_to_twisted()

        self._loadSettings()
        self._configureCrochet()
        if settings.DEBUG:
            # Always log at debug level in debug mode.
            self._configureLogging(3)
        else:
            self._configureLogging(options["verbosity"])

        with ClusterConfiguration.open() as config:
            tftp_root = config.tftp_root
            tftp_port = config.tftp_port

        from provisioningserver import services
        for service in self._makeServices(tftp_root, tftp_port, clock=clock):
            service.setServiceParent(services)

        return services
Пример #17
0
def reload_boot_images():
    """Update the cached boot images so `list_boot_images` returns the
    most up-to-date boot images list."""
    global CACHED_BOOT_IMAGES
    with ClusterConfiguration.open() as config:
        tftp_root = config.tftp_root
    CACHED_BOOT_IMAGES = tftppath.list_boot_images(tftp_root)
Пример #18
0
 def _loadSettings(self):
     # Load the settings from rackd.conf.
     with ClusterConfiguration.open() as config:
         settings.DEBUG = config.debug
     # Debug mode is always on in the development environment.
     if is_dev_environment():
         settings.DEBUG = True
Пример #19
0
 def get_resource_path(self, kernel_params, path):
     """Gets the resource path from the kernel param."""
     with ClusterConfiguration.open() as config:
         resources = config.tftp_root
     return os.path.join(resources, 'windows', kernel_params.arch,
                         kernel_params.subarch, kernel_params.release,
                         kernel_params.label, path)
Пример #20
0
def update_maas_cluster_conf(urls=None,
                             uuid=None,
                             init=None,
                             tftp_port=None,
                             tftp_root=None,
                             debug=None):
    """This function handles the logic behind using the parameters passed to
    run and setting / initializing values in the config backend.

    :param urls: The MAAS URLs to set. Does nothing if None.
    :param tftp_port: The tftp port number to set. Does nothing if None.
    :param tftp_root: The tftp root file path to set. Does nothing if None.
    :param uuid: The UUID to use for this cluster. Does nothing if None.
    :param init: Initializes the config backend with a new UUID if
    the backend does not currently have a value configured.
    NOTE: that the argument parser will not let uuid
    and init be passed at the same time, as these are mutually exclusive
    parameters.
    :param debug: Enables or disables debug mode.
    """
    with ClusterConfiguration.open_for_update() as config:
        if urls is not None:
            config.maas_url = urls
        if uuid is not None:
            config.cluster_uuid = uuid
        if init:
            cur_uuid = config.cluster_uuid
            if cur_uuid == UUID_NOT_SET:
                config.cluster_uuid = str(uuid4())
        if tftp_port is not None:
            config.tftp_port = tftp_port
        if tftp_root is not None:
            config.tftp_root = tftp_root
        if debug is not None:
            config.debug = debug
Пример #21
0
 def test____sets_url(self):
     secret = factory.make_bytes()
     expected_url = factory.make_simple_http_url()
     register_command.run(
         self.make_args(url=expected_url, secret=to_hex(secret)))
     with ClusterConfiguration.open() as config:
         observed = config.maas_url
     self.assertEqual([expected_url], observed)
Пример #22
0
 def test_default_tftp_root(self):
     # The default tftp_root is calculated relative to MAAS_ROOT at module
     # import time, so we need to recreate that value.
     maas_root = os.path.join(maastesting.root, ".run")
     config = ClusterConfiguration({})
     self.assertEqual(
         os.path.join(maas_root, "var/lib/maas/boot-resources/current"),
         config.tftp_root)
Пример #23
0
def run(args):
    """Register the rack controller with a region controller."""
    # If stdin supplied to program URL must be passed as argument.
    if not stdin.isatty() and args.url is None:
        print(
            "MAAS region controller URL must be given when supplying the "
            "shared secret via stdin with a non-interactive shell."
        )
        raise SystemExit(1)
    try:
        call_and_check(["systemctl", "stop", "maas-rackd"])
    except ExternalProcessError as e:
        print("Unable to stop maas-rackd service.", file=stderr)
        print("Failed with error: %s." % e.output_as_unicode, file=stderr)
        raise SystemExit(1)
    # maas_id could be stale so remove it
    set_maas_id(None)
    if args.url is not None:
        with ClusterConfiguration.open_for_update() as config:
            config.maas_url = args.url
    else:
        try:
            url = input("MAAS region controller URL: ")
        except EOFError:
            print()  # So that the shell prompt appears on the next line.
            raise SystemExit(1)
        except KeyboardInterrupt:
            print()  # So that the shell prompt appears on the next line.
            raise
        with ClusterConfiguration.open_for_update() as config:
            config.maas_url = url
        print("MAAS region controller URL saved as %s." % url)
    if args.secret is not None:
        set_shared_secret_on_filesystem(to_bin(args.secret))
    else:
        InstallSharedSecretScript.run(args)
    try:
        call_and_check(["systemctl", "enable", "maas-rackd"])
        call_and_check(["systemctl", "start", "maas-rackd"])
    except ExternalProcessError as e:
        print(
            "Unable to enable and start the maas-rackd service.", file=stderr
        )
        print("Failed with error: %s." % e.output_as_unicode, file=stderr)
        raise SystemExit(1)
Пример #24
0
def filter_out_directories_with_extra_levels(paths):
    """Remove paths that contain directories with more levels. We don't want
    to move other operating systems under the ubuntu directory."""
    with ClusterConfiguration.open() as config:
        tftp_root = config.tftp_root
    for arch, subarch, release, label in paths:
        path = os.path.join(tftp_root, arch, subarch, release, label)
        if len(list_subdirs(path)) == 0:
            yield (arch, subarch, release, label)
Пример #25
0
    def test_config_init_creates_initial_cluster_id(self):
        with ClusterConfiguration.open() as config:
            observed_default = config.cluster_uuid
        self.assertEqual(UUID_NOT_SET, observed_default)

        cluster_config_command.run(self.make_args(init=True))

        expected, observed = self.get_parsed_uuid_from_config()
        self.assertEqual(expected, observed)
Пример #26
0
    def get_parsed_uuid_from_config(self):
        with ClusterConfiguration.open() as config:
            observed = config.cluster_uuid
        try:
            parsed_observed = str(uuid.UUID(observed))
        except:
            parsed_observed = None

        return (parsed_observed, observed)
Пример #27
0
def run(args):
    """Install a GRUB2 pre-boot loader config into the TFTP
    directory structure.
    """
    with ClusterConfiguration.open() as config:
        if not os.path.exists(config.grub_root):
            os.makedirs(config.grub_root)
        destination_file = os.path.join(config.grub_root, "grub.cfg")
    write_text_file(destination_file, CONFIG_FILE)
Пример #28
0
def run(args):
    """Perform any data migrations needed for upgrading this cluster."""
    with ClusterConfiguration.open() as config:
        tftp_root = config.tftp_root
    for hook in UPGRADE_HOOKS:
        maaslog.info("Rack controller upgrade hook '%s' started." %
                     hook.__name__)
        hook(tftp_root)
        maaslog.info("Rack controller upgrade hook '%s' finished." %
                     hook.__name__)
Пример #29
0
def get_cluster_configuration():
    config_dict = {}
    try:
        with ClusterConfiguration.open() as configuration:
            for var in vars(ClusterConfiguration):
                if not var.startswith("_"):
                    config_dict[var] = getattr(configuration, var)
    except Exception:
        print("Warning: Could not load cluster configuration.")
        print("(some data may not be accurate)")
        print()
    return config_dict
Пример #30
0
    def _find_image(
        self,
        arch,
        subarch,
        release,
        label,
        squashfs=False,
        tgz=False,
        dd=False,
        default_fname=None,
    ):
        filetypes = {}
        if squashfs:
            filetypes.update({"squashfs": "squashfs"})
        if tgz:
            filetypes.update(
                {"root-tgz": "tgz", "root-txz": "txz", "root-tbz": "tbz"}
            )
        if dd:
            filetypes.update(
                {
                    # root-dd maps to dd-tgz for backwards compatibility.
                    "root-dd": "dd-tgz",
                    "root-dd.tar": "dd-tar",
                    "root-dd.raw": "dd-raw",
                    "root-dd.bz2": "dd-bz2",
                    "root-dd.gz": "dd-gz",
                    "root-dd.xz": "dd-xz",
                    "root-dd.tar.bz2": "dd-tbz",
                    "root-dd.tar.xz": "dd-txz",
                }
            )

        with ClusterConfiguration.open() as config:
            base_path = os.path.join(
                config.tftp_root, self.name, arch, subarch, release, label
            )

        try:
            for fname in os.listdir(base_path):
                if fname in filetypes.keys():
                    return fname, filetypes[fname]
        except FileNotFoundError:
            # In case the path does not exist
            pass

        assert squashfs or tgz or dd, "One type must be selected"
        # If none is found return the default for messaging.
        if default_fname and default_fname in filetypes:
            return default_fname, filetypes[default_fname]
        else:
            return list(filetypes.items())[0]