cisco_node_utils 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +2 -1
  4. data/docs/cisco_node_utils.yaml.example +6 -0
  5. data/lib/cisco_node_utils/cisco_cmn_utils.rb +6 -15
  6. data/lib/cisco_node_utils/client/nxapi/client.rb +19 -1
  7. data/lib/cisco_node_utils/client/utils.rb +1 -1
  8. data/lib/cisco_node_utils/cmd_ref/README_YAML.md +1 -1
  9. data/lib/cisco_node_utils/cmd_ref/interface.yaml +25 -0
  10. data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +1 -1
  11. data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +1 -1
  12. data/lib/cisco_node_utils/cmd_ref/route_map.yaml +592 -0
  13. data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +40 -12
  14. data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +1 -1
  15. data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +1 -1
  16. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +1 -1
  17. data/lib/cisco_node_utils/cmd_ref/upgrade.yaml +38 -0
  18. data/lib/cisco_node_utils/dhcp_relay_global.rb +6 -2
  19. data/lib/cisco_node_utils/dns_domain.rb +2 -2
  20. data/lib/cisco_node_utils/environment.rb +1 -0
  21. data/lib/cisco_node_utils/interface.rb +58 -0
  22. data/lib/cisco_node_utils/itd_service.rb +5 -2
  23. data/lib/cisco_node_utils/node.rb +26 -13
  24. data/lib/cisco_node_utils/radius_global.rb +6 -1
  25. data/lib/cisco_node_utils/radius_server.rb +7 -1
  26. data/lib/cisco_node_utils/route_map.rb +2558 -0
  27. data/lib/cisco_node_utils/tacacs_global.rb +5 -2
  28. data/lib/cisco_node_utils/tacacs_server.rb +5 -2
  29. data/lib/cisco_node_utils/tacacs_server_host.rb +10 -4
  30. data/lib/cisco_node_utils/upgrade.rb +118 -0
  31. data/lib/cisco_node_utils/version.rb +1 -1
  32. data/spec/environment_spec.rb +16 -2
  33. data/tests/test_bgp_af.rb +8 -1
  34. data/tests/test_dhcp_relay_global.rb +3 -2
  35. data/tests/test_evpn_vni.rb +2 -2
  36. data/tests/test_feature.rb +4 -1
  37. data/tests/test_interface.rb +93 -0
  38. data/tests/test_interface_svi.rb +1 -0
  39. data/tests/test_itd_service.rb +4 -0
  40. data/tests/test_radius_global.rb +2 -2
  41. data/tests/test_radius_server.rb +6 -6
  42. data/tests/test_route_map.rb +1489 -0
  43. data/tests/test_router_bgp.rb +2 -0
  44. data/tests/test_snmpcommunity.rb +12 -0
  45. data/tests/test_snmpserver.rb +1 -1
  46. data/tests/test_snmpuser.rb +6 -9
  47. data/tests/test_tacacs_server.rb +2 -2
  48. data/tests/test_tacacs_server_host.rb +2 -2
  49. data/tests/test_upgrade.rb +106 -0
  50. data/tests/test_vlan.rb +2 -4
  51. data/tests/upgrade_info.yaml.example +3 -0
  52. data/tests/yum_package.yaml +13 -3
  53. metadata +9 -2
@@ -80,8 +80,10 @@ module Cisco
80
80
  end
81
81
 
82
82
  def key
83
- match = config_get('tacacs_global', 'key')
84
- match.empty? ? TacacsGlobal.default_key : match[1]
83
+ str = config_get('tacacs_global', 'key')
84
+ return TacacsGlobal.default_key if str.empty?
85
+ str = str[1].strip
86
+ Utils.add_quotes(str)
85
87
  end
86
88
 
87
89
  # Get default encryption password
@@ -90,6 +92,7 @@ module Cisco
90
92
  end
91
93
 
92
94
  def encryption_key_set(key_format, key)
95
+ key = Utils.add_quotes(key)
93
96
  if key_format == TACACS_GLOBAL_ENC_UNKNOWN
94
97
  config_set('tacacs_server', 'encryption', state: 'no',
95
98
  option: key_format, key: key)
@@ -145,8 +145,10 @@ module Cisco
145
145
 
146
146
  # Get encryption password
147
147
  def encryption_password
148
- match = config_get('tacacs_server', 'encryption_password')
149
- match.empty? ? TacacsServer.default_encryption_password : match[1]
148
+ str = config_get('tacacs_server', 'encryption_password')
149
+ return TacacsServer.default_encryption_password if str.empty?
150
+ str = str[1].strip
151
+ Utils.add_quotes(str)
150
152
  end
151
153
 
152
154
  # Get default encryption password
@@ -156,6 +158,7 @@ module Cisco
156
158
 
157
159
  # Set encryption type and password
158
160
  def encryption_key_set(enctype, password)
161
+ password = Utils.add_quotes(password)
159
162
  # if enctype is TACACS_SERVER_ENC_UNKNOWN, we will unset the key
160
163
  if enctype == TACACS_SERVER_ENC_UNKNOWN
161
164
  # if current encryption type is not TACACS_SERVER_ENC_UNKNOWN, we
@@ -140,10 +140,15 @@ module Cisco
140
140
  end
141
141
 
142
142
  def encryption_password
143
- config_get('tacacs_server_host',
144
- 'encryption_password',
145
- ip: @name,
146
- port: @port)
143
+ str = config_get('tacacs_server_host',
144
+ 'encryption_password',
145
+ ip: @name,
146
+ port: @port)
147
+ return str if str.nil? || str.empty?
148
+ index = str.index('port')
149
+ str = str[0..index - 2] unless index.nil?
150
+ str = str.strip
151
+ Utils.add_quotes(str)
147
152
  end
148
153
 
149
154
  def self.default_encryption_password
@@ -156,6 +161,7 @@ module Cisco
156
161
  TACACS_SERVER_ENC_CISCO_TYPE_7,
157
162
  TACACS_SERVER_ENC_UNKNOWN,
158
163
  ].include?(enctype)
164
+ password = Utils.add_quotes(password) unless password.empty?
159
165
  # if enctype is TACACS_SERVER_ENC_UNKNOWN, we'll unset the key
160
166
  if enctype == TACACS_SERVER_ENC_UNKNOWN
161
167
  # if current encryption type is not TACACS_SERVER_ENC_UNKNOWN, we need
@@ -0,0 +1,118 @@
1
+ # October 2016, Michael G Wiebe and Rahul Shenoy
2
+ #
3
+ # Copyright (c) 2016-2017 Cisco and/or its affiliates.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'node_util'
18
+ require_relative 'logger'
19
+
20
+ module Cisco
21
+ # Upgrade - node util class for upgrading Cisco devices
22
+ class Upgrade < NodeUtil
23
+ # Delete install logs from previous installation
24
+ def self.clear_status
25
+ config_set('upgrade', 'clear_status')
26
+ end
27
+
28
+ # Deletes 'image' from 'uri'
29
+ def self.delete(image, uri='bootflash:')
30
+ config_set('upgrade', 'delete', image: image, uri: uri)
31
+ rescue Cisco::CliError => e
32
+ raise e
33
+ end
34
+
35
+ # Deletes currently booted image
36
+ def self.delete_boot(uri='bootflash:')
37
+ # Incase of a N9K, N3K and N9Kv the system and kickstart images are
38
+ # the same.
39
+ # Incase of a N5K, N6K and N7K the system and kickstart images are
40
+ # different.
41
+ system_image = config_get('show_version', 'system_image').split('/')[-1]
42
+ kickstart_image = config_get('show_version', 'boot_image').split('/')[-1]
43
+ if kickstart_image == system_image
44
+ config_set('upgrade', 'delete_boot', image: system_image, uri: uri)
45
+ else
46
+ config_set('upgrade', 'delete_boot', image: system_image,
47
+ uri: uri)
48
+ config_set('upgrade', 'delete_boot', image: kickstart_image,
49
+ uri: uri)
50
+ end
51
+ rescue Cisco::CliError => e
52
+ raise e
53
+ end
54
+
55
+ # Returns version of the 'image'
56
+ def self.image_version(image=nil, uri=nil)
57
+ # Returns version of currently booted image by default
58
+ if image && uri
59
+ config_get('upgrade', 'image_version', image: image, uri: uri)
60
+ else
61
+ config_get('show_version', 'version').split(' ')[0]
62
+ end
63
+ end
64
+
65
+ # Return true if box is online and config mode is ready to be used
66
+ def self.box_online?
67
+ output = config_set('upgrade', 'is_box_online')
68
+ output[0]['body'] == {}
69
+ end
70
+
71
+ def self.save_config
72
+ config_set('upgrade', 'save_config')
73
+ rescue Cisco::CliError => e
74
+ raise e
75
+ end
76
+
77
+ # Returns True if device upgraded
78
+ def self.upgraded?
79
+ return false unless config_get('upgrade', 'upgraded')
80
+ (0..500).each do
81
+ sleep 1
82
+ return true if box_online?
83
+ end
84
+ fail 'Configuration is still blocked'
85
+ end
86
+
87
+ # Attempts to upgrade the device to 'image'
88
+ def self.upgrade(version, image, uri='bootflash:', del_boot=false,
89
+ force_all=false)
90
+ # Only 'bootflash:' is a supported URI. Fail otherwise.
91
+ fail "The Uri #{uri} is not supported" unless uri == 'bootflash:'
92
+ # IMPORTANT - Check if version of image equals the version provided.
93
+ # This is to avoid entering a loop with the Programmability Agent
94
+ # continuously trying to reload the device if versions don't match.
95
+ image_ver = image_version(image, uri)
96
+ err_str = "Version Mismatch.\n
97
+ The version of the image:#{image_ver}\n
98
+ The version provided:#{version}\n
99
+ Aborting upgrade."
100
+ fail err_str unless image_ver.to_s.strip == version.to_s.strip
101
+ delete_boot(uri) if del_boot
102
+ force_all ? upgrade_str = 'upgrade_force' : upgrade_str = 'upgrade'
103
+ begin
104
+ Cisco::Logger.debug("Upgrading to version: #{image}")
105
+ config_set('upgrade', upgrade_str, image: image, uri: uri)
106
+ rescue Cisco::RequestFailed
107
+ # Catch 'Backend Processing Error'. Install continues inspite of the
108
+ # error thrown. Resend install command and expect a CliError.
109
+ begin
110
+ config_set('upgrade', upgrade_str, image: image, uri: uri)
111
+ rescue Cisco::CliError => e
112
+ raise e unless
113
+ e.message.include?('Another install procedure may be in progress')
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -14,7 +14,7 @@
14
14
 
15
15
  # Container module for version number only.
16
16
  module CiscoNodeUtils
17
- VERSION = '1.5.0'
17
+ VERSION = '1.6.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,6 +47,7 @@ describe Cisco::Environment do
47
47
  port: 57_799,
48
48
  username: nil,
49
49
  password: nil,
50
+ cookie: nil,
50
51
  } }
51
52
  expect(Cisco::Environment).to receive(:data_from_file).and_return(
52
53
  'hello' => { host: '1.1.1.1' }, 'goodbye' => { password: 'foo' })
@@ -56,12 +57,14 @@ describe Cisco::Environment do
56
57
  port: 57_799,
57
58
  username: nil,
58
59
  password: nil,
60
+ cookie: nil,
59
61
  },
60
62
  'goodbye' => {
61
63
  host: nil,
62
64
  port: nil,
63
65
  username: nil,
64
66
  password: 'foo',
67
+ cookie: nil,
65
68
  },
66
69
  )
67
70
  end
@@ -78,12 +81,14 @@ describe Cisco::Environment do
78
81
 
79
82
  global_config = {
80
83
  'default' => {
81
- host: '127.0.0.1',
82
- port: 57_400,
84
+ host: '127.0.0.1',
85
+ port: 57_400,
86
+ cookie: nil,
83
87
  },
84
88
  'global' => {
85
89
  username: 'global',
86
90
  password: 'global',
91
+ cookie: nil,
87
92
  },
88
93
  }
89
94
 
@@ -91,10 +96,12 @@ describe Cisco::Environment do
91
96
  'default' => {
92
97
  port: 57_799,
93
98
  username: 'user',
99
+ cookie: nil,
94
100
  },
95
101
  'user' => {
96
102
  username: 'user',
97
103
  password: 'user',
104
+ cookie: nil,
98
105
  },
99
106
  }
100
107
 
@@ -137,18 +144,21 @@ describe Cisco::Environment do
137
144
  port: 57_799, # user overrides global
138
145
  username: 'user', # user config
139
146
  password: nil, # auto-populated with nil
147
+ cookie: nil,
140
148
  },
141
149
  'global' => { # global config
142
150
  host: nil,
143
151
  port: nil,
144
152
  username: 'global',
145
153
  password: 'global',
154
+ cookie: nil,
146
155
  },
147
156
  'user' => { # user config
148
157
  host: nil,
149
158
  port: nil,
150
159
  username: 'user',
151
160
  password: 'user',
161
+ cookie: nil,
152
162
  },
153
163
  )
154
164
  end
@@ -185,6 +195,7 @@ describe Cisco::Environment do
185
195
  port: nil,
186
196
  username: nil,
187
197
  password: nil,
198
+ cookie: nil,
188
199
  }
189
200
  it 'can be loaded explicitly by name' do
190
201
  expect(Cisco::Environment.environment('nxapi_local')).to eq(expected)
@@ -205,6 +216,7 @@ describe Cisco::Environment do
205
216
  port: nil,
206
217
  username: 'devops',
207
218
  password: 'devops',
219
+ cookie: nil,
208
220
  }
209
221
  it 'can be loaded explicitly by name' do
210
222
  expect(Cisco::Environment.environment('nxapi_remote')).to eq(expected)
@@ -225,6 +237,7 @@ describe Cisco::Environment do
225
237
  port: 57_999,
226
238
  username: 'admin',
227
239
  password: 'admin',
240
+ cookie: nil,
228
241
  }
229
242
  it 'can be loaded explicitly by name' do
230
243
  expect(Cisco::Environment.environment('grpc_local')).to eq(expected)
@@ -245,6 +258,7 @@ describe Cisco::Environment do
245
258
  port: nil,
246
259
  username: 'admin',
247
260
  password: 'admin',
261
+ cookie: nil,
248
262
  }
249
263
  it 'can be loaded explicitly by name' do
250
264
  expect(Cisco::Environment.environment('grpc_remote')).to eq(expected)
data/tests/test_bgp_af.rb CHANGED
@@ -168,7 +168,14 @@ class TestBgpAF < CiscoTestCase
168
168
  # to the device is available. If the entry is :runtime this
169
169
  # triggers a version check below.
170
170
  if expect == :runtime
171
- expect = Utils.image_version?(/8.0/) ? :success : :CliError
171
+ case Platform.image_version
172
+ when /8.0/
173
+ expect = :success
174
+ when /I5.2/
175
+ expect = :success if test == :maximum_paths || test == :maximum_paths_ibgp
176
+ else
177
+ expect = :CliError
178
+ end
172
179
  end
173
180
  return expect if expect == :success || expect == :skip
174
181
 
@@ -212,8 +212,9 @@ class TestDhcpRelayGlobal < CiscoTestCase
212
212
  return
213
213
  end
214
214
  assert_equal(drg.default_ipv4_sub_option_circuit_id_string, drg.ipv4_sub_option_circuit_id_string)
215
- drg.ipv4_sub_option_circuit_id_string = '%p%p'
216
- assert_equal('%p%p', drg.ipv4_sub_option_circuit_id_string)
215
+ str = '%p%p'
216
+ drg.ipv4_sub_option_circuit_id_string = str
217
+ assert_match(/#{str}/, drg.ipv4_sub_option_circuit_id_string)
217
218
  drg.ipv4_sub_option_circuit_id_string = drg.default_ipv4_sub_option_circuit_id_string
218
219
  assert_equal(drg.default_ipv4_sub_option_circuit_id_string, drg.ipv4_sub_option_circuit_id_string)
219
220
  end
@@ -75,7 +75,7 @@ class TestEvpnVni < CiscoTestCase
75
75
  vni = EvpnVni.new(4096)
76
76
  opts = [:both, :import, :export]
77
77
 
78
- # 'route_target_both' has limited support with I3 and later images.
78
+ # 'route_target_both' has limited support with I2.5 and later images.
79
79
  # The Puppet README states:
80
80
  # Caveat: The route_target_both property is discouraged due to the
81
81
  # inconsistent behavior of the property across Nexus platforms and image
@@ -86,7 +86,7 @@ class TestEvpnVni < CiscoTestCase
86
86
  # in the configuration it causes an idempotency problem for puppet. For
87
87
  # this reason it is recommended to use explicit 'route_target_export' and
88
88
  # 'route_target_import' properties instead of route_target_both.
89
- opts.delete(:both) unless Utils.nexus_i2_image
89
+ opts.delete(:both)
90
90
 
91
91
  # Master list of communities to test against
92
92
  master = ['1.2.3.4:55', '2:2', '55:33', 'auto']
@@ -225,7 +225,10 @@ class TestFeature < CiscoTestCase
225
225
  fs = 'feature-set fex'
226
226
 
227
227
  # clean
228
- config("no #{fs} ; no install #{fs}") if Feature.fex_installed?
228
+ if Feature.fex_installed?
229
+ config_no_warn("no #{fs}")
230
+ config_no_warn("no install #{fs}")
231
+ end
229
232
  refute_show_match(
230
233
  command: "show running | i '^install #{fs}$'",
231
234
  pattern: /^install #{fs}$/,
@@ -629,6 +629,7 @@ class TestInterface < CiscoTestCase
629
629
  end
630
630
 
631
631
  def test_speed
632
+ skip_legacy_defect?('7.0.3.I5.2', 'CSCvd41419')
632
633
  interface = Interface.new(interfaces[0])
633
634
  if validate_property_excluded?('interface', 'speed')
634
635
  assert_nil(interface.speed)
@@ -664,6 +665,7 @@ class TestInterface < CiscoTestCase
664
665
  end
665
666
 
666
667
  def test_duplex
668
+ skip_legacy_defect?('7.0.3.I5.2', 'CSCvd41419')
667
669
  interface = Interface.new(interfaces[0])
668
670
  if validate_property_excluded?('interface', 'duplex')
669
671
  assert_nil(interface.duplex)
@@ -818,6 +820,7 @@ class TestInterface < CiscoTestCase
818
820
  end
819
821
 
820
822
  def test_negotiate_auto_ethernet
823
+ skip_legacy_defect?('7.0.3.I5.2', 'CSCvd41419')
821
824
  inf_name = interfaces[0]
822
825
  interface = Interface.new(inf_name)
823
826
 
@@ -1740,4 +1743,94 @@ class TestInterface < CiscoTestCase
1740
1743
  interface.pim_bfd = interface.default_pim_bfd
1741
1744
  assert_equal(interface.default_pim_bfd, interface.pim_bfd)
1742
1745
  end
1746
+
1747
+ def test_load_interval_counter_1_delay
1748
+ inf_name = interfaces[0]
1749
+ interface = Interface.new(inf_name)
1750
+ if validate_property_excluded?('interface',
1751
+ 'load_interval_counter_1_delay')
1752
+ assert_nil(interface.load_interval_counter_1_delay)
1753
+ assert_raises(Cisco::UnsupportedError) do
1754
+ interface.load_interval_counter_1_delay = 100
1755
+ end
1756
+ return
1757
+ end
1758
+ assert_equal(interface.default_load_interval_counter_1_delay,
1759
+ interface.load_interval_counter_1_delay)
1760
+ interface.load_interval_counter_1_delay = 100
1761
+ assert_equal(100, interface.load_interval_counter_1_delay)
1762
+ interface.load_interval_counter_1_delay =
1763
+ interface.default_load_interval_counter_1_delay
1764
+ assert_equal(interface.default_load_interval_counter_1_delay,
1765
+ interface.load_interval_counter_1_delay)
1766
+ # check nil for subintf and loopback
1767
+ subif = Interface.new(interfaces[0] + '.1')
1768
+ assert_nil(subif.load_interval_counter_1_delay)
1769
+ assert_raises(ArgumentError) { subif.load_interval_counter_1_delay = 100 }
1770
+ lb = Interface.new('loopback0')
1771
+ assert_nil(lb.load_interval_counter_1_delay)
1772
+ assert_raises(ArgumentError) { lb.load_interval_counter_1_delay = 100 }
1773
+ subif.destroy
1774
+ lb.destroy
1775
+ end
1776
+
1777
+ def test_load_interval_counter_2_delay
1778
+ inf_name = interfaces[0]
1779
+ interface = Interface.new(inf_name)
1780
+ if validate_property_excluded?('interface',
1781
+ 'load_interval_counter_2_delay')
1782
+ assert_nil(interface.load_interval_counter_2_delay)
1783
+ assert_raises(Cisco::UnsupportedError) do
1784
+ interface.load_interval_counter_2_delay = 200
1785
+ end
1786
+ return
1787
+ end
1788
+ assert_equal(interface.default_load_interval_counter_2_delay,
1789
+ interface.load_interval_counter_2_delay)
1790
+ interface.load_interval_counter_2_delay = 200
1791
+ assert_equal(200, interface.load_interval_counter_2_delay)
1792
+ interface.load_interval_counter_2_delay =
1793
+ interface.default_load_interval_counter_2_delay
1794
+ assert_equal(interface.default_load_interval_counter_2_delay,
1795
+ interface.load_interval_counter_2_delay)
1796
+ # check nil for subintf and loopback
1797
+ subif = Interface.new(interfaces[0] + '.1')
1798
+ assert_nil(subif.load_interval_counter_2_delay)
1799
+ assert_raises(ArgumentError) { subif.load_interval_counter_2_delay = 100 }
1800
+ lb = Interface.new('loopback0')
1801
+ assert_nil(lb.load_interval_counter_2_delay)
1802
+ assert_raises(ArgumentError) { lb.load_interval_counter_2_delay = 100 }
1803
+ subif.destroy
1804
+ lb.destroy
1805
+ end
1806
+
1807
+ def test_load_interval_counter_3_delay
1808
+ inf_name = interfaces[0]
1809
+ interface = Interface.new(inf_name)
1810
+ if validate_property_excluded?('interface',
1811
+ 'load_interval_counter_3_delay')
1812
+ assert_nil(interface.load_interval_counter_3_delay)
1813
+ assert_raises(Cisco::UnsupportedError) do
1814
+ interface.load_interval_counter_3_delay = 150
1815
+ end
1816
+ return
1817
+ end
1818
+ assert_equal(interface.default_load_interval_counter_3_delay,
1819
+ interface.load_interval_counter_3_delay)
1820
+ interface.load_interval_counter_3_delay = 150
1821
+ assert_equal(150, interface.load_interval_counter_3_delay)
1822
+ interface.load_interval_counter_3_delay =
1823
+ interface.default_load_interval_counter_3_delay
1824
+ assert_equal(interface.default_load_interval_counter_3_delay,
1825
+ interface.load_interval_counter_3_delay)
1826
+ # check nil for subintf and loopback
1827
+ subif = Interface.new(interfaces[0] + '.1')
1828
+ assert_nil(subif.load_interval_counter_3_delay)
1829
+ assert_raises(ArgumentError) { subif.load_interval_counter_3_delay = 100 }
1830
+ lb = Interface.new('loopback0')
1831
+ assert_nil(lb.load_interval_counter_3_delay)
1832
+ assert_raises(ArgumentError) { lb.load_interval_counter_3_delay = 100 }
1833
+ subif.destroy
1834
+ lb.destroy
1835
+ end
1743
1836
  end