Browse Source

Initial commit

Jan Sušnik 8 years ago
commit
e8d5662974
100 changed files with 10045 additions and 0 deletions
  1. 372 0
      CHANGELOG.md
  2. 21 0
      Gemfile
  3. 13 0
      LICENSE
  4. 14 0
      README.md
  5. 137 0
      README_ORIGINAL
  6. 1 0
      Rakefile
  7. 0 0
      bindep.txt
  8. 55 0
      examples/nova_with_pacemaker.pp
  9. 31 0
      examples/nova_wsgi.pp
  10. 11 0
      lib/facter/libvirt_uuid.rb
  11. 27 0
      lib/puppet/parser/functions/check_array_of_hash.rb
  12. 227 0
      lib/puppet/provider/nova.rb
  13. 107 0
      lib/puppet/provider/nova_aggregate/openstack.rb
  14. 87 0
      lib/puppet/provider/nova_cells/nova_manage.rb
  15. 10 0
      lib/puppet/provider/nova_config/openstackconfig.rb
  16. 122 0
      lib/puppet/provider/nova_flavor/openstack.rb
  17. 85 0
      lib/puppet/provider/nova_floating/nova_manage.rb
  18. 43 0
      lib/puppet/provider/nova_network/nova.rb
  19. 27 0
      lib/puppet/provider/nova_paste_api_ini/ini_setting.rb
  20. 37 0
      lib/puppet/provider/nova_security_group/nova.rb
  21. 51 0
      lib/puppet/provider/nova_security_rule/nova.rb
  22. 66 0
      lib/puppet/provider/nova_service/openstack.rb
  23. 10 0
      lib/puppet/provider/novajoin_config/ini_setting.rb
  24. 120 0
      lib/puppet/type/nova_aggregate.rb
  25. 115 0
      lib/puppet/type/nova_cells.rb
  26. 61 0
      lib/puppet/type/nova_config.rb
  27. 144 0
      lib/puppet/type/nova_flavor.rb
  28. 19 0
      lib/puppet/type/nova_floating.rb
  29. 66 0
      lib/puppet/type/nova_network.rb
  30. 47 0
      lib/puppet/type/nova_paste_api_ini.rb
  31. 66 0
      lib/puppet/type/nova_security_group.rb
  32. 141 0
      lib/puppet/type/nova_security_rule.rb
  33. 73 0
      lib/puppet/type/nova_service.rb
  34. 53 0
      lib/puppet/type/novajoin_config.rb
  35. 506 0
      manifests/api.pp
  36. 43 0
      manifests/availability_zone.pp
  37. 117 0
      manifests/cache.pp
  38. 51 0
      manifests/cell_v2/cell.pp
  39. 23 0
      manifests/cell_v2/discover_hosts.pp
  40. 28 0
      manifests/cell_v2/map_cell0.pp
  41. 22 0
      manifests/cell_v2/map_cell_and_hosts.pp
  42. 47 0
      manifests/cell_v2/map_instances.pp
  43. 52 0
      manifests/cell_v2/simple_setup.pp
  44. 239 0
      manifests/cells.pp
  45. 36 0
      manifests/cert.pp
  46. 21 0
      manifests/client.pp
  47. 337 0
      manifests/compute.pp
  48. 35 0
      manifests/compute/ironic.pp
  49. 268 0
      manifests/compute/libvirt.pp
  50. 55 0
      manifests/compute/libvirt/qemu.pp
  51. 108 0
      manifests/compute/libvirt/services.pp
  52. 48 0
      manifests/compute/neutron.pp
  53. 140 0
      manifests/compute/rbd.pp
  54. 34 0
      manifests/compute/serial.pp
  55. 67 0
      manifests/compute/spice.pp
  56. 109 0
      manifests/compute/vmware.pp
  57. 376 0
      manifests/compute/xenserver.pp
  58. 71 0
      manifests/conductor.pp
  59. 42 0
      manifests/config.pp
  60. 39 0
      manifests/consoleauth.pp
  61. 85 0
      manifests/cron/archive_deleted_rows.pp
  62. 154 0
      manifests/db.pp
  63. 82 0
      manifests/db/mysql.pp
  64. 74 0
      manifests/db/mysql_api.pp
  65. 59 0
      manifests/db/mysql_placement.pp
  66. 39 0
      manifests/db/online_data_migrations.pp
  67. 48 0
      manifests/db/postgresql.pp
  68. 48 0
      manifests/db/postgresql_api.pp
  69. 39 0
      manifests/db/sync.pp
  70. 52 0
      manifests/db/sync_api.pp
  71. 118 0
      manifests/deps.pp
  72. 75 0
      manifests/generic_service.pp
  73. 779 0
      manifests/init.pp
  74. 111 0
      manifests/ironic/common.pp
  75. 142 0
      manifests/keystone/auth.pp
  76. 93 0
      manifests/keystone/auth_placement.pp
  77. 279 0
      manifests/keystone/authtoken.pp
  78. 136 0
      manifests/logging.pp
  79. 89 0
      manifests/manage/cells.pp
  80. 17 0
      manifests/manage/floating.pp
  81. 71 0
      manifests/manage/network.pp
  82. 207 0
      manifests/metadata/novajoin/api.pp
  83. 210 0
      manifests/migration/libvirt.pp
  84. 54 0
      manifests/migration/qemu.pp
  85. 210 0
      manifests/network.pp
  86. 43 0
      manifests/network/bridge.pp
  87. 42 0
      manifests/network/flat.pp
  88. 79 0
      manifests/network/flatdhcp.pp
  89. 237 0
      manifests/network/neutron.pp
  90. 72 0
      manifests/network/vlan.pp
  91. 44 0
      manifests/objectstore.pp
  92. 144 0
      manifests/params.pp
  93. 76 0
      manifests/placement.pp
  94. 43 0
      manifests/policy.pp
  95. 189 0
      manifests/quota.pp
  96. 75 0
      manifests/rabbitmq.pp
  97. 50 0
      manifests/scheduler.pp
  98. 256 0
      manifests/scheduler/filter.pp
  99. 51 0
      manifests/serialproxy.pp
  100. 0 0
      manifests/spicehtml5proxy.pp

+ 372 - 0
CHANGELOG.md

@@ -0,0 +1,372 @@
+## 8.0.0 and beyond
+
+From 8.0.0 release and beyond, release notes are published on
+[docs.openstack.org](http://docs.openstack.org/releasenotes/puppet-nova/).
+
+##2015-11-25 - 7.0.0
+###Summary
+
+This is a backwards-incompatible major release for OpenStack Liberty.
+
+####Backwards-incompatible changes
+- change section name for AMQP qpid parameters
+- change section name for AMQP rabbit parameters
+- remove deprecated mysql_module
+- do not manage python-greenlet anymore
+- rabbitmq: do not manage rabbitmq service anymore
+- remove openstackocci installation feature
+- enable nova service by default
+
+####Features
+- add tag to package and service resources
+- add nova::db::sync
+- add an ability to manage use_stderr parameter
+- reflect provider change in puppet-openstacklib
+- add nameservers (dns) parameters
+- move os_region_name config option
+- use auth_nova method to create nova network
+- api: add default_floating_pool parameter
+- db: Use postgresql lib class for psycopg package
+- add support for RabbitMQ connection heartbeat
+- move cinder_catalog_info to init
+- don't add non-existent hosts to host aggregates
+- make libvirt migration security configurable
+- add region support to nova providers
+- floating IP range support in Nova network
+- rename neuton/url_timeout to neutron/timeout
+- add upgrade_levels configuration options
+- switch nova to leverage os_package_type fact
+- use os_package_type for libvirt service name
+- making instance_name_template configurable
+- remove POSIX users, groups, and file modes
+- allows the modification of the nova-api ports
+- put all the logging related parameters to the logging class
+- add kombu_reconnect_delay option
+- update nova::db class to match other module pattern
+- volume: allow to change catalog_info
+- add config_drive_format option to nova_compute
+- handle libvirt/cpu_model option
+- add ability to set default baremetal filters
+
+####Bugfixes
+- rely on autorequire for config resource ordering
+- avoid empty notification driver
+- fixed issue with rabbit_hosts parameter
+- docfix: update default image_service param in doc
+
+####Maintenance
+- fix rspec 3.x syntax
+- acceptance: enable debug & verbosity for OpenStack logs
+- initial msync run for all Puppet OpenStack modules
+- try to use zuul-cloner to prepare fixtures
+- remove class_parameter_defaults puppet-lint check
+- acceptance: use common bits from puppet-openstack-integration
+- spec: enable webmock connect to IPv4 link-local
+
+##2015-10-10 - 6.1.0
+###Summary
+
+This is a feature and maintenance release in the Kilo series.
+
+####Features
+- Allow to change archive destination
+- Support allow_start and allow_end parameters
+- Add ability to override compute_driver
+
+####Maintenance
+- acceptance: checkout stable/kilo puppet modules
+- Remove dead nova providers
+- Remove very old xenserver configs
+
+##2015-07-08 - 6.0.0
+###Summary
+
+This is a backwards-incompatible major release for OpenStack Kilo.
+
+####Backwards-incompatible changes
+- Remove deprecated parameters
+- Disable file injection when using RBD as compute ephemeral storage
+- Remove Python Package Declaration
+- move setting of novncproxy_base_url
+- Move rabbit/kombu settings to oslo_messaging_rabbit section
+- MySQL: change default MySQL collate to utf8_general_ci
+- Moved spice configuration options from DEFAULT to spice section
+
+####Features
+- Puppet 4.x support
+- Refactorise Keystone resources management
+- Configure database parameters on the right nodes
+- Add parameters for availability zones configuration
+- Migrate postgresql backend to use openstacklib::db::postgresql
+- Allow auth_name and auth_name_v3 to be the same
+- Add an option to not configure RabbitMQ service
+- Database: add slave_connection support
+- Support for heal_instance_info_cache_interval
+- Only tag packages with openstack tag
+- Add PCI Passthrough/SR-IOV support
+- Add support for identity_uri
+- IPv6 support for migration check
+- Allow libvirt secret key setting from param
+- Adds OracleLinux support
+- Ensure /etc/nova exists before creating secret.xml
+- Run db-sync if nova packages are upgraded
+- Make package 'bridge-utils' install optional
+- Introduce public_url, internal_url and admin_url (and v3/ec2)
+- Better handling of package dependencies in nova generic_service
+- Add scheduler_driver parameter to nova::scheduler class
+- Add parameter to control use of rbd for the ephemeral storage
+- Install only required libvirt packages
+- keystone/auth: make service description configurable
+
+####Bugfixes
+- Fix catalog compilation when not configuring endpoint
+- Fix behaviour of 'set-secret-value virsh' exec
+- Fix variable access in RBD secret template
+
+####Maintenance
+- Acceptance tests with Beaker
+- Fix spec tests for RSpec 3.x and Puppet 4.x
+
+##2015-06-17 - 5.1.0
+###Summary
+
+This is a feature and bugfix release in the Juno series.
+
+####Features
+- Added parameters for availability zones configuration
+- IPv6 support for migration check
+- Database: add slave_connection support
+- supporting lxc cpu mode
+- Add serialproxy configuration
+- Switch to TLSv1 as SSLv3 is considered insecure and is disabled by default
+- Add PCI Passthrough/SR-IOV support
+- Add Ironic support into nova puppet modules
+
+####Bugfixes
+- Move setting of novncproxy_base_url
+- 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
+- Make group on /var/log/nova OS specific
+- 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
+- virsh returns a list of secret uuids, not keyring names
+- Disable file injection when using RBD as compute ephemeral storage
+- Correct section for cell_type nova.conf parameter
+- crontab: ensure the script is run with shell
+- Configure database parameters on the right nodes
+
+####Maintenance
+- Pin puppetlabs-concat to 1.2.1 in fixtures
+- Pin fixtures for stables branches
+- spec: pin rspec-puppet to 1.0.1
+
+##2014-11-24 - 5.0.0
+###Summary
+
+This is a backwards-incompatible major release for OpenStack Juno.
+
+####Backwards-incompatible changes
+- Update the [glance] and [neutron] section parameters for Juno
+- Bump stdlib dependency to >=4.0.0
+- Update nova quota parameters for Juno
+- Migrate the ceilometer::db::mysql class to use openstacklib::db::mysql,
+  adding new dependency on openstacklib
+- Removed deprecation notice for sectionless nova_config names
+
+####Features
+- Add tags to all nova packages
+- Add parameter dhcp_domain to nova class
+- Add parameters for nova service validation to nova::api
+- Add nova::policy to control policy.json
+- Add force_raw_images parameter to nova::compute class
+- Add parameter ec2_workers to nova::api
+- Add parameter rabbit_ha_queues to nova class
+- Add parameter pool to nova_floating type
+- Add parameters to control whether to configure keystone users
+- Add nova::cron::archive_deleted_rows class to create a crontab for archiving
+  deleted database rows
+- Add parameter keystone_ec2_url to nova::api
+- Add the ability to override the keystone service name in
+  ceilometer::keystone::auth
+- Add parameter workers to in nova::conductor and deprecate conductor_workers
+  in nova::api
+- Add parameter vnc_keymap in nova::compute
+- Add parameter osapi_v3 to nova::api
+
+####Bugfixes
+- Fix potential duplicate declaration errors for sysctl::value in nova::network
+- Fix dependency cycle in nova::migration::libvirt
+- Update the libvirtd init script path for Debian
+- Fix the rabbit_virtual_host default in nova::cells
+- Fix bug in usage of --vlan versus --vlan_start in nova_network provider
+- Change the keystone_service to only be configured if the endpoint is to be
+  configured
+- Remove dynamic scoping of File resources in nova class
+
+####Maintenance
+- Replace usage of the keyword type with the string 'type' since type is a
+  reserved keyword in puppet 3.7
+
+##2014-11-17 - 4.2.0
+###Summary
+
+This is a feature and bugfix release in the Icehouse series.
+
+####Features
+- Add option to configure libvirt service name via class parameters
+- Add support for multiple SSL APIs
+- Add option to configure os_region_name in the nova config
+- Add class for extended logging options
+
+####Bugfixes
+- Correct resource dependencies on the nova user
+- Fix os version fact comparison for RedHat-based operating systems
+  for specifying service provider
+- Fix ssl parameter requirements when using kombu and rabbit
+
+##2014-06-20 - 4.1.0
+###Summary
+
+This is a feature and bugfix release in the Icehouse series.
+
+####Features
+- Add API v3 endpoint support
+- Add configuration of rbd keyring name
+- Add support for run Nova SSL endpoints
+
+####Bugfixes
+- Update RabbitMQ dependency
+- Update mysql charset to UTF8
+
+####Maintenance
+- Pin major gems
+
+##2014-05-01 - 4.0.0
+###Summary
+
+This is a major release for OpenStack Icehouse but contains no API-breaking
+changes.
+
+####Features
+- Add support for RHEL 7
+- Add support for metadata and conductor workers
+- Add support for vif_plugging parameters
+- Add support for puppetlabs-mysql 2.2 and greater
+- Add support for instance_usage_audit parameters
+- Add support to manage the nova uid/gid for NFS live migration
+- Add nova::config to handle additional custom options
+- Add support to disable installation of nova utilities
+- Add support for durable RabbitMQ queues
+- Add SSL support for RabbitMQ
+- Add support for nova-objectstore bind address
+
+####Bugfixes
+- Update support for notification parameters
+- Fix packaging bugs
+- Fix report_interval configuration
+- Fix file location for nova compute rbd secret
+
+##2014-04-15 - 3.2.1
+###Summary
+
+This is a bugfix release in the Havana series.
+
+####Bugfixes
+- Fix consoleauth/spice resource duplication on Red Hat systems
+
+##2014-03-26 - 3.2.0
+###Summary
+
+This is a feature and bugfix release in the Havana series.
+
+####Features
+- Deprecate logdir parameter in favor of log_dir
+- Allow log_dir to be set to false in order to disable file logging
+- Add RBD backend support for VM image storage
+- Parameterize libvirt cpu_mode and disk_cachemodes
+- Add support for https auth endpoints
+- Add ability to disable installation of nova utilities
+
+####Bugfixes
+- Replace pip with native package manager for VMWare
+- Enable libvirt at boot
+
+##2014-02-14 - 3.1.0
+###Summary
+
+This is a bugfix release in the Havana series.
+
+####Bugfixes
+- Add libguestfs-tools package to nova utilities
+- Fix vncproxy package naming for Ubuntu
+- Fix libvirt configuration
+
+##2014-01-13 - 3.0.0
+###Summary
+
+This is a backwards-incompatible major release for OpenStack Havana.
+
+####Backwards-incompatible changes
+
+- Remove api-paste.ini configuration
+
+####Features
+- Add support for live migrations with using the libvirt Nova driver
+- Add support for VMWareVCDriver
+
+####Bugfixes
+- Fix bug to ensure keystone endpoint is set before service is started
+- Fix nova-spiceproxy support on Ubuntu
+
+##2013-10-07 - 2.2.0
+###Summary
+
+This is a feature and bugfix release in the Grizzly series.
+
+####Features
+- Add a check to install bridge-utils only if needed
+- Add syslog support
+- Add installation of pm-utils for VM power management support
+
+####Bugfixes
+- Fix cinder include dependency bug
+
+##2013-08-07 - 2.1.0
+###Summary
+
+This is a feature and bugfix release in the Grizzly series.
+
+####Features
+- Add support for X-Forwarded-For HTTP Headers
+- Add html5 spice support
+- Add config drive support
+- Add RabbitMQ clustering support
+- Add memcached support
+- Add SQL idle timeout support
+
+####Bugfixes
+- Fix allowed_hosts/database connection bug
+
+####Maintenance
+- Pin RabbitMQ and database module versions
+
+##2013-06-24 - 2.0.0
+###Summary
+
+Initial release on StackForge.
+
+####Features
+- 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']
+- The Apache Qpid message broker is available as an RPC backend
+- Further compatibility fixes for RHEL and its derivatives
+- Postgres support added
+- Adjustments to help in supporting the still in development neutron module
+- Config changes can be hidden from Puppet logs
+- Move from deprecated rabbit_notifier to rpc_notifier

+ 21 - 0
Gemfile

@@ -0,0 +1,21 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+group :development, :test, :system_tests do
+  gem 'puppet-openstack_spec_helper',
+      :git     => 'https://git.openstack.org/openstack/puppet-openstack_spec_helper',
+      :require => false
+end
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby

+ 13 - 0
LICENSE

@@ -0,0 +1,13 @@
+Copyright 2012 OpenStack Foundation
+
+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.

+ 14 - 0
README.md

@@ -0,0 +1,14 @@
+puppet-nova
+===
+
+This repository contains fix when installing Packstack with Ironic for OpenStack Ocata release (otherwise it shouldn't be used). There are only few changes in `manifests/scheduler/filter.pp` file - removal of anything that depends on `$scheduler_host_manager` since it is duplicated in official repository and Packstack installation fails.
+
+Development and general information
+-----------------------------------
+
+For any additional information about development or anything other connected to puppet-nova, please refer to original README (in file `README_ORIGINAL`), or check official repository located at https://github.com/openstack/puppet-nova
+
+License
+-------
+
+The software is provided "as is", without warranty of any kind from my side. All files in project are included as fetched from source and may have been changed in the way to make things work with technologies specified above. Please read original license which is added to the project if you want to further use this software or modify it. All respective rights reserved to authors and contributors.

+ 137 - 0
README_ORIGINAL

@@ -0,0 +1,137 @@
+Team and repository tags
+========================
+
+[![Team and repository tags](http://governance.openstack.org/badges/puppet-nova.svg)](http://governance.openstack.org/reference/tags/index.html)
+
+<!-- Change things from this point on -->
+
+nova
+====
+
+#### Table of Contents
+
+1. [Overview - What is the nova module?](#overview)
+2. [Module Description - What does the module do?](#module-description)
+3. [Setup - The basics of getting started with nova](#setup)
+4. [Implementation - An under-the-hood peek at what the module is doing](#implementation)
+5. [Limitations - OS compatibility, etc.](#limitations)
+6. [Development - Guide for contributing to the module](#development)
+7. [Contributors - Those with commits](#contributors)
+
+Overview
+--------
+
+The nova module is a part of [OpenStack](https://github.com/openstack), an effort by the OpenStack infrastructure team to provide continuous integration testing and code review for OpenStack and OpenStack community projects as part of the core software.  The module its self is used to flexibly configure and manage the compute service for OpenStack.
+
+Module Description
+------------------
+
+The nova module is a thorough attempt to make Puppet capable of managing the entirety of nova.  This includes manifests to provision such things as keystone endpoints, RPC configurations specific to nova, and database connections.  Types are shipped as part of the nova module to assist in manipulation of configuration files.
+
+This module is tested in combination with other modules needed to build and leverage an entire OpenStack software stack.
+
+Setup
+-----
+
+**What the nova module affects:**
+
+* [Nova](https://wiki.openstack.org/wiki/Nova), the compute service for OpenStack.
+
+### Installing nova
+
+    puppet module install openstack/nova
+
+### Beginning with nova
+
+To utilize the nova module's functionality you will need to declare multiple resources. This is not an exhaustive list of all the components needed, we recommend you consult and understand the [core openstack](http://docs.openstack.org) documentation.
+
+```puppet
+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',
+  rabbit_host         => '127.0.0.1',
+}
+
+class { 'nova::compute':
+  enabled                       => true,
+  vnc_enabled                   => true,
+}
+
+class { 'nova::compute::libvirt':
+  migration_support => true,
+}
+```
+
+Implementation
+--------------
+
+### nova
+
+nova is a combination of Puppet manifest and ruby code to delivery configuration and extra functionality through types and providers.
+
+### Types
+
+#### nova_config
+
+The `nova_config` provider is a children of the ini_setting provider. It allows one to write an entry in the `/etc/nova/nova.conf` file.
+
+```puppet
+nova_config { 'DEFAULT/image_service' :
+  value => nova.image.glance.GlanceImageService,
+}
+```
+
+This will write `image_service=nova.image.glance.GlanceImageService` in the `[DEFAULT]` section.
+
+##### name
+
+Section/setting name to manage from `nova.conf`
+
+##### value
+
+The value of the setting to be defined.
+
+##### secret
+
+Whether to hide the value from Puppet logs. Defaults to `false`.
+
+##### ensure_absent_val
+
+If value is equal to ensure_absent_val then the resource will behave as if `ensure => absent` was specified. Defaults to `<SERVICE DEFAULT>`
+
+Limitations
+-----------
+
+* Supports libvirt, xenserver and vmware compute drivers.
+* Tested on EL and Debian derivatives.
+
+Development
+-----------
+
+Developer documentation for the entire puppet-openstack project.
+
+* http://docs.openstack.org/developer/puppet-openstack-guide/
+
+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-rspec/blob/master/README.md
+
+Contributors
+------------
+
+* https://github.com/openstack/puppet-nova/graphs/contributors

+ 1 - 0
Rakefile

@@ -0,0 +1 @@
+require 'puppet-openstack_spec_helper/rake_tasks'

+ 0 - 0
bindep.txt


+ 55 - 0
examples/nova_with_pacemaker.pp

@@ -0,0 +1,55 @@
+# Example: managing nova compute controller services with pacemaker
+#
+# By setting enabled to false, these services will not be started at boot.  By setting
+# manage_service to false, puppet will not kill these services on every run.  This
+# allows the Pacemaker resource manager to dynamically determine on which node each
+# service should run.
+#
+# The puppet commands below would ideally be applied to at least three nodes.
+#
+# Note that nova-api and nova-novncproxy are associated with the virtual IP address as
+# they are called from external services.  The remaining services connect to the
+# database and/or message broker independently.
+#
+# Example pacemaker resource configuration commands (configured once per cluster):
+#
+# sudo pcs resource create nova_vip ocf:heartbeat:IPaddr2 params ip=192.0.2.3 \
+#   cidr_netmask=24 op monitor interval=10s
+#
+# sudo pcs resource create nova_api_service lsb:openstack-nova-api
+# sudo pcs resource create nova_conductor_service lsb:openstack-nova-conductor
+# sudo pcs resource create nova_consoleauth_service lsb:openstack-nova-consoleauth
+# sudo pcs resource create nova_novncproxy_service lsb:openstack-nova-novncproxy
+# sudo pcs resource create nova_scheduler_service lsb:openstack-nova-scheduler
+#
+# 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::api':
+  enabled        => false,
+  manage_service => false,
+  admin_password => 'PASSWORD',
+}
+
+class { '::nova::conductor':
+  enabled        => false,
+  manage_service => false,
+}
+
+class { '::nova::consoleauth':
+  enabled        => false,
+  manage_service => false,
+}
+
+class { '::nova::scheduler':
+  enabled        => false,
+  manage_service => false,
+}
+
+class { '::nova::vncproxy':
+  enabled        => false,
+  manage_service => false,
+}
+

+ 31 - 0
examples/nova_wsgi.pp

@@ -0,0 +1,31 @@
+# This manifest documents different use cases when running WSGI in Nova API
+
+# Use Case #1: running Nova API with osapi_compute in WSGI, and metadata
+class { '::nova': }
+class { '::nova::api':
+  admin_password => 'a_big_secret',
+  service_name   => 'httpd',
+}
+include ::apache
+class { '::nova::wsgi::apache':
+  ssl => false,
+}
+
+# Use Case #2: running Nova API with osapi_compute in WSGI, and metadata disabled
+class { '::nova': }
+class { '::nova::api':
+  admin_password => 'a_big_secret',
+  enabled_apis   => ['osapi_compute'],
+  service_name   => 'httpd',
+}
+include ::apache
+class { '::nova::wsgi::apache':
+  ssl => false,
+}
+
+# Use Case #3: not running osapi_compute, just enabling metadata
+class { '::nova': }
+class { '::nova::api':
+  admin_password => 'a_big_secret',
+  enabled_apis   => ['metadata'],
+}

+ 11 - 0
lib/facter/libvirt_uuid.rb

@@ -0,0 +1,11 @@
+require 'facter'
+Facter.add(:libvirt_uuid) do
+  setcode do
+    uuid_file_path = '/etc/libvirt/libvirt_uuid'
+    if File.file? uuid_file_path
+      File.read uuid_file_path
+    else
+      nil
+    end
+  end
+end

+ 27 - 0
lib/puppet/parser/functions/check_array_of_hash.rb

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

+ 227 - 0
lib/puppet/provider/nova.rb

@@ -0,0 +1,227 @@
+# Run test ie with: rspec spec/unit/provider/nova_spec.rb
+
+# Add openstacklib code to $LOAD_PATH so that we can load this during
+# standalone compiles without error.
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
+require 'puppet/util/inifile'
+require 'puppet/provider/openstack'
+require 'puppet/provider/openstack/auth'
+require 'puppet/provider/openstack/credentials'
+
+class Puppet::Provider::Nova < Puppet::Provider::Openstack
+
+  extend Puppet::Provider::Openstack::Auth
+
+  def self.request(service, action, properties=nil)
+    begin
+      super
+    rescue Puppet::Error::OpenstackAuthInputError => error
+      nova_request(service, action, error, properties)
+    end
+  end
+
+  def self.nova_request(service, action, error, properties=nil)
+    properties ||= []
+    @credentials.username = nova_credentials['username']
+    @credentials.password = nova_credentials['password']
+    @credentials.project_name = nova_credentials['project_name']
+    @credentials.auth_url = auth_endpoint
+    if @credentials.version == '3'
+      @credentials.user_domain_name = nova_credentials['user_domain_name']
+      @credentials.project_domain_name = nova_credentials['project_domain_name']
+    end
+    if nova_credentials['region_name']
+      @credentials.region_name = nova_credentials['region_name']
+    end
+    raise error unless @credentials.set?
+    Puppet::Provider::Openstack.request(service, action, properties, @credentials)
+  end
+
+  def self.conf_filename
+    '/etc/nova/nova.conf'
+  end
+
+  # deprecated: method for old nova cli auth
+  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_uri', 'project_name', 'username', 'password']
+    conf = nova_conf
+    if conf and conf['keystone_authtoken'] and
+        auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
+      creds = Hash[ auth_keys.map \
+                   { |k| [k, conf['keystone_authtoken'][k].strip] } ]
+      if conf['neutron'] and conf['neutron']['region_name']
+        creds['region_name'] = conf['neutron']['region_name'].strip
+      end
+      if !conf['keystone_authtoken']['project_domain_name'].nil?
+        creds['project_domain_name'] = conf['keystone_authtoken']['project_domain_name'].strip
+      else
+        creds['project_domain_name'] = 'Default'
+      end
+      if !conf['keystone_authtoken']['user_domain_name'].nil?
+        creds['user_domain_name'] = conf['keystone_authtoken']['user_domain_name'].strip
+      else
+        creds['user_domain_name'] = 'Default'
+      end
+      return creds
+    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_uri']}"
+  end
+
+  def self.auth_endpoint
+    @auth_endpoint ||= get_auth_endpoint
+  end
+
+  # deprecated: method for old nova cli auth
+  def self.auth_nova(*args)
+    q = nova_credentials
+    authenv = {
+      :OS_AUTH_URL     => self.auth_endpoint,
+      :OS_USERNAME     => q['username'],
+      :OS_PROJECT_NAME => q['project_name'],
+      :OS_PASSWORD     => q['password']
+    }
+    if q.key?('region_name')
+      authenv[:OS_REGION_NAME] = q['region_name']
+    end
+    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
+
+  # deprecated: method for old nova cli auth
+  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
+
+  # deprecated: string to list for nova cli
+  def self.str2list(s)
+    #parse string
+    if s.include? ","
+      if s.include? "="
+        new = {}
+      else
+        new = []
+      end
+      if s =~ /^'.+'$/
+        s.split("', '").each do |el|
+          ret = str2hash(el.strip())
+          if s.include? "="
+            new.update(ret)
+          else
+            new.push(ret)
+          end
+        end
+      else
+        s.split(",").each do |el|
+          ret = str2hash(el.strip())
+          if s.include? "="
+            new.update(ret)
+          else
+            new.push(ret)
+          end
+        end
+      end
+      return new
+    else
+      return str2hash(s.strip())
+    end
+  end
+
+  # deprecated: nova cli to list
+  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
+
+end

+ 107 - 0
lib/puppet/provider/nova_aggregate/openstack.rb

@@ -0,0 +1,107 @@
+require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/nova')
+
+Puppet::Type.type(:nova_aggregate).provide(
+  :openstack,
+  :parent => Puppet::Provider::Nova
+) do
+  desc <<-EOT
+    Provider to manage nova aggregations
+  EOT
+
+  @credentials = Puppet::Provider::Openstack::CredentialsV3.new
+
+  mk_resource_methods
+
+  def self.instances
+    request('aggregate', 'list').collect do |el|
+      attrs = request('aggregate', 'show', el[:name])
+      new(
+          :ensure => :present,
+          :name => attrs[:name],
+          :id => attrs[:id],
+          :availability_zone => attrs[:availability_zone],
+          :metadata => str2hash(attrs[:properties]),
+          :hosts => string2list(attrs[:hosts]).sort
+      )
+    end
+  end
+
+  def self.string2list(input)
+    return input[1..-2].split(",").map { |x| x.match(/'(.*?)'/)[1] }
+  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
+    @property_hash[:hosts].each do |h|
+      properties = [@property_hash[:name], h]
+      self.class.request('aggregate', 'remove host', properties)
+    end
+    self.class.request('aggregate', 'delete', @property_hash[:name])
+  end
+
+  def create
+    properties = [@resource[:name]]
+    if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty?
+      properties << "--zone" << @resource[:availability_zone]
+    end
+    if not @resource[:metadata].nil? and not @resource[:metadata].empty?
+      @resource[:metadata].each do |key, value|
+        properties << "--property" << "#{key}=#{value}"
+      end
+    end
+    @property_hash = self.class.request('aggregate', 'create', properties)
+
+    if not @resource[:hosts].nil? and not @resource[:hosts].empty?
+      @resource[:hosts].each do |host|
+        properties = [@property_hash[:name], host]
+        self.class.request('aggregate', 'add host', properties)
+      end
+    end
+  end
+
+  def availability_zone=(value)
+    self.class.request('aggregate', 'set', [ @resource[:name], '--zone', @resource[:availability_zone] ])
+  end
+
+  def metadata=(value)
+    # clear obsolete keys
+    # wip untill #1559866
+#   if @property_hash[:metadata].keys.length > 0
+#     properties = [@resource[:name] ]
+#     (@property_hash[:metadata].keys - @resource[:metadata].keys).each do |key|
+#       properties << "--property" << "#{key}"
+#     end
+#     self.class.request('aggregate', 'unset', properties)
+#   end
+    properties = [@resource[:name] ]
+    @resource[:metadata].each do |key, value|
+      properties << "--property" << "#{key}=#{value}"
+    end
+    self.class.request('aggregate', 'set', properties)
+  end
+
+  def hosts=(value)
+    # remove hosts, which are not present in update
+    (@property_hash[:hosts] - @resource[:hosts]).each do |host|
+      properties = [@property_hash[:id], host]
+      self.class.request('aggregate', 'remove host', properties)
+    end
+    # add new hosts
+    (@resource[:hosts] - @property_hash[:hosts]).each do |host|
+      properties = [@property_hash[:id], host]
+      self.class.request('aggregate', 'add host', properties)
+    end
+  end
+end

+ 87 - 0
lib/puppet/provider/nova_cells/nova_manage.rb

@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Emilien Macchi <emilien.macchi@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
+# 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_cells provider
+#
+
+Puppet::Type.type(:nova_cells).provide(:nova_manage) do
+
+  desc "Manage nova cells"
+
+  optional_commands :nova_manage => 'nova-manage'
+
+  def self.instances
+    begin
+      cells_list = nova_manage("cell", "list")
+    rescue Exception => e
+      if e.message =~ /No cells defined/
+        return []
+      else
+        raise(e)
+      end
+    end
+    cells_list.split("\n")[1..-1].collect do |net|
+      if net =~ /^(\S+)\s+(\S+)/
+        new(:name => $2 )
+      end
+    end.compact
+  end
+
+
+  def create
+    optional_opts = []
+    {
+      :name                => '--name',
+      :cell_type           => '--cell_type',
+      :rabbit_username     => '--username',
+      :rabbit_password     => '--password',
+      :rabbit_hosts        => '--hostname',
+      :rabbit_port         => '--port',
+      :rabbit_virtual_host => '--virtual_host',
+      :weight_offset       => '--woffset',
+      :weight_scale        => '--wscale'
+
+    }.each do |param, opt|
+      if resource[param]
+        optional_opts.push(opt).push(resource[param])
+      end
+    end
+
+    nova_manage('cell', 'create',
+      optional_opts
+    )
+  end
+
+  def exists?
+    begin
+      cells_list = nova_manage("cell", "list")
+      return cells_list.split("\n")[1..-1].detect do |n|
+        n =~ /^(\S+)\s+(#{resource[:cells].split('/').first})/
+      end
+    rescue
+      return false
+    end
+  end
+
+
+  def destroy
+    nova_manage("cell", "delete", resource[:name])
+  end
+
+end

+ 10 - 0
lib/puppet/provider/nova_config/openstackconfig.rb

@@ -0,0 +1,10 @@
+Puppet::Type.type(:nova_config).provide(
+  :openstackconfig,
+  :parent => Puppet::Type.type(:openstack_config).provider(:ruby)
+) do
+
+  def self.file_path
+    '/etc/nova/nova.conf'
+  end
+
+end

+ 122 - 0
lib/puppet/provider/nova_flavor/openstack.rb

@@ -0,0 +1,122 @@
+require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/nova')
+
+Puppet::Type.type(:nova_flavor).provide(
+  :openstack,
+  :parent => Puppet::Provider::Nova
+) do
+  desc <<-EOT
+     Manage Nova flavor
+  EOT
+
+  @credentials = Puppet::Provider::Openstack::CredentialsV3.new
+
+  def initialize(value={})
+    super(value)
+    @property_flush = {}
+  end
+
+  def create
+    opts = [@resource[:name]]
+    opts << (@resource[:is_public] == :true ? '--public' : '--private')
+    (opts << '--id' << @resource[:id]) if @resource[:id]
+    (opts << '--ram' << @resource[:ram]) if @resource[:ram]
+    (opts << '--disk' << @resource[:disk]) if @resource[:disk]
+    (opts << '--ephemeral' << @resource[:ephemeral]) if @resource[:ephemeral]
+    (opts << '--vcpus' << @resource[:vcpus]) if @resource[:vcpus]
+    (opts << '--swap' << @resource[:swap]) if @resource[:swap]
+    (opts << '--rxtx-factor' << @resource[:rxtx_factor]) if @resource[:rxtx_factor]
+    @property_hash = self.class.request('flavor', 'create', opts)
+    if @resource[:properties]
+      prop_opts = [@resource[:name]]
+      prop_opts << props_to_s(@resource[:properties])
+      self.class.request('flavor', 'set', prop_opts)
+    end
+    @property_hash[:ensure] = :present
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present
+  end
+
+  def destroy
+    self.class.request('flavor', 'delete', @property_hash[:id])
+  end
+
+  mk_resource_methods
+
+  def is_public=(value)
+    fail('is_public is read only')
+  end
+
+  def id=(value)
+    fail('id is read only')
+  end
+
+  def ram=(value)
+    fail('ram is read only')
+  end
+
+  def disk=(value)
+    fail('disk is read only')
+  end
+
+  def vcpus=(value)
+    fail('vcpus is read only')
+  end
+
+  def swap=(value)
+    fail('swap is read only')
+  end
+
+  def rxtx_factor=(value)
+    fail('rxtx_factor is read only')
+  end
+
+  def properties=(value)
+    @property_flush[:properties] = value
+  end
+
+  def self.instances
+    request('flavor', 'list', ['--long', '--all']).collect do |attrs|
+      properties = Hash[attrs[:properties].scan(/(\S+)='([^']*)'/)] rescue nil
+      new(
+          :ensure      => :present,
+          :name        => attrs[:name],
+          :id          => attrs[:id],
+          :ram         => attrs[:ram],
+          :disk        => attrs[:disk],
+          :ephemeral   => attrs[:ephemeral],
+          :vcpus       => attrs[:vcpus],
+          :is_public   => attrs[:is_public].downcase.chomp == 'true'? true : false,
+          :swap        => attrs[:swap],
+          :rxtx_factor => attrs[:rxtx_factor],
+          :properties  => properties
+      )
+    end
+  end
+
+  def self.prefetch(resources)
+    flavors = instances
+    resources.keys.each do |name|
+      if provider = flavors.find{ |flavor| flavor.name == name }
+        resources[name].provider = provider
+      end
+    end
+  end
+
+  def flush
+    unless @property_flush.empty?
+      opts = [@resource[:name]]
+      opts << props_to_s(@property_flush[:properties])
+
+      self.class.request('flavor', 'set', opts)
+      @property_flush.clear
+    end
+  end
+  private
+
+  def props_to_s(props)
+    props.flat_map{ |k, v| ['--property', "#{k}=#{v}"] }
+  end
+end
+

+ 85 - 0
lib/puppet/provider/nova_floating/nova_manage.rb

@@ -0,0 +1,85 @@
+Puppet::Type.type(:nova_floating).provide(:nova_manage) do
+
+  desc "Manage nova floating"
+
+  optional_commands :nova_manage => 'nova-manage'
+
+  def exists?
+    if resource[:network] =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/
+      # Calculate num quads to grab for prefix$$
+      mask=resource[:network].sub(/.*\/([0-9][0-9]?)/, '\1').to_i
+      num_quads = 4 - mask / 8
+      prefix=resource[:network].sub(/(\.[0-9]{1,3}){#{num_quads}}(\/[0-9]{1,2})?$/, '') + "."
+      return nova_manage("floating", "list").match(/#{prefix}/)
+
+    elsif resource[:network].to_s =~ /^.{0,2}\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}.{0,2}/
+      if resource[:ensure] == :absent
+        operate_range.any?
+      else
+        operate_range.empty?
+      end
+    end
+  end
+
+  def create
+    if resource[:network] =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/
+      nova_manage("floating", "create", '--pool', resource[:pool], resource[:network])
+
+    elsif resource[:network].to_s =~ /^.{0,2}\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}.{0,2}/
+      mixed_range.each do |ip|
+        nova_manage("floating", "create", ip)
+      end
+    end
+  end
+
+  def destroy
+    if resource[:network] =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/
+      nova_manage("floating", "delete", resource[:network])
+
+    elsif resource[:network].to_s =~ /^.{0,2}\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}.{0,2}/
+      mixed_range.each do |ip|
+        nova_manage("floating", "delete", ip )
+      end
+    end
+  end
+
+  # Create range in cidr, including first and last ip
+  # Nova will create this range, excluding network and broadcast IPs
+  def mixed_range
+    require 'netaddr'
+    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 existed IPs and provided ip ranges
+  def operate_range
+    exist_range = []
+    output = nova_manage("floating", "list")
+    range_list = output.scan(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
+    range_list.each do |element|
+      exist_range << element
+    end
+    if @resource[:ensure] == :absent
+       ip_range & exist_range
+    else
+       ip_range - exist_range
+    end
+  end
+
+  def ip_range
+    require 'netaddr'
+    ip_range = []
+    Array(@resource[:network]).each do |rng|
+      ip = rng.split('-')
+      generated_range = NetAddr.range(NetAddr::CIDR.create(ip.first), NetAddr::CIDR.create(ip.last))
+      ip_range += generated_range.unshift(ip.first).push(ip.last)
+    end
+    return ip_range
+  end
+end

+ 43 - 0
lib/puppet/provider/nova_network/nova.rb

@@ -0,0 +1,43 @@
+require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/nova')
+
+Puppet::Type.type(:nova_network).provide(:nova, :parent => Puppet::Provider::Nova) do
+
+  desc "Manage nova network"
+
+  optional_commands :nova => 'nova'
+
+  def create
+    optional_opts = []
+    {
+      # this needs to be converted from a project name to an id
+      :project          => '--project_id',
+      :dns1             => '--dns1',
+      :dns2             => '--dns2',
+      :gateway          => '--gateway',
+      :bridge           => '--bridge',
+      :vlan_start       => '--vlan-start',
+      :allowed_start    => '--allowed-start',
+      :allowed_end      => '--allowed-end',
+    }.each do |param, opt|
+      if resource[param]
+        optional_opts.push(opt).push(resource[param])
+      end
+    end
+
+    opts = [resource[:label], "--fixed-range-v4", resource[:name]]
+
+    auth_nova('network-create', opts + optional_opts)
+  end
+
+  def exists?
+    instances = auth_nova('network-list')
+    return instances.split('\n')[1..-1].detect do |n|
+        n =~ /(\S+)\s+(#{resource[:network]})\s+(\S+)/
+    end
+  end
+
+  def destroy
+    auth_nova("network-delete", resource[:network])
+  end
+
+end

+ 27 - 0
lib/puppet/provider/nova_paste_api_ini/ini_setting.rb

@@ -0,0 +1,27 @@
+Puppet::Type.type(:nova_paste_api_ini).provide(
+  :ini_setting,
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
+) do
+
+  def section
+    resource[:name].split('/', 2).first
+  end
+
+  def setting
+    resource[:name].split('/', 2).last
+  end
+
+  def separator
+    '='
+  end
+
+  def self.file_path
+    '/etc/nova/api-paste.ini'
+  end
+
+  # this needs to be removed. This has been replaced with the class method
+  def file_path
+    self.class.file_path
+  end
+
+end

+ 37 - 0
lib/puppet/provider/nova_security_group/nova.rb

@@ -0,0 +1,37 @@
+require File.join(File.dirname(__FILE__), '..','..','..',
+                  'puppet/provider/nova')
+
+Puppet::Type.type(:nova_security_group).provide(
+  :nova,
+  :parent => Puppet::Provider::Nova
+) do
+
+  desc "Manage nova security groups"
+
+  commands :nova => 'nova'
+
+  mk_resource_methods
+
+  def exists?
+    sec_groups = self.class.cliout2list(auth_nova('secgroup-list'))
+    return sec_groups.detect do |n|
+        n['Name'] == resource['name']
+    end
+  end
+
+  def destroy
+    auth_nova("secgroup-delete", name)
+    @property_hash[:ensure] = :absent
+  end
+
+  def create
+    result = self.class.cliout2list(auth_nova("secgroup-create", resource[:name], resource[:description]))
+
+    @property_hash = {
+      :ensure => :present,
+      :name => resource[:name],
+      :id => result[0]['Id'],
+      :description => resource[:description]
+    }
+  end
+end

+ 51 - 0
lib/puppet/provider/nova_security_rule/nova.rb

@@ -0,0 +1,51 @@
+require File.join(File.dirname(__FILE__), '..','..','..',
+                  'puppet/provider/nova')
+
+Puppet::Type.type(:nova_security_rule).provide(
+  :nova,
+  :parent => Puppet::Provider::Nova
+) do
+
+  desc "Manage nova security rules"
+
+  commands :nova => 'nova'
+
+  mk_resource_methods
+
+  def exists?
+    @property_hash[:ensure] == :present
+  end
+
+  def destroy
+    args = Array.new
+
+    args << "#{@resource[:security_group]}"
+    args << "#{@resource[:ip_protocol]}"
+    args << "#{@resource[:from_port]}"
+    args << "#{@resource[:to_port]}"
+    if not @resource[:ip_range].nil?
+      args << "#{@resource[:ip_range]}"
+    else
+      args << "#{@resource[:source_group]}"
+    end
+
+    auth_nova("secgroup-delete-rule", args)
+    @property_hash[:ensure] = :absent
+  end
+
+  def create
+    args = Array.new
+
+    args << "#{@resource[:security_group]}"
+    args << "#{@resource[:ip_protocol]}"
+    args << "#{@resource[:from_port]}"
+    args << "#{@resource[:to_port]}"
+    if not @resource[:ip_range].nil?
+      args << "#{@resource[:ip_range]}"
+    else
+      args << "#{@resource[:source_group]}"
+    end
+
+    result = auth_nova("secgroup-add-rule", args)
+  end
+end

+ 66 - 0
lib/puppet/provider/nova_service/openstack.rb

@@ -0,0 +1,66 @@
+require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/nova')
+
+Puppet::Type.type(:nova_service).provide(
+  :openstack,
+  :parent => Puppet::Provider::Nova
+) do
+  desc <<-EOT
+    Provider to manage nova host services
+  EOT
+
+  @credentials = Puppet::Provider::Openstack::CredentialsV3.new
+
+  mk_resource_methods
+
+  def self.instances
+    hosts = {}
+    request('compute service', 'list').collect do |host_svc|
+      hname = host_svc[:host]
+      if hosts[hname].nil?
+        hosts[hname] = Hash.new {|h,k| h[k]=[]}
+        hosts[hname][:ids] = []
+        hosts[hname][:service_name] = []
+      end
+      hosts[hname][:ids] << host_svc[:id]
+      hosts[hname][:service_name] << host_svc[:binary]
+    end
+    hosts.collect do |hname, host|
+      new(
+        :ensure => :present,
+        :name => hname,
+        :ids => host[:ids],
+        :service_name => host[:service_name]
+      )
+    end
+  end
+
+  def self.prefetch(resources)
+    instances_ = self.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
+    return unless @property_hash[:ids].kind_of?(Array)
+    svcname_id_map = @property_hash[:service_name].zip(@property_hash[:ids]) || {}
+    svcname_id_map.each do |service_name, id|
+      if (@resource[:service_name].empty? ||
+          (@resource[:service_name].include? service_name))
+        self.class.request('compute service', 'delete', id)
+      end
+    end
+    @property_hash[:ensure] = :absent
+  end
+
+  def create
+    warning("Nova_service provider can only delete compute services because "\
+            "of openstackclient limitations.")
+  end
+end

+ 10 - 0
lib/puppet/provider/novajoin_config/ini_setting.rb

@@ -0,0 +1,10 @@
+Puppet::Type.type(:novajoin_config).provide(
+  :ini_setting,
+  :parent => Puppet::Type.type(:openstack_config).provider(:ini_setting)
+) do
+
+  def self.file_path
+    '/etc/nova/join.conf'
+  end
+
+end

+ 120 - 0
lib/puppet/type/nova_aggregate.rb

@@ -0,0 +1,120 @@
+# -*- 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_uri', 'project_name', 'username', '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|
+      if value.is_a?(Hash)
+        return value
+      end
+      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|
+      if value.is_a?(Hash)
+        return true
+      end
+      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|
+      if value.is_a?(Array)
+        return value
+      else
+        return value.split(",").map{|el| el.strip()}.sort
+      end
+    end
+  end
+
+  validate do
+    raise ArgumentError, 'Name type must be set' unless self[:name]
+  end
+
+end

+ 115 - 0
lib/puppet/type/nova_cells.rb

@@ -0,0 +1,115 @@
+#
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Emilien Macchi <emilien.macchi@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
+# 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_cells type
+#
+# == Parameters
+#  [*name*]
+#    Name for the new cell
+#    Optional
+#
+#  [*cell_type*]
+#    Whether the cell is a 'parent' or 'child'
+#    Required
+#
+#  [*rabbit_username*]
+#    Username for the message broker in this cell
+#    Optional
+#
+#  [*rabbit_password*]
+#    Password for the message broker in this cell
+#    Optional
+#
+#  [*rabbit_hosts*]
+#    Address of the message broker in this cell
+#    Optional
+#
+#  [*rabbit_port*]
+#    Port number of the message broker in this cell
+#    Optional
+#
+#  [*rabbit_virtual_host*]
+#    The virtual host of the message broker in this cell
+#    Optional
+#
+#  [*weight_offset*]
+#    It might be used by some cell scheduling code in the future
+#    Optional
+#
+#  [*weight_scale*]
+#    It might be used by some cell scheduling code in the future
+#    Optional
+#
+
+Puppet::Type.newtype(:nova_cells) do
+
+  @doc = "Manage creation/deletion of nova cells."
+
+  ensurable
+
+  newparam(:name) do
+    desc "Name for the new cell"
+    defaultto "api"
+  end
+
+  newparam(:cell_type) do
+    desc 'Whether the cell is a parent or child'
+  end
+
+  newparam(:rabbit_username) do
+    desc 'Username for the message broker in this cell'
+    defaultto "guest"
+  end
+
+  newparam(:rabbit_password) do
+    desc 'Password for the message broker in this cell'
+    defaultto "guest"
+  end
+
+  newparam(:rabbit_port) do
+    desc 'Port number for the message broker in this cell'
+    defaultto "5672"
+  end
+
+  newparam(:rabbit_hosts) do
+    desc 'Address of the message broker in this cell'
+    defaultto "localhost"
+  end
+
+  newparam(:rabbit_virtual_host) do
+    desc 'The virtual host of the message broker in this cell'
+    defaultto "/"
+  end
+
+  newparam(:weight_offset) do
+    desc 'It might be used by some cell scheduling code in the future'
+    defaultto "1.0"
+  end
+
+  newparam(:weight_scale) do
+    desc 'It might be used by some cell scheduling code in the future'
+    defaultto "1.0"
+  end
+
+
+  validate do
+    raise(Puppet::Error, 'Cell type must be set') unless self[:cell_type]
+  end
+
+end

+ 61 - 0
lib/puppet/type/nova_config.rb

@@ -0,0 +1,61 @@
+Puppet::Type.newtype(:nova_config) do
+
+  ensurable
+
+  newparam(:name, :namevar => true) do
+    desc 'Section/setting name to manage from nova.conf'
+    newvalues(/\S+\/\S+/)
+  end
+
+  newproperty(:value, :array_matching => :all) do
+    desc 'The value of the setting to be defined.'
+    def insync?(is)
+      return true if @should.empty?
+      return false unless is.is_a? Array
+      return false unless is.length == @should.length
+      return (
+        is & @should == is or
+        is & @should.map(&:to_s) == is
+      )
+    end
+    munge do |value|
+      value = value.to_s.strip
+      value.capitalize! if value =~ /^(true|false)$/i
+      value
+    end
+
+    def is_to_s( currentvalue )
+      if resource.secret?
+        return '[old secret redacted]'
+      else
+        return currentvalue
+      end
+    end
+
+    def should_to_s( newvalue )
+      if resource.secret?
+        return '[new secret redacted]'
+      else
+        return newvalue
+      end
+    end
+  end
+
+  newparam(:secret, :boolean => true) do
+    desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
+
+    newvalues(:true, :false)
+
+    defaultto false
+  end
+
+  newparam(:ensure_absent_val) do
+    desc 'A value that is specified as the value property will behave as if ensure => absent was specified'
+    defaultto('<SERVICE DEFAULT>')
+  end
+
+  autorequire(:package) do
+    'nova-common'
+  end
+
+end

+ 144 - 0
lib/puppet/type/nova_flavor.rb

@@ -0,0 +1,144 @@
+# nova_flavor type
+#
+# == Parameters
+#  [*name*]
+#    Name for the flavor
+#    Required
+#
+#  [*id*]
+#    Unique ID (integer or UUID) for the flavor.
+#    Optional
+#
+#  [*ram*]
+#    Amount of RAM to use (in megabytes).
+#    Optional
+#
+#  [*disk*]
+#    Amount of disk space (in gigabytes) to use for the root (/) partition.
+#    Optional
+#
+#  [*vcpus*]
+#    Number of virtual CPUs to use.
+#    Optional
+#
+#  [*ephemeral*]
+#    Amount of disk space (in gigabytes) to use for the ephemeral partition.
+#    Optional
+#
+#  [*swap*]
+#    Amount of swap space (in megabytes) to use.
+#    Optional
+#
+#  [*rxtx_factor*]
+#    The slice of bandwidth that the instances with this flavor can use
+#    (through the Virtual Interface (vif) creation in the hypervisor)
+#    Optional
+#
+#  [*is_public*]
+#    A boolean to indicate visibility
+#    Optional
+#
+#  [*properties*]
+#    A key => value hash used to set the properties for the flavor. This is
+#    the only parameter that can be updated after the creation of the flavor.
+#    Optional
+require 'puppet'
+
+Puppet::Type.newtype(:nova_flavor) do
+
+  @doc = "Manage creation of nova flavors."
+
+  ensurable
+
+  autorequire(:nova_config) do
+    ['auth_uri', 'project_name', 'username', 'password']
+  end
+
+  # Require the nova-api service to be running
+  autorequire(:service) do
+    ['nova-api']
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'Name for the flavor'
+    validate do |value|
+      if not value.is_a? String
+        raise ArgumentError, "name parameter must be a String"
+      end
+      unless value =~ /^[a-zA-Z0-9\-\._]+$/
+        raise ArgumentError, "#{value} is not a valid name"
+      end
+    end
+  end
+
+  newparam(:id) do
+    desc 'Unique ID (integer or UUID) for the flavor.'
+  end
+
+  newparam(:ram) do
+    desc 'Amount of RAM to use (in megabytes).'
+  end
+
+  newparam(:disk) do
+    desc 'Amount of disk space (in gigabytes) to use for the root (/) partition.'
+  end
+
+  newparam(:vcpus) do
+    desc 'Number of virtual CPUs to use.'
+  end
+
+  newparam(:ephemeral) do
+    desc 'Amount of disk space (in gigabytes) to use for the ephemeral partition.'
+  end
+
+  newparam(:swap) do
+    desc 'Amount of swap space (in megabytes) to use.'
+  end
+
+  newparam(:rxtx_factor) do
+    desc 'The slice of bandiwdth that the instances with this flavor can use (through the Virtual Interface (vif) creation in the hypervisor)'
+  end
+
+  newparam(:is_public) do
+    desc "Whether the image is public or not. Default true"
+    newvalues(/(y|Y)es/, /(n|N)o/, /(t|T)rue/, /(f|F)alse/, true, false)
+    defaultto(true)
+    munge do |v|
+      if v =~ /^(y|Y)es$/
+        :true
+      elsif v =~ /^(n|N)o$/
+        :false
+      else
+        v.to_s.downcase.to_sym
+      end
+    end
+  end
+
+  newproperty(:properties) do
+    desc "The set of flavor properties"
+
+    munge do |value|
+      return value if value.is_a? Hash
+
+      # wrap property value in commas
+      value.gsub!(/=(\w+)/, '=\'\1\'')
+      Hash[value.scan(/(\S+)='([^']*)'/)]
+    end
+
+    validate do |value|
+      return true if value.is_a? Hash
+
+      value.split(',').each do |property|
+        raise ArgumentError, "Key/value pairs should be separated by an =" unless property.include?('=')
+      end
+    end
+  end
+
+  validate do
+    unless self[:name]
+      raise(ArgumentError, 'Name must be set')
+    end
+  end
+
+end
+

+ 19 - 0
lib/puppet/type/nova_floating.rb

@@ -0,0 +1,19 @@
+Puppet::Type.newtype(:nova_floating) do
+
+  @doc = "Manage creation/deletion of nova floating ip ranges. "
+
+  ensurable
+
+  newparam(:network, :namevar => true) do
+    desc "It can contain network (ie, 192.168.1.0/24 or 192.168.1.128/25 etc.),
+          ip range ('192.168.1.1-192.168.1.55' or list of ip ranges ['192.168.1.1-192.168.1.25', '192.168.1.30-192.168.1.55'])"
+    newvalues(/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$ || ^(\d{1,3}\.){3}\d{1,3}-(\d{1,3}\.){3}\d{1,3}$/)
+  end
+
+  newparam(:pool) do
+    desc "Floating IP pool name. Default: 'nova'"
+    defaultto :nova
+    newvalues(/^.{1,255}$/)
+  end
+
+end

+ 66 - 0
lib/puppet/type/nova_network.rb

@@ -0,0 +1,66 @@
+Puppet::Type.newtype(:nova_network) do
+
+  @doc = "Manage creation/deletion of nova networks.  During creation, network
+          CIDR and netmask will be calculated automatically"
+
+  ensurable
+
+  # there are concerns about determining uniqiueness of network
+  # segments b/c it is actually the combination of network/prefix
+  # that determine uniqueness
+  newparam(:network, :namevar => true) do
+    desc "IPv4 Network (ie, 192.168.1.0/24)"
+    newvalues(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$/)
+  end
+
+  newparam(:label) do
+    desc "The Nova network label"
+    defaultto "novanetwork"
+  end
+
+  newparam(:num_networks) do
+    desc 'Number of networks to create'
+    defaultto(1)
+  end
+
+  newparam(:bridge) do
+    desc 'bridge to use for flat network'
+  end
+
+  newparam(:project) do
+    desc 'project that the network is associated with'
+  end
+
+  newparam(:gateway) do
+  end
+
+  newparam(:dns1) do
+    desc 'first dns server'
+   end
+
+  newparam(:dns2) do
+    desc 'second dns server'
+  end
+
+  newparam(:allowed_start) do
+    desc 'Start of allowed addresses for instances'
+    newvalues(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/)
+  end
+
+  newparam(:allowed_end) do
+    desc 'End of allowed addresses for instances'
+    newvalues(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/)
+  end
+
+  newparam(:vlan_start) do
+  end
+
+  newparam(:network_size) do
+    defaultto('256')
+  end
+
+  validate do
+    raise(Puppet::Error, 'Label must be set') unless self[:label]
+  end
+
+end

+ 47 - 0
lib/puppet/type/nova_paste_api_ini.rb

@@ -0,0 +1,47 @@
+Puppet::Type.newtype(:nova_paste_api_ini) do
+
+  ensurable
+
+  newparam(:name, :namevar => true) do
+    desc 'Section/setting name to manage from nova/paste-api.ini'
+    newvalues(/\S+\/\S+/)
+  end
+
+  newproperty(:value) do
+    desc 'The value of the setting to be defined.'
+    munge do |value|
+      value = value.to_s.strip
+      value.capitalize! if value =~ /^(true|false)$/i
+      value
+    end
+
+    def is_to_s( currentvalue )
+      if resource.secret?
+        return '[old secret redacted]'
+      else
+        return currentvalue
+      end
+    end
+
+    def should_to_s( newvalue )
+      if resource.secret?
+        return '[new secret redacted]'
+      else
+        return newvalue
+      end
+    end
+  end
+
+  newparam(:secret, :boolean => true) do
+    desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
+
+    newvalues(:true, :false)
+
+    defaultto false
+  end
+
+  autorequire(:package) do
+    'nova-common'
+  end
+
+end

+ 66 - 0
lib/puppet/type/nova_security_group.rb

@@ -0,0 +1,66 @@
+# Copyright (C) 2016 Mirantis Inc.
+#
+# Author: Alexey Deryugin <aderyugin@mirantis.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.
+#
+# nova_security_group type
+#
+# == Parameters
+#  [*name*]
+#    Name for the new security group
+#    Required
+#
+#  [*description*]
+#    Description for the new security group
+#    Optional
+#
+
+
+require 'puppet'
+
+Puppet::Type.newtype(:nova_security_group) do
+
+  @doc = "Manage creation of nova security groups."
+
+  ensurable
+
+  newparam(:name, :namevar => true) do
+    desc 'Name for the new security group'
+    validate do |value|
+      if not value.is_a? String
+        raise ArgumentError, "name parameter must be a String"
+      end
+      unless value =~ /^[a-zA-Z0-9\-_]+$/
+        raise ArgumentError, "#{value} is not a valid name"
+      end
+    end
+  end
+
+  newproperty(:id) do
+    desc 'The unique Id of the security group'
+    validate do |v|
+      raise ArgumentError, 'This is a read only property'
+    end
+  end
+
+  newproperty(:description) do
+    desc "Description of the security group"
+    defaultto ''
+  end
+
+  validate do
+    raise ArgumentError, 'Name type must be set' unless self[:name]
+  end
+
+end

+ 141 - 0
lib/puppet/type/nova_security_rule.rb

@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2016 Mirantis Inc.
+#
+# Author: Alexey Deryugin <aderyugin@mirantis.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.
+#
+# nova_security_group type
+#
+# == Parameters
+#  [*ip_protocol*]
+#    IP protocol from new security rule
+#    Required
+#
+#  [*from_port*]
+#    Port range begin for security rule
+#    Required
+#
+#  [*to_port*]
+#    Port range end for security rule
+#    Required
+#
+#  [*ip_range*]
+#    IP range for security rule
+#    Optional
+#
+#  [*source_group*]
+#    Source group for security rule
+#    Optional
+#
+#  [*security_group*]
+#    Target security group for security rule
+#    Required
+#
+
+
+require 'puppet'
+
+Puppet::Type.newtype(:nova_security_rule) do
+
+  desc "Manage nova security rules"
+
+  ensurable
+
+  newparam(:name) do
+    isnamevar
+  end
+
+  newparam(:ip_protocol) do
+    defaultto do
+      raise Puppet::Error, 'You should give protocol!'
+    end
+    newvalues 'tcp', 'udp', 'icmp'
+  end
+
+  newparam(:from_port) do
+    defaultto do
+      raise Puppet::Error, 'You should give the source port!'
+    end
+    validate do |value|
+      if value !~ /\d+/ or value.to_i <= 0 or value.to_i >= 65536
+        raise Puppet::Error, 'Incorrect from port!'
+      end
+    end
+  end
+
+  newparam(:to_port) do
+    defaultto do
+      raise Puppet::Error, 'You should give the destination port!'
+    end
+    validate do |value|
+      if value !~ /\d+/ or value.to_i <= 0 or value.to_i >= 65536
+        raise Puppet::Error, 'Incorrect to port!'
+      end
+    end
+  end
+
+  newparam(:ip_range) do
+
+    validate do |value|
+      def is_cidr_net?(value)
+        begin
+          address, mask = value.split('/')
+          return false unless address and mask
+          octets = address.split('.')
+          return false unless octets.length == 4
+
+          cidr = true
+          octets.each do |octet|
+            n = octet.to_i
+            cidr = false unless n <= 255
+            cidr = false unless n >= 0
+            break unless cidr
+          end
+
+          cidr = false unless mask.to_i <= 32
+          cidr = false unless mask.to_i >= 0
+          cidr
+        rescue
+          false
+        end
+      end
+
+      raise Puppet::Error, 'Incorrect ip_range!' unless is_cidr_net? value
+    end
+  end
+
+  newparam(:source_group) do
+  end
+
+  newparam(:security_group) do
+    defaultto do
+      raise Puppet::Error, 'You should provide the security group to add this rule to!'
+    end
+  end
+
+  validate do
+    unless !!self[:ip_range] ^ !!self[:source_group]
+      raise Puppet::Error, 'You should give either ip_range or source_group. Not none or both!'
+    end
+    unless self[:from_port].to_i <= self[:to_port].to_i
+      raise Puppet::Error, 'From_port should be lesser or equal to to_port!'
+    end
+  end
+
+  autorequire(:nova_security_group) do
+    self[:security_group]
+  end
+
+end

+ 73 - 0
lib/puppet/type/nova_service.rb

@@ -0,0 +1,73 @@
+# Copyright (C) 2016 Mirantis Inc.
+#
+# Author: Matthew Mosesohn <mmosesohn@mirantis.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.
+#
+# nova_security_group type
+#
+# == Parameters
+#  [*name*]
+#    Name for the host
+#    Required
+#
+#  [*ensure*]
+#    Marks status of service(s) on a given host.
+#    Possible values are enabled, disabled, purged
+#    Optional
+#
+#  [*service_name*]
+#    Name of a given service. Defaults to "undef", which modifies all.
+#    Optional
+#
+
+
+require 'puppet'
+
+Puppet::Type.newtype(:nova_service) do
+
+  @doc = "Manage status of nova services on hosts."
+
+  ensurable
+
+  newparam(:name, :namevar => true) do
+    desc 'Name of host'
+    validate do |value|
+      if not value.is_a? String
+        raise ArgumentError, "name parameter must be a String"
+      end
+      unless value =~ /^[a-zA-Z0-9\-_.]+$/
+        raise ArgumentError, "#{value} is not a valid name"
+      end
+    end
+  end
+
+  newproperty(:ids) do
+    desc 'The unique Ids of the compute service'
+    validate do |v|
+      raise ArgumentError, 'This is a read only property'
+    end
+  end
+
+  newproperty(:service_name, :array_matching => :all) do
+    desc "String or Array of services on a host to modify"
+    validate do |value|
+      raise(
+        ArgumentError,
+        'service_name parameter must be String or Array'
+      ) unless [String, Array].any? { |type| value.is_a? type }
+    end
+    defaultto []
+  end
+
+end

+ 53 - 0
lib/puppet/type/novajoin_config.rb

@@ -0,0 +1,53 @@
+Puppet::Type.newtype(:novajoin_config) do
+
+  ensurable
+
+  newparam(:name, :namevar => true) do
+    desc 'Section/setting name to manage from join.conf'
+    newvalues(/\S+\/\S+/)
+  end
+
+  newproperty(:value) do
+    desc 'The value of the setting to be defined.'
+    munge do |value|
+      value = value.to_s.strip
+      value.capitalize! if value =~ /^(true|false)$/i
+      value
+    end
+    newvalues(/^[\S ]*$/)
+
+    def is_to_s( currentvalue )
+      if resource.secret?
+        return '[old secret redacted]'
+      else
+        return currentvalue
+      end
+    end
+
+    def should_to_s( newvalue )
+      if resource.secret?
+        return '[new secret redacted]'
+      else
+        return newvalue
+      end
+    end
+  end
+
+  newparam(:secret, :boolean => true) do
+    desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
+
+    newvalues(:true, :false)
+
+    defaultto false
+  end
+
+  newparam(:ensure_absent_val) do
+    desc 'A value that is specified as the value property will behave as if ensure => absent was specified'
+    defaultto('<SERVICE DEFAULT>')
+  end
+
+  autorequire(:package) do
+    'novajoin'
+  end
+
+end

+ 506 - 0
manifests/api.pp

@@ -0,0 +1,506 @@
+# == Class: nova::api
+#
+# Setup and configure the Nova API endpoint
+#
+# === Parameters
+#
+# [*enabled*]
+#   (optional) Whether the nova api service will be run
+#   Defaults to true
+#
+# [*api_paste_config*]
+#   (optional) File name for the paste.deploy config for nova-api
+#   Defaults to 'api-paste.ini'
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (optional) Whether the nova api package will be installed
+#   Defaults to 'present'
+#
+# [*api_bind_address*]
+#   (optional) IP address for nova-api server to listen
+#   Defaults to '0.0.0.0'
+#
+# [*metadata_listen*]
+#   (optional) IP address  for metadata server to listen
+#   Defaults to '0.0.0.0'
+#
+# [*metadata_listen_port*]
+#   (optional) The port on which the metadata API will listen.
+#   Defaults to 8775
+#
+# [*enabled_apis*]
+#   (optional) A list of apis to enable
+#   Defaults to ['osapi_compute', 'metadata']
+#
+# [*use_forwarded_for*]
+#   (optional) Treat X-Forwarded-For as the canonical remote address. Only
+#   enable this if you have a sanitizing proxy.
+#   Defaults to false
+#
+# [*osapi_compute_workers*]
+#   (optional) Number of workers for OpenStack API service
+#   Defaults to $::processorcount
+#
+# [*osapi_compute_listen_port*]
+#   (optional) The port on which the OpenStack API will listen.
+#   Defaults to port 8774
+#
+# [*metadata_workers*]
+#   (optional) Number of workers for metadata service
+#   Defaults to $::processorcount
+#
+# [*instance_name_template*]
+#   (optional) Template string to be used to generate instance names
+#   Defaults to undef
+#
+# [*sync_db*]
+#   (optional) Run nova-manage db sync on api nodes after installing the package.
+#   Defaults to true
+#
+# [*sync_db_api*]
+#   (optional) Run nova-manage api_db sync on api nodes after installing the package.
+#   Defaults to true
+#
+# [*db_online_data_migrations*]
+#   (optional) Run nova-manage db online_data_migrations on api nodes after
+#   installing the package - required on upgrade.
+#   Defaults to false.
+#
+# [*neutron_metadata_proxy_shared_secret*]
+#   (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
+#   Example: '(POST, "*", .*, 10, MINUTE);(POST, "*/servers", ^/servers, 50, DAY);(PUT, "*", .*, 10, MINUTE)'
+#   Defaults to undef
+#
+# [*ratelimits_factory*]
+#   (optional) The rate limiting factory to use
+#   Defaults to 'nova.api.openstack.compute.limits:RateLimitingMiddleware.factory'
+#
+# [*enable_proxy_headers_parsing*]
+#   (optional) This determines if the HTTPProxyToWSGI
+#   middleware should parse the proxy headers or not.(boolean value)
+#   Defaults to $::os_service_default
+#
+# [*default_floating_pool*]
+#   (optional) Default pool for floating IPs
+#   Defaults to 'nova'
+#
+# [*validate*]
+#   (optional) Whether to validate the service is working after any service refreshes
+#   Defaults to false
+#
+# [*fping_path*]
+#   (optional) Full path to fping.
+#   Defaults to '/usr/sbin/fping'
+#
+# [*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 {}
+#
+# [*service_name*]
+#   (optional) Name of the service that will be providing the
+#   server functionality of nova-api.
+#   If the value is 'httpd', this means nova-api will be a web
+#   service, and you must use another class to configure that
+#   web service. For example, use class { 'nova::wsgi::apache'...}
+#   to make nova be a web app using apache mod_wsgi.
+#   Defaults to '$::nova::params::api_service_name'
+#
+# [*metadata_cache_expiration*]
+#   (optional) This option is the time (in seconds) to cache metadata.
+#   Defaults to $::os_service_default
+#
+# [*vendordata_jsonfile_path*]
+#   (optional) Represent the path to the data file.
+#   Cloud providers may store custom data in vendor data file that will then be
+#   available to the instances via the metadata service, and to the rendering of
+#   config-drive. The default class for this, JsonFileVendorData, loads this
+#   information from a JSON file, whose path is configured by this option
+#   Defaults to $::os_service_default
+#
+# [*vendordata_providers*]
+#   (optional) vendordata providers are how deployers can provide metadata via
+#   configdrive and metadata that is specific to their deployment. There are
+#   currently two supported providers: StaticJSON and DynamicJSON.
+#   Defaults to $::os_service_default
+#
+# [*vendordata_dynamic_targets*]
+#   (optional) A list of targets for the dynamic vendordata provider. These
+#   targets are of the form <name>@<url>.
+#   Defaults to $::os_service_default
+#
+# [*vendordata_dynamic_connect_timeout*]
+#   (optional) Maximum wait time for an external REST service to connect.
+#   Defaults to $::os_service_default
+#
+# [*vendordata_dynamic_read_timeout*]
+#   (optional) Maximum wait time for an external REST service to return data
+#   once connected.
+#   Defaults to $::os_service_default
+#
+# [*max_limit*]
+#   (optional) This option is limit the maximum number of items in a single response.
+#   Defaults to $::os_service_default
+#
+# [*compute_link_prefix*]
+#   (optional) This string is prepended to the normal URL that is returned in links
+#   to the OpenStack Compute API.
+#   Defaults to $::os_service_default
+#
+# [*glance_link_prefix*]
+#   (optional) This string is prepended to the normal URL that is returned in links
+#   to Glance resources.
+#   Defaults to $::os_service_default
+#
+# [*hide_server_address_states*]
+#   (optional) This option is a list of all instance states for which network address
+#   information should not be returned from the API.
+#   Defaults to $::os_service_default
+#
+# [*allow_instance_snapshots*]
+#   (optional) Operators can turn off the ability for a user to take snapshots of their
+#   instances by setting this option to False
+#   Defaults to $::os_service_default
+#
+# [*enable_network_quota*]
+#   (optional) This option is used to enable or disable quota checking for tenant networks
+#   Defaults to $::os_service_default
+#
+# [*enable_instance_password*]
+#   (optional) Enables returning of the instance password by the relevant server API calls
+#   Defaults to $::os_service_default
+#
+# [*password_length*]
+#   (optional) Length of generated instance admin passwords (integer value)
+#   Defaults to $::os_service_default
+#
+# [*install_cinder_client*]
+#   (optional) Whether the cinder::client class should be used to install the cinder client.
+#   Defaults to true
+#
+#  [*allow_resize_to_same_host*]
+#   (optional) Allow destination machine to match source for resize. Note that this
+#   is also settable in the compute class. In some sitautions you need it set here
+#   and in others you need it set there.
+#   Defaults to false
+#
+# DEPRECATED
+#
+# [*conductor_workers*]
+#   (optional) DEPRECATED. Use workers parameter of nova::conductor
+#   Class instead.
+#   Defaults to undef
+#
+# [*osapi_max_limit*]
+#   (optional) This option is limit the maximum number of items in a single response.
+#   Defaults to undef
+#
+# [*osapi_compute_link_prefix*]
+#   (optional) This string is prepended to the normal URL that is returned in links
+#   to the OpenStack Compute API.
+#   Defaults to undef
+#
+# [*osapi_glance_link_prefix*]
+#   (optional) This string is prepended to the normal URL that is returned in links
+#   to Glance resources.
+#   Defaults to undef
+#
+# [*osapi_hide_server_address_states*]
+#   (optional) This option is a list of all instance states for which network address
+#   information should not be returned from the API.
+#   Defaults to undef
+#
+class nova::api(
+  $enabled                              = true,
+  $manage_service                       = true,
+  $api_paste_config                     = 'api-paste.ini',
+  $ensure_package                       = 'present',
+  $api_bind_address                     = '0.0.0.0',
+  $osapi_compute_listen_port            = 8774,
+  $metadata_listen                      = '0.0.0.0',
+  $metadata_listen_port                 = 8775,
+  $enabled_apis                         = ['osapi_compute', 'metadata'],
+  $use_forwarded_for                    = false,
+  $osapi_compute_workers                = $::processorcount,
+  $metadata_workers                     = $::processorcount,
+  $sync_db                              = true,
+  $sync_db_api                          = true,
+  $db_online_data_migrations            = false,
+  $neutron_metadata_proxy_shared_secret = undef,
+  $default_floating_pool                = 'nova',
+  $pci_alias                            = undef,
+  $ratelimits                           = undef,
+  $ratelimits_factory                   =
+    'nova.api.openstack.compute.limits:RateLimitingMiddleware.factory',
+  $validate                             = false,
+  $validation_options                   = {},
+  $instance_name_template               = undef,
+  $fping_path                           = '/usr/sbin/fping',
+  $service_name                         = $::nova::params::api_service_name,
+  $enable_proxy_headers_parsing         = $::os_service_default,
+  $metadata_cache_expiration            = $::os_service_default,
+  $vendordata_jsonfile_path             = $::os_service_default,
+  $vendordata_providers                 = $::os_service_default,
+  $vendordata_dynamic_targets           = $::os_service_default,
+  $vendordata_dynamic_connect_timeout   = $::os_service_default,
+  $vendordata_dynamic_read_timeout      = $::os_service_default,
+  $max_limit                            = $::os_service_default,
+  $compute_link_prefix                  = $::os_service_default,
+  $glance_link_prefix                   = $::os_service_default,
+  $hide_server_address_states           = $::os_service_default,
+  $allow_instance_snapshots             = $::os_service_default,
+  $enable_network_quota                 = $::os_service_default,
+  $enable_instance_password             = $::os_service_default,
+  $password_length                      = $::os_service_default,
+  $install_cinder_client                = true,
+  $allow_resize_to_same_host            = false,
+  # DEPRECATED PARAMETER
+  $conductor_workers                    = undef,
+  $osapi_max_limit                      = undef,
+  $osapi_compute_link_prefix            = undef,
+  $osapi_glance_link_prefix             = undef,
+  $osapi_hide_server_address_states     = undef,
+) inherits nova::params {
+
+  include ::nova::deps
+  include ::nova::db
+  include ::nova::policy
+  include ::nova::keystone::authtoken
+
+  if $install_cinder_client {
+    include ::cinder::client
+    Class['cinder::client'] ~> Nova::Generic_service['api']
+  }
+
+  if $conductor_workers {
+    warning('The conductor_workers parameter is deprecated and has no effect. Use workers parameter of nova::conductor class instead.')
+  }
+
+  if $instance_name_template {
+    nova_config {
+      'DEFAULT/instance_name_template': value => $instance_name_template;
+    }
+  } else {
+    nova_config{
+      'DEFAULT/instance_name_template': ensure => absent;
+    }
+  }
+
+  if $osapi_max_limit {
+    warning('The osapi_max_limit parameter is deprecated. Please use max_limit instead')
+    $max_limit_real = $osapi_max_limit
+  } else {
+    $max_limit_real = $max_limit
+  }
+
+  if $osapi_compute_link_prefix {
+    warning('The osapi_compute_link_prefix parameter is deprecated. Please use compute_link_prefix instead')
+    $compute_link_prefix_real = $osapi_compute_link_prefix
+  } else {
+    $compute_link_prefix_real = $compute_link_prefix
+  }
+
+  if $osapi_glance_link_prefix {
+    warning('The osapi_glance_link_prefix parameter is deprecated. Please use glance_link_prefix instead')
+    $glance_link_prefix_real = $osapi_glance_link_prefix
+  } else {
+    $glance_link_prefix_real = $glance_link_prefix
+  }
+
+  if $osapi_hide_server_address_states {
+    warning('The osapi_hide_server_address_states parameter is deprecated. Please use hide_server_address_states instead')
+    $hide_server_address_states_real = $osapi_hide_server_address_states
+  } else {
+    $hide_server_address_states_real = $hide_server_address_states
+  }
+
+  if !is_service_default($vendordata_providers) and !empty($vendordata_providers){
+    validate_array($vendordata_providers)
+    $vendordata_providers_real = join($vendordata_providers, ',')
+  } else {
+    $vendordata_providers_real = $::os_service_default
+  }
+
+  if !is_service_default($vendordata_dynamic_targets) and !empty($vendordata_dynamic_targets){
+    validate_array($vendordata_dynamic_targets)
+    $vendordata_dynamic_targets_real = join($vendordata_dynamic_targets, ',')
+  } else {
+    $vendordata_dynamic_targets_real = $::os_service_default
+  }
+
+  # metadata can't be run in wsgi so we have to enable it in eventlet anyway.
+  if ('metadata' in $enabled_apis and $service_name == 'httpd') {
+    $enable_metadata = true
+  } else {
+    $enable_metadata = false
+  }
+
+  # sanitize service_name and prepare DEFAULT/enabled_apis parameter
+  if $service_name == $::nova::params::api_service_name {
+    # if running evenlet, we use the original puppet parameter
+    # so people can enable custom service names and we keep backward compatibility.
+    $enabled_apis_real = $enabled_apis
+    $service_enabled   = $enabled
+  } elsif $service_name == 'httpd' {
+    # when running wsgi, we want to enable metadata in eventlet if part of enabled_apis
+    if $enable_metadata {
+      $enabled_apis_real = ['metadata']
+      $service_enabled   = $enabled
+    } else {
+      # otherwise, set it to empty list
+      $enabled_apis_real = []
+      # if running wsgi for compute, and metadata disabled
+      # we don't need to enable nova-api service.
+      $service_enabled   = false
+    }
+    policy_rcd { 'nova-api':
+      ensure   => present,
+      set_code => '101',
+      before   => Package['nova-api'],
+    }
+    # make sure we start apache before nova-api to avoid binding issues
+    Service[$service_name] -> Service['nova-api']
+  } else {
+    fail("Invalid service_name. Either nova-api/openstack-nova-api for running \
+as a standalone service, or httpd for being run by a httpd server")
+  }
+
+  nova::generic_service { 'api':
+    enabled        => $service_enabled,
+    manage_service => $manage_service,
+    ensure_package => $ensure_package,
+    package_name   => $::nova::params::api_package_name,
+    service_name   => $::nova::params::api_service_name,
+  }
+
+  nova_config {
+    'wsgi/api_paste_config':                  value => $api_paste_config;
+    'DEFAULT/enabled_apis':                   value => join($enabled_apis_real, ',');
+    'DEFAULT/osapi_compute_listen':           value => $api_bind_address;
+    'DEFAULT/metadata_listen':                value => $metadata_listen;
+    'DEFAULT/metadata_listen_port':           value => $metadata_listen_port;
+    'DEFAULT/osapi_compute_listen_port':      value => $osapi_compute_listen_port;
+    'DEFAULT/osapi_volume_listen':            value => $api_bind_address;
+    'DEFAULT/osapi_compute_workers':          value => $osapi_compute_workers;
+    'DEFAULT/metadata_workers':               value => $metadata_workers;
+    'DEFAULT/default_floating_pool':          value => $default_floating_pool;
+    'DEFAULT/enable_network_quota':           value => $enable_network_quota;
+    'DEFAULT/password_length':                value => $password_length;
+    'api/metadata_cache_expiration':          value => $metadata_cache_expiration;
+    'api/use_forwarded_for':                  value => $use_forwarded_for;
+    'api/fping_path':                         value => $fping_path;
+    'api/vendordata_jsonfile_path':           value => $vendordata_jsonfile_path;
+    'api/vendordata_providers':               value => $vendordata_providers_real;
+    'api/vendordata_dynamic_targets':         value => $vendordata_dynamic_targets_real;
+    'api/vendordata_dynamic_connect_timeout': value => $vendordata_dynamic_connect_timeout;
+    'api/vendordata_dynamic_read_timeout':    value => $vendordata_dynamic_read_timeout;
+    'api/max_limit':                          value => $max_limit_real;
+    'api/compute_link_prefix':                value => $compute_link_prefix_real;
+    'api/glance_link_prefix':                 value => $glance_link_prefix_real;
+    'api/hide_server_address_states':         value => $hide_server_address_states_real;
+    'api/allow_instance_snapshots':           value => $allow_instance_snapshots;
+    'api/enable_instance_password':           value => $enable_instance_password;
+  }
+
+  oslo::middleware {'nova_config':
+    enable_proxy_headers_parsing => $enable_proxy_headers_parsing,
+  }
+
+  if ($neutron_metadata_proxy_shared_secret){
+    nova_config {
+      'neutron/service_metadata_proxy': value => true;
+      'neutron/metadata_proxy_shared_secret':
+        value => $neutron_metadata_proxy_shared_secret;
+    }
+  } else {
+    nova_config {
+      'neutron/service_metadata_proxy':       value  => false;
+      'neutron/metadata_proxy_shared_secret': ensure => absent;
+    }
+  }
+
+  if ($ratelimits != undef) {
+    nova_paste_api_ini {
+      'filter:ratelimit/paste.filter_factory': value => $ratelimits_factory;
+      'filter:ratelimit/limits':               value => $ratelimits;
+    }
+  }
+
+  # Added arg and if statement prevents this from being run
+  # where db is not active i.e. the compute
+  if $sync_db {
+    include ::nova::db::sync
+  }
+  if $sync_db_api {
+    include ::nova::db::sync_api
+  }
+  if $db_online_data_migrations {
+    include ::nova::db::online_data_migrations
+  }
+
+  # Remove auth configuration from api-paste.ini
+  nova_paste_api_ini {
+    'filter:authtoken/auth_uri':          ensure => absent;
+    'filter:authtoken/auth_host':         ensure => absent;
+    'filter:authtoken/auth_port':         ensure => absent;
+    'filter:authtoken/auth_protocol':     ensure => absent;
+    'filter:authtoken/admin_tenant_name': ensure => absent;
+    'filter:authtoken/admin_user':        ensure => absent;
+    'filter:authtoken/admin_password':    ensure => absent;
+    'filter:authtoken/auth_admin_prefix': ensure => absent;
+  }
+
+  if $pci_alias {
+    nova_config {
+      'DEFAULT/pci_alias': value => check_array_of_hash($pci_alias);
+    }
+  }
+
+  if $validate {
+    #Shrinking the variables names in favor of not
+    #having more than 140 chars per line
+    #Admin user real
+    $aur = $::nova::keystone::authtoken::username
+    #Admin password real
+    $apr = $::nova::keystone::authtoken::password
+    #Admin tenan name real
+    $atnr = $::nova::keystone::authtoken::project_name
+    #Keystone Auth URI
+    $kau = $::nova::keystone::authtoken::auth_uri
+    $defaults = {
+      'nova-api' => {
+        'command'  => "nova --os-auth-url ${kau} --os-project-name ${atnr} --os-username ${aur} --os-password ${apr} flavor-list",
+      }
+    }
+    $validation_options_hash = merge ($defaults, $validation_options)
+    create_resources('openstacklib::service_validation', $validation_options_hash, {'subscribe' => 'Service[nova-api]'})
+  }
+
+  ensure_resource('nova_config', 'DEFAULT/allow_resize_to_same_host', { value => $allow_resize_to_same_host })
+}

+ 43 - 0
manifests/availability_zone.pp

@@ -0,0 +1,43 @@
+# == Class: nova::availability_zone
+#
+# nova availability zone configuration
+#
+# === Parameters:
+#
+#  [*default_availability_zone*]
+#   (optional) Default compute node availability zone.
+#   Defaults to $::os_service_default
+#
+#  [*default_schedule_zone*]
+#   (optional) Availability zone to use when user doesn't specify one.
+#   Defaults to $::os_service_default
+#
+#  [*internal_service_availability_zone*]
+#   (optional) The availability zone to show internal services under.
+#   Defaults to $::os_service_default
+#
+class nova::availability_zone (
+  $default_availability_zone          = $::os_service_default,
+  $default_schedule_zone              = $::os_service_default,
+  $internal_service_availability_zone = $::os_service_default,
+) {
+
+  # NOTE(dalees): In order to keep backward compatibility from nova::compute we
+  # rely on the pick function.
+  $default_availability_zone_real = pick(
+    $::nova::compute::default_availability_zone,
+    $default_availability_zone)
+  $default_schedule_zone_real = pick(
+    $::nova::compute::default_schedule_zone,
+    $default_schedule_zone)
+  $internal_service_availability_zone_real = pick(
+    $::nova::compute::internal_service_availability_zone,
+    $internal_service_availability_zone)
+
+  nova_config {
+    'DEFAULT/default_availability_zone':          value => $default_availability_zone_real;
+    'DEFAULT/default_schedule_zone':              value => $default_schedule_zone_real;
+    'DEFAULT/internal_service_availability_zone': value => $internal_service_availability_zone_real;
+  }
+
+}

+ 117 - 0
manifests/cache.pp

@@ -0,0 +1,117 @@
+# Class nova::cache
+#
+#  nova cache configuration
+#
+# == parameters
+#
+# [*config_prefix*]
+#   (Optional) Prefix for building the configuration dictionary for
+#   the cache region. This should not need to be changed unless there
+#   is another dogpile.cache region with the same configuration name.
+#   (string value)
+#   Defaults to $::os_service_default
+#
+# [*expiration_time*]
+#   (Optional) Default TTL, in seconds, for any cached item in the
+#   dogpile.cache region. This applies to any cached method that
+#   doesn't have an explicit cache expiration time defined for it.
+#   (integer value)
+#   Defaults to $::os_service_default
+#
+# [*backend*]
+#   (Optional) Dogpile.cache backend module. It is recommended that
+#   Memcache with pooling (oslo_cache.memcache_pool) or Redis
+#   (dogpile.cache.redis) be used in production deployments. (string value)
+#   Defaults to $::os_service_default
+#
+# [*backend_argument*]
+#   (Optional) Arguments supplied to the backend module. Specify this option
+#   once per argument to be passed to the dogpile.cache backend.
+#   Example format: "<argname>:<value>". (list value)
+#   Defaults to $::os_service_default
+#
+# [*proxies*]
+#   (Optional) Proxy classes to import that will affect the way the
+#   dogpile.cache backend functions. See the dogpile.cache documentation on
+#   changing-backend-behavior. (list value)
+#   Defaults to $::os_service_default
+#
+# [*enabled*]
+#   (Optional) Global toggle for caching. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*debug_cache_backend*]
+#   (Optional) Extra debugging from the cache backend (cache keys,
+#   get/set/delete/etc calls). This is only really useful if you need
+#   to see the specific cache-backend get/set/delete calls with the keys/values.
+#   Typically this should be left set to false. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*memcache_servers*]
+#   (Optional) Memcache servers in the format of "host:port".
+#   (dogpile.cache.memcache and oslo_cache.memcache_pool backends only).
+#   (list value)
+#   Defaults to $::os_service_default
+#
+# [*memcache_dead_retry*]
+#   (Optional) Number of seconds memcached server is considered dead before
+#   it is tried again. (dogpile.cache.memcache and oslo_cache.memcache_pool
+#   backends only). (integer value)
+#   Defaults to $::os_service_default
+#
+# [*memcache_socket_timeout*]
+#   (Optional) Timeout in seconds for every call to a server.
+#   (dogpile.cache.memcache and oslo_cache.memcache_pool backends only).
+#   (integer value)
+#   Defaults to $::os_service_default
+#
+# [*memcache_pool_maxsize*]
+#   (Optional) Max total number of open connections to every memcached server.
+#   (oslo_cache.memcache_pool backend only). (integer value)
+#   Defaults to $::os_service_default
+#
+# [*memcache_pool_unused_timeout*]
+#   (Optional) Number of seconds a connection to memcached is held unused
+#   in the pool before it is closed. (oslo_cache.memcache_pool backend only)
+#   (integer value)
+#   Defaults to $::os_service_default
+#
+# [*memcache_pool_connection_get_timeout*]
+#   (Optional) Number of seconds that an operation will wait to get a memcache
+#   client connection. (integer value)
+#   Defaults to $::os_service_default
+#
+class nova::cache (
+  $config_prefix                        = $::os_service_default,
+  $expiration_time                      = $::os_service_default,
+  $backend                              = $::os_service_default,
+  $backend_argument                     = $::os_service_default,
+  $proxies                              = $::os_service_default,
+  $enabled                              = $::os_service_default,
+  $debug_cache_backend                  = $::os_service_default,
+  $memcache_servers                     = $::os_service_default,
+  $memcache_dead_retry                  = $::os_service_default,
+  $memcache_socket_timeout              = $::os_service_default,
+  $memcache_pool_maxsize                = $::os_service_default,
+  $memcache_pool_unused_timeout         = $::os_service_default,
+  $memcache_pool_connection_get_timeout = $::os_service_default,
+) {
+
+  include ::nova::deps
+
+  oslo::cache { 'nova_config':
+    config_prefix                        => $config_prefix,
+    expiration_time                      => $expiration_time,
+    backend                              => $backend,
+    backend_argument                     => $backend_argument,
+    proxies                              => $proxies,
+    enabled                              => $enabled,
+    debug_cache_backend                  => $debug_cache_backend,
+    memcache_servers                     => $memcache_servers,
+    memcache_dead_retry                  => $memcache_dead_retry,
+    memcache_socket_timeout              => $memcache_socket_timeout,
+    memcache_pool_maxsize                => $memcache_pool_maxsize,
+    memcache_pool_unused_timeout         => $memcache_pool_unused_timeout,
+    memcache_pool_connection_get_timeout => $memcache_pool_connection_get_timeout,
+  }
+}

+ 51 - 0
manifests/cell_v2/cell.pp

@@ -0,0 +1,51 @@
+# == Type: nova::cell_v2::cell
+#
+# Resource for managing cell_v2 cells.
+#
+# === Parameters
+#
+# [*extra_params*]
+#  (String) Extra parameters to pass to the nova-manage commands.
+#  Defaults to ''.
+#
+# [*transport_url*]
+#  (String) AMQP transport url for the cell.
+#  If not defined, the [DEFAULT]/transport_url is used from the nova
+#  configuration file.
+#  Defaults to undef.
+#
+# [*database_connection*]
+#  (String)  Database connection url for the cell.
+#  If not defined, the [DEFAULT]/database_connection is used from the nova
+#  configuration file.
+#  Defaults to undef.
+#
+define nova::cell_v2::cell (
+  $extra_params        = '',
+  $transport_url       = undef,
+  $database_connection = undef
+) {
+
+  include ::nova::deps
+
+  if $transport_url {
+    $transport_url_real = "--transport-url=${transport_url}"
+  } else {
+    $transport_url_real = ''
+  }
+
+  if $database_connection {
+    $database_connection_real = "--database_connection=${database_connection}"
+  } else {
+    $database_connection_real = ''
+  }
+
+  exec { "nova-cell_v2-cell-${title}":
+    path      => [ '/bin', '/usr/bin' ],
+    command   => "nova-manage ${extra_params} cell_v2 create_cell --name=${title} ${transport_url_real} ${database_connection_real}",
+    unless    => "nova-manage ${extra_params} cell_v2 list_cells | grep -q ${title}",
+    logoutput => on_failure,
+    subscribe => Anchor['nova::cell_v2::begin'],
+    notify    => Anchor['nova::cell_v2::end'],
+  }
+}

+ 23 - 0
manifests/cell_v2/discover_hosts.pp

@@ -0,0 +1,23 @@
+# == Class: nova::cell_v2::discover_hosts
+#
+#  Class to run the discover_hosts action for cell v2
+#
+# === Parameters
+#
+# [*extra_params*]
+#  (String) Extra parameters to pass to the nova-manage commands.
+#  Defaults to ''.
+#
+class nova::cell_v2::discover_hosts (
+  $extra_params = '',
+) {
+
+  include ::nova::deps
+
+  exec { 'nova-cell_v2-discover_hosts':
+    path        => ['/bin', '/usr/bin'],
+    command     => "nova-manage ${extra_params} cell_v2 discover_hosts",
+    refreshonly => true,
+    subscribe   => Anchor['nova::service::end']
+  }
+}

+ 28 - 0
manifests/cell_v2/map_cell0.pp

@@ -0,0 +1,28 @@
+# == Class: nova::cell_v2::map_cell0
+#
+# Class to execute nova cell_v2 map_cell0
+#
+# === Parameters
+#
+# [*extra_params*]
+#   (optional) String of extra command line parameters to pass
+#   to the nova-manage command. These will be inserted in
+#   the command line between 'nova-manage' and 'cell_v2'.
+#   Defaults to ''
+#
+#
+class nova::cell_v2::map_cell0 (
+  $extra_params = '',
+) {
+
+  include ::nova::deps
+
+  exec { 'nova-cell_v2-map_cell0':
+    path        => ['/bin', '/usr/bin'],
+    command     => "nova-manage ${extra_params} cell_v2 map_cell0",
+    refreshonly => true,
+    logoutput   => on_failure,
+    subscribe   => Anchor['nova::cell_v2::begin'],
+    notify      => Anchor['nova::cell_v2::end'],
+  }
+}

+ 22 - 0
manifests/cell_v2/map_cell_and_hosts.pp

@@ -0,0 +1,22 @@
+# == Class: nova::cell_v2::map_cell_and_hosts
+#
+#  Class to run the map_cell_and_hosts action for cell v2
+#
+# === Parameters
+#
+# [*extra_params*]
+#  (String) Extra parameters to pass to the nova-manage commands.
+#  Defaults to ''.
+#
+class nova::cell_v2::map_cell_and_hosts (
+  $extra_params = '',
+) {
+
+  include ::nova::deps
+
+  exec { 'nova-cell_v2-map_cell_and_hosts':
+    path        => ['/bin', '/usr/bin'],
+    command     => "nova-manage ${extra_params} cell_v2 map_cell_and_hosts",
+    refreshonly => true,
+  }
+}

+ 47 - 0
manifests/cell_v2/map_instances.pp

@@ -0,0 +1,47 @@
+# == Class: nova::cell_v2::map_instances
+#
+#  Resource to run the map_instances action for cell v2
+#
+# === Parameters
+#
+# [*cell_uuid*]
+#  (String) Cell UUID to map unmigrated instances to. It is recommended to use
+#  this rather than cell name. Either cell_uuid or cell_name must be provided.
+#  Defaults to undef.
+#
+# [*cell_name*]
+#  (String) Cell name to map the unmigrated instances to. We will attempt to
+#  extract the cell uuid using the name as the command requires a cell uuid.
+#  NOTE: This will not work if you have multiple cells with the same name.
+#  Defaults to undef.
+#
+# [*extra_params*]
+#  (String) Extra parameters to pass to the nova-manage commands.
+#  Defaults to ''.
+#
+class nova::cell_v2::map_instances (
+  $cell_uuid    = undef,
+  $cell_name    = undef,
+  $extra_params = '',
+) {
+
+  include ::nova::deps
+
+  if (!$cell_uuid and !$cell_name) {
+    fail('Either cell_uuid or cell_name must be provided')
+  }
+
+  if ($cell_uuid) {
+    $cell_uuid_real = $cell_uuid
+  } else {
+    # NOTE(aschultz): This is what breaks if you have multiple cells with the
+    # same name. So that's why using cell_uuid is better.
+    $cell_uuid_real = "$(nova-manage cell_v2 list_cells | sed -e '1,3d' -e '\$d' | awk -F ' *| *' '\$2 == \"${cell_name}\" {print \$4}')"
+  }
+
+  exec { 'nova-cell_v2-map_instances':
+    path        => ['/bin', '/usr/bin'],
+    command     => "nova-manage ${extra_params} cell_v2 map_instances --cell_uuid=${cell_uuid_real}",
+    refreshonly => true,
+  }
+}

+ 52 - 0
manifests/cell_v2/simple_setup.pp

@@ -0,0 +1,52 @@
+# == Class: nova::cell_v2::simple_setup
+#
+# Class to execute minimal nova cell_v2 setup. This is a manual implementation
+# of the cell_v2 simple_cell_setup in puppet.
+#
+# === Parameters
+#
+# [*extra_params*]
+#   (optional) String of extra command line parameters to pass
+#   to the nova-manage command. These will be inserted in
+#   the command line between 'nova-manage' and 'cell_v2'.
+#   Defaults to ''
+#
+# [*transport_url*]
+#   (optional) This is the transport url to use for the cell_v2 commands.
+#   By default the command should look for the DEFAULT/transport_url from
+#   the nova configuration. If not available, you need to provide the
+#   transport url via the parameters. Prior to Ocata, the transport-url
+#   was a required parameter.
+#   Defaults to undef.
+#
+# [*database_connection*]
+#   (optional) This is the database url to use for the cell_v2 create command
+#   for the initial cell1 cell.
+#   By default the command should look for the DEFAULT/database_connection from
+#   the nova configuration. If not available, you need to provide the database
+#   url via the parameters.
+#   Defaults to undef.
+#
+class nova::cell_v2::simple_setup (
+  $extra_params        = '',
+  $transport_url       = undef,
+  $database_connection = undef,
+) {
+
+  include ::nova::deps
+
+  include ::nova::cell_v2::map_cell0
+
+  nova::cell_v2::cell { 'default':
+    extra_params        => $extra_params,
+    transport_url       => $transport_url,
+    database_connection => $database_connection
+  }
+
+  include ::nova::cell_v2::discover_hosts
+
+  Class['nova::cell_v2::map_cell0'] ->
+    Nova::Cell_v2::Cell <| |> ~>
+      Class['nova::cell_v2::discover_hosts']
+
+}

+ 239 - 0
manifests/cells.pp

@@ -0,0 +1,239 @@
+#
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Emilien Macchi <emilien.macchi@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
+# 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::cells
+#
+# Installs the Nova Cells
+#
+# === Parameters:
+#
+#  [*enabled*]
+#    Use Nova Cells or not
+#    Defaults to true
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+#  [*create_cells*]
+#    Create cells with nova-manage
+#    Defaults to 'True'
+#
+#  [*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'
+#
+#  [*max_hop_count*]
+#    Maximum number of hops for cells routing
+#    Defaults to '10'
+#
+#  [*scheduler*]
+#    Cells scheduler to use
+#    Defaults to 'nova.cells.scheduler.CellsScheduler'
+#
+#  [*instance_update_num_instances*]
+#    Number of instances to update per periodic task run
+#    Defaults to '1'
+#
+#  [*cell_name*]
+#    name of this cell
+#    Defaults to 'nova'
+#
+#  [*cell_parent_name*]
+#    * If a child cell, this is the name of the 'parent' cell.
+#    * If a parent cell, should be left to undef.
+#
+#  [*capabilities*]
+#    Key/Multi-value list with the capabilities of the cell
+#    Defaults to 'hypervisor=xenserver;kvm,os=linux;windows'
+#
+#  [*call_timeout*]
+#    Seconds to wait for response from a call to a cell
+#    Defaults to '60'
+#
+#  [*reserve_percent*]
+#    Percentage of cell capacity to hold in reserve. Affects both memory and disk utilization
+#    Defaults to '10.0'
+#
+#  [*cell_type*]
+#    Type of cell: parent or child
+#    Defaults to 'None'
+#
+#  [*mute_child_interval*]
+#    Number of seconds after which a lack of capability and
+#    capacity updates signals the child cell is to be treated as a mute
+#    Defaults to '300'
+#
+#  [*bandwidth_update_interval*]
+#    Seconds between bandwidth updates for cells
+#    Defaults to '600'
+#
+#  [*rpc_driver_queue_base*]
+#    Base queue name to use when communicating between cells
+#    Various topics by message type will be appended to this
+#    Defaults to 'cells.intercell'
+#
+#  [*scheduler_filter_classes*]
+#    Filter classes the cells scheduler should use
+#    Defaults to 'nova.cells.filters.all_filters'
+#
+#  [*scheduler_weight_classes*]
+#    Weigher classes the cells scheduler should use
+#    Defaults to 'nova.cells.weights.all_weighers'
+#
+#  [*scheduler_retries*]
+#    How many retries when no cells are available
+#    Defaults to '10'
+#
+#  [*scheduler_retry_delay*]
+#    How often to retry in seconds when no cells are available
+#    Defaults to '2'
+#
+#  [*db_check_interval*]
+#    Seconds between getting fresh cell info from db
+#    Defaults to '60'
+#
+#  [*mute_weight_multiplier*]
+#    Multiplier used to weigh mute children (The value should be negative)
+#    Defaults to '-10.0'
+#
+#  [*mute_weight_value*]
+#    Weight value assigned to mute children (The value should be positive)
+#    Defaults to '1000.0'
+#
+#  [*ram_weight_multiplier*]
+#    Multiplier used for weighing ram. Negative numbers mean to stack vs spread
+#    Defaults to '10.0'
+#
+#  [*weight_offset*]
+#    It might be used by some cell scheduling code in the future
+#    Defaults to '1.0'
+#
+#  [*weight_scale*]
+#    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',
+  $capabilities                  = ['hypervisor=xenserver;kvm','os=linux;windows'],
+  $cell_name                     = 'nova',
+  $cell_type                     = undef,
+  $cell_parent_name              = undef,
+  $create_cells                  = true,
+  $db_check_interval             = '60',
+  $enabled                       = true,
+  $ensure_package                = 'present',
+  $instance_updated_at_threshold = '3600',
+  $instance_update_num_instances = '1',
+  $manage_service                = true,
+  $max_hop_count                 = '10',
+  $mute_child_interval           = '300',
+  $mute_weight_multiplier        = '-10.0',
+  $mute_weight_value             = '1000.0',
+  $ram_weight_multiplier         = '10.0',
+  $reserve_percent               = '10.0',
+  $rpc_driver_queue_base         = 'cells.intercell',
+  $scheduler_filter_classes      = 'nova.cells.filters.all_filters',
+  $scheduler                     = 'nova.cells.scheduler.CellsScheduler',
+  $scheduler_retries             = '10',
+  $scheduler_retry_delay         = '2',
+  $scheduler_weight_classes      = 'nova.cells.weights.all_weighers',
+  $weight_offset                 = '1.0',
+  $weight_scale                  = '1.0',
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  case $cell_type {
+    'parent': {
+      nova_config { 'DEFAULT/compute_api_class': value => 'nova.compute.cells_api.ComputeCellsAPI' }
+      nova_config { 'cells/cell_type': value         => 'api' }
+    }
+    'child': {
+      nova_config { 'cells/cell_type': value    => 'compute' }
+    }
+    default: { fail("Unsupported cell_type parameter value: '${cell_type}'. Should be 'parent' or 'child'.") }
+  }
+
+  nova_config {
+    'cells/bandwidth_update_interval':     value => $bandwidth_update_interval;
+    'cells/call_timeout':                  value => $call_timeout;
+    'cells/capabilities':                  value => join($capabilities, ',');
+    'cells/db_check_interval':             value => $db_check_interval;
+    'cells/enable':                        value => $enabled;
+    'cells/instance_updated_at_threshold': value => $instance_updated_at_threshold;
+    'cells/instance_update_num_instances': value => $instance_update_num_instances;
+    'cells/max_hop_count':                 value => $max_hop_count;
+    'cells/mute_child_interval':           value => $mute_child_interval;
+    'cells/mute_weight_multiplier':        value => $mute_weight_multiplier;
+    'cells/mute_weight_value':             value => $mute_weight_value;
+    'cells/name':                          value => $cell_name;
+    'cells/ram_weight_multiplier':         value => $ram_weight_multiplier;
+    'cells/reserve_percent':               value => $reserve_percent;
+    'cells/rpc_driver_queue_base':         value => $rpc_driver_queue_base;
+    'cells/scheduler_filter_classes':      value => $scheduler_filter_classes;
+    'cells/scheduler_retries':             value => $scheduler_retries;
+    'cells/scheduler_retry_delay':         value => $scheduler_retry_delay;
+    'cells/scheduler':                     value => $scheduler;
+    'cells/scheduler_weight_classes':      value => $scheduler_weight_classes;
+  }
+
+  nova::generic_service { 'cells':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::cells_package_name,
+    service_name   => $::nova::params::cells_service_name,
+    ensure_package => $ensure_package,
+  }
+
+  if $create_cells {
+    @@nova::manage::cells { $cell_name:
+      cell_type           => $cell_type,
+      cell_parent_name    => $cell_parent_name,
+      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']
+    }
+
+    case $cell_type {
+      'parent': {
+        # A parent cell must declare its child cell(s)
+        Nova::Manage::Cells <<| cell_parent_name == $cell_parent_name and cell_type == 'child' |>>
+      }
+      'child': {
+        # A child cell must declare its parent cell
+        Nova::Manage::Cells <<| name == $cell_parent_name and cell_type == 'parent' |>>
+      }
+      default: {
+        fail("Invalid cell_type parameter value: ${cell_type}")
+      }
+    }
+  }
+
+}

+ 36 - 0
manifests/cert.pp

@@ -0,0 +1,36 @@
+# == Class: nova::cert
+#
+# Installs nova cert package and service
+#
+# === Parameters:
+#
+# [*enabled*]
+#   (optional) Whether or not to enable the nova cert service
+#   Defaults to true
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (optional) The state to set for the nova-cert package
+#   Defaults to 'present'
+#
+class nova::cert(
+  $enabled        = true,
+  $manage_service = true,
+  $ensure_package = 'present'
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  nova::generic_service { 'cert':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::cert_package_name,
+    service_name   => $::nova::params::cert_service_name,
+    ensure_package => $ensure_package,
+  }
+
+}

+ 21 - 0
manifests/client.pp

@@ -0,0 +1,21 @@
+# == Class nova::client
+#
+# installs nova client
+#
+# === Parameters:
+#
+# [*ensure*]
+#   (optional) The state for the nova client package
+#   Defaults to 'present'
+#
+class nova::client(
+  $ensure = 'present'
+) {
+  include ::nova::deps
+
+  package { 'python-novaclient':
+    ensure => $ensure,
+    tag    => ['openstack', 'nova-support-package'],
+  }
+
+}

+ 337 - 0
manifests/compute.pp

@@ -0,0 +1,337 @@
+# == Class: nova::compute
+#
+# Installs the nova-compute service
+#
+# === Parameters:
+#
+# [*enabled*]
+#   (optional) Whether to enable the nova-compute service
+#   Defaults to true
+#
+# [*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
+#
+# [*ensure_package*]
+#   (optional) The state for the nova-compute package
+#   Defaults to 'present'
+#
+# [*vnc_enabled*]
+#   (optional) Whether to use a VNC proxy
+#   Defaults to true
+#
+# [*vncserver_proxyclient_address*]
+#   (optional) The IP address of the server running the VNC proxy client
+#   Defaults to '127.0.0.1'
+#
+# [*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'
+#
+# [*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
+#   Defaults to false
+#
+# [*virtio_nic*]
+#   (optional) Whether to use virtio for the nic driver of VMs
+#   Defaults to false
+#
+# [*neutron_enabled*]
+#   (optional) Whether to use Neutron for networking of VMs
+#   Defaults to true
+#
+# [*install_bridge_utils*]
+#   (optional) Whether to install the bridge-utils package or not.
+#   Applicable only for cases when Neutron was disabled
+#   Defaults to true
+#
+# [*instance_usage_audit*]
+#   (optional) Generate periodic compute.instance.exists notifications.
+#   Defaults to false
+#
+# [*instance_usage_audit_period*]
+#   (optional) Time period to generate instance usages for.
+#   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'
+#
+#  [*pci_passthrough*]
+#   (optional) Pci passthrough list of hash.
+#   Defaults to $::os_service_default
+#   Example of format:
+#  "[ { 'vendor_id':'1234','product_id':'5678' },
+#     { 'vendor_id':'4321','product_id':'8765','physical_network':'default' } ] "
+#
+#  [*config_drive_format*]
+#   (optional) Config drive format. One of iso9660 (default) or vfat
+#   Defaults to undef
+#
+#  [*allow_resize_to_same_host*]
+#   (optional) Allow destination machine to match source for resize.
+#   Useful when testing in single-host environments. Note that this
+#   can also be set in the api.pp class.
+#   Defaults to false
+#
+#  [*resize_confirm_window*]
+#   (optional) Automatically confirm resizes after N seconds.
+#   Resize functionality will save the existing server before resizing.
+#   After the resize completes, user is requested to confirm the resize.
+#   The user has the opportunity to either confirm or revert all
+#   changes. Confirm resize removes the original server and changes
+#   server status from resized to active. Setting this option to a time
+#   period (in seconds) will automatically confirm the resize if the
+#   server is in resized state longer than that time.
+#   Defaults to $::os_service_default
+#
+#  [*vcpu_pin_set*]
+#   (optional) A list or range of physical CPU cores to reserve
+#   for virtual machine processes
+#   Defaults to $::os_service_default
+#
+#  [*resume_guests_state_on_host_boot*]
+#   (optional) This option specifies whether to start guests that were running before the
+#   host rebooted. It ensures that all of the instances on a Nova compute node
+#   resume their state each time the compute node boots or restarts.
+#   Defaults to $::os_service_default
+#
+# [*keymgr_api_class*]
+#   (optional) Key Manager service.
+#   Example of valid value: castellan.key_manager.barbican_key_manager.BarbicanKeyManager
+#   Defaults to $::os_service_default
+#
+# [*barbican_auth_endpoint*]
+#   (optional) Keystone v3 API URL.
+#   Example: http://localhost:5000/v3
+#   Defaults to $::os_service_default
+#
+# [*barbican_endpoint*]
+#   (optional) Barbican URL.
+#   Defaults to $::os_service_default
+#
+# [*barbican_api_version*]
+#   (optional) Barbican API version.
+#   Defaults to $::os_service_default
+#
+# [*max_concurrent_live_migrations*]
+#   (optional) Maximum number of live migrations to run in parallel.
+#   Defaults to $::os_service_default
+#
+# DEPRECATED PARAMETERS
+#
+#  [*default_availability_zone*]
+#   (optional) Default compute node availability zone.
+#   Defaults to undef
+#
+#  [*default_schedule_zone*]
+#   (optional) Availability zone to use when user doesn't specify one.
+#   Defaults to undef
+#
+#  [*internal_service_availability_zone*]
+#   (optional) The availability zone to show internal services under.
+#   Defaults to undef
+#
+#  [*compute_manager*]
+#   Deprecated. Compute manager
+#   The driver that will manage the running instances.
+#   Defaults to $::os_service_default
+#
+class nova::compute (
+  $enabled                            = true,
+  $manage_service                     = true,
+  $ensure_package                     = 'present',
+  $vnc_enabled                        = true,
+  $vncserver_proxyclient_address      = '127.0.0.1',
+  $vncproxy_host                      = false,
+  $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,
+  $install_bridge_utils               = true,
+  $instance_usage_audit               = false,
+  $instance_usage_audit_period        = 'month',
+  $force_raw_images                   = true,
+  $reserved_host_memory               = '512',
+  $heal_instance_info_cache_interval  = '60',
+  $pci_passthrough                    = $::os_service_default,
+  $config_drive_format                = $::os_service_default,
+  $allow_resize_to_same_host          = false,
+  $resize_confirm_window              = $::os_service_default,
+  $vcpu_pin_set                       = $::os_service_default,
+  $resume_guests_state_on_host_boot   = $::os_service_default,
+  $keymgr_api_class                   = $::os_service_default,
+  $barbican_auth_endpoint             = $::os_service_default,
+  $barbican_endpoint                  = $::os_service_default,
+  $barbican_api_version               = $::os_service_default,
+  $max_concurrent_live_migrations     = $::os_service_default,
+  # DEPRECATED PARAMETERS
+  $default_availability_zone          = undef,
+  $default_schedule_zone              = undef,
+  $internal_service_availability_zone = undef,
+  $compute_manager                    = $::os_service_default,
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  if $default_availability_zone {
+    warning("The default_availability_zone parameter is deprecated and will be removed in a \
+future release. Use default_availability_zone parameter of nova class instead.")
+  }
+
+  if $default_schedule_zone {
+    warning("The default_schedule_zone parameter is deprecated and will be removed in a \
+future release. Use default_schedule_zone parameter of nova class instead.")
+  }
+
+  if $internal_service_availability_zone {
+    warning("The internal_service_availability_zone parameter is deprecated and will be \
+removed in a future release. Use internal_service_availability_zone parameter of nova class instead.")
+  }
+
+  if $compute_manager {
+    warning("compute_manager is marked as deprecated in Nova but still needed when Ironic \
+is used. It will be removed once Nova removes it.")
+  }
+
+  $vcpu_pin_set_real = pick(join(any2array($vcpu_pin_set), ','), $::os_service_default)
+
+  # in the case of pci_passthrough, we can't use the same mechanism as vcpu_pin_set because
+  # the value is computed in a function and it makes things more complex. Let's just check if
+  # a value is set or if it's empty.
+  if !is_service_default($pci_passthrough) and !empty($pci_passthrough) {
+    $pci_passthrough_real = check_array_of_hash($pci_passthrough)
+  } else {
+    $pci_passthrough_real = $::os_service_default
+  }
+
+  # cryptsetup is required when Barbican is encrypting volumes
+  if $keymgr_api_class =~ /barbican/ {
+    ensure_packages('cryptsetup', {
+      ensure => present,
+      tag    => 'openstack',
+    })
+  }
+
+  include ::nova::availability_zone
+
+  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;
+    'DEFAULT/pci_passthrough_whitelist':         value => $pci_passthrough_real;
+    'DEFAULT/resize_confirm_window':             value => $resize_confirm_window;
+    'DEFAULT/vcpu_pin_set':                      value => $vcpu_pin_set_real;
+    'DEFAULT/resume_guests_state_on_host_boot':  value => $resume_guests_state_on_host_boot;
+    'key_manager/api_class':                     value => $keymgr_api_class;
+    'barbican/auth_endpoint':                    value => $barbican_auth_endpoint;
+    'barbican/barbican_endpoint':                value => $barbican_endpoint;
+    'barbican/barbican_api_version':             value => $barbican_api_version;
+    'DEFAULT/max_concurrent_live_migrations':    value => $max_concurrent_live_migrations;
+  }
+
+  ensure_resource('nova_config', 'DEFAULT/allow_resize_to_same_host', { value => $allow_resize_to_same_host })
+
+  if ($vnc_enabled) {
+    include ::nova::vncproxy::common
+
+    nova_config {
+      'vnc/vncserver_proxyclient_address': value =>
+        $vncserver_proxyclient_address;
+      'vnc/keymap':                        value => $vnc_keymap;
+    }
+  } else {
+    nova_config {
+      'vnc/vncserver_proxyclient_address': ensure => absent;
+      'vnc/keymap':                        ensure => absent;
+    }
+  }
+  nova_config {
+    'vnc/enabled': value => $vnc_enabled;
+  }
+
+  if $neutron_enabled != true and $install_bridge_utils {
+    # Install bridge-utils if we use nova-network
+    package { 'bridge-utils':
+      ensure => present,
+      tag    => ['openstack', 'nova-support-package'],
+    }
+  }
+
+  nova::generic_service { 'compute':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::compute_package_name,
+    service_name   => $::nova::params::compute_service_name,
+    ensure_package => $ensure_package,
+    before         => Exec['networking-refresh']
+  }
+
+  if $force_config_drive {
+    nova_config { 'DEFAULT/force_config_drive': value => true }
+  } else {
+    nova_config { 'DEFAULT/force_config_drive': ensure => absent }
+  }
+
+  if $virtio_nic {
+    # Enable the virtio network card for instances
+    nova_config { 'DEFAULT/libvirt_use_virtio_for_bridges': value => true }
+  }
+
+  if $instance_usage_audit and $instance_usage_audit_period in ['hour', 'day', 'month', 'year'] {
+    nova_config {
+      'DEFAULT/instance_usage_audit':        value => $instance_usage_audit;
+      'DEFAULT/instance_usage_audit_period': value => $instance_usage_audit_period;
+    }
+  } else {
+    nova_config {
+      'DEFAULT/instance_usage_audit':        ensure => absent;
+      'DEFAULT/instance_usage_audit_period': ensure => absent;
+    }
+  }
+
+  nova_config {
+    'DEFAULT/force_raw_images': value => $force_raw_images;
+  }
+
+  if is_service_default($config_drive_format) or $config_drive_format == 'iso9660' {
+    ensure_packages($::nova::params::genisoimage_package_name, {
+      tag => ['openstack', 'nova-support-package'],
+    })
+  }
+
+  nova_config {
+    'DEFAULT/config_drive_format': value => $config_drive_format;
+  }
+
+}

+ 35 - 0
manifests/compute/ironic.pp

@@ -0,0 +1,35 @@
+# == Class: nova::compute::ironic
+#
+# Configures Nova compute service to use Ironic.
+#
+# === Parameters:
+#
+# [*compute_driver*]
+#   (optional) Compute driver.
+#   Defaults to 'ironic.IronicDriver'
+#
+# [*max_concurrent_builds*]
+#   (optional) Maximum number of instance builds to run concurrently
+#   Defaults to $::os_service_default.
+#
+class nova::compute::ironic (
+  $max_concurrent_builds = $::os_service_default,
+  # DEPRECATED PARAMETERS
+  $admin_username        = undef,
+  $admin_password        = undef,
+  $admin_url             = undef,
+  $admin_tenant_name     = undef,
+  $api_endpoint          = undef,
+  $admin_user            = undef,
+  $admin_passwd          = undef,
+  $compute_driver        = 'ironic.IronicDriver'
+) {
+
+  include ::nova::deps
+  require ::nova::ironic::common
+
+  nova_config {
+    'DEFAULT/compute_driver':           value => $compute_driver;
+    'DEFAULT/max_concurrent_builds':    value => $max_concurrent_builds;
+  }
+}

+ 268 - 0
manifests/compute/libvirt.pp

@@ -0,0 +1,268 @@
+# == Class: nova::compute::libvirt
+#
+# Install and manage nova-compute guests managed
+# by libvirt
+#
+# === Parameters:
+#
+# [*ensure_package*]
+#   (optional) The state of nova packages
+#   Defaults to 'present'
+#
+# [*libvirt_virt_type*]
+#   (optional) Libvirt domain type. Options are: kvm, lxc, qemu, uml, xen
+#   Defaults to 'kvm'
+#
+# [*vncserver_listen*]
+#   (optional) IP address on which instance vncservers should listen
+#   Defaults to '127.0.0.1'
+#
+# [*migration_support*]
+#   (optional) Whether to support virtual machine migration
+#   Defaults to false
+#
+# [*libvirt_cpu_mode*]
+#   (optional) The libvirt CPU mode to configure.  Possible values
+#   include custom, host-model, none, host-passthrough.
+#   Defaults to 'host-model' if libvirt_virt_type is set to kvm,
+#   otherwise defaults to 'none'.
+#
+# [*libvirt_cpu_model*]
+#   (optional) The named libvirt CPU model (see names listed in
+#   /usr/share/libvirt/cpu_map.xml). Only has effect if
+#   cpu_mode="custom" and virt_type="kvm|qemu".
+#   Defaults to undef
+#
+# [*libvirt_disk_cachemodes*]
+#   (optional) A list of cachemodes for different disk types, e.g.
+#   ["file=directsync", "block=none"]
+#   If an empty list is specified, the disk_cachemodes directive
+#   will be removed from nova.conf completely.
+#   Defaults to an empty list
+#
+# [*libvirt_hw_disk_discard*]
+#   (optional) Discard option for nova managed disks. Need Libvirt(1.0.6)
+#   Qemu1.5 (raw format) Qemu1.6(qcow2 format).
+#   Defaults to $::os_service_default
+#
+# [*libvirt_hw_machine_type*]
+#   (optional) Option to specify a default machine type per host architecture.
+#   Defaults to $::os_service_default
+#
+# [*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
+#
+# [*libvirt_enabled_perf_events*]
+#   (optional) This is a performance event list which could be used as monitor.
+#   A string list. For example: ``enabled_perf_events = cmt, mbml, mbmt``
+#   The supported events list can be found in
+#   https://libvirt.org/html/libvirt-libvirt-domain.html ,
+#   which you may need to search key words ``VIR_PERF_PARAM_*``
+#   Defaults to $::os_service_default
+#
+# [*remove_unused_base_images*]
+#   (optional) Should unused base images be removed?
+#   If undef is specified, remove the line in nova.conf
+#   otherwise, use a boolean to remove or not the base images.
+#   Defaults to undef
+#
+# [*remove_unused_resized_minimum_age_seconds*]
+#   (optional) Unused resized base images younger
+#   than this will not be removed
+#   If undef is specified, remove the line in nova.conf
+#   otherwise, use a integer or a string to define after
+#   how many seconds it will be removed.
+#   Defaults to undef
+#
+# [*remove_unused_original_minimum_age_seconds*]
+#   (optional) Unused unresized base images younger
+#   than this will not be removed
+#   If undef is specified, remove the line in nova.conf
+#   otherwise, use a integer or a string to define after
+#   how many seconds it will be removed.
+#   Defaults to undef
+#
+# [*libvirt_service_name*]
+#   (optional) libvirt service name.
+#   Defaults to $::nova::params::libvirt_service_name
+#
+# [*virtlock_service_name*]
+#   (optional) virtlock service name.
+#   Defaults to $::nova::params::virtlock_service_name
+#
+# [*virtlog_service_name*]
+#   (optional) virtlog service name.
+#   Defaults to $::nova::params::virtlog_service_name
+#
+# [*compute_driver*]
+#   (optional) Compute driver.
+#   Defaults to 'libvirt.LibvirtDriver'
+#
+# [*preallocate_images*]
+#   (optional) The image preallocation mode to use.
+#   Valid values are 'none' or 'space'.
+#   Defaults to $::os_service_default
+#
+# [*manage_libvirt_services*]
+#   (optional) Whether or not deploy Libvirt services.
+#   In the case of micro-services, set it to False and use
+#   nova::compute::libvirt::services + hiera to select what
+#   you actually want to deploy.
+#   Defaults to true for backward compatibility.
+#
+class nova::compute::libvirt (
+  $ensure_package                             = 'present',
+  $libvirt_virt_type                          = 'kvm',
+  $vncserver_listen                           = '127.0.0.1',
+  $migration_support                          = false,
+  $libvirt_cpu_mode                           = false,
+  $libvirt_cpu_model                          = undef,
+  $libvirt_disk_cachemodes                    = [],
+  $libvirt_hw_disk_discard                    = $::os_service_default,
+  $libvirt_hw_machine_type                    = $::os_service_default,
+  $libvirt_inject_password                    = false,
+  $libvirt_inject_key                         = false,
+  $libvirt_inject_partition                   = -2,
+  $libvirt_enabled_perf_events                = $::os_service_default,
+  $remove_unused_base_images                  = undef,
+  $remove_unused_resized_minimum_age_seconds  = undef,
+  $remove_unused_original_minimum_age_seconds = undef,
+  $libvirt_service_name                       = $::nova::params::libvirt_service_name,
+  $virtlock_service_name                      = $::nova::params::virtlock_service_name,
+  $virtlog_service_name                       = $::nova::params::virtlog_service_name,
+  $compute_driver                             = 'libvirt.LibvirtDriver',
+  $preallocate_images                         = $::os_service_default,
+  $manage_libvirt_services                    = true,
+) inherits nova::params {
+
+  include ::nova::deps
+  include ::nova::params
+
+  # libvirt_cpu_mode has different defaults depending on hypervisor.
+  if !$libvirt_cpu_mode {
+    case $libvirt_virt_type {
+      'kvm': {
+        $libvirt_cpu_mode_real = 'host-model'
+      }
+      default: {
+        $libvirt_cpu_mode_real = 'none'
+      }
+    }
+  } else {
+    $libvirt_cpu_mode_real = $libvirt_cpu_mode
+  }
+
+  if($::osfamily == 'Debian') {
+    package { "nova-compute-${libvirt_virt_type}":
+      ensure => $ensure_package,
+      tag    => ['openstack', 'nova-package'],
+    }
+  }
+
+  if $migration_support {
+    include ::nova::migration::libvirt
+  }
+
+  # manage_libvirt_services is here for backward compatibility to support
+  # deployments that do not include nova::compute::libvirt::services
+  #
+  # If you're using hiera:
+  #  - set nova::compute::libvirt::manage_libvirt_services to false
+  #  - include ::nova::compute::libvirt::services in your composition layer
+  #  - select which services you want to deploy with
+  #    ::nova::compute::libvirt::services:* parameters.
+  #
+  # If you're not using hiera:
+  #  - set nova::compute::libvirt::manage_libvirt_services to true (default).
+  #  - select which services you want to deploy with
+  #    ::nova::compute::libvirt::*_service_name parameters.
+  if $manage_libvirt_services {
+    class { '::nova::compute::libvirt::services':
+      libvirt_service_name  => $libvirt_service_name,
+      virtlock_service_name => $virtlock_service_name,
+      virtlog_service_name  => $virtlog_service_name,
+      libvirt_virt_type     => $libvirt_virt_type,
+    }
+  }
+
+  nova_config {
+    'DEFAULT/compute_driver':      value => $compute_driver;
+    'DEFAULT/preallocate_images':  value => $preallocate_images;
+    'vnc/vncserver_listen':        value => $vncserver_listen;
+    '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;
+    'libvirt/hw_disk_discard':     value => $libvirt_hw_disk_discard;
+    'libvirt/hw_machine_type':     value => $libvirt_hw_machine_type;
+    'libvirt/enabled_perf_events': value => $libvirt_enabled_perf_events;
+  }
+
+  # cpu_model param is only valid if cpu_mode=custom
+  # otherwise it should be commented out
+  if $libvirt_cpu_mode_real == 'custom' {
+    validate_string($libvirt_cpu_model)
+    nova_config {
+      'libvirt/cpu_model': value => $libvirt_cpu_model;
+    }
+  } else {
+    nova_config {
+      'libvirt/cpu_model': ensure => absent;
+    }
+    if $libvirt_cpu_model {
+      warning('$libvirt_cpu_model requires that $libvirt_cpu_mode => "custom" and will be ignored')
+    }
+  }
+
+  if size($libvirt_disk_cachemodes) > 0 {
+    nova_config {
+      'libvirt/disk_cachemodes': value => join($libvirt_disk_cachemodes, ',');
+    }
+  } else {
+    nova_config {
+      'libvirt/disk_cachemodes': ensure => absent;
+    }
+  }
+
+  if $remove_unused_resized_minimum_age_seconds != undef {
+    nova_config {
+      'libvirt/remove_unused_resized_minimum_age_seconds': value => $remove_unused_resized_minimum_age_seconds;
+    }
+  } else {
+    nova_config {
+      'libvirt/remove_unused_resized_minimum_age_seconds': ensure => absent;
+    }
+  }
+
+  if $remove_unused_base_images != undef {
+    nova_config {
+      'DEFAULT/remove_unused_base_images': value => $remove_unused_base_images;
+    }
+  } else {
+    nova_config {
+      'DEFAULT/remove_unused_base_images': ensure => absent;
+    }
+  }
+
+  if $remove_unused_original_minimum_age_seconds != undef {
+    nova_config {
+      'DEFAULT/remove_unused_original_minimum_age_seconds': value => $remove_unused_original_minimum_age_seconds;
+    }
+  } else {
+    nova_config {
+      'DEFAULT/remove_unused_original_minimum_age_seconds': ensure => absent;
+    }
+  }
+}

+ 55 - 0
manifests/compute/libvirt/qemu.pp

@@ -0,0 +1,55 @@
+# == Class: nova::compute::libvirt::qemu
+#
+# Configures qemu limits for use by libvirt
+#
+# === Parameters:
+#
+# [*configure_qemu*]
+#   (optional) Whether or not configure qemu bits.
+#   Defaults to false.
+#
+# [*max_files*]
+#   (optional) Maximum number of opened files, per process.
+#   Defaults to 1024.
+#
+# [*max_processes*]
+#   (optional) Maximum number of processes that can be run by qemu user.
+#   Defaults to 4096.
+#
+class nova::compute::libvirt::qemu(
+  $configure_qemu = false,
+  $max_files      = 1024,
+  $max_processes  = 4096,
+){
+
+  include ::nova::deps
+  require ::nova::compute::libvirt
+
+  Anchor['nova::config::begin']
+  -> Augeas<| tag == 'qemu-conf-augeas'|>
+  -> Anchor['nova::config::end']
+
+  Augeas<| tag == 'qemu-conf-augeas'|>
+  ~> Service['libvirt']
+
+  if $configure_qemu {
+
+    augeas { 'qemu-conf-limits':
+      context => '/files/etc/libvirt/qemu.conf',
+      changes => [
+        "set max_files ${max_files}",
+        "set max_processes ${max_processes}",
+      ],
+      tag     => 'qemu-conf-augeas',
+    }
+  } else {
+    augeas { 'qemu-conf-limits':
+      context => '/files/etc/libvirt/qemu.conf',
+      changes => [
+        'rm max_files',
+        'rm max_processes',
+      ],
+      tag     => 'qemu-conf-augeas',
+    }
+  }
+}

+ 108 - 0
manifests/compute/libvirt/services.pp

@@ -0,0 +1,108 @@
+# == Class: nova::compute::libvirt::services
+#
+# Install and manage libvirt services.
+#
+# === Parameters:
+#
+# [*libvirt_service_name*]
+#   (optional) libvirt service name.
+#   Defaults to $::nova::params::libvirt_service_name
+#
+# [*virtlock_service_name*]
+#   (optional) virtlock service name.
+#   Defaults to $::nova::params::virtlock_service_name
+#
+# [*virtlog_service_name*]
+#   (optional) virtlog service name.
+#   Defaults to $::nova::params::virtlog_service_name
+#
+# [*libvirt_virt_type*]
+#   (optional) Libvirt domain type. Options are: kvm, lxc, qemu, uml, xen
+#   Defaults to 'kvm'
+#
+class nova::compute::libvirt::services (
+  $libvirt_service_name  = $::nova::params::libvirt_service_name,
+  $virtlock_service_name = $::nova::params::virtlock_service_name,
+  $virtlog_service_name  = $::nova::params::virtlog_service_name,
+  $libvirt_virt_type     = 'kvm',
+) inherits nova::params {
+
+  include ::nova::deps
+  include ::nova::params
+
+  if $libvirt_service_name {
+    # messagebus
+    if($::osfamily == 'RedHat' and $::operatingsystem != 'Fedora') {
+      service { 'messagebus':
+        ensure   => running,
+        enable   => true,
+        name     => $::nova::params::messagebus_service_name,
+        provider => $::nova::params::special_service_provider,
+
+      }
+      Package['libvirt'] -> Service['messagebus'] -> Service['libvirt']
+    }
+
+    # libvirt-nwfilter
+    if $::osfamily == 'RedHat' {
+      package { 'libvirt-nwfilter':
+        ensure => present,
+        name   => $::nova::params::libvirt_nwfilter_package_name,
+        before => Service['libvirt'],
+        tag    => ['openstack', 'nova-support-package'],
+      }
+      case $libvirt_virt_type {
+        'qemu': {
+          $libvirt_package_name_real = "${::nova::params::libvirt_daemon_package_prefix}kvm"
+        }
+        'parallels': {
+          $libvirt_package_name_real = $::nova::params::libvirt_package_name
+        }
+        default: {
+          $libvirt_package_name_real = "${::nova::params::libvirt_daemon_package_prefix}${libvirt_virt_type}"
+        }
+      }
+    } else {
+      $libvirt_package_name_real = $::nova::params::libvirt_package_name
+    }
+
+    # libvirt
+    package { 'libvirt':
+      ensure => present,
+      name   => $libvirt_package_name_real,
+      tag    => ['openstack', 'nova-support-package'],
+    }
+    service { 'libvirt' :
+      ensure   => running,
+      enable   => true,
+      name     => $libvirt_service_name,
+      provider => $::nova::params::special_service_provider,
+      require  => Package['libvirt'],
+    }
+
+    # when nova-compute & libvirt run together
+    Service['libvirt'] -> Service<| title == 'nova-compute'|>
+  }
+
+
+  if $virtlock_service_name {
+    service { 'virtlockd':
+      ensure   => running,
+      enable   => true,
+      name     => $virtlock_service_name,
+      provider => $::nova::params::special_service_provider,
+      require  => Package['libvirt']
+    }
+  }
+
+  if $virtlog_service_name {
+    service { 'virtlogd':
+      ensure   => running,
+      enable   => true,
+      name     => $virtlog_service_name,
+      provider => $::nova::params::special_service_provider,
+      require  => Package['libvirt']
+    }
+  }
+
+}

+ 48 - 0
manifests/compute/neutron.pp

@@ -0,0 +1,48 @@
+# == Class: nova::compute::neutron
+#
+# Manage the network driver to use for compute guests
+# This will use virtio for VM guests and the
+# specified driver for the VIF
+#
+# === Parameters
+#
+# [*libvirt_vif_driver*]
+#   (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',
+  $force_snat_range   = '0.0.0.0/0',
+) {
+  include ::nova::deps
+
+  if $libvirt_vif_driver == 'nova.virt.libvirt.vif.LibvirtOpenVswitchDriver' {
+    fail('nova.virt.libvirt.vif.LibvirtOpenVswitchDriver as vif_driver is removed from Icehouse')
+  }
+
+  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;
+    }
+  }
+
+}

+ 140 - 0
manifests/compute/rbd.pp

@@ -0,0 +1,140 @@
+#
+# Copyright (C) 2014 OpenStack Fondation
+#
+# Author: Emilien Macchi <emilien.macchi@enovance.com>
+#         Donald Talton  <dotalton@cisco.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::compute::rbd
+#
+# Configure nova-compute to store virtual machines on RBD
+#
+# === Parameters
+#
+# [*libvirt_images_rbd_pool*]
+#   (optional) The RADOS pool in which rbd volumes are stored.
+#   Defaults to 'rbd'.
+#
+# [*libvirt_images_rbd_ceph_conf*]
+#   (optional) The path to the ceph configuration file to use.
+#   Defaults to '/etc/ceph/ceph.conf'.
+#
+# [*libvirt_rbd_user*]
+#   (Required) The RADOS client name for accessing rbd volumes.
+#
+# [*libvirt_rbd_secret_uuid*]
+#   (optional) The libvirt uuid of the secret for the rbd_user.
+#   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'
+#
+# [*ephemeral_storage*]
+#   (optional) Wether or not to use the rbd driver for the nova
+#   ephemeral storage or for the cinder volumes only.
+#   Defaults to true.
+#
+# [*manage_ceph_client*]
+#  (optional) Whether to manage the ceph client package.
+#  Defaults to true.
+#
+# [*ceph_client_ensure*]
+#  (optional) Ensure value for ceph client package.
+#  Defaults to 'present'.
+
+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',
+  $ephemeral_storage            = true,
+  $manage_ceph_client           = true,
+  $ceph_client_ensure           = 'present',
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  if $manage_ceph_client {
+    # Install ceph client libraries
+    package { 'ceph-client-package':
+      ensure => $ceph_client_ensure,
+      name   => $nova::params::ceph_client_package_name,
+      tag    => ['openstack'],
+    }
+  }
+
+  nova_config {
+    'libvirt/rbd_user': value => $libvirt_rbd_user;
+  }
+
+  if $libvirt_rbd_secret_uuid {
+    nova_config {
+      'libvirt/rbd_secret_uuid': value => $libvirt_rbd_secret_uuid;
+    }
+
+    file { '/etc/nova/secret.xml':
+      content => template('nova/secret.xml-compute.erb'),
+      require => Anchor['nova::config::begin'],
+    }
+
+    #Variable name shrinked in favor of removing
+    #the more than 140 chars puppet-lint warning.
+    #variable used in the get-or-set virsh secret
+    #resource.
+    $cm = '/usr/bin/virsh secret-define --file /etc/nova/secret.xml | /usr/bin/awk \'{print $2}\' | sed \'/^$/d\' > /etc/nova/virsh.secret'
+    exec { 'get-or-set virsh secret':
+      command => $cm,
+      unless  => "/usr/bin/virsh secret-list | grep ${libvirt_rbd_secret_uuid}",
+      require => [File['/etc/nova/secret.xml'], Service['libvirt']],
+    }
+
+    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 ${libvirt_rbd_secret_uuid} --base64 ${libvirt_key}",
+      unless  => "/usr/bin/virsh secret-get-value ${libvirt_rbd_secret_uuid} | grep ${libvirt_key}",
+      require => Exec['get-or-set virsh secret'],
+      before  => Anchor['nova::config::end'],
+    }
+  }
+
+  if $ephemeral_storage {
+    nova_config {
+      'libvirt/images_type':          value => 'rbd';
+      'libvirt/images_rbd_pool':      value => $libvirt_images_rbd_pool;
+      'libvirt/images_rbd_ceph_conf': value => $libvirt_images_rbd_ceph_conf;
+    }
+  } else {
+    nova_config {
+      'libvirt/images_rbd_pool':      ensure => absent;
+      'libvirt/images_rbd_ceph_conf': ensure => absent;
+    }
+  }
+
+}

+ 34 - 0
manifests/compute/serial.pp

@@ -0,0 +1,34 @@
+# == 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/'
+#
+# [*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/',
+  $proxyclient_address = '127.0.0.1',
+) {
+
+  include ::nova::deps
+
+  nova_config {
+    'serial_console/enabled':             value => true;
+    'serial_console/port_range':          value => $port_range;
+    'serial_console/base_url':            value => $base_url;
+    'serial_console/proxyclient_address': value => $proxyclient_address;
+  }
+}

+ 67 - 0
manifests/compute/spice.pp

@@ -0,0 +1,67 @@
+# == Class: nova::compute::spice
+#
+# Configure spice on the compute side
+#
+# === Parameters:
+#
+# [*agent_enabled*]
+#   (optional) enable spice guest agent support
+#   Defaults to true
+#
+# [*server_listen*]
+#   (optional)  IP address on which instance spice servers should listen
+#   Defaults to undef
+#
+# [*server_proxyclient_address*]
+#   (optional) Management IP Address on which instance spiceservers will
+#   listen on the compute host.
+#   Defaults to '127.0.0.1'
+#
+# [*keymap*]
+#   (optional) keymap for spice
+#   Defaults to 'en-us'
+#
+# [*proxy_host*]
+#   (optional) Host for the html5 console proxy
+#   Defaults to false
+#
+# [*proxy_port*]
+#   (optional) Port for the html5 console proxy
+#   Defaults to '6082'
+#
+# [*proxy_protocol*]
+#   (optional) Protocol for the html5 console proxy
+#   Defaults to 'http'
+#
+# [*proxy_path*]
+#   (optional) Path of the spice html file for the html5 console proxy
+#   Defaults to '/spice_auto.html'
+#
+class nova::compute::spice(
+  $agent_enabled                    = true,
+  $server_listen                    = undef,
+  $server_proxyclient_address       = '127.0.0.1',
+  $keymap                           = 'en-us',
+  $proxy_host                       = false,
+  $proxy_protocol                   = 'http',
+  $proxy_port                       = '6082',
+  $proxy_path                       = '/spice_auto.html'
+) {
+
+  include ::nova::deps
+
+  if $proxy_host {
+    $html5proxy_base_url = "${proxy_protocol}://${proxy_host}:${proxy_port}${proxy_path}"
+    nova_config {
+      'spice/html5proxy_base_url': value => $html5proxy_base_url;
+    }
+  }
+
+  nova_config {
+    'spice/enabled':                    value => true;
+    'spice/agent_enabled':              value => $agent_enabled;
+    'spice/server_listen':              value => $server_listen;
+    'spice/server_proxyclient_address': value => $server_proxyclient_address;
+    'spice/keymap':                     value => $keymap;
+  }
+}

+ 109 - 0
manifests/compute/vmware.pp

@@ -0,0 +1,109 @@
+#
+# Configure the VMware compute driver for nova.
+#
+# === Parameters
+#
+# [*host_ip*]
+#   The IP address of the VMware vCenter server.
+#
+# [*host_username*]
+#   The username for connection to VMware vCenter server.
+#
+# [*host_password*]
+#   The password for connection to VMware vCenter server.
+#
+# [*cluster_name*]
+#   The name of a vCenter cluster compute resource.
+#
+# [*api_retry_count*]
+#   (optional) The number of times we retry on failures,
+#   e.g., socket error, etc.
+#   Defaults to 5.
+#
+# [*maximum_objects*]
+#   (optional) The maximum number of ObjectContent data objects that should
+#   be returned in a single result. A positive value will cause
+#   the operation to suspend the retrieval when the count of
+#   objects reaches the specified maximum. The server may still
+#   limit the count to something less than the configured value.
+#   Any remaining objects may be retrieved with additional requests.
+#   Defaults to 100.
+#
+# [*task_poll_interval*]
+#   (optional) The interval in seconds used for polling of remote tasks.
+#   Defaults to 5.0
+#
+# [*use_linked_clone*]
+#   (optional) Whether to use linked clone strategy while creating VM's.
+#   Defaults to true.
+#
+# [*compute_driver*]
+#   (optional) Compute driver.
+#   Defaults to 'vmwareapi.VMwareVCDriver'
+#
+# [*insecure*]
+#   (optional) Allow insecure conections.
+#   If true, the vCenter server certificate is not verified. If
+#   false, then the default CA truststore is used for verification. This
+#   option is ignored if 'ca_file' is set.
+#   Defaults to $::os_service_default
+#
+# [*ca_file*]
+#   (optional) Specify a CA bundle file to use in verifying the vCenter server
+#   certificate.
+#   Defaults to $::os_service_default
+#
+# [*datastore_regex*]
+#   (optional) Regex to match the name of a datastore.
+#   Defaults to $::os_service_default
+#
+# DEPRECATED PARAMETERS
+# [*wsdl_location*]
+#   (optional) VIM Service WSDL Location e.g
+#   http://<server>/vimService.wsdl. Optional over-ride to
+#   default location for bug work-arounds.
+#   Defaults to undef
+#
+class nova::compute::vmware(
+  $host_ip,
+  $host_username,
+  $host_password,
+  $cluster_name,
+  $api_retry_count    = 5,
+  $maximum_objects    = 100,
+  $task_poll_interval = 5.0,
+  $use_linked_clone   = true,
+  $compute_driver     = 'vmwareapi.VMwareVCDriver',
+  $insecure           = $::os_service_default,
+  $ca_file            = $::os_service_default,
+  $datastore_regex    = $::os_service_default,
+  # DEPRECATED PARAMETERS
+  $wsdl_location      = undef,
+) {
+
+  include ::nova::deps
+
+  if $wsdl_location {
+    warning('wsdl_location is deprecated, has no effect and will be removed in the future release.')
+  }
+
+  nova_config {
+    'DEFAULT/compute_driver':    value => $compute_driver;
+    'vmware/host_ip':            value => $host_ip;
+    'vmware/host_username':      value => $host_username;
+    'vmware/host_password':      value => $host_password;
+    'vmware/cluster_name':       value => $cluster_name;
+    'vmware/api_retry_count':    value => $api_retry_count;
+    'vmware/maximum_objects':    value => $maximum_objects;
+    'vmware/task_poll_interval': value => $task_poll_interval;
+    'vmware/use_linked_clone':   value => $use_linked_clone;
+    'vmware/insecure':           value => $insecure;
+    'vmware/ca_file':            value => $ca_file;
+    'vmware/datastore_regex':    value => $datastore_regex;
+  }
+
+  package { 'python-suds':
+    ensure => present,
+    tag    => ['openstack', 'nova-support-package'],
+  }
+}

+ 376 - 0
manifests/compute/xenserver.pp

@@ -0,0 +1,376 @@
+# == Class: nova::compute::xenserver
+#
+# Configures nova-compute to manage xen guests
+#
+# === Parameters:
+#
+# [*connection_url*]
+#   (required) URL for connection to XenServer/Xen Cloud Platform.
+#
+# [*connection_username*]
+#   (required) Username for connection to XenServer/Xen Cloud Platform
+#
+# [*connection_password*]
+#   (required) Password for connection to XenServer/Xen Cloud Platform
+#
+# [*compute_driver*]
+#   (optional) Compute driver.
+#   Defaults to 'xenapi.XenAPIDriver'
+#
+# [*ovs_integration_bridge*]
+#   (optional) Name of Integration Bridge used by Open vSwitch (string value)
+#   Defaults to $::os_service_default
+#
+# [*agent_timeout*]
+#   (optional) Number of seconds to wait for agent reply (integer value)
+#   Defaults to $::os_service_default
+#
+# [*agent_version_timeout*]
+#   (optional) Number of seconds to wait for agent to be fully operational (integer value)
+#   Defaults to $::os_service_default
+#
+# [*agent_resetnetwork_timeout*]
+#   (optional) Number of seconds to wait for agent reply to resetnetwork request (integer value)
+#   Defaults to $::os_service_default
+#
+# [*agent_path*]
+#   (optional) Specifies the path in which the XenAPI guest agent should be located. If the
+#   agent is present, network configuration is not injected into the image. Used
+#   if compute_driver=xenapi.XenAPIDriver and flat_injected=True (string value)
+#   Defaults to $::os_service_default
+#
+# [*disable_agent*]
+#   (optional) Disables the use of the XenAPI agent in any image regardless of what image
+#   properties are present (boolean value).
+#   Defaults to $::os_service_default
+#
+# [*use_agent_default*]
+#   (optional) Determines if the XenAPI agent should be used when the image used does not
+#   contain a hint to declare if the agent is present or not. The hint is a
+#   glance property "xenapi_use_agent" that has the value "True" or "False". Note
+#   that waiting for the agent when it is not present will significantly increase
+#   server boot times. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*login_timeout*]
+#   (optional) Timeout in seconds for XenAPI login. (integer value)
+#   Defaults to $::os_service_default
+#
+# [*connection_concurrent*]
+#   {optional} Maximum number of concurrent XenAPI connections.
+#   Defaults to $::os_service_default
+#
+# [*vhd_coalesce_poll_interval*]
+#   (optional) The interval used for polling of coalescing vhds. (floating point value)
+#   Defaults to $::os_service_default
+#
+# [*check_host*]
+#   (optional) Ensure compute service is running on host XenAPI connects to. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*vhd_coalesce_max_attempts*]
+#   (optional) Max number of times to poll for VHD to coalesce.
+#   Defaults to $::os_service_default
+#
+# [*sr_base_path*]
+#   (optional) Base path to the storage repository (string value)
+#   Defaults to $::os_service_default
+#
+# [*target_host*]
+#   (optional) The iSCSI Target Host (string value)
+#   Defaults to $::os_service_default
+#
+# [*target_port*]
+#   (optional) The iSCSI Target Port, default is port 3260 (string value)
+#   Defaults to $::os_service_default
+#
+# [*iqn_prefix*]
+#   (optional) IQN Prefix (string value)
+#   Defaults to $::os_service_default
+#
+# [*remap_vbd_dev*]
+#   (optional) Used to enable the remapping of VBD dev (Works around an issue in Ubuntu
+#   Maverick) (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*remap_vbd_dev_prefix*]
+#   (optional) Specify prefix to remap VBD dev to (ex. /dev/xvdb -> /dev/sdb) (string value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_base_url*]
+#   (optional) Base URL for torrent files; must contain a slash character (see RFC 1808,
+#   step 6) (string value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_seed_chance*]
+#   (optional) Probability that peer will become a seeder. (1.0 = 100%) (floating poin value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_seed_duration*]
+#   (optional) Number of seconds after downloading an image via BitTorrent that it should be
+#   seeded for other peers. (integer value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_max_last_accessed*]
+#   (optional) Cached torrent files not accessed within this number of seconds can be reaped
+#   (integer value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_listen_port_start*]
+#   (optional) Beginning of port range to listen on (integer value)
+#   Minimum value: 1
+#   Maximum value: 65535
+#   Defaults to $::os_service_default
+#
+# [*torrent_listen_port_end*]
+#   (optional) End of port range to listen on (integer value)
+#   Minimum value: 1
+#   Maximum value: 65535
+#   Defaults to $::os_service_default
+#
+# [*torrent_download_stall_cutoff*]
+#   (optional) Number of seconds a download can remain at the same progress percentage w/o
+#   being considered a stall (integer value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_max_seeder_processes_per_host*]
+#   (optional) Maximum number of seeder processes to run concurrently within a given dom0.
+#   (-1 = no limit) (integer value)
+#   Defaults to $::os_service_default
+#
+# [*use_join_force*]
+#   (optional) To use for hosts with different CPUs (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*cache_images*]
+#   (optional) Cache glance images locally. `all` will cache all images, `some` will only
+#   cache images that have the image_property `cache_in_nova=True`, and `none`
+#   turns off caching entirely (string value)
+#   Allowed values: all, some, none
+#   Defaults to $::os_service_default
+#
+# [*image_compression_level*]
+#   (optional) Compression level for images, e.g., 9 for gzip -9. Range is 1-9, 9 being most
+#   compressed but most CPU intensive on dom0. (integer value)
+#   Minimum value: 1
+#   Maximum value: 9
+#   Defaults to $::os_service_default
+#
+# [*default_os_type*]
+#   (optional) Default OS type (string value)
+#   Defaults to $::os_service_default
+#
+# [*block_device_creation_timeout*]
+#  (optional) Time to wait for a block device to be created (integer value)
+#   Defaults to $::os_service_default
+#
+# [*max_kernel_ramdisk_size*]
+#   (optional) Maximum size in bytes of kernel or ramdisk images (integer value)
+#   Defaults to $::os_service_default
+#
+# [*sr_matching_filter*]
+#   (optional) Filter for finding the SR to be used to install guest instances on. To use
+#   the Local Storage in default XenServer/XCP installations set this flag to
+#   other-config:i18n-key=local-storage. To select an SR with a different
+#   matching criteria, you could set it to other-config:my_favorite_sr=true. On
+#   the other hand, to fall back on the Default SR, as displayed by XenCenter,
+#   set this flag to: default-sr:true (string value)
+#   Defaults to $::os_service_default
+#
+# [*sparse_copy*]
+#   (optional) Whether to use sparse_copy for copying data on a resize down (False will use
+#   standard dd). This speeds up resizes down considerably since large runs of
+#   zeros won't have to be rsynced (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*num_vbd_unplug_retries*]
+#   (optional) Maximum number of retries to unplug VBD. if <=0, should try once and no retry
+#   (integer value)
+#   Defaults to $::os_service_default
+#
+# [*torrent_images*]
+#   (optional) Whether or not to download images via Bit Torrent. (string value)
+#   Allowed values: all, some, none
+#   Defaults to $::os_service_default
+#
+# [*ipxe_network_name*]
+#   (optional) Name of network to use for booting iPXE ISOs (string value)
+#   Defaults to $::os_service_default
+#
+# [*ipxe_boot_menu_url*]
+#   (optional) URL to the iPXE boot menu (string value)
+#   Defaults to $::os_service_default
+#
+# [*ipxe_mkisofs_cmd*]
+#   (optional) Name and optionally path of the tool used for ISO image creation (string
+#   value)
+#   Defaults to $::os_service_default
+#
+# [*running_timeout*]
+#   (optional) Number of seconds to wait for instance to go to running state (integer value)
+#   Defaults to $::os_service_default
+#
+# [*vif_driver*]
+#   (optional) The XenAPI VIF driver using XenServer Network APIs. (string value)
+#   Defaults to $::os_service_default
+#
+# [*image_upload_handler*]
+#   (optional) Dom0 plugin driver used to handle image uploads. (string value)
+#   Defaults to $::os_service_default
+#
+# [*introduce_vdi_retry_wait*]
+#   (optional) Number of seconds to wait for an SR to settle if the VDI does not exist when
+#   first introduced (integer value)
+#   Defaults to $::os_service_default
+#
+# DEPRECATED PARAMETERS
+#
+# [*xenapi_inject_image*]
+#   (optional) DEPRECATED: This parameter does nothing.
+#
+# [*xenapi_connection_url*]
+#   (optional) DEPRECATED: URL for connection to XenServer/Xen Cloud Platform.
+#   Please use connection_url parameter.
+#
+# [*xenapi_connection_username*]
+#   (optional) DEPRECATED: Username for connection to XenServer/Xen Cloud Platform
+#   Please use connection_username parameter.
+#
+# [*xenapi_connection_password*]
+#   (optional) DEPRECATED: Password for connection to XenServer/Xen Cloud Platform.
+#   Please use connection_password parameter.
+#
+class nova::compute::xenserver(
+  $connection_url,
+  $connection_username,
+  $connection_password,
+  $compute_driver                        = 'xenapi.XenAPIDriver',
+  $ovs_integration_bridge                = $::os_service_default,
+  $agent_timeout                         = $::os_service_default,
+  $agent_version_timeout                 = $::os_service_default,
+  $agent_resetnetwork_timeout            = $::os_service_default,
+  $agent_path                            = $::os_service_default,
+  $disable_agent                         = $::os_service_default,
+  $use_agent_default                     = $::os_service_default,
+  $login_timeout                         = $::os_service_default,
+  $connection_concurrent                 = $::os_service_default,
+  $vhd_coalesce_poll_interval            = $::os_service_default,
+  $check_host                            = $::os_service_default,
+  $vhd_coalesce_max_attempts             = $::os_service_default,
+  $sr_base_path                          = $::os_service_default,
+  $target_host                           = $::os_service_default,
+  $target_port                           = $::os_service_default,
+  $iqn_prefix                            = $::os_service_default,
+  $remap_vbd_dev                         = $::os_service_default,
+  $remap_vbd_dev_prefix                  = $::os_service_default,
+  $torrent_base_url                      = $::os_service_default,
+  $torrent_seed_chance                   = $::os_service_default,
+  $torrent_seed_duration                 = $::os_service_default,
+  $torrent_max_last_accessed             = $::os_service_default,
+  $torrent_listen_port_start             = $::os_service_default,
+  $torrent_listen_port_end               = $::os_service_default,
+  $torrent_download_stall_cutoff         = $::os_service_default,
+  $torrent_max_seeder_processes_per_host = $::os_service_default,
+  $use_join_force                        = $::os_service_default,
+  $cache_images                          = $::os_service_default,
+  $image_compression_level               = $::os_service_default,
+  $default_os_type                       = $::os_service_default,
+  $block_device_creation_timeout         = $::os_service_default,
+  $max_kernel_ramdisk_size               = $::os_service_default,
+  $sr_matching_filter                    = $::os_service_default,
+  $sparse_copy                           = $::os_service_default,
+  $num_vbd_unplug_retries                = $::os_service_default,
+  $torrent_images                        = $::os_service_default,
+  $ipxe_network_name                     = $::os_service_default,
+  $ipxe_boot_menu_url                    = $::os_service_default,
+  $ipxe_mkisofs_cmd                      = $::os_service_default,
+  $running_timeout                       = $::os_service_default,
+  $vif_driver                            = 'nova.virt.xenapi.vif.XenAPIOpenVswitchDriver',
+  $image_upload_handler                  = $::os_service_default,
+  $introduce_vdi_retry_wait              = $::os_service_default,
+  # DEPRECATED PARAMETERS
+  $xenapi_inject_image                   = undef,
+  $xenapi_connection_url                 = undef,
+  $xenapi_connection_username            = undef,
+  $xenapi_connection_password            = undef,
+) {
+
+  include ::nova::deps
+
+  if $xenapi_inject_image != undef {
+    warning('The xenapi_inject_image parameter is deprecated and has no effect.')
+  }
+
+  if $xenapi_connection_url {
+    warning('The xenapi_connection_url parameter is deprecated and has no effect, please use connection_url.')
+  }
+
+  if $xenapi_connection_username {
+    warning('The xenapi_connection_username parameter is deprecated and has no effect, please use connection_username.')
+  }
+
+  if $xenapi_connection_password {
+    warning('The xenapi_connection_password parameter is deprecated and has no effect, please use connection_password.')
+  }
+
+
+  nova_config {
+    'DEFAULT/compute_driver':                          value => $compute_driver;
+    'xenserver/connection_url':                        value => $connection_url;
+    'xenserver/connection_username':                   value => $connection_username;
+    'xenserver/connection_password':                   value => $connection_password;
+    'xenserver/ovs_integration_bridge':                value => $ovs_integration_bridge;
+    'xenserver/agent_timeout':                         value => $agent_timeout;
+    'xenserver/agent_version_timeout':                 value => $agent_version_timeout;
+    'xenserver/agent_resetnetwork_timeout':            value => $agent_resetnetwork_timeout;
+    'xenserver/agent_path':                            value => $agent_path;
+    'xenserver/disable_agent':                         value => $disable_agent;
+    'xenserver/use_agent_default':                     value => $use_agent_default;
+    'xenserver/login_timeout':                         value => $login_timeout;
+    'xenserver/connection_concurrent':                 value => $connection_concurrent;
+    'xenserver/vhd_coalesce_poll_interval':            value => $vhd_coalesce_poll_interval;
+    'xenserver/check_host':                            value => $check_host;
+    'xenserver/vhd_coalesce_max_attempts':             value => $vhd_coalesce_max_attempts;
+    'xenserver/sr_base_path':                          value => $sr_base_path;
+    'xenserver/target_host':                           value => $target_host;
+    'xenserver/target_port':                           value => $target_port;
+    'xenserver/iqn_prefix':                            value => $iqn_prefix;
+    'xenserver/remap_vbd_dev':                         value => $remap_vbd_dev;
+    'xenserver/remap_vbd_dev_prefix':                  value => $remap_vbd_dev_prefix;
+    'xenserver/torrent_base_url':                      value => $torrent_base_url;
+    'xenserver/torrent_seed_chance':                   value => $torrent_seed_chance;
+    'xenserver/torrent_seed_duration':                 value => $torrent_seed_duration;
+    'xenserver/torrent_max_last_accessed':             value => $torrent_max_last_accessed;
+    'xenserver/torrent_listen_port_start':             value => $torrent_listen_port_start;
+    'xenserver/torrent_listen_port_end':               value => $torrent_listen_port_end;
+    'xenserver/torrent_download_stall_cutoff':         value => $torrent_download_stall_cutoff;
+    'xenserver/torrent_max_seeder_processes_per_host': value => $torrent_max_seeder_processes_per_host;
+    'xenserver/use_join_force':                        value => $use_join_force;
+    'xenserver/cache_images':                          value => $cache_images;
+    'xenserver/image_compression_level':               value => $image_compression_level;
+    'xenserver/default_os_type':                       value => $default_os_type;
+    'xenserver/block_device_creation_timeout':         value => $block_device_creation_timeout;
+    'xenserver/max_kernel_ramdisk_size':               value => $max_kernel_ramdisk_size;
+    'xenserver/sr_matching_filter':                    value => $sr_matching_filter;
+    'xenserver/sparse_copy':                           value => $sparse_copy;
+    'xenserver/num_vbd_unplug_retries':                value => $num_vbd_unplug_retries;
+    'xenserver/torrent_images':                        value => $torrent_images;
+    'xenserver/ipxe_network_name':                     value => $ipxe_network_name;
+    'xenserver/ipxe_boot_menu_url':                    value => $ipxe_boot_menu_url;
+    'xenserver/ipxe_mkisofs_cmd':                      value => $ipxe_mkisofs_cmd;
+    'xenserver/running_timeout':                       value => $running_timeout;
+    'xenserver/vif_driver':                            value => $vif_driver;
+    'xenserver/image_upload_handler':                  value => $image_upload_handler;
+    'xenserver/introduce_vdi_retry_wait':              value => $introduce_vdi_retry_wait;
+  }
+
+  ensure_packages(['python-pip'])
+
+  package { 'xenapi':
+    ensure   => present,
+    provider => pip,
+    tag      => ['openstack', 'nova-support-package'],
+  }
+
+  Package['python-pip'] -> Package['xenapi']
+}

+ 71 - 0
manifests/conductor.pp

@@ -0,0 +1,71 @@
+# == Class: nova::conductor
+#
+# Manages nova conductor package and service
+#
+# === Parameters:
+#
+# [*enabled*]
+#   (optional) Whether to enable the nova-conductor service
+#   Defaults to true
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (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)
+#
+# [*enable_new_services*]
+#   (optional) When a new service (for example "nova-compute") start up, it gets
+#   registered in the database as an enabled service. Setting this to false will
+#   cause new services to be disabled when added. This config option is only used
+#   by the conductor service which is responsible for creating the service entries.
+#   Defaults to $::os_service_default
+#
+# DEPRECATED PARAMETERS
+#
+# [*use_local*]
+#   (optional) Perform nova-conductor operations locally
+#   Defaults to undef
+#
+class nova::conductor(
+  $enabled             = true,
+  $manage_service      = true,
+  $ensure_package      = 'present',
+  $workers             = undef,
+  $enable_new_services = $::os_service_default,
+  # DEPREACTED PARAMETERS
+  $use_local           = undef,
+) {
+
+  if $use_local {
+    warning('use_local parameter is deprecated, has no effect and will be dropped in a future release.')
+  }
+
+  include ::nova::deps
+  include ::nova::db
+  include ::nova::params
+
+  nova::generic_service { 'conductor':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::conductor_package_name,
+    service_name   => $::nova::params::conductor_service_name,
+    ensure_package => $ensure_package,
+  }
+
+  if $workers {
+    nova_config {
+      'conductor/workers': value => $workers;
+    }
+  }
+
+  nova_config {
+    'DEFAULT/enable_new_services': value => $enable_new_services
+  }
+}

+ 42 - 0
manifests/config.pp

@@ -0,0 +1,42 @@
+# == Class: nova::config
+#
+# This class is used to manage arbitrary Nova configurations.
+#
+# === Parameters
+#
+# [*nova_config*]
+#   (optional) Allow configuration of arbitrary Nova configurations.
+#   The value is an hash of nova_config resources. Example:
+#   { 'DEFAULT/foo' => { value => 'fooValue'},
+#     'DEFAULT/bar' => { value => 'barValue'}
+#   }
+#   In yaml format, Example:
+#   nova_config:
+#     DEFAULT/foo:
+#       value: fooValue
+#     DEFAULT/bar:
+#       value: barValue
+#
+#   NOTE: The configuration MUST NOT be already handled by this module
+#   or Puppet catalog compilation will fail with duplicate resources.
+#
+# [*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 = {},
+) {
+
+  include ::nova::deps
+
+  validate_hash($nova_config)
+  validate_hash($nova_paste_api_ini)
+
+  create_resources('nova_config', $nova_config)
+  create_resources('nova_paste_api_ini', $nova_paste_api_ini)
+}

+ 39 - 0
manifests/consoleauth.pp

@@ -0,0 +1,39 @@
+# == Class: nova::consoleauth
+#
+# Installs and configures consoleauth service
+#
+# The consoleauth service is required for vncproxy auth
+# for Horizon
+#
+# === Parameters
+#
+# [*enabled*]
+#   (optional) Whether the nova consoleauth service will be run
+#   Defaults to true
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (optional) Whether the nova consoleauth package will be installed
+#   Defaults to 'present'
+#
+class nova::consoleauth(
+  $enabled        = true,
+  $manage_service = true,
+  $ensure_package = 'present'
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  nova::generic_service { 'consoleauth':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::consoleauth_package_name,
+    service_name   => $::nova::params::consoleauth_service_name,
+    ensure_package => $ensure_package,
+  }
+
+}

+ 85 - 0
manifests/cron/archive_deleted_rows.pp

@@ -0,0 +1,85 @@
+#
+# 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'.
+#
+#  [*destination*]
+#    (optional) Path to file to which rows should be archived
+#    Defaults to '/var/log/nova/nova-rowsflush.log'.
+#
+#  [*until_complete*]
+#    (optional) Adds --until_complete to the archive command
+#    Defaults to false.
+#
+class nova::cron::archive_deleted_rows (
+  $minute      = 1,
+  $hour        = 0,
+  $monthday    = '*',
+  $month       = '*',
+  $weekday     = '*',
+  $max_rows    = '100',
+  $user        = 'nova',
+  $destination = '/var/log/nova/nova-rowsflush.log',
+  $until_complete = false,
+) {
+
+  include ::nova::deps
+
+  if $until_complete {
+    $until_complete_real = '--until_complete'
+  }
+
+  cron { 'nova-manage db archive_deleted_rows':
+    command     => "nova-manage db archive_deleted_rows --max_rows ${max_rows} ${until_complete_real} >>${destination} 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     => Anchor['nova::dbsync::end']
+  }
+}

+ 154 - 0
manifests/db.pp

@@ -0,0 +1,154 @@
+#
+# 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_db_max_retries*]
+#   (optional) Maximum retries in case of connection error or deadlock error
+#   before error is raised. Set to -1 to specify an infinite retry count.
+#   Defaults to $::os_service_default
+#
+# [*database_connection*]
+#   (optional) Connection url to connect to nova database.
+#   Defaults to $::os_service_default
+#
+# [*slave_connection*]
+#   (optional) Connection url to connect to nova slave database (read-only).
+#   Defaults to $::os_service_default
+#
+# [*api_database_connection*]
+#   (optional) Connection url to connect to nova api database.
+#   Defaults to $::os_service_default
+#
+# [*api_slave_connection*]
+#   (optional) Connection url to connect to nova api slave database (read-only).
+#   Defaults to $::os_service_default
+#
+# [*placement_database_connection*]
+#   (optional) Connection url to connect to nova placement database.
+#   Defaults to $::os_service_default
+#
+# [*placement_slave_connection*]
+#   (optional) Connection url to connect to nova placement slave database (read-only).
+#   Defaults to $::os_service_default
+#
+# [*database_idle_timeout*]
+#   Timeout when db connections should be reaped.
+#   (Optional) Defaults to $::os_service_default
+#
+# [*database_min_pool_size*]
+#   Minimum number of SQL connections to keep open in a pool.
+#   (Optional) Defaults to $::os_service_default
+#
+# [*database_max_pool_size*]
+#   Maximum number of SQL connections to keep open in a pool.
+#   (Optional) Defaults to $::os_service_default
+#
+# [*database_max_retries*]
+#   Maximum db connection retries during startup.
+#   Setting -1 implies an infinite retry count.
+#   (Optional) Defaults to $::os_service_default
+#
+# [*database_retry_interval*]
+#   Interval between retries of opening a sql connection.
+#   (Optional) Defaults to $::os_service_default
+#
+# [*database_max_overflow*]
+#   If set, use this value for max_overflow with sqlalchemy.
+#   (Optional) Defaults to $::os_service_default
+#
+class nova::db (
+  $database_db_max_retries       = $::os_service_default,
+  $database_connection           = $::os_service_default,
+  $slave_connection              = $::os_service_default,
+  $api_database_connection       = $::os_service_default,
+  $api_slave_connection          = $::os_service_default,
+  $placement_database_connection = $::os_service_default,
+  $placement_slave_connection    = $::os_service_default,
+  $database_idle_timeout         = $::os_service_default,
+  $database_min_pool_size        = $::os_service_default,
+  $database_max_pool_size        = $::os_service_default,
+  $database_max_retries          = $::os_service_default,
+  $database_retry_interval       = $::os_service_default,
+  $database_max_overflow         = $::os_service_default,
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  # NOTE(spredzy): In order to keep backward compatibility we rely on the pick function
+  # to use nova::<myparam> first the nova::db::<myparam>
+  $database_connection_real = pick($::nova::database_connection, $database_connection)
+  $slave_connection_real = pick($::nova::slave_connection, $slave_connection)
+  $api_database_connection_real = pick($::nova::api_database_connection, $api_database_connection)
+  $api_slave_connection_real = pick($::nova::api_slave_connection, $api_slave_connection)
+  $placement_database_connection_real = pick($::nova::placement_database_connection, $placement_database_connection)
+  $placement_slave_connection_real = pick($::nova::placement_slave_connection, $placement_slave_connection)
+  $database_idle_timeout_real = pick($::nova::database_idle_timeout, $database_idle_timeout)
+  $database_min_pool_size_real = pick($::nova::database_min_pool_size, $database_min_pool_size)
+  $database_max_pool_size_real = pick($::nova::database_max_pool_size, $database_max_pool_size)
+  $database_max_retries_real = pick($::nova::database_max_retries, $database_max_retries)
+  $database_retry_interval_real = pick($::nova::database_retry_interval, $database_retry_interval)
+  $database_max_overflow_real = pick($::nova::database_max_overflow, $database_max_overflow)
+
+  if !is_service_default($database_connection_real) {
+
+    validate_re($database_connection_real,
+      '^(sqlite|mysql(\+pymysql)?|postgresql):\/\/(\S+:\S+@\S+\/\S+)?')
+
+    oslo::db { 'nova_config':
+      db_max_retries   => $database_db_max_retries,
+      connection       => $database_connection_real,
+      idle_timeout     => $database_idle_timeout_real,
+      min_pool_size    => $database_min_pool_size_real,
+      max_pool_size    => $database_max_pool_size_real,
+      max_retries      => $database_max_retries_real,
+      retry_interval   => $database_retry_interval_real,
+      max_overflow     => $database_max_overflow_real,
+      slave_connection => $slave_connection_real,
+    }
+  }
+
+  if !is_service_default($api_database_connection_real) {
+
+    validate_re($api_database_connection_real,
+      '^(sqlite|mysql(\+pymysql)?|postgresql):\/\/(\S+:\S+@\S+\/\S+)?')
+
+    nova_config {
+      'api_database/connection':       value => $api_database_connection_real, secret => true;
+      'api_database/slave_connection': value => $api_slave_connection_real, secret => true;
+    }
+
+  }
+
+  if !is_service_default($placement_database_connection_real) {
+
+    validate_re($placement_database_connection_real,
+      '^(sqlite|mysql(\+pymysql)?|postgresql):\/\/(\S+:\S+@\S+\/\S+)?')
+
+    nova_config {
+      'placement_database/connection':       value => $placement_database_connection_real, secret => true;
+      'placement_database/slave_connection': value => $placement_slave_connection_real, secret => true;
+    }
+
+  }
+
+}

+ 82 - 0
manifests/db/mysql.pp

@@ -0,0 +1,82 @@
+# == Class: nova::db::mysql
+#
+# Class that configures mysql for nova
+#
+# === Parameters:
+#
+# [*password*]
+#   Password to use for the nova user
+#
+# [*dbname*]
+#   (optional) The name of the database
+#   Defaults to 'nova'
+#
+# [*user*]
+#   (optional) The mysql user to create
+#   Defaults to 'nova'
+#
+# [*host*]
+#   (optional) The IP address of the mysql server
+#   Defaults to '127.0.0.1'
+#
+# [*charset*]
+#   (optional) The charset to use for the nova database
+#   Defaults to 'utf8'
+#
+# [*collate*]
+#   (optional) The collate to use for the nova database
+#   Defaults to 'utf8_general_ci'
+#
+# [*allowed_hosts*]
+#   (optional) Additional hosts that are allowed to access this DB
+#   Defaults to undef
+#
+# [*setup_cell0*]
+#   (optional) Setup a cell0 for the cell_v2 functionality. This option will
+#   be set to true by default in Ocata when the cell v2 setup is mandatory.
+#   Defaults to false
+#
+
+class nova::db::mysql(
+  $password,
+  $dbname        = 'nova',
+  $user          = 'nova',
+  $host          = '127.0.0.1',
+  $charset       = 'utf8',
+  $collate       = 'utf8_general_ci',
+  $allowed_hosts = undef,
+  $setup_cell0   = true,
+) {
+
+  include ::nova::deps
+
+  $setup_cell0_real = pick($::nova::db::mysql_api::setup_cell0, $setup_cell0)
+
+  ::openstacklib::db::mysql { 'nova':
+    user          => $user,
+    password_hash => mysql_password($password),
+    dbname        => $dbname,
+    host          => $host,
+    charset       => $charset,
+    collate       => $collate,
+    allowed_hosts => $allowed_hosts,
+  }
+
+  if $setup_cell0_real {
+    # need for cell_v2
+    ::openstacklib::db::mysql { 'nova_cell0':
+      user          => $user,
+      password_hash => mysql_password($password),
+      dbname        => "${dbname}_cell0",
+      host          => $host,
+      charset       => $charset,
+      collate       => $collate,
+      allowed_hosts => $allowed_hosts,
+      create_user   => false,
+    }
+  }
+
+  Anchor['nova::db::begin']
+  ~> Class['nova::db::mysql']
+  ~> Anchor['nova::db::end']
+}

+ 74 - 0
manifests/db/mysql_api.pp

@@ -0,0 +1,74 @@
+# == Class: nova::db::mysql_api
+#
+# Class that configures mysql for the nova_api database.
+#
+# === Parameters:
+#
+# [*password*]
+#   Password to use for the nova user
+#
+# [*dbname*]
+#   (optional) The name of the database
+#   Defaults to 'nova_api'
+#
+# [*user*]
+#   (optional) The mysql user to create
+#   Defaults to 'nova_api'
+#
+# [*host*]
+#   (optional) The IP address of the mysql server
+#   Defaults to '127.0.0.1'
+#
+# [*charset*]
+#   (optional) The charset to use for the nova database
+#   Defaults to 'utf8'
+#
+# [*collate*]
+#   (optional) The collate to use for the nova database
+#   Defaults to 'utf8_general_ci'
+#
+# [*allowed_hosts*]
+#   (optional) Additional hosts that are allowed to access this DB
+#   Defaults to undef
+#
+# === DEPRECATED
+#
+# TODO(aschultz): we can just remove this after tripleo gets fixed to use
+# the new param
+# [*setup_cell0*]
+#   (optional) Setup a cell0 for the cell_v2 functionality. This option will
+#   be set to true by default in Ocata when the cell v2 setup is mandatory.
+#   Defaults to undef
+#
+class nova::db::mysql_api(
+  $password,
+  $dbname        = 'nova_api',
+  $user          = 'nova_api',
+  $host          = '127.0.0.1',
+  $charset       = 'utf8',
+  $collate       = 'utf8_general_ci',
+  $allowed_hosts = undef,
+  # DEPREACTED
+  $setup_cell0   = undef
+) {
+
+  if $setup_cell0 {
+    warning('nova::db::mysql_api::setup_cell0 is deprecated, use nova::db::mysql::setup_cell0 instead. This will be removed in Pike')
+  }
+
+  include ::nova::deps
+
+  ::openstacklib::db::mysql { 'nova_api':
+    user          => $user,
+    password_hash => mysql_password($password),
+    dbname        => $dbname,
+    host          => $host,
+    charset       => $charset,
+    collate       => $collate,
+    allowed_hosts => $allowed_hosts,
+  }
+
+  Anchor['nova::db::begin']
+  ~> Class['nova::db::mysql_api']
+  ~> Anchor['nova::db::end']
+}

+ 59 - 0
manifests/db/mysql_placement.pp

@@ -0,0 +1,59 @@
+# == Class: nova::db::mysql_placement
+#
+# Class that configures mysql for the nova_placement database.
+#
+# === Parameters:
+#
+# [*password*]
+#   Password to use for the nova user
+#
+# [*dbname*]
+#   (optional) The name of the database
+#   Defaults to 'nova_placement'
+#
+# [*user*]
+#   (optional) The mysql user to create
+#   Defaults to 'nova_placement'
+#
+# [*host*]
+#   (optional) The IP address of the mysql server
+#   Defaults to '127.0.0.1'
+#
+# [*charset*]
+#   (optional) The charset to use for the nova database
+#   Defaults to 'utf8'
+#
+# [*collate*]
+#   (optional) The collate to use for the nova database
+#   Defaults to 'utf8_general_ci'
+#
+# [*allowed_hosts*]
+#   (optional) Additional hosts that are allowed to access this DB
+#   Defaults to undef
+#
+class nova::db::mysql_placement(
+  $password,
+  $dbname        = 'nova_placement',
+  $user          = 'nova_placement',
+  $host          = '127.0.0.1',
+  $charset       = 'utf8',
+  $collate       = 'utf8_general_ci',
+  $allowed_hosts = undef,
+) {
+
+  include ::nova::deps
+
+  ::openstacklib::db::mysql { 'nova_placement':
+    user          => $user,
+    password_hash => mysql_password($password),
+    dbname        => $dbname,
+    host          => $host,
+    charset       => $charset,
+    collate       => $collate,
+    allowed_hosts => $allowed_hosts,
+  }
+
+  Anchor['nova::db::begin']
+  ~> Class['nova::db::mysql_placement']
+  ~> Anchor['nova::db::end']
+}

+ 39 - 0
manifests/db/online_data_migrations.pp

@@ -0,0 +1,39 @@
+#
+# Class to execute nova api_db sync
+#
+# ==Parameters
+#
+# [*extra_params*]
+#   (optional) String of extra command line parameters to append
+#   to the nova-manage db sync command. These will be inserted in
+#   the command line between 'nova-manage' and 'db sync'.
+#   Defaults to undef
+#
+# [*db_sync_timeout*]
+#   (optional) Timeout for the execution of the db_sync
+#   Defaults to 300.
+#
+class nova::db::online_data_migrations(
+  $extra_params    = undef,
+  $db_sync_timeout = 300,
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  exec { 'nova-db-online-data-migrations':
+    command     => "/usr/bin/nova-manage ${extra_params} db online_data_migrations",
+    refreshonly => true,
+    try_sleep   => 5,
+    tries       => 10,
+    timeout     => $db_sync_timeout,
+    logoutput   => on_failure,
+    subscribe   => [
+      Anchor['nova::install::end'],
+      Anchor['nova::config::end'],
+      Anchor['nova::dbsync_api::end'],
+      Anchor['nova::db_online_data_migrations::begin']
+    ],
+    notify      => Anchor['nova::db_online_data_migrations::end'],
+  }
+}

+ 48 - 0
manifests/db/postgresql.pp

@@ -0,0 +1,48 @@
+# == Class: nova::db::postgresql
+#
+# Class that configures postgresql for nova
+# Requires the Puppetlabs postgresql module.
+#
+# === Parameters
+#
+# [*password*]
+#   (Required) Password to connect to the database.
+#
+# [*dbname*]
+#   (Optional) Name of the database.
+#   Defaults to 'nova'.
+#
+# [*user*]
+#   (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',
+  $encoding   = undef,
+  $privileges = 'ALL',
+) {
+
+  include ::nova::deps
+
+  ::openstacklib::db::postgresql { 'nova':
+    password_hash => postgresql_password($user, $password),
+    dbname        => $dbname,
+    user          => $user,
+    encoding      => $encoding,
+    privileges    => $privileges,
+  }
+
+  Anchor['nova::db::begin']
+  ~> Class['nova::db::postgresql']
+  ~> Anchor['nova::db::end']
+}

+ 48 - 0
manifests/db/postgresql_api.pp

@@ -0,0 +1,48 @@
+# == Class: nova::db::postgresql_api
+#
+# Class that configures postgresql for the nova_api database.
+# Requires the Puppetlabs postgresql module.
+#
+# === Parameters
+#
+# [*password*]
+#   (Required) Password to connect to the database.
+#
+# [*dbname*]
+#   (Optional) Name of the database.
+#   Defaults to 'nova_api'.
+#
+# [*user*]
+#   (Optional) User to connect to the database.
+#   Defaults to 'nova_api'.
+#
+#  [*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_api(
+  $password,
+  $dbname     = 'nova_api',
+  $user       = 'nova_api',
+  $encoding   = undef,
+  $privileges = 'ALL',
+) {
+
+  include ::nova::deps
+
+  ::openstacklib::db::postgresql { 'nova_api':
+    password_hash => postgresql_password($user, $password),
+    dbname        => $dbname,
+    user          => $user,
+    encoding      => $encoding,
+    privileges    => $privileges,
+  }
+
+  Anchor['nova::db::begin']
+  ~> Class['nova::db::postgresql_api']
+  ~> Anchor['nova::db::end']
+}

+ 39 - 0
manifests/db/sync.pp

@@ -0,0 +1,39 @@
+#
+# Class to execute nova dbsync
+#
+# ==Parameters
+#
+# [*extra_params*]
+#   (optional) String of extra command line parameters to append
+#   to the nova-manage db sync command. These will be inserted in
+#   the command line between 'nova-manage' and 'db sync'.
+#   Defaults to undef
+#
+# [*db_sync_timeout*]
+#   (optional) Timeout for the execution of the db_sync
+#   Defaults to 300
+#
+class nova::db::sync(
+  $extra_params    = undef,
+  $db_sync_timeout = 300,
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  exec { 'nova-db-sync':
+    command     => "/usr/bin/nova-manage ${extra_params} db sync",
+    refreshonly => true,
+    try_sleep   => 5,
+    tries       => 10,
+    timeout     => $db_sync_timeout,
+    logoutput   => on_failure,
+    subscribe   => [
+      Anchor['nova::install::end'],
+      Anchor['nova::config::end'],
+      Anchor['nova::db::end'],
+      Anchor['nova::dbsync::begin']
+    ],
+    notify      => Anchor['nova::dbsync::end'],
+  }
+}

+ 52 - 0
manifests/db/sync_api.pp

@@ -0,0 +1,52 @@
+#
+# Class to execute nova api_db sync
+#
+# ==Parameters
+#
+# [*extra_params*]
+#   (optional) String of extra command line parameters to append
+#   to the nova-manage db sync command. These will be inserted in
+#   the command line between 'nova-manage' and 'db sync'.
+#   Defaults to undef
+#
+# [*cellv2_setup*]
+#   (optional) This flag toggles if we preform a minimal cell_v2 setup of a
+#   a single cell.
+#   NOTE: 'nova-manage cell_v2 discover_hosts' must be
+#   run after any nova-compute hosts have been deployed.
+#   This flag will be set to true in Ocata when the cell v2 setup is mandatory.
+#   Defaults to false.
+#
+# [*db_sync_timeout*]
+#   (optional) Timeout for the execution of the db_sync
+#   Defaults to 300.
+#
+class nova::db::sync_api(
+  $extra_params    = undef,
+  $cellv2_setup    = false,
+  $db_sync_timeout = 300,
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  exec { 'nova-db-sync-api':
+    command     => "/usr/bin/nova-manage ${extra_params} api_db sync",
+    refreshonly => true,
+    try_sleep   => 5,
+    tries       => 10,
+    timeout     => $db_sync_timeout,
+    logoutput   => on_failure,
+    subscribe   => [
+      Anchor['nova::install::end'],
+      Anchor['nova::config::end'],
+      Anchor['nova::db::end'],
+      Anchor['nova::dbsync_api::begin']
+    ],
+    notify      => Anchor['nova::dbsync_api::end'],
+  }
+
+  if $cellv2_setup {
+    include ::nova::cell_v2::simple_setup
+  }
+}

+ 118 - 0
manifests/deps.pp

@@ -0,0 +1,118 @@
+# == Class: nova::deps
+#
+#  Nova anchors and dependency management
+#
+class nova::deps {
+  # Setup anchors for install, config and service phases of the module.  These
+  # anchors allow external modules to hook the begin and end of any of these
+  # phases.  Package or service management can also be replaced by ensuring the
+  # package is absent or turning off service management and having the
+  # replacement depend on the appropriate anchors.  When applicable, end tags
+  # should be notified so that subscribers can determine if installation,
+  # config or service state changed and act on that if needed.
+  anchor { 'nova::install::begin': }
+  -> Package<| tag == 'nova-package'|>
+  ~> anchor { 'nova::install::end': }
+  -> anchor { 'nova::config::begin': }
+  -> Nova_config<||>
+  ~> anchor { 'nova::config::end': }
+  -> anchor { 'nova::db::begin': }
+  -> anchor { 'nova::db::end': }
+  ~> anchor { 'nova::service::begin': }
+  ~> Service<| tag == 'nova-service' |>
+  ~> anchor { 'nova::service::end': }
+
+  # paste-api.ini config shold occur in the config block also.
+  Anchor['nova::config::begin']
+  -> Nova_paste_api_ini<||>
+  ~> Anchor['nova::config::end']
+
+  # Support packages need to be installed in the install phase, but we don't
+  # put them in the chain above because we don't want any false dependencies
+  # between packages with the nova-package tag and the nova-support-package
+  # tag.  Note: the package resources here will have a 'before' relationshop on
+  # the nova::install::end anchor.  The line between nova-support-package and
+  # nova-package should be whether or not Nova services would need to be
+  # restarted if the package state was changed.
+  Anchor['nova::install::begin']
+  -> Package<| tag == 'nova-support-package'|>
+  -> Anchor['nova::install::end']
+
+  # TODO(aschultz): check if we can remove these as I think they are no longer
+  # valid since nova_cells is replaced by cell_v2 and the others are part of
+  # nova network
+  # The following resourcs are managed by calling 'nova manage' and so the
+  # database must be provisioned before they can be applied.
+  Anchor['nova::dbsync_api::end']
+  -> Nova_cells<||>
+  Anchor['nova::dbsync::end']
+  -> Nova_cells<||>
+  Anchor['nova::dbsync_api::end']
+  -> Nova_floating<||>
+  Anchor['nova::dbsync::end']
+  -> Nova_floating<||>
+  Anchor['nova::dbsync_api::end']
+  -> Nova_network<||>
+  Anchor['nova::dbsync::end']
+  -> Nova_network<||>
+
+  # all db settings should be applied and all packages should be installed
+  # before dbsync starts
+  Oslo::Db<||> -> Anchor['nova::dbsync::begin']
+
+  # Installation or config changes will always restart services.
+  Anchor['nova::install::end'] ~> Anchor['nova::service::begin']
+  Anchor['nova::config::end']  ~> Anchor['nova::service::begin']
+
+  # This is here for backwards compatability for any external users of the
+  # nova-start anchor.  This should be considered deprecated and removed in the
+  # N cycle
+  anchor { 'nova-start':
+    require => Anchor['nova::install::end'],
+    before  => Anchor['nova::config::begin'],
+  }
+
+  #############################################################################
+  # NOTE(aschultz): these are defined here because this syntax allows us
+  # to override the subscribe/notify order using the spaceship operator.
+  # The ->/~> does not seem to be able to be updated after the fact. Since
+  # we have to flip cell v2 ordering for the N->O upgrade process, we need
+  # to not use the chaining arrows. ugh.
+  #############################################################################
+  # Wedge this in after the db creation and before the services
+  anchor { 'nova::dbsync_api::begin':
+    subscribe => Anchor['nova::db::end']
+  } ->
+  anchor { 'nova::dbsync_api::end':
+    notify => Anchor['nova::service::begin'],
+  }
+
+  # Wedge this after db creation and api sync but before the services
+  anchor { 'nova::dbsync::begin':
+    subscribe => [
+      Anchor['nova::db::end'],
+      Anchor['nova::dbsync_api::end']
+    ]
+  } ->
+  anchor { 'nova::dbsync::end':
+    notify => Anchor['nova::service::begin']
+  }
+
+  # Wedge cell_v2 put this between api sync and db sync by default but can
+  # be overridden using the spaceship operator to move it around when needed
+  anchor { 'nova::cell_v2::begin':
+    subscribe => Anchor['nova::dbsync_api::end']
+  } ->
+  Nova::Cell_v2::Cell<||> ~>
+  anchor { 'nova::cell_v2::end':
+    notify => Anchor['nova::dbsync::begin']
+  }
+
+  # Wedge online data migrations after db/api_sync and before service
+  anchor { 'nova::db_online_data_migrations::begin':
+    subscribe => Anchor['nova::dbsync_api::end']
+  } ->
+  anchor { 'nova::db_online_data_migrations::end':
+    notify => Anchor['nova::service::begin']
+  }
+}

+ 75 - 0
manifests/generic_service.pp

@@ -0,0 +1,75 @@
+# == Define: nova::generic_service
+#
+# This defined type implements basic nova services.
+# It is introduced to attempt to consolidate
+# common code.
+#
+# It also allows users to specify ad-hoc services
+# as needed
+#
+# This define creates a service resource with title nova-${name} and
+# conditionally creates a package resource with title nova-${name}
+#
+# === Parameters:
+#
+# [*package_name*]
+#   (mandatory) The package name (for the generic_service)
+#
+# [*service_name*]
+#   (mandatory) The service name (for the generic_service)
+#
+# [*enabled*]
+#   (optional) Define if the service must be enabled or not
+#   Defaults to false.
+#
+# [*manage_service*]
+#   (optional) Manage or not the service (if a service_name is provided).
+#   Defaults to true.
+#
+# [*ensure_package*]
+#   (optional) Control the ensure parameter for the package ressource.
+#   Defaults to 'present'.
+#
+define nova::generic_service(
+  $package_name,
+  $service_name,
+  $enabled        = true,
+  $manage_service = true,
+  $ensure_package = 'present'
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  $nova_title = "nova-${name}"
+
+  # I need to mark that ths package should be
+  # installed before nova_config
+  if ($package_name) {
+    if !defined(Package[$nova_title]) and !defined(Package[$package_name]) {
+      package { $nova_title:
+        ensure => $ensure_package,
+        name   => $package_name,
+        tag    => ['openstack', 'nova-package'],
+      }
+    }
+  }
+
+  if $service_name {
+    if $manage_service {
+      if $enabled {
+        $service_ensure = 'running'
+      } else {
+        $service_ensure = 'stopped'
+      }
+    }
+
+    service { $nova_title:
+      ensure    => $service_ensure,
+      name      => $service_name,
+      enable    => $enabled,
+      hasstatus => true,
+      tag       => 'nova-service',
+    }
+  }
+}

+ 779 - 0
manifests/init.pp

@@ -0,0 +1,779 @@
+# == Class: nova
+#
+# This class is used to specify configuration parameters that are common
+# across all nova services.
+#
+# === Parameters:
+#
+# [*ensure_package*]
+#   (optional) The state of nova packages
+#   Defaults to 'present'
+#
+# [*database_connection*]
+#   (optional) Connection url for the nova database.
+#   Defaults to undef.
+#
+# [*slave_connection*]
+#   (optional) Connection url to connect to nova slave database (read-only).
+#   Defaults to undef.
+#
+# [*api_database_connection*]
+#   (optional) Connection url for the nova API database.
+#   Defaults to undef.
+#
+# [*api_slave_connection*]
+#   (optional) Connection url to connect to nova API slave database (read-only).
+#   Defaults to undef.
+#
+# [*placement_database_connection*]
+#   (optional) Connection url for the nova placement database.
+#   Defaults to undef.
+#
+# [*placement_slave_connection*]
+#   (optional) Connection url to connect to nova placement slave database (read-only).
+#   Defaults to undef.
+#
+# [*database_max_retries*]
+#   (optional) Maximum database connection retries during startup.
+#   Defaults to undef.
+#
+# [*database_idle_timeout*]
+#   (optional) Timeout before idle database connections are reaped.
+#   Defaults to undef.
+#
+# [*database_retry_interval*]
+#   (optional) Interval between retries of opening a database connection.
+#   Defaults to undef.
+#
+# [*database_min_pool_size*]
+#   (optional) Minimum number of SQL connections to keep open in a pool.
+#   Defaults to undef.
+#
+# [*database_max_pool_size*]
+#   (optional) Maximum number of SQL connections to keep open in a pool.
+#   Defaults to undef.
+#
+# [*database_max_overflow*]
+#   (optional) If set, use this value for max_overflow with sqlalchemy.
+#   Defaults to: undef.
+#
+# [*default_transport_url*]
+#    (optional) A URL representing the messaging driver to use and its full
+#    configuration. Transport URLs take the form:
+#      transport://user:pass@host1:port[,hostN:portN]/virtual_host
+#    Defaults to $::os_service_default
+#
+# [*rpc_response_timeout*]
+#   (Optional) Seconds to wait for a response from a call. (integer value)
+#   Defaults to $::os_service_default.
+#
+# [*rpc_backend*]
+#   (optional) The rpc backend implementation to use, can be:
+#     rabbit (for rabbitmq)
+#     zmq (for zeromq)
+#   Defaults to $::os_service_default
+#
+# [*image_service*]
+#   (optional) Service used to search for and retrieve images.
+#   Defaults to 'nova.image.glance.GlanceImageService'
+#
+# [*glance_api_servers*]
+#   (optional) List of addresses for api servers.
+#   Defaults to 'http://localhost:9292'
+#
+# [*rabbit_use_ssl*]
+#   (optional) Boolean. Connect over SSL for RabbitMQ. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_ha_queues*]
+#   (optional) Use HA queues in RabbitMQ. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_heartbeat_timeout_threshold*]
+#   (optional) Number of seconds after which the RabbitMQ broker is considered
+#   down if the heartbeat keepalive fails.  Any value >0 enables heartbeats.
+#   Heartbeating helps to ensure the TCP connection to RabbitMQ isn't silently
+#   closed, resulting in missed or lost messages from the queue.
+#   Requires kombu >= 3.0.7 and amqp >= 1.4.0. (integer value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_heartbeat_rate*]
+#   (optional) How often during the rabbit_heartbeat_timeout_threshold period
+#   to check the heartbeat on RabbitMQ connection.
+#   i.e. rabbit_heartbeat_rate=2 when rabbit_heartbeat_timeout_threshold=60,
+#   the heartbeat will be checked every 30 seconds. (integer value)
+#   Defaults to $::os_service_default
+#
+# [*kombu_ssl_ca_certs*]
+#   (optional) SSL certification authority file (valid only if SSL enabled).
+#   (string value)
+#   Defaults to $::os_service_default
+#
+# [*kombu_ssl_certfile*]
+#   (optional) SSL cert file (valid only if SSL enabled). (string value)
+#   Defaults to $::os_service_default
+#
+# [*kombu_ssl_keyfile*]
+#   (optional) SSL key file (valid only if SSL enabled). (string value)
+#   Defaults to $::os_service_default
+#
+# [*kombu_ssl_version*]
+#   (optional) SSL version to use (valid only if SSL enabled).
+#   Valid values are TLSv1, SSLv23 and SSLv3. SSLv2 may be
+#   available on some distributions. (string value)
+#   Defaults to $::os_service_default
+#
+# [*kombu_reconnect_delay*]
+#   (optional) How long to wait before reconnecting in response to an AMQP
+#   consumer cancel notification. (floating point value)
+#   Defaults to $::os_service_default
+#
+# [*kombu_compression*]
+#   (optional) Possible values are: gzip, bz2. If not set compression will not
+#   be used. This option may notbe available in future versions. EXPERIMENTAL.
+#   (string value)
+#   Defaults to $::os_service_default
+#
+# [*amqp_durable_queues*]
+#   (optional) Define queues as "durable" to rabbitmq. (boolean value)
+#   Defaults to $::os_service_default
+#
+# [*amqp_server_request_prefix*]
+#   (Optional) Address prefix used when sending to a specific server
+#   Defaults to $::os_service_default.
+#
+# [*amqp_broadcast_prefix*]
+#   (Optional) address prefix used when broadcasting to all servers
+#   Defaults to $::os_service_default.
+#
+# [*amqp_group_request_prefix*]
+#   (Optional) address prefix when sending to any server in group
+#   Defaults to $::os_service_default.
+#
+# [*amqp_container_name*]
+#   (Optional) Name for the AMQP container
+#   Defaults to $::os_service_default.
+#
+# [*amqp_idle_timeout*]
+#   (Optional) Timeout for inactive connections
+#   Defaults to $::os_service_default.
+#
+# [*amqp_trace*]
+#   (Optional) Debug: dump AMQP frames to stdout
+#   Defaults to $::os_service_default.
+#
+# [*amqp_ssl_ca_file*]
+#   (Optional) CA certificate PEM file to verify server certificate
+#   Defaults to $::os_service_default.
+#
+# [*amqp_ssl_cert_file*]
+#   (Optional) Identifying certificate PEM file to present to clients
+#   Defaults to $::os_service_default.
+#
+# [*amqp_ssl_key_file*]
+#   (Optional) Private key PEM file used to sign cert_file certificate
+#   Defaults to $::os_service_default.
+#
+# [*amqp_ssl_key_password*]
+#   (Optional) Password for decrypting ssl_key_file (if encrypted)
+#   Defaults to $::os_service_default.
+#
+# [*amqp_allow_insecure_clients*]
+#   (Optional) Accept clients using either SSL or plain TCP
+#   Defaults to $::os_service_default.
+#
+# [*amqp_sasl_mechanisms*]
+#   (Optional) Space separated list of acceptable SASL mechanisms
+#   Defaults to $::os_service_default.
+#
+# [*amqp_sasl_config_dir*]
+#   (Optional) Path to directory that contains the SASL configuration
+#   Defaults to $::os_service_default.
+#
+# [*amqp_sasl_config_name*]
+#   (Optional) Name of configuration file (without .conf suffix)
+#   Defaults to $::os_service_default.
+#
+# [*amqp_username*]
+#   (Optional) User name for message broker authentication
+#   Defaults to $::os_service_default.
+#
+# [*amqp_password*]
+#   (Optional) Password for message broker authentication
+#   Defaults to $::os_service_default.
+#
+# [*host*]
+#   (Optional) Name of this node. This is typically a hostname, FQDN, or
+#   IP address.
+#   Defaults to $::os_service_default.
+#
+# [*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
+#
+# [*log_dir*]
+#   (optional) Directory where logs should be stored.
+#   If set to $::os_service_default, it will not log to any directory.
+#   Defaults to undef
+#
+# [*state_path*]
+#   (optional) Directory for storing state.
+#   Defaults to '/var/lib/nova'
+#
+# [*lock_path*]
+#   (optional) Directory for lock files.
+#   On RHEL will be '/var/lib/nova/tmp' and on Debian '/var/lock/nova'
+#   Defaults to $::nova::params::lock_path
+#
+# [*debug*]
+#   (optional) Set log output to debug output.
+#   Defaults to undef
+#
+# [*periodic_interval*]
+#   (optional) Seconds between running periodic tasks.
+#   Defaults to '60'
+#
+# [*report_interval*]
+#   (optional) Interval at which nodes report to data store.
+#    Defaults to '10'
+#
+# [*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
+#   Defaults to undef
+#
+# [*use_stderr*]
+#   (optional) Use stderr for logging
+#   Defaults to undef
+#
+# [*log_facility*]
+#   (optional) Syslog facility to receive log lines.
+#   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 : '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.
+#   Expects a hash of the form { type => 'key-type', key => 'key-data' } where
+#   'key-type' is one of (ssh-rsa, ssh-dsa, ssh-ecdsa) and 'key-data' is the
+#   actual key data (e.g, 'AAAA...').
+#
+# [*nova_private_key*]
+#   (optional) Install private key into .ssh/id_rsa (or appropriate equivalent
+#   for key type).  Expects a hash of the form { type => 'key-type', key =>
+#   '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.
+#
+# [*notification_transport_url*]
+#   (optional) A URL representing the messaging driver to use for notifications
+#   and its full configuration. Transport URLs take the form:
+#     transport://user:pass@host1:port[,hostN:portN]/virtual_host
+#   Defaults to $::os_service_default
+#
+# [*notification_driver*]
+#   (optional) Driver or drivers to handle sending notifications.
+#   Value can be a string or a list.
+#   Defaults to $::os_service_default.
+#
+# [*notification_topics*]
+#   (optional) AMQP topic used for OpenStack notifications
+#   Defaults to ::os_service_default
+#
+# [*notify_api_faults*]
+#   (optional) If set, send api.fault notifications on caught
+#   exceptions in the API service
+#   Defaults to false
+#
+# [*notify_on_state_change*]
+#   (optional) If set, send compute.instance.update notifications
+#   on instance state changes. Valid values are None for no notifications,
+#   "vm_state" for notifications on VM state changes, or "vm_and_task_state"
+#   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 $::os_service_default
+#
+# [*cinder_catalog_info*]
+#   (optional) Info to match when looking for cinder in the service
+#   catalog. Format is: separated values of the form:
+#   <service_type>:<service_name>:<endpoint_type>
+#   Defaults to 'volumev2:cinderv2:publicURL'
+#
+# [*upgrade_level_cells*]
+#  (optional) Sets a version cap for messages sent to local cells services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_cert*]
+#  (optional) Sets a version cap for messages sent to cert services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_compute*]
+#  (optional) Sets a version cap for messages sent to compute services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_conductor*]
+#  (optional) Sets a version cap for messages sent to conductor services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_console*]
+#  (optional) Sets a version cap for messages sent to console services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_consoleauth*]
+#  (optional) Sets a version cap for messages sent to consoleauth services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_intercell*]
+#  (optional) Sets a version cap for messages sent between cells services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_network*]
+#  (optional) Sets a version cap for messages sent to network services
+#  Defaults to $::os_service_default
+#
+# [*upgrade_level_scheduler*]
+#  (optional) Sets a version cap for messages sent to scheduler services
+#  Defaults to $::os_service_default
+#
+# [*use_ipv6*]
+#   (optional) Use IPv6 or not.
+#   Defaults to $::os_service_default
+#
+# [*purge_config*]
+#   (optional) Whether to set only the specified config options
+#   in the nova config.
+#   Defaults to false.
+#
+# [*block_device_allocate_retries*]
+#   (optional) Number of times to retry block device allocation on failures
+#   Defaults to $::os_service_default
+#
+# [*block_device_allocate_retries_interval*]
+#   (optional) Waiting time interval (seconds) between block device allocation
+#   retries on failures
+#   Defaults to $::os_service_default
+#
+# [*cpu_allocation_ratio*]
+#   (optional) Virtual CPU to physical CPU allocation ratio which affects all
+#   CPU filters.  This can be set on the scheduler, or can be overridden
+#   per compute node.
+#   Defaults to $::os_service_default
+#
+# [*ram_allocation_ratio*]
+#   (optional) Virtual ram to physical ram allocation ratio which affects all
+#   ram filters. This can be set on the scheduler, or can be overridden
+#   per compute node.
+#   Defaults to $::os_service_default
+#
+# [*disk_allocation_ratio*]
+#   (optional) Virtual disk to physical disk allocation ratio which is used
+#   by the disk filter. This can be set on the scheduler, or can be overridden
+#   per compute node.
+#   Defaults to $::os_service_default
+#
+# DEPRECATED PARAMETERS
+#
+# [*rabbit_host*]
+#   (optional) Location of rabbitmq installation. (string value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_hosts*]
+#   (optional) List of clustered rabbit servers. (string value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_port*]
+#   (optional) Port for rabbitmq instance. (port value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_password*]
+#   (optional) Password used to connect to rabbitmq. (string value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_userid*]
+#   (optional) User used to connect to rabbitmq. (string value)
+#   Defaults to $::os_service_default
+#
+# [*rabbit_virtual_host*]
+#   (optional) The RabbitMQ virtual host. (string value)
+#   Defaults to $::os_service_default
+#
+class nova(
+  $ensure_package                         = 'present',
+  $database_connection                    = undef,
+  $slave_connection                       = undef,
+  $api_database_connection                = undef,
+  $api_slave_connection                   = undef,
+  $placement_database_connection          = undef,
+  $placement_slave_connection             = undef,
+  $block_device_allocate_retries          = $::os_service_default,
+  $block_device_allocate_retries_interval = $::os_service_default,
+  $database_idle_timeout                  = undef,
+  $database_min_pool_size                 = undef,
+  $database_max_pool_size                 = undef,
+  $database_max_retries                   = undef,
+  $database_retry_interval                = undef,
+  $database_max_overflow                  = undef,
+  $default_transport_url                  = $::os_service_default,
+  $rpc_response_timeout                   = $::os_service_default,
+  $rpc_backend                            = $::os_service_default,
+  $image_service                          = 'nova.image.glance.GlanceImageService',
+  # these glance params should be optional
+  # this should probably just be configured as a glance client
+  $glance_api_servers                     = 'http://localhost:9292',
+  $rabbit_use_ssl                         = $::os_service_default,
+  $rabbit_heartbeat_timeout_threshold     = $::os_service_default,
+  $rabbit_heartbeat_rate                  = $::os_service_default,
+  $rabbit_ha_queues                       = $::os_service_default,
+  $kombu_ssl_ca_certs                     = $::os_service_default,
+  $kombu_ssl_certfile                     = $::os_service_default,
+  $kombu_ssl_keyfile                      = $::os_service_default,
+  $kombu_ssl_version                      = $::os_service_default,
+  $kombu_reconnect_delay                  = $::os_service_default,
+  $kombu_compression                      = $::os_service_default,
+  $amqp_durable_queues                    = $::os_service_default,
+  $amqp_server_request_prefix             = $::os_service_default,
+  $amqp_broadcast_prefix                  = $::os_service_default,
+  $amqp_group_request_prefix              = $::os_service_default,
+  $amqp_container_name                    = $::os_service_default,
+  $amqp_idle_timeout                      = $::os_service_default,
+  $amqp_trace                             = $::os_service_default,
+  $amqp_ssl_ca_file                       = $::os_service_default,
+  $amqp_ssl_cert_file                     = $::os_service_default,
+  $amqp_ssl_key_file                      = $::os_service_default,
+  $amqp_ssl_key_password                  = $::os_service_default,
+  $amqp_allow_insecure_clients            = $::os_service_default,
+  $amqp_sasl_mechanisms                   = $::os_service_default,
+  $amqp_sasl_config_dir                   = $::os_service_default,
+  $amqp_sasl_config_name                  = $::os_service_default,
+  $amqp_username                          = $::os_service_default,
+  $amqp_password                          = $::os_service_default,
+  $host                                   = $::os_service_default,
+  $auth_strategy                          = 'keystone',
+  $service_down_time                      = 60,
+  $log_dir                                = undef,
+  $state_path                             = '/var/lib/nova',
+  $lock_path                              = $::nova::params::lock_path,
+  $debug                                  = undef,
+  $periodic_interval                      = '60',
+  $report_interval                        = '10',
+  $rootwrap_config                        = '/etc/nova/rootwrap.conf',
+  $use_ssl                                = false,
+  $enabled_ssl_apis                       = ['metadata', 'osapi_compute'],
+  $ca_file                                = false,
+  $cert_file                              = false,
+  $key_file                               = false,
+  $nova_public_key                        = undef,
+  $nova_private_key                       = undef,
+  $use_syslog                             = undef,
+  $use_stderr                             = undef,
+  $log_facility                           = undef,
+  $notification_transport_url             = $::os_service_default,
+  $notification_driver                    = $::os_service_default,
+  $notification_topics                    = $::os_service_default,
+  $notify_api_faults                      = false,
+  $notify_on_state_change                 = undef,
+  $os_region_name                         = $::os_service_default,
+  $cinder_catalog_info                    = 'volumev2:cinderv2:publicURL',
+  $upgrade_level_cells                    = $::os_service_default,
+  $upgrade_level_cert                     = $::os_service_default,
+  $upgrade_level_compute                  = $::os_service_default,
+  $upgrade_level_conductor                = $::os_service_default,
+  $upgrade_level_console                  = $::os_service_default,
+  $upgrade_level_consoleauth              = $::os_service_default,
+  $upgrade_level_intercell                = $::os_service_default,
+  $upgrade_level_network                  = $::os_service_default,
+  $upgrade_level_scheduler                = $::os_service_default,
+  $use_ipv6                               = $::os_service_default,
+  $cpu_allocation_ratio                   = $::os_service_default,
+  $ram_allocation_ratio                   = $::os_service_default,
+  $disk_allocation_ratio                  = $::os_service_default,
+  $purge_config                           = false,
+  # DEPRECATED PARAMETERS
+  $rabbit_host                            = $::os_service_default,
+  $rabbit_hosts                           = $::os_service_default,
+  $rabbit_password                        = $::os_service_default,
+  $rabbit_port                            = $::os_service_default,
+  $rabbit_userid                          = $::os_service_default,
+  $rabbit_virtual_host                    = $::os_service_default,
+) inherits nova::params {
+
+  include ::nova::deps
+
+  # maintain backward compatibility
+  include ::nova::db
+  include ::nova::logging
+
+  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')
+  }
+
+  if !is_service_default($rabbit_host) or
+    !is_service_default($rabbit_hosts) or
+    !is_service_default($rabbit_password) or
+    !is_service_default($rabbit_port) or
+    !is_service_default($rabbit_userid) or
+    !is_service_default($rabbit_virtual_host) {
+    warning("nova::rabbit_host, nova::rabbit_hosts, nova::rabbit_password, \
+nova::rabbit_port, nova::rabbit_userid and nova::rabbit_virtual_host are \
+deprecated. Please use nova::default_transport_url instead.")
+  }
+
+  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 $nova_public_key or $nova_private_key {
+    file { '/var/lib/nova/.ssh':
+      ensure  => directory,
+      mode    => '0700',
+      owner   => 'nova',
+      group   => 'nova',
+      require => Anchor['nova::config::begin'],
+      before  => Anchor['nova::config::end'],
+    }
+
+    if $nova_public_key {
+      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'],
+        user    => 'nova',
+        require => File['/var/lib/nova/.ssh'],
+      }
+    }
+
+    if $nova_private_key {
+      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'] ? {
+        'ssh-rsa'   => '/var/lib/nova/.ssh/id_rsa',
+        'ssh-dsa'   => '/var/lib/nova/.ssh/id_dsa',
+        'ssh-ecdsa' => '/var/lib/nova/.ssh/id_ecdsa',
+        default     => undef
+      }
+
+      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.")
+      }
+
+      file { $nova_private_key_file:
+        content => $nova_private_key[key],
+        mode    => '0600',
+        owner   => 'nova',
+        group   => 'nova',
+        require => File['/var/lib/nova/.ssh'],
+      }
+    }
+  }
+
+  package { 'python-nova':
+    ensure => $ensure_package,
+    tag    => ['openstack', 'nova-package'],
+  }
+
+  package { 'nova-common':
+    ensure  => $ensure_package,
+    name    => $::nova::params::common_package_name,
+    require => Package['python-nova'],
+    tag     => ['openstack', 'nova-package'],
+  }
+
+  # used by debian/ubuntu in nova::network_bridge to refresh
+  # interfaces based on /etc/network/interfaces
+  exec { 'networking-refresh':
+    command     => '/sbin/ifdown -a ; /sbin/ifup -a',
+    refreshonly => true,
+  }
+
+  resources { 'nova_config':
+    purge => $purge_config,
+  }
+
+  if $image_service == 'nova.image.glance.GlanceImageService' {
+    if $glance_api_servers {
+      nova_config { 'glance/api_servers': value => $glance_api_servers }
+    }
+  }
+
+  # maintain backwards compatibility
+  $real_cpu_allocation_ratio = pick($::nova::scheduler::filter::cpu_allocation_ratio, $cpu_allocation_ratio)
+  ensure_resource('nova_config', 'DEFAULT/cpu_allocation_ratio', { value => $real_cpu_allocation_ratio })
+  $real_ram_allocation_ratio = pick($::nova::scheduler::filter::ram_allocation_ratio, $ram_allocation_ratio)
+  ensure_resource('nova_config', 'DEFAULT/ram_allocation_ratio', { value => $real_ram_allocation_ratio })
+  $real_disk_allocation_ratio = pick($::nova::scheduler::filter::disk_allocation_ratio, $disk_allocation_ratio)
+  ensure_resource('nova_config', 'DEFAULT/disk_allocation_ratio', { value => $real_disk_allocation_ratio })
+
+  nova_config {
+    'api/auth_strategy':     value => $auth_strategy;
+    'DEFAULT/image_service': value => $image_service;
+    'DEFAULT/host':          value => $host;
+  }
+
+  # we keep "nova.openstack.common.rpc.impl_kombu" for backward compatibility
+  # but since Icehouse, "rabbit" is enough.
+  if $rpc_backend in [$::os_service_default, 'nova.openstack.common.rpc.impl_kombu', 'rabbit'] {
+    oslo::messaging::rabbit {'nova_config':
+      rabbit_password             => $rabbit_password,
+      rabbit_userid               => $rabbit_userid,
+      rabbit_virtual_host         => $rabbit_virtual_host,
+      rabbit_use_ssl              => $rabbit_use_ssl,
+      heartbeat_timeout_threshold => $rabbit_heartbeat_timeout_threshold,
+      heartbeat_rate              => $rabbit_heartbeat_rate,
+      kombu_reconnect_delay       => $kombu_reconnect_delay,
+      amqp_durable_queues         => $amqp_durable_queues,
+      kombu_compression           => $kombu_compression,
+      kombu_ssl_ca_certs          => $kombu_ssl_ca_certs,
+      kombu_ssl_certfile          => $kombu_ssl_certfile,
+      kombu_ssl_keyfile           => $kombu_ssl_keyfile,
+      kombu_ssl_version           => $kombu_ssl_version,
+      rabbit_hosts                => $rabbit_hosts,
+      rabbit_host                 => $rabbit_host,
+      rabbit_port                 => $rabbit_port,
+      rabbit_ha_queues            => $rabbit_ha_queues,
+    }
+  } elsif $rpc_backend == 'amqp' {
+    oslo::messaging::amqp { 'nova_config':
+      server_request_prefix  => $amqp_server_request_prefix,
+      broadcast_prefix       => $amqp_broadcast_prefix,
+      group_request_prefix   => $amqp_group_request_prefix,
+      container_name         => $amqp_container_name,
+      idle_timeout           => $amqp_idle_timeout,
+      trace                  => $amqp_trace,
+      ssl_ca_file            => $amqp_ssl_ca_file,
+      ssl_cert_file          => $amqp_ssl_cert_file,
+      ssl_key_file           => $amqp_ssl_key_file,
+      ssl_key_password       => $amqp_ssl_key_password,
+      allow_insecure_clients => $amqp_allow_insecure_clients,
+      sasl_mechanisms        => $amqp_sasl_mechanisms,
+      sasl_config_dir        => $amqp_sasl_config_dir,
+      sasl_config_name       => $amqp_sasl_config_name,
+      username               => $amqp_username,
+      password               => $amqp_password,
+    }
+  } else {
+    nova_config { 'DEFAULT/rpc_backend': value => $rpc_backend }
+  }
+
+  # SSL Options
+  if $use_ssl {
+    nova_config {
+      'DEFAULT/enabled_ssl_apis' : value => join($enabled_ssl_apis, ',');
+      'ssl/cert_file' :            value => $cert_file;
+      'ssl/key_file' :             value => $key_file;
+      'wsgi/ssl_cert_file' :       value => $cert_file;
+      'wsgi/ssl_key_file' :        value => $key_file;
+    }
+    if $ca_file {
+      nova_config { 'ssl/ca_file' :
+        value => $ca_file,
+      }
+      nova_config { 'wsgi/ssl_ca_file' :
+        value => $ca_file,
+      }
+    } else {
+      nova_config { 'ssl/ca_file' :
+        ensure => absent,
+      }
+    }
+  } else {
+    nova_config {
+      'DEFAULT/enabled_ssl_apis' : ensure => absent;
+      'ssl/cert_file' :            ensure => absent;
+      'ssl/key_file' :             ensure => absent;
+      'ssl/ca_file' :              ensure => absent;
+    }
+  }
+
+  oslo::messaging::default { 'nova_config':
+    transport_url        => $default_transport_url,
+    rpc_response_timeout => $rpc_response_timeout,
+  }
+
+  oslo::messaging::notifications { 'nova_config':
+    transport_url => $notification_transport_url,
+    driver        => $notification_driver,
+    topics        => $notification_topics,
+  }
+
+  nova_config {
+    'cinder/catalog_info':                            value => $cinder_catalog_info;
+    'os_vif_linux_bridge/use_ipv6':                   value => $use_ipv6;
+    'DEFAULT/notify_api_faults':                      value => $notify_api_faults;
+    # Following may need to be broken out to different nova services
+    'DEFAULT/state_path':                             value => $state_path;
+    'DEFAULT/service_down_time':                      value => $service_down_time;
+    'DEFAULT/rootwrap_config':                        value => $rootwrap_config;
+    'DEFAULT/report_interval':                        value => $report_interval;
+    'DEFAULT/block_device_allocate_retries':          value => $block_device_allocate_retries;
+    'DEFAULT/block_device_allocate_retries_interval': value => $block_device_allocate_retries_interval;
+  }
+
+  oslo::concurrency { 'nova_config': lock_path => $lock_path }
+
+  if $notify_on_state_change and $notify_on_state_change in ['vm_state', 'vm_and_task_state'] {
+    nova_config {
+      'DEFAULT/notify_on_state_change': value => $notify_on_state_change;
+    }
+  } else {
+    nova_config { 'DEFAULT/notify_on_state_change': ensure => absent; }
+  }
+
+  nova_config {
+    'cinder/os_region_name':      value => $os_region_name;
+    'upgrade_levels/cells':       value => $upgrade_level_cells;
+    'upgrade_levels/cert':        value => $upgrade_level_cert;
+    'upgrade_levels/compute':     value => $upgrade_level_compute;
+    'upgrade_levels/conductor':   value => $upgrade_level_conductor;
+    'upgrade_levels/console':     value => $upgrade_level_console;
+    'upgrade_levels/consoleauth': value => $upgrade_level_consoleauth;
+    'upgrade_levels/intercell':   value => $upgrade_level_intercell;
+    'upgrade_levels/network':     value => $upgrade_level_network;
+    'upgrade_levels/scheduler':   value => $upgrade_level_scheduler;
+  }
+
+}

+ 111 - 0
manifests/ironic/common.pp

@@ -0,0 +1,111 @@
+# == Class: nova::ironic::common
+#
+# [*api_endpoint*]
+#   The url for Ironic api endpoint.
+#   Defaults to 'http://127.0.0.1:6385/v1'
+#
+# [*auth_plugin*]
+#   The authentication plugin to use when connecting to nova.
+#   Defaults to 'password'
+#
+# [*auth_url*]
+#   The address of the Keystone api endpoint.
+#   Defaults to 'http://127.0.0.1:35357/'
+#
+# [*project_name*]
+#   The Ironic Keystone project name.
+#   Defaults to 'services'
+#
+# [*password*]
+#   The admin password for Ironic to connect to Nova.
+#   Defaults to 'ironic'
+#
+# [*username*]
+#   The admin username for Ironic to connect to Nova.
+#   Defaults to 'admin'
+#
+# [*api_max_retries*]
+#   Max times for ironic driver to poll ironic api
+#
+# [*api_retry_interval*]
+#   Interval in second for ironic driver to poll ironic api
+#
+# === DEPRECATED
+#
+# [*admin_username*]
+#   The admin username for Ironic to connect to Nova.
+#   Defaults to 'admin'
+#
+# [*admin_password*]
+#   The admin password for Ironic to connect to Nova.
+#   Defaults to 'ironic'
+#
+# [*admin_url*]
+#   The address of the Keystone api endpoint.
+#   Defaults to 'http://127.0.0.1:35357/v2.0'
+#
+# [*admin_tenant_name*]
+#   The Ironic Keystone tenant name.
+#   Defaults to 'services'
+#
+class nova::ironic::common (
+  $api_endpoint         = 'http://127.0.0.1:6385/v1',
+  $auth_plugin          = 'password',
+  $auth_url             = 'http://127.0.0.1:35357/',
+  $password             = 'ironic',
+  $project_name         = 'services',
+  $username             = 'admin',
+  $api_max_retries      = $::os_service_default,
+  $api_retry_interval   = $::os_service_default,
+  # DEPRECATED
+  $admin_username       = undef,
+  $admin_password       = undef,
+  $admin_tenant_name    = undef,
+  $admin_url            = undef,
+) {
+
+  include ::nova::deps
+
+  if ($admin_username) {
+    warning('nova::ironic::common::admin_username is deprecated. Please use username')
+  }
+
+  if ($admin_password) {
+    warning('nova::ironic::common::admin_password is deprecated. Please use password')
+  }
+
+  if ($admin_tenant_name) {
+    warning('nova::ironic::common::admin_tenant_name is deprecated. Please use project_name')
+  }
+
+  if ($admin_url) {
+    warning('nova::ironic::common::admin_url is deprecated. Please use auth_url')
+  }
+
+
+
+  $username_real = pick($admin_username, $username)
+  $password_real = pick($admin_password, $password)
+  $auth_url_real = pick($admin_url, $auth_url)
+  $project_name_real = pick($admin_tenant_name, $project_name)
+
+
+  nova_config {
+    'ironic/auth_plugin':          value => $auth_plugin;
+    'ironic/username':             value => $username_real;
+    'ironic/password':             value => $password_real;
+    'ironic/auth_url':             value => $auth_url_real;
+    'ironic/project_name':         value => $project_name_real;
+    'ironic/api_endpoint':         value => $api_endpoint;
+    'ironic/api_max_retries':      value => $api_max_retries;
+    'ironic/api_retry_interval':   value => $api_retry_interval;
+  }
+
+  # TODO(aschultz): these are deprecated, remove in P
+  nova_config {
+    'ironic/admin_username':    value => $username_real;
+    'ironic/admin_password':    value => $password_real;
+    'ironic/admin_url':         value => $auth_url_real;
+    'ironic/admin_tenant_name': value => $project_name_real;
+  }
+}

+ 142 - 0
manifests/keystone/auth.pp

@@ -0,0 +1,142 @@
+# == Class: nova::keystone::auth
+#
+# Creates nova endpoints and service account in keystone
+#
+# === Parameters:
+#
+# [*password*]
+#   Password to create for the service user
+#
+# [*auth_name*]
+#   (optional) The name of the nova service user
+#   Defaults to 'nova'
+#
+# [*service_name*]
+#   (optional) Name of the service.
+#   Defaults to 'nova'.
+#
+# [*service_description*]
+#   (optional) Description for keystone service.
+#   Defaults to 'Openstack Compute Service'.
+#
+# [*public_url*]
+#   (optional) The endpoint's public url.
+#   Defaults to 'http://127.0.0.1:8774/v2.1'
+#
+# [*internal_url*]
+#   (optional) The endpoint's internal url.
+#   Defaults to 'http://127.0.0.1:8774/v2.1'
+#
+# [*admin_url*]
+#   (optional) The endpoint's admin url.
+#   Defaults to 'http://127.0.0.1:8774/v2.1'
+#
+# [*region*]
+#   (optional) The region in which to place the endpoints
+#   Defaults to 'RegionOne'
+#
+# [*tenant*]
+#   (optional) The tenant to use for the nova service user
+#   Defaults to 'services'
+#
+# [*email*]
+#   (optional) The email address for the nova service user
+#   Defaults to 'nova@localhost'
+#
+# [*configure_endpoint*]
+#   (optional) Whether to create the 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
+#
+# DEPRECATED PARAMETERS
+#
+# [*public_url_v3*]
+#   (optional) Deprecated. The v3 endpoint's public url.
+#   Defaults to undef.
+#
+# [*internal_url_v3*]
+#   (optional) Deprecated. The v3 endpoint's internal url.
+#   Defaults to undef.
+#
+# [*admin_url_v3*]
+#   (optional) DEPRECATED The v3 endpoint's admin url.
+#   Defaults to undef.
+#
+# [*service_description_v3*]
+#   (optional) Deprecated. Description for keystone v3 service.
+#   Defaults to undef.
+#
+# [*service_name_v3*]
+#   (optional) Deprecated. Name of the v3 service.
+#   Defaults to undef.
+#
+# [*auth_name_v3*]
+#   (optional) Deprecated. The name of the nova v3 service user
+#   Defaults to undef.
+#
+# [*configure_endpoint_v3*]
+#   (optional) Deprecated. Whether to create the v3 endpoint.
+#   Defaults to undef.
+#
+class nova::keystone::auth(
+  $password,
+  $auth_name               = 'nova',
+  $service_name            = 'nova',
+  $service_description     = 'Openstack Compute Service',
+  $region                  = 'RegionOne',
+  $tenant                  = 'services',
+  $email                   = 'nova@localhost',
+  $public_url              = 'http://127.0.0.1:8774/v2.1',
+  $internal_url            = 'http://127.0.0.1:8774/v2.1',
+  $admin_url               = 'http://127.0.0.1:8774/v2.1',
+  $configure_endpoint      = true,
+  $configure_user          = true,
+  $configure_user_role     = true,
+  # DEPRECATED PARAMETERS
+  $auth_name_v3            = undef,
+  $service_description_v3  = undef,
+  $service_name_v3         = undef,
+  $public_url_v3           = undef,
+  $internal_url_v3         = undef,
+  $admin_url_v3            = undef,
+  $configure_endpoint_v3   = undef,
+) {
+
+  include ::nova::deps
+
+  if $auth_name_v3 or $service_description_v3 or $service_name_v3 or
+      $public_url_v3 or $internal_url_v3 or $admin_url_v3 or $configure_endpoint_v3 {
+
+    warning("all parameters related to v3 API in nova::keystone::auth are \
+deprecated, have no effect and will be removed after Newton release.")
+  }
+
+  if $configure_endpoint {
+    Keystone_endpoint["${region}/${service_name}::compute"] ~> Service <| name == 'nova-api' |>
+  }
+
+  keystone::resource::service_identity { 'nova':
+    configure_user      => $configure_user,
+    configure_user_role => $configure_user_role,
+    configure_endpoint  => $configure_endpoint,
+    service_type        => 'compute',
+    service_description => $service_description,
+    service_name        => $service_name,
+    region              => $region,
+    auth_name           => $auth_name,
+    password            => $password,
+    email               => $email,
+    tenant              => $tenant,
+    public_url          => $public_url,
+    admin_url           => $admin_url,
+    internal_url        => $internal_url,
+  }
+
+}

+ 93 - 0
manifests/keystone/auth_placement.pp

@@ -0,0 +1,93 @@
+# == Class: nova::keystone::auth_placement
+#
+# Creates nova placement api endpoints and service account in keystone
+#
+# === Parameters:
+#
+# [*password*]
+#   Password to create for the service user
+#
+# [*auth_name*]
+#   (optional) The name of the placement service user
+#   Defaults to 'placement'
+#
+# [*service_name*]
+#   (optional) Name of the service.
+#   Defaults to 'placement'.
+#
+# [*service_description*]
+#   (optional) Description for keystone service.
+#   Defaults to 'Openstack Placement Service'.
+#
+# [*public_url*]
+#   (optional) The endpoint's public url.
+#   Defaults to 'http://127.0.0.1/placement'
+#
+# [*internal_url*]
+#   (optional) The endpoint's internal url.
+#   Defaults to 'http://127.0.0.1/placement'
+#
+# [*admin_url*]
+#   (optional) The endpoint's admin url.
+#   Defaults to 'http://127.0.0.1/placement'
+#
+# [*region*]
+#   (optional) The region in which to place the endpoints
+#   Defaults to 'RegionOne'
+#
+# [*tenant*]
+#   (optional) The tenant to use for the nova service user
+#   Defaults to 'services'
+#
+# [*email*]
+#   (optional) The email address for the nova service user
+#   Defaults to 'placement@localhost'
+#
+# [*configure_endpoint*]
+#   (optional) Whether to create the 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
+#
+class nova::keystone::auth_placement(
+  $password,
+  $auth_name               = 'placement',
+  $service_name            = 'placement',
+  $service_description     = 'Openstack Placement Service',
+  $region                  = 'RegionOne',
+  $tenant                  = 'services',
+  $email                   = 'placement@localhost',
+  $public_url              = 'http://127.0.0.1/placement',
+  $internal_url            = 'http://127.0.0.1/placement',
+  $admin_url               = 'http://127.0.0.1/placement',
+  $configure_endpoint      = true,
+  $configure_user          = true,
+  $configure_user_role     = true,
+) {
+
+  include ::nova::deps
+
+  keystone::resource::service_identity { 'placement':
+    configure_user      => $configure_user,
+    configure_user_role => $configure_user_role,
+    configure_endpoint  => $configure_endpoint,
+    service_type        => 'placement',
+    service_description => $service_description,
+    service_name        => $service_name,
+    region              => $region,
+    auth_name           => $auth_name,
+    password            => $password,
+    email               => $email,
+    tenant              => $tenant,
+    public_url          => $public_url,
+    admin_url           => $admin_url,
+    internal_url        => $internal_url,
+  }
+
+}

+ 279 - 0
manifests/keystone/authtoken.pp

@@ -0,0 +1,279 @@
+# class: nova::keystone::authtoken
+#
+# Configure the keystone_authtoken section in the configuration file
+#
+# === Parameters
+#
+# [*username*]
+#   (Optional) The name of the service user
+#   Defaults to 'nova'
+#
+# [*password*]
+#   (Optional) Password to create for the service user
+#   Defaults to $::os_service_default
+#
+# [*auth_url*]
+#   (Optional) The URL to use for authentication.
+#   Defaults to 'http:://127.0.0.1:35357'
+#
+# [*project_name*]
+#   (Optional) Service project name
+#   Defaults to 'services'
+#
+# [*user_domain_name*]
+#   (Optional) Name of domain for $username
+#   Defaults to $::os_service_default
+#
+# [*project_domain_name*]
+#   (Optional) Name of domain for $project_name
+#   Defaults to $::os_service_default
+#
+# [*insecure*]
+#   (Optional) If true, explicitly allow TLS without checking server cert
+#   against any certificate authorities.  WARNING: not recommended.  Use with
+#   caution.
+#   Defaults to $:os_service_default
+#
+# [*auth_section*]
+#   (Optional) Config Section from which to load plugin specific options
+#   Defaults to $::os_service_default.
+#
+# [*auth_type*]
+#   (Optional) Authentication type to load
+#   Defaults to $::os_service_default
+#
+# [*auth_uri*]
+#   (Optional) Complete public Identity API endpoint.
+#   Defaults to 'http://127.0.0.1:5000/'.
+#
+# [*auth_version*]
+#   (Optional) API version of the admin Identity API endpoint.
+#   Defaults to $::os_service_default.
+#
+# [*cache*]
+#   (Optional) Env key for the swift cache.
+#   Defaults to $::os_service_default.
+#
+# [*cafile*]
+#   (Optional) A PEM encoded Certificate Authority to use when verifying HTTPs
+#   connections.
+#   Defaults to $::os_service_default.
+#
+# [*certfile*]
+#   (Optional) Required if identity server requires client certificate
+#   Defaults to $::os_service_default.
+#
+# [*check_revocations_for_cached*]
+#   (Optional) If true, the revocation list will be checked for cached tokens.
+#   This requires that PKI tokens are configured on the identity server.
+#   boolean value.
+#   Defaults to $::os_service_default.
+#
+# [*delay_auth_decision*]
+#   (Optional) Do not handle authorization requests within the middleware, but
+#   delegate the authorization decision to downstream WSGI components. Boolean
+#   value
+#   Defaults to $::os_service_default.
+#
+# [*enforce_token_bind*]
+#   (Optional) Used to control the use and type of token binding. Can be set
+#   to: "disabled" to not check token binding. "permissive" (default) to
+#   validate binding information if the bind type is of a form known to the
+#   server and ignore it if not. "strict" like "permissive" but if the bind
+#   type is unknown the token will be rejected. "required" any form of token
+#   binding is needed to be allowed. Finally the name of a binding method that
+#   must be present in tokens. String value.
+#   Defaults to $::os_service_default.
+#
+# [*hash_algorithms*]
+#   (Optional) Hash algorithms to use for hashing PKI tokens. This may be a
+#   single algorithm or multiple. The algorithms are those supported by Python
+#   standard hashlib.new(). The hashes will be tried in the order given, so put
+#   the preferred one first for performance. The result of the first hash will
+#   be stored in the cache. This will typically be set to multiple values only
+#   while migrating from a less secure algorithm to a more secure one. Once all
+#   the old tokens are expired this option should be set to a single value for
+#   better performance. List value.
+#   Defaults to $::os_service_default.
+#
+# [*http_connect_timeout*]
+#   (Optional) Request timeout value for communicating with Identity API
+#   server.
+#   Defaults to $::os_service_default.
+#
+# [*http_request_max_retries*]
+#   (Optional) How many times are we trying to reconnect when communicating
+#   with Identity API Server. Integer value
+#   Defaults to $::os_service_default.
+#
+# [*include_service_catalog*]
+#   (Optional) Indicate whether to set the X-Service-Catalog header. If False,
+#   middleware will not ask for service catalog on token validation and will
+#   not set the X-Service-Catalog header. Boolean value.
+#   Defaults to $::os_service_default.
+#
+# [*keyfile*]
+#   (Optional) Required if identity server requires client certificate
+#   Defaults to $::os_service_default.
+#
+# [*memcache_pool_conn_get_timeout*]
+#   (Optional) Number of seconds that an operation will wait to get a memcached
+#   client connection from the pool. Integer value
+#   Defaults to $::os_service_default.
+#
+# [*memcache_pool_dead_retry*]
+#   (Optional) Number of seconds memcached server is considered dead before it
+#   is tried again. Integer value
+#   Defaults to $::os_service_default.
+#
+# [*memcache_pool_maxsize*]
+#   (Optional) Maximum total number of open connections to every memcached
+#    server. Integer value
+#  Defaults to $::os_service_default.
+#
+# [*memcache_pool_socket_timeout*]
+#   (Optional) Number of seconds a connection to memcached is held unused in
+#   the pool before it is closed. Integer value
+#   Defaults to $::os_service_default.
+#
+# [*memcache_pool_unused_timeout*]
+#   (Optional) Number of seconds a connection to memcached is held unused in
+#   the pool before it is closed. Integer value
+#   Defaults to $::os_service_default.
+#
+# [*memcache_secret_key*]
+#   (Optional, mandatory if memcache_security_strategy is defined) This string
+#   is used for key derivation.
+#   Defaults to $::os_service_default.
+#
+# [*memcache_security_strategy*]
+#   (Optional) If defined, indicate whether token data should be authenticated
+#   or authenticated and encrypted. If MAC, token data is authenticated (with
+#   HMAC) in the cache. If ENCRYPT, token data is encrypted and authenticated in the
+#   cache. If the value is not one of these options or empty, auth_token will
+#   raise an exception on initialization.
+#   Defaults to $::os_service_default.
+#
+# [*memcache_use_advanced_pool*]
+#   (Optional)  Use the advanced (eventlet safe) memcached client pool. The
+#   advanced pool will only work under python 2.x Boolean value
+#   Defaults to $::os_service_default.
+#
+# [*memcached_servers*]
+#   (Optional) Optionally specify a list of memcached server(s) to use for
+#   caching. If left undefined, tokens will instead be cached in-process.
+#   Defaults to $::os_service_default.
+#
+# [*manage_memcache_package*]
+#  (Optional) Whether to install the python-memcache package.
+#  Defaults to false.
+#
+# [*region_name*]
+#   (Optional) The region in which the identity server can be found.
+#   Defaults to $::os_service_default.
+#
+# [*revocation_cache_time*]
+#   (Optional) Determines the frequency at which the list of revoked tokens is
+#   retrieved from the Identity service (in seconds). A high number of
+#   revocation events combined with a low cache duration may significantly
+#   reduce performance. Only valid for PKI tokens. Integer value
+#   Defaults to $::os_service_default.
+#
+# [*token_cache_time*]
+#   (Optional) In order to prevent excessive effort spent validating tokens,
+#   the middleware caches previously-seen tokens for a configurable duration
+#   (in seconds). Set to -1 to disable caching completely. Integer value
+#   Defaults to $::os_service_default.
+#
+# DEPRECATED PARAMETERS
+#
+# [*signing_dir*]
+#   (Optional) Directory used to cache files related to PKI tokens.
+#   Defaults to undef
+#
+class nova::keystone::authtoken(
+  $username                       = 'nova',
+  $password                       = $::os_service_default,
+  $auth_url                       = 'http://127.0.0.1:35357/',
+  $project_name                   = 'services',
+  $user_domain_name               = $::os_service_default,
+  $project_domain_name            = $::os_service_default,
+  $insecure                       = $::os_service_default,
+  $auth_section                   = $::os_service_default,
+  $auth_type                      = 'password',
+  $auth_uri                       = 'http://127.0.0.1:5000/',
+  $auth_version                   = $::os_service_default,
+  $cache                          = $::os_service_default,
+  $cafile                         = $::os_service_default,
+  $certfile                       = $::os_service_default,
+  $check_revocations_for_cached   = $::os_service_default,
+  $delay_auth_decision            = $::os_service_default,
+  $enforce_token_bind             = $::os_service_default,
+  $hash_algorithms                = $::os_service_default,
+  $http_connect_timeout           = $::os_service_default,
+  $http_request_max_retries       = $::os_service_default,
+  $include_service_catalog        = $::os_service_default,
+  $keyfile                        = $::os_service_default,
+  $memcache_pool_conn_get_timeout = $::os_service_default,
+  $memcache_pool_dead_retry       = $::os_service_default,
+  $memcache_pool_maxsize          = $::os_service_default,
+  $memcache_pool_socket_timeout   = $::os_service_default,
+  $memcache_pool_unused_timeout   = $::os_service_default,
+  $memcache_secret_key            = $::os_service_default,
+  $memcache_security_strategy     = $::os_service_default,
+  $memcache_use_advanced_pool     = $::os_service_default,
+  $memcached_servers              = $::os_service_default,
+  $manage_memcache_package        = false,
+  $region_name                    = $::os_service_default,
+  $revocation_cache_time          = $::os_service_default,
+  $token_cache_time               = $::os_service_default,
+  # DEPRECATED PARAMETERS
+  $signing_dir                    = undef,
+) {
+
+  if is_service_default($password) {
+    fail('Please set password for nova service user')
+  }
+
+  if $signing_dir {
+    warning('signing_dir parameter is deprecated, has no effect and will be removed in the P release.')
+  }
+
+  keystone::resource::authtoken { 'nova_config':
+    username                       => $username,
+    password                       => $password,
+    project_name                   => $project_name,
+    auth_url                       => $auth_url,
+    auth_uri                       => $auth_uri,
+    auth_version                   => $auth_version,
+    auth_type                      => $auth_type,
+    auth_section                   => $auth_section,
+    user_domain_name               => $user_domain_name,
+    project_domain_name            => $project_domain_name,
+    insecure                       => $insecure,
+    cache                          => $cache,
+    cafile                         => $cafile,
+    certfile                       => $certfile,
+    check_revocations_for_cached   => $check_revocations_for_cached,
+    delay_auth_decision            => $delay_auth_decision,
+    enforce_token_bind             => $enforce_token_bind,
+    hash_algorithms                => $hash_algorithms,
+    http_connect_timeout           => $http_connect_timeout,
+    http_request_max_retries       => $http_request_max_retries,
+    include_service_catalog        => $include_service_catalog,
+    keyfile                        => $keyfile,
+    memcache_pool_conn_get_timeout => $memcache_pool_conn_get_timeout,
+    memcache_pool_dead_retry       => $memcache_pool_dead_retry,
+    memcache_pool_maxsize          => $memcache_pool_maxsize,
+    memcache_pool_socket_timeout   => $memcache_pool_socket_timeout,
+    memcache_secret_key            => $memcache_secret_key,
+    memcache_security_strategy     => $memcache_security_strategy,
+    memcache_use_advanced_pool     => $memcache_use_advanced_pool,
+    memcache_pool_unused_timeout   => $memcache_pool_unused_timeout,
+    memcached_servers              => $memcached_servers,
+    manage_memcache_package        => $manage_memcache_package,
+    region_name                    => $region_name,
+    revocation_cache_time          => $revocation_cache_time,
+    token_cache_time               => $token_cache_time,
+  }
+}

+ 136 - 0
manifests/logging.pp

@@ -0,0 +1,136 @@
+# Class nova::logging
+#
+#  nova logging configuration
+#
+# == parameters
+#
+#  [*debug*]
+#    (Optional) Should the daemons log debug messages
+#    Defaults to $::os_service_default
+#
+#  [*use_syslog*]
+#    (Optional) Use syslog for logging.
+#    Defaults to $::os_service_default
+#
+#  [*use_stderr*]
+#    (optional) Use stderr for logging
+#    Defaults to $::os_service_default
+#
+#  [*log_facility*]
+#    (Optional) Syslog facility to receive log lines.
+#    Defaults to $::os_service_default
+#
+#  [*log_dir*]
+#    (optional) Directory where logs should be stored.
+#    If set to $::os_service_default, it will not log to any directory.
+#    Defaults to '/var/log/nova'
+#
+#  [*logging_context_format_string*]
+#    (optional) Format string to use for log messages with context.
+#    Defaults to $::os_service_default
+#    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 $::os_service_default
+#    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 $::os_service_default
+#    Example: '%(funcName)s %(pathname)s:%(lineno)d'
+#
+#  [*logging_exception_prefix*]
+#    (optional) Prefix each line of exception output with this format.
+#    Defaults to $::os_service_default
+#    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 $::os_service_default
+#    See https://docs.python.org/2/howto/logging.html
+#
+#  [*default_log_levels*]
+#    (optional) Hash of logger (keys) and level (values) pairs.
+#    Defaults to $::os_service_default
+#    Example:
+#      { 'amqp' => 'WARN', 'amqplib' => 'WARN', 'boto' => 'WARN',
+#        'sqlalchemy' => 'WARN', 'suds' => 'INFO', 'iso8601' => 'WARN',
+#        'requests.packages.urllib3.connectionpool' => 'WARN' }
+#
+#  [*publish_errors*]
+#    (optional) Publish error events (boolean value).
+#    Defaults to $::os_service_default
+#
+#  [*fatal_deprecations*]
+#    (optional) Make deprecations fatal (boolean value)
+#    Defaults to $::os_service_default
+#
+#  [*instance_format*]
+#    (optional) If an instance is passed with the log message, format it
+#               like this (string value).
+#    Defaults to $::os_service_default
+#    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 $::os_service_default
+#    Example: instance_uuid_format='[instance: %(uuid)s] '
+#
+#  [*log_date_format*]
+#    (optional) Format string for %%(asctime)s in log records.
+#    Defaults to $::os_service_default
+#    Example: 'Y-%m-%d %H:%M:%S'
+#
+class nova::logging(
+  $use_syslog                    = $::os_service_default,
+  $use_stderr                    = $::os_service_default,
+  $log_facility                  = $::os_service_default,
+  $log_dir                       = '/var/log/nova',
+  $debug                         = $::os_service_default,
+  $logging_context_format_string = $::os_service_default,
+  $logging_default_format_string = $::os_service_default,
+  $logging_debug_format_suffix   = $::os_service_default,
+  $logging_exception_prefix      = $::os_service_default,
+  $log_config_append             = $::os_service_default,
+  $default_log_levels            = $::os_service_default,
+  $publish_errors                = $::os_service_default,
+  $fatal_deprecations            = $::os_service_default,
+  $instance_format               = $::os_service_default,
+  $instance_uuid_format          = $::os_service_default,
+  $log_date_format               = $::os_service_default,
+) {
+
+  include ::nova::deps
+
+  # NOTE(spredzy): In order to keep backward compatibility we rely on the pick function
+  # to use nova::<myparam> first then nova::logging::<myparam>.
+  $use_syslog_real = pick($::nova::use_syslog,$use_syslog)
+  $use_stderr_real = pick($::nova::use_stderr,$use_stderr)
+  $log_facility_real = pick($::nova::log_facility,$log_facility)
+  $log_dir_real = pick($::nova::log_dir,$log_dir)
+  $debug_real = pick($::nova::debug,$debug)
+
+  oslo::log { 'nova_config':
+    debug                         => $debug_real,
+    use_stderr                    => $use_stderr_real,
+    use_syslog                    => $use_syslog_real,
+    log_dir                       => $log_dir_real,
+    syslog_log_facility           => $log_facility_real,
+    logging_context_format_string => $logging_context_format_string,
+    logging_default_format_string => $logging_default_format_string,
+    logging_debug_format_suffix   => $logging_debug_format_suffix,
+    logging_exception_prefix      => $logging_exception_prefix,
+    log_config_append             => $log_config_append,
+    default_log_levels            => $default_log_levels,
+    publish_errors                => $publish_errors,
+    fatal_deprecations            => $fatal_deprecations,
+    instance_format               => $instance_format,
+    instance_uuid_format          => $instance_uuid_format,
+    log_date_format               => $log_date_format,
+  }
+
+}

+ 89 - 0
manifests/manage/cells.pp

@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Emilien Macchi <emilien.macchi@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
+# 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.
+#
+#
+# Configuring the database in each cell
+# == Namevar
+#  The namevar will be the name of the cell
+#
+# == Parameters
+#  [*cell_type*]
+#    (optional) Whether the cell is a 'parent' or 'child'
+#    Defaults to 'parent'
+#
+#  [*cell_parent_name*]
+#    (optional) If a child cell, this is the name of the 'parent' cell.
+#    If a parent cell, should be left to undef.
+#    Defaults to undef
+#
+#  [*rabbit_username*]
+#    (optional) Username for the message broker in this cell
+#    Defaults to 'guest'
+#
+#  [*rabbit_password*]
+#    (optional) Password for the message broker in this cell
+#    Defaults to 'guest'
+#
+#  [*rabbit_hosts*]
+#    (optional) Address of the message broker in this cell
+#    Defaults to ['localhost']
+#
+#  [*rabbit_port*]
+#    (optional) Port number of the message broker in this cell
+#    Defaults to '5672'
+#
+#  [*rabbit_virtual_host*]
+#    (optional) The virtual host of the message broker in this cell
+#    Defaults to '/'
+#
+#  [*weight_offset*]
+#    (optional) It might be used by some cell scheduling code in the future
+#    Defaults to '1.0'
+#
+#  [*weight_scale*]
+#    (optional) It might be used by some cell scheduling code in the future
+#    Defaults to '1.0'
+#
+define nova::manage::cells (
+  $cell_type           = 'parent',
+  $cell_parent_name    = undef,
+  $rabbit_username     = 'guest',
+  $rabbit_password     = 'guest',
+  $rabbit_hosts        = ['localhost'],
+  $rabbit_port         = '5672',
+  $rabbit_virtual_host = '/',
+  $weight_offset       = '1.0',
+  $weight_scale        = '1.0'
+) {
+
+  include ::nova::deps
+
+  nova_cells { $name:
+    ensure              => present,
+    cell_type           => $cell_type,
+    cell_parent_name    => $cell_parent_name,
+    rabbit_username     => $rabbit_username,
+    rabbit_password     => $rabbit_password,
+    rabbit_hosts        => $rabbit_hosts,
+    rabbit_port         => $rabbit_port,
+    rabbit_virtual_host => $rabbit_virtual_host,
+    weight_offset       => $weight_offset,
+    weight_scale        => $weight_scale
+  }
+
+}

+ 17 - 0
manifests/manage/floating.pp

@@ -0,0 +1,17 @@
+# Creates floating networks
+#
+# === Parameters:
+#
+# [*network*]
+#  (mandatory) The network name to work on
+#
+define nova::manage::floating ( $network ) {
+
+  include ::nova::deps
+
+  nova_floating { $name:
+    ensure   => present,
+    network  => $network,
+    provider => 'nova_manage',
+  }
+}

+ 71 - 0
manifests/manage/network.pp

@@ -0,0 +1,71 @@
+# === Parameters:
+#
+# [*network*]
+#   (required) IPv4 CIDR of network to create.
+#
+# [*label*]
+#   (optional) The label of the network.
+#   Defaults to 'novanetwork'.
+#
+# [*num_networks*]
+#   (optional) Number of networks to split $network into.
+#   Defaults to 1
+#
+# [*network_size*]
+#   (optional) Size of the network to create
+#   Defaults to 255
+#
+# [*vlan_start*]
+#   (optional) The vlan number to use if in vlan mode
+#   Defaults to undef
+#
+# [*allowed_start*]
+#   (optional) Start of allowed addresses for instances
+#   Defaults to undef
+#
+# [*allowed_end*]
+#   (optional) End of allowed addresses for instances
+#   Defaults to undef
+#
+# [*project*]
+#   (optional) Project that network should be associated with
+#   Defaults to undef
+#
+# [*dns1*]
+#   (optional) First DNS server
+#   Defaults to undef
+#
+# [*dns2*]
+#   (optional) Second DNS server
+#   Defaults to undef
+#
+define nova::manage::network (
+  $network,
+  $label         = 'novanetwork',
+  $num_networks  = 1,
+  $network_size  = 255,
+  $vlan_start    = undef,
+  $project       = undef,
+  $allowed_start = undef,
+  $allowed_end   = undef,
+  $dns1          = undef,
+  $dns2          = undef
+) {
+
+  include ::nova::deps
+
+  nova_network { $name:
+    ensure        => present,
+    network       => $network,
+    label         => $label,
+    num_networks  => $num_networks,
+    network_size  => $network_size,
+    project       => $project,
+    vlan_start    => $vlan_start,
+    allowed_start => $allowed_start,
+    allowed_end   => $allowed_end,
+    dns1          => $dns1,
+    dns2          => $dns2,
+  }
+
+}

+ 207 - 0
manifests/metadata/novajoin/api.pp

@@ -0,0 +1,207 @@
+# == Class: nova::metadata::novajoin::api
+#
+# The nova::metadata::novajoin::api class encapsulates an
+# IPA Nova Join API service.
+#
+# === Parameters
+#
+# [*nova_password*]
+#   (required) Password for the nova service user.
+#
+# [*transport_url*]
+#   (required) Transport URL for notifier service to talk to
+#   the messaging queue.
+#
+# [*bind_address*]
+#   (optional) IP address for novajoin server to listen
+#   Defaults to '127.0.0.1'
+#
+# [*api_paste_config*]
+#   (optional) Filename for the paste deploy file.
+#   Defaults to '/etc/nova/join-api-paste.ini'.
+#
+# [*auth_strategy*]
+#   (optional) Strategy to use for authentication.
+#   Defaults to 'keystone'.
+#
+# [*auth_type*]
+#   (optional) Authentication type.
+#   Defaults to 'password'.
+#
+# [*cacert*]
+#   (optional) CA cert file.
+#   Defaults to '/etc/ipa/ca.crt'.
+#
+# [*connect_retries*]
+#   (optional) Number of connection retries to IPA.
+#   Defaults to 1.
+#
+# [*debug*]
+#   (optional) Set log level to debug.
+#   Defaults to false.
+#
+# [*enabled*]
+#   (optional) Whether to enable services.
+#   Defaults to true.
+#
+# [*enable_ipa_client_install*]
+#   (optional) whether to perform ipa_client_install
+#   Defaults to true.
+#
+# [*ensure_package*]
+#   (optional) The state of novajoin packages.
+#   Defaults to 'present'
+#
+# [*ipa_domain*]
+#   (optional) IPA domain
+#   Reads the value from /etc/ipa/default.conf if not defined.
+#
+# [*join_listen_port*]
+#   (optional) Port for novajoin service to listen on.
+#   Defaults to 9090
+#
+# [*keystone_auth_url*]
+#   (optional) auth_url for the keystone instance.
+#   Defaults to 'http:://127.0.0.1:35357'
+#
+# [*keytab*]
+#   (optional) Kerberos client keytab file.
+#   Defaults to '/etc/nova/krb5.keytab'
+#
+# [*log_dir*]
+#   (optional) log directory.
+#   Defaults to '/var/log/novajoin'
+#
+# [*manage_service*]
+#   (optional) If Puppet should manage service startup / shutdown.
+#   Defaults to true.
+#
+# [*nova_user*]
+#   (optional) User that nova services run as.
+#   Defaults to 'nova'
+#
+# [*project_domain_name*]
+#   (optional) Domain name containing project (for nova auth).
+#   Defaults to 'default'
+#
+# [*project_name*]
+#   (optional) Project name (for nova auth).
+#   Defaults to 'service'
+#
+# [*user_domain_id*]
+#   (optional) Domain for nova user.
+#   Defaults to 'default'
+#
+class nova::metadata::novajoin::api (
+  $nova_password,
+  $transport_url,
+  $bind_address              = '127.0.0.1',
+  $api_paste_config          = '/etc/nova/join-api-paste.ini',
+  $auth_strategy             = $::os_service_default,
+  $auth_type                 = 'password',
+  $cacert                    = '/etc/ipa/ca.crt',
+  $connect_retries           = $::os_service_default,
+  $debug                     = $::os_service_default,
+  $enabled                   = true,
+  $enable_ipa_client_install = true,
+  $ensure_package            = 'present',
+  $ipa_domain                = undef,
+  $join_listen_port          = $::os_service_default,
+  $keystone_auth_url         = 'http://127.0.0.1:35357/',
+  $keytab                    = '/etc/nova/krb5.keytab',
+  $log_dir                   = '/var/log/novajoin',
+  $manage_service            = true,
+  $nova_user                 = 'nova',
+  $project_domain_name       = 'default',
+  $project_name              = 'service',
+  $user_domain_id            = 'default',
+) {
+
+  case $::osfamily {
+    'RedHat': {
+      $package_name        = 'python-novajoin'
+      $service_name        = 'novajoin-server'
+      $notify_service_name = 'novajoin-notify'
+    }
+    default: {
+      fail("Unsupported osfamily: ${::osfamily} operatingsystem")
+    }
+  } # Case $::osfamily
+
+  if $enable_ipa_client_install {
+    require ::ipaclient
+  }
+
+  package { 'python-novajoin':
+    ensure => $ensure_package,
+    name   => $package_name,
+    tag    => ['openstack', 'novajoin-package'],
+  }
+
+  if $ipa_domain != undef {
+    novajoin_config {
+      'DEFAULT/domain': value => $ipa_domain;
+    }
+  }
+
+  novajoin_config {
+    'DEFAULT/join_listen':                     value => $bind_address;
+    'DEFAULT/api_paste_config':                value => $api_paste_config;
+    'DEFAULT/auth_strategy':                   value => $auth_strategy;
+    'DEFAULT/cacert':                          value => $cacert;
+    'DEFAULT/connect_retries':                 value => $connect_retries;
+    'DEFAULT/debug':                           value => $debug;
+    'DEFAULT/join_listen_port':                value => $join_listen_port;
+    'DEFAULT/keytab':                          value => $keytab;
+    'DEFAULT/log_dir':                         value => $log_dir;
+    'DEFAULT/transport_url':                   value => $transport_url;
+    'service_credentials/auth_type':           value => $auth_type;
+    'service_credentials/auth_url':            value => $keystone_auth_url;
+    'service_credentials/password':            value => $nova_password;
+    'service_credentials/username':            value => $nova_user;
+    'service_credentials/project_name':        value => $project_name;
+    'service_credentials/user_domain_id':      value => $user_domain_id;
+    'service_credentials/project_domain_name':
+      value => $project_domain_name;
+  }
+
+  if $manage_service {
+    if $enabled {
+      $service_ensure = 'running'
+    } else {
+      $service_ensure = 'stopped'
+    }
+  }
+
+  service { 'novajoin-server':
+    ensure     => $service_ensure,
+    name       => $service_name,
+    enable     => $enabled,
+    hasstatus  => true,
+    hasrestart => true,
+    tag        => 'openstack',
+  }
+
+  service { 'novajoin-notify':
+    ensure     => $service_ensure,
+    name       => $notify_service_name,
+    enable     => $enabled,
+    hasstatus  => true,
+    hasrestart => true,
+    tag        => 'openstack',
+  }
+
+  exec { 'get-service-user-keytab':
+    command => "/usr/bin/kinit -kt /etc/krb5.keytab && ipa-getkeytab -s `grep xmlrpc_uri /etc/ipa/default.conf  | cut -d/ -f3` \
+                -p nova/${::fqdn} -k ${keytab}",
+    creates => $keytab,
+    require => Package['python-novajoin']
+  }
+
+  ensure_resource('file', $keytab, { owner => $nova_user, require => Exec['get-service-user-keytab'] })
+
+  Novajoin_config<||> ~> Service<| title == 'nova-api'|>
+  Exec['get-service-user-keytab'] ~> Service['novajoin-server']
+  Exec['get-service-user-keytab'] ~> Service['novajoin-notify']
+  Exec['get-service-user-keytab'] ~> Service<| title == 'nova-api'|>
+}

+ 210 - 0
manifests/migration/libvirt.pp

@@ -0,0 +1,210 @@
+# == Class: nova::migration::libvirt
+#
+# Sets libvirt config that is required for migration
+#
+# === Parameters:
+#
+# [*use_tls*]
+#   (optional) Use tls for remote connections to libvirt
+#   Defaults to false
+#
+# [*auth*]
+#   (optional) Use this authentication scheme for remote libvirt connections.
+#   Valid options are none and sasl.
+#   Defaults to 'none'
+#
+# [*live_migration_tunnelled*]
+#   (optional) Whether to use tunnelled migration, where migration data is
+#   transported over the libvirtd connection.
+#   If True, we use the VIR_MIGRATE_TUNNELLED migration flag, avoiding the
+#   need to configure the network to allow direct hypervisor to hypervisor
+#   communication.
+#   If False, use the native transport.
+#   If not set, Nova will choose a sensible default based on, for example
+#   the availability of native encryption support in the hypervisor.
+#   Defaults to $::os_service_default
+#
+# [*live_migration_completion_timeout*]
+#   (optional) Time to wait, in seconds, for migration to successfully complete
+#   transferring data before aborting the operation. Value is per GiB of guest
+#   RAM + disk to be transferred, with lower bound of a minimum of 2 GiB. Set
+#   to 0 to disable timeouts.
+#   Defaults to $::os_service_default
+#
+# [*live_migration_progress_timeout*]
+#   (optional) Time to wait, in seconds, for migration to make forward progress
+#   in transferring data before aborting the operation. Set to 0 to disable
+#   timeouts.
+#   Defaults to $::os_service_default
+#
+# [*override_uuid*]
+#   (optional) Set uuid not equal to output from dmidecode (boolean)
+#   Defaults to false
+#
+# [*configure_libvirt*]
+#   (optional) Whether or not configure libvirt bits.
+#   Defaults to true.
+#
+# [*configure_nova*]
+#   (optional) Whether or not configure libvirt bits.
+#   Defaults to true.
+#
+class nova::migration::libvirt(
+  $use_tls                           = false,
+  $auth                              = 'none',
+  $live_migration_tunnelled          = $::os_service_default,
+  $live_migration_completion_timeout = $::os_service_default,
+  $live_migration_progress_timeout   = $::os_service_default,
+  $override_uuid                     = false,
+  $configure_libvirt                 = true,
+  $configure_nova                    = true,
+){
+
+  include ::nova::deps
+
+  validate_re($auth, [ '^sasl$', '^none$' ], 'Valid options for auth are none and sasl.')
+
+  if $use_tls {
+    $listen_tls = '1'
+    $listen_tcp = '0'
+  } else {
+    $listen_tls = '0'
+    $listen_tcp = '1'
+  }
+
+  if $configure_nova {
+    if $use_tls {
+      nova_config {
+        'libvirt/live_migration_uri': value => 'qemu+tls://%s/system';
+      }
+    }
+
+    nova_config {
+      'libvirt/live_migration_tunnelled':          value => $live_migration_tunnelled;
+      'libvirt/live_migration_completion_timeout': value => $live_migration_completion_timeout;
+      'libvirt/live_migration_progress_timeout':   value => $live_migration_progress_timeout;
+    }
+  }
+
+  if $configure_libvirt {
+    Anchor['nova::config::begin']
+    -> File_line<| tag == 'libvirt-file_line'|>
+    -> Anchor['nova::config::end']
+
+    File_line<| tag == 'libvirt-file_line' |>
+    ~> Service['libvirt']
+
+    if $override_uuid {
+      if ! $::libvirt_uuid {
+        $host_uuid = generate('/bin/cat', '/proc/sys/kernel/random/uuid')
+        file { '/etc/libvirt/libvirt_uuid':
+          content => $host_uuid,
+          require => Package['libvirt'],
+        }
+      } else {
+        $host_uuid = $::libvirt_uuid
+      }
+
+      augeas { 'libvirt-conf-uuid':
+        context => '/files/etc/libvirt/libvirtd.conf',
+        changes => [
+          "set host_uuid ${host_uuid}",
+        ],
+        notify  => Service['libvirt'],
+        require => Package['libvirt'],
+      }
+    }
+
+    case $::osfamily {
+      'RedHat': {
+        file_line { '/etc/libvirt/libvirtd.conf listen_tls':
+          path  => '/etc/libvirt/libvirtd.conf',
+          line  => "listen_tls = ${listen_tls}",
+          match => 'listen_tls =',
+          tag   => 'libvirt-file_line',
+        }
+
+        file_line { '/etc/libvirt/libvirtd.conf listen_tcp':
+          path  => '/etc/libvirt/libvirtd.conf',
+          line  => "listen_tcp = ${listen_tcp}",
+          match => 'listen_tcp =',
+          tag   => 'libvirt-file_line',
+        }
+
+        if $use_tls {
+          file_line { '/etc/libvirt/libvirtd.conf auth_tls':
+            path  => '/etc/libvirt/libvirtd.conf',
+            line  => "auth_tls = \"${auth}\"",
+            match => 'auth_tls =',
+            tag   => 'libvirt-file_line',
+          }
+        } else {
+          file_line { '/etc/libvirt/libvirtd.conf auth_tcp':
+            path  => '/etc/libvirt/libvirtd.conf',
+            line  => "auth_tcp = \"${auth}\"",
+            match => 'auth_tcp =',
+            tag   => 'libvirt-file_line',
+          }
+        }
+
+        file_line { '/etc/sysconfig/libvirtd libvirtd args':
+          path  => '/etc/sysconfig/libvirtd',
+          line  => 'LIBVIRTD_ARGS="--listen"',
+          match => 'LIBVIRTD_ARGS=',
+          tag   => 'libvirt-file_line',
+        }
+      }
+
+      'Debian': {
+        file_line { '/etc/libvirt/libvirtd.conf listen_tls':
+          path  => '/etc/libvirt/libvirtd.conf',
+          line  => "listen_tls = ${listen_tls}",
+          match => 'listen_tls =',
+          tag   => 'libvirt-file_line',
+        }
+
+        file_line { '/etc/libvirt/libvirtd.conf listen_tcp':
+          path  => '/etc/libvirt/libvirtd.conf',
+          line  => "listen_tcp = ${listen_tcp}",
+          match => 'listen_tcp =',
+          tag   => 'libvirt-file_line',
+        }
+
+        if $use_tls {
+          file_line { '/etc/libvirt/libvirtd.conf auth_tls':
+            path  => '/etc/libvirt/libvirtd.conf',
+            line  => "auth_tls = \"${auth}\"",
+            match => 'auth_tls =',
+            tag   => 'libvirt-file_line',
+          }
+        } else {
+          file_line { '/etc/libvirt/libvirtd.conf auth_tcp':
+            path  => '/etc/libvirt/libvirtd.conf',
+            line  => "auth_tcp = \"${auth}\"",
+            match => 'auth_tcp =',
+            tag   => 'libvirt-file_line',
+          }
+        }
+
+        if $::operatingsystem == 'Ubuntu' and versioncmp($::operatingsystemmajrelease, '16') >= 0 {
+          # If systemd is being used then libvirtd is already being launched correctly and
+          # adding -d causes a second consecutive start to fail which causes puppet to fail.
+          $libvirtd_opts = 'libvirtd_opts="-l"'
+        } else {
+          $libvirtd_opts = 'libvirtd_opts="-d -l"'
+        }
+
+        file_line { "/etc/default/${::nova::compute::libvirt::libvirt_service_name} libvirtd opts":
+          path  => "/etc/default/${::nova::compute::libvirt::libvirt_service_name}",
+          line  => $libvirtd_opts,
+          match => 'libvirtd_opts=',
+          tag   => 'libvirt-file_line',
+        }
+      }
+
+      default:  {
+        warning("Unsupported osfamily: ${::osfamily}, make sure you are configuring this yourself")
+      }
+    }
+  }
+}

+ 54 - 0
manifests/migration/qemu.pp

@@ -0,0 +1,54 @@
+# == Class: nova::migration::qemu
+#
+# Sets qemu config that is required for migration
+#
+# === Parameters:
+#
+# [*configure_qemu*]
+#   (optional) Whether or not configure qemu bits.
+#   Defaults to false.
+#
+# [*migration_port_min*]
+#   (optional) Lower limit of port range used for migration.
+#   Defaults to 49152.
+#
+# [*migration_port_max*]
+#   (optional) Higher limit of port range used for migration.
+#   Defaults to 49215.
+#
+class nova::migration::qemu(
+  $configure_qemu     = false,
+  $migration_port_min = 49152,
+  $migration_port_max = 49215,
+){
+
+  include ::nova::deps
+
+  Anchor['nova::config::begin']
+  -> Augeas<| tag == 'qemu-conf-augeas'|>
+  -> Anchor['nova::config::end']
+
+  Augeas<| tag == 'qemu-conf-augeas'|>
+  ~> Service['libvirt']
+
+  if $configure_qemu {
+
+    augeas { 'qemu-conf-migration-ports':
+      context => '/files/etc/libvirt/qemu.conf',
+      changes => [
+        "set migration_port_min ${migration_port_min}",
+        "set migration_port_max ${migration_port_max}",
+      ],
+      tag     => 'qemu-conf-augeas',
+    }
+  } else {
+    augeas { 'qemu-conf-migration-ports':
+      context => '/files/etc/libvirt/qemu.conf',
+      changes => [
+        'rm migration_port_min',
+        'rm migration_port_max',
+      ],
+      tag     => 'qemu-conf-augeas',
+    }
+  }
+}

+ 210 - 0
manifests/network.pp

@@ -0,0 +1,210 @@
+# == Class: nova::network
+#
+# 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:
+#
+# [*private_interface*]
+#   (optional) Interface used by private network.
+#   Defaults to undef
+#
+# [*fixed_range*]
+#   (optional) Fixed private network range.
+#   Defaults to '10.0.0.0/8'
+#
+# [*public_interface*]
+#   (optional) Interface used to connect vms to public network.
+#   Defaults to undef
+#
+# [*num_networks*]
+#   (optional) Number of networks that fixed range network should be
+#   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
+#
+# [*enabled*]
+#   (optional) Whether the network service should be enabled.
+#   Defaults to true
+#
+# [*network_manager*]
+#   (optional) The type of network manager to use.
+#   Defaults to 'nova.network.manager.FlatDHCPManager'
+#
+# [*config_overrides*]
+#   (optional) Additional parameters to pass to the network manager class
+#   Defaults to {}
+#
+# [*create_networks*]
+#   (optional) Whether actual nova networks should be created using
+#   the fixed and floating ranges provided.
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (optional) The state of the nova network package
+#   Defaults to 'present'
+#
+# [*install_service*]
+#   (optional) Whether to install and enable the service
+#   Defaults to true
+#
+# [*allowed_start*]
+#   (optional) Start of allowed addresses for instances
+#   Defaults to undef
+#
+# [*allowed_end*]
+#   (optional) End of allowed addresses for instances
+#   Defaults to undef
+#
+# [*dns1*]
+#   (optional) First DNS server
+#   Defaults to undef
+#
+# [*dns2*]
+#   (optional) Second DNS server
+#   Defaults to undef
+#
+# [*multi_host*]
+#   (optional) Default value for multi_host in networks.
+#   Also, if set, some rpc network calls will be sent directly to host.
+#   Defaults to false.
+#
+# [*auto_assign_floating_ip*]
+#   (optional) Autoassigning floating IP to VM
+#   Defaults to false.
+#
+class nova::network(
+  $private_interface       = undef,
+  $fixed_range             = '10.0.0.0/8',
+  $public_interface        = undef,
+  $num_networks            = 1,
+  $network_size            = 255,
+  $floating_range          = false,
+  $enabled                 = true,
+  $network_manager         = 'nova.network.manager.FlatDHCPManager',
+  $config_overrides        = {},
+  $create_networks         = true,
+  $ensure_package          = 'present',
+  $install_service         = true,
+  $allowed_start           = undef,
+  $allowed_end             = undef,
+  $dns1                    = undef,
+  $dns2                    = undef,
+  $multi_host              = false,
+  $auto_assign_floating_ip = false,
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  warning('nova-network is deprecated in Newton and will be removed in the future.')
+
+  # forward all ipv4 traffic
+  # this is required for the vms to pass through the gateways
+  # public interface
+  Exec {
+    path => $::path
+  }
+
+  ensure_resource('sysctl::value', 'net.ipv4.ip_forward', { value => '1' })
+
+  if $floating_range {
+    nova_config {
+      'DEFAULT/floating_range':          value => $floating_range;
+      'DEFAULT/auto_assign_floating_ip': value => $auto_assign_floating_ip;
+    }
+  }
+
+  nova_config {
+    'DEFAULT/multi_host': value => $multi_host;
+  }
+
+  if has_key($config_overrides, 'vlan_start') {
+    $vlan_start = $config_overrides['vlan_start']
+  } else {
+    $vlan_start = undef
+  }
+
+  if $install_service {
+    nova::generic_service { 'network':
+      enabled        => $enabled,
+      package_name   => $::nova::params::network_package_name,
+      service_name   => $::nova::params::network_service_name,
+      ensure_package => $ensure_package,
+      before         => Exec['networking-refresh']
+    }
+
+    # because nova_network provider uses nova client, so it assumes
+    # that nova-network service is running already
+    Service<| title == 'nova-network' |> -> Nova_network<| |>
+    if $create_networks {
+      if $enabled {
+        nova::manage::network { 'nova-vm-net':
+          network       => $fixed_range,
+          num_networks  => $num_networks,
+          network_size  => $network_size,
+          vlan_start    => $vlan_start,
+          allowed_start => $allowed_start,
+          allowed_end   => $allowed_end,
+          dns1          => $dns1,
+          dns2          => $dns2,
+        }
+        if $floating_range {
+          nova::manage::floating { 'nova-vm-floating':
+            network => $floating_range,
+          }
+        }
+      } else {
+        warning('Can not create networks, when nova-network service is disabled.')
+      }
+    }
+  }
+
+  case $network_manager {
+
+    'nova.network.manager.FlatDHCPManager': {
+      # I am not proud of this
+      $parameters = { fixed_range      => $fixed_range,
+                      public_interface => $public_interface,
+                      flat_interface   => $private_interface
+      }
+      $resource_parameters = merge($config_overrides, $parameters)
+      $flatdhcp_resource = {'nova::network::flatdhcp' => $resource_parameters }
+      create_resources('class', $flatdhcp_resource)
+    }
+    'nova.network.manager.FlatManager': {
+      $parameters = { fixed_range      => $fixed_range,
+                      public_interface => $public_interface,
+                      flat_interface   => $private_interface
+      }
+      $resource_parameters = merge($config_overrides, $parameters)
+      $flat_resource = {'nova::network::flat' => $resource_parameters }
+      create_resources('class', $flat_resource)
+    }
+    'nova.network.manager.VlanManager': {
+      $parameters = { fixed_range      => $fixed_range,
+                      public_interface => $public_interface,
+                      vlan_interface   => $private_interface
+      }
+      $resource_parameters = merge($config_overrides, $parameters)
+      $vlan_resource = { 'nova::network::vlan' => $resource_parameters }
+      create_resources('class', $vlan_resource)
+    }
+    default: {
+      fail("Unsupported network manager: ${nova::network_manager} The supported network managers are \
+nova.network.manager.FlatManager, nova.network.FlatDHCPManager and nova.network.manager.VlanManager")
+    }
+  }
+
+}

+ 43 - 0
manifests/network/bridge.pp

@@ -0,0 +1,43 @@
+# bridge.pp
+#
+# === Parameters:
+#
+# [*ip*]
+#  (mandatory) IP address of the bridge interface.
+#
+# [*netmask*]
+#  (optional) Netmask of the bridge interface.
+#  Defaults to '255.255.255.0' (/24).
+#
+define nova::network::bridge (
+  $ip,
+  $netmask = '255.255.255.0'
+) {
+  include ::nova::deps
+
+  case $::osfamily {
+
+    'Debian': {
+      $context = '/files/etc/network/interfaces'
+      augeas { "bridge_${name}":
+        context => $context,
+        changes => [
+          "set auto[child::1 = '${name}']/1 ${name}",
+          "set iface[. = '${name}'] ${name}",
+          "set iface[. = '${name}']/family inet",
+          "set iface[. = '${name}']/method static",
+          "set iface[. = '${name}']/address ${ip}",
+          "set iface[. = '${name}']/netmask ${netmask}",
+          "set iface[. = '${name}']/bridge_ports none",
+        ],
+        notify  => Exec['networking-refresh'],
+      }
+    }
+
+    'RedHat' : {
+    }
+
+    default: { fail('nova::network_bridge currently only supports osfamily Debian and RedHat') }
+
+  }
+}

+ 42 - 0
manifests/network/flat.pp

@@ -0,0 +1,42 @@
+# == Class: nova::network::flat
+#
+# Configuration settings for nova flat network
+#
+# === Parameters:
+#
+# [*fixed_range*]
+#   (required) The IPv4 CIDR for the network
+#
+# [*flat_interface*]
+#   (optional) Interface that flat network will use for bridging
+#   Defaults to undef
+#
+# [*public_interface*]
+#   (optional) The interface to use for public traffic
+#   Defaults to undef
+#
+# [*flat_network_bridge*]
+#   (optional) The name of the bridge to use
+#   Defaults to 'br100'
+#
+class nova::network::flat (
+  $fixed_range,
+  $flat_interface=undef,
+  $public_interface   = undef,
+  $flat_network_bridge = 'br100'
+) {
+
+  include ::nova::deps
+
+  if $public_interface {
+    nova_config { 'DEFAULT/public_interface': value => $public_interface }
+  }
+
+  nova_config {
+    'DEFAULT/network_manager':     value => 'nova.network.manager.FlatManager';
+    'DEFAULT/fixed_range':         value => $fixed_range;
+    'DEFAULT/flat_interface':      value => $flat_interface;
+    'DEFAULT/flat_network_bridge': value => $flat_network_bridge;
+  }
+
+}

+ 79 - 0
manifests/network/flatdhcp.pp

@@ -0,0 +1,79 @@
+# == Class: nova::network::flatdhcp
+#
+# Configures nova-network with flat dhcp option
+#
+# === Parameters:
+#
+# [*fixed_range*]
+#   (required) The IPv4 CIDR for the flat network
+#
+# [*flat_interface*]
+#   (optional) FlatDHCP will bridge into this interface
+#   Defaults to undef
+#
+# [*public_interface*]
+#   (optional)
+#   Defaults to undef
+#
+# [*flat_network_bridge*]
+#   (optional) Bridge for simple network instances (
+#   Defaults to 'br100'
+#
+# [*force_dhcp_release*]
+#   (optional) Send a dhcp release on instance termination
+#   Defaults to true
+#
+# [*flat_injected*]
+#   (optional) Whether to attempt to inject network setup into guest
+#   Defaults to false
+#
+# [*dhcp_domain*]
+#   (optional) domain to use for building the hostnames
+#   Defaults to 'novalocal'
+#
+# [*dhcpbridge*]
+#   (optional) 'location of nova-dhcpbridge'
+#   Defaults to '/usr/bin/nova-dhcpbridge'
+#
+# [*dhcpbridge_flagfile*]
+#   (optional) location of flagfiles for dhcpbridge
+#   Defaults to '/etc/nova/nova.conf
+#
+class nova::network::flatdhcp (
+  $fixed_range,
+  $flat_interface      = undef,
+  $public_interface    = undef,
+  $flat_network_bridge = 'br100',
+  $force_dhcp_release  = true,
+  $flat_injected       = false,
+  $dhcp_domain         = 'novalocal',
+  $dhcpbridge          = '/usr/bin/nova-dhcpbridge',
+  $dhcpbridge_flagfile = '/etc/nova/nova.conf'
+) {
+
+  include ::nova::deps
+
+  if $::osfamily == 'RedHat' and $::operatingsystem != 'Fedora' {
+    package { 'dnsmasq-utils':
+      ensure => present,
+      tag    => ['openstack', 'nova-support-package'],
+    }
+  }
+
+  if $public_interface {
+    nova_config { 'DEFAULT/public_interface': value => $public_interface }
+  }
+
+  nova_config {
+    'DEFAULT/network_manager':     value => 'nova.network.manager.FlatDHCPManager';
+    'DEFAULT/fixed_range':         value => $fixed_range;
+    'DEFAULT/flat_interface':      value => $flat_interface;
+    'DEFAULT/flat_network_bridge': value => $flat_network_bridge;
+    'DEFAULT/force_dhcp_release':  value => $force_dhcp_release;
+    'DEFAULT/flat_injected':       value => $flat_injected;
+    'DEFAULT/dhcp_domain':         value => $dhcp_domain;
+    'DEFAULT/dhcpbridge':          value => $dhcpbridge;
+    'DEFAULT/dhcpbridge_flagfile': value => $dhcpbridge_flagfile;
+  }
+
+}

+ 237 - 0
manifests/network/neutron.pp

@@ -0,0 +1,237 @@
+# == Class: nova::network::neutron
+#
+# Configures Nova network to use Neutron.
+#
+# === Parameters:
+#
+# [*neutron_password*]
+#   (required) Password for connecting to Neutron network services in
+#   admin context through the OpenStack Identity service.
+#
+# [*neutron_auth_type*]
+#   Name of the auth type to load (string value)
+#   Defaults to 'v3password'
+#
+# [*neutron_url*]
+#   (optional) URL for connecting to the Neutron networking service.
+#   Defaults to 'http://127.0.0.1:9696'
+#
+# [*neutron_url_timeout*]
+#   (optional) Timeout value for connecting to neutron in seconds.
+#   Defaults to '30'
+#
+# [*neutron_project_name*]
+#   (optional) Project name for connecting to Neutron network services in
+#   admin context through the OpenStack Identity service.
+#   Defaults to 'services'
+#
+# [*neutron_project_domain_name*]
+#   (optional) Project Domain name for connecting to Neutron network services in
+#   admin context through the OpenStack Identity service.
+#   Defaults to 'Default'
+#
+# [*neutron_user_domain_name*]
+#   (optional) User Domain name for connecting to Neutron network services in
+#   admin context through the OpenStack Identity service.
+#   Defaults to 'Default'
+#
+# [*neutron_region_name*]
+#   (optional) Region name for connecting to neutron in admin context
+#   through the OpenStack Identity service.
+#   Defaults to 'RegionOne'
+#
+# [*neutron_username*]
+#   (optional) Username for connecting to Neutron network services in admin context
+#   through the OpenStack Identity service.
+#   Defaults to 'neutron'
+#
+# [*neutron_ovs_bridge*]
+#   (optional) Name of Integration Bridge used by Open vSwitch
+#   Defaults to 'br-int'
+#
+# [*neutron_extension_sync_interval*]
+#   (optional) Number of seconds before querying neutron for extensions
+#   Defaults to '600'
+#
+# [*neutron_auth_url*]
+#   (optional) Points to the OpenStack Identity server IP and port.
+#   This is the Identity (keystone) admin API server IP and port value,
+#   and not the Identity service API IP and port.
+#   Defaults to 'http://127.0.0.1:35357/v3'
+#
+# [*firewall_driver*]
+#   (optional) Firewall driver.
+#   This prevents nova from maintaining a firewall so it does not interfere
+#   with Neutron's. Set to 'nova.virt.firewall.IptablesFirewallDriver'
+#   to re-enable the Nova firewall.
+#   Defaults to 'nova.virt.firewall.NoopFirewallDriver'
+#
+# [*vif_plugging_is_fatal*]
+#   (optional) Fail to boot instance if vif plugging fails.
+#   This prevents nova from booting an instance if vif plugging notification
+#   is not received from neutron.
+#   Defaults to 'True'
+#
+# [*vif_plugging_timeout*]
+#   (optional) Number of seconds to wait for neutron vif plugging events.
+#   Set to '0' and vif_plugging_is_fatal to 'False' if vif plugging
+#   notification is not being used.
+#   Defaults to '300'
+#
+# [*dhcp_domain*]
+#   (optional) domain to use for building the hostnames
+#   Defaults to 'novalocal'
+#
+# DEPRECATED PARAMETERS
+# [*neutron_auth_strategy*]
+#   (optional) DEPRECATED.
+#
+# [*neutron_admin_password*]
+#   DEPRECATED. Password for connecting to Neutron network services
+#   in admin context through the OpenStack Identity service.
+#   Use neutron_password instead.
+#
+# [*neutron_admin_tenant_name*]
+#   (optional) DEPRECATED. Tenant name for connecting to Neutron network
+#   services in admin context through the OpenStack Identity service.
+#   Use neutron_project_name instead.
+#
+# [*neutron_admin_username*]
+#   (optional) DEPRECATED. Username for connecting to Neutron network services
+#   in admin context through the OpenStack Identity service.
+#   Use neutron_username instead.
+#
+# [*neutron_admin_auth_url*]
+#   (optional) DEPRECATED. Points to the OpenStack Identity server IP and port.
+#   This is the Identity (keystone) admin API server IP and port value,
+#   and not the Identity service API IP and port.
+#   Use neutron_auth_url instead.
+#
+# [*neutron_default_tenant_id*]
+#   (optional) DEPRECATED. Default tenant id when creating neutron networks
+#
+# [*neutron_auth_plugin*]
+#   Name of the plugin to load (string value)
+#   Defaults to undef
+#
+# [*neutron_ca_certificates_file*]
+#   (optional) Location of ca certicates file to use for neutronclient requests.
+#   Defaults to undef
+#
+class nova::network::neutron (
+  $neutron_password                = false,
+  $neutron_auth_type               = 'v3password',
+  $neutron_project_name            = 'services',
+  $neutron_project_domain_name     = 'Default',
+  $neutron_username                = 'neutron',
+  $neutron_user_domain_name        = 'Default',
+  $neutron_auth_url                = 'http://127.0.0.1:35357/v3',
+  $neutron_url                     = 'http://127.0.0.1:9696',
+  $neutron_url_timeout             = '30',
+  $neutron_region_name             = 'RegionOne',
+  $neutron_ovs_bridge              = 'br-int',
+  $neutron_extension_sync_interval = '600',
+  $firewall_driver                 = 'nova.virt.firewall.NoopFirewallDriver',
+  $vif_plugging_is_fatal           = true,
+  $vif_plugging_timeout            = '300',
+  $dhcp_domain                     = 'novalocal',
+  # DEPRECATED PARAMETERS
+  $neutron_admin_password          = false,
+  $neutron_auth_strategy           = undef,
+  $neutron_admin_tenant_name       = undef,
+  $neutron_admin_username          = undef,
+  $neutron_admin_auth_url          = undef,
+  $neutron_default_tenant_id       = undef,
+  $neutron_auth_plugin             = undef,
+  $neutron_ca_certificates_file    = undef,
+) {
+
+  include ::nova::deps
+
+  # neutron_admin params removed in Mitaka
+  if $neutron_password {
+    $neutron_password_real = $neutron_password
+  } else {
+    if $neutron_admin_password {
+      warning('neutron_admin_password is deprecated. Use neutron_password')
+      $neutron_password_real = $neutron_admin_password
+    } else {
+      fail('neutron_password is required')
+    }
+  }
+
+  # neutron_auth_plugin deprecated in Newton
+  if $neutron_auth_plugin {
+    warning('neutron_auth_plugin parameter is deprecated and will be removed in a future release, use neutron_auth_type instead.')
+    $neutron_auth_type_real = $neutron_auth_plugin
+  } else {
+    $neutron_auth_type_real = $neutron_auth_type
+  }
+
+  if $neutron_admin_tenant_name {
+    warning('neutron_admin_tenant_name is deprecated. Use neutron_project_name')
+    $neutron_project_name_real = $neutron_admin_tenant_name
+  } else {
+    $neutron_project_name_real = $neutron_project_name
+  }
+
+  if $neutron_admin_username {
+    warning('neutron_admin_username is deprecated. Use neutron_username')
+    $neutron_username_real = $neutron_admin_username
+  } else {
+    $neutron_username_real = $neutron_username
+  }
+
+  if $neutron_admin_auth_url {
+    warning('neutron_admin_auth_url is deprecated. Use neutron_auth_url')
+    $neutron_auth_url_real = $neutron_admin_auth_url
+  } else {
+    $neutron_auth_url_real = $neutron_auth_url
+  }
+
+  # neutron_auth_strategy removed in Mitaka
+  if $neutron_auth_strategy {
+    warning('neutron_auth_strategy is deprecated')
+  }
+  nova_config {
+    'neutron/auth_strategy': ensure => absent;
+  }
+
+  # neutron_default_tenant_id removed in Mitaka
+  # the parameter is deprecated but still can be used if needed
+  if $neutron_default_tenant_id {
+    warning('neutron_default_tenant_id is deprecated')
+    nova_config {
+      'neutron/default_tenant_id': value => $neutron_default_tenant_id;
+    }
+  } else {
+    nova_config {
+      'neutron/default_tenant_id': ensure => absent;
+    }
+  }
+
+  nova_config {
+    'DEFAULT/dhcp_domain':             value => $dhcp_domain;
+    '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/use_neutron':             value => true;
+    'neutron/url':                     value => $neutron_url;
+    'neutron/timeout':                 value => $neutron_url_timeout;
+    'neutron/project_name':            value => $neutron_project_name_real;
+    'neutron/project_domain_name':     value => $neutron_project_domain_name;
+    'neutron/region_name':             value => $neutron_region_name;
+    'neutron/username':                value => $neutron_username_real;
+    'neutron/user_domain_name':        value => $neutron_user_domain_name;
+    'neutron/password':                value => $neutron_password_real, secret => true;
+    'neutron/auth_url':                value => $neutron_auth_url_real;
+    'neutron/ovs_bridge':              value => $neutron_ovs_bridge;
+    'neutron/extension_sync_interval': value => $neutron_extension_sync_interval;
+    'neutron/auth_type':               value => $neutron_auth_type_real;
+  }
+
+  if $neutron_ca_certificates_file {
+    warning('neutron_ca_certificates_file parameter is deprecated, has no effect and will be dropped in a future release.')
+  }
+
+}

+ 72 - 0
manifests/network/vlan.pp

@@ -0,0 +1,72 @@
+# == Class: nova::network::vlan
+#
+# Configures nova network to use vlans
+#
+# === Parameters:
+#
+# [*fixed_range*]
+#   (required) IPv4 CIDR of the network
+#
+# [*vlan_interface*]
+#   (required) Physical ethernet adapter name for vlan networking
+#
+# [*public_interface*]
+#   (optional) Interface for public traffic
+#   Defaults to undef
+#
+# [*vlan_start*]
+#   (optional) First vlan to use
+#   Defaults to '300'
+#
+# [*force_dhcp_release*]
+#   (optional) Whether to send a dhcp release on instance termination
+#   Defaults to true
+#
+# [*dhcp_domain*]
+#   (optional) Domain to use for building the hostnames
+#   Defaults to 'novalocal'
+#
+# [*dhcpbridge*]
+#   (optional) location of nova-dhcpbridge
+#   Defaults to '/usr/bin/nova-dhcpbridge'
+#
+# [*dhcpbridge_flagfile*]
+#   (optional) location of flagfiles for dhcpbridge
+#   Defaults to '/etc/nova/nova.conf'
+#
+class nova::network::vlan (
+  $fixed_range,
+  $vlan_interface,
+  $public_interface    = undef,
+  $vlan_start          = '300',
+  $force_dhcp_release  = true,
+  $dhcp_domain         = 'novalocal',
+  $dhcpbridge          = '/usr/bin/nova-dhcpbridge',
+  $dhcpbridge_flagfile = '/etc/nova/nova.conf'
+) {
+
+  include ::nova::deps
+
+  if $::osfamily == 'RedHat' and $::operatingsystem != 'Fedora' {
+    package { 'dnsmasq-utils':
+      ensure => present,
+      tag    => ['openstack', 'nova-support-package'],
+    }
+  }
+
+  if $public_interface {
+    nova_config { 'DEFAULT/public_interface': value => $public_interface }
+  }
+
+  nova_config {
+    'DEFAULT/network_manager':     value => 'nova.network.manager.VlanManager';
+    'DEFAULT/fixed_range':         value => $fixed_range;
+    'DEFAULT/vlan_interface':      value => $vlan_interface;
+    'DEFAULT/vlan_start':          value => $vlan_start;
+    'DEFAULT/force_dhcp_release':  value => $force_dhcp_release;
+    'DEFAULT/dhcp_domain':         value => $dhcp_domain;
+    'DEFAULT/dhcpbridge':          value => $dhcpbridge;
+    'DEFAULT/dhcpbridge_flagfile': value => $dhcpbridge_flagfile;
+  }
+
+}

+ 44 - 0
manifests/objectstore.pp

@@ -0,0 +1,44 @@
+# == Class: nova::objectstore
+#
+# Manages the nova-objectstore service
+#
+# === Parameters:
+#
+# [*enabled*]
+#   (optional) Whether to enable the service
+#   Defaults to true
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (optional) The package state to set
+#   Defaults to 'present'
+#
+# [*bind_address*]
+#   (optional) The address to bind to
+#   Defaults to '0.0.0.0'
+#
+class nova::objectstore(
+  $enabled        = true,
+  $manage_service = true,
+  $ensure_package = 'present',
+  $bind_address   = '0.0.0.0'
+) {
+
+  include ::nova::deps
+  include ::nova::params
+
+  nova::generic_service { 'objectstore':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::objectstore_package_name,
+    service_name   => $::nova::params::objectstore_service_name,
+    ensure_package => $ensure_package,
+  }
+
+  nova_config {
+    'DEFAULT/s3_listen':  value => $bind_address;
+  }
+}

+ 144 - 0
manifests/params.pp

@@ -0,0 +1,144 @@
+# == Class: nova::params
+#
+# These parameters need to be accessed from several locations and
+# should be considered to be constant
+class nova::params {
+  include ::openstacklib::defaults
+
+  case $::osfamily {
+    'RedHat': {
+      # package names
+      $api_package_name              = 'openstack-nova-api'
+      $placement_package_name        = 'openstack-nova-placement-api'
+      $cells_package_name            = 'openstack-nova-cells'
+      $cert_package_name             = 'openstack-nova-cert'
+      $common_package_name           = 'openstack-nova-common'
+      $compute_package_name          = 'openstack-nova-compute'
+      $conductor_package_name        = 'openstack-nova-conductor'
+      $consoleauth_package_name      = 'openstack-nova-console'
+      $doc_package_name              = 'openstack-nova-doc'
+      $libvirt_package_name          = 'libvirt'
+      $libvirt_daemon_package_prefix = 'libvirt-daemon-'
+      $libvirt_nwfilter_package_name = 'libvirt-daemon-config-nwfilter'
+      $network_package_name          = 'openstack-nova-network'
+      $objectstore_package_name      = 'openstack-nova-objectstore'
+      $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'
+      $ceph_client_package_name      = 'ceph-common'
+      $genisoimage_package_name      = 'genisoimage'
+      # service names
+      $api_service_name              = 'openstack-nova-api'
+      $cells_service_name            = 'openstack-nova-cells'
+      $cert_service_name             = 'openstack-nova-cert'
+      $compute_service_name          = 'openstack-nova-compute'
+      $conductor_service_name        = 'openstack-nova-conductor'
+      $consoleauth_service_name      = 'openstack-nova-consoleauth'
+      $libvirt_service_name          = 'libvirtd'
+      $virtlock_service_name         = 'virtlockd'
+      $virtlog_service_name          = undef
+      $network_service_name          = 'openstack-nova-network'
+      $objectstore_service_name      = 'openstack-nova-objectstore'
+      $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'
+      $nova_wsgi_script_path         = '/var/www/cgi-bin/nova'
+      $nova_api_wsgi_script_source   = '/usr/lib/python2.7/site-packages/nova/wsgi/nova-api.py'
+      $placement_wsgi_script_source  = '/usr/bin/nova-placement-api'
+      case $::operatingsystem {
+        'RedHat', 'CentOS', 'Scientific', 'OracleLinux': {
+          if (versioncmp($::operatingsystemmajrelease, '7') < 0) {
+            $messagebus_service_name  = 'messagebus'
+            $special_service_provider = undef
+          } else {
+            if (versioncmp($::puppetversion, '4.5') < 0) {
+              $special_service_provider = 'redhat'
+            } else {
+              $special_service_provider = undef
+            }
+            $messagebus_service_name = 'dbus'
+          }
+        }
+        default: {
+          # not required on Fedora
+          $special_service_provider = undef
+          $messagebus_service_name  = undef
+        }
+      }
+    }
+    'Debian': {
+      # package names
+      $api_package_name             = 'nova-api'
+      $placement_package_name       = 'nova-placement-api'
+      $cells_package_name           = 'nova-cells'
+      $cert_package_name            = 'nova-cert'
+      $common_package_name          = 'nova-common'
+      $compute_package_name         = 'nova-compute'
+      $conductor_package_name       = 'nova-conductor'
+      $consoleauth_package_name     = 'nova-consoleauth'
+      $doc_package_name             = 'nova-doc'
+      $libvirt_package_name         = 'libvirt-bin'
+      $network_package_name         = 'nova-network'
+      $objectstore_package_name     = 'nova-objectstore'
+      $scheduler_package_name       = 'nova-scheduler'
+      $tgt_package_name             = 'tgt'
+      $serialproxy_package_name     = 'nova-serialproxy'
+      $ceph_client_package_name     = 'ceph'
+      $genisoimage_package_name     = 'genisoimage'
+      # service names
+      $api_service_name             = 'nova-api'
+      $cells_service_name           = 'nova-cells'
+      $cert_service_name            = 'nova-cert'
+      $compute_service_name         = 'nova-compute'
+      $conductor_service_name       = 'nova-conductor'
+      $consoleauth_service_name     = 'nova-consoleauth'
+      $network_service_name         = 'nova-network'
+      $objectstore_service_name     = 'nova-objectstore'
+      $scheduler_service_name       = 'nova-scheduler'
+      $vncproxy_service_name        = 'nova-novncproxy'
+      $serialproxy_service_name     = 'nova-serialproxy'
+      $tgt_service_name             = 'tgt'
+      $nova_log_group               = 'adm'
+      $nova_wsgi_script_path        = '/usr/lib/cgi-bin/nova'
+      $nova_api_wsgi_script_source  = '/usr/lib/python2.7/dist-packages/nova/wsgi/nova-api.py'
+      $placement_wsgi_script_source = '/usr/bin/nova-placement-api'
+      # debian specific nova config
+      $root_helper                  = 'sudo nova-rootwrap'
+      $lock_path                    = '/var/lock/nova'
+      case $::os_package_type {
+        '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
+          $virtlock_service_name           = undef
+          $virtlog_service_name            = undef
+        }
+        default: {
+          $spicehtml5proxy_package_name    = 'nova-spiceproxy'
+          $spicehtml5proxy_service_name    = 'nova-spiceproxy'
+          $vncproxy_package_name           = 'nova-novncproxy'
+          # Use default provider on Debian
+          $special_service_provider        = undef
+          $virtlock_service_name           = 'virtlockd'
+          $virtlog_service_name            = 'virtlogd'
+        }
+      }
+      $libvirt_service_name            = 'libvirtd'
+    }
+    default: {
+      fail("Unsupported osfamily: ${::osfamily} operatingsystem: ${::operatingsystem}, \
+module ${module_name} only support osfamily RedHat and Debian")
+    }
+  }
+
+}

+ 76 - 0
manifests/placement.pp

@@ -0,0 +1,76 @@
+# == Class: nova::placement
+#
+# Class for configuring [placement] section in nova.conf.
+#
+# === Parameters:
+#
+# [*password*]
+#   (required) Password for connecting to Nova Placement API service in
+#   admin context through the OpenStack Identity service.
+#
+# [*auth_type*]
+#   Name of the auth type to load (string value)
+#   Defaults to 'password'
+#
+# [*project_name*]
+#   (optional) Project name for connecting to Nova Placement API service in
+#   admin context through the OpenStack Identity service.
+#   Defaults to 'services'
+#
+# [*project_domain_name*]
+#   (optional) Project Domain name for connecting to Nova Placement API service in
+#   admin context through the OpenStack Identity service.
+#   Defaults to 'Default'
+#
+# [*user_domain_name*]
+#   (optional) User Domain name for connecting to Nova Placement API service in
+#   admin context through the OpenStack Identity service.
+#   Defaults to 'Default'
+#
+# [*os_region_name*]
+#   (optional) Region name for connecting to Nova Placement API service in admin context
+#   through the OpenStack Identity service.
+#   Defaults to 'RegionOne'
+#
+# [*os_interface*]
+#   (optional) interface name name used for getting the keystone endpoint for
+#   the placement API.
+#   Defaults to $::os_service_default
+#
+# [*username*]
+#   (optional) Username for connecting to Nova Placement API service in admin context
+#   through the OpenStack Identity service.
+#   Defaults to 'placement'
+#
+# [*auth_url*]
+#   (optional) Points to the OpenStack Identity server IP and port.
+#   This is the Identity (keystone) admin API server IP and port value,
+#   and not the Identity service API IP and port.
+#   Defaults to 'http://127.0.0.1:35357/v3'
+#
+class nova::placement(
+  $password            = false,
+  $auth_type           = 'password',
+  $auth_url            = 'http://127.0.0.1:35357/v3',
+  $os_region_name      = 'RegionOne',
+  $os_interface        = $::os_service_default,
+  $project_domain_name = 'Default',
+  $project_name        = 'services',
+  $user_domain_name    = 'Default',
+  $username            = 'placement',
+) {
+  include ::nova::deps
+
+  nova_config {
+    'placement/auth_type':           value => $auth_type;
+    'placement/auth_url':            value => $auth_url;
+    'placement/password':            value => $password, secret => true;
+    'placement/project_domain_name': value => $project_domain_name;
+    'placement/project_name':        value => $project_name;
+    'placement/user_domain_name':    value => $user_domain_name;
+    'placement/username':            value => $username;
+    'placement/os_region_name':      value => $os_region_name;
+    'placement/os_interface':        value => $os_interface;
+  }
+
+}

+ 43 - 0
manifests/policy.pp

@@ -0,0 +1,43 @@
+# == 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)
+
+  $policy_defaults = {
+    'file_path' => $policy_path,
+    'require'   => Anchor['nova::config::begin'],
+    'notify'    => Anchor['nova::config::end'],
+  }
+
+  create_resources('openstacklib::policy::base', $policies, $policy_defaults)
+
+  oslo::policy { 'nova_config': policy_file => $policy_path }
+
+}

+ 189 - 0
manifests/quota.pp

@@ -0,0 +1,189 @@
+# == Class: nova::quota
+#
+# Class for overriding the default quota settings.
+#
+# === Parameters:
+#
+# [*quota_instances*]
+#   (optional) Number of instances
+#   Defaults to 10
+#
+# [*quota_cores*]
+#   (optional) Number of cores
+#   Defaults to 20
+#
+# [*quota_ram*]
+#   (optional) Ram in MB
+#   Defaults to 51200
+#
+# [*quota_volumes*]
+#   (optional) Deprecated. This parameter does nothing and will be removed.
+#   Defaults to undef
+#
+# [*quota_gigabytes*]
+#   (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_injected_file_content_bytes*]
+#   (optional) Maximum size in bytes of injected files
+#   Defaults to 10240
+#
+# [*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
+#
+# [*quota_security_groups*]
+#   (optional) Number of security groups
+#   Defaults to 10
+#
+# [*quota_security_group_rules*]
+#   (optional) Number of security group rules
+#   Defaults to 20
+#
+# [*quota_key_pairs*]
+#   (optional) Number of key pairs
+#   Defaults to 100
+#
+# [*quota_server_groups*]
+#   (optional) Number of server groups per project
+#   Defaults to 10
+#
+# [*quota_server_group_members*]
+#   (optional) Number of servers per server group
+#   Defaults to 10
+#
+# [*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
+#
+# [*quota_driver*]
+#   (optional) Deprecated. Driver to use for quota checks
+#   Defaults to undef
+#
+class nova::quota(
+  $quota_instances = 10,
+  $quota_cores = 20,
+  $quota_ram = 51200,
+  $quota_floating_ips = 10,
+  $quota_fixed_ips = -1,
+  $quota_metadata_items = 128,
+  $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 = 100,
+  $quota_server_groups = 10,
+  $quota_server_group_members = 10,
+  $reservation_expire = 86400,
+  $until_refresh = 0,
+  $max_age = 0,
+  # 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,
+  $quota_driver = undef,
+) {
+  include ::nova::deps
+
+  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_driver {
+    warning('The quota_driver 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_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/quota_server_groups':               value => $quota_server_groups;
+    'DEFAULT/quota_server_group_members':        value => $quota_server_group_members;
+    'DEFAULT/reservation_expire':                value => $reservation_expire;
+    'DEFAULT/until_refresh':                     value => $until_refresh;
+    'DEFAULT/max_age':                           value => $max_age;
+  }
+
+}

+ 75 - 0
manifests/rabbitmq.pp

@@ -0,0 +1,75 @@
+# == Class: nova::rabbitmq
+#
+# Installs and manages rabbitmq server for nova
+#
+# == Parameters:
+#
+# [*userid*]
+#   (optional) The username to use when connecting to Rabbit
+#   Defaults to 'guest'
+#
+# [*password*]
+#   (optional) The password to use when connecting to Rabbit
+#   Defaults to 'guest'
+#
+# [*port*]
+#   (optional) Deprecated. The port to use when connecting to Rabbit
+#   This parameter keeps backward compatibility when we used to manage
+#   RabbitMQ service.
+#   Defaults to '5672'
+#
+# [*virtual_host*]
+#   (optional) The virtual host to use when connecting to Rabbit
+#   Defaults to '/'
+#
+# [*cluster_disk_nodes*]
+#   (optional) Enables/disables RabbitMQ clustering.  Specify an array of Rabbit Broker
+#   IP addresses to configure clustering.
+#   Defaults to false
+#
+# [*enabled*]
+#   (optional) Deprecated. Whether to enable the Rabbit resources
+#   This parameter keeps backward compatibility when we used to manage
+#   RabbitMQ service.
+#   Defaults to true
+#
+class nova::rabbitmq(
+  $userid             ='guest',
+  $password           ='guest',
+  $virtual_host       ='/',
+  # DEPRECATED PARAMETER
+  $cluster_disk_nodes = false,
+  $enabled            = true,
+  $port               ='5672',
+) {
+
+  warning('nova::rabbitmq class is deprecated and will be removed in next release. Make other plans to configure rabbitmq resources.')
+
+  include ::nova::deps
+
+  if ($enabled) {
+    if $userid == 'guest' {
+      $delete_guest_user = false
+    } else {
+      $delete_guest_user = true
+      rabbitmq_user { $userid:
+        admin    => true,
+        password => $password,
+        provider => 'rabbitmqctl',
+      }
+      # I need to figure out the appropriate permissions
+      rabbitmq_user_permissions { "${userid}@${virtual_host}":
+        configure_permission => '.*',
+        write_permission     => '.*',
+        read_permission      => '.*',
+        provider             => 'rabbitmqctl',
+      }
+    }
+    rabbitmq_vhost { $virtual_host:
+      provider => 'rabbitmqctl',
+    }
+  }
+
+  # Only start Nova after the queue is up
+  Class['nova::rabbitmq'] -> Anchor['nova::service::end']
+}

+ 50 - 0
manifests/scheduler.pp

@@ -0,0 +1,50 @@
+# == Class: nova::scheduler
+#
+# Install and manage nova scheduler
+#
+# === Parameters:
+#
+# [*enabled*]
+#   (optional) Whether to run the scheduler service
+#   Defaults to true
+#
+# [*manage_service*]
+#   (optional) Whether to start/stop the service
+#   Defaults to true
+#
+# [*ensure_package*]
+#   (optional) The state of the scheduler package
+#   Defaults to 'present'
+#
+# [*scheduler_driver*]
+#   (optional) Default driver to use for the scheduler
+#   Defaults to 'filter_scheduler'
+#
+class nova::scheduler(
+  $enabled          = true,
+  $manage_service   = true,
+  $ensure_package   = 'present',
+  $scheduler_driver = 'filter_scheduler',
+) {
+
+  include ::nova::deps
+  include ::nova::db
+  include ::nova::params
+
+  nova::generic_service { 'scheduler':
+    enabled        => $enabled,
+    manage_service => $manage_service,
+    package_name   => $::nova::params::scheduler_package_name,
+    service_name   => $::nova::params::scheduler_service_name,
+    ensure_package => $ensure_package,
+  }
+
+  nova_config {
+    'scheduler/driver': value => $scheduler_driver;
+  }
+
+  # TODO(aschultz): old options, remove in P
+  nova_config {
+    'DEFAULT/scheduler_driver': ensure => 'absent';
+  }
+}

+ 256 - 0
manifests/scheduler/filter.pp

@@ -0,0 +1,256 @@
+# == Class: nova::scheduler::filter
+#
+# This class is aim to configure nova.scheduler filter
+#
+# === Parameters:
+#
+# [*scheduler_max_attempts*]
+#   (optional) Maximum number of attempts to schedule an instance
+#   Defaults to '3'
+#
+# [*scheduler_host_subset_size*]
+#   (optional) defines the subset size that a host is chosen from
+#   Defaults to '1'
+#
+# [*max_io_ops_per_host*]
+#   (optional) Ignore hosts that have too many builds/resizes/snaps/migrations
+#   Defaults to '8'
+#
+# [*isolated_images*]
+#   (optional) An array of images to run on isolated host
+#   Defaults to $::os_service_default
+#
+# [*isolated_hosts*]
+#   (optional) An array of hosts reserved for specific images
+#   Defaults to $::os_service_default
+#
+# [*max_instances_per_host*]
+#   (optional) Ignore hosts that have too many instances
+#   Defaults to '50'
+#
+# [*scheduler_available_filters*]
+#   (optional) An array with filter classes available to the scheduler.
+#   Example: ['first.filter.class', 'second.filter.class']
+#   Defaults to ['nova.scheduler.filters.all_filters']
+#
+# [*scheduler_default_filters*]
+#   (optional) An array of filters to be used by default
+#   Defaults to $::os_service_default
+#
+# [*scheduler_weight_classes*]
+#   (optional) Which weight class names to use for weighing hosts
+#   Defaults to 'nova.scheduler.weights.all_weighers'
+#
+# [*baremetal_scheduler_default_filters*]
+#   (optional) An array of filters to be used by default for baremetal hosts
+#   Defaults to $::os_service_default
+#
+# [*scheduler_use_baremetal_filters*]
+#   (optional) Use baremetal_scheduler_default_filters or not.
+#   Defaults to false
+#
+# [*periodic_task_interval*]
+#   (optional) This value controls how often (in seconds) to run periodic tasks
+#   in the scheduler. The specific tasks that are run for each period are
+#   determined by the particular scheduler being used.
+#   Defaults to $::os_service_default
+#
+# [*track_instance_changes*]
+#   (optional) Enable querying of individual hosts for instance information.
+#   Defaults to $::os_service_default
+#
+# [*ram_weight_multiplier*]
+#   (optional) Ram weight multipler ratio. This option determines how hosts
+#   with more or less available RAM are weighed.
+#   Defaults to $::os_service_default
+#
+# [*disk_weight_multiplier*]
+#   (optional) Disk weight multipler ratio. Multiplier used for weighing free
+#   disk space. Negative numbers mean to stack vs spread.
+#   Defaults to $::os_service_default
+#
+# [*io_ops_weight_multiplier*]
+#   (optional) IO operations weight multipler ratio. This option determines
+#   how hosts with differing workloads are weighed
+#   Defaults to $::os_service_default
+#
+# [*soft_affinity_weight_multiplier*]
+#   (optional) Multiplier used for weighing hosts for group soft-affinity
+#   Defaults to $::os_service_default
+#
+# [*soft_anti_affinity_weight_multiplier*]
+#   (optional) Multiplier used for weighing hosts for group soft-anti-affinity
+#   Defaults to $::os_service_default
+#
+# [*restrict_isolated_hosts_to_isolated_images*]
+#   (optional) Prevent non-isolated images from being built on isolated hosts.
+#   Defaults to $::os_service_default
+#
+# [*aggregate_image_properties_isolation_namespace*]
+#   (optional) Image property namespace for use in the host aggregate
+#   Defaults to $::os_service_default
+#
+# [*aggregate_image_properties_isolation_separator*]
+#   (optional) Separator character(s) for image property namespace and name
+#   Defaults to $::os_service_default
+#
+# DEPRECATED PARAMETERS
+#
+# [*cpu_allocation_ratio*]
+#   (optional) Virtual CPU to Physical CPU allocation ratio
+#   Defaults to undef
+#
+# [*ram_allocation_ratio*]
+#   (optional) Virtual ram to physical ram allocation ratio
+#   Defaults to undef
+#
+# [*disk_allocation_ratio*]
+#   (optional) Virtual disk to physical disk allocation ratio
+#   Defaults to undef
+#
+class nova::scheduler::filter (
+  $scheduler_max_attempts                         = '3',
+  $scheduler_host_subset_size                     = '1',
+  $max_io_ops_per_host                            = '8',
+  $max_instances_per_host                         = '50',
+  $isolated_images                                = $::os_service_default,
+  $isolated_hosts                                 = $::os_service_default,
+  $scheduler_available_filters                    = ['nova.scheduler.filters.all_filters'],
+  $scheduler_default_filters                      = $::os_service_default,
+  $scheduler_weight_classes                       = 'nova.scheduler.weights.all_weighers',
+  $baremetal_scheduler_default_filters            = $::os_service_default,
+  $scheduler_use_baremetal_filters                = false,
+  $periodic_task_interval                         = $::os_service_default,
+  $track_instance_changes                         = $::os_service_default,
+  $ram_weight_multiplier                          = $::os_service_default,
+  $disk_weight_multiplier                         = $::os_service_default,
+  $io_ops_weight_multiplier                       = $::os_service_default,
+  $soft_affinity_weight_multiplier                = $::os_service_default,
+  $soft_anti_affinity_weight_multiplier           = $::os_service_default,
+  $restrict_isolated_hosts_to_isolated_images     = $::os_service_default,
+  $aggregate_image_properties_isolation_namespace = $::os_service_default,
+  $aggregate_image_properties_isolation_separator = $::os_service_default,
+  # DEPRECATED PARAMETERS
+  $cpu_allocation_ratio                           = undef,
+  $ram_allocation_ratio                           = undef,
+  $disk_allocation_ratio                          = undef,
+) {
+
+  include ::nova::deps
+
+  # The following values are following this rule:
+  # - default is $::os_service_default so Puppet won't try to configure it.
+  # - if set, we'll validate it's an array that is not empty and configure the parameter.
+  # - Otherwise, fallback to default.
+  if !is_service_default($scheduler_default_filters) and !empty($scheduler_default_filters){
+    validate_array($scheduler_default_filters)
+    $scheduler_default_filters_real = join($scheduler_default_filters, ',')
+  } else {
+    $scheduler_default_filters_real = $::os_service_default
+  }
+
+  if is_array($scheduler_available_filters) {
+    if empty($scheduler_available_filters) {
+      $scheduler_available_filters_real = $::os_service_default
+    } else {
+      $scheduler_available_filters_real = $scheduler_available_filters
+    }
+  } else {
+    warning('scheduler_available_filters must be an array and will fail in the future')
+    $scheduler_available_filters_real = any2array($scheduler_available_filters)
+  }
+
+  if !is_service_default($baremetal_scheduler_default_filters) and !empty($baremetal_scheduler_default_filters){
+    validate_array($baremetal_scheduler_default_filters)
+    $baremetal_scheduler_default_filters_real = join($baremetal_scheduler_default_filters, ',')
+  } else {
+    $baremetal_scheduler_default_filters_real = $::os_service_default
+  }
+  if !is_service_default($isolated_images) and !empty($isolated_images){
+    validate_array($isolated_images)
+    $isolated_images_real = join($isolated_images, ',')
+  } else {
+    $isolated_images_real = $::os_service_default
+  }
+  if !is_service_default($isolated_hosts) and !empty($isolated_hosts){
+    validate_array($isolated_hosts)
+    $isolated_hosts_real = join($isolated_hosts, ',')
+  } else {
+    $isolated_hosts_real = $::os_service_default
+  }
+
+  if $cpu_allocation_ratio {
+    warning('cpu_allocation_ratio is deprecated in nova::scheduler::filter, please add to nova::init instead')
+  }
+
+  if $ram_allocation_ratio {
+    warning('ram_allocation_ratio is deprecated in nova::scheduler::filter, please add to nova::init instead')
+  }
+
+  if $disk_allocation_ratio {
+    warning('disk_allocation_ratio is deprecated in nova::scheduler::filter, please add to nova::init instead')
+  }
+
+  # TODO(aschultz): these should probably be in nova::scheduler ...
+  nova_config {
+    'scheduler/max_attempts':           value => $scheduler_max_attempts;
+    'scheduler/periodic_task_interval': value => $periodic_task_interval;
+  }
+
+  nova_config {
+    'filter_scheduler/host_subset_size':
+      value => $scheduler_host_subset_size;
+    'filter_scheduler/max_io_ops_per_host':
+      value => $max_io_ops_per_host;
+    'filter_scheduler/max_instances_per_host':
+      value => $max_instances_per_host;
+    'filter_scheduler/track_instance_changes':
+      value => $track_instance_changes;
+    'filter_scheduler/available_filters':
+      value => $scheduler_available_filters_real;
+    'filter_scheduler/weight_classes':
+      value => $scheduler_weight_classes;
+    'filter_scheduler/use_baremetal_filters':
+      value => $scheduler_use_baremetal_filters;
+    'filter_scheduler/enabled_filters':
+      value => $scheduler_default_filters_real;
+    'filter_scheduler/baremetal_enabled_filters':
+      value => $baremetal_scheduler_default_filters_real;
+    'filter_scheduler/isolated_images':
+      value => $isolated_images_real;
+    'filter_scheduler/isolated_hosts':
+      value => $isolated_hosts_real;
+    'filter_scheduler/ram_weight_multiplier':
+      value => $ram_weight_multiplier;
+    'filter_scheduler/disk_weight_multiplier':
+      value => $disk_weight_multiplier;
+    'filter_scheduler/io_ops_weight_multiplier':
+      value => $io_ops_weight_multiplier;
+    'filter_scheduler/soft_affinity_weight_multiplier':
+      value => $soft_affinity_weight_multiplier;
+    'filter_scheduler/soft_anti_affinity_weight_multiplier':
+      value => $soft_anti_affinity_weight_multiplier;
+    'filter_scheduler/restrict_isolated_hosts_to_isolated_images':
+      value => $restrict_isolated_hosts_to_isolated_images;
+    'filter_scheduler/aggregate_image_properties_isolation_namespace':
+      value => $aggregate_image_properties_isolation_namespace;
+    'filter_scheduler/aggregate_image_properties_isolation_separator':
+      value => $aggregate_image_properties_isolation_separator;
+  }
+
+  # TODO(aschultz): old options, remove in P
+  nova_config {
+    'DEFAULT/scheduler_max_attempts':              ensure => 'absent';
+    'DEFAULT/scheduler_host_subset_size':          ensure => 'absent';
+    'DEFAULT/max_io_ops_per_host':                 ensure => 'absent';
+    'DEFAULT/max_instances_per_host':              ensure => 'absent';
+    'DEFAULT/scheduler_available_filters':         ensure => 'absent';
+    'DEFAULT/scheduler_weight_classes':            ensure => 'absent';
+    'DEFAULT/scheduler_use_baremetal_filters':     ensure => 'absent';
+    'DEFAULT/scheduler_default_filters':           ensure => 'absent';
+    'DEFAULT/baremetal_scheduler_default_filters': ensure => 'absent';
+    'DEFAULT/isolated_images':                     ensure => 'absent';
+    'DEFAULT/isolated_hosts':                      ensure => 'absent';
+  }
+
+}

+ 51 - 0
manifests/serialproxy.pp

@@ -0,0 +1,51 @@
+# == 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::deps
+  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
+  }
+
+}

+ 0 - 0
manifests/spicehtml5proxy.pp


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