Add option to ignore a directory on a vessel

This commit is contained in:
Kumi 2021-11-30 15:44:50 +01:00
parent 4de807b37e
commit c072f15b16
3 changed files with 31 additions and 13 deletions

View file

@ -50,7 +50,7 @@ Note: Currently, the same Location value is used on both the shore and the vesse
### Vessel ### Vessel
You can configure as many vessels to replicate your files to as you want by adding multiple `Vessel` sections. All configured directories are replicated to all vessels. If you want to use an SSH key to authenticate on the vessels, make sure that it is picked up by the local SSH agent (i.e. you can login using the key when connecting with the `ssh` command). You can configure as many vessels to replicate your files to as you want by adding multiple `Vessel` sections. All configured directories are replicated to all vessels by default, but you can use the IgnoreDirs directive to exclude a directory from a given vessel. If you want to use an SSH key to authenticate on the vessels, make sure that it is picked up by the local SSH agent (i.e. you can login using the key when connecting with the `ssh` command).
```ini ```ini
[Vessel samplevessel] # Each vessel needs a unique name - here: "samplevessel" [Vessel samplevessel] # Each vessel needs a unique name - here: "samplevessel"
@ -60,10 +60,9 @@ Username = replication # Username to authenticate as on the vessel (default: sa
Password = verysecret # Password to use to authenticate on the vessel (default: none, use SSH key) Password = verysecret # Password to use to authenticate on the vessel (default: none, use SSH key)
Passphrase = moresecret # Passphrase of the SSH key you use to authenticate (default: none, key has no passphrase) Passphrase = moresecret # Passphrase of the SSH key you use to authenticate (default: none, key has no passphrase)
Port = 22 # Port of the SSH server on the vessel (default: 22) Port = 22 # Port of the SSH server on the vessel (default: 22)
IgnoreDirs = sampledir, anotherdir # Names of directories *not* to replicate to this vessel, separated by commas
``` ```
Note: All configured directories are replicated to all of the configured vessels. This may be configurable in a future version.
## Running ## Running
To run the application after creating the `settings.ini`, navigate to ContentMonster's base directory in a terminal and make sure you are in the right virtual environment: To run the application after creating the `settings.ini`, navigate to ContentMonster's base directory in a terminal and make sure you are in the right virtual environment:

View file

@ -50,9 +50,12 @@ class Vessel:
if "Port" in config.keys(): if "Port" in config.keys():
port = config["Port"] port = config["Port"]
if "IgnoreDirs" in config.keys():
ignoredirs = [d.strip() for d in config["IgnoreDirs"].split(",")]
if "Address" in config.keys(): if "Address" in config.keys():
return cls(config.name.split()[1], config["Address"], username, return cls(config.name.split()[1], config["Address"], username,
password, passphrase, tempdir) password, passphrase, tempdir, ignoredirs)
else: else:
raise ValueError("Definition for Vessel " + raise ValueError("Definition for Vessel " +
config.name.split()[1] + " does not contain Address!") config.name.split()[1] + " does not contain Address!")
@ -60,7 +63,8 @@ class Vessel:
def __init__(self, name: str, address: str, username: Optional[str] = None, def __init__(self, name: str, address: str, username: Optional[str] = None,
password: Optional[str] = None, passphrase: Optional[str] = None, password: Optional[str] = None, passphrase: Optional[str] = None,
port: Optional[int] = None, timeout: Optional[int] = None, port: Optional[int] = None, timeout: Optional[int] = None,
tempdir: Optional[Union[str, pathlib.Path]] = None) -> None: tempdir: Optional[Union[str, pathlib.Path]] = None,
ignoredirs: list[Optional[str]] = []) -> None:
"""Initialize new Vessel object """Initialize new Vessel object
Args: Args:
@ -79,6 +83,7 @@ class Vessel:
self.timeout = timeout or 10 self.timeout = timeout or 10
self._connection = None self._connection = None
self._uploaded = self.getUploadedFromDB() # Files already uploaded self._uploaded = self.getUploadedFromDB() # Files already uploaded
self._ignoredirs = ignoredirs # Directories not replicated to this vessel
@property @property
def connection(self) -> Connection: def connection(self) -> Connection:

View file

@ -45,9 +45,10 @@ class VesselThread(Process):
@retry() @retry()
def assertDirectories(self) -> None: def assertDirectories(self) -> None:
for directory in self._state["config"].directories: for directory in self._state["config"].directories:
print( if not directory.name in self.vessel._ignoredirs:
f"Making sure directory {directory.name} exists on Vessel {self.vessel.name}") print(
self.vessel.connection.assertDirectories(directory) f"Making sure directory {directory.name} exists on Vessel {self.vessel.name}")
self.vessel.connection.assertDirectories(directory)
@retry() @retry()
def upload(self) -> None: def upload(self) -> None:
@ -72,7 +73,7 @@ class VesselThread(Process):
if not directory: if not directory:
self._logger.debug( self._logger.debug(
f"Directory {dirname} not specified in config - deleting File from Vessel {self.name}") f"Directory {dirname} not specified in config - deleting File from Vessel {self.vessel.name}")
self.vessel.clearTempDir() self.vessel.clearTempDir()
return return
@ -87,6 +88,17 @@ class VesselThread(Process):
else: else:
fileobj = current fileobj = current
if fileobj.directory.name in self.vessel._ignoredirs:
self._logger.debug(
f"Not replicating Directory {fileobj.directory.name} to Vessel {self.vessel.name} - marking complete")
db = Database()
db.logCompletion(fileobj, self.vessel)
del(db)
self.checkFileCompletion(fileobj, self.vessel)
return
remotefile = RemoteFile(fileobj, self.vessel, remotefile = RemoteFile(fileobj, self.vessel,
self._state["config"].chunksize) self._state["config"].chunksize)
@ -146,10 +158,12 @@ class VesselThread(Process):
complete = db.getCompletionByFileUUID(fileobj.uuid) complete = db.getCompletionByFileUUID(fileobj.uuid)
del(db) del(db)
for vessel in [v.name for v in self._state["config"].vessels]: for vessel in self._state["config"].vessels:
if vessel not in complete: if vessel.name not in complete and fileobj.directory.name not in vessel._ignoredirs:
return return
self._logger.debug(
f"File {fileobj.name} from Directory {fileobj.directory.name} transferred to all Vessels. Moving out of replication directory.")
fileobj.moveCompleted() fileobj.moveCompleted()
def processQueue(self) -> Optional[str]: def processQueue(self) -> Optional[str]: