pve/lib/pve/cli/ct.rb

148 lines
6.5 KiB
Ruby

class PVE::Cli
def cli_ct
cli.sub :ct, "Containers", aliases: %w[lx lxc] do |ct_cli|
ct_cli.cmd :list, "List CT-IDs", aliases: ['ls'], &lambda {|node=nil|
connect
nodes = node ? Proxmox::Node.find_by_name( name) : Proxmox::Node.all
nodes.flat_map do |n|
n.lxc.map {|c| c.vmid.to_i }
end.sort.each {|c| puts c }
}
ct_cli.cmd( :status, "Lists CTs with status", aliases: [nil], &lambda {|target=nil, sort: nil, node: nil, status: nil, tags: nil|
hosting_table target: target, status: status, sort: sort, tags: tags do |push|
node_opt( node).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)", 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)").
opt( :tags, '-t', '--tags=TAGS', "Filter by comma-seperated tags. All tags must be present for CT")
ct_cli.cmd :enter, "Enter Console of CT", &lambda {|name_or_id|
connect
@out.host = name_or_id
@out.failed "Exitstatus #{$?.exitstatus}" unless Proxmox::LXC.find!( name_or_id).enter
}
ct_cli.cmd :exec, "Executes Command in CT", min: 4, &lambda {|name_or_id, *command|
connect
@out.host = name_or_id
@out.failed "Exitstatus #{$?.exitstatus}" unless Proxmox::LXC.find!( name_or_id).exec *command
}
ct_cli.cmd( :migrate, "Migrates halted CT(s) to an other host", min: 2, &lambda {|target, *names_or_ids, fire:, timeout:, secs:|
connect
node = Proxmox::Node.find_by_name! target
per_argument names_or_ids, print: "Migrate CT:" do |name_or_id|
ct = Proxmox::LXC.find! name_or_id
task = ct.migrate node
wait task, text: "Migrating", timeout: timeout unless fire
end
}).tap {|c| opts_wait c }
ct_cli.cmd( :volume_move, "Moves volume to an other storage/pool and marks old volume as unused.", min: 11, aliases: %i[volmv mv], &lambda {|name_or_id, volume, destination|
connect
ct = Proxmox::LXC.find! name_or_id
ct_volume_move ct, volume, destination
})
ct_cli.cmd( :start, "Starts CT(s)", min: 4, &lambda {|*names_or_ids, node: nil, fire:, timeout:, secs:|
connect
per_argument names_or_ids, print: "Start CT:" do |name_or_id|
ct = Proxmox::LXC.find! name_or_id
start ct, node: node, fire: fire, timeout: timeout, secs: secs
end
}).tap {|c| opts_wait c }
ct_cli.cmd( :stop, "Stops CT(s)", min: 3, &lambda {|*names_or_ids, fire: nil, timeout:, secs:|
connect
per_argument names_or_ids, print: "Start CT:" do |name_or_id|
ct = Proxmox::LXC.find! name_or_id
stop ct, fire: fire, timeout: timeout, secs: secs
end
}).tap {|c| opts_wait c }
ct_cli.cmd( :wait, "Wait till CT is in state", &lambda {|name_or_id, state, timeout: nil, secs: nil|
connect
ct = Proxmox::LXC.find! name_or_id
wait ct, state, timeout: timeout, secs: secs
}).
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", 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"
STDERR.puts " ct create -l # Listing available templates"
exit 1
elsif %w[-l --list].include? template
STDERR.puts PVE::CTTemplate.constants.reject {|c|:Base==c}.map {|c|c.to_s.titlecase.dasherize.downcase}
exit 0
end
ctopts = {}
OptionParser.new do |opts|
ctt = PVE::CTTemplate.const_get template.classify
opts.banner = <<EOU
Usage: ct create #{template} [options]
#{ctt.help}
Options: (*=Required)
EOU
opts.on '-h', '--help', " Help!" do
STDERR.puts opts
exit 1 unless interactive?
return
end
opts.on( '-r', '--[no-]-start', " Start container after creation") {|v| ctopts[:start] = v }
opts.on( '-f', '--[no-]-fire', " Do not wait till running") {|v| ctopts[:start] = v }
opts.on( '-t', '--timeout=TIMEOUT', " Wait for max TIMEOUT seconds (default: endless)") {|v| ctopts[:timeout] = v }
opts.on( '-s', '--seconds=SECONDS', " Check every SECONDS for state (default: 0.2)") {|v| ctopts[:seconds] = v }
ctt.requirements.each do |name, (type, req, desc, *args)|
req = req ? "*" : " "
case type
when :boolean
opts.on( "--[no-]#{name}", "#{req}#{desc}") {|v| ctopts[name] = v }
when :string, :numeric
opts.on( "--#{name}=#{type.upcase}", "#{req}#{desc}") {|v| ctopts[name] = v }
when :enum
opts.on( "--#{name}=#{type.upcase}", "#{req}#{desc} (#{args.first.join ', '})") do |v|
ctopts[name] = v
end
end
end
end.parse! options
connect
create Proxmox::LXC, template, **ctopts
})
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)
})
ct_cli.cmd( :resize, 'Resize a disk', &lambda {|name_or_id, disk, size|
connect
ct = Proxmox::LXC.find! name_or_id
task = ct.resize disk, size
wait task, text: "Resizing #{ct.sid} #{disk} to #{size}"
})
ct_cli.cmd( :destroy, '', min: 7, &lambda {|name_or_id, fire:, secs:, timeout:, i_really_want_to_destroy:|
raise UsageError, "Name/ID is not what you want to destroy" unless name_or_id == i_really_want_to_destroy
connect
ct = Proxmox::LXC.find! name_or_id
raise UsageError, "Container is not stopped" unless ct.stopped?
destroy ct, fire: fire, timeout: timeout, secs: secs
}).tap {|c| opts_wait c }.
opt( :i_really_want_to_destroy, "--i-really-want-to-destroy=NAMEORID", "Repeat the name/ID")
ct_cli.cmd( :help, '', aliases: ['-h', '--help']) {|*args| help ct_cli, *args }
end
end
end