Skip to content

Instantly share code, notes, and snippets.

@csabahenk
Last active December 2, 2016 14:48

Revisions

  1. csabahenk revised this gist Dec 2, 2016. 1 changed file with 1 addition and 4 deletions.
    5 changes: 1 addition & 4 deletions glusterconf.rb
    Original file line number Diff line number Diff line change
    @@ -155,10 +155,7 @@ def report summary, fields=nil
    op.on("--show-columns[=bool]", TrueClass, "show colums used for CSV output") { |v| showcols = v }
    op.parse!

    if showcols
    puts (cols || GlusterConf::DEFAULTFIELDS).join(" ")
    exit
    end
    showcols and puts (cols || GlusterConf::DEFAULTFIELDS).join(",")

    $*.each { |f|
    GlusterConf.module_eval {
  2. csabahenk revised this gist Dec 1, 2016. 1 changed file with 64 additions and 1 deletion.
    65 changes: 64 additions & 1 deletion glusterconf.rb
    Original file line number Diff line number Diff line change
    @@ -98,15 +98,78 @@ def parse src
    topvol
    end

    def summarize vol, perf=[], cluster={"distribute"=>0, "replicate"=>0}
    xclass, xtype = vol["type"].split("/")
    case xclass
    when "performance"
    perf << xtype
    when "cluster"
    cluster[xtype] = vol["subvolumes"].size
    end
    (vol["subvolumes"]||[]).each { |sv| summarize sv, perf, cluster }
    {performance: perf, cluster: cluster}
    end

    DEFAULTFIELDS = %w[distribute replicate write-behind readdir-ahead quick-read md-cache perf-other]

    def report summary, fields=nil
    fields ||= DEFAULTFIELDS
    perf_hot = []
    perf_other = ""
    rep = fields.map { |n|
    case n
    when "distribute", "replicate"
    summary[:cluster][n]
    when "perf-other"
    perf_other
    else
    perf_hot << n
    summary[:performance].include?(n) ? '✓' : '✖'
    end
    }
    perf_other << (summary[:performance] - perf_hot).reverse.join(" ")
    rep
    end

    end

    if __FILE__ == $0
    require 'yaml'
    require 'csv'
    require 'optparse'

    fmt = 'yaml'
    cols = nil
    showcols = false

    op = OptionParser.new
    op.banner << " [<volfile>|<logfile>]..."
    op.on("-f", "--format FMT", "output format (csv or yaml)") { |v|
    %w[csv yaml].include? v or raise "Unknown format #{v}"
    fmt = v
    }
    op.on("--columns COLS", Array,
    "comma-separated column names for CSV (one of #{GlusterConf::DEFAULTFIELDS.join(",")})") { |v|
    cols = v
    }
    op.on("--show-columns[=bool]", TrueClass, "show colums used for CSV output") { |v| showcols = v }
    op.parse!

    if showcols
    puts (cols || GlusterConf::DEFAULTFIELDS).join(" ")
    exit
    end

    $*.each { |f|
    GlusterConf.module_eval {
    preparse(f == "-" ? STDIN : IO.readlines(f)).each { |v|
    print parse(v).to_yaml
    vol = parse v
    print case fmt
    when "yaml"
    vol.to_yaml
    when "csv"
    report(summarize(vol), cols).to_csv
    end
    }
    }
    }
  3. csabahenk revised this gist Dec 1, 2016. 1 changed file with 43 additions and 2 deletions.
    45 changes: 43 additions & 2 deletions glusterconf.rb
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,44 @@ def assert x, *bool
    bool.each { |b| raise GlusterConfError, "#{$.}: #{x}" unless bool }
    end

    LOGSEP = /\A\+---/
    IDP = proc {|x| x}

    # extract conf from logs
    def preparse src
    vols = []
    in_vol = nil
    is_log = nil
    preprocess = nil
    src.each { |l|
    (preprocess || IDP)[l] =~ /\A\s*\Z/ and next
    if in_vol
    if is_log and l =~ LOGSEP
    in_vol = false
    else
    vols.last << preprocess[l]
    end
    else
    if l =~ /\A\s*(volume|type|option|subvolumes|end-volume)(\s|\Z)/
    in_vol == false and raise "mixed source"
    in_vol = true
    preprocess = IDP
    is_log = false
    vols << [l]
    else
    is_log = true
    preprocess ||= proc { |x| x.sub /\A\s*\d+: /, "" }
    if l =~ LOGSEP
    in_vol = true
    vols << []
    end
    end
    end
    }

    vols
    end

    def parse src
    volh = {}
    vol = {}
    @@ -66,7 +104,10 @@ def parse src
    require 'yaml'

    $*.each { |f|
    print GlusterConf.parse(
    f == "-" ? STDIN : IO.readlines(f)).to_yaml
    GlusterConf.module_eval {
    preparse(f == "-" ? STDIN : IO.readlines(f)).each { |v|
    print parse(v).to_yaml
    }
    }
    }
    end
  4. csabahenk revised this gist Dec 1, 2016. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion glusterconf.rb
    Original file line number Diff line number Diff line change
    @@ -65,5 +65,8 @@ def parse src
    if __FILE__ == $0
    require 'yaml'

    puts GlusterConf.parse($<).to_yaml
    $*.each { |f|
    print GlusterConf.parse(
    f == "-" ? STDIN : IO.readlines(f)).to_yaml
    }
    end
  5. csabahenk revised this gist Dec 1, 2016. 2 changed files with 69 additions and 57 deletions.
    57 changes: 0 additions & 57 deletions gluster2yaml.rb
    Original file line number Diff line number Diff line change
    @@ -1,57 +0,0 @@
    #!/usr/bin/env ruby

    require 'yaml'

    class GlusterConfError < Exception
    end

    def assert x, *bool
    bool.each { |b| raise GlusterConfError, "#{$.}: #{x}" unless bool }
    end

    volh = {}
    vol = {}

    $<.each { |l|
    ls = l.split
    case ls[0]
    when "volume"
    assert l, ls.size == 2, vol.empty?
    vol["name"] = ls[1]
    when "type"
    assert l, ls.size == 2, vol["name"], !vol["type"]
    vol["type"] = ls[1]
    when "option"
    assert l, ls.size == 3, vol["name"]
    (vol["option"] ||= {})[ls[1]] = case ls[2]
    when /\A\d+\Z/
    Integer ls[2]
    when /\Aon|yes|true|enable\Z/i
    true
    when /\Aoff|no|false|disable\Z/i
    false
    else
    ls[2]
    end
    when "subvolumes"
    assert l, ls.size > 1, vol["name"], !vol["subvolumes"]
    vol["subvolumes"] = ls[1..-1]
    when "end-volume"
    assert l, ls.size == 1, vol["name"], vol["type"]
    volh[vol["name"]] = vol
    vol = {}
    when nil
    else
    assert l, false
    end
    }

    subvolumes = []
    volh.each_value { |vol| subvolumes.concat(vol["subvolumes"] || []) }
    topvols = volh.keys - subvolumes
    assert "ambiguous toplevel volume: #{topvols.join(", ")}", topvols.size == 1
    topvol = volh[topvols[0]]

    volh.each_value { |vol| (vol["subvolumes"] || []).map! { |w| volh[w] } }

    puts topvol.to_yaml
    69 changes: 69 additions & 0 deletions glusterconf.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    #!/usr/bin/env ruby

    module GlusterConf
    extend self

    class GlusterConfError < Exception
    end

    def assert x, *bool
    bool.each { |b| raise GlusterConfError, "#{$.}: #{x}" unless bool }
    end

    def parse src
    volh = {}
    vol = {}

    src.each { |l|
    ls = l.split
    case ls[0]
    when "volume"
    assert l, ls.size == 2, vol.empty?
    vol["name"] = ls[1]
    when "type"
    assert l, ls.size == 2, vol["name"], !vol["type"]
    vol["type"] = ls[1]
    when "option"
    assert l, ls.size == 3, vol["name"]
    (vol["option"] ||= {})[ls[1]] = case ls[2]
    when /\A\d+\Z/
    Integer ls[2]
    when /\Aon|yes|true|enable\Z/i
    true
    when /\Aoff|no|false|disable\Z/i
    false
    else
    ls[2]
    end
    when "subvolumes"
    assert l, ls.size > 1, vol["name"], !vol["subvolumes"]
    vol["subvolumes"] = ls[1..-1]
    when "end-volume"
    assert l, ls.size == 1, vol["name"], vol["type"]
    volh[vol["name"]] = vol
    vol = {}
    when nil
    else
    assert l, false
    end
    }

    # XXX we could have more proper check to see if graph is a tree
    subvolumes = []
    volh.each_value { |vol| subvolumes.concat(vol["subvolumes"] || []) }
    topvols = volh.keys - subvolumes
    assert "ambiguous toplevel volume: #{topvols.join(", ")}", topvols.size == 1
    topvol = volh[topvols[0]]

    volh.each_value { |vol| (vol["subvolumes"] || []).map! { |w| volh.fetch w } }

    topvol
    end

    end

    if __FILE__ == $0
    require 'yaml'

    puts GlusterConf.parse($<).to_yaml
    end
  6. csabahenk created this gist Dec 1, 2016.
    57 changes: 57 additions & 0 deletions gluster2yaml.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    #!/usr/bin/env ruby

    require 'yaml'

    class GlusterConfError < Exception
    end

    def assert x, *bool
    bool.each { |b| raise GlusterConfError, "#{$.}: #{x}" unless bool }
    end

    volh = {}
    vol = {}

    $<.each { |l|
    ls = l.split
    case ls[0]
    when "volume"
    assert l, ls.size == 2, vol.empty?
    vol["name"] = ls[1]
    when "type"
    assert l, ls.size == 2, vol["name"], !vol["type"]
    vol["type"] = ls[1]
    when "option"
    assert l, ls.size == 3, vol["name"]
    (vol["option"] ||= {})[ls[1]] = case ls[2]
    when /\A\d+\Z/
    Integer ls[2]
    when /\Aon|yes|true|enable\Z/i
    true
    when /\Aoff|no|false|disable\Z/i
    false
    else
    ls[2]
    end
    when "subvolumes"
    assert l, ls.size > 1, vol["name"], !vol["subvolumes"]
    vol["subvolumes"] = ls[1..-1]
    when "end-volume"
    assert l, ls.size == 1, vol["name"], vol["type"]
    volh[vol["name"]] = vol
    vol = {}
    when nil
    else
    assert l, false
    end
    }

    subvolumes = []
    volh.each_value { |vol| subvolumes.concat(vol["subvolumes"] || []) }
    topvols = volh.keys - subvolumes
    assert "ambiguous toplevel volume: #{topvols.join(", ")}", topvols.size == 1
    topvol = volh[topvols[0]]

    volh.each_value { |vol| (vol["subvolumes"] || []).map! { |w| volh[w] } }

    puts topvol.to_yaml