wip
This commit is contained in:
125
zfs_autobackup
125
zfs_autobackup
@ -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"""
|
||||||
|
|||||||
Reference in New Issue
Block a user