sys-cpu 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,784 @@
1
+ require 'win32ole'
2
+ require 'socket'
3
+
4
+ # The Sys module serves only as a namespace
5
+ module Sys
6
+ # Encapsulates system CPU information
7
+ class CPU
8
+ # Error raised if any of the Sys::CPU methods fail.
9
+ class Error < StandardError; end
10
+
11
+ # The version of this library
12
+ VERSION = '0.6.2'
13
+
14
+ # Base connect string
15
+ BASE_CS = "winmgmts:{impersonationLevel=impersonate}" # :nodoc:
16
+
17
+ # Fields used in the CPUStruct
18
+ fields = %w/
19
+ address_width
20
+ architecture
21
+ availability
22
+ caption
23
+ config_manager_error_code
24
+ config_manager_user_config
25
+ cpu_status
26
+ creation_class_name
27
+ freq
28
+ voltage
29
+ data_width
30
+ description
31
+ device_id
32
+ error_cleared?
33
+ error_description
34
+ ext_clock
35
+ family
36
+ install_date
37
+ l2_cache_size
38
+ l2_cache_speed
39
+ last_error_code
40
+ level
41
+ load_avg
42
+ manufacturer
43
+ max_clock_speed
44
+ name
45
+ other_family_description
46
+ pnp_device_id
47
+ power_management_supported?
48
+ power_management_capabilities
49
+ processor_id
50
+ processor_type
51
+ revision
52
+ role
53
+ socket_designation
54
+ status
55
+ status_info
56
+ stepping
57
+ system_creation_class_name
58
+ system_name
59
+ unique_id
60
+ upgrade_method
61
+ version
62
+ voltage_caps
63
+ /
64
+
65
+ # The struct returned by the CPU.processors method
66
+ CPUStruct = Struct.new("CPUStruct", *fields) # :nodoc:
67
+
68
+ # Returns the +host+ CPU's architecture, or nil if it cannot be
69
+ # determined.
70
+ #
71
+ def self.architecture(host=Socket.gethostname)
72
+ cs = BASE_CS + "//#{host}/root/cimv2:Win32_Processor='cpu0'"
73
+ begin
74
+ wmi = WIN32OLE.connect(cs)
75
+ rescue WIN32OLERuntimeError => e
76
+ raise Error, e
77
+ else
78
+ self.get_cpu_arch(wmi.Architecture)
79
+ end
80
+ end
81
+
82
+ # Returns an integer indicating the speed (i.e. frequency in Mhz) of
83
+ # +cpu_num+ on +host+, or the localhost if no +host+ is specified.
84
+ # If +cpu_num+ +1 is greater than the number of cpu's on your system
85
+ # or this call fails for any other reason, a Error is raised.
86
+ #
87
+ def self.freq(cpu_num = 0, host = Socket.gethostname)
88
+ cs = BASE_CS + "//#{host}/root/cimv2:Win32_Processor='cpu#{cpu_num}'"
89
+ begin
90
+ wmi = WIN32OLE.connect(cs)
91
+ rescue WIN32OLERuntimeError => e
92
+ raise Error, e
93
+ else
94
+ return wmi.CurrentClockSpeed
95
+ end
96
+ end
97
+
98
+ # Returns the load capacity for +cpu_num+ on +host+, or the localhost
99
+ # if no host is specified, averaged to the last second. Processor
100
+ # loading refers to the total computing burden for each processor at
101
+ # one time.
102
+ #
103
+ # Note that this attribute is actually the LoadPercentage. I may use
104
+ # one of the Win32_Perf* classes in the future.
105
+ #
106
+ def self.load_avg(cpu_num = 0, host = Socket.gethostname)
107
+ cs = BASE_CS + "//#{host}/root/cimv2:Win32_Processor='cpu#{cpu_num}'"
108
+ begin
109
+ wmi = WIN32OLE.connect(cs)
110
+ rescue WIN32OLERuntimeError => e
111
+ raise Error, e
112
+ else
113
+ return wmi.LoadPercentage
114
+ end
115
+ end
116
+
117
+ # Returns a string indicating the cpu model, e.g. Intel Pentium 4.
118
+ #
119
+ def self.model(host = Socket.gethostname)
120
+ cs = BASE_CS + "//#{host}/root/cimv2:Win32_Processor='cpu0'"
121
+ begin
122
+ wmi = WIN32OLE.connect(cs)
123
+ rescue WIN32OLERuntimeError => e
124
+ raise Error, e
125
+ else
126
+ return wmi.Name
127
+ end
128
+ end
129
+
130
+ # Returns an integer indicating the number of cpu's on the system.
131
+ #--
132
+ # This (oddly) requires a different class.
133
+ #
134
+ def self.num_cpu(host = Socket.gethostname)
135
+ cs = BASE_CS + "//#{host}/root/cimv2:Win32_ComputerSystem='#{host}'"
136
+ begin
137
+ wmi = WIN32OLE.connect(cs)
138
+ rescue WIN32OLERuntimeError => e
139
+ raise Error, e
140
+ else
141
+ return wmi.NumberOfProcessors
142
+ end
143
+ end
144
+
145
+ # Returns a CPUStruct for each CPU on +host+, or the localhost if no
146
+ # +host+ is specified. A CPUStruct contains the following members:
147
+ #
148
+ # * address_width
149
+ # * architecture
150
+ # * availability
151
+ # * caption
152
+ # * config_manager_error_code
153
+ # * config_manager_user_config
154
+ # * cpu_status
155
+ # * creation_class_name
156
+ # * freq
157
+ # * voltage
158
+ # * data_width
159
+ # * description
160
+ # * device_id
161
+ # * error_cleared?
162
+ # * error_description
163
+ # * ext_clock
164
+ # * family
165
+ # * install_date
166
+ # * l2_cache_size
167
+ # * l2_cache_speed
168
+ # * last_error_code
169
+ # * level
170
+ # * load_avg
171
+ # * manufacturer
172
+ # * max_clock_speed
173
+ # * name
174
+ # * other_family_description
175
+ # * pnp_device_id
176
+ # * power_management_supported?
177
+ # * power_management_capabilities
178
+ # * processor_id
179
+ # * processor_type
180
+ # * revision
181
+ # * role
182
+ # * socket_designation
183
+ # * status
184
+ # * status_info
185
+ # * stepping
186
+ # * system_creation_class_name
187
+ # * system_name
188
+ # * unique_id
189
+ # * upgrade_method
190
+ # * version
191
+ # * voltage_caps
192
+ #
193
+ # Note that not all of these members will necessarily be defined.
194
+ #
195
+ def self.processors(host = Socket.gethostname) # :yields: CPUStruct
196
+ begin
197
+ wmi = WIN32OLE.connect(BASE_CS + "//#{host}/root/cimv2")
198
+ rescue WIN32OLERuntimeError => e
199
+ raise Error, e
200
+ else
201
+ wmi.InstancesOf("Win32_Processor").each{ |cpu|
202
+ yield CPUStruct.new(
203
+ cpu.AddressWidth,
204
+ self.get_cpu_arch(cpu.Architecture),
205
+ self.get_availability(cpu.Availability),
206
+ cpu.Caption,
207
+ self.get_cmec(cpu.ConfigManagerErrorCode),
208
+ cpu.ConfigManagerUserConfig,
209
+ get_status(cpu.CpuStatus),
210
+ cpu.CreationClassName,
211
+ cpu.CurrentClockSpeed,
212
+ cpu.CurrentVoltage,
213
+ cpu.DataWidth,
214
+ cpu.Description,
215
+ cpu.DeviceId,
216
+ cpu.ErrorCleared,
217
+ cpu.ErrorDescription,
218
+ cpu.ExtClock,
219
+ self.get_family(cpu.Family),
220
+ cpu.InstallDate,
221
+ cpu.L2CacheSize,
222
+ cpu.L2CacheSpeed,
223
+ cpu.LastErrorCode,
224
+ cpu.Level,
225
+ cpu.LoadPercentage,
226
+ cpu.Manufacturer,
227
+ cpu.MaxClockSpeed,
228
+ cpu.Name,
229
+ cpu.OtherFamilyDescription,
230
+ cpu.PNPDeviceID,
231
+ cpu.PowerManagementSupported,
232
+ cpu.PowerManagementCapabilities,
233
+ cpu.ProcessorId,
234
+ self.get_processor_type(cpu.ProcessorType),
235
+ cpu.Revision,
236
+ cpu.Role,
237
+ cpu.SocketDesignation,
238
+ cpu.Status,
239
+ cpu.StatusInfo,
240
+ cpu.Stepping,
241
+ cpu.SystemCreationClassName,
242
+ cpu.SystemName,
243
+ cpu.UniqueId,
244
+ self.get_upgrade_method(cpu.UpgradeMethod),
245
+ cpu.Version,
246
+ self.get_voltage_caps(cpu.VoltageCaps)
247
+ )
248
+ }
249
+ end
250
+ end
251
+
252
+ # Returns a string indicating the type of processor, e.g. GenuineIntel.
253
+ #
254
+ def self.type(host = Socket.gethostname)
255
+ cs = BASE_CS + "//#{host}/root/cimv2:Win32_Processor='cpu0'"
256
+ begin
257
+ wmi = WIN32OLE.connect(cs)
258
+ rescue WIN32OLERuntimeError => e
259
+ raise Error, e
260
+ else
261
+ return wmi.Manufacturer
262
+ end
263
+ end
264
+
265
+ private
266
+
267
+ # Convert the ConfigManagerErrorCode number to its corresponding string
268
+ # Note that this value returns nil on my system.
269
+ #
270
+ def self.get_cmec(num)
271
+ case
272
+ when 0
273
+ str = "The device is working properly."
274
+ return str
275
+ when 1
276
+ str = "The device is not configured correctly."
277
+ return str
278
+ when 2
279
+ str = "Windows cannot load the driver for the device."
280
+ return str
281
+ when 3
282
+ str = "The driver for the device might be corrupted, or the"
283
+ str << " system may be running low on memory or other"
284
+ str << " resources."
285
+ return str
286
+ when 4
287
+ str = "The device is not working properly. One of the drivers"
288
+ str << " or the registry might be corrupted."
289
+ return str
290
+ when 5
291
+ str = "The driver for this device needs a resource that"
292
+ str << " Windows cannot manage."
293
+ return str
294
+ when 6
295
+ str = "The boot configuration for this device conflicts with"
296
+ str << " other devices."
297
+ return str
298
+ when 7
299
+ str = "Cannot filter."
300
+ return str
301
+ when 8
302
+ str = "The driver loader for the device is missing."
303
+ return str
304
+ when 9
305
+ str = "This device is not working properly because the"
306
+ str << " controlling firmware is reporting the resources"
307
+ str << " for the device incorrectly."
308
+ return str
309
+ when 10
310
+ str = "This device cannot start."
311
+ return str
312
+ when 11
313
+ str = "This device failed."
314
+ return str
315
+ when 12
316
+ str = "This device cannot find enough free resources that"
317
+ str << " it can use."
318
+ return str
319
+ when 13
320
+ str = "Windows cannot verify this device's resources."
321
+ return str
322
+ when 14
323
+ str = "This device cannot work properly until you restart"
324
+ str << " your computer."
325
+ return str
326
+ when 15
327
+ str = "This device is not working properly because there is"
328
+ str << " probably a re-enumeration problem."
329
+ return str
330
+ when 16
331
+ str = "Windows cannot identify all the resources this device "
332
+ str << " uses."
333
+ return str
334
+ when 17
335
+ str = "This device is asking for an unknown resource type."
336
+ return str
337
+ when 18
338
+ str = "Reinstall the drivers for this device."
339
+ return str
340
+ when 19
341
+ str = "Failure using the VXD loader."
342
+ return str
343
+ when 20
344
+ str = "Your registry might be corrupted."
345
+ return str
346
+ when 21
347
+ str = "System failure: try changing the driver for this device."
348
+ str << " If that does not work, see your hardware documentation."
349
+ str << " Windows is removing this device."
350
+ return str
351
+ when 22
352
+ str = "This device is disabled."
353
+ return str
354
+ when 23
355
+ str = "System failure: try changing the driver for this device."
356
+ str << "If that doesn't work, see your hardware documentation."
357
+ return str
358
+ when 24
359
+ str = "This device is not present, not working properly, or"
360
+ str << " does not have all its drivers installed."
361
+ return str
362
+ when 25
363
+ str = "Windows is still setting up this device."
364
+ return str
365
+ when 26
366
+ str = "Windows is still setting up this device."
367
+ return str
368
+ when 27
369
+ str = "This device does not have valid log configuration."
370
+ return str
371
+ when 28
372
+ str = "The drivers for this device are not installed."
373
+ return str
374
+ when 29
375
+ str = "This device is disabled because the firmware of the"
376
+ str << " device did not give it the required resources."
377
+ return str
378
+ when 30
379
+ str = "This device is using an Interrupt Request (IRQ)"
380
+ str << " resource that another device is using."
381
+ return str
382
+ when 31
383
+ str = "This device is not working properly because Windows"
384
+ str << " cannot load the drivers required for this device"
385
+ return str
386
+ else
387
+ return nil
388
+ end
389
+ end
390
+
391
+ # Convert an cpu architecture number to a string
392
+ def self.get_cpu_arch(num)
393
+ case num
394
+ when 0
395
+ return "x86"
396
+ when 1
397
+ return "MIPS"
398
+ when 2
399
+ return "Alpha"
400
+ when 3
401
+ return "PowerPC"
402
+ when 4
403
+ return "IA64"
404
+ else
405
+ return nil
406
+ end
407
+ end
408
+
409
+ # convert an Availability number into a string
410
+ def self.get_availability(num)
411
+ case num
412
+ when 1
413
+ return "Other"
414
+ when 2
415
+ return "Unknown"
416
+ when 3
417
+ return "Running"
418
+ when 4
419
+ return "Warning"
420
+ when 5
421
+ return "In Test"
422
+ when 6
423
+ return "Not Applicable"
424
+ when 7
425
+ return "Power Off"
426
+ when 8
427
+ return "Off Line"
428
+ when 9
429
+ return "Off Duty"
430
+ when 10
431
+ return "Degraded"
432
+ when 11
433
+ return "Not Installed"
434
+ when 12
435
+ return "Install Error"
436
+ when 13
437
+ return "Power Save - Unknown"
438
+ when 14
439
+ return "Power Save - Low Power Mode"
440
+ when 15
441
+ return "Power Save - Standby"
442
+ when 16
443
+ return "Power Cycle"
444
+ when 17
445
+ return "Power Save - Warning"
446
+ when 18
447
+ return "Paused"
448
+ when 19
449
+ return "Not Ready"
450
+ when 20
451
+ return "Not Configured"
452
+ when 21
453
+ return "Quiesced"
454
+ else
455
+ return nil
456
+ end
457
+ end
458
+
459
+ # convert CpuStatus to a string form. Note that values 5 and 6 are
460
+ # skipped because they're reserved.
461
+ def self.get_status(num)
462
+ case num
463
+ when 0
464
+ return "Unknown"
465
+ when 1
466
+ return "Enabled"
467
+ when 2
468
+ return "Disabled by User via BIOS Setup"
469
+ when 3
470
+ return "Disabled By BIOS (POST Error)"
471
+ when 4
472
+ return "Idle"
473
+ when 7
474
+ return "Other"
475
+ else
476
+ return nil
477
+ end
478
+ end
479
+
480
+ # Convert a family number into the equivalent string
481
+ def self.get_family(num)
482
+ case num
483
+ when 1
484
+ return "Other"
485
+ when 2
486
+ return "Unknown"
487
+ when 3
488
+ return "8086"
489
+ when 4
490
+ return "80286"
491
+ when 5
492
+ return "80386"
493
+ when 6
494
+ return "80486"
495
+ when 7
496
+ return "8087"
497
+ when 8
498
+ return "80287"
499
+ when 9
500
+ return "80387"
501
+ when 10
502
+ return "80487"
503
+ when 11
504
+ return "Pentium?"
505
+ when 12
506
+ return "Pentium?"
507
+ when 13
508
+ return "Pentium?"
509
+ when 14
510
+ return "Pentium?"
511
+ when 15
512
+ return "Celeron?"
513
+ when 16
514
+ return "Pentium?"
515
+ when 17
516
+ return "Pentium?"
517
+ when 18
518
+ return "M1"
519
+ when 19
520
+ return "M2"
521
+ when 24
522
+ return "K5"
523
+ when 25
524
+ return "K6"
525
+ when 26
526
+ return "K6-2"
527
+ when 27
528
+ return "K6-3"
529
+ when 28
530
+ return "AMD"
531
+ when 29
532
+ return "AMD?"
533
+ when 30
534
+ return "AMD2900"
535
+ when 31
536
+ return "K6-2+"
537
+ when 32
538
+ return "Power"
539
+ when 33
540
+ return "Power"
541
+ when 34
542
+ return "Power"
543
+ when 35
544
+ return "Power"
545
+ when 36
546
+ return "Power"
547
+ when 37
548
+ return "Power"
549
+ when 38
550
+ return "Power"
551
+ when 39
552
+ return "Power"
553
+ when 48
554
+ return "Alpha"
555
+ when 49
556
+ return "Alpha"
557
+ when 50
558
+ return "Alpha"
559
+ when 51
560
+ return "Alpha"
561
+ when 52
562
+ return "Alpha"
563
+ when 53
564
+ return "Alpha"
565
+ when 54
566
+ return "Alpha"
567
+ when 55
568
+ return "Alpha"
569
+ when 64
570
+ return "MIPS"
571
+ when 65
572
+ return "MIPS"
573
+ when 66
574
+ return "MIPS"
575
+ when 67
576
+ return "MIPS"
577
+ when 68
578
+ return "MIPS"
579
+ when 69
580
+ return "MIPS"
581
+ when 80
582
+ return "SPARC"
583
+ when 81
584
+ return "SuperSPARC"
585
+ when 82
586
+ return "microSPARC"
587
+ when 83
588
+ return "microSPARC"
589
+ when 84
590
+ return "UltraSPARC"
591
+ when 85
592
+ return "UltraSPARC"
593
+ when 86
594
+ return "UltraSPARC"
595
+ when 87
596
+ return "UltraSPARC"
597
+ when 88
598
+ return "UltraSPARC"
599
+ when 96
600
+ return "68040"
601
+ when 97
602
+ return "68xxx"
603
+ when 98
604
+ return "68000"
605
+ when 99
606
+ return "68010"
607
+ when 100
608
+ return "68020"
609
+ when 101
610
+ return "68030"
611
+ when 112
612
+ return "Hobbit"
613
+ when 120
614
+ return "Crusoe?"
615
+ when 121
616
+ return "Crusoe?"
617
+ when 128
618
+ return "Weitek"
619
+ when 130
620
+ return "Itanium?"
621
+ when 144
622
+ return "PA-RISC"
623
+ when 145
624
+ return "PA-RISC"
625
+ when 146
626
+ return "PA-RISC"
627
+ when 147
628
+ return "PA-RISC"
629
+ when 148
630
+ return "PA-RISC"
631
+ when 149
632
+ return "PA-RISC"
633
+ when 150
634
+ return "PA-RISC"
635
+ when 160
636
+ return "V30"
637
+ when 176
638
+ return "Pentium?"
639
+ when 177
640
+ return "Pentium?"
641
+ when 178
642
+ return "Pentium?"
643
+ when 179
644
+ return "Intel?"
645
+ when 180
646
+ return "AS400"
647
+ when 181
648
+ return "Intel?"
649
+ when 182
650
+ return "AMD"
651
+ when 183
652
+ return "AMD"
653
+ when 184
654
+ return "Intel?"
655
+ when 185
656
+ return "AMD"
657
+ when 190
658
+ return "K7"
659
+ when 200
660
+ return "IBM390"
661
+ when 201
662
+ return "G4"
663
+ when 202
664
+ return "G5"
665
+ when 250
666
+ return "i860"
667
+ when 251
668
+ return "i960"
669
+ when 260
670
+ return "SH-3"
671
+ when 261
672
+ return "SH-4"
673
+ when 280
674
+ return "ARM"
675
+ when 281
676
+ return "StrongARM"
677
+ when 300
678
+ return "6x86"
679
+ when 301
680
+ return "MediaGX"
681
+ when 302
682
+ return "MII"
683
+ when 320
684
+ return "WinChip"
685
+ when 350
686
+ return "DSP"
687
+ when 500
688
+ return "Video"
689
+ else
690
+ return nil
691
+ end
692
+ end
693
+
694
+ # Convert power management capabilities number to its equivalent string
695
+ def self.get_pmc(num)
696
+ case num
697
+ when 0
698
+ return "Unknown"
699
+ when 1
700
+ return "Not Supported"
701
+ when 2
702
+ return "Disabled"
703
+ when 3
704
+ return "Enabled"
705
+ when 4
706
+ return "Power Saving Modes Entered Automatically"
707
+ when 5
708
+ return "Power State Settable"
709
+ when 6
710
+ return "Power Cycling Supported"
711
+ when 7
712
+ return "Timed Power On Supported"
713
+ else
714
+ return nil
715
+ end
716
+ end
717
+
718
+ # Convert a processor type into its equivalent string
719
+ def self.get_processor_type(num)
720
+ case num
721
+ when 1
722
+ return "Other"
723
+ when 2
724
+ return "Unknown"
725
+ when 3
726
+ return "Central Processor"
727
+ when 4
728
+ return "Math Processor"
729
+ when 5
730
+ return "DSP Processor"
731
+ when 6
732
+ return "Video Processor"
733
+ else
734
+ return nil
735
+ end
736
+ end
737
+
738
+ # Convert an upgrade method into its equivalent string
739
+ def self.get_upgrade_method(num)
740
+ case num
741
+ when 1
742
+ return "Other"
743
+ when 2
744
+ return "Unknown"
745
+ when 3
746
+ return "Daughter Board"
747
+ when 4
748
+ return "ZIF Socket"
749
+ when 5
750
+ return "Replacement/Piggy Back"
751
+ when 6
752
+ return "None"
753
+ when 7
754
+ return "LIF Socket"
755
+ when 8
756
+ return "Slot 1"
757
+ when 9
758
+ return "Slot 2"
759
+ when 10
760
+ return "370 Pin Socket"
761
+ when 11
762
+ return "Slot A"
763
+ when 12
764
+ return "Slot M"
765
+ else
766
+ return nil
767
+ end
768
+ end
769
+
770
+ # Convert return values to voltage cap values (floats)
771
+ def self.get_voltage_caps(num)
772
+ case num
773
+ when 1
774
+ return 5.0
775
+ when 2
776
+ return 3.3
777
+ when 4
778
+ return 2.9
779
+ else
780
+ return nil
781
+ end
782
+ end
783
+ end
784
+ end