示例#1
0
def ceph_conf_file_fs(request: SubRequest, fs: fake_filesystem.FakeFilesystem):
    """ This fixture uses pyfakefs to stub filesystem calls and return
    any files created with the parent `fs` fixture. """
    fs.add_real_file(  # pyright: reportUnknownMemberType=false
        os.path.join(
            DATA_DIR,
            request.param  # pyright: reportUnknownArgumentType=false
        ),
        target_path='/etc/ceph/ceph.conf')
    yield fs
示例#2
0
def test_not_mounted(fs: fake_filesystem.FakeFilesystem) -> None:

    fs.add_real_file(
        source_path=os.path.join(DATA_DIR, "mounts_without_aquarium.raw"),
        target_path="/proc/mounts",
    )

    from gravel.controllers.nodes.systemdisk import SystemDisk

    systemdisk = SystemDisk()
    assert not systemdisk.mounted
示例#3
0
def test_silly_mounts(fs: fake_filesystem.FakeFilesystem) -> None:
    fs.add_real_file(
        source_path=os.path.join(DATA_DIR, "mounts_silly.raw"),
        target_path="/proc/mounts",
    )

    from gravel.controllers.nodes.systemdisk import MountEntry, get_mounts

    lst: List[MountEntry] = get_mounts()
    assert len(lst) == 2
    assert lst[0].source == "foo" and lst[0].dest == "bar"
    assert lst[1].source == "asd" and lst[1].dest == "fgh"
示例#4
0
def test_get_mounts(fs: fake_filesystem.FakeFilesystem) -> None:

    fs.add_real_file(
        source_path=os.path.join(DATA_DIR, "mounts_with_aquarium.raw"),
        target_path="/proc/mounts",
    )

    from gravel.controllers.nodes.systemdisk import MountEntry, get_mounts

    lst: List[MountEntry] = get_mounts()
    found = False
    for entry in lst:
        if (entry.source == "/dev/mapper/aquarium-systemdisk"
                and entry.dest == "/var/lib/aquarium-system"):
            found = True
            break
    assert found
示例#5
0
def fake_filesystem(fs: FakeFilesystem) -> FakeFilesystem:
    """A pytest fixture which mocks the filesystem before each test."""
    # The "fs" argument triggers pyfakefs' own pytest fixture to register
    # After pyfakefs has started all filesystem actions will happen on a fake in-memory filesystem

    # Proxy access to certifi's certificate authority bundle to the real filesystem
    # This is required to be able to send HTTP requests using requests
    fs.add_real_file(certifi.where())

    # Proxy access to package data to the real filesystem
    fs.add_real_directory(os.path.join(os.path.dirname(__file__), "../lean/ssh"))

    # Create a fake home directory and set the cwd to an empty directory
    fs.create_dir(Path.home() / "testing")
    os.chdir(Path.home() / "testing")

    # Reset all singletons so Path instances get recreated
    # Path instances are bound to the filesystem that was active at the time of their creation
    # When the filesystem changes, old Path instances bound to previous filesystems may cause weird behavior
    container.reset_singletons()

    return fs
示例#6
0
def test_ceph_conf(fs: fake_filesystem.FakeFilesystem):
    # default location
    fs.add_real_file(  # pyright: reportUnknownMemberType=false
        os.path.join(TEST_DIR, 'data/default_ceph.conf'),
        target_path='/etc/ceph/ceph.conf'
    )
    Mgr()
    Mon()

    # custom location
    conf_file = '/foo/bar/baz.conf'
    fs.add_real_file(
        os.path.join(TEST_DIR, 'data/default_ceph.conf'),
        target_path=conf_file
    )
    Mgr(conf_file=conf_file)
    Mon(conf_file=conf_file)

    # invalid location
    conf_file = "missing.conf"
    with pytest.raises(FileNotFoundError, match=conf_file):
        Mgr(conf_file=conf_file)
        Mon(conf_file=conf_file)
示例#7
0
def test_ceph_conf(fs: fake_filesystem.FakeFilesystem, mocker: MockerFixture):
    mock_ceph_modules(mocker)
    from gravel.controllers.orch.ceph import Ceph

    # default location
    fs.add_real_file(  # pyright: reportUnknownMemberType=false
        os.path.join(TEST_DIR, "data/default_ceph.conf"),
        target_path="/etc/ceph/ceph.conf",
    )
    ceph = Ceph()
    ceph._check_config()  # pyright: reportPrivateUsage=false

    # custom location
    conf_file = "/foo/bar/baz.conf"
    fs.add_real_file(os.path.join(TEST_DIR, "data/default_ceph.conf"),
                     target_path=conf_file)
    ceph = Ceph(conf_file=conf_file)
    ceph._check_config()  # pyright: reportPrivateUsage=false

    # invalid location
    conf_file = "missing.conf"
    with pytest.raises(FileNotFoundError, match=conf_file):
        ceph = Ceph(conf_file=conf_file)
        ceph._check_config()  # pyright: reportPrivateUsage=false
示例#8
0
async def test_enable(
    gstate: GlobalState,
    fs: fake_filesystem.FakeFilesystem,
    mocker: MockerFixture,
) -> None:

    from gravel.controllers.nodes.systemdisk import (
        MountError,
        OverlayError,
        SystemDisk,
    )

    async def mount_fail() -> None:
        raise MountError("Failed mount.")

    overlayed_paths = []
    bindmounts = []

    async def mock_call(
        cmd: List[str],
    ) -> Tuple[int, Optional[str], Optional[str]]:

        if cmd[2] == "overlay":
            assert "lower" in cmd[4]
            lowerstr = (cmd[4].split(","))[0]
            lower = (lowerstr.split("="))[1]
            overlayed_paths.append(lower)
        elif cmd[1] == "--bind":
            assert len(cmd) == 4
            bindmounts.append(cmd[3])
        else:
            raise Exception(f"Unknown call: {cmd}")
        return 0, None, None

    # ensure we don't have a mounted fs
    fs.add_real_file(
        source_path=os.path.join(DATA_DIR, "mounts_without_aquarium.raw"),
        target_path="/proc/mounts",
    )

    systemdisk = SystemDisk(gstate)
    assert not systemdisk.mounted
    systemdisk.mount = mount_fail

    mocker.patch(
        "gravel.controllers.nodes.systemdisk.aqr_run_cmd", new=mock_call
    )

    throws = False
    try:
        await systemdisk.enable()
    except OverlayError as e:
        assert "failed mount" in e.message.lower()
        throws = True
    assert throws

    systemdisk.mount = mocker.AsyncMock()

    for upper in systemdisk._overlaydirs.keys():
        fs.create_dir(f"/var/lib/aquarium-system/{upper}/overlay")
        fs.create_dir(f"/var/lib/aquarium-system/{upper}/temp")

    for ours in systemdisk._bindmounts.keys():
        fs.create_dir(f"/var/lib/aquarium-system/{ours}")

    await systemdisk.enable()

    for lower in systemdisk._overlaydirs.values():
        assert fs.exists(lower)
        assert lower in overlayed_paths

    for theirs in systemdisk._bindmounts.values():
        assert fs.exists(theirs)
        assert theirs in bindmounts
示例#9
0
async def test_network(
    mocker: MockerFixture,
    fs: fake_filesystem.FakeFilesystem,
) -> None:
    async def mock_restart_network(
        cmd: List[str], ) -> Tuple[int, Optional[str], Optional[str]]:
        assert cmd == ["systemctl", "restart", "network.service"]
        return 0, None, None

    mocker.patch(
        "gravel.controllers.resources.network.aqr_run_cmd",
        new=mock_restart_network,
    )

    from gravel.controllers.resources.network import (
        InterfaceConfigModel,
        InterfaceModel,
        Network,
        RouteModel,
    )

    fs.create_dir(
        "/sys/devices/pci0000:00/0000:00:02.0/0000:01:00.0/net/enp1s0")
    fs.create_symlink(
        "/sys/class/net/enp1s0/device",
        "/sys/devices/pci0000:00/0000:00:02.0/0000:01:00.0/net/enp1s0",
    )
    fs.create_dir("/sys/class/net/virbr0")

    fs.add_real_file(
        source_path=os.path.join(DATA_DIR, "ifcfg-eth0"),
        target_path="/etc/sysconfig/network/ifcfg-eth0",
    )
    fs.create_file("/etc/sysconfig/network/ifcfg-eth0~")
    fs.create_file("/etc/sysconfig/network/ifcfg-eth0.rpmsave")
    fs.create_file("/etc/sysconfig/network/ifcfg-lo")
    fs.add_real_file(
        source_path=os.path.join(DATA_DIR, "config"),
        target_path="/etc/sysconfig/network/config",
    )

    network = Network(5.0)
    assert await network._should_tick()

    await network._do_tick()

    ifaces = network.interfaces
    assert len(ifaces) > 0

    assert "eth0" in ifaces
    assert ifaces["eth0"].name == "eth0"
    assert ifaces["eth0"].config.bootproto == "dhcp"
    assert ifaces["eth0"].config.ipaddr == ""
    assert ifaces["eth0"].config.bonding_slaves == []

    assert "eth0~" not in ifaces
    assert "eth0.rpmsave" not in ifaces

    assert "enp1s0" in ifaces
    assert ifaces["enp1s0"].config is None

    assert "virbr0" not in ifaces

    assert "lo" not in ifaces

    assert network.nameservers == []

    assert network.routes == []

    ifaces["bond0"] = InterfaceModel(
        name="bond0",
        config=InterfaceConfigModel(
            bootproto="static",
            ipaddr="192.168.121.10/24",
            bonding_slaves=["enp1s0", "enp2s0"],
        ),
    )
    await network.apply_config(
        ifaces,
        ["8.8.8.8", "1.1.1.1"],
        routes=[
            RouteModel(destination="default", gateway="192.168.121.1"),
            RouteModel(destination="192.168.0.0/16", interface="bond0"),
        ],
    )

    ifaces = network.interfaces
    assert "bond0" in ifaces
    assert os.path.exists("/etc/sysconfig/network/ifcfg-enp1s0")
    assert os.path.exists("/etc/sysconfig/network/ifcfg-enp2s0")
    assert network.nameservers == ["8.8.8.8", "1.1.1.1"]
    assert os.path.exists("/etc/sysconfig/network/routes")
    assert os.path.exists("/etc/sysconfig/network/ifroute-bond0")
    assert len(network.routes) == 2