2021-04-19 20:35:39 +02:00
require 'pmap'
class PVE :: Cli
2021-06-07 13:54:17 +02:00
using IPAddress :: ToSWithNetmaskForNetworks
2021-04-19 20:35:39 +02:00
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
2021-11-25 15:55:07 +01:00
nodes = node ? Proxmox :: Node . find_by_name ( name ) : Proxmox :: Node . all
2021-04-19 20:35:39 +02:00
nodes .
2021-12-08 22:35:21 +01:00
flat_map { | n | [ Thread . new ( n , & :lxc ) , Thread . new ( n , & :qemu ) ] } .
each { | n | n . value . each & push }
2021-04-19 20:35:39 +02:00
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 |
2021-12-08 22:35:21 +01:00
ccli . cmd :help , '' , aliases : [ nil , '-h' , '--help' ] , & lambda { | * args | help ccli , * args }
2021-04-19 20:35:39 +02:00
2021-09-27 16:07:08 +02:00
ccli . cmd :set , " Set Configs for CT/VM " , min : 3 , & lambda { | name_or_id , * args |
2021-04-19 20:35:39 +02:00
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
}
2021-09-27 16:07:08 +02:00
ccli . cmd :show , " Show Config of CT/VM " , aliases : %w[ s ] , & lambda { | name_or_id |
connect
th = Proxmox :: LXC . find ( name_or_id ) || Proxmox :: Qemu . find_by_name ( name_or_id )
show_config th . config
}
2021-04-19 20:35:39 +02:00
end
2021-11-25 15:55:07 +01:00
cli . cmd ( :enter , " Enter Console of CT/Node " , & lambda { | name_or_id |
2021-04-19 20:35:39 +02:00
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
2021-11-25 15:55:07 +01:00
} ) .
completion do | * pre , arg |
completion_helper * pre , arg do | f |
complete_lxc ( f ) + complete_node ( f )
end
end
2021-04-19 20:35:39 +02:00
2021-11-25 15:55:07 +01:00
cli . cmd ( :run , " Starts CT/VM " , aliases : %w[ start star ] , & lambda { | name_or_id |
2021-04-19 20:35:39 +02:00
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
2021-11-25 15:55:07 +01:00
} ) .
completion do | * pre , arg |
completion_helper * pre , arg do | f |
complete_lxc ( f ) + complete_qemu ( f )
end
end
2021-04-19 20:35:39 +02:00
#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
#}
2021-11-25 15:55:07 +01:00
cli . cmd ( :stop , " Stops CT/VM " , min : 4 , & lambda { | name_or_id |
2021-04-19 20:35:39 +02:00
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
2021-11-25 15:55:07 +01:00
} ) .
completion do | * pre , arg |
completion_helper * pre , arg do | f |
complete_lxc ( f ) + complete_qemu ( f )
end
end
2021-04-19 20:35:39 +02:00
2021-12-08 22:35:21 +01:00
cli . cmd ( :help , '' , aliases : [ '-h' , '--help' ] , & lambda { | * args , full : |
if full
cli . help_full * args , output : STDERR
else
cli . help * args , output : STDERR
end
} ) .
opt ( :full , '-f' , '--[no-]full' , 'Includes all commands of all subcommands.' , default : false )
2021-04-19 20:35:39 +02:00
2021-12-08 22:35:21 +01:00
cli . cmd :cli , 'Opens interactive console' , min : 3 , aliases : [ nil ] , & lambda {
2021-04-19 20:35:39 +02:00
@interactive = true
cli . interactive ( File . basename ( $0 , '.rb' ) ) . run
}
end
end