├── .gitignore ├── .gitreview ├── Rakefile ├── README.markdown ├── Gemfile ├── lib └── puppet │ ├── provider │ ├── tempest_config │ │ └── ini_setting.rb │ ├── tempest_glance_id_setter │ │ └── ruby.rb │ └── tempest_neutron_net_id_setter │ │ └── ruby.rb │ └── type │ ├── tempest_neutron_net_id_setter.rb │ ├── tempest_glance_id_setter.rb │ └── tempest_config.rb ├── Modulefile └── manifests ├── params.pp └── init.pp /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | spec/fixtures/modules/* 3 | spec/fixtures/manifests/site.pp 4 | *.swp 5 | pkg 6 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=review.openstack.org 3 | port=29418 4 | project=stackforge/puppet-tempest.git 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'puppetlabs_spec_helper/rake_tasks' 2 | require 'puppet-lint/tasks/puppet-lint' 3 | 4 | PuppetLint.configuration.fail_on_warnings = true 5 | PuppetLint.configuration.send('disable_80chars') 6 | PuppetLint.configuration.send('disable_class_parameter_defaults') 7 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Module for installing and configuring tempest. 2 | 3 | Tempest is the test suite that can be used to run integration 4 | tests on an installed openstack environment. 5 | 6 | This module assumes the provisioning of the initial OpenStack 7 | resources has been done beforehand. 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | group :development, :test do 4 | gem 'puppetlabs_spec_helper', :require => false 5 | gem 'puppet-lint', '~> 0.3.2' 6 | end 7 | 8 | if puppetversion = ENV['PUPPET_GEM_VERSION'] 9 | gem 'puppet', puppetversion, :require => false 10 | else 11 | gem 'puppet', :require => false 12 | end 13 | 14 | # vim:ft=ruby 15 | -------------------------------------------------------------------------------- /lib/puppet/provider/tempest_config/ini_setting.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.type(:tempest_config).provide( 2 | :ini_setting, 3 | :parent => Puppet::Type.type(:ini_setting).provider(:ruby) 4 | ) do 5 | 6 | def section 7 | resource[:name].split('/', 2).first 8 | end 9 | 10 | def setting 11 | resource[:name].split('/', 2).last 12 | end 13 | 14 | def separator 15 | '=' 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /lib/puppet/type/tempest_neutron_net_id_setter.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:tempest_neutron_net_id_setter) do 2 | 3 | ensurable 4 | 5 | newparam(:name, :namevar => true) do 6 | desc 'The name of the setting to update.' 7 | end 8 | 9 | newparam(:tempest_conf_path) do 10 | desc 'The path to tempest conf file.' 11 | end 12 | 13 | newparam(:network_name) do 14 | desc 'The name of the neutron network.' 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /Modulefile: -------------------------------------------------------------------------------- 1 | name 'puppet-tempest' 2 | version '0.0.1' 3 | source 'https://github.com/stackforge/puppet-tempest' 4 | license 'Apache License 2.0' 5 | summary 'Puppet module for Tempest' 6 | description 'Puppet module to install and configure Tempest' 7 | project_page 'https://launchpad.net/puppet-tempest' 8 | 9 | dependency 'puppetlabs/inifile', '>=1.0.0 <2.0.0' 10 | dependency 'puppetlabs/stdlib', '>=2.5.0' 11 | dependency 'puppetlabs/vcsrepo', '>=0.1.2 <1.0.0' 12 | -------------------------------------------------------------------------------- /lib/puppet/type/tempest_glance_id_setter.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:tempest_glance_id_setter) do 2 | # 3 | # tempest_glance_id_setter { 'image_id': 4 | # tempest_conf_path => '/var/lib/tempest/etc/tempest.conf', 5 | # image_name => $name, 6 | # } 7 | # 8 | 9 | ensurable 10 | 11 | newparam(:name, :namevar => true) do 12 | desc 'name of the setting to update' 13 | end 14 | 15 | newparam(:tempest_conf_path) do 16 | desc 'path to tempest conf file' 17 | end 18 | 19 | newparam(:image_name) do 20 | desc 'name of glance image' 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /lib/puppet/type/tempest_config.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.newtype(:tempest_config) do 2 | 3 | ensurable 4 | 5 | newparam(:name, :namevar => true) do 6 | desc 'Section/setting name to manage from tempest.conf' 7 | newvalues(/\S+\/\S+/) 8 | end 9 | 10 | newproperty(:value) do 11 | desc 'The value of the setting to be defined.' 12 | munge do |value| 13 | value = value.to_s.strip 14 | value.capitalize! if value =~ /^(true|false)$/i 15 | value 16 | end 17 | end 18 | 19 | newparam(:path) do 20 | desc 'The ini file Puppet will ensure contains the specified setting.' 21 | validate do |value| 22 | unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/)) 23 | raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'") 24 | end 25 | end 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /manifests/params.pp: -------------------------------------------------------------------------------- 1 | # 2 | class tempest::params { 3 | case $::osfamily { 4 | 'RedHat': { 5 | $pip_bin_path = '/usr/bin' 6 | if $::operatingsystem == 'Fedora' and $::operatingsystemrelease >= 19 { 7 | $pkg_set1 = [ 'mariadb-devel' ] 8 | } else { 9 | $pkg_set1 = [ 'mysql-devel' ] 10 | } 11 | $pkg_set2 = [ 12 | 'python-devel', 13 | 'libxslt-devel', 14 | 'libxml2-devel', 15 | 'openssl-devel', 16 | 'postgresql-devel', 17 | 'patch', 18 | 'gcc', 19 | ] 20 | $dev_packages = concat( $pkg_set1, $pkg_set2 ) 21 | } 22 | 'Debian': { 23 | $pip_bin_path = '/usr/local/bin' 24 | $dev_packages = [ 25 | 'libmysqlclient-dev', 26 | 'libpq-dev', 27 | 'python-dev', 28 | 'libxslt1-dev', 29 | 'libxml2-dev', 30 | 'libssl-dev', 31 | 'patch', 32 | 'gcc', 33 | ] 34 | } 35 | default: { 36 | fail("Unsupported osfamily: ${::osfamily} operatingsystem: ${::operatingsystem}, module ${module_name} only support osfamily RedHat and Debian") 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /lib/puppet/provider/tempest_glance_id_setter/ruby.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.type(:tempest_glance_id_setter).provide(:ruby) do 2 | 3 | # almost entirely lifted from stdlib's file_line 4 | 5 | def exists? 6 | lines.find do |line| 7 | should_line.chomp == line.chomp 8 | end 9 | end 10 | 11 | def create 12 | handle_create_with_match 13 | end 14 | 15 | def get_image_id 16 | @image_id ||= model.catalog.resource("Glance_image[#{resource[:image_name]}]").provider.id 17 | end 18 | 19 | def should_line 20 | "#{resource[:name]} = #{get_image_id}" 21 | end 22 | 23 | def match 24 | /^\s*#{resource[:name]}\s*=\s*/ 25 | end 26 | 27 | def handle_create_with_match() 28 | regex = match 29 | match_count = lines.select { |l| regex.match(l) }.count 30 | if match_count > 1 31 | raise Puppet::Error, "More than one line in file '#{resource[:tempest_conf_path]}' matches pattern '#{regex.to_s}'" 32 | end 33 | File.open(resource[:tempest_conf_path], 'w') do |fh| 34 | lines.each do |l| 35 | fh.puts(regex.match(l) ? should_line : l) 36 | end 37 | 38 | if (match_count == 0) 39 | fh.puts(should_line) 40 | end 41 | end 42 | end 43 | 44 | private 45 | def lines 46 | # If this type is ever used with very large files, we should 47 | # write this in a different way, using a temp 48 | # file; for now assuming that this type is only used on 49 | # small-ish config files that can fit into memory without 50 | # too much trouble. 51 | @lines ||= File.readlines(resource[:tempest_conf_path]) 52 | end 53 | 54 | end 55 | -------------------------------------------------------------------------------- /lib/puppet/provider/tempest_neutron_net_id_setter/ruby.rb: -------------------------------------------------------------------------------- 1 | Puppet::Type.type(:tempest_neutron_net_id_setter).provide(:ruby) do 2 | 3 | # almost entirely lifted from stdlib's file_line 4 | 5 | def exists? 6 | lines.find do |line| 7 | should_line.chomp == line.chomp 8 | end 9 | end 10 | 11 | def create 12 | handle_create_with_match 13 | end 14 | 15 | def self.get_network_id(network_name) 16 | network = Puppet::Type.type('neutron_network').instances.find do |i| 17 | i.provider.name == network_name 18 | end 19 | if network 20 | return network.provider.id 21 | end 22 | end 23 | 24 | def get_network_id 25 | @network_id ||= self.class.get_network_id(@resource[:network_name]) 26 | end 27 | 28 | def should_line 29 | "#{resource[:name]} = #{get_network_id}" 30 | end 31 | 32 | def match 33 | /^\s*#{resource[:name]}\s*=\s*/ 34 | end 35 | 36 | def handle_create_with_match() 37 | regex = match 38 | match_count = lines.select { |l| regex.match(l) }.count 39 | if match_count > 1 40 | raise Puppet::Error, "More than one line in file \ 41 | '#{resource[:tempest_conf_path]}' matches pattern '#{regex.to_s}'" 42 | end 43 | File.open(resource[:tempest_conf_path], 'w') do |fh| 44 | lines.each do |l| 45 | fh.puts(regex.match(l) ? should_line : l) 46 | end 47 | 48 | if (match_count == 0) 49 | fh.puts(should_line) 50 | end 51 | end 52 | end 53 | 54 | private 55 | def lines 56 | # If this type is ever used with very large files, we should 57 | # write this in a different way, using a temp 58 | # file; for now assuming that this type is only used on 59 | # small-ish config files that can fit into memory without 60 | # too much trouble. 61 | @lines ||= File.readlines(resource[:tempest_conf_path]) 62 | end 63 | 64 | end 65 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # class for installing and configuring tempest 2 | # 3 | # The class checks out the tempest repo and sets the basic config. 4 | # 5 | # Note that only parameters for which values are provided will be 6 | # managed in tempest.conf. 7 | # 8 | class tempest( 9 | # Clone config 10 | # 11 | $tempest_repo_uri = 'git://github.com/openstack/tempest.git', 12 | $tempest_repo_revision = undef, 13 | $tempest_clone_path = '/var/lib/tempest', 14 | $tempest_clone_owner = 'root', 15 | 16 | $setup_venv = false, 17 | 18 | # Glance image config 19 | # 20 | $configure_images = true, 21 | $image_name = undef, 22 | $image_name_alt = undef, 23 | 24 | # Neutron network config 25 | # 26 | $configure_networks = true, 27 | $public_network_name = undef, 28 | 29 | # tempest.conf parameters 30 | # 31 | $identity_uri = undef, 32 | # non admin user 33 | $username = undef, 34 | $password = undef, 35 | $tenant_name = undef, 36 | # another non-admin user 37 | $alt_username = undef, 38 | $alt_password = undef, 39 | $alt_tenant_name = undef, 40 | # admin user 41 | $admin_username = undef, 42 | $admin_password = undef, 43 | $admin_tenant_name = undef, 44 | $admin_role = undef, 45 | # image information 46 | $image_ref = undef, 47 | $image_ref_alt = undef, 48 | $image_ssh_user = undef, 49 | $image_alt_ssh_user = undef, 50 | $flavor_ref = undef, 51 | $flavor_ref_alt = undef, 52 | # whitebox 53 | $whitebox_db_uri = undef, 54 | # testing features that are supported 55 | $resize_available = undef, 56 | $change_password_available = undef, 57 | # neutron config 58 | $public_network_id = undef, 59 | # Upstream has a bad default - set it to empty string. 60 | $public_router_id = '', 61 | # Service configuration 62 | $cinder_available = true, 63 | $glance_available = true, 64 | $heat_available = false, 65 | $horizon_available = true, 66 | $neutron_available = false, 67 | $nova_available = true, 68 | $swift_available = false 69 | ) { 70 | 71 | include 'tempest::params' 72 | 73 | ensure_packages([ 74 | 'git', 75 | 'python-setuptools', 76 | ]) 77 | 78 | ensure_packages($tempest::params::dev_packages) 79 | 80 | exec { 'install-pip': 81 | command => '/usr/bin/easy_install pip', 82 | unless => '/usr/bin/which pip', 83 | require => Package['python-setuptools'], 84 | } 85 | 86 | exec { 'install-tox': 87 | command => "${tempest::params::pip_bin_path}/pip install -U tox", 88 | unless => '/usr/bin/which tox', 89 | require => Exec['install-pip'], 90 | } 91 | 92 | vcsrepo { $tempest_clone_path: 93 | ensure => 'present', 94 | source => $tempest_repo_uri, 95 | revision => $tempest_repo_revision, 96 | provider => 'git', 97 | require => Package['git'], 98 | user => $tempest_clone_owner, 99 | } 100 | 101 | if $setup_venv { 102 | # virtualenv will be installed along with tox 103 | exec { 'setup-venv': 104 | command => "/usr/bin/python ${tempest_clone_path}/tools/install_venv.py", 105 | cwd => $tempest_clone_path, 106 | unless => "/usr/bin/test -d ${tempest_clone_path}/.venv", 107 | require => [ 108 | Vcsrepo[$tempest_clone_path], 109 | Exec['install-tox'], 110 | ], 111 | } 112 | } 113 | 114 | $tempest_conf = "${tempest_clone_path}/etc/tempest.conf" 115 | 116 | file { $tempest_conf: 117 | replace => false, 118 | source => "${tempest_conf}.sample", 119 | require => Vcsrepo[$tempest_clone_path], 120 | owner => $tempest_clone_owner, 121 | } 122 | 123 | Tempest_config { 124 | path => $tempest_conf, 125 | require => File[$tempest_conf], 126 | } 127 | 128 | tempest_config { 129 | 'compute/change_password_available': value => $change_password_available; 130 | 'compute/flavor_ref': value => $flavor_ref; 131 | 'compute/flavor_ref_alt': value => $flavor_ref_alt; 132 | 'compute/image_alt_ssh_user': value => $image_alt_ssh_user; 133 | 'compute/image_ref': value => $image_ref; 134 | 'compute/image_ref_alt': value => $image_ref_alt; 135 | 'compute/image_ssh_user': value => $image_ssh_user; 136 | 'compute/resize_available': value => $resize_available; 137 | 'identity/admin_password': value => $admin_password; 138 | 'identity/admin_tenant_name': value => $admin_tenant_name; 139 | 'identity/admin_username': value => $admin_username; 140 | 'identity/admin_role': value => $admin_role; 141 | 'identity/alt_password': value => $alt_password; 142 | 'identity/alt_tenant_name': value => $alt_tenant_name; 143 | 'identity/alt_username': value => $alt_username; 144 | 'identity/password': value => $password; 145 | 'identity/tenant_name': value => $tenant_name; 146 | 'identity/uri': value => $identity_uri; 147 | 'identity/username': value => $username; 148 | 'network/public_network_id': value => $public_network_id; 149 | 'network/public_router_id': value => $public_router_id; 150 | 'service_available/cinder': value => $cinder_available; 151 | 'service_available/glance': value => $glance_available; 152 | 'service_available/heat': value => $heat_available; 153 | 'service_available/horizon': value => $horizon_available; 154 | 'service_available/neutron': value => $neutron_available; 155 | 'service_available/nova': value => $nova_available; 156 | 'service_available/swift': value => $swift_available; 157 | 'whitebox/db_uri': value => $whitebox_db_uri; 158 | } 159 | 160 | if $configure_images { 161 | if ! $image_ref and $image_name { 162 | # If the image id was not provided, look it up via the image name 163 | # and set the value in the conf file. 164 | tempest_glance_id_setter { 'image_ref': 165 | ensure => present, 166 | tempest_conf_path => $tempest_conf, 167 | image_name => $image_name, 168 | require => File[$tempest_conf], 169 | } 170 | } 171 | else { 172 | fail('A value for either image_name or image_ref must be provided.') 173 | } 174 | if ! $image_ref_alt and $image_name_alt { 175 | tempest_glance_id_setter { 'image_ref_alt': 176 | ensure => present, 177 | tempest_conf_path => $tempest_conf, 178 | image_name => $image_name_alt, 179 | require => File[$tempest_conf], 180 | } 181 | } 182 | else { 183 | fail('A value for either image_name_alt or image_ref_alt must \ 184 | be provided.') 185 | } 186 | } 187 | 188 | if $neutron_available and $configure_networks { 189 | if ! $public_network_id and $public_network_name { 190 | tempest_neutron_net_id_setter { 'public_network_id': 191 | ensure => present, 192 | tempest_conf_path => $tempest_conf, 193 | network_name => $public_network_name, 194 | require => File[$tempest_conf], 195 | } 196 | } 197 | else { 198 | fail('A value for either public_network_id or public_network_name \ 199 | must be provided.') 200 | } 201 | } 202 | 203 | } 204 | --------------------------------------------------------------------------------