1 require 'puppetlabs_spec_helper/module_spec_helper'
2 require 'rspec-puppet-facts'
3 include RspecPuppetFacts
5 # Customize filters to ignore 3rd-party code
6 # If the rspec coverage report shows not-our-code results, add it here
9 RSpec::Puppet::Coverage.filters.push(*custom_filters)
12 # NB: This is a library of helper fns used by the rspec-puppet tests
15 # Tests that are common to all possible configurations
16 def generic_tests(options = {})
17 java_opts = options.fetch(:java_opts, '')
18 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
19 inactivity_probe = options.fetch(:inactivity_probe, :undef)
21 # Confirm that module compiles
23 it { should compile.with_all_deps }
25 # Confirm presence of classes
26 it { should contain_class('opendaylight') }
27 it { should contain_class('opendaylight::params') }
28 it { should contain_class('opendaylight::install') }
29 it { should contain_class('opendaylight::config') }
30 it { should contain_class('opendaylight::post_config') }
31 it { should contain_class('opendaylight::service') }
33 # Confirm relationships between classes
34 it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') }
35 it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') }
36 it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') }
37 it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') }
38 it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') }
39 it { should contain_class('opendaylight::post_config').that_requires('Class[opendaylight::service]') }
40 it { should contain_class('opendaylight::post_config').that_comes_before('Class[opendaylight]') }
41 it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') }
43 # Confirm presence of generic resources
44 it { should contain_service('opendaylight') }
45 it { should contain_file('org.apache.karaf.features.cfg') }
47 # Confirm properties of generic resources
48 # NB: These hashes don't work with Ruby 1.8.7, but we
49 # don't support 1.8.7 so that's okay. See issue #36.
51 should contain_service('opendaylight').with(
52 'ensure' => 'running',
54 'hasstatus' => 'true',
55 'hasrestart' => 'true',
59 should contain_file('org.apache.karaf.features.cfg').with(
61 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
68 if odl_bind_ip =~ /.*:.*/
69 java_options = '-Djava.net.preferIPv6Addresses=true'
71 java_options = '-Djava.net.preferIPv4Stack=true'
74 should contain_file_line('Karaf Java Options').with(
75 'ensure' => 'present',
76 'path' => '/opt/opendaylight/bin/karaf',
77 'line' => "EXTRA_JAVA_OPTS=\"#{java_options}\"",
78 'match' => '^EXTRA_JAVA_OPTS=.*$',
79 'after' => '^PROGNAME=.*$'
84 should contain_file('org.opendaylight.ovsdb.library.cfg').with(
86 'path' => '/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg',
89 'content' => /ovsdb-listener-ip = #{odl_bind_ip}/
94 should contain_file('default-openflow-connection-config.xml').with(
96 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/default-openflow-connection-config.xml',
99 'content' => /<address>#{odl_bind_ip}<\/address>/
103 unless inactivity_probe == :undef
105 should contain_file('Configure inactivity probe timer').with(
107 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
110 'content' => /<controller-inactivity-probe>#{inactivity_probe}<\/controller-inactivity-probe>/
117 # Shared tests that specialize in testing log file size and rollover
118 def log_settings(options = {})
119 # Extraxt params. The dafault value should be same as in opendaylight::params
120 log_max_size = options.fetch(:log_max_size, '10GB')
121 log_max_rollover = options.fetch(:log_max_rollover, 2)
122 log_rollover_fileindex = options.fetch(:log_rollover_fileindex, 'min')
123 log_pattern = options.fetch(:log_pattern, '%d{ISO8601} | %-5p | %-16t | %-60c{6} | %m%n')
124 log_mechanism = options.fetch(:log_mechanism, 'file')
125 enable_paxosgi_logger = options.fetch(:enable_paxosgi_logger, false)
127 if log_mechanism == 'console'
129 should contain_file_line('consoleappender').with(
130 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
131 'line' => 'karaf.log.console=INFO',
132 'after' => 'log4j2.rootLogger.appenderRef.Console.filter.threshold.type = ThresholdFilter',
133 'match' => '^karaf.log.console.*$'
137 should contain_file_line('direct').with(
138 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
139 'line' => 'log4j2.appender.console.direct = true',
140 'after' => 'karaf.log.console=INFO',
141 'match' => '^log4j2.appender.console.direct.*$'
147 should contain_file_line('logmaxsize').with(
148 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
149 'line' => "log4j2.appender.rolling.policies.size.size = #{log_max_size}",
150 'match' => '^log4j2.appender.rolling.policies.size.size.*$',
154 should contain_file_line('rolloverstrategy').with(
155 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
156 'line' => 'log4j2.appender.rolling.strategy.type = DefaultRolloverStrategy'
160 should contain_file_line('logmaxrollover').with(
161 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
162 'line' => "log4j2.appender.rolling.strategy.max = #{log_max_rollover}",
163 'match' => '^log4j2.appender.rolling.strategy.max.*$',
167 should contain_file_line('logrolloverfileindex').with(
168 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
169 'line' => "log4j2.appender.rolling.strategy.fileIndex = #{log_rollover_fileindex}",
170 'match' => '^log4j2.appender.rolling.strategy.fileIndex.*$',
175 should contain_file_line('logpattern').with(
176 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
177 'line' => "log4j2.pattern = #{log_pattern}",
178 'match' => '^log4j2.pattern.*$',
181 if enable_paxosgi_logger == true
188 should contain_file_line('paxosgiappenderref').with(
189 'ensure' => presence,
190 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
191 'line' => "log4j2.rootLogger.appenderRef.PaxOsgi.ref = PaxOsgi",
195 should contain_file_line('paxosgisection').with(
196 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
197 'line' => "# OSGi appender",
201 should contain_file_line('paxosgitype').with(
202 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
203 'line' => "log4j2.appender.osgi.type = PaxOsgi",
207 should contain_file_line('paxosginame').with(
208 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
209 'line' => "log4j2.appender.osgi.name = PaxOsgi",
213 should contain_file_line('paxosgifilter').with(
214 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
215 'line' => "log4j2.appender.osgi.filter = *",
220 # Shared tests that specialize in testing Karaf feature installs
221 def karaf_feature_tests(options = {})
223 # NB: This default list should be the same as the one in opendaylight::params
224 default_features = options.fetch(:default_features, ['standard', 'wrap', 'ssh'])
225 extra_features = options.fetch(:extra_features, [])
227 # The order of this list concat matters
228 features = default_features + extra_features
229 features_csv = features.join(',')
231 # Confirm properties of Karaf features config file
232 # NB: These hashes don't work with Ruby 1.8.7, but we
233 # don't support 1.8.7 so that's okay. See issue #36.
235 should contain_file('org.apache.karaf.features.cfg').with(
237 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
243 should contain_file_line('featuresBoot').with(
244 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
245 'line' => "featuresBoot=#{features_csv}",
246 'match' => '^featuresBoot=.*$',
251 # Shared tests that specialize in testing ODL's REST port config
252 def odl_rest_port_tests(options = {})
254 # NB: This default value should be the same as one in opendaylight::params
255 odl_rest_port = options.fetch(:odl_rest_port, 8181)
256 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
257 # Confirm properties of ODL REST port config file
258 # NB: These hashes don't work with Ruby 1.8.7, but we
259 # don't support 1.8.7 so that's okay. See issue #36.
261 should contain_augeas('ODL REST Port')
264 if not odl_bind_ip.eql? '0.0.0.0'
266 should contain_augeas('ODL REST IP')
267 should contain_file_line('set pax bind IP').with(
268 'ensure' => 'present',
269 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
270 'line' => "org.ops4j.pax.web.listening.addresses = #{odl_bind_ip}",
271 'require' => 'File[org.ops4j.pax.web.cfg]'
273 should contain_file_line('set karaf IP').with(
274 'ensure' => 'present',
275 'path' => '/opt/opendaylight/etc/org.apache.karaf.shell.cfg',
276 'line' => "sshHost = #{odl_bind_ip}",
277 'match' => '^sshHost\s*=.*$',
282 should_not contain_augeas('ODL REST IP')
287 should contain_file_line('set pax bind port').with(
288 'ensure' => 'present',
289 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
290 'line' => "org.osgi.service.http.port = #{odl_rest_port}",
291 'match' => '^#?org.osgi.service.http.port\s.*$',
292 'require' => 'File[org.ops4j.pax.web.cfg]'
297 def log_level_tests(options = {})
299 # NB: This default value should be the same as one in opendaylight::params
300 log_levels = options.fetch(:log_levels, {})
303 # Should contain log level config file
305 should_not contain_file_line('logger-org.opendaylight.ovsdb-level')
308 should_not contain_file_line('logger-org.opendaylight.ovsdb-name')
311 # Verify each custom log level config entry
312 log_levels.each_pair do |logger, level|
313 underscored_version = "#{logger}".gsub('.', '_')
315 should contain_file_line("logger-#{logger}-level").with(
316 'ensure' => 'present',
317 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
318 'line' => "log4j2.logger.#{underscored_version}.level = #{level}",
319 'match' => "log4j2.logger.#{underscored_version}.level = .*$"
321 should contain_file_line("logger-#{logger}-name").with(
322 'ensure' => 'present',
323 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
324 'line' => "log4j2.logger.#{underscored_version}.name = #{logger}",
325 'match' => "log4j2.logger.#{underscored_version}.name = .*$"
332 def enable_ha_tests(options = {})
334 enable_ha = options.fetch(:enable_ha, false)
335 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
336 ha_node_ips = options.fetch(:ha_node_ips, [])
337 ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false })
339 ha_node_count = ha_node_ips.size
341 if (enable_ha) && (ha_node_count < 2)
342 # Check for HA_NODE_COUNT < 2
343 fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
347 ha_node_index = ha_node_ips.index(odl_bind_ip)
349 should contain_file('akka.conf').with(
350 'path' => '/opt/opendaylight/configuration/initial/akka.conf',
354 'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
358 ha_db_modules.each do |mod, urn|
359 it { should contain_file('module-shards.conf').with(
360 'path' => '/opt/opendaylight/configuration/initial/module-shards.conf',
364 'content' => /name = "#{mod}"/
367 it { should contain_file('modules.conf').with(
368 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
374 it { should contain_file('modules.conf').with(
375 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
379 'content' => /name = "#{mod}"/,
385 should_not contain_file('akka.conf')
386 should_not contain_file('module-shards.conf')
387 should_not contain_file('modules.conf')
392 def rpm_install_tests(options = {})
394 rpm_repo = options.fetch(:rpm_repo, 'https://nexus.opendaylight.org/content/repositories/opendaylight-neon-epel-7-$basearch-devel')
397 # Default to CentOS 7 Yum repo URL
399 # Confirm presence of RPM-related resources
400 it { should contain_yumrepo('opendaylight') }
401 it { should contain_package('opendaylight') }
403 # Confirm relationships between RPM-related resources
404 it { should contain_package('opendaylight').that_requires('Yumrepo[opendaylight]') }
405 it { should contain_yumrepo('opendaylight').that_comes_before('Package[opendaylight]') }
407 # Confirm properties of RPM-related resources
408 # NB: These hashes don't work with Ruby 1.8.7, but we
409 # don't support 1.8.7 so that's okay. See issue #36.
411 should contain_yumrepo('opendaylight').with(
414 'descr' => 'OpenDaylight SDN Controller',
415 'baseurl' => "#{rpm_repo}",
419 should contain_package('opendaylight').with(
420 'ensure' => 'present',
425 def deb_install_tests(options = {})
427 deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/nitrogen')
429 # Confirm the presence of Deb-related resources
430 it { should contain_apt__ppa(deb_repo) }
431 it { should contain_package('opendaylight') }
433 # Confirm relationships between Deb-related resources
434 it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
435 it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
437 # Confirm presence of Deb-related resources
439 should contain_package('opendaylight').with(
440 'ensure' => 'present',
445 # Shared tests for unsupported OSs
446 def unsupported_os_tests(options = {})
448 expected_msg = options.fetch(:expected_msg)
449 rpm_repo = options.fetch(:rpm_repo, 'https://nexus.opendaylight.org/content/repositories/opendaylight-neon-epel-7-$basearch-devel')
451 # Confirm that classes fail on unsupported OSs
452 it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
453 it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
454 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
455 it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
457 # Confirm that other resources fail on unsupported OSs
458 it { expect { should contain_yumrepo('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
459 it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
460 it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
461 it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
464 # Shared tests that specialize in testing SNAT mechanism
465 def snat_mechanism_tests(snat_mechanism='controller')
466 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
467 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
468 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
469 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
471 # Confirm snat_mechanism
473 should contain_file('netvirt-natservice-config.xml').with(
475 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
478 'content' => /<nat-mode>#{snat_mechanism}<\/nat-mode>/
483 # Shared tests that specialize in testing SFC Config
484 def sfc_tests(options = {})
485 extra_features = options.fetch(:extra_features, [])
487 if extra_features.include? 'odl-netvirt-sfc'
493 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
494 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
495 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
496 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
499 should contain_file('genius-itm-config.xml').with(
501 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
504 'content' => /<gpe-extension-enabled>#{sfc_enabled}<\/gpe-extension-enabled>/
509 # Shared tests that specialize in testing DSCP marking config
510 def dscp_tests(options = {})
511 inherit_dscp_marking = options.fetch(:inherit_dscp_marking, false)
513 if inherit_dscp_marking
515 should contain_file('genius-itm-config.xml').with(
517 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
520 'content' => /<default-tunnel-tos>inherit<\/default-tunnel-tos>/
525 should contain_file('genius-itm-config.xml').with(
527 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
530 'content' => /<default-tunnel-tos>0<\/default-tunnel-tos>/
536 # Shared tests that specialize in testing VPP routing node config
537 def vpp_routing_node_tests(options = {})
539 # NB: This default list should be the same as the one in opendaylight::params
540 routing_node = options.fetch(:routing_node, '')
542 if routing_node.empty?
543 it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
544 it { should_not contain_file_line('routing-node') }
546 # Confirm properties of Karaf config file
547 # NB: These hashes don't work with Ruby 1.8.7, but we
548 # don't support 1.8.7 so that's okay. See issue #36.
550 should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
552 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
558 should contain_file_line('routing-node').with(
559 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
560 'line' => "routing-node=#{routing_node}",
561 'match' => '^routing-node=.*$',
567 # ODL username/password tests
568 def username_password_tests(username, password)
571 should contain_odl_user(username).with(
572 :password => password
577 # ODL websocket address tests
578 def odl_websocket_address_tests(options = {})
580 # NB: This default value should be the same as one in opendaylight::params
581 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
582 # Confirm properties of ODL REST port config file
583 # NB: These hashes don't work with Ruby 1.8.7, but we
584 # don't support 1.8.7 so that's okay. See issue #36.
586 if not odl_bind_ip.eql? '0.0.0.0'
588 should contain_file('/opt/opendaylight/etc/org.opendaylight.restconf.cfg').with(
590 'path' => '/opt/opendaylight/etc/org.opendaylight.restconf.cfg',
596 should contain_file_line('websocket-address').with(
597 'path' => '/opt/opendaylight/etc/org.opendaylight.restconf.cfg',
598 'line' => "websocket-address=#{odl_bind_ip}",
599 'match' => '^websocket-address=.*$',
604 should_not contain_file_line('websocket-address')
609 def odl_tls_tests(options = {})
610 enable_tls = options.fetch(:enable_tls, false)
611 tls_keystore_password = options.fetch(:tls_keystore_password, nil)
612 tls_trusted_certs = options.fetch(:tls_trusted_certs, [])
613 tls_keystore_password = options.fetch(:tls_keystore_password, nil)
614 tls_key_file = options.fetch(:tls_key_file, nil)
615 tls_cert_file = options.fetch(:tls_cert_file, nil)
616 tls_ca_cert_file = options.fetch(:tls_ca_cert_file, nil)
617 odl_rest_port = options.fetch(:odl_rest_port, 8181)
620 if tls_keystore_password.nil?
621 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::PreformattedError) }
625 if tls_key_file or tls_cert_file
626 if tls_key_file and tls_cert_file
628 should contain_odl_keystore('controller')
631 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::PreformattedError) }
635 should contain_augeas('Remove HTTP ODL REST Port')
636 should contain_augeas('ODL SSL REST Port')
637 should contain_file_line('set pax TLS port').with(
638 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
639 'line' => "org.osgi.service.http.port.secure = #{odl_rest_port}",
640 'match' => '^#?org.osgi.service.http.port.secure.*$',
642 should contain_file_line('set pax TLS keystore location').with(
643 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
644 'line' => 'org.ops4j.pax.web.ssl.keystore = configuration/ssl/ctl.jks',
645 'match' => '^#?org.ops4j.pax.web.ssl.keystore.*$',
647 should contain_file_line('set pax TLS keystore integrity password').with(
648 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
649 'line' => "org.ops4j.pax.web.ssl.password = #{tls_keystore_password}",
650 'match' => '^#?org.ops4j.pax.web.ssl.password.*$',
652 should contain_file_line('set pax TLS keystore password').with(
653 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
654 'line' => "org.ops4j.pax.web.ssl.keypassword = #{tls_keystore_password}",
655 'match' => '^#?org.ops4j.pax.web.ssl.keypassword.*$',
657 should contain_file('aaa-cert-config.xml').with(
659 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/aaa-cert-config.xml',
663 should contain_file('org.opendaylight.ovsdb.library.cfg').with(
665 'path' => '/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg',
668 'content' => /use-ssl = true/
670 should contain_file('/opt/opendaylight/configuration/ssl').with(
671 'ensure' => 'directory',
672 'path' => '/opt/opendaylight/configuration/ssl',
677 should contain_file_line('enable pax TLS').with(
678 'ensure' => 'present',
679 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
680 'line' => 'org.osgi.service.http.secure.enabled = true',
681 'match' => '^#?org.osgi.service.http.secure.enabled.*$',
683 should contain_file_line('disable pax HTTP').with(
684 'ensure' => 'present',
685 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
686 'line' => 'org.osgi.service.http.enabled = false',
687 'match' => '^#?org.osgi.service.http.enabled.*$',
689 should contain_file('org.ops4j.pax.web.cfg').with(
691 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
695 should contain_file('default-openflow-connection-config.xml').with(
697 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/default-openflow-connection-config.xml',
700 'content' => /<transport-protocol>TLS<\/transport-protocol>/
706 def stats_polling_enablement_tests(options = {})
708 # NB: This default value should be the same as one in opendaylight::params
709 stats_polling_enabled = options.fetch(:stats_polling_enabled, false)
710 # Confirm properties of ODL REST port config file
711 # NB: These hashes don't work with Ruby 1.8.7, but we
712 # don't support 1.8.7 so that's okay. See issue #36.
714 should contain_file('openflowplugin.cfg').with(
716 'path' => '/opt/opendaylight/etc/org.opendaylight.openflowplugin.cfg',
720 should contain_file_line('stats-polling').with(
721 'ensure' => 'present',
722 'path' => '/opt/opendaylight/etc/org.opendaylight.openflowplugin.cfg',
723 'line' => "is-statistics-polling-on=#{stats_polling_enabled}",
724 'match' => '^is-statistics-polling-on=.*$',