Set min for commands with same (sort) aliases. Table improvements.

This commit is contained in:
Denis Knauf 2022-01-12 20:07:52 +01:00
parent efe4f41eda
commit 8994faad9e
8 changed files with 101 additions and 81 deletions

View file

@ -153,6 +153,48 @@ class PVE::Cli
end end
end end
def node_opt node = nil
node &&= /\A#{node}\z/
node ? Proxmox::Node.find_by_name( name) : Proxmox::Node.all
end
def target_opt target = nil, &exe
if target
target = /\A#{target}\z/
lambda {|n| exe.call n if n === target }
else
exe
end
end
def hosting_table target:, status:, sort:
connect
to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU/% Mem/MiB Mem/% Disk/MiB Disk/%], format: '<<<<<>>>>>>'
target &&= /\A#{target}\z/i
status =
case status
when /\Asta(r(t(ed?)?)?)?\z/i, /\Aon(l(i(ne?)?)?)?\z/i, /\Ar(u(n(n(i(ng?)?)?)?)?)?\z/i, '1'
%i[started online running]
when /\Asto(p(p(ed?)?)?)?\z/i, /\Aof(f(l(i(ne?)?)?)?)?\z/i, '0'
%i[stopped offline]
when nil, '', /\Aa(ll?)?\z/i then nil
else
raise DenKn::UsageError, "Unknown state #{status}"
end
push =
if target and status
lambda {|n| to.virt n if n === target and status.include?( n.state) }
elsif target
lambda {|n| to.virt n if n === target }
elsif status
lambda {|n| to.virt n if status.include? n.state }
else
to.method :virt
end
yield push
to.print order: sort.each_char.map {|c| (2*c.ord[5]-1) * (' sainhucmd'.index( c.downcase)) }
end
def help cl, *args def help cl, *args
STDERR.puts cl.help( *args) STDERR.puts cl.help( *args)
exit 1 unless interactive? exit 1 unless interactive?

View file

@ -15,26 +15,17 @@ def cli_base
each {|c| puts c } each {|c| puts c }
} }
cli.cmd( :status, "Lists Nodes/VMs/CTs with status", &lambda {|target=nil, sort: 'n', node: nil| cli.cmd( :status, "Lists Nodes/VMs/CTs with status", &lambda {|target=nil, sort:, node: nil, status: nil|
connect hosting_table target: target, status: status, sort: sort do |push|
node &&= /\A#{node}\z/ node_opt( node).
to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU/% Mem/MiB Mem/% Disk/MiB Disk/%] each( &push).lazy.
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.each &push
nodes.
flat_map {|n| [ Thread.new( n, &:lxc), Thread.new( n, &:qemu) ] }. flat_map {|n| [ Thread.new( n, &:lxc), Thread.new( n, &:qemu) ] }.
each {|n| n.value.each &push } each {|n| n.value.each &push }
to.print order: sort.each_char.map {|c| (2*c.ord[5]-1) * (' sainhucmd'.index( c.downcase)) } end
}). }).
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( :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)", default: 'n').
opt( :node, '-n', '--node=NODE', "List only hosted by this NODE") opt( :node, '-n', '--node=NODE', "List only hosted by this NODE").
opt( :status, '-S', '--status=STATUS', "Filter for status (running, stopped, ...) (default: no filter)")
def prepare_show_config cnf def prepare_show_config cnf
r = {} r = {}
@ -144,7 +135,7 @@ def cli_base
show_config th.config, old show_config th.config, old
} }
ccli.cmd :show, "Show Config of CT/VM", aliases: %w[s], &lambda {|name_or_id| ccli.cmd :show, "Show Config of CT/VM", &lambda {|name_or_id|
connect connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id) th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
show_config th.config show_config th.config

View file

@ -9,25 +9,17 @@ def cli_ct
end.sort.each {|c| puts c } end.sort.each {|c| puts c }
} }
ct_cli.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: 'n', node: nil| ct_cli.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: nil, node: nil, status: nil|
connect hosting_table target: target, status: status, sort: sort do |push|
node &&= /\A#{node}\z/ node_opt( node).
to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU/% Mem/MiB Mem/% Disk/MiB Disk/%] each( &push).lazy.
push = map {|n| Thread.new n, &:lxc }.
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 } each {|n| n.value.each &push }
to.print order: sort.each_char.map {|c| (2*c.ord[5]-1) * (' sainhucmd'.index( c.downcase)) } end
}). }).
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( :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)", default: 'n').
opt( :node, '-n', '--node=NODE', "List only hosted by this NODE") opt( :node, '-n', '--node=NODE', "List only hosted by this NODE").
opt( :status, '-S', '--status=STATUS', "Filter for status (running, stopped, ...) (default: no filter)")
ct_cli.cmd :enter, "Enter Console of CT", &lambda {|name_or_id| ct_cli.cmd :enter, "Enter Console of CT", &lambda {|name_or_id|
connect connect
@ -39,7 +31,7 @@ def cli_ct
STDERR.puts "! #{$?.exitstatus}" unless Proxmox::LXC.find!( name_or_id).exec *command STDERR.puts "! #{$?.exitstatus}" unless Proxmox::LXC.find!( name_or_id).exec *command
} }
ct_cli.cmd( :start, "Starts CT", min: 3, &lambda {|name_or_id, node: nil, fire:, timeout:, secs:| ct_cli.cmd( :start, "Starts CT", min: 4, &lambda {|name_or_id, node: nil, fire:, timeout:, secs:|
connect connect
ct = Proxmox::LXC.find! name_or_id ct = Proxmox::LXC.find! name_or_id
start ct, node: node, fire: fire, timeout: timeout, secs: secs start ct, node: node, fire: fire, timeout: timeout, secs: secs
@ -61,7 +53,7 @@ def cli_ct
opt( :timeout, "-tTIMEOUT", "--timeout=TIMEOUT", "Wait for max TIMEOUT seconds (default: endless)", default: nil). opt( :timeout, "-tTIMEOUT", "--timeout=TIMEOUT", "Wait for max TIMEOUT seconds (default: endless)", default: nil).
opt( :secs, "-sSECONDS", "--seconds=SECONDS", "Check every SECONDS for state (default: 0.2)", default: 0.2) opt( :secs, "-sSECONDS", "--seconds=SECONDS", "Check every SECONDS for state (default: 0.2)", default: 0.2)
ct_cli.cmd( :create, "Creates a new container", &lambda {|template, *options| #, fire:, timeout:, secs:, start:| ct_cli.cmd( :create, "Creates a new container", min: 2, &lambda {|template, *options| #, fire:, timeout:, secs:, start:|
if %w[-h --help].include? template if %w[-h --help].include? template
STDERR.puts "Usage: ct create TEMPLATE -h # Shows template-related options" STDERR.puts "Usage: ct create TEMPLATE -h # Shows template-related options"
STDERR.puts " ct create TEMPLATE [OPTIONS] # Creates a container" STDERR.puts " ct create TEMPLATE [OPTIONS] # Creates a container"
@ -107,7 +99,7 @@ EOU
create Proxmox::LXC, template, **ctopts create Proxmox::LXC, template, **ctopts
}) })
ct_cli.cmd( :config, 'Shows current config', aliases: %w[cnf], &lambda {|name_or_id| ct_cli.cmd( :config, 'Shows current config', aliases: %w[cnf], min: 2, &lambda {|name_or_id|
connect connect
ct = Proxmox::LXC.find! name_or_id ct = Proxmox::LXC.find! name_or_id
STDOUT.puts JSON.dump( ct.config) STDOUT.puts JSON.dump( ct.config)

View file

@ -9,7 +9,7 @@ def opts_ha cl
end end
def cli_ha def cli_ha
cli.sub :ha, "Inspect High-Availability" do |hacli| cli.sub :ha, "Inspect High-Availability", min: 2 do |hacli|
hacli.cmd( :create, "Create HA for CT/VM", &lambda {|name_or_id, group:, comment: nil, max_relocate:, max_restart:, state:| hacli.cmd( :create, "Create HA for CT/VM", &lambda {|name_or_id, group:, comment: nil, max_relocate:, max_restart:, state:|
connect connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id) th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
@ -19,7 +19,7 @@ def cli_ha
ha.create group: group, comment: comment, max_relocate: max_relocate, max_restart: max_restart ha.create group: group, comment: comment, max_relocate: max_relocate, max_restart: max_restart
}).tap {|cl| opts_ha cl } }).tap {|cl| opts_ha cl }
hacli.cmd :remove, "Remove CT/VM from HA", &lambda {|name_or_id| hacli.cmd :remove, "Remove CT/VM from HA", min: 5, &lambda {|name_or_id|
connect connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id) th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
raise UsageError, "Container or VirtualMachine not found: #{name_or_id}" unless th raise UsageError, "Container or VirtualMachine not found: #{name_or_id}" unless th
@ -63,7 +63,7 @@ def cli_ha
ha.stopped! ha.stopped!
} }
hacli.cmd :reset, "If state of CT/VM is failed, Proxmox will not start/stop it anyway. You have to reset state (state=disabled), first", &lambda {|name_or_id| hacli.cmd :reset, "If state of CT/VM is failed, Proxmox will not start/stop it anyway. You have to reset state (state=disabled), first", min: 3, aliases: [:rst], &lambda {|name_or_id|
connect connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id) th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
raise UsageError, "Container or VirtualMachine not found: #{name_or_id}" unless th raise UsageError, "Container or VirtualMachine not found: #{name_or_id}" unless th

View file

@ -30,7 +30,7 @@ def cli_node
end end
nod_cli.sub :task, "Inspect tasks" do |tcli| nod_cli.sub :task, "Inspect tasks" do |tcli|
tcli.cmd :list, "List done tasks", aliases: [nil, 'ls'], &lambda {|node| tcli.cmd :list, "List done tasks", aliases: [:ls], &lambda {|node|
connect connect
Proxmox::Node.find_by_name!( node). Proxmox::Node.find_by_name!( node).
tasks. tasks.

View file

@ -10,25 +10,17 @@ def cli_qm
end.sort.each {|c| puts c } end.sort.each {|c| puts c }
} }
qm.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: 'n', node: nil| qm.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: nil, node: nil, status: nil|
connect hosting_table target: target, state: state, sort: sort do |push|
node &&= /\A#{node}\z/ node_opt( node).
to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU/% Mem/MiB Mem/% Disk/MiB Disk/%] each( &push).lazy.
push = flat_map {|n| [ Thread.new( n, &:lxc), Thread.new( n, &:qemu) ] }.
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 } each {|n| n.value.each &push }
to.print order: sort.each_char.map {|c| (2*c.ord[5]-1) * (' sainhucmd'.index( c.downcase)) } end
}). }).
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( :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)", default: 'n').
opt( :node, '-n', '--node=NODE', "List only hosted by this NODE") opt( :node, '-n', '--node=NODE', "List only hosted by this NODE").
opt( :status, '-S', '--status=STATUS', "Filter for status (running, stopped, ...) (default: no filter)")
qm.cmd :exec, "Executes Command in VM via qemu-guest-agent", min: 4, &lambda {|name_or_id, *command| qm.cmd :exec, "Executes Command in VM via qemu-guest-agent", min: 4, &lambda {|name_or_id, *command|
connect connect

View file

@ -58,14 +58,14 @@ def cli_storage
opt( :system, '-s', '--system', 'Only system templates', default: nil). opt( :system, '-s', '--system', 'Only system templates', default: nil).
opt( :applications, '-a', '--applications', 'Only applications (non system) templates', default: nil) opt( :applications, '-a', '--applications', 'Only applications (non system) templates', default: nil)
cli_apl.cmd( :system, "Table of provided systems", aliases: [nil], &lambda {|node:, regexp:| cli_apl.cmd( :system, "Table of provided systems", &lambda {|node:, regexp:|
connect connect
appliances node, regexp, true, nil appliances node, regexp, true, nil
}). }).
opt( :node, '-n=NODE', '--node', 'Ask this node for appliances (any node should list the same)', default: nil). opt( :node, '-n=NODE', '--node', 'Ask this node for appliances (any node should list the same)', default: nil).
opt( :regexp, '-r=REGEXP', '--regexp', 'Filter by template', default: nil) opt( :regexp, '-r=REGEXP', '--regexp', 'Filter by template', default: nil)
cli_apl.cmd( :applications, "Table of provided applications", aliases: [nil], &lambda {|node:, regexp:| cli_apl.cmd( :applications, "Table of provided applications", &lambda {|node:, regexp:|
connect connect
appliances node, regexp, nil, true appliances node, regexp, nil, true
}). }).

View file

@ -94,7 +94,6 @@ class ColoredString
end end
class TablizedOutput class TablizedOutput
def initialize header, stdout: nil, format: nil def initialize header, stdout: nil, format: nil
@header = header.map &:to_s @header = header.map &:to_s
@ -125,10 +124,14 @@ class TablizedOutput
def inspect() "#<TO:Percentage #{@v}%>" end def inspect() "#<TO:Percentage #{@v}%>" end
def to_s def to_s
y = (v*w).round vw = v*w
x = (100*v).round percent = (100*v).round
r = "%*s" % [w, 0==x ? '·' : x] vwi = vw.to_i
"\e[1;4;#{0.75>v ? 32 : 31}m#{r[0...y]}\e[0m#{r[y..-1]}" rounded = (vw+0.5).to_i
s = "%*s" % [w, 0==percent ? '·' : percent]
pre = "\e[1;4;#{0.75>v ? 32 : 31}m"
mid = (vw % 1) > 0.5 ? "\e[2m" : "\e[0m"
"#{pre}#{s[0...vwi]}#{mid}#{s[vwi]}\e[0m#{s[(vwi+1)..-1]}"
end end
end end
@ -161,8 +164,8 @@ class TablizedOutput
@stdout.puts \ @stdout.puts \
@header.each_with_index.map {|s, i| @header.each_with_index.map {|s, i|
"#{' ' * (@maxs[i] - s.length)}#{s}" "#{' ' * (@maxs[i] - s.length)}#{s}"
}.join( ' ') }.join( ' | ')
ls.each_with_index do |l| ls.each_with_index do |l, i|
@stdout.puts \ @stdout.puts \
l.each_with_index.map {|s, i| l.each_with_index.map {|s, i|
pad = ' ' * (@maxs[i] - s.length) pad = ' ' * (@maxs[i] - s.length)
@ -172,7 +175,7 @@ class TablizedOutput
else else
"#{pad}#{s}" "#{pad}#{s}"
end end
}.join( ' ') }.join( "\e[3#{i.even? ? 6 : 3}m | \e[0m")
end end
end end