cisco_node_utils 0.9.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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +3 -0
  4. data/.rubocop_todo.yml +293 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CONTRIBUTING.md +31 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +201 -0
  9. data/README.md +113 -0
  10. data/Rakefile +4 -0
  11. data/cisco_node_utils.gemspec +30 -0
  12. data/lib/cisco_node_utils.rb +33 -0
  13. data/lib/cisco_node_utils/README_YAML.md +333 -0
  14. data/lib/cisco_node_utils/cisco_cmn_utils.rb +92 -0
  15. data/lib/cisco_node_utils/command_reference.rb +415 -0
  16. data/lib/cisco_node_utils/command_reference_common.yaml +845 -0
  17. data/lib/cisco_node_utils/command_reference_n3064.yaml +13 -0
  18. data/lib/cisco_node_utils/command_reference_n7k.yaml +48 -0
  19. data/lib/cisco_node_utils/command_reference_n9k.yaml +35 -0
  20. data/lib/cisco_node_utils/configparser_lib.rb +196 -0
  21. data/lib/cisco_node_utils/interface.rb +501 -0
  22. data/lib/cisco_node_utils/interface_ospf.rb +241 -0
  23. data/lib/cisco_node_utils/node.rb +673 -0
  24. data/lib/cisco_node_utils/platform.rb +184 -0
  25. data/lib/cisco_node_utils/platform_info.rb +58 -0
  26. data/lib/cisco_node_utils/platform_info.yaml +10 -0
  27. data/lib/cisco_node_utils/router_ospf.rb +96 -0
  28. data/lib/cisco_node_utils/router_ospf_vrf.rb +258 -0
  29. data/lib/cisco_node_utils/snmpcommunity.rb +91 -0
  30. data/lib/cisco_node_utils/snmpgroup.rb +55 -0
  31. data/lib/cisco_node_utils/snmpserver.rb +150 -0
  32. data/lib/cisco_node_utils/snmpuser.rb +342 -0
  33. data/lib/cisco_node_utils/tacacs_server.rb +175 -0
  34. data/lib/cisco_node_utils/tacacs_server_host.rb +128 -0
  35. data/lib/cisco_node_utils/version.rb +17 -0
  36. data/lib/cisco_node_utils/vlan.rb +153 -0
  37. data/lib/cisco_node_utils/vtp.rb +127 -0
  38. data/lib/cisco_node_utils/yum.rb +84 -0
  39. data/tests/basetest.rb +93 -0
  40. data/tests/ciscotest.rb +136 -0
  41. data/tests/cmd_config.yaml +51 -0
  42. data/tests/cmd_config_invalid.yaml +16 -0
  43. data/tests/test_all_cisco.rb +46 -0
  44. data/tests/test_command_config.rb +192 -0
  45. data/tests/test_command_reference.rb +222 -0
  46. data/tests/test_interface.rb +1017 -0
  47. data/tests/test_interface_ospf.rb +763 -0
  48. data/tests/test_interface_svi.rb +267 -0
  49. data/tests/test_interface_switchport.rb +722 -0
  50. data/tests/test_node.rb +108 -0
  51. data/tests/test_node_ext.rb +450 -0
  52. data/tests/test_platform.rb +188 -0
  53. data/tests/test_router_ospf.rb +164 -0
  54. data/tests/test_router_ospf_vrf.rb +753 -0
  55. data/tests/test_snmpcommunity.rb +344 -0
  56. data/tests/test_snmpgroup.rb +71 -0
  57. data/tests/test_snmpserver.rb +443 -0
  58. data/tests/test_snmpuser.rb +803 -0
  59. data/tests/test_tacacs_server.rb +388 -0
  60. data/tests/test_tacacs_server_host.rb +391 -0
  61. data/tests/test_vlan.rb +264 -0
  62. data/tests/test_vtp.rb +319 -0
  63. data/tests/test_yum.rb +106 -0
  64. metadata +188 -0
@@ -0,0 +1,264 @@
1
+ # Copyright (c) 2013-2015 Cisco and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require File.expand_path("../ciscotest", __FILE__)
16
+ require File.expand_path("../../lib/cisco_node_utils/vlan", __FILE__)
17
+ require File.expand_path("../../lib/cisco_node_utils/interface", __FILE__)
18
+
19
+ include Cisco
20
+
21
+ class TestVlan < CiscoTestCase
22
+ def interface_ethernet_default(ethernet_id)
23
+ s = @device.cmd("configure terminal")
24
+ s = @device.cmd("default interface ethernet #{ethernet_id}")
25
+ s = @device.cmd("end")
26
+ node.cache_flush
27
+ end
28
+
29
+ def test_vlan_collection_not_empty
30
+ vlans = Vlan.vlans
31
+ assert_equal(false, vlans.empty?(), "VLAN collection is empty")
32
+ assert(vlans.key?("1"), "VLAN 1 does not exist")
33
+ end
34
+
35
+ def test_vlan_create_invalid
36
+ e = assert_raises(CliError) do
37
+ v = Vlan.new(5000)
38
+ end
39
+ assert_match(/Invalid value.range/, e.message)
40
+ end
41
+
42
+ def test_vlan_create_invalid_non_numeric_vlan
43
+ e = assert_raises(ArgumentError) do
44
+ v = Vlan.new("fred")
45
+ end
46
+ assert_match(/Invalid value.non-numeric/, e.message)
47
+ end
48
+
49
+ def test_vlan_create_and_destroy
50
+ v = Vlan.new(1000)
51
+ vlans = Vlan.vlans
52
+ assert(vlans.key?("1000"), "Error: failed to create vlan 1000")
53
+
54
+ v.destroy
55
+ vlans = Vlan.vlans
56
+ refute(vlans.key?("1000"), "Error: failed to destroy vlan 1000")
57
+ end
58
+
59
+ def test_vlan_name_default_1000
60
+ v = Vlan.new(1000)
61
+ assert_equal(v.default_vlan_name, v.vlan_name,
62
+ "Error: Vlan name not initialized to default")
63
+
64
+ name = "Uplink-Chicago"
65
+ v.vlan_name = name
66
+ assert_equal(name, v.vlan_name, "Error: Vlan name not updated to #{name}")
67
+
68
+ v.vlan_name = v.default_vlan_name
69
+ assert_equal(v.default_vlan_name, v.vlan_name,
70
+ "Error: Vlan name not restored to default")
71
+ v.destroy
72
+ end
73
+
74
+ def test_vlan_name_default_40
75
+ v = Vlan.new(40)
76
+ assert_equal(v.default_vlan_name, v.vlan_name,
77
+ "Error: Vlan name not initialized to default")
78
+
79
+ name = "Uplink-Chicago"
80
+ v.vlan_name = name
81
+ assert_equal(name, v.vlan_name, "Error: Vlan name not updated to #{name}")
82
+
83
+ v.vlan_name = v.default_vlan_name
84
+ assert_equal(v.default_vlan_name, v.vlan_name,
85
+ "Error: Vlan name not restored to default")
86
+ v.destroy
87
+ end
88
+
89
+ def test_vlan_name_nil
90
+ v = Vlan.new(1000)
91
+ assert_raises(TypeError) do
92
+ v.vlan_name = nil
93
+ end
94
+ v.destroy
95
+ end
96
+
97
+ def test_vlan_name_invalid
98
+ v = Vlan.new(1000)
99
+ assert_raises(TypeError) do
100
+ v.vlan_name = Cisco::Node.instance
101
+ end
102
+ v.destroy
103
+ end
104
+
105
+ def test_vlan_name_zero_length
106
+ v = Vlan.new(1000)
107
+ v.vlan_name = ""
108
+ assert("", v.vlan_name)
109
+ v.destroy
110
+ end
111
+
112
+ def test_vlan_name_length_valid
113
+ v = Vlan.new(1000)
114
+ alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
115
+ name = ""
116
+ 1.upto(VLAN_NAME_SIZE - 1) { | i |
117
+ begin
118
+ name += alphabet[i % alphabet.size, 1]
119
+ # puts "n is #{name}"
120
+ if i == VLAN_NAME_SIZE - 1
121
+ v.vlan_name = name
122
+ assert_equal(name, v.vlan_name)
123
+ end
124
+ end
125
+ }
126
+ v.destroy
127
+ end
128
+
129
+ def test_vlan_name_too_long
130
+ v = Vlan.new(1000)
131
+ name = "a" * VLAN_NAME_SIZE
132
+ assert_raises(RuntimeError, "vlan misconfig did not raise RuntimeError") do
133
+ v.vlan_name = name
134
+ end
135
+ ref = cmd_ref.lookup("vlan", "name")
136
+ assert(ref, "Error, reference not found for vlan name")
137
+ ref = nil
138
+ v.destroy
139
+ end
140
+
141
+ def test_vlan_name_duplicate
142
+ # Testbed cleanup
143
+ v = Vlan.new(1000)
144
+ v.destroy
145
+ v = Vlan.new(1001)
146
+ v.destroy
147
+ # start test
148
+ v1 = Vlan.new(1000)
149
+ v1.vlan_name = "test"
150
+ v2 = Vlan.new(1001)
151
+ assert_raises(RuntimeError, "vlan misconfig did not raise RuntimeError") do
152
+ v2.vlan_name = "test"
153
+ end
154
+ v1.destroy
155
+ v2.destroy
156
+ end
157
+
158
+ def test_vlan_state_extended
159
+ v = Vlan.new(2000)
160
+ v.state = "suspend"
161
+ v.destroy
162
+ end
163
+
164
+ def test_vlan_state_invalid
165
+ v = Vlan.new(1000)
166
+ assert_raises(RuntimeError) do
167
+ v.state = "unknown"
168
+ end
169
+ v.destroy
170
+ end
171
+
172
+ def test_vlan_state_valid
173
+ states = %w(unknown active suspend)
174
+ v = Vlan.new(1000)
175
+ states.each { | start |
176
+ states.each { | finish |
177
+ if start != "unknown" &&
178
+ finish != "unknown"
179
+ v.state = start
180
+ assert_equal(start, v.state, "start")
181
+ v.state = finish
182
+ assert_equal(finish, v.state, "finish")
183
+ end
184
+ }
185
+ }
186
+ v.destroy
187
+ end
188
+
189
+ def test_vlan_shutdown_extended
190
+ v = Vlan.new(2000)
191
+ assert_raises(RuntimeError, "vlan misconfig did not raise RuntimeError") do
192
+ v.shutdown = "shutdown"
193
+ end
194
+ v.destroy
195
+ end
196
+
197
+ def test_vlan_shutdown_valid
198
+ shutdown_states = [
199
+ true,
200
+ false
201
+ ]
202
+ v = Vlan.new(1000)
203
+ shutdown_states.each { | start |
204
+ shutdown_states.each { | finish |
205
+ v.shutdown = start
206
+ assert_equal(start, v.shutdown, "start")
207
+ v.shutdown = finish
208
+ assert_equal(finish, v.shutdown, "finish")
209
+ }
210
+ }
211
+ v.destroy
212
+ end
213
+
214
+ def test_vlan_add_remove_interface_valid
215
+ v = Vlan.new(1000)
216
+ interfaces = Interface.interfaces
217
+ interfaces_added_to_vlan = []
218
+ count = 3
219
+ interfaces.each { | name, interface |
220
+ if interface.name.match(/ethernet/) && count > 0
221
+ interfaces_added_to_vlan << name
222
+ interface.switchport_mode = :access
223
+ v.add_interface(interface)
224
+ count -= 1
225
+ end
226
+ }
227
+
228
+ interfaces = v.interfaces
229
+ interfaces.each { | name, interface |
230
+ assert_includes(interfaces_added_to_vlan, name)
231
+ assert_equal(v.vlan_id, interface.access_vlan, "Interface.access_vlan")
232
+ v.remove_interface(interface)
233
+ }
234
+
235
+ interfaces = v.interfaces
236
+ assert(interfaces.empty?)
237
+ v.destroy
238
+ end
239
+
240
+ def test_vlan_add_interface_invalid
241
+ v = Vlan.new(1000)
242
+ interface = Interface.new(interfaces[0])
243
+ interface.switchport_mode = :disabled
244
+ assert_raises(RuntimeError) {
245
+ v.add_interface(interface)
246
+ }
247
+ v.destroy
248
+ interface_ethernet_default(interfaces_id[0])
249
+ end
250
+
251
+ def test_vlan_remove_interface_invalid
252
+ v = Vlan.new(1000)
253
+ interface = Interface.new(interfaces[0])
254
+ interface.switchport_mode = :access
255
+ v.add_interface(interface)
256
+ interface.switchport_mode = :disabled
257
+ assert_raises(RuntimeError) {
258
+ v.remove_interface(interface)
259
+ }
260
+
261
+ v.destroy
262
+ interface_ethernet_default(interfaces_id[0])
263
+ end
264
+ end
@@ -0,0 +1,319 @@
1
+ # Copyright (c) 2014-2015 Cisco and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require File.expand_path("../ciscotest", __FILE__)
16
+ require File.expand_path("../../lib/cisco_node_utils/vtp", __FILE__)
17
+
18
+ class TestVtp < CiscoTestCase
19
+ def setup
20
+ super
21
+ no_feature_vtp
22
+ end
23
+
24
+ def no_feature_vtp
25
+ # VTP will raise an error if the domain is configured twice so we need to
26
+ # turn the feature off for a clean test.
27
+ @device.cmd("conf t ; no feature vtp ; end")
28
+ node.cache_flush()
29
+ end
30
+
31
+ def vtp_domain(domain)
32
+ vtp = Vtp.new
33
+ vtp.domain = domain
34
+ vtp
35
+ end
36
+
37
+ def test_vtp_create_valid
38
+ no_feature_vtp
39
+ vtp = vtp_domain("accounting")
40
+ s = @device.cmd("show run vtp | incl '^vtp domain'")
41
+ assert_match(/^vtp domain accounting/, s,
42
+ "Error: failed to create vtp domain")
43
+ vtp.destroy
44
+ end
45
+
46
+ def test_vtp_domain_name_change
47
+ no_feature_vtp
48
+ vtp = vtp_domain("accounting")
49
+ vtp_new = vtp_domain("uplink")
50
+ assert_equal("uplink", vtp.domain,
51
+ "Error: vtp domain name incorrect")
52
+ vtp_new.destroy
53
+ end
54
+
55
+ def test_vtp_create_preconfig_no_change
56
+ no_feature_vtp
57
+ s = @device.cmd("configure terminal")
58
+ s = @device.cmd("feature vtp")
59
+ s = @device.cmd("vtp domain accounting")
60
+ s = @device.cmd("end")
61
+
62
+ # Flush the cache since we've modified the device
63
+ node.cache_flush()
64
+
65
+ vtp = vtp_domain("accounting")
66
+ assert_equal("accounting", vtp.domain,
67
+ "Error: vtp domain wrong")
68
+ vtp.destroy
69
+ end
70
+
71
+ def test_vtp_create_double
72
+ no_feature_vtp
73
+ vtp = vtp_domain("accounting")
74
+ vtp_new = vtp_domain("accounting")
75
+
76
+ assert_equal("accounting", vtp.domain,
77
+ "Error: vtp domain wrong")
78
+ assert_equal("accounting", vtp_new.domain,
79
+ "Error: vtp_new domain wrong")
80
+ vtp_new.destroy
81
+ end
82
+
83
+ def test_vtp_create_domain_invalid
84
+ no_feature_vtp
85
+ assert_raises(ArgumentError) do
86
+ vtp_domain(node)
87
+ end
88
+ end
89
+
90
+ def test_vtp_create_domain_nil
91
+ no_feature_vtp
92
+ assert_raises(ArgumentError) do
93
+ vtp_domain(nil)
94
+ end
95
+ end
96
+
97
+ def test_vtp_create_domain_empty
98
+ no_feature_vtp
99
+ assert_raises(ArgumentError) do
100
+ vtp_domain("")
101
+ end
102
+ end
103
+
104
+ def test_vtp_assignment
105
+ no_feature_vtp
106
+ vtp = vtp_domain("accounting")
107
+ vtp.password = "copy_test"
108
+ assert_equal("copy_test", vtp.password,
109
+ "Error: vtp password not set")
110
+ vtp_extra = vtp
111
+ assert_equal("copy_test", vtp_extra.password,
112
+ "Error: vtp password not set")
113
+ vtp.destroy
114
+ end
115
+
116
+ def test_vtp_domain_get
117
+ no_feature_vtp
118
+ vtp = vtp_domain("accounting")
119
+ assert_equal("accounting", vtp.domain,
120
+ "Error: vtp domain incorrect")
121
+ vtp.destroy
122
+ end
123
+
124
+ def test_vtp_password_nil
125
+ no_feature_vtp
126
+ vtp = vtp_domain("accounting")
127
+ assert_raises(TypeError) do
128
+ vtp.password = nil
129
+ end
130
+ vtp.destroy
131
+ end
132
+
133
+ def test_vtp_password_default
134
+ no_feature_vtp
135
+ vtp = vtp_domain("accounting")
136
+ vtp.password = "test_me"
137
+ assert_equal("test_me", vtp.password,
138
+ "Error: vtp password not correct")
139
+
140
+ vtp.password = vtp.default_password
141
+ assert_equal(node.config_get_default("vtp", "password"), vtp.password,
142
+ "Error: vtp password not correct")
143
+
144
+ vtp.destroy
145
+ end
146
+
147
+ def test_vtp_password_zero_length
148
+ no_feature_vtp
149
+ vtp = vtp_domain("accounting")
150
+ vtp.password = ""
151
+ assert_equal("", vtp.password,
152
+ "Error: vtp password not empty")
153
+ vtp.destroy
154
+ end
155
+
156
+ def test_vtp_password_get
157
+ no_feature_vtp
158
+ vtp = vtp_domain("accounting")
159
+
160
+ s = @device.cmd("configure terminal")
161
+ s = @device.cmd("vtp password cisco123")
162
+ s = @device.cmd("end")
163
+ # Flush the cache since we've modified the device
164
+ node.cache_flush()
165
+ assert_equal("cisco123", vtp.password,
166
+ "Error: vtp password not correct")
167
+ vtp.destroy
168
+ end
169
+
170
+ def test_vtp_password_get_not_set
171
+ no_feature_vtp
172
+ vtp = vtp_domain("accounting")
173
+ assert_equal("", vtp.password,
174
+ "Error: vtp password not empty")
175
+ vtp.destroy
176
+ end
177
+
178
+ def test_vtp_password_clear
179
+ no_feature_vtp
180
+ vtp = vtp_domain("accounting")
181
+ vtp.password = "cisco123"
182
+ assert_equal("cisco123", vtp.password,
183
+ "Error: vtp password not set")
184
+
185
+ vtp.password = ""
186
+ assert_equal("", vtp.password,
187
+ "Error: vtp default password not set")
188
+
189
+ vtp.destroy
190
+ end
191
+
192
+ def test_vtp_password_valid
193
+ no_feature_vtp
194
+ vtp = vtp_domain("accounting")
195
+ alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
196
+ password = ""
197
+ 1.upto(Vtp::MAX_VTP_PASSWORD_SIZE - 1) { | i |
198
+ begin
199
+ password += alphabet[i % alphabet.size, 1]
200
+ vtp.password = password
201
+ assert_equal(password.rstrip, vtp.password,
202
+ "Error: vtp password not set")
203
+ end
204
+ }
205
+ vtp.destroy
206
+ end
207
+
208
+ def test_vtp_password_too_long
209
+ no_feature_vtp
210
+ vtp = vtp_domain("accounting")
211
+ password = "a"
212
+ Vtp::MAX_VTP_PASSWORD_SIZE.times {
213
+ password += "a"
214
+ }
215
+ assert_raises(ArgumentError) {
216
+ vtp.password = password
217
+ }
218
+ vtp.destroy
219
+ end
220
+
221
+ def test_vtp_filename_nil
222
+ no_feature_vtp
223
+ vtp = vtp_domain("accounting")
224
+ assert_raises(TypeError) do
225
+ vtp.filename = nil
226
+ end
227
+ vtp.destroy
228
+ end
229
+
230
+ def test_vtp_filename_valid
231
+ no_feature_vtp
232
+ vtp = vtp_domain("accounting")
233
+ vtp.filename = "bootflash:/test.dat"
234
+ assert_equal("bootflash:/test.dat", vtp.filename,
235
+ "Error: vtp file content wrong")
236
+ vtp.destroy
237
+ end
238
+
239
+ def test_vtp_filename_zero_length
240
+ no_feature_vtp
241
+ vtp = vtp_domain("accounting")
242
+ vtp.filename = vtp.default_filename
243
+ assert_equal(node.config_get_default("vtp", "filename"), vtp.filename,
244
+ "Error: vtp file content wrong")
245
+
246
+ # send in 'no' to remove the config. That will cause the default
247
+ # to get reapplied.
248
+ vtp.filename = ""
249
+ assert_equal(node.config_get_default("vtp", "filename"), vtp.filename,
250
+ "Error: vtp file content wrong")
251
+ vtp.destroy
252
+ end
253
+
254
+ def test_vtp_version_valid
255
+ no_feature_vtp
256
+ vtp = vtp_domain("accounting")
257
+ vtp.version = vtp.default_version
258
+ assert_equal(node.config_get_default("vtp", "version"), vtp.version,
259
+ "Error: vtp version not default")
260
+ vtp.destroy
261
+ end
262
+
263
+ def test_vtp_version3_valid
264
+ no_feature_vtp
265
+ vtp = vtp_domain("accounting")
266
+
267
+ ref = cmd_ref.lookup("vtp", "version")
268
+ assert(ref, "Error, reference not found for vtp version3")
269
+
270
+ assert_result(ref.test_config_result(3), "Error: vtp version3 error") {
271
+ vtp.version = 3
272
+ vtp.version
273
+ }
274
+
275
+ ref = nil
276
+ vtp.destroy
277
+ end
278
+
279
+ # Decides whether to check for a raised Exception or an equal value.
280
+ def assert_result(expected_result, err_msg, &block)
281
+ if /Error/ =~ expected_result.to_s
282
+ expected_result = eval(expected_result) if expected_result.is_a?(String)
283
+ assert_raises(expected_result, &block)
284
+ else
285
+ value = block.call
286
+ assert_equal(expected_result, value, err_msg)
287
+ end
288
+ end
289
+
290
+ def test_vtp_version_invalid
291
+ no_feature_vtp
292
+ vtp = vtp_domain("accounting")
293
+ assert_raises(Cisco::CliError) do
294
+ vtp.version = 34
295
+ end
296
+ vtp.destroy
297
+ end
298
+
299
+ def test_vtp_version_default
300
+ no_feature_vtp
301
+ vtp = vtp_domain("accounting")
302
+ vtp.version = 2
303
+ assert_equal(2, vtp.version,
304
+ "Error: vtp version not correct")
305
+ vtp.version = vtp.default_version
306
+ assert_equal(node.config_get_default("vtp", "version"), vtp.version,
307
+ "Error: vtp version not default")
308
+ vtp.destroy
309
+ end
310
+
311
+ def test_vtp_feature_enable_disable
312
+ no_feature_vtp
313
+ Vtp.new.enable
314
+ assert(Vtp.enabled, "Error: vtp is not enabled")
315
+
316
+ Vtp.new.destroy
317
+ refute(Vtp.enabled, "Error: vtp is not disabled")
318
+ end
319
+ end