diff --git a/deployment/puppet/fuel/.gitignore b/deployment/puppet/fuel/.gitignore new file mode 100644 index 0000000000..b5db85e051 --- /dev/null +++ b/deployment/puppet/fuel/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml diff --git a/deployment/puppet/fuel/README b/deployment/puppet/fuel/README new file mode 100644 index 0000000000..e69de29bb2 diff --git a/deployment/puppet/fuel/examples/astute.pp b/deployment/puppet/fuel/examples/astute.pp new file mode 100644 index 0000000000..bc197849a5 --- /dev/null +++ b/deployment/puppet/fuel/examples/astute.pp @@ -0,0 +1,17 @@ +notice('MODULAR: astute.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +$bootstrap_settings = pick($::fuel_settings['BOOTSTRAP'], {}) +$bootstrap_flavor = pick($bootstrap_settings['flavor'], 'centos') + +class { 'fuel::astute': + rabbitmq_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + rabbitmq_astute_user => $::fuel_settings['astute']['user'], + rabbitmq_astute_password => $::fuel_settings['astute']['password'], + bootstrap_flavor => $bootstrap_flavor, +} + +fuel::systemd { 'astute': + require => Class['fuel::astute'] +} diff --git a/deployment/puppet/fuel/examples/client.pp b/deployment/puppet/fuel/examples/client.pp new file mode 100644 index 0000000000..ba52405d2e --- /dev/null +++ b/deployment/puppet/fuel/examples/client.pp @@ -0,0 +1,19 @@ +notice('MODULAR: client.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +class { "fuel::nailgun::client": + server_address => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + keystone_user => $::fuel_settings['FUEL_ACCESS']['user'], + keystone_password => $::fuel_settings['FUEL_ACCESS']['password'], +} + +# This exec needs python-fuelclient to be installed and nailgun running +# Probably this should be moved to a separate task +exec {'sync_deployment_tasks': + command => 'fuel rel --sync-deployment-tasks --dir /etc/puppet/', + path => '/usr/bin', + tries => 12, + try_sleep => 10, + require => Class['fuel::nailgun::client'] +} diff --git a/deployment/puppet/fuel/examples/cobbler.pp b/deployment/puppet/fuel/examples/cobbler.pp new file mode 100644 index 0000000000..01edfce77a --- /dev/null +++ b/deployment/puppet/fuel/examples/cobbler.pp @@ -0,0 +1,54 @@ +notice('MODULAR: cobbler.pp') + +Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + +$fuel_settings = parseyaml($astute_settings_yaml) +$admin_network = $::fuel_settings['ADMIN_NETWORK'] +$nailgun_api_url = "http://${::fuel_settings['ADMIN_NETWORK']['ipaddress']}:8000/api" +$bootstrap_settings = pick($::fuel_settings['BOOTSTRAP'], {}) +$dhcp_gw = $::fuel_settings['ADMIN_NETWORK']['dhcp_gateway'] +if $dhcp_gw { + $dhcp_gateway = $dhcp_gw +} +else { + $dhcp_gateway = $cobbler_host +} + +class { "fuel::cobbler": + cobbler_user => $::fuel_settings['cobbler']['user'], + cobbler_password => $::fuel_settings['cobbler']['password'], + bootstrap_flavor => pick($bootstrap_settings['flavor'], 'centos'), + bootstrap_path => pick($bootstrap_settings['path'], '/var/www/nailgun/bootstraps/active_bootstrap'), + bootstrap_meta => pick(loadyaml("${bootstrap_path}/metadata.yaml"), {}), + server => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + name_server => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + next_server => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + mco_user => $::fuel_settings['mcollective']['user'], + mco_pass => $::fuel_settings['mcollective']['password'], + dns_upstream => $::fuel_settings['DNS_UPSTREAM'], + dns_domain => $::fuel_settings['DNS_DOMAIN'], + dns_search => $::fuel_settings['DNS_SEARCH'], + dhcp_interface => $::fuel_settings['ADMIN_NETWORK']['interface'], + nailgun_api_url => $nailgun_api_url, + bootstrap_ethdevice_timeout => pick($bootstrap_settings['ethdevice_timeout'], '120'), + # dhcp_start_address => $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_start'], + # dhcp_end_address => $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_end'], + # dhcp_netmask => $::fuel_settings['ADMIN_NETWORK']['netmask'], + # dhcp_gateway => $dhcp_gateway, +} + +fuel::systemd {['httpd', 'cobblerd', 'dnsmasq', 'xinetd']: + start => true, + template_path => 'fuel/systemd/restart_template.erb', + config_name => 'restart.conf', + require => Class["fuel::cobbler"], +} + +fuel::dnsmasq::dhcp_range {'default': + dhcp_start_address => $admin_network['dhcp_pool_start'], + dhcp_end_address => $admin_network['dhcp_pool_end'], + dhcp_netmask => $admin_network['netmask'], + dhcp_gateway => $admin_network['dhcp_gateway'], + next_server => $admin_network['ipaddress'], + notify => Service['dnsmasq'], +} diff --git a/deployment/puppet/fuel/examples/deploy.sh b/deployment/puppet/fuel/examples/deploy.sh new file mode 100755 index 0000000000..dec55250c5 --- /dev/null +++ b/deployment/puppet/fuel/examples/deploy.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright 2016 Mirantis, Inc. +# +# 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. + + +TASKS=" +host +cobbler +postgresql +rabbitmq +mcollective +astute +keystone +nailgun +ostf +nginx_repo +nginx_services +client +rsyslog +puppetsync +" + +for task in $TASKS; do + cat < { + next_server => $admin_network['ipaddress'], +} + +# Ensure dir with purge and recurse to remove configs for +# non-existing (removed) nodegroups and ip ranges +file { '/etc/dnsmasq.d': + ensure => 'directory', + recurse => true, + purge => true, +} + +# Create admin networks dhcp-range files except for 'default' nodegroup +# by creating Nailgun::Dnsmasq::Dhcp_range puppet resources +create_dnsmasq_dhcp_ranges($admin_networks) diff --git a/deployment/puppet/fuel/examples/host.pp b/deployment/puppet/fuel/examples/host.pp new file mode 100644 index 0000000000..d6249b29b3 --- /dev/null +++ b/deployment/puppet/fuel/examples/host.pp @@ -0,0 +1,252 @@ +notice('MODULAR: host.pp') + +Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + +$fuel_settings = parseyaml($astute_settings_yaml) + +#Purge empty NTP server entries +$ntp_servers = delete(delete_undef_values([$::fuel_settings['NTP1'], + $::fuel_settings['NTP2'], $::fuel_settings['NTP3']]), '') + +# Vars for File['/etc/resolv.conf'] +$dns_domain = $::fuel_settings['DNS_DOMAIN'] +$dns_search = $::fuel_settings['DNS_SEARCH'] +$dns_upstream = split($::fuel_settings['DNS_UPSTREAM'], ',') + +# Vars for File['/etc/dhcp/dhclient.conf'] +$cobbler_host = $::fuel_settings['ADMIN_NETWORK']['ipaddress'] + +# Vars for File['/etc/fuel-utils/config'] +$admin_ip = $::fuel_settings['ADMIN_NETWORK']['ipaddress'] + +# Vars for File['/etc/fuel/free_disk_check.yaml'] +$monitord_user = $::fuel_settings['keystone']['monitord_user'] +$monitord_password = $::fuel_settings['keystone']['monitord_password'] +$monitord_tenant = 'services' + +ensure_packages(["sudo", "ami-creator", "python-daemon", "httpd", + "iptables", "crontabs", "cronie-anacron", + "rsyslog", "rsync", "screen", "acpid", + "fuel-migrate", "dhcp", "yum-plugin-priorities", + "fuel-notify"]) + +Class['openstack::logrotate'] -> +Class['monit'] -> +Class['fuel::bootstrap_cli'] + +fuel::sshkeygen { '/root/.ssh/id_rsa': + homedir => '/root', + username => 'root', + groupname => 'root', + keytype => 'rsa', +} + +file { '/root/.ssh/config': + content => template('fuel/root_ssh_config.erb'), + owner => 'root', + group => 'root', + mode => '0600', +} + +file { '/var/log/remote': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0750', +} + +file { '/var/www/nailgun/dump': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', +} + +file { '/etc/dhcp/dhcp-enter-hooks': + content => template('fuel/dhcp-enter-hooks.erb'), + owner => 'root', + group => 'root', + mode => '0755', +} + +file { '/etc/resolv.conf': + content => template('fuel/resolv.conf.erb'), + owner => 'root', + group => 'root', + mode => '0644', +} + +file { '/etc/dhcp/dhclient.conf': + content => template('fuel/dhclient.conf.erb'), + owner => 'root', + group => 'root', + mode => '0644', +} + +#Suppress kernel messages to console +sysctl::value{'kernel.printk': value => '4 1 1 7'} + +#Increase values for neighbour table +sysctl::value{'net.ipv4.neigh.default.gc_thresh1': value => '256'} +sysctl::value{'net.ipv4.neigh.default.gc_thresh2': value => '1024'} +sysctl::value{'net.ipv4.neigh.default.gc_thresh3': value => '2048'} + +service {'dhcrelay': + ensure => stopped, +} + +# Enable monit +class { 'monit': } + +# Free disk space monitoring +Package['fuel-notify'] ~> Service['monit'] + +file { '/etc/fuel/free_disk_check.yaml': + content => template('fuel/free_disk_check.yaml.erb'), + owner => 'root', + group => 'root', + mode => '0755', +} + +# Change link to UI on upgrades from old releases +exec { "Change protocol and port in in issue": + command => 'sed -i -e "s|http://\(.*\):8000\(.*\)|https://\1:8443\2|g" /etc/issue', + onlyif => 'grep -q 8000 /etc/issue', +} + +if $::virtual != 'physical' { + if ($::acpi_event == true and $::acpid_version == '1') or $::acpid_version == '2' { + service { 'acpid': + ensure => 'running', + enable => true, + } + } +} + +class { 'osnailyfacter::atop': } + +class { 'osnailyfacter::ssh': + password_auth => 'yes', + listen_address => [$::fuel_settings['ADMIN_NETWORK']['ipaddress']], +} + +class { 'fuel::iptables': + admin_iface => $::fuel_settings['ADMIN_NETWORK']['interface'], + network_address => ipcalc_network_by_address_netmask($::fuel_settings['ADMIN_NETWORK']['ipaddress'],$::fuel_settings['ADMIN_NETWORK']['netmask']), + network_cidr => ipcalc_network_cidr_by_netmask($::fuel_settings['ADMIN_NETWORK']['netmask']), +} + +# FIXME(kozhukalov): this should be a part of repo management tool +class { 'fuel::auxiliaryrepos': + fuel_version => $::fuel_release, + repo_root => "/var/www/nailgun/${::fuel_openstack_version}", +} + +class { 'openstack::clocksync': + ntp_servers => $ntp_servers, + config_template => 'ntp/ntp.conf.erb', +} + +class { 'openstack::logrotate': + role => 'server', + rotation => 'weekly', + keep => '4', + minsize => '10M', + maxsize => '100M', +} + +class { 'fuel::bootstrap_cli': + settings => $::fuel_settings['BOOTSTRAP'], + direct_repo_addresses => [ $::fuel_settings['ADMIN_NETWORK']['ipaddress'], '127.0.0.1' ], + bootstrap_cli_package => 'fuel-bootstrap-cli', + config_path => '/etc/fuel-bootstrap-cli/fuel_bootstrap_cli.yaml', +} + +augeas { 'Remove ssh_config SendEnv defaults': + lens => 'ssh.lns', + incl => '/etc/ssh/ssh_config', + changes => [ + 'rm */SendEnv', + 'rm SendEnv', + ], +} + +augeas { 'Password aging and length settings': + lens => 'login_defs.lns', + incl => '/etc/login.defs', + changes => [ + 'set PASS_MAX_DAYS 365', + 'set PASS_MIN_DAYS 2', + 'set PASS_MIN_LEN 8', + 'set PASS_WARN_AGE 30' + ], +} + +augeas { 'Password complexity': + lens => 'pam.lns', + incl => '/etc/pam.d/system-auth', + changes => [ + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/control requisite", + "rm *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument", + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument[1] try_first_pass", + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument[2] retry=3", + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument[3] dcredit=-1", + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument[4] ucredit=-1", + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument[5] ocredit=-1", + "set *[type='password'][module='pam_pwquality.so' or module='pam_cracklib.so']/argument[6] lcredit=-1", + ], + onlyif => "match *[type='password'][control='requisite'][module='pam_pwquality.so' or module='pam_cracklib.so'] size > 0", +} + +augeas { 'Enable only SSHv2 connections from the master node': + lens => 'ssh.lns', + incl => '/etc/ssh/ssh_config', + changes => [ + 'rm Protocol', + 'ins Protocol before Host[1]', + 'set Protocol 2', + ], +} + +augeas { "Turn off sudo requiretty": + changes => [ + 'set /files/etc/sudoers/Defaults[*]/requiretty/negate ""', + ], +} + +file {'/etc/fuel-utils/config': + content => template('fuel/fuel_utils_config.erb'), + owner => 'root', + group => 'root', + mode => 0644, +} + +# The requirement of former mcollective container. +# This directory is used for building target OS images. +file {['/var/lib/fuel', '/var/lib/fuel/ibp']: + ensure => directory, + owner => 'root', + group => 'root', + mode => 0755, +} + +# The requirement of former mcollective container. +# TODO(kozhukalov): make sure we need this +file {'/var/lib/hiera': + ensure => directory, + owner => 'root', + group => 'root', + mode => 0755, +} + +# The requirement of former mcollective container. +# TODO(kozhukalov): make sure we need this +file {['/etc/puppet/hiera.yaml', '/var/lib/hiera/common.yaml']: + ensure => present, +} + +exec { 'create-loop-devices': + command => "/bin/bash -c 'for loopdev in \$(seq 1 9); do + mknod \"/dev/loop\${loopdev}\" -m0660 b 7 \${loopdev} || : +done'" +} diff --git a/deployment/puppet/fuel/examples/keystone.pp b/deployment/puppet/fuel/examples/keystone.pp new file mode 100644 index 0000000000..841cc21488 --- /dev/null +++ b/deployment/puppet/fuel/examples/keystone.pp @@ -0,0 +1,31 @@ +notice('MODULAR: keystone.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +class { 'fuel::keystone': + admin_token => $::fuel_settings['keystone']['admin_token'], + host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + auth_version => "v2.0", + db_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + db_name => $::fuel_settings['postgres']['keystone_dbname'], + db_user => $::fuel_settings['postgres']['keystone_user'], + db_password => $::fuel_settings['postgres']['keystone_password'], + + admin_password => $::fuel_settings['FUEL_ACCESS']['password'], + + monitord_user => $::fuel_settings['keystone']['monitord_user'], + monitord_password => $::fuel_settings['keystone']['monitord_password'], + + nailgun_user => $::fuel_settings['keystone']['nailgun_user'], + nailgun_password => $::fuel_settings['keystone']['nailgun_password'], + + ostf_user => $::fuel_settings['keystone']['ostf_user'], + ostf_password => $::fuel_settings['keystone']['ostf_password'], +} + +fuel::systemd {['openstack-keystone']: + start => true, + template_path => 'fuel/systemd/restart_template.erb', + config_name => 'restart.conf', + require => Class["fuel::keystone"], +} diff --git a/deployment/puppet/fuel/examples/mcollective.pp b/deployment/puppet/fuel/examples/mcollective.pp new file mode 100644 index 0000000000..00191ec460 --- /dev/null +++ b/deployment/puppet/fuel/examples/mcollective.pp @@ -0,0 +1,9 @@ +notice('MODULAR: mcollective.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +class { 'fuel::mcollective': + mco_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + mco_user => $::fuel_settings['mcollective']['user'], + mco_password => $::fuel_settings['mcollective']['password'], +} diff --git a/deployment/puppet/fuel/examples/nailgun.pp b/deployment/puppet/fuel/examples/nailgun.pp new file mode 100644 index 0000000000..77db529cd8 --- /dev/null +++ b/deployment/puppet/fuel/examples/nailgun.pp @@ -0,0 +1,70 @@ +notice('MODULAR: nailgun.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +if $::fuel_settings['FEATURE_GROUPS'] { + $feature_groups = $::fuel_settings['FEATURE_GROUPS'] +} +else { + $feature_groups = [] +} + +$debug = pick($::fuel_settings['DEBUG'],false) +if $debug { + $nailgun_log_level = "DEBUG" +} else { + $nailgun_log_level = "INFO" +} + +if empty($::fuel_settings['NTP1']) and + empty($::fuel_settings['NTP2']) and + empty($::fuel_Settings['NTP3']) { + $ntp_servers = $::fuel_settings['ADMIN_NETWORK']['ipaddress'] +} else { + $ntp_server_list = delete(delete_undef_values([$::fuel_settings['NTP1'], + $::fuel_settings['NTP2'], $::fuel_settings['NTP3']]), '') + $ntp_servers = join($ntp_server_list, ', ') +} + +Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + +class { "fuel::nailgun::server": + keystone_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + keystone_user => $::fuel_settings['keystone']['nailgun_user'], + keystone_password => $::fuel_settings['keystone']['nailgun_password'], + + feature_groups => $feature_groups, + nailgun_log_level => $nailgun_log_level, + + db_name => $::fuel_settings['postgres']['nailgun_dbname'], + db_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + db_user => $::fuel_settings['postgres']['nailgun_user'], + db_password => $::fuel_settings['postgres']['nailgun_password'], + + rabbitmq_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + rabbitmq_astute_user => $::fuel_settings['astute']['user'], + rabbitmq_astute_password => $::fuel_settings['astute']['password'], + + admin_network => ipcalc_network_by_address_netmask($::fuel_settings['ADMIN_NETWORK']['ipaddress'], $::fuel_settings['ADMIN_NETWORK']['netmask']), + admin_network_cidr => ipcalc_network_cidr_by_netmask($::fuel_settings['ADMIN_NETWORK']['netmask']), + admin_network_size => ipcalc_network_count_addresses($::fuel_settings['ADMIN_NETWORK']['ipaddress'], $::fuel_settings['ADMIN_NETWORK']['netmask']), + admin_network_first => $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_start'], + admin_network_last => $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_end'], + admin_network_netmask => $::fuel_settings['ADMIN_NETWORK']['netmask'], + admin_network_mac => $::fuel_settings['ADMIN_NETWORK']['mac'], + admin_network_ip => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + admin_network_gateway => $::fuel_settings['ADMIN_NETWORK']['dhcp_gateway'], + + cobbler_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + cobbler_url => "http://${::fuel_settings['ADMIN_NETWORK']['ipaddress']}:80/cobbler_api", + cobbler_user => $::fuel_settings['cobbler']['user'], + cobbler_password => $::fuel_settings['cobbler']['password'], + + mco_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + mco_user => $::fuel_settings['mcollective']['user'], + mco_password => $::fuel_settings['mcollective']['password'], + + ntp_upstream => $ntp_servers, + dns_upstream => regsubst($::fuel_settings['DNS_UPSTREAM'], ' ', ', ', 'G'), + dns_domain => $::fuel_settings['DNS_DOMAIN'], +} diff --git a/deployment/puppet/fuel/examples/nginx_repo.pp b/deployment/puppet/fuel/examples/nginx_repo.pp new file mode 100644 index 0000000000..88eb9e4536 --- /dev/null +++ b/deployment/puppet/fuel/examples/nginx_repo.pp @@ -0,0 +1,18 @@ +notice('MODULAR: nginx_repo.pp') + +case $::osfamily { + 'RedHat': { + if ($::operatingsystemrelease =~ /^7.*/) { + $service_enabled = true + } else { + $service_enabled = false + } + } + default: { $service_enabled = false } +} + +node default { + class { '::fuel::nginx::repo': + service_enabled => $service_enabled, + } +} diff --git a/deployment/puppet/fuel/examples/nginx_services.pp b/deployment/puppet/fuel/examples/nginx_services.pp new file mode 100644 index 0000000000..240e66fc5f --- /dev/null +++ b/deployment/puppet/fuel/examples/nginx_services.pp @@ -0,0 +1,34 @@ +notice('MODULAR: nginx_services.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +if $fuel_settings['SSL'] { + $force_https = $fuel_settings['SSL']['force_https'] +} else { + $force_https = undef +} + +case $::osfamily { + 'RedHat': { + if ($::operatingsystemrelease =~ /^7.*/) { + $service_enabled = true + } else { + $service_enabled = false + } + } + default: { $service_enabled = false } +} + +node default { + + Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + + class { 'fuel::nginx::services': + ostf_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + keystone_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + nailgun_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + service_enabled => $service_enabled, + ssl_enabled => true, + force_https => $force_https, + } +} diff --git a/deployment/puppet/fuel/examples/ostf.pp b/deployment/puppet/fuel/examples/ostf.pp new file mode 100644 index 0000000000..041576c2b3 --- /dev/null +++ b/deployment/puppet/fuel/examples/ostf.pp @@ -0,0 +1,21 @@ +notice('MODULAR: ostf.pp') + +Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + +$fuel_settings = parseyaml($astute_settings_yaml) + +class { "fuel::ostf": + dbname => $::fuel_settings['postgres']['ostf_dbname'], + dbuser => $::fuel_settings['postgres']['ostf_user'], + dbpass => $::fuel_settings['postgres']['ostf_password'], + dbhost => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + nailgun_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + host => "0.0.0.0", + keystone_host => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + keystone_ostf_user => $::fuel_settings['keystone']['ostf_user'], + keystone_ostf_pass => $::fuel_settings['keystone']['ostf_password'], +} + +fuel::systemd {['ostf']: + require => Class["fuel::ostf"], +} diff --git a/deployment/puppet/fuel/examples/postgresql.pp b/deployment/puppet/fuel/examples/postgresql.pp new file mode 100644 index 0000000000..5d2b712c88 --- /dev/null +++ b/deployment/puppet/fuel/examples/postgresql.pp @@ -0,0 +1,17 @@ +notice('MODULAR: postgresql.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +class { "fuel::postgresql": + nailgun_db_name => $::fuel_settings['postgres']['nailgun_dbname'], + nailgun_db_user => $::fuel_settings['postgres']['nailgun_user'], + nailgun_db_password => $::fuel_settings['postgres']['nailgun_password'], + + keystone_db_name => $::fuel_settings['postgres']['keystone_dbname'], + keystone_db_user => $::fuel_settings['postgres']['keystone_user'], + keystone_db_password => $::fuel_settings['postgres']['keystone_password'], + + ostf_db_name => $::fuel_settings['postgres']['ostf_dbname'], + ostf_db_user => $::fuel_settings['postgres']['ostf_user'], + ostf_db_password => $::fuel_settings['postgres']['ostf_password'], +} diff --git a/deployment/puppet/fuel/examples/puppetsync.pp b/deployment/puppet/fuel/examples/puppetsync.pp new file mode 100644 index 0000000000..391e5d2e12 --- /dev/null +++ b/deployment/puppet/fuel/examples/puppetsync.pp @@ -0,0 +1,14 @@ +notice('MODULAR: puppetsync.pp') + +Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + +$fuel_settings = parseyaml($astute_settings_yaml) + +class { "fuel::puppetsync": } + +fuel::systemd {['rsyncd']: + start => true, + template_path => 'fuel/systemd/restart_template.erb', + config_name => 'restart.conf', + require => Class["fuel::puppetsync"], +} diff --git a/deployment/puppet/fuel/examples/rabbitmq.pp b/deployment/puppet/fuel/examples/rabbitmq.pp new file mode 100644 index 0000000000..eb5d6e522a --- /dev/null +++ b/deployment/puppet/fuel/examples/rabbitmq.pp @@ -0,0 +1,18 @@ +notice('MODULAR: rabbitmq.pp') + +$fuel_settings = parseyaml($astute_settings_yaml) + +$thread_pool_calc = min(100,max(12*$physicalprocessorcount,30)) + +class { 'fuel::rabbitmq': + astute_user => $::fuel_settings['astute']['user'], + astute_password => $::fuel_settings['astute']['password'], + bind_ip => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + mco_user => $::fuel_settings['mcollective']['user'], + mco_password => $::fuel_settings['mcollective']['password'], + env_config => { + 'RABBITMQ_SERVER_ERL_ARGS' => "+K true +A${thread_pool_calc} +P 1048576", + 'ERL_EPMD_ADDRESS' => $::fuel_settings['ADMIN_NETWORK']['ipaddress'], + 'NODENAME' => "rabbit@${::hostname}", + }, +} diff --git a/deployment/puppet/fuel/examples/rsyslog.pp b/deployment/puppet/fuel/examples/rsyslog.pp new file mode 100644 index 0000000000..4fcc4d4746 --- /dev/null +++ b/deployment/puppet/fuel/examples/rsyslog.pp @@ -0,0 +1,39 @@ +notice('MODULAR: rsyslog.pp') + +Class['rsyslog::server'] -> +Class['openstack::logrotate'] + +class {"::rsyslog::server": + enable_tcp => true, + enable_udp => true, + server_dir => '/var/log/', + port => 514, + high_precision_timestamps => true, +} + +# Fuel specific config for logging parse formats used for /var/log/remote +$show_timezone = true +$logconf = "${::rsyslog::params::rsyslog_d}30-remote-log.conf" +file { $logconf : + content => template('openstack/30-server-remote-log.conf.erb'), + require => Class['::rsyslog::server'], + owner => root, + group => $::rsyslog::params::run_group, + mode => 0640, + notify => Class["::rsyslog::service"], +} + +class { '::openstack::logrotate': + role => 'server', + rotation => 'weekly', + keep => '4', + minsize => '10M', + maxsize => '20M', +} + +fuel::systemd {'rsyslog': + start => true, + template_path => 'fuel/systemd/restart_template.erb', + config_name => 'restart.conf', + require => Class["::rsyslog::server"], +} diff --git a/deployment/puppet/fuel/lib/facter/acpi_event.rb b/deployment/puppet/fuel/lib/facter/acpi_event.rb new file mode 100644 index 0000000000..c9ceaa85fa --- /dev/null +++ b/deployment/puppet/fuel/lib/facter/acpi_event.rb @@ -0,0 +1,5 @@ +Facter.add('acpi_event') do + setcode do + File.exist?('/proc/acpi/event') + end +end diff --git a/deployment/puppet/fuel/lib/facter/acpid_version.rb b/deployment/puppet/fuel/lib/facter/acpid_version.rb new file mode 100644 index 0000000000..1c8ff54f0d --- /dev/null +++ b/deployment/puppet/fuel/lib/facter/acpid_version.rb @@ -0,0 +1,8 @@ +require 'facter' + +Facter.add('acpid_version') do + setcode do + version = Facter::Util::Resolution.exec('acpid -v 2>/dev/null') + version.split('-')[1][0] unless version.nil? + end +end diff --git a/deployment/puppet/fuel/lib/facter/fuel_openstack_version.rb b/deployment/puppet/fuel/lib/facter/fuel_openstack_version.rb new file mode 100644 index 0000000000..a354f2e338 --- /dev/null +++ b/deployment/puppet/fuel/lib/facter/fuel_openstack_version.rb @@ -0,0 +1,16 @@ +require 'facter' + +fuel_openstack_version_path = '/etc/fuel_openstack_version' +# FIXME(kozhukalov): This default value is necessary +# to solve chicken/egg problem. The thing is that +# deployment tests use the ISO where this file is not +# installed. This default value should be removed +# once the ISO is updated. +read_data = "2015.1.0-8.0" + +Facter.add('fuel_openstack_version') do + if File.exist?(fuel_openstack_version_path) + read_data = File.read(fuel_openstack_version_path).strip + end + setcode { read_data } +end diff --git a/deployment/puppet/fuel/lib/facter/fuel_release.rb b/deployment/puppet/fuel/lib/facter/fuel_release.rb new file mode 100644 index 0000000000..077c1bf649 --- /dev/null +++ b/deployment/puppet/fuel/lib/facter/fuel_release.rb @@ -0,0 +1,16 @@ +require 'facter' + +fuel_release_path = '/etc/fuel_release' +# FIXME(kozhukalov): This default value is necessary +# to solve chicken/egg problem. The thing is that +# deployment tests use the ISO where this file is not +# installed. This default value should be removed +# once the ISO is updated. +read_data = "8.0" + +Facter.add('fuel_release') do + if File.exist?(fuel_release_path) + read_data = File.read(fuel_release_path).strip + end + setcode { read_data } +end diff --git a/deployment/puppet/fuel/lib/facter/generate_fuel_key.rb b/deployment/puppet/fuel/lib/facter/generate_fuel_key.rb new file mode 100644 index 0000000000..409b257656 --- /dev/null +++ b/deployment/puppet/fuel/lib/facter/generate_fuel_key.rb @@ -0,0 +1,11 @@ +require 'facter' +fuel_uuid_path = [ '/etc/fuel/fuel-uuid', '/etc/fuel-uuid' ] + +fuel_uuid_path.each do |uuid_file| + if File.exist?(uuid_file) + Facter.add('generate_fuel_key') do + setcode { File.read(uuid_file).chomp } + end + break + end +end diff --git a/deployment/puppet/fuel/lib/facter/iops.rb b/deployment/puppet/fuel/lib/facter/iops.rb new file mode 100644 index 0000000000..6b42b80e3c --- /dev/null +++ b/deployment/puppet/fuel/lib/facter/iops.rb @@ -0,0 +1,15 @@ +require 'facter' + +# Requires sysstat package on Ubuntu and CentOS +# Fact iops totals tps values from iostat + +Facter.add('iops') do + confine :kernel => :linux + str = Facter::Util::Resolution.exec("iostat | grep -v 'dm-'" \ + " | awk '{print $2}'") + iops = 0 + str.split("\n").each do |iops_val| + iops = iops + iops_val.to_f + end + setcode { iops } +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb new file mode 100644 index 0000000000..1d51b1bdb5 --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb @@ -0,0 +1,33 @@ +require 'ipaddr' +require 'zlib' + +module Puppet::Parser::Functions + newfunction(:create_dnsmasq_dhcp_ranges, :doc => <<-EOS +Creates nailgun::dnsmasq::dhcp_range puppet resources from list of admin networks. + EOS +) do |args| + admin_nets = args[0] + unless admin_nets.is_a?(Array) and admin_nets[0].is_a?(Hash) + raise(Puppet::ParseError, 'Should pass list of hashes as a parameter') + end + admin_nets.each do |net| + net['ip_ranges'].each do |ip_range| + netmask = IPAddr.new('255.255.255.255').mask(net['cidr'].split('/')[1]).to_s + print_range = ip_range.join('_') + resource_name = sprintf("range_%08x", Zlib::crc32("#{print_range}_#{net['cidr']}").to_i) + range_comment = "# Environment: #{net['cluster_name']}\n# Nodegroup: #{net['node_group_name']}\n# IP range: #{ip_range}" + dhcp_range_resource = { + resource_name => { + 'file_header' => "# Generated automatically by puppet\n#{range_comment}", + 'dhcp_start_address' => ip_range[0], + 'dhcp_end_address' => ip_range[1], + 'dhcp_netmask' => netmask, + 'dhcp_gateway' => net['gateway'], + } + } + debug("Trying to create nailgun::dnsmasq::dhcp_range resource #{dhcp_range_resource}") + function_create_resources(['nailgun::dnsmasq::dhcp_range', dhcp_range_resource]) + end + end + end +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/extend_kopts.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/extend_kopts.rb new file mode 100644 index 0000000000..bb7c49af2c --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/extend_kopts.rb @@ -0,0 +1,60 @@ +module MultipleKopts + # Transform string into hash and provide array of keys: + # Example: + # Input data: "first=21 first=12 second=44" + # Output data: [{ first => "21 12", second => "44"}, [ first, first, second]] + def self.string_to_hash_with_keys(string) + hash, option_order = {}, [] + string.to_s.split(' ').each() do |e| + key, value = e.split("=", 2).map { |i| i.strip()} + hash[key] = hash.has_key?(key) ? "#{hash[key]} #{value}" : value + option_order << key + end + [hash, option_order] + end + + # Transform hash into string using key's order from 'keys' array: + # Example: + # Input data: { first => "21 12", second => "44"}, [ first, second] + # Output data: "first=21 first=12 second=44" + def self.hash_to_string(hash, keys) + string = "" + keys.each() do |key| + value = hash[key] + opt_string = value.nil? ? key : value.split(' ').map { |e| "#{key}=#{e}" }.join(' ') + string = "#{string} #{opt_string}" + end + string.strip() + end +end + +module Puppet::Parser::Functions + newfunction(:extend_kopts, :type => :rvalue, :doc => <<-EOS + This function changes "kopts" parameter if user modified it + and return the string. It takes two arguments: string from + metadata.yaml from "extend_kopts" option and default string + in format "key1=value1 key2=value2 key3". + For example: + + $metadata = loadyaml('path/to/metadata.yaml') + extend_kopts($metadata['extend_kopts'], 'key1=a key2=b") + + Function compare two strings, make changes into default option + and return it. + + So, if in the /path/to/metadata.yaml in the "extend_kopts" will be + "key3=c key4 key1=not_a", we will get in the output: + "key2=b key3=c key4 key1=not_a". + EOS + ) do |args| + + raise Puppet::ParseError, ("extend_kopts(): wrong number of arguments - #{args.length}, must be 2") unless args.length == 2 + + hash_new_kopts, new_kopts_keys = MultipleKopts.string_to_hash_with_keys(args[0]) + hash_default_kopts, default_kopts_keys = MultipleKopts.string_to_hash_with_keys(args[1]) + + keys = (new_kopts_keys + default_kopts_keys).uniq() + + return MultipleKopts.hash_to_string(hash_default_kopts.merge(hash_new_kopts), keys) + end +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_by_address_netmask.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_by_address_netmask.rb new file mode 100644 index 0000000000..e50c684e7f --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_by_address_netmask.rb @@ -0,0 +1,22 @@ +module Puppet::Parser::Functions + newfunction(:ipcalc_network_by_address_netmask, :type => :rvalue, :doc => <<-EOS +Returns network address by host ip address and netmask. + EOS + ) do |arguments| + + require 'ipaddr' + + if (arguments.size != 2) then + raise(Puppet::ParseError, "ipcalc_network_by_address_netmask(): Wrong number of arguments "+ + "given #{arguments.size} for 2") + end + + begin + ip = IPAddr.new("#{arguments[0]}/#{arguments[1]}") + rescue ArgumentError + raise(Puppet::ParseError, "ipcalc_network_by_address_netmask(): bad arguments #{arguments[0]} #{arguments[1]}") + end + + return ip.to_s + end +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_cidr_by_netmask.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_cidr_by_netmask.rb new file mode 100644 index 0000000000..07132f4c5f --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_cidr_by_netmask.rb @@ -0,0 +1,20 @@ +module Puppet::Parser::Functions + newfunction(:ipcalc_network_cidr_by_netmask, :type => :rvalue, :doc => <<-EOS +Returns network cidr netmask by network netmask. + EOS + ) do |arguments| + + require 'ipaddr' + + if (arguments.size != 1) then + raise(Puppet::ParseError, "ipcalc_network_cidr_by_netmask(): Wrong number of arguments "+ + "given #{arguments.size} for 1") + end + + begin + return arguments[0].to_s.split('.').map { |e| e.to_i.to_s(2).rjust(8,"0")}.join.count("1").to_s + rescue ArgumentError + raise(Puppet::ParseError, "ipcalc_network_cidr_by_netmask(): bad argument #{arguments[0]}") + end + end +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_count_addresses.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_count_addresses.rb new file mode 100644 index 0000000000..adc7070a14 --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_count_addresses.rb @@ -0,0 +1,22 @@ +module Puppet::Parser::Functions + newfunction(:ipcalc_network_count_addresses, :type => :rvalue, :doc => <<-EOS +Returns count of addresses of network. + EOS + ) do |arguments| + + require 'ipaddr' + + if (arguments.size != 2) then + raise(Puppet::ParseError, "ipcalc_network_count_addresses(): Wrong number of arguments "+ + "given #{arguments.size} for 2") + end + + begin + ip = IPAddr.new("#{arguments[0]}/#{arguments[1]}") + rescue ArgumentError + raise(Puppet::ParseError, "ipcalc_network_count_addresses(): bad arguments #{arguments[0]} #{arguments[1]}") + end + + return ip.to_range.to_a.size + end +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_nth_address.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_nth_address.rb new file mode 100644 index 0000000000..8e3c5c2a1c --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_nth_address.rb @@ -0,0 +1,28 @@ +module Puppet::Parser::Functions + newfunction(:ipcalc_network_nth_address, :type => :rvalue, :doc => <<-EOS +Returns N-th address of network. + EOS + ) do |arguments| + + require 'ipaddr' + + if (arguments.size != 3) then + raise(Puppet::ParseError, "ipcalc_network_nth_address(): Wrong number of arguments "+ + "given #{arguments.size} for 3") + end + + begin + ip = IPAddr.new("#{arguments[0]}/#{arguments[1]}") + rescue ArgumentError + raise(Puppet::ParseError, "ipcalc_network_nth_address(): bad arguments #{arguments[0]} #{arguments[1]} #{arguments[2]}") + end + + if arguments[2].to_s =~ /^last$/ + return ip.to_range.to_a[-2].to_s + elsif arguments[2].to_s =~ /^first$/ + return ip.to_range.to_a[1].to_s + else + return ip.to_range.to_a[arguments[2].to_i].to_s + end + end +end diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_wildcard.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_wildcard.rb new file mode 100644 index 0000000000..640cf864a0 --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/ipcalc_network_wildcard.rb @@ -0,0 +1,42 @@ +module Puppet::Parser::Functions + newfunction(:ipcalc_network_wildcard, :type => :rvalue, :doc => <<-EOS +Returns network wildcard by host ip address and netmask. + EOS + ) do |arguments| + + require 'ipaddr' + + if (arguments.size != 2) then + raise(Puppet::ParseError, "ipcalc_network_wilrdcard(): Wrong number of arguments "+ + "given #{arguments.size} for 2") + end + + begin + ip = arguments[0] + mask = arguments[1] + address = IPAddr.new("#{ip}/#{mask}") + + class << address + def mask_length + @mask_addr.to_s(2).count("1") + end + + def wildcard_notation + return unless ipv4? + octets = mask_length / 8 + pattern = [] + (0...octets).map do |i| + pattern << ((@addr >> (24 - 8 * i)) & 0xff) + end + pattern << '*' if octets < 4 + pattern.join '.' + end + end + + return address.wildcard_notation + rescue ArgumentError + raise(Puppet::ParseError, "ipcalc_network_wildcard(): bad arguments #{arguments[0]} #{arguments[1]}") + end + end +end + diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/ipsort.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/ipsort.rb new file mode 100644 index 0000000000..e511ca81a0 --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/parser/functions/ipsort.rb @@ -0,0 +1,13 @@ +module Puppet::Parser::Functions + newfunction(:ipsort, :type => :rvalue , :doc => <<-EOS +Returns list sorted of sorted IP addresses. + EOS +) do |args| + require 'rubygems' + require 'ipaddr' + ips = args[0] + sorted_ips = ips.sort { |a,b| IPAddr.new( a ) <=> IPAddr.new( b ) } + sorted_ips + end +end + diff --git a/deployment/puppet/fuel/lib/puppet/provider/package/gem.rb b/deployment/puppet/fuel/lib/puppet/provider/package/gem.rb new file mode 100644 index 0000000000..3b047a498b --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/provider/package/gem.rb @@ -0,0 +1,132 @@ +# THIS FILE IS JUST A BIT PATCHED VERSION OF STANDARD GEM +# PACKAGE PROVIDER FROM puppet 2.7.19 +# TWO ADDITIONAL OPTIONS HAVE BEEN ADDED TO gem COMMAND +# --no-ri --no-rdoc + +require 'puppet/provider/package' +require 'uri' + +# Ruby gems support. +Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package do + desc "Ruby Gem support. If a URL is passed via `source`, then that URL is used as the + remote gem repository; if a source is present but is not a valid URL, it will be + interpreted as the path to a local gem file. If source is not present at all, + the gem will be installed from the default gem repositories." + + has_feature :versionable + + commands :gemcmd => "gem" + + def self.gemlist(options) + gem_list_command = [command(:gemcmd), "list"] + + if options[:local] + gem_list_command << "--local" + else + gem_list_command << "--remote" + end + + if name = options[:justme] + gem_list_command << name + "$" + end + + begin + list = execute(gem_list_command).lines. + map {|set| gemsplit(set) }. + reject {|x| x.nil? } + rescue Puppet::ExecutionFailure => detail + raise Puppet::Error, "Could not list gems: #{detail}" + end + + if options[:justme] + return list.shift + else + return list + end + end + + def self.gemsplit(desc) + # `gem list` when output console has a line like: + # *** LOCAL GEMS *** + # but when it's not to the console that line + # and all blank lines are stripped + # so we don't need to check for them + + if desc =~ /^(\S+)\s+\((.+)\)/ + name = $1 + versions = $2.split(/,\s*/) + { + :name => name, + :ensure => versions, + :provider => :gem + } + else + Puppet.warning "Could not match #{desc}" + nil + end + end + + def self.instances(justme = false) + gemlist(:local => true).collect do |hash| + new(hash) + end + end + + def install(useversion = true) + command = [command(:gemcmd), "install"] + command << "-v" << resource[:ensure] if (! resource[:ensure].is_a? Symbol) and useversion + # Always include dependencies + command << "--include-dependencies" + + command << "--no-rdoc" << "--no-ri" + + if source = resource[:source] + begin + uri = URI.parse(source) + rescue => detail + fail "Invalid source '#{uri}': #{detail}" + end + + case uri.scheme + when nil + # no URI scheme => interpret the source as a local file + command << source + when /file/i + command << uri.path + when 'puppet' + # we don't support puppet:// URLs (yet) + raise Puppet::Error.new("puppet:// URLs are not supported as gem sources") + else + # interpret it as a gem repository + command << "--source" << "#{source}" << resource[:name] + end + else + command << resource[:name] + end + + output = execute(command) + # Apparently some stupid gem versions don't exit non-0 on failure + self.fail "Could not install: #{output.chomp}" if output.include?("ERROR") + end + + def latest + # This always gets the latest version available. + hash = self.class.gemlist(:justme => resource[:name]) + + hash[:ensure][0] + end + + def query + self.class.gemlist(:justme => resource[:name], :local => true) + end + + def uninstall + gemcmd "uninstall", "-x", "-a", resource[:name] + end + + def update + self.install(false) + end + +end + diff --git a/deployment/puppet/fuel/lib/puppet/provider/postgres_config/ini_setting.rb b/deployment/puppet/fuel/lib/puppet/provider/postgres_config/ini_setting.rb new file mode 100644 index 0000000000..f25cd6e379 --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/provider/postgres_config/ini_setting.rb @@ -0,0 +1,22 @@ +Puppet::Type.type(:postgres_config).provide( + :ini_setting, + :parent => Puppet::Type.type(:ini_setting).provider(:ruby) +) do + + def section + "" + end + + def setting + resource[:name] + end + + def separator + '=' + end + + def file_path + '/var/lib/pgsql/9.3/data/postgresql.conf' + end + +end diff --git a/deployment/puppet/fuel/lib/puppet/type/postgres_config.rb b/deployment/puppet/fuel/lib/puppet/type/postgres_config.rb new file mode 100644 index 0000000000..72bf1fcc67 --- /dev/null +++ b/deployment/puppet/fuel/lib/puppet/type/postgres_config.rb @@ -0,0 +1,19 @@ +Puppet::Type.newtype(:postgres_config) do + + ensurable + + newparam(:name, :namevar => true) do + desc 'Section/setting name to manage from postgres.conf' + newvalues(/\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 + end + +end diff --git a/deployment/puppet/fuel/manifests/astute.pp b/deployment/puppet/fuel/manifests/astute.pp new file mode 100644 index 0000000000..daf70a7991 --- /dev/null +++ b/deployment/puppet/fuel/manifests/astute.pp @@ -0,0 +1,84 @@ +class fuel::astute( + $rabbitmq_host = $::fuel::params::rabbitmq_host, + $rabbitmq_astute_user = $::fuel::params::rabbitmq_astute_user, + $rabbitmq_astute_password = $::fuel::params::rabbitmq_astute_password, + $bootstrap_flavor = 'centos', + ) inherits fuel::params { + + $bootstrap_profile = $bootstrap_flavor ? { + /(?i)centos/ => 'bootstrap', + /(?i)ubuntu/ => 'ubuntu_bootstrap', + default => 'bootstrap', + } + + $packages = [ + "psmisc", + "python-editor", + "nailgun-mcagents", + "sysstat", + "rubygem-amqp", + "rubygem-amq-protocol", + "rubygem-i18n", + "rubygem-tzinfo", + "rubygem-minitest", + "rubygem-symboltable", + "rubygem-thread_safe", + ] + + ensure_packages($packages) + + case $::operatingsystem { + /(?i)(centos|redhat)/: { + case $::operatingsystemrelease { + /7.+/: { + ensure_packages(['rubygem-astute']) + Package[$packages] -> Package['rubygem-astute'] + } + } + } + } + + file { '/etc/sysconfig/astute': + content => template('fuel/astute/sysconfig.erb'), + owner => 'root', + group => 'root', + mode => '0644' + } + + file { '/usr/bin/astuted': + content => template('fuel/astute/astuted.erb'), + owner => 'root', + group => 'root', + mode => 0755, + } + + file {"/etc/astute": + ensure => directory, + owner => 'root', + group => 'root', + mode => 0755, + } + + file {"/etc/astute/astuted.conf": + content => template("fuel/astute/astuted.conf.erb"), + owner => 'root', + group => 'root', + mode => 0644, + require => File["/etc/astute"], + } + + file {"/var/log/astute": + ensure => directory, + owner => 'root', + group => 'root', + mode => 0755, + } + + # This hack came from setup.sh of astute docker container + # FIXME(dteselkin): use correct versions of rubygem packages + exec {'use correct versions of rubygem packages': + command => '/usr/bin/sed -i "/amq-protocol/ s/~>/>=/" /usr/share/gems/specifications/amqp-*.gemspec', + require => Package[$packages], + } + +} diff --git a/deployment/puppet/fuel/manifests/auth.pp b/deployment/puppet/fuel/manifests/auth.pp new file mode 100644 index 0000000000..b94f587123 --- /dev/null +++ b/deployment/puppet/fuel/manifests/auth.pp @@ -0,0 +1,68 @@ +# == Class: nailgun::auth +# +# This class creates keystone users, services, endpoints, and roles +# for Nailgun services. +# +# The user is given the admin role in the services tenant. +# +# === Parameters +# [*auth_user*] +# String. The name of the user. +# Optional. Defaults to 'nailgun'. +# +# [*password*] +# String. The user's password. +# Optional. Defaults to 'nailgun'. +# +class fuel::auth( + $auth_name = $::fuel::params::keystone_nailgun_user, + $password = $::fuel::params::keystone_nailgun_password, + $address = $::fuel::params::keystone_host, + $internal_address = undef, + $admin_address = undef, + $public_address = undef, + $port = '8000', + $region = 'RegionOne', + ) inherits fuel::params { + if ($internal_address == undef) { + $internal_address_real = $address + } else { + $internal_address_real = $internal_address + } + + if ($admin_address == undef) { + $admin_address_real = $address + } else { + $admin_address_real = $admin_address + } + + if ($public_address == undef) { + $public_address_real = $address + } else { + $public_address_real = $public_address + } + + keystone_user { $auth_name: + ensure => present, + enabled => 'True', + password => $password, + } + + keystone_user_role { "${auth_name}@services": + ensure => present, + roles => 'admin', + } + + keystone_service { 'nailgun': + ensure => present, + type => 'fuel', + description => 'Nailgun API', + } + + keystone_endpoint { "$region/nailgun": + ensure => present, + public_url => "http://${public_address_real}:${port}/api", + admin_url => "http://${admin_address_real}:${port}/api", + internal_url => "http://${internal_address_real}:${port}/api", + } +} diff --git a/deployment/puppet/fuel/manifests/auxiliaryrepos.pp b/deployment/puppet/fuel/manifests/auxiliaryrepos.pp new file mode 100644 index 0000000000..3937138605 --- /dev/null +++ b/deployment/puppet/fuel/manifests/auxiliaryrepos.pp @@ -0,0 +1,70 @@ +class fuel::auxiliaryrepos( + $fuel_version, + $repo_root = $::fuel::params::repo_root, + $priority = '15', + ) inherits fuel::params { + + $centos_dir = "${repo_root}/centos/auxiliary/" + $ubuntu_dir = "${repo_root}/ubuntu/auxiliary/" + + file { $centos_dir: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + + File[$centos_dir] -> + Package['createrepo'] -> + Exec["createrepo ${centos_dir}"] -> + Yumrepo["${fuel_version}_auxiliary"] + + yumrepo { "${fuel_version}_auxiliary": + name => "${fuel_version}_auxiliary", + descr => "${fuel_version}_auxiliary", + baseurl => "file://${centos_dir}", + gpgcheck => '0', + priority => $priority, + } + + ensure_packages(['createrepo']) + + exec { "createrepo ${centos_dir}": + path => '/bin:/sbin:/usr/bin:/usr/sbin', + cwd => $centos_dir, + creates => "${centos_dir}/repodata/repomd.xml", + } + + $release_files = [ + "${ubuntu_dir}/dists/auxiliary/Release", + "${ubuntu_dir}/dists/auxiliary/main/binary-amd64/Release", + "${ubuntu_dir}/dists/auxiliary/restricted/binary-amd64/Release"] + + Exec['create_ubuntu_repo_dirs'] -> + Exec['create_ubuntu_repo_Packages'] -> + File[$release_files] + + exec { 'create_ubuntu_repo_dirs': + path => '/bin:/sbin:/usr/bin:/usr/sbin', + command => "bash -c \"mkdir -p ${ubuntu_dir}/pool/{main,restricted} ${ubuntu_dir}/dists/auxiliary/{main,restricted}/binary-amd64/\"", + unless => "test -d ${ubuntu_dir}/pool && \ + test -d ${ubuntu_dir}/dists/auxiliary/main/binary-amd64 && \ + test -d ${ubuntu_dir}/dists/auxiliary/restricted/binary-amd64", + } + + exec { 'create_ubuntu_repo_Packages': + path => '/bin:/sbin:/usr/bin:/usr/sbin', + command => "bash -c \"touch ${ubuntu_dir}/dists/auxiliary/{main,restricted}/binary-amd64/Packages\"", + unless => "test -f ${ubuntu_dir}/dists/auxiliary/main/binary-amd64/Packages && \ + test -f ${ubuntu_dir}/dists/auxiliary/restricted/binary-amd64/Packages", + } + + file { $release_files: + ensure => file, + replace => false, + source => 'puppet:///modules/nailgun/Release-auxiliary', + mode => '0644', + owner => 'root', + group => 'root', + } +} diff --git a/deployment/puppet/fuel/manifests/bootstrap_cli.pp b/deployment/puppet/fuel/manifests/bootstrap_cli.pp new file mode 100644 index 0000000000..ba19bd3e10 --- /dev/null +++ b/deployment/puppet/fuel/manifests/bootstrap_cli.pp @@ -0,0 +1,55 @@ +# +# == Class: nailgun::bootstrap_cli +# +# Installs and configures fuel-bootstrap-cli package +# +# === Parameters +# +# [*bootstrap_cli_package*] +# (optional) The bootstrap cli package name +# Defaults to 'fuel-bootstrap-cli' +# +# [*settings*] +# (optional) The hash of new settings for bootstrap cli package. +# It will be merged with current package's settings(config_path) +# and parameters from current variable will have highest priority +# in case of equal parameters in both configuration sources. +# Defaults to {} +# +# [*direct_repo_addresses*] +# (optional) Array containing direct repositories ip addresses. +# Proxy servers will not be used for these ip addresses. +# Defaults to ['127.0.0.1'] +# +# [*config_path*] +# (optional) The path to configuration file of bootstrap cli package +# Defaults to '/etc/fuel-bootstrap-cli/fuel_bootstrap_cli.yaml' +# +# === Examples +# +# class { 'nailgun::bootstrap_cli': +# bootstrap_cli_package => 'fuel-bootstrap-cli', +# settings => {}, +# direct_repo_addresses => [ '192.168.0.1' ], +# config_path => '/etc/fuel-bootstrap-cli/fuel_bootstrap_cli.yaml', +# } +# +class fuel::bootstrap_cli( + $bootstrap_cli_package = 'fuel-bootstrap-cli', + $settings = {}, + $direct_repo_addresses = ['127.0.0.1'], + $config_path = '/etc/fuel-bootstrap-cli/fuel_bootstrap_cli.yaml', + ) { + + $additional_settings = {'direct_repo_addresses' => $direct_repo_addresses} + $custom_settings = merge($settings, $additional_settings) + + ensure_packages([$bootstrap_cli_package]) + + merge_yaml_settings { $config_path: + sample_settings => $config_path, + override_settings => $custom_settings, + ensure => present, + require => Package[$bootstrap_cli_package], + } +} diff --git a/deployment/puppet/fuel/manifests/cobbler.pp b/deployment/puppet/fuel/manifests/cobbler.pp new file mode 100644 index 0000000000..165313aff4 --- /dev/null +++ b/deployment/puppet/fuel/manifests/cobbler.pp @@ -0,0 +1,250 @@ +class fuel::cobbler( + $repo_root = $::fuel::params::repo_root, + $cobbler_user = $::fuel::params::cobbler_user, + $cobbler_password = $::fuel::params::cobbler_password, + # NOTE(kozhukalov): to be deprecated + $bootstrap_flavor = $::fuel::params::bootstrap_flavor, + $bootstrap_path, + $bootstrap_meta, + # network interface configuration timeout (in seconds) + $bootstrap_ethdevice_timeout = $::fuel::params::bootstrap_ethdevice_timeout, + $centos_repos = $::fuel::params::centos_repos, + $ks_system_timezone = $::fuel::params::ks_system_timezone, + $server = $::fuel::params::cobbler_host, + $name_server = $::fuel::params::cobbler_host, + $next_server = $::fuel::params::cobbler_host, + $dns_upstream = $::fuel::params::dns_upstream, + $dns_domain = $::fuel::params::dns_domain, + $dns_search = $::fuel::params::dns_search, + $mco_user = $::fuel::params::mco_user, + $mco_pass = $::fuel::params::mco_password, + # $dhcp_start_address, + # $dhcp_end_address, + # $dhcp_netmask, + # $dhcp_gateway = $::ipaddress, + $dhcp_interface = $::fuel::params::dhcp_interface, + $nailgun_api_url = "http://${::fuel::params::nailgun_host}:${::fuel::params::nailgun_port}/api", + # default password is 'r00tme' + $ks_encrypted_root_password = $::fuel::params::ks_encrypted_root_password, + ) inherits fuel::params { + + anchor { 'nailgun-cobbler-begin': } + anchor { 'nailgun-cobbler-end': } + + Anchor<| title == 'nailgun-cobbler-begin' |> -> + Class['::cobbler'] -> + Anchor<| title == 'nailgun-cobbler-end' |> + + #Set real_server so Cobbler identifies its own IP correctly in Docker + $real_server = $next_server + + $bootstrap_profile = $bootstrap_flavor ? { + /(?i)centos/ => 'bootstrap', + /(?i)ubuntu/ => 'ubuntu_bootstrap', + default => 'bootstrap', + } + + if $::osfamily == 'RedHat' { + case $operatingsystemmajrelease { + '6': { + $fence_ssh_source = 'puppet:///modules/nailgun/cobbler/fence_ssh.centos6.py' + } + '7': { + $fence_ssh_source = 'puppet:///modules/nailgun/cobbler/fence_ssh.centos7.py' + } + default: { + $fence_ssh_source = 'puppet:///modules/nailgun/cobbler/fence_ssh.centos6.py' + } + } + } + + class { '::cobbler': + server => $server, + domain_name => $domain_name, + dns_upstream => $dns_upstream, + dns_domain => $dns_domain, + dns_search => $dns_search, + name_server => $name_server, + next_server => $next_server, + # dhcp_start_address => $dhcp_start_address, + # dhcp_end_address => $dhcp_end_address, + # dhcp_netmask => $dhcp_netmask, + # dhcp_gateway => $dhcp_gateway, + dhcp_interface => $dhcp_interface, + cobbler_user => $cobbler_user, + cobbler_password => $cobbler_password, + pxetimeout => '50' + } + + # ADDING send2syslog.py SCRIPT AND CORRESPONDING SNIPPET + + ensure_packages(['send2syslog']) + + file { '/var/www/cobbler/aux/send2syslog.py': + ensure => link, + target => '/usr/bin/send2syslog.py', + require => [ + Class['::cobbler::server'], + Package['send2syslog']] + } + + file { '/etc/cobbler/power/fence_ssh.template': + content => template('fuel/cobbler/fence_ssh.template.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Class['::cobbler::server'], + } + + file { '/usr/sbin/fence_ssh': + source => $fence_ssh_source, + owner => 'root', + group => 'root', + mode => '0755', + require => Class['::cobbler::server'], + } + + # THIS VARIABLE IS NEEDED FOR TEMPLATING centos-x86_64.ks + $ks_repo = $centos_repos + + file { '/var/lib/cobbler/kickstarts/centos-x86_64.ks': + content => template('cobbler/kickstart/centos.ks.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Class['::cobbler::server'], + } -> + + cobbler_distro { 'centos-x86_64': + kernel => "${repo_root}/centos/x86_64/isolinux/vmlinuz", + initrd => "${repo_root}/centos/x86_64/isolinux/initrd.img", + arch => 'x86_64', + breed => 'redhat', + osversion => 'rhel6', + ksmeta => 'tree=http://@@server@@:8080/centos/x86_64/', + require => Class['::cobbler::server'], + } + + file { '/var/lib/cobbler/kickstarts/ubuntu-amd64.preseed': + content => template('cobbler/preseed/ubuntu-1404.preseed.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Class['::cobbler::server'], + } -> + + cobbler_distro { 'ubuntu_1404_x86_64': + kernel => "${repo_root}/ubuntu/x86_64/images/linux", + initrd => "${repo_root}/ubuntu/x86_64/images/initrd.gz", + arch => 'x86_64', + breed => 'ubuntu', + osversion => 'trusty', + ksmeta => '', + require => Class['::cobbler::server'], + } + + cobbler_profile { 'centos-x86_64': + kickstart => '/var/lib/cobbler/kickstarts/centos-x86_64.ks', + kopts => 'biosdevname=0 sshd=1 dhcptimeout=120', + distro => 'centos-x86_64', + ksmeta => '', + menu => false, + server => $real_server, + require => Cobbler_distro['centos-x86_64'], + } + + cobbler_profile { 'ubuntu_1404_x86_64': + kickstart => '/var/lib/cobbler/kickstarts/ubuntu-amd64.preseed', + kopts => 'net.ifnames=0 biosdevname=0 netcfg/choose_interface=eth0 netcfg/dhcp_timeout=120 netcfg/link_detection_timeout=20', + distro => 'ubuntu_1404_x86_64', + ksmeta => '', + menu => false, + server => $real_server, + require => Cobbler_distro['ubuntu_1404_x86_64'], + } + + cobbler_distro { 'bootstrap': + kernel => "${repo_root}/bootstrap/linux", + initrd => "${repo_root}/bootstrap/initramfs.img", + arch => 'x86_64', + breed => 'redhat', + osversion => 'rhel6', + ksmeta => '', + require => Class['::cobbler::server'], + } + + cobbler_distro { 'ubuntu_bootstrap': + kernel => "${bootstrap_path}/vmlinuz", + initrd => "${bootstrap_path}/initrd.img", + arch => 'x86_64', + breed => 'ubuntu', + osversion => 'trusty', + ksmeta => '', + require => Class['::cobbler::server'], + } + + cobbler_profile { 'bootstrap': + distro => 'bootstrap', + menu => true, + kickstart => '', + kopts => "intel_pstate=disable console=ttyS0,9600 console=tty0 biosdevname=0 url=${nailgun_api_url} mco_user=${mco_user} mco_pass=${mco_pass}", + ksmeta => '', + server => $real_server, + require => Cobbler_distro['bootstrap'], + } + + cobbler_profile { 'ubuntu_bootstrap': + distro => 'ubuntu_bootstrap', + menu => true, + kickstart => '', + kopts => extend_kopts($bootstrap_meta['extend_kopts'], "console=ttyS0,9600 console=tty0 panic=60 ethdevice-timeout=${bootstrap_ethdevice_timeout} boot=live toram components fetch=http://${server}:8080/bootstraps/active_bootstrap/root.squashfs biosdevname=0 url=${nailgun_api_url} mco_user=${mco_user} mco_pass=${mco_pass}"), + ksmeta => '', + server => $real_server, + require => Cobbler_distro['ubuntu_bootstrap'], + } + + if str2bool($::is_virtual) { class { 'cobbler::checksum_bootpc': } } + + exec { 'cobbler_system_add_default': + command => "cobbler system add --name=default \ + --profile=${bootstrap_profile} --netboot-enabled=True", + onlyif => 'test -z `cobbler system find --name=default`', + require => Cobbler_profile[$bootstrap_profile], + } + + exec { 'cobbler_system_edit_default': + command => "cobbler system edit --name=default \ + --profile=${bootstrap_profile} --netboot-enabled=True", + unless => "cobbler system report --name default 2>/dev/null | grep -q -E '^Profile\\s*:\\s*${bootstrap_profile}'", + require => Cobbler_profile[$bootstrap_profile], + } + + exec { 'nailgun_cobbler_sync': + command => 'cobbler sync', + refreshonly => true, + } + + Exec['cobbler_system_add_default'] ~> Exec['nailgun_cobbler_sync'] + Exec['cobbler_system_edit_default'] ~> Exec['nailgun_cobbler_sync'] + Cobbler_profile<| |> ~> Exec['nailgun_cobbler_sync'] + + #FIXME(mattymo): move pubkey to astute fact or download it + exec { 'cp /root/.ssh/id_rsa.pub /etc/cobbler/authorized_keys': + command => 'cp /root/.ssh/id_rsa.pub /etc/cobbler/authorized_keys', + creates => '/etc/cobbler/authorized_keys', + require => Class['::cobbler::server'], + } + + file { '/etc/dnsmasq.conf': + ensure => link, + target => '/etc/cobbler.dnsmasq.conf', + } + + file { ["/var/log/cobbler/anamon", + "/var/log/cobbler/kicklog", + "/var/log/cobbler/syslog", + "/var/log/cobbler/tasks"] : + ensure => directory + } + +} diff --git a/deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp b/deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp new file mode 100644 index 0000000000..80959abb9b --- /dev/null +++ b/deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp @@ -0,0 +1,28 @@ +# +# nailgun::dnsmasq::dhcp_range creates config files in /etc/dnsmasq.d/ +# +# [next_server] IP address that will be used as PXE tftp server +# [dhcp_start_address] First address of dhcp range +# [dhcp_end_address] Last address of dhcp range +# [dhcp_netmask] Netmask of the network +# [dhcp_gateway] Gateway address for installed nodes +# [lease_time] DHCP lease time +# [file_header] File header for comments + +define fuel::dnsmasq::dhcp_range( + $dhcp_start_address = '10.0.0.201', + $dhcp_end_address = '10.0.0.254', + $dhcp_netmask = '255.255.255.0', + $dhcp_gateway = $::ipaddress, + $file_header = undef, + $lease_time = '120m', + $next_server = $::ipaddress, +){ + $range_name = $name + file { "/etc/dnsmasq.d/${name}.conf": + content => template('fuel/dnsmasq.dhcp-range.erb'), + owner => 'root', + group => 'root', + mode => '0644', + } +} diff --git a/deployment/puppet/fuel/manifests/iptables.pp b/deployment/puppet/fuel/manifests/iptables.pp new file mode 100644 index 0000000000..fd6acb4843 --- /dev/null +++ b/deployment/puppet/fuel/manifests/iptables.pp @@ -0,0 +1,243 @@ +class fuel::iptables ( + $network_address, + $network_cidr, + + $admin_iface = $::fuel::params::admin_interface, + $ssh_port = '22', + $nailgun_web_port = $::fuel::params::nailgun_port, + $nailgun_internal_port = $::fuel::params::nailgun_internal_port, + $nailgun_repo_port = $::fuel::params::repo_port, + $postgres_port = $::fuel::params::db_port, + $ostf_port = $::fuel::params::ostf_port, + $rsync_port = '873', + $rsyslog_port = '514', + $ntp_port = '123', + $rabbitmq_ports = ['4369','5672','15672','61613'], + $fuelweb_port = $::fuel::params::nailgun_ssl_port, + $keystone_port = $::fuel::params::keystone_port, + $keystone_admin_port = $::fuel::params::keystone_admin_port, + $chain = 'INPUT', + ) inherits fuel::params { + + #Enable cobbler's iptables rules even if Cobbler not called + include cobbler::iptables + + firewall { '002 accept related established rules': + proto => 'all', + state => ['RELATED', 'ESTABLISHED'], + action => 'accept', + } -> + + #Host services + firewall { '004 forward_admin_net': + chain => 'POSTROUTING', + table => 'nat', + proto => 'all', + source => "${network_address}/${network_cidr}", + outiface => 'e+', + jump => 'MASQUERADE', + } + sysctl::value{'net.ipv4.ip_forward': value=>'1'} + + firewall { '005 ssh': + port => $ssh_port, + proto => 'tcp', + action => 'accept', + } + + firewall { '006 ntp': + port => $ntp_port, + proto => 'tcp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '007 ntp_udp': + port => $ntp_port, + proto => 'udp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '008 snmp': + port => '162', + proto => 'udp', + action => 'accept', + } + + #Containerized services + firewall { '009 nailgun_web': + chain => $chain, + port => $nailgun_web_port, + proto => 'tcp', + action => 'accept', + } + + firewall { '010 nailgun_internal': + chain => $chain, + port => $nailgun_internal_port, + proto => 'tcp', + iniface => 'docker0', + action => 'accept', + } + firewall { '011 nailgun_internal_local': + chain => $chain, + port => $nailgun_internal_port, + proto => 'tcp', + src_type => "LOCAL", + action => 'accept', + } + + firewall { '012 nailgun_internal_block_ext': + chain => $chain, + port => $nailgun_internal_port, + proto => 'tcp', + action => 'reject', + } + + firewall { '013 postgres_local': + chain => $chain, + port => $postgres_port, + proto => 'tcp', + src_type => "LOCAL", + action => 'accept', + } + + firewall { '014 postgres': + chain => $chain, + port => $postgres_port, + proto => 'tcp', + iniface => 'docker0', + action => 'accept', + } + + firewall { '015 postgres_block_ext': + chain => $chain, + port => $postgres_port, + proto => 'tcp', + action => 'reject', + } + + firewall { '020 ostf_admin': + chain => $chain, + port => $ostf_port, + proto => 'tcp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '021 ostf_local': + chain => $chain, + port => $ostf_port, + proto => 'tcp', + src_type => "LOCAL", + action => 'accept', + } + + firewall { '022 ostf_block_ext': + chain => $chain, + port => $ostf_port, + proto => 'tcp', + action => 'reject', + } + + firewall { '023 rsync': + chain => $chain, + port => $rsync_port, + proto => 'tcp', + action => 'accept', + } + + firewall { '024 rsyslog': + chain => $chain, + port => $rsyslog_port, + proto => 'tcp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '025 rsyslog': + chain => $chain, + port => $rsyslog_port, + proto => 'udp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '040 rabbitmq_admin': + chain => $chain, + port => $rabbitmq_ports, + proto => 'tcp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '041 rabbitmq_local': + chain => $chain, + port => $rabbitmq_ports, + proto => 'tcp', + src_type => "LOCAL", + action => 'accept', + } + + firewall { '042 rabbitmq_block_ext': + chain => $chain, + port => $rabbitmq_ports, + proto => 'tcp', + action => 'reject', + } + + firewall {'043 fuelweb_port': + chain => $chain, + port => $fuelweb_port, + proto => 'tcp', + action => 'accept', + } + + firewall { '046 keystone_admin': + chain => $chain, + port => $keystone_port, + proto => 'tcp', + action => 'accept' + } + + firewall { '047 keystone_admin_port admin_net': + chain => $chain, + port => $keystone_admin_port, + proto => 'tcp', + iniface => $admin_iface, + action => 'accept', + } + + firewall { '049 nailgun_repo_admin': + chain => $chain, + port => $nailgun_repo_port, + proto => 'tcp', + action => 'accept' + } + + firewall { '050 forward admin_net': + chain => 'FORWARD', + proto => 'all', + source => "${network_address}/${network_cidr}", + iniface => $admin_iface, + action => 'accept', + } + + firewall { '051 forward admin_net conntrack': + chain => 'FORWARD', + proto => 'all', + ctstate => ['ESTABLISHED', 'RELATED'], + action => 'accept' + } + + firewall {'999 iptables denied': + chain => 'INPUT', + limit => '5/min', + jump => 'LOG', + log_prefix => 'iptables denied: ', + log_level => '7', + } + + +} diff --git a/deployment/puppet/fuel/manifests/keystone.pp b/deployment/puppet/fuel/manifests/keystone.pp new file mode 100644 index 0000000000..abc43aae65 --- /dev/null +++ b/deployment/puppet/fuel/manifests/keystone.pp @@ -0,0 +1,134 @@ +class fuel::keystone ( + $host = $::fuel::params::keystone_host, + $port = $::fuel::params::keystone_port, + $admin_port = $::fuel::params::keystone_admin_port, + + $db_engine = $::fuel::params::db_engine, + $db_host = $::fuel::params::db_host, + $db_port = $::fuel::params::db_port, + $db_name = $::fuel::params::keystone_db_name, + $db_user = $::fuel::params::keystone_db_user, + $db_password = $::fuel::params::keystone_db_password, + + $admin_token = $::fuel::params::keystone_admin_token, + + $admin_user = $::fuel::params::keystone_admin_user, + $admin_password = $::fuel::params::keystone_admin_password, + + $monitord_user = $::fuel::params::keystone_monitord_user, + $monitord_password = $::fuel::params::keystone_monitord_password, + + $nailgun_user = $::fuel::params::keystone_nailgun_user, + $nailgun_password = $::fuel::params::keystone_nailgun_password, + + $ostf_user = $::fuel::params::keystone_ostf_user, + $ostf_password = $::fuel::params::keystone_ostf_password, + + $auth_version = $::fuel::params::keystone_auth_version, + ) inherits fuel::params { + + ensure_packages(['crontabs', 'os-client-config', 'python-tablib', + 'python-unicodecsv', 'rubygem-thread_safe']) + + class { '::keystone': + admin_token => $admin_token, + catalog_type => 'sql', + database_connection => "${db_engine}://${db_user}:${db_password}@${db_host}:${db_port}/${db_name}", + token_expiration => 86400, + token_provider => 'keystone.token.providers.uuid.Provider', + } + + #FIXME(mattymo): We should enable db_sync on every run inside keystone, + #but this is related to a larger scope fix for concurrent deployment of + #secondary controllers. + Exec <| title == 'keystone-manage db_sync' |> { + refreshonly => false, + } + + # Creating tenants + keystone_tenant { 'admin': + ensure => present, + enabled => 'True', + } + + keystone_tenant { 'services': + ensure => present, + enabled => 'True', + description => 'fuel services tenant', + } + + # Creating roles + keystone_role { 'admin': + ensure => present, + } + + keystone_role { 'monitoring': + ensure => present, + } + + # Creating users + + # Admin user + keystone_user { $admin_user : + ensure => present, + password => $admin_password, + enabled => 'True', + replace_password => false, + } + + # assigning role 'admin' to user 'admin' in tenant 'admin' + keystone_user_role { "${admin_user}@admin": + ensure => present, + roles => ['admin'], + } + + # Monitord user + keystone_user { $monitord_user : + ensure => present, + password => $monitord_password, + enabled => 'True', + email => 'monitord@localhost', + } + + keystone_user_role { "${monitord_user}@services": + ensure => present, + roles => ['monitoring'], + } + + # Keystone Endpoint + class { 'keystone::endpoint': + public_url => "http://${host}:${port}/${auth_version}", + admin_url => "http://${host}:${admin_port}/${auth_version}", + internal_url => "http://${host}:${port}/${auth_version}", + } + + # Nailgun + class { 'fuel::auth': + auth_name => $nailgun_user, + password => $nailgun_password, + address => $host, + } + + # OSTF + class { 'fuel::ostf::auth': + auth_name => $ostf_user, + password => $ostf_password, + address => $host, + } + + service { 'crond': + ensure => running, + enable => true, + } + + # Flush expired tokens + cron { 'keystone-flush-token': + ensure => present, + command => 'keystone-manage token_flush', + environment => 'PATH=/bin:/usr/bin:/usr/sbin', + user => 'root', + hour => '1', + require => Package['crontabs'], + } + +} diff --git a/deployment/puppet/fuel/manifests/mcollective.pp b/deployment/puppet/fuel/manifests/mcollective.pp new file mode 100644 index 0000000000..622d442173 --- /dev/null +++ b/deployment/puppet/fuel/manifests/mcollective.pp @@ -0,0 +1,78 @@ +class fuel::mcollective( + $mco_host = $::fuel::params::mco_host, + $mco_port = $::fuel::params::mco_port, + $mco_pskey = $::fuel::params::mco_pskey, + $mco_vhost = $::fuel::params::mco_vhost, + $mco_user = $::fuel::params::mco_user, + $mco_password = $::fuel::params::mco_password, + $mco_connector = $::fuel::params::mco_connector, + $mco_packages_extra = $::fuel::params::mco_packages_extra, + ) inherits fuel::params { + + include stdlib + + $mco_settings = { + 'identity' => { + value => 'master' + }, + 'ttl' => { + value => '4294957' + }, + 'direct_addressing' => { + value => '1' + }, + 'plugin.rabbitmq.vhost' => { + value => $mco_vhost + }, + 'plugin.rabbitmq.pool.1.host' => { + value => $mco_host + }, + 'plugin.rabbitmq.pool.1.port' => { + value => $mco_port + }, + 'plugin.rabbitmq.pool.1.user' => { + value => $mco_user + }, + 'plugin.rabbitmq.pool.1.password' => { + value => $mco_password + }, + 'plugin.rabbitmq.heartbeat_interval' => { + value => '30' + } + } + + if $::osfamily == 'RedHat' { + case $operatingsystemmajrelease { + '6': { + $mco_packages = ['ruby21-rubygem-mcollective-client', + 'ruby21-nailgun-mcagents'] + } + '7': { + $mco_packages = ['mcollective-client', + 'rubygem-mcollective-client', + 'nailgun-mcagents'] + } + default: { + fail("Unsupported ${::osfamily} release: ${::operatingsystemmajrelease}") + } + } + } + + ensure_packages($mco_packages) + ensure_packages($mco_packages_extra) + + class { '::mcollective': + connector => $mco_connector, + middleware_hosts => [$mco_host], + server_loglevel => 'debug', + psk => $mco_pskey, + manage_packages => false, + server => true, + client => true, + require => Package[$mco_packages], + } + + create_resources(mcollective::server::setting, $mco_settings, { 'order' => 90 }) + create_resources(mcollective::client::setting, $mco_settings, { 'order' => 90 }) + +} diff --git a/deployment/puppet/fuel/manifests/nailgun/client.pp b/deployment/puppet/fuel/manifests/nailgun/client.pp new file mode 100644 index 0000000000..54c5c3f8ff --- /dev/null +++ b/deployment/puppet/fuel/manifests/nailgun/client.pp @@ -0,0 +1,24 @@ +class fuel::nailgun::client ( + $server_address = $::fuel::params::nailgun_host, + $server_port = $::fuel::params::nailgun_port, + $keystone_port = $::fuel::params::keystone_port, + $keystone_user = $::fuel::params::keystone_admin_user, + $keystone_password = $::fuel::params::keystone_admin_password, + ) inherits fuel::params { + + ensure_packages(["python-fuelclient"]) + + file {['/root/.config', + '/root/.config/fuel']: + ensure => directory + } + + file { "/root/.config/fuel/fuel_client.yaml": + owner => 'root', + group => 'root', + mode => '0600', + content => template("fuel/nailgun/client.yaml.erb"), + require => File['/root/.config/fuel'], + } + +} diff --git a/deployment/puppet/fuel/manifests/nailgun/server.pp b/deployment/puppet/fuel/manifests/nailgun/server.pp new file mode 100644 index 0000000000..70c9a3f919 --- /dev/null +++ b/deployment/puppet/fuel/manifests/nailgun/server.pp @@ -0,0 +1,176 @@ +class fuel::nailgun::server ( + $listen_port = $::fuel::params::nailgun_internal_port, + + $keystone_host = $::fuel::params::keystone_host, + $keystone_user = $::fuel::params::keystone_nailgun_user, + $keystone_password = $::fuel::params::keystone_nailgun_password, + + $feature_groups = $::fuel::params::feature_groups, + $nailgun_log_level = $::fuel::params::nailgun_log_level, + + $db_name = $::fuel::params::nailgun_db_name, + $db_engine = $::fuel::params::db_engine, + $db_host = $::fuel::params::db_host, + $db_port = $::fuel::params::db_port, + $db_user = $::fuel::params::nailgun_db_user, + $db_password = $::fuel::params::nailgun_db_password, + + $rabbitmq_host = $::fuel::params::rabbitmq_host, + $rabbitmq_astute_user = $::fuel::params::rabbitmq_astute_user, + $rabbitmq_astute_password = $::fuel::params::rabbitmq_astute_password, + + $admin_network, + $admin_network_cidr, + $admin_network_size, + $admin_network_first, + $admin_network_last, + $admin_network_netmask, + $admin_network_mac, + $admin_network_ip, + $admin_network_gateway, + + $cobbler_host = $::fuel::params::cobbler_host, + $cobbler_url = $::fuel::params::cobbler_url, + $cobbler_user = $::fuel::params::cobbler_user, + $cobbler_password = $::fuel::params::cobbler_password, + + $mco_pskey = $::fuel::params::mco_pskey, + $mco_vhost = $::fuel::params::mco_vhost, + $mco_host = $::fuel::params::mco_host, + $mco_user = $::fuel::params::mco_user, + $mco_password = $::fuel::params::mco_password, + $mco_connector = $::fuel::params::mco_connector, + + $ntp_upstream = $::fuel::params::ntp_upstream, + $dns_upstream = $::fuel::params::dns_upstream, + $dns_domain = $::fuel::params::dns_domain, + + $exclude_network = $admin_network, + $exclude_cidr = $admin_network_cidr, + + ) inherits fuel::params { + + ensure_packages(['fuel-nailgun', 'python-psycopg2', 'crontabs', 'cronie-anacron', + 'uwsgi', 'uwsgi-plugin-common', 'uwsgi-plugin-python']) + + $services = [ 'assassind', + 'nailgun', + 'oswl_flavor_collectord', + 'oswl_image_collectord', + 'oswl_keystone_user_collectord', + 'oswl_tenant_collectord', + 'oswl_vm_collectord', + 'oswl_volume_collectord', + 'receiverd', + 'statsenderd' ] + + # FIXME(kozhukalov): fuel-nailgun package should provide nailgun group + group { 'nailgun' : + provider => "groupadd", + ensure => "present", + } + + # FIXME(kozhukalov): fuel-nailgun package should provide nailgun user + user { 'nailgun' : + ensure => "present", + gid => 'nailgun', + home => "/", + shell => "/bin/false", + require => Group['nailgun'], + } + + # FIXME(kozhukalov): fuel-nailgun package should provide + # /etc/nailgun directory + file { "/etc/nailgun": + ensure => directory, + owner => 'root', + group => 'root', + mode => 0755, + } + + file { "/etc/logrotate.d/nailgun": + content => template("fuel/logrotate.conf.erb"), + } + + # FIXME(kozhukalov): fuel-nailgun package should provide + # /var/log/nailgun directory + file {"/var/log/nailgun": + ensure => directory, + owner => 'root', + group => 'root', + mode => 0755, + } + + file { "/etc/nailgun/settings.yaml": + content => template("fuel/nailgun/settings.yaml.erb"), + owner => 'root', + group => 'root', + mode => 0644, + require => File["/etc/nailgun"], + notify => Service[$services], + } + + exec {"nailgun_syncdb": + command => "/usr/bin/nailgun_syncdb", + require => [ + File["/etc/nailgun/settings.yaml"], + ], + } + + exec {"nailgun_upload_fixtures": + command => "/usr/bin/nailgun_fixtures", + require => Exec["nailgun_syncdb"], + } + + file {"/etc/cron.daily/capacity": + content => template("fuel/nailgun/cron_daily_capacity.erb"), + owner => 'root', + group => 'root', + mode => '0644', + require => Package['cronie-anacron'] + } + + cron { 'oswl_cleaner': + ensure => present, + command => 'oswl_cleaner', + environment => 'PATH=/bin:/usr/bin:/usr/sbin', + user => 'nailgun', + hour => '1', + require => Package['crontabs'], + } + + service { 'crond': + ensure => running, + enable => true, + } + + $fuel_key = $::generate_fuel_key + + if $::physicalprocessorcount > 4 { + $physicalprocessorcount = 8 + } else { + $physicalprocessorcount = $::physicalprocessorcount * 2 + } + + $somaxconn = "4096" + sysctl::value{'net.core.somaxconn': value => $somaxconn} + + file { '/etc/nailgun/uwsgi_nailgun.yaml': + content => template('nailgun/uwsgi_nailgun.yaml.erb'), + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + require => Package[['uwsgi', 'fuel-nailgun']], + } -> + + file { '/var/lib/nailgun-uwsgi': + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + } -> + + fuel::systemd { $services: } + +} diff --git a/deployment/puppet/fuel/manifests/nginx.pp b/deployment/puppet/fuel/manifests/nginx.pp new file mode 100644 index 0000000000..32df39a3c6 --- /dev/null +++ b/deployment/puppet/fuel/manifests/nginx.pp @@ -0,0 +1,38 @@ +class fuel::nginx inherits fuel::params { + + Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + + ensure_packages(['nginx']) + Package['nginx'] ~> Service['nginx'] + + file { ['/etc/nginx/conf.d/default.conf', + '/etc/nginx/conf.d/virtual.conf', + '/etc/nginx/conf.d/ssl.conf']: + ensure => 'absent', + notify => Service['nginx'], + before => File["/etc/nginx/nginx.conf"], + } + + if ( $service_enabled == false ){ + $ensure = false + } else { + $ensure = 'running' + } + + file { '/etc/nginx/nginx.conf': + ensure => present, + content => template('fuel/nginx/nginx.conf.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Package['nginx'], + notify => Service['nginx'], + } + + service { 'nginx': + ensure => $ensure, + enable => $service_enabled, + require => File['/etc/nginx/nginx.conf'], + } + +} diff --git a/deployment/puppet/fuel/manifests/nginx/repo.pp b/deployment/puppet/fuel/manifests/nginx/repo.pp new file mode 100644 index 0000000000..d01f5790ae --- /dev/null +++ b/deployment/puppet/fuel/manifests/nginx/repo.pp @@ -0,0 +1,16 @@ +class fuel::nginx::repo( + $repo_root = $::fuel::params::repo_root, + $repo_port = $::fuel::params::repo_port, + $service_enabled = true, + ) inherits fuel::nginx { + + file { '/etc/nginx/conf.d/repo.conf': + content => template('fuel/nginx/repo.conf.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Package['nginx'], + notify => Service['nginx'], + } + +} diff --git a/deployment/puppet/fuel/manifests/nginx/services.pp b/deployment/puppet/fuel/manifests/nginx/services.pp new file mode 100644 index 0000000000..59e33bdaa9 --- /dev/null +++ b/deployment/puppet/fuel/manifests/nginx/services.pp @@ -0,0 +1,57 @@ +class fuel::nginx::services ( + $staticdir = $::fuel::params::staticdir, + $logdumpdir = $::fuel::params::logdumpdir, + $ostf_host = $::fuel::params::ostf_host, + $ostf_port = $::fuel::params::ostf_port, + $keystone_host = $::fuel::params::keystone_host, + $keystone_port = $::fuel::params::keystone_port, + $nailgun_host = $::fuel::params::nailgun_host, + $nailgun_port = $::fuel::params::nailgun_internal_port, + $ssl_enabled = false, + $force_https = undef, + $service_enabled = true, + ) inherits fuel::nginx { + + if $ssl_enabled and $force_https { + $plain_http = false + } else { + $plain_http = true + } + + file { '/etc/nginx/conf.d/services.conf': + content => template('fuel/nginx/services.conf.erb'), + owner => 'root', + group => 'root', + mode => '0644', + require => Package['nginx'], + notify => Service['nginx'], + } + + file { ['/var/lib/fuel', + '/var/lib/fuel/keys', + '/var/lib/fuel/keys/master', + '/var/lib/fuel/keys/master/nginx', + ]: + ensure => 'directory', + } + + if $ssl_enabled { + openssl::certificate::x509 { 'nginx': + ensure => present, + country => 'US', + organization => 'Fuel', + commonname => 'fuel.master.local', + altnames => [$nailgun_host], + state => 'California', + unit => 'Fuel Deployment Team', + email => 'root@fuel.master.local', + days => 3650, + base_dir => '/var/lib/fuel/keys/master/nginx/', + owner => 'root', + group => 'root', + force => false, + require => File['/var/lib/fuel/keys/master/nginx'], + cnf_tpl => 'openssl/cert.cnf.erb', + } -> File["/etc/nginx/conf.d/services.conf"] + } +} diff --git a/deployment/puppet/fuel/manifests/ostf.pp b/deployment/puppet/fuel/manifests/ostf.pp new file mode 100644 index 0000000000..324dfa6d3f --- /dev/null +++ b/deployment/puppet/fuel/manifests/ostf.pp @@ -0,0 +1,51 @@ +class fuel::ostf( + $dbuser = $::fuel::params::ostf_db_user, + $dbpass = $::fuel::params::ostf_db_password, + $dbname = $::fuel::params::ostf_db_name, + $dbhost = $::fuel::params::db_host, + $dbport = $::fuel::params::db_port, + $nailgun_host = $::fuel::params::nailgun_host, + $nailgun_port = $::fuel::params::nailgun_port, + $dbengine = 'postgresql+psycopg2', + $host = $::fuel::params::ostf_host, + $port = $::fuel::params::ostf_port, + $logfile = '/var/log/ostf.log', + $keystone_host = $::fuel::params::keystone_host, + $keystone_port = $::fuel::params::keystone_admin_port, + $keystone_ostf_user = $::fuel::params::keystone_ostf_user, + $keystone_ostf_pass = $::fuel::params::keystone_ostf_password, + $auth_enable = 'True', + ) inherits fuel::params { + + ensure_packages(['libevent-devel', 'openssl-devel', 'fuel-ostf', 'python-psycopg2']) + + exec {'ostf-init': + command => "/usr/bin/ostf-server \ + --after-initialization-environment-hook", + tries => 50, + try_sleep => 5, + } + + Package['fuel-ostf'] -> Exec['ostf-init'] + File['/etc/ostf/ostf.conf'] -> Exec['ostf-init'] + + file { '/etc/ostf/': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0750', + } + + file { '/etc/ostf/ostf.conf': + owner => 'root', + group => 'root', + content => template('fuel/ostf.conf.erb'), + } + + file { '/var/log/ostf': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } +} diff --git a/deployment/puppet/fuel/manifests/ostf/auth.pp b/deployment/puppet/fuel/manifests/ostf/auth.pp new file mode 100644 index 0000000000..b14f449c91 --- /dev/null +++ b/deployment/puppet/fuel/manifests/ostf/auth.pp @@ -0,0 +1,68 @@ +# == Class: fuel::ostf::auth +# +# This class creates keystone users, services, endpoints, and roles +# for OSTF services. +# +# The user is given the admin role in the services tenant. +# +# === Parameters +# [*auth_user*] +# String. The name of the user. +# Optional. Defaults to 'ostf'. +# +# [*password*] +# String. The user's password. +# Optional. Defaults to 'ostf'. +# +class fuel::ostf::auth ( + $auth_name = $::fuel::params::keystone_ostf_user, + $password = $::fuel::params::keystone_ostf_password, + $address = $::fuel::params::keystone_host, + $internal_address = undef, + $admin_address = undef, + $public_address = undef, + $port = '8000', + $region = 'RegionOne', + ) inherits fuel::params { + if ($internal_address == undef) { + $internal_address_real = $address + } else { + $internal_address_real = $internal_address + } + + if ($admin_address == undef) { + $admin_address_real = $address + } else { + $admin_address_real = $admin_address + } + + if ($public_address == undef) { + $public_address_real = $address + } else { + $public_address_real = $public_address + } + + keystone_user { $auth_name: + ensure => present, + enabled => 'True', + password => $password, + } + + keystone_user_role { "${auth_name}@services": + ensure => present, + roles => 'admin', + } + + keystone_service { 'ostf': + ensure => present, + type => 'ostf', + description => 'OSTF', + } + + keystone_endpoint { "$region/ostf": + ensure => present, + public_url => "http://${public_address_real}:${port}/ostf", + admin_url => "http://${admin_address_real}:${port}/ostf", + internal_url => "http://${internal_address_real}:${port}/ostf", + } +} diff --git a/deployment/puppet/fuel/manifests/params.pp b/deployment/puppet/fuel/manifests/params.pp new file mode 100644 index 0000000000..eeeab72607 --- /dev/null +++ b/deployment/puppet/fuel/manifests/params.pp @@ -0,0 +1,110 @@ +class fuel::params { + + $db_engine = "postgresql" + $db_host = "127.0.0.1" + $db_port = "5432" + + $nailgun_db_name = 'nailgun' + $nailgun_db_user = 'nailgun' + $nailgun_db_password = 'nailgun' + + $keystone_db_name = 'keystone' + $keystone_db_user = 'keystone' + $keystone_db_password = 'keystone' + + $feature_groups = [] + $staticdir = '/usr/share/nailgun/static' + $templatedir = '/usr/share/nailgun/static' + $logdumpdir = '/var/dump' + + # keystone + $keystone_host = '127.0.0.1' + $keystone_port = '5000' + $keystone_admin_port = '35357' + + $keystone_admin_user = 'admin' + $keystone_admin_password = 'admin' + $keystone_nailgun_user = 'nailgun' + $keystone_nailgun_password = 'nailgun' + $keystone_monitord_user = 'monitord' + $keystone_monitord_password = 'monitord' + $keystone_monitord_tenant = 'services' + + $keystone_auth_version = 'v2.0' + $keystone_admin_token = 'admin' + + $bootstrap_flavor = 'centos' + # network interface configuration timeout (in seconds) + $bootstrap_ethdevice_timeout = '120' + + $rabbitmq_host = '127.0.0.1' + $rabbitmq_astute_user = 'naily' + $rabbitmq_astute_password = 'naily' + + $rabbitmq_gid = 495 + $rabbitmq_uid = 495 + + $cobbler_host = $::ipaddress + $cobbler_url = "http://${::ipaddress}/cobbler_api" + $cobbler_user = 'cobbler' + $cobbler_password = 'cobbler' + $centos_repos = [ + { + "id" => "nailgun", + "name" => "Nailgun", + "url" => "\$tree" + } + ] + + $ks_system_timezone = 'Etc/UTC' + $dns_upstream = '8.8.8.8' + $dns_domain = 'domain.tld' + $dns_search = 'domain.tld' + $dhcp_interface = "eth0" + $admin_interface = "eth0" + $admin_network = "10.20.0.*" + $extra_networks = undef + + $nailgun_api_url = "http://${::ipaddress}:8000/api" + # default password is 'r00tme' + $ks_encrypted_root_password = '\$6\$tCD3X7ji\$1urw6qEMDkVxOkD33b4TpQAjRiCeDZx0jmgMhDYhfB9KuGfqO9OcMaKyUxnGGWslEDQ4HxTw7vcAMP85NxQe61' + + $ntp_upstream = '' + + $mco_host = $::ipaddress + $mco_port = '61613' + $mco_pskey = 'unset' + $mco_vhost = 'mcollective' + $mco_user = 'mcollective' + $mco_password = 'marionette' + $mco_connector = 'rabbitmq' + $mco_packages_extra = [ + 'fuel-agent', + 'fuel-provisioning-scripts', + 'shotgun', + 'ironic-fa-bootstrap-configs', + 'fuel-bootstrap-cli', + ] + + $keystone_ostf_user = "ostf" + $keystone_ostf_password = "ostf" + + $puppet_master_hostname = "${hostname}.${domain}" + + $repo_root = "/var/www/nailgun" + $repo_port = '8080' + + $nailgun_log_level = "DEBUG" + + + $nailgun_host = '127.0.0.1' + $nailgun_port = '8000' + $nailgun_internal_port = '8001' + $nailgun_ssl_port = '8443' + + $ostf_host = '127.0.0.1' + $ostf_port = '8777' + $ostf_db_user = "ostf" + $ostf_db_password = "ostf" + $ostf_db_name = "ostf" +} diff --git a/deployment/puppet/fuel/manifests/postgresql.pp b/deployment/puppet/fuel/manifests/postgresql.pp new file mode 100644 index 0000000000..8373370c75 --- /dev/null +++ b/deployment/puppet/fuel/manifests/postgresql.pp @@ -0,0 +1,49 @@ +class fuel::postgresql( + $nailgun_db_name = $::fuel::params::nailgun_db_name, + $nailgun_db_user = $::fuel::params::nailgun_db_user, + $nailgun_db_password = $::fuel::params::nailgun_db_password, + + $keystone_db_name = $::fuel::params::keystone_db_name, + $keystone_db_user = $::fuel::params::keystone_db_user, + $keystone_db_password = $::fuel::params::keystone_db_password, + + $ostf_db_name = $::fuel::params::ostf_db_name, + $ostf_db_user = $::fuel::params::ostf_db_user, + $ostf_db_password = $::fuel::params::ostf_db_password, +) inherits fuel::params { + + # install and configure postgresql server + class { 'postgresql::globals': + server_package_name => "postgresql-server", + client_package_name => "postgresql", + encoding => 'UTF8', + } + + class { 'postgresql::server': + listen_addresses => '0.0.0.0', + ip_mask_allow_all_users => '0.0.0.0/0', + } + + postgresql::server::db{ $nailgun_db_name: + user => $nailgun_db_user, + password => $nailgun_db_password, + grant => 'all', + require => Class['::postgresql::server'], + } + + postgresql::server::db { $keystone_db_name: + user => $keystone_db_user, + password => $keystone_db_password, + grant => 'all', + require => Class['::postgresql::server'], + } + + postgresql::server::db { $ostf_db_name: + user => $ostf_db_user, + password => $ostf_db_password, + grant => 'all', + require => Class['::postgresql::server'], + } + + ensure_packages(['python-psycopg2', 'postgresql-libs']) +} diff --git a/deployment/puppet/fuel/manifests/puppetsync.pp b/deployment/puppet/fuel/manifests/puppetsync.pp new file mode 100644 index 0000000000..28eaffb1d3 --- /dev/null +++ b/deployment/puppet/fuel/manifests/puppetsync.pp @@ -0,0 +1,35 @@ +class fuel::puppetsync ( + $puppet_folder = '/etc/puppet', + $xinetd_config = '/etc/xinetd.d/rsync', + $rsync_config = '/etc/rsyncd.conf', + ){ + + File { + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + } + + file { 'rsync_conf' : + path => $rsync_config, + content => template('fuel/rsyncd.conf.erb'), + } + + file { 'rsync_xinetd' : + path => $xinetd_config, + content => template('fuel/rsyncd_xinetd.erb'), + } + + ensure_packages(['xinetd', 'rsync']) + + if ! defined(Service['xinetd']) { + service { 'xinetd': + ensure => running, + enable => true, + require => Package['xinetd'], + } + } + + Package['rsync'] -> File['rsync_conf', 'rsync_xinetd'] ~> Service['xinetd'] +} diff --git a/deployment/puppet/fuel/manifests/rabbitmq.pp b/deployment/puppet/fuel/manifests/rabbitmq.pp new file mode 100644 index 0000000000..93a0bc8752 --- /dev/null +++ b/deployment/puppet/fuel/manifests/rabbitmq.pp @@ -0,0 +1,199 @@ +class fuel::rabbitmq ( + $rabbitmq_gid = $::fuel::params::rabbitmq_gid, + $rabbitmq_uid = $::fuel::params::rabbitmq_uid, + + $astute_user = $::fuel::params::rabbitmq_astute_user, + $astute_password = $::fuel::params::rabbitmq_astute_password, + + $mco_user = $::fuel::params::mco_user, + $mco_password = $::fuel::params::mco_password, + $mco_vhost = $::fuel::params::mco_vhost, + + $bind_ip = $::fuel::params::mco_host, + $management_port = '15672', + $stompport = $::fuel::params::mco_port, + $env_config = {}, + $stomp = false, + ) inherits fuel::params { + + include stdlib + anchor { 'rabbitmq-begin' :} + anchor { 'rabbitmq-end' :} + + file { '/etc/default/rabbitmq-server': + ensure => absent, + require => Package['rabbitmq-server'], + before => Service['rabbitmq-server'], + } + + group { "rabbitmq" : + provider => "groupadd", + ensure => "present", + gid => $rabbitmq_gid, + } + + user { "rabbitmq": + ensure => present, + managehome => true, + uid => $rabbitmq_uid, + gid => $rabbitmq_gid, + shell => '/bin/bash', + home => '/var/lib/rabbitmq', + comment => 'RabbitMQ messaging server', + require => Group["rabbitmq"], + } + + file { "/var/log/rabbitmq": + ensure => directory, + owner => 'rabbitmq', + group => 'rabbitmq', + mode => 0755, + require => User['rabbitmq'], + before => Service["rabbitmq-server"], + } + + rabbitmq_user { $astute_user: + admin => true, + password => $astute_password, + provider => 'rabbitmqctl', + require => Class['::rabbitmq'], + } + + rabbitmq_vhost { "/": + require => Class['::rabbitmq'], + } + + rabbitmq_user_permissions { "${astute_user}@/": + configure_permission => '.*', + write_permission => '.*', + read_permission => '.*', + provider => 'rabbitmqctl', + require => [Class['::rabbitmq'], Rabbitmq_vhost['/']] + } + + file { "/etc/rabbitmq/enabled_plugins": + content => '[amqp_client,rabbitmq_stomp,rabbitmq_management].', + owner => root, + group => root, + mode => 0644, + require => Package["rabbitmq-server"], + notify => Service["rabbitmq-server"], + } + + if $stomp { + $actual_mco_vhost = "/" + } else { + rabbitmq_vhost { $mco_vhost: + require => Class['::rabbitmq'], + } + $actual_mco_vhost = $mco_vhost + } + + rabbitmq_user { $mco_user: + admin => true, + password => $mco_password, + provider => 'rabbitmqctl', + require => Class['::rabbitmq'], + } + + rabbitmq_user_permissions { "${mco_user}@${actual_mco_vhost}": + configure_permission => '.*', + write_permission => '.*', + read_permission => '.*', + provider => 'rabbitmqctl', + require => Class['::rabbitmq'], + } + + exec { 'create-mcollective-directed-exchange': + + command => "curl -L -i -u ${mco_user}:${mco_password} -H \"content-type:application/json\" -XPUT \ + -d'{\"type\":\"direct\",\"durable\":true}'\ + http://${bind_ip}:${management_port}/api/exchanges/${actual_mco_vhost}/mcollective_directed", + logoutput => true, + require => [ + Service['rabbitmq-server'], + Rabbitmq_user_permissions["${mco_user}@${actual_mco_vhost}"], + ], + path => '/bin:/usr/bin:/sbin:/usr/sbin', + tries => 10, + try_sleep => 3, + } + + exec { 'create-mcollective-broadcast-exchange': + command => "curl -L -i -u ${mco_user}:${mco_password} -H \"content-type:application/json\" -XPUT \ + -d'{\"type\":\"topic\",\"durable\":true}' \ + http://${bind_ip}:${management_port}/api/exchanges/${actual_mco_vhost}/mcollective_broadcast", + logoutput => true, + require => [Service['rabbitmq-server'], + Rabbitmq_user_permissions["${mco_user}@${actual_mco_vhost}"]], + path => '/bin:/usr/bin:/sbin:/usr/sbin', + tries => 10, + try_sleep => 3, + } + + # NOTE(bogdando) indentation is important + $rabbit_tcp_listen_options = + '[ + binary, + {packet, raw}, + {reuseaddr, true}, + {backlog, 128}, + {nodelay, true}, + {exit_on_close, false}, + {keepalive, true} + ]' + + $rabbitmq_management_variables = {'listener' => "[{port, 15672}, {ip, \"${bind_ip}\"}]"} + + # NOTE(bogdando) requires rabbitmq module >=4.0 + class { '::rabbitmq': + repos_ensure => false, + package_provider => 'yum', + package_source => undef, + environment_variables => $env_config, + service_ensure => 'running', + delete_guest_user => true, + config_cluster => false, + cluster_nodes => [], + config_stomp => true, + stomp_port => $stompport, + ssl => false, + node_ip_address => $bind_ip, + config_kernel_variables => { + 'inet_dist_listen_min' => '41055', + 'inet_dist_listen_max' => '41055', + 'inet_default_connect_options' => '[{nodelay,true}]', + }, + config_variables => { + 'log_levels' => '[{connection,debug,info,error}]', + 'default_vhost' => '<<"">>', + 'default_permissions' => '[<<".*">>, <<".*">>, <<".*">>]', + 'tcp_listen_options' => $rabbit_tcp_listen_options, + }, + + config_management_variables => $rabbitmq_management_variables, + require => User["rabbitmq"], + } + + # NOTE(bogdando) retries for the rabbitmqadmin curl command, unmerged MODULES-1650 + Staging::File <| title == 'rabbitmqadmin' |> { + tries => 30, + try_sleep => 6, + } + # TODO(bogdando) contribute this to puppetlabs-rabbitmq + # Start epmd as rabbitmq so it doesn't run as root when installing plugins + exec { 'epmd_daemon': + command => 'epmd -daemon', + path => '/bin:/sbin:/usr/bin:/usr/sbin', + user => 'rabbitmq', + group => 'rabbitmq', + unless => 'pgrep epmd', + } + # Make sure the various providers have their requirements in place. + Class['::rabbitmq::install'] -> Exec['epmd_daemon'] + -> Rabbitmq_plugin<| |> -> Rabbitmq_exchange<| |> + + Anchor['rabbitmq-begin'] -> + Class['::rabbitmq'] -> + Anchor['rabbitmq-end'] +} diff --git a/deployment/puppet/fuel/manifests/sshkeygen.pp b/deployment/puppet/fuel/manifests/sshkeygen.pp new file mode 100644 index 0000000000..ed303ea97c --- /dev/null +++ b/deployment/puppet/fuel/manifests/sshkeygen.pp @@ -0,0 +1,67 @@ +define fuel::sshkeygen ( + $length = 2048, + $homedir = "/root", + $username = "root", + $groupname = "root", + $keytype = "rsa", + ){ + + Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'} + + if ! $keytype =~ /^(rsa|dsa)$/ { + fail("Wrong keytype parameter: ${keytype}") + } + + file { $homedir : + mode => 0755, + owner => $username, + group => $groupname, + ensure => directory, + } + + file { "${homedir}/.ssh" : + mode => 0700, + owner => $username, + group => $groupname, + ensure => directory, + require => File[$homedir], + } + + exec { "Generate ssh key for #{username}": + command => "ssh-keygen -t ${keytype} -b ${length} -N '' -f ${homedir}/.ssh/id_${keytype}", + creates => "${homedir}/.ssh/id_${keytype}", + user => $username, + group => $groupname, + require => File["${homedir}/.ssh"], + } + + file { "${homedir}/.ssh/id_${keytype}": + owner => $username, + group => $groupname, + mode => 0600, + require => Exec["Generate ssh key for #{username}"], + } + + exec { "Public ssh key for #{username}": + command => "ssh-keygen -y -f ${homedir}/.ssh/id_${keytype} > ${homedir}/.ssh/id_${keytype}.pub", + creates => "${homedir}/.ssh/id_${keytype}.pub", + user => $username, + group => $groupname, + require => [ + File["${homedir}/.ssh"], + Exec["Generate ssh key for #{username}"], + ] + } + + file { "${homedir}/.ssh/id_${keytype}.pub": + owner => $username, + group => $groupname, + mode => 0644, + require => Exec["Public ssh key for #{username}"], + } + + exec {"copy public key to authorized_keys": + command => "cat ${homedir}/.ssh/id_${keytype}.pub | tee -a ${homedir}/.ssh/authorized_keys", + require => File["${homedir}/.ssh/id_${keytype}.pub"] + } + } diff --git a/deployment/puppet/fuel/manifests/systemd.pp b/deployment/puppet/fuel/manifests/systemd.pp new file mode 100644 index 0000000000..56cdaceca6 --- /dev/null +++ b/deployment/puppet/fuel/manifests/systemd.pp @@ -0,0 +1,45 @@ +define fuel::systemd ( + $start = true, + $template_path = 'fuel/systemd/service_template.erb', + $config_name = 'fuel.conf' + ) { + + if !defined(File["/etc/systemd/system/${title}.service.d"]) { + file { "/etc/systemd/system/${title}.service.d": + ensure => directory + } + } + + file { "/etc/systemd/system/${title}.service.d/${config_name}": + content => template($template_path), + owner => 'root', + group => 'root', + mode => '0644', + notify => Exec['fuel_systemd_reload'] + } + + if !defined(Exec['fuel_systemd_reload']) { + exec { 'fuel_systemd_reload': + command => '/usr/bin/systemctl daemon-reload', + refreshonly => true, + } + } + + if !defined(Service[$title]) { + if $start { + service { "${title}": + ensure => running, + enable => true, + require => Exec['fuel_systemd_reload'], + subscribe => File["/etc/systemd/system/${title}.service.d/${config_name}"] + } + } + else { + service { "${title}": + enable => true, + require => Exec['fuel_systemd_reload'], + subscribe => File["/etc/systemd/system/${title}.service.d/${config_name}"] + } + } + } +} diff --git a/deployment/puppet/fuel/spec/classes/fuel__rabbitmq__spec.rb b/deployment/puppet/fuel/spec/classes/fuel__rabbitmq__spec.rb new file mode 100644 index 0000000000..6d41796ec9 --- /dev/null +++ b/deployment/puppet/fuel/spec/classes/fuel__rabbitmq__spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe 'fuel::rabbitmq', :type => :class do + context 'on supported platform' do + let(:facts) {{ + :osfamily => 'Debian', + :lsbdistid => 'Ubuntu', + :operatingsystem => 'Ubuntu', + :operatingsystemrelease => '14.04', + }} + context 'with default parameters' do + describe 'declares rabbitmq class' do + it { + should contain_class('rabbitmq') + } + end + describe 'and sets appropriate log_level configuration for rabbitmq' do + it { + should contain_file('rabbitmq.config').with({ + 'content' => /{log_levels, \[{connection,debug,info,error}\]},/, + }) + } + end + end + end +end diff --git a/deployment/puppet/fuel/spec/classes/nginx_nailgun_spec.rb b/deployment/puppet/fuel/spec/classes/nginx_nailgun_spec.rb new file mode 100644 index 0000000000..c5295ff1da --- /dev/null +++ b/deployment/puppet/fuel/spec/classes/nginx_nailgun_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe 'fuel::nginx::services' do + context 'when TLS enabled' do + let :params do + { + :staticdir => '/var/www/static/', + :logdumpdir => '/var/log/', + :ssl_enabled => true, + } + end + + it 'should create new Diffie-Hellmann parameters file' do + should contain_exec('create new dhparam file') + end + end +end diff --git a/deployment/puppet/fuel/spec/classes/nginx_service_spec.rb b/deployment/puppet/fuel/spec/classes/nginx_service_spec.rb new file mode 100644 index 0000000000..20032f29a5 --- /dev/null +++ b/deployment/puppet/fuel/spec/classes/nginx_service_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' + +describe 'fuel::nginx' do + it 'should contain X-Frame-Options SAMEORIGIN header' do + should contain_file('/etc/nginx/nginx.conf').with_content(/^\s*add_header X-Frame-Options SAMEORIGIN;$/) + end +end diff --git a/deployment/puppet/fuel/spec/fixtures/manifests/site.pp b/deployment/puppet/fuel/spec/fixtures/manifests/site.pp new file mode 100644 index 0000000000..fb21f5da69 --- /dev/null +++ b/deployment/puppet/fuel/spec/fixtures/manifests/site.pp @@ -0,0 +1,50 @@ +node 'default' { + $admin_networks = [ + {"id"=>1, + "node_group_name"=>nil, + "node_group_id"=>nil, + "cluster_name"=>nil, + "cluster_id"=>nil, + "cidr"=>"10.145.0.0/24", + "gateway"=>"10.145.0.2", + "ip_ranges"=>[["10.145.0.3", "10.145.0.250"]]}, + {"id"=>2, + "node_group_name"=>"default2", + "node_group_id"=>22, + "cluster_name"=>"default2", + "cluster_id"=>2, + "cidr"=>"10.144.0.0/24", + "gateway"=>"10.144.0.5", + "ip_ranges"=>[["10.144.0.10", "10.144.0.254"]]}, + # Network id=3 has parameters shared with network id=2 + {"id"=>3, + "node_group_name"=>"default3", + "node_group_id"=>23, + "cluster_name"=>"default3", + "cluster_id"=>3, + "cidr"=>"10.144.0.0/24", + "gateway"=>"10.144.0.5", + "ip_ranges"=>[["10.144.0.10", "10.144.0.254"]]}] + + $admin_network = {"interface"=>"eth0", + "ipaddress"=>"10.145.0.2", + "netmask"=>"255.255.255.0", + "cidr"=>"10.20.0.0/24", + "size"=>"256", + "dhcp_pool_start"=>"10.145.0.3", + "dhcp_pool_end"=>"10.145.0.254", + "mac"=>"64:42:d3:10:64:68", + "dhcp_gateway"=>"10.145.0.1"} + + Fuel::Dnsmasq::Dhcp_range <||> { + next_server => $admin_network['ipaddress'], + } + + file { '/etc/dnsmasq.d': + ensure => 'directory', + recurse => true, + purge => true, + } + + create_dnsmasq_dhcp_ranges($admin_networks, ['default']) +} diff --git a/deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb b/deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb new file mode 100644 index 0000000000..dd3f504993 --- /dev/null +++ b/deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe 'create_dnsmasq_dhcp_ranges' do + + it 'refuses String' do + is_expected.to run.with_params('foo').\ + and_raise_error(Puppet::ParseError, /Should pass list of hashes as a parameter/) + end + +end diff --git a/deployment/puppet/fuel/spec/functions/extend_kopts_spec.rb b/deployment/puppet/fuel/spec/functions/extend_kopts_spec.rb new file mode 100644 index 0000000000..095105b10d --- /dev/null +++ b/deployment/puppet/fuel/spec/functions/extend_kopts_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe 'extend_kopts' do + + it 'number args' do + is_expected.to run.with_params('foo').and_raise_error(Puppet::ParseError, "extend_kopts(): wrong number of arguments - 1, must be 2") + end + + it { should run.with_params("biosdevname=0 ifnames=1 rd.luks.uuid=30 panic=15 quiet debug udev.log-priority=2 systemd.gpt_auto=1","console=ttyS0,9600 console=tty0 console=tty1 panic=60 boot=live toram fetch=http://127.0.0.1:8080/active_bootstrap/root.squashfs biosdevname=0").and_return("biosdevname=0 ifnames=1 rd.luks.uuid=30 panic=15 quiet debug udev.log-priority=2 systemd.gpt_auto=1 console=ttyS0,9600 console=tty0 console=tty1 boot=live toram fetch=http://127.0.0.1:8080/active_bootstrap/root.squashfs") } + + it 'should merge options with the same key using first argument as high priority source' do + should run.with_params("bios=0 rd.luks=30", "bios=1 rd.luks=20").and_return("bios=0 rd.luks=30") + end + + it 'should combine unique options' do + should run.with_params("biosdevname=0 quit", "biosdevname=1 debug").and_return("biosdevname=0 quit debug") + end + + it 'should properly merge options contain key-value separator' do + should run.with_params("abc=def=123 debug", "abc=ttt=44 quit").and_return("abc=def=123 debug quit") + end + + it 'should save options order' do + should run.with_params("zx=123 ar bh=test", "").and_return("zx=123 ar bh=test") + end + + it 'should use default options if new are not present' do + should run.with_params("", "ff=11 quit ko=12").and_return("ff=11 quit ko=12") + end + + it 'should merge options with multiple values' do + should run.with_params("c=ttyS0,9600 c=tty0", "c=tty3 ff=11").and_return("c=ttyS0,9600 c=tty0 ff=11") + end + +end diff --git a/deployment/puppet/fuel/spec/hosts/default_spec.rb b/deployment/puppet/fuel/spec/hosts/default_spec.rb new file mode 100644 index 0000000000..747c452eed --- /dev/null +++ b/deployment/puppet/fuel/spec/hosts/default_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' +require 'zlib' +require 'ipaddr' + +describe 'default' do + admin_nets = [ + {"id"=>1, + "node_group_name"=>nil, + "node_group_id"=>nil, + "cluster_name"=>nil, + "cluster_id"=>nil, + "cidr"=>"10.145.0.0/24", + "gateway"=>"10.145.0.2", + "ip_ranges"=>[["10.145.0.3", "10.145.0.250"]]}, + {"id"=>2, + "node_group_name"=>"default2", + "node_group_id"=>22, + "cluster_name"=>"default2", + "cluster_id"=>2, + "cidr"=>"10.144.0.0/24", + "gateway"=>"10.144.0.5", + "ip_ranges"=>[["10.144.0.10", "10.144.0.254"]]}, + # Network with parameters shared with id=2 + {"id"=>3, + "node_group_name"=>"default3", + "node_group_id"=>23, + "cluster_name"=>"default3", + "cluster_id"=>3, + "cidr"=>"10.144.0.0/24", + "gateway"=>"10.144.0.5", + "ip_ranges"=>[["10.144.0.10", "10.144.0.254"]]} + ] + admin_network = {"interface"=>"eth0", + "ipaddress"=>"10.145.0.2", + "netmask"=>"255.255.255.0", + "cidr"=>"10.20.0.0/24", + "size"=>"256", + "dhcp_pool_start"=>"10.145.0.3", + "dhcp_pool_end"=>"10.145.0.254", + "mac"=>"64:42:d3:10:64:68", + "dhcp_gateway"=>"10.145.0.1"} + + admin_nets.each do |net| + net['ip_ranges'].each do |ip_range| + netmask = IPAddr.new('255.255.255.255').mask(net['cidr'].split('/')[1]).to_s + print_range = ip_range.join('_') + resource_name = sprintf("range_%08x", Zlib::crc32("#{print_range}_#{net['cidr']}").to_i) + it { should contain_file("/etc/dnsmasq.d/#{resource_name}.conf") \ + .with_content(/^dhcp-range=#{resource_name}.*#{netmask},120m\n|,boothost,#{admin_network['ipaddress']}\n/) + } + it { should contain_file("/etc/dnsmasq.d/#{resource_name}.conf") \ + .with_content(/^dhcp-match=set:ipxe,175$/) + } + it { should contain_file("/etc/dnsmasq.d/#{resource_name}.conf") \ + .with_content(/^dhcp-option-force=tag:ipxe,210,http:/) + } + end + end + +end diff --git a/deployment/puppet/fuel/spec/spec_helper.rb b/deployment/puppet/fuel/spec/spec_helper.rb new file mode 100644 index 0000000000..9384c6916f --- /dev/null +++ b/deployment/puppet/fuel/spec/spec_helper.rb @@ -0,0 +1,17 @@ +require 'rspec-puppet' +require 'puppetlabs_spec_helper/module_spec_helper' + +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) + +RSpec.configure do |c| + c.module_path = File.join(fixture_path, 'modules') + c.manifest_dir = File.join(fixture_path, 'manifests') + c.mock_with(:mocha) +end + +def puppet_debug_override + if ENV['SPEC_PUPPET_DEBUG'] + Puppet::Util::Log.level = :debug + Puppet::Util::Log.newdestination(:console) + end +end diff --git a/deployment/puppet/fuel/spec/unit/puppet/provider/merge_yaml_settings/ruby_spec.rb b/deployment/puppet/fuel/spec/unit/puppet/provider/merge_yaml_settings/ruby_spec.rb new file mode 100755 index 0000000000..c76ee268c7 --- /dev/null +++ b/deployment/puppet/fuel/spec/unit/puppet/provider/merge_yaml_settings/ruby_spec.rb @@ -0,0 +1,155 @@ +require 'spec_helper' +require 'yaml' + +provider_class = Puppet::Type.type(:merge_yaml_settings).provider(:ruby) +describe provider_class do + + let(:sample_filepath) { "/test/sample_file_path.yaml" } + let(:settings_filepath) { "/test/settings_file_path.yaml" } + let(:dest_filepath) { "/test/dest_file_path.yaml" } + + let(:sample) { + { + :SETTING_A => 'Value1', + :SETTING_B => 'Value2', + } + } + + let(:settings) { + { + :SETTING_A => 'new_value1', + :SETTING_B => 'new_value2', + :SETTING_C => 'new_value', + } + } + + let(:result) { + { + :SETTING_A => 'new_value1', + :SETTING_B => 'new_value2', + :SETTING_C => 'new_value' + } + } + + before(:each) do + puppet_debug_override() + end + + it 'should merge settings if sample is file and settings is hash' do + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :sample_settings => sample_filepath, + :provider => 'ruby', + :override_settings => settings + } + ) + + provider = provider_class.new(resource) + provider.stubs(:get_dict).with(sample_filepath).returns(sample) + provider.stubs(:get_dict).with(settings).returns(settings) + provider.stubs(:write_to_file).with(dest_filepath, YAML.dump(result)).once + provider.create() + end + + it 'should FAIL if file can not be written' do + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :sample_settings => sample_filepath, + :provider => 'ruby', + :override_settings => settings + } + ) + + provider = provider_class.new(resource) + provider.stubs(:get_dict).with(sample_filepath).returns(sample) + provider.stubs(:get_dict).with(settings).returns(settings) + File.class.stubs(:open) + .with(dest_filepath) + .raises(IOError) + expect{ provider.create() }.to raise_error(Puppet::Error, %r{merge_yaml_settings:\s+the\s+file\s+\/test\/dest_file_path.yaml\s+can\s+not\s+be\s+written!}) + end + + + it 'should merge settings if both are files' do + + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :sample_settings => sample_filepath, + :provider => 'ruby', + :override_settings => settings_filepath + } + ) + + provider = provider_class.new(resource) + provider.stubs(:get_dict).with(sample_filepath).returns(sample) + provider.stubs(:get_dict).with(settings_filepath).returns(settings) + provider.stubs(:write_to_file).with(dest_filepath, YAML.dump(result)).once + provider.create() + end + + it 'should merge settings if both are hashes' do + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :sample_settings => sample, + :provider => 'ruby', + :override_settings => settings + } + ) + + provider = provider_class.new(resource) + provider.stubs(:write_to_file).with(dest_filepath, YAML.dump(result)).once + provider.create() + end + + it 'should use sample settings if other is not present' do + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :sample_settings => sample, + :provider => 'ruby', + } + ) + + provider = provider_class.new(resource) + provider.stubs(:write_to_file).with(dest_filepath, YAML.dump(sample)).once + provider.create() + end + + it 'should use new settings if other is not present' do + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :override_settings => settings, + :provider => 'ruby', + } + ) + + provider = provider_class.new(resource) + provider.stubs(:write_to_file).with(dest_filepath, YAML.dump(settings)).once + provider.create() + end + + it 'should not write to file if result is empty' do + + resource = Puppet::Type::Merge_yaml_settings.new( + { + :name => dest_filepath, + :provider => 'ruby', + } + ) + + provider = provider_class.new(resource) + provider.stubs(:write_to_file).with(dest_filepath, YAML.dump(sample)).never + provider.create() + end +end diff --git a/deployment/puppet/fuel/templates/astute/astuted.conf.erb b/deployment/puppet/fuel/templates/astute/astuted.conf.erb new file mode 100644 index 0000000000..8d2a5d1aa9 --- /dev/null +++ b/deployment/puppet/fuel/templates/astute/astuted.conf.erb @@ -0,0 +1,18 @@ +# Warning! If you restart container, this file will be return +# to original state by puppet. If you do not want it, please comment +# `puppet apply -v /etc/puppet/modules/nailgun/examples/astute-only.pp` +# in /usr/local/bin/start.sh + +broker_host: '<%= @rabbitmq_host %>' +broker_port: 5672 +broker_username: '<%= @rabbitmq_astute_user %>' +broker_password: '<%= @rabbitmq_astute_password %>' +broker_queue: 'naily' +broker_publisher_queue: 'nailgun' +broker_exchange: 'nailgun' +iops: <%= @iops %> +bootstrap_profile: '<%= @bootstrap_profile %>' +#reboot_timeout: 120 # Wait for reboot request +#provisioning_timeout: 5400 # Timeout for target nodes to install OS +#dump_timeout: 3600 # Timeout for dump +#puppet_timeout: 5400 # Timeout for single puppet run diff --git a/deployment/puppet/fuel/templates/astute/astuted.erb b/deployment/puppet/fuel/templates/astute/astuted.erb new file mode 100644 index 0000000000..6860449be5 --- /dev/null +++ b/deployment/puppet/fuel/templates/astute/astuted.erb @@ -0,0 +1,2 @@ +#!/bin/bash +ruby -r 'rubygems' -e "gem 'astute', '>= 0'; load Gem.bin_path('astute', 'astuted', '>= 0')" -- $@ \ No newline at end of file diff --git a/deployment/puppet/fuel/templates/astute/sysconfig.erb b/deployment/puppet/fuel/templates/astute/sysconfig.erb new file mode 100644 index 0000000000..6c40b8ba66 --- /dev/null +++ b/deployment/puppet/fuel/templates/astute/sysconfig.erb @@ -0,0 +1 @@ +ASTUTE_OPTIONS="--config /etc/astute/astuted.conf --logfile /var/log/astute/astute.log --loglevel debug --workers 7" diff --git a/deployment/puppet/fuel/templates/cobbler/fence_ssh.template.erb b/deployment/puppet/fuel/templates/cobbler/fence_ssh.template.erb new file mode 100644 index 0000000000..130703c632 --- /dev/null +++ b/deployment/puppet/fuel/templates/cobbler/fence_ssh.template.erb @@ -0,0 +1,7 @@ +action=$power_mode +login=$power_user +passwd="unset" +identity_file=$power_pass +port=1 +ipaddr=$power_address +power_timeout=20 \ No newline at end of file diff --git a/deployment/puppet/fuel/templates/dhclient.conf.erb b/deployment/puppet/fuel/templates/dhclient.conf.erb new file mode 100644 index 0000000000..d17616c357 --- /dev/null +++ b/deployment/puppet/fuel/templates/dhclient.conf.erb @@ -0,0 +1 @@ +prepend domain-name-servers <%= @cobbler_host %>; diff --git a/deployment/puppet/fuel/templates/dhcp-enter-hooks.erb b/deployment/puppet/fuel/templates/dhcp-enter-hooks.erb new file mode 100644 index 0000000000..93cd566cfe --- /dev/null +++ b/deployment/puppet/fuel/templates/dhcp-enter-hooks.erb @@ -0,0 +1,4 @@ +#!/bin/bash +make_resolv_conf() { + return 0 +} diff --git a/deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb b/deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb new file mode 100644 index 0000000000..25ad52ed15 --- /dev/null +++ b/deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb @@ -0,0 +1,6 @@ +<% if @file_header %><%= @file_header %><% end %> +dhcp-range=<%= @range_name %>,<%= @dhcp_start_address %>,<%= @dhcp_end_address %>,<%= @dhcp_netmask %>,<%= @lease_time %> +dhcp-option=net:<%= @range_name %>,option:router,<%= @dhcp_gateway %> +dhcp-boot=net:<%= @range_name %>,pxelinux.0,boothost,<%= @next_server %> +dhcp-match=set:ipxe,175 +dhcp-option-force=tag:ipxe,210,http://<%= @next_server %>/cobbler/boot/ diff --git a/deployment/puppet/fuel/templates/free_disk_check.yaml.erb b/deployment/puppet/fuel/templates/free_disk_check.yaml.erb new file mode 100644 index 0000000000..43c60e3cb4 --- /dev/null +++ b/deployment/puppet/fuel/templates/free_disk_check.yaml.erb @@ -0,0 +1,3 @@ +monitord_user: <%= scope.lookupvar('monitord_user') %> +monitord_password: <%= scope.lookupvar('monitord_password') %> +monitord_tenant: <%= scope.lookupvar('monitord_tenant') %> diff --git a/deployment/puppet/fuel/templates/fuel_utils_config.erb b/deployment/puppet/fuel/templates/fuel_utils_config.erb new file mode 100644 index 0000000000..ed7f31b80f --- /dev/null +++ b/deployment/puppet/fuel/templates/fuel_utils_config.erb @@ -0,0 +1,4 @@ +ASTUTE_YAML="/etc/fuel/astute.yaml" +CHECK_RETRIES=240 +SYSTEMD="true" +ADMIN_IP="<%= @admin_ip %>" diff --git a/deployment/puppet/fuel/templates/logrotate.conf.erb b/deployment/puppet/fuel/templates/logrotate.conf.erb new file mode 100644 index 0000000000..769c3fabf0 --- /dev/null +++ b/deployment/puppet/fuel/templates/logrotate.conf.erb @@ -0,0 +1,11 @@ +/var/log/nailgun/api.log +/var/log/nailgun/app.log +{ + copytruncate + size 20M + rotate 5 + compress + delaycompress + missingok + notifempty +} diff --git a/deployment/puppet/fuel/templates/nailgun/client.yaml.erb b/deployment/puppet/fuel/templates/nailgun/client.yaml.erb new file mode 100644 index 0000000000..25c3bcf5a7 --- /dev/null +++ b/deployment/puppet/fuel/templates/nailgun/client.yaml.erb @@ -0,0 +1,5 @@ +SERVER_ADDRESS: "<%= @server_address %>" +SERVER_PORT: "<%= @server_port %>" +KEYSTONE_USER: "<%= @keystone_user %>" +KEYSTONE_PASS: "<%= @keystone_password %>" +KEYSTONE_PORT: "<%= @keystone_port %>" diff --git a/deployment/puppet/fuel/templates/nailgun/cron_daily_capacity.erb b/deployment/puppet/fuel/templates/nailgun/cron_daily_capacity.erb new file mode 100644 index 0000000000..744b85cdec --- /dev/null +++ b/deployment/puppet/fuel/templates/nailgun/cron_daily_capacity.erb @@ -0,0 +1,3 @@ +#!/bin/sh + +curl -X PUT -d {} http://localhost:8000/api/capacity \ No newline at end of file diff --git a/deployment/puppet/fuel/templates/nailgun/settings.yaml.erb b/deployment/puppet/fuel/templates/nailgun/settings.yaml.erb new file mode 100644 index 0000000000..99abd2b071 --- /dev/null +++ b/deployment/puppet/fuel/templates/nailgun/settings.yaml.erb @@ -0,0 +1,100 @@ +LISTEN_ADDRESS: "0.0.0.0" +LISTEN_PORT: "8001" +DEVELOPMENT: false +AUTH: + # Possible options: + # - none - authentication is disabled + # - fake - no keystone required, credentials: admin/admin + # - keystone - authentication enabled. + AUTHENTICATION_METHOD: "keystone" + # use only if AUTHENTICATION_METHOD is set to "keystone" + auth_host: "<%= @keystone_host %>" + auth_protocol: "http" + auth_version: "v2.0" + admin_user: "<%= @keystone_user %>" + admin_password: "<%= @keystone_password %>" + admin_tenant_name: "services" + +<% if @feature_groups.empty? -%> +FEATURE_GROUPS: [] +<% else -%> +FEATURE_GROUPS: + <% @feature_groups.each do |fgrp| -%> + - <%= fgrp %> + <% end -%> +<% end -%> + +DATABASE: + engine: "<%= @db_engine %>" + name: "<%= @db_name %>" + host: "<%= @db_host %>" + port: "<%= @db_port %>" + user: "<%= @db_user %>" + passwd: "<%= @db_password %>" + +FUEL_KEY: "<%= @fuel_key %>" + +STATIC_DIR: "<%= @staticdir %>" +TEMPLATE_DIR: "<%= @templatedir %>" +NETWORK_POOLS: + public: + - "172.16.0.0/16" + private10: + - "10.0.0.0/8" + private192: + - "192.168.0.0/16" + +NET_EXCLUDE: + - "<%= @exclude_network %>/<%= @exclude_cidr %>" + +ADMIN_NETWORK: + cidr: "<%= @admin_network %>/<%= @admin_network_cidr %>" + netmask: "<%= @admin_network_netmask %>" + mac: "<%= @admin_network_mac %>" + size: "<%= @admin_network_size %>" + first: "<%= @admin_network_first %>" + last: "<%= @admin_network_last %>" + gateway: "<%= @admin_network_gateway %>" + +VLANS_RANGE_START: "100" +VLANS_RANGE_END: "1000" + +RABBITMQ: + fake: "0" + hostname: "<%= @rabbitmq_host %>" + port: 5672 + userid: "<%= @rabbitmq_astute_user %>" + password: "<%= @rabbitmq_astute_password %>" + virtual_host: "/" + +APP_LOG: "/var/log/nailgun/app.log" +API_LOG: "/var/log/nailgun/api.log" + +# possible values: "CRITICAL", "ERROR", "WARNING", "INFO" and "DEBUG" +APP_LOGLEVEL: "<%= @nailgun_log_level %>" + +PATH_TO_SSH_KEY: "/root/.ssh/id_rsa" +PATH_TO_BOOTSTRAP_SSH_KEY: "/root/.ssh/bootstrap.rsa" +AUTHORIZED_KEYS: + - "<%= scope.function_strip([scope.function_file(["/root/.ssh/id_rsa.pub"])]) %>" + +MASTER_IP: "<%= @admin_network_ip %>" + +COBBLER_URL: "<%= @cobbler_url %>" +COBBLER_USER: "<%= @cobbler_user %>" +COBBLER_PASSWORD: "<%= @cobbler_password %>" +COBBLER_PROFILE: "centos-x86_64" + +MCO_PSKEY: "<%= @mco_pskey %>" +MCO_VHOST: "<%= @mco_vhost %>" +MCO_HOST: <%= @mco_host %> +MCO_USER: "<%= @mco_user %>" +MCO_PASSWORD: "<%= @mco_password %>" +MCO_CONNECTOR: "<%= @mco_connector %>" + +DNS_DOMAIN: "<%= @dns_domain %>" +DNS_SERVERS: "<%= @cobbler_host %>" +DNS_SEARCH: "<%= @dns_domain.gsub(/,/, ' ') %>" +DNS_UPSTREAM: "<%= @dns_upstream %>" + +NTP_UPSTREAM: "<%= @ntp_upstream %>" diff --git a/deployment/puppet/fuel/templates/nailgun/uwsgi_nailgun.yaml.erb b/deployment/puppet/fuel/templates/nailgun/uwsgi_nailgun.yaml.erb new file mode 100644 index 0000000000..89b2089add --- /dev/null +++ b/deployment/puppet/fuel/templates/nailgun/uwsgi_nailgun.yaml.erb @@ -0,0 +1,19 @@ +uwsgi: + enable-threads: 1 + threads: 1 + workers: <%= (@physicalprocessorcount) %> + master: 1 + socket: :8001 + plugin: python + chown-socket: nginx:nginx + pythonpath: /usr/lib/python2.7/site-packages/nailgun + touch-reload: /var/lib/nailgun-uwsgi + virtualenv: /usr + module: nailgun.wsgi + buffer-size: 49180 + listen: <%= @somaxconn %> + pidfile: /var/run/nailgun.pid + logto: /var/log/nailgun/app.log + mule: 1 + lazy: true + shared-pyimport: /usr/lib/python2.7/site-packages/nailgun/utils/mule.py diff --git a/deployment/puppet/fuel/templates/nginx/nginx.conf.erb b/deployment/puppet/fuel/templates/nginx/nginx.conf.erb new file mode 100644 index 0000000000..546136ff51 --- /dev/null +++ b/deployment/puppet/fuel/templates/nginx/nginx.conf.erb @@ -0,0 +1,44 @@ +user nginx; +worker_processes <%= [[@processorcount.to_i, 2].min, @processorcount.to_i / 2].max %>; + +error_log /var/log/nginx/error.log; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + + # don't buffer data-sends (disable Nagle algorithm). + # Good for sending frequent small bursts of data in real time. + tcp_nodelay on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + server_tokens off; + #gzip on; + + #prefer server ciphers over client ones + ssl_prefer_server_ciphers on; + + #prevent from clickjacking attacks + add_header X-Frame-Options SAMEORIGIN; + + # Load config files from the /etc/nginx/conf.d directory + # The default server is in conf.d/default.conf + include /etc/nginx/conf.d/*.conf; +} diff --git a/deployment/puppet/fuel/templates/nginx/repo.conf.erb b/deployment/puppet/fuel/templates/nginx/repo.conf.erb new file mode 100644 index 0000000000..f68bc6e838 --- /dev/null +++ b/deployment/puppet/fuel/templates/nginx/repo.conf.erb @@ -0,0 +1,25 @@ +server { + listen <%= @repo_port %>; + + server_name localhost; + + access_log /var/log/nginx/access_repo.log; + error_log /var/log/nginx/error_repo.log debug; + + charset utf-8; + client_max_body_size 2M; + + location / { + autoindex on; + root <%= @repo_root %>; + } + + location ~ /\.ht { + deny all; + } + + location /dump/ { + deny all; + } + +} diff --git a/deployment/puppet/fuel/templates/nginx/services.conf.erb b/deployment/puppet/fuel/templates/nginx/services.conf.erb new file mode 100644 index 0000000000..50769d9535 --- /dev/null +++ b/deployment/puppet/fuel/templates/nginx/services.conf.erb @@ -0,0 +1,66 @@ +server { + <%- if @plain_http -%> + listen 8000; + <% else %> + listen 8000; + return 301 https://$host:8443$request_uri; +} + +server { + <%- end -%> + <%- if @ssl_enabled -%> + listen 8443 ssl; + ssl_certificate /var/lib/fuel/keys/master/nginx/nginx.crt; + ssl_certificate_key /var/lib/fuel/keys/master/nginx/nginx.key; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + <%- end -%> + + server_name localhost; + + access_log /var/log/nginx/access_services.log; + error_log /var/log/nginx/error_services.log debug; + + charset utf-8; + client_max_body_size 10M; + + location = /favicon.ico { + log_not_found off; + access_log off; + } + + gzip on; + gzip_min_length 1000; + gzip_types text/plain text/css application/json application/javascript application/x-javascript; + + location /static { + autoindex on; + alias <%= @staticdir %>; + } + + location /dump { + internal; + alias <%= @logdumpdir %>; + } + + location ~ ^/ostf/(.*) { + proxy_pass http://<%= @ostf_host %>:<%= @ostf_port %>/v1/$1; + proxy_buffering off; + } + + location ~ ^/keystone/(.*) { + proxy_pass http://<%= @keystone_host %>:<%= @keystone_port %>/$1; + proxy_buffering off; + } + + location / { + expires -1; + root <%= @staticdir %>; + } + + location /api { + include uwsgi_params; + uwsgi_pass <%= @nailgun_host %>:<%= @nailgun_port %>; + client_max_body_size 100m; + } +} diff --git a/deployment/puppet/fuel/templates/ostf.conf.erb b/deployment/puppet/fuel/templates/ostf.conf.erb new file mode 100644 index 0000000000..9709a6bb43 --- /dev/null +++ b/deployment/puppet/fuel/templates/ostf.conf.erb @@ -0,0 +1,19 @@ +[adapter] +server_host = <%= @host %> +server_port = <%= @port %> +dbpath = <%= @dbengine %>://<%= @dbuser %>:<%= @dbpass %>@<%= @dbhost %>/<%= @dbname %> +lock_dir = /var/lock +nailgun_host = <%= @nailgun_host %> +nailgun_port = <%= @nailgun_port %> +log_file = <%= @logfile %> +after_init_hook = False +auth_enable = <%= @auth_enable %> + +[keystone_authtoken] +auth_protocol=http +auth_port=<%= @keystone_port %> +auth_host=<%= @keystone_host %> +auth_version=v2.0 +admin_user=<%= @keystone_ostf_user %> +admin_password=<%= @keystone_ostf_pass %> +admin_tenant_name=services diff --git a/deployment/puppet/fuel/templates/resolv.conf.erb b/deployment/puppet/fuel/templates/resolv.conf.erb new file mode 100644 index 0000000000..d24b1ce1f9 --- /dev/null +++ b/deployment/puppet/fuel/templates/resolv.conf.erb @@ -0,0 +1,6 @@ +search <%= @dns_search %> +domain <%= @dns_domain %> +nameserver <%= @cobbler_host %> +<%- @dns_upstream.each do |dns| -%> +nameserver <%= dns %> +<%- end -%> diff --git a/deployment/puppet/fuel/templates/root_ssh_config.erb b/deployment/puppet/fuel/templates/root_ssh_config.erb new file mode 100644 index 0000000000..b1bfbf4c65 --- /dev/null +++ b/deployment/puppet/fuel/templates/root_ssh_config.erb @@ -0,0 +1,14 @@ +Host * + IdentityFile ~/.ssh/bootstrap.rsa + IdentityFile ~/.ssh/id_rsa + +Host *.<%= @dns_domain %> node-* controller-* compute-* storage-* 10.* 192.168.* 172.30.* 172.31.* 172.2?.* 172.1?.* <%= @admin_network %> <% +if @extra_networks.is_a?(Hash) + @extra_networks.each do |netname, net| -%> + <%= scope.function_ipcalc_network_wildcard([net['ipaddress'],net['netmask']]) %><% + end +end %> + CheckHostIP no + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + AddressFamily inet diff --git a/deployment/puppet/fuel/templates/rsyncd.conf.erb b/deployment/puppet/fuel/templates/rsyncd.conf.erb new file mode 100644 index 0000000000..39a940f283 --- /dev/null +++ b/deployment/puppet/fuel/templates/rsyncd.conf.erb @@ -0,0 +1,13 @@ +[puppet] +path = <%= @puppet_folder %> +read only = true +uid = 0 +gid = 0 +use chroot = no + +[plugins] +path = /var/www/nailgun/plugins +read only = true +uid = 0 +gid = 0 +use chroot = no \ No newline at end of file diff --git a/deployment/puppet/fuel/templates/rsyncd_xinetd.erb b/deployment/puppet/fuel/templates/rsyncd_xinetd.erb new file mode 100644 index 0000000000..85cae57504 --- /dev/null +++ b/deployment/puppet/fuel/templates/rsyncd_xinetd.erb @@ -0,0 +1,13 @@ +service rsync +{ + disable = no + socket_type = stream + wait = no + user = root + server = /usr/bin/rsync + server_args = --daemon --log-file=/var/log/rsync.log + cps = 512 10 + flags = IPv4 + per_source = UNLIMITED + log_on_failure += USERID +} diff --git a/deployment/puppet/fuel/templates/systemd/restart_template.erb b/deployment/puppet/fuel/templates/systemd/restart_template.erb new file mode 100644 index 0000000000..a43a4f39ba --- /dev/null +++ b/deployment/puppet/fuel/templates/systemd/restart_template.erb @@ -0,0 +1,3 @@ +[Service] +Restart=on-failure +RestartSec=5 diff --git a/deployment/puppet/fuel/templates/systemd/service_template.erb b/deployment/puppet/fuel/templates/systemd/service_template.erb new file mode 100644 index 0000000000..394cd17026 --- /dev/null +++ b/deployment/puppet/fuel/templates/systemd/service_template.erb @@ -0,0 +1,12 @@ +[Service] +Restart=on-failure +RestartSec=10s +StartLimitBurst=10 +TimeoutStartSec=10s +TimeoutStopSec=5s + +StandardInput=null +StandardOutput=syslog +StandardError=syslog+console +SyslogIdentifier=<%= @title %> + diff --git a/files/fuel-utils/config b/files/fuel-utils/config new file mode 100644 index 0000000000..6567f3142e --- /dev/null +++ b/files/fuel-utils/config @@ -0,0 +1,4 @@ +ASTUTE_YAML="/etc/fuel/astute.yaml" +CHECK_RETRIES=240 +SYSTEMD="true" +ADMIN_IP="10.20.0.2" diff --git a/files/fuel-utils/flat_yaml.py b/files/fuel-utils/flat_yaml.py new file mode 100644 index 0000000000..1030c35a61 --- /dev/null +++ b/files/fuel-utils/flat_yaml.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +# Copyright 2016 Mirantis, Inc. +# +# 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. + +import sys +import yaml + +yamlfile = sys.argv[1] +data = yaml.load(open(yamlfile)) + + +def traverse(data, head=''): + if isinstance(data, dict): + for key, value in data.iteritems(): + new_head = "{head}_{tail}".format(head=head, tail=key).lstrip('_') + traverse(value, new_head) + elif isinstance(data, (unicode, str)): + if "'" in data: + print("#Skipped because value contains single quote") + print("#{head}='{value}'".format(head=head, value=data)) + print("{head}='{value}'".format(head=head, value=data)) + elif isinstance(data, list): + for i, item in enumerate(data): + new_head = "{head}_{tail}".format(head=head, tail=i).lstrip('_') + traverse(item, new_head) + +traverse(data) diff --git a/files/fuel-utils/fuel-utils b/files/fuel-utils/fuel-utils new file mode 100644 index 0000000000..7dd886d812 --- /dev/null +++ b/files/fuel-utils/fuel-utils @@ -0,0 +1,59 @@ +#!/bin/bash +# Copyright 2016 Mirantis, Inc. +# +# 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. + +. "/etc/fuel-utils/config" +. "/usr/share/fuel-utils/functions.sh" + +usage(){ + cat >&1 < +Available subcommands: + check_all - Check whether all Fuel services are up and running + check_service - Check whether a particular service is up and running +Available service names: + astute + cobbler + keystone + mcollective + nailgun + nginx + ostf + postgres + rabbitmq + rsync + rsyslog +EOF + exit 1 +} + +case $1 in + check_all) + exit_code=0 + all_services="nailgun ostf cobbler rabbitmq postgres astute mcollective nginx keystone rsyslog rsync" + for service in $all_services; do + check_ready $service || exit_code=1 + done + exit $exit_code + ;; + check_service) + if [[ $# -ne 2 ]]; then + usage + fi + check_ready $2 || exit 1 + ;; + *) + usage + ;; +esac diff --git a/files/fuel-utils/functions.sh b/files/fuel-utils/functions.sh new file mode 100644 index 0000000000..4369905941 --- /dev/null +++ b/files/fuel-utils/functions.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# Copyright 2016 Mirantis, Inc. +# +# 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. + +function retry_checker { + tries=0 + echo "checking with command \"$*\"" + until eval $*; do + rc=$? + let 'tries=tries+1' + echo "try number $tries" + echo "return code is $rc" + if [ $tries -gt $CHECK_RETRIES ];then + failure=1 + break + fi + sleep 5 + done +} + +function get_service_credentials { + credentialfile=$(mktemp /tmp/servicepws.XXXXX) + flat_yaml.py $ASTUTE_YAML > $credentialfile + . $credentialfile + rm -f $credentialfile +} + +function check_ready { + #Uses a custom command to ensure a container is ready + get_service_credentials + failure=0 + + case $1 in + nailgun) + if [ "${SYSTEMD:-false}" == "true" ]; then + retry_checker "systemctl is-active nailgun" + else + retry_checker "supervisorctl status nailgun | grep -q RUNNING" + fi + ;; + ostf) + retry_checker "egrep -q ^[2-4][0-9]? < <(curl --connect-timeout 1 -s -w '%{http_code}' http://$ADMIN_IP:8777/ostf/not_found -o /dev/null)" + ;; + #NOTICE: Cobbler console tool does not comply unix conversation: 'cobbler profile find' always return 0 as exit code + cobbler) + retry_checker "ps waux | grep -q 'cobblerd -F' && pgrep dnsmasq" + retry_checker "cobbler profile find --name=centos* | grep -q centos && cobbler profile find --name=ubuntu* | grep -q ubuntu && cobbler profile find --name=bootstrap* | grep -q bootstrap" + ;; + rabbitmq) + retry_checker "curl -f -L -i -u \"$astute_user:$astute_password\" http://$ADMIN_IP:15672/api/nodes 1>/dev/null 2>&1" + retry_checker "curl -f -L -u \"$mcollective_user:$mcollective_password\" -s http://$ADMIN_IP:15672/api/exchanges | grep -qw 'mcollective_broadcast'" + retry_checker "curl -f -L -u \"$mcollective_user:$mcollective_password\" -s http://$ADMIN_IP:15672/api/exchanges | grep -qw 'mcollective_directed'" + ;; + postgres) + retry_checker "PGPASSWORD=$postgres_nailgun_password /usr/bin/psql -h $ADMIN_IP -U \"$postgres_nailgun_user\" \"$postgres_nailgun_dbname\" -c '\copyright' 2>&1 1>/dev/null" + ;; + astute) + retry_checker "ps waux | grep -q 'astuted'" + retry_checker "curl -f -L -u \"$astute_user:$astute_password\" -s http://$ADMIN_IP:15672/api/exchanges | grep -qw 'nailgun'" + retry_checker "curl -f -L -u \"$astute_user:$astute_password\" -s http://$ADMIN_IP:15672/api/exchanges | grep -qw 'naily_service'" + ;; + rsync) + retry_checker "netstat -ntl | grep -q 873" + ;; + rsyslog) + retry_checker "netstat -nl | grep -q 514" + ;; + mcollective) + retry_checker "ps waux | grep -q mcollectived" + ;; + nginx) + retry_checker "ps waux | grep -q nginx" + ;; + keystone) + retry_checker "keystone --os-auth-url \"http://$ADMIN_IP:35357/v2.0\" --os-username \"$keystone_nailgun_user\" --os-password \"$keystone_nailgun_password\" token-get &>/dev/null" + ;; + *) + echo "No defined test for determining if $1 is ready." + ;; + esac + + #Catch all to ensure puppet is not running + retry_checker "! pgrep puppet" + + if [ $failure -eq 1 ]; then + echo "ERROR: $1 failed to start." + return 1 + else + echo "$1 is ready." + return 0 + fi +} diff --git a/specs/fuel-library9.0.spec b/specs/fuel-library9.0.spec index 9aaf75df8a..0f50bc9407 100644 --- a/specs/fuel-library9.0.spec +++ b/specs/fuel-library9.0.spec @@ -24,6 +24,7 @@ Requires: fuel-misc python-fuelclient %define files_source %{_builddir}/%{name}-%{version}/files %define dockerctl_source %{files_source}/fuel-docker-utils +%define fuel_utils_source %{files_source}/fuel-utils %define openstack_version liberty-%{fuel_release} %define predefined_upstream_modules %{_sourcedir}/upstream_modules.tar.gz @@ -60,10 +61,12 @@ mkdir -p %{buildroot}/etc/monit.d/ mkdir -p %{buildroot}/etc/profile.d/ mkdir -p %{buildroot}/etc/init.d/ mkdir -p %{buildroot}/etc/dockerctl +mkdir -p %{buildroot}/etc/fuel-utils mkdir -p %{buildroot}/usr/bin/ mkdir -p %{buildroot}/usr/sbin/ mkdir -p %{buildroot}/usr/lib/ mkdir -p %{buildroot}/usr/share/dockerctl +mkdir -p %{buildroot}/usr/share/fuel-utils mkdir -p %{buildroot}/sbin/ mkdir -p %{buildroot}/sbin/ cp -fr %{_builddir}/%{name}-%{version}/deployment/puppet/* %{buildroot}/etc/puppet/%{openstack_version}/modules/ @@ -76,6 +79,11 @@ install -m 0755 %{dockerctl_source}/dockerctl %{buildroot}/usr/bin install -m 0755 %{dockerctl_source}/get_service_credentials.py %{buildroot}/usr/bin install -m 0644 %{dockerctl_source}/dockerctl_config %{buildroot}/etc/dockerctl/config install -m 0644 %{dockerctl_source}/functions.sh %{buildroot}/usr/share/dockerctl/functions +#fuel-utils +install -m 0755 %{fuel_utils_source}/fuel-utils %{buildroot}/usr/bin +install -m 0755 %{fuel_utils_source}/flat_yaml.py %{buildroot}/usr/bin +install -m 0644 %{fuel_utils_source}/config %{buildroot}/etc/fuel-utils/config +install -m 0644 %{fuel_utils_source}/functions.sh %{buildroot}/usr/share/fuel-utils/functions.sh #fuel-misc install -m 0755 %{files_source}/fuel-misc/centos_ifdown-local %{buildroot}/sbin/ifup-local install -m 0755 %{files_source}/fuel-misc/logrotate %{buildroot}/usr/bin/fuel-logrotate @@ -195,6 +203,27 @@ during Fuel All-in-One deployment toolkit installation %config(noreplace) /etc/dockerctl/config +%package -n fuel-utils +Summary: Fuel project utilities +Version: %{version} +Release: %{release} +Group: System Environment/Libraries +License: GPLv2 +Provides: fuel-utils +URL: http://github.com/openstack/fuel-library +BuildArch: noarch +BuildRoot: %{_tmppath}/fuel-library-%{version}-%{release} + +%description -n fuel-utils +This package contains a set of helpers to maintain Fuel services + +%files -n fuel-utils +/usr/bin/fuel-utils +/usr/bin/flat_yaml.py +/usr/share/fuel-utils/functions.sh + +%config(noreplace) /etc/fuel-utils/config + %package -n fuel-misc Summary: Fuel project misc utilities Version: %{version} @@ -306,7 +335,7 @@ BuildRoot: %{_tmppath}/fuel-library-%{version}-%{release} %description -n fuel-umm Packet provide posibility to put operation system in the state when it has only -critical set of working services which are needed for basic network and disk +critical set of working services which are needed for basic network and disk operations. Also node in MM state is reachable with ssh from network. For further information go to: