Beispiel #1
0
    def test_remove_calls_omshell_correctly(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        mac_address = factory.make_mac_address()
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Instead of calling a real omshell, we'll just record the
        # parameters passed to Popen.
        recorder = FakeMethod(result=(0, b"thing1\nthing2\nobj: <null>"))
        shell._run = recorder

        shell.remove(mac_address)

        expected_script = dedent("""\
            server {server}
            port {port}
            key omapi_key {key}
            connect
            new host
            set name = "{mac}"
            open
            remove
            """).format(
            server=server_address,
            port=self.port,
            key=shared_key,
            mac=mac_address.replace(":", "-"),
        )
        expected_results = (expected_script.encode("utf-8"), )

        # Check that the 'stdin' arg contains the correct set of
        # commands.
        self.assertEqual([expected_results], recorder.extract_args())
Beispiel #2
0
    def test_try_connection_calls_omshell_correctly(self):
        server_address = factory.make_string()
        shell = Omshell(server_address, "", ipv6=self.ipv6)

        # Instead of calling a real omshell, we'll just record the
        # parameters passed to Popen.
        recorder = FakeMethod(result=(0, b"obj: <null>"))
        shell._run = recorder

        shell.try_connection()

        expected_script = dedent("""\
            server {server}
            port {port}
            connect
            """)
        expected_script = expected_script.format(server=server_address,
                                                 port=self.port)

        # Check that the 'stdin' arg contains the correct set of
        # commands.
        self.assertEqual(
            [1, (expected_script.encode("utf-8"), )],
            [recorder.call_count,
             recorder.extract_args()[0]],
        )
Beispiel #3
0
    def test__calls_omshell_correctly(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Instead of calling a real omshell, we'll just record the
        # parameters passed to Popen.
        run = self.patch(shell, "_run")
        run.return_value = (0, b"\nends = 00:00:00:00")
        expected_script = dedent("""\
            server {server}
            port {port}
            key omapi_key {key}
            connect
            new lease
            set ip-address = {ip}
            open
            set ends = 00:00:00:00
            update
            """)
        expected_script = expected_script.format(
            server=server_address,
            port=self.port,
            key=shared_key,
            ip=ip_address,
        )
        shell.nullify_lease(ip_address)
        self.assertThat(run,
                        MockCalledOnceWith(expected_script.encode("utf-8")))
Beispiel #4
0
 def test_create_succeeds_when_host_map_already_exists(self):
     # To omshell, creating the same host map twice is an error.  But
     # Omshell.create swallows the error and makes it look like
     # success.
     params = {
         "ip": factory.make_ip_address(ipv6=self.ipv6),
         "mac": factory.make_mac_address(),
         "hostname": factory.make_name("hostname"),
     }
     shell = Omshell(
         factory.make_name("server"),
         factory.make_name("key"),
         ipv6=self.ipv6,
     )
     # This is the kind of error output we get if a host map has
     # already been created.
     error_output = (dedent("""\
         obj: host
         ip-address = %(ip)s
         hardware-address = %(mac)s
         name = "%(hostname)s"
         >
         can't open object: I/O error
         obj: host
         ip-address = %(ip)s
         hardware-address = %(mac)s
         name = "%(hostname)s"
         """) % params)
     shell._run = Mock(return_value=(0, error_output.encode("ascii")))
     shell.create(params["ip"], params["mac"])
     # The test is that we get here without error.
     pass
Beispiel #5
0
    def test_modify_calls_omshell_correctly(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        mac_address = factory.make_mac_address()
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Instead of calling a real omshell, we'll just record the
        # parameters passed to Popen.
        recorder = FakeMethod(result=(0, b"hardware-type"))
        shell._run = recorder

        shell.modify(ip_address, mac_address)

        expected_script = dedent("""\
            server {server}
            key omapi_key {key}
            connect
            new host
            set name = "{name}"
            open
            set ip-address = {ip}
            set hardware-address = {mac}
            set hardware-type = 1
            update
            """)
        expected_script = expected_script.format(
            server=server_address, key=shared_key, ip=ip_address,
            mac=mac_address, name=mac_address.replace(':', '-'))

        # Check that the 'stdin' arg contains the correct set of
        # commands.
        self.assertEqual(
            [1, (expected_script.encode("utf-8"),)],
            [recorder.call_count, recorder.extract_args()[0]])
Beispiel #6
0
    def test_remove_works_when_object_already_removed(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        output = b"obj: <null>\nobj: host\ncan't open object: not found\n"
        self.patch(shell, "_run").return_value = (0, output)
        self.assertIsNone(shell.remove(ip_address))
Beispiel #7
0
    def test_try_connection_returns_False(self):
        server_address = factory.make_string()
        shell = Omshell(server_address, "", ipv6=self.ipv6)

        # Instead of calling a real omshell, we'll just record the
        # parameters passed to Popen.
        recorder = FakeMethod(result=(0, factory.make_bytes()))
        shell._run = recorder

        self.assertFalse(shell.try_connection())
Beispiel #8
0
    def test__considers_nonexistent_lease_a_success(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        output = (b"obj: <null>\nobj: lease\nobj: lease\n"
                  b"can't open object: not found\nobj: lease\n")
        self.patch(shell, "_run").return_value = (0, output)
        shell.nullify_lease(ip_address)  # No exception.
        self.assertThat(shell._run, MockCalledOnceWith(ANY))
Beispiel #9
0
    def test_remove_works_when_extraneous_gt_char_present(self):
        # Sometimes omshell puts a leading '>' character in responses.
        # We need to test that the code still works if that's the case.
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Fake a call that results in a something with our special output.
        output = b"\n>obj: <null>\n>\n"
        self.patch(shell, "_run").return_value = (0, output)
        self.assertIsNone(shell.remove(ip_address))
Beispiel #10
0
    def test_remove_works_when_extraneous_blank_last_lines(self):
        # Sometimes omshell puts blank lines after the 'obj: <null>' so
        # we need to test that the code still works if that's the case.
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Fake a call that results in a something with our special output.
        output = b"\n> obj: <null>\n\n"
        self.patch(shell, "_run").return_value = (0, output)
        self.assertIsNone(shell.remove(ip_address))
Beispiel #11
0
    def test__catches_failed_update(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # make "ends" different to what we asked, so the post-run check
        # should fail.
        output = dedent("""\
            obj: <null>
            obj: lease
            obj: lease
            ip-address = 0a:00:00:72
            state = 00:00:00:01
            subnet = 00:00:00:03
            pool = 00:00:00:04
            hardware-address = 00:16:3e:06:45:5e
            hardware-type = 00:00:00:01
            ends = 00:00:00:FF
            starts = "T@v'"
            tstp = 54:41:1e:e7
            tsfp = 00:00:00:00
            atsfp = 00:00:00:00
            cltt = "T@v'"
            flags = 00
            """).encode("ascii")
        self.patch(shell, "_run").return_value = (0, output)
        self.assertRaises(ExternalProcessError, shell.nullify_lease,
                          ip_address)
Beispiel #12
0
    def test_remove_raises_when_omshell_fails(self):
        # If the call to omshell doesn't result in output ending in the
        # text 'obj: <null>' we can be fairly sure this operation
        # failed.
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Fake a call that results in a failure with random output.
        random_output = factory.make_bytes()
        recorder = FakeMethod(result=(0, random_output))
        shell._run = recorder

        exc = self.assertRaises(subprocess.CalledProcessError, shell.remove,
                                ip_address)
        self.assertEqual(random_output, exc.output)
Beispiel #13
0
 def test_initialisation(self):
     server_address = factory.make_string()
     shared_key = factory.make_string()
     shell = Omshell(server_address, shared_key)
     self.assertThat(
         shell, MatchesStructure.byEquality(
             server_address=server_address,
             shared_key=shared_key))
Beispiel #14
0
    def test__catches_invalid_error(self):
        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        output = b"obj: <null>\nobj: lease\ninvalid value."
        self.patch(shell, "_run").return_value = (0, output)
        self.assertRaises(ExternalProcessError, shell.nullify_lease,
                          ip_address)
Beispiel #15
0
    def test_modify_raises_when_omshell_fails(self):
        # If the call to omshell doesn't result in output containing the
        # magic string 'hardware-type' it means the set of commands
        # failed.

        server_address = factory.make_string()
        shared_key = factory.make_string()
        ip_address = factory.make_ip_address(ipv6=self.ipv6)
        mac_address = factory.make_mac_address()
        shell = Omshell(server_address, shared_key, ipv6=self.ipv6)

        # Fake a call that results in a failure with random output.
        random_output = factory.make_bytes()
        recorder = FakeMethod(result=(0, random_output))
        shell._run = recorder

        exc = self.assertRaises(ExternalProcessError, shell.modify, ip_address,
                                mac_address)
        self.assertEqual(random_output, exc.output)
Beispiel #16
0
def _update_hosts(server, remove, add, modify):
    """Update the hosts using the OMAPI."""
    omshell = Omshell(server_address='127.0.0.1',
                      shared_key=server.omapi_key,
                      ipv6=server.ipv6)
    for host in remove:
        _remove_host_map(omshell, host["mac"])
    for host in add:
        _create_host_map(omshell, host["mac"], host["ip"])
    for host in modify:
        _modify_host_map(omshell, host["mac"], host["ip"])