Created
April 25, 2014 00:15
-
-
Save Xaroth/11273909 to your computer and use it in GitHub Desktop.
libzfs-python zpool status
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ..zpool import ZPool, c_libzfs, ffi_libzfs, enums | |
zpool_status_t = enums.zpool_status | |
import sys | |
from datetime import datetime | |
import time | |
def nicenum(value): | |
pass | |
def _state_to_name(state, aux): | |
return ffi_libzfs.string(c_libzfs.zpool_state_to_name(state, aux)) | |
def print_scan_status(stats): | |
if stats is None or stats[0] == int(enums.pool_scan_func.NONE) or stats[0] == int(enums.pool_scan_func.FUNCS): | |
value = "none requested" | |
else: | |
(func, state, start_time, end_time, to_examine, examined, to_process, | |
processed, errors, pass_examined, pass_start) = stats | |
func = enums.pool_scan_func(func) | |
state = enums.dsl_scan_state(state) | |
minutes_taken = (end_time - start_time) / 60 | |
end_time = datetime.fromtimestamp(end_time) | |
ftype = "scrub" if func == enums.pool_scan_func.SCRUB else "resilver" | |
if state == enums.dsl_scan_state.FINISHED: | |
if func == enums.pool_scan_func.SCRUB: | |
value = "scrub repaired %s in %dh%dm with %d errors on %s" | |
elif func == enums.pool_scan_func.RESILVER: | |
value = "resilvered %s in %dh%dm with %d errors on %s" | |
value = value % (processed, int(minutes_taken / 60), int(minutes_taken % 60), errors, end_time) | |
elif state == enums.dsl_scan_state.CANCELED: | |
value = "%s canceled on %s" % (ftype, end_time) | |
else: | |
value = "%s in progress since %s" % (ftype, start_time) | |
examined = examined or 1 | |
fraction_done = float(examined) / float(to_examine) | |
elapsed = (time.time() - pass_start) or 1 | |
pass_examined = pass_examined or 1 | |
rate = (pass_examined / elapsed) or 1 | |
mins_left = ((to_examine - examined) / rate) / 60 | |
hours_left = int(mins_left / 60) | |
value += "\n %s scanned out of %s at %s/s" % (examined, to_examine, rate) | |
if hours_left < (30 * 24): | |
value += ", %dh%dm to go\n" % (hours_left, mins_left) | |
ftype = "repaired" if func == enums.pool_scan_func.SCRUB else "resilvered" | |
value += "\n %s %s, %.2f%% done" % (processed, ftype, fraction_done * 100) | |
print(" scan: %s" % value) | |
status_messages = { | |
zpool_status_t.MISSING_DEV_R: [ | |
"status: One or more devices could not be opened. Sufficient replicas exist for", | |
" the pool to continue functioning in a degraded state", | |
"action: Attach the missing device and online it using 'zpool online'." | |
], | |
zpool_status_t.MISSING_DEV_NR: [ | |
"status: One or more devices could not be opened. There are insufficient", | |
" replicas for the pool to continue functioning.", | |
"action: Attach the missing device and online it using 'zpool online'." | |
], | |
zpool_status_t.CORRUPT_LABEL_R: [ | |
"status: One or more devices could not be used because the label is missing or", | |
" invalid. Sufficient replicas exist for the pool to continue", | |
" functioning in a degraded state." | |
"action: Replace the device using 'zpool replace'." | |
], | |
zpool_status_t.CORRUPT_LABEL_NR: [ | |
"status: One or more devices could not be used because the label is missing or", | |
" invalid. There are insufficient replicas for the pool to continue", | |
" functioning." | |
], | |
zpool_status_t.FAILING_DEV: [ | |
"status: One or more devices has experienced an unrecoverable error. An", | |
" attempt was made to correct the error. Applications are unaffected.", | |
"action: Determine if the device needs to be replaced, and clear the errors", | |
" using 'zpool clear' or replace the device with 'zpool replace'", | |
], | |
zpool_status_t.OFFLINE_DEV: [ | |
"status: One or more devices has been taken offline by the administrator.", | |
" Sufficient replicas exist for the pool to continue functioning in a", | |
" degraded state.", | |
"action: Online the device using 'zpool online' or replace the device with", | |
" 'zpool replace'.", | |
], | |
zpool_status_t.REMOVED_DEV: [ | |
"status: One or more devices has been removed by the administrator.", | |
" Sufficient replicas exist for the pool to continue functioning in a", | |
" degraded state.", | |
"action: Online the device using 'zpool online' or replace the device with", | |
" 'zpool replace'.", | |
], | |
zpool_status_t.RESILVERING: [ | |
"status: One or more devices is currently being resilvered. The pool will", | |
" continue to function, possibly in a degraded state.", | |
"action: Wait for the resilver to complete", | |
], | |
# TODO: more status messages | |
} | |
def zpool_status(): | |
for pool in ZPool.list(): | |
config = pool.config | |
vdev_stats = config['vdev_tree']['vdev_stats'] | |
vs_state, vs_aux = vdev_stats[1:3] | |
state = _state_to_name(vs_state, vs_aux) | |
print(" pool: %s" % pool.name) | |
print(" state: %s" % state) | |
status = pool.status | |
if status in status_messages: | |
print('\n'.join(status_messages[status])) | |
if pool.status_extra: | |
print(" see: http://zfsonlinux.org/msg/%s" % pool.status_extra) | |
print_scan_status(config['vdev_tree'].get('scan_stats')) | |
print("") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment