SlideShare a Scribd company logo
@oliverleach
Automating application deployments using Puppet and CloudStack
Cloudstack European User Group
11th April 2013 – London
Automating application deployments using Puppet and CloudStack
• Getting Cloudstack to deploy Cloudstack
Today’s gimmick
• Incomplete code examples coming up
Automating application deployments using puppet and CloudStack
• A script to create a deployment mechanism. I’m using Python for this
demo
• Using the Cloudstack API to provision compute resources
• Writing Puppet manifests to deploy and configure your applications
Involves:
• Preconfigured puppet master and a puppet agent template in Cloudstack
• Specifying userdata in deployVirtualMachine API to classify
puppet nodes
How:
Automating application deployments using puppet and CloudStack
High level process flow summary:
Acquire a public IP address and capture details
Deploy the puppet master and capture details
Deploy the puppet nodes and classify the node role
Configure a static NAT with firewall rules
Automating application deployments using puppet and CloudStack
How to query the Cloudstack async job for deployment details
Wait for job to
finish & review
job response
Automating application deployments using puppet and CloudStack
def associateip(self, zone_id):
associateip = cs_api.request(dict({'command':'associateIpAddress', 'zoneid': zone_id}))
....
for key, value in associateip.iteritems():
if key == 'jobid' : asyncjob = value
....
def asyncresults(self, *args)
....
status=0
while status==0:
qryasyncjob = cs_api.request(dict({'command':'queryAsyncJobResult', 'jobid':asyncjob}))
....
for key, value in qryasyncjob.iteritems():
if key == 'jobstatus' : status = value
time.sleep(5)
Deploy resource using the CS API then get and query the asnyc jobid
Automating application deployments using puppet and CloudStack
Wait for job to finish & review job response
associateip_qryjob = associateip_qryjob.queryasyncjobresultresponse.jobresult.ipaddress
for key, value in associateip_qryjob.items():
print key, ‘=‘, value
# returns the following values...
networkid = 8e67fa8a-aa68-4d8d-9de5-1979840bb53d
physicalnetworkid = b37ed19d-f997-421c-9da7-f90e985992e4
account = puppet
domainid = b351cbc3-6d41-4266-8715-96b4e55177f2
issourcenat = False
isstaticnat = False
tags = []
associatednetworkname = puppet network
domain = AA000001
zoneid = 6fdd9a36-2187-419d-99ad-8b3ecd47082f
state = Allocated
associatednetworkid = b598215e-ac3d-4fd6-8c83-b4191c6b2e5c
forvirtualnetwork = True
allocated = 2012-04-01T18:30:00+0100
issystem = False
ipaddress = 195.125.133.14
id = 76e15bad-cd08-4012-bcbd-4bffe08096ea
zonename = Cloud1-Zone1
Automating application deployments using puppet and CloudStack
associateip_qryjob = associateip_qryjob.queryasyncjobresultresponse.jobresult.ipaddress
for key, value in associateip_qryjob.items():
if key == 'id': Cloudstack_Cmds.snat_ipid = value
if key == 'ipaddress' : Cloudstack_Cmds.snat_ipaddress = value
Now what can I do?
Take job response values & store as variables e.g., (Cloudstack_Cmds.snat_ipid)
and use as part of the userdata in deployVirtualMachine
Automating application deployments using puppet and CloudStack
How to deploy the VMs with the userdata parameter
import base64
....
puppet_node = 'puppet-agent'
node_role = 'csm_server', 'nfs_server'
template_id = puppet_agent
for value in node_role:
if value == 'csm_server': getvmid = True
userdata = ('puppet_master_ip=%snrole=%snsnat_ipaddress=%sn' % 
(Cloudstack_Cmds.pm_ipaddress, value, Cloudstack_Cmds.snat_ipaddress))
api_cmd.deployvm(getvmid, command = 'deployVirtualMachine', serviceofferingid = so_id, 
templateid = template_id, zoneid = zone_id, networkids = network_id, 
puppet_node = puppet_node, userdata = base64.b64encode(userdata))
Automating application deployments using puppet and CloudStack
What does this translate to on the puppet node?
By querying the domain router for the userdata, I can turn
the values in to a puppet fact which can be used to classify
my puppet nodes
[root@2e57b8ae-a226-42e2-ac2b-72401ece4259 ~]# facter |grep 'role|snat|puppet'
role => csm_server
snat_ipaddress => 195.125.133.14
puppet_master_ip => 10.1.1.188
[root@7a9e0e74-7884-4999-8b24-f7168f76edbc facter]# curl
http://10.1.1.1/latest/user-data
puppet_master_ip=10.1.1.188
role=csm_server
snat_ipaddress = 195.125.133.14
....
lines.each do |line|
if line =~ /^(.+)=(.+)$/
var = $1; val = $2
Facter.add(var) do
setcode { val }
....
CSM server
Automating application deployments using puppet and CloudStack
How to apply puppet manifests to these nodes
class cs_vms {
$mysql_password = (‘<mysql_password_goes_here>')
....
case $role {
'csm_server': {
class { 'cloudstack' :
mysql_password => [ $mysql_password ],
require => Class[ 'mysql::server' ],
}
include 'apache'
class { 'selinux' : mode => 'permissive' }
class { 'mysql::server' :
mysql_password => [ $mysql_password ],
}
class { 'iptables' :
require => Class[ 'cloudstack' ],
}
....
Automating application deployments using puppet and CloudStack
A quick look at the Cloudstack puppet module
class cloudstack ($mysql_password) {
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",
creates => '/var/lib/mysql/cloud',
require => Package["cloud-client"],}
service { "cloud-management":
ensure => "running",
enable => "true",
require => Exec["cloud-setup"],}
}
Automating application deployments using puppet and CloudStack
What did I use the snat_ipaddress for?
....
NameVirtualHost *:80
<VirtualHost *:80>
ServerName < snat_ipaddress >
DocumentRoot /var/www/html/
Redirect permanent / https://<snat_ipaddress>/client
</VirtualHost>
Listen 443
NameVirtualHost *:443
<VirtualHost *:443>
SSLEngine On
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>
....
NameVirtualHost *:80
<VirtualHost *:80>
ServerName 195.125.133.14
DocumentRoot /var/www/html/
Redirect permanent / https://195.125.133.14/client
</VirtualHost>
Listen 443
NameVirtualHost *:443
<VirtualHost *:443>
SSLEngine On
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>
Automating application deployments using puppet and CloudStack
Automating application deployments using puppet and CloudStack
That’s a gimmick! How about some real use case examples?
Automating application deployments using puppet and CloudStack
Thank you

More Related Content

Oliver leech cloudstack

  • 1. @oliverleach Automating application deployments using Puppet and CloudStack Cloudstack European User Group 11th April 2013 – London
  • 2. Automating application deployments using Puppet and CloudStack • Getting Cloudstack to deploy Cloudstack Today’s gimmick • Incomplete code examples coming up
  • 3. Automating application deployments using puppet and CloudStack • A script to create a deployment mechanism. I’m using Python for this demo • Using the Cloudstack API to provision compute resources • Writing Puppet manifests to deploy and configure your applications Involves: • Preconfigured puppet master and a puppet agent template in Cloudstack • Specifying userdata in deployVirtualMachine API to classify puppet nodes How:
  • 4. Automating application deployments using puppet and CloudStack High level process flow summary: Acquire a public IP address and capture details Deploy the puppet master and capture details Deploy the puppet nodes and classify the node role Configure a static NAT with firewall rules
  • 5. Automating application deployments using puppet and CloudStack How to query the Cloudstack async job for deployment details Wait for job to finish & review job response
  • 6. Automating application deployments using puppet and CloudStack def associateip(self, zone_id): associateip = cs_api.request(dict({'command':'associateIpAddress', 'zoneid': zone_id})) .... for key, value in associateip.iteritems(): if key == 'jobid' : asyncjob = value .... def asyncresults(self, *args) .... status=0 while status==0: qryasyncjob = cs_api.request(dict({'command':'queryAsyncJobResult', 'jobid':asyncjob})) .... for key, value in qryasyncjob.iteritems(): if key == 'jobstatus' : status = value time.sleep(5) Deploy resource using the CS API then get and query the asnyc jobid
  • 7. Automating application deployments using puppet and CloudStack Wait for job to finish & review job response associateip_qryjob = associateip_qryjob.queryasyncjobresultresponse.jobresult.ipaddress for key, value in associateip_qryjob.items(): print key, ‘=‘, value # returns the following values... networkid = 8e67fa8a-aa68-4d8d-9de5-1979840bb53d physicalnetworkid = b37ed19d-f997-421c-9da7-f90e985992e4 account = puppet domainid = b351cbc3-6d41-4266-8715-96b4e55177f2 issourcenat = False isstaticnat = False tags = [] associatednetworkname = puppet network domain = AA000001 zoneid = 6fdd9a36-2187-419d-99ad-8b3ecd47082f state = Allocated associatednetworkid = b598215e-ac3d-4fd6-8c83-b4191c6b2e5c forvirtualnetwork = True allocated = 2012-04-01T18:30:00+0100 issystem = False ipaddress = 195.125.133.14 id = 76e15bad-cd08-4012-bcbd-4bffe08096ea zonename = Cloud1-Zone1
  • 8. Automating application deployments using puppet and CloudStack associateip_qryjob = associateip_qryjob.queryasyncjobresultresponse.jobresult.ipaddress for key, value in associateip_qryjob.items(): if key == 'id': Cloudstack_Cmds.snat_ipid = value if key == 'ipaddress' : Cloudstack_Cmds.snat_ipaddress = value Now what can I do? Take job response values & store as variables e.g., (Cloudstack_Cmds.snat_ipid) and use as part of the userdata in deployVirtualMachine
  • 9. Automating application deployments using puppet and CloudStack How to deploy the VMs with the userdata parameter import base64 .... puppet_node = 'puppet-agent' node_role = 'csm_server', 'nfs_server' template_id = puppet_agent for value in node_role: if value == 'csm_server': getvmid = True userdata = ('puppet_master_ip=%snrole=%snsnat_ipaddress=%sn' % (Cloudstack_Cmds.pm_ipaddress, value, Cloudstack_Cmds.snat_ipaddress)) api_cmd.deployvm(getvmid, command = 'deployVirtualMachine', serviceofferingid = so_id, templateid = template_id, zoneid = zone_id, networkids = network_id, puppet_node = puppet_node, userdata = base64.b64encode(userdata))
  • 10. Automating application deployments using puppet and CloudStack What does this translate to on the puppet node? By querying the domain router for the userdata, I can turn the values in to a puppet fact which can be used to classify my puppet nodes [root@2e57b8ae-a226-42e2-ac2b-72401ece4259 ~]# facter |grep 'role|snat|puppet' role => csm_server snat_ipaddress => 195.125.133.14 puppet_master_ip => 10.1.1.188 [root@7a9e0e74-7884-4999-8b24-f7168f76edbc facter]# curl http://10.1.1.1/latest/user-data puppet_master_ip=10.1.1.188 role=csm_server snat_ipaddress = 195.125.133.14 .... lines.each do |line| if line =~ /^(.+)=(.+)$/ var = $1; val = $2 Facter.add(var) do setcode { val } .... CSM server
  • 11. Automating application deployments using puppet and CloudStack How to apply puppet manifests to these nodes class cs_vms { $mysql_password = (‘<mysql_password_goes_here>') .... case $role { 'csm_server': { class { 'cloudstack' : mysql_password => [ $mysql_password ], require => Class[ 'mysql::server' ], } include 'apache' class { 'selinux' : mode => 'permissive' } class { 'mysql::server' : mysql_password => [ $mysql_password ], } class { 'iptables' : require => Class[ 'cloudstack' ], } ....
  • 12. Automating application deployments using puppet and CloudStack A quick look at the Cloudstack puppet module class cloudstack ($mysql_password) { 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", creates => '/var/lib/mysql/cloud', require => Package["cloud-client"],} service { "cloud-management": ensure => "running", enable => "true", require => Exec["cloud-setup"],} }
  • 13. Automating application deployments using puppet and CloudStack What did I use the snat_ipaddress for? .... NameVirtualHost *:80 <VirtualHost *:80> ServerName < snat_ipaddress > DocumentRoot /var/www/html/ Redirect permanent / https://<snat_ipaddress>/client </VirtualHost> Listen 443 NameVirtualHost *:443 <VirtualHost *:443> SSLEngine On 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> .... NameVirtualHost *:80 <VirtualHost *:80> ServerName 195.125.133.14 DocumentRoot /var/www/html/ Redirect permanent / https://195.125.133.14/client </VirtualHost> Listen 443 NameVirtualHost *:443 <VirtualHost *:443> SSLEngine On 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>
  • 14. Automating application deployments using puppet and CloudStack
  • 15. Automating application deployments using puppet and CloudStack That’s a gimmick! How about some real use case examples?
  • 16. Automating application deployments using puppet and CloudStack Thank you