cisco_node_utils 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
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