cisco_node_utils 0.9.0

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