Exemple #1
0
    def test__bad_config(self):
        omapi_key = factory.make_name("omapi_key")
        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover([shared_network],
                                                        [failover_peers])
        host = make_host()
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()
        dhcpd_error = (
            "Internet Systems Consortium DHCP Server 4.3.3\n"
            "Copyright 2004-2015 Internet Systems Consortium.\n"
            "All rights reserved.\n"
            "For info, please visit https://www.isc.org/software/dhcp/\n"
            "/tmp/maas-dhcpd-z5c7hfzt line 14: semicolon expected.\n"
            "ignore \n"
            "^\n"
            "Configuration file errors encountered -- exiting\n"
            "\n"
            "If you think you have received this message due to a bug rather\n"
            "than a configuration issue please read the section on submitting"
            "\n"
            "bugs on either our web page at www.isc.org or in the README file"
            "\n"
            "before submitting a bug.  These pages explain the proper\n"
            "process and the information we find helpful for debugging..\n"
            "\n"
            "exiting.")
        self.mock_call_and_check.side_effect = ExternalProcessError(
            returncode=1, cmd=("dhcpd", ), output=dhcpd_error)

        self.assertEqual(
            [{
                "error": "semicolon expected.",
                "line_num": 14,
                "line": "ignore ",
                "position": "^",
            }],
            self.validate(
                omapi_key,
                [failover_peers],
                [shared_network],
                [host],
                [interface],
                global_dhcp_snippets,
            ),
        )
Exemple #2
0
    def test__writes_config_and_calls_restart_when_non_host_state_diff(self):
        write_file = self.patch_sudo_write_file()
        restart_service = self.patch_restartService()

        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover(
            [shared_network], [failover_peers])
        host = make_host()
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()
        expected_config = factory.make_name('config')
        self.patch_get_config().return_value = expected_config

        dhcp_service = dhcp.service_monitor.getServiceByName(
            self.server.dhcp_service)
        on = self.patch_autospec(dhcp_service, "on")

        old_state = dhcp.DHCPState(
            factory.make_name("omapi_key"), [failover_peers], [shared_network],
            [host], [interface], global_dhcp_snippets)
        dhcp._current_server_state[self.server.dhcp_service] = old_state

        omapi_key = factory.make_name('omapi_key')
        yield self.configure(
            omapi_key,
            [failover_peers], [shared_network], [host], [interface],
            global_dhcp_snippets)

        self.assertThat(
            write_file,
            MockCallsMatch(
                call(
                    self.server.config_filename,
                    expected_config.encode("utf-8")),
                call(
                    self.server.interfaces_filename,
                    interface["name"].encode("utf-8")),
                ))
        self.assertThat(on, MockCalledOnceWith())
        self.assertThat(
            restart_service, MockCalledOnceWith(self.server.dhcp_service))
        self.assertEquals(
            dhcp._current_server_state[self.server.dhcp_service],
            dhcp.DHCPState(
                omapi_key, [failover_peers], [shared_network],
                [host], [interface], global_dhcp_snippets))
Exemple #3
0
 def test__does_not_log_ServiceActionError_when_restarting(self):
     self.patch_sudo_write_file()
     self.patch_restartService().side_effect = ServiceActionError()
     failover_peers = [make_failover_peer_config()]
     shared_networks = fix_shared_networks_failover([make_shared_network()],
                                                    failover_peers)
     with FakeLogger("maas") as logger:
         with ExpectedException(exceptions.CannotConfigureDHCP):
             yield self.configure(
                 factory.make_name("key"),
                 failover_peers,
                 shared_networks,
                 [make_host()],
                 [make_interface()],
                 make_global_dhcp_snippets(),
             )
     self.assertDocTestMatches("", logger.output)
Exemple #4
0
 def test__converts_failure_writing_file_to_CannotConfigureDHCP(self):
     self.patch_sudo_delete_file()
     self.patch_sudo_write_file().side_effect = ExternalProcessError(
         1, "sudo something")
     self.patch_restartService()
     failover_peers = [make_failover_peer_config()]
     shared_networks = fix_shared_networks_failover([make_shared_network()],
                                                    failover_peers)
     with ExpectedException(exceptions.CannotConfigureDHCP):
         yield self.configure(
             factory.make_name("key"),
             failover_peers,
             shared_networks,
             [make_host()],
             [make_interface()],
             make_global_dhcp_snippets(),
         )
Exemple #5
0
 def make_args(self):
     omapi_key = factory.make_name("omapi_key")
     failover_peers = [make_failover_peer_config() for _ in range(3)]
     shared_networks = [make_shared_network() for _ in range(3)]
     shared_networks = fix_shared_networks_failover(
         shared_networks, failover_peers
     )
     hosts = [make_host() for _ in range(3)]
     interfaces = [make_interface() for _ in range(3)]
     return (
         omapi_key,
         failover_peers,
         shared_networks,
         hosts,
         interfaces,
         make_global_dhcp_snippets(),
     )
Exemple #6
0
 def test__does_log_other_exceptions_when_restarting(self):
     self.patch_sudo_write_file()
     self.patch_restartService().side_effect = (
         factory.make_exception("DHCP is on strike today"))
     failover_peers = [make_failover_peer_config()]
     shared_networks = fix_shared_networks_failover(
         [make_shared_network()], failover_peers)
     with FakeLogger("maas") as logger:
         with ExpectedException(exceptions.CannotConfigureDHCP):
             yield self.configure(
                 factory.make_name('key'),
                 failover_peers, shared_networks,
                 [make_host()], [make_interface()],
                 make_global_dhcp_snippets())
     self.assertDocTestMatches(
         "DHCPv... server failed to restart: "
         "DHCP is on strike today", logger.output)
Exemple #7
0
    def test__bad_config(self):
        omapi_key = factory.make_name('omapi_key')
        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover(
            [shared_network], [failover_peers])
        host = make_host()
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()
        dhcpd_error = (
            'Internet Systems Consortium DHCP Server 4.3.3\n'
            'Copyright 2004-2015 Internet Systems Consortium.\n'
            'All rights reserved.\n'
            'For info, please visit https://www.isc.org/software/dhcp/\n'
            '/tmp/maas-dhcpd-z5c7hfzt line 14: semicolon expected.\n'
            'ignore \n'
            '^\n'
            'Configuration file errors encountered -- exiting\n'
            '\n'
            'If you think you have received this message due to a bug rather\n'
            'than a configuration issue please read the section on submitting'
            '\n'
            'bugs on either our web page at www.isc.org or in the README file'
            '\n'
            'before submitting a bug.  These pages explain the proper\n'
            'process and the information we find helpful for debugging..\n'
            '\n'
            'exiting.'
        )
        self.patch(dhcp, 'call_and_check').side_effect = ExternalProcessError(
            returncode=1, cmd=("dhcpd",), output=dhcpd_error)

        self.assertEqual([{
            'error': 'semicolon expected.',
            'line_num': 14,
            'line': 'ignore ',
            'position': '^',
            }],
            self.validate(
                omapi_key, [failover_peers], [shared_network], [host],
                [interface], global_dhcp_snippets))
Exemple #8
0
    def test__good_config(self):
        omapi_key = factory.make_name("omapi_key")
        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover([shared_network],
                                                        [failover_peers])
        host = make_host()
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()

        self.assertEqual(
            None,
            self.validate(
                omapi_key,
                [failover_peers],
                [shared_network],
                [host],
                [interface],
                global_dhcp_snippets,
            ),
        )
Exemple #9
0
def make_sample_params_only(ipv6=False):
    """Return a dict of arbitrary DHCP configuration parameters.

    :param ipv6: When true, prepare configuration for a DHCPv6 server,
        otherwise prepare configuration for a DHCPv4 server.
    :return: A dictionary of sample configuration.
    """
    failover_peers = [make_failover_peer_config() for _ in range(3)]
    shared_networks = [make_shared_network(ipv6=ipv6) for _ in range(3)]

    shared_networks = fix_shared_networks_failover(shared_networks,
                                                   failover_peers)

    return {
        'omapi_key': b64encode(factory.make_bytes()).decode("ascii"),
        'failover_peers': failover_peers,
        'shared_networks': shared_networks,
        'hosts': [make_host(ipv6=ipv6) for _ in range(3)],
        'global_dhcp_snippets': make_global_dhcp_snippets(),
        'ipv6': ipv6,
    }
Exemple #10
0
    def test__writes_config_and_uses_omapi_to_update_hosts(self):
        write_file = self.patch_sudo_write_file()
        get_service_state = self.patch_getServiceState()
        get_service_state.return_value = ServiceState(SERVICE_STATE.ON,
                                                      "running")
        restart_service = self.patch_restartService()
        ensure_service = self.patch_ensureService()
        update_hosts = self.patch_update_hosts()

        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover([shared_network],
                                                        [failover_peers])
        old_hosts = [make_host(dhcp_snippets=[]) for _ in range(3)]
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()
        expected_config = factory.make_name("config")
        self.patch_get_config().return_value = expected_config

        dhcp_service = dhcp.service_monitor.getServiceByName(
            self.server.dhcp_service)
        on = self.patch_autospec(dhcp_service, "on")

        omapi_key = factory.make_name("omapi_key")
        old_state = dhcp.DHCPState(
            omapi_key,
            [failover_peers],
            [shared_network],
            old_hosts,
            [interface],
            global_dhcp_snippets,
        )
        dhcp._current_server_state[self.server.dhcp_service] = old_state

        new_hosts = copy.deepcopy(old_hosts)
        removed_host = new_hosts.pop()
        modified_host = new_hosts[0]
        modified_host["ip"] = factory.make_ip_address()
        added_host = make_host(dhcp_snippets=[])
        new_hosts.append(added_host)

        yield self.configure(
            omapi_key,
            [failover_peers],
            [shared_network],
            new_hosts,
            [interface],
            global_dhcp_snippets,
        )

        self.assertThat(
            write_file,
            MockCallsMatch(
                call(
                    self.server.config_filename,
                    expected_config.encode("utf-8"),
                    mode=0o640,
                ),
                call(
                    self.server.interfaces_filename,
                    interface["name"].encode("utf-8"),
                    mode=0o640,
                ),
            ),
        )
        self.assertThat(on, MockCalledOnceWith())
        self.assertThat(
            get_service_state,
            MockCalledOnceWith(self.server.dhcp_service, now=True),
        )
        self.assertThat(restart_service, MockNotCalled())
        self.assertThat(ensure_service,
                        MockCalledOnceWith(self.server.dhcp_service))
        self.assertThat(
            update_hosts,
            MockCalledOnceWith(ANY, [removed_host], [added_host],
                               [modified_host]),
        )
        self.assertEquals(
            dhcp._current_server_state[self.server.dhcp_service],
            dhcp.DHCPState(
                omapi_key,
                [failover_peers],
                [shared_network],
                new_hosts,
                [interface],
                global_dhcp_snippets,
            ),
        )
Exemple #11
0
    def test__writes_config_and_doesnt_use_omapi_when_was_off(self):
        write_file = self.patch_sudo_write_file()
        get_service_state = self.patch_getServiceState()
        get_service_state.return_value = ServiceState(SERVICE_STATE.OFF,
                                                      "dead")
        restart_service = self.patch_restartService()
        ensure_service = self.patch_ensureService()
        update_hosts = self.patch_update_hosts()

        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover([shared_network],
                                                        [failover_peers])
        host = make_host(dhcp_snippets=[])
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()
        expected_config = factory.make_name("config")
        self.patch_get_config().return_value = expected_config

        dhcp_service = dhcp.service_monitor.getServiceByName(
            self.server.dhcp_service)
        on = self.patch_autospec(dhcp_service, "on")

        omapi_key = factory.make_name("omapi_key")
        old_host = make_host(dhcp_snippets=[])
        old_state = dhcp.DHCPState(
            omapi_key,
            [failover_peers],
            [shared_network],
            [old_host],
            [interface],
            global_dhcp_snippets,
        )
        dhcp._current_server_state[self.server.dhcp_service] = old_state

        yield self.configure(
            omapi_key,
            [failover_peers],
            [shared_network],
            [host],
            [interface],
            global_dhcp_snippets,
        )

        self.assertThat(
            write_file,
            MockCallsMatch(
                call(
                    self.server.config_filename,
                    expected_config.encode("utf-8"),
                    mode=0o640,
                ),
                call(
                    self.server.interfaces_filename,
                    interface["name"].encode("utf-8"),
                    mode=0o640,
                ),
            ),
        )
        self.assertThat(on, MockCalledOnceWith())
        self.assertThat(
            get_service_state,
            MockCalledOnceWith(self.server.dhcp_service, now=True),
        )
        self.assertThat(restart_service, MockNotCalled())
        self.assertThat(ensure_service,
                        MockCalledOnceWith(self.server.dhcp_service))
        self.assertThat(update_hosts, MockNotCalled())
        self.assertEquals(
            dhcp._current_server_state[self.server.dhcp_service],
            dhcp.DHCPState(
                omapi_key,
                [failover_peers],
                [shared_network],
                [host],
                [interface],
                global_dhcp_snippets,
            ),
        )
Exemple #12
0
    def test_writes_config_and_restarts_when_omapi_fails(self):
        write_file = self.patch_sudo_write_file()
        get_service_state = self.patch_getServiceState()
        get_service_state.return_value = ServiceState(SERVICE_STATE.ON,
                                                      "running")
        restart_service = self.patch_restartService()
        ensure_service = self.patch_ensureService()
        update_hosts = self.patch_update_hosts()
        update_hosts.side_effect = factory.make_exception()

        failover_peers = make_failover_peer_config()
        shared_network = make_shared_network()
        [shared_network] = fix_shared_networks_failover([shared_network],
                                                        [failover_peers])
        old_hosts = [make_host(dhcp_snippets=[]) for _ in range(3)]
        interface = make_interface()
        global_dhcp_snippets = make_global_dhcp_snippets()
        expected_config = factory.make_name("config")
        self.patch_get_config().return_value = expected_config

        dhcp_service = dhcp.service_monitor.getServiceByName(
            self.server.dhcp_service)
        on = self.patch_autospec(dhcp_service, "on")

        omapi_key = factory.make_name("omapi_key")
        old_state = dhcp.DHCPState(
            omapi_key,
            [failover_peers],
            [shared_network],
            old_hosts,
            [interface],
            global_dhcp_snippets,
        )
        dhcp._current_server_state[self.server.dhcp_service] = old_state

        new_hosts = copy.deepcopy(old_hosts)
        removed_host = new_hosts.pop()
        modified_host = new_hosts[0]
        modified_host["ip"] = factory.make_ip_address(
            ipv6=self.server.dhcp_service == "DHCPv6")
        added_host = make_host(dhcp_snippets=[])
        new_hosts.append(added_host)

        with FakeLogger("maas") as logger:
            yield self.configure(
                omapi_key,
                [failover_peers],
                [shared_network],
                new_hosts,
                [interface],
                global_dhcp_snippets,
            )

        self.assertThat(
            write_file,
            MockCallsMatch(
                call(
                    self.server.config_filename,
                    expected_config.encode("utf-8"),
                    mode=0o640,
                ),
                call(
                    self.server.interfaces_filename,
                    interface["name"].encode("utf-8"),
                    mode=0o640,
                ),
            ),
        )
        self.assertThat(on, MockCalledOnceWith())
        self.assertThat(
            get_service_state,
            MockCalledOnceWith(self.server.dhcp_service, now=True),
        )
        self.assertThat(restart_service,
                        MockCalledOnceWith(self.server.dhcp_service))
        self.assertThat(ensure_service,
                        MockCalledOnceWith(self.server.dhcp_service))
        self.assertThat(
            update_hosts,
            MockCalledOnceWith(ANY, [removed_host], [added_host],
                               [modified_host]),
        )
        self.assertEqual(
            dhcp._current_server_state[self.server.dhcp_service],
            dhcp.DHCPState(
                omapi_key,
                [failover_peers],
                [shared_network],
                new_hosts,
                [interface],
                global_dhcp_snippets,
            ),
        )
        self.assertDocTestMatches(
            "Failed to update all host maps. Restarting DHCPv... "
            "service to ensure host maps are in-sync.",
            logger.output,
        )