Add setters for images and neutron
Change-Id: I2d7555f5d5f5276509fa9752a2922244cc6f0f2d
This commit is contained in:
parent
bd3d860645
commit
e09382edd6
|
@ -1,6 +1,3 @@
|
|||
[submodule "deployment_scripts/puppet/modules/tftp"]
|
||||
path = deployment_scripts/puppet/modules/tftp
|
||||
url = https://github.com/puppetlabs/puppetlabs-tftp
|
||||
[submodule "deployment_scripts/puppet/modules/ironic"]
|
||||
path = deployment_scripts/puppet/modules/ironic
|
||||
url = https://github.com/openstack/puppet-ironic
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
notice('MODULAR: ironic/ironic-conductor-config.pp')
|
||||
|
||||
$ironic_hash = hiera_hash('fuel-plugin-ironic', {})
|
||||
$management_vip = hiera('management_vip')
|
||||
$keystone_endpoint = hiera('keystone_endpoint', $management_vip)
|
||||
$neutron_endpoint = hiera('neutron_endpoint', $management_vip)
|
||||
|
||||
$ironic_tenant = pick($ironic_hash['tenant'],'services')
|
||||
$ironic_user = pick($ironic_hash['user'],'ironic')
|
||||
$ironic_user_password = pick($ironic_hash['password'],'ironic')
|
||||
|
||||
include ::ironic::params
|
||||
|
||||
ironic_images_setter {'ironic_images':
|
||||
ensure => present,
|
||||
auth_url => "http://${keystone_endpoint}:5000/v2.0/",
|
||||
auth_username => $ironic_user,
|
||||
auth_password => $ironic_user_password,
|
||||
auth_tenant_name => $ironic_tenant,
|
||||
glance_url => "http://${management_vip}:9292/v2.0/",
|
||||
}
|
||||
|
||||
ironic_neutron_setter {'ironic_network':
|
||||
ensure => present,
|
||||
auth_url => "http://${keystone_endpoint}:5000/v2.0/",
|
||||
auth_username => $ironic_user,
|
||||
auth_password => $ironic_user_password,
|
||||
auth_tenant_name => $ironic_tenant,
|
||||
neutron_url => "http://${neutron_endpoint}:9696/v2.0/",
|
||||
}
|
||||
|
||||
service { 'ironic-conductor':
|
||||
ensure => 'running',
|
||||
name => $::ironic::params::conductor_service,
|
||||
enable => true,
|
||||
hasstatus => true,
|
||||
tag => 'ironic-service',
|
||||
}
|
||||
|
||||
Ironic_images_setter<||> ~> Service['ironic-conductor']
|
||||
Ironic_neutron_setter<||> ~> Service['ironic-conductor']
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 69fa70013893a323a7cf62bc57963bd7a86bab04
|
|
@ -0,0 +1,14 @@
|
|||
fixtures:
|
||||
repositories:
|
||||
'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile'
|
||||
'concat':
|
||||
'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git'
|
||||
'ref': '1.2.1'
|
||||
'keystone': 'git://github.com/openstack/puppet-keystone.git'
|
||||
'mysql': 'git://github.com/puppetlabs/puppetlabs-mysql.git'
|
||||
'openstacklib': 'git://github.com/openstack/puppet-openstacklib.git'
|
||||
'postgresql': 'git://github.com/puppetlabs/puppet-postgresql.git'
|
||||
'stdlib': 'git://github.com/puppetlabs/puppetlabs-stdlib.git'
|
||||
'vcsrepo': 'git://github.com/puppetlabs/puppetlabs-vcsrepo.git'
|
||||
symlinks:
|
||||
'ironic': "#{source_dir}"
|
|
@ -0,0 +1,5 @@
|
|||
*.swp
|
||||
spec/fixtures/modules/*
|
||||
spec/fixtures/manifests/site.pp
|
||||
Gemfile.lock
|
||||
.vendor
|
|
@ -0,0 +1,4 @@
|
|||
[gerrit]
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/puppet-ironic.git
|
|
@ -0,0 +1,4 @@
|
|||
##2015-07-08 - 6.0.0
|
||||
###Summary
|
||||
|
||||
- Initial release of the puppet-ironic module
|
|
@ -0,0 +1,30 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
group :development, :test do
|
||||
gem 'puppetlabs_spec_helper', :require => false
|
||||
gem 'rspec-puppet', '~> 2.1.0', :require => false
|
||||
|
||||
gem 'metadata-json-lint'
|
||||
gem 'puppet-lint-absolute_classname-check'
|
||||
gem 'puppet-lint-absolute_template_path'
|
||||
gem 'puppet-lint-trailing_newline-check'
|
||||
|
||||
# Puppet 4.x related lint checks
|
||||
gem 'puppet-lint-unquoted_string-check'
|
||||
gem 'puppet-lint-leading_zero-check'
|
||||
gem 'puppet-lint-variable_contains_upcase'
|
||||
gem 'puppet-lint-numericvariable'
|
||||
|
||||
gem 'beaker-rspec', :require => false
|
||||
gem 'beaker-puppet_install_helper', :require => false
|
||||
gem 'json'
|
||||
gem 'webmock'
|
||||
end
|
||||
|
||||
if puppetversion = ENV['PUPPET_GEM_VERSION']
|
||||
gem 'puppet', puppetversion, :require => false
|
||||
else
|
||||
gem 'puppet', :require => false
|
||||
end
|
||||
|
||||
# vim:ft=ruby
|
|
@ -0,0 +1,176 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
puppet-ironic
|
||||
=============
|
||||
|
||||
6.0.0 - 2015.1 - Kilo
|
||||
|
||||
#### Table of Contents
|
||||
|
||||
1. [Overview - What is the ironic module?](#overview)
|
||||
2. [Module Description - What does the module do?](#module-description)
|
||||
3. [Setup - The basics of getting started with ironic](#setup)
|
||||
4. [Implementation - An under-the-hood peek at what the module is doing](#implementation)
|
||||
5. [Limitations - OS compatibility, etc.](#limitations)
|
||||
6. [Development - Guide for contributing to the module](#development)
|
||||
7. [Contributors - Those with commits](#contributors)
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ironic module is a part of [OpenStack](https://github.com/openstack), an effort by the Openstack infrastructure team to provide continuous integration testing and code review for Openstack and Openstack community projects as part of the core software. The module itself is used to flexibly configure and manage the baremetal service for Openstack.
|
||||
|
||||
Module Description
|
||||
------------------
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
**What the ironic module affects:**
|
||||
|
||||
* [Ironic](https://wiki.openstack.org/wiki/Ironic), the baremetal service for Openstack.
|
||||
|
||||
### Installing Ironic
|
||||
|
||||
puppet module install openstack/ironic
|
||||
|
||||
### Beginning with ironic
|
||||
|
||||
To utilize the ironic module's functionality you will need to declare multiple resources.
|
||||
The following is a modified excerpt from the [openstack module](httpd://github.com/stackforge/puppet-openstack).
|
||||
This is not an exhaustive list of all the components needed. We recommend that you consult and understand the
|
||||
[openstack module](https://github.com/stackforge/puppet-openstack) and the [core openstack](http://docs.openstack.org)
|
||||
documentation to assist you in understanding the available deployment options.
|
||||
|
||||
```puppet
|
||||
# enable Ironic resources
|
||||
class { '::ironic':
|
||||
rabbit_userid => 'ironic',
|
||||
rabbit_password => 'an_even_bigger_secret',
|
||||
rabbit_host => '127.0.0.1',
|
||||
database_connection => 'mysql://ironic:a_big_secret@127.0.0.1/ironic?charset=utf8',
|
||||
}
|
||||
|
||||
class { '::ironic::db::mysql':
|
||||
password => 'a_big_secret',
|
||||
}
|
||||
|
||||
class { '::ironic::keystone::auth':
|
||||
password => 'a_big_secret',
|
||||
}
|
||||
|
||||
class { '::ironic::client': }
|
||||
|
||||
class { '::ironic::conductor': }
|
||||
|
||||
class { '::ironic::api':
|
||||
admin_password => 'a_big_secret',
|
||||
}
|
||||
|
||||
class { '::ironic::drivers::ipmi': }
|
||||
```
|
||||
|
||||
Examples of usage also can be found in the *examples* directory.
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
### puppet-ironic
|
||||
|
||||
puppet-ironic is a combination of Puppet manifest and ruby code to delivery configuration and extra functionality through types and providers.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Beaker-Rspec
|
||||
------------
|
||||
|
||||
This module has beaker-rspec tests
|
||||
|
||||
To run:
|
||||
|
||||
``shell
|
||||
bundle install
|
||||
bundle exec rspec spec/acceptance
|
||||
``
|
||||
|
||||
Development
|
||||
-----------
|
||||
|
||||
Developer documentation for the entire puppet-openstack project.
|
||||
|
||||
* https://wiki.openstack.org/wiki/Puppet-openstack#Developer_documentation
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* https://github.com/openstack/puppet-ironic/graphs/contributors
|
|
@ -0,0 +1,9 @@
|
|||
require 'puppetlabs_spec_helper/rake_tasks'
|
||||
require 'puppet-lint/tasks/puppet-lint'
|
||||
|
||||
PuppetLint.configuration.fail_on_warnings = true
|
||||
PuppetLint.configuration.send('disable_80chars')
|
||||
PuppetLint.configuration.send('disable_class_parameter_defaults')
|
||||
|
||||
task(:default).clear
|
||||
task :default => [:spec, :lint]
|
|
@ -0,0 +1,119 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Deploy Ironic
|
||||
#
|
||||
|
||||
$db_host = 'db'
|
||||
$db_username = 'ironic'
|
||||
$db_name = 'ironic'
|
||||
$db_password = 'password'
|
||||
$rabbit_user = 'ironic'
|
||||
$rabbit_password = 'ironic'
|
||||
$rabbit_vhost = '/'
|
||||
$rabbit_hosts = ['rabbitmq:5672']
|
||||
$rabbit_port = '5672'
|
||||
$glance_api_servers = 'glance:9292'
|
||||
$deploy_kernel = 'glance://deploy_kernel_uuid'
|
||||
$deploy_ramdisk = 'glance://deploy_ramdisk_uuid'
|
||||
$baremetal_json_hosts = '
|
||||
"ironic-bm-test.bifrost.example": {
|
||||
"ansible_ssh_host": "1.1.1.1",
|
||||
"uuid": "11111111-1111-1111-1111-111111111111",
|
||||
"driver_info": {
|
||||
"power": {
|
||||
"ipmi_address": "10.0.0.1",
|
||||
"ipmi_username": "admin",
|
||||
"ipmi_password": "pass"
|
||||
},
|
||||
},
|
||||
"nics": [
|
||||
{
|
||||
"mac": "ff:ff:ff:ff:ff:ff"
|
||||
}
|
||||
],
|
||||
"driver": "agent_ipmitool",
|
||||
"ipv4_address": "1.1.1.1",
|
||||
"properties": {
|
||||
"cpu_arch": "x86_64",
|
||||
"ram": null,
|
||||
"disk_size": null,
|
||||
"cpus": null
|
||||
},
|
||||
"name": "ironic-bm-test.bifrost.example"
|
||||
}
|
||||
'
|
||||
|
||||
node 'db' {
|
||||
|
||||
class { '::mysql::server':
|
||||
config_hash => {
|
||||
'bind_address' => '0.0.0.0',
|
||||
},
|
||||
}
|
||||
|
||||
class { '::mysql::ruby': }
|
||||
|
||||
class { '::ironic::db::mysql':
|
||||
password => $db_password,
|
||||
dbname => $db_name,
|
||||
user => $db_username,
|
||||
host => $clientcert,
|
||||
allowed_hosts => ['controller'],
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
node controller {
|
||||
|
||||
class { '::ironic':
|
||||
db_password => $db_password,
|
||||
db_name => $db_name,
|
||||
db_user => $db_username,
|
||||
db_host => $db_host,
|
||||
|
||||
rabbit_password => $rabbit_password,
|
||||
rabbit_userid => $rabbit_user,
|
||||
rabbit_virtual_host => $rabbit_vhost,
|
||||
rabbit_hosts => $rabbit_hosts,
|
||||
|
||||
glance_api_servers => $glance_api_servers,
|
||||
}
|
||||
|
||||
class { '::ironic::api': }
|
||||
|
||||
class { '::ironic::conductor': }
|
||||
|
||||
class { '::ironic::drivers::ipmi': }
|
||||
|
||||
class { '::ironic::drivers::pxe':
|
||||
deploy_kernel => $deploy_kernel,
|
||||
deploy_ramdisk => $deploy_ramdisk,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
node bifrost-controller {
|
||||
|
||||
class { '::ironic::bifrost':
|
||||
network_interface => 'eth1',
|
||||
ironic_db_password => 'changeme',
|
||||
mysql_password => 'changemetoo',
|
||||
baremetal_json_hosts => $baremetal_json_hosts,
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
require 'csv'
|
||||
require 'puppet/util/inifile'
|
||||
|
||||
class Puppet::Provider::Ironic < Puppet::Provider
|
||||
|
||||
def self.conf_filename
|
||||
'/etc/ironic/ironic.conf'
|
||||
end
|
||||
|
||||
def self.withenv(hash, &block)
|
||||
saved = ENV.to_hash
|
||||
hash.each do |name, val|
|
||||
ENV[name.to_s] = val
|
||||
end
|
||||
|
||||
yield
|
||||
ensure
|
||||
ENV.clear
|
||||
saved.each do |name, val|
|
||||
ENV[name] = val
|
||||
end
|
||||
end
|
||||
|
||||
def self.ironic_credentials
|
||||
@ironic_credentials ||= get_ironic_credentials
|
||||
end
|
||||
|
||||
def self.get_ironic_credentials
|
||||
auth_keys = ['auth_host', 'auth_port', 'auth_protocol',
|
||||
'admin_tenant_name', 'admin_user', 'admin_password']
|
||||
conf = ironic_conf
|
||||
if conf and conf['keystone_authtoken'] and
|
||||
auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
|
||||
return Hash[ auth_keys.map \
|
||||
{ |k| [k, conf['keystone_authtoken'][k].strip] } ]
|
||||
else
|
||||
raise(Puppet::Error, "File: #{conf_filename} does not contain all \
|
||||
required sections. Ironic types will not work if ironic is not \
|
||||
correctly configured.")
|
||||
end
|
||||
end
|
||||
|
||||
def ironic_credentials
|
||||
self.class.ironic_credentials
|
||||
end
|
||||
|
||||
def self.auth_endpoint
|
||||
@auth_endpoint ||= get_auth_endpoint
|
||||
end
|
||||
|
||||
def self.get_auth_endpoint
|
||||
q = ironic_credentials
|
||||
"#{q['auth_protocol']}://#{q['auth_host']}:#{q['auth_port']}/v2.0/"
|
||||
end
|
||||
|
||||
def self.ironic_conf
|
||||
return @ironic_conf if @ironic_conf
|
||||
@ironic_conf = Puppet::Util::IniConfig::File.new
|
||||
@ironic_conf.read(conf_filename)
|
||||
@ironic_conf
|
||||
end
|
||||
|
||||
def self.auth_ironic(*args)
|
||||
q = ironic_credentials
|
||||
authenv = {
|
||||
:OS_AUTH_URL => self.auth_endpoint,
|
||||
:OS_USERNAME => q['admin_user'],
|
||||
:OS_TENANT_NAME => q['admin_tenant_name'],
|
||||
:OS_PASSWORD => q['admin_password']
|
||||
}
|
||||
begin
|
||||
withenv authenv do
|
||||
ironic(args)
|
||||
end
|
||||
rescue Exception => e
|
||||
if (e.message =~ /\[Errno 111\] Connection refused/) or
|
||||
(e.message =~ /\(HTTP 400\)/)
|
||||
sleep 10
|
||||
withenv authenv do
|
||||
ironic(args)
|
||||
end
|
||||
else
|
||||
raise(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def auth_ironic(*args)
|
||||
self.class.auth_ironic(args)
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@ironic_conf = nil
|
||||
@ironic_credentials = nil
|
||||
end
|
||||
|
||||
def self.list_ironic_resources(type)
|
||||
ids = []
|
||||
list = auth_ironic("#{type}-list", '--format=csv',
|
||||
'--column=id', '--quote=none')
|
||||
(list.split("\n")[1..-1] || []).compact.collect do |line|
|
||||
ids << line.strip
|
||||
end
|
||||
return ids
|
||||
end
|
||||
|
||||
def self.get_ironic_resource_attrs(type, id)
|
||||
attrs = {}
|
||||
net = auth_ironic("#{type}-show", '--format=shell', id)
|
||||
last_key = nil
|
||||
(net.split("\n") || []).compact.collect do |line|
|
||||
if line.include? '='
|
||||
k, v = line.split('=', 2)
|
||||
attrs[k] = v.gsub(/\A"|"\Z/, '')
|
||||
last_key = k
|
||||
else
|
||||
# Handle the case of a list of values
|
||||
v = line.gsub(/\A"|"\Z/, '')
|
||||
attrs[last_key] = [attrs[last_key], v]
|
||||
end
|
||||
end
|
||||
return attrs
|
||||
end
|
||||
|
||||
def self.get_tenant_id(catalog, name)
|
||||
instance_type = 'keystone_tenant'
|
||||
instance = catalog.resource("#{instance_type.capitalize!}[#{name}]")
|
||||
if ! instance
|
||||
instance = Puppet::Type.type(instance_type).instances.find do |i|
|
||||
i.provider.name == name
|
||||
end
|
||||
end
|
||||
if instance
|
||||
return instance.provider.id
|
||||
else
|
||||
fail("Unable to find #{instance_type} for name #{name}")
|
||||
end
|
||||
end
|
||||
|
||||
def self.parse_creation_output(data)
|
||||
hash = {}
|
||||
data.split("\n").compact.each do |line|
|
||||
if line.include? '='
|
||||
hash[line.split('=').first] = line.split('=', 2)[1].gsub(/\A"|"\Z/, '')
|
||||
end
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
Puppet::Type.type(:ironic_config).provide(
|
||||
:ini_setting,
|
||||
:parent => Puppet::Type.type(:ini_setting).provider(:ruby)
|
||||
) do
|
||||
|
||||
def section
|
||||
resource[:name].split('/', 2).first
|
||||
end
|
||||
|
||||
def setting
|
||||
resource[:name].split('/', 2).last
|
||||
end
|
||||
|
||||
def separator
|
||||
'='
|
||||
end
|
||||
|
||||
def self.file_path
|
||||
'/etc/ironic/ironic.conf'
|
||||
end
|
||||
|
||||
# added for backwards compatibility with older versions of inifile
|
||||
def file_path
|
||||
self.class.file_path
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,150 @@
|
|||
require 'rubygems'
|
||||
require 'net/http'
|
||||
require 'net/https'
|
||||
require 'json'
|
||||
require 'puppet/util/inifile'
|
||||
|
||||
class KeystoneError < Puppet::Error
|
||||
end
|
||||
|
||||
class KeystoneConnectionError < KeystoneError
|
||||
end
|
||||
|
||||
class KeystoneAPIError < KeystoneError
|
||||
end
|
||||
|
||||
RETRY_COUNT = 10
|
||||
RETRY_SLEEP = 3
|
||||
|
||||
def handle_request(req, url)
|
||||
begin
|
||||
use_ssl = url.scheme == "https" ? true : false
|
||||
http = Net::HTTP.start(url.hostname, url.port, {:use_ssl => use_ssl})
|
||||
res = http.request(req)
|
||||
|
||||
if res.code != '200'
|
||||
raise KeystoneAPIError, "Received error response from Keystone server at #{url}: #{res.message}"
|
||||
end
|
||||
rescue Errno::ECONNREFUSED => detail
|
||||
raise KeystoneConnectionError, "Failed to connect to Keystone server at #{url}: #{detail}"
|
||||
rescue SocketError => detail
|
||||
raise KeystoneConnectionError, "Failed to connect to Keystone server at #{url}: #{detail}"
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def keystone_v2_authenticate(auth_url,
|
||||
username,
|
||||
password,
|
||||
tenantId=nil,
|
||||
tenantName=nil)
|
||||
|
||||
post_args = {
|
||||
'auth' => {
|
||||
'passwordCredentials' => {
|
||||
'username' => username,
|
||||
'password' => password
|
||||
},
|
||||
}}
|
||||
|
||||
if tenantId
|
||||
post_args['auth']['tenantId'] = tenantId
|
||||
end
|
||||
|
||||
if tenantName
|
||||
post_args['auth']['tenantName'] = tenantName
|
||||
end
|
||||
|
||||
url = URI.parse("#{auth_url}/tokens")
|
||||
req = Net::HTTP::Post.new url.path
|
||||
req['content-type'] = 'application/json'
|
||||
req.body = post_args.to_json
|
||||
|
||||
res = handle_request(req, url)
|
||||
data = JSON.parse res.body
|
||||
return data['access']['token']['id']
|
||||
end
|
||||
|
||||
def glance_images(glance_url, token)
|
||||
|
||||
url = URI.parse("#{glance_url}/images")
|
||||
req = Net::HTTP::Get.new url.path
|
||||
req['content-type'] = 'application/json'
|
||||
req['x-auth-token'] = token
|
||||
|
||||
res = handle_request(req, url)
|
||||
data = JSON.parse res.body
|
||||
data['images']
|
||||
end
|
||||
|
||||
Puppet::Type.type(:ironic_images_setter).provide(:ruby) do
|
||||
@ironic_images = nil
|
||||
|
||||
def authenticate
|
||||
keystone_v2_authenticate(
|
||||
@resource[:auth_url],
|
||||
@resource[:auth_username],
|
||||
@resource[:auth_password],
|
||||
nil,
|
||||
@resource[:auth_tenant_name])
|
||||
end
|
||||
|
||||
def find_image_by_name(images, name)
|
||||
found_images = images.select{|image| image['name'] == name}
|
||||
if found_images.length == 1
|
||||
return found_images[0]['id']
|
||||
elsif found_images.length == 0
|
||||
raise KeystoneAPIError, "Image with name '#{name}' not found."
|
||||
elsif found_images.length > 1
|
||||
raise KeystoneAPIError, "Found multiple matches for name: '#{name}'"
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
ini_file = Puppet::Util::IniConfig::File.new
|
||||
ini_file.read("/etc/ironic/ironic.conf")
|
||||
ironic_images.each do |setting, id|
|
||||
if ! ( ini_file['fuel'] && ini_file['fuel'][setting] && ini_file['fuel'][setting] == id)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
config
|
||||
end
|
||||
|
||||
def ironic_images
|
||||
@ironic_images ||= get_ironic_images
|
||||
end
|
||||
|
||||
def get_ironic_images
|
||||
token = authenticate
|
||||
RETRY_COUNT.times do |n|
|
||||
begin
|
||||
all_images = glance_images(@resource[:glance_url], token)
|
||||
rescue => e
|
||||
debug "Request failed: '#{e.message}' Retry: '#{n}'"
|
||||
if n == RETRY_COUNT - 1
|
||||
raise KeystoneAPIError, 'Unable to get images.'
|
||||
end
|
||||
sleep RETRY_SLEEP
|
||||
next
|
||||
end
|
||||
ironic_images = Hash.new
|
||||
ironic_images['deploy_kernel'] = find_image_by_name(all_images, 'ironic-deploy-linux')
|
||||
ironic_images['deploy_ramdisk'] = find_image_by_name(all_images, 'ironic-deploy-initramfs')
|
||||
ironic_images['deploy_squashfs'] = find_image_by_name(all_images, 'ironic-deploy-squashfs')
|
||||
return ironic_images
|
||||
end
|
||||
end
|
||||
|
||||
def config
|
||||
ironic_images.each do |setting, id|
|
||||
Puppet::Type.type(:ironic_config).new(
|
||||
{:name => "fuel/#{setting}", :value => id}
|
||||
).provider.create
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,140 @@
|
|||
require 'rubygems'
|
||||
require 'net/http'
|
||||
require 'net/https'
|
||||
require 'json'
|
||||
require 'puppet/util/inifile'
|
||||
|
||||
class KeystoneError < Puppet::Error
|
||||
end
|
||||
|
||||
class KeystoneConnectionError < KeystoneError
|
||||
end
|
||||
|
||||
class KeystoneAPIError < KeystoneError
|
||||
end
|
||||
|
||||
RETRY_COUNT = 10
|
||||
RETRY_SLEEP = 3
|
||||
|
||||
def handle_request(req, url)
|
||||
begin
|
||||
use_ssl = url.scheme == "https" ? true : false
|
||||
http = Net::HTTP.start(url.hostname, url.port, {:use_ssl => use_ssl})
|
||||
res = http.request(req)
|
||||
|
||||
if res.code != '200'
|
||||
raise KeystoneAPIError, "Received error response from Keystone server at #{url}: #{res.message}"
|
||||
end
|
||||
rescue Errno::ECONNREFUSED => detail
|
||||
raise KeystoneConnectionError, "Failed to connect to Keystone server at #{url}: #{detail}"
|
||||
rescue SocketError => detail
|
||||
raise KeystoneConnectionError, "Failed to connect to Keystone server at #{url}: #{detail}"
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def keystone_v2_authenticate(auth_url,
|
||||
username,
|
||||
password,
|
||||
tenantId=nil,
|
||||
tenantName=nil)
|
||||
|
||||
post_args = {
|
||||
'auth' => {
|
||||
'passwordCredentials' => {
|
||||
'username' => username,
|
||||
'password' => password
|
||||
},
|
||||
}}
|
||||
|
||||
if tenantId
|
||||
post_args['auth']['tenantId'] = tenantId
|
||||
end
|
||||
|
||||
if tenantName
|
||||
post_args['auth']['tenantName'] = tenantName
|
||||
end
|
||||
|
||||
url = URI.parse("#{auth_url}/tokens")
|
||||
req = Net::HTTP::Post.new url.path
|
||||
req['content-type'] = 'application/json'
|
||||
req.body = post_args.to_json
|
||||
|
||||
res = handle_request(req, url)
|
||||
data = JSON.parse res.body
|
||||
return data['access']['token']['id']
|
||||
end
|
||||
|
||||
def neutron_networks(neutron_url, token)
|
||||
|
||||
url = URI.parse("#{neutron_url}/networks")
|
||||
req = Net::HTTP::Get.new url.path
|
||||
req['content-type'] = 'application/json'
|
||||
req['x-auth-token'] = token
|
||||
|
||||
res = handle_request(req, url)
|
||||
data = JSON.parse res.body
|
||||
data['networks']
|
||||
end
|
||||
|
||||
Puppet::Type.type(:ironic_neutron_setter).provide(:ruby) do
|
||||
@neutron_network = nil
|
||||
|
||||
def authenticate
|
||||
keystone_v2_authenticate(
|
||||
@resource[:auth_url],
|
||||
@resource[:auth_username],
|
||||
@resource[:auth_password],
|
||||
nil,
|
||||
@resource[:auth_tenant_name])
|
||||
end
|
||||
|
||||
def find_network_by_name(networks, name)
|
||||
found_networks = networks.select{|net| net['name'] == name}
|
||||
if found_networks.length == 1
|
||||
return found_networks[0]['id']
|
||||
elsif found_networks.length == 0
|
||||
raise KeystoneAPIError, "Network with name '#{name}' not found."
|
||||
elsif found_networks.length > 1
|
||||
raise KeystoneAPIError, "Found multiple matches for name: '#{name}'"
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
ini_file = Puppet::Util::IniConfig::File.new
|
||||
ini_file.read("/etc/ironic/ironic.conf")
|
||||
ini_file['neutron'] && ini_file['neutron']['cleaning_network_uuid'] && ini_file['neutron']['cleaning_network_uuid'] == neutron_network
|
||||
end
|
||||
|
||||
def create
|
||||
config
|
||||
end
|
||||
|
||||
def neutron_network
|
||||
@neutron_network ||= get_neutron_network
|
||||
end
|
||||
|
||||
def get_neutron_network
|
||||
token = authenticate
|
||||
RETRY_COUNT.times do |n|
|
||||
begin
|
||||
all_networks = neutron_networks(@resource[:neutron_url], token)
|
||||
rescue => e
|
||||
debug "Request failed: '#{e.message}' Retry: '#{n}'"
|
||||
if n == RETRY_COUNT - 1
|
||||
raise KeystoneAPIError, 'Unable to get networks.'
|
||||
end
|
||||
sleep RETRY_SLEEP
|
||||
next
|
||||
end
|
||||
return find_network_by_name(all_networks, 'baremetal')
|
||||
end
|
||||
end
|
||||
|
||||
def config
|
||||
Puppet::Type.type(:ironic_config).new(
|
||||
{:name => "neutron/cleaning_network_uuid", :value => neutron_network}
|
||||
).provider.create
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
Puppet::Type.newtype(:ironic_config) do
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
desc 'Section/setting name to manage from /etc/ironic/ironic.conf'
|
||||
newvalues(/\S+\/\S+/)
|
||||
end
|
||||
|
||||
newproperty(:value) do
|
||||
desc 'The value of the setting to be defined.'
|
||||
munge do |value|
|
||||
value = value.to_s.strip
|
||||
value.capitalize! if value =~ /^(true|false)$/i
|
||||
value
|
||||
end
|
||||
|
||||
def is_to_s( currentvalue )
|
||||
if resource.secret?
|
||||
return '[old secret redacted]'
|
||||
else
|
||||
return currentvalue
|
||||
end
|
||||
end
|
||||
|
||||
def should_to_s( newvalue )
|
||||
if resource.secret?
|
||||
return '[new secret redacted]'
|
||||
else
|
||||
return newvalue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newparam(:secret, :boolean => true) do
|
||||
desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
|
||||
|
||||
newvalues(:true, :false)
|
||||
|
||||
defaultto false
|
||||
end
|
||||
|
||||
autorequire(:package) do
|
||||
'ironic-common'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
Puppet::Type.newtype(:ironic_images_setter) do
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
desc 'The name of the setting to update'
|
||||
end
|
||||
|
||||
newparam(:auth_url) do
|
||||
desc 'The Keystone endpoint URL'
|
||||
defaultto 'http://localhost:35357/v2.0'
|
||||
end
|
||||
|
||||
newparam(:auth_username) do
|
||||
desc 'Username with which to authenticate'
|
||||
defaultto 'admin'
|
||||
end
|
||||
|
||||
newparam(:auth_password) do
|
||||
desc 'Password with which to authenticate'
|
||||
end
|
||||
|
||||
newparam(:auth_tenant_name) do
|
||||
desc 'Tenant name with which to authenticate'
|
||||
defaultto 'admin'
|
||||
end
|
||||
|
||||
newparam(:glance_url) do
|
||||
desc 'Glance endpoint'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
Puppet::Type.newtype(:ironic_neutron_setter) do
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
desc 'The name of the setting to update'
|
||||
end
|
||||
|
||||
newparam(:auth_url) do
|
||||
desc 'The Keystone endpoint URL'
|
||||
defaultto 'http://localhost:35357/v2.0'
|
||||
end
|
||||
|
||||
newparam(:auth_username) do
|
||||
desc 'Username with which to authenticate'
|
||||
defaultto 'admin'
|
||||
end
|
||||
|
||||
newparam(:auth_password) do
|
||||
desc 'Password with which to authenticate'
|
||||
end
|
||||
|
||||
newparam(:auth_tenant_name) do
|
||||
desc 'Tenant name with which to authenticate'
|
||||
defaultto 'admin'
|
||||
end
|
||||
|
||||
newparam(:neutron_url) do
|
||||
desc 'Neutron endpoint'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,182 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Configure the API service in Ironic
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*package_ensure*]
|
||||
# (optional) Control the ensure parameter for the package ressource.
|
||||
# Defaults to 'present'.
|
||||
#
|
||||
# [*enabled*]
|
||||
# (optional) Define if the service must be enabled or not.
|
||||
# Defaults to true.
|
||||
#
|
||||
# [*host_ip*]
|
||||
# (optional) The listen IP for the Ironic API server.
|
||||
# Should be an valid IP address
|
||||
# Defaults to '0.0.0.0'.
|
||||
#
|
||||
# [*port*]
|
||||
# (optional) The port for the Ironic API server.
|
||||
# Should be an valid port
|
||||
# Defaults to '0.0.0.0'.
|
||||
#
|
||||
# [*max_limit*]
|
||||
# (optional) The maximum number of items returned in a single response
|
||||
# from a collection resource.
|
||||
# Should be an valid interger
|
||||
# Defaults to '1000'.
|
||||
#
|
||||
# [*auth_host*]
|
||||
# (optional) The IP of the server running keystone
|
||||
# Defaults to '127.0.0.1'
|
||||
#
|
||||
# [*auth_port*]
|
||||
# (optional) The port to use when authenticating against Keystone
|
||||
# Defaults to 35357
|
||||
#
|
||||
# [*auth_protocol*]
|
||||
# (optional) The protocol to use when authenticating against Keystone
|
||||
# Defaults to 'http'
|
||||
#
|
||||
# [*auth_uri*]
|
||||
# (optional) The uri of a Keystone service to authenticate against
|
||||
# Defaults to false
|
||||
#
|
||||
# [*auth_admin_prefix*]
|
||||
# (optional) Prefix to prepend at the beginning of the keystone path
|
||||
# Defaults to false
|
||||
#
|
||||
# [*auth_version*]
|
||||
# (optional) API version of the admin Identity API endpoint
|
||||
# for example, use 'v3.0' for the keystone version 3.0 api
|
||||
# Defaults to false
|
||||
#
|
||||
# [*admin_tenant_name*]
|
||||
# (optional) The name of the tenant to create in keystone for use by the ironic services
|
||||
# Defaults to 'services'
|
||||
#
|
||||
# [*admin_user*]
|
||||
# (optional) The name of the user to create in keystone for use by the ironic services
|
||||
# Defaults to 'ironic'
|
||||
#
|
||||
# [*neutron_url*]
|
||||
# (optional) The Neutron URL to be used for requests from ironic
|
||||
# Defaults to false
|
||||
#
|
||||
# [*admin_password*]
|
||||
# (required) The password to set for the ironic admin user in keystone
|
||||
#
|
||||
|
||||
class ironic::api (
|
||||
$package_ensure = 'present',
|
||||
$enabled = true,
|
||||
$host_ip = '0.0.0.0',
|
||||
$port = '6385',
|
||||
$max_limit = '1000',
|
||||
$auth_host = '127.0.0.1',
|
||||
$auth_port = '35357',
|
||||
$auth_protocol = 'http',
|
||||
$auth_uri = false,
|
||||
$auth_admin_prefix = false,
|
||||
$auth_version = false,
|
||||
$admin_tenant_name = 'services',
|
||||
$admin_user = 'ironic',
|
||||
$neutron_url = false,
|
||||
$admin_password,
|
||||
) {
|
||||
|
||||
include ::ironic::params
|
||||
include ::ironic::policy
|
||||
|
||||
Ironic_config<||> ~> Service['ironic-api']
|
||||
Class['ironic::policy'] ~> Service['ironic-api']
|
||||
|
||||
# Configure ironic.conf
|
||||
ironic_config {
|
||||
'api/host_ip': value => $host_ip;
|
||||
'api/port': value => $port;
|
||||
'api/max_limit': value => $max_limit;
|
||||
}
|
||||
|
||||
# Install package
|
||||
if $::ironic::params::api_package {
|
||||
Package['ironic-api'] -> Class['ironic::policy']
|
||||
Package['ironic-api'] -> Service['ironic-api']
|
||||
package { 'ironic-api':
|
||||
ensure => $package_ensure,
|
||||
name => $::ironic::params::api_package,
|
||||
tag => ['openstack', 'ironic-package'],
|
||||
}
|
||||
}
|
||||
|
||||
if $enabled {
|
||||
$ensure = 'running'
|
||||
} else {
|
||||
$ensure = 'stopped'
|
||||
}
|
||||
|
||||
# Manage service
|
||||
service { 'ironic-api':
|
||||
ensure => $ensure,
|
||||
name => $::ironic::params::api_service,
|
||||
enable => $enabled,
|
||||
hasstatus => true,
|
||||
tag => 'ironic-service',
|
||||
}
|
||||
|
||||
if $neutron_url {
|
||||
ironic_config { 'neutron/url': value => $neutron_url; }
|
||||
} else {
|
||||
ironic_config { 'neutron/url': value => "${auth_protocol}://${auth_host}:9696/"; }
|
||||
}
|
||||
|
||||
if $auth_uri {
|
||||
ironic_config { 'keystone_authtoken/auth_uri': value => $auth_uri; }
|
||||
} else {
|
||||
ironic_config { 'keystone_authtoken/auth_uri': value => "${auth_protocol}://${auth_host}:5000/"; }
|
||||
}
|
||||
|
||||
if $auth_version {
|
||||
ironic_config { 'keystone_authtoken/auth_version': value => $auth_version; }
|
||||
} else {
|
||||
ironic_config { 'keystone_authtoken/auth_version': ensure => absent; }
|
||||
}
|
||||
|
||||
ironic_config {
|
||||
'keystone_authtoken/auth_host': value => $auth_host;
|
||||
'keystone_authtoken/auth_port': value => $auth_port;
|
||||
'keystone_authtoken/auth_protocol': value => $auth_protocol;
|
||||
'keystone_authtoken/admin_tenant_name': value => $admin_tenant_name;
|
||||
'keystone_authtoken/admin_user': value => $admin_user;
|
||||
'keystone_authtoken/admin_password': value => $admin_password, secret => true;
|
||||
}
|
||||
|
||||
if $auth_admin_prefix {
|
||||
validate_re($auth_admin_prefix, '^(/.+[^/])?$')
|
||||
ironic_config {
|
||||
'keystone_authtoken/auth_admin_prefix': value => $auth_admin_prefix;
|
||||
}
|
||||
} else {
|
||||
ironic_config {
|
||||
'keystone_authtoken/auth_admin_prefix': ensure => absent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# == Class: ironic::bifrost
|
||||
#
|
||||
# Installs and configures Bifrost
|
||||
# Bifrost is a set of Ansible playbooks that automates the task of deploying a
|
||||
# base image onto a set of known hardware using Ironic. It provides modular
|
||||
# utility for one-off operating system deployment with as few operational requirements
|
||||
# as reasonably possible.
|
||||
# Bifrost also allows to install Ironic in a stand-alone fashion. In this kind of setup,
|
||||
# neither Keystone nor Neutron is installed, and dnsmasq is used to provide PXE booting.
|
||||
#
|
||||
# [*ironic_db_password*]
|
||||
# (required) The Ironic DB password
|
||||
#
|
||||
# [*mysql_password*]
|
||||
# (required) The mysql server password
|
||||
#
|
||||
# [*baremetal_json_hosts*]
|
||||
# (required) Baremetal hosts in JSON format, will be included in baremetal.json
|
||||
#
|
||||
# [*git_source_repo*]
|
||||
# (optional) Git repository location for pulling Bifrost
|
||||
# Defaults to 'https://git.openstack.org/openstack/bifrost'
|
||||
#
|
||||
# [*revision*]
|
||||
# (optional) The branch or commit to checkout on Bifrost repository
|
||||
# Defaults to 'master'
|
||||
#
|
||||
# [*ensure*]
|
||||
# (optional) Ensure value for cloning the Bifrost repository.
|
||||
# This is a pass-thru variable for vcsrepo, acceptable values are
|
||||
# present/bare/absent/latest
|
||||
# Typically, you may want to set this value to either present or absent and use
|
||||
# revision for setting the branch or commit to clone.
|
||||
# Defaults to 'present'
|
||||
#
|
||||
# [*revision*]
|
||||
# (optional) The branch or commit to checkout on Bifrost repository
|
||||
# Defaults to 'master'
|
||||
#
|
||||
# [*git_dest_repo_folder*]
|
||||
# (optional) Folder to clone the Bifrost git repository
|
||||
# Defaults to '/opt/stack/bifrost'
|
||||
#
|
||||
# [*ironic_url*]
|
||||
# (optional) The URL of the Ironic server
|
||||
# Defaults to '"http://localhost:6385"'
|
||||
#
|
||||
# [*network_interface*]
|
||||
# (optional) The network interface DHCP will serve requests on
|
||||
# Defaults to '"virbr0"'
|
||||
#
|
||||
# [*testing*]
|
||||
# (optional) If true, Ironic will provision libvirt and VMs instead of baremetal
|
||||
# Defaults to 'false'
|
||||
#
|
||||
# [*testing_user*]
|
||||
# (optional) VM default user in case testing is enabled
|
||||
# Defaults to 'ubuntu'
|
||||
#
|
||||
# [*http_boot_folder*]
|
||||
# (optional) gPXE folder location for HTTP PXE boot
|
||||
# Defaults to '/httpboot'
|
||||
#
|
||||
# [*nginx_port*]
|
||||
# (optional) NGINX HTTP port
|
||||
# Defaults to 8080
|
||||
|
||||
# [*ssh_public_key_path*]
|
||||
# (optional) SSH public key location, this will be injected in provisioned servers
|
||||
# Defaults to '"{{ ansible_env.HOME }}/.ssh/id_rsa.pub"'
|
||||
#
|
||||
# [*deploy_kernel*]
|
||||
# (optional) Kernel to PXE boot from
|
||||
# Defaults to '"{{http_boot_folder}}/coreos_production_pxe.vmlinuz"'
|
||||
#
|
||||
# [*deploy_ramdisk*]
|
||||
# (optional) Ramdisk to load after kernel boot
|
||||
# Defaults to '"{{http_boot_folder}}/coreos_production_pxe_image-oem.cpio.gz"'
|
||||
#
|
||||
# [*deploy_kernel_url*]
|
||||
# (optional) Kernel URL
|
||||
# Defaults to '"http://{{ hostvars[inventory_hostname][\'ansible_\' + network_interface][\'ipv4\'][\'address\'] }}:{{nginx_port}}/coreos_production_pxe.vmlinuz"'
|
||||
#
|
||||
# [*deploy_ramdisk_url*]
|
||||
# (optional) Ramdisk URL
|
||||
# Defaults to '"http://{{ hostvars[inventory_hostname][\'ansible_\' + network_interface][\'ipv4\'][\'address\'] }}:{{nginx_port}}/coreos_production_pxe_image-oem.cpio.gz"'
|
||||
#
|
||||
# [*deploy_image_filename*]
|
||||
# (optional) Deploy image filename
|
||||
# Defaults to '"deployment_image.qcow2"'
|
||||
#
|
||||
# [*deploy_image*]
|
||||
# (optional) URL for the deployment image
|
||||
# Defaults to '"{{http_boot_folder}}/{{deploy_image_filename}}"'
|
||||
#
|
||||
# [*create_image_via_dib*]
|
||||
# (optional) Flag to enable/disable image creation with diskimage-builder
|
||||
# Defaults to 'true'
|
||||
#
|
||||
# [*transform_boot_image*]
|
||||
# (optional) Flag to prepend a partition image with boot sector and partition table
|
||||
# Defaults to 'false'
|
||||
#
|
||||
# [*node_default_network_interface*]
|
||||
# (optional) Default network interface to configure with configdrive settings
|
||||
# Defaults to 'eth0'
|
||||
#
|
||||
# [*ipv4_subnet_mask*]
|
||||
# (optional) Subnet mask for configured NIC
|
||||
# Defaults to '255.255.255.0'
|
||||
#
|
||||
# [*ipv4_gateway*]
|
||||
# (optional) Gateway for configured NIC
|
||||
# Defaults to '192.168.1.1'
|
||||
#
|
||||
# [*ipv4_nameserver*]
|
||||
# (optional) Nameserver for DNS configuration
|
||||
# Defaults to '8.8.8.8'
|
||||
#
|
||||
# [*network_mtu*]
|
||||
# (optional) MTU for configured NIC
|
||||
# Defaults to '1500'
|
||||
#
|
||||
# [*dhcp_pool_start*]
|
||||
# (optional) Dnsmasq DHCP pool start
|
||||
# Defaults to '192.168.1.200'
|
||||
#
|
||||
# [*dhcp_pool_end*]
|
||||
# (optional) Dnsmasq DHCP pool end
|
||||
# Defaults to '192.168.1.250'
|
||||
#
|
||||
# [*ipmi_bridging*]
|
||||
# (optional) Flag to enable/disable IPMI bridging
|
||||
# Defaults to 'no'
|
||||
|
||||
class ironic::bifrost (
|
||||
$ironic_db_password,
|
||||
$mysql_password,
|
||||
$baremetal_json_hosts,
|
||||
$git_source_repo = 'https://git.openstack.org/openstack/bifrost',
|
||||
$ensure = present,
|
||||
$revision = 'master',
|
||||
$git_dest_repo_folder = '/opt/stack/bifrost',
|
||||
$ironic_url = '"http://localhost:6385/"',
|
||||
$network_interface = '"virbr0"',
|
||||
$testing = false,
|
||||
$testing_user = 'ubuntu',
|
||||
$http_boot_folder = '/httpboot',
|
||||
$nginx_port = 8080,
|
||||
$ssh_public_key_path = '"{{ ansible_env.HOME }}/.ssh/id_rsa.pub"',
|
||||
$deploy_kernel = '"{{http_boot_folder}}/coreos_production_pxe.vmlinuz"',
|
||||
$deploy_ramdisk = '"{{http_boot_folder}}/coreos_production_pxe_image-oem.cpio.gz"',
|
||||
$deploy_kernel_url = '"http://{{ hostvars[inventory_hostname][\'ansible_\' + network_interface][\'ipv4\'][\'address\'] }}:{{nginx_port}}/coreos_production_pxe.vmlinuz"',
|
||||
$deploy_ramdisk_url = '"http://{{ hostvars[inventory_hostname][\'ansible_\' + network_interface][\'ipv4\'][\'address\'] }}:{{nginx_port}}/coreos_production_pxe_image-oem.cpio.gz"',
|
||||
$deploy_image_filename = '"deployment_image.qcow2"',
|
||||
$deploy_image = '"{{http_boot_folder}}/{{deploy_image_filename}}"',
|
||||
$create_image_via_dib = true,
|
||||
$transform_boot_image = false,
|
||||
$node_default_network_interface = 'eth0',
|
||||
$ipv4_subnet_mask = '255.255.255.0',
|
||||
$ipv4_gateway = '192.168.1.1',
|
||||
$ipv4_nameserver = '8.8.8.8',
|
||||
$network_mtu = '1500',
|
||||
$dhcp_pool_start = '192.168.1.200',
|
||||
$dhcp_pool_end = '192.168.1.250',
|
||||
$ipmi_bridging = 'no',
|
||||
) {
|
||||
|
||||
vcsrepo { $git_dest_repo_folder:
|
||||
ensure => $ensure,
|
||||
provider => git,
|
||||
revision => $revision,
|
||||
source => $git_source_repo,
|
||||
}
|
||||
|
||||
file { "${git_dest_repo_folder}/playbooks/inventory/group_vars/all":
|
||||
ensure => present,
|
||||
content => template('ironic/group_vars_all.erb'),
|
||||
require => Vcsrepo[$git_dest_repo_folder],
|
||||
}
|
||||
|
||||
file { "${git_dest_repo_folder}/baremetal.json":
|
||||
ensure => present,
|
||||
content => template('ironic/baremetal.json.erb'),
|
||||
require => Vcsrepo[$git_dest_repo_folder],
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# ironic::client
|
||||
#
|
||||
# Manages the ironic client package on systems
|
||||
#
|
||||
# === Parameters:
|
||||
#
|
||||
# [*package_ensure*]
|
||||
# (optional) The state of the package
|
||||
# Defaults to present
|
||||
#
|
||||
|
||||
class ironic::client (
|
||||
$package_ensure = present
|
||||
) {
|
||||
|
||||
include ::ironic::params
|
||||
|
||||
package { 'python-ironicclient':
|
||||
ensure => $package_ensure,
|
||||
name => $::ironic::params::client_package,
|
||||
tag => 'openstack',
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Configure the conductor service in Ironic
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*package_ensure*]
|
||||
# (optional) Control the ensure parameter for the package ressource.
|
||||
# Defaults to 'present'.
|
||||
#
|
||||
# [*enabled*]
|
||||
# (optional) Define if the service must be enabled or not.
|
||||
# Defaults to true.
|
||||
#
|
||||
# [*max_time_interval*]
|
||||
# (optional) Maximum time, in seconds, since the last check-in of a conductor.
|
||||
# Should be an interger value
|
||||
# Defaults to '120'.
|
||||
#
|
||||
# [*force_power_state_during_sync*]
|
||||
# (optional) Should the hardware power state be set to the state recorded in
|
||||
# the database (True) or should the database be updated based on the hardware
|
||||
# state (False).
|
||||
# Defaults to true.
|
||||
#
|
||||
class ironic::conductor (
|
||||
$package_ensure = 'present',
|
||||
$enabled = true,
|
||||
$max_time_interval = '120',
|
||||
$force_power_state_during_sync = true,
|
||||
) {
|
||||
|
||||
include ::ironic::params
|
||||
|
||||
Ironic_config<||> ~> Service['ironic-conductor']
|
||||
|
||||
# Configure ironic.conf
|
||||
ironic_config {
|
||||
'conductor/max_time_interval': value => $max_time_interval;
|
||||
'conductor/force_power_state_during_sync': value => $force_power_state_during_sync;
|
||||
}
|
||||
|
||||
# Install package
|
||||
if $::ironic::params::conductor_package {
|
||||
Package['ironic-conductor'] -> Service['ironic-conductor']
|
||||
package { 'ironic-conductor':
|
||||
ensure => $package_ensure,
|
||||
name => $::ironic::params::conductor_package,
|
||||
tag => ['openstack', 'ironic-package'],
|
||||
}
|
||||
}
|
||||
|
||||
if $enabled {
|
||||
$ensure = 'running'
|
||||
} else {
|
||||
$ensure = 'stopped'
|
||||
}
|
||||
|
||||
# Manage service
|
||||
service { 'ironic-conductor':
|
||||
ensure => $ensure,
|
||||
name => $::ironic::params::conductor_service,
|
||||
enable => $enabled,
|
||||
hasstatus => true,
|
||||
tag => 'ironic-service',
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
# == Class: ironic::config
|
||||
#
|
||||
# This class is used to manage arbitrary Ironic configurations.
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*ironic_config*]
|
||||
# (optional) Allow configuration of arbitrary Ironic configurations.
|
||||
# The value is an hash of ironic_config resources. Example:
|
||||
# { 'DEFAULT/foo' => { value => 'fooValue'},
|
||||
# 'DEFAULT/bar' => { value => 'barValue'}
|
||||
# }
|
||||
# In yaml format, Example:
|
||||
# ironic_config:
|
||||
# DEFAULT/foo:
|
||||
# value: fooValue
|
||||
# DEFAULT/bar:
|
||||
# value: barValue
|
||||
#
|
||||
# NOTE: The configuration MUST NOT be already handled by this module
|
||||
# or Puppet catalog compilation will fail with duplicate resources.
|
||||
#
|
||||
class ironic::config (
|
||||
$ironic_config = {},
|
||||
) {
|
||||
|
||||
validate_hash($ironic_config)
|
||||
|
||||
create_resources('ironic_config', $ironic_config)
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# ironic::db::mysql
|
||||
#
|
||||
# [*password*]
|
||||
# Password to use for the nova user
|
||||
#
|
||||
# [*dbname*]
|
||||
# (optional) The name of the database
|
||||
# Defaults to 'nova'
|
||||
#
|
||||
# [*user*]
|
||||
# (optional) The mysql user to create
|
||||
# Defaults to 'nova'
|
||||
#
|
||||
# [*host*]
|
||||
# (optional) The IP address of the mysql server
|
||||
# Defaults to '127.0.0.1'
|
||||
#
|
||||
# [*charset*]
|
||||
# (optional) The charset to use for the nova database
|
||||
# Defaults to 'utf8'
|
||||
#
|
||||
# [*collate*]
|
||||
# (optional) The collate to use for the nova database
|
||||
# Defaults to 'utf8_general_ci'
|
||||
#
|
||||
# [*allowed_hosts*]
|
||||
# (optional) Additional hosts that are allowed to access this DB
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*cluster_id*]
|
||||
# (optional) Deprecated. Does nothing
|
||||
|
||||
class ironic::db::mysql (
|
||||
$password,
|
||||
$dbname = 'ironic',
|
||||
$user = 'ironic',
|
||||
$host = '127.0.0.1',
|
||||
$allowed_hosts = undef,
|
||||
$charset = 'utf8',
|
||||
$collate = 'utf8_general_ci',
|
||||
$cluster_id = undef,
|
||||
) {
|
||||
|
||||
if $cluster_id {
|
||||
warning('The cluster_id parameter is deprecated and has no effect.')
|
||||
}
|
||||
|
||||
::openstacklib::db::mysql { 'ironic':
|
||||
user => $user,
|
||||
password_hash => mysql_password($password),
|
||||
dbname => $dbname,
|
||||
host => $host,
|
||||
charset => $charset,
|
||||
collate => $collate,
|
||||
allowed_hosts => $allowed_hosts,
|
||||
}
|
||||
|
||||
::Openstacklib::Db::Mysql['ironic'] ~> Exec<| title == 'ironic-dbsync' |>
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
# == Class: ironic::db::postgresql
|
||||
#
|
||||
# Class that configures postgresql for ironic
|
||||
# Requires the Puppetlabs postgresql module.
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*password*]
|
||||
# (Required) Password to connect to the database.
|
||||
#
|
||||
# [*dbname*]
|
||||
# (Optional) Name of the database.
|
||||
# Defaults to 'ironic'.
|
||||
#
|
||||
# [*user*]
|
||||
# (Optional) User to connect to the database.
|
||||
# Defaults to 'ironic'.
|
||||
#
|
||||
# [*encoding*]
|
||||
# (Optional) The charset to use for the database.
|
||||
# Default to undef.
|
||||
#
|
||||
# [*privileges*]
|
||||
# (Optional) Privileges given to the database user.
|
||||
# Default to 'ALL'
|
||||
#
|
||||
class ironic::db::postgresql(
|
||||
$password,
|
||||
$dbname = 'ironic',
|
||||
$user = 'ironic',
|
||||
$encoding = undef,
|
||||
$privileges = 'ALL',
|
||||
) {
|
||||
|
||||
Class['ironic::db::postgresql'] -> Service<| title == 'ironic' |>
|
||||
|
||||
::openstacklib::db::postgresql { 'ironic':
|
||||
password_hash => postgresql_password($user, $password),
|
||||
dbname => $dbname,
|
||||
user => $user,
|
||||
encoding => $encoding,
|
||||
privileges => $privileges,
|
||||
}
|
||||
|
||||
::Openstacklib::Db::Postgresql['ironic'] ~> Exec<| title == 'ironic-dbsync' |>
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# Class to execute ironic dbsync
|
||||
#
|
||||
class ironic::db::sync {
|
||||
|
||||
include ::ironic::params
|
||||
|
||||
Package<| tag == 'ironic-package' |> ~> Exec['ironic-dbsync']
|
||||
Exec['ironic-dbsync'] ~> Service <| tag == 'ironic-service' |>
|
||||
|
||||
Ironic_config<||> -> Exec['ironic-dbsync']
|
||||
Ironic_config<| title == 'database/connection' |> ~> Exec['ironic-dbsync']
|
||||
|
||||
exec { 'ironic-dbsync':
|
||||
command => $::ironic::params::dbsync_command,
|
||||
path => '/usr/bin',
|
||||
# Ubuntu packaging is running dbsync command as root during ironic-common
|
||||
# postinstall script so when Puppet tries to run dbsync again, it fails
|
||||
# because it is run with ironic user.
|
||||
# This is a temporary patch until it's changed in Packaging
|
||||
# https://bugs.launchpad.net/cloud-archive/+bug/1450942
|
||||
user => 'root',
|
||||
refreshonly => true,
|
||||
logoutput => on_failure,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Configure the IPMI driver in Ironic
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*retry_timeout*]
|
||||
# (optional) Maximum time in seconds to retry IPMI operations.
|
||||
# Should be an interger value
|
||||
# Defaults to '10'.
|
||||
#
|
||||
|
||||
class ironic::drivers::ipmi (
|
||||
$retry_timeout = '10'
|
||||
) {
|
||||
|
||||
# Configure ironic.conf
|
||||
ironic_config {
|
||||
'ipmi/retry_timeout': value => $retry_timeout;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Configure the PXE driver in Ironic
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*deploy_kernel*]
|
||||
# (optional) Default kernel image ID used in deployment phase.
|
||||
# Should be an valid id
|
||||
# Defaults to undef.
|
||||
#
|
||||
# [*deploy_ramdisk*]
|
||||
# (optional) Default kernel image ID used in deployment phase.
|
||||
# Should be an valid id
|
||||
# Defaults to undef.
|
||||
#
|
||||
# [*pxe_append_params*]
|
||||
# (optional) Additional append parameters for baremetal PXE boot.
|
||||
# Should be valid pxe parameters
|
||||
# Defaults to 'nofb nomodeset vga=normal'.
|
||||
#
|
||||
# [*pxe_config_template*]
|
||||
# (optional) Template file for PXE configuration.
|
||||
# Should be an valid template file
|
||||
# Defaults to '$pybasedir/drivers/modules/pxe_config.template'.
|
||||
#
|
||||
# [*pxe_deploy_timeout*]
|
||||
# (optional) Timeout for PXE deployments.
|
||||
# Should be an valid integer
|
||||
# Defaults to '0' for unlimited.
|
||||
#
|
||||
# [*tftp_server*]
|
||||
# (optional) IP address of Ironic compute node's tftp server.
|
||||
# Should be an valid IP address
|
||||
# Defaults to '$my_ip'.
|
||||
#
|
||||
# [*tftp_root*]
|
||||
# (optional) Ironic compute node's tftp root path.
|
||||
# Should be an valid path
|
||||
# Defaults to '/tftpboot'.
|
||||
#
|
||||
# [*images_path*]
|
||||
# (optional) Directory where images are stored on disk.
|
||||
# Should be an valid directory
|
||||
# Defaults to '/tftpboot'.
|
||||
#
|
||||
# [*tftp_master_path*]
|
||||
# (optional) Directory where master tftp images are stored on disk.
|
||||
# Should be an valid directory
|
||||
# Defaults to '/tftpboot/master_images'.
|
||||
#
|
||||
# [*instance_master_path*]
|
||||
# (optional) Directory where master tftp images are stored on disk.
|
||||
# Should be an valid directory
|
||||
# Defaults to '/var/lib/ironic/master_images'.
|
||||
#
|
||||
|
||||
class ironic::drivers::pxe (
|
||||
$deploy_kernel = undef,
|
||||
$deploy_ramdisk = undef,
|
||||
$pxe_append_params = 'nofb nomodeset vga=normal',
|
||||
$pxe_config_template = '$pybasedir/drivers/modules/pxe_config.template',
|
||||
$pxe_deploy_timeout = '0',
|
||||
$tftp_server = '$my_ip',
|
||||
$tftp_root = '/tftpboot',
|
||||
$images_path = '/var/lib/ironic/images/',
|
||||
$tftp_master_path = '/tftpboot/master_images',
|
||||
$instance_master_path = '/var/lib/ironic/master_images',
|
||||
) {
|
||||
|
||||
# Configure ironic.conf
|
||||
ironic_config {
|
||||
'pxe/pxe_append_params': value => $pxe_append_params;
|
||||
'pxe/pxe_config_template': value => $pxe_config_template;
|
||||
'pxe/pxe_deploy_timeout': value => $pxe_deploy_timeout;
|
||||
'pxe/tftp_server': value => $tftp_server;
|
||||
'pxe/tftp_root': value => $tftp_root;
|
||||
'pxe/images_path': value => $images_path;
|
||||
'pxe/tftp_master_path': value => $tftp_master_path;
|
||||
'pxe/instance_master_path': value => $instance_master_path;
|
||||
}
|
||||
|
||||
if $deploy_kernel {
|
||||
ironic_config {
|
||||
'pxe/deploy_kernel': value => $deploy_kernel;
|
||||
}
|
||||
}
|
||||
|
||||
if $deploy_ramdisk {
|
||||
ironic_config {
|
||||
'pxe/deploy_ramdisk': value => $deploy_ramdisk;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,402 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# == Class: ironic
|
||||
#
|
||||
# Installs the ironic package and configures /etc/ironic/ironic.conf
|
||||
#
|
||||
# === Parameters:
|
||||
#
|
||||
# [*enabled*]
|
||||
# (required) Whether or not to enable the ironic service
|
||||
# true/false
|
||||
#
|
||||
# [*package_ensure*]
|
||||
# (optional) The state of the package
|
||||
# Defaults to 'present'
|
||||
#
|
||||
# [*verbose*]
|
||||
# (optional) Verbose logging
|
||||
# Defaults to False
|
||||
#
|
||||
# [*debug*]
|
||||
# (optional) Print debug messages in the logs
|
||||
# Defaults to False
|
||||
#
|
||||
# [*auth_strategy*]
|
||||
# (optional) Default protocol to use when connecting to glance
|
||||
# Defaults to 'keystone'. 'https' is the only other valid option for SSL
|
||||
#
|
||||
# [*enabled_drivers*]
|
||||
# (optional) Array of drivers to load during service
|
||||
# initialization.
|
||||
# Defaults to ['pxe_ipmitool'].
|
||||
#
|
||||
# [*control_exchange*]
|
||||
# (optional) What RPC queue/exchange to use
|
||||
# Defaults to openstack
|
||||
#
|
||||
# [*rpc_backend*]
|
||||
# (optional) what rpc/queuing service to use
|
||||
# Defaults to impl_kombu (rabbitmq)
|
||||
#
|
||||
# [*rabbit_host*]
|
||||
# (Optional) IP or hostname of the rabbit server.
|
||||
# Defaults to 'localhost'
|
||||
#
|
||||
# [*rabbit_port*]
|
||||
# (Optional) Port of the rabbit server.
|
||||
# Defaults to 5672.
|
||||
#
|
||||
# [*rabbit_hosts*]
|
||||
# (Optional) Array of host:port (used with HA queues).
|
||||
# If defined, will remove rabbit_host & rabbit_port parameters from config
|
||||
# Defaults to undef.
|
||||
#
|
||||
# [*rabbit_user*]
|
||||
# (Optional) User to connect to the rabbit server.
|
||||
# Defaults to undef.
|
||||
# Deprecated, use rabbit_userid instead.
|
||||
#
|
||||
# [*rabbit_userid*]
|
||||
# (Optional) User to connect to the rabbit server.
|
||||
# Defaults to 'guest'
|
||||
#
|
||||
# [*rabbit_password*]
|
||||
# (Optional) Password to connect to the rabbit_server.
|
||||
# Defaults to empty.
|
||||
#
|
||||
# [*rabbit_virtual_host*]
|
||||
# (Optional) Virtual_host to use.
|
||||
# Defaults to '/'
|
||||
#
|
||||
# [*rabbit_use_ssl*]
|
||||
# (optional) Connect over SSL for RabbitMQ
|
||||
# Defaults to false
|
||||
#
|
||||
# [*kombu_ssl_ca_certs*]
|
||||
# (optional) SSL certification authority file (valid only if SSL enabled).
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*kombu_ssl_certfile*]
|
||||
# (optional) SSL cert file (valid only if SSL enabled).
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*kombu_ssl_keyfile*]
|
||||
# (optional) SSL key file (valid only if SSL enabled).
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*kombu_ssl_version*]
|
||||
# (optional) SSL version to use (valid only if SSL enabled).
|
||||
# Valid values are TLSv1, SSLv23 and SSLv3. SSLv2 may be
|
||||
# available on some distributions.
|
||||
# Defaults to 'TLSv1'
|
||||
#
|
||||
# [*amqp_durable_queues*]
|
||||
# Use durable queues in amqp.
|
||||
# (Optional) Defaults to false.
|
||||
#
|
||||
# [*rabbit_virtual_host*]
|
||||
# (optional) Various rabbitmq settings
|
||||
#
|
||||
# [*rabbit_hosts*]
|
||||
# (optional) array of rabbitmq servers for HA.
|
||||
# A single IP address, such as a VIP, can be used for load-balancing
|
||||
# multiple RabbitMQ Brokers.
|
||||
# Defaults to false
|
||||
#
|
||||
# [*qpid_hostname*]
|
||||
# [*qpid_port*]
|
||||
# [*qpid_username*]
|
||||
# [*qpid_password*]
|
||||
# [*qpid_heartbeat*]
|
||||
# [*qpid_protocol*]
|
||||
# [*qpid_tcp_nodelay*]
|
||||
# [*qpid_reconnect*]
|
||||
# [*qpid_reconnect_timeout*]
|
||||
# [*qpid_reconnect_limit*]
|
||||
# [*qpid_reconnect_interval*]
|
||||
# [*qpid_reconnect_interval_min*]
|
||||
# [*qpid_reconnect_interval_max*]
|
||||
# (optional) various QPID options
|
||||
#
|
||||
# [*use_syslog*]
|
||||
# (optional) Use syslog for logging
|
||||
# Defaults to false
|
||||
#
|
||||
# [*log_facility*]
|
||||
# (optional) Syslog facility to receive log lines
|
||||
# Defaults to LOG_USER
|
||||
#
|
||||
# [*database_connection*]
|
||||
# (optional) Connection url for the ironic database.
|
||||
# Defaults to: sqlite:////var/lib/ironic/ironic.sqlite
|
||||
#
|
||||
# [*database_max_retries*]
|
||||
# (optional) Database reconnection retry times.
|
||||
# Defaults to: 10
|
||||
#
|
||||
# [*database_idle_timeout*]
|
||||
# (optional) Timeout before idle db connections are reaped.
|
||||
# Defaults to: 3600
|
||||
#
|
||||
# [*database_reconnect_interval*]
|
||||
# (optional) Database reconnection interval in seconds.
|
||||
# Defaults to: 10
|
||||
#
|
||||
# [*database_retry_interval*]
|
||||
# (optional) Database reconnection interval in seconds.
|
||||
# Defaults to: 10
|
||||
#
|
||||
# [*glance_api_servers*]
|
||||
# (optional) A list of the glance api servers available to ironic.
|
||||
# Should be an array with [hostname|ip]:port
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*glance_num_retries*]
|
||||
# (optional) Number retries when downloading an image from glance.
|
||||
# Defaults to 0
|
||||
#
|
||||
# [*glance_api_insecure*]
|
||||
# (optional) Allow to perform insecure SSL (https) requests to glance.
|
||||
# Defaults to false
|
||||
#
|
||||
# [*sync_db*]
|
||||
# Enable dbsync
|
||||
# Defaults to true
|
||||
#
|
||||
class ironic (
|
||||
$enabled = true,
|
||||
$package_ensure = 'present',
|
||||
$verbose = false,
|
||||
$debug = false,
|
||||
$auth_strategy = 'keystone',
|
||||
$enabled_drivers = ['pxe_ipmitool'],
|
||||
$control_exchange = 'openstack',
|
||||
$rpc_backend = 'ironic.openstack.common.rpc.impl_kombu',
|
||||
$rabbit_hosts = false,
|
||||
$rabbit_virtual_host = '/',
|
||||
$rabbit_host = 'localhost',
|
||||
$rabbit_port = 5672,
|
||||
$rabbit_hosts = false,
|
||||
$rabbit_virtual_host = '/',
|
||||
$rabbit_userid = 'guest',
|
||||
$rabbit_password = false,
|
||||
$rabbit_use_ssl = false,
|
||||
$kombu_ssl_ca_certs = undef,
|
||||
$kombu_ssl_certfile = undef,
|
||||
$kombu_ssl_keyfile = undef,
|
||||
$kombu_ssl_version = 'TLSv1',
|
||||
$amqp_durable_queues = false,
|
||||
$qpid_hostname = 'localhost',
|
||||
$qpid_port = '5672',
|
||||
$qpid_username = 'guest',
|
||||
$qpid_password = 'guest',
|
||||
$qpid_heartbeat = 60,
|
||||
$qpid_protocol = 'tcp',
|
||||
$qpid_tcp_nodelay = true,
|
||||
$qpid_reconnect = true,
|
||||
$qpid_reconnect_timeout = 0,
|
||||
$qpid_reconnect_limit = 0,
|
||||
$qpid_reconnect_interval_min = 0,
|
||||
$qpid_reconnect_interval_max = 0,
|
||||
$qpid_reconnect_interval = 0,
|
||||
$use_syslog = false,
|
||||
$log_facility = 'LOG_USER',
|
||||
$database_connection = 'sqlite:////var/lib/ironic/ovs.sqlite',
|
||||
$database_max_retries = '10',
|
||||
$database_idle_timeout = '3600',
|
||||
$database_reconnect_interval = '10',
|
||||
$database_retry_interval = '10',
|
||||
$glance_api_servers = undef,
|
||||
$glance_num_retries = '0',
|
||||
$glance_api_insecure = false,
|
||||
$sync_db = true,
|
||||
# DEPRECATED PARAMETERS
|
||||
$rabbit_user = undef,
|
||||
) {
|
||||
|
||||
include ::ironic::params
|
||||
|
||||
if $rabbit_user {
|
||||
warning('The rabbit_user parameter is deprecated. Please use rabbit_userid instead.')
|
||||
$rabbit_user_real = $rabbit_user
|
||||
} else {
|
||||
$rabbit_user_real = $rabbit_userid
|
||||
}
|
||||
|
||||
file { '/etc/ironic':
|
||||
ensure => directory,
|
||||
require => Package['ironic-common'],
|
||||
group => 'ironic',
|
||||
}
|
||||
|
||||
file { '/etc/ironic/ironic.conf':
|
||||
require => Package['ironic-common'],
|
||||
group => 'ironic',
|
||||
}
|
||||
|
||||
package { 'ironic-common':
|
||||
ensure => $package_ensure,
|
||||
name => $::ironic::params::common_package_name,
|
||||
tag => ['openstack', 'ironic-package'],
|
||||
notify => Exec['ironic-dbsync'],
|
||||
}
|
||||
|
||||
validate_re($database_connection, '(sqlite|mysql|postgresql):\/\/(\S+:\S+@\S+\/\S+)?')
|
||||
validate_array($enabled_drivers)
|
||||
|
||||
case $database_connection {
|
||||
/mysql:\/\/\S+:\S+@\S+\/\S+/: {
|
||||
$database_backend_package = false
|
||||
require 'mysql::bindings'
|
||||
require 'mysql::bindings::python'
|
||||
}
|
||||
/postgresql:\/\/\S+:\S+@\S+\/\S+/: {
|
||||
$database_backend_package = 'python-psycopg2'
|
||||
}
|
||||
/sqlite:\/\//: {
|
||||
$database_backend_package = 'python-pysqlite2'
|
||||
}
|
||||
default: {
|
||||
fail("Invalid database connection: ${database_connection}")
|
||||
}
|
||||
}
|
||||
|
||||
if $database_backend_package and !defined(Package[$database_backend_package]) {
|
||||
package { 'ironic-database-backend':
|
||||
ensure => present,
|
||||
name => $database_backend_package,
|
||||
tag => 'openstack',
|
||||
}
|
||||
}
|
||||
|
||||
if is_array($glance_api_servers) {
|
||||
ironic_config {
|
||||
'glance/glance_api_servers': value => join($glance_api_servers, ',');
|
||||
}
|
||||
} elsif is_string($glance_api_servers) {
|
||||
ironic_config {
|
||||
'glance/glance_api_servers': value => $glance_api_servers;
|
||||
}
|
||||
}
|
||||
|
||||
ironic_config {
|
||||
'DEFAULT/verbose': value => $verbose;
|
||||
'DEFAULT/debug': value => $debug;
|
||||
'DEFAULT/auth_strategy': value => $auth_strategy;
|
||||
'DEFAULT/rpc_backend': value => $rpc_backend;
|
||||
'DEFAULT/enabled_drivers': value => join($enabled_drivers, ',');
|
||||
'database/connection': value => $database_connection, secret => true;
|
||||
'database/idle_timeout': value => $database_idle_timeout;
|
||||
'database/retry_interval': value => $database_retry_interval;
|
||||
'database/max_retries': value => $database_max_retries;
|
||||
'glance/glance_num_retries': value => $glance_num_retries;
|
||||
'glance/glance_api_insecure': value => $glance_api_insecure;
|
||||
}
|
||||
|
||||
if $sync_db {
|
||||
include ::ironic::db::sync
|
||||
}
|
||||
|
||||
if $rpc_backend == 'ironic.openstack.common.rpc.impl_kombu' {
|
||||
|
||||
if ! $rabbit_password {
|
||||
fail('When rpc_backend is rabbitmq, you must set rabbit password')
|
||||
}
|
||||
|
||||
ironic_config {
|
||||
'oslo_messaging_rabbit/rabbit_userid': value => $rabbit_user_real;
|
||||
'oslo_messaging_rabbit/rabbit_password': value => $rabbit_password, secret => true;
|
||||
'oslo_messaging_rabbit/rabbit_virtual_host': value => $rabbit_virtual_host;
|
||||
'oslo_messaging_rabbit/rabbit_use_ssl': value => $rabbit_use_ssl;
|
||||
'DEFAULT/control_exchange': value => $control_exchange;
|
||||
'DEFAULT/amqp_durable_queues': value => $amqp_durable_queues;
|
||||
}
|
||||
|
||||
if $rabbit_hosts {
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_hosts': value => join($rabbit_hosts, ',') }
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => true }
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_host': ensure => absent }
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_port': ensure => absent }
|
||||
} else {
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_host': value => $rabbit_host }
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_port': value => $rabbit_port }
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_hosts': value => "${rabbit_host}:${rabbit_port}" }
|
||||
ironic_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => false }
|
||||
}
|
||||
|
||||
if $rabbit_use_ssl {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_version': value => $kombu_ssl_version }
|
||||
|
||||
if $kombu_ssl_ca_certs {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs }
|
||||
} else {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_ca_certs': ensure => absent}
|
||||
}
|
||||
|
||||
if $kombu_ssl_certfile {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_certfile': value => $kombu_ssl_certfile }
|
||||
} else {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_certfile': ensure => absent}
|
||||
}
|
||||
|
||||
if $kombu_ssl_keyfile {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_keyfile': value => $kombu_ssl_keyfile }
|
||||
} else {
|
||||
ironic_config { 'oslo_messaging_rabbit/kombu_ssl_keyfile': ensure => absent}
|
||||
}
|
||||
} else {
|
||||
ironic_config {
|
||||
'oslo_messaging_rabbit/kombu_ssl_ca_certs': ensure => absent;
|
||||
'oslo_messaging_rabbit/kombu_ssl_certfile': ensure => absent;
|
||||
'oslo_messaging_rabbit/kombu_ssl_keyfile': ensure => absent;
|
||||
'oslo_messaging_rabbit/kombu_ssl_version': ensure => absent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if $rpc_backend == 'ironic.openstack.common.rpc.impl_qpid' {
|
||||
ironic_config {
|
||||
'DEFAULT/qpid_hostname': value => $qpid_hostname;
|
||||
'DEFAULT/qpid_port': value => $qpid_port;
|
||||
'DEFAULT/qpid_username': value => $qpid_username;
|
||||
'DEFAULT/qpid_password': value => $qpid_password, secret => true;
|
||||
'DEFAULT/qpid_heartbeat': value => $qpid_heartbeat;
|
||||
'DEFAULT/qpid_protocol': value => $qpid_protocol;
|
||||
'DEFAULT/qpid_tcp_nodelay': value => $qpid_tcp_nodelay;
|
||||
'DEFAULT/qpid_reconnect': value => $qpid_reconnect;
|
||||
'DEFAULT/qpid_reconnect_timeout': value => $qpid_reconnect_timeout;
|
||||
'DEFAULT/qpid_reconnect_limit': value => $qpid_reconnect_limit;
|
||||
'DEFAULT/qpid_reconnect_interval_min': value => $qpid_reconnect_interval_min;
|
||||
'DEFAULT/qpid_reconnect_interval_max': value => $qpid_reconnect_interval_max;
|
||||
'DEFAULT/qpid_reconnect_interval': value => $qpid_reconnect_interval;
|
||||
}
|
||||
}
|
||||
|
||||
if $use_syslog {
|
||||
ironic_config {
|
||||
'DEFAULT/use_syslog': value => true;
|
||||
'DEFAULT/syslog_log_facility': value => $log_facility;
|
||||
}
|
||||
} else {
|
||||
ironic_config {
|
||||
'DEFAULT/use_syslog': value => false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# ironic::keystone::auth
|
||||
#
|
||||
# Configures Ironic user, service and endpoint in Keystone.
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*password*]
|
||||
# (required) Password for Ironic user.
|
||||
#
|
||||
# [*auth_name*]
|
||||
# Username for Ironic service. Defaults to 'ironic'.
|
||||
#
|
||||
# [*email*]
|
||||
# Email for Ironic user. Defaults to 'ironic@localhost'.
|
||||
#
|
||||
# [*tenant*]
|
||||
# Tenant for Ironic user. Defaults to 'services'.
|
||||
#
|
||||
# [*configure_endpoint*]
|
||||
# Should Ironic endpoint be configured? Defaults to 'true'.
|
||||
#
|
||||
# [*configure_user*]
|
||||
# (Optional) Should the service user be configured?
|
||||
# Defaults to 'true'.
|
||||
#
|
||||
# [*configure_user_role*]
|
||||
# (Optional) Should the admin role be configured for the service user?
|
||||
# Defaults to 'true'.
|
||||
#
|
||||
# [*service_name*]
|
||||
# (Optional) Name of the service.
|
||||
# Defaults to the value of auth_name, but must differ from the value.
|
||||
#
|
||||
# [*service_type*]
|
||||
# Type of service. Defaults to 'baremetal'.
|
||||
#
|
||||
# [*service_description*]
|
||||
# (Optional) Description for keystone service.
|
||||
# Defaults to 'Ironic Bare Metal Provisioning Service'.
|
||||
#
|
||||
# [*region*]
|
||||
# Region for endpoint. Defaults to 'RegionOne'.
|
||||
#
|
||||
# [*public_url*]
|
||||
# (optional) The endpoint's public url. (Defaults to 'http://127.0.0.1:6385')
|
||||
# This url should *not* contain any trailing '/'.
|
||||
#
|
||||
# [*admin_url*]
|
||||
# (optional) The endpoint's admin url. (Defaults to 'http://127.0.0.1:6385')
|
||||
# This url should *not* contain any trailing '/'.
|
||||
#
|
||||
# [*internal_url*]
|
||||
# (optional) The endpoint's internal url. (Defaults to 'http://127.0.0.1:6385')
|
||||
# This url should *not* contain any trailing '/'.
|
||||
#
|
||||
# [*port*]
|
||||
# (optional) DEPRECATED: Use public_url, internal_url and admin_url instead.
|
||||
# Default port for endpoints. (Defaults to 6385)
|
||||
# Setting this parameter overrides public_url, internal_url and admin_url parameters.
|
||||
#
|
||||
# [*public_protocol*]
|
||||
# (optional) DEPRECATED: Use public_url instead.
|
||||
# Protocol for public endpoint. (Defaults to 'http')
|
||||
# Setting this parameter overrides public_url parameter.
|
||||
#
|
||||
# [*public_port*]
|
||||
# (optional) DEPRECATED: Use public_url instead.
|
||||
# Default port for endpoints. (Defaults to $port)
|
||||
# Setting this parameter overrides public_url parameter.
|
||||
#
|
||||
# [*public_address*]
|
||||
# (optional) DEPRECATED: Use public_url instead.
|
||||
# Public address for endpoint. (Defaults to '127.0.0.1')
|
||||
# Setting this parameter overrides public_url parameter.
|
||||
#
|
||||
# [*internal_address*]
|
||||
# (optional) DEPRECATED: Use internal_url instead.
|
||||
# Internal address for endpoint. (Defaults to '127.0.0.1')
|
||||
# Setting this parameter overrides internal_url parameter.
|
||||
#
|
||||
# [*admin_address*]
|
||||
# (optional) DEPRECATED: Use admin_url instead.
|
||||
# Admin address for endpoint. (Defaults to '127.0.0.1')
|
||||
# Setting this parameter overrides admin_url parameter.
|
||||
#
|
||||
# === Deprecation notes
|
||||
#
|
||||
# If any value is provided for public_protocol, public_address or port parameters,
|
||||
# public_url will be completely ignored. The same applies for internal and admin parameters.
|
||||
#
|
||||
# === Examples
|
||||
#
|
||||
# class { 'ironic::keystone::auth':
|
||||
# public_url => 'https://10.0.0.10:6385',
|
||||
# internal_url => 'https://10.0.0.11:6385',
|
||||
# admin_url => 'https://10.0.0.11:6385',
|
||||
# }
|
||||
#
|
||||
class ironic::keystone::auth (
|
||||
$password,
|
||||
$auth_name = 'ironic',
|
||||
$email = 'ironic@localhost',
|
||||
$tenant = 'services',
|
||||
$configure_endpoint = true,
|
||||
$configure_user = true,
|
||||
$configure_user_role = true,
|
||||
$service_name = undef,
|
||||
$service_type = 'baremetal',
|
||||
$service_description = 'Ironic Bare Metal Provisioning Service',
|
||||
$public_protocol = 'http',
|
||||
$region = 'RegionOne',
|
||||
$public_url = 'http://127.0.0.1:6385',
|
||||
$admin_url = 'http://127.0.0.1:6385',
|
||||
$internal_url = 'http://127.0.0.1:6385',
|
||||
# DEPRECATED PARAMETERS
|
||||
$port = undef,
|
||||
$public_protocol = undef,
|
||||
$public_address = undef,
|
||||
$public_port = undef,
|
||||
$internal_address = undef,
|
||||
$admin_address = undef,
|
||||
) {
|
||||
|
||||
if $port {
|
||||
warning('The port parameter is deprecated, use public_url, internal_url and admin_url instead.')
|
||||
}
|
||||
|
||||
if $public_port {
|
||||
warning('The public_port parameter is deprecated, use public_url instead.')
|
||||
}
|
||||
|
||||
if $public_protocol {
|
||||
warning('The public_protocol parameter is deprecated, use public_url instead.')
|
||||
}
|
||||
|
||||
if $public_address {
|
||||
warning('The public_address parameter is deprecated, use public_url instead.')
|
||||
}
|
||||
|
||||
if $internal_address {
|
||||
warning('The internal_address parameter is deprecated, use internal_url instead.')
|
||||
}
|
||||
|
||||
if $admin_address {
|
||||
warning('The admin_address parameter is deprecated, use admin_url instead.')
|
||||
}
|
||||
|
||||
if ($public_protocol or $public_address or $port or $public_port) {
|
||||
$public_url_real = sprintf('%s://%s:%s',
|
||||
pick($public_protocol, 'http'),
|
||||
pick($public_address, '127.0.0.1'),
|
||||
pick($public_port, $port, '6385'))
|
||||
} else {
|
||||
$public_url_real = $public_url
|
||||
}
|
||||
|
||||
if ($admin_address or $port) {
|
||||
$admin_url_real = sprintf('http://%s:%s',
|
||||
pick($admin_address, '127.0.0.1'),
|
||||
pick($port, '6385'))
|
||||
} else {
|
||||
$admin_url_real = $admin_url
|
||||
}
|
||||
|
||||
if ($internal_address or $port) {
|
||||
$internal_url_real = sprintf('http://%s:%s',
|
||||
pick($internal_address, '127.0.0.1'),
|
||||
pick($port, '6385'))
|
||||
} else {
|
||||
$internal_url_real = $internal_url
|
||||
}
|
||||
|
||||
$real_service_name = pick($service_name, $auth_name)
|
||||
|
||||
if $configure_user_role {
|
||||
Keystone_user_role["${auth_name}@${tenant}"] ~> Service <| name == 'ironic-server' |>
|
||||
}
|
||||
|
||||
Keystone_endpoint["${region}/${real_service_name}"] ~> Service <| name == 'ironic-server' |>
|
||||
|
||||
keystone::resource::service_identity { $auth_name:
|
||||
configure_user => $configure_user,
|
||||
configure_user_role => $configure_user_role,
|
||||
configure_endpoint => $configure_endpoint,
|
||||
service_name => $real_service_name,
|
||||
service_type => $service_type,
|
||||
service_description => $service_description,
|
||||
region => $region,
|
||||
password => $password,
|
||||
email => $email,
|
||||
tenant => $tenant,
|
||||
public_url => $public_url_real,
|
||||
internal_url => $internal_url_real,
|
||||
admin_url => $admin_url_real,
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# ironic::params
|
||||
#
|
||||
|
||||
class ironic::params {
|
||||
|
||||
$dbsync_command =
|
||||
'ironic-dbsync --config-file /etc/ironic/ironic.conf'
|
||||
|
||||
case $::osfamily {
|
||||
'RedHat': {
|
||||
$common_package_name = 'openstack-ironic-common'
|
||||
$api_package = 'openstack-ironic-api'
|
||||
$api_service = 'openstack-ironic-api'
|
||||
$conductor_package = 'openstack-ironic-conductor'
|
||||
$conductor_service = 'openstack-ironic-conductor'
|
||||
$client_package = 'python-ironicclient'
|
||||
}
|
||||
'Debian': {
|
||||
$common_package_name = 'ironic-common'
|
||||
$api_service = 'ironic-api'
|
||||
$api_package = 'ironic-api'
|
||||
$conductor_service = 'ironic-conductor'
|
||||
$conductor_package = 'ironic-conductor'
|
||||
$client_package = 'python-ironicclient'
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported osfamily ${::osfamily}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
# == Class: ironic::policy
|
||||
#
|
||||
# Configure the ironic policies
|
||||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*policies*]
|
||||
# (optional) Set of policies to configure for ironic
|
||||
# Example : { 'ironic-context_is_admin' => {'context_is_admin' => 'true'}, 'ironic-default' => {'default' => 'rule:admin_or_owner'} }
|
||||
# Defaults to empty hash.
|
||||
#
|
||||
# [*policy_path*]
|
||||
# (optional) Path to the ironic policy.json file
|
||||
# Defaults to /etc/ironic/policy.json
|
||||
#
|
||||
class ironic::policy (
|
||||
$policies = {},
|
||||
$policy_path = '/etc/ironic/policy.json',
|
||||
) {
|
||||
|
||||
validate_hash($policies)
|
||||
|
||||
Openstacklib::Policy::Base {
|
||||
file_path => $policy_path,
|
||||
}
|
||||
|
||||
create_resources('openstacklib::policy::base', $policies)
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "openstack-ironic",
|
||||
"version": "6.0.0",
|
||||
"author": "eNovance and OpenStack Contributors",
|
||||
"summary": "Puppet module for OpenStack Ironic",
|
||||
"license": "Apache-2.0",
|
||||
"source": "git://github.com/openstack/puppet-ironic.git",
|
||||
"project_page": "https://launchpad.net/puppet-ironic",
|
||||
"issues_url": "https://bugs.launchpad.net/puppet-ironic",
|
||||
"requirements": [
|
||||
{ "name": "pe","version_requirement": "3.x" },
|
||||
{ "name": "puppet","version_requirement": "3.x" }
|
||||
],
|
||||
"operatingsystem_support": [
|
||||
{
|
||||
"operatingsystem": "Debian",
|
||||
"operatingsystemrelease": ["7"]
|
||||
},
|
||||
{
|
||||
"operatingsystem": "Fedora",
|
||||
"operatingsystemrelease": ["20"]
|
||||
},
|
||||
{
|
||||
"operatingsystem": "RedHat",
|
||||
"operatingsystemrelease": ["6.5","7"]
|
||||
},
|
||||
{
|
||||
"operatingsystem": "Ubuntu",
|
||||
"operatingsystemrelease": ["12.04","14.04"]
|
||||
}
|
||||
],
|
||||
"description": "Installs and configures OpenStack Ironic (Bare metal).",
|
||||
"dependencies": [
|
||||
{ "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" },
|
||||
{ "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" },
|
||||
{ "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" },
|
||||
{ "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" },
|
||||
{ "name": "puppetlabs/vcsrepo", "version_requirement": ">=1.3.0 <2.0.0"}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
require 'spec_helper_acceptance'
|
||||
|
||||
describe 'basic ironic' do
|
||||
|
||||
context 'default parameters' do
|
||||
|
||||
it 'should work with no errors' do
|
||||
pp= <<-EOS
|
||||
Exec { logoutput => 'on_failure' }
|
||||
|
||||
# Common resources
|
||||
case $::osfamily {
|
||||
'Debian': {
|
||||
include ::apt
|
||||
class { '::openstack_extras::repo::debian::ubuntu':
|
||||
release => 'kilo',
|
||||
package_require => true,
|
||||
}
|
||||
$package_provider = 'apt'
|
||||
}
|
||||
'RedHat': {
|
||||
class { '::openstack_extras::repo::redhat::redhat':
|
||||
# Kilo is not GA yet, so let's use the testing repo
|
||||
manage_rdo => false,
|
||||
repo_hash => {
|
||||
'rdo-kilo-testing' => {
|
||||
'baseurl' => 'https://repos.fedorapeople.org/repos/openstack/openstack-kilo/testing/el7/',
|
||||
# packages are not GA so not signed
|
||||
'gpgcheck' => '0',
|
||||
'priority' => 97,
|
||||
},
|
||||
},
|
||||
}
|
||||
$package_provider = 'yum'
|
||||
}
|
||||
default: {
|
||||
fail("Unsupported osfamily (${::osfamily})")
|
||||
}
|
||||
}
|
||||
|
||||
class { '::mysql::server': }
|
||||
|
||||
class { '::rabbitmq':
|
||||
delete_guest_user => true,
|
||||
package_provider => $package_provider,
|
||||
}
|
||||
|
||||
rabbitmq_vhost { '/':
|
||||
provider => 'rabbitmqctl',
|
||||
require => Class['rabbitmq'],
|
||||
}
|
||||
|
||||
rabbitmq_user { 'ironic':
|
||||
admin => true,
|
||||
password => 'an_even_bigger_secret',
|
||||
provider => 'rabbitmqctl',
|
||||
require => Class['rabbitmq'],
|
||||
}
|
||||
|
||||
rabbitmq_user_permissions { 'ironic@/':
|
||||
configure_permission => '.*',
|
||||
write_permission => '.*',
|
||||
read_permission => '.*',
|
||||
provider => 'rabbitmqctl',
|
||||
require => Class['rabbitmq'],
|
||||
}
|
||||
|
||||
|
||||
# Keystone resources, needed by Ironic to run
|
||||
class { '::keystone::db::mysql':
|
||||
password => 'keystone',
|
||||
}
|
||||
class { '::keystone':
|
||||
verbose => true,
|
||||
debug => true,
|
||||
database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
|
||||
admin_token => 'admin_token',
|
||||
enabled => true,
|
||||
}
|
||||
class { '::keystone::roles::admin':
|
||||
email => 'test@example.tld',
|
||||
password => 'a_big_secret',
|
||||
}
|
||||
class { '::keystone::endpoint':
|
||||
public_url => "https://${::fqdn}:5000/",
|
||||
admin_url => "https://${::fqdn}:35357/",
|
||||
}
|
||||
|
||||
case $::osfamily {
|
||||
'Debian': {
|
||||
# Ironic resources
|
||||
class { '::ironic':
|
||||
rabbit_userid => 'ironic',
|
||||
rabbit_password => 'an_even_bigger_secret',
|
||||
rabbit_host => '127.0.0.1',
|
||||
database_connection => 'mysql://ironic:a_big_secret@127.0.0.1/ironic?charset=utf8',
|
||||
}
|
||||
class { '::ironic::db::mysql':
|
||||
password => 'a_big_secret',
|
||||
}
|
||||
class { '::ironic::keystone::auth':
|
||||
password => 'a_big_secret',
|
||||
}
|
||||
class { '::ironic::client': }
|
||||
class { '::ironic::conductor': }
|
||||
class { '::ironic::api':
|
||||
admin_password => 'a_big_secret',
|
||||
}
|
||||
class { '::ironic::drivers::ipmi': }
|
||||
}
|
||||
'RedHat': {
|
||||
warning("Ironic packaging is not ready on ${::osfamily}.")
|
||||
}
|
||||
}
|
||||
EOS
|
||||
|
||||
|
||||
# Run it twice and test for idempotency
|
||||
apply_manifest(pp, :catch_failures => true)
|
||||
apply_manifest(pp, :catch_changes => true)
|
||||
end
|
||||
|
||||
if os[:family] == 'Debian'
|
||||
describe port(6385) do
|
||||
it { is_expected.to be_listening.with('tcp') }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
HOSTS:
|
||||
ubuntu-14.04-amd64:
|
||||
roles:
|
||||
- master
|
||||
platform: ubuntu-14.04-amd64
|
||||
hypervisor : none
|
||||
ip: 127.0.0.1
|
||||
CONFIG:
|
||||
type: foss
|
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
centos-70-x64:
|
||||
roles:
|
||||
- master
|
||||
platform: el-7-x86_64
|
||||
hypervisor : none
|
||||
ip: 127.0.0.1
|
||||
CONFIG:
|
||||
type: foss
|
||||
set_env: false
|
|
@ -0,0 +1,10 @@
|
|||
HOSTS:
|
||||
ubuntu-14.04-amd64:
|
||||
roles:
|
||||
- master
|
||||
platform: ubuntu-14.04-amd64
|
||||
hypervisor : none
|
||||
ip: 127.0.0.1
|
||||
CONFIG:
|
||||
type: foss
|
||||
set_env: false
|
|
@ -0,0 +1,120 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::api class
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::api' do
|
||||
|
||||
let :default_params do
|
||||
{ :package_ensure => 'present',
|
||||
:enabled => true,
|
||||
:port => '6385',
|
||||
:max_limit => '1000',
|
||||
:host_ip => '0.0.0.0',
|
||||
:admin_user => 'ironic',
|
||||
}
|
||||
end
|
||||
|
||||
let :params do
|
||||
{ :admin_password => 'thepassword' }
|
||||
end
|
||||
|
||||
shared_examples_for 'ironic api' do
|
||||
let :p do
|
||||
default_params.merge(params)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_class('ironic::params') }
|
||||
it { is_expected.to contain_class('ironic::policy') }
|
||||
|
||||
it 'installs ironic api package' do
|
||||
if platform_params.has_key?(:api_package)
|
||||
is_expected.to contain_package('ironic-api').with(
|
||||
:name => platform_params[:api_package],
|
||||
:ensure => p[:package_ensure],
|
||||
:tag => ['openstack', 'ironic-package'],
|
||||
)
|
||||
is_expected.to contain_package('ironic-api').with_before(/Service\[ironic-api\]/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'ensure ironic api service is running' do
|
||||
is_expected.to contain_service('ironic-api').with(
|
||||
'hasstatus' => true,
|
||||
'tag' => 'ironic-service',
|
||||
)
|
||||
end
|
||||
|
||||
it 'configures ironic.conf' do
|
||||
is_expected.to contain_ironic_config('api/port').with_value(p[:port])
|
||||
is_expected.to contain_ironic_config('api/host_ip').with_value(p[:host_ip])
|
||||
is_expected.to contain_ironic_config('api/max_limit').with_value(p[:max_limit])
|
||||
is_expected.to contain_ironic_config('keystone_authtoken/admin_password').with_value(p[:admin_password])
|
||||
is_expected.to contain_ironic_config('keystone_authtoken/admin_user').with_value(p[:admin_user])
|
||||
is_expected.to contain_ironic_config('keystone_authtoken/auth_uri').with_value('http://127.0.0.1:5000/')
|
||||
is_expected.to contain_ironic_config('neutron/url').with_value('http://127.0.0.1:9696/')
|
||||
end
|
||||
|
||||
context 'when overriding parameters' do
|
||||
before :each do
|
||||
params.merge!(
|
||||
:port => '3430',
|
||||
:host_ip => '127.0.0.1',
|
||||
:max_limit => '10',
|
||||
:auth_protocol => 'https',
|
||||
:auth_host => '1.2.3.4'
|
||||
)
|
||||
end
|
||||
it 'should replace default parameter with new value' do
|
||||
is_expected.to contain_ironic_config('api/port').with_value(p[:port])
|
||||
is_expected.to contain_ironic_config('api/host_ip').with_value(p[:host_ip])
|
||||
is_expected.to contain_ironic_config('api/max_limit').with_value(p[:max_limit])
|
||||
is_expected.to contain_ironic_config('keystone_authtoken/auth_uri').with_value('https://1.2.3.4:5000/')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
let :platform_params do
|
||||
{ :api_package => 'ironic-api',
|
||||
:api_service => 'ironic-api' }
|
||||
end
|
||||
|
||||
it_configures 'ironic api'
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
let :platform_params do
|
||||
{ :api_service => 'ironic-api' }
|
||||
end
|
||||
|
||||
it_configures 'ironic api'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,84 @@
|
|||
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::bifrost class
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::bifrost' do
|
||||
|
||||
let :default_params do
|
||||
{ :git_source_repo => 'https://git.openstack.org/openstack/bifrost',
|
||||
:revision => master,
|
||||
:git_dest_repo_folder => '/opt/stack/bifrost',
|
||||
:ironic_url => '"http://localhost:6385/"',
|
||||
:network_interface => '"virbr0"',
|
||||
:testing => false,
|
||||
:testing_user => 'ubuntu',
|
||||
:http_boot_folder => '/httpboot',
|
||||
:nginx_port => 8080,
|
||||
:ssh_public_key_path => '"{{ ansible_env.HOME }}/.ssh/id_rsa.pub"',
|
||||
:deploy_kernel => '"{{http_boot_folder}}/coreos_production_pxe.vmlinuz"',
|
||||
:deploy_ramdisk => '"{{http_boot_folder}}/coreos_production_pxe_image-oem.cpio.gz"',
|
||||
:deploy_kernel_url => '"http://{{ hostvars[inventory_hostname][\'ansible_\' + network_interface][\'ipv4\'][\'address\'] }}:{{nginx_port}}/coreos_production_pxe.vmlinuz"',
|
||||
:deploy_ramdisk_url => '"http://{{ hostvars[inventory_hostname][\'ansible_\' + network_interface][\'ipv4\'][\'address\'] }}:{{nginx_port}}/coreos_production_pxe_image-oem.cpio.gz"',
|
||||
:deploy_image_filename => '"deployment_image.qcow2"',
|
||||
:deploy_image => '"{{http_boot_folder}}/{{deploy_image_filename}}"',
|
||||
:create_image_via_dib => true,
|
||||
:transform_boot_image => false,
|
||||
:node_default_network_interface => 'eth0',
|
||||
:ipv4_subnet_mask => '255.255.255.0',
|
||||
:ipv4_gateway => '192.168.1.1',
|
||||
:ipv4_nameserver => '8.8.8.8',
|
||||
:network_mtu => '1500',
|
||||
:dhcp_pool_start => '192.168.1.200',
|
||||
:dhcp_pool_end => '192.168.1.250',
|
||||
:ipmi_bridging => 'no',
|
||||
}
|
||||
end
|
||||
|
||||
let :params do
|
||||
{ :mysql_password => 'changeme',
|
||||
:ironic_db_password => 'changeme',
|
||||
:baremetal_json_hosts => 'test',
|
||||
}
|
||||
end
|
||||
|
||||
it 'should clone with vcsrepo bifrost repo with master branch' do
|
||||
should contain_vcsrepo('/opt/stack/bifrost').with(
|
||||
'ensure' => 'present',
|
||||
'provider' => 'git',
|
||||
'revision' => 'master',
|
||||
'source' => 'https://git.openstack.org/openstack/bifrost',
|
||||
)
|
||||
end
|
||||
|
||||
it 'should contain file group_vars/all' do
|
||||
should contain_file('/opt/stack/bifrost/playbooks/inventory/group_vars/all').with(
|
||||
'ensure' => 'present',
|
||||
'require' => 'Vcsrepo[/opt/stack/bifrost]',
|
||||
'content' => /ironic_url/,
|
||||
)
|
||||
end
|
||||
|
||||
it 'should contain file baremetal.json' do
|
||||
should contain_file('/opt/stack/bifrost/baremetal.json').with(
|
||||
'ensure' => 'present',
|
||||
'require' => 'Vcsrepo[/opt/stack/bifrost]',
|
||||
'content' => /test/,
|
||||
)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::client
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::client' do
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_class('ironic::client') }
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_class('ironic::client') }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,106 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::conductor class
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::conductor' do
|
||||
|
||||
let :default_params do
|
||||
{ :package_ensure => 'present',
|
||||
:enabled => true,
|
||||
:max_time_interval => '120',
|
||||
:force_power_state_during_sync => true }
|
||||
end
|
||||
|
||||
let :params do
|
||||
{}
|
||||
end
|
||||
|
||||
shared_examples_for 'ironic conductor' do
|
||||
let :p do
|
||||
default_params.merge(params)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_class('ironic::params') }
|
||||
|
||||
it 'installs ironic conductor package' do
|
||||
if platform_params.has_key?(:conductor_package)
|
||||
is_expected.to contain_package('ironic-conductor').with(
|
||||
:name => platform_params[:conductor_package],
|
||||
:ensure => p[:package_ensure],
|
||||
:tag => ['openstack', 'ironic-package'],
|
||||
)
|
||||
is_expected.to contain_package('ironic-conductor').with_before(/Service\[ironic-conductor\]/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'ensure ironic conductor service is running' do
|
||||
is_expected.to contain_service('ironic-conductor').with(
|
||||
'hasstatus' => true,
|
||||
'tag' => 'ironic-service',
|
||||
)
|
||||
end
|
||||
|
||||
it 'configures ironic.conf' do
|
||||
is_expected.to contain_ironic_config('conductor/max_time_interval').with_value(p[:max_time_interval])
|
||||
is_expected.to contain_ironic_config('conductor/force_power_state_during_sync').with_value(p[:force_power_state_during_sync])
|
||||
end
|
||||
|
||||
context 'when overriding parameters' do
|
||||
before :each do
|
||||
params.merge!(
|
||||
:max_time_interval => '50',
|
||||
:force_power_state_during_sync => false
|
||||
)
|
||||
end
|
||||
it 'should replace default parameter with new value' do
|
||||
is_expected.to contain_ironic_config('conductor/max_time_interval').with_value(p[:max_time_interval])
|
||||
is_expected.to contain_ironic_config('conductor/force_power_state_during_sync').with_value(p[:force_power_state_during_sync])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
let :platform_params do
|
||||
{ :conductor_package => 'ironic-conductor',
|
||||
:conductor_service => 'ironic-conductor' }
|
||||
end
|
||||
|
||||
it_configures 'ironic conductor'
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
let :platform_params do
|
||||
{ :conductor_service => 'ironic-conductor' }
|
||||
end
|
||||
|
||||
it_configures 'ironic conductor'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::config' do
|
||||
|
||||
let :params do
|
||||
{ :ironic_config => {
|
||||
'DEFAULT/foo' => { 'value' => 'fooValue' },
|
||||
'DEFAULT/bar' => { 'value' => 'barValue' },
|
||||
'DEFAULT/baz' => { 'ensure' => 'absent' }
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'configures arbitrary ironic configurations' do
|
||||
is_expected.to contain_ironic_config('DEFAULT/foo').with_value('fooValue')
|
||||
is_expected.to contain_ironic_config('DEFAULT/bar').with_value('barValue')
|
||||
is_expected.to contain_ironic_config('DEFAULT/baz').with_ensure('absent')
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,89 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::db::mysql
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::db::mysql' do
|
||||
|
||||
let :pre_condition do
|
||||
'include mysql::server'
|
||||
end
|
||||
|
||||
let :params do
|
||||
{ :password => 'passw0rd' }
|
||||
end
|
||||
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_openstacklib__db__mysql('ironic').with(
|
||||
:user => 'ironic',
|
||||
:password_hash => '*74B1C21ACE0C2D6B0678A5E503D2A60E8F9651A3',
|
||||
:charset => 'utf8',
|
||||
:collate => 'utf8_general_ci',
|
||||
)}
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_openstacklib__db__mysql('ironic').with(
|
||||
:user => 'ironic',
|
||||
:password_hash => '*74B1C21ACE0C2D6B0678A5E503D2A60E8F9651A3',
|
||||
:charset => 'utf8',
|
||||
:collate => 'utf8_general_ci',
|
||||
)}
|
||||
end
|
||||
|
||||
describe "overriding allowed_hosts param to array" do
|
||||
let :params do
|
||||
{
|
||||
:allowed_hosts => ['127.0.0.1','%']
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "overriding allowed_hosts param to string" do
|
||||
let :params do
|
||||
{
|
||||
:allowed_hosts => '192.168.1.1'
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "overriding allowed_hosts param equals to host param " do
|
||||
let :params do
|
||||
{
|
||||
:allowed_hosts => '127.0.0.1'
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::db::postgresql' do
|
||||
|
||||
let :req_params do
|
||||
{ :password => 'pw' }
|
||||
end
|
||||
|
||||
let :pre_condition do
|
||||
'include postgresql::server'
|
||||
end
|
||||
|
||||
context 'on a RedHat osfamily' do
|
||||
let :facts do
|
||||
{
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystemrelease => '7.0',
|
||||
:concat_basedir => '/var/lib/puppet/concat'
|
||||
}
|
||||
end
|
||||
|
||||
context 'with only required parameters' do
|
||||
let :params do
|
||||
req_params
|
||||
end
|
||||
|
||||
it { is_expected.to contain_postgresql__server__db('ironic').with(
|
||||
:user => 'ironic',
|
||||
:password => 'md554bdb85e136b50c40104fd9f73e1294d'
|
||||
)}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on a Debian osfamily' do
|
||||
let :facts do
|
||||
{
|
||||
:operatingsystemrelease => '7.8',
|
||||
:operatingsystem => 'Debian',
|
||||
:osfamily => 'Debian',
|
||||
:concat_basedir => '/var/lib/puppet/concat'
|
||||
}
|
||||
end
|
||||
|
||||
context 'with only required parameters' do
|
||||
let :params do
|
||||
req_params
|
||||
end
|
||||
|
||||
it { is_expected.to contain_postgresql__server__db('ironic').with(
|
||||
:user => 'ironic',
|
||||
:password => 'md554bdb85e136b50c40104fd9f73e1294d'
|
||||
)}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::db::sync' do
|
||||
|
||||
shared_examples_for 'ironic-dbsync' do
|
||||
|
||||
it 'runs ironic-manage db_sync' do
|
||||
is_expected.to contain_exec('ironic-dbsync').with(
|
||||
:command => 'ironic-dbsync --config-file /etc/ironic/ironic.conf',
|
||||
:path => '/usr/bin',
|
||||
:user => 'root',
|
||||
:refreshonly => 'true',
|
||||
:logoutput => 'on_failure'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on a RedHat osfamily' do
|
||||
let :facts do
|
||||
{
|
||||
:osfamily => 'RedHat',
|
||||
:operatingsystemrelease => '7.0',
|
||||
:concat_basedir => '/var/lib/puppet/concat'
|
||||
}
|
||||
end
|
||||
|
||||
it_configures 'ironic-dbsync'
|
||||
end
|
||||
|
||||
context 'on a Debian osfamily' do
|
||||
let :facts do
|
||||
{
|
||||
:operatingsystemrelease => '7.8',
|
||||
:operatingsystem => 'Debian',
|
||||
:osfamily => 'Debian',
|
||||
:concat_basedir => '/var/lib/puppet/concat'
|
||||
}
|
||||
end
|
||||
|
||||
it_configures 'ironic-dbsync'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::drivers::ipmi class
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::drivers::ipmi' do
|
||||
|
||||
let :default_params do
|
||||
{ :retry_timeout => '10' }
|
||||
end
|
||||
|
||||
let :params do
|
||||
{}
|
||||
end
|
||||
|
||||
shared_examples_for 'ironic ipmi driver' do
|
||||
let :p do
|
||||
default_params.merge(params)
|
||||
end
|
||||
|
||||
it 'configures ironic.conf' do
|
||||
is_expected.to contain_ironic_config('ipmi/retry_timeout').with_value(p[:retry_timeout])
|
||||
end
|
||||
|
||||
context 'when overriding parameters' do
|
||||
before do
|
||||
params.merge!(:retry_timeout => '50')
|
||||
end
|
||||
it 'should replace default parameter with new value' do
|
||||
is_expected.to contain_ironic_config('ipmi/retry_timeout').with_value(p[:retry_timeout])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
it_configures 'ironic ipmi driver'
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
it_configures 'ironic ipmi driver'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,104 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::drivers::pxe class
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::drivers::pxe' do
|
||||
|
||||
let :default_params do
|
||||
{ :pxe_append_params => 'nofb nomodeset vga=normal',
|
||||
:pxe_config_template => '$pybasedir/drivers/modules/pxe_config.template',
|
||||
:pxe_deploy_timeout => '0',
|
||||
:tftp_server => '$my_ip',
|
||||
:tftp_root => '/tftpboot',
|
||||
:images_path => '/var/lib/ironic/images/',
|
||||
:tftp_master_path => '/tftpboot/master_images',
|
||||
:instance_master_path => '/var/lib/ironic/master_images' }
|
||||
end
|
||||
|
||||
let :params do
|
||||
{}
|
||||
end
|
||||
|
||||
shared_examples_for 'ironic pxe driver' do
|
||||
let :p do
|
||||
default_params.merge(params)
|
||||
end
|
||||
|
||||
it 'configures ironic.conf' do
|
||||
is_expected.to contain_ironic_config('pxe/pxe_append_params').with_value(p[:pxe_append_params])
|
||||
is_expected.to contain_ironic_config('pxe/pxe_config_template').with_value(p[:pxe_config_template])
|
||||
is_expected.to contain_ironic_config('pxe/pxe_deploy_timeout').with_value(p[:pxe_deploy_timeout])
|
||||
is_expected.to contain_ironic_config('pxe/tftp_server').with_value(p[:tftp_server])
|
||||
is_expected.to contain_ironic_config('pxe/tftp_root').with_value(p[:tftp_root])
|
||||
is_expected.to contain_ironic_config('pxe/images_path').with_value(p[:images_path])
|
||||
is_expected.to contain_ironic_config('pxe/tftp_master_path').with_value(p[:tftp_master_path])
|
||||
is_expected.to contain_ironic_config('pxe/instance_master_path').with_value(p[:instance_master_path])
|
||||
end
|
||||
|
||||
context 'when overriding parameters' do
|
||||
before do
|
||||
params.merge!(
|
||||
:deploy_kernel => 'foo',
|
||||
:deploy_ramdisk => 'bar',
|
||||
:pxe_append_params => 'foo',
|
||||
:pxe_config_template => 'bar',
|
||||
:pxe_deploy_timeout => '40',
|
||||
:tftp_server => '192.168.0.1',
|
||||
:tftp_root => '/mnt/ftp',
|
||||
:images_path => '/mnt/images',
|
||||
:tftp_master_path => '/mnt/master_images',
|
||||
:instance_master_path => '/mnt/ironic/master_images'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should replace default parameter with new value' do
|
||||
is_expected.to contain_ironic_config('pxe/deploy_kernel').with_value(p[:deploy_kernel])
|
||||
is_expected.to contain_ironic_config('pxe/deploy_ramdisk').with_value(p[:deploy_ramdisk])
|
||||
is_expected.to contain_ironic_config('pxe/pxe_append_params').with_value(p[:pxe_append_params])
|
||||
is_expected.to contain_ironic_config('pxe/pxe_config_template').with_value(p[:pxe_config_template])
|
||||
is_expected.to contain_ironic_config('pxe/pxe_deploy_timeout').with_value(p[:pxe_deploy_timeout])
|
||||
is_expected.to contain_ironic_config('pxe/tftp_server').with_value(p[:tftp_server])
|
||||
is_expected.to contain_ironic_config('pxe/tftp_root').with_value(p[:tftp_root])
|
||||
is_expected.to contain_ironic_config('pxe/images_path').with_value(p[:images_path])
|
||||
is_expected.to contain_ironic_config('pxe/tftp_master_path').with_value(p[:tftp_master_path])
|
||||
is_expected.to contain_ironic_config('pxe/instance_master_path').with_value(p[:instance_master_path])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
it_configures 'ironic pxe driver'
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
it_configures 'ironic pxe driver'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,315 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic' do
|
||||
|
||||
let :params do
|
||||
{ :package_ensure => 'present',
|
||||
:verbose => false,
|
||||
:debug => false,
|
||||
:enabled_drivers => ['pxe_ipmitool'],
|
||||
:rabbit_host => '127.0.0.1',
|
||||
:rabbit_port => 5672,
|
||||
:rabbit_hosts => false,
|
||||
:rabbit_userid => 'guest',
|
||||
:rabbit_password => 'guest',
|
||||
:rabbit_virtual_host => '/',
|
||||
:database_connection => 'sqlite:////var/lib/ironic/ironic.sqlite',
|
||||
:database_max_retries => 10,
|
||||
:database_idle_timeout => 3600,
|
||||
:database_reconnect_interval => 10,
|
||||
:database_retry_interval => 10,
|
||||
:glance_num_retries => 0,
|
||||
:glance_api_insecure => false
|
||||
}
|
||||
end
|
||||
|
||||
shared_examples_for 'ironic' do
|
||||
|
||||
context 'and if rabbit_host parameter is provided' do
|
||||
it_configures 'a ironic base installation'
|
||||
it_configures 'with SSL disabled'
|
||||
it_configures 'with SSL enabled without kombu'
|
||||
it_configures 'with SSL enabled with kombu'
|
||||
end
|
||||
|
||||
context 'and if rabbit_hosts parameter is provided' do
|
||||
before do
|
||||
params.delete(:rabbit_host)
|
||||
params.delete(:rabbit_port)
|
||||
end
|
||||
|
||||
context 'with one server' do
|
||||
before { params.merge!( :rabbit_hosts => ['127.0.0.1:5672'] ) }
|
||||
it_configures 'a ironic base installation'
|
||||
it_configures 'rabbit HA with a single virtual host'
|
||||
end
|
||||
|
||||
context 'with multiple servers' do
|
||||
before { params.merge!( :rabbit_hosts => ['rabbit1:5672', 'rabbit2:5672'] ) }
|
||||
it_configures 'a ironic base installation'
|
||||
it_configures 'rabbit HA with multiple hosts'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with mysql database backend' do
|
||||
before do
|
||||
params.merge!(:database_connection => 'mysql://ironic:ironic@localhost/ironic')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sqlite database backend' do
|
||||
before do
|
||||
params.merge!(:database_connection => 'sqlite:////var/lib/ironic/ironic.sqlite')
|
||||
end
|
||||
it { is_expected.to contain_package('ironic-database-backend').with_name('python-pysqlite2')}
|
||||
end
|
||||
|
||||
context 'with postgresql database backend' do
|
||||
before do
|
||||
params.merge!(:database_connection => 'postgresql://ironic:ironic@localhost/ironic')
|
||||
end
|
||||
it { is_expected.to contain_package('ironic-database-backend').with_name('python-psycopg2')}
|
||||
end
|
||||
|
||||
it_configures 'with syslog disabled'
|
||||
it_configures 'with syslog enabled'
|
||||
it_configures 'with syslog enabled and custom settings'
|
||||
end
|
||||
|
||||
shared_examples_for 'a ironic base installation' do
|
||||
|
||||
it { is_expected.to contain_class('ironic::params') }
|
||||
|
||||
it 'configures ironic configuration folder' do
|
||||
is_expected.to contain_file('/etc/ironic/').with(
|
||||
:ensure => 'directory',
|
||||
:group => 'ironic',
|
||||
:require => 'Package[ironic-common]'
|
||||
)
|
||||
end
|
||||
|
||||
it 'configures ironic configuration file' do
|
||||
is_expected.to contain_file('/etc/ironic/ironic.conf').with(
|
||||
:group => 'ironic',
|
||||
:require => 'Package[ironic-common]'
|
||||
)
|
||||
end
|
||||
|
||||
it 'installs ironic package' do
|
||||
is_expected.to contain_package('ironic-common').with(
|
||||
:ensure => 'present',
|
||||
:name => platform_params[:common_package_name],
|
||||
:tag => ['openstack', 'ironic-package'],
|
||||
)
|
||||
end
|
||||
|
||||
it 'configures enabled_drivers' do
|
||||
is_expected.to contain_ironic_config('DEFAULT/enabled_drivers').with_value( params[:enabled_drivers] )
|
||||
end
|
||||
|
||||
it 'configures credentials for rabbit' do
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_userid').with_value( params[:rabbit_userid] )
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_password').with_value( params[:rabbit_password] )
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_virtual_host').with_value( params[:rabbit_virtual_host] )
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_password').with_secret( true )
|
||||
end
|
||||
|
||||
it 'should perform default database configuration' do
|
||||
is_expected.to contain_ironic_config('database/connection').with_value(params[:database_connection])
|
||||
is_expected.to contain_ironic_config('database/max_retries').with_value(params[:database_max_retries])
|
||||
is_expected.to contain_ironic_config('database/idle_timeout').with_value(params[:database_idle_timeout])
|
||||
is_expected.to contain_ironic_config('database/retry_interval').with_value(params[:database_retry_interval])
|
||||
end
|
||||
|
||||
it 'configures glance connection' do
|
||||
is_expected.to contain_ironic_config('glance/glance_num_retries').with_value(params[:glance_num_retries])
|
||||
is_expected.to contain_ironic_config('glance/glance_api_insecure').with_value(params[:glance_api_insecure])
|
||||
end
|
||||
|
||||
it 'configures ironic.conf' do
|
||||
is_expected.to contain_ironic_config('DEFAULT/verbose').with_value( params[:verbose] )
|
||||
is_expected.to contain_ironic_config('DEFAULT/auth_strategy').with_value('keystone')
|
||||
is_expected.to contain_ironic_config('DEFAULT/control_exchange').with_value('openstack')
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'rabbit HA with a single virtual host' do
|
||||
it 'in ironic.conf' do
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_host').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_port').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_hosts').with_value( params[:rabbit_hosts] )
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value(true)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'rabbit HA with multiple hosts' do
|
||||
it 'in ironic.conf' do
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_host').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_port').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_hosts').with_value( params[:rabbit_hosts].join(',') )
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value(true)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'with SSL enabled with kombu' do
|
||||
before do
|
||||
params.merge!(
|
||||
:rabbit_use_ssl => true,
|
||||
:kombu_ssl_ca_certs => '/path/to/ssl/ca/certs',
|
||||
:kombu_ssl_certfile => '/path/to/ssl/cert/file',
|
||||
:kombu_ssl_keyfile => '/path/to/ssl/keyfile',
|
||||
:kombu_ssl_version => 'TLSv1'
|
||||
)
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value('true')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_value('/path/to/ssl/ca/certs')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_value('/path/to/ssl/cert/file')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_value('/path/to/ssl/keyfile')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_version').with_value('TLSv1')
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'with SSL enabled without kombu' do
|
||||
before do
|
||||
params.merge!(
|
||||
:rabbit_use_ssl => true,
|
||||
)
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value('true')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_version').with_value('TLSv1')
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'with SSL disabled' do
|
||||
before do
|
||||
params.merge!(
|
||||
:rabbit_use_ssl => false,
|
||||
:kombu_ssl_ca_certs => 'undef',
|
||||
:kombu_ssl_certfile => 'undef',
|
||||
:kombu_ssl_keyfile => 'undef',
|
||||
:kombu_ssl_version => 'TLSv1'
|
||||
)
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value('false')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_ensure('absent')
|
||||
is_expected.to contain_ironic_config('oslo_messaging_rabbit/kombu_ssl_version').with_ensure('absent')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
shared_examples_for 'with amqp_durable_queues disabled' do
|
||||
it { is_expected.to contain_ironic_config('DEFAULT/amqp_durable_queues').with_value(false) }
|
||||
end
|
||||
|
||||
shared_examples_for 'with amqp_durable_queues enabled' do
|
||||
before do
|
||||
params.merge( :amqp_durable_queues => true )
|
||||
end
|
||||
|
||||
it { is_expected.to contain_ironic_config('DEFAULT/amqp_durable_queues').with_value(true) }
|
||||
end
|
||||
|
||||
shared_examples_for 'with syslog disabled' do
|
||||
it { is_expected.to contain_ironic_config('DEFAULT/use_syslog').with_value(false) }
|
||||
end
|
||||
|
||||
shared_examples_for 'with syslog enabled' do
|
||||
before do
|
||||
params.merge!( :use_syslog => true )
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_ironic_config('DEFAULT/use_syslog').with_value(true)
|
||||
is_expected.to contain_ironic_config('DEFAULT/syslog_log_facility').with_value('LOG_USER')
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'with syslog enabled and custom settings' do
|
||||
before do
|
||||
params.merge!(
|
||||
:use_syslog => true,
|
||||
:log_facility => 'LOG_LOCAL0'
|
||||
)
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_ironic_config('DEFAULT/use_syslog').with_value(true)
|
||||
is_expected.to contain_ironic_config('DEFAULT/syslog_log_facility').with_value('LOG_LOCAL0')
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'with one glance server' do
|
||||
before do
|
||||
params.merge!(:glance_api_servers => '10.0.0.1:9292')
|
||||
end
|
||||
|
||||
it 'should configure one glance server' do
|
||||
is_expected.to contain_ironic_config('glance/glance_api_servers').with_value(p[:glance_api_servers])
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'with two glance servers' do
|
||||
before do
|
||||
params.merge!(:glance_api_servers => ['10.0.0.1:9292','10.0.0.2:9292'])
|
||||
end
|
||||
|
||||
it 'should configure one glance server' do
|
||||
is_expected.to contain_ironic_config('glance/glance_api_servers').with_value(p[:glance_api_servers].join(','))
|
||||
end
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
let :platform_params do
|
||||
{ :common_package_name => 'ironic-common' }
|
||||
end
|
||||
|
||||
it_configures 'ironic'
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
let :platform_params do
|
||||
{ :common_package_name => 'openstack-ironic-common' }
|
||||
end
|
||||
|
||||
it_configures 'ironic'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,177 @@
|
|||
#
|
||||
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
|
||||
#
|
||||
# Author: Emilien Macchi <emilien.macchi@enovance.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Unit tests for ironic::keystone::auth
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::keystone::auth' do
|
||||
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
describe 'with default class parameters' do
|
||||
let :params do
|
||||
{ :password => 'ironic_password',
|
||||
:tenant => 'foobar' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_keystone_user('ironic').with(
|
||||
:ensure => 'present',
|
||||
:password => 'ironic_password',
|
||||
:tenant => 'foobar'
|
||||
) }
|
||||
|
||||
it { is_expected.to contain_keystone_user_role('ironic@foobar').with(
|
||||
:ensure => 'present',
|
||||
:roles => ['admin']
|
||||
)}
|
||||
|
||||
it { is_expected.to contain_keystone_service('ironic').with(
|
||||
:ensure => 'present',
|
||||
:type => 'baremetal',
|
||||
:description => 'Ironic Bare Metal Provisioning Service'
|
||||
) }
|
||||
|
||||
it { is_expected.to contain_keystone_endpoint('RegionOne/ironic').with(
|
||||
:ensure => 'present',
|
||||
:public_url => "http://127.0.0.1:6385",
|
||||
:admin_url => "http://127.0.0.1:6385",
|
||||
:internal_url => "http://127.0.0.1:6385"
|
||||
) }
|
||||
end
|
||||
|
||||
describe 'when configuring ironic-server' do
|
||||
let :pre_condition do
|
||||
"class { 'ironic::server': auth_password => 'test' }"
|
||||
end
|
||||
|
||||
let :params do
|
||||
{ :password => 'ironic_password',
|
||||
:tenant => 'foobar' }
|
||||
end
|
||||
|
||||
#FIXME it { should contain_keystone_endpoint('RegionOne/ironic').with_notify('Service[ironic-server]') }
|
||||
end
|
||||
|
||||
describe 'with endpoint parameters' do
|
||||
let :params do
|
||||
{ :password => 'ironic_password',
|
||||
:public_url => 'https://10.0.0.10:6385',
|
||||
:admin_url => 'https://10.0.0.11:6385',
|
||||
:internal_url => 'https://10.0.0.11:6385' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_keystone_endpoint('RegionOne/ironic').with(
|
||||
:ensure => 'present',
|
||||
:public_url => 'https://10.0.0.10:6385',
|
||||
:admin_url => 'https://10.0.0.11:6385',
|
||||
:internal_url => 'https://10.0.0.11:6385'
|
||||
) }
|
||||
end
|
||||
|
||||
describe 'with deprecated endpoint parameters' do
|
||||
let :params do
|
||||
{ :password => 'ironic_password',
|
||||
:public_protocol => 'https',
|
||||
:public_port => '80',
|
||||
:public_address => '10.10.10.10',
|
||||
:port => '81',
|
||||
:internal_address => '10.10.10.11',
|
||||
:admin_address => '10.10.10.12' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_keystone_endpoint('RegionOne/ironic').with(
|
||||
:ensure => 'present',
|
||||
:public_url => "https://10.10.10.10:80",
|
||||
:internal_url => "http://10.10.10.11:81",
|
||||
:admin_url => "http://10.10.10.12:81"
|
||||
) }
|
||||
end
|
||||
|
||||
describe 'when overriding auth name' do
|
||||
let :params do
|
||||
{ :password => 'foo',
|
||||
:auth_name => 'ironicy' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_keystone_user('ironicy') }
|
||||
it { is_expected.to contain_keystone_user_role('ironicy@services') }
|
||||
it { is_expected.to contain_keystone_service('ironicy') }
|
||||
it { is_expected.to contain_keystone_endpoint('RegionOne/ironicy') }
|
||||
end
|
||||
|
||||
describe 'when overriding service name' do
|
||||
let :params do
|
||||
{
|
||||
:service_name => 'ironic_service',
|
||||
:password => 'ironic_password',
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.to contain_keystone_user('ironic') }
|
||||
it { is_expected.to contain_keystone_user_role('ironic@services') }
|
||||
it { is_expected.to contain_keystone_service('ironic_service') }
|
||||
it { is_expected.to contain_keystone_endpoint('RegionOne/ironic_service') }
|
||||
end
|
||||
|
||||
describe 'when disabling user configuration' do
|
||||
|
||||
let :params do
|
||||
{
|
||||
:password => 'ironic_password',
|
||||
:configure_user => false
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.not_to contain_keystone_user('ironic') }
|
||||
|
||||
it { is_expected.to contain_keystone_user_role('ironic@services') }
|
||||
|
||||
it { is_expected.to contain_keystone_service('ironic').with(
|
||||
:ensure => 'present',
|
||||
:type => 'baremetal',
|
||||
:description => 'Ironic Bare Metal Provisioning Service'
|
||||
) }
|
||||
|
||||
end
|
||||
|
||||
describe 'when disabling user and user role configuration' do
|
||||
|
||||
let :params do
|
||||
{
|
||||
:password => 'ironic_password',
|
||||
:configure_user => false,
|
||||
:configure_user_role => false
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.not_to contain_keystone_user('ironic') }
|
||||
|
||||
it { is_expected.not_to contain_keystone_user_role('ironic@services') }
|
||||
|
||||
it { is_expected.to contain_keystone_service('ironic').with(
|
||||
:ensure => 'present',
|
||||
:type => 'baremetal',
|
||||
:description => 'Ironic Bare Metal Provisioning Service'
|
||||
) }
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'ironic::policy' do
|
||||
|
||||
shared_examples_for 'ironic policies' do
|
||||
let :params do
|
||||
{
|
||||
:policy_path => '/etc/ironic/policy.json',
|
||||
:policies => {
|
||||
'context_is_admin' => {
|
||||
'key' => 'context_is_admin',
|
||||
'value' => 'foo:bar'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'set up the policies' do
|
||||
is_expected.to contain_openstacklib__policy__base('context_is_admin').with({
|
||||
:key => 'context_is_admin',
|
||||
:value => 'foo:bar'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'on Debian platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'Debian' }
|
||||
end
|
||||
|
||||
it_configures 'ironic policies'
|
||||
end
|
||||
|
||||
context 'on RedHat platforms' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
it_configures 'ironic policies'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
shared_examples_for "a Puppet::Error" do |description|
|
||||
it "with message matching #{description.inspect}" do
|
||||
expect { is_expected.to have_class_count(1) }.to raise_error(Puppet::Error, description)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
require 'puppetlabs_spec_helper/module_spec_helper'
|
||||
require 'shared_examples'
|
||||
|
||||
RSpec.configure do |c|
|
||||
c.alias_it_should_behave_like_to :it_configures, 'configures'
|
||||
c.alias_it_should_behave_like_to :it_raises, 'raises'
|
||||
end
|
|
@ -0,0 +1,56 @@
|
|||
require 'beaker-rspec'
|
||||
require 'beaker/puppet_install_helper'
|
||||
|
||||
run_puppet_install_helper
|
||||
|
||||
RSpec.configure do |c|
|
||||
# Project root
|
||||
proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
modname = JSON.parse(open('metadata.json').read)['name'].split('-')[1]
|
||||
|
||||
# Readable test descriptions
|
||||
c.formatter = :documentation
|
||||
|
||||
# Configure all nodes in nodeset
|
||||
c.before :suite do
|
||||
# Install module and dependencies
|
||||
hosts.each do |host|
|
||||
|
||||
# install git
|
||||
install_package host, 'git'
|
||||
|
||||
zuul_ref = ENV['ZUUL_REF']
|
||||
zuul_branch = ENV['ZUUL_BRANCH']
|
||||
zuul_url = ENV['ZUUL_URL']
|
||||
|
||||
repo = 'openstack/puppet-openstack-integration'
|
||||
|
||||
# Start out with clean moduledir, don't trust r10k to purge it
|
||||
on host, "rm -rf /etc/puppet/modules/*"
|
||||
# Install dependent modules via git or zuul
|
||||
r = on host, "test -e /usr/zuul-env/bin/zuul-cloner", { :acceptable_exit_codes => [0,1] }
|
||||
if r.exit_code == 0
|
||||
zuul_clone_cmd = '/usr/zuul-env/bin/zuul-cloner '
|
||||
zuul_clone_cmd += '--cache-dir /opt/git '
|
||||
zuul_clone_cmd += "--zuul-ref #{zuul_ref} "
|
||||
zuul_clone_cmd += "--zuul-branch #{zuul_branch} "
|
||||
zuul_clone_cmd += "--zuul-url #{zuul_url} "
|
||||
zuul_clone_cmd += "git://git.openstack.org #{repo}"
|
||||
on host, zuul_clone_cmd
|
||||
else
|
||||
on host, "git clone https://git.openstack.org/#{repo} #{repo}"
|
||||
end
|
||||
|
||||
on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh"
|
||||
|
||||
# Install the module being tested
|
||||
on host, "rm -fr /etc/puppet/modules/#{modname}"
|
||||
puppet_module_install(:source => proj_root, :module_name => modname)
|
||||
|
||||
on host, "rm -fr #{repo}"
|
||||
|
||||
# List modules installed to help with debugging
|
||||
on host, puppet('module','list'), { :acceptable_exit_codes => 0 }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
$LOAD_PATH.push(
|
||||
File.join(
|
||||
File.dirname(__FILE__),
|
||||
'..',
|
||||
'..',
|
||||
'..',
|
||||
'fixtures',
|
||||
'modules',
|
||||
'inifile',
|
||||
'lib')
|
||||
)
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
provider_class = Puppet::Type.type(:ironic_config).provider(:ini_setting)
|
||||
|
||||
describe provider_class do
|
||||
|
||||
it 'should default to the default setting when no other one is specified' do
|
||||
resource = Puppet::Type::Ironic_config.new(
|
||||
{
|
||||
:name => 'DEFAULT/foo',
|
||||
:value => 'bar'
|
||||
}
|
||||
)
|
||||
provider = provider_class.new(resource)
|
||||
expect(provider.section).to eq('DEFAULT')
|
||||
expect(provider.setting).to eq('foo')
|
||||
end
|
||||
|
||||
it 'should allow setting to be set explicitly' do
|
||||
resource = Puppet::Type::Ironic_config.new(
|
||||
{
|
||||
:name => 'dude/foo',
|
||||
:value => 'bar'
|
||||
}
|
||||
)
|
||||
provider = provider_class.new(resource)
|
||||
expect(provider.section).to eq('dude')
|
||||
expect(provider.setting).to eq('foo')
|
||||
end
|
||||
end
|
|
@ -0,0 +1,111 @@
|
|||
require 'puppet'
|
||||
require 'spec_helper'
|
||||
require 'puppet/provider/ironic'
|
||||
require 'tempfile'
|
||||
|
||||
describe Puppet::Provider::Ironic do
|
||||
|
||||
def klass
|
||||
described_class
|
||||
end
|
||||
|
||||
let :credential_hash do
|
||||
{
|
||||
'auth_host' => '192.168.56.210',
|
||||
'auth_port' => '35357',
|
||||
'auth_protocol' => 'https',
|
||||
'admin_tenant_name' => 'admin_tenant',
|
||||
'admin_user' => 'admin',
|
||||
'admin_password' => 'password',
|
||||
}
|
||||
end
|
||||
|
||||
let :auth_endpoint do
|
||||
'https://192.168.56.210:35357/v2.0/'
|
||||
end
|
||||
|
||||
let :credential_error do
|
||||
/Ironic types will not work/
|
||||
end
|
||||
|
||||
after :each do
|
||||
klass.reset
|
||||
end
|
||||
|
||||
describe 'when determining credentials' do
|
||||
|
||||
it 'should fail if config is empty' do
|
||||
conf = {}
|
||||
klass.expects(:ironic_conf).returns(conf)
|
||||
expect do
|
||||
klass.ironic_credentials
|
||||
end.to raise_error(Puppet::Error, credential_error)
|
||||
end
|
||||
|
||||
it 'should fail if config does not have keystone_authtoken section.' do
|
||||
conf = {'foo' => 'bar'}
|
||||
klass.expects(:ironic_conf).returns(conf)
|
||||
expect do
|
||||
klass.ironic_credentials
|
||||
end.to raise_error(Puppet::Error, credential_error)
|
||||
end
|
||||
|
||||
it 'should fail if config does not contain all auth params' do
|
||||
conf = {'keystone_authtoken' => {'invalid_value' => 'foo'}}
|
||||
klass.expects(:ironic_conf).returns(conf)
|
||||
expect do
|
||||
klass.ironic_credentials
|
||||
end.to raise_error(Puppet::Error, credential_error)
|
||||
end
|
||||
|
||||
it 'should use specified host/port/protocol in the auth endpoint' do
|
||||
conf = {'keystone_authtoken' => credential_hash}
|
||||
klass.expects(:ironic_conf).returns(conf)
|
||||
expect(klass.get_auth_endpoint).to eq(auth_endpoint)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'when invoking the ironic cli' do
|
||||
|
||||
it 'should set auth credentials in the environment' do
|
||||
authenv = {
|
||||
:OS_AUTH_URL => auth_endpoint,
|
||||
:OS_USERNAME => credential_hash['admin_user'],
|
||||
:OS_TENANT_NAME => credential_hash['admin_tenant_name'],
|
||||
:OS_PASSWORD => credential_hash['admin_password'],
|
||||
}
|
||||
klass.expects(:get_ironic_credentials).with().returns(credential_hash)
|
||||
klass.expects(:withenv).with(authenv)
|
||||
klass.auth_ironic('test_retries')
|
||||
end
|
||||
|
||||
['[Errno 111] Connection refused',
|
||||
'(HTTP 400)'].reverse.each do |valid_message|
|
||||
it "should retry when ironic cli returns with error #{valid_message}" do
|
||||
klass.expects(:get_ironic_credentials).with().returns({})
|
||||
klass.expects(:sleep).with(10).returns(nil)
|
||||
klass.expects(:ironic).twice.with(['test_retries']).raises(
|
||||
Exception, valid_message).then.returns('')
|
||||
klass.auth_ironic('test_retries')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'when listing ironic resources' do
|
||||
|
||||
it 'should exclude the column header' do
|
||||
output = <<-EOT
|
||||
id
|
||||
net1
|
||||
net2
|
||||
EOT
|
||||
klass.expects(:auth_ironic).returns(output)
|
||||
result = klass.list_ironic_resources('foo')
|
||||
expect(result).to eql(['net1', 'net2'])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require 'puppet'
|
||||
require 'puppet/type/ironic_config'
|
||||
|
||||
describe 'Puppet::Type.type(:ironic_config)' do
|
||||
before :each do
|
||||
@ironic_config = Puppet::Type.type(:ironic_config).new(:name => 'DEFAULT/foo', :value => 'bar')
|
||||
end
|
||||
|
||||
it 'should autorequire the package that install the file' do
|
||||
catalog = Puppet::Resource::Catalog.new
|
||||
package = Puppet::Type.type(:package).new(:name => 'ironic-common')
|
||||
catalog.add_resource package, @ironic_config
|
||||
dependency = @ironic_config.autorequire
|
||||
expect(dependency.size).to eq(1)
|
||||
expect(dependency[0].target).to eq(@ironic_config)
|
||||
expect(dependency[0].source).to eq(package)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
<%= @baremetal_json_hosts %>
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
ironic_url: <%= @ironic_url %>
|
||||
network_interface: <%= @network_interface %>
|
||||
# ironic_db_password ironic user password for rabbit
|
||||
ironic_db_password: <%= @ironic_db_password %>
|
||||
# mysql_password: mysql root user password
|
||||
mysql_password: <%= @mysql_password %>
|
||||
# If testing is true, then the environment is setup for using libvirt
|
||||
# virtual machines for the hardware instead of real hardware.
|
||||
# testing: true
|
||||
#
|
||||
# Normally this user should be ubuntu, however if cirros is used,
|
||||
# a user may wish to define a specific user for testing VM
|
||||
# connectivity during atest sequence
|
||||
testing: <%= @testing %>
|
||||
testing_user: <%= @testing_user %>
|
||||
http_boot_folder: <%= @http_boot_folder %>
|
||||
nginx_port: <%= @nginx_port %>
|
||||
ssh_public_key_path: <%= @ssh_public_key_path %>
|
||||
deploy_kernel: <%= @deploy_kernel %>
|
||||
deploy_ramdisk: <%= @deploy_ramdisk %>
|
||||
deploy_kernel_url: <%= @deploy_kernel_url %>
|
||||
deploy_ramdisk_url: <%= @deploy_ramdisk_url %>
|
||||
# When using disk image builder based image generation, which is the
|
||||
# default at this time, the deploy_image_filename must end with .qcow2
|
||||
# due to the image creation process.
|
||||
deploy_image_filename: <%= @deploy_image_filename %>
|
||||
deploy_image: <%= @deploy_image %>
|
||||
# Setting to utilize diskimage-builder to create a bootable image.
|
||||
create_image_via_dib: <%= @create_image_via_dib %>
|
||||
# Transform boot image is intended for use with the Ubuntu trusty image. It makes the image bootable by installing Grub.
|
||||
# Setting to prepend a partition image with a boot sector and partition table.
|
||||
transform_boot_image: <%= @transform_boot_image %>
|
||||
node_default_network_interface: <%= @node_default_network_interface %>
|
||||
# ipv4_subnet_mask is intended for the static ipv4 address assignments.
|
||||
ipv4_subnet_mask: <%= @ipv4_subnet_mask %>
|
||||
ipv4_gateway: <%= @ipv4_gateway %>
|
||||
ipv4_nameserver: <%= @ipv4_nameserver %>
|
||||
network_mtu: <%= @network_mtu %>
|
||||
dhcp_pool_start: <%= @dhcp_pool_start %>
|
||||
dhcp_pool_end: <%= @dhcp_pool_end %>
|
||||
# ipmi_bridging: Default undefined. Valid values: "no", "single", and "dual"
|
||||
# See http://docs.openstack.org/developer/ironic/_modules/ironic/drivers/modules/ipmitool.html
|
||||
ipmi_bridging: <%= @ipmi_bridging %>
|
|
@ -61,6 +61,16 @@
|
|||
interval: 20
|
||||
timeout: 180
|
||||
|
||||
- id: ironic-conductor-config
|
||||
role: ['ironic']
|
||||
type: puppet
|
||||
required_for: [post_deployment_end]
|
||||
requires: [ironic-upload-images]
|
||||
parameters:
|
||||
puppet_manifest: puppet/manifests/ironic-conductor-config.pp
|
||||
puppet_modules: puppet/modules:/etc/puppet/modules
|
||||
timeout: 3600
|
||||
|
||||
- id: ironic-swift-key
|
||||
role: ['primary-controller']
|
||||
type: shell
|
||||
|
|
Loading…
Reference in New Issue