Skip to content

Commit

Permalink
Merge pull request #93 from plesk/check-fstab
Browse files Browse the repository at this point in the history
Add a preliminary checker to ensure the mount points in /etc/fstab are in the correct order
  • Loading branch information
SandakovMM authored Nov 26, 2024
2 parents 2391b2f + 2b13cb0 commit 240a7b3
Show file tree
Hide file tree
Showing 4 changed files with 155 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

misorderings = mounts.get_fstab_configuration_misorderings(self.FSTAB_PATH)

if len(misorderings) == 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 misorderings]))
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
48 changes: 48 additions & 0 deletions pleskdistup/common/src/mounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# 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: typing.Dict[str, int] = {}
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

misorderings: typing.List[typing.Tuple[str, str]] = []
for mount_point in mount_points_order.keys():
if mount_point == "/":
continue

parent_dir: str = mount_point
root_found: bool = False

while not root_found:
parent_dir = os.path.dirname(parent_dir)
if parent_dir in mount_points_order and mount_points_order[parent_dir] > mount_points_order[mount_point]:
misorderings.append((parent_dir, mount_point))
if parent_dir == "/":
root_found = True

return misorderings
83 changes: 83 additions & 0 deletions pleskdistup/common/tests/mountstests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 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")])

def test_file_without_root(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/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), [("/home", "/home/test")])

0 comments on commit 240a7b3

Please sign in to comment.