Skip to content

Commit

Permalink
Status improve #8
Browse files Browse the repository at this point in the history
More data, snapshot times, remote snapshot data.
HTML output type with tabulator.
  • Loading branch information
orgoj committed Apr 13, 2021
1 parent 0034e0b commit d382cf5
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 38 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ You also need the `faketime` program for some tests to simulate pyznap running o
I suggest installing [virtualenv & virtualenvwrapper](http://docs.python-guide.org/en/latest/dev/virtualenvs/),
so you don't clutter your system python installation with additional packages.

pyznap uses `mbuffer` and `lzop` (by default) to speed up zfs send/recv, and `pv` to show progress,
but also works if they are not installed. Other supported compression methods are: `none`, `lz4`,
pyznap uses `mbuffer` and `lzop` (by default) to speed up zfs send/recv, and `pv` to show progress,
but also works if they are not installed. Other supported compression methods are: `none`, `lz4`,
`gzip`, `pigz`, `bzip2` and `xz`.

Note that ZFS needs root access to run commands. Due to this you should install pyznap under your
Expand Down Expand Up @@ -246,6 +246,11 @@ Run `pyznap -h` to see all available options.

Check snapshots state and print counts with info.

Example stats as html table with petl https://pypi.org/project/petl/: `pyznap status --raw | petl 'fromjson(None, lines=True).tohtml("/tmp/pyznap.html")'`
Table manipulation in Crome with extension Tabulazer https://chrome.google.com/webstore/detail/tabulazer-table-filter-an/ikfbkffbgkdghhnjfoomdkeifljlepah

`pyznap status --raw --values 'name,zfs-origin,conf,do-*,snapshot-info-*-timestamp,snapshot-count-*,dest-0-snapshot-count*,dest-0-host,dest-0-name' | petl 'fromjson(None, lines=True).tohtml("/tmp/pyznap.html")'`


#### Usage examples ####

Expand Down
2 changes: 1 addition & 1 deletion pyznap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
"""


__version__ = '1.6.0o27 '
__version__ = '1.6.0o28 '
14 changes: 8 additions & 6 deletions pyznap/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ def _main():
subparsers.add_parser('full', help='full cycle: snap --take / send / snap --clean')

parser_status = subparsers.add_parser('status', help='check filesystem snapshots status')
parser_status.add_argument('--raw', action="store_true",
dest='status_raw', help='quiet and raw print status')
parser_status.add_argument('--format', action="store", default='log', choices=['log', 'jsonl', 'html'],
dest='status_format', help='status output format')
parser_status.add_argument('--all', action="store_true",
dest='status_all', help='show all ZFS filesystems')
parser_status.add_argument('--print-config', action="store_true",
Expand All @@ -152,6 +152,8 @@ def _main():
dest='values', help='coma separated values to print')
parser_status.add_argument('--filter', action="append",
dest='filter_values', help='add filter for col=value')
parser_status.add_argument('--exclude', action="append",
dest='filter_exclude', help='exclude name filesystems (fnmatch)')

if len(sys.argv)==1:
parser.print_help(sys.stderr)
Expand All @@ -174,7 +176,7 @@ def _main():
loglevel = logging.WARNING
if args.verbose:
loglevel = logging.DEBUG
if args.command == 'status' and args.status_raw :
if args.command == 'status' and args.status_format != 'log':
# for raw status only error show
loglevel = logging.ERROR
if args.trace:
Expand All @@ -191,7 +193,7 @@ def _main():
if loglevel < logging.WARNING:
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(console_fmt)
console_handler.addFilter(lambda record: record.levelno < logging.WARNING)
console_handler.addFilter(lambda record: record.levelno < 30) # logging.WARNING make exception in destroy
console_handler.setLevel(loglevel)
root_logger.addHandler(console_handler)
console_err_handler = logging.StreamHandler(sys.stderr)
Expand Down Expand Up @@ -306,9 +308,9 @@ def _main():
f, v = fv.split('=')
v = {'true': True, 'false': False}.get(v.lower(), v)
filter_values[f] = v
status_config(config, raw=args.status_raw, show_all=args.status_all,
status_config(config, output=args.status_format, show_all=args.status_all,
values=tuple(args.values.split(',')) if args.values else None,
filter_values=filter_values)
filter_values=filter_values, filter_exclude=args.filter_exclude)

zfs.STATS.log()
logger.info('Finished successfully...\n')
Expand Down
9 changes: 9 additions & 0 deletions pyznap/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ def __init__(self, user, host, key=None, port=22, compress=None):
'-o', 'ControlPath={:s}'.format(self.socket), '-p', str(self.port),
'-o', 'ServerAliveInterval=30', '{:s}@{:s}'.format(self.user, self.host)]

self.logger.log(8, 'SSH: init socket={}'.format(self.socket))

# setup ControlMaster. Process will hang if we call Popen with stderr=sp.PIPE, see
# https://lists.mindrot.org/pipermail/openssh-unix-dev/2014-January/031976.html
try:
run(['exit'], timeout=10, ssh=self, stderr=sp.DEVNULL)
except (sp.CalledProcessError, sp.TimeoutExpired):
pass

self._closed = False

# check if ssh connection is up
try:
run(['exit'], timeout=5, check=True, stdout=sp.PIPE, stderr=sp.PIPE, ssh=self)
Expand All @@ -108,6 +112,7 @@ def __init__(self, user, host, key=None, port=22, compress=None):
self.pv = self.setup_pv()



def __str__(self):
return '{:s}@{:s}:{:d}'.format(self.user, self.host, self.port)

Expand Down Expand Up @@ -194,8 +199,12 @@ def setup_pv(self):
def close(self):
"""Closes the ssh connection by invoking '-O exit' (deletes socket file)"""

if self._closed:
return
self.logger.log(8, 'SSH: close socket={}'.format(self.socket))
try:
run(['-O', 'exit'], timeout=5, stderr=sp.PIPE, ssh=self)
self._closed = True
except (sp.CalledProcessError, sp.TimeoutExpired):
pass

Expand Down
Loading

0 comments on commit d382cf5

Please sign in to comment.