Пример #1
0
 def test_configure(self):
     servers = [
         factory.make_ipv4_address(),
         factory.make_ipv6_address(),
         factory.make_hostname(),
     ]
     peers = [
         factory.make_ipv4_address(),
         factory.make_ipv6_address(),
         factory.make_hostname(),
     ]
     offset = randrange(0, 5)
     config.configure(servers, peers, offset)
     ntp_conf_path = get_data_path("etc", config._ntp_conf_name)
     ntp_maas_conf_path = get_data_path("etc", config._ntp_maas_conf_name)
     ntp_conf = read_configuration(ntp_conf_path)
     self.assertThat(extract_servers_and_pools(ntp_conf), Equals([]))
     self.assertThat(extract_included_files(ntp_conf),
                     Equals([ntp_maas_conf_path]))
     ntp_maas_conf = read_configuration(ntp_maas_conf_path)
     self.assertThat(extract_servers_and_pools(ntp_maas_conf),
                     Equals(servers))
     self.assertThat(extract_peers(ntp_maas_conf), Equals(peers))
     self.assertThat(extract_tos_options(ntp_maas_conf),
                     Equals([str(offset + 8), "orphan"]))
Пример #2
0
 def test_can_write_file_in_development(self):
     filename = get_data_path("/var/lib/maas/dhcpd.conf")
     contents = factory.make_bytes()  # Binary safe.
     mode = random.randint(0o000, 0o777) | 0o400  # Always u+r.
     sudo_write_file(filename, contents, mode)
     self.assertThat(filename, FileContains(contents))
     self.assertThat(os.stat(filename).st_mode & 0o777, Equals(mode))
Пример #3
0
    def _makeTFTPService(self, tftp_root, tftp_port, rpc_service):
        """Create the dynamic TFTP service."""
        from provisioningserver.rackdservices.tftp import TFTPService
        tftp_service = TFTPService(resource_root=tftp_root,
                                   port=tftp_port,
                                   client_service=rpc_service)
        tftp_service.setName("tftp")

        # *** EXPERIMENTAL ***
        # https://code.launchpad.net/~allenap/maas/tftp-offload/+merge/312146
        # If the TFTP port has been set to zero, use the experimental offload
        # service. Otherwise stick to the normal in-process TFTP service.
        if tftp_port == 0:
            from provisioningserver.path import get_data_path
            from provisioningserver.rackdservices import tftp_offload
            from twisted.internet.endpoints import UNIXServerEndpoint
            tftp_offload_socket = get_data_path(
                "/var/lib/maas/tftp-offload.sock")
            tftp_offload_endpoint = UNIXServerEndpoint(reactor,
                                                       tftp_offload_socket,
                                                       wantPID=False)
            tftp_offload_service = tftp_offload.TFTPOffloadService(
                reactor, tftp_offload_endpoint, tftp_service.backend)
            tftp_offload_service.setName("tftp-offload")
            return tftp_offload_service
        # *** /EXPERIMENTAL ***

        return tftp_service
Пример #4
0
 def test_delete(self):
     self.set_envvar(None)
     example_file = factory.make_name("config")
     self.example_configuration.DEFAULT_FILENAME = example_file
     del self.example_configuration.DEFAULT_FILENAME
     self.assertEqual(get_data_path(self.example_configuration.default),
                      self.example_configuration.DEFAULT_FILENAME)
     # The delete does not fail when called multiple times.
     del self.example_configuration.DEFAULT_FILENAME
Пример #5
0
def get_config_v4(template_name: str, global_dhcp_snippets: Sequence[dict],
                  failover_peers: Sequence[dict],
                  shared_networks: Sequence[dict], hosts: Sequence[dict],
                  omapi_key: str) -> str:
    """Return a DHCP config file based on the supplied parameters.

    :param template_name: Template file name: `dhcpd.conf.template` for the
        IPv4 template.
    :return: A full configuration, as a string.
    """
    platform_codename = linux_distribution()[2]
    template = load_template('dhcp', template_name)
    dhcp_socket = get_data_path('/var/lib/maas/dhcpd.sock')

    # Helper functions to stuff into the template namespace.
    helpers = {
        "oneline": normalise_whitespace,
        "commalist": normalise_any_iterable_to_comma_list,
        "quoted_commalist": normalise_any_iterable_to_quoted_comma_list,
        "running_in_snap": snappy.running_in_snap(),
    }

    rack_addrs = [
        IPAddress(addr) for addr in net_utils.get_all_interface_addresses()
    ]

    for shared_network in shared_networks:
        for subnet in shared_network["subnets"]:
            cidr = IPNetwork(subnet['subnet_cidr'])
            rack_ips = [
                str(rack_addr) for rack_addr in rack_addrs if rack_addr in cidr
            ]
            if len(rack_ips) > 0:
                subnet["next_server"] = rack_ips[0]
                subnet["bootloader"] = compose_conditional_bootloader(
                    False, rack_ips[0])
            ntp_servers = subnet["ntp_servers"]  # Is a list.
            ntp_servers_ipv4, ntp_servers_ipv6 = _get_addresses(*ntp_servers)
            subnet["ntp_servers_ipv4"] = ", ".join(ntp_servers_ipv4)
            subnet["ntp_servers_ipv6"] = ", ".join(ntp_servers_ipv6)

    try:
        return template.substitute(
            global_dhcp_snippets=global_dhcp_snippets,
            hosts=hosts,
            failover_peers=failover_peers,
            shared_networks=shared_networks,
            platform_codename=platform_codename,
            omapi_key=omapi_key,
            dhcp_helper=(get_path('/usr/sbin/maas-dhcp-helper')),
            dhcp_socket=dhcp_socket,
            **helpers)
    except (KeyError, NameError) as error:
        raise DHCPConfigError(
            "Failed to render DHCP configuration.") from error
Пример #6
0
 def __init__(self, name, reactor=None):
     if not isinstance(name, str):
         raise TypeError("Lock name must be str, not %s" %
                         type(name).__qualname__)
     elif not self.ACCEPTABLE_CHARACTERS.issuperset(name):
         illegal = set(name) - self.ACCEPTABLE_CHARACTERS
         raise ValueError("Lock name contains illegal characters: %s" %
                          "".join(sorted(illegal)))
     else:
         lockpath = get_data_path("run", "lock", "maas:%s" % name)
         super(NamedLock, self).__init__(lockpath, reactor=reactor)
Пример #7
0
 def setUp(self):
     """Ensures each test starts cleanly, with no pre-existing secret."""
     get_secret = self.patch(security, "get_shared_secret_filesystem_path")
     # Ensure each test uses a different filename for the shared secret,
     # so that tests cannot interfere with each other.
     get_secret.return_value = get_data_path(
         "var", "lib", "maas", "secret-%s" % factory.make_string(16))
     # Extremely unlikely, but just in case.
     self.delete_secret()
     self.addCleanup(
         setattr, security, "DEFAULT_ITERATION_COUNT",
         security.DEFAULT_ITERATION_COUNT)
     # The default high iteration count would make the tests very slow.
     security.DEFAULT_ITERATION_COUNT = 2
     super().setUp()
Пример #8
0
def set_maas_id(system_id):
    """Set the system_id for this rack/region permanently for MAAS."""
    global _maas_id
    system_id = _normalise_maas_id(system_id)
    with _maas_id_lock:
        maas_id_path = get_data_path("/var/lib/maas/maas_id")
        if system_id is None:
            try:
                atomic_delete(maas_id_path)
            except FileNotFoundError:
                _maas_id = None  # Job done already.
            else:
                _maas_id = None
        else:
            atomic_write(system_id.encode("ascii"), maas_id_path)
            _maas_id = system_id
Пример #9
0
def get_maas_id():
    """Return the system_id for this rack/region controller that is created
    when either the rack or region first starts.
    """
    global _maas_id
    with _maas_id_lock:
        if _maas_id is None:
            maas_id_path = get_data_path("/var/lib/maas/maas_id")
            try:
                with open(maas_id_path, "r", encoding="ascii") as fp:
                    contents = fp.read().strip()
            except FileNotFoundError:
                return None
            else:
                _maas_id = _normalise_maas_id(contents)
                return _maas_id
        else:
            return _maas_id
Пример #10
0
def toggle_cprofile(process_name, signum=None, stack=None):
    """Toggle cProfile profiling of the process.

    If it's called when no profiling is enabled, profiling will start.

    If it's called when profiling is enabled, profiling is stopped and
    the stats are written to MAAS_ROOT/var/lib/maas/profiling, with the
    process name and pid in the name.
    """
    global _profile
    if _profile is None:
        _profile = cProfile.Profile()
        _profile.enable()
        print('Profiling enabled')
    else:
        base_dir = Path('/') / 'var' / 'lib' / 'maas' / 'profiling'
        current_time = datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')
        output_filepath = (
            base_dir / f'{process_name}-{os.getpid()}-{current_time}.pyprof')
        full_filepath = get_data_path(str(output_filepath))
        _profile.create_stats()
        _profile.dump_stats(full_filepath)
        _profile = None
        print(f'Profiling disabled. Output written to {full_filepath}')
Пример #11
0
 def __init__(self, path, reactor=None):
     abspath = FilePath(path).asTextMode().path.lstrip("/")
     discriminator = abspath.replace(":", "::").replace("/", ":")
     lockpath = get_data_path("run", "lock", "maas@%s" % discriminator)
     super(RunLock, self).__init__(lockpath, reactor=reactor)
Пример #12
0
def get_socket_path():
    """Return path to dhcpd.sock."""
    return os.path.join(get_data_path("/var/lib/maas"), "dhcpd.sock")
Пример #13
0
def get_shared_secret_filesystem_path():
    """Return the path to shared-secret on the filesystem."""
    return get_data_path("var", "lib", "maas", "secret")
Пример #14
0
 def test_falls_back_to_default(self):
     self.set_envvar(None)
     self.assertEqual(get_data_path(self.example_configuration.default),
                      self.example_configuration.DEFAULT_FILENAME)
Пример #15
0
 def test_can_delete_file_in_development(self):
     filename = get_data_path("/var/lib/maas/dhcpd.conf")
     with open(filename, "wb") as fd:
         fd.write(factory.make_bytes())
     sudo_delete_file(filename)
     self.assertThat(filename, Not(FileExists()))
Пример #16
0
class ExampleConfigurationMeta(ConfigurationMeta):
    envvar = "MAAS_TESTING_SETTINGS"
    default = get_data_path("example.db")
    backend = None  # Define this in sub-classes.
Пример #17
0
 def setUp(self):
     super(TestMAASID, self).setUp()
     self.maas_id_path = get_data_path("/var/lib/maas/maas_id")
     self.addCleanup(env.set_maas_id, None)
     env.set_maas_id(None)
Пример #18
0
def get_maas_user_gpghome():
    """Return the GPG directory for the `maas` user.

    Set $GPGHOME to this value ad-hoc when needed.
    """
    return get_data_path('/var/lib/maas/gnupg')