@@ -172,11 +172,11 @@ def extract_properties(s):
172172 # traverse the child hierarchy or create if that fails
173173 try : fs = fs .get_child (pcomp )
174174 except KeyError :
175- fs = Dataset (pcomp , pool_cur , fs )
175+ fs = Dataset (pool_cur , pcomp , fs )
176176
177177 if snapshot :
178178 if snapshot not in [ x .name for x in fs .children ]:
179- fs = Snapshot (snapshot , fs )
179+ fs = Snapshot (pool_cur , snapshot , fs )
180180
181181 fs ._properties .update ( creations [fs .path ] )
182182
@@ -214,7 +214,8 @@ def walk(self):
214214 yield dset
215215
216216 def __iter__ (self ):
217- return self .walk ()
217+ for pool in self ._pools :
218+ yield self ._pools [pool ]
218219
219220
220221# Wrappers for testing
@@ -239,7 +240,8 @@ class ZFSItem(object):
239240
240241 creation = property (lambda self : datetime .fromtimestamp (int (self ._properties ["creation" ])))
241242
242- def __init__ (self , name , parent = None ):
243+ def __init__ (self , pool , name , parent = None ):
244+ self .pool = pool
243245 self .name = name
244246 self .children = []
245247 self ._properties = {}
@@ -265,9 +267,6 @@ def remove(self, child):
265267 for c in child .children :
266268 child .remove (c )
267269
268- def get_relative_name (self ):
269- if not self .parent : return self .name
270- return self .path [len (self .parent .path ) + 1 :]
271270
272271 def walk (self ):
273272 assert not self .invalidated , "%s invalidated" % self
@@ -286,30 +285,13 @@ def has_property(self, name):
286285 return (name in self ._properties )
287286
288287
289- # For name, use full dataset path
290- def get_dataset (self , name ):
291- assert not (isinstance (self , Snapshot )), "get_dataset(name) cannot be used on Snapshot Objects. Use Snapshot.dataset instead."
292- allds = self .get_all_datasets ()
293- pool_name = self .name if isinstance (self , Pool ) else self .pool .name
294- nfind = name if name .find (pool_name + '/' ) == 0 else '{}/{}' .format (pool_name , name )
295- for dataset in allds :
296- if dataset .path == nfind :
297- return dataset
298- raise ValueError ("Dataset '{}' not found in pool '{}'." .format (name , self .pool .name ))
299-
300-
301- # returns list(of str) or if with_depth == True then list(of tuple(of depth, Dataset))
302- def get_all_datasets (self , with_depth :bool = False , depth :int = 0 ):
303- a = []
304- for c in self .children :
305- if isinstance (c , Dataset ):
306- a .append ( (depth , c ) if with_depth else c )
307- a = a + c .get_all_datasets (with_depth = with_depth , depth = depth + 1 )
308- return a
309288
310289
311290class Snapable (ZFSItem ): # Abstract class for Pools and Datasets
312291
292+ def __init__ (self , pool , name , parent = None ):
293+ super ().__init__ (pool , name , parent )
294+
313295 # Lookup for Datasets or Snapshot by dataset relative path
314296 # Eg. for snapshots: <dataset_path>@<snapshot>
315297 def lookup (self , name ):
@@ -353,6 +335,7 @@ def get_snapshots(self, flt=True, index=False):
353335 for idx , c in enumerate (self .children ):
354336 if isinstance (c , Snapshot ) and flt (c ):
355337 res .append ( (idx , c , self .path ) if index else c )
338+
356339 return res
357340
358341
@@ -438,9 +421,57 @@ def __fil_dt(snap):
438421 else :
439422 (dt_f , dt_t ) = calcDateRange (tdelta = tdelta , dt_from = dt_from , dt_to = dt_to )
440423
424+
441425 return self .get_snapshots (flt = f , index = index )
442426
443427
428+
429+
430+
431+ # For name, use full dataset path
432+ def get_dataset (self , name ):
433+ assert not (isinstance (self , Snapshot )), "get_dataset(name) cannot be used on Snapshot Objects. Use Snapshot.dataset instead."
434+ allds = self .get_all_datasets ()
435+ pool_name = self .name if isinstance (self , Pool ) else self .pool .name
436+ nfind = name if name .find (pool_name + '/' ) == 0 else '{}/{}' .format (pool_name , name )
437+ for dataset in allds :
438+ if dataset .path == nfind :
439+ return dataset
440+ raise ValueError ("Dataset '{}' not found in pool '{}'." .format (name , self .pool .name ))
441+
442+
443+ # returns list(of str) or if with_depth == True then list(of tuple(of depth, Dataset))
444+ def get_all_datasets (self , with_depth :bool = False , depth :int = 0 ):
445+ a = []
446+ for c in self .children :
447+ if isinstance (c , Dataset ):
448+ a .append ( (depth , c ) if with_depth else c )
449+ a = a + c .get_all_datasets (with_depth = with_depth , depth = depth + 1 )
450+ return a
451+
452+
453+ class Pool (Snapable ):
454+ def __init__ (self , name , conn :Connection , have_mounts :bool ):
455+ super ().__init__ (self , name )
456+ self .connection = conn
457+ self .have_mounts = have_mounts
458+
459+
460+ def __str__ (self ):
461+ return "<Pool: %s>" % self .path
462+
463+ __repr__ = __str__
464+
465+
466+
467+ class Dataset (Snapable ):
468+
469+ def __init__ (self , pool , name , parent = None ):
470+ super ().__init__ (pool , name , parent )
471+ self .dspath = self .path [len (pool .name )+ 1 :]
472+ self ._mountpoint = None
473+
474+
444475 # get_diffs() - Gets Diffs in snapshot or between snapshots (if snap_to is specified)
445476 # snap_from - Left side of diff
446477 # snap_to - Right side of diff. If not specified, diff is to working copy
@@ -524,31 +555,6 @@ def __row(s):
524555 return diffs
525556
526557
527-
528- class Pool (Snapable ):
529- def __init__ (self , name , conn :Connection , have_mounts :bool ):
530- self .name = name
531- self .children = []
532- self ._properties = {}
533- self .connection = conn
534- self .have_mounts = have_mounts
535-
536-
537- def __str__ (self ):
538- return "<Pool: %s>" % self .path
539-
540- __repr__ = __str__
541-
542-
543-
544- class Dataset (Snapable ):
545-
546- def __init__ (self , name , pool :Pool , parent = None ):
547- super ().__init__ (name , parent )
548- self ._mountpoint = None
549- self .pool = pool
550- self .dspath = self .path [len (pool .name )+ 1 :]
551-
552558 def _get_mountpoint (self ):
553559 if self ._mountpoint is None :
554560 self .assertHaveMounts ()
@@ -569,14 +575,20 @@ def get_rel_path(self, path) -> str:
569575 p_real = os .path .realpath (p_real )
570576 mp = self .mountpoint
571577 if not p_real .find (mp ) == 0 :
572- raise KeyError ('path given is not in current datastore mountpoint {}. Path: {}' .format (mp , path ))
578+ raise KeyError ('path given is not in current dataset mountpoint {}. Path: {}' .format (mp , path ))
573579 return p_real .replace (mp , '' )
574-
580+
575581
576582 def assertHaveMounts (self ):
577583 assert self .pool .have_mounts , "Mount information not loaded. Please use Connection.load_poolset(get_mounts=True)."
578584
579585
586+
587+ def get_relative_name (self ):
588+ if not self .parent : return self .name
589+ return self .path [len (self .parent .path ) + 1 :]
590+
591+
580592 def __str__ (self ):
581593 if self .pool .have_mounts :
582594 return "<Dataset: %s> mountpoint: %s" % (self .path , self .mountpoint )
@@ -589,24 +601,23 @@ def __str__(self):
589601
590602
591603
592-
593-
594604class Snapshot (ZFSItem ):
595605
596- # def _get_dataset(self): return self.parent
597- dataset = property (lambda self : self .parent )
606+ def __init__ (self , pool , name , parent = None ):
607+ super ().__init__ (pool , name , parent )
608+ self .dataset = parent if isinstance (parent , Dataset ) else None
598609
599- pool = property (lambda self : self .parent .pool )
600610
601611 def _get_path (self ):
602612 if not self .parent : return self .name
603613 return "%s@%s" % (self .parent .path , self .name )
604614 path = property (_get_path )
605615
616+
606617 # Resolves the path to .zfs/snapshot directory
607618 def get_snap_path (self ):
608- self .dataset .assertHaveMounts ()
609- return "{}/.zfs/snapshot/{}" .format (self .dataset .mountpoint , self .name )
619+ self .parent .assertHaveMounts ()
620+ return "{}/.zfs/snapshot/{}" .format (self .parent .mountpoint , self .name )
610621 snap_path = property (get_snap_path )
611622
612623
@@ -618,7 +629,7 @@ def get_snap_path(self):
618629 # - str = Path to item if found else path to .zfs/snapshot directory
619630 # eg: (found, rel_path) = snap.resolve_snap_path('<some_path_on_system>')
620631 def resolve_snap_path (self , path ):
621- self .dataset .assertHaveMounts ()
632+ self .parent .assertHaveMounts ()
622633 if path is None or not isinstance (path , str ) or path .strip () == '' :
623634 assert 0 , "path must be a non-blank string"
624635 path = os .path .abspath ( pathlib .Path (path ).expanduser () )
@@ -734,9 +745,9 @@ def __str__(self):
734745
735746
736747
737- # Will resolve Pool and Datastore for a path on local filesystem using the mountpoint
738- # returns (Pool, DataStore , Real_Path, Relative_Path)
739- def find_datastore_for_path (poolset :PoolSet , path :str ) -> tuple :
748+ # Will resolve Pool and Dataset for a path on local filesystem using the mountpoint
749+ # returns (Pool, Dataset , Real_Path, Relative_Path)
750+ def find_dataset_for_path (poolset :PoolSet , path :str ) -> tuple :
740751 assert poolset .have_mounts , "Mount information not loaded. Please use Connection.load_poolset(get_mounts=True)."
741752 p_real = os .path .abspath ( pathlib .Path (path ).expanduser () )
742753 p_real = os .path .realpath (p_real )
0 commit comments