boris 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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