ohai 18.2.6 → 19.0.3

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