diff options
author | Ludovic Pouzenc <lpouzenc@gmail.com> | 2015-06-14 22:30:48 +0200 |
---|---|---|
committer | Ludovic Pouzenc <lpouzenc@gmail.com> | 2015-06-14 22:30:48 +0200 |
commit | 8847a025b334ea0d9814215291e8f546dd5f1e7e (patch) | |
tree | 9bcb8a853168db91d76cc7ac35df4cbc655a0480 | |
parent | 5943acb92ce0159e9f482748e4fa4aadddae6851 (diff) | |
download | raidguessfs-8847a025b334ea0d9814215291e8f546dd5f1e7e.tar.gz raidguessfs-8847a025b334ea0d9814215291e8f546dd5f1e7e.tar.bz2 raidguessfs-8847a025b334ea0d9814215291e8f546dd5f1e7e.zip |
Various minor improovements
* Log full stacktraces on exceptions
* Compute correctly raid_size
* Do all needed sanity checks on raid_disk_order
-rw-r--r-- | myraid.py | 32 | ||||
-rwxr-xr-x | raidguessfs.py | 27 |
2 files changed, 40 insertions, 19 deletions
@@ -26,17 +26,23 @@ class MyRaid(): def __init__(self, *args, **kwargs): self.raid_start = 0 self.raid_end = 0 - self.raid_size = 0 self.raid_sector_size = 512 self.raid_chunk_size = 65536 - self.raid_disk_order = range(15) + self.raid_disk_order = [] + self.raid_disk_count = 0 self.raid_types = [ '0', '1', '5', '5+0' ] - def _update_raid_size(self): - if self.raid_end > self.raid_start: - self.raid_size = self.raid_end - self.raid_start + def get_raid_size(self, raid_type): + size = self.raid_end - self.raid_start + if size <= 0: + return 0 else: - self.raid_size = 0 + return { + '0': size * self.raid_disk_count, + '1': size, + '5': size * (self.raid_disk_count - 1) if self.raid_disk_count >= 3 else 0, + '5+0': size * (self.raid_disk_count - 2) if self.raid_disk_count >= 6 and self.raid_disk_count % 2 == 0 else 0 , + }[raid_type] def get_raid_start(self): return self.raid_start @@ -53,12 +59,10 @@ class MyRaid(): def set_raid_start(self, new_raid_start): """Update the start offset of raid data on underlying disks""" self.raid_start = new_raid_start - self._update_raid_size() def set_raid_end(self, new_raid_end): """Update the end offset of raid data on underlying disks""" self.raid_end = new_raid_end - self._update_raid_size() def set_raid_chunk_size(self, new_raid_chunk_size): """Update the size of chucks of data (or slice size)""" @@ -66,7 +70,19 @@ class MyRaid(): def set_raid_disk_order(self, new_raid_disk_order): """Update the raid logical disk order""" + card=len(new_raid_disk_order) + check=[0]*card + for item in new_raid_disk_order: + d = int(item) + if not 0 <= d < card: + raise ValueError('Value out of range : %i [0,%i]'%(d,card-1)) + check[d]=check[d]+1 + + for d in range(card): + if check[d]!=1: + raise ValueError('Disk %i appears %i times (must be 1)'%(d,check[d])) self.raid_disk_order = new_raid_disk_order + self.raid_disk_count = len(new_raid_disk_order) def read_data(self,raid_type,disks,offset,size): diff --git a/raidguessfs.py b/raidguessfs.py index ffb0912..6b78a7d 100755 --- a/raidguessfs.py +++ b/raidguessfs.py @@ -120,7 +120,7 @@ class RaidGuessFS(fuse.Fuse): for raid_type in self.raid.raid_types: self.fattr['/raid/%s/data_xor'%raid_type].st_size = 0 # self.raid.raid_size self.fattr['/raid/%s/parity'%raid_type].st_size = min(self.d.disks_size) / self.raid.raid_sector_size * 16 - self.fattr['/raid/%s/result'%raid_type].st_size = self.raid.raid_size + self.fattr['/raid/%s/result'%raid_type].st_size = self.raid.get_raid_size(raid_type) logging.debug("Exit. _refresh_raid_fattr()") @@ -178,10 +178,15 @@ class RaidGuessFS(fuse.Fuse): logging.debug("Enter update_raid_disk_order(%s)"%arg) if type(arg) is str: l = arg.split() - else: + elif type(arg) is list: l = arg - # TODO : sanity checks (every disk number below disk count, len(list) below disk count, no double...) + else: + raise TypeError('update_raid_disk_order() wants a list or str') logging.debug("==> %s (%d/%d)"%(l,len(l),self.d.disk_count)) + + if len(l) != self.d.disk_count: + raise ValueError('Value count does not match disk count') + self.raid.set_raid_disk_order(l) logging.debug("Exit. update_raid_disk_order(%s)"%arg) @@ -195,7 +200,7 @@ class RaidGuessFS(fuse.Fuse): """Make some run-time initalisations after argument parsing""" logging.info("Mounting filesystem...") # WARNING : this method is called by FUSE in a context that don't show fatal exceptions, - # even with -d[ebug] flag set, so log all exceptions stupidly + # even with -d[ebug] flag set, so log all exceptions try: self.dattr = { path: self.st.make_fake_dir() for path in self.dentries.keys() @@ -218,7 +223,7 @@ class RaidGuessFS(fuse.Fuse): logging.info("Mounted.") except Exception as e: - logging.error(e) + logging.exception(e) def getattr(self, path): logging.info("getattr: %s" % path) @@ -281,7 +286,7 @@ class RaidGuessFS(fuse.Fuse): return self.raid.check_data(raid_type,self.d.disks,offset,size) except Exception as e: - logging.error(e) + logging.exception(e) return -errno.ENOENT logging.error("Unimplemented read of '%s' (%s)"%(path, str(path_chuncks))) @@ -297,14 +302,14 @@ class RaidGuessFS(fuse.Fuse): # TODO take care here idx = self.settings.index(path_chuncks[1]) try: - self.settings_updaters[idx](buf) + self.settings_updaters[idx](buf.rstrip()) return len(buf) except Exception as e: - logging.error(e) + logging.exception(e) return -errno.EIO except Exception as e: - logging.error(e) + logging.exception(e) return -errno.ENOENT logging.error("Unimplemented write of '%s' (%s)"%(path, str(path_chuncks))) @@ -321,9 +326,9 @@ RaidGuessFS is a pseudo-filesystem that allows to guess parameters and disk orde fuse.fuse_python_api = (0, 2) LOG_FILENAME = "raidguessfs.log" - logging.basicConfig(filename=LOG_FILENAME,level=logging.WARN,) + #logging.basicConfig(filename=LOG_FILENAME,level=logging.WARN,) #logging.basicConfig(filename=LOG_FILENAME,level=logging.INFO,) - #logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,) + logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,) server = RaidGuessFS(version="%prog " + fuse.__version__,usage=usage,dash_s_do='setsingle') server.multithreaded = False |