summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--combox/events.py78
-rw-r--r--tests/events_test.py64
2 files changed, 134 insertions, 8 deletions
diff --git a/combox/events.py b/combox/events.py
index c159e1e..c466139 100644
--- a/combox/events.py
+++ b/combox/events.py
@@ -23,9 +23,10 @@ from os import path
from watchdog.events import LoggingEventHandler
-from combox.crypto import split_and_encrypt
+from combox.crypto import split_and_encrypt, decrypt_and_glue
from combox.file import (mk_nodedir, rm_nodedir, rm_shards,
- relative_path, move_shards, move_nodedir)
+ relative_path, move_shards, move_nodedir,
+ cb_path)
from combox.silo import ComboxSilo
@@ -154,3 +155,76 @@ class ComboxDirMonitor(LoggingEventHandler):
split_and_encrypt(event.src_path, self.config)
# update file info in silo.
self.silo.update(event.src_path)
+
+
+class NodeDirMonitor(LoggingEventHandler):
+ """Monitors Node directory for changes and does its crypto thing.
+
+ """
+
+ def __init__(self, config):
+ """
+ config: a dictinary which contains combox configuration.
+ """
+ super(NodeDirMonitor, self).__init__()
+
+ logging.basicConfig(level=logging.INFO,
+ format='%(asctime)s - %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S')
+
+ self.config = config
+ self.silo = ComboxSilo(self.config)
+
+
+ def housekeep(self):
+ """Recursively traverses node directory, discovers changes and updates silo and combox directory.
+
+ If it detects that a shard was deleted, it purges the
+ corresponding file from the combox director and also removes
+ information about the file from the silo.
+
+ If it detects new shards, it reconstructs the file and places
+ it at the corresponding location in the combox directory.
+
+ If it detects shards have been modified, it reconstructs the
+ file and places the modified file at the corresponding
+ location in the combox directory.
+
+ """
+ pass
+
+
+ def on_moved(self, event):
+ super(NodeDirMonitor, self).on_moved(event)
+ pass
+
+
+ def on_created(self, event):
+ super(NodeDirMonitor, self).on_created(event)
+
+ file_cb_path = cb_path(event.src_path, self.config)
+
+ if event.is_directory and (not path.exists(file_cb_path)):
+ # means, the directory was created on another computer
+ # (also running combox). so, create this directory
+ # under the combox directory
+ os.mkdir(file_cb_path)
+ elif (not event.is_directory) and (not path.exists(file_cb_path)):
+ # shard created.
+
+ # means, file was created on another computer (also
+ # running combox). so, reconstruct the file and put it
+ # in the combox directory.
+ decrypt_and_glue(file_cb_path, self.config)
+ # update db.
+ self.silo.update(file_cb_path)
+
+
+ def on_deleted(self, event):
+ super(ComboxDirMonitor, self).on_deleted(event)
+ pass
+
+
+ def on_modified(self, event):
+ super(NodeDirMonitor, self).on_modified(event)
+ pass
diff --git a/tests/events_test.py b/tests/events_test.py
index a6a941b..c62d3f2 100644
--- a/tests/events_test.py
+++ b/tests/events_test.py
@@ -29,11 +29,11 @@ from nose.tools import *
from watchdog.observers import Observer
from combox.config import get_nodedirs
-from combox.crypto import decrypt_and_glue
-from combox.events import ComboxDirMonitor
+from combox.crypto import decrypt_and_glue, split_and_encrypt
+from combox.events import ComboxDirMonitor, NodeDirMonitor
from combox.file import (relative_path, purge_dir,
read_file, write_file,
- rm_shards)
+ rm_shards, mk_nodedir)
from combox.silo import ComboxSilo
from tests.utils import (get_config, shardedp, dirp, renamedp,
@@ -52,14 +52,17 @@ class TestEvents(object):
self.config = get_config()
self.FILES_DIR = self.config['combox_dir']
- self.TEST_FILE = path.join(self.FILES_DIR,'thgttg-21st.png')
+ self.NODE_DIR = get_nodedirs(self.config)[0]
+ self.TEST_FILE = path.join(self.FILES_DIR, 'thgttg-21st.png')
self.lorem = path.join(self.FILES_DIR, 'lorem.txt')
- self.ipsum = path.join(self.FILES_DIR, "ipsum.txt")
+ self.ipsum = path.join(self.FILES_DIR, 'ipsum.txt')
self.lorem_moved = path.join(self.FILES_DIR, 'lorem.moved.txt')
self.lorem_ipsum = path.join(self.FILES_DIR, 'lorem.ipsum.txt')
-
+ # files that have to be removed at the end of this test class
+ # should be appended to this list.
+ self.purge_list = []
def test_CDM(self):
"""
@@ -222,6 +225,48 @@ class TestEvents(object):
assert not silo.stale(self.lorem_ipsum)
+ def test_NDM(self):
+ """
+ Tests the NodeDirMonitor class.
+ """
+
+ event_handler = NodeDirMonitor(self.config)
+ observer = Observer()
+ observer.schedule(event_handler, self.NODE_DIR, recursive=True)
+ observer.start()
+
+ # Test - new file addition, when shard is created in node_dirs
+ self.TEST_FILE_MUTANT = "%s.mutant" % self.TEST_FILE
+
+ fmutant_content = read_file(self.TEST_FILE)
+
+ split_and_encrypt(self.TEST_FILE_MUTANT, self.config,
+ fmutant_content)
+ ## wait for NodeDirMonitor to reconstruct the shards and put
+ ## it in combox directory
+ time.sleep(1)
+ assert fmutant_content == read_file(self.TEST_FILE_MUTANT)
+ ## check if the new file's info is in silo
+ silo = ComboxSilo(self.config)
+ assert silo.exists(self.TEST_FILE_MUTANT)
+
+ # Test - directory creation
+ self.FOO_DIR = path.join(self.FILES_DIR, 'foo')
+ mk_nodedir(self.FOO_DIR, self.config)
+ time.sleep(2)
+ ## check if FOO_DIR is created under the combox directory
+ assert path.isdir(self.FOO_DIR)
+
+ self.BAR_DIR = path.join(self.FOO_DIR, 'bar')
+ mk_nodedir(self.BAR_DIR, self.config)
+ time.sleep(2)
+ ## check if BAR_DIR is created under the combox directory.
+ assert path.isdir(self.BAR_DIR)
+
+ self.purge_list.append(self.TEST_FILE_MUTANT)
+ self.purge_list.append(self.FOO_DIR)
+
+
def teardown(self):
"""Cleans up things after each test in this class"""
purge_nodedirs(self.config)
@@ -246,3 +291,10 @@ class TestEvents(object):
rm_nodedirs(self.config)
rm_configdir()
+
+ for f in self.purge_list:
+ if path.exists(f) and path.isfile(f):
+ os.remove(f)
+ elif path.exists(f) and path.isdir(f):
+ purge_dir(f)
+ os.rmdir(f)