cisco_node_utils 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +14 -0
  4. data/ext/mkrf_conf.rb +1 -1
  5. data/lib/cisco_node_utils/ace.rb +142 -7
  6. data/lib/cisco_node_utils/banner.rb +63 -0
  7. data/lib/cisco_node_utils/bridge_domain.rb +1 -1
  8. data/lib/cisco_node_utils/cisco_cmn_utils.rb +1 -1
  9. data/lib/cisco_node_utils/client/utils.rb +20 -10
  10. data/lib/cisco_node_utils/cmd_ref/acl.yaml +1 -1
  11. data/lib/cisco_node_utils/cmd_ref/banner.yaml +7 -0
  12. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +2 -2
  13. data/lib/cisco_node_utils/cmd_ref/hostname.yaml +8 -0
  14. data/lib/cisco_node_utils/cmd_ref/interface.yaml +20 -12
  15. data/lib/cisco_node_utils/cmd_ref/interface_hsrp_group.yaml +3 -3
  16. data/lib/cisco_node_utils/cmd_ref/ip_multicast.yaml +6 -2
  17. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +4 -1
  18. data/lib/cisco_node_utils/cmd_ref/syslog_facility.yaml +10 -0
  19. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +3 -3
  20. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +16 -0
  21. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +2 -2
  22. data/lib/cisco_node_utils/environment.rb +8 -1
  23. data/lib/cisco_node_utils/hostname.rb +62 -0
  24. data/lib/cisco_node_utils/interface.rb +59 -2
  25. data/lib/cisco_node_utils/interface_DEPRECATED.rb +5 -0
  26. data/lib/cisco_node_utils/interface_hsrp_group.rb +17 -6
  27. data/lib/cisco_node_utils/ip_multicast.rb +13 -9
  28. data/lib/cisco_node_utils/node.rb +4 -1
  29. data/lib/cisco_node_utils/syslog_facility.rb +64 -0
  30. data/lib/cisco_node_utils/syslog_server.rb +18 -13
  31. data/lib/cisco_node_utils/syslog_settings.rb +43 -1
  32. data/lib/cisco_node_utils/version.rb +1 -1
  33. data/lib/cisco_node_utils/vlan.rb +1 -1
  34. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +21 -8
  35. data/spec/environment_spec.rb +107 -0
  36. data/tests/ciscotest.rb +8 -1
  37. data/tests/test_ace.rb +60 -3
  38. data/tests/test_banner.rb +85 -0
  39. data/tests/test_bgp_af.rb +1 -1
  40. data/tests/test_hostname.rb +64 -0
  41. data/tests/test_interface.rb +22 -1
  42. data/tests/test_interface_hsrp_group.rb +12 -24
  43. data/tests/test_ip_multicast.rb +32 -21
  44. data/tests/test_nxapi.rb +8 -4
  45. data/tests/test_syslog_facility.rb +80 -0
  46. data/tests/test_syslog_server.rb +3 -2
  47. data/tests/test_syslog_settings.rb +16 -1
  48. data/tests/yum_package.yaml +5 -0
  49. metadata +12 -3
@@ -65,6 +65,7 @@ module Cisco
65
65
  end
66
66
 
67
67
  def switchport_mode_private_vlan_host
68
+ return nil if switchport_mode == :disabled
68
69
  mode = config_get('DEPRECATED',
69
70
  'switchport_mode_private_vlan_host',
70
71
  name: @name)
@@ -299,6 +300,7 @@ module Cisco
299
300
  end
300
301
 
301
302
  def switchport_mode_private_vlan_trunk_promiscuous
303
+ return nil if switchport_mode == :disabled
302
304
  config_get('DEPRECATED',
303
305
  'switchport_mode_private_vlan_trunk_promiscuous',
304
306
  name: @name)
@@ -331,6 +333,7 @@ module Cisco
331
333
  end
332
334
 
333
335
  def switchport_mode_private_vlan_trunk_secondary
336
+ return nil if switchport_mode == :disabled
334
337
  config_get('DEPRECATED',
335
338
  'switchport_mode_private_vlan_trunk_secondary',
336
339
  name: @name)
@@ -361,6 +364,7 @@ module Cisco
361
364
  end
362
365
 
363
366
  def switchport_private_vlan_trunk_allowed_vlan
367
+ return nil if switchport_mode == :disabled
364
368
  result = config_get('DEPRECATED',
365
369
  'switchport_private_vlan_trunk_allowed_vlan',
366
370
  name: @name)
@@ -400,6 +404,7 @@ module Cisco
400
404
  end
401
405
 
402
406
  def switchport_private_vlan_trunk_native_vlan
407
+ return nil if switchport_mode == :disabled
403
408
  config_get('DEPRECATED',
404
409
  'switchport_private_vlan_trunk_native_vlan',
405
410
  name: @name)
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # October 2016, Sai Chintalapudi
3
3
  #
4
- # Copyright (c) 2016 Cisco and/or its affiliates.
4
+ # Copyright (c) 2016-2018 Cisco and/or its affiliates.
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -96,6 +96,12 @@ module Cisco
96
96
  # authentication md5 key-string ABCXYZ timeout 22
97
97
  # authentication md5 key-string 7 12345678901234567890 timeout 22
98
98
  # authentication md5 key-string 7 123456789 compatibility timeout 22
99
+ # if passwd
100
+ # req auth_enc_type
101
+ # if encrypted
102
+ # req authentication_key_type, authentication_enc_type
103
+ # if key-string
104
+ # optional compat and timeout
99
105
  def authentication
100
106
  hash = {}
101
107
  hash[:auth_type] = default_authentication_auth_type
@@ -203,8 +209,13 @@ module Cisco
203
209
  end
204
210
 
205
211
  def authentication_timeout=(val)
206
- @set_args[:tval] = val
207
- @set_args[:timeout] = 'timeout'
212
+ if val.nil?
213
+ @set_args[:tval] = ''
214
+ @set_args[:timeout] = ''
215
+ else
216
+ @set_args[:tval] = val
217
+ @set_args[:timeout] = 'timeout'
218
+ end
208
219
  end
209
220
 
210
221
  def default_authentication_timeout
@@ -227,14 +238,14 @@ module Cisco
227
238
  :authentication_compatibility,
228
239
  :authentication_timeout,
229
240
  ].each do |p|
230
- send(p.to_s + '=', attrs[p]) unless attrs[p].nil?
241
+ send(p.to_s + '=', attrs[p])
231
242
  end
232
- return if @set_args[:passwd] == default_authentication_string
243
+ return if @set_args[:passwd].nil? || @set_args[:passwd].empty?
233
244
  @set_args[:state] = ''
234
245
  if @set_args[:authtype] == 'text'
235
246
  @set_args[:keytype] = @set_args[:enctype] = ''
236
247
  @set_args[:compatible] = @set_args[:timeout] = @set_args[:tval] = ''
237
- elsif @set_args[:keytype] == default_authentication_key_type
248
+ elsif @set_args[:keytype] == 'key-chain'
238
249
  @set_args[:enctype] = @set_args[:compatible] = ''
239
250
  @set_args[:timeout] = @set_args[:tval] = ''
240
251
  end
@@ -64,23 +64,27 @@ module Cisco
64
64
  end
65
65
 
66
66
  def overlay_spt_only
67
- config_get('ip_multicast', 'overlay_spt_only')
67
+ result = config_get('ip_multicast', 'overlay_spt_only')
68
+ result.nil? ? false : result
68
69
  end
69
70
 
70
71
  def overlay_spt_only=(bool)
71
72
  fail TypeError unless [true, false].include?(bool)
72
73
  @set_args[:state] = bool ? '' : 'no'
73
- if @set_args[:state] == 'no'
74
- unless overlay_spt_only == default_overlay_spt_only
75
- config_set('ip_multicast', 'overlay_spt_only', @set_args)
76
- end
77
- else
78
- config_set('ip_multicast', 'overlay_spt_only', @set_args)
79
- end
74
+ config_set('ip_multicast', 'overlay_spt_only', @set_args)
80
75
  end
81
76
 
82
77
  def default_overlay_spt_only
83
- config_get_default('ip_multicast', 'overlay_spt_only')
78
+ val = config_get_default('ip_multicast', 'overlay_spt_only')
79
+ # The default value for this property is different for older
80
+ # Nexus software verions.
81
+ #
82
+ # Versions: 7.0(3)I7(1), 7.0(3)I7(2), 7.0(3)I7(3)
83
+ # Default State: false
84
+ #
85
+ # Versions: 7.0(3)I7(4) and later
86
+ # Default State: true
87
+ node.os_version[/7\.0\(3\)I7\([1-3]\)/] ? !val : val
84
88
  end
85
89
  end
86
90
  end
@@ -122,7 +122,10 @@ module Cisco
122
122
  value = value.is_a?(Hash) ? [value] : value
123
123
  data = nil
124
124
  value.each do |row|
125
- data = row[data_key] if row[row_key].to_s[/#{row_index}/]
125
+ if row[row_key].to_s[/#{row_index}/]
126
+ data = row[data_key]
127
+ data = data.nil? ? '' : data
128
+ end
126
129
  end
127
130
  return value if data.nil?
128
131
  if regexp_filter
@@ -0,0 +1,64 @@
1
+ # Syslog facility 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
+ # SyslogFacility - node utility class for Syslog facility severity management
23
+ class SyslogFacility < NodeUtil
24
+ attr_reader :facility, :level
25
+
26
+ def initialize(opts, instantiate=true)
27
+ @facility = opts['facility']
28
+ @level = opts['level']
29
+
30
+ create if instantiate
31
+ end
32
+
33
+ def self.facilities
34
+ keys = %w(facility level)
35
+ hash = {}
36
+ facility_key_list = config_get('syslog_facility', 'facility')
37
+ return hash if facility_key_list.nil?
38
+
39
+ facility_key_list.each do |id|
40
+ hash[id[0]] = SyslogFacility.new(Hash[keys.zip(id)], false)
41
+ end
42
+
43
+ hash
44
+ end
45
+
46
+ def ==(other)
47
+ facility == other.facility && level == other.level
48
+ end
49
+
50
+ def create
51
+ config_set('syslog_facility', 'facility', state: '', facility: @facility,
52
+ level: @level)
53
+ end
54
+
55
+ def destroy
56
+ config_set('syslog_facility', 'facility', state: 'no',
57
+ facility: @facility, level: @level)
58
+ end
59
+
60
+ def level
61
+ @level.to_i
62
+ end
63
+ end # class
64
+ end # module
@@ -1,8 +1,9 @@
1
1
  # Syslog Server provider class
2
2
  #
3
+ # June 2018
3
4
  # Jonathan Tripathy et al., September 2015
4
5
  #
5
- # Copyright (c) 2014-2017 Cisco and/or its affiliates.
6
+ # Copyright (c) 2014-2018 Cisco and/or its affiliates.
6
7
  #
7
8
  # Licensed under the Apache License, Version 2.0 (the "License");
8
9
  # you may not use this file except in compliance with the License.
@@ -22,7 +23,7 @@ require 'resolv'
22
23
  module Cisco
23
24
  # SyslogServer - node utility class for syslog server configuration management
24
25
  class SyslogServer < NodeUtil
25
- attr_reader :name, :level, :port, :vrf, :severity_level
26
+ attr_reader :name, :level, :port, :vrf, :severity_level, :facility
26
27
 
27
28
  LEVEL_TO_NUM = { 'emergencies' => 0,
28
29
  'alerts' => 1,
@@ -40,6 +41,7 @@ module Cisco
40
41
  @port = opts['port']
41
42
  @vrf = opts['vrf']
42
43
  @severity_level = opts['severity_level'] || opts['level']
44
+ @facility = opts['facility']
43
45
 
44
46
  hostname_regex = /^(?=.{1,255}$)[0-9A-Za-z]
45
47
  (?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?
@@ -56,7 +58,7 @@ module Cisco
56
58
  end
57
59
 
58
60
  def self.syslogservers
59
- keys = %w(name level port vrf severity_level)
61
+ keys = %w(name level port vrf facility severity_level)
60
62
  hash = {}
61
63
  syslogservers_list = config_get('syslog_server', 'server')
62
64
  return hash if syslogservers_list.nil?
@@ -65,6 +67,7 @@ module Cisco
65
67
  value_hash = Hash[keys.zip(id)]
66
68
  value_hash['severity_level'] = value_hash['level']
67
69
  value_hash['vrf'] = 'default' if value_hash['vrf'].nil?
70
+ value_hash['facility'] = 'local7' if value_hash['facility'].nil?
68
71
  hash[id[0]] = SyslogServer.new(value_hash, false)
69
72
  end
70
73
 
@@ -93,11 +96,12 @@ module Cisco
93
96
  else
94
97
  config_set('syslog_server',
95
98
  'server',
96
- state: '',
97
- ip: @name,
98
- level: @level ? "#{@level}" : '',
99
- port: @port ? "port #{@port}" : '',
100
- vrf: @vrf ? "use-vrf #{@vrf}" : '',
99
+ state: '',
100
+ ip: @name,
101
+ level: @level ? "#{@level}" : '',
102
+ port: @port ? "port #{@port}" : '',
103
+ vrf: @vrf ? "use-vrf #{@vrf}" : '',
104
+ facility: @facility ? "facility #{@facility}" : '',
101
105
  )
102
106
  end
103
107
  end
@@ -129,11 +133,12 @@ module Cisco
129
133
  else
130
134
  config_set('syslog_server',
131
135
  'server',
132
- state: 'no',
133
- ip: @name,
134
- level: '',
135
- port: '',
136
- vrf: '',
136
+ state: 'no',
137
+ ip: @name,
138
+ level: '',
139
+ port: '',
140
+ vrf: '',
141
+ facility: '',
137
142
  )
138
143
  end
139
144
  end
@@ -1,8 +1,9 @@
1
1
  # Syslog Settings provider class
2
2
  #
3
+ # August 2018
3
4
  # Jonathan Tripathy et al., September 2015
4
5
  #
5
- # Copyright (c) 2014-2017 Cisco and/or its affiliates.
6
+ # Copyright (c) 2014-2018 Cisco and/or its affiliates.
6
7
  #
7
8
  # Licensed under the Apache License, Version 2.0 (the "License");
8
9
  # you may not use this file except in compliance with the License.
@@ -126,6 +127,47 @@ module Cisco
126
127
  units: val)
127
128
  end
128
129
 
130
+ def logfile_severity_level
131
+ logfile_severity_level =
132
+ config_get('syslog_settings', 'logfile_severity_level')
133
+ if logfile_severity_level.is_a?(Array)
134
+ if logfile_severity_level[0] == 'no'
135
+ logfile_severity_level = nil
136
+ else
137
+ logfile_severity_level = logfile_severity_level[1]
138
+ end
139
+ end
140
+ logfile_severity_level
141
+ end
142
+
143
+ def logfile_name=(logname, severity, size)
144
+ if logname
145
+ config_set(
146
+ 'syslog_settings', 'logfile_name',
147
+ state: '', logname: logname, severity: severity, size: size)
148
+ else
149
+ config_set(
150
+ 'syslog_settings', 'logfile_name',
151
+ state: 'no', logname: logname, severity: severity, size: size)
152
+ end
153
+ end
154
+
155
+ def logfile_name
156
+ logfile_name = config_get('syslog_settings', 'logfile_name')
157
+ if logfile_name.is_a?(Array)
158
+ logfile_name = (logfile_name[0] == 'no') ? 'unset' : logfile_name[1]
159
+ end
160
+ logfile_name
161
+ end
162
+
163
+ def logfile_size
164
+ logfile_size = config_get('syslog_settings', 'logfile_size')
165
+ if logfile_size.is_a?(Array)
166
+ logfile_size = (logfile_size[0] == 'no') ? nil : logfile_size[1]
167
+ end
168
+ logfile_size
169
+ end
170
+
129
171
  alias_method :time_stamp_units, :timestamp
130
172
  alias_method :time_stamp_units=, :timestamp=
131
173
  end # class
@@ -14,7 +14,7 @@
14
14
 
15
15
  # Container module for version number only.
16
16
  module CiscoNodeUtils
17
- VERSION = '1.9.0'
17
+ VERSION = '1.10.0'
18
18
  gem_version = Gem::Version.new(Gem::VERSION)
19
19
  min_gem_version = Gem::Version.new('2.1.0')
20
20
  fail 'Required rubygems version >= 2.1.0' if gem_version < min_gem_version
@@ -47,7 +47,7 @@ module Cisco
47
47
  return hash if vlan_list.nil?
48
48
 
49
49
  vlan_list.each do |id|
50
- hash[id] = Vlan.new(id, false)
50
+ hash[id.to_s] = Vlan.new(id, false)
51
51
  end
52
52
  hash
53
53
  end
@@ -112,20 +112,33 @@ module Cisco
112
112
  config_get('vxlan_vtep_vni', 'ingress_replication', @get_args)
113
113
  end
114
114
 
115
+ def set_host_reachability(vtep_name, protocol)
116
+ # This is a helper method for the ingress_replication setter.
117
+ # In later versions of Nexus, a check was added to make sure
118
+ # the host_reachability setting is correct for the desired
119
+ # ingress_replication setting.
120
+ #
121
+ case protocol
122
+ when 'bgp'
123
+ host_reachability = 'evpn'
124
+ when 'static'
125
+ host_reachability = 'flood'
126
+ else
127
+ fail "Protocol #{protocol} currently not supported"
128
+ end
129
+ VxlanVtep.new(vtep_name).host_reachability = host_reachability
130
+ end
131
+
115
132
  def remove_add_ingress_replication(protocol)
116
133
  # Note: ingress-replication is not supported on all platforms.
117
134
  # Use to_s.empty check to also handle nil check.
118
- if ingress_replication.to_s.empty?
119
- set_args_keys(state: '', protocol: protocol)
120
- config_set('vxlan_vtep_vni', 'ingress_replication', @set_args)
121
- else
122
- # Sadly, the only way to change between protocols is to
123
- # first remove the existing protocol.
135
+ unless ingress_replication.to_s.empty?
124
136
  set_args_keys(state: 'no', protocol: ingress_replication)
125
137
  config_set('vxlan_vtep_vni', 'ingress_replication', @set_args)
126
- set_args_keys(state: '', protocol: protocol)
127
- config_set('vxlan_vtep_vni', 'ingress_replication', @set_args)
128
138
  end
139
+ set_host_reachability(@set_args[:name], protocol)
140
+ set_args_keys(state: '', protocol: protocol)
141
+ config_set('vxlan_vtep_vni', 'ingress_replication', @set_args)
129
142
  end
130
143
 
131
144
  def ingress_replication=(protocol)
@@ -70,6 +70,37 @@ describe Cisco::Environment do
70
70
  end
71
71
  end
72
72
 
73
+ describe '.add_env' do
74
+ it 'rejects empty environment name' do
75
+ expect { described_class.add_env('', {}) }.to \
76
+ raise_error(ArgumentError, 'empty environment name')
77
+ end
78
+
79
+ it 'rejects incorrectly typed environment hash' do
80
+ expect { described_class.add_env('default', 'hash') }.to \
81
+ raise_error(TypeError, 'invalid environment hash')
82
+ end
83
+
84
+ context 'environment can be loaded by funcion' do
85
+ expected = {
86
+ host: '192.168.1.1',
87
+ port: nil,
88
+ username: 'admin',
89
+ password: 'admin',
90
+ cookie: nil,
91
+ }
92
+ it 'can be loaded explicitly by name' do
93
+ described_class.add_env('test', expected)
94
+ expect(Cisco::Environment.environment('test')).to eq(expected)
95
+ end
96
+
97
+ it 'can be default' do
98
+ described_class.add_env('default', expected)
99
+ expect(Cisco::Environment.environment).to eq(expected)
100
+ end
101
+ end
102
+ end
103
+
73
104
  describe '.environments' do
74
105
  before(:each) do
75
106
  allow(Cisco::Environment).to receive(:data_from_file).and_return({})
@@ -162,6 +193,82 @@ describe Cisco::Environment do
162
193
  },
163
194
  )
164
195
  end
196
+
197
+ it 'loaded file can be overridden by add_env' do
198
+ expect(Cisco::Environment).to receive(:data_from_file).with(
199
+ '/etc/cisco_node_utils.yaml').and_return(global_config)
200
+ expect(Cisco::Environment).to receive(:data_from_file).with(
201
+ '~/cisco_node_utils.yaml').and_return(user_config)
202
+ expect(Cisco::Environment.environments).to eq(
203
+ 'default' => {
204
+ host: '127.0.0.1', # global config
205
+ port: 57_799, # user overrides global
206
+ username: 'user', # user config
207
+ password: nil, # auto-populated with nil
208
+ cookie: nil,
209
+ },
210
+ 'global' => { # global config
211
+ host: nil,
212
+ port: nil,
213
+ username: 'global',
214
+ password: 'global',
215
+ cookie: nil,
216
+ },
217
+ 'user' => { # user config
218
+ host: nil,
219
+ port: nil,
220
+ username: 'user',
221
+ password: 'user',
222
+ cookie: nil,
223
+ },
224
+ )
225
+ added_env = {
226
+ host: '192.168.1.1',
227
+ port: nil,
228
+ username: 'admin',
229
+ password: 'admin',
230
+ cookie: nil,
231
+ }
232
+ overide_defult = {
233
+ host: '192.168.2.2',
234
+ port: nil,
235
+ username: 'overridden',
236
+ password: 'overridden',
237
+ cookie: nil,
238
+ }
239
+ described_class.add_env('added', added_env)
240
+ described_class.add_env('default', overide_defult)
241
+ expect(Cisco::Environment.environments).to eq(
242
+ 'added' => { # added by method
243
+ host: '192.168.1.1',
244
+ port: nil,
245
+ username: 'admin',
246
+ password: 'admin',
247
+ cookie: nil,
248
+ },
249
+ 'default' => {
250
+ host: '192.168.2.2', # method overrides files
251
+ port: nil, # method overrides files
252
+ username: 'overridden', # method overrides files
253
+ password: 'overridden', # method overrides files
254
+ cookie: nil, # auto-popuplated with nil
255
+ },
256
+ 'global' => { # global config
257
+ host: nil,
258
+ port: nil,
259
+ username: 'global',
260
+ password: 'global',
261
+ cookie: nil,
262
+ },
263
+ 'user' => { # user config
264
+ host: nil,
265
+ port: nil,
266
+ username: 'user',
267
+ password: 'user',
268
+ cookie: nil,
269
+ },
270
+ )
271
+ end
165
272
  end
166
273
 
167
274
  context '.environment' do