Class: Cisco::Utils
- Inherits:
-
Object
- Object
- Cisco::Utils
- Defined in:
- lib/cisco_node_utils/cisco_cmn_utils.rb
Overview
General utility class
Class Method Summary collapse
-
.add_quotes(value) ⇒ Object
merge_range.
-
.array_to_str(array, sort = true) ⇒ Object
This method converts an array to string form for ex: if the array has 1, 2 to 10, 83 to 2014, 3022 and the string will be “1,2-10,83-2014,3022”.
-
.attach_prefix(val, prop, prefix = nil) ⇒ Object
This method is used in config_set for CLIs which can set multiple properties using the same CLI.
- .bitmask_to_length(bitmask) ⇒ Object
- .chassis_pid?(ver_regexp) ⇒ Boolean
-
.dash_range_to_elements(range) ⇒ Object
Convert a dash-range set into individual elements.
-
.dash_range_to_ruby_range(range) ⇒ Object
Convert a cli-dash-syntax range to ruby-range.
- .delta_add_remove(should, current = [], opt = nil) ⇒ Object
-
.depth(a) ⇒ Object
Helper to build a hash of add/remove commands for a nested array.
-
.extract_value(match_method, prop, prefix = nil) ⇒ Object
This method is used in config_get for CLIs which have multiple properties in the same output Given a match_method which defines regex pattern and the match criteria, this method, extracts the value of a property with or without a prefix.
-
.get_reset_range(total_range, remove_ranges) ⇒ Object
For spanning tree range based parameters, the range is very dynamic and so before the parameters are set, the rest of the range needs to be reset For ex: if the ranges 2-42 and 83-200 are getting set, and the total range of the given parameter is 1-4000 then 1,43-82,201-4000 needs to be reset.
- .image_version?(ver_regexp) ⇒ Boolean
-
.length_to_bitmask(length) ⇒ Object
delta_add_remove.
-
.merge_range(range) ⇒ Object
Merge overlapping ranges.
-
.nexus_i2_image ⇒ Object
Helper utility to check for older Nexus I2 images.
-
.normalize_range_array(range, fmt = :array) ⇒ Object
normalize_range_array.
-
.process_network_mask(network) ⇒ Object
Helper utility method for ip/prefix format networks.
-
.ruby_range_to_dash_range(range, type = :array) ⇒ Object
Convert a ruby-range to cli-dash-syntax.
-
.zero_pad_macaddr(mac) ⇒ Object
Helper to 0-pad a mac address.
Class Method Details
.add_quotes(value) ⇒ Object
merge_range
364 365 366 367 368 369 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 364 def self.add_quotes(value) return value if image_version?(/7.3.0/) value = "\"#{value}\"" unless value.start_with?('"') && value.end_with?('"') value end |
.array_to_str(array, sort = true) ⇒ Object
This method converts an array to string form for ex: if the array has 1, 2 to 10, 83 to 2014, 3022 and the string will be “1,2-10,83-2014,3022”
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 212 def self.array_to_str(array, sort=true) farray = sort ? array.compact.uniq.sort : array.compact lranges = [] unless farray.empty? l = array.first r = nil farray.each do |aelem| if r && aelem != r.succ if l == r lranges << l else lranges << Range.new(l, r) end l = aelem end r = aelem end if l == r lranges << l else lranges << Range.new(l, r) end end lranges.to_s.gsub('..', '-').delete('[').delete(']').delete(' ') end |
.attach_prefix(val, prop, prefix = nil) ⇒ Object
This method is used in config_set for CLIs which can set multiple properties using the same CLI. This method attaches prefix to the given property when the prefix is different from the property name else it attaches property name itself. It also appends the value to be set. For ex. if the set_value is <precedence> <time_range> the prop for precedence could be ‘precedence’, and for time_range, the prop and prefix could be ‘time_range’ and ‘time-range’
406 407 408 409 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 406 def self.attach_prefix(val, prop, prefix=nil) prefix = prop.to_s if prefix.nil? val.to_s.empty? ? val : "#{prefix} #{val}" end |
.bitmask_to_length(bitmask) ⇒ Object
164 165 166 167 168 169 170 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 164 def self.bitmask_to_length(bitmask) # Convert bitmask to a 32-bit integer, # convert that to binary, and count the 1s IPAddr.new(bitmask).to_i.to_s(2).count('1') rescue IPAddr::InvalidAddressError => e raise ArgumentError, "bitmask '#{bitmask}' is not valid: #{e}" end |
.chassis_pid?(ver_regexp) ⇒ Boolean
111 112 113 114 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 111 def self.chassis_pid?(ver_regexp) require_relative 'platform' return true if Platform.chassis['pid'][ver_regexp] end |
.dash_range_to_elements(range) ⇒ Object
Convert a dash-range set into individual elements. This is useful for preparing inputs to delta_add_remove().
Inputs an array or string of dash-ranges:
["2-5", "9", "4-6"] or '2-5, 9, 4-6' or ['2-5, 9, 4-6']
Returns an array of range elements:
["2", "3", "4", "5", "6", "9"]
328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 328 def self.dash_range_to_elements(range) return [] if range.nil? range = range.shift if range.is_a?(Array) && range.length == 1 range = range.split(',') if range.is_a?(String) final = [] range = dash_range_to_ruby_range(range) range.each do |rng| # 2..5 maps to ["2", "3", "4", "5"] final << rng.map(&:to_s) end final.flatten.uniq.sort end |
.dash_range_to_ruby_range(range) ⇒ Object
Convert a cli-dash-syntax range to ruby-range. This is useful for preparing inputs to merge_range().
Inputs an array or string of dash-syntax ranges -> returns an array of ruby ranges.
Accepts an array or string: [“2-5”, “9”, “4-6”] or ‘2-5, 9, 4-6’ Returns an array of ranges: [2..5, 9..9, 4..6]
282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 282 def self.dash_range_to_ruby_range(range) range = range.split(',') if range.is_a?(String) range.map! do |rng| if rng[/-/] # '2-5' -> 2..5 rng.split('-').inject { |a, e| a.to_i..e.to_i } else # '9' -> 9..9 rng.to_i..rng.to_i end end range end |
.delta_add_remove(should, current = [], opt = nil) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 136 def self.delta_add_remove(should, current=[], opt=nil) current = [] if current.nil? should = [] if should.nil? # Remove nil entries from array should.each(&:compact!) if depth(should) > 1 delta = { add: should - current, remove: current - should } # Some cli properties cannot be updated, thus must be removed first return delta if opt == :updates_not_allowed # Delete entries from :remove if f1 is an update to an existing command delta[:add].each do |id, _| # Differentiate between comparing nested and unnested arrays by # checking the depth of the array. if depth(should) == 1 delta[:remove].delete_if { |f1| [f1] if f1.to_s == id.to_s } else delta[:remove].delete_if { |f1, f2| [f1, f2] if f1.to_s == id.to_s } end end delta end |
.depth(a) ⇒ Object
Helper to build a hash of add/remove commands for a nested array. Useful for network, redistribute, etc.
should: an array of expected cmds (manifest/recipe)
current: an array of existing cmds on the device
131 132 133 134 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 131 def self.depth(a) return 0 unless a.is_a?(Array) 1 + depth(a[0]) end |
.extract_value(match_method, prop, prefix = nil) ⇒ Object
This method is used in config_get for CLIs which have multiple properties in the same output Given a match_method which defines regex pattern and the match criteria, this method, extracts the value of a property with or without a prefix. For ex. if the regex pattern is something like: (?<action>S+)? the property to extract is action and prefix is nil for (?<src_port>range S+) the property to extract is src_port and prefix is range
381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 381 def self.extract_value(match_method, prop, prefix=nil) prefix = prop if prefix.nil? mm = match_method return nil if mm.nil? return nil unless mm.names.include?(prop) # extract and return value that follows prefix + <space> regexp = Regexp.new("#{Regexp.escape(prefix)} (?<extracted>.*)") value_match = regexp.match(mm[prop]) return nil if value_match.nil? value_match[:extracted] end |
.get_reset_range(total_range, remove_ranges) ⇒ Object
For spanning tree range based parameters, the range is very dynamic and so before the parameters are set, the rest of the range needs to be reset For ex: if the ranges 2-42 and 83-200 are getting set, and the total range of the given parameter is 1-4000 then 1,43-82,201-4000 needs to be reset. This method takes the set ranges and gives back the range to be reset
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 186 def self.get_reset_range(total_range, remove_ranges) fail 'invalid range' unless total_range.include?('-') return total_range if remove_ranges.empty? trs = total_range.gsub('-', '..') tra = trs.split('..').map { |d| Integer(d) } tr = tra[0]..tra[1] tarray = tr.to_a remove_ranges.each do |rr, _val| rarray = rr.gsub('-', '..').split(',') rarray.each do |elem| if elem.include?('..') elema = elem.split('..').map { |d| Integer(d) } ele = elema[0]..elema[1] tarray -= ele.to_a else tarray.delete(elem.to_i) end end end Utils.array_to_str(tarray) end |
.image_version?(ver_regexp) ⇒ Boolean
106 107 108 109 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 106 def self.image_version?(ver_regexp) require_relative 'platform' return true if Platform.image_version[ver_regexp] end |
.length_to_bitmask(length) ⇒ Object
delta_add_remove
160 161 162 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 160 def self.length_to_bitmask(length) IPAddr.new('255.255.255.255').mask(length).to_s end |
.merge_range(range) ⇒ Object
Merge overlapping ranges.
Inputs an array of ruby ranges: [2..5, 9..9, 4..6] Returns an array of merged ruby ranges: [2..6, 9..9]
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 347 def self.merge_range(range) # sort to lowest range 'first' values: # [2..5, 9..9, 4..6] -> [2..5, 4..6, 9..9] range = range.sort_by(&:first) *merged = range.shift range.each do |r| lastr = merged[-1] if lastr.last >= r.first - 1 merged[-1] = lastr.first..[r.last, lastr.last].max else merged.push(r) end end merged end |
.nexus_i2_image ⇒ Object
Helper utility to check for older Nexus I2 images
101 102 103 104 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 101 def self.nexus_i2_image require_relative 'platform' true if Platform.image_version[/7.0.3.I2/] end |
.normalize_range_array(range, fmt = :array) ⇒ Object
normalize_range_array
Given a list of ranges, merge any overlapping ranges and sort them.
Note: The ranges are converted to ruby ranges for easy merging, then converted back to a cli-syntax range.
Accepts an array or string:
["2-5", "9", "4-6"] -or- '2-5, 9, 4-6' -or- ["2-5, 9, 4-6"]
Returns a merged and ordered range as an array or string:
["2-6", "9"] -or- '2-6,9'
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 250 def self.normalize_range_array(range, fmt=:array) return range if range.nil? || range.empty? range = range.clone # Handle string within an array: ["2-5, 9, 4-6"] to '2-5, 9, 4-6' range = range.shift if range.is_a?(Array) && range.length == 1 # Handle string only: '2-5, 9, 4-6' to ["2-5", "9", "4-6"] range = range.split(',') if range.is_a?(String) # Convert to ruby-syntax ranges range = dash_range_to_ruby_range(range) # Sort & Merge merged = merge_range(range) # Convert back to cli dash-syntax merged_array = ruby_range_to_dash_range(merged) return merged_array.join(',') if fmt == :string merged_array end |
.process_network_mask(network) ⇒ Object
Helper utility method for ip/prefix format networks. For ip/prefix format ‘1.1.1.1/24’ or ‘2000:123:38::34/64’, we need to mask the address using the prefix length so that they are converted to ‘1.1.1.0/24’ or ‘2000:123:38::/64’
120 121 122 123 124 125 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 120 def self.process_network_mask(network) mask = network.split('/')[1] address = IPAddr.new(network).to_s network = address + '/' + mask unless mask.nil? network end |
.ruby_range_to_dash_range(range, type = :array) ⇒ Object
Convert a ruby-range to cli-dash-syntax.
Inputs an array of ruby ranges -> returns an array or string of dash-syntax ranges.
when (:array) [2..6, 9..9] -> [‘2-6’, ‘9’]
when (:string) [2..6, 9..9] -> ‘2-6, 9’
305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 305 def self.ruby_range_to_dash_range(range, type=:array) fail unless range.is_a?(Array) range.map! do |r| if r.first == r.last # 9..9 -> '9' r.first.to_s else # 2..6 -> '2-6' r.first.to_s + '-' + r.last.to_s end end return range.join(', ') if type == :string range end |
.zero_pad_macaddr(mac) ⇒ Object
Helper to 0-pad a mac address.
173 174 175 176 177 |
# File 'lib/cisco_node_utils/cisco_cmn_utils.rb', line 173 def self.zero_pad_macaddr(mac) return nil if mac.nil? || mac.empty? o1, o2, o3 = mac.split('.').map { |o| o.to_i(16).to_s(10) } sprintf('%04x.%04x.%04x', o1, o2, o3) end |