UPID-Parser, Task status & monitoring
This commit is contained in:
parent
83211a817f
commit
6530c40749
|
@ -380,9 +380,9 @@ class PVE::Cli
|
||||||
end
|
end
|
||||||
status =
|
status =
|
||||||
case 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'
|
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]
|
%i[started online running]
|
||||||
when /\Asto(p(p(ed?)?)?)?\z/i, /\Aof(f(l(i(ne?)?)?)?)?\z/i, '0'
|
when /\Asto(?:p(?:p(?:ed?)?)?)?\z/i, /\Aof(?:f(?:l(?:i(?:ne?)?)?)?)?\z/i, '0'
|
||||||
%i[stopped offline]
|
%i[stopped offline]
|
||||||
when nil, '', /\Aa(ll?)?\z/i then nil
|
when nil, '', /\Aa(ll?)?\z/i then nil
|
||||||
else
|
else
|
||||||
|
@ -533,7 +533,7 @@ class PVE::Cli
|
||||||
end
|
end
|
||||||
[
|
[
|
||||||
case v.status
|
case v.status
|
||||||
when :running, :online then ColoredString.new v.status, "32"
|
when :running, :online then ColoredString.new v.status, "32"
|
||||||
when :stopped, :offline then ColoredString.new v.status, "31"
|
when :stopped, :offline then ColoredString.new v.status, "31"
|
||||||
else v.status
|
else v.status
|
||||||
end,
|
end,
|
||||||
|
@ -546,14 +546,14 @@ class PVE::Cli
|
||||||
end,
|
end,
|
||||||
v.name, node,
|
v.name, node,
|
||||||
v.respond_to?(:uptime) ? TablizedOutput::V.new( v.uptime, Measured.seconds( v.uptime)) : unknown,
|
v.respond_to?(:uptime) ? TablizedOutput::V.new( v.uptime, Measured.seconds( v.uptime)) : unknown,
|
||||||
v.respond_to?(:cpu) ? TablizedOutput::Percentage.new( v.cpu) : unknown,
|
v.respond_to?(:cpu) ? TablizedOutput::Percentage.new( v.cpu) : unknown,
|
||||||
v.respond_to?(:mem) ? TablizedOutput::V.new( v.mem, Measured.bytes( v.mem)) : unknown,
|
v.respond_to?(:mem) ? TablizedOutput::V.new( v.mem, Measured.bytes( v.mem)) : unknown,
|
||||||
v.respond_to?(:maxmem) ? TablizedOutput::Percentage.new( v.mem/v.maxmem.to_f) : unknown,
|
v.respond_to?(:maxmem) ? TablizedOutput::Percentage.new( v.mem/v.maxmem.to_f) : unknown,
|
||||||
v.respond_to?(:disk) ? TablizedOutput::V.new( v.disk.to_i, Measured.bytes( v.disk.to_i)) : unknown,
|
v.respond_to?(:disk) ? TablizedOutput::V.new( v.disk.to_i, Measured.bytes( v.disk.to_i)) : unknown,
|
||||||
if v.respond_to?(:maxdisk) and 0 < v.maxdisk.to_i
|
if v.respond_to?(:maxdisk) and 0 < v.maxdisk.to_i
|
||||||
TablizedOutput::Percentage.new( v.disk.to_f/v.maxdisk.to_f)
|
TablizedOutput::Percentage.new( v.disk.to_f/v.maxdisk.to_f)
|
||||||
else unknown end,
|
else unknown end,
|
||||||
v.respond_to?(:tags) ? v.tags.join(', ') : '',
|
v.respond_to?(:tags) ? v.tags.join(', ') : '',
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,33 @@
|
||||||
class PVE::Cli
|
class PVE::Cli
|
||||||
|
def task_table order: nil, &exe
|
||||||
|
to = TablizedOutput.new %w[S Starttime Node SID Type UPID], format: '<<<<<<'
|
||||||
|
hosted = {}
|
||||||
|
Proxmox::Hosted.all.each {|h| hosted[h.vmid.to_i] = h }
|
||||||
|
hosted.delete nil
|
||||||
|
exe.call lambda {|t|
|
||||||
|
u = t.upid
|
||||||
|
v = u.id ? hosted[u.id.to_i] : t.node
|
||||||
|
to.push [
|
||||||
|
case t.status.state
|
||||||
|
when :running then ColoredString.new '...', '30'
|
||||||
|
when :success then ColoredString.new 'OK', '32'
|
||||||
|
when :failed then ColoredString.new 'failed', '31'
|
||||||
|
end,
|
||||||
|
u.starttime.strftime( '%Y-%m-%d %H:%M:%S'),
|
||||||
|
u.node,
|
||||||
|
case v&.t
|
||||||
|
when 'nd' then ColoredString.new v.sid, '33'
|
||||||
|
when 'qm' then ColoredString.new v.sid, '35'
|
||||||
|
when 'ct' then ColoredString.new v.sid, '36'
|
||||||
|
when nil then u.id.inspect
|
||||||
|
else v.sid
|
||||||
|
end,
|
||||||
|
u.dtype, u.upid
|
||||||
|
]
|
||||||
|
}
|
||||||
|
to.print order: order
|
||||||
|
end
|
||||||
|
|
||||||
def cli_task
|
def cli_task
|
||||||
cli.sub :task, "Inspect tasks" do |tcli|
|
cli.sub :task, "Inspect tasks" do |tcli|
|
||||||
tcli.cmd :list, "List done tasks", &lambda {|node=nil|
|
tcli.cmd :list, "List done tasks", &lambda {|node=nil|
|
||||||
|
@ -7,7 +36,7 @@ def cli_task
|
||||||
nodes = nodes.select {|n| node == n.name } if node
|
nodes = nodes.select {|n| node == n.name } if node
|
||||||
nodes.flat_map do |n|
|
nodes.flat_map do |n|
|
||||||
n.tasks.map &:upid
|
n.tasks.map &:upid
|
||||||
end.sort.each {|upid| puts upid }
|
end.sort_by(&:upid).each {|upid| puts upid }
|
||||||
}
|
}
|
||||||
|
|
||||||
tcli.cmd :get, "Inspect a task", &lambda {|upid|
|
tcli.cmd :get, "Inspect a task", &lambda {|upid|
|
||||||
|
@ -22,21 +51,39 @@ def cli_task
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
tcli.cmd :status, "Shows tasks states", &lambda {|upid|
|
tcli.cmd( :status, "Lists tasks with status", aliases: [nil], &lambda {|target=nil, sort: nil, node: nil, status: nil|
|
||||||
}
|
connect
|
||||||
|
task_table order: [2] do |push|
|
||||||
|
Proxmox::Node.all.each {|n| n.tasks.each {|t| p t; push.call t } }
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
tcli.cmd :monitor, "Monitors running tasks", &lambda {|node: nil|
|
tcli.cmd( :monitor, "Monitors running tasks", &lambda {|node: nil|
|
||||||
connect
|
connect
|
||||||
nodes = Proxmox::Node.all
|
nodes = Proxmox::Node.all
|
||||||
nodes = nodes.select {|n| node == n.name } if node
|
nodes = nodes.select {|n| node == n.name } if node
|
||||||
tasks = {}
|
tasks = {}
|
||||||
loop do
|
nodes.each {|n| n.tasks.each {|t| tasks[t.upid.upid] = true } }
|
||||||
nodes.flat_map do |n|
|
begin
|
||||||
n.tasks.map &:upid
|
loop do
|
||||||
end.sort.each do |upid|
|
task_table order: [2] do |push|
|
||||||
|
begin
|
||||||
|
nodes.
|
||||||
|
flat_map {|n| n.tasks }.
|
||||||
|
select {|t| tasks[t.upid.upid] != true or t.running? }.
|
||||||
|
each( &push)
|
||||||
|
STDERR.print "\e[2J\e[1;1H"
|
||||||
|
rescue RestClient::InternalServerError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep 1
|
||||||
end
|
end
|
||||||
|
rescue Interrupt
|
||||||
|
STDERR.print "\e[2J\e[1;1H"
|
||||||
end
|
end
|
||||||
}
|
})
|
||||||
|
|
||||||
|
tcli.cmd( :help, '', aliases: ['-h', '--help']) {|*args| help ct_cli, *args }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,8 @@ module Proxmox
|
||||||
end
|
end
|
||||||
class AlreadyLocked < Exception
|
class AlreadyLocked < Exception
|
||||||
end
|
end
|
||||||
|
class UnparsableUPID < Exception
|
||||||
|
end
|
||||||
|
|
||||||
def self.cnfstr2hash str
|
def self.cnfstr2hash str
|
||||||
str.
|
str.
|
||||||
|
@ -84,7 +86,7 @@ module Proxmox
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_by_vmid vmid
|
def self.find_by_vmid vmid
|
||||||
Proxmox::LXC.find_by_vmid( vmid) || Proxmox::Qemu.find_by_vmid( vmid) || Proxmox::Node.find_by_vmid( vmid)
|
Proxmox::LXC.find_by_vmid( vmid) || Proxmox::Qemu.find_by_vmid( vmid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find name_or_id
|
def self.find name_or_id
|
||||||
|
@ -299,12 +301,22 @@ module Proxmox
|
||||||
def refresh!
|
def refresh!
|
||||||
d = rest_get @rest_prefix
|
d = rest_get @rest_prefix
|
||||||
d[:starttime] &&= Time.at d[:starttime]
|
d[:starttime] &&= Time.at d[:starttime]
|
||||||
d = {exitstatus: nil}.merge d
|
|
||||||
__update__ d.merge( node: @node, upid: @upid, task: @task)
|
__update__ d.merge( node: @node, upid: @upid, task: @task)
|
||||||
end
|
end
|
||||||
|
|
||||||
def __update__ **data
|
def __update__ **data
|
||||||
data = data.merge t: 'status'
|
data = data.merge t: 'status'
|
||||||
|
data[:status] = data[:status]&.to_sym
|
||||||
|
data[:exitstatus] = data[:exitstatus]&.to_sym
|
||||||
|
data[:state] =
|
||||||
|
case data[:status]
|
||||||
|
when :running then :running
|
||||||
|
when :stopped
|
||||||
|
case data[:exitstatus]
|
||||||
|
when :OK then :success
|
||||||
|
else :failed
|
||||||
|
end
|
||||||
|
end
|
||||||
super **data
|
super **data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -319,11 +331,51 @@ module Proxmox
|
||||||
"#<#{self.class.name}|#{@upid} node=#{@node.node} #{h.join ' '}>"
|
"#<#{self.class.name}|#{@upid} node=#{@node.node} #{h.join ' '}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
def running?() 'running' == @status end
|
def running?() :running == @status end
|
||||||
def finished?() 'stopped' == @status end
|
def finished?() :stopped == @status end
|
||||||
alias stopped? finished?
|
alias stopped? finished?
|
||||||
def successfull?() stopped? ? 'OK' == @exitstatus : nil end
|
def successfull?() stopped? ? :OK == @exitstatus : nil end
|
||||||
def failed?() stopped? ? 'OK' != @exitstatus : nil end
|
def failed?() stopped? ? :OK != @exitstatus : nil end
|
||||||
|
end
|
||||||
|
|
||||||
|
def running?() status.running? end
|
||||||
|
def finished?() status.finished? end
|
||||||
|
alias stopped? finished?
|
||||||
|
def successfull?() status.successfull? end
|
||||||
|
def failed?() status.failed? end
|
||||||
|
|
||||||
|
class UPID
|
||||||
|
RE =
|
||||||
|
/^
|
||||||
|
UPID :
|
||||||
|
(?<node>[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?) :
|
||||||
|
(?<pid>[0-9A-Fa-f]{8}) :
|
||||||
|
(?<pstart>[0-9A-Fa-f]{8,9}) :
|
||||||
|
(?<starttime>[0-9A-Fa-f]{8}) :
|
||||||
|
(?<dtype>[^:\s]+) :
|
||||||
|
(?<id>[^:\s]*) :
|
||||||
|
(?<user>[^:\s]+) :
|
||||||
|
$/x
|
||||||
|
|
||||||
|
attr_reader :upid, :node, :pid, :pstart, :starttime, :dtype, :id, :user
|
||||||
|
alias to_s upid
|
||||||
|
|
||||||
|
def initialize upid
|
||||||
|
m = RE.match upid
|
||||||
|
raise UnparsableUPID, "UPID cannot be parsed: #{upid.inspect} (#{upid.class})" unless m
|
||||||
|
@upid = upid
|
||||||
|
@node = m[:node]
|
||||||
|
@pid = m[:pid].to_i 16
|
||||||
|
@pstart = m[:pstart].to_i 16
|
||||||
|
@starttime = Time.at m[:starttime].to_i( 16)
|
||||||
|
@dtype = m[:dtype]
|
||||||
|
@id = case m[:id] when '' then nil else m[:id].to_i end
|
||||||
|
@user = m[:user]
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"#<#{self.class.name} #{@upid}>"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def rest_prefix
|
def rest_prefix
|
||||||
|
@ -332,7 +384,7 @@ module Proxmox
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
rest_prefix
|
rest_prefix
|
||||||
@sid = upid
|
@sid, @upid = upid, UPID.new( upid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
|
@ -349,6 +401,10 @@ module Proxmox
|
||||||
end
|
end
|
||||||
|
|
||||||
class Hosted < Base
|
class Hosted < Base
|
||||||
|
def self.all
|
||||||
|
Node.all.flat_map {|n| n.qemu + n.lxc }
|
||||||
|
end
|
||||||
|
|
||||||
def refresh!
|
def refresh!
|
||||||
__updata__ rest_get( "#{@rest_prefix}/status/current").merge( node: @node, t: @t)
|
__updata__ rest_get( "#{@rest_prefix}/status/current").merge( node: @node, t: @t)
|
||||||
end
|
end
|
||||||
|
@ -450,25 +506,23 @@ module Proxmox
|
||||||
rest_put "#{@rest_prefix}/config", **r
|
rest_put "#{@rest_prefix}/config", **r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# it is only allowed to lock local guests, because it is only possible to unlock local guests.
|
||||||
def lock reason, &exe
|
def lock reason, &exe
|
||||||
cnf = config
|
cnf = config
|
||||||
raise Proxmox::AlreadyLocked, "Machine #{self} Already locked for: #{cnf[:lock].inspect}" unless cnf[:lock].nil?
|
raise Proxmox::AlreadyLocked, "Machine #{self} Already locked for: #{cnf[:lock].inspect}" unless cnf[:lock].nil?
|
||||||
r = rest_put "#{@rest_prefix}/config", {lock: reason}
|
r = rest_put "#{@rest_prefix}/config", {lock: reason}
|
||||||
if block_given?
|
if block_given?
|
||||||
begin
|
begin return yield
|
||||||
return yield
|
ensure unlock
|
||||||
ensure
|
|
||||||
unlock
|
|
||||||
end
|
end
|
||||||
else
|
else r
|
||||||
r
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unlock
|
def unlock
|
||||||
system 'pct', 'unlock', @vmid.to_s
|
system 'pct', 'unlock', @vmid.to_s
|
||||||
raise Proxmox::UnlockFailed unless $?.success?
|
raise Proxmox::UnlockFailed unless $?.success?
|
||||||
#rest_put "#{@rest_prefix}/config", {delete: %w[lock]}
|
#rest_put "#{@rest_prefix}/config", {delete: %w[lock], skiplock: 1}
|
||||||
end
|
end
|
||||||
|
|
||||||
def resize disk, size
|
def resize disk, size
|
||||||
|
|
Loading…
Reference in a new issue