boris 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +58 -30
  4. data/Rakefile +7 -1
  5. data/code_lookups.yml +94 -0
  6. data/lib/boris.rb +17 -2
  7. data/lib/boris/connectors.rb +3 -2
  8. data/lib/boris/connectors/ssh.rb +92 -48
  9. data/lib/boris/connectors/wmi.rb +8 -5
  10. data/lib/boris/{helpers → core_ext}/array.rb +0 -0
  11. data/lib/boris/core_ext/datetime.rb +38 -0
  12. data/lib/boris/{helpers → core_ext}/hash.rb +0 -0
  13. data/lib/boris/{helpers → core_ext}/string.rb +91 -33
  14. data/lib/boris/{helpers → core_ext}/time.rb +0 -0
  15. data/lib/boris/helpers/constants.rb +6 -3
  16. data/lib/boris/helpers/scrubber.rb +2 -1
  17. data/lib/boris/options.rb +29 -7
  18. data/lib/boris/profiler_core.rb +15 -0
  19. data/lib/boris/profilers/big_ip/big_ip10.rb +10 -0
  20. data/lib/boris/profilers/big_ip/big_ip11.rb +10 -0
  21. data/lib/boris/profilers/big_ip_core.rb +210 -0
  22. data/lib/boris/profilers/brocade_fos/fos6.rb +10 -0
  23. data/lib/boris/profilers/brocade_fos_core.rb +144 -0
  24. data/lib/boris/profilers/cisco/ios12.rb +21 -0
  25. data/lib/boris/profilers/cisco/nxos5.rb +11 -0
  26. data/lib/boris/profilers/cisco_ios_core.rb +138 -0
  27. data/lib/boris/profilers/cisco_nxos_core.rb +148 -0
  28. data/lib/boris/profilers/linux/redhat/rhel5.rb +13 -0
  29. data/lib/boris/profilers/linux/redhat/rhel6.rb +13 -0
  30. data/lib/boris/profilers/linux/{redhat.rb → redhat_core.rb} +2 -8
  31. data/lib/boris/profilers/linux_core.rb +25 -7
  32. data/lib/boris/profilers/onboard_administrator/oa3.rb +10 -0
  33. data/lib/boris/profilers/onboard_administrator_core.rb +96 -0
  34. data/lib/boris/profilers/unix/solaris/solaris10.rb +11 -0
  35. data/lib/boris/profilers/unix/solaris/solaris11.rb +11 -0
  36. data/lib/boris/profilers/unix/{solaris.rb → solaris_core.rb} +13 -13
  37. data/lib/boris/profilers/unix_core.rb +23 -6
  38. data/lib/boris/profilers/windows/windows2003.rb +1 -2
  39. data/lib/boris/profilers/windows/windows2008.rb +1 -2
  40. data/lib/boris/profilers/windows/windows2012.rb +1 -2
  41. data/lib/boris/profilers/windows_core.rb +29 -8
  42. data/lib/boris/structure.rb +15 -0
  43. data/lib/boris/target.rb +19 -3
  44. data/lib/boris/version.rb +1 -1
  45. metadata +27 -11
  46. data/lib/boris/helpers.rb +0 -7
  47. data/lib/boris/profiler.rb +0 -18
@@ -59,15 +59,15 @@ module Boris
59
59
  @connected = false
60
60
  if error.message =~ /access is denied/i
61
61
  warn "connection failed (connection made but credentials not accepted with user #{@user})"
62
- @failure_message = CONN_FAILURE_AUTH_FAILED
62
+ @failure_messages << CONN_FAILURE_AUTH_FAILED
63
63
  @reconnectable = true
64
64
  elsif error.message =~ /call was canceled by the message filter/i
65
65
  warn CONN_FAILURE_RPC_FILTERED
66
- @failure_message = CONN_FAILURE_RPC_FILTERED
66
+ @failure_messages << CONN_FAILURE_RPC_FILTERED
67
67
  @reconnectable = false
68
68
  elsif error.message =~ /rpc server is unavailable/i
69
69
  warn CONN_FAILURE_RPC_UNAVAILABLE
70
- @failure_message = CONN_FAILURE_RPC_UNAVAILABLE
70
+ @failure_messages << CONN_FAILURE_RPC_UNAVAILABLE
71
71
  @reconnectable = false
72
72
  elsif error.message =~ /user credentials cannot be used for local connections/i
73
73
  # clear the credentials then try to connect again
@@ -78,7 +78,7 @@ module Boris
78
78
  else
79
79
  message = "connection failed (#{error.message.gsub(/\n\s*/, '. ')})"
80
80
  warn message
81
- @failure_message = message
81
+ @failure_messages << message
82
82
  @reconnectable = true
83
83
  end
84
84
  end
@@ -120,8 +120,11 @@ module Boris
120
120
  rescue => error
121
121
  if error.message =~ /access is denied/i
122
122
  info "access denied on checking access on #{key_path}"
123
+ elsif error.message =~ /class not registered/i
124
+ info "error while checking access on #{key_path} (class not registered)"
125
+ info 'this could be caused by a lack of permissions or corrupted wmi installation'
123
126
  else
124
- info "error while checking access on #{key_path}"
127
+ info "error while checking access on #{key_path} (#{error.message})"
125
128
  end
126
129
  end
127
130
 
File without changes
@@ -0,0 +1,38 @@
1
+ class DateTime
2
+
3
+ # Returns a new DateTime object showing the exact date and time that
4
+ # something occurred by using the difference in time between a date
5
+ # and the time that has elapsed. This is used to calculate the exact
6
+ # date and time that something occurred when we only know the current
7
+ # time and the time that elapsed since that event occurred.
8
+ #
9
+ # For example, in UNIX, we can't easily determine when a process was
10
+ # kicked off (by using data from the 'ps' command). But the 'ps' command
11
+ # will show us the time elapsed, so coupling that data with the current time,
12
+ # we can figure out when that process was started.
13
+ #
14
+ # now = DateTime.parse('2013-04-12T12:00:00-04:00')
15
+ # process_run_time = '1-05:59:59'
16
+ # DateTime.parse_start_date(now, process_run_time) #=> #<DateTime: 2013-04-11T10:00:01-04:00>
17
+ #
18
+ # @param base_time the base DateTime to calculate from (typically the current time)
19
+ # @param time_elapsed String showing the time elapsed (format: %d-%H:%M:%S)
20
+ # @return [DateTime] a new DateTime object showing the start date/time
21
+ def self.parse_start_date(base_time, time_elapsed)
22
+ time_elapsed = "0-#{time_elapsed}" unless time_elapsed =~ /-/
23
+
24
+ time_elapsed = time_elapsed.split('-')
25
+ days_back = time_elapsed[0].to_i
26
+ time_elapsed = time_elapsed[1].split(':')
27
+
28
+ hours_since = time_elapsed[0].to_i
29
+ minutes_since = time_elapsed[1].to_i
30
+ seconds_since = time_elapsed[2].to_i
31
+
32
+ seconds_since += minutes_since * 60
33
+ seconds_since += hours_since * 60 * 60
34
+ seconds_since += days_back * 60 * 60 * 24
35
+
36
+ started_on = (base_time.to_time - seconds_since).to_datetime
37
+ end
38
+ end
File without changes
@@ -79,14 +79,22 @@ class String
79
79
  value_before_character('\\\\|\/')
80
80
  end
81
81
 
82
+ # Returns the string value found between a pair of curly brackets from self.
83
+ #
84
+ # 'A{B}C'.between_curlies #=> "B"
85
+ #
86
+ # @return [Nil, String] string if value found, else returns nil
87
+ def between_curlies
88
+ self.extract(/\{(.*)\}/)
89
+ end
90
+
82
91
  # Returns the string value found between a pair of parenthesis from self.
83
92
  #
84
93
  # 'A(B)C'.between_parenthesis #=> "B"
85
94
  #
86
95
  # @return [Nil, String] string if value found, else returns nil
87
96
  def between_parenthesis
88
- x = self.scan(/\((.*)\)/)
89
- x.empty? ? nil : x.join
97
+ self.extract(/\((.*)\)/)
90
98
  end
91
99
 
92
100
  # Returns the string value found between a pair of quotes (single or double)
@@ -96,8 +104,36 @@ class String
96
104
  #
97
105
  # @return [Nil, String] string if value found, else returns nil
98
106
  def between_quotes
99
- x = self.scan(/["|'](.*?)["|']/).flatten
100
- x.empty? ? nil : x
107
+ self.extract(/["|'](.*?)["|']/)
108
+ end
109
+
110
+ # Cleans self by stripping leading/trailing spaces, any consecutive spaces, and
111
+ # removing any ASCII characters that are sometimes reported by devices. Also
112
+ # removes registered (R) characters.
113
+ #
114
+ # 'Microsoft(R) Windows(R)'.clean_string #=> "Microsoft Windows"
115
+ # "string with\u00A0 weird character".clean_string #=> "string with weird character"
116
+ #
117
+ # @return [String] the cleaned up string
118
+ def clean_string
119
+ # remove registered "(R)" and trademark "(tm)" marks
120
+ string = self.gsub(/\(r\)|\(tm\)/i, '')
121
+ string.gsub!(/\s+/, ' ')
122
+
123
+ string.encode(Encoding.find('ASCII'), :undef=>:replace, :replace=>'').strip
124
+ end
125
+
126
+ # Attempts to pull only the first match inside the parenthesis for a given
127
+ # regex. It's similar to using String#match or String#scan..join to extract
128
+ # the first matching value (that is, the value to match on found within the
129
+ # parenthesis in the regex).
130
+ #
131
+ # 'abcdef'.extract(/ab(cd)ef/) #=> "cd"
132
+ # 'abcdef'.extract(/abcdef/) #=> nil
133
+ #
134
+ # @return [String, NilClass] the matched string, else returns nil
135
+ def extract(regex)
136
+ self[regex, 1]
101
137
  end
102
138
 
103
139
  # Attempts to grab the hardware model from self and formats it for
@@ -111,25 +147,23 @@ class String
111
147
  # 'sun fire 400'.format_model #=> "SunFire 400"
112
148
  # 't1000'.format_model #=> "SPARC Enterprise T1000"
113
149
  #
114
- # @return [Nil, String] the formatted model, else returns self
150
+ # @return [String] the formatted model, else returns self
115
151
  def format_model
116
- return nil if self == ''
152
+ return self if self == ''
117
153
 
118
- # delete models containing "server" or beginning with "ibm"
119
- # also remove configuration numbers appended (typically on IBM
120
- # products... ex 'System x1000 M3 -[123456]-')
121
- model = self.gsub(/(^ibm|server)/i, '').split(/-*(\[|\()/)[0]
154
+ model = self.sub(/server/i, '')
122
155
 
123
156
  model = if model =~ /^sun.*blade/i
124
- 'SunBlade ' + model.scan(/\d/).join
157
+ 'SunBlade ' + model.extract(/(\d+)/)
125
158
  elsif model =~ /^sun.*fire/i
126
- 'SunFire ' + model.scan(/\d/).join
159
+ 'SunFire ' + model.extract(/(\d+)/)
127
160
  elsif model =~ /^T\d{4}/
128
161
  'SPARC Enterprise ' + model
129
162
  elsif model =~ /^big-*ip/i
130
163
  model.sub(/^big-*ip/i, 'BIG-IP')
131
164
  elsif model =~ /^wsc\d{4}-*.*/i
132
- 'Catalyst ' + (model.scan(/\d/).join + '-' + model.scan(/[a-z]$/i).join).sub(/-$/, '')
165
+ model.sub!(/wsc/i, 'Catalyst ')
166
+ model.include?('-') ? model : model.sub(/(\d{4})(.*)/) {$2.empty? ? "#{$1}" : "#{$1}-#{$2}" }
133
167
  else
134
168
  model
135
169
  end
@@ -194,6 +228,44 @@ class String
194
228
  def hex_to_ip_address
195
229
  self.scan(/../).map {|octet| octet.hex}.join('.')
196
230
  end
231
+
232
+ # Pads self with leading zeros if needed. Useful for properly formatting a String
233
+ # (usually from the ps command in UNIX representing elapsed time) to a more complete,
234
+ # zero-padded string to the format dd-hh:mm:ss. mm::ss is the bare-minimum required
235
+ # String.
236
+ #
237
+ # '00:01'.pad_elapsed_time #=> '00-00:00:01'
238
+ # '01:01'.pad_elapsed_time #=> '00-00:01:01'
239
+ # '01:01:01'.pad_elapsed_time #=> '00-01:01:01'
240
+ # '1-01:00:01'.pad_elapsed_time #=> '01-01:01:01'
241
+ #
242
+ # @return String the padded elapsed time
243
+ def pad_elapsed_time
244
+ return self if self =~ /\d{2}\-\d{2}:\d{2}:\d{2}/
245
+
246
+ return "0#{self}" if self =~ /\d{1}-/
247
+
248
+ case self.count(':')
249
+ when 2; "00-#{self}"
250
+ when 1; "00-00:#{self}"
251
+ end
252
+ end
253
+
254
+ # Pads self with leading zeros if needed. Useful for properly formatting MAC addresses.
255
+ # Takes an optional delimiter used for splitting and returning the provided string in
256
+ # the proper format. The string to be formatted is expected to already be in a six-octet
257
+ # format.
258
+ #
259
+ # '0:0:0:0:0:AA'.pad_mac_address #=> "00:00:00:00:00:AA"
260
+ # '0-0-0-0-AA-12'.pad_mac_address('-') #=> "00-00-00-00-AA-12"
261
+ #
262
+ # @param delimiter an optional delimiter for the MAC address (default is ':')
263
+ # @return [String] the padded MAC address
264
+ def pad_mac_address(delimiter=':')
265
+ self.split(delimiter).inject([]) do |mac, octet|
266
+ octet.length == 1 ? mac << "0#{octet}" : mac << octet
267
+ end.join(delimiter).upcase
268
+ end
197
269
 
198
270
  # Returns a new string with the architecture removed. See {String#remove_arch!}.
199
271
  #
@@ -211,32 +283,17 @@ class String
211
283
  self.replace(self.gsub(/\s+\(*(32|64)(-|\s)*bit\)*/, ''))
212
284
  end
213
285
 
214
- # Cleans self by stripping leading/trailing spaces, and removing any ASCII
215
- # characters that are sometimes reported by devices. Also removes registered
216
- # (R) characters.
217
- #
218
- # 'Microsoft(R) Windows(R)'.clean_string #=> "Microsoft Windows"
219
- # "string with\u00A0 weird characters".clean_string #=> "string with weird characters"
220
- #
221
- # @return [String] the cleaned up string
222
- def clean_string
223
- # remove registered "(R)" and trademark "(tm)" marks
224
- string = self.gsub(/\(r\)|\(tm\)/i, '')
225
- string.gsub!(/\s+/, ' ')
226
-
227
- string.encode(Encoding.find('ASCII'), :undef=>:replace, :replace=>'').strip
228
- end
229
-
230
286
  # Allows you to specify your own delimiter to grab the string value found
231
287
  # after the last delimiter. It's mainly used internally with the
232
288
  # #after_ helper methods.
233
289
  #
234
290
  # 'A&B&C'.value_after_character('&') #=> "C"
235
291
  #
292
+ # @param delimiter
236
293
  # @return [Nil, String] returns the found value, else returns nil
237
294
  def value_after_character(delimiter)
238
- x = self.scan(/^.*[#{delimiter}](.*)$/)
239
- x.empty? ? nil : x.join.strip
295
+ x = self.extract(/^.*[#{delimiter}](.*)$/)
296
+ x.nil? ? nil : x.strip
240
297
  end
241
298
 
242
299
  # Allows you to specify your own delimiter to grab the string value found
@@ -245,9 +302,10 @@ class String
245
302
  #
246
303
  # 'A&B&C'.value_before_character('&') #=> "A"
247
304
  #
305
+ # @param delimiter
248
306
  # @return [Nil, String] returns the found value, else returns nil
249
307
  def value_before_character(delimiter)
250
- x = self.scan(/^(.*?)[#{delimiter}]/)
251
- x.empty? ? nil : x.join.strip
308
+ x = self.extract(/(.*?)[#{delimiter}]/)
309
+ x.nil? ? nil : x.strip
252
310
  end
253
311
  end
File without changes
@@ -2,10 +2,10 @@ module Boris
2
2
  VENDOR_ADOBE = 'Adobe Systems, Inc.'
3
3
  VENDOR_AMD = 'AMD, Inc.'
4
4
  VENDOR_APC = 'APC Corp.'
5
- VENDOR_BROCADE = 'Brocade Communications Corp.'
5
+ VENDOR_BROCADE = 'Brocade Communications, Inc.'
6
6
  VENDOR_CISCO = 'Cisco Systems, Inc.'
7
7
  VENDOR_CITRIX = 'Citrix Systems, Inc.'
8
- VENDOR_DELL = 'Dell Inc.'
8
+ VENDOR_DELL = 'Dell, Inc.'
9
9
  VENDOR_EMULEX = 'Emulex Corp.'
10
10
  VENDOR_F5 = 'F5 Networks, Inc.'
11
11
  VENDOR_HP = 'Hewlett Packard, Inc.'
@@ -14,7 +14,7 @@ module Boris
14
14
  VENDOR_MICROSOFT = 'Microsoft Corp.'
15
15
  VENDOR_ORACLE = 'Oracle Corp.'
16
16
  VENDOR_QLOGIC = 'QLogic Corp.'
17
- VENDOR_REDHAT = 'Red Hat Inc.'
17
+ VENDOR_REDHAT = 'Red Hat, Inc.'
18
18
  VENDOR_SUSE = 'SUSE Linux GmbH'
19
19
  VENDOR_VMWARE = 'VMware, Inc.'
20
20
 
@@ -28,5 +28,8 @@ module Boris
28
28
  CONN_FAILURE_RPC_UNAVAILABLE = 'connection failed (wmi: rpc server unavailable)'
29
29
  CONN_FAILURE_LOCAL_CREDENTIALS = 'connection failed (wmi: credentials used locally, will try again)'
30
30
  CONN_FAILURE_PASSWORD_EXPIRED = 'connection failed (password expired, requires changing)'
31
+ CONN_FAILURE_REFUSED = 'connection failed (target actively refused the connection)'
32
+ CONN_FAILURE_CONNECTION_CLOSED = 'connection failed (connection closed by remote host)'
31
33
 
34
+ CODE_LOOKUPS = YAML::load(File.open(File.join(LIB_PATH, '..', 'code_lookups.yml')))
32
35
  end
@@ -1,4 +1,4 @@
1
- require 'boris/helpers/string'
1
+ require 'boris/core_ext/string'
2
2
 
3
3
  module Boris
4
4
  module Structure
@@ -36,6 +36,7 @@ module Boris
36
36
  interface[:node_wwn].downcase! unless !interface[:node_wwn]
37
37
  interface[:port_wwn].downcase! unless !interface[:port_wwn]
38
38
  interface[:remote_mac_address].upcase! unless !interface[:remote_mac_address]
39
+ interface[:remote_wwn].upcase! unless !interface[:remote_wwn]
39
40
  interface[:vendor] = interface[:vendor].format_vendor unless !interface[:vendor]
40
41
  end if @network_interfaces
41
42
  debug 'network interface data cleaned up'
@@ -1,7 +1,13 @@
1
- require 'boris/profiler'
2
-
3
- require 'boris/profilers/linux/redhat'
4
- require 'boris/profilers/unix/solaris'
1
+ require 'boris/profilers/big_ip/big_ip10'
2
+ require 'boris/profilers/big_ip/big_ip11'
3
+ require 'boris/profilers/brocade_fos/fos6'
4
+ require 'boris/profilers/cisco/ios12'
5
+ require 'boris/profilers/cisco/nxos5'
6
+ require 'boris/profilers/linux/redhat/rhel5'
7
+ require 'boris/profilers/linux/redhat/rhel6'
8
+ require 'boris/profilers/onboard_administrator/oa3'
9
+ require 'boris/profilers/unix/solaris/solaris10'
10
+ require 'boris/profilers/unix/solaris/solaris11'
5
11
  require 'boris/profilers/windows/windows2003'
6
12
  require 'boris/profilers/windows/windows2008'
7
13
  require 'boris/profilers/windows/windows2012'
@@ -39,8 +45,24 @@ module Boris
39
45
  # set our defaults
40
46
  @options[:auto_scrub_data] ||= true
41
47
  @options[:credentials] ||= []
42
- @options[:profilers] ||= [Profilers::RedHat, Profilers::Solaris]
43
- @options[:profilers].concat([Profilers::Windows2003, Profilers::Windows2008, Profilers::Windows2012]) if PLATFORM == :win32
48
+ if !@options[:profilers]
49
+
50
+ @options[:profilers] = [
51
+ Profilers::RHEL5,
52
+ Profilers::RHEL6,
53
+ Profilers::Solaris10,
54
+ Profilers::Solaris11
55
+ ]
56
+
57
+ if PLATFORM == :win32
58
+ @options[:profilers].concat([
59
+ Profilers::Windows2003,
60
+ Profilers::Windows2008,
61
+ Profilers::Windows2012
62
+ ])
63
+ end
64
+
65
+ end
44
66
  @options[:snmp_options] ||= {}
45
67
  @options[:ssh_options] ||= {}
46
68
 
@@ -64,7 +86,7 @@ module Boris
64
86
 
65
87
  # Setter method for setting the value in the options hash
66
88
  # puts options[:profilers] #=> [Profilers::RedHat]
67
- # options[:profilers] << Profilers::Solaris
89
+ # options[:profilers] << Bases::Solaris
68
90
  # puts options[:profilers] #=> [Profilers::RedHat, Profilers::Solaris]
69
91
  # @raise ArgumentError when invalid options are provided
70
92
  def []=(key, val)
@@ -0,0 +1,15 @@
1
+ require 'boris/structure'
2
+
3
+ module Boris; module ProfilerCore
4
+ include Lumberjack
5
+ include Structure
6
+
7
+ attr_reader :cache
8
+
9
+ def initialize(connector)
10
+ @host = connector.host
11
+ @logger = Boris.logger
12
+ @connector = connector
13
+ @cache = {:users=>[]}
14
+ end
15
+ end; end
@@ -0,0 +1,10 @@
1
+ require 'boris/profilers/big_ip_core'
2
+
3
+ module Boris; module Profilers
4
+ class BigIP10 < BigIPCore
5
+
6
+ def self.matches_target?(connector)
7
+ return true if connector.values_at('show sys version').join =~ /version 10/i
8
+ end
9
+ end
10
+ end; end
@@ -0,0 +1,10 @@
1
+ require 'boris/profilers/big_ip_core'
2
+
3
+ module Boris; module Profilers
4
+ class BigIP11 < BigIPCore
5
+
6
+ def self.matches_target?(connector)
7
+ return true if connector.values_at('show sys version').join =~ /version 11/i
8
+ end
9
+ end
10
+ end; end
@@ -0,0 +1,210 @@
1
+ require 'boris/profiler_core'
2
+
3
+ module Boris; module Profilers
4
+ class BigIPCore
5
+ include ProfilerCore
6
+
7
+ attr_reader :license_data, :os_data
8
+
9
+ def self.connection_type
10
+ Boris::SSHConnector
11
+ end
12
+
13
+ def license_data
14
+ @license_data ||= @connector.values_at('show sys license')
15
+ end
16
+
17
+ def os_data
18
+ @os_data ||= @connector.values_at('show sys version')
19
+ end
20
+
21
+ def get_file_systems; super; end
22
+
23
+ def get_hardware
24
+ super
25
+
26
+ hardware_data = @connector.values_at('show sys hardware').join("\n").split(/\n\s*\n/)
27
+ cpu_mem_data = @connector.values_at('show sys host').join("\n").split(/\n\s*\n/)
28
+
29
+ cpu_data = hardware_data.grep(/name\s+cpus/i)[0].split(/\n/)
30
+ platform_data = hardware_data.grep(/platform/i)[0].split(/\n/)
31
+ mem_data = cpu_mem_data.grep(/memory \(bytes\)/i)[0].split(/\n/)
32
+
33
+ @hardware[:cpu_core_count] = cpu_data.grep(/\s{2,}cores/i)[0].split(/\s+/)[2].to_i
34
+ @hardware[:cpu_model] = cpu_data.grep(/model/i)[0].split(/\s{2,}/).last
35
+ @hardware[:cpu_physical_count] = cpu_mem_data.grep(/\s{2,}cpu count/i)[0].split.last.to_i
36
+ @hardware[:cpu_speed_mhz] = cpu_data.grep(/cpu mhz/i)[0].split.last.to_i
37
+ firmware = platform_data.grep(/bios revision/i)[0].split(/\s{2,}/).last
38
+ @hardware[:firmware_version] = firmware =~ /bios|ver\:/i ? firmware.split(/bios|ver\:/i).last : firmware
39
+ @hardware[:model] = platform_data.grep(/name/i)[0].split(/\s{2,}/).last + " (#{license_data.grep(/platform id/i)[0].split.last})"
40
+
41
+ memory = mem_data.grep(/total/i)[0].split.last
42
+ @hardware[:memory_installed_mb] = if memory =~ /g$/i
43
+ (memory.sub('g', '').to_f * 1024).to_i
44
+ elsif memory =~ /m$/i
45
+ memory.sub('m', '').to_f
46
+ end
47
+
48
+ @hardware[:serial] = hardware_data.grep(/system information/i)[0].split(/\n/).grep(/chassis serial/i)[0].split.last
49
+
50
+ @hardware[:vendor] = VENDOR_F5
51
+
52
+ @hardware
53
+ end
54
+
55
+ def get_hosted_shares; super; end
56
+
57
+ def get_installed_applications
58
+ super
59
+
60
+ license_data.grep(/.*\(.*\)/).each do |application|
61
+ h = installed_application_template
62
+
63
+ h[:license_key] = application.between_parenthesis
64
+ h[:name] = application.split('(')[0].strip
65
+ h[:vendor] = VENDOR_F5
66
+
67
+ @installed_applications << h
68
+ end
69
+
70
+ @installed_applications
71
+ end
72
+
73
+ def get_installed_patches
74
+ super
75
+
76
+ patch_data = os_data.join("\n")
77
+
78
+ if patch_data =~ /hotfix list/i
79
+ patch_data.split(/hotfix list/i).last.scan(/\w+/).each do |patch|
80
+ @installed_patches << {:date_installed=>nil, :installed_by=>nil, :patch_code=>patch}
81
+ end
82
+ end
83
+
84
+ @installed_patches
85
+ end
86
+
87
+ def get_installed_services; super; end
88
+ def get_local_user_groups; super; end
89
+
90
+ def get_network_id
91
+ super
92
+
93
+ hostname = @connector.values_at('list sys global-settings hostname').grep(/hostname/)[0].split.last.split('.')
94
+
95
+ @network_id[:hostname] = hostname.shift
96
+ @network_id[:domain] = hostname.join('.') if hostname.any?
97
+
98
+ @network_id
99
+ end
100
+
101
+ def get_network_interfaces
102
+ super
103
+
104
+ dns_servers = @connector.values_at('list sys dns').grep(/servers/)[0].between_curlies.strip.split
105
+
106
+ interfaces = []
107
+ @connector.values_at('list net interface all-properties').join("\n").split(/\}/).each do |interface|
108
+ interface = interface.strip.split(/\n/)
109
+ h = network_interface_template
110
+
111
+ h[:mac_address] = interface.grep(/mac\-address/)[0].split.last.pad_mac_address
112
+ h[:model] = 'Unknown Ethernet Adapter'
113
+ h[:name] = interface[0].split[2]
114
+
115
+ interfaces << h
116
+ end
117
+
118
+ interface_properties = @connector.values_at('show net interface all-properties field-fmt').grep(/\{|\}|media|status|trunk/)
119
+ interface_properties = interface_properties.join("\n").split(/^\s*net/)
120
+
121
+ vlans = @connector.values_at('list net vlan').grep(/\{|\}/)
122
+ vlans = vlans.join("\n").split(/^\s*net/)
123
+
124
+ self_ips = @connector.values_at('show running-config net self all-properties').grep(/\{|vlan|address|\}/)
125
+ self_ips = self_ips.join("\n").split(/^\s*net/)
126
+
127
+ interfaces.each do |h|
128
+
129
+ next if h[:mac_address] =~ /none/i
130
+
131
+ properties = interface_properties.grep(/interface #{h[:name]} \{/).join.split(/\n/)
132
+
133
+ h[:status] = properties.grep(/status/i)[0].split.last
134
+ h[:status] = 'down' unless h[:status] == 'up'
135
+
136
+ media = properties.grep(/media\-active/i)[0].split.last
137
+ media = nil if media =~ /none/i
138
+
139
+ h[:type] = 'ethernet'
140
+ h[:vendor] = VENDOR_F5
141
+
142
+ if h[:status] == 'up'
143
+ h[:current_speed_mbps] = media.scan(/\d+/)[0].to_i
144
+ h[:dns_servers] = dns_servers
145
+ h[:duplex] = case
146
+ when media =~ /fd$/i
147
+ 'full'
148
+ when media =~ /hd$/i
149
+ 'half'
150
+ end
151
+
152
+ #h[:mtu] = properties.grep(/mtu/i)[0].split.last.to_i
153
+
154
+ trunk = properties.grep(/trunk\-name/i)[0].split.last
155
+ trunk = nil if trunk =~ /none/i
156
+
157
+ bound_vlans = []
158
+
159
+ [h[:name], trunk].each do |interface_name|
160
+ matched_vlans = vlans.grep(/ #{interface_name} \{/)
161
+
162
+ matched_vlans.each do |matched_vlan|
163
+ bound_vlans << matched_vlan.split[1]
164
+ end
165
+ end
166
+
167
+ bound_vlans.each do |bound_vlan|
168
+ bound_ips = self_ips.grep(/vlan #{bound_vlan}/)
169
+
170
+ bound_ips.each do |bound_ip|
171
+ bound_ip = bound_ip.split(/\n/)
172
+
173
+ # bigip version 10 reports ip address as first line, where
174
+ # version 11 reports ip on its own line with bitmask attached
175
+ ip_data = if bound_ip[1] =~ /address/i #aka version 11
176
+ bound_ip.grep(/address/)[0].split.last
177
+ else #aka version 10
178
+ bound_ip.grep(/self/)[0].split[1]
179
+ end
180
+
181
+ ip_data = ip_data.split(/\//)
182
+
183
+ ip_address = ip_data.first
184
+ subnet = NetAddr.i_to_ip(NetAddr.bits_to_mask(ip_data.last.to_i, NetAddr::CIDRv4))
185
+
186
+ h[:ip_addresses] << {:ip_address=>ip_address, :subnet=>subnet}
187
+ end
188
+ end
189
+ end
190
+
191
+ @network_interfaces << h
192
+ end
193
+
194
+ @network_interfaces
195
+ end
196
+
197
+ def get_operating_system
198
+ super
199
+
200
+ @operating_system[:kernel] = os_data.grep(/build/i)[0].split.last
201
+ @operating_system[:license_key] = license_data.grep(/registration key/i)[0].split.last
202
+ @operating_system[:name] = os_data.grep(/product/i)[0].split.last
203
+ @operating_system[:service_pack] = os_data.grep(/edition/i)[0].split(/\s{2,}/).last
204
+ @operating_system[:version] = os_data.grep(/version\s+/i)[0].split.last
205
+
206
+ @operating_system
207
+ end
208
+
209
+ end
210
+ end; end