pve/lib/pve/cli/base.rb

188 lines
6.0 KiB
Ruby

require 'pmap'
class PVE::Cli
def cli_base
cli.cmd :list, "List CT/VM-IDs", aliases: ['ls'], &lambda {|target=nil|
connect
nodes = Proxmox::Node.all
nodes.
flat_map {|n| [ n.method(:lxc), n.method(:qemu) ] }.
flat_pmap {|m| m.call.map {|c| c.vmid.to_i } }.
sort.
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 = Proxmox::Node.all
nodes.
select {|n| not node or n === node }.
flat_map {|n| [ n.method(:lxc), n.method(:qemu) ] }.
each {|m| m.call.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")
def prepare_show_config cnf
r = {}
cnf.each do |k,v|
case k
when :network
v.each do |net|
s =
net.
reject {|k, v| :card == k }.
sort_by {|k, v| :name == k ? :AAAAAAAAA : k }.
map {|k, v| case v when true then [k,1] when false then [k,0] else [k,v] end }.
map {|k, v| "#{k}=#{v}" }
r[net[:card].to_sym] = s.join(",")
end
when :sshkeys
r[k] = CGI.unescape(v).gsub( /^/, " "*14).gsub /\A {14}|\n\z/, ''
else
case v
when true then v = 1
when false then v = 0
end
r[k] = v.to_s.gsub( /$^/, " "*14).gsub /\n\z/, ''
end
end
r
end
def show_config cnf, old = nil
cnf = prepare_show_config cnf
if old
old = prepare_show_config old
(cnf.keys+old.keys).uniq.sort.each do |k|
v, o = cnf[k], old[k]
if v == o
puts "#{k}:#{' ' * (12-k.length)} #{v}"
else
puts "\e[31m#{k}:#{' ' * (12-k.length)} #{o}\e[0m" unless o.nil?
puts "\e[32m#{k}:#{' ' * (12-k.length)} #{v}\e[0m" unless v.nil?
end
end
else
cnf.sort_by{|k,v|k}.each do |k,v|
puts "#{k}:#{' ' * (12-k.length)} #{v}"
end
end
end
cli.sub :config, "CT/VM Configuration", min: 2, aliases: %w[cnf] do |ccli|
ccli.cmd 'help', '', aliases: [nil, '-h', '--help'], &lambda {|*args| help ccli, *args }
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
}
ccli.cmd :set, "Set Configs for CT/VM", &lambda {|name_or_id, *args|
if %w[-h --help].include? name_or_id
STDERR.puts "Usage: set -h|--help # Show help"
STDERR.puts " set ct|vm --CNF1=VAL1 --CNF2=VAL2 ... # Set config-value. Empty value clears field."
exit 1
end
opts = {}
until args.empty?
case arg = args.shift
when /\A--(\w+)=(.*)\z/
opts[$1.to_sym] = $2
when /\A--(\w+)\z/
opts[$1.to_sym] = args.shift
else
raise UsageError, "Expection option to set. What do you mean with: #{arg}"
end
end
opts.each do |k, v|
opts[k] =
case v = opts[k]
when '' then nil
else v
end
end
%i[migrate_downtime].each do |k|
next unless opts.has_key? k
opts[k] =
case v = opts[k]
when nil, '', 'nil' then nil
else v.to_f
end
end
%i[memory background_delay balloon cores cpulimit cpuunits migrate_speed shares smp sockets vcpus swap tty].each do |k|
next unless opts.has_key? k
opts[k] =
case v = opts[k]
when nil, '', 'nil' then nil
else v.to_i
end
end
%i[unprivileged debug onboot protection template].each do |k|
next unless opts.has_key? k
opts[k] =
case v = opts[k]
when *%w[1 T TRUE t true True Y YES y yes Yes] then true
when *%w[0 F FALSE f false False N NO n no No] then false
when '', 'nil', nil then nil
else raise UsageError, "Boolean expected, given: #{v.inspect}"
end
end
connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
old = th.config
opts[:digest] ||= old[:digest]
th.cnfset opts
show_config th.config, old
}
end
cli.cmd :enter, "Enter Console of CT/Node", &lambda {|name_or_id|
connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Node.find_by_name( name_or_id)
raise UsageError, "Container or Node not found: #{name_or_id}" unless th
STDERR.puts "! #{$?.exitstatus}" unless th.enter
}
cli.cmd :run, "Starts CT/VM", aliases: %w[start star], &lambda {|name_or_id|
connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
raise UsageError, "Container or Node not found: #{name_or_id}" unless th
start th
}
#cli.cmd :reboot, "Reboot CT/VM (not implemented, yet)", min: 6, &lambda {|name_or_id|
# connect
# th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
# raise UsageError, "Container or Node not found: #{name_or_id}" unless th
# reboot th
#}
cli.cmd :stop, "Stops CT/VM", min: 4, &lambda {|name_or_id|
connect
th = Proxmox::LXC.find( name_or_id) || Proxmox::Qemu.find_by_name( name_or_id)
raise UsageError, "Container or Node not found: #{name_or_id}" unless th
stop th
}
cli.cmd 'help', '', aliases: ['-h', '--help'], &lambda {|*args| help cli, *args }
cli.cmd 'cli', 'Opens interactive console', min: 3, aliases: [nil], &lambda {
@interactive = true
cli.interactive( File.basename($0,'.rb')).run
}
end
end