Merge "Upgrade Nova puppet module"

This commit is contained in:
Jenkins 2015-07-08 12:09:40 +00:00 committed by Gerrit Code Review
commit 63ee231dc7
149 changed files with 4814 additions and 6454 deletions

View File

@ -1,5 +0,0 @@
* 2012-06-12 0.1.1
- Fix dependency for automatic forge installation
* 2012-06-12 0.1.0
- Initial release

View File

@ -2,8 +2,23 @@ source 'https://rubygems.org'
group :development, :test do
gem 'puppetlabs_spec_helper', :require => false
gem 'puppet-lint', '~> 0.3.2'
gem 'rake', '10.1.1'
gem 'rspec-puppet', '~> 2.1.0', :require => false
gem 'metadata-json-lint'
gem 'puppet-lint-param-docs'
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 'json'
gem 'webmock'
end
if puppetversion = ENV['PUPPET_GEM_VERSION']

View File

@ -1,201 +1,13 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright 2012 OpenStack Foundation
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
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
1. Definitions.
http://www.apache.org/licenses/LICENSE-2.0
"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.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
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.

View File

@ -1,19 +0,0 @@
name 'puppetlabs-nova'
version '4.0.0'
source 'https://github.com/stackforge/puppet-nova'
author 'Puppet Labs'
license 'Apache License 2.0'
summary 'Puppet Labs Nova Module'
description 'Puppet module to install and configure the OpenStack Nova compute service'
project_page 'https://launchpad.net/puppet-nova'
## Add dependencies, if any:
dependency 'dprince/qpid', '>= 1.0.0 <2.0.0'
dependency 'duritong/sysctl', '>=0.0.1 <1.0.0'
dependency 'puppetlabs/cinder', '>=4.0.0 <5.0.0'
dependency 'puppetlabs/glance', '>=4.0.0 <5.0.0'
dependency 'puppetlabs/inifile', '>=1.0.0 <2.0.0'
dependency 'puppetlabs/keystone', '>=4.0.0 <5.0.0'
dependency 'puppetlabs/mysql', '>=0.9.0 <3.0.0'
dependency 'puppetlabs/rabbitmq', '>=2.0.2 <4.0.0'
dependency 'puppetlabs/stdlib', '>=3.2.0'

View File

@ -1,10 +0,0 @@
h1. Prerequisites
The openstack repo should be made available:
see: http://docs.openstack.org/cactus/openstack-compute/admin/content/installing-the-cloud-controller.html
This is currently known not to work on 2.6.4.
Master of this repo is now targetting the essex version of openstack.
For Diablo support, try the diablo branch of this repo

View File

@ -1,7 +1,7 @@
nova
====
4.0.0 - 2014.1.0 - Icehouse
5.1.0 - 2014.2 - Juno
#### Table of Contents
@ -39,7 +39,7 @@ Setup
### Beginning with nova
To utilize the nova module's functionality you will need to declare multiple resources. The following is a modified excerpt from the [openstack module](https://github.com/stackfoge/puppet-openstack). This is not an exhaustive list of all the components needed, we recommend you consult and understand the [openstack module](https://github.com/stackfoge/puppet-openstack) and the [core openstack](http://docs.openstack.org) documentation.
To utilize the nova module's functionality you will need to declare multiple resources. The following is a modified excerpt from the [openstack module](https://github.com/stackforge/puppet-openstack). This is not an exhaustive list of all the components needed, we recommend you consult and understand the [openstack module](https://github.com/stackforge/puppet-openstack) and the [core openstack](http://docs.openstack.org) documentation.
```puppet
class { 'nova':
@ -74,7 +74,6 @@ Limitations
* Supports libvirt, xenserver and vmware compute drivers.
* Tested on EL and Debian derivatives.
* The Nova Openstack service depends on a sqlalchemy database. If you are using puppetlabs-mysql to achieve this, there is a parameter called mysql_module that can be used to swap between the two supported versions: 0.9 and 2.2. This is needed because the puppetlabs-mysql module was rewritten and the custom type names have changed between versions.
Development
-----------
@ -83,6 +82,23 @@ Developer documentation for the entire puppet-openstack project.
* https://wiki.openstack.org/wiki/Puppet-openstack#Developer_documentation
Beaker-Rspec
------------
This module has beaker-rspec tests
To run the tests on the default vagrant node:
```shell
bundle install
bundle exec rspec spec/acceptance
```
For more information on writing and running beaker-rspec tests visit the documentation:
* https://github.com/puppetlabs/beaker/wiki/How-to-Write-a-Beaker-Test-for-a-Module
Contributors
------------
@ -91,6 +107,88 @@ Contributors
Release Notes
-------------
**5.1.0**
* move setting of novncproxy_base_url
* Added parameters for availability zones configuration
* crontab: ensure nova-common is installed before
* Correct docs on format for nova::policy data
* Allow libvirt secret key setting from param
* Fix behaviour of 'set-secret-value virsh' exec
* MySQL: change default MySQL collate to utf8_general_ci
* Pin puppetlabs-concat to 1.2.1 in fixtures
* Make group on /var/log/nova OS specific
* IPv6 support for migration check.
* Database: add slave_connection support
* Correct references to ::nova::rabbit_* variables
* Add optional network_api_class parameter to nova::network::neutron class
* Add Nova Aggregate support
* rpc_backend: simplify parameters
* supporting lxc cpu mode Fixing the default cpu_mode from None to none
* virsh returns a list of secret uuids, not keyring names
* Pin fixtures for stables branches
* Add serialproxy configuration
* Switch to TLSv1 as SSLv3 is considered insecure and is disabled by default
* Disable file injection when using RBD as compute ephemeral storage
* Add PCI Passthrough/SR-IOV support
* Add Ironic support into nova puppet modules
* spec: pin rspec-puppet to 1.0.1
* Correct section for cell_type nova.conf parameter
* crontab: ensure the script is run with shell
* Configure database parameters on the right nodes
**5.0.0**
* Stable Juno release
* Added tags to all nova packages
* Added parameter dhcp_domain to nova class
* Updated the [glance] and [neutron] section parameters for Juno
* Fixed potential duplicate declaration errors for sysctl::value in nova::network
* Fixed dependency cycle in nova::migration::libvirt
* Updated the libvirtd init script path for Debian
* Added parameters for nova service validation to nova::api
* Added nova::policy to control policy.json
* Fixed the rabbit_virtual_host default in nova::cells
* Bumped stdlib dependency to >=4.0.0
* Added force_raw_images parameter to nova::compute class
* Replaced usage of the keyword type with the string 'type' since type is a reserved keyword in puppet 3.7
* Added parameter ec2_workers to nova::api
* Fixed bug in usage of --vlan versus --vlan_start in nova_network provider
* Added parameter rabbit_ha_queues to nova class
* Added parameter pool to nova_floating type
* Added parameters to control whether to configure keystone users
* Added nova::cron::archive_deleted_rows class to create a crontab for archiving deleted database rows
* Changed the keystone_service to only be configured if the endpoint is to be configured
* Added parameter keystone_ec2_url to nova::api
* Added the ability to override the keystone service name in ceilometer::keystone::auth
* Removed dynamic scoping of File resources in nova class
* Add parameter workers to in nova::conductor and deprecate conductor_workers in nova::api
* Update nova quota parameters for Juno
* Migrated the ceilometer::db::mysql class to use openstacklib::db::mysql and deprecated the mysql_module parameter
* Removed deprecation notice for sectionless nova_config names
* Added parameter vnc_keymap in nova::compute
* Added parameter osapi_v3 to nova::api
**4.2.0**
* Added option to configure libvirt service name via class parameters
* Added support for multiple SSL APIs
* Added option to configure os_region_name in the nova config
* Corrected resource dependencies on the nova user
* Fixed os version fact comparison for RedHat-based operating systems
for specifying service provider
* Fixed ssl parameter requirements when using kombu and rabbit
* Added class for extended logging options
**4.1.0**
* Added API v3 endpoint support.
* Added configuration of rbd keyring name.
* Added support for run Nova SSL endpoints.
* Updated RabbitMQ dependency.
* Updated mysql charset to UTF8.
* Pinned major gems.
**4.0.0**
* Stable Icehouse release.
@ -162,7 +260,7 @@ Release Notes
**2.0.0**
* Upstream is now part of stackfoge.
* Upstream is now part of stackforge.
* The ini_file type is now used by nova_config.
* Support for nova-conductor added.
* Networks can now be labeled by Class['nova::manage::network'].

View File

@ -1,7 +1,7 @@
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-lint/tasks/puppet-lint'
PuppetLint.configuration.fail_on_warnings = false
PuppetLint.configuration.fail_on_warnings = true
PuppetLint.configuration.send('disable_80chars')
PuppetLint.configuration.send('disable_class_parameter_defaults')
PuppetLint.configuration.send('disable_class_inherits_from_params_class')

View File

@ -1 +0,0 @@
cert support has only been added for Redhat. Should this be added for Ubuntu?

View File

@ -25,30 +25,30 @@
# sudo pcs constraint colocation add nova_api_service with nova_vip
# sudo pcs constraint colocation add nova_novncproxy_service with nova_vip
class { 'nova': }
class { '::nova': }
class { 'nova::api':
enabled => false,
manage_service => false,
admin_password => 'PASSWORD',
class { '::nova::api':
enabled => false,
manage_service => false,
admin_password => 'PASSWORD',
}
class { 'nova::conductor':
class { '::nova::conductor':
enabled => false,
manage_service => false,
}
class { 'nova::consoleauth':
class { '::nova::consoleauth':
enabled => false,
manage_service => false,
}
class { 'nova::scheduler':
class { '::nova::scheduler':
enabled => false,
manage_service => false,
}
class { 'nova::vncproxy':
class { '::nova::vncproxy':
enabled => false,
manage_service => false,
}

View File

@ -1,30 +0,0 @@
#!/bin/bash
#
# assumes that resonable credentials have been stored at
# /root/auth
source /root/auth
# get an image to test with
#wget http://uec-images.ubuntu.com/releases/11.10/release/ubuntu-11.10-server-cloudimg-amd64-disk1.img
# import that image into glance
#glance add name="Ubuntu 11.10 cloudimg amd64" is_public=true container_format=ovf disk_format=qcow2 < ubuntu-11.10-server-cloudimg-amd64-disk1.img
#IMAGE_ID=`glance index | grep 'Ubuntu 11.10 cloudimg amd64' | head -1 | awk -F' ' '{print $1}'`
wget https://launchpad.net/cirros/trunk/0.3.0/+download/cirros-0.3.0-x86_64-disk.img
glance add name='cirros image' is_public=true container_format=bare disk_format=qcow2 < cirros-0.3.0-x86_64-disk.img
IMAGE_ID=`glance index | grep 'cirros image' | head -1 | awk -F' ' '{print $1}'`
# create a pub key
ssh-keygen -f /tmp/id_rsa -t rsa -N ''
nova keypair-add --pub_key /tmp/id_rsa.pub key1
nova boot --flavor 1 --image ${IMAGE_ID} --key_name key1 dans_vm
nova show dans_vm
# create ec2 credentials
keystone ec2-credentials-create

View File

@ -1,193 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 OpenStack, LLC.
# All Rights Reserved.
#
# 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.
from nova.rootwrap import filters
filterlist = [
# This line was patched by Puppet
filters.CommandFilter("/usr/bin/virsh", "root"),
# nova/virt/disk/mount.py: 'kpartx', '-a', device
# nova/virt/disk/mount.py: 'kpartx', '-d', device
filters.CommandFilter("/sbin/kpartx", "root"),
# nova/virt/disk/mount.py: 'tune2fs', '-c', 0, '-i', 0, mapped_device
# nova/virt/xenapi/vm_utils.py: "tune2fs", "-O ^has_journal", part_path
# nova/virt/xenapi/vm_utils.py: "tune2fs", "-j", partition_path
filters.CommandFilter("/sbin/tune2fs", "root"),
# nova/virt/disk/mount.py: 'mount', mapped_device, mount_dir
# nova/virt/xenapi/vm_utils.py: 'mount', '-t', 'ext2,ext3,ext4,reiserfs'..
filters.CommandFilter("/bin/mount", "root"),
# nova/virt/disk/mount.py: 'umount', mapped_device
# nova/virt/xenapi/vm_utils.py: 'umount', dev_path
filters.CommandFilter("/bin/umount", "root"),
# nova/virt/disk/nbd.py: 'qemu-nbd', '-c', device, image
# nova/virt/disk/nbd.py: 'qemu-nbd', '-d', device
filters.CommandFilter("/usr/bin/qemu-nbd", "root"),
# nova/virt/disk/loop.py: 'losetup', '--find', '--show', image
# nova/virt/disk/loop.py: 'losetup', '--detach', device
filters.CommandFilter("/sbin/losetup", "root"),
# nova/virt/disk/guestfs.py: 'guestmount', '--rw', '-a', image, '-i'
# nova/virt/disk/guestfs.py: 'guestmount', '--rw', '-a', image, '-m' dev
filters.CommandFilter("/usr/bin/guestmount", "root"),
# nova/virt/disk/guestfs.py: 'fusermount', 'u', mount_dir
filters.CommandFilter("/bin/fusermount", "root"),
filters.CommandFilter("/usr/bin/fusermount", "root"),
# nova/virt/disk/api.py: 'tee', metadata_path
# nova/virt/disk/api.py: 'tee', '-a', keyfile
# nova/virt/disk/api.py: 'tee', netfile
filters.CommandFilter("/usr/bin/tee", "root"),
# nova/virt/disk/api.py: 'mkdir', '-p', sshdir
# nova/virt/disk/api.py: 'mkdir', '-p', netdir
filters.CommandFilter("/bin/mkdir", "root"),
# nova/virt/disk/api.py: 'chown', 'root', sshdir
# nova/virt/disk/api.py: 'chown', 'root:root', netdir
# nova/virt/libvirt/connection.py: 'chown', os.getuid(), console_log
# nova/virt/libvirt/connection.py: 'chown', os.getuid(), console_log
# nova/virt/libvirt/connection.py: 'chown', 'root', basepath('disk')
# nova/utils.py: 'chown', owner_uid, path
filters.CommandFilter("/bin/chown", "root"),
# nova/virt/disk/api.py: 'chmod', '700', sshdir
# nova/virt/disk/api.py: 'chmod', 755, netdir
filters.CommandFilter("/bin/chmod", "root"),
# nova/virt/disk/api.py: 'cp', os.path.join(fs...
filters.CommandFilter("/bin/cp", "root"),
# nova/virt/libvirt/vif.py: 'ip', 'tuntap', 'add', dev, 'mode', 'tap'
# nova/virt/libvirt/vif.py: 'ip', 'link', 'set', dev, 'up'
# nova/virt/libvirt/vif.py: 'ip', 'link', 'delete', dev
# nova/network/linux_net.py: 'ip', 'addr', 'add', str(floating_ip)+'/32'i..
# nova/network/linux_net.py: 'ip', 'addr', 'del', str(floating_ip)+'/32'..
# nova/network/linux_net.py: 'ip', 'addr', 'add', '169.254.169.254/32',..
# nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', dev, 'scope',..
# nova/network/linux_net.py: 'ip', 'addr', 'del/add', ip_params, dev)
# nova/network/linux_net.py: 'ip', 'addr', 'del', params, fields[-1]
# nova/network/linux_net.py: 'ip', 'addr', 'add', params, bridge
# nova/network/linux_net.py: 'ip', '-f', 'inet6', 'addr', 'change', ..
# nova/network/linux_net.py: 'ip', 'link', 'set', 'dev', dev, 'promisc',..
# nova/network/linux_net.py: 'ip', 'link', 'add', 'link', bridge_if ...
# nova/network/linux_net.py: 'ip', 'link', 'set', interface, "address",..
# nova/network/linux_net.py: 'ip', 'link', 'set', interface, 'up'
# nova/network/linux_net.py: 'ip', 'link', 'set', bridge, 'up'
# nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', interface, ..
# nova/network/linux_net.py: 'ip', 'link', 'set', dev, "address", ..
# nova/network/linux_net.py: 'ip', 'link', 'set', dev, 'up'
filters.CommandFilter("/sbin/ip", "root"),
# nova/virt/libvirt/vif.py: 'tunctl', '-b', '-t', dev
# nova/network/linux_net.py: 'tunctl', '-b', '-t', dev
filters.CommandFilter("/usr/sbin/tunctl", "root"),
# nova/virt/libvirt/vif.py: 'ovs-vsctl', ...
# nova/virt/libvirt/vif.py: 'ovs-vsctl', 'del-port', ...
# nova/network/linux_net.py: 'ovs-vsctl', ....
filters.CommandFilter("/usr/bin/ovs-vsctl", "root"),
# nova/network/linux_net.py: 'ovs-ofctl', ....
filters.CommandFilter("/usr/bin/ovs-ofctl", "root"),
# nova/virt/libvirt/connection.py: 'dd', "if=%s" % virsh_output, ...
filters.CommandFilter("/bin/dd", "root"),
# nova/virt/xenapi/volume_utils.py: 'iscsiadm', '-m', ...
filters.CommandFilter("/sbin/iscsiadm", "root"),
# nova/virt/xenapi/vm_utils.py: "parted", "--script", ...
# nova/virt/xenapi/vm_utils.py: 'parted', '--script', dev_path, ..*.
filters.CommandFilter("/sbin/parted", "root"),
# nova/virt/xenapi/vm_utils.py: fdisk %(dev_path)s
filters.CommandFilter("/sbin/fdisk", "root"),
# nova/virt/xenapi/vm_utils.py: "e2fsck", "-f", "-p", partition_path
filters.CommandFilter("/sbin/e2fsck", "root"),
# nova/virt/xenapi/vm_utils.py: "resize2fs", partition_path
filters.CommandFilter("/sbin/resize2fs", "root"),
# nova/network/linux_net.py: 'ip[6]tables-save' % (cmd,), '-t', ...
filters.CommandFilter("/sbin/iptables-save", "root"),
filters.CommandFilter("/sbin/ip6tables-save", "root"),
# nova/network/linux_net.py: 'ip[6]tables-restore' % (cmd,)
filters.CommandFilter("/sbin/iptables-restore", "root"),
filters.CommandFilter("/sbin/ip6tables-restore", "root"),
# nova/network/linux_net.py: 'arping', '-U', floating_ip, '-A', '-I', ...
# nova/network/linux_net.py: 'arping', '-U', network_ref['dhcp_server'],..
filters.CommandFilter("/usr/bin/arping", "root"),
# nova/network/linux_net.py: 'route', '-n'
# nova/network/linux_net.py: 'route', 'del', 'default', 'gw'
# nova/network/linux_net.py: 'route', 'add', 'default', 'gw'
# nova/network/linux_net.py: 'route', '-n'
# nova/network/linux_net.py: 'route', 'del', 'default', 'gw', old_gw, ..
# nova/network/linux_net.py: 'route', 'add', 'default', 'gw', old_gateway
filters.CommandFilter("/sbin/route", "root"),
# nova/network/linux_net.py: 'dhcp_release', dev, address, mac_address
filters.CommandFilter("/usr/bin/dhcp_release", "root"),
# nova/network/linux_net.py: 'kill', '-9', pid
# nova/network/linux_net.py: 'kill', '-HUP', pid
filters.KillFilter("/bin/kill", "root",
['-9', '-HUP'], ['/usr/sbin/dnsmasq']),
# nova/network/linux_net.py: 'kill', pid
filters.KillFilter("/bin/kill", "root", [''], ['/usr/sbin/radvd']),
# nova/network/linux_net.py: dnsmasq call
filters.DnsmasqFilter("/usr/sbin/dnsmasq", "root"),
# nova/network/linux_net.py: 'radvd', '-C', '%s' % _ra_file(dev, 'conf'),..
filters.CommandFilter("/usr/sbin/radvd", "root"),
# nova/network/linux_net.py: 'brctl', 'addbr', bridge
# nova/network/linux_net.py: 'brctl', 'setfd', bridge, 0
# nova/network/linux_net.py: 'brctl', 'stp', bridge, 'off'
# nova/network/linux_net.py: 'brctl', 'addif', bridge, interface
filters.CommandFilter("/sbin/brctl", "root"),
filters.CommandFilter("/usr/sbin/brctl", "root"),
# nova/virt/libvirt/utils.py: 'mkswap'
# nova/virt/xenapi/vm_utils.py: 'mkswap'
filters.CommandFilter("/sbin/mkswap", "root"),
# nova/virt/xenapi/vm_utils.py: 'mkfs'
filters.CommandFilter("/sbin/mkfs", "root"),
# nova/virt/libvirt/utils.py: 'qemu-img'
filters.CommandFilter("/usr/bin/qemu-img", "root"),
# nova/virt/disk/api.py: 'touch', target
filters.CommandFilter("/usr/bin/touch", "root"),
# nova/virt/libvirt/connection.py:
filters.ReadFileFilter("/etc/iscsi/initiatorname.iscsi"),
]

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
--- a/manager.py 2012-10-31 14:09:36.153257689 +0400
+++ b/manager.py 2012-10-31 14:10:01.261260402 +0400
@@ -65,11 +65,11 @@
'internal_access_path': internal_access_path,
'last_activity_at': time.time()}
data = jsonutils.dumps(token_dict)
- self.mc.set(token, data, FLAGS.console_token_ttl)
+ self.mc.set(token.encode('UTF-8'), data, FLAGS.console_token_ttl)
LOG.audit(_("Received Token: %(token)s, %(token_dict)s)"), locals())
def check_token(self, context, token):
- token_str = self.mc.get(token)
+ token_str = self.mc.get(token.encode('UTF-8'))
token_valid = (token_str is not None)
LOG.audit(_("Checking Token: %(token)s, %(token_valid)s)"), locals())
if token_valid:

View File

@ -1 +0,0 @@
libguestfs0 libguestfs/update-appliance boolean true

View File

@ -1,35 +0,0 @@
# Master configuration file for the QEMU driver.
# All settings described here are optional - if omitted, sensible
# defaults are used.
# The user ID for QEMU processes run by the system instance.
user = "root"
# The group ID for QEMU processes run by the system instance.
group = "root"
# This is the basic set of devices allowed / required by
# all virtual machines.
#
# As well as this, any configured block backed disks,
# all sound device, and all PTY devices are allowed.
#
# This will only need setting if newer QEMU suddenly
# wants some device we don't already know about.
#
cgroup_device_acl = [
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
"/dev/rtc", "/dev/hpet", '/dev/net/tun',
]
# If clear_emulator_capabilities is enabled, libvirt will drop all
# privileged capabilities of the QEmu/KVM emulator. This is enabled by
# default.
#
# Warning: Disabling this option means that a compromised guest can
# exploit the privileges and possibly do damage to the host.
#
clear_emulator_capabilities = 0

View File

@ -1,254 +0,0 @@
commit 0b5a6543d1a7bcac03565abcde2e3888df55084d
Author: Devananda van der Veen <devananda.vdv@gmail.com>
Date: Wed Jul 18 18:47:25 2012 -0700
Catch database-has-gone-away errors and retry
Wrap certain session and query methods, and catch exceptions caused by a
failed or broken database connection. When caught, retry the last query
in a loop until it succeeds, or until we time out. The time out is
configurable with min, max, and increment options. The current defaults
will result in 20 retries spread over 155 seconds.
As a result of better disconnect error handling, we can remove the
ping_listener() which generated spurious "SELECT 1" queries.
However, we can not yet disable pool_reset_on_return; doing so would
cause dangling transactions and lead to random failures between threads
viewing old versions of the data.
Fixes bug 1007027.
Change-Id: If4b20ab75ef712314327a6c8e167a28d89657091
diff --git a/db/sqlalchemy/session.py b/db/sqlalchemy/session.py
index 6e754be..d5f7330 100644
--- a/db/sqlalchemy/session.py
+++ b/db/sqlalchemy/session.py
@@ -21,12 +21,16 @@
import re
import time
-from sqlalchemy.exc import DisconnectionError, OperationalError
+from sqlalchemy.exc import DisconnectionError
+from sqlalchemy.exc import OperationalError
import sqlalchemy.interfaces
import sqlalchemy.orm
-from sqlalchemy.pool import NullPool, StaticPool
+from sqlalchemy.pool import NullPool
+from sqlalchemy.pool import StaticPool
import nova.exception
+from nova.exception import DBError
+from nova.exception import InvalidUnicodeParameter
import nova.flags as flags
import nova.openstack.common.log as logging
@@ -47,8 +51,10 @@ def get_session(autocommit=True, expire_on_commit=False):
_MAKER = get_maker(engine, autocommit, expire_on_commit)
session = _MAKER()
- session.query = nova.exception.wrap_db_error(session.query)
- session.flush = nova.exception.wrap_db_error(session.flush)
+ session.begin = wrap_db_error(session.begin)
+ session.execute = wrap_db_error(session.execute)
+ session.flush = wrap_db_error(session.flush)
+ session.query = wrap_db_error(session.query)
return session
@@ -66,24 +72,6 @@ def add_regexp_listener(dbapi_con, con_record):
dbapi_con.create_function('regexp', 2, regexp)
-def ping_listener(dbapi_conn, connection_rec, connection_proxy):
- """
- Ensures that MySQL connections checked out of the
- pool are alive.
-
- Borrowed from:
- http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f
- """
- try:
- dbapi_conn.cursor().execute('select 1')
- except dbapi_conn.OperationalError, ex:
- if ex.args[0] in (2006, 2013, 2014, 2045, 2055):
- LOG.warn('Got mysql server has gone away: %s', ex)
- raise DisconnectionError("Database server went away")
- else:
- raise
-
-
def is_db_connection_error(args):
"""Return True if error in connecting to db."""
# NOTE(adam_g): This is currently MySQL specific and needs to be extended
@@ -95,6 +83,51 @@ def is_db_connection_error(args):
return False
+def wrap_db_error(f):
+ """Function wrapper to capture DB errors
+
+ If an exception is thrown by the wrapped function,
+ determine if it represents a database connection error.
+ If so, retry the wrapped function, and repeat until it succeeds
+ or we reach a configurable maximum number of retries.
+ If it is not a connection error, or we exceeded the retry limit,
+ raise a DBError.
+
+ """
+ def _wrap_db_error(*args, **kwargs):
+ next_interval = FLAGS.sql_retry_interval
+ remaining = FLAGS.sql_max_retries
+ if remaining == -1:
+ remaining = 'infinite'
+ while True:
+ try:
+ return f(*args, **kwargs)
+ except UnicodeEncodeError:
+ raise InvalidUnicodeParameter()
+ except OperationalError, e:
+ if is_db_connection_error(e.args[0]):
+ if remaining == 0:
+ LOG.exception(_('DB exceeded retry limit.'))
+ raise DBError(e)
+ if remaining != 'infinite':
+ remaining -= 1
+ LOG.exception(_('DB connection error, '
+ 'retrying in %i seconds.') % next_interval)
+ time.sleep(next_interval)
+ if FLAGS.sql_inc_retry_interval:
+ next_interval = min(next_interval * 2,
+ FLAGS.sql_max_retry_interval)
+ else:
+ LOG.exception(_('DB exception wrapped.'))
+ raise DBError(e)
+ except Exception, e:
+ LOG.exception(_('DB exception wrapped.'))
+ raise DBError(e)
+
+ _wrap_db_error.func_name = f.func_name
+ return _wrap_db_error
+
+
def get_engine():
"""Return a SQLAlchemy engine."""
global _ENGINE
@@ -122,9 +155,7 @@ def get_engine():
_ENGINE = sqlalchemy.create_engine(FLAGS.sql_connection, **engine_args)
- if 'mysql' in connection_dict.drivername:
- sqlalchemy.event.listen(_ENGINE, 'checkout', ping_listener)
- elif "sqlite" in connection_dict.drivername:
+ if "sqlite" in connection_dict.drivername:
if not FLAGS.sqlite_synchronous:
sqlalchemy.event.listen(_ENGINE, 'connect',
synchronous_switch_listener)
@@ -142,6 +173,7 @@ def get_engine():
if not is_db_connection_error(e.args[0]):
raise
+ next_interval = FLAGS.sql_retry_interval
remaining = FLAGS.sql_max_retries
if remaining == -1:
remaining = 'infinite'
@@ -150,7 +182,7 @@ def get_engine():
LOG.warn(msg % remaining)
if remaining != 'infinite':
remaining -= 1
- time.sleep(FLAGS.sql_retry_interval)
+ time.sleep(next_interval)
try:
_ENGINE.connect()
break
@@ -158,14 +190,22 @@ def get_engine():
if (remaining != 'infinite' and remaining == 0) or \
not is_db_connection_error(e.args[0]):
raise
+ if FLAGS.sql_inc_retry_interval:
+ next_interval = min(next_interval * 2,
+ FLAGS.sql_max_retry_interval)
+
return _ENGINE
def get_maker(engine, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy sessionmaker using the given engine."""
+ query = sqlalchemy.orm.query.Query
+ query.all = wrap_db_error(query.all)
+ query.first = wrap_db_error(query.first)
return sqlalchemy.orm.sessionmaker(bind=engine,
autocommit=autocommit,
- expire_on_commit=expire_on_commit)
+ expire_on_commit=expire_on_commit,
+ query_cls=query)
def debug_mysql_do_query():
@@ -185,7 +225,7 @@ def debug_mysql_do_query():
continue
if file.endswith('utils.py') and method == '_inner':
continue
- if file.endswith('exception.py') and method == '_wrap':
+ if file.endswith('session.py') and method == '_wrap_db_error':
continue
# nova/db/api is just a wrapper around nova/db/sqlalchemy/api
if file.endswith('nova/db/api.py'):
diff --git a/exception.py b/exception.py
index c9f339e..7ec7a9e 100644
--- a/exception.py
+++ b/exception.py
@@ -62,19 +62,6 @@ class ProcessExecutionError(IOError):
IOError.__init__(self, message)
-def wrap_db_error(f):
- def _wrap(*args, **kwargs):
- try:
- return f(*args, **kwargs)
- except UnicodeEncodeError:
- raise InvalidUnicodeParameter()
- except Exception, e:
- LOG.exception(_('DB exception wrapped.'))
- raise DBError(e)
- _wrap.func_name = f.func_name
- return _wrap
-
-
def wrap_exception(notifier=None, publisher_id=None, event_type=None,
level=None):
"""This decorator wraps a method to catch any exceptions that may
diff --git a/flags.py b/flags.py
index 76766b7..40f83b5 100644
--- a/flags.py
+++ b/flags.py
@@ -258,15 +258,23 @@ global_opts = [
default=True,
help='If passed, use synchronous mode for sqlite'),
cfg.IntOpt('sql_idle_timeout',
- default=3600,
- help='timeout before idle sql connections are reaped'),
+ default=30,
+ help='seconds before idle sql connections are reaped'),
cfg.IntOpt('sql_max_retries',
- default=10,
- help='maximum db connection retries during startup. '
+ default=20,
+ help='maximum sql connection retries before error is raised. '
'(setting -1 implies an infinite retry count)'),
cfg.IntOpt('sql_retry_interval',
+ default=1,
+ help='seconds between sql connection retries'),
+ cfg.BoolOpt('sql_inc_retry_interval',
+ default=True,
+ help='Whether to increase interval between sql connection '
+ 'retries, up to sql_max_retry_interval'),
+ cfg.IntOpt('sql_max_retry_interval',
default=10,
- help='interval between retries of opening a sql connection'),
+ help='max seconds between sql connection retries, if '
+ 'sql_inc_retry_interval is enabled'),
cfg.StrOpt('compute_manager',
default='nova.compute.manager.ComputeManager',
help='full class name for the Manager for compute'),

View File

@ -1,85 +0,0 @@
#!/bin/bash -e
# upstart-job
#
# Symlink target for initscripts that have been converted to Upstart.
set -e
INITSCRIPT="$(basename "$0")"
JOB="${INITSCRIPT%.sh}"
if [ "$JOB" = "upstart-job" ]; then
if [ -z "$1" ]; then
echo "Usage: upstart-job JOB COMMAND" 1>&2
exit 1
fi
JOB="$1"
INITSCRIPT="$1"
shift
else
if [ -z "$1" ]; then
echo "Usage: $0 COMMAND" 1>&2
exit 1
fi
fi
COMMAND="$1"
shift
if [ -z "$DPKG_MAINTSCRIPT_PACKAGE" ]; then
ECHO=echo
else
ECHO=:
fi
$ECHO "Rather than invoking init scripts through /etc/init.d, use the service(8)"
$ECHO "utility, e.g. service $INITSCRIPT $COMMAND"
case $COMMAND in
status)
$ECHO
$ECHO "Since the script you are attempting to invoke has been converted to an"
$ECHO "Upstart job, you may also use the $COMMAND(8) utility, e.g. $COMMAND $JOB"
$COMMAND "$JOB"
;;
start|stop)
$ECHO
$ECHO "Since the script you are attempting to invoke has been converted to an"
$ECHO "Upstart job, you may also use the $COMMAND(8) utility, e.g. $COMMAND $JOB"
if status "$JOB" 2>/dev/null | grep -q ' start/'; then
RUNNING=1
fi
if [ -z "$RUNNING" ] && [ "$COMMAND" = "stop" ]; then
exit 0
elif [ -n "$RUNNING" ] && [ "$COMMAND" = "start" ]; then
exit 0
fi
$COMMAND "$JOB"
;;
restart)
$ECHO
$ECHO "Since the script you are attempting to invoke has been converted to an"
$ECHO "Upstart job, you may also use the stop(8) and then start(8) utilities,"
$ECHO "e.g. stop $JOB ; start $JOB. The restart(8) utility is also available."
if status "$JOB" 2>/dev/null | grep -q ' start/'; then
RUNNING=1
fi
if [ -n "$RUNNING" ] ; then
stop "$JOB"
fi
start "$JOB"
;;
reload|force-reload)
$ECHO
$ECHO "Since the script you are attempting to invoke has been converted to an"
$ECHO "Upstart job, you may also use the reload(8) utility, e.g. reload $JOB"
reload "$JOB"
;;
*)
$ECHO
$ECHO "The script you are attempting to invoke has been converted to an Upstart" 1>&2
$ECHO "job, but $COMMAND is not supported for Upstart jobs." 1>&2
exit 1
esac

View File

@ -1,136 +0,0 @@
--- a/openstack/common/rpc/impl_qpid.py
+++ a/openstack/common/rpc/impl_qpid.py
@@ -41,6 +41,9 @@
cfg.StrOpt('qpid_port',
default='5672',
help='Qpid broker port'),
+ cfg.ListOpt('qpid_hosts',
+ default=['$qpid_hostname:$qpid_port'],
+ help='Qpid HA cluster host:port pairs'),
cfg.StrOpt('qpid_username',
default='',
help='Username for qpid connection'),
@@ -50,24 +53,6 @@
cfg.StrOpt('qpid_sasl_mechanisms',
default='',
help='Space separated list of SASL mechanisms to use for auth'),
- cfg.BoolOpt('qpid_reconnect',
- default=True,
- help='Automatically reconnect'),
- cfg.IntOpt('qpid_reconnect_timeout',
- default=0,
- help='Reconnection timeout in seconds'),
- cfg.IntOpt('qpid_reconnect_limit',
- default=0,
- help='Max reconnections before giving up'),
- cfg.IntOpt('qpid_reconnect_interval_min',
- default=0,
- help='Minimum seconds between reconnection attempts'),
- cfg.IntOpt('qpid_reconnect_interval_max',
- default=0,
- help='Maximum seconds between reconnection attempts'),
- cfg.IntOpt('qpid_reconnect_interval',
- default=0,
- help='Equivalent to setting max and min to the same value'),
cfg.IntOpt('qpid_heartbeat',
default=60,
help='Seconds between connection keepalive heartbeats'),
@@ -296,47 +281,32 @@
if server_params is None:
server_params = {}
- default_params = dict(hostname=self.conf.qpid_hostname,
- port=self.conf.qpid_port,
+ default_params = dict(hosts=self.conf.qpid_hosts,
username=self.conf.qpid_username,
password=self.conf.qpid_password)
- params = server_params
+ self.params = server_params
for key in default_params.keys():
- params.setdefault(key, default_params[key])
+ self.params.setdefault(key, default_params[key])
- self.broker = params['hostname'] + ":" + str(params['port'])
+ self.brokers = self.params['hosts']
+ self.create_connection(self.brokers[0])
+ self.reconnect()
+
+ def create_connection(self, broker):
# Create the connection - this does not open the connection
- self.connection = qpid.messaging.Connection(self.broker)
+ self.connection = qpid.messaging.Connection(broker)
# Check if flags are set and if so set them for the connection
# before we call open
- self.connection.username = params['username']
- self.connection.password = params['password']
+ self.connection.username = self.params['username']
+ self.connection.password = self.params['password']
+ self.connection.reconnect = False
self.connection.sasl_mechanisms = self.conf.qpid_sasl_mechanisms
- self.connection.reconnect = self.conf.qpid_reconnect
- if self.conf.qpid_reconnect_timeout:
- self.connection.reconnect_timeout = (
- self.conf.qpid_reconnect_timeout)
- if self.conf.qpid_reconnect_limit:
- self.connection.reconnect_limit = self.conf.qpid_reconnect_limit
- if self.conf.qpid_reconnect_interval_max:
- self.connection.reconnect_interval_max = (
- self.conf.qpid_reconnect_interval_max)
- if self.conf.qpid_reconnect_interval_min:
- self.connection.reconnect_interval_min = (
- self.conf.qpid_reconnect_interval_min)
- if self.conf.qpid_reconnect_interval:
- self.connection.reconnect_interval = (
- self.conf.qpid_reconnect_interval)
self.connection.heartbeat = self.conf.qpid_heartbeat
self.connection.protocol = self.conf.qpid_protocol
self.connection.tcp_nodelay = self.conf.qpid_tcp_nodelay
- # Open is part of reconnect -
- # NOTE(WGH) not sure we need this with the reconnect flags
- self.reconnect()
-
def _register_consumer(self, consumer):
self.consumers[str(consumer.get_receiver())] = consumer
@@ -351,23 +321,32 @@
except qpid.messaging.exceptions.ConnectionError:
pass
+ delay = 1
+ attempt = 0
while True:
+ broker = self.brokers[attempt % len(self.brokers)]
+ attempt += 1
try:
+ self.create_connection(broker)
self.connection.open()
except qpid.messaging.exceptions.ConnectionError, e:
- LOG.error(_('Unable to connect to AMQP server: %s'), e)
- time.sleep(self.conf.qpid_reconnect_interval or 1)
+ LOG.error(_('Unable to connect to AMQP server %s: %s'), broker, e)
+ time.sleep(delay)
+ delay = min(2*delay, 60)
else:
break
- LOG.info(_('Connected to AMQP server on %s'), self.broker)
+ LOG.info(_('Connected to AMQP server on %s'), broker)
self.session = self.connection.session()
- for consumer in self.consumers.itervalues():
- consumer.reconnect(self.session)
-
if self.consumers:
+ consumers = self.consumers
+ self.consumers = {}
+ for consumer in consumers.itervalues():
+ consumer.reconnect(self.session)
+ self._register_consumer(consumer)
+
LOG.debug(_("Re-established AMQP queues"))
def ensure(self, error_callback, method, *args, **kwargs):

View File

@ -1,381 +0,0 @@
From 32aae43c94d692d02324c1a299996e5f979f9613 Mon Sep 17 00:00:00 2001
From: Eugene Kirpichov <ekirpichov@gmail.com>
Date: Tue, 30 Oct 2012 11:30:59 +0000
Subject: [PATCH] Support for several HA RabbitMQ servers.
Backport from https://review.openstack.org/#/c/13665/
Change-Id: Ib44abf115b42c3df42771344f6722ce1db043bbd
---
openstack/common/network_utils.py | 68 ++++++++++++++++++
openstack/common/rpc/impl_kombu.py | 120 +++++++++++++++++++++----------
openstack-common.conf | 2 +-
3 files changed, 150 insertions(+), 40 deletions(-)
create mode 100644 openstack/common/network_utils.py
diff --git a/openstack/common/network_utils.py b/openstack/common/network_utils.py
new file mode 100644
index 0000000..69f6732
--- /dev/null
+++ b/openstack/common/network_utils.py
@@ -0,0 +1,68 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack LLC.
+# All Rights Reserved.
+#
+# 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.
+
+"""
+Network-related utilities and helper functions.
+"""
+
+import logging
+
+LOG = logging.getLogger(__name__)
+
+
+def parse_host_port(address, default_port=None):
+ """
+ Interpret a string as a host:port pair.
+ An IPv6 address MUST be escaped if accompanied by a port,
+ because otherwise ambiguity ensues: 2001:db8:85a3::8a2e:370:7334
+ means both [2001:db8:85a3::8a2e:370:7334] and
+ [2001:db8:85a3::8a2e:370]:7334.
+
+ >>> parse_host_port('server01:80')
+ ('server01', 80)
+ >>> parse_host_port('server01')
+ ('server01', None)
+ >>> parse_host_port('server01', default_port=1234)
+ ('server01', 1234)
+ >>> parse_host_port('[::1]:80')
+ ('::1', 80)
+ >>> parse_host_port('[::1]')
+ ('::1', None)
+ >>> parse_host_port('[::1]', default_port=1234)
+ ('::1', 1234)
+ >>> parse_host_port('2001:db8:85a3::8a2e:370:7334', default_port=1234)
+ ('2001:db8:85a3::8a2e:370:7334', 1234)
+
+ """
+ if address[0] == '[':
+ # Escaped ipv6
+ _host, _port = address[1:].split(']')
+ host = _host
+ if ':' in _port:
+ port = _port.split(':')[1]
+ else:
+ port = default_port
+ else:
+ if address.count(':') == 1:
+ host, port = address.split(':')
+ else:
+ # 0 means ipv4, >1 means ipv6.
+ # We prohibit unescaped ipv6 addresses with port.
+ host = address
+ port = default_port
+
+ return (host, None if port is None else int(port))
diff --git a/openstack/common/rpc/impl_kombu.py b/openstack/common/rpc/impl_kombu.py
index fff1ed9..3469a9b 100644
--- a/openstack/common/rpc/impl_kombu.py
+++ b/openstack/common/rpc/impl_kombu.py
@@ -33,6 +33,7 @@ from nova.openstack.common import cfg
from nova.openstack.common.gettextutils import _
from nova.openstack.common.rpc import amqp as rpc_amqp
from nova.openstack.common.rpc import common as rpc_common
+from nova.openstack.common import network_utils
kombu_opts = [
cfg.StrOpt('kombu_ssl_version',
@@ -50,10 +51,13 @@ kombu_opts = [
'(valid only if SSL enabled)')),
cfg.StrOpt('rabbit_host',
default='localhost',
- help='the RabbitMQ host'),
+ help='The RabbitMQ broker address where a single node is used'),
cfg.IntOpt('rabbit_port',
default=5672,
- help='the RabbitMQ port'),
+ help='The RabbitMQ broker port where a single node is used'),
+ cfg.ListOpt('rabbit_hosts',
+ default=['$rabbit_host:$rabbit_port'],
+ help='RabbitMQ HA cluster host:port pairs'),
cfg.BoolOpt('rabbit_use_ssl',
default=False,
help='connect over SSL for RabbitMQ'),
@@ -80,6 +84,11 @@ kombu_opts = [
cfg.BoolOpt('rabbit_durable_queues',
default=False,
help='use durable queues in RabbitMQ'),
+ cfg.BoolOpt('rabbit_ha_queues',
+ default=False,
+ help='use H/A queues in RabbitMQ (x-ha-policy: all).'
+ 'You need to wipe RabbitMQ database when '
+ 'changing this option.'),
]
@@ -88,6 +97,20 @@ cfg.CONF.register_opts(kombu_opts)
LOG = rpc_common.LOG
+def _get_queue_arguments(conf):
+ """Construct the arguments for declaring a queue.
+
+ If the rabbit_ha_queues option is set, we declare a mirrored queue
+ as described here:
+
+ http://www.rabbitmq.com/ha.html
+
+ Setting x-ha-policy to all means that the queue will be mirrored
+ to all nodes in the cluster.
+ """
+ return {'x-ha-policy': 'all'} if conf.rabbit_ha_queues else {}
+
+
class ConsumerBase(object):
"""Consumer base class."""
@@ -172,6 +195,7 @@ class DirectConsumer(ConsumerBase):
"""
# Default options
options = {'durable': False,
+ 'queue_arguments': _get_queue_arguments(conf),
'auto_delete': True,
'exclusive': True}
options.update(kwargs)
@@ -207,6 +231,7 @@ class TopicConsumer(ConsumerBase):
"""
# Default options
options = {'durable': conf.rabbit_durable_queues,
+ 'queue_arguments': _get_queue_arguments(conf),
'auto_delete': False,
'exclusive': False}
options.update(kwargs)
@@ -242,6 +267,7 @@ class FanoutConsumer(ConsumerBase):
# Default options
options = {'durable': False,
+ 'queue_arguments': _get_queue_arguments(conf),
'auto_delete': True,
'exclusive': True}
options.update(kwargs)
@@ -289,6 +315,7 @@ class DirectPublisher(Publisher):
"""
options = {'durable': False,
+ 'queue_arguments': _get_queue_arguments(conf),
'auto_delete': True,
'exclusive': True}
options.update(kwargs)
@@ -304,6 +331,7 @@ class TopicPublisher(Publisher):
Kombu options may be passed as keyword args to override defaults
"""
options = {'durable': conf.rabbit_durable_queues,
+ 'queue_arguments': _get_queue_arguments(conf),
'auto_delete': False,
'exclusive': False}
options.update(kwargs)
@@ -319,6 +347,7 @@ class FanoutPublisher(Publisher):
Kombu options may be passed as keyword args to override defaults
"""
options = {'durable': False,
+ 'queue_arguments': _get_queue_arguments(conf),
'auto_delete': True,
'exclusive': True}
options.update(kwargs)
@@ -331,6 +360,7 @@ class NotifyPublisher(TopicPublisher):
def __init__(self, conf, channel, topic, **kwargs):
self.durable = kwargs.pop('durable', conf.rabbit_durable_queues)
+ self.queue_arguments = _get_queue_arguments(conf)
super(NotifyPublisher, self).__init__(conf, channel, topic, **kwargs)
def reconnect(self, channel):
@@ -343,7 +373,8 @@ class NotifyPublisher(TopicPublisher):
exchange=self.exchange,
durable=self.durable,
name=self.routing_key,
- routing_key=self.routing_key)
+ routing_key=self.routing_key,
+ queue_arguments=self.queue_arguments)
queue.declare()
@@ -368,31 +399,39 @@ class Connection(object):
if server_params is None:
server_params = {}
-
# Keys to translate from server_params to kombu params
server_params_to_kombu_params = {'username': 'userid'}
- params = {}
- for sp_key, value in server_params.iteritems():
- p_key = server_params_to_kombu_params.get(sp_key, sp_key)
- params[p_key] = value
+ ssl_params = self._fetch_ssl_params()
+ params_list = []
+ for adr in self.conf.rabbit_hosts:
+ hostname, port = network_utils.parse_host_port(
+ adr, default_port=self.conf.rabbit_port)
- params.setdefault('hostname', self.conf.rabbit_host)
- params.setdefault('port', self.conf.rabbit_port)
- params.setdefault('userid', self.conf.rabbit_userid)
- params.setdefault('password', self.conf.rabbit_password)
- params.setdefault('virtual_host', self.conf.rabbit_virtual_host)
+ params = {}
- self.params = params
+ for sp_key, value in server_params.iteritems():
+ p_key = server_params_to_kombu_params.get(sp_key, sp_key)
+ params[p_key] = value
- if self.conf.fake_rabbit:
- self.params['transport'] = 'memory'
- self.memory_transport = True
- else:
- self.memory_transport = False
+ params.setdefault('hostname', hostname)
+ params.setdefault('port', port)
+ params.setdefault('userid', self.conf.rabbit_userid)
+ params.setdefault('password', self.conf.rabbit_password)
+ params.setdefault('virtual_host', self.conf.rabbit_virtual_host)
+
+ if self.conf.fake_rabbit:
+ params['transport'] = 'memory'
+ else:
+ params['transport'] = 'pyamqp'
+ if self.conf.rabbit_use_ssl:
+ params['ssl'] = ssl_params
- if self.conf.rabbit_use_ssl:
- self.params['ssl'] = self._fetch_ssl_params()
+ params_list.append(params)
+
+ self.params_list = params_list
+
+ self.memory_transport = self.conf.fake_rabbit
self.connection = None
self.reconnect()
@@ -422,23 +461,24 @@ class Connection(object):
# Return the extended behavior
return ssl_params
- def _connect(self):
+ def _connect(self, params):
"""Connect to rabbit. Re-establish any queues that may have
been declared before if we are reconnecting. Exceptions should
be handled by the caller.
"""
if self.connection:
LOG.info(_("Reconnecting to AMQP server on "
- "%(hostname)s:%(port)d") % self.params)
+ "%(hostname)s:%(port)d") % params)
try:
self.connection.close()
- except self.connection_errors:
+ except (self.connection_errors, self.channel_errors):
pass
# Setting this in case the next statement fails, though
# it shouldn't be doing any network operations, yet.
self.connection = None
- self.connection = kombu.connection.BrokerConnection(**self.params)
+ self.connection = kombu.connection.BrokerConnection(**params)
self.connection_errors = self.connection.connection_errors
+ self.channel_errors = self.connection.channel_errors
if self.memory_transport:
# Kludge to speed up tests.
self.connection.transport.polling_interval = 0.0
@@ -450,8 +490,8 @@ class Connection(object):
self.channel._new_queue('ae.undeliver')
for consumer in self.consumers:
consumer.reconnect(self.channel)
- LOG.info(_('Connected to AMQP server on %(hostname)s:%(port)d'),
- self.params)
+ LOG.info(_('Connected to AMQP server on %(hostname)s:%(port)d') %
+ params)
def reconnect(self):
"""Handles reconnecting and re-establishing queues.
@@ -464,11 +504,12 @@ class Connection(object):
attempt = 0
while True:
+ params = self.params_list[attempt % len(self.params_list)]
attempt += 1
try:
- self._connect()
+ self._connect(params)
return
- except (self.connection_errors, IOError), e:
+ except (IOError, self.connection_errors, self.channel_errors) as e:
pass
except Exception, e:
# NOTE(comstud): Unfortunately it's possible for amqplib
@@ -483,12 +524,12 @@ class Connection(object):
log_info = {}
log_info['err_str'] = str(e)
log_info['max_retries'] = self.max_retries
- log_info.update(self.params)
+ log_info.update(params)
if self.max_retries and attempt == self.max_retries:
- LOG.exception(_('Unable to connect to AMQP server on '
- '%(hostname)s:%(port)d after %(max_retries)d '
- 'tries: %(err_str)s') % log_info)
+ LOG.error(_('Unable to connect to AMQP server on '
+ '%(hostname)s:%(port)d after %(max_retries)d '
+ 'tries: %(err_str)s') % log_info)
# NOTE(comstud): Copied from original code. There's
# really no better recourse because if this was a queue we
# need to consume on, we have no way to consume anymore.
@@ -502,9 +543,9 @@ class Connection(object):
sleep_time = min(sleep_time, self.interval_max)
log_info['sleep_time'] = sleep_time
- LOG.exception(_('AMQP server on %(hostname)s:%(port)d is'
- ' unreachable: %(err_str)s. Trying again in '
- '%(sleep_time)d seconds.') % log_info)
+ LOG.error(_('AMQP server on %(hostname)s:%(port)d is '
+ 'unreachable: %(err_str)s. Trying again in '
+ '%(sleep_time)d seconds.') % log_info)
time.sleep(sleep_time)
def ensure(self, error_callback, method, *args, **kwargs):
@@ -512,7 +553,8 @@ class Connection(object):
try:
return method(*args, **kwargs)
except (self.connection_errors, socket.timeout, IOError), e:
- pass
+ if error_callback:
+ error_callback(e)
except Exception, e:
# NOTE(comstud): Unfortunately it's possible for amqplib
# to return an error not covered by its transport
@@ -522,8 +564,8 @@ class Connection(object):
# and try to reconnect in this case.
if 'timeout' not in str(e):
raise
- if error_callback:
- error_callback(e)
+ if error_callback:
+ error_callback(e)
self.reconnect()
def get_channel(self):

View File

@ -0,0 +1,27 @@
require 'json'
def array_of_hash?(list)
return false unless !list.empty? && list.class == Array
list.each do |e|
return false unless e.class == Hash
end
true
end
module Puppet::Parser::Functions
newfunction(:check_array_of_hash, :arity =>1, :type => :rvalue, :doc => "Check
input String is a valid Array of Hash in JSON style") do |arg|
if arg[0].class == String
begin
list = JSON.load(arg[0].gsub("'","\""))
rescue JSON::ParserError
raise Puppet::ParseError, "Syntax error: #{arg[0]} is invalid"
else
return arg[0] if array_of_hash?(list)
end
else
raise Puppet::ParseError, "Syntax error: #{arg[0]} is not a String"
end
return ''
end
end

View File

@ -0,0 +1,199 @@
# Run test ie with: rspec spec/unit/provider/nova_spec.rb
require 'puppet/util/inifile'
class Puppet::Provider::Nova < Puppet::Provider
def self.conf_filename
'/etc/nova/nova.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.nova_conf
return @nova_conf if @nova_conf
@nova_conf = Puppet::Util::IniConfig::File.new
@nova_conf.read(conf_filename)
@nova_conf
end
def self.nova_credentials
@nova_credentials ||= get_nova_credentials
end
def nova_credentials
self.class.nova_credentials
end
def self.get_nova_credentials
#needed keys for authentication
auth_keys = ['auth_host', 'auth_port', 'auth_protocol',
'admin_tenant_name', 'admin_user', 'admin_password']
conf = nova_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. Nova types will not work if nova is not " +
"correctly configured.")
end
end
def self.get_auth_endpoint
q = nova_credentials
"#{q['auth_protocol']}://#{q['auth_host']}:#{q['auth_port']}/v2.0/"
end
def self.auth_endpoint
@auth_endpoint ||= get_auth_endpoint
end
def self.auth_nova(*args)
q = nova_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
nova(args)
end
rescue Exception => e
if (e.message =~ /\[Errno 111\] Connection refused/) or
(e.message =~ /\(HTTP 400\)/)
sleep 10
withenv authenv do
nova(args)
end
else
raise(e)
end
end
end
def auth_nova(*args)
self.class.auth_nova(args)
end
def self.reset
@nova_conf = nil
@nova_credentials = nil
end
def self.str2hash(s)
#parse string
if s.include? "="
k, v = s.split("=", 2)
return {k.gsub(/'/, "") => v.gsub(/'/, "")}
else
return s.gsub(/'/, "")
end
end
def self.str2list(s)
#parse string
if s.include? ","
if s.include? "="
new = {}
else
new = []
end
s.split(",").each do |el|
ret = str2hash(el.strip())
if s.include? "="
new.update(ret)
else
new.push(ret)
end
end
return new
else
return str2hash(s.strip())
end
end
def self.cliout2list(output)
#don't proceed with empty output
if output.empty?
return []
end
lines = []
output.each_line do |line|
#ignore lines starting with '+'
if not line.match("^\\+")
#split line at '|' and remove useless information
line = line.gsub(/^\| /, "").gsub(/ \|$/, "").gsub(/[\n]+/, "")
line = line.split("|").map do |el|
el.strip().gsub(/^-$/, "")
end
#check every element for list
line = line.map do |el|
el = str2list(el)
end
lines.push(line)
end
end
#create a list of hashes and return the list
hash_list = []
header = lines[0]
lines[1..-1].each do |line|
hash_list.push(Hash[header.zip(line)])
end
return hash_list
end
def self.nova_aggregate_resources_ids
#produce a list of hashes with Id=>Name pairs
lines = []
#run command
cmd_output = auth_nova("aggregate-list")
#parse output
hash_list = cliout2list(cmd_output)
#only interessted in Id and Name
hash_list.map{ |e| e.delete("Availability Zone")}
hash_list.map{ |e| e['Id'] = e['Id'].to_i}
return hash_list
end
def self.nova_aggregate_resources_get_name_by_id(name)
#find the id by the given name
nova_aggregate_resources_ids.each do |entry|
if entry["Name"] == name
return entry["Id"]
end
end
#name not found
return nil
end
def self.nova_aggregate_resources_attr(id)
#run command to get details for given Id
cmd_output = auth_nova("aggregate-details", id)
list = cliout2list(cmd_output)[0]
if ! list["Hosts"].is_a?(Array)
if list["Hosts"] == ""
list["Hosts"] = []
else
list["Hosts"] = [ list["Hosts"] ]
end
end
return list
end
end

View File

@ -0,0 +1,157 @@
require File.join(File.dirname(__FILE__), '..','..','..',
'puppet/provider/nova')
Puppet::Type.type(:nova_aggregate).provide(
:nova,
:parent => Puppet::Provider::Nova
) do
desc "Manage nova aggregations"
commands :nova => 'nova'
mk_resource_methods
def self.instances
nova_aggregate_resources_ids().collect do |el|
attrs = nova_aggregate_resources_attr(el['Id'])
new(
:ensure => :present,
:name => attrs['Name'],
:id => attrs['Id'],
:availability_zone => attrs['Availability Zone'],
:metadata => attrs['Metadata'],
:hosts => attrs['Hosts']
)
end
end
def self.prefetch(resources)
instances_ = instances
resources.keys.each do |name|
if provider = instances_.find{ |instance| instance.name == name }
resources[name].provider = provider
end
end
end
def exists?
@property_hash[:ensure] == :present
end
def destroy
#delete hosts first
if not @property_hash[:hosts].nil?
@property_hash[:hosts].each do |h|
auth_nova("aggregate-remove-host", name, h)
end
end
#now delete aggregate
auth_nova("aggregate-delete", name)
@property_hash[:ensure] = :absent
end
def create
extras = Array.new
#check for availability zone
if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty?
extras << "#{@resource[:availability_zone]}"
end
#run the command
result = auth_nova("aggregate-create", resource[:name], extras)
#get Id by Name
id = self.class.nova_aggregate_resources_get_name_by_id(resource[:name])
@property_hash = {
:ensure => :present,
:name => resource[:name],
:id => id,
:availability_zone => resource[:availability_zone]
}
#add metadata
if not @resource[:metadata].nil? and not @resource[:metadata].empty?
@resource[:metadata].each do |key, value|
set_metadata_helper(id, key, value)
end
@property_hash[:metadata] = resource[:metadata]
end
#add hosts - This throws an error if the host is already attached to another aggregate!
if not @resource[:hosts].nil? and not @resource[:hosts].empty?
@resource[:hosts].each do |host|
auth_nova("aggregate-add-host", id, "#{host}")
end
@property_hash[:hosts] = resource[:hosts]
end
end
def hosts=(val)
#get current hosts
id = self.class.nova_aggregate_resources_get_name_by_id(name)
attrs = self.class.nova_aggregate_resources_attr(id)
#remove all hosts which are not in new value list
attrs['Hosts'].each do |h|
if not val.include? h
auth_nova("aggregate-remove-host", id, "#{h}")
end
end
#add hosts from the value list
val.each do |h|
if not attrs['Hosts'].include? h
auth_nova("aggregate-add-host", id, "#{h}")
end
end
end
def set_metadata_helper(agg_id, key, value)
auth_nova("aggregate-set-metadata", agg_id, "#{key}=#{value}")
end
def metadata
#get current metadata
id = self.class.nova_aggregate_resources_get_name_by_id(name)
attrs = self.class.nova_aggregate_resources_attr(id)
#just ignore the availability_zone. that's handled directly by nova
attrs['Metadata'].delete('availability_zone')
return attrs['Metadata']
end
def metadata=(val)
#get current metadata
id = self.class.nova_aggregate_resources_get_name_by_id(name)
attrs = self.class.nova_aggregate_resources_attr(id)
#get keys which are in current metadata but not in val. Make sure it has data first!
if attrs['Metadata'].length > 0
obsolete_keys = attrs['Metadata'].keys - val.keys
end
# clear obsolete keys. If there are any!
if obsolete_keys
obsolete_keys.each do |key|
if not key.include? 'availability_zone'
auth_nova("aggregate-set-metadata", id, "#{key}")
end
end
#handle keys (with obsolete keys)
new_keys = val.keys - obsolete_keys
else
#handle keys (without obsolete keys)
new_keys = val.keys
end
#set new metadata if value changed
new_keys.each do |key|
if val[key] != attrs['Metadata'][key.to_s]
value = val[key]
set_metadata_helper(id, key, value)
end
end
end
def availability_zone=(val)
id = self.class.nova_aggregate_resources_get_name_by_id(name)
auth_nova("aggregate-set-metadata", id, "availability_zone=#{val}")
end
end

View File

@ -2,7 +2,7 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# Author: Emilien Macchi <emilien.macchi@enovance.com>
# François Charlier <francois.charlier@enovance.com>
# Francois Charlier <francois.charlier@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

View File

@ -13,7 +13,7 @@ Puppet::Type.type(:nova_floating).provide(:nova_manage) do
end
def create
nova_manage("floating", "create", resource[:network])
nova_manage("floating", "create", '--pool', resource[:pool], resource[:network])
end
def destroy

View File

@ -1,77 +0,0 @@
require 'openstack'
require 'netaddr'
Puppet::Type.type(:nova_floating_range).provide :nova_manage do
desc 'Create nova floating range'
commands :nova_manage => 'nova-manage'
def exists?
@resource[:ensure] = 'present' unless @resource[:ensure]
if @resource[:ensure] == :absent
operate_range.any?
else
operate_range.empty?
end
end
def create
mixed_range.each do |ip|
connect.create_floating_ips_bulk :ip_range => ip, :pool => @resource[:pool]
end
end
def destroy
mixed_range.each do |ip|
nova_manage("floating", "delete", ip )
end
end
# Create range in cidr, including first and last ip
# Nova will create this range, excluding network and broadcast IPs
def mixed_range
range = []
NetAddr.merge(operate_range).each do |cidr|
tmp_range = NetAddr::CIDR.create(cidr).enumerate
range << tmp_range.first.to_s
range << tmp_range.last.to_s
end
range.uniq!
range += NetAddr.merge(operate_range).delete_if{ |part| part =~ /\/3[12]/}
end
# Calculate exist IP and current range
def operate_range
exist_range = []
connect.get_floating_ips_bulk.each do |element|
exist_range << element.address
end
if @resource[:ensure] == :absent
ip_range & exist_range
else
ip_range - exist_range
end
end
# Create array of IPs from range
def ip_range
ip = @resource[:name].split('-')
ip_range = NetAddr.range NetAddr::CIDR.create(ip.first), NetAddr::CIDR.create(ip.last)
ip_range.unshift(ip.first).push(ip.last)
end
# Connect to OpenStack
def connect
@connect ||= OpenStack::Connection.create :username => @resource[:username],
:api_key => @resource[:api_key],
:auth_method => @resource[:auth_method],
:auth_url => @resource[:auth_url],
:authtenant_name => @resource[:authtenant_name],
:service_type => @resource[:service_type],
:retries => @resource[:api_retries],
:is_debug => Puppet[:debug]
end
end

View File

@ -27,7 +27,6 @@ Puppet::Type.type(:nova_network).provide(:nova_manage) do
{
# this needs to be converted from a project name to an id
:project => '--project_id',
:dns1 => '--dns1',
:dns2 => '--dns2',
:gateway => '--gateway',
:bridge => '--bridge',

View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 Deutsche Telekom AG
#
# Author: Thomas Bechtold <t.bechtold@telekom.de>
#
# 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.
#
# nova_aggregate type
#
# == Parameters
# [*name*]
# Name for the new aggregate
# Required
#
# [*availability_zone*]
# The availability zone. ie "zone1"
# Optional
#
# [*metadata*]
# String with key/value pairs. ie "key=value,key=value"
# Optional
#
# [*hosts*]
# A comma seperated list with hosts or a single host. ie "host1,host2"
# Optional
#
require 'puppet'
Puppet::Type.newtype(:nova_aggregate) do
@doc = "Manage creation of nova aggregations."
ensurable
autorequire(:nova_config) do
['auth_host', 'auth_port', 'auth_protocol', 'admin_tenant_name', 'admin_user', 'admin_password']
end
newparam(:name, :namevar => true) do
desc 'Name for the new aggregate'
validate do |value|
if not value.is_a? String
raise ArgumentError, "name parameter must be a String"
end
unless value =~ /[a-z0-9]+/
raise ArgumentError, "#{value} is not a valid name"
end
end
end
newproperty(:id) do
desc 'The unique Id of the aggregate'
validate do |v|
raise ArgumentError, 'This is a read only property'
end
end
newproperty(:availability_zone) do
desc 'The availability zone of the aggregate'
validate do |value|
if not value.is_a? String
raise ArgumentError, "availability zone must be a String"
end
end
end
newproperty(:metadata) do
desc 'The metadata of the aggregate'
#convert DSL/string form to internal form which is a single hash
munge do |value|
internal = Hash.new
value.split(",").map{|el| el.strip()}.each do |pair|
key, value = pair.split("=", 2)
internal[key.strip()] = value.strip()
end
return internal
end
validate do |value|
value.split(",").each do |kv|
raise ArgumentError, "Key/value pairs must be separated by an =" unless value.include?("=")
end
end
end
newproperty(:hosts) do
desc 'Single host or comma seperated list of hosts'
#convert DSL/string form to internal form
munge do |value|
return value.split(",").map{|el| el.strip()}
end
end
validate do
raise ArgumentError, 'Name type must be set' unless self[:name]
end
end

View File

@ -2,7 +2,7 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# Author: Emilien Macchi <emilien.macchi@enovance.com>
# François Charlier <francois.charlier@enovance.com>
# Francois Charlier <francois.charlier@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

View File

@ -3,11 +3,7 @@ Puppet::Type.newtype(:nova_config) do
ensurable
newparam(:name, :namevar => true) do
validate do |value|
unless value =~ /\S+\/\S+/
fail("Invalid nova_config #{value}, entries without sections are no longer supported, please add an explicit section (probably DEFAULT) to all nova_config resources")
end
end
newvalues(/\S+\/\S+/)
end
newproperty(:value) do
@ -43,13 +39,4 @@ Puppet::Type.newtype(:nova_config) do
defaultto false
end
validate do
if self[:ensure] == :present
if self[:value].nil?
raise Puppet::Error, "Property value must be set for #{self[:name]} when ensure is present"
end
end
end
end

View File

@ -5,8 +5,14 @@ Puppet::Type.newtype(:nova_floating) do
ensurable
newparam(:network, :namevar => true) do
desc "Network (ie, 192.168.1.0/24 or 192.168.1.128/25 etc.)"
desc "Network (ie, 192.168.1.0/24 or 192.168.1.128/25 etc.)"
newvalues(/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/)
end
newparam(:pool) do
desc "Floating IP pool name. Default: 'nova'"
defaultto :nova
newvalues(/^.{1,255}$/)
end
end

View File

@ -1,88 +0,0 @@
Puppet::Type.newtype(:nova_floating_range) do
@doc = 'Manage creation/deletion of nova floating ip ranges.'
ensurable
newparam(:name, :namevar => true) do
desc 'IP range ("192.168.1.1-192.168.1.55")'
validate do |value|
raise Puppet::Error, " #{value} does not look like IP range" unless value =~ /^(\d{1,3}\.){3}\d{1,3}-(\d{1,3}\.){3}\d{1,3}$/
end
end
newparam(:pool) do
desc 'Pool ranges'
defaultto 'nova'
end
newparam(:interface) do
# I don't know how use it
desc 'Interface for floating IP'
end
newparam(:username) do
desc 'authorization user'
munge do |value|
String value
end
end
newparam(:api_key) do
desc 'authorization key'
munge do |value|
String value
end
end
newparam(:auth_method) do
desc 'authorization password'
munge do |value|
String value
end
end
newparam(:auth_url) do
desc 'URL to keystone authorization http://192.168.1.1:5000/v2.0/'
validate do |value|
raise Puppet::Error, "#{value} does not look like URL" unless value =~ /^https?:\/\/\S+:\d{1,5}\/v[\d\.]{1,5}\//
end
end
newparam(:authtenant_name) do
desc 'Tenant name'
munge do |value|
String value
end
end
newparam(:api_retries) do
desc 'number of API reconnect retries'
validate do |value|
raise Puppet::Error, "#{value} does not look like numeric" unless value.is_a?(Integer) || value =~ /^\d+$/
end
munge do |value|
Integer value
end
end
newparam(:service_type) do
desc 'Connection type :service_type parameter to "compute", "object-store", "volume" or "network" (defaults to "compute")'
defaultto 'compute'
munge do |value|
String value
end
end
end

View File

@ -34,12 +34,7 @@ Puppet::Type.newtype(:nova_network) do
newparam(:gateway) do
end
newparam(:dns1) do
desc 'first dns server'
end
newparam(:dns2) do
desc 'second dns server'
end
newparam(:vlan_start) do

View File

@ -19,28 +19,28 @@
# (optional) Whether the nova api package will be installed
# Defaults to 'present'
#
# [*auth_strategy*]
# (DEPRECATED) Does nothing and will be removed in Icehouse
# Defaults to false
#
# [*auth_host*]
# (optional) The IP of the server running keystone
# (optional) DEPRECATED. The IP of the server running keystone
# Defaults to '127.0.0.1'
#
# [*auth_port*]
# (optional) The port to use when authenticating against Keystone
# (optional) DEPRECATED. The port to use when authenticating against Keystone
# Defaults to 35357
#
# [*auth_protocol*]
# (optional) The protocol to use when authenticating against Keystone
# (optional) DEPRECATED. The protocol to use when authenticating against Keystone
# Defaults to 'http'
#
# [*auth_uri*]
# (optional) The uri of a Keystone service to authenticate against
# (optional) Complete public Identity API endpoint.
# Defaults to false
#
# [*identity_uri*]
# (optional) Complete admin Identity API endpoint.
# Defaults to: false
#
# [*auth_admin_prefix*]
# (optional) Prefix to prepend at the beginning of the keystone path
# (optional) DEPRECATED. Prefix to prepend at the beginning of the keystone path
# Defaults to false
#
# [*auth_version*]
@ -68,6 +68,10 @@
# (optional) A comma separated list of apis to enable
# Defaults to 'ec2,osapi_compute,metadata'
#
# [*keystone_ec2_url*]
# (optional) The keystone url where nova should send requests for ec2tokens
# Defaults to false
#
# [*volume_api_class*]
# (optional) The name of the class that nova will use to access volumes. Cinder is the only option.
# Defaults to 'nova.volume.cinder.API'
@ -81,13 +85,18 @@
# (optional) Number of workers for OpenStack API service
# Defaults to $::processorcount
#
# [*ec2_workers*]
# (optional) Number of workers for EC2 service
# Defaults to $::processorcount
#
# [*metadata_workers*]
# (optional) Number of workers for metadata service
# Defaults to $::processorcount
#
# [*conductor_workers*]
# (optional) Number of workers for OpenStack Conductor service
# Defaults to $::processorcount
# (optional) DEPRECATED. Use workers parameter of nova::conductor
# Class instead.
# Defaults to undef
#
# [*sync_db*]
# (optional) Run nova-manage db sync on api nodes after installing the package.
@ -97,6 +106,12 @@
# (optional) Shared secret to validate proxies Neutron metadata requests
# Defaults to undef
#
# [*pci_alias*]
# (optional) Pci passthrough for controller:
# Defaults to undef
# Example
# "[ {'vendor_id':'1234', 'product_id':'5678', 'name':'default'}, {...} ]"
#
# [*ratelimits*]
# (optional) A string that is a semicolon-separated list of 5-tuples.
# See http://docs.openstack.org/trunk/config-reference/content/configuring-compute-API.html
@ -107,58 +122,84 @@
# (optional) The rate limiting factory to use
# Defaults to 'nova.api.openstack.compute.limits:RateLimitingMiddleware.factory'
#
# [*osapi_v3*]
# (optional) Enable or not Nova API v3
# Defaults to false
#
# [*validate*]
# (optional) Whether to validate the service is working after any service refreshes
# Defaults to false
#
# [*validation_options*]
# (optional) Service validation options
# Should be a hash of options defined in openstacklib::service_validation
# If empty, defaults values are taken from openstacklib function.
# Default command list nova flavors.
# Require validate set at True.
# Example:
# nova::api::validation_options:
# nova-api:
# command: check_nova.py
# path: /usr/bin:/bin:/usr/sbin:/sbin
# provider: shell
# tries: 5
# try_sleep: 10
# Defaults to {}
#
class nova::api(
$admin_password,
$enabled = false,
$manage_service = true,
$ensure_package = 'present',
$auth_strategy = undef,
$auth_host = '127.0.0.1',
$auth_port = 35357,
$auth_protocol = 'http',
$auth_uri = false,
$auth_admin_prefix = false,
$identity_uri = false,
$auth_version = false,
$admin_tenant_name = 'services',
$admin_user = 'nova',
$api_bind_address = '0.0.0.0',
$metadata_listen = '0.0.0.0',
$enabled_apis = 'ec2,osapi_compute,metadata',
$keystone_ec2_url = false,
$volume_api_class = 'nova.volume.cinder.API',
$use_forwarded_for = false,
$osapi_compute_workers = $::processorcount,
$ec2_workers = $::processorcount,
$metadata_workers = $::processorcount,
$conductor_workers = $::processorcount,
$sync_db = true,
$neutron_metadata_proxy_shared_secret = undef,
$osapi_v3 = false,
$pci_alias = undef,
$ratelimits = undef,
$ratelimits_factory =
'nova.api.openstack.compute.limits:RateLimitingMiddleware.factory',
$validate = false,
$validation_options = {},
# DEPRECATED PARAMETER
$workers = undef,
$auth_protocol = 'http',
$auth_port = 35357,
$auth_host = '127.0.0.1',
$auth_admin_prefix = false,
$conductor_workers = undef,
) {
include nova::params
require keystone::python
include cinder::client
include ::nova::db
include ::nova::params
include ::nova::policy
require ::keystone::python
include ::cinder::client
Package<| title == 'nova-api' |> -> Nova_paste_api_ini<| |>
Package<| title == 'nova-common' |> -> Class['nova::api']
Package<| title == 'nova-common' |> -> Class['nova::policy']
Nova_paste_api_ini<| |> ~> Exec['post-nova_config']
Nova_paste_api_ini<| |> ~> Service['nova-api']
Class['nova::policy'] ~> Service['nova-api']
if $auth_strategy {
warning('The auth_strategy parameter is deprecated and has no effect.')
}
if $workers {
warning('The workers parameter is deprecated, use osapi_compute_workers instead.')
$osapi_compute_workers_real = $workers
} else {
$osapi_compute_workers_real = $osapi_compute_workers
if $conductor_workers {
warning('The conductor_workers parameter is deprecated and has no effect. Use workers parameter of nova::conductor class instead.')
}
nova::generic_service { 'api':
@ -177,29 +218,37 @@ class nova::api(
'DEFAULT/osapi_compute_listen': value => $api_bind_address;
'DEFAULT/metadata_listen': value => $metadata_listen;
'DEFAULT/osapi_volume_listen': value => $api_bind_address;
'DEFAULT/osapi_compute_workers': value => $osapi_compute_workers_real;
'DEFAULT/osapi_compute_workers': value => $osapi_compute_workers;
'DEFAULT/ec2_workers': value => $ec2_workers;
'DEFAULT/metadata_workers': value => $metadata_workers;
'conductor/workers': value => $conductor_workers;
'DEFAULT/use_forwarded_for': value => $use_forwarded_for;
'osapi_v3/enabled': value => $osapi_v3;
}
if ($neutron_metadata_proxy_shared_secret){
nova_config {
'DEFAULT/service_neutron_metadata_proxy': value => true;
'DEFAULT/neutron_metadata_proxy_shared_secret':
'neutron/service_metadata_proxy': value => true;
'neutron/metadata_proxy_shared_secret':
value => $neutron_metadata_proxy_shared_secret;
}
} else {
nova_config {
'DEFAULT/service_neutron_metadata_proxy': value => false;
'DEFAULT/neutron_metadata_proxy_shared_secret': ensure => absent;
'neutron/service_metadata_proxy': value => false;
'neutron/metadata_proxy_shared_secret': ensure => absent;
}
}
if $auth_uri {
nova_config { 'keystone_authtoken/auth_uri': value => $auth_uri; }
$auth_uri_real = $auth_uri
} else {
nova_config { 'keystone_authtoken/auth_uri': value => "${auth_protocol}://${auth_host}:5000/"; }
$auth_uri_real = "${auth_protocol}://${auth_host}:5000/"
}
nova_config { 'keystone_authtoken/auth_uri': value => $auth_uri_real; }
if $identity_uri {
nova_config { 'keystone_authtoken/identity_uri': value => $identity_uri; }
} else {
nova_config { 'keystone_authtoken/identity_uri': ensure => absent; }
}
if $auth_version {
@ -208,23 +257,62 @@ class nova::api(
nova_config { 'keystone_authtoken/auth_version': ensure => absent; }
}
# if both auth_uri and identity_uri are set we skip these deprecated settings entirely
if !$auth_uri or !$identity_uri {
if $auth_host {
warning('The auth_host parameter is deprecated. Please use auth_uri and identity_uri instead.')
nova_config { 'keystone_authtoken/auth_host': value => $auth_host; }
} else {
nova_config { 'keystone_authtoken/auth_host': ensure => absent; }
}
if $auth_port {
warning('The auth_port parameter is deprecated. Please use auth_uri and identity_uri instead.')
nova_config { 'keystone_authtoken/auth_port': value => $auth_port; }
} else {
nova_config { 'keystone_authtoken/auth_port': ensure => absent; }
}
if $auth_protocol {
warning('The auth_protocol parameter is deprecated. Please use auth_uri and identity_uri instead.')
nova_config { 'keystone_authtoken/auth_protocol': value => $auth_protocol; }
} else {
nova_config { 'keystone_authtoken/auth_protocol': ensure => absent; }
}
if $auth_admin_prefix {
warning('The auth_admin_prefix parameter is deprecated. Please use auth_uri and identity_uri instead.')
validate_re($auth_admin_prefix, '^(/.+[^/])?$')
nova_config {
'keystone_authtoken/auth_admin_prefix': value => $auth_admin_prefix;
}
} else {
nova_config { 'keystone_authtoken/auth_admin_prefix': ensure => absent; }
}
} else {
nova_config {
'keystone_authtoken/auth_host': ensure => absent;
'keystone_authtoken/auth_port': ensure => absent;
'keystone_authtoken/auth_protocol': ensure => absent;
'keystone_authtoken/auth_admin_prefix': ensure => absent;
}
}
nova_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, '^(/.+[^/])?$')
if $keystone_ec2_url {
nova_config {
'keystone_authtoken/auth_admin_prefix': value => $auth_admin_prefix;
'DEFAULT/keystone_ec2_url': value => $keystone_ec2_url;
}
} else {
nova_config {
'keystone_authtoken/auth_admin_prefix': ensure => absent;
'DEFAULT/keystone_ec2_url': ensure => absent;
}
}
@ -258,7 +346,9 @@ class nova::api(
# Added arg and if statement prevents this from being run
# where db is not active i.e. the compute
if $sync_db {
Package<| title == 'nova-api' |> -> Exec['nova-db-sync']
Package<| title == $::nova::params::api_package_name |> ~> Exec['nova-db-sync']
Package<| title == $::nova::params::common_package_name |> ~> Exec['nova-db-sync']
exec { 'nova-db-sync':
command => '/usr/bin/nova-manage db sync',
refreshonly => true,
@ -278,4 +368,19 @@ class nova::api(
'filter:authtoken/auth_admin_prefix': ensure => absent;
}
if $pci_alias {
nova_config {
'DEFAULT/pci_alias': value => check_array_of_hash($pci_alias);
}
}
if $validate {
$defaults = {
'nova-api' => {
'command' => "nova --os-auth-url ${auth_uri_real} --os-tenant-name ${admin_tenant_name} --os-username ${admin_user} --os-password ${admin_password} flavor-list",
}
}
$validation_options_hash = merge ($defaults, $validation_options)
create_resources('openstacklib::service_validation', $validation_options_hash, {'subscribe' => 'Service[nova-api]'})
}
}

View File

@ -2,7 +2,7 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# Author: Emilien Macchi <emilien.macchi@enovance.com>
# François Charlier <francois.charlier@enovance.com>
# Francois Charlier <francois.charlier@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
@ -16,9 +16,12 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# The nova::cells class installs the Nova Cells
# == Class: nova::cells
#
# Installs the Nova Cells
#
# === Parameters:
#
# == Parameters
# [*enabled*]
# Use Nova Cells or not
# Defaults to 'False'
@ -35,6 +38,10 @@
# Cells communication driver to use
# Defaults to 'nova.cells.rpc_driver.CellsRPCDriver'
#
# [*ensure_package*]
# Desired ensure state of packages.
# Defaults to present
#
# [*instance_updated_at_threshold*]
# Number of seconds after an instance was updated or deleted to continue to update cells
# Defaults to '3600'
@ -133,7 +140,6 @@
# It might be used by some cell scheduling code in the future
# Defaults to '1.0'
#
class nova::cells (
$bandwidth_update_interval = '600',
$call_timeout = '60',
@ -166,16 +172,16 @@ class nova::cells (
$weight_scale = '1.0'
) {
include nova::params
include ::nova::params
case $cell_type {
'parent': {
nova_config { 'DEFAULT/compute_api_class': value => 'nova.compute.cells_api.ComputeCellsAPI' }
nova_config { 'DEFAULT/cell_type': value => 'api' }
nova_config { 'cells/cell_type': value => 'api' }
}
'child': {
nova_config { 'DEFAULT/quota_driver': value => 'nova.quota.NoopQuotaDriver' }
nova_config { 'DEFAULT/cell_type': value => 'compute' }
nova_config { 'cells/cell_type': value => 'compute' }
}
default: { fail("Unsupported cell_type parameter value: '${cell_type}'. Should be 'parent' or 'child'.") }
}
@ -217,11 +223,11 @@ class nova::cells (
@@nova::manage::cells { $cell_name:
cell_type => $cell_type,
cell_parent_name => $cell_parent_name,
rabbit_username => $::nova::init::rabbit_userid,
rabbit_password => $::nova::init::rabbit_password,
rabbit_hosts => $::nova::init::rabbit_hosts,
rabbit_port => $::nova::init::rabbit_port,
rabbit_virtual_host => $::nova::init::virtual_host,
rabbit_username => $::nova::rabbit_userid,
rabbit_password => $::nova::rabbit_password,
rabbit_hosts => $::nova::rabbit_hosts,
rabbit_port => $::nova::rabbit_port,
rabbit_virtual_host => $::nova::rabbit_virtual_host,
weight_offset => $weight_offset,
weight_scale => $weight_scale,
before => Service['cells']

View File

@ -22,7 +22,7 @@ class nova::cert(
$ensure_package = 'present'
) {
include nova::params
include ::nova::params
nova::generic_service { 'cert':
enabled => $enabled,

View File

@ -14,6 +14,7 @@ class nova::client(
package { 'python-novaclient':
ensure => $ensure,
tag => ['openstack'],
}
}

View File

@ -8,6 +8,10 @@
# (optional) Whether to enable the nova-compute service
# Defaults to false
#
# [*heal_instance_info_cache_interval*]
# (optional) Controls how often the instance info should be updated.
# Defaults to '60' , to disable you can set the value to zero.
#
# [*manage_service*]
# (optional) Whether to start/stop the service
# Defaults to true
@ -38,7 +42,11 @@
#
# [*vncproxy_path*]
# (optional) The path at the end of the uri for communication with the VNC proxy server
# Defaults to './vnc_auto.html'
# Defaults to '/vnc_auto.html'
#
# [*vnc_keymap*]
# (optional) The keymap to use with VNC (ls -alh /usr/share/qemu/keymaps to list available keymaps)
# Defaults to 'en-us'
#
# [*force_config_drive*]
# (optional) Whether to force the config drive to be attached to all VMs
@ -65,9 +73,23 @@
# Time period must be hour, day, month or year
# Defaults to 'month'
#
# [*force_raw_images*]
# (optional) Force backing images to raw format.
# Defaults to true
#
# [*reserved_host_memory*]
# Reserved host memory
# The amount of memory in MB reserved for the host.
# Defaults to '512'
#
# [*compute_manager*]
# Compute manager
# The driver that will manage the running instances.
# Defaults to nova.compute.manager.ComputeManager
#
# [*default_availability_zone*]
# (optional) Default compute node availability zone.
# Defaults to undef
# Defaults to nova
#
# [*default_schedule_zone*]
# (optional) Availability zone to use when user doesn't specify one.
@ -75,7 +97,14 @@
#
# [*internal_service_availability_zone*]
# (optional) The availability zone to show internal services under.
# Defaults to internal
#
# [*pci_passthrough*]
# (optional) Pci passthrough hash in format of:
# Defaults to undef
# Example
# "[ { 'vendor_id':'1234','product_id':'5678' },
# { 'vendor_id':'4321','product_id':'8765','physical_network':'default' } ] "
#
class nova::compute (
$enabled = false,
@ -87,39 +116,47 @@ class nova::compute (
$vncproxy_protocol = 'http',
$vncproxy_port = '6080',
$vncproxy_path = '/vnc_auto.html',
$vnc_keymap = 'en-us',
$force_config_drive = false,
$virtio_nic = false,
$neutron_enabled = true,
$network_device_mtu = undef,
$instance_usage_audit = false,
$instance_usage_audit_period = 'month',
$default_availability_zone = undef,
$force_raw_images = true,
$reserved_host_memory = '512',
$compute_manager = 'nova.compute.manager.ComputeManager',
$default_availability_zone = 'nova',
$default_schedule_zone = undef,
$internal_service_availability_zone = undef,
$internal_service_availability_zone = 'internal',
$heal_instance_info_cache_interval = '60',
$pci_passthrough = undef,
) {
include nova::params
include stdlib
include ::nova::params
nova_config {
'DEFAULT/reserved_host_memory_mb': value => $reserved_host_memory;
'DEFAULT/compute_manager': value => $compute_manager;
'DEFAULT/heal_instance_info_cache_interval': value => $heal_instance_info_cache_interval;
}
if ($vnc_enabled) {
if ($vncproxy_host) {
$vncproxy_base_url = "${vncproxy_protocol}://${vncproxy_host}:${vncproxy_port}${vncproxy_path}"
# config for vnc proxy
nova_config {
'DEFAULT/novncproxy_base_url': value => $vncproxy_base_url;
}
}
include ::nova::vncproxy::common
}
nova_config {
'DEFAULT/vnc_enabled': value => $vnc_enabled;
'DEFAULT/vncserver_proxyclient_address': value => $vncserver_proxyclient_address;
'DEFAULT/vnc_keymap': value => $vnc_keymap;
}
if $neutron_enabled != true {
# Install bridge-utils if we use nova-network
ensure_packages('bridge-utils')
Package <| title == 'bridge-utils' |> -> Nova::Generic_service['compute']
package { 'bridge-utils':
ensure => present,
before => Nova::Generic_service['compute'],
}
}
nova::generic_service { 'compute':
@ -164,22 +201,28 @@ class nova::compute (
}
}
if $default_availability_zone {
nova_config {
'DEFAULT/default_availability_zone':value => $default_availability_zone;
}
package { 'pm-utils':
ensure => present,
}
nova_config {
'DEFAULT/force_raw_images': value => $force_raw_images;
}
nova_config {
'DEFAULT/default_availability_zone': value => $default_availability_zone;
'DEFAULT/internal_service_availability_zone': value => $internal_service_availability_zone;
}
if $default_schedule_zone {
nova_config {
'DEFAULT/default_schedule_zone':value => $default_schedule_zone;
'DEFAULT/default_schedule_zone': value => $default_schedule_zone;
}
}
if $internal_service_availability_zone {
if ($pci_passthrough) {
nova_config {
'DEFAULT/internal_service_availability_zone':value => $internal_service_availability_zone;
'DEFAULT/pci_passthrough_whitelist': value => check_array_of_hash($pci_passthrough);
}
}
}

View File

@ -1,31 +0,0 @@
#
# This is a temporary manifest that patches
# nova compute to resolve the folowing issue:
# https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/996840
#
# This is only intended as a temporary fix and needs to be removed
# once the issue is resolved with upstream.
#
# TODO - check if this is still required for folsom
#
#
class nova::compute::file_hack() {
# this only works on Ubunty
File {
owner => 'root',
group => 'root',
mode => '755',
require => Package['nova-compute'],
notify => Service['nova-compute'],
}
file { '/usr/lib/python2.7/dist-packages/nova/virt/libvirt/connection.py':
source => 'puppet:///modules/nova/connection.py',
}
file { '/usr/lib/python2.7/dist-packages/nova/rootwrap/compute.py':
source => 'puppet:///modules/nova/compute.py',
}
}

View File

@ -0,0 +1,49 @@
# == Class: nova::compute::ironic
#
# Configures Nova compute service to use Ironic.
#
# === Parameters:
#
# [*admin_user*]
# Admin username
# The admin username for Ironic to connect to Nova.
# Defaults to 'admin'
#
# [*admin_passwd*]
# Admin password
# The admin password for Ironic to connect to Nova.
# Defaults to 'ironic'
#
# [*admin_url*]
# Admin url
# The address of the Keystone api endpoint.
# Defaults to 'http://127.0.0.1:35357/v2.0'
#
# [*admin_tenant_name*]
# Admin tenant name
# The Ironic Keystone tenant name.
# Defaults to 'services'
#
# [*api_endpoint*]
# Api endpoint
# The url for Ironic api endpoint.
# Defaults to 'http://127.0.0.1:6385/v1'
#
class nova::compute::ironic (
$admin_user = 'admin',
$admin_passwd = 'ironic',
$admin_url = 'http://127.0.0.1:35357/v2.0',
$admin_tenant_name = 'services',
$api_endpoint = 'http://127.0.0.1:6385/v1',
) {
nova_config {
'ironic/admin_username': value => $admin_user;
'ironic/admin_password': value => $admin_passwd;
'ironic/admin_url': value => $admin_url;
'ironic/admin_tenant_name': value => $admin_tenant_name;
'ironic/api_endpoint': value => $api_endpoint;
'DEFAULT/compute_driver': value => 'nova.virt.ironic.IronicDriver';
}
}

View File

@ -7,7 +7,6 @@
#
# [*libvirt_virt_type*]
# (optional) Libvirt domain type. Options are: kvm, lxc, qemu, uml, xen
# Replaces libvirt_type
# Defaults to 'kvm'
#
# [*vncserver_listen*]
@ -20,9 +19,9 @@
#
# [*libvirt_cpu_mode*]
# (optional) The libvirt CPU mode to configure. Possible values
# include custom, host-model, None, host-passthrough.
# include custom, host-model, none, host-passthrough.
# Defaults to 'host-model' if libvirt_virt_type is set to either
# kvm or qemu, otherwise defaults to 'None'.
# kvm or qemu, otherwise defaults to 'none'.
#
# [*libvirt_disk_cachemodes*]
# (optional) A list of cachemodes for different disk types, e.g.
@ -31,6 +30,20 @@
# will be removed from nova.conf completely.
# Defaults to an empty list
#
# [*libvirt_inject_password*]
# (optional) Inject the admin password at boot time, without an agent.
# Defaults to false
#
# [*libvirt_inject_key*]
# (optional) Inject the ssh public key at boot time.
# Defaults to false
#
# [*libvirt_inject_partition*]
# (optional) The partition to inject to : -2 => disable, -1 => inspect
# (libguestfs only), 0 => not partitioned, >0 => partition
# number (integer value)
# Defaults to -2
#
# [*remove_unused_base_images*]
# (optional) Should unused base images be removed?
# If undef is specified, remove the line in nova.conf
@ -61,40 +74,38 @@
# how many seconds it will be removed.
# Defaults to undef
#
# [*libvirt_service_name*]
# (optional) libvirt service name.
# Defaults to $::nova::params::libvirt_service_name
#
class nova::compute::libvirt (
$libvirt_virt_type = 'kvm',
$vncserver_listen = '127.0.0.1',
$migration_support = false,
$libvirt_cpu_mode = false,
$libvirt_disk_cachemodes = [],
$libvirt_inject_password = false,
$libvirt_inject_key = false,
$libvirt_inject_partition = -2,
$remove_unused_base_images = undef,
$remove_unused_kernels = undef,
$remove_unused_resized_minimum_age_seconds = undef,
$remove_unused_original_minimum_age_seconds = undef,
# DEPRECATED PARAMETER
$libvirt_type = false
) {
$libvirt_service_name = $::nova::params::libvirt_service_name,
) inherits nova::params {
include nova::params
include ::nova::params
Service['libvirt'] -> Service['nova-compute']
if $libvirt_type {
warning ('The libvirt_type parameter is deprecated, use libvirt_virt_type instead.')
$libvirt_virt_type_real = $libvirt_type
} else {
$libvirt_virt_type_real = $libvirt_virt_type
}
# libvirt_cpu_mode has different defaults depending on hypervisor.
if !$libvirt_cpu_mode {
case $libvirt_virt_type_real {
case $libvirt_virt_type {
'kvm','qemu': {
$libvirt_cpu_mode_real = 'host-model'
}
default: {
$libvirt_cpu_mode_real = 'None'
$libvirt_cpu_mode_real = 'none'
}
}
} else {
@ -102,10 +113,11 @@ class nova::compute::libvirt (
}
if($::osfamily == 'Debian') {
package { "nova-compute-${libvirt_virt_type_real}":
package { "nova-compute-${libvirt_virt_type}":
ensure => present,
before => Package['nova-compute'],
require => User['nova'],
require => Package['nova-common'],
tag => ['openstack'],
}
}
@ -113,17 +125,17 @@ class nova::compute::libvirt (
service { 'messagebus':
ensure => running,
enable => true,
name => $::nova::params::messagebus_service_name,
provider => $::nova::params::special_service_provider,
}
Package['libvirt'] -> Service['messagebus'] -> Service['libvirt']
}
if $migration_support {
if $vncserver_listen != '0.0.0.0' {
fail('For migration support to work, you MUST set vncserver_listen to \'0.0.0.0\'')
if $vncserver_listen != '0.0.0.0' and $vncserver_listen != '::0' {
fail('For migration support to work, you MUST set vncserver_listen to \'0.0.0.0\' or \'::0\'')
} else {
class { 'nova::migration::libvirt': }
class { '::nova::migration::libvirt': }
}
}
@ -135,7 +147,7 @@ class nova::compute::libvirt (
service { 'libvirt' :
ensure => running,
enable => true,
name => $::nova::params::libvirt_service_name,
name => $libvirt_service_name,
provider => $::nova::params::special_service_provider,
require => Package['libvirt'],
}
@ -143,8 +155,11 @@ class nova::compute::libvirt (
nova_config {
'DEFAULT/compute_driver': value => 'libvirt.LibvirtDriver';
'DEFAULT/vncserver_listen': value => $vncserver_listen;
'libvirt/virt_type': value => $libvirt_virt_type_real;
'libvirt/virt_type': value => $libvirt_virt_type;
'libvirt/cpu_mode': value => $libvirt_cpu_mode_real;
'libvirt/inject_password': value => $libvirt_inject_password;
'libvirt/inject_key': value => $libvirt_inject_key;
'libvirt/inject_partition': value => $libvirt_inject_partition;
}
if size($libvirt_disk_cachemodes) > 0 {

View File

@ -10,9 +10,14 @@
# (optional) The libvirt VIF driver to configure the VIFs.
# Defaults to 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver'.
#
# [*force_snat_range*]
# (optional) Force SNAT rule to specified network for nova-network
# Default to 0.0.0.0/0
# Due to architecture constraints in nova_config, it's not possible to setup
# more than one SNAT rule though initial parameter is MultiStrOpt
class nova::compute::neutron (
$libvirt_vif_driver = 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver'
$libvirt_vif_driver = 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver',
$force_snat_range = '0.0.0.0/0',
) {
if $libvirt_vif_driver == 'nova.virt.libvirt.vif.LibvirtOpenVswitchDriver' {
@ -22,4 +27,21 @@ class nova::compute::neutron (
nova_config {
'libvirt/vif_driver': value => $libvirt_vif_driver;
}
if $libvirt_vif_driver == 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver' and $force_snat_range {
# Validate ip and mask for force_snat_range
$force_snat_range_array = split($force_snat_range, '/')
if is_ip_address($force_snat_range_array[0]) and is_integer($force_snat_range_array[1]) {
nova_config {
'DEFAULT/force_snat_range': value => $force_snat_range;
}
} else {
fail('force_snat_range should be IPv4 or IPv6 CIDR notation')
}
} else {
nova_config {
'DEFAULT/force_snat_range': ensure => absent;
}
}
}

View File

@ -38,15 +38,28 @@
# Required to use cephx.
# Default to false.
#
# [*libvirt_rbd_secret_key*]
# (optional) The cephx key to use as key for the libvirt secret,
# it must be base64 encoded; when not provided this key will be
# requested to the ceph cluster, which assumes the node is
# provided of the client.admin keyring as well.
# Default to undef.
#
# [*rbd_keyring*]
# (optional) The keyring name to use when retrieving the RBD secret
# Default to 'client.nova'
#
class nova::compute::rbd (
$libvirt_rbd_user,
$libvirt_rbd_secret_uuid = false,
$libvirt_rbd_secret_key = undef,
$libvirt_images_rbd_pool = 'rbd',
$libvirt_images_rbd_ceph_conf = '/etc/ceph/ceph.conf',
$rbd_keyring = 'client.nova',
) {
include nova::params
include ::nova::params
nova_config {
'libvirt/images_type': value => 'rbd';
@ -61,7 +74,8 @@ class nova::compute::rbd (
}
file { '/etc/nova/secret.xml':
content => template('nova/secret.xml-compute.erb')
content => template('nova/secret.xml-compute.erb'),
require => Class['::nova']
}
exec { 'get-or-set virsh secret':
@ -70,8 +84,14 @@ class nova::compute::rbd (
require => File['/etc/nova/secret.xml']
}
if $libvirt_rbd_secret_key {
$libvirt_key = $libvirt_rbd_secret_key
} else {
$libvirt_key = "$(ceph auth get-key ${rbd_keyring})"
}
exec { 'set-secret-value virsh':
command => '/usr/bin/virsh secret-set-value --secret $(cat /etc/nova/virsh.secret) --base64 $(ceph auth get-key client.nova)',
command => "/usr/bin/virsh secret-set-value --secret ${libvirt_rbd_secret_uuid} --base64 ${libvirt_key}",
unless => "/usr/bin/virsh secret-get-value ${libvirt_rbd_secret_uuid}",
require => Exec['get-or-set virsh secret']
}

View File

@ -0,0 +1,39 @@
# == Class: nova::compute::serial
#
# Configures nova serial console
#
# === Parameters:
#
# [*port_range*]
# (optional) Range of TCP ports to use for serial ports on compute hosts
# Defaults to 10000:20000
#
# [*base_url*]
# (optional) URL that gets passed to the clients
# Defaults to 'ws://127.0.0.1:6083/'
#
# [*listen*]
# IP address on which instance serial console should listen
# Defaults to 127.0.0.1
#
# [*proxyclient_address*]
# The address to which proxy clients (like nova-serialproxy)
# should connect (string value)
# Defaults to 127.0.0.1
#
class nova::compute::serial(
$port_range = '10000:20000',
$base_url = 'ws://127.0.0.1:6083/',
$listen = '127.0.0.1',
$proxyclient_address = '127.0.0.1',
) {
nova_config {
'serial_console/enabled': value => true;
'serial_console/port_range': value => $port_range;
'serial_console/base_url': value => $base_url;
'serial_console/listen': value => $listen;
'serial_console/proxyclient_address': value => $proxyclient_address;
}
}

View File

@ -16,13 +16,19 @@
# (optional) The state of the nova conductor package
# Defaults to 'present'
#
# [*workers*]
# (optional) Number of workers for OpenStack Conductor service
# Defaults to undef (i.e. parameter will not be present)
#
class nova::conductor(
$enabled = false,
$manage_service = true,
$ensure_package = 'present'
$ensure_package = 'present',
$workers = undef,
) {
include nova::params
include ::nova::db
include ::nova::params
nova::generic_service { 'conductor':
enabled => $enabled,
@ -32,4 +38,9 @@ class nova::conductor(
ensure_package => $ensure_package,
}
if $workers {
nova_config {
'conductor/workers': value => $workers;
}
}
}

View File

@ -20,6 +20,13 @@
# NOTE: The configuration MUST NOT be already handled by this module
# or Puppet catalog compilation will fail with duplicate resources.
#
# [*nova_paste_api_ini*]
# (optional) Allow configuration of arbitrary Nova paste api configurations.
# The value is an hash of nova_paste_api_ini resources. Example:
# { 'DEFAULT/foo' => { value => 'fooValue'},
# 'DEFAULT/bar' => { value => 'barValue'}
# }
#
class nova::config (
$nova_config = {},
$nova_paste_api_ini = {},

View File

@ -25,7 +25,7 @@ class nova::consoleauth(
$ensure_package = 'present'
) {
include nova::params
include ::nova::params
nova::generic_service { 'consoleauth':
enabled => $enabled,
@ -33,7 +33,7 @@ class nova::consoleauth(
package_name => $::nova::params::consoleauth_package_name,
service_name => $::nova::params::consoleauth_service_name,
ensure_package => $ensure_package,
require => User['nova'],
require => Package['nova-common'],
}
}

View File

@ -0,0 +1,69 @@
#
# Copyright (C) 2014 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: nova::cron::archive_deleted_rows
#
# Move deleted instances to another table that you don't have to backup
# unless you have data retention policies.
#
# === Parameters
#
# [*minute*]
# (optional) Defaults to '1'.
#
# [*hour*]
# (optional) Defaults to '0'.
#
# [*monthday*]
# (optional) Defaults to '*'.
#
# [*month*]
# (optional) Defaults to '*'.
#
# [*weekday*]
# (optional) Defaults to '*'.
#
# [*max_rows*]
# (optional) Maximum number of deleted rows to archive.
# Defaults to '100'.
#
# [*user*]
# (optional) User with access to nova files.
# Defaults to 'nova'.
#
class nova::cron::archive_deleted_rows (
$minute = 1,
$hour = 0,
$monthday = '*',
$month = '*',
$weekday = '*',
$max_rows = '100',
$user = 'nova',
) {
cron { 'nova-manage db archive_deleted_rows':
command => "nova-manage db archive_deleted_rows --max_rows ${max_rows} >>/var/log/nova/nova-rowsflush.log 2>&1",
environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh',
user => $user,
minute => $minute,
hour => $hour,
monthday => $monthday,
month => $month,
weekday => $weekday,
require => Package['nova-common'],
}
}

View File

@ -0,0 +1,71 @@
#
# Copyright (C) 2014 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: nova::db
# Configures the nova database.
#
# == Parameters
#
# [*database_connection*]
# (optional) Connection url to connect to nova database.
# Defaults to undef
#
# [*slave_connection*]
# (optional) Connection url to connect to nova slave database (read-only).
# Defaults to undef
#
# [*database_idle_timeout*]
# (optional) Timeout before idle db connections are reaped.
# Defaults to undef
#
class nova::db (
$database_connection = undef,
$slave_connection = undef,
$database_idle_timeout = undef,
) {
$database_connection_real = pick($database_connection, $::nova::database_connection, false)
$slave_connection_real = pick($slave_connection, $::nova::slave_connection, false)
$database_idle_timeout_real = pick($database_idle_timeout, $::nova::database_idle_timeout, false)
if $database_connection_real {
if($database_connection_real =~ /mysql:\/\/\S+:\S+@\S+\/\S+/) {
require 'mysql::bindings'
require 'mysql::bindings::python'
} elsif($database_connection_real =~ /postgresql:\/\/\S+:\S+@\S+\/\S+/) {
} elsif($database_connection_real =~ /sqlite:\/\//) {
} else {
fail("Invalid db connection ${database_connection_real}")
}
nova_config {
'database/connection': value => $database_connection_real, secret => true;
'database/idle_timeout': value => $database_idle_timeout_real;
}
if $slave_connection_real {
nova_config {
'database/slave_connection': value => $slave_connection_real, secret => true;
}
} else {
nova_config {
'database/slave_connection': ensure => absent;
}
}
}
}

View File

@ -21,11 +21,11 @@
#
# [*charset*]
# (optional) The charset to use for the nova database
# Defaults to 'latin1'
# Defaults to 'utf8'
#
# [*collate*]
# (optional) The collate to use for the nova database
# Defaults to 'latin1_swedish_ci'
# Defaults to 'utf8_general_ci'
#
# [*allowed_hosts*]
# (optional) Additional hosts that are allowed to access this DB
@ -36,64 +36,32 @@
# Defaults to 'localzone'
#
# [*mysql_module*]
# (optional) Mysql puppet module version to use. Tested versions
# are 0.9 and 2.2.
# Defaults to '0.9'
# (optional) Deprecated. Does nothing.
#
class nova::db::mysql(
$password,
$dbname = 'nova',
$user = 'nova',
$host = '127.0.0.1',
$charset = 'latin1',
$collate = 'latin1_swedish_ci',
$charset = 'utf8',
$collate = 'utf8_general_ci',
$allowed_hosts = undef,
$mysql_module = '0.9',
$cluster_id = undef
$mysql_module = undef,
) {
if $cluster_id {
warning('The cluster_id parameter is deprecated and has no effect.')
if $mysql_module {
warning('The mysql_module parameter is deprecated. The latest 2.x mysql module will be used.')
}
if ($mysql_module >= 2.2) {
mysql::db { $dbname:
user => $user,
password => $password,
host => $host,
charset => $charset,
collate => $collate,
require => Class['mysql::server'],
}
} else {
require 'mysql::python'
mysql::db { $dbname:
user => $user,
password => $password,
host => $host,
charset => $charset,
require => Class['mysql::config'],
}
::openstacklib::db::mysql { 'nova':
user => $user,
password_hash => mysql_password($password),
dbname => $dbname,
host => $host,
charset => $charset,
collate => $collate,
allowed_hosts => $allowed_hosts,
}
# Create the db instance before openstack-nova if its installed
Mysql::Db[$dbname] -> Anchor<| title == 'nova-start' |>
Mysql::Db[$dbname] ~> Exec<| title == 'nova-db-sync' |>
# Check allowed_hosts to avoid duplicate resource declarations
if is_array($allowed_hosts) and delete($allowed_hosts,$host) != [] {
$real_allowed_hosts = delete($allowed_hosts,$host)
} elsif is_string($allowed_hosts) and ($allowed_hosts != $host) {
$real_allowed_hosts = $allowed_hosts
}
if $real_allowed_hosts {
nova::db::mysql::host_access { $real_allowed_hosts:
user => $user,
password => $password,
database => $dbname,
mysql_module => $mysql_module,
}
}
::Openstacklib::Db::Mysql['nova'] ~> Exec<| title == 'nova-db-sync' |>
}

View File

@ -1,29 +0,0 @@
# db/allowed_hosts.pp
define nova::db::mysql::host_access ($user, $password, $database, $mysql_module = '0.9') {
if ($mysql_module >= 2.2) {
mysql_user { "${user}@${name}":
password_hash => mysql_password($password),
require => Mysql_database[$database],
}
mysql_grant { "${user}@${name}/${database}.*":
privileges => ['ALL'],
options => ['GRANT'],
table => "${database}.*",
require => Mysql_user["${user}@${name}"],
user => "${user}@${name}"
}
} else {
database_user { "${user}@${name}":
password_hash => mysql_password($password),
provider => 'mysql',
require => Database[$database],
}
database_grant { "${user}@${name}/${database}":
# TODO figure out which privileges to grant.
privileges => 'all',
provider => 'mysql',
require => Database_user["${user}@${name}"]
}
}
}

View File

@ -3,34 +3,44 @@
# Class that configures postgresql for nova
# Requires the Puppetlabs postgresql module.
#
# === Parameters:
# === Parameters
#
# [*password*]
# Password to use to connect to postgresql
# (Required) Password to connect to the database.
#
# [*dbname*]
# (optional) Name of the database to create for nova
# Defaults to 'nova'
# (Optional) Name of the database.
# Defaults to 'nova'.
#
# [*user*]
# (optional) Name of the user to connect to postgresql
# Defaults to 'nova'
# (Optional) User to connect to the database.
# Defaults to 'nova'.
#
# [*encoding*]
# (Optional) The charset to use for the database.
# Default to undef.
#
# [*privileges*]
# (Optional) Privileges given to the database user.
# Default to 'ALL'
#
class nova::db::postgresql(
$password,
$dbname = 'nova',
$user = 'nova'
$dbname = 'nova',
$user = 'nova',
$encoding = undef,
$privileges = 'ALL',
) {
require 'postgresql::python'
Postgresql::Server::Db[$dbname] -> Anchor<| title == 'nova-start' |>
Postgresql::Server::Db[$dbname] ~> Exec<| title == 'nova-db-sync' |>
Package['python-psycopg2'] -> Exec<| title == 'nova-db-sync' |>
postgresql::server::db { $dbname:
user => $user,
password => $password,
::openstacklib::db::postgresql { 'nova':
password_hash => postgresql_password($user, $password),
dbname => $dbname,
user => $user,
encoding => $encoding,
privileges => $privileges,
}
::Openstacklib::Db::Postgresql['nova'] ~> Exec<| title == 'nova-db-sync' |>
::Openstacklib::Db::Postgresql['nova'] -> Anchor<| title == 'nova-start' |>
}

View File

@ -18,7 +18,7 @@ define nova::generic_service(
$ensure_package = 'present'
) {
include nova::params
include ::nova::params
$nova_title = "nova-${name}"
# ensure that the service is only started after
@ -32,13 +32,22 @@ define nova::generic_service(
# I need to mark that ths package should be
# installed before nova_config
if ($package_name) {
if !defined(Package[$package_name]) {
if !defined(Package[$nova_title]) and !defined(Package[$package_name]) {
package { $nova_title:
ensure => $ensure_package,
name => $package_name,
notify => Service[$nova_title],
tag => ['openstack'],
}
}
if $service_name {
# Do the dependency relationship here in case the package
# has been defined elsewhere, either as Package[$nova_title]
# or Package[$package_name]
Package<| title == $nova_title |> -> Service[$nova_title]
Package<| title == $package_name |> -> Service[$nova_title]
}
}
if $service_name {
@ -54,9 +63,8 @@ define nova::generic_service(
ensure => $service_ensure,
name => $service_name,
enable => $enabled,
hasstatus => true,
hasrestart => true,
require => [Package['nova-common'], Package[$package_name]],
hasstatus => true,
require => [Package['nova-common']],
}
}
}

View File

@ -9,31 +9,24 @@
# (optional) The state of nova packages
# Defaults to 'present'
#
# [*nova_cluster_id*]
# (optional) Deprecated. This parameter does nothing and will be removed.
# Defaults to 'localcluster'
#
# [*sql_connection*]
# (optional) Deprecated. Use database_connection instead.
# Defaults to false
#
# [*sql_idle_timeout*]
# (optional) Deprecated. Use database_idle_timeout instead
# Defaults to false
#
# [*database_connection*]
# (optional) Connection url to connect to nova database.
# Defaults to false
#
# [*slave_connection*]
# (optional) Connection url to connect to nova slave database (read-only).
# Defaults to false
#
# [*database_idle_timeout*]
# (optional) Timeout before idle db connections are reaped.
# Defaults to 3600
#
# [*rpc_backend*]
# (optional) The rpc backend implementation to use, can be:
# nova.openstack.common.rpc.impl_kombu (for rabbitmq)
# nova.openstack.common.rpc.impl_qpid (for qpid)
# Defaults to 'nova.openstack.common.rpc.impl_kombu'
# rabbit (for rabbitmq)
# qpid (for qpid)
# zmq (for zeromq)
# Defaults to 'rabbit'
#
# [*image_service*]
# (optional) Service used to search for and retrieve images.
@ -75,6 +68,10 @@
# (optional) Connect over SSL for RabbitMQ
# Defaults to false
#
# [*rabbit_ha_queues*]
# (optional) Use HA queues in RabbitMQ.
# Defaults to undef
#
# [*kombu_ssl_ca_certs*]
# (optional) SSL certification authority file (valid only if SSL enabled).
# Defaults to undef
@ -91,7 +88,7 @@
# (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 'SSLv3'
# Defaults to 'TLSv1'
#
# [*amqp_durable_queues*]
# (optional) Define queues as "durable" to rabbitmq.
@ -129,14 +126,14 @@
# (optional) Disable Nagle algorithm
# Defaults to true
#
# [*auth_strategy*]
# (optional) The strategy to use for auth: noauth or keystone.
# Defaults to 'keystone'
#
# [*service_down_time*]
# (optional) Maximum time since last check-in for up service.
# Defaults to 60
#
# [*logdir*]
# (optional) Deprecated. Use log_dir instead.
# Defaults to false
#
# [*log_dir*]
# (optional) Directory where logs should be stored.
# If set to boolean false, it will not log to any directory.
@ -155,6 +152,10 @@
# (optional) Set log output to verbose output.
# Defaults to false
#
# [*debug*]
# (optional) Set log output to debug output.
# Defaults to false
#
# [*periodic_interval*]
# (optional) Seconds between running periodic tasks.
# Defaults to '60'
@ -163,9 +164,9 @@
# (optional) Interval at which nodes report to data store.
# Defaults to '10'
#
# [*monitoring_notifications*]
# (optional) Whether or not to send system usage data notifications out on the message queue. Only valid for stable/essex.
# Defaults to false
# [*rootwrap_config*]
# (optional) Path to the rootwrap configuration file to use for running commands as root
# Defaults to '/etc/nova/rootwrap.conf'
#
# [*use_syslog*]
# (optional) Use syslog for logging
@ -175,19 +176,30 @@
# (optional) Syslog facility to receive log lines.
# Defaults to 'LOG_USER'
#
# [*nova_user_id*]
# (optional) Create the nova user with the specified gid.
# Changing to a new uid after specifying a different uid previously,
# or using this option after the nova account already exists will break
# the ownership of all files/dirs owned by nova.
# Defaults to undef.
# [*install_utilities*]
# (optional) Install nova utilities (Extra packages used by nova tools)
# Defaults to true,
#
# [*nova_group_id*]
# (optional) Create the nova user with the specified gid.
# Changing to a new uid after specifying a different uid previously,
# or using this option after the nova account already exists will break
# the ownership of all files/dirs owned by nova.
# Defaults to undef.
# [*use_ssl*]
# (optional) Enable SSL on the API server
# Defaults to false, not set
#
# [*enabled_ssl_apis*]
# (optional) List of APIs to SSL enable
# Defaults to []
# Possible values : 'ec2', 'osapi_compute', 'metadata'
#
# [*cert_file*]
# (optinal) Certificate file to use when starting API server securely
# Defaults to false, not set
#
# [*key_file*]
# (optional) Private key file to use when starting API server securely
# Defaults to false, not set
#
# [*ca_file*]
# (optional) CA certificate file to use to verify connecting clients
# Defaults to false, not set_
#
# [*nova_public_key*]
# (optional) Install public key in .ssh/authorized_keys for the 'nova' user.
@ -201,14 +213,8 @@
# 'key-data' }, where 'key-type' is one of (ssh-rsa, ssh-dsa, ssh-ecdsa) and
# 'key-data' is the contents of the private key file.
#
# [*nova_shell*]
# (optional) Set shell for 'nova' user to the specified value.
# Defaults to '/bin/false'.
#
# [*mysql_module*]
# (optional) Mysql module version to use. Tested versions
# are 0.9 and 2.2
# Defaults to '0.9'
# (optional) Deprecated. Does nothing.
#
# [*notification_driver*]
# (optional) Driver or drivers to handle sending notifications.
@ -231,11 +237,20 @@
# for notifications on VM and task state changes.
# Defaults to undef
#
# [*os_region_name*]
# (optional) Sets the os_region_name flag. For environments with
# more than one endpoint per service, this is required to make
# things such as cinder volume attach work. If you don't set this
# and you have multiple endpoints, you will get AmbiguousEndpoint
# exceptions in the nova API service.
# Defaults to undef
#
class nova(
$ensure_package = 'present',
$database_connection = false,
$slave_connection = false,
$database_idle_timeout = 3600,
$rpc_backend = 'nova.openstack.common.rpc.impl_kombu',
$rpc_backend = 'rabbit',
$image_service = 'nova.image.glance.GlanceImageService',
# these glance params should be optional
# this should probably just be configured as a glance client
@ -248,10 +263,11 @@ class nova(
$rabbit_userid = 'guest',
$rabbit_virtual_host = '/',
$rabbit_use_ssl = false,
$rabbit_ha_queues = undef,
$kombu_ssl_ca_certs = undef,
$kombu_ssl_certfile = undef,
$kombu_ssl_keyfile = undef,
$kombu_ssl_version = 'SSLv3',
$kombu_ssl_version = 'TLSv1',
$amqp_durable_queues = false,
$qpid_hostname = 'localhost',
$qpid_port = '5672',
@ -271,80 +287,88 @@ class nova(
$periodic_interval = '60',
$report_interval = '10',
$rootwrap_config = '/etc/nova/rootwrap.conf',
$nova_user_id = undef,
$nova_group_id = undef,
$use_ssl = false,
$enabled_ssl_apis = ['ec2', 'metadata', 'osapi_compute'],
$ca_file = false,
$cert_file = false,
$key_file = false,
$nova_public_key = undef,
$nova_private_key = undef,
$nova_shell = '/bin/false',
# deprecated in folsom
#$root_helper = $::nova::params::root_helper,
$monitoring_notifications = false,
$use_syslog = false,
$log_facility = 'LOG_USER',
$install_utilities = true,
$mysql_module = '0.9',
$notification_driver = [],
$notification_topics = 'notifications',
$notify_api_faults = false,
$notify_on_state_change = undef,
# DEPRECATED PARAMETERS
# this is how to query all resources from our clutser
$nova_cluster_id = undef,
$sql_connection = false,
$sql_idle_timeout = false,
$logdir = false,
$mysql_module = undef,
$os_region_name = undef,
) inherits nova::params {
if $nova_cluster_id {
warning('The nova_cluster_id parameter is deprecated and has no effect.')
# maintain backward compatibility
include ::nova::db
if $mysql_module {
warning('The mysql_module parameter is deprecated. The latest 2.x mysql module will be used.')
}
group { 'nova':
ensure => present,
system => true,
gid => $nova_group_id,
before => User['nova'],
validate_array($enabled_ssl_apis)
if empty($enabled_ssl_apis) and $use_ssl {
warning('enabled_ssl_apis is empty but use_ssl is set to true')
}
user { 'nova':
ensure => present,
system => true,
groups => 'nova',
home => '/var/lib/nova',
managehome => false,
shell => $nova_shell,
uid => $nova_user_id,
gid => $nova_group_id,
if $use_ssl {
if !$cert_file {
fail('The cert_file parameter is required when use_ssl is set to true')
}
if !$key_file {
fail('The key_file parameter is required when use_ssl is set to true')
}
}
if $kombu_ssl_ca_certs and !$rabbit_use_ssl {
fail('The kombu_ssl_ca_certs parameter requires rabbit_use_ssl to be set to true')
}
if $kombu_ssl_certfile and !$rabbit_use_ssl {
fail('The kombu_ssl_certfile parameter requires rabbit_use_ssl to be set to true')
}
if $kombu_ssl_keyfile and !$rabbit_use_ssl {
fail('The kombu_ssl_keyfile parameter requires rabbit_use_ssl to be set to true')
}
if ($kombu_ssl_certfile and !$kombu_ssl_keyfile) or ($kombu_ssl_keyfile and !$kombu_ssl_certfile) {
fail('The kombu_ssl_certfile and kombu_ssl_keyfile parameters must be used together')
}
if $nova_public_key or $nova_private_key {
file { '/var/lib/nova/.ssh':
ensure => directory,
mode => '0700',
owner => nova,
group => nova,
ensure => directory,
mode => '0700',
owner => 'nova',
group => 'nova',
require => Package['nova-common'],
}
if $nova_public_key {
if ! $nova_public_key[key] or ! $nova_public_key[type] {
if ! $nova_public_key['key'] or ! $nova_public_key['type'] {
fail('You must provide both a key type and key data.')
}
ssh_authorized_key { 'nova-migration-public-key':
ensure => present,
key => $nova_public_key[key],
type => $nova_public_key[type],
key => $nova_public_key['key'],
type => $nova_public_key['type'],
user => 'nova',
require => File['/var/lib/nova/.ssh'],
}
}
if $nova_private_key {
if ! $nova_private_key[key] or ! $nova_private_key[type] {
if ! $nova_private_key[key] or ! $nova_private_key['type'] {
fail('You must provide both a key type and key data.')
}
$nova_private_key_file = $nova_private_key[type] ? {
$nova_private_key_file = $nova_private_key['type'] ? {
'ssh-rsa' => '/var/lib/nova/.ssh/id_rsa',
'ssh-dsa' => '/var/lib/nova/.ssh/id_dsa',
'ssh-ecdsa' => '/var/lib/nova/.ssh/id_ecdsa',
@ -352,15 +376,15 @@ class nova(
}
if ! $nova_private_key_file {
fail("Unable to determine name of private key file. Type specified was '${nova_private_key[type]}' but should be one of: ssh-rsa, ssh-dsa, ssh-ecdsa.")
fail("Unable to determine name of private key file. Type specified was '${nova_private_key['type']}' but should be one of: ssh-rsa, ssh-dsa, ssh-ecdsa.")
}
file { $nova_private_key_file:
content => $nova_private_key[key],
mode => '0600',
owner => nova,
group => nova,
require => File['/var/lib/nova/.ssh'],
owner => 'nova',
group => 'nova',
require => [ File['/var/lib/nova/.ssh'], Package['nova-common'] ],
}
}
}
@ -373,24 +397,14 @@ class nova(
Package['nova-common'] -> Nova_config<| |> -> File['/etc/nova/nova.conf']
Nova_config<| |> ~> Exec['post-nova_config']
File {
require => Package['nova-common'],
owner => 'nova',
group => 'nova',
}
# TODO - see if these packages can be removed
# they should be handled as package deps by the OS
package { 'python':
ensure => present,
}
package { 'python-greenlet':
ensure => present,
require => Package['python'],
}
if $install_utilities {
class { 'nova::utilities': }
class { '::nova::utilities': }
}
# this anchor is used to simplify the graph between nova components by
@ -399,17 +413,22 @@ class nova(
package { 'python-nova':
ensure => $ensure_package,
require => Package['python-greenlet']
require => Package['python-greenlet'],
tag => ['openstack'],
}
package { 'nova-common':
ensure => $ensure_package,
name => $::nova::params::common_package_name,
require => [Package['python-nova'], Anchor['nova-start'], User['nova']]
require => [Package['python-nova'], Anchor['nova-start']],
tag => ['openstack'],
}
file { '/etc/nova/nova.conf':
mode => '0640',
mode => '0640',
owner => 'nova',
group => 'nova',
require => Package['nova-common'],
}
# used by debian/ubuntu in nova::network_bridge to refresh
@ -419,48 +438,11 @@ class nova(
refreshonly => true,
}
if $sql_connection {
warning('The sql_connection parameter is deprecated, use database_connection instead.')
$database_connection_real = $sql_connection
} else {
$database_connection_real = $database_connection
}
if $sql_idle_timeout {
warning('The sql_idle_timeout parameter is deprecated, use database_idle_timeout instead.')
$database_idle_timeout_real = $sql_idle_timeout
} else {
$database_idle_timeout_real = $database_idle_timeout
}
# both the database_connection and rabbit_host are things
# that may need to be collected from a remote host
if $database_connection_real {
if($database_connection_real =~ /mysql:\/\/\S+:\S+@\S+\/\S+/) {
if ($mysql_module >= 2.2) {
require 'mysql::bindings'
require 'mysql::bindings::python'
} else {
require 'mysql::python'
}
} elsif($database_connection_real =~ /postgresql:\/\/\S+:\S+@\S+\/\S+/) {
} elsif($database_connection_real =~ /sqlite:\/\//) {
} else {
fail("Invalid db connection ${database_connection_real}")
}
nova_config {
'database/connection': value => $database_connection_real, secret => true;
'database/idle_timeout': value => $database_idle_timeout_real;
}
}
nova_config { 'DEFAULT/image_service': value => $image_service }
if $image_service == 'nova.image.glance.GlanceImageService' {
if $glance_api_servers {
nova_config { 'DEFAULT/glance_api_servers': value => $glance_api_servers }
nova_config { 'glance/api_servers': value => $glance_api_servers }
}
}
@ -472,61 +454,74 @@ class nova(
nova_config { 'DEFAULT/memcached_servers': ensure => absent }
}
if $rpc_backend == 'nova.openstack.common.rpc.impl_kombu' {
# we keep "nova.openstack.common.rpc.impl_kombu" for backward compatibility
# but since Icehouse, "rabbit" is enough.
if $rpc_backend == 'nova.openstack.common.rpc.impl_kombu' or $rpc_backend == 'rabbit' {
# I may want to support exporting and collecting these
nova_config {
'DEFAULT/rabbit_password': value => $rabbit_password, secret => true;
'DEFAULT/rabbit_userid': value => $rabbit_userid;
'DEFAULT/rabbit_virtual_host': value => $rabbit_virtual_host;
'DEFAULT/rabbit_use_ssl': value => $rabbit_use_ssl;
'oslo_messaging_rabbit/rabbit_password': value => $rabbit_password, secret => true;
'oslo_messaging_rabbit/rabbit_userid': value => $rabbit_userid;
'oslo_messaging_rabbit/rabbit_virtual_host': value => $rabbit_virtual_host;
'oslo_messaging_rabbit/rabbit_use_ssl': value => $rabbit_use_ssl;
'DEFAULT/amqp_durable_queues': value => $amqp_durable_queues;
}
if $rabbit_use_ssl {
if $kombu_ssl_ca_certs {
nova_config { 'DEFAULT/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs }
nova_config { 'oslo_messaging_rabbit/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs; }
} else {
nova_config { 'DEFAULT/kombu_ssl_ca_certs': ensure => absent}
nova_config { 'oslo_messaging_rabbit/kombu_ssl_ca_certs': ensure => absent; }
}
if $kombu_ssl_certfile {
nova_config { 'DEFAULT/kombu_ssl_certfile': value => $kombu_ssl_certfile }
if $kombu_ssl_certfile or $kombu_ssl_keyfile {
nova_config {
'oslo_messaging_rabbit/kombu_ssl_certfile': value => $kombu_ssl_certfile;
'oslo_messaging_rabbit/kombu_ssl_keyfile': value => $kombu_ssl_keyfile;
}
} else {
nova_config { 'DEFAULT/kombu_ssl_certfile': ensure => absent}
}
if $kombu_ssl_keyfile {
nova_config { 'DEFAULT/kombu_ssl_keyfile': value => $kombu_ssl_keyfile }
} else {
nova_config { 'DEFAULT/kombu_ssl_keyfile': ensure => absent}
nova_config {
'oslo_messaging_rabbit/kombu_ssl_certfile': ensure => absent;
'oslo_messaging_rabbit/kombu_ssl_keyfile': ensure => absent;
}
}
if $kombu_ssl_version {
nova_config { 'DEFAULT/kombu_ssl_version': value => $kombu_ssl_version }
nova_config { 'oslo_messaging_rabbit/kombu_ssl_version': value => $kombu_ssl_version; }
} else {
nova_config { 'DEFAULT/kombu_ssl_version': ensure => absent}
nova_config { 'oslo_messaging_rabbit/kombu_ssl_version': ensure => absent; }
}
} else {
nova_config {
'DEFAULT/kombu_ssl_ca_certs': ensure => absent;
'DEFAULT/kombu_ssl_certfile': ensure => absent;
'DEFAULT/kombu_ssl_keyfile': ensure => absent;
'DEFAULT/kombu_ssl_version': ensure => absent;
'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 $rabbit_hosts {
nova_config { 'DEFAULT/rabbit_hosts': value => join($rabbit_hosts, ',') }
nova_config { 'DEFAULT/rabbit_ha_queues': value => true }
nova_config { 'oslo_messaging_rabbit/rabbit_hosts': value => join($rabbit_hosts, ',') }
} else {
nova_config { 'DEFAULT/rabbit_host': value => $rabbit_host }
nova_config { 'DEFAULT/rabbit_port': value => $rabbit_port }
nova_config { 'DEFAULT/rabbit_hosts': value => "${rabbit_host}:${rabbit_port}" }
nova_config { 'DEFAULT/rabbit_ha_queues': value => false }
nova_config { 'oslo_messaging_rabbit/rabbit_host': value => $rabbit_host }
nova_config { 'oslo_messaging_rabbit/rabbit_port': value => $rabbit_port }
nova_config { 'oslo_messaging_rabbit/rabbit_hosts': value => "${rabbit_host}:${rabbit_port}" }
}
if $rabbit_ha_queues == undef {
if $rabbit_hosts {
nova_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => true }
} else {
nova_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => false }
}
} else {
nova_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => $rabbit_ha_queues }
}
}
if $rpc_backend == 'nova.openstack.common.rpc.impl_qpid' {
# we keep "nova.openstack.common.rpc.impl_qpid" for backward compatibility
# but since Icehouse, "qpid" is enough.
if $rpc_backend == 'nova.openstack.common.rpc.impl_qpid' or $rpc_backend == 'qpid' {
nova_config {
'DEFAULT/qpid_hostname': value => $qpid_hostname;
'DEFAULT/qpid_port': value => $qpid_port;
@ -553,31 +548,47 @@ class nova(
}
}
if $logdir {
warning('The logdir parameter is deprecated, use log_dir instead.')
$log_dir_real = $logdir
# SSL Options
if $use_ssl {
nova_config {
'DEFAULT/enabled_ssl_apis' : value => join($enabled_ssl_apis, ',');
'DEFAULT/ssl_cert_file' : value => $cert_file;
'DEFAULT/ssl_key_file' : value => $key_file;
}
if $ca_file {
nova_config { 'DEFAULT/ssl_ca_file' :
value => $ca_file,
}
} else {
nova_config { 'DEFAULT/ssl_ca_file' :
ensure => absent,
}
}
} else {
$log_dir_real = $log_dir
nova_config {
'DEFAULT/enabled_ssl_apis' : ensure => absent;
'DEFAULT/ssl_cert_file' : ensure => absent;
'DEFAULT/ssl_key_file' : ensure => absent;
'DEFAULT/ssl_ca_file' : ensure => absent;
}
}
if $log_dir_real {
file { $log_dir_real:
if $log_dir {
file { $log_dir:
ensure => directory,
mode => '0750',
owner => 'nova',
group => $::nova::params::nova_log_group,
require => Package['nova-common'],
}
nova_config { 'DEFAULT/log_dir': value => $log_dir_real;}
nova_config { 'DEFAULT/log_dir': value => $log_dir;}
} else {
nova_config { 'DEFAULT/log_dir': ensure => absent;}
}
if $monitoring_notifications {
warning('The monitoring_notifications parameter is deprecated, use notification_driver instead.')
$notification_driver_real = 'nova.openstack.common.notifier.rpc_notifier'
} else {
$notification_driver_real = is_string($notification_driver) ? {
true => $notification_driver,
default => join($notification_driver, ',')
}
$notification_driver_real = is_string($notification_driver) ? {
true => $notification_driver,
default => join($notification_driver, ',')
}
nova_config {
@ -615,6 +626,17 @@ class nova(
}
}
if $os_region_name {
nova_config {
'DEFAULT/os_region_name': value => $os_region_name;
}
}
else {
nova_config {
'DEFAULT/os_region_name': ensure => absent;
}
}
exec { 'post-nova_config':
command => '/bin/echo "Nova config has changed"',
refreshonly => true,

View File

@ -11,29 +11,55 @@
# (optional) The name of the nova service user
# Defaults to 'nova'
#
# [*public_address*]
# (optional) The public nova-api endpoint
# Defaults to '127.0.0.1'
# [*auth_name_v3*]
# (optional) The name of the nova v3 service user
# Defaults to 'novav3'
#
# [*admin_address*]
# (optional) The admin nova-api endpoint
# Defaults to '127.0.0.1'
# [*service_name*]
# (optional) Name of the service.
# Defaults to the value of auth_name, but must differ from the value
# of service_name_v3.
#
# [*internal_address*]
# (optional) The internal nova-api endpoint
# Defaults to '127.0.0.1'
# [*service_name_v3*]
# (optional) Name of the v3 service.
# Defaults to the value of auth_name_v3, but must differ from the value
# of service_name.
#
# [*compute_port*]
# (optional) The port to use for the compute endpoint
# Defaults to '8774'
# [*public_url*]
# (optional) The endpoint's public url. (Defaults to 'http://127.0.0.1:8774/v2/%(tenant_id)s')
# This url should *not* contain any version or trailing '/'.
#
# [*ec2_port*]
# (optional) The port to use for the ec2 endpoint
# Defaults to '8773'
# [*internal_url*]
# (optional) The endpoint's internal url. (Defaults to 'http://127.0.0.1:8774/v2/%(tenant_id)s')
# This url should *not* contain any version or trailing '/'.
#
# [*compute_version*]
# (optional) The version of the compute api to put in the endpoint
# Defaults to 'v2'
# [*admin_url*]
# (optional) The endpoint's admin url. (Defaults to 'http://127.0.0.1:8774/v2/%(tenant_id)s')
# This url should *not* contain any version or trailing '/'.
#
# [*public_url_v3*]
# (optional) The v3 endpoint's public url. (Defaults to 'http://127.0.0.1:8774/v3')
# This url should *not* contain any version or trailing '/'.
#
# [*internal_url_v3*]
# (optional) The v3 endpoint's internal url. (Defaults to 'http://127.0.0.1:8774/v3')
# This url should *not* contain any version or trailing '/'.
#
# [*admin_url_v3*]
# (optional) The v3 endpoint's admin url. (Defaults to 'http://127.0.0.1:8774/v3')
# This url should *not* contain any version or trailing '/'.
#
# [*ec2_public_url*]
# (optional) The endpoint's public url for EC2.
# (Defaults to 'http://127.0.0.1:8773/services/Cloud')
#
# [*ec2_internal_url*]
# (optional) The endpoint's internal url for EC2.
# (Defaults to 'http://127.0.0.1:8773/services/Cloud')
#
# [*ec2_admin_url*]
# (optional) The endpoint's admin url for EC2.
# (Defaults to 'http://127.0.0.1:8773/services/Admin')
#
# [*region*]
# (optional) The region in which to place the endpoints
@ -55,82 +81,275 @@
# (optional) Whether to create the endpoint.
# Defaults to true
#
# [*cinder*]
# (optional) Deprecated and has no effect
# Defaults to undef
# [*configure_endpoint_v3*]
# (optional) Whether to create the v3 endpoint.
# Defaults to true
#
# [*configure_user*]
# (optional) Whether to create the service user.
# Defaults to true
#
# [*configure_user_role*]
# (optional) Whether to configure the admin role for the service user.
# Defaults to true
#
# [*compute_version*]
# (optional) DEPRECATED: Use public_url, internal_url and admin_url OR
# public_url_v3, internal_url_v3 and admin_url_v3 instead.
# The version of the compute api to put in the endpoint. (Defaults to v2)
# Setting this parameter overrides public_url, internal_url and admin_url parameters.
#
# [*compute_port*]
# (optional) DEPRECATED: Use public_url, internal_url and admin_url instead.
# Port for endpoint. (Defaults to 9696)
# Setting this parameter overrides public_url, internal_url and admin_url parameters.
#
# [*ec2_port*]
# (optional) DEPRECATED: Use ec2_public_url, ec2_internal_url and ec2_admin_url instead.
# (optional) The port to use for the ec2 endpoint. (Defaults to 8773)
#
# [*public_protocol*]
# (optional) Protocol to use for the public endpoint. Can be http or https.
# Defaults to 'http'
# (optional) DEPRECATED: Use public_url and ec2_public_url instead.
# Protocol for public endpoint. (Defaults to 'http')
# Setting this parameter overrides public_url and ec2_public_url parameters.
#
# [*admin_protocol*]
# Protocol for admin endpoints. Defaults to 'http'.
# [*public_address*]
# (optional) DEPRECATED: Use public_url and ec2_public_url instead.
# Public address for endpoint. (Defaults to '127.0.0.1')
# Setting this parameter overrides public_url and ec2_public_url parameters.
#
# [*internal_protocol*]
# Protocol for internal endpoints. Defaults to 'http'.
# (optional) DEPRECATED: Use internal_url and ec2_internal_url instead.
# Protocol for internal endpoint. (Defaults to 'http')
# Setting this parameter overrides internal_url and ec2_internal_url parameters.
#
# [*internal_address*]
# (optional) DEPRECATED: Use internal_url and ec2_internal_url instead.
# Internal address for endpoint. (Defaults to '127.0.0.1')
# Setting this parameter overrides internal_url and ec2_internal_url parameters.
#
# [*admin_protocol*]
# (optional) DEPRECATED: Use admin_url and ec2_admin_url instead.
# Protocol for admin endpoint. (Defaults to 'http')
# Setting this parameter overrides admin_url and ec2_admin_url parameters.
#
# [*admin_address*]
# (optional) DEPRECATED: Use admin_url and ec2_admin_url instead.
# Admin address for endpoint. (Defaults to '127.0.0.1')
# Setting this parameter overrides admin_url and ec2_admin_url parameters.
#
class nova::keystone::auth(
$password,
$auth_name = 'nova',
$public_address = '127.0.0.1',
$admin_address = '127.0.0.1',
$internal_address = '127.0.0.1',
$compute_port = '8774',
$ec2_port = '8773',
$compute_version = 'v2',
$auth_name_v3 = 'novav3',
$service_name = undef,
$service_name_v3 = undef,
$region = 'RegionOne',
$tenant = 'services',
$email = 'nova@localhost',
$public_url = 'http://127.0.0.1:8774/v2/%(tenant_id)s',
$internal_url = 'http://127.0.0.1:8774/v2/%(tenant_id)s',
$admin_url = 'http://127.0.0.1:8774/v2/%(tenant_id)s',
$public_url_v3 = 'http://127.0.0.1:8774/v3',
$internal_url_v3 = 'http://127.0.0.1:8774/v3',
$admin_url_v3 = 'http://127.0.0.1:8774/v3',
$ec2_public_url = 'http://127.0.0.1:8773/services/Cloud',
$ec2_internal_url = 'http://127.0.0.1:8773/services/Cloud',
$ec2_admin_url = 'http://127.0.0.1:8773/services/Admin',
$configure_ec2_endpoint = true,
$cinder = undef,
$public_protocol = 'http',
$configure_endpoint = true,
$admin_protocol = 'http',
$internal_protocol = 'http'
$configure_endpoint_v3 = true,
$configure_user = true,
$configure_user_role = true,
# DEPRECATED PARAMETERS
$compute_version = undef,
$compute_port = undef,
$ec2_port = undef,
$public_protocol = undef,
$public_address = undef,
$admin_protocol = undef,
$admin_address = undef,
$internal_protocol = undef,
$internal_address = undef,
) {
if $cinder != undef {
warning('The cinder parameter is deprecated and has no effect.')
if $compute_version {
warning('The compute_version parameter is deprecated, use public_url, internal_url and admin_url instead.')
}
Keystone_endpoint["${region}/${auth_name}"] ~> Service <| name == 'nova-api' |>
if $compute_port {
warning('The compute_port parameter is deprecated, use public_url, internal_url and admin_url instead.')
}
keystone_user { $auth_name:
ensure => present,
password => $password,
email => $email,
tenant => $tenant,
if $ec2_port {
warning('The ec2_port parameter is deprecated, use ec2_public_url, ec2_internal_url and ec2_admin_url instead.')
}
keystone_user_role { "${auth_name}@${tenant}":
ensure => present,
roles => 'admin',
if $public_protocol {
warning('The public_protocol parameter is deprecated, use public_url instead.')
if $configure_ec2_endpoint {
warning('The public_protocol parameter is deprecated, use ec2_public_url instead.')
}
}
keystone_service { $auth_name:
ensure => present,
type => 'compute',
description => 'Openstack Compute Service',
if $internal_protocol {
warning('The internal_protocol parameter is deprecated, use internal_url instead.')
if $configure_ec2_endpoint {
warning('The internal_protocol parameter is deprecated, use ec2_public_url instead.')
}
}
if $admin_protocol {
warning('The admin_protocol parameter is deprecated, use admin_url instead.')
if $configure_ec2_endpoint {
warning('The admin_protocol parameter is deprecated, use ec2_admin_url instead.')
}
}
if $public_address {
warning('The public_address parameter is deprecated, use public_url instead.')
if $configure_ec2_endpoint {
warning('The public_address parameter is deprecated, use ec2_public_url instead.')
}
}
if $internal_address {
warning('The internal_address parameter is deprecated, use internal_url instead.')
if $configure_ec2_endpoint {
warning('The internal_address parameter is deprecated, use ec2_internal_url instead.')
}
}
if $admin_address {
warning('The admin_address parameter is deprecated, use admin_url instead.')
if $configure_ec2_endpoint {
warning('The admin_address parameter is deprecated, use ec2_admin_url instead.')
}
}
if $service_name == undef {
$real_service_name = $auth_name
} else {
$real_service_name = $service_name
}
if $service_name_v3 == undef {
$real_service_name_v3 = $auth_name_v3
} else {
$real_service_name_v3 = $service_name_v3
}
if $real_service_name == $real_service_name_v3 {
fail('nova::keystone::auth parameters service_name and service_name_v3 must be different.')
}
if ($public_protocol or $public_address or $compute_port) {
$public_url_real = sprintf('%s://%s:%s/%s/%%(tenant_id)s',
pick($public_protocol, 'http'),
pick($public_address, '127.0.0.1'),
pick($compute_port, '8774'),
pick($compute_version, 'v2'))
} else {
$public_url_real = $public_url
}
if ($internal_protocol or $internal_address or $compute_port) {
$internal_url_real = sprintf('%s://%s:%s/%s/%%(tenant_id)s',
pick($internal_protocol, 'http'),
pick($internal_address, '127.0.0.1'),
pick($compute_port, '8774'),
pick($compute_version, 'v2'))
} else {
$internal_url_real = $internal_url
}
if ($admin_protocol or $admin_address or $compute_port) {
$admin_url_real = sprintf('%s://%s:%s/%s/%%(tenant_id)s',
pick($admin_protocol, 'http'),
pick($admin_address, '127.0.0.1'),
pick($compute_port, '8774'),
pick($compute_version, 'v2'))
} else {
$admin_url_real = $admin_url
}
# EC2 endpoints
if ($public_protocol or $public_address or $ec2_port) {
$ec2_public_url_real = sprintf('%s://%s:%s/services/Cloud',
pick($public_protocol, 'http'),
pick($public_address, '127.0.0.1'),
pick($ec2_port, '8773'))
} else {
$ec2_public_url_real = $ec2_public_url
}
if ($internal_protocol or $internal_address or $ec2_port) {
$ec2_internal_url_real = sprintf('%s://%s:%s/services/Cloud',
pick($internal_protocol, 'http'),
pick($internal_address, '127.0.0.1'),
pick($ec2_port, '8773'))
} else {
$ec2_internal_url_real = $ec2_internal_url
}
if ($admin_protocol or $admin_address or $ec2_port) {
$ec2_admin_url_real = sprintf('%s://%s:%s/services/Admin',
pick($admin_protocol, 'http'),
pick($admin_address, '127.0.0.1'),
pick($ec2_port, '8773'))
} else {
$ec2_admin_url_real = $ec2_admin_url
}
if $configure_endpoint {
keystone_endpoint { "${region}/${auth_name}":
ensure => present,
public_url => "${public_protocol}://${public_address}:${compute_port}/${compute_version}/%(tenant_id)s",
admin_url => "${admin_protocol}://${admin_address}:${compute_port}/${compute_version}/%(tenant_id)s",
internal_url => "${internal_protocol}://${internal_address}:${compute_port}/${compute_version}/%(tenant_id)s",
}
Keystone_endpoint["${region}/${real_service_name}"] ~> Service <| name == 'nova-api' |>
}
if $configure_ec2_endpoint {
keystone_service { "${auth_name}_ec2":
ensure => present,
type => 'ec2',
description => 'EC2 Service',
}
keystone_endpoint { "${region}/${auth_name}_ec2":
ensure => present,
public_url => "${public_protocol}://${public_address}:${ec2_port}/services/Cloud",
admin_url => "${admin_protocol}://${admin_address}:${ec2_port}/services/Admin",
internal_url => "${internal_protocol}://${internal_address}:${ec2_port}/services/Cloud",
}
keystone::resource::service_identity { "nova service, user ${auth_name}":
configure_user => $configure_user,
configure_user_role => $configure_user_role,
configure_endpoint => $configure_endpoint,
service_type => 'compute',
service_description => 'Openstack Compute Service',
service_name => $real_service_name,
region => $region,
auth_name => $auth_name,
password => $password,
email => $email,
tenant => $tenant,
public_url => $public_url_real,
admin_url => $admin_url_real,
internal_url => $internal_url_real,
}
keystone::resource::service_identity { "nova v3 service, user ${auth_name_v3}":
configure_user => false,
configure_user_role => false,
configure_endpoint => $configure_endpoint_v3,
configure_service => $configure_endpoint_v3,
service_type => 'computev3',
service_description => 'Openstack Compute Service v3',
service_name => $real_service_name_v3,
region => $region,
auth_name => $auth_name_v3,
public_url => $public_url_v3,
admin_url => $admin_url_v3,
internal_url => $internal_url_v3,
}
keystone::resource::service_identity { "nova ec2 service, user ${auth_name}_ec2":
configure_user => false,
configure_user_role => false,
configure_endpoint => $configure_ec2_endpoint,
configure_service => $configure_ec2_endpoint,
service_type => 'ec2',
service_description => 'EC2 Service',
service_name => "${real_service_name}_ec2",
region => $region,
auth_name => "${auth_name}_ec2",
public_url => $ec2_public_url_real,
admin_url => $ec2_admin_url_real,
internal_url => $ec2_internal_url_real,
}
}

View File

@ -1,23 +0,0 @@
class nova::limits ($limits = {})
{
$default_limits = {
'POST' => 10,
'POST_SERVERS' => 50,
'PUT' => 10,
'GET' => 3,
'DELETE' => 100,
}
$merged_limits = merge($default_limits, $limits)
$post_limit=$merged_limits[POST]
$put_limit=$merged_limits[PUT]
$get_limit=$merged_limits[GET]
$delete_limit=$merged_limits[DELETE]
$post_servers_limit=$merged_limits[POST_SERVERS]
Package<| title == 'nova-common' |> -> Nova_paste_api_ini<| |>
nova_paste_api_ini {'filter:ratelimit/limits': value => "(POST, \"*\", .*, ${post_limit}, MINUTE);(POST, \"*/servers\", ^/servers, ${post_servers_limit}, DAY);(PUT, \"*\", .*, ${put_limit}, MINUTE);(GET, \"*changes-since*\", .*changes-since.*, ${get_limit}, MINUTE);(DELETE, \"*\", .*, ${delete_limit}, MINUTE)"}
}

View File

@ -0,0 +1,208 @@
# Class nova::logging
#
# nova extended logging configuration
#
# == parameters
#
# [*logging_context_format_string*]
# (optional) Format string to use for log messages with context.
# Defaults to undef.
# Example: '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s\
# [%(request_id)s %(user_identity)s] %(instance)s%(message)s'
#
# [*logging_default_format_string*]
# (optional) Format string to use for log messages without context.
# Defaults to undef.
# Example: '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s\
# [-] %(instance)s%(message)s'
#
# [*logging_debug_format_suffix*]
# (optional) Formatted data to append to log format when level is DEBUG.
# Defaults to undef.
# Example: '%(funcName)s %(pathname)s:%(lineno)d'
#
# [*logging_exception_prefix*]
# (optional) Prefix each line of exception output with this format.
# Defaults to undef.
# Example: '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s'
#
# [*log_config_append*]
# The name of an additional logging configuration file.
# Defaults to undef.
# See https://docs.python.org/2/howto/logging.html
#
# [*default_log_levels*]
# (optional) Hash of logger (keys) and level (values) pairs.
# Defaults to undef.
# Example:
# { 'amqp' => 'WARN', 'amqplib' => 'WARN', 'boto' => 'WARN',
# 'qpid' => 'WARN', 'sqlalchemy' => 'WARN', 'suds' => 'INFO',
# 'iso8601' => 'WARN',
# 'requests.packages.urllib3.connectionpool' => 'WARN' }
#
# [*publish_errors*]
# (optional) Publish error events (boolean value).
# Defaults to undef (false if unconfigured).
#
# [*fatal_deprecations*]
# (optional) Make deprecations fatal (boolean value)
# Defaults to undef (false if unconfigured).
#
# [*instance_format*]
# (optional) If an instance is passed with the log message, format it
# like this (string value).
# Defaults to undef.
# Example: '[instance: %(uuid)s] '
#
# [*instance_uuid_format*]
# (optional) If an instance UUID is passed with the log message, format
# it like this (string value).
# Defaults to undef.
# Example: instance_uuid_format='[instance: %(uuid)s] '
# [*log_date_format*]
# (optional) Format string for %%(asctime)s in log records.
# Defaults to undef.
# Example: 'Y-%m-%d %H:%M:%S'
class nova::logging(
$logging_context_format_string = undef,
$logging_default_format_string = undef,
$logging_debug_format_suffix = undef,
$logging_exception_prefix = undef,
$log_config_append = undef,
$default_log_levels = undef,
$publish_errors = undef,
$fatal_deprecations = undef,
$instance_format = undef,
$instance_uuid_format = undef,
$log_date_format = undef,
) {
if $logging_context_format_string {
nova_config {
'DEFAULT/logging_context_format_string' :
value => $logging_context_format_string;
}
}
else {
nova_config {
'DEFAULT/logging_context_format_string' : ensure => absent;
}
}
if $logging_default_format_string {
nova_config {
'DEFAULT/logging_default_format_string' :
value => $logging_default_format_string;
}
}
else {
nova_config {
'DEFAULT/logging_default_format_string' : ensure => absent;
}
}
if $logging_debug_format_suffix {
nova_config {
'DEFAULT/logging_debug_format_suffix' :
value => $logging_debug_format_suffix;
}
}
else {
nova_config {
'DEFAULT/logging_debug_format_suffix' : ensure => absent;
}
}
if $logging_exception_prefix {
nova_config {
'DEFAULT/logging_exception_prefix' : value => $logging_exception_prefix;
}
}
else {
nova_config {
'DEFAULT/logging_exception_prefix' : ensure => absent;
}
}
if $log_config_append {
nova_config {
'DEFAULT/log_config_append' : value => $log_config_append;
}
}
else {
nova_config {
'DEFAULT/log_config_append' : ensure => absent;
}
}
if $default_log_levels {
nova_config {
'DEFAULT/default_log_levels' :
value => join(sort(join_keys_to_values($default_log_levels, '=')), ',');
}
}
else {
nova_config {
'DEFAULT/default_log_levels' : ensure => absent;
}
}
if $publish_errors {
nova_config {
'DEFAULT/publish_errors' : value => $publish_errors;
}
}
else {
nova_config {
'DEFAULT/publish_errors' : ensure => absent;
}
}
if $fatal_deprecations {
nova_config {
'DEFAULT/fatal_deprecations' : value => $fatal_deprecations;
}
}
else {
nova_config {
'DEFAULT/fatal_deprecations' : ensure => absent;
}
}
if $instance_format {
nova_config {
'DEFAULT/instance_format' : value => $instance_format;
}
}
else {
nova_config {
'DEFAULT/instance_format' : ensure => absent;
}
}
if $instance_uuid_format {
nova_config {
'DEFAULT/instance_uuid_format' : value => $instance_uuid_format;
}
}
else {
nova_config {
'DEFAULT/instance_uuid_format' : ensure => absent;
}
}
if $log_date_format {
nova_config {
'DEFAULT/log_date_format' : value => $log_date_format;
}
}
else {
nova_config {
'DEFAULT/log_date_format' : ensure => absent;
}
}
}

View File

@ -2,7 +2,7 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# Author: Emilien Macchi <emilien.macchi@enovance.com>
# François Charlier <francois.charlier@enovance.com>
# Francois Charlier <francois.charlier@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

View File

@ -1,21 +0,0 @@
# Class for creating floating ip range
# - ip_range = ['192.168.1.1-192.168.1.55','192.168.2.1-192.168.2.66']
class nova::manage::floating_range (
$ip_range,
$pool = 'nova',
$username = 'admin',
$api_key = 'nova',
$password = 'nova',
$auth_url = undef,
$authtenant_name = 'admin',
){
nova_floating_range{$ip_range:
ensure => 'present',
pool => $pool,
username => $username,
api_key => $api_key,
auth_method => $password,
auth_url => $auth_url,
authtenant_name => $authtenant_name,
}
}

View File

@ -25,8 +25,7 @@ define nova::manage::network (
$num_networks = 1,
$network_size = 255,
$vlan_start = undef,
$project = undef,
$nameservers = ['8.8.8.8','8.8.4.4']
$project = undef
) {
File['/etc/nova/nova.conf'] -> Nova_network[$name]
@ -40,8 +39,6 @@ define nova::manage::network (
network_size => $network_size,
project => $project,
vlan_start => $vlan_start,
dns1 => $nameservers[0],
dns2 => $nameservers[1]
}
}

View File

@ -30,9 +30,10 @@ class nova::migration::libvirt {
}
file_line { '/etc/sysconfig/libvirtd libvirtd args':
path => '/etc/sysconfig/libvirtd',
line => 'LIBVIRTD_ARGS="--listen"',
match => 'LIBVIRTD_ARGS=',
path => '/etc/sysconfig/libvirtd',
line => 'LIBVIRTD_ARGS="--listen"',
match => 'LIBVIRTD_ARGS=',
notify => Service['libvirt'],
}
Package['libvirt'] -> File_line<| path == '/etc/sysconfig/libvirtd' |>
@ -59,14 +60,14 @@ class nova::migration::libvirt {
match => 'auth_tcp =',
notify => Service['libvirt'],
}
file_line { '/etc/default/libvirt-bin libvirtd opts':
path => '/etc/default/libvirt-bin',
line => 'libvirtd_opts="-d -l"',
match => 'libvirtd_opts=',
file_line { "/etc/default/${::nova::compute::libvirt::libvirt_service_name} libvirtd opts":
path => "/etc/default/${::nova::compute::libvirt::libvirt_service_name}",
line => 'libvirtd_opts="-d -l"',
match => 'libvirtd_opts=',
notify => Service['libvirt'],
}
Package['libvirt'] -> File_line<| path == '/etc/default/libvirt-bin' |>
Package['libvirt'] -> File_line<| path == "/etc/default/${::nova::compute::libvirt::libvirt_service_name}" |>
}
default: {

View File

@ -1,8 +1,11 @@
# == Class: nova::network
#
# Manages nova-network. Note that
# Nova-network is not receiving upstream patches any more
# and Neutron should be used in its place
# Manages nova-network.
#
# An OpenStack deployment that includes compute and networking will use either
# nova-network or Neutron. Neutron is newer and nova-network is the legacy
# networking support built directly into Nova. However, nova-network is still
# fully supported, is not feature frozen, and is not yet officially deprecated.
#
# === Parameters:
#
@ -23,6 +26,10 @@
# split into.
# Defaults to 1
#
# [*network_size*]
# (optional) Number of addresses in each private subnet.
# Defaults to 255
#
# [*floating_range*]
# (optional) Range of floating ip addresses to create.
# Defaults to false
@ -64,11 +71,10 @@ class nova::network(
$config_overrides = {},
$create_networks = true,
$ensure_package = 'present',
$install_service = true,
$nameservers = ['8.8.8.8','8.8.4.4']
$install_service = true
) {
include nova::params
include ::nova::params
# forward all ipv4 traffic
# this is required for the vms to pass through the gateways
@ -77,16 +83,7 @@ class nova::network(
path => $::path
}
# NOTE(bogdando) contribute change to upstream #1384145
if !defined(Sysctl::Value['net.ipv4.ip_forward']) {
sysctl::value { 'net.ipv4.ip_forward':
value => '1'
}
} else {
Sysctl::Value<| name == 'net.ipv4.ip_forward' |> {
value => '1'
}
}
ensure_resource('sysctl::value', 'net.ipv4.ip_forward', { value => '1' })
if $floating_range {
nova_config { 'DEFAULT/floating_range': value => $floating_range }
@ -110,11 +107,10 @@ class nova::network(
if $create_networks {
nova::manage::network { 'nova-vm-net':
network => $fixed_range,
num_networks => $num_networks,
network_size => $network_size,
nameservers => $nameservers,
vlan_start => $vlan_start,
network => $fixed_range,
num_networks => $num_networks,
network_size => $network_size,
vlan_start => $vlan_start,
}
if $floating_range {
nova::manage::floating { 'nova-vm-floating':

View File

@ -7,7 +7,7 @@
# [*fixed_range*]
# (required) The IPv4 CIDR for the network
#
# [flat_interface]
# [*flat_interface*]
# (optional) Interface that flat network will use for bridging
# Defaults to undef
#
@ -15,7 +15,7 @@
# (optional) The interface to use for public traffic
# Defaults to undef
#
# [flat_network_bridge]
# [*flat_network_bridge*]
# (optional) The name of the bridge to use
# Defaults to 'br100'
#

View File

@ -57,6 +57,11 @@
# and not the Identity service API IP and port.
# Defaults to 'http://127.0.0.1:35357/v2.0'
#
# [*network_api_class*]
# (optional) The full class name of the network API class.
# The default configures Nova to use Neutron for the network API.
# Defaults to 'nova.network.neutronv2.api.API'
#
# [*security_group_api*]
# (optional) The full class name of the security API class.
# The default configures Nova to use Neutron for security groups.
@ -82,6 +87,10 @@
# notification is not being used.
# Defaults to '300'
#
# [*dhcp_domain*]
# (optional) domain to use for building the hostnames
# Defaults to 'novalocal'
#
class nova::network::neutron (
$neutron_admin_password,
$neutron_auth_strategy = 'keystone',
@ -95,35 +104,38 @@ class nova::network::neutron (
$neutron_ovs_bridge = 'br-int',
$neutron_extension_sync_interval = '600',
$neutron_ca_certificates_file = undef,
$network_api_class = 'nova.network.neutronv2.api.API',
$security_group_api = 'neutron',
$firewall_driver = 'nova.virt.firewall.NoopFirewallDriver',
$vif_plugging_is_fatal = true,
$vif_plugging_timeout = '300'
$vif_plugging_timeout = '300',
$dhcp_domain = 'novalocal',
) {
nova_config {
'DEFAULT/neutron_auth_strategy': value => $neutron_auth_strategy;
'DEFAULT/network_api_class': value => 'nova.network.neutronv2.api.API';
'DEFAULT/neutron_url': value => $neutron_url;
'DEFAULT/neutron_url_timeout': value => $neutron_url_timeout;
'DEFAULT/neutron_admin_tenant_name': value => $neutron_admin_tenant_name;
'DEFAULT/neutron_default_tenant_id': value => $neutron_default_tenant_id;
'DEFAULT/neutron_region_name': value => $neutron_region_name;
'DEFAULT/neutron_admin_username': value => $neutron_admin_username;
'DEFAULT/neutron_admin_password': value => $neutron_admin_password, secret => true;
'DEFAULT/neutron_admin_auth_url': value => $neutron_admin_auth_url;
'DEFAULT/neutron_ovs_bridge': value => $neutron_ovs_bridge;
'DEFAULT/neutron_extension_sync_interval': value => $neutron_extension_sync_interval;
'DEFAULT/security_group_api': value => $security_group_api;
'DEFAULT/firewall_driver': value => $firewall_driver;
'DEFAULT/vif_plugging_is_fatal': value => $vif_plugging_is_fatal;
'DEFAULT/vif_plugging_timeout': value => $vif_plugging_timeout;
'DEFAULT/dhcp_domain': value => $dhcp_domain;
'DEFAULT/firewall_driver': value => $firewall_driver;
'DEFAULT/network_api_class': value => $network_api_class;
'DEFAULT/security_group_api': value => $security_group_api;
'DEFAULT/vif_plugging_is_fatal': value => $vif_plugging_is_fatal;
'DEFAULT/vif_plugging_timeout': value => $vif_plugging_timeout;
'neutron/auth_strategy': value => $neutron_auth_strategy;
'neutron/url': value => $neutron_url;
'neutron/url_timeout': value => $neutron_url_timeout;
'neutron/admin_tenant_name': value => $neutron_admin_tenant_name;
'neutron/default_tenant_id': value => $neutron_default_tenant_id;
'neutron/region_name': value => $neutron_region_name;
'neutron/admin_username': value => $neutron_admin_username;
'neutron/admin_password': value => $neutron_admin_password, secret => true;
'neutron/admin_auth_url': value => $neutron_admin_auth_url;
'neutron/ovs_bridge': value => $neutron_ovs_bridge;
'neutron/extension_sync_interval': value => $neutron_extension_sync_interval;
}
if ! $neutron_ca_certificates_file {
nova_config { 'DEFAULT/neutron_ca_certificates_file': ensure => absent }
nova_config { 'neutron/ca_certificates_file': ensure => absent }
} else {
nova_config { 'DEFAULT/neutron_ca_certificates_file': value => $neutron_ca_certificates_file }
nova_config { 'neutron/ca_certificates_file': value => $neutron_ca_certificates_file }
}
}

View File

@ -27,7 +27,7 @@ class nova::objectstore(
$bind_address = '0.0.0.0'
) {
include nova::params
include ::nova::params
nova::generic_service { 'objectstore':
enabled => $enabled,
@ -35,7 +35,7 @@ class nova::objectstore(
package_name => $::nova::params::objectstore_package_name,
service_name => $::nova::params::objectstore_service_name,
ensure_package => $ensure_package,
require => User['nova'],
require => Package['nova-common'],
}
nova_config {

View File

@ -22,6 +22,7 @@ class nova::params {
$scheduler_package_name = 'openstack-nova-scheduler'
$tgt_package_name = 'scsi-target-utils'
$vncproxy_package_name = 'openstack-nova-novncproxy'
$serialproxy_package_name = 'openstack-nova-serialproxy'
$spicehtml5proxy_package_name = 'openstack-nova-console'
# service names
$api_service_name = 'openstack-nova-api'
@ -36,18 +37,22 @@ class nova::params {
$scheduler_service_name = 'openstack-nova-scheduler'
$tgt_service_name = 'tgtd'
$vncproxy_service_name = 'openstack-nova-novncproxy'
$serialproxy_service_name = 'openstack-nova-serialproxy'
$spicehtml5proxy_service_name = 'openstack-nova-spicehtml5proxy'
# redhat specific config defaults
$root_helper = 'sudo nova-rootwrap'
$lock_path = '/var/lib/nova/tmp'
$nova_log_group = 'nova'
case $::operatingsystem {
'Fedora', 'RedHat': {
'Fedora': {
$special_service_provider = undef
}
'RedHat': {
if ($::operatingsystemrelease < 7) {
'RedHat', 'CentOS', 'Scientific', 'OracleLinux': {
if (versioncmp($::operatingsystemmajrelease, '7') < 0) {
$messagebus_service_name = 'messagebus'
$special_service_provider = 'init'
} else {
$messagebus_service_name = 'dbus'
$special_service_provider = undef
}
}
@ -72,6 +77,7 @@ class nova::params {
$objectstore_package_name = 'nova-objectstore'
$scheduler_package_name = 'nova-scheduler'
$tgt_package_name = 'tgt'
$serialproxy_package_name = 'nova-serialproxy'
# service names
$api_service_name = 'nova-api'
$cells_service_name = 'nova-cells'
@ -83,8 +89,8 @@ class nova::params {
$network_service_name = 'nova-network'
$objectstore_service_name = 'nova-objectstore'
$scheduler_service_name = 'nova-scheduler'
$spicehtml5proxy_service_name = 'nova-spicehtml5proxy'
$vncproxy_service_name = 'nova-novncproxy'
$serialproxy_service_name = 'nova-serialproxy'
$tgt_service_name = 'tgt'
# debian specific nova config
$root_helper = 'sudo nova-rootwrap'
@ -92,15 +98,19 @@ class nova::params {
case $::operatingsystem {
'Debian': {
$spicehtml5proxy_package_name = 'nova-consoleproxy'
$spicehtml5proxy_service_name = 'nova-spicehtml5proxy'
$vncproxy_package_name = 'nova-consoleproxy'
# Use default provider on Debian
$special_service_provider = undef
$nova_log_group = 'nova'
}
default: {
$spicehtml5proxy_package_name = 'nova-spiceproxy'
$spicehtml5proxy_service_name = 'nova-spiceproxy'
$vncproxy_package_name = 'nova-novncproxy'
# some of the services need to be started form the special upstart provider
$special_service_provider = 'upstart'
$nova_log_group = 'adm'
}
}
}

View File

@ -0,0 +1,39 @@
# == Class: nova::policy
#
# Configure the nova policies
#
# === Parameters
#
# [*policies*]
# (optional) Set of policies to configure for nova
# Example :
# {
# 'nova-context_is_admin' => {
# 'key' => 'context_is_admin',
# 'value' => 'true'
# },
# 'nova-default' => {
# 'key' => 'default',
# 'value' => 'rule:admin_or_owner'
# }
# }
# Defaults to empty hash.
#
# [*policy_path*]
# (optional) Path to the nova policy.json file
# Defaults to /etc/nova/policy.json
#
class nova::policy (
$policies = {},
$policy_path = '/etc/nova/policy.json',
) {
validate_hash($policies)
Openstacklib::Policy::Base {
file_path => $policy_path,
}
create_resources('openstacklib::policy::base', $policies)
}

View File

@ -39,18 +39,18 @@ class nova::qpid(
$service_ensure = 'running'
qpid_user { $user:
password => $password,
file => $file,
realm => $realm,
provider => 'saslpasswd2',
require => Class['qpid::server'],
password => $password,
file => $file,
realm => $realm,
provider => 'saslpasswd2',
require => Class['qpid::server'],
}
} else {
$service_ensure = 'stopped'
}
class { 'qpid::server':
class { '::qpid::server':
service_ensure => $service_ensure
}

View File

@ -17,30 +17,50 @@
# Defaults to 51200
#
# [*quota_volumes*]
# (optional) Number of volumes
# Defaults to 10
# (optional) Deprecated. This parameter does nothing and will be removed.
# Defaults to undef
#
# [*quota_gigabytes*]
# (optional) Amount of ephemeral disk storage in GB
# Defaults to 1000
# (optional) Deprecated. This parameter does nothing and will be removed.
# Defaults to undef
#
# [*quota_floating_ips*]
# (optional) Number of floating IPs
# Defaults to 10
#
# [*quota_fixed_ips*]
# (optional) Number of fixed IPs (this should be at least the number of instances allowed)
# Defaults to -1
#
# [*quota_metadata_items*]
# (optional) Number of metadata items per instance
# Defaults to 128
#
# [*quota_max_injected_files*]
# (optional) Deprecated. Use quota_injected_files instead
# Defaults to undef
#
# [*quota_max_injected_file_content_bytes*]
# (optional) Deprecated. Use quota_injected_file_content_bytes instead
# Defaults to undef
#
# [*quota_max_injected_file_path_bytes*]
# (optional) Deprecated. Use quota_injected_file_path_bytes instead
# Defaults to undef
#
# [*quota_injected_files*]
# (optional) Number of files that can be injected per instance
# Defaults to 5
#
# [*quota_max_injected_file_content_bytes*]
# [*quota_injected_file_content_bytes*]
# (optional) Maximum size in bytes of injected files
# Defaults to 10240
#
# [*quota_max_injected_file_path_bytes*]
# [*quota_injected_file_path_bytes*]
# (optional) Deprecated. Use quota_injected_file_path_length instead
# Defaults to undef
#
# [*quota_injected_file_path_length*]
# (optional) Maximum size in bytes of injected file path
# Defaults to 255
#
@ -54,12 +74,16 @@
#
# [*quota_key_pairs*]
# (optional) Number of key pairs
# Defaults to 10
# Defaults to 100
#
# [*reservation_expire*]
# (optional) Time until reservations expire in seconds
# Defaults to 86400
#
# [*until_refresh*]
# (optional) Count of reservations until usage is refreshed
# Defaults to 0
#
# [*max_age*]
# (optional) Number of seconds between subsequent usage refreshes
# Defaults to 0
@ -72,38 +96,78 @@ class nova::quota(
$quota_instances = 10,
$quota_cores = 20,
$quota_ram = 51200,
$quota_volumes = 10,
$quota_gigabytes = 1000,
$quota_floating_ips = 10,
$quota_fixed_ips = -1,
$quota_metadata_items = 128,
$quota_max_injected_files = 5,
$quota_max_injected_file_content_bytes = 10240,
$quota_max_injected_file_path_bytes = 255,
$quota_injected_files = 5,
$quota_injected_file_content_bytes = 10240,
$quota_injected_file_path_length = 255,
$quota_security_groups = 10,
$quota_security_group_rules = 20,
$quota_key_pairs = 10,
$quota_key_pairs = 100,
$reservation_expire = 86400,
$until_refresh = 0,
$max_age = 0,
$quota_driver = 'nova.quota.DbQuotaDriver'
$quota_driver = 'nova.quota.DbQuotaDriver',
# DEPRECATED PARAMETERS
$quota_volumes = undef,
$quota_gigabytes = undef,
$quota_max_injected_files = undef,
$quota_injected_file_path_bytes = undef,
$quota_max_injected_file_content_bytes = undef,
$quota_max_injected_file_path_bytes = undef
) {
if $quota_volumes {
warning('The quota_volumes parameter is deprecated and has no effect.')
}
if $quota_gigabytes {
warning('The quota_gigabytes parameter is deprecated and has no effect.')
}
if $quota_max_injected_files {
warning('The quota_max_injected_files parameter is deprecated, use quota_injected_files instead.')
$quota_injected_files_real = $quota_max_injected_files
} else {
$quota_injected_files_real = $quota_injected_files
}
if $quota_max_injected_file_content_bytes {
warning('The quota_max_injected_file_content_bytes is deprecated, use quota_injected_file_content_bytes instead.')
$quota_injected_file_content_bytes_real = $quota_max_injected_file_content_bytes
} else {
$quota_injected_file_content_bytes_real = $quota_injected_file_content_bytes
}
if $quota_max_injected_file_path_bytes {
fail('The quota_max_injected_file_path_bytes parameter is deprecated, use quota_injected_file_path_length instead.')
}
if $quota_injected_file_path_bytes {
warning('The quota_injected_file_path_bytes parameter is deprecated, use quota_injected_file_path_length instead.')
$quota_injected_file_path_length_real = $quota_injected_file_path_bytes
} else {
$quota_injected_file_path_length_real = $quota_injected_file_path_length
}
nova_config {
'DEFAULT/quota_instances': value => $quota_instances;
'DEFAULT/quota_cores': value => $quota_cores;
'DEFAULT/quota_ram': value => $quota_ram;
'DEFAULT/quota_volumes': value => $quota_volumes;
'DEFAULT/quota_gigabytes': value => $quota_gigabytes;
'DEFAULT/quota_floating_ips': value => $quota_floating_ips;
'DEFAULT/quota_metadata_items': value => $quota_metadata_items;
'DEFAULT/quota_max_injected_files': value => $quota_max_injected_files;
'DEFAULT/quota_max_injected_file_content_bytes': value => $quota_max_injected_file_content_bytes;
'DEFAULT/quota_max_injected_file_path_bytes': value => $quota_max_injected_file_path_bytes;
'DEFAULT/quota_security_groups': value => $quota_security_groups;
'DEFAULT/quota_security_group_rules': value => $quota_security_group_rules;
'DEFAULT/quota_key_pairs': value => $quota_key_pairs;
'DEFAULT/reservation_expire': value => $reservation_expire;
'DEFAULT/max_age': value => $max_age;
'DEFAULT/quota_driver': value => $quota_driver
'DEFAULT/quota_instances': value => $quota_instances;
'DEFAULT/quota_cores': value => $quota_cores;
'DEFAULT/quota_ram': value => $quota_ram;
'DEFAULT/quota_floating_ips': value => $quota_floating_ips;
'DEFAULT/quota_fixed_ips': value => $quota_fixed_ips;
'DEFAULT/quota_metadata_items': value => $quota_metadata_items;
'DEFAULT/quota_injected_files': value => $quota_injected_files_real;
'DEFAULT/quota_injected_file_content_bytes': value => $quota_injected_file_content_bytes_real;
'DEFAULT/quota_injected_file_path_length': value => $quota_injected_file_path_length_real;
'DEFAULT/quota_security_groups': value => $quota_security_groups;
'DEFAULT/quota_security_group_rules': value => $quota_security_group_rules;
'DEFAULT/quota_key_pairs': value => $quota_key_pairs;
'DEFAULT/reservation_expire': value => $reservation_expire;
'DEFAULT/until_refresh': value => $until_refresh;
'DEFAULT/max_age': value => $max_age;
'DEFAULT/quota_driver': value => $quota_driver
}
}

View File

@ -30,10 +30,10 @@
# Defaults to false
#
# [*rabbitmq_class*]
# (optional) The rabbitmq puppet class to depend on,
# (optional) Deprecated. The rabbitmq puppet class to depend on,
# which is dependent on the puppet-rabbitmq version.
# Use the default for 1.x, use 'rabbitmq' for 3.x.
# Use false, if rabbitmq class should not be configured
# Use false if rabbitmq class should not be configured
# here
# Defaults to 'rabbitmq::server'
#
@ -44,6 +44,7 @@ class nova::rabbitmq(
$virtual_host ='/',
$cluster_disk_nodes = false,
$enabled = true,
# DEPRECATED PARAMETER
$rabbitmq_class = 'rabbitmq::server'
) {
@ -53,9 +54,9 @@ class nova::rabbitmq(
} else {
$delete_guest_user = true
rabbitmq_user { $userid:
admin => true,
password => $password,
provider => 'rabbitmqctl',
admin => true,
password => $password,
provider => 'rabbitmqctl',
}
# I need to figure out the appropriate permissions
rabbitmq_user_permissions { "${userid}@${virtual_host}":
@ -70,9 +71,11 @@ class nova::rabbitmq(
$service_ensure = 'stopped'
}
# TODO(bogdando) contribute this to puppet-nova as they
# do not want nova manage rabbitmq service anymore.
# NOTE(bogdando) do not nova manage rabbitmq service
# if rabbitmq_class is set to False
if $rabbitmq_class {
warning('The rabbitmq_class parameter is deprecated.')
if $cluster_disk_nodes {
class { $rabbitmq_class:
service_ensure => $service_ensure,

View File

@ -1,4 +1,4 @@
# == Class: nova::schedule
# == Class: nova::scheduler
#
# Install and manage nova scheduler
#
@ -22,7 +22,8 @@ class nova::scheduler(
$ensure_package = 'present'
) {
include nova::params
include ::nova::db
include ::nova::params
nova::generic_service { 'scheduler':
enabled => $enabled,

View File

@ -40,7 +40,7 @@
# (optional) Ignore hosts that have too many instances
# Defaults to '50'
#
# [*ram_allocation_ratio:*]
# [*ram_allocation_ratio*]
# (optional) Virtual ram to physical ram allocation ratio
# Defaults to '1.5'
#
@ -49,7 +49,7 @@
# Defaults to 'nova.scheduler.filters.all_filters'
#
# [*scheduler_default_filters*]
# (optional) A comma separated list of filters to be used by default
# (optional) An array of filters to be used by default
# Defaults to false
#
# [*scheduler_weight_classes*]

View File

@ -0,0 +1,50 @@
# == Class: nova:serialproxy
#
# Configures nova serialproxy
#
# === Parameters:
#
# [*enabled*]
# (optional) Whether to run the serialproxy service
# Defaults to false
#
# [*manage_service*]
# (optional) Whether to start/stop the service
# Defaults to true
#
# [*serialproxy_host*]
# (optional) Host on which to listen for incoming requests
# Defaults to '0.0.0.0'
#
# [*serialproxy_port*]
# (optional) Port on which to listen for incoming requests
# Defaults to '6083'
#
# [*ensure_package*]
# (optional) The state of the nova-serialproxy package
# Defaults to 'present'
#
class nova::serialproxy(
$enabled = true,
$manage_service = true,
$serialproxy_host = '0.0.0.0',
$serialproxy_port = '6083',
$ensure_package = 'present'
) {
include ::nova::params
nova_config {
'serial_console/serialproxy_port': value => $serialproxy_port;
'serial_console/serialproxy_host': value => $serialproxy_host;
}
nova::generic_service { 'serialproxy':
enabled => $enabled,
manage_service => $manage_service,
package_name => $::nova::params::serialproxy_package_name,
service_name => $::nova::params::serialproxy_service_name,
ensure_package => $ensure_package
}
}

View File

@ -36,11 +36,13 @@ class nova::spicehtml5proxy(
$ensure_package = 'present'
) {
include nova::params
include ::nova::params
nova_config {
'DEFAULT/spicehtml5proxy_host': value => $host;
'DEFAULT/spicehtml5proxy_port': value => $port;
'spice/enabled': value => $enabled;
'spice/agent_enabled': value => $enabled;
'spice/html5proxy_host': value => $host;
'spice/html5proxy_port': value => $port;
}
nova::generic_service { 'spicehtml5proxy':

View File

@ -13,9 +13,9 @@ class nova::utilities {
}
file {'guestfs.seed':
ensure => present,
path => '/var/run/guestfs.seed',
content => 'libguestfs0 libguestfs/update-appliance boolean true'
ensure => present,
path => '/var/run/guestfs.seed',
content => 'libguestfs0 libguestfs/update-appliance boolean true'
}
}
}

View File

@ -24,17 +24,26 @@
# (optional) The state of the nova-novncproxy package
# Defaults to 'present'
#
# [*vncproxy_protocol*]
# (optional) The protocol to communicate with the VNC proxy server
# Defaults to 'http'
#
# [*vncproxy_path*]
# (optional) The path at the end of the uri for communication with the VNC
# proxy server
# Defaults to '/vnc_auto.html'
#
class nova::vncproxy(
$enabled = false,
$manage_service = true,
$host = '0.0.0.0',
$port = '6080',
$ensure_package = 'present'
$enabled = false,
$manage_service = true,
$vncproxy_protocol = 'http',
$host = '0.0.0.0',
$port = '6080',
$vncproxy_path = '/vnc_auto.html',
$ensure_package = 'present'
) {
include nova::params
# TODO make this work on Fedora
include ::nova::params
# See http://nova.openstack.org/runnova/vncconsole.html for more details.
@ -43,6 +52,8 @@ class nova::vncproxy(
'DEFAULT/novncproxy_port': value => $port;
}
include ::nova::vncproxy::common
if ! defined(Package['python-numpy']) {
package { 'python-numpy':
ensure => present,

View File

@ -0,0 +1,54 @@
# == Class: nova::vncproxy::common
#
# [*vncproxy_host*]
# (optional) The host of the VNC proxy server
# Defaults to false
#
# [*vncproxy_protocol*]
# (optional) The protocol to communicate with the VNC proxy server
# Defaults to 'http'
#
# [*vncproxy_port*]
# (optional) The port to communicate with the VNC proxy server
# Defaults to '6080'
#
# [*vncproxy_path*]
# (optional) The path at the end of the uri for communication with the VNC proxy server
# Defaults to '/vnc_auto.html'
#
class nova::vncproxy::common (
$vncproxy_host = undef,
$vncproxy_protocol = undef,
$vncproxy_port = undef,
$vncproxy_path = undef,
) {
$vncproxy_host_real = pick(
$vncproxy_host,
$::nova::compute::vncproxy_host,
$::nova::vncproxy::host,
false)
$vncproxy_protocol_real = pick(
$vncproxy_protocol,
$::nova::compute::vncproxy_protocol,
$::nova::vncproxy::vncproxy_protocol,
'http')
$vncproxy_port_real = pick(
$vncproxy_port,
$::nova::compute::vncproxy_port,
$::nova::vncproxy::port,
6080)
$vncproxy_path_real = pick(
$vncproxy_path,
$::nova::compute::vncproxy_path,
$::nova::vncproxy::vncproxy_path,
'/vnc_auto.html')
if ($vncproxy_host_real) {
$vncproxy_base_url = "${vncproxy_protocol_real}://${vncproxy_host_real}:${vncproxy_port_real}${vncproxy_path_real}"
# config for vnc proxy
nova_config {
'DEFAULT/novncproxy_base_url': value => $vncproxy_base_url;
}
}
}

View File

@ -0,0 +1,44 @@
{
"name": "stackforge-nova",
"version": "5.1.0",
"author": "Puppet Labs and OpenStack Contributors",
"summary": "Puppet module for OpenStack Nova",
"license": "Apache-2.0",
"source": "git://github.com/openstack/puppet-nova.git",
"project_page": "https://launchpad.net/puppet-nova",
"issues_url": "https://bugs.launchpad.net/puppet-nova",
"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 Nova (Compute).",
"dependencies": [
{ "name": "dprince/qpid", "version_requirement": ">=1.0.0 <2.0.0" },
{ "name": "duritong/sysctl", "version_requirement": ">=0.0.1 <1.0.0" },
{ "name": "stackforge/cinder", "version_requirement": ">=5.0.0 <6.0.0" },
{ "name": "stackforge/glance", "version_requirement": ">=5.0.0 <6.0.0" },
{ "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" },
{ "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" },
{ "name": "puppetlabs/rabbitmq", "version_requirement": ">=2.0.2 <4.0.0" },
{ "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" },
{ "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" }
]
}

View File

@ -0,0 +1,156 @@
require 'spec_helper_acceptance'
describe 'basic nova' 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,
erlang_cookie => 'secrete',
package_provider => $package_provider,
}
rabbitmq_vhost { '/':
provider => 'rabbitmqctl',
require => Class['rabbitmq'],
}
rabbitmq_user { 'nova':
admin => true,
password => 'an_even_bigger_secret',
provider => 'rabbitmqctl',
require => Class['rabbitmq'],
}
rabbitmq_user_permissions { 'nova@/':
configure_permission => '.*',
write_permission => '.*',
read_permission => '.*',
provider => 'rabbitmqctl',
require => Class['rabbitmq'],
}
# Keystone resources, needed by Nova 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/",
}
# Nova resources
class { '::nova':
database_connection => 'mysql://nova:a_big_secret@127.0.0.1/nova?charset=utf8',
rabbit_userid => 'nova',
rabbit_password => 'an_even_bigger_secret',
image_service => 'nova.image.glance.GlanceImageService',
glance_api_servers => 'localhost:9292',
verbose => false,
rabbit_host => '127.0.0.1',
}
class { '::nova::db::mysql':
password => 'a_big_secret',
}
class { '::nova::keystone::auth':
password => 'a_big_secret',
}
class { '::nova::api':
enabled => true,
admin_password => 'a_big_secret',
identity_uri => 'http://127.0.0.1:35357/',
osapi_v3 => true,
}
class { '::nova::cert': enabled => true }
class { '::nova::client': }
class { '::nova::conductor': enabled => true }
class { '::nova::consoleauth': enabled => true }
class { '::nova::cron::archive_deleted_rows': }
class { '::nova::compute':
enabled => true,
vnc_enabled => true,
}
class { '::nova::compute::libvirt':
migration_support => true,
vncserver_listen => '0.0.0.0',
}
class { '::nova::scheduler': enabled => true }
class { '::nova::vncproxy': enabled => true }
# TODO: networking with neutron
EOS
# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe port(8773) do
it { is_expected.to be_listening.with('tcp') }
end
describe port(8774) do
it { is_expected.to be_listening.with('tcp') }
end
describe port(8775) do
it { is_expected.to be_listening.with('tcp') }
end
describe port(6080) do
it { is_expected.to be_listening.with('tcp') }
end
describe cron do
it { should have_entry('1 0 * * * nova-manage db archive_deleted_rows --max_rows 100 >>/var/log/nova/nova-rowsflush.log 2>&1').with_user('nova') }
end
end
end

View File

@ -0,0 +1,11 @@
HOSTS:
ubuntu-server-1404-x64:
roles:
- master
platform: ubuntu-14.04-amd64
box : puppetlabs/ubuntu-14.04-64-nocm
box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
hypervisor : vagrant
CONFIG:
log_level : debug
type: git

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,11 @@
HOSTS:
ubuntu-server-1404-x64:
roles:
- master
platform: ubuntu-14.04-amd64
box : puppetlabs/ubuntu-14.04-64-nocm
box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
hypervisor : vagrant
CONFIG:
log_level : debug
type: git

View File

@ -19,64 +19,59 @@ describe 'nova::api' do
context 'with default parameters' do
it 'installs nova-api package and service' do
should contain_service('nova-api').with(
is_expected.to contain_service('nova-api').with(
:name => platform_params[:nova_api_service],
:ensure => 'stopped',
:hasstatus => true,
:enable => false
)
should contain_package('nova-api').with(
is_expected.to contain_package('nova-api').with(
:name => platform_params[:nova_api_package],
:ensure => 'present',
:notify => 'Service[nova-api]'
:tag => ['openstack']
)
is_expected.to contain_package('nova-api').that_notifies('Service[nova-api]')
is_expected.to_not contain_exec('validate_nova_api')
end
it 'configures keystone_authtoken middleware' do
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_host').with_value('127.0.0.1')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_port').with_value('35357')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_protocol').with_value('http')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_uri').with_value('http://127.0.0.1:5000/')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_admin_prefix').with_ensure('absent')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_version').with_ensure('absent')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/admin_tenant_name').with_value('services')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/admin_user').with_value('nova')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/admin_password').with_value('passw0rd').with_secret(true)
end
it 'configures various stuff' do
should contain_nova_config('DEFAULT/ec2_listen').with('value' => '0.0.0.0')
should contain_nova_config('DEFAULT/osapi_compute_listen').with('value' => '0.0.0.0')
should contain_nova_config('DEFAULT/metadata_listen').with('value' => '0.0.0.0')
should contain_nova_config('DEFAULT/osapi_volume_listen').with('value' => '0.0.0.0')
should contain_nova_config('DEFAULT/osapi_compute_workers').with('value' => '5')
should contain_nova_config('DEFAULT/metadata_workers').with('value' => '5')
should contain_nova_config('conductor/workers').with('value' => '5')
is_expected.to contain_nova_config('DEFAULT/ec2_listen').with('value' => '0.0.0.0')
is_expected.to contain_nova_config('DEFAULT/osapi_compute_listen').with('value' => '0.0.0.0')
is_expected.to contain_nova_config('DEFAULT/metadata_listen').with('value' => '0.0.0.0')
is_expected.to contain_nova_config('DEFAULT/osapi_volume_listen').with('value' => '0.0.0.0')
is_expected.to contain_nova_config('DEFAULT/osapi_compute_workers').with('value' => '5')
is_expected.to contain_nova_config('DEFAULT/ec2_workers').with('value' => '5')
is_expected.to contain_nova_config('DEFAULT/metadata_workers').with('value' => '5')
end
it 'do not configure v3 api' do
is_expected.to contain_nova_config('osapi_v3/enabled').with('value' => false)
end
it 'unconfigures neutron_metadata proxy' do
should contain_nova_config('DEFAULT/service_neutron_metadata_proxy').with(:value => false)
should contain_nova_config('DEFAULT/neutron_metadata_proxy_shared_secret').with(:ensure => 'absent')
end
end
context 'with deprecated parameters' do
before do
params.merge!({
:workers => 1,
})
end
it 'configures various stuff' do
should contain_nova_config('DEFAULT/osapi_compute_workers').with('value' => '1')
is_expected.to contain_nova_config('neutron/service_metadata_proxy').with(:value => false)
is_expected.to contain_nova_config('neutron/metadata_proxy_shared_secret').with(:ensure => 'absent')
end
end
@ -102,16 +97,19 @@ describe 'nova::api' do
:neutron_metadata_proxy_shared_secret => 'secrete',
:osapi_compute_workers => 1,
:metadata_workers => 2,
:conductor_workers => 3,
:osapi_v3 => true,
:keystone_ec2_url => 'https://example.com:5000/v2.0/ec2tokens',
:pci_alias => "[{\"vendor_id\":\"8086\",\"product_id\":\"0126\",\"name\":\"graphic_card\"},{\"vendor_id\":\"9096\",\"product_id\":\"1520\",\"name\":\"network_card\"}]"
})
end
it 'installs nova-api package and service' do
should contain_package('nova-api').with(
is_expected.to contain_package('nova-api').with(
:name => platform_params[:nova_api_package],
:ensure => '2012.1-2'
:ensure => '2012.1-2',
:tag => ['openstack']
)
should contain_service('nova-api').with(
is_expected.to contain_service('nova-api').with(
:name => platform_params[:nova_api_service],
:ensure => 'running',
:hasstatus => true,
@ -120,39 +118,49 @@ describe 'nova::api' do
end
it 'configures keystone_authtoken middleware' do
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_host').with_value('10.0.0.1')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_port').with_value('1234')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_protocol').with_value('https')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_admin_prefix').with_value('/keystone/admin')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_uri').with_value('https://10.0.0.1:9999/')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/auth_version').with_value('v3.0')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/admin_tenant_name').with_value('service2')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/admin_user').with_value('nova2')
should contain_nova_config(
is_expected.to contain_nova_config(
'keystone_authtoken/admin_password').with_value('passw0rd2').with_secret(true)
should contain_nova_paste_api_ini(
is_expected.to contain_nova_paste_api_ini(
'filter:ratelimit/limits').with_value('(GET, "*", .*, 100, MINUTE);(POST, "*", .*, 200, MINUTE)')
end
it 'configures various stuff' do
should contain_nova_config('DEFAULT/ec2_listen').with('value' => '192.168.56.210')
should contain_nova_config('DEFAULT/osapi_compute_listen').with('value' => '192.168.56.210')
should contain_nova_config('DEFAULT/metadata_listen').with('value' => '127.0.0.1')
should contain_nova_config('DEFAULT/osapi_volume_listen').with('value' => '192.168.56.210')
should contain_nova_config('DEFAULT/use_forwarded_for').with('value' => false)
should contain_nova_config('DEFAULT/osapi_compute_workers').with('value' => '1')
should contain_nova_config('DEFAULT/metadata_workers').with('value' => '2')
should contain_nova_config('conductor/workers').with('value' => '3')
should contain_nova_config('DEFAULT/service_neutron_metadata_proxy').with('value' => true)
should contain_nova_config('DEFAULT/neutron_metadata_proxy_shared_secret').with('value' => 'secrete')
is_expected.to contain_nova_config('DEFAULT/ec2_listen').with('value' => '192.168.56.210')
is_expected.to contain_nova_config('DEFAULT/osapi_compute_listen').with('value' => '192.168.56.210')
is_expected.to contain_nova_config('DEFAULT/metadata_listen').with('value' => '127.0.0.1')
is_expected.to contain_nova_config('DEFAULT/osapi_volume_listen').with('value' => '192.168.56.210')
is_expected.to contain_nova_config('DEFAULT/use_forwarded_for').with('value' => false)
is_expected.to contain_nova_config('DEFAULT/osapi_compute_workers').with('value' => '1')
is_expected.to contain_nova_config('DEFAULT/metadata_workers').with('value' => '2')
is_expected.to contain_nova_config('neutron/service_metadata_proxy').with('value' => true)
is_expected.to contain_nova_config('neutron/metadata_proxy_shared_secret').with('value' => 'secrete')
is_expected.to contain_nova_config('DEFAULT/keystone_ec2_url').with('value' => 'https://example.com:5000/v2.0/ec2tokens')
end
it 'configure nova api v3' do
is_expected.to contain_nova_config('osapi_v3/enabled').with('value' => true)
end
it 'configures nova pci_alias entries' do
is_expected.to contain_nova_config('DEFAULT/pci_alias').with(
'value' => "[{\"vendor_id\":\"8086\",\"product_id\":\"0126\",\"name\":\"graphic_card\"},{\"vendor_id\":\"9096\",\"product_id\":\"1520\",\"name\":\"network_card\"}]"
)
end
end
@ -168,11 +176,50 @@ describe 'nova::api' do
before do
params.merge!({ :auth_admin_prefix => auth_admin_prefix })
end
it { expect { should contain_nova_config('keystone_authtoken/auth_admin_prefix') }.to \
it { expect { is_expected.to contain_nova_config('keystone_authtoken/auth_admin_prefix') }.to \
raise_error(Puppet::Error, /validate_re\(\): "#{auth_admin_prefix}" does not match/) }
end
end
context 'while validating the service with default command' do
before do
params.merge!({
:validate => true,
})
end
it { is_expected.to contain_exec('execute nova-api validation').with(
:path => '/usr/bin:/bin:/usr/sbin:/sbin',
:provider => 'shell',
:tries => '10',
:try_sleep => '2',
:command => 'nova --os-auth-url http://127.0.0.1:5000/ --os-tenant-name services --os-username nova --os-password passw0rd flavor-list',
)}
it { is_expected.to contain_anchor('create nova-api anchor').with(
:require => 'Exec[execute nova-api validation]',
)}
end
context 'while validating the service with custom command' do
before do
params.merge!({
:validate => true,
:validation_options => { 'nova-api' => { 'command' => 'my-script' } }
})
end
it { is_expected.to contain_exec('execute nova-api validation').with(
:path => '/usr/bin:/bin:/usr/sbin:/sbin',
:provider => 'shell',
:tries => '10',
:try_sleep => '2',
:command => 'my-script',
)}
it { is_expected.to contain_anchor('create nova-api anchor').with(
:require => 'Exec[execute nova-api validation]',
)}
end
context 'while not managing service state' do
before do
params.merge!({
@ -181,8 +228,67 @@ describe 'nova::api' do
})
end
it { should contain_service('nova-api').without_ensure }
it { is_expected.to contain_service('nova-api').without_ensure }
end
context 'with default database parameters' do
let :pre_condition do
"include nova"
end
it { is_expected.to_not contain_nova_config('database/connection') }
it { is_expected.to_not contain_nova_config('database/slave_connection') }
it { is_expected.to_not contain_nova_config('database/idle_timeout').with_value('3600') }
end
context 'with overridden database parameters' do
let :pre_condition do
"class { 'nova':
database_connection => 'mysql://user:pass@db/db',
slave_connection => 'mysql://user:pass@slave/db',
database_idle_timeout => '30',
}
"
end
it { is_expected.to contain_nova_config('database/connection').with_value('mysql://user:pass@db/db').with_secret(true) }
it { is_expected.to contain_nova_config('database/slave_connection').with_value('mysql://user:pass@slave/db').with_secret(true) }
it { is_expected.to contain_nova_config('database/idle_timeout').with_value('30') }
end
context 'with custom keystone identity_uri' do
before do
params.merge!({
:identity_uri => 'https://foo.bar:1234/',
})
end
it 'configures identity_uri' do
is_expected.to contain_nova_config('keystone_authtoken/identity_uri').with_value("https://foo.bar:1234/");
# since only auth_uri is set the deprecated auth parameters is_expected.to
# still get set in case they are still in use
is_expected.to contain_nova_config('keystone_authtoken/auth_host').with_value('127.0.0.1');
is_expected.to contain_nova_config('keystone_authtoken/auth_port').with_value('35357');
is_expected.to contain_nova_config('keystone_authtoken/auth_protocol').with_value('http');
end
end
context 'with custom keystone identity_uri and auth_uri' do
before do
params.merge!({
:identity_uri => 'https://foo.bar:35357/',
:auth_uri => 'https://foo.bar:5000/v2.0/',
})
end
it 'configures identity_uri' do
is_expected.to contain_nova_config('keystone_authtoken/identity_uri').with_value("https://foo.bar:35357/");
is_expected.to contain_nova_config('keystone_authtoken/auth_uri').with_value("https://foo.bar:5000/v2.0/");
is_expected.to contain_nova_config('keystone_authtoken/auth_host').with_ensure('absent')
is_expected.to contain_nova_config('keystone_authtoken/auth_port').with_ensure('absent')
is_expected.to contain_nova_config('keystone_authtoken/auth_protocol').with_ensure('absent')
is_expected.to contain_nova_config('keystone_authtoken/auth_admin_prefix').with_ensure('absent')
end
end
end
context 'on Debian platforms' do

View File

@ -2,7 +2,7 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# Author: Emilien Macchi <emilien.macchi@enovance.com>
# François Charlier <francois.charlier@enovance.com>
# Francois Charlier <francois.charlier@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
@ -55,43 +55,44 @@ describe 'nova::cells' do
shared_examples_for 'nova-cells' do
it { should contain_class('nova::params') }
it { is_expected.to contain_class('nova::params') }
it 'installs nova-cells package' do
should contain_package('nova-cells').with(
is_expected.to contain_package('nova-cells').with(
:ensure => 'present',
:name => platform_params[:cells_package_name]
:name => platform_params[:cells_package_name],
:tag => ['openstack']
)
end
it 'configures nova-cells service' do
should contain_service('nova-cells').with(
is_expected.to contain_service('nova-cells').with(
:ensure => 'running',
:name => platform_params[:cells_service_name]
)
end
it 'configures cell' do
should contain_nova_config('cells/bandwidth_update_interval').with(:value => '600')
should contain_nova_config('cells/call_timeout').with(:value => '60')
should contain_nova_config('cells/capabilities').with(:value => 'hypervisor=xenserver;kvm,os=linux;windows')
should contain_nova_config('cells/db_check_interval').with(:value => '60')
should contain_nova_config('cells/driver').with(:value => 'nova.cells.rpc_driver.CellsRPCDriver')
should contain_nova_config('cells/instance_updated_at_threshold').with(:value => '3600')
should contain_nova_config('cells/instance_update_num_instances').with(:value => '1')
should contain_nova_config('cells/manager').with(:value => 'nova.cells.manager.CellsManager')
should contain_nova_config('cells/max_hop_count').with(:value => '10')
should contain_nova_config('cells/mute_child_interval').with(:value => '300')
should contain_nova_config('cells/mute_weight_multiplier').with(:value => '-10.0')
should contain_nova_config('cells/mute_weight_value').with(:value => '1000.0')
should contain_nova_config('cells/ram_weight_multiplier').with(:value => '10.0')
should contain_nova_config('cells/reserve_percent').with(:value => '10.0')
should contain_nova_config('cells/rpc_driver_queue_base').with(:value => 'cells.intercell')
should contain_nova_config('cells/scheduler_filter_classes').with(:value => 'nova.cells.filters.all_filters')
should contain_nova_config('cells/scheduler_retries').with(:value => '10')
should contain_nova_config('cells/scheduler_retry_delay').with(:value => '2')
should contain_nova_config('cells/scheduler_weight_classes').with(:value => 'nova.cells.weights.all_weighers')
should contain_nova_config('cells/scheduler').with(:value => 'nova.cells.scheduler.CellsScheduler')
is_expected.to contain_nova_config('cells/bandwidth_update_interval').with(:value => '600')
is_expected.to contain_nova_config('cells/call_timeout').with(:value => '60')
is_expected.to contain_nova_config('cells/capabilities').with(:value => 'hypervisor=xenserver;kvm,os=linux;windows')
is_expected.to contain_nova_config('cells/db_check_interval').with(:value => '60')
is_expected.to contain_nova_config('cells/driver').with(:value => 'nova.cells.rpc_driver.CellsRPCDriver')
is_expected.to contain_nova_config('cells/instance_updated_at_threshold').with(:value => '3600')
is_expected.to contain_nova_config('cells/instance_update_num_instances').with(:value => '1')
is_expected.to contain_nova_config('cells/manager').with(:value => 'nova.cells.manager.CellsManager')
is_expected.to contain_nova_config('cells/max_hop_count').with(:value => '10')
is_expected.to contain_nova_config('cells/mute_child_interval').with(:value => '300')
is_expected.to contain_nova_config('cells/mute_weight_multiplier').with(:value => '-10.0')
is_expected.to contain_nova_config('cells/mute_weight_value').with(:value => '1000.0')
is_expected.to contain_nova_config('cells/ram_weight_multiplier').with(:value => '10.0')
is_expected.to contain_nova_config('cells/reserve_percent').with(:value => '10.0')
is_expected.to contain_nova_config('cells/rpc_driver_queue_base').with(:value => 'cells.intercell')
is_expected.to contain_nova_config('cells/scheduler_filter_classes').with(:value => 'nova.cells.filters.all_filters')
is_expected.to contain_nova_config('cells/scheduler_retries').with(:value => '10')
is_expected.to contain_nova_config('cells/scheduler_retry_delay').with(:value => '2')
is_expected.to contain_nova_config('cells/scheduler_weight_classes').with(:value => 'nova.cells.weights.all_weighers')
is_expected.to contain_nova_config('cells/scheduler').with(:value => 'nova.cells.scheduler.CellsScheduler')
end
end
@ -104,8 +105,9 @@ describe 'nova::cells' do
let :expected_params do
default_params.merge(params)
end
it { should contain_nova_config('cells/name').with_value(expected_params[:cell_name]) }
it { should contain_nova_config('DEFAULT/compute_api_class').with_value('nova.compute.cells_api.ComputeCellsAPI')}
it { is_expected.to contain_nova_config('cells/name').with_value(expected_params[:cell_name]) }
it { is_expected.to contain_nova_config('DEFAULT/compute_api_class').with_value('nova.compute.cells_api.ComputeCellsAPI')}
it { is_expected.to contain_nova_config('cells/cell_type').with_value('api')}
it_configures 'nova-cells'
end
@ -119,7 +121,7 @@ describe 'nova::cells' do
let :expected_params do
default_params.merge(params)
end
it { should contain_service(platform_params[:cells_service_name]).without_ensure }
it { is_expected.to contain_service(platform_params[:cells_service_name]).without_ensure }
end
shared_examples_for 'a child cell' do
@ -131,8 +133,9 @@ describe 'nova::cells' do
let :expected_params do
default_params.merge(params)
end
it { should contain_nova_config('cells/name').with_value(expected_params[:cell_name]) }
it { should contain_nova_config('DEFAULT/quota_driver').with_value('nova.quota.NoopQuotaDriver')}
it { is_expected.to contain_nova_config('cells/name').with_value(expected_params[:cell_name]) }
it { is_expected.to contain_nova_config('DEFAULT/quota_driver').with_value('nova.quota.NoopQuotaDriver')}
it { is_expected.to contain_nova_config('cells/cell_type').with_value('compute')}
it_configures 'nova-cells'
end

View File

@ -3,13 +3,18 @@ require 'spec_helper'
describe 'nova::client' do
context 'with default parameters' do
it { should contain_package('python-novaclient').with_ensure('present') }
it {
is_expected.to contain_package('python-novaclient').with(
:ensure => 'present',
:tag => ['openstack']
)
}
end
context 'with ensure parameter provided' do
let :params do
{ :ensure => '2012.1-2' }
end
it { should contain_package('python-novaclient').with_ensure('2012.1-2') }
it { is_expected.to contain_package('python-novaclient').with_ensure('2012.1-2') }
end
end

View File

@ -0,0 +1,13 @@
require 'spec_helper'
describe 'nova::compute::ironic' do
it 'configures ironic in nova.conf' do
is_expected.to contain_nova_config('ironic/admin_username').with_value('admin')
is_expected.to contain_nova_config('ironic/admin_password').with_value('ironic')
is_expected.to contain_nova_config('ironic/admin_url').with_value('http://127.0.0.1:35357/v2.0')
is_expected.to contain_nova_config('ironic/admin_tenant_name').with_value('services')
is_expected.to contain_nova_config('ironic/api_endpoint').with_value('http://127.0.0.1:6385/v1')
is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('nova.virt.ironic.IronicDriver')
end
end

View File

@ -12,36 +12,40 @@ describe 'nova::compute::libvirt' do
describe 'with default parameters' do
it { should contain_class('nova::params')}
it { is_expected.to contain_class('nova::params')}
it { should contain_package('nova-compute-kvm').with(
it { is_expected.to contain_package('nova-compute-kvm').with(
:ensure => 'present',
:before => 'Package[nova-compute]'
:before => 'Package[nova-compute]',
:tag => ['openstack']
) }
it { should contain_package('libvirt').with(
it { is_expected.to contain_package('libvirt').with(
:name => 'libvirt-bin',
:ensure => 'present'
) }
it { should contain_service('libvirt').with(
it { is_expected.to contain_service('libvirt').with(
:name => 'libvirt-bin',
:enable => true,
:ensure => 'running',
:provider => 'upstart',
:require => 'Package[libvirt]',
:before => 'Service[nova-compute]'
:before => ['Service[nova-compute]']
)}
it { should contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.LibvirtDriver')}
it { should contain_nova_config('libvirt/virt_type').with_value('kvm')}
it { should contain_nova_config('libvirt/cpu_mode').with_value('host-model')}
it { should contain_nova_config('libvirt/disk_cachemodes').with_ensure('absent')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('127.0.0.1')}
it { should contain_nova_config('DEFAULT/remove_unused_base_images').with_ensure('absent')}
it { should contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_ensure('absent')}
it { should contain_nova_config('libvirt/remove_unused_kernels').with_ensure('absent')}
it { should contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_ensure('absent')}
it { is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.LibvirtDriver')}
it { is_expected.to contain_nova_config('libvirt/virt_type').with_value('kvm')}
it { is_expected.to contain_nova_config('libvirt/cpu_mode').with_value('host-model')}
it { is_expected.to contain_nova_config('libvirt/disk_cachemodes').with_ensure('absent')}
it { is_expected.to contain_nova_config('libvirt/inject_password').with_value(false)}
it { is_expected.to contain_nova_config('libvirt/inject_key').with_value(false)}
it { is_expected.to contain_nova_config('libvirt/inject_partition').with_value(-2)}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('127.0.0.1')}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_base_images').with_ensure('absent')}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_ensure('absent')}
it { is_expected.to contain_nova_config('libvirt/remove_unused_kernels').with_ensure('absent')}
it { is_expected.to contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_ensure('absent')}
end
describe 'with params' do
@ -53,27 +57,26 @@ describe 'nova::compute::libvirt' do
:remove_unused_base_images => true,
:remove_unused_kernels => true,
:remove_unused_resized_minimum_age_seconds => 3600,
:remove_unused_original_minimum_age_seconds => 3600
:remove_unused_original_minimum_age_seconds => 3600,
:libvirt_service_name => 'custom_service'
}
end
it { should contain_nova_config('libvirt/virt_type').with_value('qemu')}
it { should contain_nova_config('libvirt/cpu_mode').with_value('host-passthrough')}
it { should contain_nova_config('libvirt/disk_cachemodes').with_value('file=directsync,block=none')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { should contain_nova_config('DEFAULT/remove_unused_base_images').with_value(true)}
it { should contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_value(3600)}
it { should contain_nova_config('libvirt/remove_unused_kernels').with_value(true)}
it { should contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_value(3600)}
end
describe 'with deprecated params' do
let :params do
{ :libvirt_type => 'qemu'
}
end
it { should contain_nova_config('libvirt/virt_type').with_value('qemu')}
it { is_expected.to contain_nova_config('libvirt/virt_type').with_value('qemu')}
it { is_expected.to contain_nova_config('libvirt/cpu_mode').with_value('host-passthrough')}
it { is_expected.to contain_nova_config('libvirt/disk_cachemodes').with_value('file=directsync,block=none')}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_base_images').with_value(true)}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_value(3600)}
it { is_expected.to contain_nova_config('libvirt/remove_unused_kernels').with_value(true)}
it { is_expected.to contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_value(3600)}
it { is_expected.to contain_service('libvirt').with(
:name => 'custom_service',
:enable => true,
:ensure => 'running',
:require => 'Package[libvirt]',
:before => ['Service[nova-compute]']
)}
end
describe 'with migration_support enabled' do
@ -84,8 +87,20 @@ describe 'nova::compute::libvirt' do
:migration_support => true }
end
it { should contain_class('nova::migration::libvirt')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { is_expected.to contain_class('nova::migration::libvirt')}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { is_expected.to contain_file_line('/etc/default/libvirt-bin libvirtd opts').with(:line => 'libvirtd_opts="-d -l"') }
end
context 'with vncserver_listen set to ::0' do
let :params do
{ :vncserver_listen => '::0',
:migration_support => true }
end
it { is_expected.to contain_class('nova::migration::libvirt')}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('::0')}
it { is_expected.to contain_file_line('/etc/default/libvirt-bin libvirtd opts').with(:line => 'libvirtd_opts="-d -l"') }
end
context 'with vncserver_listen not set to 0.0.0.0' do
@ -94,8 +109,18 @@ describe 'nova::compute::libvirt' do
:migration_support => true }
end
it { expect { should contain_class('nova::compute::libvirt') }.to \
raise_error(Puppet::Error, /For migration support to work, you MUST set vncserver_listen to '0.0.0.0'/) }
it { expect { is_expected.to contain_class('nova::compute::libvirt') }.to \
raise_error(Puppet::Error, /For migration support to work, you MUST set vncserver_listen to '0.0.0.0' or '::0'/) }
end
context 'with custom libvirt service name on Debian platforms' do
let :params do
{ :libvirt_service_name => 'libvirtd',
:vncserver_listen => '0.0.0.0',
:migration_support => true }
end
it { is_expected.to contain_file_line('/etc/default/libvirtd libvirtd opts').with(:line => 'libvirtd_opts="-d -l"') }
end
end
end
@ -104,54 +129,61 @@ describe 'nova::compute::libvirt' do
describe 'on rhel platforms' do
let :facts do
{ :operatingsystem => 'RedHat', :osfamily => 'RedHat',
:operatingsystemrelease => 6.5 }
:operatingsystemrelease => 6.5,
:operatingsystemmajrelease => '6' }
end
describe 'with default parameters' do
it { should contain_class('nova::params')}
it { is_expected.to contain_class('nova::params')}
it { should contain_package('libvirt').with(
it { is_expected.to contain_package('libvirt').with(
:name => 'libvirt',
:ensure => 'present'
) }
it { should contain_service('libvirt').with(
it { is_expected.to contain_service('libvirt').with(
:name => 'libvirtd',
:enable => true,
:ensure => 'running',
:provider => nil,
:provider => 'init',
:require => 'Package[libvirt]',
:before => 'Service[nova-compute]'
:before => ['Service[nova-compute]']
)}
it { should contain_service('messagebus').with(
it { is_expected.to contain_service('messagebus').with(
:ensure => 'running',
:enable => true,
:before => 'Service[libvirt]',
:provider => nil
:before => ['Service[libvirt]'],
:provider => 'init',
:name => 'messagebus'
) }
describe 'on rhel 7' do
let :facts do
super().merge(:operatingsystemrelease => 7.0)
super().merge(:operatingsystemmajrelease => '7')
end
it { should contain_service('libvirt').with(
it { is_expected.to contain_service('libvirt').with(
:provider => nil
)}
it { should contain_service('messagebus').with(
:provider => nil
it { is_expected.to contain_service('messagebus').with(
:provider => nil,
:name => 'dbus'
)}
end
it { should contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.LibvirtDriver')}
it { should contain_nova_config('libvirt/virt_type').with_value('kvm')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('127.0.0.1')}
it { should contain_nova_config('DEFAULT/remove_unused_base_images').with_ensure('absent')}
it { should contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_ensure('absent')}
it { should contain_nova_config('libvirt/remove_unused_kernels').with_ensure('absent')}
it { should contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_ensure('absent')}
it { is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.LibvirtDriver')}
it { is_expected.to contain_nova_config('libvirt/virt_type').with_value('kvm')}
it { is_expected.to contain_nova_config('libvirt/inject_password').with_value(false)}
it { is_expected.to contain_nova_config('libvirt/inject_key').with_value(false)}
it { is_expected.to contain_nova_config('libvirt/inject_partition').with_value(-2)}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('127.0.0.1')}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_base_images').with_ensure('absent')}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_ensure('absent')}
it { is_expected.to contain_nova_config('libvirt/remove_unused_kernels').with_ensure('absent')}
it { is_expected.to contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_ensure('absent')}
end
describe 'with params' do
@ -165,21 +197,12 @@ describe 'nova::compute::libvirt' do
}
end
it { should contain_nova_config('libvirt/virt_type').with_value('qemu')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { should contain_nova_config('DEFAULT/remove_unused_base_images').with_value(true)}
it { should contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_value(3600)}
it { should contain_nova_config('libvirt/remove_unused_kernels').with_value(true)}
it { should contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_value(3600)}
end
describe 'with deprecated params' do
let :params do
{ :libvirt_type => 'qemu'
}
end
it { should contain_nova_config('libvirt/virt_type').with_value('qemu')}
it { is_expected.to contain_nova_config('libvirt/virt_type').with_value('qemu')}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_base_images').with_value(true)}
it { is_expected.to contain_nova_config('DEFAULT/remove_unused_original_minimum_age_seconds').with_value(3600)}
it { is_expected.to contain_nova_config('libvirt/remove_unused_kernels').with_value(true)}
it { is_expected.to contain_nova_config('libvirt/remove_unused_resized_minimum_age_seconds').with_value(3600)}
end
describe 'with migration_support enabled' do
@ -190,8 +213,8 @@ describe 'nova::compute::libvirt' do
:migration_support => true }
end
it { should contain_class('nova::migration::libvirt')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
it { is_expected.to contain_class('nova::migration::libvirt')}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('0.0.0.0')}
end
context 'with vncserver_listen not set to 0.0.0.0' do
@ -200,7 +223,7 @@ describe 'nova::compute::libvirt' do
:migration_support => true }
end
it { expect { should contain_class('nova::compute::libvirt') }.to \
it { expect { is_expected.to contain_class('nova::compute::libvirt') }.to \
raise_error(Puppet::Error, /For migration support to work, you MUST set vncserver_listen to '0.0.0.0'/) }
end
end
@ -210,25 +233,25 @@ describe 'nova::compute::libvirt' do
{ :operatingsystem => 'Fedora', :osfamily => 'RedHat' }
end
it { should contain_class('nova::params')}
it { is_expected.to contain_class('nova::params')}
it { should contain_package('libvirt').with(
it { is_expected.to contain_package('libvirt').with(
:name => 'libvirt',
:ensure => 'present'
) }
it { should contain_service('libvirt').with(
it { is_expected.to contain_service('libvirt').with(
:name => 'libvirtd',
:enable => true,
:ensure => 'running',
:provider => nil,
:require => 'Package[libvirt]',
:before => 'Service[nova-compute]'
:before => ['Service[nova-compute]']
)}
it { should contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.LibvirtDriver')}
it { should contain_nova_config('libvirt/virt_type').with_value('kvm')}
it { should contain_nova_config('DEFAULT/vncserver_listen').with_value('127.0.0.1')}
it { is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.LibvirtDriver')}
it { is_expected.to contain_nova_config('libvirt/virt_type').with_value('kvm')}
it { is_expected.to contain_nova_config('DEFAULT/vncserver_listen').with_value('127.0.0.1')}
end
end

View File

@ -1,22 +1,56 @@
require 'spec_helper'
describe 'nova::compute::neutron' do
it { should contain_nova_config('libvirt/vif_driver').with_value('nova.virt.libvirt.vif.LibvirtGenericVIFDriver')}
context 'with default parameters' do
it { is_expected.to contain_nova_config('libvirt/vif_driver').with_value('nova.virt.libvirt.vif.LibvirtGenericVIFDriver')}
it { is_expected.to contain_nova_config('DEFAULT/force_snat_range').with(:value => '0.0.0.0/0') }
end
context 'when overriding params' do
let :params do
{:libvirt_vif_driver => 'foo' }
end
it { should contain_nova_config('libvirt/vif_driver').with_value('foo')}
it { is_expected.to contain_nova_config('libvirt/vif_driver').with_value('foo')}
it { is_expected.to contain_nova_config('DEFAULT/force_snat_range').with_ensure(:absent) }
end
context 'when overriding with a removed libvirt_vif_driver param' do
let :params do
{:libvirt_vif_driver => 'nova.virt.libvirt.vif.LibvirtOpenVswitchDriver' }
end
it 'should fails to configure libvirt_vif_driver with old OVS driver' do
expect { subject }.to raise_error(Puppet::Error, /nova.virt.libvirt.vif.LibvirtOpenVswitchDriver as vif_driver is removed from Icehouse/)
it_raises 'a Puppet::Error', /nova.virt.libvirt.vif.LibvirtOpenVswitchDriver as vif_driver is removed from Icehouse/
end
context 'with force_snat_range parameter set to false' do
let :params do
{ :force_snat_range => false, }
end
it { is_expected.to contain_nova_config('DEFAULT/force_snat_range').with_ensure('absent') }
end
context 'with force_snat_range parameter set to 10.0.0.0/24' do
let :params do
{ :force_snat_range => '10.0.0.0/24', }
end
it { is_expected.to contain_nova_config('DEFAULT/force_snat_range').with_value('10.0.0.0/24') }
end
context 'with force_snat_range parameter set to fe80::/64' do
let :params do
{ :force_snat_range => 'fe80::/64', }
end
it { is_expected.to contain_nova_config('DEFAULT/force_snat_range').with_value('fe80::/64') }
end
context 'with force_snat_range parameter set ip without mask' do
let :params do
{ :force_snat_range => '10.0.0.0', }
end
it_raises 'a Puppet::Error', /force_snat_range should be IPv4 or IPv6 CIDR notation/
end
end

View File

@ -31,13 +31,13 @@ describe 'nova::compute::rbd' do
shared_examples_for 'nova compute rbd' do
it { should contain_class('nova::params') }
it { is_expected.to contain_class('nova::params') }
it 'configure nova.conf with default parameters' do
should contain_nova_config('libvirt/images_type').with_value('rbd')
should contain_nova_config('libvirt/images_rbd_pool').with_value('rbd')
should contain_nova_config('libvirt/images_rbd_ceph_conf').with_value('/etc/ceph/ceph.conf')
should contain_nova_config('libvirt/rbd_user').with_value('nova')
is_expected.to contain_nova_config('libvirt/images_type').with_value('rbd')
is_expected.to contain_nova_config('libvirt/images_rbd_pool').with_value('rbd')
is_expected.to contain_nova_config('libvirt/images_rbd_ceph_conf').with_value('/etc/ceph/ceph.conf')
is_expected.to contain_nova_config('libvirt/rbd_user').with_value('nova')
end
context 'when overriding default parameters' do
@ -50,41 +50,57 @@ describe 'nova::compute::rbd' do
)
end
it 'configure nova.conf with overriden parameters' do
should contain_nova_config('libvirt/images_type').with_value('rbd')
should contain_nova_config('libvirt/images_rbd_pool').with_value('AnotherPool')
should contain_nova_config('libvirt/images_rbd_ceph_conf').with_value('/tmp/ceph.conf')
should contain_nova_config('libvirt/rbd_user').with_value('joe')
it 'configure nova.conf with overridden parameters' do
is_expected.to contain_nova_config('libvirt/images_type').with_value('rbd')
is_expected.to contain_nova_config('libvirt/images_rbd_pool').with_value('AnotherPool')
is_expected.to contain_nova_config('libvirt/images_rbd_ceph_conf').with_value('/tmp/ceph.conf')
is_expected.to contain_nova_config('libvirt/rbd_user').with_value('joe')
end
end
context 'when using cephx' do
before :each do
params.merge!(
:libvirt_rbd_secret_uuid => 'UUID'
:libvirt_rbd_secret_uuid => 'UUID',
:rbd_keyring => 'client.rbd_test'
)
end
it 'configure nova.conf with RBD secret UUID' do
should contain_nova_config('libvirt/rbd_secret_uuid').with_value('UUID')
is_expected.to contain_nova_config('libvirt/rbd_secret_uuid').with_value('UUID')
end
it 'configure ceph on compute nodes' do
verify_contents(subject, '/etc/nova/secret.xml', [
verify_contents(catalogue, '/etc/nova/secret.xml', [
"<secret ephemeral=\'no\' private=\'no\'>",
" <usage type=\'ceph\'>",
" <name>client.nova secret</name>",
" <name>client.rbd_test secret</name>",
" </usage>",
" <uuid>UUID</uuid>",
"</secret>"
])
should contain_exec('get-or-set virsh secret').with(
is_expected.to contain_exec('get-or-set virsh secret').with(
:command => '/usr/bin/virsh secret-define --file /etc/nova/secret.xml | /usr/bin/awk \'{print $2}\' | sed \'/^$/d\' > /etc/nova/virsh.secret',
:creates => '/etc/nova/virsh.secret',
:require => 'File[/etc/nova/secret.xml]'
)
should contain_exec('set-secret-value virsh').with(
:command => "/usr/bin/virsh secret-set-value --secret $(cat /etc/nova/virsh.secret) --base64 $(ceph auth get-key client.nova)"
is_expected.to contain_exec('set-secret-value virsh').with(
:command => "/usr/bin/virsh secret-set-value --secret UUID --base64 $(ceph auth get-key client.rbd_test)"
)
end
end
context 'when using cephx and passing libvirt_rbd_secret_key' do
before :each do
params.merge!(
:libvirt_rbd_secret_uuid => 'UUID',
:libvirt_rbd_secret_key => 'LIBVIRT/SECRET/KEY',
)
end
it 'set libvirt secret key from passed key' do
is_expected.to contain_exec('set-secret-value virsh').with(
:command => "/usr/bin/virsh secret-set-value --secret #{params[:libvirt_rbd_secret_uuid]} --base64 #{params[:libvirt_rbd_secret_key]}"
)
end
end

View File

@ -0,0 +1,21 @@
require 'spec_helper'
describe 'nova::compute::serial' do
it { is_expected.to contain_nova_config('serial_console/enabled').with_value('true') }
it { is_expected.to contain_nova_config('serial_console/port_range').with_value('10000:20000')}
it { is_expected.to contain_nova_config('serial_console/base_url').with_value('ws://127.0.0.1:6083/')}
it { is_expected.to contain_nova_config('serial_console/listen').with_value('127.0.0.1')}
it { is_expected.to contain_nova_config('serial_console/proxyclient_address').with_value('127.0.0.1')}
context 'when overriding params' do
let :params do
{
:proxyclient_address => '10.10.10.10',
:listen => '10.10.11.11',
}
end
it { is_expected.to contain_nova_config('serial_console/proxyclient_address').with_value('10.10.10.10')}
it { is_expected.to contain_nova_config('serial_console/listen').with_value('10.10.11.11')}
end
end

View File

@ -11,28 +11,38 @@ describe 'nova::compute' do
context 'with default parameters' do
it 'installs nova-compute package and service' do
should contain_service('nova-compute').with({
is_expected.to contain_service('nova-compute').with({
:name => platform_params[:nova_compute_service],
:ensure => 'stopped',
:hasstatus => true,
:enable => false
})
should contain_package('nova-compute').with({
:name => platform_params[:nova_compute_package]
is_expected.to contain_package('nova-compute').with({
:name => platform_params[:nova_compute_package],
:tag => ['openstack']
})
end
it { should contain_nova_config('DEFAULT/network_device_mtu').with(:ensure => 'absent') }
it { should_not contain_nova_config('DEFAULT/novncproxy_base_url') }
it { is_expected.to contain_nova_config('DEFAULT/network_device_mtu').with(:ensure => 'absent') }
it { is_expected.to_not contain_nova_config('DEFAULT/novncproxy_base_url') }
it { should_not contain_package('bridge-utils').with(
it { is_expected.to_not contain_package('bridge-utils').with(
:ensure => 'present',
:before => 'Nova::Generic_service[compute]'
) }
it { should contain_package('pm-utils').with(
it { is_expected.to contain_package('pm-utils').with(
:ensure => 'present'
) }
it { is_expected.to contain_nova_config('DEFAULT/force_raw_images').with(:value => true) }
it 'configures availability zones' do
is_expected.to contain_nova_config('DEFAULT/default_availability_zone').with_value('nova')
is_expected.to contain_nova_config('DEFAULT/internal_service_availability_zone').with_value('internal')
end
it { is_expected.to contain_nova_config('DEFAULT/heal_instance_info_cache_interval').with_value('60') }
end
context 'with overridden parameters' do
@ -41,41 +51,62 @@ describe 'nova::compute' do
:ensure_package => '2012.1-2',
:vncproxy_host => '127.0.0.1',
:network_device_mtu => 9999,
:force_raw_images => false,
:reserved_host_memory => '0',
:compute_manager => 'ironic.nova.compute.manager.ClusteredComputeManager',
:default_availability_zone => 'az1',
:default_schedule_zone => 'az2',
:internal_service_availability_zone => 'az_int1',
:heal_instance_info_cache_interval => '120',
:pci_passthrough => "[{\"vendor_id\":\"8086\",\"product_id\":\"0126\"},{\"vendor_id\":\"9096\",\"product_id\":\"1520\",\"physical_network\":\"physnet1\"}]"
}
end
it 'installs nova-compute package and service' do
should contain_service('nova-compute').with({
is_expected.to contain_service('nova-compute').with({
:name => platform_params[:nova_compute_service],
:ensure => 'running',
:hasstatus => true,
:enable => true
})
should contain_package('nova-compute').with({
is_expected.to contain_package('nova-compute').with({
:name => platform_params[:nova_compute_package],
:ensure => '2012.1-2'
:ensure => '2012.1-2',
:tag => ['openstack']
})
end
it 'configures ironic in nova.conf' do
is_expected.to contain_nova_config('DEFAULT/reserved_host_memory_mb').with_value('0')
is_expected.to contain_nova_config('DEFAULT/compute_manager').with_value('ironic.nova.compute.manager.ClusteredComputeManager')
end
it 'configures network_device_mtu' do
should contain_nova_config('DEFAULT/network_device_mtu').with_value('9999')
is_expected.to contain_nova_config('DEFAULT/network_device_mtu').with_value('9999')
end
it 'configures vnc in nova.conf' do
should contain_nova_config('DEFAULT/vnc_enabled').with_value(true)
should contain_nova_config('DEFAULT/vncserver_proxyclient_address').with_value('127.0.0.1')
should contain_nova_config('DEFAULT/novncproxy_base_url').with_value(
is_expected.to contain_nova_config('DEFAULT/vnc_enabled').with_value(true)
is_expected.to contain_nova_config('DEFAULT/vncserver_proxyclient_address').with_value('127.0.0.1')
is_expected.to contain_nova_config('DEFAULT/novncproxy_base_url').with_value(
'http://127.0.0.1:6080/vnc_auto.html'
)
end
it 'configures availability zones' do
should contain_nova_config('DEFAULT/default_availability_zone').with_value('az1')
should contain_nova_config('DEFAULT/default_schedule_zone').with_value('az2')
should contain_nova_config('DEFAULT/internal_service_availability_zone').with_value('az_int1')
is_expected.to contain_nova_config('DEFAULT/default_availability_zone').with_value('az1')
is_expected.to contain_nova_config('DEFAULT/default_schedule_zone').with_value('az2')
is_expected.to contain_nova_config('DEFAULT/internal_service_availability_zone').with_value('az_int1')
end
it { is_expected.to contain_nova_config('DEFAULT/heal_instance_info_cache_interval').with_value('120') }
it { is_expected.to contain_nova_config('DEFAULT/force_raw_images').with(:value => false) }
it 'configures nova pci_passthrough_whitelist entries' do
is_expected.to contain_nova_config('DEFAULT/pci_passthrough_whitelist').with(
'value' => "[{\"vendor_id\":\"8086\",\"product_id\":\"0126\"},{\"vendor_id\":\"9096\",\"product_id\":\"1520\",\"physical_network\":\"physnet1\"}]"
)
end
end
@ -85,7 +116,7 @@ describe 'nova::compute' do
end
it 'installs bridge-utils package for nova-network' do
should contain_package('bridge-utils').with(
is_expected.to contain_package('bridge-utils').with(
:ensure => 'present',
:before => 'Nova::Generic_service[compute]'
)
@ -98,9 +129,9 @@ describe 'nova::compute' do
end
it 'disables vnc in nova.conf' do
should contain_nova_config('DEFAULT/vnc_enabled').with_value(false)
should contain_nova_config('DEFAULT/vncserver_proxyclient_address').with_value('127.0.0.1')
should_not contain_nova_config('DEFAULT/novncproxy_base_url')
is_expected.to contain_nova_config('DEFAULT/vnc_enabled').with_value(false)
is_expected.to contain_nova_config('DEFAULT/vncserver_proxyclient_address').with_value('127.0.0.1')
is_expected.to_not contain_nova_config('DEFAULT/novncproxy_base_url')
end
end
@ -109,7 +140,7 @@ describe 'nova::compute' do
{ :force_config_drive => true }
end
it { should contain_nova_config('DEFAULT/force_config_drive').with_value(true) }
it { is_expected.to contain_nova_config('DEFAULT/force_config_drive').with_value(true) }
end
context 'while not managing service state' do
@ -119,7 +150,7 @@ describe 'nova::compute' do
}
end
it { should contain_service('nova-compute').without_ensure }
it { is_expected.to contain_service('nova-compute').without_ensure }
end
context 'with instance_usage_audit parameter set to false' do
@ -127,8 +158,8 @@ describe 'nova::compute' do
{ :instance_usage_audit => false, }
end
it { should contain_nova_config('DEFAULT/instance_usage_audit').with_ensure('absent') }
it { should contain_nova_config('DEFAULT/instance_usage_audit_period').with_ensure('absent') }
it { is_expected.to contain_nova_config('DEFAULT/instance_usage_audit').with_ensure('absent') }
it { is_expected.to contain_nova_config('DEFAULT/instance_usage_audit_period').with_ensure('absent') }
end
context 'with instance_usage_audit parameter and wrong period' do
@ -137,8 +168,8 @@ describe 'nova::compute' do
:instance_usage_audit_period => 'fake', }
end
it { should contain_nova_config('DEFAULT/instance_usage_audit').with_ensure('absent') }
it { should contain_nova_config('DEFAULT/instance_usage_audit_period').with_ensure('absent') }
it { is_expected.to contain_nova_config('DEFAULT/instance_usage_audit').with_ensure('absent') }
it { is_expected.to contain_nova_config('DEFAULT/instance_usage_audit_period').with_ensure('absent') }
end
context 'with instance_usage_audit parameter and period' do
@ -147,8 +178,15 @@ describe 'nova::compute' do
:instance_usage_audit_period => 'year', }
end
it { should contain_nova_config('DEFAULT/instance_usage_audit').with_value(true) }
it { should contain_nova_config('DEFAULT/instance_usage_audit_period').with_value('year') }
it { is_expected.to contain_nova_config('DEFAULT/instance_usage_audit').with_value(true) }
it { is_expected.to contain_nova_config('DEFAULT/instance_usage_audit_period').with_value('year') }
end
context 'with vnc_keymap set to fr' do
let :params do
{ :vnc_keymap => 'fr', }
end
it { is_expected.to contain_nova_config('DEFAULT/vnc_keymap').with_value('fr') }
end
end

View File

@ -1,11 +1,11 @@
require 'spec_helper'
describe 'nova::compute::spice' do
it { should contain_nova_config('spice/enabled').with_value('true')}
it { should contain_nova_config('spice/agent_enabled').with_value('true')}
it { should contain_nova_config('spice/server_proxyclient_address').with_value('127.0.0.1')}
it { should_not contain_nova_config('spice/html5proxy_base_url')}
it { should contain_nova_config('spice/server_listen').with_value(nil)}
it { is_expected.to contain_nova_config('spice/enabled').with_value('true')}
it { is_expected.to contain_nova_config('spice/agent_enabled').with_value('true')}
it { is_expected.to contain_nova_config('spice/server_proxyclient_address').with_value('127.0.0.1')}
it { is_expected.to_not contain_nova_config('spice/html5proxy_base_url')}
it { is_expected.to contain_nova_config('spice/server_listen').with_value(nil)}
context 'when overriding params' do
let :params do
@ -15,9 +15,9 @@ describe 'nova::compute::spice' do
:agent_enabled => false
}
end
it { should contain_nova_config('spice/html5proxy_base_url').with_value('http://10.10.10.10:6082/spice_auto.html')}
it { should contain_nova_config('spice/server_listen').with_value('10.10.11.11')}
it { should contain_nova_config('spice/agent_enabled').with_value('false')}
it { is_expected.to contain_nova_config('spice/html5proxy_base_url').with_value('http://10.10.10.10:6082/spice_auto.html')}
it { is_expected.to contain_nova_config('spice/server_listen').with_value('10.10.11.11')}
it { is_expected.to contain_nova_config('spice/agent_enabled').with_value('false')}
end
end

View File

@ -18,20 +18,20 @@ describe 'nova::compute::vmware' do
end
it 'configures vmwareapi in nova.conf' do
should contain_nova_config('DEFAULT/compute_driver').with_value('vmwareapi.VMwareVCDriver')
should contain_nova_config('VMWARE/host_ip').with_value(params[:host_ip])
should contain_nova_config('VMWARE/host_username').with_value(params[:host_username])
should contain_nova_config('VMWARE/host_password').with_value(params[:host_password])
should contain_nova_config('VMWARE/cluster_name').with_value(params[:cluster_name])
should contain_nova_config('VMWARE/api_retry_count').with_value(5)
should contain_nova_config('VMWARE/maximum_objects').with_value(100)
should contain_nova_config('VMWARE/task_poll_interval').with_value(5.0)
should contain_nova_config('VMWARE/use_linked_clone').with_value(true)
should_not contain_nova_config('VMWARE/wsdl_location')
is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('vmwareapi.VMwareVCDriver')
is_expected.to contain_nova_config('VMWARE/host_ip').with_value(params[:host_ip])
is_expected.to contain_nova_config('VMWARE/host_username').with_value(params[:host_username])
is_expected.to contain_nova_config('VMWARE/host_password').with_value(params[:host_password])
is_expected.to contain_nova_config('VMWARE/cluster_name').with_value(params[:cluster_name])
is_expected.to contain_nova_config('VMWARE/api_retry_count').with_value(5)
is_expected.to contain_nova_config('VMWARE/maximum_objects').with_value(100)
is_expected.to contain_nova_config('VMWARE/task_poll_interval').with_value(5.0)
is_expected.to contain_nova_config('VMWARE/use_linked_clone').with_value(true)
is_expected.to_not contain_nova_config('VMWARE/wsdl_location')
end
it 'installs suds python package' do
should contain_package('python-suds').with(
is_expected.to contain_package('python-suds').with(
:ensure => 'present'
)
end
@ -42,11 +42,11 @@ describe 'nova::compute::vmware' do
end
it 'configures vmwareapi in nova.conf' do
should contain_nova_config('VMWARE/api_retry_count').with_value(params[:api_retry_count])
should contain_nova_config('VMWARE/maximum_objects').with_value(params[:maximum_objects])
should contain_nova_config('VMWARE/task_poll_interval').with_value(params[:task_poll_interval])
should contain_nova_config('VMWARE/use_linked_clone').with_value(false)
should contain_nova_config('VMWARE/wsdl_location').with_value(params[:wsdl_location])
is_expected.to contain_nova_config('VMWARE/api_retry_count').with_value(params[:api_retry_count])
is_expected.to contain_nova_config('VMWARE/maximum_objects').with_value(params[:maximum_objects])
is_expected.to contain_nova_config('VMWARE/task_poll_interval').with_value(params[:task_poll_interval])
is_expected.to contain_nova_config('VMWARE/use_linked_clone').with_value(false)
is_expected.to contain_nova_config('VMWARE/wsdl_location').with_value(params[:wsdl_location])
end
end
end

View File

@ -11,16 +11,16 @@ describe 'nova::compute::xenserver' do
context 'with required parameters' do
it 'configures xenapi in nova.conf' do
should contain_nova_config('DEFAULT/compute_driver').with_value('xenapi.XenAPIDriver')
should contain_nova_config('DEFAULT/connection_type').with_value('xenapi')
should contain_nova_config('DEFAULT/xenapi_connection_url').with_value(params[:xenapi_connection_url])
should contain_nova_config('DEFAULT/xenapi_connection_username').with_value(params[:xenapi_connection_username])
should contain_nova_config('DEFAULT/xenapi_connection_password').with_value(params[:xenapi_connection_password])
should contain_nova_config('DEFAULT/xenapi_inject_image').with_value(false)
is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('xenapi.XenAPIDriver')
is_expected.to contain_nova_config('DEFAULT/connection_type').with_value('xenapi')
is_expected.to contain_nova_config('DEFAULT/xenapi_connection_url').with_value(params[:xenapi_connection_url])
is_expected.to contain_nova_config('DEFAULT/xenapi_connection_username').with_value(params[:xenapi_connection_username])
is_expected.to contain_nova_config('DEFAULT/xenapi_connection_password').with_value(params[:xenapi_connection_password])
is_expected.to contain_nova_config('DEFAULT/xenapi_inject_image').with_value(false)
end
it 'installs xenapi with pip' do
should contain_package('xenapi').with(
is_expected.to contain_package('xenapi').with(
:ensure => 'present',
:provider => 'pip'
)

View File

@ -6,25 +6,101 @@ describe 'nova::conductor' do
'include nova'
end
let :params do
{ :enabled => true }
end
shared_examples 'nova-conductor' do
it { is_expected.to contain_package('nova-conductor').with(
:name => platform_params[:conductor_package_name],
:ensure => 'present'
) }
it { is_expected.to contain_service('nova-conductor').with(
:name => platform_params[:conductor_service_name],
:hasstatus => 'true',
:ensure => 'running'
)}
context 'with manage_service as false' do
let :params do
{ :enabled => true,
:manage_service => false
}
end
it { is_expected.to contain_service('nova-conductor').without_ensure }
end
context 'with package version' do
let :params do
{ :ensure_package => '2012.1-2' }
end
it { is_expected.to contain_package('nova-conductor').with(
:ensure => params[:ensure_package]
)}
end
context 'with overriden workers parameter' do
before do
params.merge!({:workers => '5' })
end
it { is_expected.to contain_nova_config('conductor/workers').with_value('5') }
end
context 'with default database parameters' do
let :pre_condition do
"include nova"
end
it { is_expected.to_not contain_nova_config('database/connection') }
it { is_expected.to_not contain_nova_config('database/slave_connection') }
it { is_expected.to_not contain_nova_config('database/idle_timeout').with_value('3600') }
end
context 'with overridden database parameters' do
let :pre_condition do
"class { 'nova':
database_connection => 'mysql://user:pass@db/db',
slave_connection => 'mysql://user:pass@slave/db',
database_idle_timeout => '30',
}
"
end
it { is_expected.to contain_nova_config('database/connection').with_value('mysql://user:pass@db/db').with_secret(true) }
it { is_expected.to contain_nova_config('database/slave_connection').with_value('mysql://user:pass@slave/db').with_secret(true) }
it { is_expected.to contain_nova_config('database/idle_timeout').with_value('30') }
end
end
context 'on Debian platforms' do
let :facts do
{ :osfamily => 'Debian' }
end
it_behaves_like 'generic nova service', {
:name => 'nova-conductor',
:package_name => 'nova-conductor',
:service_name => 'nova-conductor' }
let :platform_params do
{ :conductor_package_name => 'nova-conductor',
:conductor_service_name => 'nova-conductor' }
end
it_configures 'nova-conductor'
end
context 'on RedHat platforms' do
context 'on Redhat platforms' do
let :facts do
{ :osfamily => 'RedHat' }
end
it_behaves_like 'generic nova service', {
:name => 'nova-conductor',
:package_name => 'openstack-nova-conductor',
:service_name => 'openstack-nova-conductor' }
let :platform_params do
{ :conductor_package_name => 'openstack-nova-conductor',
:conductor_service_name => 'openstack-nova-conductor' }
end
it_configures 'nova-conductor'
end
end

View File

@ -17,14 +17,14 @@ describe 'nova::config' do
end
it 'configures arbitrary nova configurations' do
should contain_nova_config('DEFAULT/foo').with_value('fooValue')
should contain_nova_config('DEFAULT/bar').with_value('barValue')
should contain_nova_config('DEFAULT/baz').with_ensure('absent')
is_expected.to contain_nova_config('DEFAULT/foo').with_value('fooValue')
is_expected.to contain_nova_config('DEFAULT/bar').with_value('barValue')
is_expected.to contain_nova_config('DEFAULT/baz').with_ensure('absent')
end
it 'configures arbitrary nova api-paste configurations' do
should contain_nova_paste_api_ini('DEFAULT/foo2').with_value('fooValue')
should contain_nova_paste_api_ini('DEFAULT/bar2').with_value('barValue')
should contain_nova_paste_api_ini('DEFAULT/baz2').with_ensure('absent')
is_expected.to contain_nova_paste_api_ini('DEFAULT/foo2').with_value('fooValue')
is_expected.to contain_nova_paste_api_ini('DEFAULT/bar2').with_value('barValue')
is_expected.to contain_nova_paste_api_ini('DEFAULT/baz2').with_ensure('absent')
end
end

View File

@ -0,0 +1,22 @@
require 'spec_helper'
describe 'nova::cron::archive_deleted_rows' do
let :facts do
{ :osfamily => 'Debian' }
end
it 'configures a cron' do
is_expected.to contain_cron('nova-manage db archive_deleted_rows').with(
:command => 'nova-manage db archive_deleted_rows --max_rows 100 >>/var/log/nova/nova-rowsflush.log 2>&1',
:environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh',
:user => 'nova',
:minute => 1,
:hour => 0,
:monthday => '*',
:month => '*',
:weekday => '*',
:require => 'Package[nova-common]',
)
end
end

View File

@ -20,20 +20,20 @@ describe 'nova::db::mysql' do
required_params
end
it { should contain_mysql__db('nova').with(
:user => 'nova',
:password => 'qwerty',
:charset => 'latin1',
:require => "Class[Mysql::Config]"
it { is_expected.to contain_openstacklib__db__mysql('nova').with(
:user => 'nova',
:password_hash => '*AA1420F182E88B9E5F874F6FBE7459291E8F4601',
:charset => 'utf8',
:collate => 'utf8_general_ci',
)}
end
context 'when overriding charset' do
let :params do
{ :charset => 'utf8' }.merge(required_params)
{ :charset => 'latin1' }.merge(required_params)
end
it { should contain_mysql__db('nova').with_charset(params[:charset]) }
it { is_expected.to contain_openstacklib__db__mysql('nova').with_charset(params[:charset]) }
end
end
@ -47,20 +47,20 @@ describe 'nova::db::mysql' do
required_params
end
it { should contain_mysql__db('nova').with(
:user => 'nova',
:password => 'qwerty',
:charset => 'latin1',
:require => "Class[Mysql::Config]"
it { is_expected.to contain_openstacklib__db__mysql('nova').with(
:user => 'nova',
:password_hash => '*AA1420F182E88B9E5F874F6FBE7459291E8F4601',
:charset => 'utf8',
:collate => 'utf8_general_ci',
)}
end
context 'when overriding charset' do
let :params do
{ :charset => 'utf8' }.merge(required_params)
{ :charset => 'latin1' }.merge(required_params)
end
it { should contain_mysql__db('nova').with_charset(params[:charset]) }
it { is_expected.to contain_openstacklib__db__mysql('nova').with_charset(params[:charset]) }
end
end
@ -75,16 +75,6 @@ describe 'nova::db::mysql' do
}
end
it {should_not contain_nova__db__mysql__host_access("127.0.0.1").with(
:user => 'nova',
:password => 'novapass',
:database => 'nova'
)}
it {should contain_nova__db__mysql__host_access("%").with(
:user => 'nova',
:password => 'novapass',
:database => 'nova'
)}
end
describe "overriding allowed_hosts param to string" do
@ -98,11 +88,6 @@ describe 'nova::db::mysql' do
}
end
it {should contain_nova__db__mysql__host_access("192.168.1.1").with(
:user => 'nova',
:password => 'novapass2',
:database => 'nova'
)}
end
describe "overriding allowed_hosts param equals to host param " do
@ -116,10 +101,5 @@ describe 'nova::db::mysql' do
}
end
it {should_not contain_nova__db__mysql__host_access("127.0.0.1").with(
:user => 'nova',
:password => 'novapass2',
:database => 'nova'
)}
end
end

View File

@ -1,26 +1,32 @@
require 'spec_helper'
describe 'nova::db::postgresql' do
let :required_params do
{ :password => "qwerty" }
let :req_params do
{ :password => 'pw' }
end
let :pre_condition do
'include postgresql::server'
end
context 'on a RedHat osfamily' do
let :facts do
{
:postgres_default_version => '8.4',
:osfamily => 'RedHat'
:osfamily => 'RedHat',
:operatingsystemrelease => '7.0',
:concat_basedir => '/var/lib/puppet/concat'
}
end
context 'with only required parameters' do
let :params do
required_params
req_params
end
it { should contain_postgresql__db('nova').with(
:user => 'nova',
:password => 'qwerty'
it { is_expected.to contain_postgresql__server__db('nova').with(
:user => 'nova',
:password => 'md557ae0608fad632bf0155cb9502a6b454'
)}
end
@ -29,19 +35,21 @@ describe 'nova::db::postgresql' do
context 'on a Debian osfamily' do
let :facts do
{
:postgres_default_version => '8.4',
:osfamily => 'Debian'
:operatingsystemrelease => '7.8',
:operatingsystem => 'Debian',
:osfamily => 'Debian',
:concat_basedir => '/var/lib/puppet/concat'
}
end
context 'with only required parameters' do
let :params do
required_params
req_params
end
it { should contain_postgresql__db('nova').with(
:user => 'nova',
:password => 'qwerty'
it { is_expected.to contain_postgresql__server__db('nova').with(
:user => 'nova',
:password => 'md557ae0608fad632bf0155cb9502a6b454'
)}
end

View File

@ -0,0 +1,49 @@
require 'spec_helper'
describe 'nova::db' do
let :params do
{}
end
shared_examples 'nova-db' do
context 'with default parameters' do
it { is_expected.to_not contain_nova_config('database/connection') }
it { is_expected.to_not contain_nova_config('database/slave_connection') }
it { is_expected.to_not contain_nova_config('database/idle_timeout') }
end
context 'with overriden parameters' do
before :each do
params.merge!(
:database_connection => 'mysql://user:pass@db/db',
:slave_connection => 'mysql://user:pass@slave/db',
:database_idle_timeout => '30',
)
end
it { is_expected.to contain_nova_config('database/connection').with_value('mysql://user:pass@db/db').with_secret(true) }
it { is_expected.to contain_nova_config('database/slave_connection').with_value('mysql://user:pass@slave/db').with_secret(true) }
it { is_expected.to contain_nova_config('database/idle_timeout').with_value('30') }
end
end
context 'on Debian platforms' do
let :facts do
{ :osfamily => 'Debian' }
end
it_configures 'nova-db'
end
context 'on Redhat platforms' do
let :facts do
{ :osfamily => 'RedHat' }
end
it_configures 'nova-db'
end
end

Some files were not shown because too many files have changed in this diff Show More