Here are some of my puppet manifests for Cloudstack and co. You can also find more information here:
https://github.com/oliverleach/cloudstack-puppet
I also recently did a presentation at the Cloudstack European meetup in London on the 11th April about deploying applications using puppet and Cloudstack. The talk was well received so I thought I would jot down the manifests that I wrote as part of the talk.
Here is the Cloudstack manifest:
# Class cloudstack
#
# This class installs cloudstack
#
# Author: Oliver Leach
# Date : 18th March 2013
#
# Actions:
# Installs the cloudstakc package
#
# This includes, the cloudstack-client, mysql-server and any install commands
#
# Currently the clodustack class is monlithic for demo purposes.
#
# Requires:
# Centos - other operating systems are not supported by this manifest
#
# Sample Usage:
# include cloudstack
#
class cloudstack ($mysql_password) {
case $::operatingsystem {
'centos': {
$supported = true
}
}
if ($supported == true) {
yumrepo { 'cloudstack':
baseurl => "http://cloudstack.apt-get.eu/rhel/4.0/",
descr => "Cloudstack 4.0.1 yum repo",
enabled => 1,
gpgcheck => 0,
}
package { "cloud-client":
ensure => "installed",
require => Yumrepo["cloudstack"],
}
exec { "cloud-setup" :
command => "/usr/bin/cloud-setup-databases cloud:cloud@localhost
--deploy-as=root:${mysql_password} && /bin/sleep 3 &&
/usr/bin/cloud-setup-management && /bin/sleep 3 &&
/usr/bin/cloud-setup-databases cloud:cloud@localhost
--deploy-as=root:${mysql_password} && /bin/sleep 3 &&
/usr/bin/cloud-setup-management",
creates => '/var/lib/mysql/cloud',
require => Package["cloud-client"],
}
service { "cloud-management":
ensure => "running",
enable => "true",
require => Exec["cloud-setup"],
}
}
}
MySQL server manifest
# Class myslqserver
#
# This class installs cloudstack
#
# Author: Oliver Leach
# Date : 20th March 2013
#
# Actions:
# Installs the mysql server package
#
# This includes, the mysql-server package
#
# Requires:
# Centos - other operating systems are not supported by this manifest
#
# Sample Usage:
# include mysql::server
#
class mysql::server ($mysql_password) {
case $::operatingsystem {
"centos": {
$supported = true
}
}
if ($supported == true) {
file { "flag-files" :
ensure => directory,
path => "/var/lib/puppet/flags/",
owner => root,
group => root,
mode => "0644",
}
package { "mysql-server":
ensure => installed,
require => File["flag-files"],
}
file { "/etc/my.cnf" :
owner => "root",
group => "root",
source => "puppet:///modules/mysql/my.cnf",
require => Package["mysql-server"],
}
service { "mysqld" :
enable => true,
ensure => running,
require => File["/etc/my.cnf"],
}
$mysql_server_exec_1 = "0000000000001"
$mysql_server_file_1 = "/var/lib/puppet/flags/mysql_server_exec_1"
exec { "restart-mysqld" :
command => "/sbin/service mysqld restart && echo
\"$mysql_server_exec_1\" > \"$mysql_server_file_1\"",
unless => "/usr/bin/test \"`/bin/cat $mysql_server_file_1
2>/dev/null`\" = \"$mysql_server_exec_1\"",
require => Service["mysqld"],
}
exec { "set-mysql-password" :
unless => "/usr/bin/mysqladmin -uroot -p${mysql_password} status",
command => "/usr/bin/mysqladmin -uroot password ${mysql_password}",
require => Exec["restart-mysqld"],
}
$mysql_server_exec_2 = "0000000000001"
$mysql_server_file_2 = "/var/lib/puppet/flags/mysql_server_exec_2"
exec { "remove-test-dbs" :
command => "/usr/bin/mysql -u root -p${mysql_password} -e
\"DELETE FROM mysql.db WHERE Db='test' OR Db='test
\\_%';\" && echo \"$mysql_server_exec_2\" >
\"$mysql_server_file_2\"",
unless => "/usr/bin/test \"`/bin/cat $mysql_server_file_2 2>
/dev/null`\" = \"$mysql_server_exec_2\"",
require => Exec["set-mysql-password"],
}
$mysql_server_exec_3 = "0000000000003"
$mysql_server_file_3 = "/var/lib/puppet/flags/mysql_server_exec_3"
exec { "remove-remote-root-access" :
command => "/usr/bin/mysql -u root -p${mysql_password} -e
\"DELETE FROM mysql.user WHERE User='root' AND
Host NOT IN ('localhost', '127.0.0.1', '::1');
\" && echo \"$mysql_server_exec_3\" > \
"$mysql_server_file_3\"",
unless => "/usr/bin/test \"`/bin/cat $mysql_server_file_3
2>/dev/null`\" = \"$mysql_server_exec_3\"",
require => Exec["set-mysql-password"],
}
}
}
Apache manifest
class apache {
$snat_ip = $snat_ipaddress
case $operatingsystem {
'CentOS', 'RedHat' : {
$supported = true
}
}
if ($supported == true) {
file { 'httpd_conf_d' :
ensure => directory,
path => '/etc/httpd/conf.d/',
recurse => true,
purge => true,
force => true,
owner => "root",
group => "root",
mode => 0644,
require => Package['httpd'],
}
file { 'cloudstack_conf' :
path => '/etc/httpd/conf.d/cloudstack.conf',
owner => root,
group => root,
mode => '0644',
content => template('apache/cloudstack.conf.erb'),
require => File['httpd_conf_d'],
}
package { 'httpd' :
ensure => present,
}
package { 'mod_ssl' :
ensure => present,
}
service { 'httpd' :
ensure => 'running',
enable => true,
require => File['cloudstack_conf'],
}
}
}
and the ERB template:
LoadModule ssl_module modules/mod_ssl.so
NameVirtualHost *:80
<VirtualHost *:80>
ServerName <%= snat_ip %>
DocumentRoot /var/www/html/
Redirect permanent / https://<%= snat_ip %>/client
</VirtualHost>
Listen 443
NameVirtualHost *:443
<VirtualHost *:443>
SSLEngine On
#SSLCertificateFile /var/lib/puppet/ssl/certs/ca.pem
#SSLCertificateKeyFile /var/lib/puppet/ssl/certs/cert001.pem
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
RewriteEngine On
ProxyRequests On
ProxyVia On
<Proxy *>
Order deny,allow
Deny from all
Allow from all
</Proxy>
Redirect permanent / /client
ProxyPass /client http://localhost:8080/client
ProxyPassReverse /client http://localhost:8080/client
</VirtualHost>
And the iptables manifest
class iptables {
$ipv4_file = $operatingsystem ? {
"debian" => '/etc/iptables/rules.v4',
/(RedHat|CentOS)/ => '/etc/sysconfig/iptables',
}
exec { "purge default firewall":
command => "/sbin/iptables -F && /sbin/iptables-save >
$ipv4_file && /sbin/service iptables restart",
onlyif => "/usr/bin/test `/bin/grep \"Firewall configuration
written by\" $ipv4_file | /usr/bin/wc -l` -gt 0",
user => 'root',
}
/* Make the firewall persistent */
exec { "persist-firewall":
command => "/bin/echo \"# This file is managed by puppet.
Do not modify manually.\" > $ipv4_file &&
/sbin/iptables-save >> $ipv4_file",
refreshonly => true,
user => 'root',
}
/* purge anything not managed by puppet */
resources { 'firewall':
purge => true,
}
firewall { '000 INPUT allow related and established':
state => ['RELATED', 'ESTABLISHED'],
action => 'accept',
proto => 'all',
}
firewall { "001 accept all icmp requests":
proto => 'icmp',
action => 'accept',
}
firewall { '002 INPUT allow loopback':
iniface => 'lo',
chain => 'INPUT',
action => 'accept',
}
firewall { '100 allow ssh':
state => ['NEW'],
dport => '22',
proto => 'tcp',
action => 'accept',
}
firewall { '100 allow port 80':
state => ['NEW'],
dport => '80',
proto => 'tcp',
action => 'accept',
}
firewall { '100 allow port 443':
state => ['NEW'],
dport => '443',
proto => 'tcp',
action => 'accept',
}
firewall { '100 allow 9090':
state => ['NEW'],
dport => '9090',
proto => 'tcp',
action => 'accept',
}
firewall { '100 allow 8250':
state => ['NEW'],
dport => '8250',
proto => 'tcp',
action => 'accept',
}
firewall { '100 allow 7080':
state => ['NEW'],
dport => '7080',
proto => 'tcp',
action => 'accept',
}
firewall { '100 allow 8080':
state => ['NEW'],
dport => '8080',
proto => 'tcp',
action => 'accept',
}
firewall { "998 deny all other requests":
action => 'reject',
proto => 'all',
reject => 'icmp-host-prohibited',
}
firewall { "999 deny all other requests":
chain => 'FORWARD',
action => 'reject',
proto => 'all',
reject => 'icmp-host-prohibited',
}
}