Skip to content

Commit

Permalink
Add a preliminary checker to ensure the mount points in /etc/fstab ar…
Browse files Browse the repository at this point in the history
…e in the correct order
  • Loading branch information
Mikhail Sandakov committed Nov 25, 2024
1 parent 2391b2f commit 3b10ded
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 1 deletion.
24 changes: 23 additions & 1 deletion pleskdistup/actions/common_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import typing
from abc import abstractmethod

from pleskdistup.common import action, log, packages, php, plesk, version
from pleskdistup.common import action, log, mounts, packages, php, plesk, version


# This action should be considered as deprecated
Expand Down Expand Up @@ -677,3 +677,25 @@ def _do_check(self) -> bool:
return True

return False


class AssertFstabOrderingIsFine(action.CheckAction):
FSTAB_PATH: str = "/etc/fstab"

def __init__(self):
self.name = "checking if /etc/fstab is ordered properly"
self.description = """The /etc/fstab file entries is not ordered properly.
\t- {}"""

def _do_check(self) -> bool:
if not os.path.exists(self.FSTAB_PATH):
# Might be a problem, but it is not something we checking in scope of this check
return True

missorderings = mounts.get_fstab_configuration_misorderings(self.FSTAB_PATH)

if len(missorderings) == 0:
return True

self.description = self.description.format("\n\t- ".join([f"Mount point {mount_point} should be placed after {parent_dir}" for parent_dir, mount_point in missorderings]))
return False
1 change: 1 addition & 0 deletions pleskdistup/common/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from . import mariadb
from . import leapp_configs
from . import motd
from . import mounts
from . import packages
from . import php
from . import plesk
Expand Down
47 changes: 47 additions & 0 deletions pleskdistup/common/src/mounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2023-2024. WebPros International GmbH. All rights reserved.
import os
import typing


def get_fstab_configuration_misorderings(configpath: str) -> typing.List[typing.Tuple[str, str]]:
"""
Analyzes the fstab configuration file to find misorderings in mount points.
This function reads the fstab configuration file specified by `configpath` and checks for any misorderings
in the mount points. A misordering is defined as a mount point that appears before its parent directory
in the fstab file.
Args:
configpath (str): The path to the fstab configuration file.
Returns:
List[Tuple[str, str]]: A list of tuples where each tuple contains a misordered parent directory and
its corresponding mount point.
Example:
>>> get_fstab_configuration_misorderings('/etc/fstab')
[('/home', '/home/user'), ('/var', '/var/log')]
"""

if not os.path.exists(configpath):
return []

mount_points_order = {}
with open(configpath, "r") as f:
for iter, line in enumerate(f.readlines()):
if line.startswith("#") or line == "\n" or line == "":
continue
mount_point = line.split()[1]
mount_points_order[mount_point] = iter

missorderings = []
for mount_point in mount_points_order.keys():
if mount_point == "/":
continue

if mount_points_order["/"] > mount_points_order[mount_point]:
missorderings.append(("/", mount_point))

leading_paths = mount_point.split("/")[:-1]
for i in range(1, len(leading_paths) + 1):
parent_dir = "/".join(leading_paths[:i])
if parent_dir in mount_points_order and mount_points_order[parent_dir] > mount_points_order[mount_point]:
missorderings.append((parent_dir, mount_point))

return missorderings
72 changes: 72 additions & 0 deletions pleskdistup/common/tests/mountstests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright 2023-2024. WebPros International GmbH. All rights reserved.
import unittest
import tempfile

import src.mounts as mounts


class FstabMisorderingTests(unittest.TestCase):
def setUp(self):
self.test_file_path = tempfile.mktemp()

def test_no_file(self):
self.assertEqual(mounts.get_fstab_configuration_misorderings("noexist.txt"), [])

def test_empty_file(self):
with open(self.test_file_path, "w") as _:
pass
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [])

def test_empty_string(self):
with open(self.test_file_path, "w") as f:
f.write("")
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [])

def test_one_mount_point(self):
with open(self.test_file_path, "w") as f:
f.write("# comment\n")
f.write("/dev/sda1 / ext4 defaults 0 1\n")
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [])

def test_no_misorderings(self):
with open(self.test_file_path, "w") as f:
f.write("# comment\n")
f.write("/dev/sda1 / ext4 defaults 0 1\n")
f.write("/dev/sda2 /var ext4 defaults 0 1\n")
f.write("proc /proc proc defaults 0 0\n")
f.write("devpts /dev/pts devpts gid=5,mode=620 0 0\n")
f.write("tmpfs /dev/shm tmpfs defaults 0 0\n")
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [])

def test_one_misordering(self):
with open(self.test_file_path, "w") as f:
f.write("# comment\n")
f.write("/dev/sda2 /var ext4 defaults 0 1\n")
f.write("/dev/sda1 / ext4 defaults 0 1\n")
f.write("proc /proc proc defaults 0 0\n")
f.write("devpts /dev/pts devpts gid=5,mode=620 0 0\n")
f.write("tmpfs /dev/shm tmpfs defaults 0 0\n")
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [("/", "/var")])

def test_two_misorderings_for_one_parent(self):
with open(self.test_file_path, "w") as f:
f.write("# comment\n")
f.write("/dev/sda2 /var ext4 defaults 0 1\n")
f.write("/dev/sda3 /var/log ext4 defaults 0 1\n")
f.write("/dev/sda1 / ext4 defaults 0 1\n")
f.write("proc /proc proc defaults 0 0\n")
f.write("devpts /dev/pts devpts gid=5,mode=620 0 0\n")
f.write("tmpfs /dev/shm tmpfs defaults 0 0\n")
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [("/", "/var"), ("/", "/var/log")])

def test_several_different_misorderings(self):
with open(self.test_file_path, "w") as f:
f.write("# comment\n")
f.write("/dev/sda2 /var ext4 defaults 0 1\n")
f.write("/dev/sda1 / ext4 defaults 0 1\n")
f.write("/dev/sda5 /home/test ext4 defaults 0 1\n")
f.write("/dev/sda4 /home ext4 defaults 0 1\n")
f.write("proc /proc proc defaults 0 0\n")
f.write("devpts /dev/pts devpts gid=5,mode=620 0 0\n")
f.write("tmpfs /dev/shm tmpfs defaults 0 0\n")
self.assertEqual(mounts.get_fstab_configuration_misorderings(self.test_file_path), [("/", "/var"), ("/home", "/home/test")])

0 comments on commit 3b10ded

Please sign in to comment.