ohai 15.7.4 → 16.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -5
- data/lib/ohai/common/dmi.rb +13 -5
- data/lib/ohai/config.rb +1 -1
- data/lib/ohai/mash.rb +21 -201
- data/lib/ohai/mixin/azure_metadata.rb +70 -14
- data/lib/ohai/mixin/ec2_metadata.rb +1 -1
- data/lib/ohai/mixin/gce_metadata.rb +2 -2
- data/lib/ohai/plugins/c.rb +2 -2
- data/lib/ohai/plugins/cpu.rb +1 -1
- data/lib/ohai/plugins/docker.rb +1 -1
- data/lib/ohai/plugins/ec2.rb +1 -1
- data/lib/ohai/plugins/eucalyptus.rb +2 -2
- data/lib/ohai/plugins/filesystem.rb +9 -43
- data/lib/ohai/plugins/{linux/fips.rb → fips.rb} +1 -1
- data/lib/ohai/plugins/gce.rb +1 -1
- data/lib/ohai/plugins/kernel.rb +8 -7
- data/lib/ohai/plugins/linux/interrupts.rb +83 -0
- data/lib/ohai/plugins/linux/ipc.rb +51 -0
- data/lib/ohai/plugins/linux/network.rb +90 -0
- data/lib/ohai/plugins/linux/selinux.rb +68 -0
- data/lib/ohai/plugins/linux/virtualization.rb +2 -2
- data/lib/ohai/plugins/openstack.rb +3 -3
- data/lib/ohai/plugins/packages.rb +1 -1
- data/lib/ohai/plugins/rackspace.rb +1 -1
- data/lib/ohai/plugins/shard.rb +11 -1
- data/lib/ohai/plugins/virtualbox.rb +2 -2
- data/lib/ohai/plugins/windows/dmi.rb +94 -0
- data/lib/ohai/plugins/windows/system_enclosure.rb +3 -5
- data/lib/ohai/version.rb +1 -1
- data/ohai.gemspec +2 -1
- metadata +29 -6
- data/lib/ohai/plugins/windows/fips.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b01a821d5ffa3a329d434aa798b7e6396cd38329a5aed167cc9fa5d790e1e40b
|
4
|
+
data.tar.gz: 832b596c834b379cd996bdad0d097e38684be9e175fcd50d59fce4cebc04ec19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad4cbe610a98f04f3525b4d025e7053712dbe7c9218d38e506dd6beb031ded0e5d969ede709a0b2fdf95cea747905d18b021eea7d29db25271f24792c439bc4b
|
7
|
+
data.tar.gz: 5359aff83afbfceb44068bc838ce4a8153e863a6684319a65b1164e48169e6ba406e38e537c4686d1102e4bfc29e1f783fe4bdc216654fd0d19af53d8c5fbbf0
|
data/Gemfile
CHANGED
@@ -13,10 +13,6 @@ group :development do
|
|
13
13
|
gem "ipaddr_extensions"
|
14
14
|
end
|
15
15
|
|
16
|
-
group :ci do
|
17
|
-
gem "rspec_junit_formatter"
|
18
|
-
end
|
19
|
-
|
20
16
|
group :docs do
|
21
17
|
gem "yard"
|
22
18
|
gem "redcarpet"
|
@@ -26,6 +22,6 @@ end
|
|
26
22
|
group :debug do
|
27
23
|
gem "pry"
|
28
24
|
gem "pry-byebug"
|
29
|
-
gem "pry-stack_explorer"
|
25
|
+
gem "pry-stack_explorer", "~> 0.4.0" # pin until we drop ruby < 2.6
|
30
26
|
gem "rb-readline"
|
31
27
|
end
|
data/lib/ohai/common/dmi.rb
CHANGED
@@ -111,6 +111,15 @@ module Ohai
|
|
111
111
|
id
|
112
112
|
end
|
113
113
|
|
114
|
+
SKIPPED_CONVENIENCE_KEYS = %w{
|
115
|
+
application_identifier
|
116
|
+
caption
|
117
|
+
creation_class_name
|
118
|
+
size
|
119
|
+
system_creation_class_name
|
120
|
+
record_id
|
121
|
+
}.freeze
|
122
|
+
|
114
123
|
# create simplified convenience access keys for each record type
|
115
124
|
# for single occurrences of one type, copy to top level all fields and values
|
116
125
|
# for multiple occurrences of same type, copy to top level all fields and values that are common to all records
|
@@ -122,13 +131,12 @@ module Ohai
|
|
122
131
|
|
123
132
|
records[:all_records].each do |record|
|
124
133
|
record.each do |field, value|
|
125
|
-
next
|
126
|
-
next if field.to_s == "application_identifier"
|
127
|
-
next if field.to_s == "size"
|
128
|
-
next if field.to_s == "record_id"
|
134
|
+
next unless value.is_a?(String)
|
129
135
|
|
130
136
|
translated = field.downcase.gsub(/[^a-z0-9]/, "_")
|
131
|
-
|
137
|
+
next if SKIPPED_CONVENIENCE_KEYS.include?(translated.to_s)
|
138
|
+
|
139
|
+
value = value.strip
|
132
140
|
if in_common.key?(translated)
|
133
141
|
in_common[translated] = nil unless in_common[translated] == value
|
134
142
|
else
|
data/lib/ohai/config.rb
CHANGED
@@ -39,7 +39,7 @@ module Ohai
|
|
39
39
|
# causes all optional plugins to be run.
|
40
40
|
default :run_all_plugins, false
|
41
41
|
# optional plugins are the set of plugins that are marked optional but you wish to run.
|
42
|
-
default
|
42
|
+
default(:optional_plugins, []).writes_value { |arr| arr.map(&:to_sym) }
|
43
43
|
default :shellout_timeout, 30
|
44
44
|
end
|
45
45
|
end
|
data/lib/ohai/mash.rb
CHANGED
@@ -1,201 +1,21 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
#
|
21
|
-
|
22
|
-
# ---
|
23
|
-
# ---
|
24
|
-
|
25
|
-
# Some portions of blank.rb and mash.rb are verbatim copies of software
|
26
|
-
# licensed under the MIT license. That license is included below:
|
27
|
-
|
28
|
-
# Copyright (c) 2005-2008 David Heinemeier Hansson
|
29
|
-
|
30
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
31
|
-
# a copy of this software and associated documentation files (the
|
32
|
-
# "Software"), to deal in the Software without restriction, including
|
33
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
34
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
35
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
36
|
-
# the following conditions:
|
37
|
-
|
38
|
-
# The above copyright notice and this permission notice shall be
|
39
|
-
# included in all copies or substantial portions of the Software.
|
40
|
-
|
41
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
42
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
43
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
44
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
45
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
46
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
47
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
48
|
-
|
49
|
-
# This class has dubious semantics and we only have it so that people can write
|
50
|
-
# params[:key] instead of params['key'].
|
51
|
-
class Mash < Hash
|
52
|
-
|
53
|
-
# @param constructor [Object] The default value for the mash.
|
54
|
-
# If constructor is a Hash, a new mash will be created based on the keys of the hash and
|
55
|
-
# no default value will be set.
|
56
|
-
def initialize(constructor = {})
|
57
|
-
if constructor.is_a?(Hash)
|
58
|
-
super()
|
59
|
-
update(constructor)
|
60
|
-
else
|
61
|
-
super(constructor)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# @param key [Object] The default value for the mash.
|
66
|
-
# If key is a Symbol and it is a key in the mash, then the default value will be set to
|
67
|
-
# the value matching the key.
|
68
|
-
def default(key = nil)
|
69
|
-
if key.is_a?(Symbol) && include?(key = key.to_s)
|
70
|
-
self[key]
|
71
|
-
else
|
72
|
-
super
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
77
|
-
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
78
|
-
|
79
|
-
# @param key [Object] The key to set.
|
80
|
-
# @param value [Object] The value to set the key to.
|
81
|
-
#
|
82
|
-
# @see Mash#convert_key
|
83
|
-
# @see Mash#convert_value
|
84
|
-
def []=(key, value)
|
85
|
-
regular_writer(convert_key(key), convert_value(value))
|
86
|
-
end
|
87
|
-
|
88
|
-
# @param other_hash [Hash]
|
89
|
-
# A hash to update values in the mash with. The keys and the values will be
|
90
|
-
# converted to Mash format.
|
91
|
-
#
|
92
|
-
# @return [Mash] The updated mash.
|
93
|
-
def update(other_hash)
|
94
|
-
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
95
|
-
self
|
96
|
-
end
|
97
|
-
|
98
|
-
alias_method :merge!, :update
|
99
|
-
|
100
|
-
# @param key [Object] The key to check for. This will be run through convert_key.
|
101
|
-
#
|
102
|
-
# @return [Boolean] True if the key exists in the mash.
|
103
|
-
def key?(key)
|
104
|
-
super(convert_key(key))
|
105
|
-
end
|
106
|
-
|
107
|
-
# def include? def has_key? def member?
|
108
|
-
alias_method :include?, :key?
|
109
|
-
alias_method :has_key?, :key?
|
110
|
-
alias_method :member?, :key?
|
111
|
-
|
112
|
-
# @param key [Object] The key to fetch. This will be run through convert_key.
|
113
|
-
# @param extras [Array] Default value.
|
114
|
-
#
|
115
|
-
# @return [Object] The value at key or the default value.
|
116
|
-
def fetch(key, *extras)
|
117
|
-
super(convert_key(key), *extras)
|
118
|
-
end
|
119
|
-
|
120
|
-
# @param indices [Array] The keys to retrieve values for. These will be run through +convert_key+.
|
121
|
-
#
|
122
|
-
# @return [Array] The values at each of the provided keys
|
123
|
-
def values_at(*indices)
|
124
|
-
indices.collect { |key| self[convert_key(key)] }
|
125
|
-
end
|
126
|
-
|
127
|
-
# @param hash [Hash] The hash to merge with the mash.
|
128
|
-
#
|
129
|
-
# @return [Mash] A new mash with the hash values merged in.
|
130
|
-
def merge(hash)
|
131
|
-
dup.update(hash)
|
132
|
-
end
|
133
|
-
|
134
|
-
# @param key [Object] The key to delete from the mash.
|
135
|
-
def delete(key)
|
136
|
-
super(convert_key(key))
|
137
|
-
end
|
138
|
-
|
139
|
-
# @param keys [Array<String, Symbol>] The mash keys to exclude.
|
140
|
-
#
|
141
|
-
# @return [Mash] A new mash without the selected keys.
|
142
|
-
#
|
143
|
-
# @example
|
144
|
-
# { :one => 1, :two => 2, :three => 3 }.except(:one)
|
145
|
-
# #=> { "two" => 2, "three" => 3 }
|
146
|
-
def except(*keys)
|
147
|
-
super(*keys.map { |k| convert_key(k) })
|
148
|
-
end
|
149
|
-
|
150
|
-
# Used to provide the same interface as Hash.
|
151
|
-
#
|
152
|
-
# @return [Mash] This mash unchanged.
|
153
|
-
def stringify_keys!; self end
|
154
|
-
|
155
|
-
# @return [Hash] The mash as a Hash with symbolized keys.
|
156
|
-
def symbolize_keys
|
157
|
-
h = Hash.new(default)
|
158
|
-
each { |key, val| h[key.to_sym] = val }
|
159
|
-
h
|
160
|
-
end
|
161
|
-
|
162
|
-
# @return [Hash] The mash as a Hash with string keys.
|
163
|
-
def to_hash
|
164
|
-
Hash.new(default).merge(self)
|
165
|
-
end
|
166
|
-
|
167
|
-
# Convert a Hash into a Mash. The input Hash's default value is maintained
|
168
|
-
# @return [Mash]
|
169
|
-
def self.from_hash(hash)
|
170
|
-
mash = Mash.new(hash)
|
171
|
-
mash.default = hash.default
|
172
|
-
mash
|
173
|
-
end
|
174
|
-
|
175
|
-
protected
|
176
|
-
|
177
|
-
# @param key [Object] The key to convert.
|
178
|
-
# @return [Object] The converted key. If the key was a symbol, it will be converted to a string.
|
179
|
-
#
|
180
|
-
# @api private
|
181
|
-
def convert_key(key)
|
182
|
-
key.is_a?(Symbol) ? key.to_s : key
|
183
|
-
end
|
184
|
-
|
185
|
-
# @param value [Object] The value to convert.
|
186
|
-
#
|
187
|
-
# @return [Object]
|
188
|
-
# The converted value. A Hash or an Array of hashes, will be converted to
|
189
|
-
# their Mash equivalents.
|
190
|
-
#
|
191
|
-
# @api private
|
192
|
-
def convert_value(value)
|
193
|
-
if value.class == Hash
|
194
|
-
Mash.from_hash(value)
|
195
|
-
elsif value.is_a?(Array)
|
196
|
-
value.collect { |e| convert_value(e) }
|
197
|
-
else
|
198
|
-
value
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 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 "chef-utils/mash" unless defined?(ChefUtils::Mash)
|
19
|
+
|
20
|
+
# For historical reasons we inject Mash directly into the top level class namespace
|
21
|
+
Mash = ChefUtils::Mash unless defined?(Mash)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Tim Smith (<tsmith@chef.io>)
|
3
|
-
# Copyright::
|
3
|
+
# Copyright:: 2017-2020 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -19,30 +19,86 @@ require "net/http" unless defined?(Net::HTTP)
|
|
19
19
|
|
20
20
|
module Ohai
|
21
21
|
module Mixin
|
22
|
+
#
|
23
|
+
# This code parses the Azure Instance Metadata API to provide details
|
24
|
+
# of the running instance.
|
25
|
+
#
|
26
|
+
# The code probes the instance metadata endpoint for
|
27
|
+
# available versions, determines the most advanced version known to
|
28
|
+
# work and executes the metadata retrieval using that version.
|
29
|
+
#
|
30
|
+
# If no compatible version is found, an empty hash is returned.
|
31
|
+
#
|
22
32
|
module AzureMetadata
|
23
33
|
|
24
34
|
AZURE_METADATA_ADDR ||= "169.254.169.254".freeze
|
25
|
-
AZURE_METADATA_URL ||= "/metadata/instance?api-version=2017-08-01".freeze
|
26
35
|
|
27
|
-
#
|
36
|
+
# it's important that the newer versions are at the end of this array so we can skip sorting it
|
37
|
+
AZURE_SUPPORTED_VERSIONS ||= %w{ 2017-04-02 2017-08-01 2017-12-01 2018-02-01 2018-04-02
|
38
|
+
2018-10-01 2019-02-01 2019-03-11 2019-04-30 2019-06-01
|
39
|
+
2019-06-04 2019-08-01 2019-08-15 2019-11-01 }.freeze
|
40
|
+
|
41
|
+
def best_api_version
|
42
|
+
@api_version ||= begin
|
43
|
+
logger.trace("Mixin AzureMetadata: Fetching http://#{AZURE_METADATA_ADDR}/metadata/instance to determine the latest supported metadata release")
|
44
|
+
response = http_get("/metadata/instance")
|
45
|
+
if response.code == "404"
|
46
|
+
logger.trace("Mixin AzureMetadata: Received HTTP 404 from metadata server while determining API version, assuming #{AZURE_SUPPORTED_VERSIONS.last}")
|
47
|
+
return AZURE_SUPPORTED_VERSIONS.last
|
48
|
+
elsif response.code != "400" # 400 is actually what we want
|
49
|
+
raise "Mixin AzureMetadata: Unable to determine Azure metadata version (returned #{response.code} response)"
|
50
|
+
end
|
51
|
+
|
52
|
+
# azure returns a list of the 3 latest versions it supports
|
53
|
+
versions = parse_json(response.body).fetch("newest-versions", [])
|
54
|
+
versions.sort!
|
55
|
+
|
56
|
+
until versions.empty? || AZURE_SUPPORTED_VERSIONS.include?(versions.last)
|
57
|
+
pv = versions.pop
|
58
|
+
logger.trace("Mixin AzureMetadata: Azure metadata version #{pv} is not present in the versions provided by the Azure Instance Metadata service")
|
59
|
+
end
|
60
|
+
|
61
|
+
if versions.empty?
|
62
|
+
logger.debug "Mixin AzureMetadata: The short list of supported versions provided by Azure Instance Metadata service doesn't match any known versions to Ohai. Using the latest supported release known to Ohai instead: #{AZURE_SUPPORTED_VERSIONS.last}"
|
63
|
+
return AZURE_SUPPORTED_VERSIONS.last
|
64
|
+
end
|
65
|
+
|
66
|
+
logger.trace("Mixin AzureMetadata: Latest supported Azure metadata version: #{versions.last}")
|
67
|
+
versions.last
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# fetch the meta content with a timeout and the required header and a read timeout of 6s
|
72
|
+
#
|
73
|
+
# @param [String] the relative uri to fetch from the Azure Metadata Service URL
|
74
|
+
#
|
75
|
+
# @return [Net::HTTP]
|
28
76
|
def http_get(uri)
|
29
77
|
conn = Net::HTTP.start(AZURE_METADATA_ADDR)
|
30
78
|
conn.read_timeout = 6
|
31
79
|
conn.get(uri, { "Metadata" => "true" })
|
32
80
|
end
|
33
81
|
|
34
|
-
|
35
|
-
|
36
|
-
|
82
|
+
# parse JSON data from a String to a Hash
|
83
|
+
#
|
84
|
+
# @param [String] response_body json as string to parse
|
85
|
+
#
|
86
|
+
# @return [Hash]
|
87
|
+
def parse_json(response_body)
|
88
|
+
data = String(response_body)
|
89
|
+
parser = FFI_Yajl::Parser.new
|
90
|
+
parser.parse(data)
|
91
|
+
rescue FFI_Yajl::ParseError
|
92
|
+
logger.warn("Mixin AzureMetadata: Metadata response is NOT valid JSON")
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def fetch_metadata(api_version = nil)
|
97
|
+
metadata_url = "/metadata/instance?api-version=#{best_api_version}"
|
98
|
+
logger.trace("Mixin AzureMetadata: Fetching metadata from host #{AZURE_METADATA_ADDR} at #{metadata_url}")
|
99
|
+
response = http_get(metadata_url)
|
37
100
|
if response.code == "200"
|
38
|
-
|
39
|
-
data = StringIO.new(response.body)
|
40
|
-
parser = FFI_Yajl::Parser.new
|
41
|
-
parser.parse(data)
|
42
|
-
rescue FFI_Yajl::ParseError
|
43
|
-
logger.warn("Mixin AzureMetadata: Metadata response is NOT valid JSON")
|
44
|
-
nil
|
45
|
-
end
|
101
|
+
parse_json(response.body)
|
46
102
|
else
|
47
103
|
logger.warn("Mixin AzureMetadata: Received response code #{response.code} requesting metadata")
|
48
104
|
nil
|
@@ -160,7 +160,7 @@ module Ohai
|
|
160
160
|
if key[-1..-1] != "/"
|
161
161
|
retr_meta = metadata_get("#{id}#{key}", api_version)
|
162
162
|
data = retr_meta ? retr_meta : ""
|
163
|
-
json =
|
163
|
+
json = String(data)
|
164
164
|
parser = FFI_Yajl::Parser.new
|
165
165
|
metadata[metadata_key(key)] = parser.parse(json)
|
166
166
|
elsif not key.eql?("/")
|
@@ -39,7 +39,7 @@ module Ohai
|
|
39
39
|
return nil unless response.code == "200"
|
40
40
|
|
41
41
|
if json?(response.body)
|
42
|
-
data =
|
42
|
+
data = String(response.body)
|
43
43
|
parser = FFI_Yajl::Parser.new
|
44
44
|
parser.parse(data)
|
45
45
|
elsif has_trailing_slash?(id) || (id == "")
|
@@ -57,7 +57,7 @@ module Ohai
|
|
57
57
|
#
|
58
58
|
# @return [Boolean] is the data JSON or not?
|
59
59
|
def json?(data)
|
60
|
-
data =
|
60
|
+
data = String(data)
|
61
61
|
parser = FFI_Yajl::Parser.new
|
62
62
|
begin
|
63
63
|
parser.parse(data)
|
data/lib/ohai/plugins/c.rb
CHANGED
@@ -36,10 +36,10 @@ Ohai.plugin(:C) do
|
|
36
36
|
so = shell_out("/usr/bin/xcode-select -p")
|
37
37
|
if so.exitstatus == 0
|
38
38
|
logger.trace("Plugin C: Xcode Command Line Tools found.")
|
39
|
-
|
39
|
+
true
|
40
40
|
else
|
41
41
|
logger.trace("Plugin C: Xcode Command Line Tools not found.")
|
42
|
-
|
42
|
+
false
|
43
43
|
end
|
44
44
|
rescue Ohai::Exceptions::Exec
|
45
45
|
logger.trace("Plugin C: xcode-select binary could not be found. Skipping data.")
|
data/lib/ohai/plugins/cpu.rb
CHANGED
@@ -364,7 +364,7 @@ Ohai.plugin(:CPU) do
|
|
364
364
|
cpu["cpustates"][value] += 1
|
365
365
|
when /core_id/
|
366
366
|
cpu[instance]["core_id"] = value
|
367
|
-
|
367
|
+
# Detect hyperthreading/multithreading
|
368
368
|
cpucores.push(value) if cpucores.index(value).nil?
|
369
369
|
when /family|fpu_type|model|stepping|vendor_id/
|
370
370
|
cpu[instance][key] = value
|