Oliver leech cloudstack
- 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>