Add option to ignore a directory on a vessel
This commit is contained in:
parent
4de807b37e
commit
c072f15b16
3 changed files with 31 additions and 13 deletions
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
Loading…
Reference in a new issue