lib/zfs_mgmt.rb in zfs_mgmt-0.3.5 vs lib/zfs_mgmt.rb in zfs_mgmt-0.3.6

- old
+ new

@@ -1,8 +1,9 @@ # coding: utf-8 require "zfs_mgmt/version" require "zfs_mgmt/restic" +require "zfs_mgmt/zfs_mgr" require 'pp' require 'date' require 'logger' require 'text-table' require 'open3' @@ -62,11 +63,49 @@ return md[1].to_i * $time_specs[md[2].downcase] else return md[1].to_i end end - + + def self.zfs_holds(snapshot) + com = ['zfs', 'holds', '-H', snapshot] + $logger.debug("#{com.join(' ')}") + out = %x(#{com.join(' ')}) + unless $?.success? + errstr = "unable to retrieves holds for snapshot: #{snapshot}" + $logger.error(errstr) + raise errstr + end + a = [] + out.split("\n").each do |ln| + a.push(ln.split("\t")[1]) + end + a + end + + def self.zfs_hold(hold,snapshot) + com = ['zfs', 'hold', hold, snapshot] + $logger.debug("#{com.join(' ')}") + system(com.join(' ')) + unless $?.success? + errstr = "unable to set hold: #{hold} for snapshot: #{snapshot}" + $logger.error(errstr) + raise errstr + end + end + + def self.zfs_release(hold,snapshot) + com = ['zfs', 'release', hold, snapshot] + $logger.debug("#{com.join(' ')}") + system(com.join(' ')) + unless $?.success? + errstr = "unable to release hold: #{hold} for snapshot: #{snapshot}" + $logger.error(errstr) + raise errstr + end + end + def self.zfsget(properties: ['name'],types: ['filesystem','volume'],zfs: '') results={} com = ['zfs', 'get', '-Hp', properties.join(','), '-t', types.join(','), zfs] so,se,status = Open3.capture3(com.join(' ')) if status.signaled? @@ -190,28 +229,29 @@ true end } return saved,saved_snaps,deleteme end - def self.zfs_managed_list(filter: '.+') + def self.zfs_managed_list(filter: '.+', properties: custom_properties(), property_match: { 'zfsmgmt:manage' => 'true' } ) zfss = [] # array of arrays - zfsget(properties: custom_properties()).each do |zfs,props| + zfsget(properties: properties).each do |zfs,props| unless /#{filter}/ =~ zfs next end - unless props.has_key?('zfsmgmt:manage') and props['zfsmgmt:manage'] == 'true' - next + managed = true + property_match.each do |k,v| + unless props.has_key?(k) and props[k] == v + managed = false + break + end end + next unless managed snaps = self.zfsget(properties: ['name','creation','userrefs','used','written','referenced'],types: ['snapshot'], zfs: zfs) if snaps.length == 0 $logger.warn("unable to process this zfs, no snapshots at all: #{zfs}") next end - unless props.has_key?('zfsmgmt:policy') and policy = policy_parser(props['zfsmgmt:policy']) - $logger.error("zfs_mgmt is configured to manage #{zfs}, but there is no valid policy configuration, skipping") - next # zfs - end zfss.push([zfs,props,snaps]) end return zfss end def self.snapshot_policy(verbopt: false, debugopt: false, filter: '.+') @@ -220,10 +260,14 @@ else $logger.level = Logger::INFO end zfs_managed_list(filter: filter).each do |zdata| (zfs,props,snaps) = zdata + unless props.has_key?('zfsmgmt:policy') and policy_parser(props['zfsmgmt:policy']) + $logger.error("zfs_mgmt is configured to manage #{zfs}, but there is no valid policy configuration, skipping") + next # zfs + end # call the function that decides who to save and who to delete (saved,saved_snaps,deleteme) = snapshot_destroy_policy(zfs,props,snaps) if saved_snaps.length == 0 $logger.info("no snapshots marked as saved by policy for #{zfs}") @@ -245,10 +289,15 @@ else $logger.level = Logger::INFO end zfs_managed_list(filter: filter).each do |zdata| (zfs,props,snaps) = zdata + unless props.has_key?('zfsmgmt:policy') and policy_parser(props['zfsmgmt:policy']) + $logger.error("zfs_mgmt is configured to manage #{zfs}, but there is no valid policy configuration, skipping") + next # zfs + end + # call the function that decides who to save and who to delete (saved,saved_snaps,deleteme) = snapshot_destroy_policy(zfs,props,snaps) $logger.info("deleting #{deleteme.length} snapshots for #{zfs}") deleteme.reverse! # oldest first for removal @@ -328,31 +377,8 @@ end com.push("#{zfs}@#{[prefix,dt.strftime(ts)].join('-')}") $logger.info(com) system(com.join(' ')) end - end - end -end -class ZfsMgmtList < Thor - class_option :filter, :type => :string, :default => '.+', - :desc => 'only act on zfs matching this regexp' - desc "stale", "list all zfs with stale snapshots" - method_option :age, :desc => "timeframe outside of which the zfs will be considered stale", :default => '1d' - def stale() - cutoff = Time.at(Time.now.to_i - ZfsMgmt.timespec_to_seconds(options[:age])) - table = Text::Table.new - table.head = ['zfs','snapshot','age'] - table.rows = [] - ZfsMgmt.zfs_managed_list(filter: options[:filter]).each do |blob| - zfs,props,snaps = blob - last = snaps.keys.sort { |a,b| snaps[a]['creation'] <=> snaps[b]['creation'] }.last - snap_time = Time.at(snaps[last]['creation']) - if snap_time < cutoff - table.rows << [zfs,last.split('@')[1],snap_time] - end - end - if table.rows.count > 0 - print table.to_s end end end