diff --git a/lib/pve/cli/base.rb b/lib/pve/cli/base.rb index 86f81f6..8000d5d 100644 --- a/lib/pve/cli/base.rb +++ b/lib/pve/cli/base.rb @@ -27,6 +27,7 @@ def cli_base lambda {|n| to.virt n } end nodes = node ? Proxmox::Node.find_by_name( name) : Proxmox::Node.all + nodes.each &push nodes. flat_map {|n| [ Thread.new( n, &:lxc), Thread.new( n, &:qemu) ] }. each {|n| n.value.each &push } diff --git a/lib/pve/cli/ct.rb b/lib/pve/cli/ct.rb index 31bc3d8..a50387d 100644 --- a/lib/pve/cli/ct.rb +++ b/lib/pve/cli/ct.rb @@ -9,16 +9,25 @@ def cli_ct end.sort.each {|c| puts c } } - ct_cli.cmd :status, "List CTs with status", aliases: [nil], &lambda {|node=nil| + ct_cli.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: 'n', node: nil| connect - to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU Mem/MiB Disk/MiB] - nodes = Proxmox::Node.all - nodes = nodes.select {|n| node == n.name } if node - nodes.each do |n| - n.lxc.each &to.method( :virt) - end - to.print order: [3] - } + node &&= /\A#{node}\z/ + to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU/% Mem/MiB Mem/% Disk/MiB Disk/%] + push = + if target + target = /\A#{target}\z/ + lambda {|n| to.virt n if n === target } + else + lambda {|n| to.virt n } + end + nodes = node ? Proxmox::Node.find_by_name( name) : Proxmox::Node.all + nodes. + map {|n| Thread.new( n, &:lxc) }. + each {|n| n.value.each &push } + to.print order: sort.each_char.map {|c| (2*c.ord[5]-1) * (' sainhucmd'.index( c.downcase)) } + }). + opt( :sort, '-s', '--sort=COLUMNS', "Sort by COLUMNs eg hn for host and name ([s]tatus, h[a], [i]d, [n]ame (default), [h]ost, [u]ptime, [c]pu, [m]em, [d]isk)"). + opt( :node, '-n', '--node=NODE', "List only hosted by this NODE") ct_cli.cmd :enter, "Enter Console of CT", &lambda {|name_or_id| connect diff --git a/lib/pve/cli/qm.rb b/lib/pve/cli/qm.rb index 4f36d7c..40944fe 100644 --- a/lib/pve/cli/qm.rb +++ b/lib/pve/cli/qm.rb @@ -10,16 +10,25 @@ def cli_qm end.sort.each {|c| puts c } } - qm.cmd :status, "List VMs with status", aliases: [nil], &lambda {|node=nil| + qm.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: 'n', node: nil| connect - to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU Mem/MiB Disk/MiB] - nodes = Proxmox::Node.all - nodes = nodes.select {|n| node == n.name } if node - nodes.each do |n| - n.qemu.each &to.method( :virt) - end - to.print order: [3] - } + node &&= /\A#{node}\z/ + to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU/% Mem/MiB Mem/% Disk/MiB Disk/%] + push = + if target + target = /\A#{target}\z/ + lambda {|n| to.virt n if n === target } + else + lambda {|n| to.virt n } + end + nodes = node ? Proxmox::Node.find_by_name( name) : Proxmox::Node.all + nodes. + map {|n| Thread.new( n, &:qemu) }. + each {|n| n.value.each &push } + to.print order: sort.each_char.map {|c| (2*c.ord[5]-1) * (' sainhucmd'.index( c.downcase)) } + }). + opt( :sort, '-s', '--sort=COLUMNS', "Sort by COLUMNs eg hn for host and name ([s]tatus, h[a], [i]d, [n]ame (default), [h]ost, [u]ptime, [c]pu, [m]em, [d]isk)"). + opt( :node, '-n', '--node=NODE', "List only hosted by this NODE") qm.cmd :exec, "Executes Command in VM via qemu-guest-agent", min: 4, &lambda {|name_or_id, *command| connect diff --git a/lib/pve/helper.rb b/lib/pve/helper.rb index 365d2c0..2aaa9a5 100644 --- a/lib/pve/helper.rb +++ b/lib/pve/helper.rb @@ -13,17 +13,24 @@ end class Measured + class V + attr_reader :value, :length + + def initialize( value, length = nil) @value, @length = value, length || value.length end + def inspect() "#" end + alias :to_s :value + alias :to_str :value + end + class < v + return units '%d ' % v , :B if 512 > v %w[KiB MiBy GiByt TiByte ExiByte PetiByte].each_with_index do |m| v /= 1024 - #return "%.1f %s" % [v, m] if 10 > v - #return "%d %s" % [v, m] if 512 > v - return "%.1f %s" % [v, m] if 512 > v + return units '%.1f ' % v, m if 512 > v end - "%d PetiByte" % v + units '%d ' % v, :PetiByte end def bytes2 v @@ -40,21 +47,28 @@ class Measured end alias bytes bytes2 + def units val, unit + v = "#{val}\e[1;30m#{unit}\e[0m" + V.new v, v.length - 11 + end + def seconds i i = i.to_i - return '·' if 0 == i - return "%d s" % i if 90 > i + return V.new "\e[1;30m·\e[0m", 1 if 0 == i + return units '%d ' % i, :s if 90 > i i /= 60 - return "%d mi" % i if 90 > i + return units '%d ' % i, :mi if 90 > i i /= 60 - return "%d hou" % i if 36 > i + return units '%d ' % i, :hou if 36 > i i /= 24 - return "%d days" % i if 14 > i + return units '%d ' % i, :days if 14 > i j = i / 7 - return "%d weeks" % j if 25 > j - i /= 365 - return "%.1f years" if 550 > i - "%dy" % i + return units '%d ' % j, :weeks if 8 > j + j = i / 30 + return units '%d ' % j, :months if 11 > j + i /= 365.0 + return units '%.2f ' % i, :years if 550 > i + units '%d ' % i, :years end end end @@ -72,10 +86,8 @@ class ColoredString def length() @string.length end alias size length - #def to_str() self end def to_s() "\e[#{@color_codes}m#{@string}\e[0m" end alias to_str to_s - #alias inspect to_str include Comparable def <=>(o) @string <=> o.string end @@ -101,7 +113,7 @@ class TablizedOutput class V < B attr_reader :v, :s def initialize( v, s=nil) @v, @s = v, s || "#{v}" end - def to_s() @s end + def to_s() @s.to_s end def length() @s.length end def inspect() "#" end end @@ -113,11 +125,9 @@ class TablizedOutput def inspect() "#" end def to_s - #y = w - (v*w).round y = (v*w).round x = (100*v).round r = "%*s" % [w, 0==x ? '·' : x] - #"\e[0m#{r[0...y]}\e[1;4;#{0.75>v ? 32 : 31}m#{r[y..-1]}\e[0m" "\e[1;4;#{0.75>v ? 32 : 31}m#{r[0...y]}\e[0m#{r[y..-1]}" end end @@ -139,7 +149,6 @@ class TablizedOutput end def print order: nil - format = "#{@format.map {|f| "\e[%%sm%%#{case f when '<' then '-' else ' ' end}%ds\e[0m"}.join( ' ') % @maxs}\n" ls = @lines if order eval <<-EOC, binding, __FILE__, 1+__LINE__ @@ -149,9 +158,22 @@ class TablizedOutput } EOC end - #ls = ls.sort_by {|e| p e; order.map &e.method(:[]) } if order - @stdout.printf format, *@header.flat_map {|s|['',s]} - ls.each {|l| @stdout.printf format, *l.flat_map {|s| s.is_a?(ColoredString) ? [s.color_codes, s.string] : ["", s.to_s] } } + @stdout.puts \ + @header.each_with_index.map {|s, i| + "#{' ' * (@maxs[i] - s.length)}#{s}" + }.join( ' ') + ls.each_with_index do |l| + @stdout.puts \ + l.each_with_index.map {|s, i| + pad = ' ' * (@maxs[i] - s.length) + case @format[i] + when '<' + "#{s}#{pad}" + else + "#{pad}#{s}" + end + }.join( ' ') + end end def virt v