from xmlrpc.client import Fault

import pytest


@pytest.mark.usefixtures("cobbler_xmlrpc_base")
class TestSystem:
    """
    Test remote calls related to systems.
    """

    def test_get_systems(self, remote, token):
        """
        Test: get systems
        """
        # Arrange --> Nothing to arrange

        # Act
        result = remote.get_systems(token)

        # Assert
        assert result == []

    @pytest.mark.usefixtures("create_testdistro", "create_testmenu", "create_testprofile", "remove_testdistro",
                             "remove_testmenu", "remove_testprofile", "remove_testsystem")
    @pytest.mark.parametrize("field_name,field_value", [
        ("comment", "test comment"),
        ("enable_ipxe", True),
        ("enable_ipxe", False),
        ("kernel_options", "a=1 b=2 c=3 c=4 c=5 d e"),
        ("kernel_options_post", "a=1 b=2 c=3 c=4 c=5 d e"),
        ("autoinstall", "test.ks"),
        ("autoinstall", "test.xml"),
        ("autoinstall", "test.seed"),
        ("autoinstall_meta", "a=1 b=2 c=3 c=4 c=5 d e"),
        ("mgmt_classes", "one two three"),
        ("mgmt_parameters", "<<inherit>>"),
        ("name", "testsystem0"),
        ("netboot_enabled", True),
        ("netboot_enabled", False),
        ("owners", "user1 user2 user3"),
        ("profile", "testprofile0"),
        ("repos_enabled", True),
        ("repos_enabled", False),
        ("status", "development"),
        ("status", "testing"),
        ("status", "acceptance"),
        ("status", "production"),
        ("proxy", "testproxy"),
        ("server", "1.1.1.1"),
        # ("boot_loaders", "pxe ipxe grub"), FIXME: This raises currently but it did not in the past
        ("virt_auto_boot", True),
        ("virt_auto_boot", False),
        ("virt_auto_boot", "yes"),
        ("virt_auto_boot", "no"),
        ("virt_cpus", "<<inherit>>"),
        ("virt_cpus", 1),
        ("virt_cpus", 2),
        ("virt_cpus", "<<inherit>>"),
        ("virt_file_size", "<<inherit>>"),
        ("virt_file_size", 5),
        ("virt_file_size", 10),
        ("virt_disk_driver", "<<inherit>>"),
        ("virt_disk_driver", "raw"),
        ("virt_disk_driver", "qcow2"),
        ("virt_disk_driver", "vdmk"),
        ("virt_ram", "<<inherit>>"),
        ("virt_ram", 256),
        ("virt_ram", 1024),
        ("virt_type", "<<inherit>>"),
        ("virt_type", "xenpv"),
        ("virt_type", "xenfv"),
        ("virt_type", "qemu"),
        ("virt_type", "kvm"),
        ("virt_type", "vmware"),
        ("virt_type", "openvz"),
        ("virt_path", "<<inherit>>"),
        ("virt_path", "/path/to/test"),
        ("virt_pxe_boot", True),
        ("virt_pxe_boot", False),
        ("power_type", "ipmilanplus"),
        ("power_address", "127.0.0.1"),
        ("power_id", "pmachine:lpar1"),
        ("power_pass", "pass"),
        ("power_user", "user")
    ])
    def test_create_system_positive(self, remote, token, template_files, field_name, field_value):
        """
        Test: create/edit a system object
        """
        # Arrange
        system = remote.new_system(token)
        remote.modify_system(system, "name", "testsystem0", token)
        remote.modify_system(system, "profile", "testprofile0", token)

        # Act
        result = remote.modify_system(system, field_name, field_value, token)

        # Assert
        assert result

    @pytest.mark.usefixtures("create_testdistro", "create_testmenu", "create_testprofile", "remove_testdistro",
                             "remove_testmenu", "remove_testprofile", "remove_testsystem")
    @pytest.mark.parametrize("field_name,field_value", [
        ("autoinstall", "/path/to/bad/autoinstall"),
        ("mgmt_parameters", "badyaml"),
        ("profile", "badprofile"),
        ("boot_loaders", "badloader"),
        ("virt_cpus", "a"),
        ("virt_file_size", "a"),
        ("virt_ram", "a"),
        ("virt_type", "bad"),
        ("power_type", "bla")
    ])
    def test_create_system_negative(self, remote, token, field_name, field_value):
        """
        Test: create/edit a system object
        """
        # Arrange
        system = remote.new_system(token)
        remote.modify_system(system, "name", "testsystem0", token)
        remote.modify_system(system, "profile", "testprofile0", token)

        # Act & Assert
        try:
            remote.modify_system(system, field_name, field_value, token)
        except Fault:
            assert True
        else:
            pytest.fail("Bad field did not raise an exception!")

    def test_find_system(self, remote, token):
        """
        Test: find a system object
        """

        # Arrange --> Nothing to arrange

        # Act
        result = remote.find_system({"name": "notexisting"}, token)

        # Assert --> A not exiting system returns an empty list
        assert result == []

    @pytest.mark.usefixtures("create_testdistro", "create_testmenu", "create_testprofile", "create_testsystem",
                             "remove_testdistro",
                             "remove_testmenu", "remove_testprofile", "remove_testsystem")
    def test_copy_system(self, remote, token):
        """
        Test: copy a system object
        """

        # Arrange
        system = remote.get_item_handle("system", "testsystem0", token)

        # Act
        result = remote.copy_system(system, "testsystemcopy", token)

        # Assert
        assert result

        # Cleanup
        remote.remove_system("testsytemcopy", token)

    @pytest.mark.usefixtures("create_testdistro", "create_testmenu", "create_testprofile", "create_testsystem",
                             "remove_testdistro",
                             "remove_testmenu", "remove_testprofile", "remove_testsystem")
    def test_rename_system(self, remote, token):
        """
        Test: rename a system object
        """

        # Arrange --> Done in fixtures also.
        system = remote.get_item_handle("system", "testsystem0", token)

        # Act
        result = remote.rename_system(system, "testsystem1", token)

        # Assert
        assert result

        # Cleanup
        remote.remove_system("testsystem1", token)

    def test_remove_system(self, remote, token):
        """
        Test: remove a system object
        """

        # Arrange
        # TODO: Verify why the test passes without the fixture for creating the system!

        # Act
        result = remote.remove_system("testsystem0", token)

        # Assert
        assert result

    def test_get_repo_config_for_system(self, remote):
        """
        Test: get repository configuration of a system
        """

        # Arrange --> There is nothing to be arranged

        # Act
        result = remote.get_repo_config_for_system("testprofile0")

        # Assert --> Let the test pass if the call is okay.
        assert True
