X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=spec%2Fspec_helper.rb;h=3318939e7725762859afd5c4877b14b47d71a469;hb=4ab2b0cf3a3ce6287cc6336a2e3f125fd0f98bb1;hp=80cd929c3fb91d2a102685cd9fe766b7cea68a8c;hpb=84d79198a63f20dad196f602fcc215c9522cf471;p=integration%2Fpackaging%2Fpuppet-opendaylight.git diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 80cd929..3318939 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,33 +1,10 @@ require 'puppetlabs_spec_helper/module_spec_helper' +require 'rspec-puppet-facts' +include RspecPuppetFacts # Customize filters to ignore 3rd-party code -# If the coverage report shows not-our-code results, add it here +# If the rspec coverage report shows not-our-code results, add it here custom_filters = [ - 'Anchor[java::end]', - 'Stage[setup]', - 'Anchor[java::begin:]', - 'Archive::Download[opendaylight.tar.gz]', - 'Archive::Download[opendaylight-systemd.tar.gz]', - 'Archive::Extract[opendaylight]', - 'Archive::Extract[opendaylight-systemd]', - 'Class[Java::Config]', - 'Class[Java::Params]', - 'Class[Stdlib::Stages]', - 'Class[Stdlib]', - 'Exec[download archive opendaylight.tar.gz and check sum]', - 'Exec[download archive opendaylight-systemd.tar.gz and check sum]', - 'Exec[opendaylight unpack]', - 'Exec[opendaylight-systemd unpack]', - 'Exec[rm-on-error-opendaylight.tar.gz]', - 'Exec[rm-on-error-opendaylight-systemd.tar.gz]', - 'Exec[update-java-alternatives]', - 'Package[curl]', - 'Stage[deploy]', - 'Stage[deploy_app]', - 'Stage[deploy_infra]', - 'Stage[runtime]', - 'Stage[setup_app]', - 'Stage[setup_infra]', ] RSpec::Puppet::Coverage.filters.push(*custom_filters) @@ -36,7 +13,11 @@ RSpec::Puppet::Coverage.filters.push(*custom_filters) # # Tests that are common to all possible configurations -def generic_tests() +def generic_tests(options = {}) + java_opts = options.fetch(:java_opts, '') + odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0') + inactivity_probe = options.fetch(:inactivity_probe, :undef) + # Confirm that module compiles it { should compile } it { should compile.with_all_deps } @@ -46,15 +27,18 @@ def generic_tests() it { should contain_class('opendaylight::params') } it { should contain_class('opendaylight::install') } it { should contain_class('opendaylight::config') } + it { should contain_class('opendaylight::post_config') } it { should contain_class('opendaylight::service') } # Confirm relationships between classes - it { should contain_class('opendaylight::install').that_comes_before('opendaylight::config') } - it { should contain_class('opendaylight::config').that_requires('opendaylight::install') } - it { should contain_class('opendaylight::config').that_notifies('opendaylight::service') } - it { should contain_class('opendaylight::service').that_subscribes_to('opendaylight::config') } - it { should contain_class('opendaylight::service').that_comes_before('opendaylight') } - it { should contain_class('opendaylight').that_requires('opendaylight::service') } + it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') } + it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') } + it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') } + it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') } + it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') } + it { should contain_class('opendaylight::post_config').that_requires('Class[opendaylight::service]') } + it { should contain_class('opendaylight::post_config').that_comes_before('Class[opendaylight]') } + it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') } # Confirm presence of generic resources it { should contain_service('opendaylight') } @@ -79,14 +63,165 @@ def generic_tests() 'group' => 'odl', ) } + + it { + if odl_bind_ip =~ /.*:.*/ + java_options = '-Djava.net.preferIPv6Addresses=true' + else + java_options = '-Djava.net.preferIPv4Stack=true' + end + + should contain_file_line('Karaf Java Options').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/bin/karaf', + 'line' => "EXTRA_JAVA_OPTS=\"#{java_options}\"", + 'match' => '^EXTRA_JAVA_OPTS=.*$', + 'after' => '^PROGNAME=.*$' + ) + } + + it { + should contain_file('org.opendaylight.ovsdb.library.cfg').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /ovsdb-listener-ip = #{odl_bind_ip}/ + ) + } + + it { + should contain_file('default-openflow-connection-config.xml').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/default-openflow-connection-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /
#{odl_bind_ip}<\/address>/ + ) + } + + unless inactivity_probe == :undef + it { + should contain_file('Configure inactivity probe timer').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /#{inactivity_probe}<\/controller-inactivity-probe>/ + ) + } + end + +end + +# Shared tests that specialize in testing log file size and rollover +def log_settings(options = {}) + # Extraxt params. The dafault value should be same as in opendaylight::params + log_max_size = options.fetch(:log_max_size, '10GB') + log_max_rollover = options.fetch(:log_max_rollover, 2) + log_rollover_fileindex = options.fetch(:log_rollover_fileindex, 'min') + log_pattern = options.fetch(:log_pattern, '%d{ISO8601} | %-5p | %-16t | %-60c{6} | %m%n') + log_mechanism = options.fetch(:log_mechanism, 'file') + enable_paxosgi_logger = options.fetch(:enable_paxosgi_logger, false) + + if log_mechanism == 'console' + it { + should contain_file_line('consoleappender').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => 'karaf.log.console=INFO', + 'after' => 'log4j2.rootLogger.appenderRef.Console.filter.threshold.type = ThresholdFilter', + 'match' => '^karaf.log.console.*$' + ) + } + it { + should contain_file_line('direct').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => 'log4j2.appender.console.direct = true', + 'after' => 'karaf.log.console=INFO', + 'match' => '^log4j2.appender.console.direct.*$' + ) + } + else + + it { + should contain_file_line('logmaxsize').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.appender.rolling.policies.size.size = #{log_max_size}", + 'match' => '^log4j2.appender.rolling.policies.size.size.*$', + ) + } + it { + should contain_file_line('rolloverstrategy').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => 'log4j2.appender.rolling.strategy.type = DefaultRolloverStrategy' + ) + } + it { + should contain_file_line('logmaxrollover').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.appender.rolling.strategy.max = #{log_max_rollover}", + 'match' => '^log4j2.appender.rolling.strategy.max.*$', + ) + } + it { + should contain_file_line('logrolloverfileindex').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.appender.rolling.strategy.fileIndex = #{log_rollover_fileindex}", + 'match' => '^log4j2.appender.rolling.strategy.fileIndex.*$', + ) + } + end + it { + should contain_file_line('logpattern').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.pattern = #{log_pattern}", + 'match' => '^log4j2.pattern.*$', + ) + } + if enable_paxosgi_logger == true + presence = 'present' + else + presence = 'absent' + end + + it { + should contain_file_line('paxosgiappenderref').with( + 'ensure' => presence, + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.rootLogger.appenderRef.PaxOsgi.ref = PaxOsgi", + ) + } + it { + should contain_file_line('paxosgisection').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "# OSGi appender", + ) + } + it { + should contain_file_line('paxosgitype').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.appender.osgi.type = PaxOsgi", + ) + } + it { + should contain_file_line('paxosginame').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.appender.osgi.name = PaxOsgi", + ) + } + it { + should contain_file_line('paxosgifilter').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.appender.osgi.filter = *", + ) + } end # Shared tests that specialize in testing Karaf feature installs def karaf_feature_tests(options = {}) # Extract params # NB: This default list should be the same as the one in opendaylight::params - # TODO: Remove this possible source of bugs^^ - default_features = options.fetch(:default_features, ['config', 'standard', 'region', 'package', 'kar', 'ssh', 'management']) + default_features = options.fetch(:default_features, ['standard', 'wrap', 'ssh']) extra_features = options.fetch(:extra_features, []) # The order of this list concat matters @@ -117,19 +252,44 @@ end def odl_rest_port_tests(options = {}) # Extract params # NB: This default value should be the same as one in opendaylight::params - # TODO: Remove this possible source of bugs^^ - odl_rest_port = options.fetch(:odl_rest_port, 8080) - + odl_rest_port = options.fetch(:odl_rest_port, 8181) + odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0') # Confirm properties of ODL REST port config file # NB: These hashes don't work with Ruby 1.8.7, but we # don't support 1.8.7 so that's okay. See issue #36. it { - should contain_file('jetty.xml').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/jetty.xml', - 'owner' => 'odl', - 'group' => 'odl', - 'content' => /Property name="jetty.port" default="#{odl_rest_port}"/ + should contain_augeas('ODL REST Port') + } + + if not odl_bind_ip.eql? '0.0.0.0' + it { + should contain_augeas('ODL REST IP') + should contain_file_line('set pax bind IP').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => "org.ops4j.pax.web.listening.addresses = #{odl_bind_ip}", + 'require' => 'File[org.ops4j.pax.web.cfg]' + ) + should contain_file_line('set karaf IP').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.apache.karaf.shell.cfg', + 'line' => "sshHost = #{odl_bind_ip}", + 'match' => '^sshHost\s*=.*$', + ) + } + else + it { + should_not contain_augeas('ODL REST IP') + } + end + + it { + should contain_file_line('set pax bind port').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => "org.osgi.service.http.port = #{odl_rest_port}", + 'match' => '^#?org.osgi.service.http.port\s.*$', + 'require' => 'File[org.ops4j.pax.web.cfg]' ) } end @@ -137,284 +297,431 @@ end def log_level_tests(options = {}) # Extract params # NB: This default value should be the same as one in opendaylight::params - # TODO: Remove this possible source of bugs^^ log_levels = options.fetch(:log_levels, {}) if log_levels.empty? # Should contain log level config file it { - should contain_file('org.ops4j.pax.logging.cfg').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', - 'owner' => 'odl', - 'group' => 'odl', - ) + should_not contain_file_line('logger-org.opendaylight.ovsdb-level') } - # Should not contain custom log level config it { - should_not contain_file('org.ops4j.pax.logging.cfg').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', - 'owner' => 'odl', - 'group' => 'odl', - 'content' => /# Log level config added by puppet-opendaylight/ - ) + should_not contain_file_line('logger-org.opendaylight.ovsdb-name') } else - # Should contain log level config file - it { - should contain_file('org.ops4j.pax.logging.cfg').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', - 'owner' => 'odl', - 'group' => 'odl', - ) - } - # Should contain custom log level config - it { - should contain_file('org.ops4j.pax.logging.cfg').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', - 'owner' => 'odl', - 'group' => 'odl', - 'content' => /# Log level config added by puppet-opendaylight/ - ) - } # Verify each custom log level config entry log_levels.each_pair do |logger, level| + underscored_version = "#{logger}".gsub('.', '_') it { - should contain_file('org.ops4j.pax.logging.cfg').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', - 'owner' => 'odl', - 'group' => 'odl', - 'content' => /^log4j.logger.#{logger} = #{level}/ + should contain_file_line("logger-#{logger}-level").with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.logger.#{underscored_version}.level = #{level}", + 'match' => "log4j2.logger.#{underscored_version}.level = .*$" + ) + should contain_file_line("logger-#{logger}-name").with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg', + 'line' => "log4j2.logger.#{underscored_version}.name = #{logger}", + 'match' => "log4j2.logger.#{underscored_version}.name = .*$" ) } end end end -# Shared tests that specialize in testing enabling L3 via ODL OVSDB -def enable_l3_tests(options = {}) +def enable_ha_tests(options = {}) # Extract params - # NB: This default value should be the same as one in opendaylight::params - # TODO: Remove this possible source of bugs^^ - enable_l3 = options.fetch(:enable_l3, 'no') + enable_ha = options.fetch(:enable_ha, false) + odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0') + ha_node_ips = options.fetch(:ha_node_ips, []) + ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false }) + # HA_NODE_IPS size + ha_node_count = ha_node_ips.size - if [true, 'yes'].include? enable_l3 - # Confirm ODL OVSDB L3 is enabled + if (enable_ha) && (ha_node_count < 2) + # Check for HA_NODE_COUNT < 2 + fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled") + end + + if enable_ha + ha_node_index = ha_node_ips.index(odl_bind_ip) it { - should contain_file('custom.properties').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/custom.properties', + should contain_file('akka.conf').with( + 'path' => '/opt/opendaylight/configuration/initial/akka.conf', + 'ensure' => 'file', 'owner' => 'odl', 'group' => 'odl', - 'content' => /^ovsdb.l3.fwd.enabled=yes/ + 'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/ ) } - elsif [false, 'no'].include? enable_l3 - # Confirm ODL OVSDB L3 is disabled - it { - should contain_file('custom.properties').with( - 'ensure' => 'file', - 'path' => '/opt/opendaylight/etc/custom.properties', + + ha_db_modules.each do |mod, urn| + it { should contain_file('module-shards.conf').with( + 'path' => '/opt/opendaylight/configuration/initial/module-shards.conf', + 'ensure' => 'file', 'owner' => 'odl', 'group' => 'odl', - 'content' => /^ovsdb.l3.fwd.enabled=no/ - ) - } + 'content' => /name = "#{mod}"/ + )} + if mod == 'default' + it { should contain_file('modules.conf').with( + 'path' => '/opt/opendaylight/configuration/initial/modules.conf', + 'ensure' => 'file', + 'owner' => 'odl', + 'group' => 'odl' + )} + else + it { should contain_file('modules.conf').with( + 'path' => '/opt/opendaylight/configuration/initial/modules.conf', + 'ensure' => 'file', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /name = "#{mod}"/, + )} + end + end + else + it { + should_not contain_file('akka.conf') + should_not contain_file('module-shards.conf') + should_not contain_file('modules.conf') + } end end -def tarball_install_tests(options = {}) +def rpm_install_tests(options = {}) # Extract params - # NB: These default values should be the same as ones in opendaylight::params - # TODO: Remove this possible source of bugs^^ - tarball_url = options.fetch(:tarball_url, 'https://nexus.opendaylight.org/content/repositories/staging/org/opendaylight/integration/distribution-karaf/0.4.0-Beryllium-RC2.2/distribution-karaf-0.4.0-Beryllium-RC2.2.tar.gz') - unitfile_url = options.fetch(:unitfile_url, 'https://github.com/dfarrell07/opendaylight-systemd/archive/master/opendaylight-unitfile.tar.gz') - osfamily = options.fetch(:osfamily, 'RedHat') - - # Confirm presence of tarball-related resources - it { should contain_archive('opendaylight') } - it { should contain_class('java') } - it { should contain_file('/opt/opendaylight/') } - it { should contain_user('odl') } - it { should contain_group('odl') } - - # Confirm relationships between tarball-related resources - it { should contain_archive('opendaylight').that_comes_before('File[/opt/opendaylight/]') } - it { should contain_archive('opendaylight').that_comes_before('User[odl]') } - it { should contain_file('/opt/opendaylight/').that_requires('Archive[opendaylight]') } - it { should contain_file('/opt/opendaylight/').that_requires('Group[odl]') } - it { should contain_file('/opt/opendaylight/').that_requires('User[odl]') } - it { should contain_user('odl').that_comes_before('File[/opt/opendaylight/]') } - it { should contain_user('odl').that_requires('Archive[opendaylight]') } - it { should contain_user('odl').that_requires('Group[odl]') } - it { should contain_group('odl').that_comes_before('File[/opt/opendaylight/]') } - it { should contain_group('odl').that_comes_before('User[odl]') } - - # Confirm properties of tarball-related resources + rpm_repo = options.fetch(:rpm_repo, 'https://nexus.opendaylight.org/content/repositories/opendaylight-neon-epel-7-$basearch-devel') + + + # Default to CentOS 7 Yum repo URL + + # Confirm presence of RPM-related resources + it { should contain_yumrepo('opendaylight') } + it { should contain_package('opendaylight') } + + # Confirm relationships between RPM-related resources + it { should contain_package('opendaylight').that_requires('Yumrepo[opendaylight]') } + it { should contain_yumrepo('opendaylight').that_comes_before('Package[opendaylight]') } + + # Confirm properties of RPM-related resources # NB: These hashes don't work with Ruby 1.8.7, but we # don't support 1.8.7 so that's okay. See issue #36. it { - should contain_archive('opendaylight').with( - 'ensure' => 'present', - 'url' => tarball_url, - 'target' => '/opt/opendaylight/', - 'checksum' => false, - 'strip_components' => 1, - 'timeout' => 600, - ) - } - it { - should contain_file('/opt/opendaylight/').with( - 'ensure' => 'directory', - 'recurse' => true, - 'owner' => 'odl', - 'group' => 'odl', + should contain_yumrepo('opendaylight').with( + 'enabled' => '1', + 'gpgcheck' => '0', + 'descr' => 'OpenDaylight SDN Controller', + 'baseurl' => "#{rpm_repo}", ) } it { - should contain_user('odl').with( - 'name' => 'odl', - 'ensure' => 'present', - 'home' => '/opt/opendaylight/', - 'membership' => 'minimum', - 'groups' => 'odl', + should contain_package('opendaylight').with( + 'ensure' => 'present', ) } +end + +def deb_install_tests(options = {}) + # Extract params + deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/nitrogen') + + # Confirm the presence of Deb-related resources + it { should contain_apt__ppa(deb_repo) } + it { should contain_package('opendaylight') } + + # Confirm relationships between Deb-related resources + it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") } + it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') } + + # Confirm presence of Deb-related resources it { - should contain_group('odl').with( - 'name' => 'odl', - 'ensure' => 'present', + should contain_package('opendaylight').with( + 'ensure' => 'present', ) } +end - # OS-specific validations - case osfamily - when 'RedHat' - # Validations specific to Red Hat family OSs (RHEL/CentOS/Fedora) - it { should contain_archive('opendaylight-systemd') } - it { should contain_file('/usr/lib/systemd/system/opendaylight.service') } - it { should contain_archive('opendaylight-systemd').that_comes_before('File[/usr/lib/systemd/system/opendaylight.service]') } - it { should contain_file('/usr/lib/systemd/system/opendaylight.service').that_requires('Archive[opendaylight-systemd]') } +# Shared tests for unsupported OSs +def unsupported_os_tests(options = {}) + # Extract params + expected_msg = options.fetch(:expected_msg) + rpm_repo = options.fetch(:rpm_repo, 'https://nexus.opendaylight.org/content/repositories/opendaylight-neon-epel-7-$basearch-devel') - # NB: These hashes don't work with Ruby 1.8.7, but we - # don't support 1.8.7 so that's okay. See issue #36. - it { - should contain_package('java').with( - 'name' => 'java-1.7.0-openjdk', + # Confirm that classes fail on unsupported OSs + it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + + # Confirm that other resources fail on unsupported OSs + it { expect { should contain_yumrepo('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } + it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) } +end + +# Shared tests that specialize in testing SNAT mechanism +def snat_mechanism_tests(snat_mechanism='controller') + it { should contain_file('/opt/opendaylight/etc/opendaylight') } + it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')} + it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')} + it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')} + + # Confirm snat_mechanism + it { + should contain_file('netvirt-natservice-config.xml').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /#{snat_mechanism}<\/nat-mode>/ ) } - it { - should contain_archive('opendaylight-systemd').with( - 'ensure' => 'present', - 'url' => unitfile_url, - 'target' => '/usr/lib/systemd/system/', - 'root_dir' => 'opendaylight.service', - 'checksum' => false, - 'strip_components' => 1, - 'follow_redirects' => true, +end + +# Shared tests that specialize in testing SFC Config +def sfc_tests(options = {}) + extra_features = options.fetch(:extra_features, []) + + if extra_features.include? 'odl-netvirt-sfc' + sfc_enabled = true + else + sfc_enabled = false + end + + it { should contain_file('/opt/opendaylight/etc/opendaylight') } + it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')} + it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')} + it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')} + + it { + should contain_file('genius-itm-config.xml').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /#{sfc_enabled}<\/gpe-extension-enabled>/ ) } +end + +# Shared tests that specialize in testing DSCP marking config +def dscp_tests(options = {}) + inherit_dscp_marking = options.fetch(:inherit_dscp_marking, false) + + if inherit_dscp_marking it { - should contain_file('/usr/lib/systemd/system/opendaylight.service').with( + should contain_file('genius-itm-config.xml').with( 'ensure' => 'file', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /inherit<\/default-tunnel-tos>/ ) } - when 'Debian' - # Validations specific to Debain family OSs (Ubuntu) + else it { - should contain_package('java').with( - 'name' => 'openjdk-7-jdk', + should contain_file('genius-itm-config.xml').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /0<\/default-tunnel-tos>/ ) } + end +end + +# Shared tests that specialize in testing VPP routing node config +def vpp_routing_node_tests(options = {}) + # Extract params + # NB: This default list should be the same as the one in opendaylight::params + routing_node = options.fetch(:routing_node, '') + + if routing_node.empty? + it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') } + it { should_not contain_file_line('routing-node') } + else + # Confirm properties of Karaf config file + # NB: These hashes don't work with Ruby 1.8.7, but we + # don't support 1.8.7 so that's okay. See issue #36. it { - should contain_file('/etc/init/opendaylight.conf').with( - 'ensure' => 'file', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', + should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg', + 'owner' => 'odl', + 'group' => 'odl', ) } - expected_msg = 'Debian has limited support, is less stable, less tested.' it { - expect { - # This could be any check, most (all?) will raise warning - should contain_file('/etc/init/opendaylight.conf').to( - raise_warning(Puppet::Warning, /#{expected_msg}/) - ) - } + should contain_file_line('routing-node').with( + 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg', + 'line' => "routing-node=#{routing_node}", + 'match' => '^routing-node=.*$', + ) } - else - fail("Unexpected osfamily #{osfamily}") end +end - # Verify that there are no unexpected resources from RPM-type installs - it { should_not contain_yumrepo('opendaylight-4-testing') } - it { should_not contain_package('opendaylight') } +# ODL username/password tests +def username_password_tests(username, password) + + it { + should contain_odl_user(username).with( + :password => password + ) + } end -def rpm_install_tests(options = {}) +# ODL websocket address tests +def odl_websocket_address_tests(options = {}) # Extract params - # Choose Yum URL based on OS (CentOS vs Fedora) - # NB: Currently using the CentOS CBS for both Fedora and CentOS - operatingsystem = options.fetch(:operatingsystem, 'CentOS') - case operatingsystem - when 'CentOS' - yum_repo = 'http://cbs.centos.org/repos/nfv7-opendaylight-4-testing/$basearch/os/' - when 'Fedora' - yum_repo = 'http://cbs.centos.org/repos/nfv7-opendaylight-4-testing/$basearch/os/' + # NB: This default value should be the same as one in opendaylight::params + odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0') + # Confirm properties of ODL REST port config file + # NB: These hashes don't work with Ruby 1.8.7, but we + # don't support 1.8.7 so that's okay. See issue #36. + + if not odl_bind_ip.eql? '0.0.0.0' + it { + should contain_file('/opt/opendaylight/etc/org.opendaylight.restconf.cfg').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/org.opendaylight.restconf.cfg', + 'owner' => 'odl', + 'group' => 'odl', + ) + } + it { + should contain_file_line('websocket-address').with( + 'path' => '/opt/opendaylight/etc/org.opendaylight.restconf.cfg', + 'line' => "websocket-address=#{odl_bind_ip}", + 'match' => '^websocket-address=.*$', + ) + } else - fail("Unknown operatingsystem: #{operatingsystem}") + it { + should_not contain_file_line('websocket-address') + } end +end - # Default to CentOS 7 Yum repo URL +def odl_tls_tests(options = {}) + enable_tls = options.fetch(:enable_tls, false) + tls_keystore_password = options.fetch(:tls_keystore_password, nil) + tls_trusted_certs = options.fetch(:tls_trusted_certs, []) + tls_keystore_password = options.fetch(:tls_keystore_password, nil) + tls_key_file = options.fetch(:tls_key_file, nil) + tls_cert_file = options.fetch(:tls_cert_file, nil) + tls_ca_cert_file = options.fetch(:tls_ca_cert_file, nil) + odl_rest_port = options.fetch(:odl_rest_port, 8181) - # Confirm presence of RPM-related resources - it { should contain_yumrepo('opendaylight-4-testing') } - it { should contain_package('opendaylight') } + if enable_tls + if tls_keystore_password.nil? + it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::PreformattedError) } + return + end - # Confirm relationships between RPM-related resources - it { should contain_package('opendaylight').that_requires('Yumrepo[opendaylight-4-testing]') } - it { should contain_yumrepo('opendaylight-4-testing').that_comes_before('Package[opendaylight]') } + if tls_key_file or tls_cert_file + if tls_key_file and tls_cert_file + it { + should contain_odl_keystore('controller') + } + else + it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::PreformattedError) } + end + end + it { + should contain_augeas('Remove HTTP ODL REST Port') + should contain_augeas('ODL SSL REST Port') + should contain_file_line('set pax TLS port').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => "org.osgi.service.http.port.secure = #{odl_rest_port}", + 'match' => '^#?org.osgi.service.http.port.secure.*$', + ) + should contain_file_line('set pax TLS keystore location').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => 'org.ops4j.pax.web.ssl.keystore = configuration/ssl/ctl.jks', + 'match' => '^#?org.ops4j.pax.web.ssl.keystore.*$', + ) + should contain_file_line('set pax TLS keystore integrity password').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => "org.ops4j.pax.web.ssl.password = #{tls_keystore_password}", + 'match' => '^#?org.ops4j.pax.web.ssl.password.*$', + ) + should contain_file_line('set pax TLS keystore password').with( + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => "org.ops4j.pax.web.ssl.keypassword = #{tls_keystore_password}", + 'match' => '^#?org.ops4j.pax.web.ssl.keypassword.*$', + ) + should contain_file('aaa-cert-config.xml').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/aaa-cert-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + ) + should contain_file('org.opendaylight.ovsdb.library.cfg').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /use-ssl = true/ + ) + should contain_file('/opt/opendaylight/configuration/ssl').with( + 'ensure' => 'directory', + 'path' => '/opt/opendaylight/configuration/ssl', + 'owner' => 'odl', + 'group' => 'odl', + 'mode' => '0755' + ) + should contain_file_line('enable pax TLS').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => 'org.osgi.service.http.secure.enabled = true', + 'match' => '^#?org.osgi.service.http.secure.enabled.*$', + ) + should contain_file_line('disable pax HTTP').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'line' => 'org.osgi.service.http.enabled = false', + 'match' => '^#?org.osgi.service.http.enabled.*$', + ) + should contain_file('org.ops4j.pax.web.cfg').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg', + 'owner' => 'odl', + 'group' => 'odl', + ) + should contain_file('default-openflow-connection-config.xml').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/default-openflow-connection-config.xml', + 'owner' => 'odl', + 'group' => 'odl', + 'content' => /TLS<\/transport-protocol>/ + ) + } + end +end - # Confirm properties of RPM-related resources +def stats_polling_enablement_tests(options = {}) + # Extract params + # NB: This default value should be the same as one in opendaylight::params + stats_polling_enabled = options.fetch(:stats_polling_enabled, false) + # Confirm properties of ODL REST port config file # NB: These hashes don't work with Ruby 1.8.7, but we # don't support 1.8.7 so that's okay. See issue #36. it { - should contain_yumrepo('opendaylight-4-testing').with( - 'enabled' => '1', - 'gpgcheck' => '0', - 'descr' => 'CentOS CBS OpenDaylight Berillium testing repository', - 'baseurl' => yum_repo, + should contain_file('openflowplugin.cfg').with( + 'ensure' => 'file', + 'path' => '/opt/opendaylight/etc/org.opendaylight.openflowplugin.cfg', + 'owner' => 'odl', + 'group' => 'odl', ) - } - it { - should contain_package('opendaylight').with( - 'ensure' => 'present', + should contain_file_line('stats-polling').with( + 'ensure' => 'present', + 'path' => '/opt/opendaylight/etc/org.opendaylight.openflowplugin.cfg', + 'line' => "is-statistics-polling-on=#{stats_polling_enabled}", + 'match' => '^is-statistics-polling-on=.*$', ) } end - -# Shared tests for unsupported OSs -def unsupported_os_tests(options = {}) - # Extract params - expected_msg = options.fetch(:expected_msg) - - # Confirm that classes fail on unsupported OSs - it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - - # Confirm that other resources fail on unsupported OSs - it { expect { should contain_yumrepo('opendaylight-4-testing') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) } - it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) } -end