From a74c583656f3d9fadf50cf070e58235db1b2de90 Mon Sep 17 00:00:00 2001 From: Siddharth Ravikumar Date: Fri, 20 Feb 2015 09:56:53 -0500 Subject: New combox.events.NodeDirMonitor class defined. At the moment only the on_created method of this class is kinda fleshed out. The tests for this class is at tests.events_test.TestEvents.test_NDM modified: combox/events.py modified: tests/events_test.py --- combox/events.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++-- tests/events_test.py | 64 ++++++++++++++++++++++++++++++++++++++---- 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) -- cgit v1.2.3