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
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
STDERR.puts cl.help( *args)
exit 1 unless interactive?

View file

@ -15,26 +15,17 @@ def cli_base
each {|c| puts c }
}
cli.cmd( :status, "Lists Nodes/VMs/CTs with status", &lambda {|target=nil, sort: 'n', node: nil|
connect
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.each &push
nodes.
flat_map {|n| [ Thread.new( n, &:lxc), 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)) }
cli.cmd( :status, "Lists Nodes/VMs/CTs with status", &lambda {|target=nil, sort:, node: nil, status: nil|
hosting_table target: target, status: status, sort: sort do |push|
node_opt( node).
each( &push).lazy.
flat_map {|n| [ Thread.new( n, &:lxc), Thread.new( n, &:qemu) ] }.
each {|n| n.value.each &push }
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( :node, '-n', '--node=NODE', "List only hosted by this NODE")
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( :status, '-S', '--status=STATUS', "Filter for status (running, stopped, ...) (default: no filter)")
def prepare_show_config cnf
r = {}
@ -144,7 +135,7 @@ def cli_base
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
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
show_config th.config

View file

@ -9,25 +9,17 @@ def cli_ct
end.sort.each {|c| puts c }
}
ct_cli.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: 'n', node: nil|
connect
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)) }
ct_cli.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: nil, node: nil, status: nil|
hosting_table target: target, status: status, sort: sort do |push|
node_opt( node).
each( &push).lazy.
map {|n| Thread.new n, &:lxc }.
each {|n| n.value.each &push }
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( :node, '-n', '--node=NODE', "List only hosted by this NODE")
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( :status, '-S', '--status=STATUS', "Filter for status (running, stopped, ...) (default: no filter)")
ct_cli.cmd :enter, "Enter Console of CT", &lambda {|name_or_id|
connect
@ -39,7 +31,7 @@ def cli_ct
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
ct = Proxmox::LXC.find! name_or_id
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( :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
STDERR.puts "Usage: ct create TEMPLATE -h # Shows template-related options"
STDERR.puts " ct create TEMPLATE [OPTIONS] # Creates a container"
@ -107,7 +99,7 @@ EOU
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
ct = Proxmox::LXC.find! name_or_id
STDOUT.puts JSON.dump( ct.config)

View file

@ -9,7 +9,7 @@ def opts_ha cl
end
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:|
connect
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
}).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
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
@ -63,7 +63,7 @@ def cli_ha
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
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

View file

@ -30,7 +30,7 @@ def cli_node
end
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
Proxmox::Node.find_by_name!( node).
tasks.

View file

@ -10,25 +10,17 @@ def cli_qm
end.sort.each {|c| puts c }
}
qm.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: 'n', node: nil|
connect
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)) }
qm.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: nil, node: nil, status: nil|
hosting_table target: target, state: state, sort: sort do |push|
node_opt( node).
each( &push).lazy.
flat_map {|n| [ Thread.new( n, &:lxc), Thread.new( n, &:qemu) ] }.
each {|n| n.value.each &push }
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( :node, '-n', '--node=NODE', "List only hosted by this NODE")
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( :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|
connect

View file

@ -53,24 +53,24 @@ def cli_storage
connect
appliances node, regexp, system, applications
}).
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( :system, '-s', '--system', 'Only system templates', default: nil).
opt( :applications, '-a', '--applications', 'Only applications (non system) templates', 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( :system, '-s', '--system', 'Only 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
appliances node, regexp, true, 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( :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)
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
appliances node, regexp, nil, true
}).
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( :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)
cli_apl.cmd( :list, "List provided appliances", aliases: ['ls'], &lambda {|node=nil, regexp:|
connect

View file

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