Class: Cisco::Node
- Inherits:
-
Object
- Object
- Cisco::Node
- 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())
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Here and below are implementation details and private APIs that most providers shouldn’t need to know about or use.
-
#cmd_ref ⇒ Object
readonly
Here and below are implementation details and private APIs that most providers shouldn’t need to know about or use.
Class Method Summary collapse
- .instance ⇒ Object
-
.reset_instance ⇒ Object
Allow instance cache to be reset.
Instance Method Summary collapse
-
#boot ⇒ String
Such as “bootflash:///n3000-uk9-kickstart.6.0.2.U5.0.941.bin”.
- #cache_auto=(enable) ⇒ Object
- #cache_auto? ⇒ Boolean
- #cache_enable=(enable) ⇒ Object
- #cache_enable? ⇒ Boolean
-
#cache_flush ⇒ Object
Clear the cache of CLI output results.
-
#config_get(feature, property, *args) ⇒ String, ...
Convenience wrapper for get() Uses CommandReference to look up the given show command and key of interest, executes that command, and returns the value corresponding to that key.
-
#config_get_default(feature, property) ⇒ String?
Uses CommandReference to lookup the default value for a given feature and feature property.
-
#config_set(feature, property, *args) ⇒ Object
Uses CommandReference to look up the given config command(s) of interest and then applies the configuration.
-
#delete_yang(yang) ⇒ Object
Delete the specified JSON YANG config from the device.
-
#domain_name ⇒ String
Such as “example.com”.
-
#drill_down_structured(value, ref) ⇒ Object
Drill down into structured nxapi table data and return value from the row specified by a two part key.
-
#get(**kwargs) ⇒ Object
Send a show command to the device.
-
#get_yang(yang_path) ⇒ Object
Retrieve JSON YANG config from the device for the specified path.
-
#get_yang_oper(yang_path) ⇒ Object
Retrieve JSON YANG operational data for the specified path.
-
#host_name ⇒ String
Such as “bxb-oa-n3k-7”.
-
#initialize ⇒ Node
constructor
A new instance of Node.
- #inspect ⇒ Object
-
#last_reset_reason ⇒ String
Such as “Reset Requested by CLI command reload”.
-
#last_reset_time ⇒ String
Timestamp of last reset time.
-
#massage(value, ref) ⇒ Object
Attempt to massage the given value into the format specified by the given CmdRef object.
- #massage_kind(value, ref) ⇒ Object
-
#massage_structured(get_args, ref) ⇒ Object
The yaml file may specifiy an Array as the get_value to drill down into nxapi_structured table output.
-
#merge_yang(yang) ⇒ Object
Merge the specified JSON YANG config with the running config on the device.
-
#os ⇒ String
Such as “Cisco Nexus Operating System (NX-OS) Software”.
-
#os_version ⇒ String
Such as “6.0(2)U5(1) [build 6.0(2)U5(0.941)]”.
- #os_version_get(feature, property) ⇒ Object
- #prod_qualifier(prod, inventory) ⇒ Object
-
#product_description ⇒ String
Such as “Nexus 3048 Chassis”.
-
#product_id ⇒ String
Such as “N3K-C3048TP-1GE”.
-
#product_serial_number ⇒ String
Such as “FOC1722R0ET”.
-
#product_version_id ⇒ String
Such as “V01”.
-
#replace_yang(yang) ⇒ Object
Replace the running config on the device with the specified JSON YANG config.
-
#set(**kwargs) ⇒ Object
Send a config command to the device.
-
#system ⇒ String
Such as “bootflash:///n3000-uk9.6.0.2.U5.0.941.bin”.
-
#system_cpu_utilization ⇒ Float
Combined user/kernel CPU utilization.
-
#system_uptime ⇒ Integer
System uptime, in seconds.
- #to_s ⇒ Object
Constructor Details
#initialize ⇒ Node
Returns a new instance of Node.
244 245 246 247 248 249 250 251 |
# File 'lib/cisco_node_utils/node.rb', line 244 def initialize @client = Cisco::Client.create @cmd_ref = nil @cmd_ref = CommandReference.new(product: product_id, platform: @client.platform, data_formats: @client.data_formats) cache_flush end |
Instance Attribute Details
#client ⇒ Object (readonly)
Here and below are implementation details and private APIs that most providers shouldn’t need to know about or use.
233 234 235 |
# File 'lib/cisco_node_utils/node.rb', line 233 def client @client end |
#cmd_ref ⇒ Object (readonly)
Here and below are implementation details and private APIs that most providers shouldn’t need to know about or use.
233 234 235 |
# File 'lib/cisco_node_utils/node.rb', line 233 def cmd_ref @cmd_ref end |
Class Method Details
.instance ⇒ Object
235 236 237 |
# File 'lib/cisco_node_utils/node.rb', line 235 def self.instance @instance ||= new end |
.reset_instance ⇒ Object
Allow instance cache to be reset
240 241 242 |
# File 'lib/cisco_node_utils/node.rb', line 240 def self.reset_instance @instance = nil end |
Instance Method Details
#boot ⇒ String
Returns such as “bootflash:///n3000-uk9-kickstart.6.0.2.U5.0.941.bin”.
429 430 431 |
# File 'lib/cisco_node_utils/node.rb', line 429 def boot config_get('show_version', 'boot_image') end |
#cache_auto=(enable) ⇒ Object
273 274 275 |
# File 'lib/cisco_node_utils/node.rb', line 273 def cache_auto=(enable) @client.cache_auto = enable end |
#cache_auto? ⇒ Boolean
269 270 271 |
# File 'lib/cisco_node_utils/node.rb', line 269 def cache_auto? @client.cache_auto? end |
#cache_enable=(enable) ⇒ Object
265 266 267 |
# File 'lib/cisco_node_utils/node.rb', line 265 def cache_enable=(enable) @client.cache_enable = enable end |
#cache_enable? ⇒ Boolean
261 262 263 |
# File 'lib/cisco_node_utils/node.rb', line 261 def cache_enable? @client.cache_enable? end |
#cache_flush ⇒ Object
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.
226 227 228 |
# File 'lib/cisco_node_utils/node.rb', line 226 def cache_flush @client.cache_flush end |
#config_get(feature, property, *args) ⇒ String, ...
Convenience wrapper for get() Uses CommandReference to look up the given show command and key of interest, executes that command, and returns the value corresponding to that key.
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/cisco_node_utils/node.rb', line 53 def config_get(feature, property, *args) ref = @cmd_ref.lookup(feature, property) # If we have a default value but no getter, just return the default return ref.default_value if ref.default_value? && !ref.getter? get_args, ref = massage_structured(ref.getter(*args).clone, ref) data = get(command: get_args[:command], data_format: get_args[:data_format], context: get_args[:context], value: get_args[:value]) massage(data, ref) end |
#config_get_default(feature, property) ⇒ String?
Uses CommandReference to lookup the default value for a given feature and feature property.
195 196 197 198 |
# File 'lib/cisco_node_utils/node.rb', line 195 def config_get_default(feature, property) ref = @cmd_ref.lookup(feature, property) ref.default_value end |
#config_set(feature, property, *args) ⇒ Object
Uses CommandReference to look up the given config command(s) of interest and then applies the configuration.
215 216 217 218 219 |
# File 'lib/cisco_node_utils/node.rb', line 215 def config_set(feature, property, *args) ref = @cmd_ref.lookup(feature, property) set_args = ref.setter(*args) set(**set_args) end |
#delete_yang(yang) ⇒ Object
Delete the specified JSON YANG config from the device.
309 310 311 |
# File 'lib/cisco_node_utils/node.rb', line 309 def delete_yang(yang) @client.set(data_format: :yang_json, values: [yang], mode: :delete_config) end |
#domain_name ⇒ String
Returns such as “example.com”.
395 396 397 |
# File 'lib/cisco_node_utils/node.rb', line 395 def domain_name config_get('dnsclient', 'domain_name') end |
#drill_down_structured(value, ref) ⇒ Object
Drill down into structured nxapi table data and return value from the row specified by a two part key.
Example: Get vlanshowbr-vlanname in the row that contains vlan id 1000 “get_value”=>[“vlanshowbr-vlanid-utf 1000”, “vlanshowbr-vlanname”] Example with optional regexp match “get_value”=>[“vlanshowbr-vlanid-utf 1000”, “vlanshowbr-vlanname”,
'/^shutdown$/']
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/cisco_node_utils/node.rb', line 104 def drill_down_structured(value, ref) # Nothing to do unless nxapi_structured return value unless ref.hash['drill_down'] row_key = ref.hash['get_value'][0][/^\S+/] # Escape special characters if any in row_index and add # anchors for exact match. row_index = Regexp.escape(ref.hash['get_value'][0][/\S+$/]) row_index = "^#{row_index}$" data_key = ref.hash['get_value'][1] regexp_filter = nil if ref.hash['get_value'][2] regexp_filter = Regexp.new ref.hash['get_value'][2][1..-2] end # Get the value using the row_key, row_index and data_key value = value.is_a?(Hash) ? [value] : value data = nil value.each do |row| if row[row_key].to_s[/#{row_index}/] data = row[data_key] data = data.nil? ? '' : data end end return value if data.nil? if regexp_filter filtered = regexp_filter.match(data) return filtered.nil? ? filtered : filtered[filtered.size - 1] end data end |
#get(**kwargs) ⇒ Object
Send a show command to the device. In general, clients should use config_get() rather than calling this function directly.
291 292 293 |
# File 'lib/cisco_node_utils/node.rb', line 291 def get(**kwargs) @client.get(**kwargs) end |
#get_yang(yang_path) ⇒ Object
Retrieve JSON YANG config from the device for the specified path.
314 315 316 |
# File 'lib/cisco_node_utils/node.rb', line 314 def get_yang(yang_path) @client.get(data_format: :yang_json, command: yang_path) end |
#get_yang_oper(yang_path) ⇒ Object
Retrieve JSON YANG operational data for the specified path.
319 320 321 |
# File 'lib/cisco_node_utils/node.rb', line 319 def get_yang_oper(yang_path) @client.get(data_format: :yang_json, command: yang_path, mode: :get_oper) end |
#host_name ⇒ String
Returns such as “bxb-oa-n3k-7”.
390 391 392 |
# File 'lib/cisco_node_utils/node.rb', line 390 def host_name config_get('show_version', 'host_name') end |
#inspect ⇒ Object
257 258 259 |
# File 'lib/cisco_node_utils/node.rb', line 257 def inspect "Node: client:'#{client.inspect}' cmd_ref:'#{cmd_ref.inspect}'" end |
#last_reset_reason ⇒ String
Returns such as “Reset Requested by CLI command reload”.
416 417 418 |
# File 'lib/cisco_node_utils/node.rb', line 416 def last_reset_reason config_get('show_version', 'last_reset_reason') end |
#last_reset_time ⇒ String
Returns timestamp of last reset time.
411 412 413 |
# File 'lib/cisco_node_utils/node.rb', line 411 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.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/cisco_node_utils/node.rb', line 139 def massage(value, ref) Cisco::Logger.debug "Massaging '#{value}' (#{value.inspect})" value = drill_down_structured(value, ref) 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.to_s.empty?) && ref.default_value? && ref.auto_default Cisco::Logger.debug "Default: #{ref.default_value}" return ref.default_value end if ref.multiple && ref.hash['get_data_format'] == :nxapi_structured return value if value.nil? value = [value.to_s] if value.is_a?(String) || value.is_a?(Fixnum) end return value unless ref.kind value = massage_kind(value, ref) Cisco::Logger.debug "Massaged to '#{value}'" value end |
#massage_kind(value, ref) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/cisco_node_utils/node.rb', line 161 def massage_kind(value, ref) case ref.kind when :boolean if value.nil? || value.empty? value = false elsif /^no / =~ value value = false elsif /disable$/ =~ 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 when :symbol value = value.to_sym unless value.nil? end value end |
#massage_structured(get_args, ref) ⇒ Object
The yaml file may specifiy an Array as the get_value to drill down into nxapi_structured table output. The table may contain multiple rows but only one of the rows has the interesting data.
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 70 def massage_structured(get_args, ref) # Nothing to do unless nxapi_structured. return [get_args, ref] unless ref.hash['get_data_format'] == :nxapi_structured # The CmdRef object will contain a get_value Array with 2 values. # The first value is the key to identify the correct row in the table # of structured output and the second is the key to identify the data # to retrieve. # # Example: Get vlanshowbr-vlanname in the row that contains a specific # vlan_id. # "get_value"=>["vlanshowbr-vlanid-utf <vlan_id>", "vlanshowbr-vlanname"] # # TBD: Why do we need to check is_a?(Array) here? if ref.hash['get_value'].is_a?(Array) && ref.hash['get_value'].size >= 2 # Replace the get_value hash entry with the value after any tokens # specified in the yaml file have been replaced and set get_args[:value] # to nil so that the structured table data can be retrieved properly. ref.hash['get_value'] = get_args[:value] ref.hash['drill_down'] = true get_args[:value] = nil end [get_args, ref] end |
#merge_yang(yang) ⇒ Object
Merge the specified JSON YANG config with the running config on the device.
297 298 299 |
# File 'lib/cisco_node_utils/node.rb', line 297 def merge_yang(yang) @client.set(data_format: :yang_json, values: [yang], mode: :merge_config) end |
#os ⇒ String
Returns such as “Cisco Nexus Operating System (NX-OS) Software”.
324 325 326 327 328 |
# File 'lib/cisco_node_utils/node.rb', line 324 def os o = config_get('show_version', 'header') fail 'failed to retrieve operating system information' if o.nil? o.split("\n")[0] end |
#os_version ⇒ String
Returns such as “6.0(2)U5(1) [build 6.0(2)U5(0.941)]”.
331 332 333 |
# File 'lib/cisco_node_utils/node.rb', line 331 def os_version config_get('show_version', 'version') end |
#os_version_get(feature, property) ⇒ Object
439 440 441 |
# File 'lib/cisco_node_utils/node.rb', line 439 def os_version_get(feature, property) @cmd_ref.lookup(feature, property).os_version end |
#prod_qualifier(prod, inventory) ⇒ Object
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/cisco_node_utils/node.rb', line 362 def prod_qualifier(prod, inventory) case prod when /N(3|9)K/ # one datapoint is used to determine if the current n9k/n3k # platform is a fretta based or non-fretta. # # Module == *-R inventory.each do |row| if row['productid'][/-R/] # Append -F for fretta platform. return prod.concat('-F') unless prod[/-F/] end end end prod end |
#product_description ⇒ String
Returns such as “Nexus 3048 Chassis”.
336 337 338 |
# File 'lib/cisco_node_utils/node.rb', line 336 def product_description config_get('show_version', 'description') end |
#product_id ⇒ String
Returns such as “N3K-C3048TP-1GE”.
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/cisco_node_utils/node.rb', line 341 def product_id if @cmd_ref prod = config_get('inventory', 'productid') all = config_get('inventory', 'all') prod_qualifier(prod, all) else # We use this function to *find* the appropriate CommandReference if @client.platform == :nexus entries = get(command: 'show inventory', data_format: :nxapi_structured) prod = entries['TABLE_inv']['ROW_inv'][0]['productid'] prod_qualifier(prod, entries['TABLE_inv']['ROW_inv']) elsif @client.platform == :ios_xr # No support for structured output for this command yet output = get(command: 'show inventory', data_format: :cli) return /NAME: .*\nPID: (\S+)/.match(output)[1] end end end |
#product_serial_number ⇒ String
Returns such as “FOC1722R0ET”.
385 386 387 |
# File 'lib/cisco_node_utils/node.rb', line 385 def product_serial_number config_get('inventory', 'serialnum') end |
#product_version_id ⇒ String
Returns such as “V01”.
380 381 382 |
# File 'lib/cisco_node_utils/node.rb', line 380 def product_version_id config_get('inventory', 'versionid') end |
#replace_yang(yang) ⇒ Object
Replace the running config on the device with the specified JSON YANG config.
303 304 305 306 |
# File 'lib/cisco_node_utils/node.rb', line 303 def replace_yang(yang) @client.set(data_format: :yang_json, values: [yang], mode: :replace_config) end |
#set(**kwargs) ⇒ Object
Send a config command to the device. In general, clients should use config_set() rather than calling this function directly.
282 283 284 |
# File 'lib/cisco_node_utils/node.rb', line 282 def set(**kwargs) @client.set(**kwargs) end |
#system ⇒ String
Returns such as “bootflash:///n3000-uk9.6.0.2.U5.0.941.bin”.
435 436 437 |
# File 'lib/cisco_node_utils/node.rb', line 435 def system config_get('show_version', 'system_image') end |
#system_cpu_utilization ⇒ Float
Returns combined user/kernel CPU utilization.
421 422 423 424 425 |
# File 'lib/cisco_node_utils/node.rb', line 421 def system_cpu_utilization output = config_get('system', 'resources') return output if output.nil? output['cpu_state_user'].to_f + output['cpu_state_kernel'].to_f end |
#system_uptime ⇒ Integer
Returns System uptime, in seconds.
400 401 402 403 404 405 406 407 408 |
# File 'lib/cisco_node_utils/node.rb', line 400 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_s ⇒ Object
253 254 255 |
# File 'lib/cisco_node_utils/node.rb', line 253 def to_s client.to_s end |