This commit is contained in:
Edwin Eefting
2019-10-19 13:52:34 +02:00
parent 765dbf124a
commit d12bff05ab

View File

@ -23,74 +23,75 @@ def debug(txt):
print(txt) print(txt)
class TreeNode(): # class TreeNode():
"""generic tree implementation, with parent/child and prev/next relations""" # """generic tree implementation, with parent/child and prev/next relations"""
def __init__(self, name, parent=None, next=None, prev=None, *args, **kwargs): # def __init__(self, name, parent=None, next=None, prev=None, *args, **kwargs):
self.childs={} # self.childs={}
#
self.name=name # self.name=name
self.parent=parent # self.parent=parent
if parent: # if parent:
if name in parent.childs: # if name in parent.childs:
raise(Exception("parent {} already has child {}").format(parent.name, name)) # raise(Exception("parent {} already has child {}").format(parent.name, name))
parent.childs[name]=self # parent.childs[name]=self
#
#
self.next=next # self.next=next
if next: # if next:
if next.prev: # if next.prev:
raise(Exception("{} already has a previous item").format(next.name)) # raise(Exception("{} already has a previous item").format(next.name))
next.prev=self # next.prev=self
#
self.prev=prev # self.prev=prev
if prev: # if prev:
if prev.next: # if prev.next:
raise(Exception("{} already has a next item").format(prev.name)) # raise(Exception("{} already has a next item").format(prev.name))
prev.next=self # prev.next=self
#
#
def remove(self): # def remove(self):
"""remove the item from other referenced TreeNodes. call before you actually delete a treeobject""" # """remove the item from other referenced TreeNodes. call before you actually delete a treeobject"""
#
if self.parent: # if self.parent:
self.parent.childs.remove(self.name) # self.parent.childs.remove(self.name)
#
#
# let previous and next objects point to eachother # # let previous and next objects point to eachother
if self.next: # if self.next:
self.next.prev=self.prev # self.next.prev=self.prev
#
if self.prev: # if self.prev:
self.prev.next=self.next # self.prev.next=self.next
#
self.parent=None # self.parent=None
self.next=None # self.next=None
self.prev=None # self.prev=None
#
#
class ZfsNode(TreeNode): class ExecuteNode:
"""an endpoint that contains zfs filesystems. """an endpoint to execute local or remote commands via ssh"""
contains lowlevel zfs wrappers for actual zfs commands on remote nodes via ssh (or local) def __init__(self, ssh_to=None, readonly=False):
"""ssh_to: server you want to ssh to. none means local
readonly: only execute commands that dont make any changes (usefull for testing-runs)
"""
methods only accept and return simple dataset names, just like the real commands
"""
def __init__(self, ssh_to, *args, **kwargs):
"""ssh_to: server you want to ssh to. specify 'local' to just use local commands without ssh"""
super().__init__(*args, **kwargs)
self.ssh_to=ssh_to self.ssh_to=ssh_to
def run(cmd, input=None, tab_split=False, valid_exitcodes=[ 0 ], test=False): def run(cmd, input=None, tab_split=False, valid_exitcodes=[ 0 ], readonly=False):
"""run a command on the node""" """run a command on the node
readonly: make this True if the command doesnt make any changes and is safe to execute in testmode
"""
encoded_cmd=[] encoded_cmd=[]
#use ssh? #use ssh?
if self.ssh_to != "local": if self.ssh_to != None:
encoded_cmd.extend(["ssh", self.ssh_to]) encoded_cmd.extend(["ssh", self.ssh_to])
#make sure the command gets all the data in utf8 format: #make sure the command gets all the data in utf8 format:
@ -106,8 +107,8 @@ class ZfsNode(TreeNode):
#debug and test stuff #debug and test stuff
debug_txt="# "+" ".join(encoded_cmd) debug_txt="# "+" ".join(encoded_cmd)
if test: if self.readonly and not readonly:
debug("[SKIPPING] "+debug_txt) debug("[NOT EXECUTING (readonly mode)] "+debug_txt)
else: else:
debug(debug_txt) debug(debug_txt)
@ -117,7 +118,7 @@ class ZfsNode(TreeNode):
else: else:
stdin=None stdin=None
if test: if self.readonly and not readonly:
return return
#execute and parse/return results #execute and parse/return results
@ -137,6 +138,12 @@ class ZfsNode(TreeNode):
"""a node that contains zfs datasets"""
class ZfsNode(ExecuteNode):
def __init__(self, ssh_to=None, readonly=False):
super().__init__(ssh_to=None, readonly=readonly)
class ZfsPool(TreeNode): class ZfsPool(TreeNode):
"""a zfs pool""" """a zfs pool"""