Esempio n. 1
0
    def test_write_dhcp_config_invokes_script_correctly(self):
        mocked_proc = Mock()
        mocked_proc.returncode = 0
        mocked_proc.communicate = Mock(return_value=('output', 'error output'))
        mocked_popen = self.patch(utils, "Popen",
                                  Mock(return_value=mocked_proc))

        config_params = self.make_dhcp_config_params()
        write_dhcp_config(**config_params)

        # It should construct Popen with the right parameters.
        mocked_popen.assert_any_call([
            "sudo", "-n", "maas-provision", "atomic-write", "--filename",
            celery_config.DHCP_CONFIG_FILE, "--mode", "0644"
        ],
                                     stdin=PIPE)

        # It should then pass the content to communicate().
        content = config.get_config(**config_params).encode("ascii")
        mocked_proc.communicate.assert_any_call(content)

        # Similarly, it also writes the DHCPD interfaces to
        # /var/lib/maas/dhcpd-interfaces.
        mocked_popen.assert_any_call([
            "sudo", "-n", "maas-provision", "atomic-write", "--filename",
            celery_config.DHCP_INTERFACES_FILE, "--mode", "0644"
        ],
                                     stdin=PIPE)
Esempio n. 2
0
 def test_renders_without_ntp_servers_set(self):
     params = make_sample_params()
     del params['ntp_server']
     template = self.patch_template()
     rendered = template.substitute(params)
     self.assertEqual(rendered, config.get_config(**params))
     self.assertNotIn("ntp-servers", rendered)
Esempio n. 3
0
 def test__renders_router_ip_if_present(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     router_ip = factory.make_ipv4_address()
     params['shared_networks'][0]['subnets'][0]['router_ip'] = router_ip
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     self.assertThat(rendered, Contains(router_ip))
Esempio n. 4
0
 def test__renders_with_hosts(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     self.assertThat(
         params["hosts"], AfterPreprocessing(
             len, GreaterThanOrEqual(1)))
     config_output = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, config_output, self.ipv6)
     self.assertThat(
         config_output,
         ContainsAll([
             host['host']
             for host in params["hosts"]
         ]))
     self.assertThat(
         config_output,
         ContainsAll([
             host['mac']
             for host in params["hosts"]
         ]))
     self.assertThat(
         config_output,
         ContainsAll([
             host['ip']
             for host in params["hosts"]
         ]))
Esempio n. 5
0
 def test_renders_without_ntp_servers_set(self):
     params = make_sample_params()
     del params['ntp_server']
     template = self.patch_template()
     rendered = template.substitute(params)
     self.assertEqual(rendered, config.get_config(**params))
     self.assertNotIn("ntp-servers", rendered)
Esempio n. 6
0
 def test__renders_without_ntp_servers_set(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     for network in params['shared_networks']:
         for subnet in network['subnets']:
             subnet['ntp_servers'] = ""
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     self.assertNotIn("ntp-servers", rendered)
Esempio n. 7
0
 def test__uses_branch_template_by_default(self):
     # Since the branch comes with dhcp templates in etc/maas, we can
     # instantiate those templates without any hackery.
     self.assertIsNotNone(
         config.get_config(
             self.template, **make_sample_params(self, ipv6=self.ipv6)
         )
     )
Esempio n. 8
0
def run(args):
    """Generate a DHCP server configuration, and write it to stdout."""
    params = vars(args)
    output = config.get_config(**params).encode("ascii")
    if args.outfile is None:
        sys.stdout.write(output)
    else:
        with open(args.outfile, "wb") as out:
            out.write(output)
Esempio n. 9
0
def run(args):
    """Generate a DHCP server configuration, and write it to stdout."""
    params = vars(args)
    output = config.get_config(**params).encode("ascii")
    if args.outfile is None:
        sys.stdout.write(output)
    else:
        with open(args.outfile, "wb") as out:
            out.write(output)
Esempio n. 10
0
 def test__renders_without_search_list_set(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     for network in params['shared_networks']:
         for subnet in network['subnets']:
             subnet['search_list'] = ""
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     self.assertNotIn("dhcp6.domain-search", rendered)  # IPv6
     self.assertNotIn("domain-search", rendered)  # IPv4
Esempio n. 11
0
 def test_renders_without_dns_servers_set(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     for network in params["shared_networks"]:
         for subnet in network["subnets"]:
             subnet["dns_servers"] = ""
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     self.assertNotIn("dhcp6.name-servers", rendered)  # IPv6
     self.assertNotIn("domain-name-servers", rendered)  # IPv4
Esempio n. 12
0
 def test__renders_global_dhcp_snippets(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     config_output = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, config_output, self.ipv6)
     self.assertThat(
         config_output,
         ContainsAll([
             dhcp_snippet['value']
             for dhcp_snippet in params['global_dhcp_snippets']
         ]))
Esempio n. 13
0
 def get_config(self, server):
     """Return the configuration for `server`."""
     dhcpd_config = get_config(
         server.template_basename, omapi_key=self.omapi_key,
         failover_peers=self.failover_peers, ipv6=server.ipv6,
         shared_networks=self.shared_networks,
         hosts=sorted(self.hosts.values(), key=itemgetter("host")),
         global_dhcp_snippets=sorted(
             self.global_dhcp_snippets, key=itemgetter("name")))
     return dhcpd_config, " ".join(self.interfaces)
Esempio n. 14
0
 def test__renders_with_empty_string_router_ip(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     for network in params['shared_networks']:
         for subnet in network['subnets']:
             subnet['router_ip'] = ''
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     # Remove all lines that have been commented out.
     rendered = "".join(line for line in rendered.splitlines(keepends=True)
                        if not line.lstrip().startswith("#"))
     self.assertNotIn("option routers", rendered)
Esempio n. 15
0
 def test__includes_compose_conditional_bootloader(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     rack_ip = params['shared_networks'][0]['subnets'][0]['router_ip']
     self.patch(
         net_utils, 'get_all_interface_addresses'
         ).return_value = [netaddr.IPAddress(rack_ip)]
     bootloader = config.compose_conditional_bootloader(
         ipv6=self.ipv6, rack_ip=rack_ip)
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     self.assertThat(rendered, Contains(bootloader))
Esempio n. 16
0
 def test_includes_next_server_in_config_from_interface_addresses(self):
     params = make_sample_params(self, ipv6=False, with_interface=True)
     subnet = params["shared_networks"][0]["subnets"][0]
     next_server_ip = factory.pick_ip_in_network(
         netaddr.IPNetwork(subnet["subnet_cidr"]))
     self.patch(
         net_utils,
         "get_all_addresses_for_interface").return_value = [next_server_ip]
     config_output = config.get_config("dhcpd.conf.template", **params)
     validate_dhcpd_configuration(self, config_output, False)
     self.assertThat(config_output,
                     Contains("next-server %s;" % next_server_ip))
Esempio n. 17
0
 def test__renders_subnet_dhcp_snippets(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     config_output = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, config_output, self.ipv6)
     for shared_network in params['shared_networks']:
         for subnet in shared_network['subnets']:
             self.assertThat(
                 config_output,
                 ContainsAll([
                     dhcp_snippet['value']
                     for dhcp_snippet in subnet['dhcp_snippets']
                 ]))
Esempio n. 18
0
 def test__renders_subnet_cidr(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     config_output = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, config_output, self.ipv6)
     for shared_network in params['shared_networks']:
         for subnet in shared_network['subnets']:
             if self.ipv6 is True:
                 expected = "subnet6 %s" % subnet['subnet_cidr']
             else:
                 expected = "subnet %s netmask %s" % (subnet['subnet'],
                                                      subnet['subnet_mask'])
             self.assertThat(config_output, Contains(expected))
Esempio n. 19
0
 def test__includes_next_server_in_config_from_all_addresses(self):
     params = make_sample_params(self, ipv6=False)
     subnet = params['shared_networks'][0]['subnets'][0]
     next_server_ip = factory.pick_ip_in_network(
         netaddr.IPNetwork(subnet['subnet_cidr']))
     self.patch(net_utils, 'get_all_interface_addresses').return_value = [
         next_server_ip
     ]
     config_output = config.get_config('dhcpd.conf.template', **params)
     validate_dhcpd_configuration(self, config_output, False)
     self.assertThat(
         config_output, Contains('next-server %s;' % next_server_ip))
Esempio n. 20
0
 def test_renders_node_dhcp_snippets(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     config_output = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, config_output, self.ipv6)
     for host in params["hosts"]:
         self.assertThat(
             config_output,
             ContainsAll([
                 dhcp_snippet["value"]
                 for dhcp_snippet in host["dhcp_snippets"]
             ]),
         )
Esempio n. 21
0
 def test__renders_dns_servers_as_comma_separated_list(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     dns_servers_expected = [
         ", ".join(map(str, subnet["dns_servers"]))
         for network in params['shared_networks']
         for subnet in network['subnets']
     ]
     dns_servers_pattern = r"\b%s\s+(.+);" % re.escape(
         "dhcp6.name-servers" if self.ipv6 else "domain-name-servers")
     dns_servers_observed = re.findall(dns_servers_pattern, rendered)
     self.assertEqual(dns_servers_expected, dns_servers_observed)
Esempio n. 22
0
def write_dhcp_config(callback=None, **kwargs):
    """Write out the DHCP configuration file and restart the DHCP server.

    :param dhcp_interfaces: Space-separated list of interfaces that the
        DHCP server should listen on.
    :param **kwargs: Keyword args passed to dhcp.config.get_config()
    """
    sudo_write_file(
        celery_config.DHCP_CONFIG_FILE, config.get_config(**kwargs))
    sudo_write_file(
        celery_config.DHCP_INTERFACES_FILE, kwargs.get('dhcp_interfaces', ''))
    if callback is not None:
        callback.delay()
Esempio n. 23
0
 def test__silently_discards_unresolvable_ntp_servers(self):
     params = make_sample_params_only(ipv6=self.ipv6)
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     ntp_servers_expected = [
         server for network in params['shared_networks']
         for subnet in network['subnets']
         for server in subnet["ntp_servers"] if is_ip_address(server)
     ]
     ntp_servers_observed = [
         server for server_line in re.findall(
             r"\b(?:ntp-servers|dhcp6[.]sntp-servers)\s+(.+);", rendered)
         for server in server_line.split(", ")
     ]
     self.assertItemsEqual(ntp_servers_expected, ntp_servers_observed)
Esempio n. 24
0
 def test_includes_compose_conditional_bootloader(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     rack_ip = params["shared_networks"][0]["subnets"][0]["router_ip"]
     self.patch(net_utils, "get_all_interface_addresses").return_value = [
         netaddr.IPAddress(rack_ip)
     ]
     bootloader = config.compose_conditional_bootloader(ipv6=self.ipv6,
                                                        rack_ip=rack_ip)
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     self.assertThat(rendered, Contains(bootloader))
     # Verify that "/images/" is automatically added to bootloaders
     # loaded over HTTP. This ensures nginx handles the result without
     # bothering rackd.
     self.assertIn("/images/bootx64.efi", rendered)
Esempio n. 25
0
 def test__renders_ntp_servers_as_comma_separated_list(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     ntp_servers_expected = flatten([
         server if is_ip_address(server) else _get_addresses(server)
         for network in params['shared_networks']
         for subnet in network['subnets']
         for server in subnet["ntp_servers"]
     ])
     ntp_servers_observed = [
         server for server_line in re.findall(
             r"\b(?:ntp-servers|dhcp6[.]sntp-servers)\s+(.+);", rendered)
         for server in server_line.split(", ")
     ]
     self.assertItemsEqual(ntp_servers_expected, ntp_servers_observed)
Esempio n. 26
0
 def test__renders_search_list_as_quoted_comma_separated_list(self):
     params = make_sample_params(self, ipv6=self.ipv6)
     for network in params['shared_networks']:
         for subnet in network['subnets']:
             subnet['search_list'].append("canonical.com")
     rendered = config.get_config(self.template, **params)
     validate_dhcpd_configuration(self, rendered, self.ipv6)
     dns_servers_expected = [
         ", ".join(map(quote, subnet["search_list"]))
         for network in params['shared_networks']
         for subnet in network['subnets']
     ]
     dns_servers_pattern = r"\b%s\s+(.+);" % re.escape(
         "dhcp6.domain-search" if self.ipv6 else "domain-search")
     dns_servers_observed = re.findall(dns_servers_pattern, rendered)
     self.assertEqual(dns_servers_expected, dns_servers_observed)
Esempio n. 27
0
    def test_write_dhcp_config_invokes_script_correctly(self):
        mocked_proc = Mock()
        mocked_proc.returncode = 0
        mocked_proc.communicate = Mock(return_value=('output', 'error output'))
        mocked_popen = self.patch(
            utils, "Popen", Mock(return_value=mocked_proc))

        config_params = self.make_dhcp_config_params()
        write_dhcp_config(**config_params)

        # It should construct Popen with the right parameters.
        mocked_popen.assert_any_call(
            ["sudo", "-n", "maas-provision", "atomic-write", "--filename",
             celery_config.DHCP_CONFIG_FILE, "--mode", "0644"], stdin=PIPE)

        # It should then pass the content to communicate().
        content = config.get_config(**config_params).encode("ascii")
        mocked_proc.communicate.assert_any_call(content)

        # Similarly, it also writes the DHCPD interfaces to
        # /var/lib/maas/dhcpd-interfaces.
        mocked_popen.assert_any_call(
            ["sudo", "-n", "maas-provision", "atomic-write", "--filename",
             celery_config.DHCP_INTERFACES_FILE, "--mode", "0644"], stdin=PIPE)
Esempio n. 28
0
 def test_param_substitution(self):
     template = self.patch_template()
     params = make_sample_params()
     self.assertEqual(template.substitute(params),
                      config.get_config(**params))
Esempio n. 29
0
 def test_uses_branch_template_by_default(self):
     # Since the branch comes with a dhcp template in etc/maas, we can
     # instantiate that template without any hackery.
     self.assertIsNotNone(config.get_config(**make_sample_params()))
Esempio n. 30
0
 def test_config_refers_to_bootloader(self):
     params = make_sample_params()
     output = config.get_config(**params)
     self.assertThat(output, Contains(compose_bootloader_path()))
Esempio n. 31
0
 def test_param_substitution(self):
     template = self.patch_template()
     params = make_sample_params()
     self.assertEqual(
         template.substitute(params),
         config.get_config(**params))
Esempio n. 32
0
 def test_uses_branch_template_by_default(self):
     # Since the branch comes with a dhcp template in etc/maas, we can
     # instantiate that template without any hackery.
     self.assertIsNotNone(config.get_config(**make_sample_params()))
Esempio n. 33
0
 def test_config_refers_to_bootloader(self):
     params = make_sample_params()
     output = config.get_config(**params)
     self.assertThat(output, Contains(compose_bootloader_path()))