ohai 18.0.26 → 18.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +28 -28
  3. data/LICENSE +201 -201
  4. data/bin/ohai +25 -25
  5. data/lib/ohai/application.rb +189 -189
  6. data/lib/ohai/common/dmi.rb +167 -167
  7. data/lib/ohai/config.rb +51 -51
  8. data/lib/ohai/dsl/plugin/versionvii.rb +203 -203
  9. data/lib/ohai/dsl/plugin.rb +232 -232
  10. data/lib/ohai/dsl.rb +22 -22
  11. data/lib/ohai/exception.rb +36 -36
  12. data/lib/ohai/hints.rb +68 -68
  13. data/lib/ohai/loader.rb +178 -178
  14. data/lib/ohai/log.rb +34 -34
  15. data/lib/ohai/mash.rb +22 -22
  16. data/lib/ohai/mixin/alibaba_metadata.rb +86 -86
  17. data/lib/ohai/mixin/azure_metadata.rb +111 -111
  18. data/lib/ohai/mixin/chef_utils_wiring.rb +52 -52
  19. data/lib/ohai/mixin/command.rb +4 -4
  20. data/lib/ohai/mixin/constant_helper.rb +55 -55
  21. data/lib/ohai/mixin/dmi_decode.rb +54 -54
  22. data/lib/ohai/mixin/do_metadata.rb +48 -48
  23. data/lib/ohai/mixin/ec2_metadata.rb +256 -256
  24. data/lib/ohai/mixin/gce_metadata.rb +83 -83
  25. data/lib/ohai/mixin/http_helper.rb +64 -64
  26. data/lib/ohai/mixin/network_helper.rb +65 -65
  27. data/lib/ohai/mixin/oci_metadata.rb +69 -0
  28. data/lib/ohai/mixin/os.rb +128 -128
  29. data/lib/ohai/mixin/scaleway_metadata.rb +51 -51
  30. data/lib/ohai/mixin/seconds_to_human.rb +52 -52
  31. data/lib/ohai/mixin/shell_out.rb +51 -51
  32. data/lib/ohai/mixin/softlayer_metadata.rb +74 -74
  33. data/lib/ohai/mixin/string.rb +31 -31
  34. data/lib/ohai/mixin/train_helpers.rb +36 -36
  35. data/lib/ohai/mixin/which.rb +39 -39
  36. data/lib/ohai/plugin_config.rb +47 -47
  37. data/lib/ohai/plugins/aix/kernel.rb +50 -50
  38. data/lib/ohai/plugins/aix/memory.rb +37 -37
  39. data/lib/ohai/plugins/aix/network.rb +142 -142
  40. data/lib/ohai/plugins/aix/platform.rb +30 -30
  41. data/lib/ohai/plugins/aix/uptime.rb +54 -54
  42. data/lib/ohai/plugins/aix/virtualization.rb +154 -154
  43. data/lib/ohai/plugins/alibaba.rb +72 -72
  44. data/lib/ohai/plugins/azure.rb +154 -154
  45. data/lib/ohai/plugins/bsd/virtualization.rb +121 -121
  46. data/lib/ohai/plugins/c.rb +178 -178
  47. data/lib/ohai/plugins/chef.rb +50 -50
  48. data/lib/ohai/plugins/cloud.rb +379 -357
  49. data/lib/ohai/plugins/command.rb +26 -26
  50. data/lib/ohai/plugins/cpu.rb +635 -635
  51. data/lib/ohai/plugins/darwin/hardware.rb +99 -99
  52. data/lib/ohai/plugins/darwin/memory.rb +62 -62
  53. data/lib/ohai/plugins/darwin/network.rb +207 -207
  54. data/lib/ohai/plugins/darwin/platform.rb +38 -38
  55. data/lib/ohai/plugins/darwin/virtualization.rb +90 -93
  56. data/lib/ohai/plugins/digital_ocean.rb +67 -67
  57. data/lib/ohai/plugins/dmi.rb +134 -134
  58. data/lib/ohai/plugins/docker.rb +58 -58
  59. data/lib/ohai/plugins/dragonflybsd/memory.rb +60 -60
  60. data/lib/ohai/plugins/dragonflybsd/network.rb +128 -128
  61. data/lib/ohai/plugins/dragonflybsd/platform.rb +28 -28
  62. data/lib/ohai/plugins/ec2.rb +148 -148
  63. data/lib/ohai/plugins/elixir.rb +36 -36
  64. data/lib/ohai/plugins/erlang.rb +60 -60
  65. data/lib/ohai/plugins/eucalyptus.rb +86 -86
  66. data/lib/ohai/plugins/filesystem.rb +751 -751
  67. data/lib/ohai/plugins/fips.rb +36 -36
  68. data/lib/ohai/plugins/freebsd/memory.rb +60 -60
  69. data/lib/ohai/plugins/freebsd/network.rb +128 -128
  70. data/lib/ohai/plugins/freebsd/platform.rb +28 -28
  71. data/lib/ohai/plugins/gce.rb +89 -89
  72. data/lib/ohai/plugins/go.rb +34 -34
  73. data/lib/ohai/plugins/groovy.rb +38 -38
  74. data/lib/ohai/plugins/grub2.rb +40 -40
  75. data/lib/ohai/plugins/habitat.rb +73 -73
  76. data/lib/ohai/plugins/haskell.rb +96 -96
  77. data/lib/ohai/plugins/hostname.rb +133 -133
  78. data/lib/ohai/plugins/init_package.rb +26 -26
  79. data/lib/ohai/plugins/java.rb +78 -78
  80. data/lib/ohai/plugins/kernel.rb +292 -292
  81. data/lib/ohai/plugins/keys.rb +27 -27
  82. data/lib/ohai/plugins/languages.rb +26 -26
  83. data/lib/ohai/plugins/libvirt.rb +114 -114
  84. data/lib/ohai/plugins/linode.rb +73 -73
  85. data/lib/ohai/plugins/linux/block_device.rb +48 -48
  86. data/lib/ohai/plugins/linux/hostnamectl.rb +34 -34
  87. data/lib/ohai/plugins/linux/interrupts.rb +84 -84
  88. data/lib/ohai/plugins/linux/ipc.rb +52 -52
  89. data/lib/ohai/plugins/linux/livepatch.rb +38 -38
  90. data/lib/ohai/plugins/linux/lsb.rb +46 -46
  91. data/lib/ohai/plugins/linux/lspci.rb +76 -76
  92. data/lib/ohai/plugins/linux/machineid.rb +36 -36
  93. data/lib/ohai/plugins/linux/mdadm.rb +120 -120
  94. data/lib/ohai/plugins/linux/memory.rb +106 -106
  95. data/lib/ohai/plugins/linux/network.rb +879 -879
  96. data/lib/ohai/plugins/linux/os_release.rb +38 -38
  97. data/lib/ohai/plugins/linux/platform.rb +314 -314
  98. data/lib/ohai/plugins/linux/selinux.rb +69 -69
  99. data/lib/ohai/plugins/linux/sessions.rb +54 -54
  100. data/lib/ohai/plugins/linux/sysctl.rb +39 -39
  101. data/lib/ohai/plugins/linux/systemd_paths.rb +36 -36
  102. data/lib/ohai/plugins/linux/tc.rb +61 -61
  103. data/lib/ohai/plugins/linux/virtualization.rb +300 -300
  104. data/lib/ohai/plugins/lua.rb +39 -39
  105. data/lib/ohai/plugins/mono.rb +50 -50
  106. data/lib/ohai/plugins/netbsd/memory.rb +99 -99
  107. data/lib/ohai/plugins/netbsd/network.rb +122 -122
  108. data/lib/ohai/plugins/netbsd/platform.rb +28 -28
  109. data/lib/ohai/plugins/network.rb +186 -186
  110. data/lib/ohai/plugins/nodejs.rb +40 -40
  111. data/lib/ohai/plugins/oci.rb +94 -0
  112. data/lib/ohai/plugins/ohai.rb +29 -29
  113. data/lib/ohai/plugins/ohai_time.rb +26 -26
  114. data/lib/ohai/plugins/openbsd/memory.rb +99 -99
  115. data/lib/ohai/plugins/openbsd/network.rb +122 -122
  116. data/lib/ohai/plugins/openbsd/platform.rb +28 -28
  117. data/lib/ohai/plugins/openstack.rb +84 -84
  118. data/lib/ohai/plugins/os.rb +55 -55
  119. data/lib/ohai/plugins/packages.rb +234 -234
  120. data/lib/ohai/plugins/passwd.rb +104 -104
  121. data/lib/ohai/plugins/perl.rb +45 -45
  122. data/lib/ohai/plugins/php.rb +52 -52
  123. data/lib/ohai/plugins/platform.rb +29 -29
  124. data/lib/ohai/plugins/powershell.rb +82 -82
  125. data/lib/ohai/plugins/ps.rb +35 -35
  126. data/lib/ohai/plugins/python.rb +43 -43
  127. data/lib/ohai/plugins/rackspace.rb +177 -177
  128. data/lib/ohai/plugins/root_group.rb +41 -41
  129. data/lib/ohai/plugins/rpm.rb +121 -121
  130. data/lib/ohai/plugins/ruby.rb +66 -66
  131. data/lib/ohai/plugins/rust.rb +34 -34
  132. data/lib/ohai/plugins/scala.rb +38 -38
  133. data/lib/ohai/plugins/scaleway.rb +58 -58
  134. data/lib/ohai/plugins/scsi.rb +52 -52
  135. data/lib/ohai/plugins/shard.rb +142 -142
  136. data/lib/ohai/plugins/shells.rb +32 -32
  137. data/lib/ohai/plugins/softlayer.rb +48 -48
  138. data/lib/ohai/plugins/solaris2/dmi.rb +191 -191
  139. data/lib/ohai/plugins/solaris2/memory.rb +32 -32
  140. data/lib/ohai/plugins/solaris2/network.rb +192 -192
  141. data/lib/ohai/plugins/solaris2/platform.rb +58 -58
  142. data/lib/ohai/plugins/solaris2/virtualization.rb +90 -90
  143. data/lib/ohai/plugins/ssh_host_key.rb +84 -84
  144. data/lib/ohai/plugins/sysconf.rb +46 -46
  145. data/lib/ohai/plugins/timezone.rb +45 -25
  146. data/lib/ohai/plugins/train.rb +35 -35
  147. data/lib/ohai/plugins/uptime.rb +95 -95
  148. data/lib/ohai/plugins/virtualbox.rb +197 -197
  149. data/lib/ohai/plugins/vmware.rb +109 -94
  150. data/lib/ohai/plugins/windows/dmi.rb +95 -95
  151. data/lib/ohai/plugins/windows/drivers.rb +52 -52
  152. data/lib/ohai/plugins/windows/memory.rb +39 -39
  153. data/lib/ohai/plugins/windows/network.rb +222 -222
  154. data/lib/ohai/plugins/windows/platform.rb +34 -34
  155. data/lib/ohai/plugins/windows/system_enclosure.rb +29 -29
  156. data/lib/ohai/plugins/windows/virtualization.rb +45 -45
  157. data/lib/ohai/plugins/zpools.rb +94 -94
  158. data/lib/ohai/provides_map.rb +208 -208
  159. data/lib/ohai/runner.rb +128 -128
  160. data/lib/ohai/system.rb +258 -258
  161. data/lib/ohai/train_transport.rb +29 -29
  162. data/lib/ohai/util/file_helper.rb +6 -6
  163. data/lib/ohai/util/ip_helper.rb +56 -56
  164. data/lib/ohai/util/win32.rb +47 -47
  165. data/lib/ohai/version.rb +23 -23
  166. data/lib/ohai.rb +23 -23
  167. data/ohai.gemspec +35 -35
  168. metadata +5 -3
@@ -1,635 +1,635 @@
1
- # frozen_string_literal: true
2
- #
3
- # Author:: Adam Jacob (<adam@chef.io>)
4
- # Author:: Bryan McLellan (btm@loftninjas.org)
5
- # Author:: Tim Smith (tsmith@chef.io)
6
- # Author:: Mathieu Sauve-Frankel <msf@kisoku.net>
7
- # Author:: Nathan L Smith (<nlloyds@gmail.com>)
8
- # Author:: Joshua Timberman <joshua@chef.io>
9
- # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
10
- # Author:: Isa Farnik (<isa@chef.io>)
11
- # Author:: Doug MacEachern <dougm@vmware.com>
12
- # Author:: Lance Albertson <lance@osuosl.org>
13
- # Copyright:: Copyright (c) Chef Software Inc.
14
- # License:: Apache License, Version 2.0
15
- #
16
- # Licensed under the Apache License, Version 2.0 (the "License");
17
- # you may not use this file except in compliance with the License.
18
- # You may obtain a copy of the License at
19
- #
20
- # http://www.apache.org/licenses/LICENSE-2.0
21
- #
22
- # Unless required by applicable law or agreed to in writing, software
23
- # distributed under the License is distributed on an "AS IS" BASIS,
24
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
- # See the License for the specific language governing permissions and
26
- # limitations under the License.
27
- #
28
-
29
- Ohai.plugin(:CPU) do
30
- provides "cpu"
31
-
32
- def parse_bsd_dmesg(&block)
33
- cpuinfo = Mash.new
34
- cpuinfo["flags"] = []
35
- file_open("/var/run/dmesg.boot").each do |line|
36
- case line
37
- when /CPU:\s+(.+) \(([\d.]+).+\)/
38
- cpuinfo["model_name"] = $1
39
- cpuinfo["mhz"] = $2
40
- when /Features=.+<(.+)>/, /Features2=[a-f\dx]+<(.+)>/
41
- cpuinfo["flags"].concat($1.downcase.split(","))
42
- # Features2=0x80000001<SSE3,<b31>>
43
- else
44
- yield(cpuinfo, line)
45
- end
46
- end
47
- cpuinfo
48
- end
49
-
50
- # Convert a string that looks like range of CPUs to an array
51
- # Given the following range: 1-7
52
- # Convert it into an array: [1, 2, 3, 4, 5, 6, 7]
53
- def range_str_to_a(range)
54
- range.split(",").each_with_object([]) do |cpu, arr|
55
- if /\d+-\d+/.match?(cpu.to_s)
56
- arr << Range.new(*cpu.split("-").map(&:to_i)).to_a
57
- else
58
- arr << cpu.to_i
59
- end
60
- end.flatten
61
- end
62
-
63
- def parse_lscpu(cpu_info)
64
- lscpu_info = Mash.new
65
- begin
66
- so = shell_out("lscpu")
67
- cpu_cores = shell_out("lscpu -p=CPU,CORE,SOCKET")
68
- if so.exitstatus == 0 && cpu_cores.exitstatus == 0
69
- lscpu_info[:numa_node_cpus] = Mash.new
70
- lscpu_info[:vulnerability] = Mash.new
71
- so.stdout.each_line do |line|
72
- case line
73
- when /^Architecture:\s+(.+)/
74
- lscpu_info[:architecture] = $1.to_s
75
- when /^CPU op-mode\(s\):\s+(.+)/
76
- lscpu_info[:cpu_opmodes] = $1.split(", ")
77
- when /^Byte Order:\s+(.+)/
78
- lscpu_info[:byte_order] = $1.downcase
79
- when /^Address sizes:\s+(.+)/
80
- lscpu_info[:address_sizes] = $1.split(", ")
81
- when /^CPU\(s\):\s+(.+)/
82
- lscpu_info[:cpus] = $1.to_i
83
- when /^On-line CPU\(s\) list:\s+(.+)/
84
- cpu_range = range_str_to_a($1)
85
- if cpu_range == [0]
86
- lscpu_info[:cpus_online] = 0
87
- else
88
- lscpu_info[:cpus_online] = cpu_range.length
89
- end
90
- when /^Off-line CPU\(s\) list:\s+(.+)/
91
- cpu_range = range_str_to_a($1)
92
- if cpu_range == [0]
93
- lscpu_info[:cpus_offline] = 0
94
- else
95
- lscpu_info[:cpus_offline] = cpu_range.length
96
- end
97
- when /^Thread\(s\) per core:\s+(.+)/ # http://rubular.com/r/lOw2pRrw1q
98
- lscpu_info[:threads_per_core] = $1.to_i
99
- when /^Core\(s\) per socket:\s+(.+)/ # http://rubular.com/r/lOw2pRrw1q
100
- lscpu_info[:cores_per_socket] = $1.to_i
101
- when /^Socket\(s\):\s+(.+)/ # http://rubular.com/r/DIzmPtJFvK
102
- lscpu_info[:sockets] = $1.to_i
103
- when /^Socket\(s\) per book:\s+(.+)/
104
- lscpu_info[:sockets_per_book] = $1.to_i
105
- when /^Book\(s\) per drawer:\s+(.+)/
106
- lscpu_info[:books_per_drawer] = $1.to_i
107
- when /^Drawer\(s\):\s+(.+)/
108
- lscpu_info[:drawers] = $1.to_i
109
- when /^NUMA node\(s\):\s+(.+)/
110
- lscpu_info[:numa_nodes] = $1.to_i
111
- when /^Vendor ID:\s+(.+)/
112
- lscpu_info[:vendor_id] = $1
113
- when /^Machine type:\s+(.+)/
114
- lscpu_info[:machine_type] = $1
115
- when /^CPU family:\s+(.+)/
116
- lscpu_info[:family] = $1
117
- when /^Model:\s+(.+)/
118
- lscpu_info[:model] = $1
119
- when /^Model name:\s+(.+)/
120
- lscpu_info[:model_name] = $1
121
- when /^Stepping:\s+(.+)/
122
- lscpu_info[:stepping] = $1
123
- when /^CPU MHz:\s+(.+)/
124
- lscpu_info[:mhz] = $1
125
- when /^CPU static MHz:\s+(.+)/
126
- lscpu_info[:mhz] = $1
127
- when /^CPU max MHz:\s+(.+)/
128
- lscpu_info[:mhz_max] = $1
129
- when /^CPU min MHz:\s+(.+)/
130
- lscpu_info[:mhz_min] = $1
131
- when /^CPU dynamic MHz:\s+(.+)/
132
- lscpu_info[:mhz_dynamic] = $1
133
- when /^BogoMIPS:\s+(.+)/
134
- lscpu_info[:bogomips] = $1
135
- when /^Virtualization:\s+(.+)/
136
- lscpu_info[:virtualization] = $1
137
- when /^Virtualization type:\s+(.+)/
138
- lscpu_info[:virtualization_type] = $1
139
- when /^Hypervisor vendor:\s+(.+)/
140
- lscpu_info[:hypervisor_vendor] = $1
141
- when /^Dispatching mode:\s+(.+)/
142
- lscpu_info[:dispatching_mode] = $1
143
- when /^L1d cache:\s+(.+)/
144
- lscpu_info[:l1d_cache] = $1
145
- when /^L1i cache:\s+(.+)/
146
- lscpu_info[:l1i_cache] = $1
147
- when /^L2 cache:\s+(.+)/
148
- lscpu_info[:l2_cache] = $1
149
- when /^L2d cache:\s+(.+)/
150
- lscpu_info[:l2d_cache] = $1
151
- when /^L2i cache:\s+(.+)/
152
- lscpu_info[:l2i_cache] = $1
153
- when /^L3 cache:\s+(.+)/
154
- lscpu_info[:l3_cache] = $1
155
- when /^L4 cache:\s+(.+)/
156
- lscpu_info[:l4_cache] = $1
157
- when /^NUMA node(\d+) CPU\(s\):\s+(.+)/
158
- numa_node = $1
159
- cpus = $2
160
- lscpu_info[:numa_node_cpus][numa_node] = range_str_to_a(cpus)
161
- when /^Vulnerability (.+?):\s+(.+)/ # https://rubular.com/r/aKtSD1ypUlKbGm
162
- name = $1.strip.downcase.tr(" ", "_")
163
- description = $2.strip
164
- lscpu_info[:vulnerability][name] = Mash.new
165
- lscpu_info[:vulnerability][name] = description
166
- when /^Flags:\s+(.+)/
167
- lscpu_info[:flags] = $1.split(" ").sort
168
- # flags are "features" on aarch64 and s390x so add it for backwards computability
169
- lscpu_info[:features] = lscpu_info[:flags] if lscpu_info[:architecture].match?(/aarch64|s390x/)
170
- end
171
- end
172
-
173
- case lscpu_info[:architecture]
174
- when "s390x"
175
- # Add data from /proc/cpuinfo that isn't available from lscpu
176
- lscpu_info[:bogomips_per_cpu] = cpu_info[:bogomips_per_cpu]
177
- lscpu_info[:version] = cpu_info["0"][:version]
178
- lscpu_info[:identification] = cpu_info["0"][:identification]
179
- lscpu_info[:machine] = cpu_info["0"][:machine]
180
- lscpu_total = lscpu_info[:sockets_per_book] * lscpu_info[:cores_per_socket] * lscpu_info[:threads_per_core] * lscpu_info[:books_per_drawer] * lscpu_info[:drawers]
181
- lscpu_real = lscpu_info[:sockets_per_book]
182
- lscpu_cores = lscpu_info[:sockets_per_book] * lscpu_info[:cores_per_socket] * lscpu_info[:books_per_drawer] * lscpu_info[:drawers]
183
- when "ppc64le"
184
- # Add data from /proc/cpuinfo that isn't available from lscpu
185
- lscpu_info[:timebase] = cpu_info[:timebase]
186
- lscpu_info[:platform] = cpu_info[:platform]
187
- lscpu_info[:machine_model] = cpu_info[:machine_model]
188
- lscpu_info[:machine] = cpu_info[:machine]
189
- lscpu_info[:firmware] = cpu_info[:firmware] if cpu_info[:firmware]
190
- lscpu_info[:mmu] = cpu_info[:mmu] if cpu_info[:mmu]
191
- lscpu_info[:mhz] = cpu_info["0"][:mhz]
192
- lscpu_total = lscpu_info[:sockets] * lscpu_info[:cores_per_socket] * lscpu_info[:threads_per_core]
193
- lscpu_real = lscpu_info[:sockets]
194
- lscpu_cores = lscpu_info[:sockets] * lscpu_info[:cores_per_socket]
195
- else
196
- threads_per_core = [lscpu_info[:threads_per_core], 1].max
197
- lscpu_total = lscpu_info[:sockets] * lscpu_info[:cores_per_socket] * threads_per_core
198
- lscpu_real = lscpu_info[:sockets]
199
- lscpu_cores = lscpu_info[:sockets] * lscpu_info[:cores_per_socket]
200
- end
201
-
202
- # Enumerate cpus and fill out data to provide backwards compatibility data
203
- cpu_cores.stdout.each_line do |line|
204
- current_cpu = nil
205
- current_core = nil
206
- current_socket = nil
207
-
208
- case line
209
- # skip comments
210
- when /^#/
211
- next
212
- # Parse data from "lscpu -p=CPU,CORE,SOCKET"
213
- when /(\d+),(\d+),(\d+)/
214
- current_cpu = $1
215
- current_core = $2
216
- current_socket = $3
217
- end
218
- lscpu_info[current_cpu] = Mash.new
219
- lscpu_info[current_cpu][:vendor_id] = lscpu_info[:vendor_id] if lscpu_info[:vendor_id]
220
- lscpu_info[current_cpu][:family] = lscpu_info[:family] if lscpu_info[:family]
221
- lscpu_info[current_cpu][:model] = lscpu_info[:model] if lscpu_info[:model]
222
- lscpu_info[current_cpu][:model_name] = lscpu_info[:model_name] if lscpu_info[:model_name]
223
- lscpu_info[current_cpu][:stepping] = lscpu_info[:stepping] if lscpu_info[:stepping]
224
- lscpu_info[current_cpu][:mhz] = lscpu_info[:mhz] if lscpu_info[:mhz]
225
- lscpu_info[current_cpu][:bogomips] = lscpu_info[:bogomips] if lscpu_info[:bogomips]
226
- # Per cpu cache_size is only really available from /proc/cpuinfo on x86
227
- lscpu_info[current_cpu][:cache_size] = cpu_info[current_cpu][:cache_size] if cpu_info[current_cpu] && cpu_info[current_cpu][:cache_size]
228
- lscpu_info[current_cpu][:physical_id] = current_socket
229
- lscpu_info[current_cpu][:core_id] = current_core
230
- lscpu_info[current_cpu][:cores] = lscpu_info[:cores_per_socket].to_s
231
- lscpu_info[current_cpu][:flags] = lscpu_info[:flags] if lscpu_info[:flags]
232
- lscpu_info[current_cpu][:features] = lscpu_info[:flags] if lscpu_info[:architecture].match?(/aarch64|s390x/)
233
- if lscpu_info[:architecture] == "s390x"
234
- lscpu_info[current_cpu][:version] = cpu_info[current_cpu][:version] if cpu_info[current_cpu][:version]
235
- lscpu_info[current_cpu][:identification] = cpu_info[current_cpu][:identification] if cpu_info[current_cpu][:identification]
236
- lscpu_info[current_cpu][:machine] = cpu_info[current_cpu][:machine] if cpu_info[current_cpu][:machine]
237
- end
238
- end
239
- lscpu_info[:total] = lscpu_total
240
- lscpu_info[:real] = lscpu_real
241
- lscpu_info[:cores] = lscpu_cores
242
- else
243
- logger.trace("Plugin CPU: Error executing lscpu. CPU data may not be available.")
244
- end
245
- rescue Ohai::Exceptions::Exec # util-linux isn't installed most likely
246
- logger.trace("Plugin CPU: Error executing lscpu. util-linux may not be installed.")
247
- end
248
- lscpu_info
249
- end
250
-
251
- def parse_cpuinfo
252
- cpuinfo = Mash.new
253
- real_cpu = Mash.new
254
- cpu_number = 0
255
- current_cpu = nil
256
-
257
- file_open("/proc/cpuinfo").each_line do |line|
258
- case line
259
- when /processor\s+:\s(.+)/
260
- cpuinfo[$1] = Mash.new
261
- current_cpu = $1
262
- cpu_number += 1
263
- when /vendor_id\s+:\s(.+)/
264
- vendor_id = $1
265
- if vendor_id.include?("IBM/S390")
266
- cpuinfo["vendor_id"] = vendor_id
267
- else
268
- cpuinfo[current_cpu]["vendor_id"] = vendor_id
269
- end
270
- when /cpu family\s+:\s(.+)/
271
- cpuinfo[current_cpu]["family"] = $1
272
- when /model\s+:\s(.+)/
273
- model = $1
274
- cpuinfo[current_cpu]["model"] = model
275
- # ppc has "model" at the end of /proc/cpuinfo. In addition it should always include a include a dash or "IBM".
276
- # So let's put this in cpu/model on ppc
277
- cpuinfo["machine_model"] = model if model.match?(/-|IBM/)
278
- when /stepping\s+:\s(.+)/
279
- cpuinfo[current_cpu]["stepping"] = $1
280
- when /physical id\s+:\s(.+)/
281
- cpuinfo[current_cpu]["physical_id"] = $1
282
- real_cpu[$1] = true
283
- when /core id\s+:\s(.+)/
284
- cpuinfo[current_cpu]["core_id"] = $1
285
- when /cpu cores\s+:\s(.+)/
286
- cpuinfo[current_cpu]["cores"] = $1
287
- when /model name\s+:\s(.+)/
288
- cpuinfo[current_cpu]["model_name"] = $1
289
- when /cpu MHz\s+:\s(.+)/
290
- cpuinfo[current_cpu]["mhz"] = $1
291
- when /cache size\s+:\s(.+)/
292
- cpuinfo[current_cpu]["cache_size"] = $1
293
- when /flags\s+:\s(.+)/
294
- cpuinfo[current_cpu]["flags"] = $1.split
295
- when /BogoMIPS\s+:\s(.+)/
296
- cpuinfo[current_cpu]["bogomips"] = $1
297
- when /Features\s+:\s(.+)/
298
- cpuinfo[current_cpu]["features"] = $1.split
299
- when /bogomips per cpu:\s(.+)/
300
- cpuinfo["bogomips_per_cpu"] = $1
301
- when /features\s+:\s(.+)/
302
- cpuinfo["features"] = $1.split
303
- # ppc64le
304
- when /revision\s+:\s(.+)/
305
- cpuinfo[current_cpu]["model"] = $1
306
- when /cpu\s+:\s(.+)/
307
- cpuinfo[current_cpu]["model_name"] = $1
308
- when /clock\s+:\s(.+)/
309
- cpuinfo[current_cpu]["mhz"] = $1
310
- when /timebase\s+:\s(.+)/
311
- cpuinfo["timebase"] = $1
312
- when /platform\s+:\s(.+)/
313
- cpuinfo["platform"] = $1
314
- when /machine\s+:\s(.+)/
315
- cpuinfo["machine"] = $1
316
- when /firmware\s+:\s(.+)/
317
- cpuinfo["firmware"] = $1
318
- when /MMU\s+:\s(.+)/
319
- cpuinfo["mmu"] = $1
320
- # s390x
321
- when /processor\s(\d):\s(.+)/
322
- current_cpu = $1
323
- cpu_number += 1
324
- cpuinfo[current_cpu] = Mash.new
325
- current_cpu_info = $2.split(",")
326
- current_cpu_info.each do |i|
327
- name_value = i.split("=")
328
- name = name_value[0].strip
329
- value = name_value[1].strip
330
- cpuinfo[current_cpu][name] = value
331
- end
332
- end
333
- end
334
-
335
- # use data we collected unless cpuinfo is lacking core information
336
- # which is the case on older linux distros
337
- if !real_cpu.empty? && cpuinfo["0"]["cores"]
338
- logger.trace("Plugin CPU: Error executing lscpu. CPU data may not be available.")
339
- cpuinfo[:real] = real_cpu.keys.length
340
- cpuinfo[:cores] = real_cpu.keys.length * cpuinfo["0"]["cores"].to_i
341
- else
342
- logger.trace("Plugin CPU: real cpu & core data is missing in /proc/cpuinfo and lscpu")
343
- end
344
- cpuinfo[:total] = cpu_number
345
- cpuinfo
346
- end
347
-
348
- # Check if the `lscpu` data looks reasonable
349
- def valid_lscpu?(lscpu)
350
- return false if lscpu.empty?
351
- return false if %i{total real cores}.any? { |key| lscpu[key].to_i == 0 }
352
-
353
- true
354
- end
355
-
356
- collect_data(:linux) do
357
- cpuinfo = parse_cpuinfo
358
- lscpu = parse_lscpu(cpuinfo)
359
-
360
- # If we don't have any sensible data from lscpu then get it from /proc/cpuinfo
361
- if valid_lscpu?(lscpu)
362
- cpu lscpu
363
- else
364
- cpu cpuinfo
365
- end
366
- end
367
-
368
- collect_data(:freebsd) do
369
- # all dmesg output for smp I can find only provides info about a single processor
370
- # identical processors is probably a hardware requirement so we'll duplicate data for each cpu
371
- # old examples: http://www.bnv-bamberg.de/home/ba3294/smp/rbuild/index.htm
372
-
373
- # /var/run/dmesg.boot
374
- # CPU: Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz (2793.59-MHz K8-class CPU)
375
- # Origin="GenuineIntel" Id=0x40661 Family=0x6 Model=0x46 Stepping=1
376
- # Features=0x783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2>
377
- # Features2=0x5ed8220b<SSE3,PCLMULQDQ,MON,SSSE3,CX16,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,AVX,RDRAND>
378
- # AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
379
- # AMD Features2=0x21<LAHF,ABM>
380
- # Structured Extended Features=0x2000<NFPUSG>
381
- # TSC: P-state invariant
382
- # ...
383
- # FreeBSD/SMP: Multiprocessor System Detected: 16 CPUs
384
- # FreeBSD/SMP: 2 package(s) x 4 core(s) x 2 SMT threads
385
-
386
- info = parse_bsd_dmesg do |cpuinfo, line|
387
- case line
388
- when /Origin.*"(.*)".*Family.*0x(\S+).*Model.*0x(\S+).*Stepping.*(\S+)/
389
- cpuinfo["vendor_id"] = $1
390
- # convert from hex value to int, but keep a string to match Linux ohai
391
- cpuinfo["family"] = $2.to_i(16).to_s
392
- cpuinfo["model"] = $3.to_i(16).to_s
393
- cpuinfo["stepping"] = $4
394
- # These _should_ match /AMD Features2?/ lines as well
395
- when %r{FreeBSD/SMP: Multiprocessor System Detected: (\d*) CPUs}
396
- cpuinfo["total"] = $1.to_i
397
- when %r{FreeBSD/SMP: (\d*) package\(s\) x (\d*) core\(s\)}
398
- cpuinfo["real"] = $1.to_i
399
- cpuinfo["cores"] = $1.to_i * $2.to_i
400
- end
401
- end
402
- cpu info
403
- end
404
-
405
- collect_data(:dragonflybsd) do
406
- # /var/run/dmesg.boot
407
- # CPU: Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz (3516.61-MHz K8-class CPU)
408
- # Origin = "GenuineIntel" Id = 0x306a9 Family = 6 Model = 3a Stepping = 9
409
- # Features=0x783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2>
410
- # Features2=0x209<SSE3,MON,SSSE3>
411
- # AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
412
- # AMD Features2=0x1<LAHF>
413
-
414
- info = parse_bsd_dmesg do |cpuinfo, line|
415
- case line
416
- when /Origin = "(.+)"\s+Id = (.+)\s+Stepping = (.+)/
417
- cpuinfo["vendor_id"] = $1
418
- cpuinfo["stepping"] = $3
419
- end
420
- end
421
-
422
- so = shell_out("sysctl -n hw.ncpu")
423
- info[:total] = so.stdout.strip.to_i
424
- cpu info
425
- end
426
-
427
- collect_data(:openbsd) do
428
- cpuinfo = Mash.new
429
-
430
- # OpenBSD provides most cpu information via sysctl, the only thing we need to
431
- # to scrape from dmesg.boot is the cpu feature list.
432
- # cpu0: FPU,V86,DE,PSE,TSC,MSR,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PAT,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,TM,SBF,EST,TM2
433
-
434
- file_open("/var/run/dmesg.boot").each do |line|
435
- case line
436
- when /cpu\d+:\s+([A-Z]+$|[A-Z]+,.*$)/
437
- cpuinfo["flags"] = $1.downcase.split(",")
438
- end
439
- end
440
-
441
- [["hw.model", :model_name], ["hw.ncpu", :total], ["hw.cpuspeed", :mhz]].each do |param, node|
442
- so = shell_out("sysctl -n #{param}")
443
- cpuinfo[node] = so.stdout.strip
444
- end
445
-
446
- cpu cpuinfo
447
- end
448
-
449
- collect_data(:netbsd) do
450
- cpuinfo = Mash.new
451
-
452
- # NetBSD provides some cpu information via sysctl, and a little via dmesg.boot
453
- # unlike OpenBSD and FreeBSD, NetBSD does not provide information about the
454
- # available instruction set
455
- # cpu0 at mainbus0 apid 0: Intel 686-class, 2134MHz, id 0x6f6
456
-
457
- file_open("/var/run/dmesg.boot").each do |line|
458
- case line
459
- when /cpu[\d\w\s]+:\s([\w\s\-]+),\s+(\w+),/
460
- cpuinfo[:model_name] = $1
461
- cpuinfo[:mhz] = $2.gsub(/mhz/i, "")
462
- end
463
- end
464
-
465
- flags = []
466
- so = shell_out("dmidecode")
467
- so.stdout.lines do |line|
468
- if line =~ /^\s+([A-Z\d-]+)\s+\([\w\s-]+\)$/
469
- flags << $1.downcase
470
- end
471
- end
472
-
473
- cpuinfo[:flags] = flags unless flags.empty?
474
-
475
- cpu cpuinfo
476
- end
477
-
478
- collect_data(:darwin) do
479
- cpu Mash.new
480
- shell_out("sysctl hw machdep").stdout.lines.each do |line|
481
- case line
482
- when /^hw.packages: (.*)$/
483
- cpu[:real] = Regexp.last_match[1].to_i
484
- when /^hw.physicalcpu: (.*)$/
485
- cpu[:cores] = Regexp.last_match[1].to_i
486
- when /^hw.logicalcpu: (.*)$/
487
- cpu[:total] = Regexp.last_match[1].to_i
488
- when /^hw.cpufrequency: (.*)$/
489
- cpu[:mhz] = Regexp.last_match[1].to_i / 1000000
490
- when /^machdep.cpu.vendor: (.*)$/
491
- cpu[:vendor_id] = Regexp.last_match[1].chomp
492
- when /^machdep.cpu.brand_string: (.*)$/
493
- cpu[:model_name] = Regexp.last_match[1].chomp
494
- when /^machdep.cpu.model: (.*)$/
495
- cpu[:model] = Regexp.last_match[1].to_i
496
- when /^machdep.cpu.family: (.*)$/
497
- cpu[:family] = Regexp.last_match[1].to_i
498
- when /^machdep.cpu.stepping: (.*)$/
499
- cpu[:stepping] = Regexp.last_match[1].to_i
500
- when /^machdep.cpu.features: (.*)$/
501
- cpu[:flags] = Regexp.last_match[1].downcase.split
502
- end
503
- end
504
- end
505
-
506
- collect_data(:aix) do
507
- cpu Mash.new
508
-
509
- cpu[:total] = shell_out("pmcycles -m").stdout.lines.length
510
-
511
- # The below is only relevant on an LPAR
512
- if shell_out("uname -W").stdout.strip == "0"
513
-
514
- # At least one CPU will be available, but we'll wait to increment this later.
515
- cpu[:available] = 0
516
-
517
- cpudevs = shell_out("lsdev -Cc processor").stdout.lines
518
- # from http://www-01.ibm.com/software/passportadvantage/pvu_terminology_for_customers.html
519
- # on AIX number of cores and processors are considered same
520
- cpu[:real] = cpu[:cores] = cpudevs.length
521
- cpudevs.each.with_index do |c, i|
522
- name, status, location = c.split
523
- index = i.to_s
524
- cpu[index] = Mash.new
525
- cpu[index][:status] = status
526
- cpu[index][:location] = location
527
- if /Available/.match?(status)
528
- cpu[:available] += 1
529
- lsattr = shell_out("lsattr -El #{name}").stdout.lines
530
- lsattr.each do |attribute|
531
- attrib, value = attribute.split
532
- if attrib == "type"
533
- cpu[index][:model_name] = value
534
- elsif attrib == "frequency"
535
- cpu[index][:mhz] = value.to_i / (1000 * 1000) # convert from hz to MHz
536
- else
537
- cpu[index][attrib] = value
538
- end
539
- end
540
- # IBM is the only maker of CPUs for AIX systems.
541
- cpu[index][:vendor_id] = "IBM"
542
- end
543
- end
544
- end
545
- end
546
-
547
- collect_data(:solaris2) do
548
- cpu Mash.new
549
- # This does assume that /usr/bin/kstat is in the path
550
- processor_info = shell_out("kstat -p cpu_info").stdout.lines
551
- cpu["total"] = 0
552
- cpu["sockets"] = 0
553
- cpu["cores"] = 0
554
- cpu["corethreads"] = 0
555
- cpu["cpustates"] = Mash.new
556
-
557
- currentcpu = 0
558
- cpucores = []
559
- cpusockets = []
560
- processor_info.each do |processor|
561
- _desc, instance, _record, keyvalue = processor.split(":")
562
- cpu[instance] ||= Mash.new
563
- if currentcpu != instance
564
- cpu["total"] += 1
565
- currentcpu = instance
566
- end
567
- kv = keyvalue.split(/\s+/)
568
- key = kv.shift
569
- value = kv.join(" ").chomp
570
- case key
571
- when /chip_id/
572
- cpu[instance]["socket"] = value
573
- cpusockets.push(value) if cpusockets.index(value).nil?
574
- when /cpu_type/
575
- cpu[instance]["arch"] = value
576
- when /clock_MHz/
577
- cpu[instance]["mhz"] = value
578
- when /brand/
579
- cpu[instance]["model_name"] = value.sub(/\s+/, " ")
580
- when /^state$/
581
- cpu[instance]["state"] = value
582
- cpu["cpustates"][value] ||= 0
583
- cpu["cpustates"][value] += 1
584
- when /core_id/
585
- cpu[instance]["core_id"] = value
586
- # Detect hyperthreading/multithreading
587
- cpucores.push(value) if cpucores.index(value).nil?
588
- when /family|fpu_type|model|stepping|vendor_id/
589
- cpu[instance][key] = value
590
- end
591
- end
592
- cpu["cores"] = cpucores.size
593
- cpu["corethreads"] = (cpu["total"] / cpucores.size)
594
- cpu["sockets"] = cpusockets.size
595
- cpu["real"] = cpusockets.size
596
- end
597
-
598
- collect_data(:windows) do
599
- require "wmi-lite/wmi" unless defined?(WmiLite::Wmi)
600
-
601
- cpu Mash.new
602
- cores = 0
603
- logical_processors = 0
604
-
605
- wmi = WmiLite::Wmi.new
606
- processors = wmi.instances_of("Win32_Processor")
607
-
608
- processors.each_with_index do |processor, index|
609
- current_cpu = index.to_s
610
- cpu[current_cpu] = Mash.new
611
-
612
- cpu[current_cpu]["cores"] = processor["numberofcores"]
613
- cores += processor["numberofcores"]
614
-
615
- logical_processors += processor["numberoflogicalprocessors"]
616
- cpu[current_cpu]["vendor_id"] = processor["manufacturer"]
617
- cpu[current_cpu]["family"] = processor["family"].to_s
618
- cpu[current_cpu]["model"] = processor["revision"].to_s
619
- cpu[current_cpu]["stepping"] = if processor["stepping"].nil?
620
- processor["description"].match(/Stepping\s+(\d+)/)[1]
621
- else
622
- processor["stepping"]
623
- end
624
- cpu[current_cpu]["physical_id"] = processor["deviceid"]
625
- cpu[current_cpu]["model_name"] = processor["name"]
626
- cpu[current_cpu]["description"] = processor["description"]
627
- cpu[current_cpu]["mhz"] = processor["maxclockspeed"].to_s
628
- cpu[current_cpu]["cache_size"] = "#{processor["l2cachesize"]} KB"
629
- end
630
-
631
- cpu[:total] = logical_processors
632
- cpu[:cores] = cores
633
- cpu[:real] = processors.length
634
- end
635
- end
1
+ # frozen_string_literal: true
2
+ #
3
+ # Author:: Adam Jacob (<adam@chef.io>)
4
+ # Author:: Bryan McLellan (btm@loftninjas.org)
5
+ # Author:: Tim Smith (tsmith@chef.io)
6
+ # Author:: Mathieu Sauve-Frankel <msf@kisoku.net>
7
+ # Author:: Nathan L Smith (<nlloyds@gmail.com>)
8
+ # Author:: Joshua Timberman <joshua@chef.io>
9
+ # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
10
+ # Author:: Isa Farnik (<isa@chef.io>)
11
+ # Author:: Doug MacEachern <dougm@vmware.com>
12
+ # Author:: Lance Albertson <lance@osuosl.org>
13
+ # Copyright:: Copyright (c) Chef Software Inc.
14
+ # License:: Apache License, Version 2.0
15
+ #
16
+ # Licensed under the Apache License, Version 2.0 (the "License");
17
+ # you may not use this file except in compliance with the License.
18
+ # You may obtain a copy of the License at
19
+ #
20
+ # http://www.apache.org/licenses/LICENSE-2.0
21
+ #
22
+ # Unless required by applicable law or agreed to in writing, software
23
+ # distributed under the License is distributed on an "AS IS" BASIS,
24
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
+ # See the License for the specific language governing permissions and
26
+ # limitations under the License.
27
+ #
28
+
29
+ Ohai.plugin(:CPU) do
30
+ provides "cpu"
31
+
32
+ def parse_bsd_dmesg(&block)
33
+ cpuinfo = Mash.new
34
+ cpuinfo["flags"] = []
35
+ file_open("/var/run/dmesg.boot").each do |line|
36
+ case line
37
+ when /CPU:\s+(.+) \(([\d.]+).+\)/
38
+ cpuinfo["model_name"] = $1
39
+ cpuinfo["mhz"] = $2
40
+ when /Features=.+<(.+)>/, /Features2=[a-f\dx]+<(.+)>/
41
+ cpuinfo["flags"].concat($1.downcase.split(","))
42
+ # Features2=0x80000001<SSE3,<b31>>
43
+ else
44
+ yield(cpuinfo, line)
45
+ end
46
+ end
47
+ cpuinfo
48
+ end
49
+
50
+ # Convert a string that looks like range of CPUs to an array
51
+ # Given the following range: 1-7
52
+ # Convert it into an array: [1, 2, 3, 4, 5, 6, 7]
53
+ def range_str_to_a(range)
54
+ range.split(",").each_with_object([]) do |cpu, arr|
55
+ if /\d+-\d+/.match?(cpu.to_s)
56
+ arr << Range.new(*cpu.split("-").map(&:to_i)).to_a
57
+ else
58
+ arr << cpu.to_i
59
+ end
60
+ end.flatten
61
+ end
62
+
63
+ def parse_lscpu(cpu_info)
64
+ lscpu_info = Mash.new
65
+ begin
66
+ so = shell_out("lscpu")
67
+ cpu_cores = shell_out("lscpu -p=CPU,CORE,SOCKET")
68
+ if so.exitstatus == 0 && cpu_cores.exitstatus == 0
69
+ lscpu_info[:numa_node_cpus] = Mash.new
70
+ lscpu_info[:vulnerability] = Mash.new
71
+ so.stdout.each_line do |line|
72
+ case line
73
+ when /^Architecture:\s+(.+)/
74
+ lscpu_info[:architecture] = $1.to_s
75
+ when /^CPU op-mode\(s\):\s+(.+)/
76
+ lscpu_info[:cpu_opmodes] = $1.split(", ")
77
+ when /^Byte Order:\s+(.+)/
78
+ lscpu_info[:byte_order] = $1.downcase
79
+ when /^Address sizes:\s+(.+)/
80
+ lscpu_info[:address_sizes] = $1.split(", ")
81
+ when /^CPU\(s\):\s+(.+)/
82
+ lscpu_info[:cpus] = $1.to_i
83
+ when /^On-line CPU\(s\) list:\s+(.+)/
84
+ cpu_range = range_str_to_a($1)
85
+ if cpu_range == [0]
86
+ lscpu_info[:cpus_online] = 0
87
+ else
88
+ lscpu_info[:cpus_online] = cpu_range.length
89
+ end
90
+ when /^Off-line CPU\(s\) list:\s+(.+)/
91
+ cpu_range = range_str_to_a($1)
92
+ if cpu_range == [0]
93
+ lscpu_info[:cpus_offline] = 0
94
+ else
95
+ lscpu_info[:cpus_offline] = cpu_range.length
96
+ end
97
+ when /^Thread\(s\) per core:\s+(.+)/ # http://rubular.com/r/lOw2pRrw1q
98
+ lscpu_info[:threads_per_core] = $1.to_i
99
+ when /^Core\(s\) per socket:\s+(.+)/ # http://rubular.com/r/lOw2pRrw1q
100
+ lscpu_info[:cores_per_socket] = $1.to_i
101
+ when /^Socket\(s\):\s+(.+)/ # http://rubular.com/r/DIzmPtJFvK
102
+ lscpu_info[:sockets] = $1.to_i
103
+ when /^Socket\(s\) per book:\s+(.+)/
104
+ lscpu_info[:sockets_per_book] = $1.to_i
105
+ when /^Book\(s\) per drawer:\s+(.+)/
106
+ lscpu_info[:books_per_drawer] = $1.to_i
107
+ when /^Drawer\(s\):\s+(.+)/
108
+ lscpu_info[:drawers] = $1.to_i
109
+ when /^NUMA node\(s\):\s+(.+)/
110
+ lscpu_info[:numa_nodes] = $1.to_i
111
+ when /^Vendor ID:\s+(.+)/
112
+ lscpu_info[:vendor_id] = $1
113
+ when /^Machine type:\s+(.+)/
114
+ lscpu_info[:machine_type] = $1
115
+ when /^CPU family:\s+(.+)/
116
+ lscpu_info[:family] = $1
117
+ when /^Model:\s+(.+)/
118
+ lscpu_info[:model] = $1
119
+ when /^Model name:\s+(.+)/
120
+ lscpu_info[:model_name] = $1
121
+ when /^Stepping:\s+(.+)/
122
+ lscpu_info[:stepping] = $1
123
+ when /^CPU MHz:\s+(.+)/
124
+ lscpu_info[:mhz] = $1
125
+ when /^CPU static MHz:\s+(.+)/
126
+ lscpu_info[:mhz] = $1
127
+ when /^CPU max MHz:\s+(.+)/
128
+ lscpu_info[:mhz_max] = $1
129
+ when /^CPU min MHz:\s+(.+)/
130
+ lscpu_info[:mhz_min] = $1
131
+ when /^CPU dynamic MHz:\s+(.+)/
132
+ lscpu_info[:mhz_dynamic] = $1
133
+ when /^BogoMIPS:\s+(.+)/
134
+ lscpu_info[:bogomips] = $1
135
+ when /^Virtualization:\s+(.+)/
136
+ lscpu_info[:virtualization] = $1
137
+ when /^Virtualization type:\s+(.+)/
138
+ lscpu_info[:virtualization_type] = $1
139
+ when /^Hypervisor vendor:\s+(.+)/
140
+ lscpu_info[:hypervisor_vendor] = $1
141
+ when /^Dispatching mode:\s+(.+)/
142
+ lscpu_info[:dispatching_mode] = $1
143
+ when /^L1d cache:\s+(.+)/
144
+ lscpu_info[:l1d_cache] = $1
145
+ when /^L1i cache:\s+(.+)/
146
+ lscpu_info[:l1i_cache] = $1
147
+ when /^L2 cache:\s+(.+)/
148
+ lscpu_info[:l2_cache] = $1
149
+ when /^L2d cache:\s+(.+)/
150
+ lscpu_info[:l2d_cache] = $1
151
+ when /^L2i cache:\s+(.+)/
152
+ lscpu_info[:l2i_cache] = $1
153
+ when /^L3 cache:\s+(.+)/
154
+ lscpu_info[:l3_cache] = $1
155
+ when /^L4 cache:\s+(.+)/
156
+ lscpu_info[:l4_cache] = $1
157
+ when /^NUMA node(\d+) CPU\(s\):\s+(.+)/
158
+ numa_node = $1
159
+ cpus = $2
160
+ lscpu_info[:numa_node_cpus][numa_node] = range_str_to_a(cpus)
161
+ when /^Vulnerability (.+?):\s+(.+)/ # https://rubular.com/r/aKtSD1ypUlKbGm
162
+ name = $1.strip.downcase.tr(" ", "_")
163
+ description = $2.strip
164
+ lscpu_info[:vulnerability][name] = Mash.new
165
+ lscpu_info[:vulnerability][name] = description
166
+ when /^Flags:\s+(.+)/
167
+ lscpu_info[:flags] = $1.split(" ").sort
168
+ # flags are "features" on aarch64 and s390x so add it for backwards computability
169
+ lscpu_info[:features] = lscpu_info[:flags] if lscpu_info[:architecture].match?(/aarch64|s390x/)
170
+ end
171
+ end
172
+
173
+ case lscpu_info[:architecture]
174
+ when "s390x"
175
+ # Add data from /proc/cpuinfo that isn't available from lscpu
176
+ lscpu_info[:bogomips_per_cpu] = cpu_info[:bogomips_per_cpu]
177
+ lscpu_info[:version] = cpu_info["0"][:version]
178
+ lscpu_info[:identification] = cpu_info["0"][:identification]
179
+ lscpu_info[:machine] = cpu_info["0"][:machine]
180
+ lscpu_total = lscpu_info[:sockets_per_book] * lscpu_info[:cores_per_socket] * lscpu_info[:threads_per_core] * lscpu_info[:books_per_drawer] * lscpu_info[:drawers]
181
+ lscpu_real = lscpu_info[:sockets_per_book]
182
+ lscpu_cores = lscpu_info[:sockets_per_book] * lscpu_info[:cores_per_socket] * lscpu_info[:books_per_drawer] * lscpu_info[:drawers]
183
+ when "ppc64le"
184
+ # Add data from /proc/cpuinfo that isn't available from lscpu
185
+ lscpu_info[:timebase] = cpu_info[:timebase]
186
+ lscpu_info[:platform] = cpu_info[:platform]
187
+ lscpu_info[:machine_model] = cpu_info[:machine_model]
188
+ lscpu_info[:machine] = cpu_info[:machine]
189
+ lscpu_info[:firmware] = cpu_info[:firmware] if cpu_info[:firmware]
190
+ lscpu_info[:mmu] = cpu_info[:mmu] if cpu_info[:mmu]
191
+ lscpu_info[:mhz] = cpu_info["0"][:mhz]
192
+ lscpu_total = lscpu_info[:sockets] * lscpu_info[:cores_per_socket] * lscpu_info[:threads_per_core]
193
+ lscpu_real = lscpu_info[:sockets]
194
+ lscpu_cores = lscpu_info[:sockets] * lscpu_info[:cores_per_socket]
195
+ else
196
+ threads_per_core = [lscpu_info[:threads_per_core], 1].max
197
+ lscpu_total = lscpu_info[:sockets] * lscpu_info[:cores_per_socket] * threads_per_core
198
+ lscpu_real = lscpu_info[:sockets]
199
+ lscpu_cores = lscpu_info[:sockets] * lscpu_info[:cores_per_socket]
200
+ end
201
+
202
+ # Enumerate cpus and fill out data to provide backwards compatibility data
203
+ cpu_cores.stdout.each_line do |line|
204
+ current_cpu = nil
205
+ current_core = nil
206
+ current_socket = nil
207
+
208
+ case line
209
+ # skip comments
210
+ when /^#/
211
+ next
212
+ # Parse data from "lscpu -p=CPU,CORE,SOCKET"
213
+ when /(\d+),(\d+),(\d+)/
214
+ current_cpu = $1
215
+ current_core = $2
216
+ current_socket = $3
217
+ end
218
+ lscpu_info[current_cpu] = Mash.new
219
+ lscpu_info[current_cpu][:vendor_id] = lscpu_info[:vendor_id] if lscpu_info[:vendor_id]
220
+ lscpu_info[current_cpu][:family] = lscpu_info[:family] if lscpu_info[:family]
221
+ lscpu_info[current_cpu][:model] = lscpu_info[:model] if lscpu_info[:model]
222
+ lscpu_info[current_cpu][:model_name] = lscpu_info[:model_name] if lscpu_info[:model_name]
223
+ lscpu_info[current_cpu][:stepping] = lscpu_info[:stepping] if lscpu_info[:stepping]
224
+ lscpu_info[current_cpu][:mhz] = lscpu_info[:mhz] if lscpu_info[:mhz]
225
+ lscpu_info[current_cpu][:bogomips] = lscpu_info[:bogomips] if lscpu_info[:bogomips]
226
+ # Per cpu cache_size is only really available from /proc/cpuinfo on x86
227
+ lscpu_info[current_cpu][:cache_size] = cpu_info[current_cpu][:cache_size] if cpu_info[current_cpu] && cpu_info[current_cpu][:cache_size]
228
+ lscpu_info[current_cpu][:physical_id] = current_socket
229
+ lscpu_info[current_cpu][:core_id] = current_core
230
+ lscpu_info[current_cpu][:cores] = lscpu_info[:cores_per_socket].to_s
231
+ lscpu_info[current_cpu][:flags] = lscpu_info[:flags] if lscpu_info[:flags]
232
+ lscpu_info[current_cpu][:features] = lscpu_info[:flags] if lscpu_info[:architecture].match?(/aarch64|s390x/)
233
+ if lscpu_info[:architecture] == "s390x"
234
+ lscpu_info[current_cpu][:version] = cpu_info[current_cpu][:version] if cpu_info[current_cpu][:version]
235
+ lscpu_info[current_cpu][:identification] = cpu_info[current_cpu][:identification] if cpu_info[current_cpu][:identification]
236
+ lscpu_info[current_cpu][:machine] = cpu_info[current_cpu][:machine] if cpu_info[current_cpu][:machine]
237
+ end
238
+ end
239
+ lscpu_info[:total] = lscpu_total
240
+ lscpu_info[:real] = lscpu_real
241
+ lscpu_info[:cores] = lscpu_cores
242
+ else
243
+ logger.trace("Plugin CPU: Error executing lscpu. CPU data may not be available.")
244
+ end
245
+ rescue Ohai::Exceptions::Exec # util-linux isn't installed most likely
246
+ logger.trace("Plugin CPU: Error executing lscpu. util-linux may not be installed.")
247
+ end
248
+ lscpu_info
249
+ end
250
+
251
+ def parse_cpuinfo
252
+ cpuinfo = Mash.new
253
+ real_cpu = Mash.new
254
+ cpu_number = 0
255
+ current_cpu = nil
256
+
257
+ file_open("/proc/cpuinfo").each_line do |line|
258
+ case line
259
+ when /processor\s+:\s(.+)/
260
+ cpuinfo[$1] = Mash.new
261
+ current_cpu = $1
262
+ cpu_number += 1
263
+ when /vendor_id\s+:\s(.+)/
264
+ vendor_id = $1
265
+ if vendor_id.include?("IBM/S390")
266
+ cpuinfo["vendor_id"] = vendor_id
267
+ else
268
+ cpuinfo[current_cpu]["vendor_id"] = vendor_id
269
+ end
270
+ when /cpu family\s+:\s(.+)/
271
+ cpuinfo[current_cpu]["family"] = $1
272
+ when /model\s+:\s(.+)/
273
+ model = $1
274
+ cpuinfo[current_cpu]["model"] = model
275
+ # ppc has "model" at the end of /proc/cpuinfo. In addition it should always include a include a dash or "IBM".
276
+ # So let's put this in cpu/model on ppc
277
+ cpuinfo["machine_model"] = model if model.match?(/-|IBM/)
278
+ when /stepping\s+:\s(.+)/
279
+ cpuinfo[current_cpu]["stepping"] = $1
280
+ when /physical id\s+:\s(.+)/
281
+ cpuinfo[current_cpu]["physical_id"] = $1
282
+ real_cpu[$1] = true
283
+ when /core id\s+:\s(.+)/
284
+ cpuinfo[current_cpu]["core_id"] = $1
285
+ when /cpu cores\s+:\s(.+)/
286
+ cpuinfo[current_cpu]["cores"] = $1
287
+ when /model name\s+:\s(.+)/
288
+ cpuinfo[current_cpu]["model_name"] = $1
289
+ when /cpu MHz\s+:\s(.+)/
290
+ cpuinfo[current_cpu]["mhz"] = $1
291
+ when /cache size\s+:\s(.+)/
292
+ cpuinfo[current_cpu]["cache_size"] = $1
293
+ when /flags\s+:\s(.+)/
294
+ cpuinfo[current_cpu]["flags"] = $1.split
295
+ when /BogoMIPS\s+:\s(.+)/
296
+ cpuinfo[current_cpu]["bogomips"] = $1
297
+ when /Features\s+:\s(.+)/
298
+ cpuinfo[current_cpu]["features"] = $1.split
299
+ when /bogomips per cpu:\s(.+)/
300
+ cpuinfo["bogomips_per_cpu"] = $1
301
+ when /features\s+:\s(.+)/
302
+ cpuinfo["features"] = $1.split
303
+ # ppc64le
304
+ when /revision\s+:\s(.+)/
305
+ cpuinfo[current_cpu]["model"] = $1
306
+ when /cpu\s+:\s(.+)/
307
+ cpuinfo[current_cpu]["model_name"] = $1
308
+ when /clock\s+:\s(.+)/
309
+ cpuinfo[current_cpu]["mhz"] = $1
310
+ when /timebase\s+:\s(.+)/
311
+ cpuinfo["timebase"] = $1
312
+ when /platform\s+:\s(.+)/
313
+ cpuinfo["platform"] = $1
314
+ when /machine\s+:\s(.+)/
315
+ cpuinfo["machine"] = $1
316
+ when /firmware\s+:\s(.+)/
317
+ cpuinfo["firmware"] = $1
318
+ when /MMU\s+:\s(.+)/
319
+ cpuinfo["mmu"] = $1
320
+ # s390x
321
+ when /processor\s(\d):\s(.+)/
322
+ current_cpu = $1
323
+ cpu_number += 1
324
+ cpuinfo[current_cpu] = Mash.new
325
+ current_cpu_info = $2.split(",")
326
+ current_cpu_info.each do |i|
327
+ name_value = i.split("=")
328
+ name = name_value[0].strip
329
+ value = name_value[1].strip
330
+ cpuinfo[current_cpu][name] = value
331
+ end
332
+ end
333
+ end
334
+
335
+ # use data we collected unless cpuinfo is lacking core information
336
+ # which is the case on older linux distros
337
+ if !real_cpu.empty? && cpuinfo["0"]["cores"]
338
+ logger.trace("Plugin CPU: Error executing lscpu. CPU data may not be available.")
339
+ cpuinfo[:real] = real_cpu.keys.length
340
+ cpuinfo[:cores] = real_cpu.keys.length * cpuinfo["0"]["cores"].to_i
341
+ else
342
+ logger.trace("Plugin CPU: real cpu & core data is missing in /proc/cpuinfo and lscpu")
343
+ end
344
+ cpuinfo[:total] = cpu_number
345
+ cpuinfo
346
+ end
347
+
348
+ # Check if the `lscpu` data looks reasonable
349
+ def valid_lscpu?(lscpu)
350
+ return false if lscpu.empty?
351
+ return false if %i{total real cores}.any? { |key| lscpu[key].to_i == 0 }
352
+
353
+ true
354
+ end
355
+
356
+ collect_data(:linux) do
357
+ cpuinfo = parse_cpuinfo
358
+ lscpu = parse_lscpu(cpuinfo)
359
+
360
+ # If we don't have any sensible data from lscpu then get it from /proc/cpuinfo
361
+ if valid_lscpu?(lscpu)
362
+ cpu lscpu
363
+ else
364
+ cpu cpuinfo
365
+ end
366
+ end
367
+
368
+ collect_data(:freebsd) do
369
+ # all dmesg output for smp I can find only provides info about a single processor
370
+ # identical processors is probably a hardware requirement so we'll duplicate data for each cpu
371
+ # old examples: http://www.bnv-bamberg.de/home/ba3294/smp/rbuild/index.htm
372
+
373
+ # /var/run/dmesg.boot
374
+ # CPU: Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz (2793.59-MHz K8-class CPU)
375
+ # Origin="GenuineIntel" Id=0x40661 Family=0x6 Model=0x46 Stepping=1
376
+ # Features=0x783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2>
377
+ # Features2=0x5ed8220b<SSE3,PCLMULQDQ,MON,SSSE3,CX16,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,AVX,RDRAND>
378
+ # AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
379
+ # AMD Features2=0x21<LAHF,ABM>
380
+ # Structured Extended Features=0x2000<NFPUSG>
381
+ # TSC: P-state invariant
382
+ # ...
383
+ # FreeBSD/SMP: Multiprocessor System Detected: 16 CPUs
384
+ # FreeBSD/SMP: 2 package(s) x 4 core(s) x 2 SMT threads
385
+
386
+ info = parse_bsd_dmesg do |cpuinfo, line|
387
+ case line
388
+ when /Origin.*"(.*)".*Family.*0x(\S+).*Model.*0x(\S+).*Stepping.*(\S+)/
389
+ cpuinfo["vendor_id"] = $1
390
+ # convert from hex value to int, but keep a string to match Linux ohai
391
+ cpuinfo["family"] = $2.to_i(16).to_s
392
+ cpuinfo["model"] = $3.to_i(16).to_s
393
+ cpuinfo["stepping"] = $4
394
+ # These _should_ match /AMD Features2?/ lines as well
395
+ when %r{FreeBSD/SMP: Multiprocessor System Detected: (\d*) CPUs}
396
+ cpuinfo["total"] = $1.to_i
397
+ when %r{FreeBSD/SMP: (\d*) package\(s\) x (\d*) core\(s\)}
398
+ cpuinfo["real"] = $1.to_i
399
+ cpuinfo["cores"] = $1.to_i * $2.to_i
400
+ end
401
+ end
402
+ cpu info
403
+ end
404
+
405
+ collect_data(:dragonflybsd) do
406
+ # /var/run/dmesg.boot
407
+ # CPU: Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz (3516.61-MHz K8-class CPU)
408
+ # Origin = "GenuineIntel" Id = 0x306a9 Family = 6 Model = 3a Stepping = 9
409
+ # Features=0x783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2>
410
+ # Features2=0x209<SSE3,MON,SSSE3>
411
+ # AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
412
+ # AMD Features2=0x1<LAHF>
413
+
414
+ info = parse_bsd_dmesg do |cpuinfo, line|
415
+ case line
416
+ when /Origin = "(.+)"\s+Id = (.+)\s+Stepping = (.+)/
417
+ cpuinfo["vendor_id"] = $1
418
+ cpuinfo["stepping"] = $3
419
+ end
420
+ end
421
+
422
+ so = shell_out("sysctl -n hw.ncpu")
423
+ info[:total] = so.stdout.strip.to_i
424
+ cpu info
425
+ end
426
+
427
+ collect_data(:openbsd) do
428
+ cpuinfo = Mash.new
429
+
430
+ # OpenBSD provides most cpu information via sysctl, the only thing we need to
431
+ # to scrape from dmesg.boot is the cpu feature list.
432
+ # cpu0: FPU,V86,DE,PSE,TSC,MSR,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PAT,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,TM,SBF,EST,TM2
433
+
434
+ file_open("/var/run/dmesg.boot").each do |line|
435
+ case line
436
+ when /cpu\d+:\s+([A-Z]+$|[A-Z]+,.*$)/
437
+ cpuinfo["flags"] = $1.downcase.split(",")
438
+ end
439
+ end
440
+
441
+ [["hw.model", :model_name], ["hw.ncpu", :total], ["hw.cpuspeed", :mhz]].each do |param, node|
442
+ so = shell_out("sysctl -n #{param}")
443
+ cpuinfo[node] = so.stdout.strip
444
+ end
445
+
446
+ cpu cpuinfo
447
+ end
448
+
449
+ collect_data(:netbsd) do
450
+ cpuinfo = Mash.new
451
+
452
+ # NetBSD provides some cpu information via sysctl, and a little via dmesg.boot
453
+ # unlike OpenBSD and FreeBSD, NetBSD does not provide information about the
454
+ # available instruction set
455
+ # cpu0 at mainbus0 apid 0: Intel 686-class, 2134MHz, id 0x6f6
456
+
457
+ file_open("/var/run/dmesg.boot").each do |line|
458
+ case line
459
+ when /cpu[\d\w\s]+:\s([\w\s\-]+),\s+(\w+),/
460
+ cpuinfo[:model_name] = $1
461
+ cpuinfo[:mhz] = $2.gsub(/mhz/i, "")
462
+ end
463
+ end
464
+
465
+ flags = []
466
+ so = shell_out("dmidecode")
467
+ so.stdout.lines do |line|
468
+ if line =~ /^\s+([A-Z\d-]+)\s+\([\w\s-]+\)$/
469
+ flags << $1.downcase
470
+ end
471
+ end
472
+
473
+ cpuinfo[:flags] = flags unless flags.empty?
474
+
475
+ cpu cpuinfo
476
+ end
477
+
478
+ collect_data(:darwin) do
479
+ cpu Mash.new
480
+ shell_out("sysctl hw machdep").stdout.lines.each do |line|
481
+ case line
482
+ when /^hw.packages: (.*)$/
483
+ cpu[:real] = Regexp.last_match[1].to_i
484
+ when /^hw.physicalcpu: (.*)$/
485
+ cpu[:cores] = Regexp.last_match[1].to_i
486
+ when /^hw.logicalcpu: (.*)$/
487
+ cpu[:total] = Regexp.last_match[1].to_i
488
+ when /^hw.cpufrequency: (.*)$/
489
+ cpu[:mhz] = Regexp.last_match[1].to_i / 1000000
490
+ when /^machdep.cpu.vendor: (.*)$/
491
+ cpu[:vendor_id] = Regexp.last_match[1].chomp
492
+ when /^machdep.cpu.brand_string: (.*)$/
493
+ cpu[:model_name] = Regexp.last_match[1].chomp
494
+ when /^machdep.cpu.model: (.*)$/
495
+ cpu[:model] = Regexp.last_match[1].to_i
496
+ when /^machdep.cpu.family: (.*)$/
497
+ cpu[:family] = Regexp.last_match[1].to_i
498
+ when /^machdep.cpu.stepping: (.*)$/
499
+ cpu[:stepping] = Regexp.last_match[1].to_i
500
+ when /^machdep.cpu.features: (.*)$/
501
+ cpu[:flags] = Regexp.last_match[1].downcase.split
502
+ end
503
+ end
504
+ end
505
+
506
+ collect_data(:aix) do
507
+ cpu Mash.new
508
+
509
+ cpu[:total] = shell_out("pmcycles -m").stdout.lines.length
510
+
511
+ # The below is only relevant on an LPAR
512
+ if shell_out("uname -W").stdout.strip == "0"
513
+
514
+ # At least one CPU will be available, but we'll wait to increment this later.
515
+ cpu[:available] = 0
516
+
517
+ cpudevs = shell_out("lsdev -Cc processor").stdout.lines
518
+ # from http://www-01.ibm.com/software/passportadvantage/pvu_terminology_for_customers.html
519
+ # on AIX number of cores and processors are considered same
520
+ cpu[:real] = cpu[:cores] = cpudevs.length
521
+ cpudevs.each.with_index do |c, i|
522
+ name, status, location = c.split
523
+ index = i.to_s
524
+ cpu[index] = Mash.new
525
+ cpu[index][:status] = status
526
+ cpu[index][:location] = location
527
+ if status.include?("Available")
528
+ cpu[:available] += 1
529
+ lsattr = shell_out("lsattr -El #{name}").stdout.lines
530
+ lsattr.each do |attribute|
531
+ attrib, value = attribute.split
532
+ if attrib == "type"
533
+ cpu[index][:model_name] = value
534
+ elsif attrib == "frequency"
535
+ cpu[index][:mhz] = value.to_i / (1000 * 1000) # convert from hz to MHz
536
+ else
537
+ cpu[index][attrib] = value
538
+ end
539
+ end
540
+ # IBM is the only maker of CPUs for AIX systems.
541
+ cpu[index][:vendor_id] = "IBM"
542
+ end
543
+ end
544
+ end
545
+ end
546
+
547
+ collect_data(:solaris2) do
548
+ cpu Mash.new
549
+ # This does assume that /usr/bin/kstat is in the path
550
+ processor_info = shell_out("kstat -p cpu_info").stdout.lines
551
+ cpu["total"] = 0
552
+ cpu["sockets"] = 0
553
+ cpu["cores"] = 0
554
+ cpu["corethreads"] = 0
555
+ cpu["cpustates"] = Mash.new
556
+
557
+ currentcpu = 0
558
+ cpucores = []
559
+ cpusockets = []
560
+ processor_info.each do |processor|
561
+ _desc, instance, _record, keyvalue = processor.split(":")
562
+ cpu[instance] ||= Mash.new
563
+ if currentcpu != instance
564
+ cpu["total"] += 1
565
+ currentcpu = instance
566
+ end
567
+ kv = keyvalue.split(/\s+/)
568
+ key = kv.shift
569
+ value = kv.join(" ").chomp
570
+ case key
571
+ when /chip_id/
572
+ cpu[instance]["socket"] = value
573
+ cpusockets.push(value) if cpusockets.index(value).nil?
574
+ when /cpu_type/
575
+ cpu[instance]["arch"] = value
576
+ when /clock_MHz/
577
+ cpu[instance]["mhz"] = value
578
+ when /brand/
579
+ cpu[instance]["model_name"] = value.sub(/\s+/, " ")
580
+ when /^state$/
581
+ cpu[instance]["state"] = value
582
+ cpu["cpustates"][value] ||= 0
583
+ cpu["cpustates"][value] += 1
584
+ when /core_id/
585
+ cpu[instance]["core_id"] = value
586
+ # Detect hyperthreading/multithreading
587
+ cpucores.push(value) if cpucores.index(value).nil?
588
+ when /family|fpu_type|model|stepping|vendor_id/
589
+ cpu[instance][key] = value
590
+ end
591
+ end
592
+ cpu["cores"] = cpucores.size
593
+ cpu["corethreads"] = (cpu["total"] / cpucores.size)
594
+ cpu["sockets"] = cpusockets.size
595
+ cpu["real"] = cpusockets.size
596
+ end
597
+
598
+ collect_data(:windows) do
599
+ require "wmi-lite/wmi" unless defined?(WmiLite::Wmi)
600
+
601
+ cpu Mash.new
602
+ cores = 0
603
+ logical_processors = 0
604
+
605
+ wmi = WmiLite::Wmi.new
606
+ processors = wmi.instances_of("Win32_Processor")
607
+
608
+ processors.each_with_index do |processor, index|
609
+ current_cpu = index.to_s
610
+ cpu[current_cpu] = Mash.new
611
+
612
+ cpu[current_cpu]["cores"] = processor["numberofcores"]
613
+ cores += processor["numberofcores"]
614
+
615
+ logical_processors += processor["numberoflogicalprocessors"]
616
+ cpu[current_cpu]["vendor_id"] = processor["manufacturer"]
617
+ cpu[current_cpu]["family"] = processor["family"].to_s
618
+ cpu[current_cpu]["model"] = processor["revision"].to_s
619
+ cpu[current_cpu]["stepping"] = if processor["stepping"].nil?
620
+ processor["description"].match(/Stepping\s+(\d+)/)[1]
621
+ else
622
+ processor["stepping"]
623
+ end
624
+ cpu[current_cpu]["physical_id"] = processor["deviceid"]
625
+ cpu[current_cpu]["model_name"] = processor["name"]
626
+ cpu[current_cpu]["description"] = processor["description"]
627
+ cpu[current_cpu]["mhz"] = processor["maxclockspeed"].to_s
628
+ cpu[current_cpu]["cache_size"] = "#{processor["l2cachesize"]} KB"
629
+ end
630
+
631
+ cpu[:total] = logical_processors
632
+ cpu[:cores] = cores
633
+ cpu[:real] = processors.length
634
+ end
635
+ end