genesis_collector 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +13 -0
- data/Rakefile +2 -0
- data/genesis_collector.gemspec +1 -3
- data/lib/genesis_collector/collector.rb +23 -4
- data/lib/genesis_collector/dmidecode.rb +41 -0
- data/lib/genesis_collector/network_interfaces.rb +16 -4
- data/lib/genesis_collector/version.rb +1 -1
- metadata +6 -21
- data/lib/core_ext/try.rb +0 -102
- data/lib/genesis_collector/lshw.rb +0 -11
- data/lib/genesis_collector/lshw_parser.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 208f4ec96b38ba5d57e06c70ec9cf0771b566da9
|
4
|
+
data.tar.gz: 08e9f2d38f9a0df9bbf83080dfb086b499c3cb5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 786aa2d00b95c9bd341adc132166346c1e764a25ea8051d0d9373b6b52e1a2898dbe83cef3fad4d8765045e48546a3e4d39ec9c66208f583fe7e0092cbb4fc49
|
7
|
+
data.tar.gz: 12c5f4036cf0908efaded80a491143ef29f9e15ed98d9d27b2520bb70ab02d0862300075220335f0640030d737b78c20e95ed62c282aef46d85521875bda0bd6
|
data/.travis.yml
ADDED
data/Rakefile
CHANGED
data/genesis_collector.gemspec
CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.
|
22
|
-
|
23
|
-
spec.add_development_dependency 'bundler', '~> 1.11'
|
21
|
+
spec.add_development_dependency 'bundler'
|
24
22
|
spec.add_development_dependency 'rake', '~> 10.0'
|
25
23
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
24
|
spec.add_development_dependency 'webmock', '~> 1.22'
|
@@ -5,8 +5,8 @@ require 'genesis_collector/simple_http'
|
|
5
5
|
require 'genesis_collector/network_interfaces'
|
6
6
|
require 'genesis_collector/chef'
|
7
7
|
require 'genesis_collector/ipmi'
|
8
|
-
require 'genesis_collector/lshw'
|
9
8
|
require 'genesis_collector/disks'
|
9
|
+
require 'genesis_collector/dmidecode'
|
10
10
|
require 'English'
|
11
11
|
|
12
12
|
module GenesisCollector
|
@@ -16,8 +16,8 @@ module GenesisCollector
|
|
16
16
|
include GenesisCollector::NetworkInterfaces
|
17
17
|
include GenesisCollector::Chef
|
18
18
|
include GenesisCollector::IPMI
|
19
|
-
include GenesisCollector::Lshw
|
20
19
|
include GenesisCollector::Disks
|
20
|
+
include GenesisCollector::DmiDecode
|
21
21
|
|
22
22
|
def initialize(config = {})
|
23
23
|
@chef_node = config.delete(:chef_node)
|
@@ -71,11 +71,30 @@ module GenesisCollector
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def collect_cpus
|
74
|
-
@payload[:cpus] =
|
74
|
+
@payload[:cpus] = get_dmi_data['processor'].map do |p|
|
75
|
+
{
|
76
|
+
description: p['version'],
|
77
|
+
cores: p['core_count'].to_i,
|
78
|
+
threads: p['thread_count'].to_i,
|
79
|
+
speed: p['current_speed'],
|
80
|
+
vendor_name: p['manufacturer'],
|
81
|
+
physid: p['socket_designation']
|
82
|
+
}
|
83
|
+
end
|
75
84
|
end
|
76
85
|
|
77
86
|
def collect_memories
|
78
|
-
@payload[:memories] =
|
87
|
+
@payload[:memories] = get_dmi_data['memory'].map do |m|
|
88
|
+
empty = m['size'] == 'No Module Installed'
|
89
|
+
{
|
90
|
+
size: m['size'].to_i * 1000000,
|
91
|
+
description: empty ? "Empty #{m['form_factor']}" : "#{m['form_factor']} #{m['type_detail']} #{m['speed']}",
|
92
|
+
bank: m['bank_locator'],
|
93
|
+
slot: m['locator'],
|
94
|
+
product: empty ? nil : m['part_number'],
|
95
|
+
vendor_name: empty ? nil : m['manufacturer']
|
96
|
+
}
|
97
|
+
end
|
79
98
|
end
|
80
99
|
|
81
100
|
private
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module GenesisCollector
|
2
|
+
module DmiDecode
|
3
|
+
|
4
|
+
def get_dmi_data
|
5
|
+
@dmi_data ||= parse_dmidecode(shellout_with_timeout('dmidecode --type processor --type memory'))
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse_dmidecode(data)
|
9
|
+
dict={}
|
10
|
+
handle = 0
|
11
|
+
current_title = nil
|
12
|
+
|
13
|
+
data.lines.each do |line|
|
14
|
+
case line
|
15
|
+
when /^End Of Table/, /^\s+$/, /^\# dmidecode/, /^SMBIOS/, /structures occupying/, /^Table at/
|
16
|
+
next
|
17
|
+
when /^Handle\s+(.*?),\s+/
|
18
|
+
handle = $1.to_i(16)
|
19
|
+
when /(.*)\s+Information\n$/, /(.*)\s+Device\n$/, /(.*)\s+Device Mapped Address\n$/, /(.*)\s+Array Mapped Address\n$/
|
20
|
+
title = standardize_dmi_key($1)
|
21
|
+
current_title = title
|
22
|
+
dict[title] ||= []
|
23
|
+
dict[title] << {'handle' => handle}
|
24
|
+
else
|
25
|
+
raw_data = line.strip.split(':')
|
26
|
+
if raw_data.is_a?(Array) && raw_data.length == 2
|
27
|
+
k, v = raw_data
|
28
|
+
dict[current_title].last[standardize_dmi_key(k)] = v.strip
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
dict
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def standardize_dmi_key(k)
|
38
|
+
k.downcase.gsub(/\s+/,'_')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -17,17 +17,14 @@ module GenesisCollector
|
|
17
17
|
end
|
18
18
|
@payload[:network_interfaces] = interfaces.reduce([]) { |memo, (k, v)| memo << v.merge(name: k) }
|
19
19
|
@payload[:network_interfaces].each do |i|
|
20
|
-
lshw_interface = get_lshw_data.network_interfaces.select { |lshw_i| lshw_i[:name] == i[:name] }[0]
|
21
20
|
i[:status] = read_interface_info(i[:name], 'operstate')
|
22
21
|
i[:mac_address] = read_mac_address(i[:name])
|
23
|
-
i[:product] = lshw_interface.try(:[], :product)
|
24
22
|
if i[:status] == 'up'
|
25
23
|
i[:speed] = get_interface_speed(i[:name])
|
26
24
|
i[:duplex] = read_interface_info(i[:name], 'duplex')
|
27
25
|
end
|
28
|
-
i[:vendor_name] = lshw_interface.try(:[], :vendor_name)
|
29
|
-
i[:link_type] = lshw_interface.try(:[], :link_type)
|
30
26
|
i[:neighbor] = get_network_neighbor(i[:name])
|
27
|
+
i.merge!(get_lspci_data(i[:name])) unless i[:name].include?('bond')
|
31
28
|
i.merge!(get_interface_driver(i[:name]))
|
32
29
|
end
|
33
30
|
end
|
@@ -91,5 +88,20 @@ module GenesisCollector
|
|
91
88
|
data
|
92
89
|
end
|
93
90
|
|
91
|
+
def get_lspci_data(interface)
|
92
|
+
slot = File.basename(File.readlink("/sys/class/net/#{interface}/device"))
|
93
|
+
raw_data = shellout_with_timeout("lspci -v -mm -s #{slot}")
|
94
|
+
data = {}
|
95
|
+
raw_data.each_line do |line|
|
96
|
+
if line.match(/^Vendor:(.*)$/)
|
97
|
+
data[:vendor_name] = $1.strip
|
98
|
+
end
|
99
|
+
if line.match(/^Device:(.*)$/)
|
100
|
+
data[:product] = $1.strip
|
101
|
+
end
|
102
|
+
end
|
103
|
+
data
|
104
|
+
end
|
105
|
+
|
94
106
|
end
|
95
107
|
end
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: genesis_collector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Radcliffe
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
|
-
type: :
|
20
|
+
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '1.11'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1.11'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rake
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +76,7 @@ extra_rdoc_files: []
|
|
90
76
|
files:
|
91
77
|
- ".gitignore"
|
92
78
|
- ".rspec"
|
79
|
+
- ".travis.yml"
|
93
80
|
- Gemfile
|
94
81
|
- LICENSE.txt
|
95
82
|
- README.md
|
@@ -100,14 +87,12 @@ files:
|
|
100
87
|
- exe/genesis_collector
|
101
88
|
- genesis_collector.gemspec
|
102
89
|
- lib/chef/handler/genesis.rb
|
103
|
-
- lib/core_ext/try.rb
|
104
90
|
- lib/genesis_collector.rb
|
105
91
|
- lib/genesis_collector/chef.rb
|
106
92
|
- lib/genesis_collector/collector.rb
|
107
93
|
- lib/genesis_collector/disks.rb
|
94
|
+
- lib/genesis_collector/dmidecode.rb
|
108
95
|
- lib/genesis_collector/ipmi.rb
|
109
|
-
- lib/genesis_collector/lshw.rb
|
110
|
-
- lib/genesis_collector/lshw_parser.rb
|
111
96
|
- lib/genesis_collector/network_interfaces.rb
|
112
97
|
- lib/genesis_collector/simple_http.rb
|
113
98
|
- lib/genesis_collector/version.rb
|
data/lib/core_ext/try.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# https://github.com/rails/rails/blob/ff7d37d5884be3939833fb52b58a95017369eda5/activesupport/lib/active_support/core_ext/object/try.rb
|
2
|
-
|
3
|
-
class Object
|
4
|
-
# Invokes the public method whose name goes as first argument just like
|
5
|
-
# +public_send+ does, except that if the receiver does not respond to it the
|
6
|
-
# call returns +nil+ rather than raising an exception.
|
7
|
-
#
|
8
|
-
# This method is defined to be able to write
|
9
|
-
#
|
10
|
-
# @person.try(:name)
|
11
|
-
#
|
12
|
-
# instead of
|
13
|
-
#
|
14
|
-
# @person.name if @person
|
15
|
-
#
|
16
|
-
# +try+ calls can be chained:
|
17
|
-
#
|
18
|
-
# @person.try(:spouse).try(:name)
|
19
|
-
#
|
20
|
-
# instead of
|
21
|
-
#
|
22
|
-
# @person.spouse.name if @person && @person.spouse
|
23
|
-
#
|
24
|
-
# +try+ will also return +nil+ if the receiver does not respond to the method:
|
25
|
-
#
|
26
|
-
# @person.try(:non_existing_method) #=> nil
|
27
|
-
#
|
28
|
-
# instead of
|
29
|
-
#
|
30
|
-
# @person.non_existing_method if @person.respond_to?(:non_existing_method) #=> nil
|
31
|
-
#
|
32
|
-
# +try+ returns +nil+ when called on +nil+ regardless of whether it responds
|
33
|
-
# to the method:
|
34
|
-
#
|
35
|
-
# nil.try(:to_i) # => nil, rather than 0
|
36
|
-
#
|
37
|
-
# Arguments and blocks are forwarded to the method if invoked:
|
38
|
-
#
|
39
|
-
# @posts.try(:each_slice, 2) do |a, b|
|
40
|
-
# ...
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
# The number of arguments in the signature must match. If the object responds
|
44
|
-
# to the method the call is attempted and +ArgumentError+ is still raised
|
45
|
-
# in case of argument mismatch.
|
46
|
-
#
|
47
|
-
# If +try+ is called without arguments it yields the receiver to a given
|
48
|
-
# block unless it is +nil+:
|
49
|
-
#
|
50
|
-
# @person.try do |p|
|
51
|
-
# ...
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# You can also call try with a block without accepting an argument, and the block
|
55
|
-
# will be instance_eval'ed instead:
|
56
|
-
#
|
57
|
-
# @person.try { upcase.truncate(50) }
|
58
|
-
#
|
59
|
-
# Please also note that +try+ is defined on +Object+. Therefore, it won't work
|
60
|
-
# with instances of classes that do not have +Object+ among their ancestors,
|
61
|
-
# like direct subclasses of +BasicObject+. For example, using +try+ with
|
62
|
-
# +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
|
63
|
-
# the delegator itself.
|
64
|
-
def try(*a, &b)
|
65
|
-
try!(*a, &b) if a.empty? || respond_to?(a.first)
|
66
|
-
end
|
67
|
-
|
68
|
-
# Same as #try, but will raise a NoMethodError exception if the receiver is not +nil+ and
|
69
|
-
# does not implement the tried method.
|
70
|
-
|
71
|
-
def try!(*a, &b)
|
72
|
-
if a.empty? && block_given?
|
73
|
-
if b.arity == 0
|
74
|
-
instance_eval(&b)
|
75
|
-
else
|
76
|
-
yield self
|
77
|
-
end
|
78
|
-
else
|
79
|
-
public_send(*a, &b)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
class NilClass
|
85
|
-
# Calling +try+ on +nil+ always returns +nil+.
|
86
|
-
# It becomes especially helpful when navigating through associations that may return +nil+.
|
87
|
-
#
|
88
|
-
# nil.try(:name) # => nil
|
89
|
-
#
|
90
|
-
# Without +try+
|
91
|
-
# @person && @person.children.any? && @person.children.first.name
|
92
|
-
#
|
93
|
-
# With +try+
|
94
|
-
# @person.try(:children).try(:first).try(:name)
|
95
|
-
def try(*args)
|
96
|
-
nil
|
97
|
-
end
|
98
|
-
|
99
|
-
def try!(*args)
|
100
|
-
nil
|
101
|
-
end
|
102
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
require 'core_ext/try'
|
3
|
-
|
4
|
-
module GenesisCollector
|
5
|
-
class LshwParser
|
6
|
-
attr_reader :doc
|
7
|
-
|
8
|
-
def initialize(doc)
|
9
|
-
@doc = Nokogiri::XML(doc)
|
10
|
-
end
|
11
|
-
|
12
|
-
def cpus
|
13
|
-
@cpus ||= doc.xpath("//node[@class='processor']").map do |cpu|
|
14
|
-
{
|
15
|
-
description: cpu.at_xpath('.//product').try(:text) || cpu.at_xpath('.//description').try(:text),
|
16
|
-
cores: cpu.at_xpath(".//configuration/setting[@id='cores']/@value").try(:value).try(:to_i),
|
17
|
-
threads: cpu.at_xpath(".//configuration/setting[@id='threads']/@value").try(:value).try(:to_i),
|
18
|
-
speed: cpu.at_xpath('.//size').try(:text).try(:to_i),
|
19
|
-
vendor_name: cpu.at_xpath('.//vendor').try(:text),
|
20
|
-
physid: cpu.at_xpath('.//physid').try(:text).try(:to_i)
|
21
|
-
}
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def memories
|
26
|
-
@memories ||= doc.xpath("//node[@class='memory']/*[@id]").map do |memory|
|
27
|
-
mem_size = memory.at_xpath('.//size')
|
28
|
-
{
|
29
|
-
size: mem_size.nil? ? 0 : mem_size.text.to_i,
|
30
|
-
description: memory.at_xpath('.//description').text,
|
31
|
-
bank: memory.at_xpath('.//physid').text.to_i,
|
32
|
-
slot: memory.at_xpath('.//slot').try(:text),
|
33
|
-
product: memory.at_xpath('.//product').try(:text),
|
34
|
-
vendor_name: memory.at_xpath('.//vendor').try(:text)
|
35
|
-
}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def network_interfaces
|
40
|
-
@network_interfaces ||= doc.xpath("//node[@class='network']").map do |network_interface|
|
41
|
-
{
|
42
|
-
name: network_interface.at_xpath('.//logicalname').try(:text),
|
43
|
-
description: network_interface.at_xpath('.//description').try(:text),
|
44
|
-
mac_address: network_interface.at_xpath('.//serial').try(:text),
|
45
|
-
product: network_interface.at_xpath('.//product').try(:text),
|
46
|
-
vendor_name: network_interface.at_xpath('.//vendor').try(:text),
|
47
|
-
driver: network_interface.at_xpath(".//configuration//setting[@id='driver']/@value").try(:text),
|
48
|
-
driver_version: network_interface.at_xpath(".//configuration//setting[@id='driverversion']/@value").try(:text),
|
49
|
-
duplex: network_interface.at_xpath(".//configuration//setting[@id='duplex']/@value").try(:text),
|
50
|
-
link_type: network_interface.at_xpath(".//configuration//setting[@id='port']/@value").try(:text)
|
51
|
-
}
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|