boris 1.0.1 → 1.0.2

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.
data/lib/boris/errors.rb CHANGED
@@ -1,17 +1,21 @@
1
1
  module Boris
2
- class MissingCredentials < Exception; end
3
2
 
4
3
  class ConnectionFailed < StandardError; end
5
4
 
6
5
  class ConnectionAlreadyActive < StandardError; end
7
6
 
7
+ class InvalidCredentials < ConnectionFailed; end
8
+
9
+ class InvalidOption < StandardError; end
10
+
11
+ class InvalidTargetName < StandardError; end
12
+
13
+ class MissingCredentials < Exception; end
14
+
8
15
  class NoActiveConnection < StandardError; end
9
16
 
10
17
  class NoProfilerDetected < StandardError; end
11
18
 
12
- class InvalidOption < StandardError; end
13
-
14
- class InvalidCredentials < ConnectionFailed; end
19
+ class PasswordExpired < StandardError; end
15
20
 
16
- class InvalidTargetName < StandardError; end
17
21
  end
@@ -0,0 +1,7 @@
1
+ require 'boris/helpers/array'
2
+ require 'boris/helpers/constants'
3
+ require 'boris/helpers/hash'
4
+ require 'boris/helpers/network'
5
+ require 'boris/helpers/scrubber'
6
+ require 'boris/helpers/string'
7
+ require 'boris/helpers/time'
@@ -1,9 +1,9 @@
1
1
  class Array
2
- def strip_string_values_in_array
2
+ def clean_string_values_in_array
3
3
  self.map! do |val|
4
- val.strip_string_values_in_array if val.is_a?(Array)
5
- val.strip_string_values_in_hash if val.is_a?(Hash)
6
- val.is_a?(String) ? val.strip : val
4
+ val.clean_string_values_in_array if val.is_a?(Array)
5
+ val.clean_string_values_in_hash if val.is_a?(Hash)
6
+ val.is_a?(String) ? val.strip.clean_string : val
7
7
  end
8
8
  end
9
9
 
@@ -18,6 +18,15 @@ module Boris
18
18
  VENDOR_SUSE = 'SUSE Linux GmbH'
19
19
  VENDOR_VMWARE = 'VMware, Inc.'
20
20
 
21
- PORT_DEFAULTS = {:ssh=>22, :wmi=>135}
22
- VALID_CONNECTION_TYPES = [:snmp, :ssh, :wmi]
21
+ PORT_DEFAULTS = {:ssh=>22, :wmi=>135}
22
+ VALID_CONNECTION_TYPES = [:snmp, :ssh, :wmi]
23
+
24
+ CONN_FAILURE_AUTH_FAILED = 'authentication failed'
25
+ CONN_FAILURE_HOST_KEY_MISMATCH = 'connection failed (ssh: host key mismatch)'
26
+ CONN_FAILURE_NO_HOST = 'connection failed (no such host)'
27
+ CONN_FAILURE_RPC_FILTERED = 'connection failed (wmi: rpc calls canceled by remote message filter)'
28
+ CONN_FAILURE_RPC_UNAVAILABLE = 'connection failed (wmi: rpc server unavailable)'
29
+ CONN_FAILURE_LOCAL_CREDENTIALS = 'connection failed (wmi: credentials used locally, will try again)'
30
+ CONN_FAILURE_PASSWORD_EXPIRED = 'connection failed (password expired, requires changing)'
31
+
23
32
  end
@@ -1,8 +1,8 @@
1
1
  class Hash
2
- def strip_string_values_in_hash
2
+ def clean_string_values_in_hash
3
3
  self.each_pair do |key, val|
4
- val.strip_string_values_in_array if val.is_a?(Array)
5
- self[key] = val.strip if val.is_a?(String)
4
+ val.clean_string_values_in_array if val.is_a?(Array)
5
+ self[key] = val.strip.clean_string if val.is_a?(String)
6
6
  end
7
7
  end
8
8
  end
@@ -10,24 +10,26 @@ module Boris
10
10
  @installed_services,
11
11
  @local_user_groups,
12
12
  @network_interfaces
13
- ].each {|arr| arr.strip_string_values_in_array}
13
+ ].collect {|arr| arr.clean_string_values_in_array if arr}
14
14
  debug 'string values from within data arrays cleaned up'
15
15
 
16
- [@hardware, @network_id, @operating_system].each {|h| h.strip_string_values_in_hash}
16
+ [@hardware, @network_id, @operating_system].collect {|h| h.clean_string_values_in_hash if h}
17
17
  debug 'string values from within data hashes cleaned up'
18
18
 
19
- @installed_applications.each do |app|
19
+ @installed_applications.collect do |app|
20
20
  app[:license_key].upcase! unless !app[:license_key]
21
- app[:name].string_clean
21
+ app[:name].clean_string
22
22
  app[:vendor].format_vendor unless !app[:vendor]
23
- end
23
+ end if @installed_applications
24
24
  debug 'installed application data cleaned up'
25
25
 
26
- @network_id[:hostname].upcase!
27
- @network_id[:domain].downcase! unless !@network_id[:domain]
26
+ if @network_id
27
+ @network_id[:hostname].upcase! unless !@network_id[:hostname]
28
+ @network_id[:domain].downcase! unless !@network_id[:domain]
29
+ end
28
30
  debug 'network id data cleaned up'
29
31
 
30
- @network_interfaces.each do |interface|
32
+ @network_interfaces.collect do |interface|
31
33
  interface[:fabric_name].downcase! unless !interface[:fabric_name]
32
34
  interface[:mac_address].upcase! unless !interface[:mac_address]
33
35
  interface[:model] = interface[:model].format_model unless !interface[:model]
@@ -35,16 +37,21 @@ module Boris
35
37
  interface[:port_wwn].downcase! unless !interface[:port_wwn]
36
38
  interface[:remote_mac_address].upcase! unless !interface[:remote_mac_address]
37
39
  interface[:vendor] = interface[:vendor].format_vendor unless !interface[:vendor]
38
- end
40
+ end if @network_interfaces
39
41
  debug 'network interface data cleaned up'
40
42
 
41
- @hardware[:cpu_vendor] = @hardware[:cpu_vendor].string_clean.format_vendor unless !@hardware[:cpu_vendor]
42
- @hardware[:model] = @hardware[:model].format_model unless !@hardware[:model]
43
- @hardware[:serial] = @hardware[:serial].format_serial unless !@hardware[:serial]
44
- @hardware[:vendor] = @hardware[:vendor].string_clean.format_vendor unless !@hardware[:vendor]
43
+ if @hardware
44
+ @hardware[:cpu_model] = @hardware[:cpu_model].clean_string unless !@hardware[:cpu_model]
45
+ @hardware[:cpu_vendor] = @hardware[:cpu_vendor].clean_string.format_vendor unless !@hardware[:cpu_vendor]
46
+ @hardware[:model] = @hardware[:model].format_model unless !@hardware[:model]
47
+ @hardware[:serial] = @hardware[:serial].format_serial unless !@hardware[:serial]
48
+ @hardware[:vendor] = @hardware[:vendor].clean_string.format_vendor unless !@hardware[:vendor]
49
+ end
45
50
  debug 'hardware data cleaned up'
46
51
 
47
- @operating_system[:license_key].upcase! unless !@operating_system[:license_key]
52
+ if @operating_system
53
+ @operating_system[:license_key].upcase! unless !@operating_system[:license_key]
54
+ end
48
55
  debug 'operating system data cleaned up'
49
56
 
50
57
  debug 'data scrubbing complete'
@@ -148,7 +148,7 @@ class String
148
148
  def format_serial
149
149
  return nil if self =~ /(^$|\(*none\)*)/i
150
150
 
151
- self.string_clean.upcase
151
+ self.clean_string.upcase
152
152
  end
153
153
 
154
154
  # Attempts to grab the hardware vendor name from self and formats it for
@@ -186,30 +186,6 @@ class String
186
186
  vendor.strip
187
187
  end
188
188
 
189
- # Allows you to specify your own delimiter to grab the string value found
190
- # after the last delimiter. It's mainly used internally with the
191
- # #after_ helper methods.
192
- #
193
- # 'A&B&C'.value_after_character('&') #=> "C"
194
- #
195
- # @return [Nil, String] returns the found value, else returns nil
196
- def value_after_character(delimiter)
197
- x = self.scan(/^.*[#{delimiter}](.*)$/)
198
- x.empty? ? nil : x.join.strip
199
- end
200
-
201
- # Allows you to specify your own delimiter to grab the string value found
202
- # before the first delimiter. It's mainly used internally with the
203
- # #after_ helper methods.
204
- #
205
- # 'A&B&C'.value_before_character('&') #=> "A"
206
- #
207
- # @return [Nil, String] returns the found value, else returns nil
208
- def value_before_character(delimiter)
209
- x = self.scan(/^(.*?)[#{delimiter}]/)
210
- x.empty? ? nil : x.join.strip
211
- end
212
-
213
189
  # Returns the IP address value derived from self in hex format.
214
190
  #
215
191
  # 'ffffff00'.hex_to_ip_address #=> "255.255.255.0"
@@ -239,14 +215,39 @@ class String
239
215
  # characters that are sometimes reported by devices. Also removes registered
240
216
  # (R) characters.
241
217
  #
242
- # 'Microsoft(R) Windows(R)'.string_clean #=> "Microsoft Windows"
243
- # "string with\u00A0 weird characters".string_clean #=> "string with weird characters"
218
+ # 'Microsoft(R) Windows(R)'.clean_string #=> "Microsoft Windows"
219
+ # "string with\u00A0 weird characters".clean_string #=> "string with weird characters"
244
220
  #
245
221
  # @return [String] the cleaned up string
246
- def string_clean
247
- # remove registered "(R)" mark
248
- string = self.gsub(/\(r\)/i, '')
222
+ def clean_string
223
+ # remove registered "(R)" and trademark "(tm)" marks
224
+ string = self.gsub(/\(r\)|\(tm\)/i, '')
225
+ string.gsub!(/\s+/, ' ')
249
226
 
250
227
  string.encode(Encoding.find('ASCII'), :undef=>:replace, :replace=>'').strip
251
228
  end
229
+
230
+ # Allows you to specify your own delimiter to grab the string value found
231
+ # after the last delimiter. It's mainly used internally with the
232
+ # #after_ helper methods.
233
+ #
234
+ # 'A&B&C'.value_after_character('&') #=> "C"
235
+ #
236
+ # @return [Nil, String] returns the found value, else returns nil
237
+ def value_after_character(delimiter)
238
+ x = self.scan(/^.*[#{delimiter}](.*)$/)
239
+ x.empty? ? nil : x.join.strip
240
+ end
241
+
242
+ # Allows you to specify your own delimiter to grab the string value found
243
+ # before the first delimiter. It's mainly used internally with the
244
+ # #after_ helper methods.
245
+ #
246
+ # 'A&B&C'.value_before_character('&') #=> "A"
247
+ #
248
+ # @return [Nil, String] returns the found value, else returns nil
249
+ def value_before_character(delimiter)
250
+ x = self.scan(/^(.*?)[#{delimiter}]/)
251
+ x.empty? ? nil : x.join.strip
252
+ end
252
253
  end
@@ -0,0 +1,5 @@
1
+ class Time
2
+ def self.filetime_to_time(filetime)
3
+ Time.at((filetime - 116444556000000000) / 10000000)
4
+ end
5
+ end
@@ -1,6 +1,6 @@
1
1
  class BorisLogger < Logger
2
- def initialize(output)
3
- super(output)
2
+ def initialize(log_device)
3
+ super(log_device)
4
4
 
5
5
  self.datetime_format = '%m-%d-%Y %H:%M:%S'
6
6
 
data/lib/boris/options.rb CHANGED
@@ -83,7 +83,7 @@ module Boris
83
83
  # @raise ArgumentError when invalid credentials or connection_types are supplied
84
84
  def add_credential(cred)
85
85
  raise ArgumentError, 'invalid credential supplied (must be Hash)' if !cred.kind_of?(Hash)
86
- raise ArgumentError, 'username required' if !cred[:user]
86
+ raise ArgumentError, 'user required' if !cred[:user]
87
87
 
88
88
  cred[:connection_types] ||= VALID_CONNECTION_TYPES
89
89
 
@@ -1,19 +1,18 @@
1
1
  require 'boris/structure'
2
-
3
- require 'boris/helpers/array'
4
- require 'boris/helpers/hash'
5
- require 'boris/helpers/string'
6
- require 'boris/helpers/scrubber'
2
+ require 'boris/helpers'
7
3
 
8
4
  module Boris; module Profilers
9
5
  class Profiler
10
6
  include Lumberjack
11
7
  include Structure
12
8
 
9
+ attr_reader :cache
10
+
13
11
  def initialize(connector)
14
12
  @host = connector.host
15
13
  @logger = Boris.logger
16
14
  @connector = connector
15
+ @cache = {:users=>[]}
17
16
  end
18
17
  end
19
18
  end; end
@@ -17,7 +17,7 @@ module Boris; module Profilers
17
17
  file_system_command = %q{df -P -T | grep "^/" | awk '{print $1 "|" $3 / 1024 "|" $5 / 1024 "|" $7}'}
18
18
  @connector.values_at(file_system_command).each do |file_system|
19
19
  h = file_system_template
20
- file_system = file_system.split("|")
20
+ file_system = file_system.split('|')
21
21
 
22
22
  h[:capacity_mb] = file_system[1].to_i
23
23
  h[:file_system] = file_system[0]
@@ -80,7 +80,7 @@ module Boris; module Profilers
80
80
 
81
81
  user_data.each do |x|
82
82
  h = {}
83
- x = x.split(":")
83
+ x = x.split(':')
84
84
  h[:status] = nil
85
85
  h[:primary_group_id] = x[3]
86
86
  h[:username] = x[0]
@@ -88,7 +88,7 @@ module Boris; module Profilers
88
88
  end
89
89
 
90
90
  group_data.each do |group|
91
- group = group.split(":")
91
+ group = group.split(':')
92
92
  h = {:members=>[], :name=>group[0]}
93
93
 
94
94
  h[:members] = users.select{|user| (user[:primary_group_id] == group[2])}.collect{|user| user[:username]}
@@ -11,6 +11,8 @@ module Boris; module Profilers
11
11
  return true if connector.value_at('uname') =~ /sunos/i
12
12
  end
13
13
 
14
+ def get_file_systems; super; end
15
+
14
16
  def get_hardware
15
17
  super
16
18
 
@@ -134,6 +136,7 @@ module Boris; module Profilers
134
136
  end
135
137
 
136
138
  def get_local_user_groups; super; end
139
+ def get_network_id; super; end
137
140
 
138
141
  def get_network_interfaces
139
142
  super
@@ -167,8 +170,14 @@ module Boris; module Profilers
167
170
 
168
171
  # if this host is in a child zone, drop any interfaces that are not found in the ifconfig
169
172
  # command output (since these would likely be picked up when scanning the zone host)
173
+ hardware_details = nil
174
+
170
175
  if @zone == :child
171
176
  found_ethernet_interfaces.delete_if{|fi| interface_configs.select{|config| config =~ /^#{fi[:driver]}#{fi[:instance]}/}.count == 0}
177
+ else
178
+ prtpicl_command = %q{/usr/sbin/prtpicl -c network -v | egrep ':model|:driver-name|:instance|:local-mac-address|:vendor-id|:device-id|\(network' | nawk '{if ($0 ~ /\(network/) print ""; else {first=$1; $1=""; print first "|" $0}}'}
179
+ prtpicl_command.gsub!(/network/, 'obp-device') if @platform == :x86
180
+ hardware_details = @connector.values_at(prtpicl_command).join("\n").split(/\n\n/)
172
181
  end
173
182
 
174
183
  # now loop through each unique ethernet interface found on this host
@@ -208,12 +217,6 @@ module Boris; module Profilers
208
217
  h[:model] = 'Virtual Ethernet Adapter'
209
218
  h[:vendor] = VENDOR_ORACLE
210
219
  else
211
- prtpicl_command = %q{/usr/sbin/prtpicl -c network -v | egrep ':model|:driver-name|:instance|:local-mac-address|:vendor-id|:device-id|\(network' | nawk '{if ($0 ~ /\(network/) print ""; else {first=$1; $1=""; print first "|" $0}}'}
212
-
213
- prtpicl_command.gsub!(/network/, 'obp-device') if @platform == :x86
214
-
215
- hardware_details = @connector.values_at(prtpicl_command).join("\n").split(/\n\n/)
216
-
217
220
  hardware = hardware_details.grep(/driver-name\|.*#{fi[:driver]}/).grep(/instance\|.*#{fi[:instance]}/)[0].split(/\n/)
218
221
 
219
222
  h[:vendor_id] = hardware.grep(/vendor-id\|/)[0].after_pipe unless hardware.grep(/vendor-id\|/).empty?
@@ -291,13 +294,14 @@ module Boris; module Profilers
291
294
  def get_operating_system
292
295
  super
293
296
 
294
- install_log_date = @connector.value_at("ls -l /var/sadm/system/logs/install_log | nawk '{print $6" "$7" "$8'}")
297
+ install_log_date = @connector.value_at(%q{ls -l /var/sadm/system/logs/install_log | nawk '{print $6" "$7" "$8'}})
298
+
295
299
  @operating_system[:date_installed] = DateTime.parse(install_log_date)
296
300
 
297
301
  os_data = @connector.value_at('uname -rv').split
298
302
  @operating_system[:kernel] = os_data[1]
299
303
  @operating_system[:name] = 'Oracle Solaris'
300
- @operating_system[:version] = os_data[0]
304
+ @operating_system[:version] = os_data[0].after_period
301
305
 
302
306
  @operating_system
303
307
  end
@@ -42,8 +42,8 @@ module Boris; module Profilers
42
42
  disk_space.each do |ds|
43
43
  h = file_system_template
44
44
  h[:mount_point] = ds[:name]
45
- h[:capacity_mb] = ds[:size].to_i / 1024
46
- h[:used_space_mb] = h[:capacity_mb] - (ds[:freespace].to_i / 1024)
45
+ h[:capacity_mb] = (ds[:size].to_i / 1024) / 1024
46
+ h[:used_space_mb] = h[:capacity_mb] - ((ds[:freespace].to_i / 1024) / 1024)
47
47
 
48
48
  ld = logical_disks.select{|ld| ld[:dependent].include?(h[:mount_point])}[0]
49
49
  h[:file_system] = ld[:antecedent].split(/\"/)[1]
@@ -65,6 +65,8 @@ module Boris; module Profilers
65
65
 
66
66
  serial_data = @connector.value_at('SELECT SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS')
67
67
  @hardware[:serial] = serial_data[:serialnumber]
68
+ @hardware[:serial] = nil if @hardware[:serial] !~ /^\w*$/
69
+
68
70
  @hardware[:firmware_version] = serial_data[:smbiosbiosversion]
69
71
 
70
72
  system_data = @connector.value_at('SELECT Manufacturer, Model, TotalPhysicalMemory FROM Win32_ComputerSystem')
@@ -113,8 +115,10 @@ module Boris; module Profilers
113
115
 
114
116
  app_values = @connector.registry_values_at(app_key)
115
117
 
116
- if app_values[:installdate].kind_of?(String) && app_values[:installdate] !~ /0000/
117
- h[:date_installed] = DateTime.parse(app_values[:installdate])
118
+ begin
119
+ h[:date_installed] = DateTime.parse(app_values[:installdate]) unless app_values[:installdate] =~ /0000/
120
+ rescue
121
+ debug "invalid install date provided (#{app_values[:installdate]})" if app_values[:installdate]
118
122
  end
119
123
 
120
124
  if app_values.has_key?(:displayname) && !(app_values[:displayname] =~ /^kb|\(kb\d+/i)
@@ -169,7 +173,13 @@ module Boris; module Profilers
169
173
  h[:installed_by] = patch[:installedby] unless patch[:installedby].empty?
170
174
  h[:installed_by] = get_username(patch[:installedby]) if patch[:installedby][0, 4] == 'S-1-'
171
175
 
172
- h[:date_installed] = DateTime.strptime(patch[:installedon], '%m/%d/%Y') unless patch[:installedon].empty?
176
+ h[:date_installed] = if patch[:installedon].length == 16
177
+ Time.filetime_to_time(patch[:installedon].hex)
178
+ elsif patch[:installedon] =~ /\d+\/\d+\/\d{4}/
179
+ DateTime.strptime(patch[:installedon], '%m/%d/%Y')
180
+ elsif patch[:installedon] =~ /\d{4}\/\d+\/\d+/
181
+ DateTime.strptime(patch[:installedon], '%Y/%m/%d')
182
+ end unless patch[:installedon].empty?
173
183
 
174
184
  @installed_patches << h
175
185
  end
@@ -240,7 +250,7 @@ module Boris; module Profilers
240
250
  system_roles = @operating_system[:roles]
241
251
  end
242
252
 
243
- if system_roles.select{|role| role =~ /domaincontroller/i}.empty?
253
+ if system_roles.select{|role| role =~ /domain_controller/i}.empty?
244
254
  # not a domain controller, so move on with retrieving users
245
255
  groups = []
246
256
 
@@ -290,7 +300,7 @@ module Boris; module Profilers
290
300
  when 1, 2; 'up'
291
301
  else; 'down'
292
302
  end
293
- h[:type] = 'ethernet'
303
+ h[:type] = h[:model] =~ /converged/i ? 'converged' : 'ethernet'
294
304
  h[:vendor] = interface_profile[:manufacturer]
295
305
 
296
306
  # retrieve config for this interface
@@ -299,7 +309,7 @@ module Boris; module Profilers
299
309
  guid = interface_config[:settingid]
300
310
  h[:dns_servers] = interface_config[:dnsserversearchorder]
301
311
 
302
- subnet = interface_config[:ipsubnet]
312
+ subnet = interface_config[:ipsubnet].is_a?(Array) ? interface_config[:ipsubnet][0] : interface_config[:ipsubnet]
303
313
 
304
314
  interface_config[:ipaddress].each do |ip_address|
305
315
  h[:ip_addresses] << {:ip_address=>ip_address, :subnet=>subnet}
@@ -347,11 +357,14 @@ module Boris; module Profilers
347
357
  device_guid = @connector.registry_values_at(cfg_keypath + '\\Linkage')[:export][0].gsub(/\\/, '\\\\\\')
348
358
 
349
359
  adapter_name_data = @connector.value_at("SELECT InstanceName FROM MSNdis_EnumerateAdapter WHERE DeviceName = '#{device_guid}'", :root_wmi)
350
- internal_adapter_name = adapter_name_data[:instancename]
351
360
 
352
- # now with the internal adapter name, we can grab the connection speed.
353
- speed_data = @connector.value_at("SELECT NdisLinkSpeed FROM MSNdis_LinkSpeed WHERE InstanceName = '#{internal_adapter_name}'", :root_wmi)
354
- h[:current_speed_mbps] = speed_data[:ndislinkspeed] / 10000
361
+ if adapter_name_data
362
+ internal_adapter_name = adapter_name_data[:instancename]
363
+
364
+ # now with the internal adapter name, we can grab the connection speed.
365
+ speed_data = @connector.value_at("SELECT NdisLinkSpeed FROM MSNdis_LinkSpeed WHERE InstanceName = '#{internal_adapter_name}'", :root_wmi)
366
+ h[:current_speed_mbps] = speed_data[:ndislinkspeed] / 10000
367
+ end
355
368
 
356
369
  @network_interfaces << h
357
370
  end
@@ -368,6 +381,9 @@ module Boris; module Profilers
368
381
  h = network_interface_template
369
382
 
370
383
  index = fibre_interface_profiles.index{|profile| profile[:instancename] == fibre_interface[:instancename]}
384
+
385
+ next if index.nil?
386
+
371
387
  profile = fibre_interface_profiles[index]
372
388
 
373
389
  h[:fabric_name] = profile[:fabricname].to_wwn
@@ -413,6 +429,7 @@ module Boris; module Profilers
413
429
  @operating_system[:date_installed] = DateTime.parse(os_data[:installdate])
414
430
  @operating_system[:kernel] = os_data[:version]
415
431
  @operating_system[:license_key] = get_product_key('microsoft windows')
432
+ @operating_system[:license_key] = nil if @operating_system[:license_key] =~ /bbbbb/i
416
433
  @operating_system[:name] = 'Microsoft Windows'
417
434
  @operating_system[:service_pack] = os_data[:csdversion]
418
435
 
@@ -517,17 +534,25 @@ module Boris; module Profilers
517
534
  debug 'product key could not be retrieved'
518
535
  end
519
536
  end
520
-
537
+
521
538
  product_key
522
539
  end
523
540
 
524
541
  def get_username(guid)
542
+ found_user = @cache[:users].select{|user| user[:guid] == guid}.first
543
+
525
544
  username = guid
526
-
527
- user = @connector.value_at("SELECT Caption, SID FROM Win32_UserAccount WHERE SID = '#{guid}'")
528
- username = user[:caption] if user[:sid] == guid
529
545
 
530
- return username
546
+ if found_user
547
+ debug "guid found in cache (#{guid})"
548
+ username = found_user[:username]
549
+ else
550
+ user = @connector.value_at("SELECT Caption, SID FROM Win32_UserAccount WHERE SID = '#{guid}'")
551
+ username = user[:caption] if user
552
+ @cache[:users] << {:guid=>guid, :username=>username}
553
+ end
554
+
555
+ username
531
556
  end
532
557
 
533
558
  private