Merged PR 373: 2536 - Removed 'real files' from FileSystem and FTP

## Summary
Removed 'real files' from FileSystem and FTP

## Test process
- Dropped any tests that contain 'real files'
- Ran remaining tests to check that everything still works

## Checklist
- [X] PR is linked to a **work item**
- [X] **acceptance criteria** of linked ticket are met
- [X] performed **self-review** of the code
- [X] written **tests** for any new functionality added with this PR
- [ ] updated the **documentation** if this PR changes or adds functionality
- [ ] written/updated **design docs** if this PR implements new functionality
- [ ] updated the **change log**
- [X] ran **pre-commit** checks for code style
- [ ] attended to any **TO-DOs** left in the code

2536 - Removed 'real files' from FileSystem and FTP

Related work items: #2536
This commit is contained in:
Christopher McCarthy
2024-05-14 08:05:56 +00:00
7 changed files with 10 additions and 88 deletions

View File

@@ -2,9 +2,7 @@ from __future__ import annotations
import hashlib import hashlib
import json import json
import os.path
import warnings import warnings
from pathlib import Path
from typing import Dict, Optional from typing import Dict, Optional
from primaite import getLogger from primaite import getLogger
@@ -21,8 +19,6 @@ class File(FileSystemItemABC):
:ivar Folder folder: The folder in which the file resides. :ivar Folder folder: The folder in which the file resides.
:ivar FileType file_type: The type of the file. :ivar FileType file_type: The type of the file.
:ivar Optional[int] sim_size: The simulated file size. :ivar Optional[int] sim_size: The simulated file size.
:ivar bool real: Indicates if the file is actually a real file in the Node sim fs output.
:ivar Optional[Path] sim_path: The path if the file is real.
""" """
folder_id: str folder_id: str
@@ -33,12 +29,6 @@ class File(FileSystemItemABC):
"The type of File." "The type of File."
sim_size: Optional[int] = None sim_size: Optional[int] = None
"The simulated file size." "The simulated file size."
real: bool = False
"Indicates whether the File is actually a real file in the Node sim fs output."
sim_path: Optional[Path] = None
"The Path if real is True."
sim_root: Optional[Path] = None
"Root path of the simulation."
num_access: int = 0 num_access: int = 0
"Number of times the file was accessed in the current step." "Number of times the file was accessed in the current step."
@@ -67,13 +57,6 @@ class File(FileSystemItemABC):
if not kwargs.get("sim_size"): if not kwargs.get("sim_size"):
kwargs["sim_size"] = kwargs["file_type"].default_size kwargs["sim_size"] = kwargs["file_type"].default_size
super().__init__(**kwargs) super().__init__(**kwargs)
if self.real:
self.sim_path = self.sim_root / self.path
if not self.sim_path.exists():
self.sim_path.parent.mkdir(exist_ok=True, parents=True)
with open(self.sim_path, mode="a"):
pass
self.sys_log.info(f"Created file /{self.path} (id: {self.uuid})") self.sys_log.info(f"Created file /{self.path} (id: {self.uuid})")
@property @property
@@ -92,8 +75,6 @@ class File(FileSystemItemABC):
:return: The size of the file in bytes. :return: The size of the file in bytes.
""" """
if self.real:
return os.path.getsize(self.sim_path)
return self.sim_size return self.sim_size
def apply_timestep(self, timestep: int) -> None: def apply_timestep(self, timestep: int) -> None:
@@ -127,7 +108,7 @@ class File(FileSystemItemABC):
self.num_access += 1 # file was accessed self.num_access += 1 # file was accessed
path = self.folder.name + "/" + self.name path = self.folder.name + "/" + self.name
self.sys_log.info(f"Scanning file {self.sim_path if self.sim_path else path}") self.sys_log.info(f"Scanning file {path}")
self.visible_health_status = self.health_status self.visible_health_status = self.health_status
return True return True
@@ -155,17 +136,8 @@ class File(FileSystemItemABC):
return False return False
current_hash = None current_hash = None
# if file is real, read the file contents # otherwise get describe_state dict and hash that
if self.real: current_hash = hashlib.blake2b(json.dumps(self.describe_state(), sort_keys=True).encode()).hexdigest()
with open(self.sim_path, "rb") as f:
file_hash = hashlib.blake2b()
while chunk := f.read(8192):
file_hash.update(chunk)
current_hash = file_hash.hexdigest()
else:
# otherwise get describe_state dict and hash that
current_hash = hashlib.blake2b(json.dumps(self.describe_state(), sort_keys=True).encode()).hexdigest()
# if the previous hash is None, set the current hash to previous # if the previous hash is None, set the current hash to previous
if self.previous_hash is None: if self.previous_hash is None:
@@ -188,7 +160,7 @@ class File(FileSystemItemABC):
self.num_access += 1 # file was accessed self.num_access += 1 # file was accessed
path = self.folder.name + "/" + self.name path = self.folder.name + "/" + self.name
self.sys_log.info(f"Repaired file {self.sim_path if self.sim_path else path}") self.sys_log.info(f"Repaired file {path}")
return True return True
def corrupt(self) -> bool: def corrupt(self) -> bool:
@@ -203,7 +175,7 @@ class File(FileSystemItemABC):
self.num_access += 1 # file was accessed self.num_access += 1 # file was accessed
path = self.folder.name + "/" + self.name path = self.folder.name + "/" + self.name
self.sys_log.info(f"Corrupted file {self.sim_path if self.sim_path else path}") self.sys_log.info(f"Corrupted file {path}")
return True return True
def restore(self) -> bool: def restore(self) -> bool:
@@ -217,7 +189,7 @@ class File(FileSystemItemABC):
self.num_access += 1 # file was accessed self.num_access += 1 # file was accessed
path = self.folder.name + "/" + self.name path = self.folder.name + "/" + self.name
self.sys_log.info(f"Restored file {self.sim_path if self.sim_path else path}") self.sys_log.info(f"Restored file {path}")
return True return True
def delete(self) -> bool: def delete(self) -> bool:

View File

@@ -1,6 +1,5 @@
from __future__ import annotations from __future__ import annotations
import shutil
from pathlib import Path from pathlib import Path
from typing import Dict, Optional from typing import Dict, Optional
@@ -230,7 +229,6 @@ class FileSystem(SimComponent):
size: Optional[int] = None, size: Optional[int] = None,
file_type: Optional[FileType] = None, file_type: Optional[FileType] = None,
folder_name: Optional[str] = None, folder_name: Optional[str] = None,
real: bool = False,
) -> File: ) -> File:
""" """
Creates a File and adds it to the list of files. Creates a File and adds it to the list of files.
@@ -239,7 +237,6 @@ class FileSystem(SimComponent):
:param size: The size the file takes on disk in bytes. :param size: The size the file takes on disk in bytes.
:param file_type: The type of the file. :param file_type: The type of the file.
:param folder_name: The folder to add the file to. :param folder_name: The folder to add the file to.
:param real: "Indicates whether the File is actually a real file in the Node sim fs output."
""" """
if folder_name: if folder_name:
# check if file with name already exists # check if file with name already exists
@@ -258,8 +255,6 @@ class FileSystem(SimComponent):
file_type=file_type, file_type=file_type,
folder_id=folder.uuid, folder_id=folder.uuid,
folder_name=folder.name, folder_name=folder.name,
real=real,
sim_path=self.sim_root if real else None,
sim_root=self.sim_root, sim_root=self.sim_root,
sys_log=self.sys_log, sys_log=self.sys_log,
) )
@@ -368,11 +363,6 @@ class FileSystem(SimComponent):
# add file to dst # add file to dst
dst_folder.add_file(file) dst_folder.add_file(file)
self.num_file_creations += 1 self.num_file_creations += 1
if file.real:
old_sim_path = file.sim_path
file.sim_path = file.sim_root / file.path
file.sim_path.parent.mkdir(exist_ok=True)
shutil.move(old_sim_path, file.sim_path)
def copy_file(self, src_folder_name: str, src_file_name: str, dst_folder_name: str): def copy_file(self, src_folder_name: str, src_file_name: str, dst_folder_name: str):
""" """
@@ -401,9 +391,6 @@ class FileSystem(SimComponent):
dst_folder.add_file(file_copy, force=True) dst_folder.add_file(file_copy, force=True)
if file.real:
file_copy.sim_path.parent.mkdir(exist_ok=True)
shutil.copy2(file.sim_path, file_copy.sim_path)
else: else:
self.sys_log.error(f"Unable to copy file. {src_file_name} does not exist.") self.sys_log.error(f"Unable to copy file. {src_file_name} does not exist.")

View File

@@ -126,7 +126,6 @@ class FTPClient(FTPServiceABC):
dest_file_name: str, dest_file_name: str,
dest_port: Optional[Port] = Port.FTP, dest_port: Optional[Port] = Port.FTP,
session_id: Optional[str] = None, session_id: Optional[str] = None,
real_file_path: Optional[str] = None,
) -> bool: ) -> bool:
""" """
Send a file to a target IP address. Send a file to a target IP address.

View File

@@ -1,4 +1,3 @@
import shutil
from abc import ABC from abc import ABC
from ipaddress import IPv4Address from ipaddress import IPv4Address
from typing import Dict, Optional from typing import Dict, Optional
@@ -55,19 +54,17 @@ class FTPServiceABC(Service, ABC):
file_name = payload.ftp_command_args["dest_file_name"] file_name = payload.ftp_command_args["dest_file_name"]
folder_name = payload.ftp_command_args["dest_folder_name"] folder_name = payload.ftp_command_args["dest_folder_name"]
file_size = payload.ftp_command_args["file_size"] file_size = payload.ftp_command_args["file_size"]
real_file_path = payload.ftp_command_args.get("real_file_path")
health_status = payload.ftp_command_args["health_status"] health_status = payload.ftp_command_args["health_status"]
is_real = real_file_path is not None
file = self.file_system.create_file( file = self.file_system.create_file(
file_name=file_name, folder_name=folder_name, size=file_size, real=is_real file_name=file_name,
folder_name=folder_name,
size=file_size,
) )
file.health_status = health_status file.health_status = health_status
self.sys_log.info( self.sys_log.info(
f"{self.name}: Created item in {self.sys_log.hostname}: {payload.ftp_command_args['dest_folder_name']}/" f"{self.name}: Created item in {self.sys_log.hostname}: {payload.ftp_command_args['dest_folder_name']}/"
f"{payload.ftp_command_args['dest_file_name']}" f"{payload.ftp_command_args['dest_file_name']}"
) )
if is_real:
shutil.copy(real_file_path, file.sim_path)
# file should exist # file should exist
return self.file_system.get_file(file_name=file_name, folder_name=folder_name) is not None return self.file_system.get_file(file_name=file_name, folder_name=folder_name) is not None
except Exception as e: except Exception as e:
@@ -115,7 +112,6 @@ class FTPServiceABC(Service, ABC):
"dest_folder_name": dest_folder_name, "dest_folder_name": dest_folder_name,
"dest_file_name": dest_file_name, "dest_file_name": dest_file_name,
"file_size": file.sim_size, "file_size": file.sim_size,
"real_file_path": file.sim_path if file.real else None,
"health_status": file.health_status, "health_status": file.health_status,
}, },
packet_payload_size=file.sim_size, packet_payload_size=file.sim_size,

View File

@@ -57,20 +57,6 @@ def test_simulated_file_check_hash(file_system):
assert file.health_status == FileSystemItemHealthStatus.CORRUPT assert file.health_status == FileSystemItemHealthStatus.CORRUPT
@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented")
def test_real_file_check_hash(file_system):
file: File = file_system.create_file(file_name="test_file.txt", real=True)
file.check_hash()
assert file.health_status == FileSystemItemHealthStatus.GOOD
# change file content
with open(file.sim_path, "a") as f:
f.write("get hacked scrub lol xD\n")
file.check_hash()
assert file.health_status == FileSystemItemHealthStatus.CORRUPT
def test_file_corrupt_repair_restore(file_system): def test_file_corrupt_repair_restore(file_system):
"""Test the ability to corrupt and repair files.""" """Test the ability to corrupt and repair files."""
file: File = file_system.create_file(file_name="test_file.txt", folder_name="test_folder") file: File = file_system.create_file(file_name="test_file.txt", folder_name="test_folder")

View File

@@ -191,7 +191,7 @@ def test_copy_file(file_system):
file_system.create_folder(folder_name="src_folder") file_system.create_folder(folder_name="src_folder")
file_system.create_folder(folder_name="dst_folder") file_system.create_folder(folder_name="dst_folder")
file = file_system.create_file(file_name="test_file.txt", size=10, folder_name="src_folder", real=True) file = file_system.create_file(file_name="test_file.txt", size=10, folder_name="src_folder")
assert file_system.num_file_creations == 1 assert file_system.num_file_creations == 1
original_uuid = file.uuid original_uuid = file.uuid

View File

@@ -132,21 +132,3 @@ def test_simulated_folder_check_hash(file_system):
file.sim_size = 0 file.sim_size = 0
folder.check_hash() folder.check_hash()
assert folder.health_status == FileSystemItemHealthStatus.CORRUPT assert folder.health_status == FileSystemItemHealthStatus.CORRUPT
@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented")
def test_real_folder_check_hash(file_system):
folder: Folder = file_system.create_folder(folder_name="test_folder")
file_system.create_file(file_name="test_file.txt", folder_name="test_folder", real=True)
folder.check_hash()
assert folder.health_status == FileSystemItemHealthStatus.GOOD
# change simulated file size
file = folder.get_file(file_name="test_file.txt")
# change file content
with open(file.sim_path, "a") as f:
f.write("get hacked scrub lol xD\n")
folder.check_hash()
assert folder.health_status == FileSystemItemHealthStatus.CORRUPT