collect2, fetch2 tests
This commit is contained in:
parent
9e9e7609c4
commit
52c72fd670
2
Gemfile
2
Gemfile
|
@ -5,3 +5,5 @@ gem 'rack'
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
gem 'sd_notify'
|
gem 'sd_notify'
|
||||||
gem 'cbor'
|
gem 'cbor'
|
||||||
|
gem 'io-extra'
|
||||||
|
gem 'ffi'
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
require 'pathname'
|
require 'pathname'
|
||||||
require 'prometheus/client'
|
require 'prometheus/client'
|
||||||
require 'lxc'
|
require 'lxc'
|
||||||
|
require 'ostruct'
|
||||||
|
|
||||||
require_relative 'ns'
|
require_relative 'ns'
|
||||||
require_relative 'file-statfs'
|
require_relative 'file-statfs'
|
||||||
|
@ -60,7 +61,7 @@ class LxcCollector
|
||||||
|
|
||||||
AptLastUpdateFile = Pathname.new '/var/cache/apt/pkgcache.bin'
|
AptLastUpdateFile = Pathname.new '/var/cache/apt/pkgcache.bin'
|
||||||
|
|
||||||
def forked wr
|
def forkedo wr
|
||||||
LXC.running_containers do |ct|
|
LXC.running_containers do |ct|
|
||||||
pid = ct.init_pid
|
pid = ct.init_pid
|
||||||
mis = MountInfo.of pid
|
mis = MountInfo.of pid
|
||||||
|
@ -106,7 +107,7 @@ class LxcCollector
|
||||||
exit 0
|
exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect
|
def collecto
|
||||||
LXC.containers do |ct|
|
LXC.containers do |ct|
|
||||||
labels = { id: ct.name, name: ct.config_item( 'lxc.uts.name') }
|
labels = { id: ct.name, name: ct.config_item( 'lxc.uts.name') }
|
||||||
@up.set ct.running? ? 1 : 0, labels: labels
|
@up.set ct.running? ? 1 : 0, labels: labels
|
||||||
|
@ -147,9 +148,105 @@ class LxcCollector
|
||||||
Process.wait pid
|
Process.wait pid
|
||||||
@prometheus
|
@prometheus
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def forked2 io, ct
|
||||||
|
pid = ct.init_pid
|
||||||
|
mis = MountInfo.of pid
|
||||||
|
id, name = ct.name, ct.config_item( 'lxc.uts.name')
|
||||||
|
NS.enter pid, keep_open: [io, STDERR, STDOUT]
|
||||||
|
|
||||||
|
# Filesystems
|
||||||
|
statfs ct, mis do |ct, mp, st|
|
||||||
|
next unless st.fstypename and 0 < st.blocks
|
||||||
|
st = st.to_h.merge mp: mp, id: id, name: name
|
||||||
|
io.write [:mountpoint, st]
|
||||||
|
end
|
||||||
|
|
||||||
|
# OS / Distribution
|
||||||
|
osr = OsRelease.read
|
||||||
|
unless osr.nil?
|
||||||
|
io.write [:os_release, {
|
||||||
|
id: id, name: name,
|
||||||
|
os_id: osr[:id],
|
||||||
|
os_name: osr[:name],
|
||||||
|
os_pretty_name: osr[:pretty_name],
|
||||||
|
os_version_id: osr[:version_id].to_i,
|
||||||
|
os_version_codename: osr[:version_codename]
|
||||||
|
}]
|
||||||
|
|
||||||
|
case osr[:id].to_sym
|
||||||
|
# Special things for Debian(-based) distributions
|
||||||
|
when :debian
|
||||||
|
upgradable = nil
|
||||||
|
pid =
|
||||||
|
IO.popen %w[apt list --upgradable], err: "/dev/null" do |apt|
|
||||||
|
upgradable = apt.readlines.length - 1
|
||||||
|
end
|
||||||
|
io.write [:pkgs, {
|
||||||
|
id: id, name: name, upgradable: upgradable,
|
||||||
|
last_update: AptLastUpdateFile.stat.mtime.to_f,
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Object
|
||||||
|
STDERR.puts "#{$!} (#{$!.class})", $!.backtrace.map {|x| " #{x}"}
|
||||||
|
end
|
||||||
|
|
||||||
|
def collect2
|
||||||
|
LXC.containers do |ct|
|
||||||
|
labels = { id: ct.name, name: ct.config_item( 'lxc.uts.name') }
|
||||||
|
@up.set ct.running? ? 1 : 0, labels: labels
|
||||||
|
@state.set CTStates[ct.state], labels: labels
|
||||||
|
end
|
||||||
|
|
||||||
|
LXC.running_containers.map do |ct|
|
||||||
|
Thread.new ct do |ct|
|
||||||
|
pid, io = CBORIO.popen(:r) {|io| forked2 io, ct }
|
||||||
|
begin
|
||||||
|
io.map do |l|
|
||||||
|
case l[0].to_sym
|
||||||
|
|
||||||
|
when :mountpoint
|
||||||
|
st = OpenStruct.new l[1]
|
||||||
|
labels = { id: st.id, mountpoint: st.mp }
|
||||||
|
@info.set 1, labels: labels.merge( name: st.name, fstype: st.fstypename)
|
||||||
|
@totalb.set st.bsize*st.blocks, labels: labels
|
||||||
|
@freeb.set st.bsize*st.bfree, labels: labels
|
||||||
|
@availb.set st.bsize*st.bavail, labels: labels
|
||||||
|
@totalf.set st.files, labels: labels
|
||||||
|
@freef.set st.ffree, labels: labels
|
||||||
|
|
||||||
|
when :os_release
|
||||||
|
osr = OpenStruct.new l[1]
|
||||||
|
@os_release.set 1, labels: {
|
||||||
|
id: osr.id, name: osr.name,
|
||||||
|
os_id: osr.os_id,
|
||||||
|
os_name: osr.os_name,
|
||||||
|
os_pretty_name: osr.os_pretty_name,
|
||||||
|
os_version_codename: osr.os_version_codename
|
||||||
|
}
|
||||||
|
@os_version.set osr.os_version_id, labels: { id: osr.id }
|
||||||
|
|
||||||
|
when :pkgs
|
||||||
|
as = OpenStruct.new l[1]
|
||||||
|
@pkgs_last_update.set as.last_update, labels: { id: as.id }
|
||||||
|
@pkgs_upgradable.set as.upgradable, labels: { id: as.id }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
io.close
|
||||||
|
Process.wait pid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end.each &:join
|
||||||
|
@prometheus
|
||||||
|
end
|
||||||
|
|
||||||
|
alias forked forked2
|
||||||
|
alias collect collect2
|
||||||
end
|
end
|
||||||
|
|
||||||
if Pathname.new( __FILE__).expand_path == Pathname.new( $0).expand_path
|
if Pathname.new( __FILE__).expand_path == Pathname.new( $0).expand_path
|
||||||
require 'prometheus/client/formats/text'
|
require 'prometheus/client/formats/text'
|
||||||
puts Prometheus::Client::Formats::Text.marshal( LxcCollector.new.collect)
|
puts Prometheus::Client::Formats::Text.marshal( LxcCollector.new.collect2)
|
||||||
end
|
end
|
||||||
|
|
71
lib/ns.rb
71
lib/ns.rb
|
@ -1,5 +1,6 @@
|
||||||
require 'fiddle'
|
require 'fiddle'
|
||||||
require 'fiddle/import'
|
require 'fiddle/import'
|
||||||
|
require 'io/extra'
|
||||||
|
|
||||||
class NS
|
class NS
|
||||||
extend Fiddle::Importer
|
extend Fiddle::Importer
|
||||||
|
@ -32,30 +33,56 @@ class NS
|
||||||
ns.change &exe
|
ns.change &exe
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
attr_reader :pid, :fds, :types
|
def enter pid, keep_open: nil
|
||||||
|
new( pid).enter keep_open: keep_open
|
||||||
def initialize pid, *types
|
|
||||||
@pid, @fds = pid, {}
|
|
||||||
types.map {|t| @fds[t] = self.class._open_nsfd pid, t }
|
|
||||||
end
|
|
||||||
|
|
||||||
def close
|
|
||||||
@fds.each {|t, fd| fd.close }
|
|
||||||
end
|
|
||||||
|
|
||||||
def change &block
|
|
||||||
@owns = @fds.map {|t, _f| Own[t] }
|
|
||||||
begin
|
|
||||||
@fds.each {|type, fd| self.class.setns fd, 0 }
|
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
@owns.each {|fd| self.class.setns fd, 0 }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Own = Hash.new {|h, ns| h[ns] = _open_nsfd $$, ns }
|
attr_reader :pid, :fds
|
||||||
|
|
||||||
|
def initialize pid, *types
|
||||||
|
@pid, @fds = pid, {}
|
||||||
|
types = Dir.children "/proc/%d/ns" % pid if types.empty? or types.include?( :any)
|
||||||
|
types.each {|t| @fds[t.to_sym] = self.class._open_nsfd pid, t }
|
||||||
|
end
|
||||||
|
|
||||||
|
def close_ios *keep_open
|
||||||
|
keep_open =
|
||||||
|
keep_open.flatten.map do |fd|
|
||||||
|
case fd
|
||||||
|
when Integer then fd
|
||||||
|
when IO then fd.to_i
|
||||||
|
when nil # ignore
|
||||||
|
else raise ArgumentError, "Unknown file descriptor for keeping opened: #{fd.inspect}"
|
||||||
|
end
|
||||||
|
end.sort
|
||||||
|
IO.fdwalk(0) {|fd| fd.close unless keep_open.include? fd.to_i }
|
||||||
|
end
|
||||||
|
|
||||||
|
def enter keep_open: nil
|
||||||
|
close_ios keep_open, @fds.values
|
||||||
|
@fds.each {|_, fd| self.class.setns fd, 0 }
|
||||||
|
close
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
@fds.each {|_, fd| fd.close }
|
||||||
|
end
|
||||||
|
|
||||||
|
def change &block
|
||||||
|
if block_given?
|
||||||
|
@owns = @fds.map {|ns, _f| self.class._open_nsfd $$, ns }
|
||||||
|
begin
|
||||||
|
@fds.each {|type, fd| self.class.setns fd, 0 }
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
@owns.each {|fd| self.class.setns fd, 0 }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@fds.each {|type, fd| self.class.setns fd, 0 }
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue