Class: Cisco::Node

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/cisco_node_utils/node.rb

Overview

class Cisco::Node Singleton representing the network node (switch/router) that is running this code. The singleton is lazily instantiated, meaning that it doesn’t exist until some client requests it (with Node.instance())

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNode

Returns a new instance of Node.



189
190
191
192
193
# File 'lib/cisco_node_utils/node.rb', line 189

def initialize
  @client = nil
  @cmd_ref = nil
  connect unless self.class.lazy_connect
end

Class Attribute Details

.lazy_connectObject

Returns the value of attribute lazy_connect.



182
183
184
# File 'lib/cisco_node_utils/node.rb', line 182

def lazy_connect
  @lazy_connect
end

Instance Attribute Details

#clientObject (readonly)

Here and below are implementation details and private APIs that most providers shouldn’t need to know about or use.



176
177
178
# File 'lib/cisco_node_utils/node.rb', line 176

def client
  @client
end

#cmd_refObject (readonly)

Here and below are implementation details and private APIs that most providers shouldn’t need to know about or use.



176
177
178
# File 'lib/cisco_node_utils/node.rb', line 176

def cmd_ref
  @cmd_ref
end

Instance Method Details

#bootString

Returns such as “bootflash:///n3000-uk9-kickstart.6.0.2.U5.0.941.bin”.

Returns:

  • (String)

    such as “bootflash:///n3000-uk9-kickstart.6.0.2.U5.0.941.bin”



358
359
360
# File 'lib/cisco_node_utils/node.rb', line 358

def boot
  config_get('show_version', 'boot_image')
end

#cache_auto=(enable) ⇒ Object



226
227
228
# File 'lib/cisco_node_utils/node.rb', line 226

def cache_auto=(enable)
  @client.cache_auto = enable
end

#cache_auto?Boolean

Returns:

  • (Boolean)


222
223
224
# File 'lib/cisco_node_utils/node.rb', line 222

def cache_auto?
  @client.cache_auto?
end

#cache_enable=(enable) ⇒ Object



218
219
220
# File 'lib/cisco_node_utils/node.rb', line 218

def cache_enable=(enable)
  @client.cache_enable = enable
end

#cache_enable?Boolean

Returns:

  • (Boolean)


214
215
216
# File 'lib/cisco_node_utils/node.rb', line 214

def cache_enable?
  @client.cache_enable?
end

#cache_flushObject

Clear the cache of CLI output results.

If cache_auto is true (default) then this will be performed automatically whenever a config_set() is called, but providers may also call this to explicitly force the cache to be cleared.



169
170
171
# File 'lib/cisco_node_utils/node.rb', line 169

def cache_flush
  @client.cache_flush
end

#config(commands) ⇒ Object

Send a config command to the device. In general, clients should use config_set() rather than calling this function directly.

Raises:



262
263
264
265
266
267
# File 'lib/cisco_node_utils/node.rb', line 262

def config(commands)
  CiscoLogger.debug("CLI Sent to device: #{commands}")
  @client.config(commands)
rescue CiscoNxapi::CliError => e
  raise Cisco::CliError.new(e.input, e.clierror, e.previous)
end

#config_get(feature, name, *args) ⇒ String, ...

Convenience wrapper for show(command, :structured). Uses CommandReference to look up the given show command and key of interest, executes that command, and returns the value corresponding to that key.

Examples:

config_get(“show_version”, “system_image”)

config_get(“ospf”, “router_id”,

{name: "green", vrf: "one"})

Parameters:

  • feature (String)
  • name (String)

Returns:

  • (String, Hash, Array)

Raises:

  • (IndexError)

    if the given (feature, name) pair is not in the CommandReference data or if the data doesn’t have values defined for the ‘config_get’ and (optional) ‘config_get_token’ fields.

  • (Cisco::CliError)

    if the given command is rejected by the device.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/cisco_node_utils/node.rb', line 69

def config_get(feature, name, *args)
  fail 'lazy_connect specified but did not request connect' unless @cmd_ref
  ref = @cmd_ref.lookup(feature, name)

  return ref.default_value if ref.default_only?

  begin
    token = ref.config_get_token(*args)
  rescue IndexError
    # IndexError: no entry for config_get_token
    token = nil
  end
  if token.nil?
    # Just get the whole output
    return massage(show(ref.config_get, :structured), ref)
  elsif token[0].kind_of?(Regexp)
    return massage(Cisco.find_ascii(show(ref.config_get, :ascii),
                                    token[-1],
                                    *token[0..-2]), ref)
  else
    return massage(
      config_get_handle_structured(token,
                                   show(ref.config_get, :structured)),
      ref)
  end
end

#config_get_default(feature, name) ⇒ String

Uses CommandReference to lookup the default value for a given feature and feature property.

Examples:

config_get_default(“vtp”, “file”)

Parameters:

  • feature (String)
  • name (String)

Returns:

  • (String)

Raises:

  • (IndexError)

    if the given (feature, name) pair is not in the CommandReference data or if the data doesn’t have values defined for the ‘default_value’ field.



138
139
140
141
142
# File 'lib/cisco_node_utils/node.rb', line 138

def config_get_default(feature, name)
  fail 'lazy_connect specified but did not request connect' unless @cmd_ref
  ref = @cmd_ref.lookup(feature, name)
  ref.default_value
end

#config_get_handle_structured(token, result) ⇒ Object

Helper method for config_get().

Parameters:

  • token (Array, Hash)

    lookup sequence

  • result (Array, Hash)

    structured output from node



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/cisco_node_utils/node.rb', line 233

def config_get_handle_structured(token, result)
  token.each do |t|
    # if token is a hash and result is an array, check each
    # array index (which should return another hash) to see if
    # it contains the matching key/value pairs specified in token,
    # and return the first match (or nil)
    if t.kind_of?(Hash)
      fail "Expected array, got #{result.class}" unless result.is_a? Array
      result = result.select { |x| t.all? { |k, v| x[k] == v } }
      fail "Multiple matches found for #{t}" if result.length > 1
      fail "No match found for #{t}" if result.length == 0
      result = result[0]
    else # result is array or hash
      fail "No key \"#{t}\" in #{result}" if result[t].nil?
      result = result[t]
    end
  end
  result
rescue RuntimeError
  # TODO: logging user story, Syslog isn't available here
  # Syslog.debug(e.message)
  nil
end

#config_set(feature, name, *args) ⇒ Object

Uses CommandReference to look up the given config command(s) of interest and then applies the configuration.

Examples:

config_set(“vtp”, “domain”, “example.com”)

config_set(“ospf”, “router_id”,

{:name => "green", :vrf => "one", :state => "",
 :router_id => "192.0.0.1"})

Parameters:

  • feature (String)
  • name (String)
  • args (*String)

    zero or more args to be substituted into the cmdref.

Raises:

  • (IndexError)

    if no relevant cmd_ref config_set exists

  • (ArgumentError)

    if too many or too few args are provided.

  • (Cisco::CliError)

    if any command is rejected by the device.



158
159
160
161
162
# File 'lib/cisco_node_utils/node.rb', line 158

def config_set(feature, name, *args)
  fail 'lazy_connect specified but did not request connect' unless @cmd_ref
  ref = @cmd_ref.lookup(feature, name)
  config(ref.config_set(*args))
end

#connect(*args) ⇒ Object

“hidden” API - used for UT but shouldn’t be used elsewhere



200
201
202
203
204
205
206
207
# File 'lib/cisco_node_utils/node.rb', line 200

def connect(*args)
  @client = CiscoNxapi::NxapiClient.new(*args)
  # Hard-code platform and cli for now
  @cmd_ref = CommandReference.new(product:  product_id,
                                  platform: :nexus,
                                  cli:      true)
  cache_flush
end

#domain_nameString

Returns such as “example.com”.

Returns:

  • (String)

    such as “example.com”



324
325
326
# File 'lib/cisco_node_utils/node.rb', line 324

def domain_name
  config_get('dnsclient', 'domain_name')
end

#host_nameString

Returns such as “bxb-oa-n3k-7”.

Returns:

  • (String)

    such as “bxb-oa-n3k-7”



319
320
321
# File 'lib/cisco_node_utils/node.rb', line 319

def host_name
  config_get('show_version', 'host_name')
end

#last_reset_reasonString

Returns such as “Reset Requested by CLI command reload”.

Returns:

  • (String)

    such as “Reset Requested by CLI command reload”



345
346
347
# File 'lib/cisco_node_utils/node.rb', line 345

def last_reset_reason
  config_get('show_version', 'last_reset_reason')
end

#last_reset_timeString

Returns timestamp of last reset time.

Returns:

  • (String)

    timestamp of last reset time



340
341
342
# File 'lib/cisco_node_utils/node.rb', line 340

def last_reset_time
  config_get('show_version', 'last_reset_time')
end

#massage(value, ref) ⇒ Object

Attempt to massage the given value into the format specified by the given CmdRef object.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/cisco_node_utils/node.rb', line 98

def massage(value, ref)
  CiscoLogger.debug "Massaging '#{value}' (#{value.inspect})"
  if value.is_a?(Array) && !ref.multiple
    fail "Expected zero/one value but got '#{value}'" if value.length > 1
    value = value[0]
  end
  if (value.nil? || value.empty?) && ref.default_value? && ref.auto_default
    CiscoLogger.debug "Default: #{ref.default_value}"
    return ref.default_value
  end
  return value unless ref.kind
  case ref.kind
  when :boolean
    if value.nil? || value.empty?
      value = false
    elsif /^no / =~ value
      value = false
    else
      value = true
    end
  when :int
    value = value.to_i unless value.nil?
  when :string
    value = '' if value.nil?
    value = value.to_s.strip
  end
  CiscoLogger.debug "Massaged to '#{value}'"
  value
end

#osString

Returns such as “Cisco Nexus Operating System (NX-OS) Software”.

Returns:

  • (String)

    such as “Cisco Nexus Operating System (NX-OS) Software”



281
282
283
284
285
# File 'lib/cisco_node_utils/node.rb', line 281

def os
  o = config_get('show_version', 'header')
  fail 'failed to retrieve operating system information' if o.nil?
  o.split("\n")[0]
end

#os_versionString

Returns such as “6.0(2)U5(1) [build 6.0(2)U5(0.941)]”.

Returns:

  • (String)

    such as “6.0(2)U5(1) [build 6.0(2)U5(0.941)]”



288
289
290
# File 'lib/cisco_node_utils/node.rb', line 288

def os_version
  config_get('show_version', 'version')
end

#product_descriptionString

Returns such as “Nexus 3048 Chassis”.

Returns:

  • (String)

    such as “Nexus 3048 Chassis”



293
294
295
# File 'lib/cisco_node_utils/node.rb', line 293

def product_description
  config_get('show_version', 'description')
end

#product_idString

Returns such as “N3K-C3048TP-1GE”.

Returns:

  • (String)

    such as “N3K-C3048TP-1GE”



298
299
300
301
302
303
304
305
306
# File 'lib/cisco_node_utils/node.rb', line 298

def product_id
  if @cmd_ref
    return config_get('inventory', 'productid')
  else
    # We use this function to *find* the appropriate CommandReference
    entries = show('show inventory', :structured)
    return entries['TABLE_inv']['ROW_inv'][0]['productid']
  end
end

#product_serial_numberString

Returns such as “FOC1722R0ET”.

Returns:

  • (String)

    such as “FOC1722R0ET”



314
315
316
# File 'lib/cisco_node_utils/node.rb', line 314

def product_serial_number
  config_get('inventory', 'serialnum')
end

#product_version_idString

Returns such as “V01”.

Returns:

  • (String)

    such as “V01”



309
310
311
# File 'lib/cisco_node_utils/node.rb', line 309

def product_version_id
  config_get('inventory', 'versionid')
end

#reloadObject

TODO: remove me



210
211
212
# File 'lib/cisco_node_utils/node.rb', line 210

def reload
  @client.reload
end

#show(command, type = :ascii) ⇒ Object

Send a show command to the device. In general, clients should use config_get() rather than calling this function directly.

Raises:



274
275
276
277
278
# File 'lib/cisco_node_utils/node.rb', line 274

def show(command, type=:ascii)
  @client.show(command, type)
rescue CiscoNxapi::CliError => e
  raise Cisco::CliError.new(e.input, e.clierror, e.previous)
end

#systemString

Returns such as “bootflash:///n3000-uk9.6.0.2.U5.0.941.bin”.

Returns:

  • (String)

    such as “bootflash:///n3000-uk9.6.0.2.U5.0.941.bin”



364
365
366
# File 'lib/cisco_node_utils/node.rb', line 364

def system
  config_get('show_version', 'system_image')
end

#system_cpu_utilizationFloat

Returns combined user/kernel CPU utilization.

Returns:

  • (Float)

    combined user/kernel CPU utilization



350
351
352
353
354
# File 'lib/cisco_node_utils/node.rb', line 350

def system_cpu_utilization
  output = config_get('system', 'resources')
  fail 'failed to retrieve cpu utilization' if output.nil?
  output['cpu_state_user'].to_f + output['cpu_state_kernel'].to_f
end

#system_uptimeInteger

Returns System uptime, in seconds.

Returns:

  • (Integer)

    System uptime, in seconds



329
330
331
332
333
334
335
336
337
# File 'lib/cisco_node_utils/node.rb', line 329

def system_uptime
  cache_flush
  t = config_get('show_system', 'uptime')
  fail 'failed to retrieve system uptime' if t.nil?
  # time units: t = ["0", "23", "15", "49"]
  t.map!(&:to_i)
  d, h, m, s = t
  (s + 60 * (m + 60 * (h + 24 * (d))))
end

#to_sObject



195
196
197
# File 'lib/cisco_node_utils/node.rb', line 195

def to_s
  @client.to_s
end