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)
class TreeNode():
"""generic tree implementation, with parent/child and prev/next relations"""
def __init__(self, name, parent=None, next=None, prev=None, *args, **kwargs):
self.childs={}
self.name=name
self.parent=parent
if parent:
if name in parent.childs:
raise(Exception("parent {} already has child {}").format(parent.name, name))
parent.childs[name]=self
self.next=next
if next:
if next.prev:
raise(Exception("{} already has a previous item").format(next.name))
next.prev=self
self.prev=prev
if prev:
if prev.next:
raise(Exception("{} already has a next item").format(prev.name))
prev.next=self
def remove(self):
"""remove the item from other referenced TreeNodes. call before you actually delete a treeobject"""
if self.parent:
self.parent.childs.remove(self.name)
# let previous and next objects point to eachother
if self.next:
self.next.prev=self.prev
if self.prev:
self.prev.next=self.next
self.parent=None
self.next=None
self.prev=None
# class TreeNode():
# """generic tree implementation, with parent/child and prev/next relations"""
# def __init__(self, name, parent=None, next=None, prev=None, *args, **kwargs):
# self.childs={}
#
# self.name=name
# self.parent=parent
# if parent:
# if name in parent.childs:
# raise(Exception("parent {} already has child {}").format(parent.name, name))
# parent.childs[name]=self
#
#
# self.next=next
# if next:
# if next.prev:
# raise(Exception("{} already has a previous item").format(next.name))
# next.prev=self
#
# self.prev=prev
# if prev:
# if prev.next:
# raise(Exception("{} already has a next item").format(prev.name))
# prev.next=self
#
#
# def remove(self):
# """remove the item from other referenced TreeNodes. call before you actually delete a treeobject"""
#
# if self.parent:
# self.parent.childs.remove(self.name)
#
#
# # let previous and next objects point to eachother
# if self.next:
# self.next.prev=self.prev
#
# if self.prev:
# self.prev.next=self.next
#
# self.parent=None
# self.next=None
# self.prev=None
#
#
class ZfsNode(TreeNode):
"""an endpoint that contains zfs filesystems.
class ExecuteNode:
"""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)
methods only accept and return simple dataset names, just like the real commands
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)
"""
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
def run(cmd, input=None, tab_split=False, valid_exitcodes=[ 0 ], test=False):
"""run a command on the node"""
def run(cmd, input=None, tab_split=False, valid_exitcodes=[ 0 ], readonly=False):
"""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=[]
#use ssh?
if self.ssh_to != "local":
if self.ssh_to != None:
encoded_cmd.extend(["ssh", self.ssh_to])
#make sure the command gets all the data in utf8 format:
@ -106,8 +107,8 @@ class ZfsNode(TreeNode):
#debug and test stuff
debug_txt="# "+" ".join(encoded_cmd)
if test:
debug("[SKIPPING] "+debug_txt)
if self.readonly and not readonly:
debug("[NOT EXECUTING (readonly mode)] "+debug_txt)
else:
debug(debug_txt)
@ -117,7 +118,7 @@ class ZfsNode(TreeNode):
else:
stdin=None
if test:
if self.readonly and not readonly:
return
#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):
"""a zfs pool"""