ohai 8.6.0.alpha.1 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -12
- data/lib/ohai/config.rb +3 -0
- data/lib/ohai/dsl/plugin/versionvii.rb +41 -0
- data/lib/ohai/exception.rb +1 -0
- data/lib/ohai/mixin/softlayer_metadata.rb +64 -0
- data/lib/ohai/plugin_config.rb +46 -0
- data/lib/ohai/plugins/aix/cpu.rb +23 -18
- data/lib/ohai/plugins/aix/memory.rb +9 -2
- data/lib/ohai/plugins/aix/network.rb +1 -1
- data/lib/ohai/plugins/cloud.rb +34 -3
- data/lib/ohai/plugins/ec2.rb +6 -0
- data/lib/ohai/plugins/linux/network.rb +245 -190
- data/lib/ohai/plugins/linux/platform.rb +50 -15
- data/lib/ohai/plugins/linux/virtualization.rb +3 -1
- data/lib/ohai/plugins/softlayer.rb +47 -0
- data/lib/ohai/plugins/solaris2/cpu.rb +46 -17
- data/lib/ohai/plugins/solaris2/memory.rb +9 -1
- data/lib/ohai/plugins/vmware.rb +73 -0
- data/lib/ohai/plugins/windows/memory.rb +38 -0
- data/lib/ohai/version.rb +1 -1
- data/spec/unit/config_spec.rb +28 -0
- data/spec/unit/dsl/plugin_spec.rb +73 -0
- data/spec/unit/mixin/softlayer_metadata_spec.rb +71 -0
- data/spec/unit/plugin_config_spec.rb +118 -0
- data/spec/unit/plugins/aix/cpu_spec.rb +31 -12
- data/spec/unit/plugins/aix/memory_spec.rb +47 -0
- data/spec/unit/plugins/aix/network_spec.rb +1 -1
- data/spec/unit/plugins/ec2_spec.rb +35 -13
- data/spec/unit/plugins/linux/memory_spec.rb +204 -0
- data/spec/unit/plugins/linux/network_spec.rb +40 -0
- data/spec/unit/plugins/linux/platform_spec.rb +62 -6
- data/spec/unit/plugins/linux/virtualization_spec.rb +21 -0
- data/spec/unit/plugins/softlayer_spec.rb +60 -0
- data/spec/unit/plugins/solaris2/cpu_spec.rb +2887 -42
- data/spec/unit/plugins/solaris2/memory_spec.rb +15 -2
- data/spec/unit/plugins/vmware_spec.rb +62 -0
- data/spec/unit/plugins/windows/memory_spec.rb +52 -0
- metadata +18 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e00fe8c9c7789a01f275184d7cfe7a6bbc4a8631
|
4
|
+
data.tar.gz: 2368b6c70151bf9b89ee2dc2d3518a8d10add807
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9aa2d69b2544e9b270429795f02e3db9e8d2b978c16afba7fecfd377cfac3553c8da4a350a1e8d4edc55577c0a64d8d1d2266dc8135f1d354455494fb7b741c5
|
7
|
+
data.tar.gz: 523a0112f688c7536c5f4bff387ec0218f4ba8f0c97e995917dba271c2f41137c4793e572c826f3050ca577b4a0483c776c98376bd71a93913b61f388db8a79c
|
data/Rakefile
CHANGED
@@ -1,18 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require 'rubygems/package_task'
|
3
|
-
require 'rubygems/specification'
|
1
|
+
require "bundler/gem_tasks"
|
4
2
|
require 'date'
|
5
3
|
require 'ohai/version'
|
6
4
|
|
7
|
-
gemspec = eval(IO.read("ohai.gemspec"))
|
8
|
-
|
9
|
-
Gem::PackageTask.new(gemspec).define
|
10
|
-
|
11
|
-
desc "install the gem locally"
|
12
|
-
task :install => [:package] do
|
13
|
-
sh %{gem install pkg/ohai-#{Ohai::VERSION}.gem}
|
14
|
-
end
|
15
|
-
|
16
5
|
begin
|
17
6
|
require 'rspec/core/rake_task'
|
18
7
|
|
data/lib/ohai/config.rb
CHANGED
@@ -18,7 +18,9 @@
|
|
18
18
|
#
|
19
19
|
|
20
20
|
require 'chef-config/config'
|
21
|
+
require 'ohai/exception'
|
21
22
|
require 'ohai/log'
|
23
|
+
require 'ohai/plugin_config'
|
22
24
|
|
23
25
|
module Ohai
|
24
26
|
Config = ChefConfig::Config
|
@@ -93,6 +95,7 @@ module Ohai
|
|
93
95
|
default :hints_path, Ohai::Config.default_hints_path
|
94
96
|
default :log_level, :auto
|
95
97
|
default :log_location, STDERR
|
98
|
+
default :plugin, Ohai::PluginConfig.new { |h, k| h[k] = Ohai::PluginConfig.new }
|
96
99
|
default :plugin_path, Ohai::Config.default_plugin_path
|
97
100
|
end
|
98
101
|
|
@@ -100,6 +100,47 @@ module Ohai
|
|
100
100
|
def require_plugin(*args)
|
101
101
|
Ohai::Log.warn("[UNSUPPORTED OPERATION] \'require_plugin\' is no longer supported. Please use \'depends\' instead.\nIgnoring plugin(s) #{args.join(", ")}")
|
102
102
|
end
|
103
|
+
|
104
|
+
def configuration(option, *options)
|
105
|
+
return nil if plugin_config.nil? || !plugin_config.key?(option)
|
106
|
+
value = plugin_config[option]
|
107
|
+
options.each do |opt|
|
108
|
+
return nil unless value.key?(opt)
|
109
|
+
value = value[opt]
|
110
|
+
end
|
111
|
+
value
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
def plugin_config
|
116
|
+
@plugin_config ||= fetch_plugin_config
|
117
|
+
end
|
118
|
+
|
119
|
+
def fetch_plugin_config
|
120
|
+
# DMI => ["DMI"]
|
121
|
+
# Memory => ["", "Memory"]
|
122
|
+
# NetworkListeners => ["", "Network", "", "Listeners"]
|
123
|
+
# SSHHostKey => ["SSH", "Host", "", "Key"]
|
124
|
+
parts = self.name.to_s.split(/([A-Z][a-z]+)/)
|
125
|
+
# ["DMI"] => ["DMI"]
|
126
|
+
# ["", "Memory"] => ["Memory"]
|
127
|
+
# ["", "Network", "", "Listeners"] => ["Network", "Listeners"]
|
128
|
+
# ["SSH", "Host", "", "Key"] => ["SSH", "Host", "Key"]
|
129
|
+
parts.delete_if { |part| part.empty? }
|
130
|
+
# ["DMI"] => :dmi
|
131
|
+
# ["Memory"] => :memory
|
132
|
+
# ["Network", "Listeners"] => :network_listeners
|
133
|
+
# ["SSH", "Host", "Key"] => :ssh_host_key
|
134
|
+
snake_case_name = parts.map { |part| part.downcase }.join("_").to_sym
|
135
|
+
|
136
|
+
# Plugin names in config hashes are auto-vivified, so we check with
|
137
|
+
# key? to avoid falsely instantiating a configuration hash.
|
138
|
+
if Ohai.config[:plugin].key?(snake_case_name)
|
139
|
+
Ohai.config[:plugin][snake_case_name]
|
140
|
+
else
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
103
144
|
end
|
104
145
|
end
|
105
146
|
end
|
data/lib/ohai/exception.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Alexey Karpik <alexey.karpik@rightscale.com>
|
3
|
+
# Author:: Peter Schroeter <peter.schroeter@rightscale.com>
|
4
|
+
# Author:: Stas Turlo <stanislav.turlo@rightscale.com>
|
5
|
+
# Copyright:: Copyright (c) 2010-2014 RightScale Inc
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
|
20
|
+
require 'net/https'
|
21
|
+
require 'uri'
|
22
|
+
|
23
|
+
# http://sldn.softlayer.com/reference/services/SoftLayer_Resource_Metadata
|
24
|
+
module ::Ohai::Mixin::SoftlayerMetadata
|
25
|
+
SOFTLAYER_API_QUERY_URL = 'https://api.service.softlayer.com/rest/v3.1/SoftLayer_Resource_Metadata' unless defined?(SOFTLAYER_API_QUERY_URL)
|
26
|
+
|
27
|
+
def fetch_metadata
|
28
|
+
metadata = {
|
29
|
+
'public_fqdn' => fetch_metadata_item("getFullyQualifiedDomainName.txt"),
|
30
|
+
'local_ipv4' => fetch_metadata_item("getPrimaryBackendIpAddress.txt"),
|
31
|
+
'public_ipv4' => fetch_metadata_item("getPrimaryIpAddress.txt"),
|
32
|
+
'region' => fetch_metadata_item("getDatacenter.txt"),
|
33
|
+
'instance_id' => fetch_metadata_item("getId.txt")
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Softlayer's metadata api is only available over HTTPS.
|
38
|
+
# Ruby by default does not link to the system's CA bundle
|
39
|
+
# however Chef-omnibus should set SSL_CERT_FILE to point to a valid file.
|
40
|
+
# Manually supply and specify a suitable CA bundle here or
|
41
|
+
# set the SSL_CERT_FILE file environment variable to a valid value otherwise.
|
42
|
+
def ca_file_location
|
43
|
+
::Ohai::Config[:ca_file]
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_metadata_item(item)
|
47
|
+
full_url = "#{SOFTLAYER_API_QUERY_URL}/#{item}"
|
48
|
+
u = URI(full_url)
|
49
|
+
net = ::Net::HTTP.new(u.hostname, u.port)
|
50
|
+
net.ssl_version = "TLSv1"
|
51
|
+
net.use_ssl = true
|
52
|
+
net.ca_file = ca_file_location
|
53
|
+
res = net.get(u.request_uri)
|
54
|
+
if res.code.to_i.between?(200,299)
|
55
|
+
res.body
|
56
|
+
else
|
57
|
+
::Ohai::Log.error("Unable to fetch item #{full_url}: status (#{res.code}) body (#{res.body})")
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
rescue => e
|
61
|
+
::Ohai::Log.error("Unable to fetch softlayer metadata from #{u}: #{e.class}: #{e.message}")
|
62
|
+
raise e
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'ohai/exception'
|
19
|
+
|
20
|
+
module Ohai
|
21
|
+
class PluginConfig < Hash
|
22
|
+
|
23
|
+
def []=(key, value_or_hash)
|
24
|
+
enforce_symbol(key)
|
25
|
+
enforce_symbol_keys(value_or_hash) if value_or_hash.is_a?(Hash)
|
26
|
+
super(key, value_or_hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def enforce_symbol(key)
|
32
|
+
unless key.is_a?(Symbol)
|
33
|
+
msg = "Expected Symbol, got #{key.inspect}"
|
34
|
+
raise Ohai::Exceptions::PluginConfigError, msg
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def enforce_symbol_keys(hash)
|
39
|
+
hash.each do |key, value|
|
40
|
+
enforce_symbol(key)
|
41
|
+
enforce_symbol_keys(value) if value.is_a?(Hash)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/ohai/plugins/aix/cpu.rb
CHANGED
@@ -22,32 +22,37 @@ Ohai.plugin(:CPU) do
|
|
22
22
|
|
23
23
|
collect_data(:aix) do
|
24
24
|
cpu Mash.new
|
25
|
-
|
26
|
-
|
27
|
-
cpu[:vendor_id] = "IBM"
|
25
|
+
|
26
|
+
cpu[:total] = shell_out("pmcycles -m").stdout.lines.length
|
28
27
|
# At least one CPU will be available, but we'll wait to increment this later.
|
29
28
|
cpu[:available] = 0
|
30
|
-
cpu[:total] = 0
|
31
29
|
|
32
30
|
cpudevs = shell_out("lsdev -Cc processor").stdout.lines
|
33
|
-
|
34
|
-
|
31
|
+
#from http://www-01.ibm.com/software/passportadvantage/pvu_terminology_for_customers.html
|
32
|
+
#on AIX number of cores and processors are considered same
|
33
|
+
cpu[:real] = cpu[:cores] = cpudevs.length
|
34
|
+
cpudevs.each.with_index do |c,i|
|
35
35
|
name, status, location = c.split
|
36
|
-
|
37
|
-
cpu[
|
38
|
-
cpu[
|
36
|
+
index = i.to_s
|
37
|
+
cpu[index] = Mash.new
|
38
|
+
cpu[index][:status] = status
|
39
|
+
cpu[index][:location] = location
|
39
40
|
if status =~ /Available/
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
cpu[:available] += 1
|
42
|
+
lsattr = shell_out("lsattr -El #{name}").stdout.lines
|
43
|
+
lsattr.each do |attribute|
|
43
44
|
attrib, value = attribute.split
|
44
|
-
|
45
|
-
|
45
|
+
if attrib == "type"
|
46
|
+
cpu[index][:model_name] = value
|
47
|
+
elsif attrib == "frequency"
|
48
|
+
cpu[index][:mhz] = value.to_i / (1000 * 1000) #convert from hz to MHz
|
49
|
+
else
|
50
|
+
cpu[index][attrib] = value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
# IBM is the only maker of CPUs for AIX systems.
|
54
|
+
cpu[index][:vendor_id] = "IBM"
|
46
55
|
end
|
47
56
|
end
|
48
|
-
|
49
|
-
# Every AIX system has proc0.
|
50
|
-
cpu[:model] = cpu[:proc0][:type]
|
51
|
-
cpu[:mhz] = cpu[:proc0][:frequency].to_i / 1024
|
52
57
|
end
|
53
58
|
end
|
@@ -20,9 +20,16 @@ Ohai.plugin(:Memory) do
|
|
20
20
|
provides "memory"
|
21
21
|
|
22
22
|
collect_data(:aix) do
|
23
|
-
memory
|
23
|
+
memory Mash.new
|
24
|
+
memory[:swap] = Mash.new
|
24
25
|
|
25
26
|
meminfo = shell_out("svmon -G -O unit=MB,summary=longreal | grep '[0-9]'").stdout
|
26
|
-
|
27
|
+
total_in_mb, u, free_in_mb = meminfo.split
|
28
|
+
memory[:total] = "#{total_in_mb.to_i * 1024}kB"
|
29
|
+
memory[:free] = "#{free_in_mb.to_i * 1024}kB"
|
30
|
+
|
31
|
+
swapinfo = shell_out("swap -s").stdout.split #returns swap info in 4K blocks
|
32
|
+
memory[:swap]['total'] = "#{(swapinfo[2].to_i) * 4}kB"
|
33
|
+
memory[:swap]['free'] = "#{(swapinfo[10].to_i) * 4}kB"
|
27
34
|
end
|
28
35
|
end
|
data/lib/ohai/plugins/cloud.rb
CHANGED
@@ -25,6 +25,7 @@ Ohai.plugin(:Cloud) do
|
|
25
25
|
depends "openstack"
|
26
26
|
depends "azure"
|
27
27
|
depends "digital_ocean"
|
28
|
+
depends "softlayer"
|
28
29
|
|
29
30
|
# Make top-level cloud hashes
|
30
31
|
#
|
@@ -60,7 +61,7 @@ Ohai.plugin(:Cloud) do
|
|
60
61
|
private_ips = gce['instance']["networkInterfaces"].collect do |interface|
|
61
62
|
interface['ip']
|
62
63
|
end.compact
|
63
|
-
|
64
|
+
|
64
65
|
cloud[:public_ips] += public_ips
|
65
66
|
cloud[:private_ips] += private_ips
|
66
67
|
cloud[:public_ipv4] += public_ips
|
@@ -108,7 +109,7 @@ Ohai.plugin(:Cloud) do
|
|
108
109
|
end
|
109
110
|
|
110
111
|
# Fill cloud hash with rackspace values
|
111
|
-
def get_rackspace_values
|
112
|
+
def get_rackspace_values
|
112
113
|
cloud[:public_ips] << rackspace['public_ipv4'] if rackspace['public_ipv4']
|
113
114
|
cloud[:private_ips] << rackspace['local_ipv4'] if rackspace['local_ipv4']
|
114
115
|
cloud[:public_ipv4] = rackspace['public_ipv4']
|
@@ -245,7 +246,31 @@ Ohai.plugin(:Cloud) do
|
|
245
246
|
cloud[:provider] = "digital_ocean"
|
246
247
|
end
|
247
248
|
|
248
|
-
|
249
|
+
# ----------------------------------------
|
250
|
+
# softlayer
|
251
|
+
# ----------------------------------------
|
252
|
+
|
253
|
+
# Is current cloud softlayer?
|
254
|
+
#
|
255
|
+
# === Return
|
256
|
+
# true:: If softlayer Hash is defined
|
257
|
+
# false:: Otherwise
|
258
|
+
def on_softlayer?
|
259
|
+
softlayer != nil
|
260
|
+
end
|
261
|
+
|
262
|
+
# Fill cloud hash with softlayer values
|
263
|
+
def get_softlayer_values
|
264
|
+
cloud[:public_ipv4] = softlayer['public_ipv4']
|
265
|
+
cloud[:local_ipv4] = softlayer['local_ipv4']
|
266
|
+
cloud[:public_ips] << softlayer['public_ipv4'] if softlayer['public_ipv4']
|
267
|
+
cloud[:private_ips] << softlayer['local_ipv4'] if softlayer['local_ipv4']
|
268
|
+
cloud[:public_hostname] = softlayer['public_fqdn']
|
269
|
+
cloud[:provider] = 'softlayer'
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
collect_data do
|
249
274
|
# setup gce cloud
|
250
275
|
if on_gce?
|
251
276
|
create_objects
|
@@ -292,5 +317,11 @@ Ohai.plugin(:Cloud) do
|
|
292
317
|
create_objects
|
293
318
|
get_digital_ocean_values
|
294
319
|
end
|
320
|
+
|
321
|
+
# setup softlayer cloud
|
322
|
+
if on_softlayer?
|
323
|
+
create_objects
|
324
|
+
get_softlayer_values
|
325
|
+
end
|
295
326
|
end
|
296
327
|
end
|
data/lib/ohai/plugins/ec2.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
|
20
20
|
require 'ohai/mixin/ec2_metadata'
|
21
|
+
require 'base64'
|
21
22
|
|
22
23
|
Ohai.plugin(:EC2) do
|
23
24
|
include Ohai::Mixin::Ec2Metadata
|
@@ -58,6 +59,11 @@ Ohai.plugin(:EC2) do
|
|
58
59
|
ec2[k] = v
|
59
60
|
end
|
60
61
|
ec2[:userdata] = self.fetch_userdata
|
62
|
+
#ASCII-8BIT is equivalent to BINARY in this case
|
63
|
+
if ec2[:userdata].encoding.to_s == "ASCII-8BIT"
|
64
|
+
Ohai::Log.debug("Binary UserData Found. Storing in base64")
|
65
|
+
ec2[:userdata] = Base64.encode64(ec2[:userdata])
|
66
|
+
end
|
61
67
|
else
|
62
68
|
Ohai::Log.debug("looks_like_ec2? == false")
|
63
69
|
false
|
@@ -41,6 +41,246 @@ Ohai.plugin(:Network) do
|
|
41
41
|
["/sbin/ip", "/usr/bin/ip", "/bin/ip"].any? { |path| File.exist?(path) }
|
42
42
|
end
|
43
43
|
|
44
|
+
def is_openvz?
|
45
|
+
::File.directory?('/proc/vz')
|
46
|
+
end
|
47
|
+
|
48
|
+
def is_openvz_host?
|
49
|
+
is_openvz? && ::File.directory?('/proc/bc')
|
50
|
+
end
|
51
|
+
|
52
|
+
def extract_neighbors(family, iface, neigh_attr)
|
53
|
+
so = shell_out("ip -f #{family[:name]} neigh show")
|
54
|
+
so.stdout.lines do |line|
|
55
|
+
if line =~ /^([a-f0-9\:\.]+)\s+dev\s+([^\s]+)\s+lladdr\s+([a-fA-F0-9\:]+)/
|
56
|
+
interface = iface[$2]
|
57
|
+
unless interface
|
58
|
+
Ohai::Log.warn("neighbor list has entries for unknown interface #{interface}")
|
59
|
+
next
|
60
|
+
end
|
61
|
+
interface[neigh_attr] = Mash.new unless interface[neigh_attr]
|
62
|
+
interface[neigh_attr][$1] = $3.downcase
|
63
|
+
end
|
64
|
+
end
|
65
|
+
iface
|
66
|
+
end
|
67
|
+
|
68
|
+
# checking the routing tables
|
69
|
+
# why ?
|
70
|
+
# 1) to set the default gateway and default interfaces attributes
|
71
|
+
# 2) on some occasions, the best way to select node[:ipaddress] is to look at
|
72
|
+
# the routing table source field.
|
73
|
+
# 3) and since we're at it, let's populate some :routes attributes
|
74
|
+
# (going to do that for both inet and inet6 addresses)
|
75
|
+
def check_routing_table(family, iface)
|
76
|
+
so = shell_out("ip -o -f #{family[:name]} route show")
|
77
|
+
so.stdout.lines do |line|
|
78
|
+
line.strip!
|
79
|
+
Ohai::Log.debug("Parsing #{line}")
|
80
|
+
if line =~ /\\/
|
81
|
+
parts = line.split('\\')
|
82
|
+
route_dest = parts.shift.strip
|
83
|
+
route_endings = parts
|
84
|
+
elsif line =~ /^([^\s]+)\s(.*)$/
|
85
|
+
route_dest = $1
|
86
|
+
route_endings = [$2]
|
87
|
+
else
|
88
|
+
next
|
89
|
+
end
|
90
|
+
route_endings.each do |route_ending|
|
91
|
+
if route_ending =~ /\bdev\s+([^\s]+)\b/
|
92
|
+
route_int = $1
|
93
|
+
else
|
94
|
+
Ohai::Log.debug("Skipping route entry without a device: '#{line}'")
|
95
|
+
next
|
96
|
+
end
|
97
|
+
route_int = 'venet0:0' if is_openvz? && !is_openvz_host? && route_int == 'venet0' && iface['venet0:0']
|
98
|
+
|
99
|
+
unless iface[route_int]
|
100
|
+
Ohai::Log.debug("Skipping previously unseen interface from 'ip route show': #{route_int}")
|
101
|
+
next
|
102
|
+
end
|
103
|
+
|
104
|
+
route_entry = Mash.new(:destination => route_dest,
|
105
|
+
:family => family[:name])
|
106
|
+
%w[via scope metric proto src].each do |k|
|
107
|
+
route_entry[k] = $1 if route_ending =~ /\b#{k}\s+([^\s]+)\b/
|
108
|
+
end
|
109
|
+
|
110
|
+
# a sanity check, especially for Linux-VServer, OpenVZ and LXC:
|
111
|
+
# don't report the route entry if the src address isn't set on the node
|
112
|
+
next if route_entry[:src] and not iface[route_int][:addresses].has_key? route_entry[:src]
|
113
|
+
|
114
|
+
iface[route_int][:routes] = Array.new unless iface[route_int][:routes]
|
115
|
+
iface[route_int][:routes] << route_entry
|
116
|
+
end
|
117
|
+
end
|
118
|
+
iface
|
119
|
+
end
|
120
|
+
|
121
|
+
# now looking at the routes to set the default attributes
|
122
|
+
# for information, default routes can be of this form :
|
123
|
+
# - default via 10.0.2.4 dev br0
|
124
|
+
# - default dev br0 scope link
|
125
|
+
# - default via 10.0.3.1 dev eth1 src 10.0.3.2 metric 10
|
126
|
+
# - default via 10.0.4.1 dev eth2 src 10.0.4.2 metric 20
|
127
|
+
|
128
|
+
# using a temporary var to hold routes and their interface name
|
129
|
+
def parse_routes(family, iface)
|
130
|
+
iface.collect do |i, iv|
|
131
|
+
iv[:routes].collect do |r|
|
132
|
+
r.merge(:dev => i) if r[:family] == family[:name]
|
133
|
+
end.compact if iv[:routes]
|
134
|
+
end.compact.flatten
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def link_statistics(iface, net_counters)
|
139
|
+
so = shell_out("ip -d -s link")
|
140
|
+
tmp_int = nil
|
141
|
+
on_rx = true
|
142
|
+
so.stdout.lines do |line|
|
143
|
+
if line =~ IPROUTE_INT_REGEX
|
144
|
+
tmp_int = $2
|
145
|
+
iface[tmp_int] = Mash.new unless iface[tmp_int]
|
146
|
+
net_counters[tmp_int] = Mash.new unless net_counters[tmp_int]
|
147
|
+
end
|
148
|
+
|
149
|
+
if line =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/
|
150
|
+
int = on_rx ? :rx : :tx
|
151
|
+
net_counters[tmp_int][int] = Mash.new unless net_counters[tmp_int][int]
|
152
|
+
net_counters[tmp_int][int][:bytes] = $1
|
153
|
+
net_counters[tmp_int][int][:packets] = $2
|
154
|
+
net_counters[tmp_int][int][:errors] = $3
|
155
|
+
net_counters[tmp_int][int][:drop] = $4
|
156
|
+
if (int == :rx)
|
157
|
+
net_counters[tmp_int][int][:overrun] = $5
|
158
|
+
else
|
159
|
+
net_counters[tmp_int][int][:carrier] = $5
|
160
|
+
net_counters[tmp_int][int][:collisions] = $6
|
161
|
+
end
|
162
|
+
|
163
|
+
on_rx = !on_rx
|
164
|
+
end
|
165
|
+
|
166
|
+
if line =~ /qlen (\d+)/
|
167
|
+
net_counters[tmp_int][:tx] = Mash.new unless net_counters[tmp_int][:tx]
|
168
|
+
net_counters[tmp_int][:tx][:queuelen] = $1
|
169
|
+
end
|
170
|
+
|
171
|
+
if line =~ /vlan id (\d+)/ or line =~ /vlan protocol ([\w\.]+) id (\d+)/
|
172
|
+
if $2
|
173
|
+
tmp_prot = $1
|
174
|
+
tmp_id = $2
|
175
|
+
else
|
176
|
+
tmp_id = $1
|
177
|
+
end
|
178
|
+
iface[tmp_int][:vlan] = Mash.new unless iface[tmp_int][:vlan]
|
179
|
+
iface[tmp_int][:vlan][:id] = tmp_id
|
180
|
+
iface[tmp_int][:vlan][:protocol] = tmp_prot if tmp_prot
|
181
|
+
|
182
|
+
vlan_flags = line.scan(/(REORDER_HDR|GVRP|LOOSE_BINDING)/)
|
183
|
+
if vlan_flags.length > 0
|
184
|
+
iface[tmp_int][:vlan][:flags] = vlan_flags.flatten.uniq
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
if line =~ /state (\w+)/
|
189
|
+
iface[tmp_int]['state'] = $1.downcase
|
190
|
+
end
|
191
|
+
end
|
192
|
+
iface
|
193
|
+
end
|
194
|
+
|
195
|
+
def match_iproute(iface, line, cint)
|
196
|
+
if line =~ IPROUTE_INT_REGEX
|
197
|
+
cint = $2
|
198
|
+
iface[cint] = Mash.new
|
199
|
+
if cint =~ /^(\w+)(\d+.*)/
|
200
|
+
iface[cint][:type] = $1
|
201
|
+
iface[cint][:number] = $2
|
202
|
+
end
|
203
|
+
|
204
|
+
if line =~ /mtu (\d+)/
|
205
|
+
iface[cint][:mtu] = $1
|
206
|
+
end
|
207
|
+
|
208
|
+
flags = line.scan(/(UP|BROADCAST|DEBUG|LOOPBACK|POINTTOPOINT|NOTRAILERS|LOWER_UP|NOARP|PROMISC|ALLMULTI|SLAVE|MASTER|MULTICAST|DYNAMIC)/)
|
209
|
+
if flags.length > 1
|
210
|
+
iface[cint][:flags] = flags.flatten.uniq
|
211
|
+
end
|
212
|
+
end
|
213
|
+
cint
|
214
|
+
end
|
215
|
+
|
216
|
+
def parse_ip_addr(iface)
|
217
|
+
so = shell_out("ip addr")
|
218
|
+
cint = nil
|
219
|
+
so.stdout.lines do |line|
|
220
|
+
cint = match_iproute(iface, line, cint)
|
221
|
+
|
222
|
+
parse_ip_addr_link_line(cint, iface, line)
|
223
|
+
cint = parse_ip_addr_inet_line(cint, iface, line)
|
224
|
+
parse_ip_addr_inet6_line(cint, iface, line)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
def parse_ip_addr_link_line(cint, iface, line)
|
230
|
+
if line =~ /link\/(\w+) ([\da-f\:]+) /
|
231
|
+
iface[cint][:encapsulation] = linux_encaps_lookup($1)
|
232
|
+
unless $2 == "00:00:00:00:00:00"
|
233
|
+
iface[cint][:addresses] = Mash.new unless iface[cint][:addresses]
|
234
|
+
iface[cint][:addresses][$2.upcase] = {"family" => "lladdr"}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def parse_ip_addr_inet_line(cint, iface, line)
|
240
|
+
if line =~ /inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\/(\d{1,2}))?/
|
241
|
+
tmp_addr, tmp_prefix = $1, $3
|
242
|
+
tmp_prefix ||= "32"
|
243
|
+
original_int = nil
|
244
|
+
|
245
|
+
# Are we a formerly aliased interface?
|
246
|
+
if line =~ /#{cint}:(\d+)$/
|
247
|
+
sub_int = $1
|
248
|
+
alias_int = "#{cint}:#{sub_int}"
|
249
|
+
original_int = cint
|
250
|
+
cint = alias_int
|
251
|
+
end
|
252
|
+
|
253
|
+
iface[cint] = Mash.new unless iface[cint] # Create the fake alias interface if needed
|
254
|
+
iface[cint][:addresses] = Mash.new unless iface[cint][:addresses]
|
255
|
+
iface[cint][:addresses][tmp_addr] = {"family" => "inet", "prefixlen" => tmp_prefix}
|
256
|
+
iface[cint][:addresses][tmp_addr][:netmask] = IPAddr.new("255.255.255.255").mask(tmp_prefix.to_i).to_s
|
257
|
+
|
258
|
+
if line =~ /peer (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
|
259
|
+
iface[cint][:addresses][tmp_addr][:peer] = $1
|
260
|
+
end
|
261
|
+
|
262
|
+
if line =~ /brd (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
|
263
|
+
iface[cint][:addresses][tmp_addr][:broadcast] = $1
|
264
|
+
end
|
265
|
+
|
266
|
+
if line =~ /scope (\w+)/
|
267
|
+
iface[cint][:addresses][tmp_addr][:scope] = ($1.eql?("host") ? "Node" : $1.capitalize)
|
268
|
+
end
|
269
|
+
|
270
|
+
# If we found we were an an alias interface, restore cint to its original value
|
271
|
+
cint = original_int unless original_int.nil?
|
272
|
+
end
|
273
|
+
cint
|
274
|
+
end
|
275
|
+
|
276
|
+
def parse_ip_addr_inet6_line(cint, iface, line)
|
277
|
+
if line =~ /inet6 ([a-f0-9\:]+)\/(\d+) scope (\w+)/
|
278
|
+
iface[cint][:addresses] = Mash.new unless iface[cint][:addresses]
|
279
|
+
tmp_addr = $1
|
280
|
+
iface[cint][:addresses][tmp_addr] = {"family" => "inet6", "prefixlen" => $2, "scope" => ($3.eql?("host") ? "Node" : $3.capitalize)}
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
44
284
|
collect_data(:linux) do
|
45
285
|
require 'ipaddr'
|
46
286
|
|
@@ -73,204 +313,19 @@ Ohai.plugin(:Network) do
|
|
73
313
|
:neighbour_attribute => :neighbour_inet6
|
74
314
|
} if ipv6_enabled?
|
75
315
|
|
76
|
-
|
77
|
-
cint = nil
|
78
|
-
so.stdout.lines do |line|
|
79
|
-
if line =~ IPROUTE_INT_REGEX
|
80
|
-
cint = $2
|
81
|
-
iface[cint] = Mash.new
|
82
|
-
if cint =~ /^(\w+)(\d+.*)/
|
83
|
-
iface[cint][:type] = $1
|
84
|
-
iface[cint][:number] = $2
|
85
|
-
end
|
86
|
-
|
87
|
-
if line =~ /mtu (\d+)/
|
88
|
-
iface[cint][:mtu] = $1
|
89
|
-
end
|
90
|
-
|
91
|
-
flags = line.scan(/(UP|BROADCAST|DEBUG|LOOPBACK|POINTTOPOINT|NOTRAILERS|LOWER_UP|NOARP|PROMISC|ALLMULTI|SLAVE|MASTER|MULTICAST|DYNAMIC)/)
|
92
|
-
if flags.length > 1
|
93
|
-
iface[cint][:flags] = flags.flatten.uniq
|
94
|
-
end
|
95
|
-
end
|
96
|
-
if line =~ /link\/(\w+) ([\da-f\:]+) /
|
97
|
-
iface[cint][:encapsulation] = linux_encaps_lookup($1)
|
98
|
-
unless $2 == "00:00:00:00:00:00"
|
99
|
-
iface[cint][:addresses] = Mash.new unless iface[cint][:addresses]
|
100
|
-
iface[cint][:addresses][$2.upcase] = { "family" => "lladdr" }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
if line =~ /inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\/(\d{1,2}))?/
|
104
|
-
tmp_addr, tmp_prefix = $1, $3
|
105
|
-
tmp_prefix ||= "32"
|
106
|
-
original_int = nil
|
107
|
-
|
108
|
-
# Are we a formerly aliased interface?
|
109
|
-
if line =~ /#{cint}:(\d+)$/
|
110
|
-
sub_int = $1
|
111
|
-
alias_int = "#{cint}:#{sub_int}"
|
112
|
-
original_int = cint
|
113
|
-
cint = alias_int
|
114
|
-
end
|
316
|
+
parse_ip_addr(iface)
|
115
317
|
|
116
|
-
|
117
|
-
iface[cint][:addresses] = Mash.new unless iface[cint][:addresses]
|
118
|
-
iface[cint][:addresses][tmp_addr] = { "family" => "inet", "prefixlen" => tmp_prefix }
|
119
|
-
iface[cint][:addresses][tmp_addr][:netmask] = IPAddr.new("255.255.255.255").mask(tmp_prefix.to_i).to_s
|
120
|
-
|
121
|
-
if line =~ /peer (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
|
122
|
-
iface[cint][:addresses][tmp_addr][:peer] = $1
|
123
|
-
end
|
124
|
-
|
125
|
-
if line =~ /brd (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
|
126
|
-
iface[cint][:addresses][tmp_addr][:broadcast] = $1
|
127
|
-
end
|
128
|
-
|
129
|
-
if line =~ /scope (\w+)/
|
130
|
-
iface[cint][:addresses][tmp_addr][:scope] = ($1.eql?("host") ? "Node" : $1.capitalize)
|
131
|
-
end
|
132
|
-
|
133
|
-
# If we found we were an an alias interface, restore cint to its original value
|
134
|
-
cint = original_int unless original_int.nil?
|
135
|
-
end
|
136
|
-
if line =~ /inet6 ([a-f0-9\:]+)\/(\d+) scope (\w+)/
|
137
|
-
iface[cint][:addresses] = Mash.new unless iface[cint][:addresses]
|
138
|
-
tmp_addr = $1
|
139
|
-
iface[cint][:addresses][tmp_addr] = { "family" => "inet6", "prefixlen" => $2, "scope" => ($3.eql?("host") ? "Node" : $3.capitalize) }
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
so = shell_out("ip -d -s link")
|
144
|
-
tmp_int = nil
|
145
|
-
on_rx = true
|
146
|
-
so.stdout.lines do |line|
|
147
|
-
if line =~ IPROUTE_INT_REGEX
|
148
|
-
tmp_int = $2
|
149
|
-
iface[tmp_int] = Mash.new unless iface[tmp_int]
|
150
|
-
net_counters[tmp_int] = Mash.new unless net_counters[tmp_int]
|
151
|
-
end
|
152
|
-
|
153
|
-
if line =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/
|
154
|
-
int = on_rx ? :rx : :tx
|
155
|
-
net_counters[tmp_int][int] = Mash.new unless net_counters[tmp_int][int]
|
156
|
-
net_counters[tmp_int][int][:bytes] = $1
|
157
|
-
net_counters[tmp_int][int][:packets] = $2
|
158
|
-
net_counters[tmp_int][int][:errors] = $3
|
159
|
-
net_counters[tmp_int][int][:drop] = $4
|
160
|
-
if(int == :rx)
|
161
|
-
net_counters[tmp_int][int][:overrun] = $5
|
162
|
-
else
|
163
|
-
net_counters[tmp_int][int][:carrier] = $5
|
164
|
-
net_counters[tmp_int][int][:collisions] = $6
|
165
|
-
end
|
166
|
-
|
167
|
-
on_rx = !on_rx
|
168
|
-
end
|
169
|
-
|
170
|
-
if line =~ /qlen (\d+)/
|
171
|
-
net_counters[tmp_int][:tx] = Mash.new unless net_counters[tmp_int][:tx]
|
172
|
-
net_counters[tmp_int][:tx][:queuelen] = $1
|
173
|
-
end
|
174
|
-
|
175
|
-
if line =~ /vlan id (\d+)/ or line =~ /vlan protocol ([\w\.]+) id (\d+)/
|
176
|
-
if $2
|
177
|
-
tmp_prot = $1
|
178
|
-
tmp_id = $2
|
179
|
-
else
|
180
|
-
tmp_id = $1
|
181
|
-
end
|
182
|
-
iface[tmp_int][:vlan] = Mash.new unless iface[tmp_int][:vlan]
|
183
|
-
iface[tmp_int][:vlan][:id] = tmp_id
|
184
|
-
iface[tmp_int][:vlan][:protocol] = tmp_prot if tmp_prot
|
185
|
-
|
186
|
-
vlan_flags = line.scan(/(REORDER_HDR|GVRP|LOOSE_BINDING)/)
|
187
|
-
if vlan_flags.length > 0
|
188
|
-
iface[tmp_int][:vlan][:flags] = vlan_flags.flatten.uniq
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
if line =~ /state (\w+)/
|
193
|
-
iface[tmp_int]['state'] = $1.downcase
|
194
|
-
end
|
195
|
-
end
|
318
|
+
iface = link_statistics(iface, net_counters)
|
196
319
|
|
197
320
|
families.each do |family|
|
198
321
|
neigh_attr = family[:neighbour_attribute]
|
199
322
|
default_prefix = family[:default_prefix]
|
200
323
|
|
201
|
-
|
202
|
-
so.stdout.lines do |line|
|
203
|
-
if line =~ /^([a-f0-9\:\.]+)\s+dev\s+([^\s]+)\s+lladdr\s+([a-fA-F0-9\:]+)/
|
204
|
-
unless iface[$2]
|
205
|
-
Ohai::Log.warn("neighbour list has entries for unknown interface #{iface[$2]}")
|
206
|
-
next
|
207
|
-
end
|
208
|
-
iface[$2][neigh_attr] = Mash.new unless iface[$2][neigh_attr]
|
209
|
-
iface[$2][neigh_attr][$1] = $3.downcase
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# checking the routing tables
|
214
|
-
# why ?
|
215
|
-
# 1) to set the default gateway and default interfaces attributes
|
216
|
-
# 2) on some occasions, the best way to select node[:ipaddress] is to look at
|
217
|
-
# the routing table source field.
|
218
|
-
# 3) and since we're at it, let's populate some :routes attributes
|
219
|
-
# (going to do that for both inet and inet6 addresses)
|
220
|
-
so = shell_out("ip -o -f #{family[:name]} route show")
|
221
|
-
so.stdout.lines do |line|
|
222
|
-
line.strip!
|
223
|
-
Ohai::Log.debug("Parsing #{line}")
|
224
|
-
if line =~ /\\/
|
225
|
-
parts = line.split('\\')
|
226
|
-
route_dest = parts.shift.strip
|
227
|
-
route_endings = parts
|
228
|
-
elsif line =~ /^([^\s]+)\s(.*)$/
|
229
|
-
route_dest = $1
|
230
|
-
route_endings = [$2]
|
231
|
-
else
|
232
|
-
next
|
233
|
-
end
|
234
|
-
route_endings.each do |route_ending|
|
235
|
-
if route_ending =~ /\bdev\s+([^\s]+)\b/
|
236
|
-
route_int = $1
|
237
|
-
else
|
238
|
-
Ohai::Log.debug("Skipping route entry without a device: '#{line}'")
|
239
|
-
next
|
240
|
-
end
|
241
|
-
|
242
|
-
unless iface[route_int]
|
243
|
-
Ohai::Log.debug("Skipping previously unseen interface from 'ip route show': #{route_int}")
|
244
|
-
next
|
245
|
-
end
|
246
|
-
|
247
|
-
route_entry = Mash.new( :destination => route_dest,
|
248
|
-
:family => family[:name] )
|
249
|
-
%w[via scope metric proto src].each do |k|
|
250
|
-
route_entry[k] = $1 if route_ending =~ /\b#{k}\s+([^\s]+)\b/
|
251
|
-
end
|
324
|
+
iface = extract_neighbors(family, iface, neigh_attr)
|
252
325
|
|
253
|
-
|
254
|
-
# don't report the route entry if the src address isn't set on the node
|
255
|
-
next if route_entry[:src] and not iface[route_int][:addresses].has_key? route_entry[:src]
|
326
|
+
iface = check_routing_table(family, iface)
|
256
327
|
|
257
|
-
|
258
|
-
iface[route_int][:routes] << route_entry
|
259
|
-
end
|
260
|
-
end
|
261
|
-
# now looking at the routes to set the default attributes
|
262
|
-
# for information, default routes can be of this form :
|
263
|
-
# - default via 10.0.2.4 dev br0
|
264
|
-
# - default dev br0 scope link
|
265
|
-
# - default via 10.0.3.1 dev eth1 src 10.0.3.2 metric 10
|
266
|
-
# - default via 10.0.4.1 dev eth2 src 10.0.4.2 metric 20
|
267
|
-
|
268
|
-
# using a temporary var to hold routes and their interface name
|
269
|
-
routes = iface.collect do |i,iv|
|
270
|
-
iv[:routes].collect do |r|
|
271
|
-
r.merge(:dev=>i) if r[:family] == family[:name]
|
272
|
-
end.compact if iv[:routes]
|
273
|
-
end.compact.flatten
|
328
|
+
routes = parse_routes(family, iface)
|
274
329
|
|
275
330
|
# using a temporary var to hold the default route
|
276
331
|
# in case there are more than 1 default route, sort it by its metric
|