Skip to content

Commit 66c23d0

Browse files
authored
Merge pull request #597 from cisco/release_1.10.0
Release 1.10.0
2 parents 88e0d96 + 976b201 commit 66c23d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1177
-147
lines changed

CHANGELOG.md

+34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
11
Changelog
22
=========
33

4+
## [v1.10.0]
5+
6+
### New Cisco Resources
7+
8+
### Added
9+
* Added syslog_facility with attribute:
10+
* `level`
11+
* Extend syslog_server with attribute:
12+
* `facility`
13+
* Extend interface with attributes:
14+
* `ipv6_redirects`
15+
* Extend ace with attributes:
16+
* `proto_option`
17+
* `vlan`
18+
* `set_erspan_dscp`
19+
* `set_erspan_gre_proto`
20+
* Extend network_dns with attributes:
21+
* `hostname`
22+
* Added ability to specify environment at run time
23+
24+
Example:
25+
```ruby
26+
env = { host: '192.168.1.1', port: nil, username: 'admin', password: 'admin123', cookie: nil }
27+
Cisco::Environment.add_env('default', env)
28+
```
29+
30+
### Changed
31+
32+
### Removed
33+
34+
### Issues Addressed
35+
* Removed default values for authentication in `interface_hsrp_group`
36+
437
## [v1.9.0]
538

639
### New Cisco Resources
@@ -554,6 +587,7 @@ Changelog
554587
[git-flow]: https://github.com/petervanderdoes/gitflow-avh
555588
[SimpleCov]: https://github.com/colszowka/simplecov
556589

590+
[v1.10.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.9.0...v1.10.0
557591
[v1.9.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.8.0...v1.9.0
558592
[v1.8.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.7.0...v1.8.0
559593
[v1.7.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.6.0...v1.7.0

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ An example configuration file (illustrating each of the above scenarios) is prov
8585

8686
*For security purposes, it is highly recommended that access to this file be restricted to only the owning user (`chmod 0600`).*
8787

88+
Configuration may also be specified at runtime and can be used in the absence of configuration files or to override them.
89+
90+
Example:
91+
```ruby
92+
env = { host: '192.168.1.1', port: nil, username: 'admin', password: 'admin123', cookie: nil }
93+
Cisco::Environment.add_env('default', env)
94+
```
95+
8896
## <a name="documentation">Documentation</a>
8997

9098
### Client
@@ -151,12 +159,18 @@ client2 = Cisco::Client.create('n9k')
151159
# Warning: Make sure to exclude devices using the 'no_proxy' environment variable
152160
# to ensure successful remote connections.
153161

162+
# Add runtime configuration for remote device and connect
163+
env = { host: '192.168.1.1', port: nil, username: 'admin', password: 'admin123', cookie: nil }
164+
Cisco::Environment.add_env('remote', env)
165+
client3 = Cisco::Client.create('remote')
166+
154167
# Use connections to get and set device state.
155168
client1.set(values: 'feature vtp')
156169
client1.set(values: 'vtp domain mycompany.com')
157170
puts client1.get(command: 'show vtp status | inc Domain')
158171

159172
puts client2.get(command: 'show version')
173+
puts client3.get(command: 'show version')
160174
```
161175

162176
#### High-level Node API

ext/mkrf_conf.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
os == 'ios_xr' || deps << Gem::Dependency.new('net_http_unix',
3838
'~> 0.2', '>= 0.2.1')
3939
# NX-OS doesn't need gRPC
40-
os == 'nexus' || deps << Gem::Dependency.new('grpc', '~> 0.12')
40+
os == 'nexus' || deps << Gem::Dependency.new('grpc', '~> 1.14.1')
4141

4242
deps.each do |dep|
4343
installed = dep.matching_specs

lib/cisco_node_utils/ace.rb

+142-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2015-2016 Cisco and/or its affiliates.
1+
# Copyright (c) 2015-2018 Cisco and/or its affiliates.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
require 'ipaddr'
1516
require_relative 'node_util'
1617

1718
module Cisco
@@ -73,6 +74,9 @@ def ace_get
7374
remark = Regexp.new('(?<seqno>\d+) remark (?<remark>.*)').match(str)
7475
return remark unless remark.nil?
7576

77+
# specialized icmp protocol handling
78+
return icmp_ace_get(str) if str.include?('icmp')
79+
7680
# rubocop:disable Metrics/LineLength
7781
regexp = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
7882
' *(?<proto>\d+|\S+)'\
@@ -95,6 +99,60 @@ def ace_get
9599
regexp.match(str)
96100
end
97101

102+
# icmp ace getter
103+
def icmp_ace_get(str)
104+
# rubocop:disable Metrics/LineLength
105+
# fragments is nvgen at a different location than all other
106+
# proto_option so get rid of it so as not to mess up other fields
107+
str.sub!('fragments ', '')
108+
regexp = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
109+
' *(?<proto>\d+|\S+)'\
110+
' *(?<src_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
111+
' *(?<dst_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
112+
' *(?<proto_option>\S+)?'\
113+
' *(?<precedence>precedence \S+)?'\
114+
' *(?<dscp>dscp \S+)?'\
115+
' *(?<time_range>time-range \S+)?'\
116+
' *(?<packet_length>packet-length (range \d+ \d+|(lt|eq|gt|neq) \d+))?'\
117+
' *(?<ttl>ttl \d+)?'\
118+
' *(?<vlan>vlan \d+)?'\
119+
' *(?<set_erspan_gre_proto>set-erspan-gre-proto \d+)?'\
120+
' *(?<set_erspan_dscp>set-erspan-dscp \d+)?'\
121+
' *(?<redirect>redirect \S+)?')
122+
regexp_no_proto_option = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
123+
' *(?<proto>\d+|\S+)'\
124+
' *(?<src_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
125+
' *(?<dst_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
126+
' *(?<precedence>precedence \S+)?'\
127+
' *(?<dscp>dscp \S+)?'\
128+
' *(?<time_range>time-range \S+)?'\
129+
' *(?<packet_length>packet-length (range \d+ \d+|(lt|eq|gt|neq) \d+))?'\
130+
' *(?<ttl>ttl \d+)?'\
131+
' *(?<vlan>vlan \d+)?'\
132+
' *(?<set_erspan_gre_proto>set-erspan-gre-proto \d+)?'\
133+
' *(?<set_erspan_dscp>set-erspan-dscp \d+)?'\
134+
' *(?<redirect>redirect \S+)?')
135+
temp = regexp.match(str)
136+
po = temp[:proto_option]
137+
if po.nil?
138+
return temp
139+
# redirect can be proto_option or an actual redirect to interface
140+
elsif po.strip.match(/redirect$/)
141+
if str.match(/Ethernet|port-channel/)
142+
# if proto_option is given as redirect and also redirect to intf
143+
# we need to do extra processing
144+
return temp if check_redirect_repeat(str)
145+
return regexp_no_proto_option.match(str)
146+
end
147+
# the reserved keywords check
148+
elsif po.strip.match(/precedence$|dscp$|time-range$|packet-length$|ttl$|vlan$|set-erspan-gre-proto$|set-erspan-dscp$|log$/)
149+
return regexp_no_proto_option.match(str)
150+
else
151+
return temp
152+
end
153+
# rubocop:enable Metrics/LineLength
154+
end
155+
98156
# common ace setter. Put the values you need in a hash and pass it in.
99157
# attrs = {:action=>'permit', :proto=>'tcp', :src =>'host 1.1.1.1'}
100158
def ace_set(attrs)
@@ -130,6 +188,10 @@ def ace_set(attrs)
130188
:tcp_option_length,
131189
:redirect,
132190
:log,
191+
:proto_option,
192+
:set_erspan_dscp,
193+
:set_erspan_gre_proto,
194+
:vlan,
133195
].each do |p|
134196
attrs[p] = '' if attrs[p].nil?
135197
send(p.to_s + '=', attrs[p])
@@ -139,6 +201,21 @@ def ace_set(attrs)
139201
config_set('acl', cmd, @set_args)
140202
end
141203

204+
def valid_ipv6?(addr)
205+
begin
206+
ret = IPAddr.new(addr.split[0]).ipv6?
207+
rescue
208+
ret = false
209+
end
210+
ret
211+
end
212+
213+
def check_redirect_repeat(str)
214+
return false unless str.include?('redirect')
215+
nstr = str.sub('redirect', '').strip
216+
nstr.include?('redirect') ? true : false
217+
end
218+
142219
# PROPERTIES
143220
# ----------
144221
def seqno
@@ -182,7 +259,7 @@ def src_addr
182259
return nil if match.nil? || !match.names.include?('src_addr')
183260
addr = match[:src_addr]
184261
# Normalize addr. Some platforms zero_pad ipv6 addrs.
185-
addr.gsub!(/^0*/, '').gsub!(/:0*/, ':')
262+
addr.gsub!(/^0*/, '').gsub!(/:0*/, ':') if valid_ipv6?(addr)
186263
addr
187264
end
188265

@@ -205,7 +282,7 @@ def dst_addr
205282
return nil if match.nil? || !match.names.include?('dst_addr')
206283
addr = match[:dst_addr]
207284
# Normalize addr. Some platforms zero_pad ipv6 addrs.
208-
addr.gsub!(/^0*/, '').gsub!(/:0*/, ':')
285+
addr.gsub!(/^0*/, '').gsub!(/:0*/, ':') if valid_ipv6?(addr)
209286
addr
210287
end
211288

@@ -261,6 +338,49 @@ def dscp=(dscp)
261338
@set_args[:dscp] = Utils.attach_prefix(dscp, :dscp)
262339
end
263340

341+
def vlan
342+
Utils.extract_value(ace_get, 'vlan')
343+
end
344+
345+
def vlan=(vlan)
346+
@set_args[:vlan] = Utils.attach_prefix(vlan, :vlan)
347+
end
348+
349+
def set_erspan_dscp
350+
ret = Utils.extract_value(ace_get, 'set_erspan_dscp', 'set-erspan-dscp')
351+
return ret if ret
352+
# position of set_erspan_dscp is different in older release so check again
353+
str = config_get('acl', 'ace', @get_args)
354+
sstr = str.split
355+
return sstr[sstr.index('set-erspan-dscp') + 1] if
356+
sstr.include?('set-erspan-dscp')
357+
end
358+
359+
def set_erspan_dscp=(set_erspan_dscp)
360+
@set_args[:set_erspan_dscp] = Utils.attach_prefix(set_erspan_dscp,
361+
:set_erspan_dscp,
362+
'set-erspan-dscp')
363+
end
364+
365+
def set_erspan_gre_proto
366+
ret = Utils.extract_value(ace_get, 'set_erspan_gre_proto',
367+
'set-erspan-gre-proto')
368+
return ret if ret
369+
# position of set_erspan_gre_proto is different in older release
370+
# so check again
371+
str = config_get('acl', 'ace', @get_args)
372+
sstr = str.split
373+
return sstr[sstr.index('set-erspan-gre-proto') + 1] if
374+
sstr.include?('set-erspan-gre-proto')
375+
end
376+
377+
def set_erspan_gre_proto=(set_erspan_gre_proto)
378+
@set_args[:set_erspan_gre_proto] =
379+
Utils.attach_prefix(set_erspan_gre_proto,
380+
:set_erspan_gre_proto,
381+
'set-erspan-gre-proto')
382+
end
383+
264384
def time_range
265385
Utils.extract_value(ace_get, 'time_range', 'time-range')
266386
end
@@ -317,12 +437,27 @@ def redirect=(redirect)
317437
@set_args[:redirect] = Utils.attach_prefix(redirect, :redirect)
318438
end
319439

320-
def log
440+
def proto_option
321441
match = ace_get
442+
return nil if match.nil? || proto != 'icmp' || !remark.nil?
443+
# fragments is nvgen at a different location than all other
444+
# proto_option
445+
if config_get('acl', 'ace', @get_args).include?('fragments')
446+
return 'fragments'
447+
end
448+
# log is special case
449+
return nil if !match.names.include?('proto_option') ||
450+
match[:proto_option] == 'log'
451+
match[:proto_option]
452+
end
453+
454+
def proto_option=(proto_option)
455+
@set_args[:proto_option] = proto_option
456+
end
457+
458+
def log
322459
return nil unless remark.nil?
323-
return false if match.nil?
324-
return false unless match.names.include?('log')
325-
match[:log] == 'log' ? true : false
460+
config_get('acl', 'ace', @get_args).include?('log') ? true : false
326461
end
327462

328463
def log=(log)

lib/cisco_node_utils/banner.rb

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Banner provider class
2+
#
3+
# Rick Sherman et al., August 2018
4+
#
5+
# Copyright (c) 2014-2018 Cisco and/or its affiliates.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
require_relative 'node_util'
20+
21+
module Cisco
22+
# Banner - node utility class for Banner configuration management
23+
class Banner < NodeUtil
24+
attr_reader :name
25+
26+
def initialize(name)
27+
fail TypeError unless name.is_a?(String)
28+
fail ArgumentError,
29+
"This provider only accepts an id of 'default'" \
30+
unless name.eql?('default')
31+
@name = name
32+
end
33+
34+
def self.banners
35+
hash = {}
36+
hash['default'] = Banner.new('default')
37+
hash
38+
end
39+
40+
def ==(other)
41+
name == other.name
42+
end
43+
44+
def motd
45+
config_get('banner', 'motd')
46+
end
47+
48+
def motd=(val)
49+
if val.nil? && (motd != default_motd)
50+
config_set('banner', 'motd', state: 'no', motd: '')
51+
elsif !val.nil?
52+
config_set('banner',
53+
'motd',
54+
state: '',
55+
motd: "^#{val.gsub(/\n/, '\\n')}^")
56+
end
57+
end
58+
59+
def default_motd
60+
config_get_default('banner', 'motd')
61+
end
62+
end # class
63+
end # module

lib/cisco_node_utils/bridge_domain.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def default_bd_name
144144
# This type property can be defined only for one bd
145145
def fabric_control
146146
match = config_get('bridge_domain', 'fabric_control', bd: @bd_ids)
147-
match == @bd_ids ? true : false
147+
match.to_s == @bd_ids ? true : false
148148
end
149149

150150
def fabric_control=(val)

lib/cisco_node_utils/cisco_cmn_utils.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def self.merge_range(range)
362362
end # merge_range
363363

364364
def self.add_quotes(value)
365-
return value if image_version?(/7.3.0/)
365+
return value if image_version?(/7.3/)
366366
value = "\"#{value}\"" unless
367367
value.start_with?('"') && value.end_with?('"')
368368
value

0 commit comments

Comments
 (0)