<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Adrián Deccico</title>
	<atom:link href="http://adrian.org.ar/feed" rel="self" type="application/rss+xml" />
	<link>http://adrian.org.ar</link>
	<description>just some random thoughts about coding</description>
	<lastBuildDate>Wed, 18 Apr 2012 13:15:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A couple of new Bellatrix posts</title>
		<link>http://adrian.org.ar/bellatrix/a-couple-of-new-bellatrix-posts</link>
		<comments>http://adrian.org.ar/bellatrix/a-couple-of-new-bellatrix-posts#comments</comments>
		<pubDate>Wed, 18 Apr 2012 13:08:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[bellatrix]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[provision]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=434</guid>
		<description><![CDATA[I just found here: http://mainlydata.kubadev.com two new Bellatrix posts: Bellatrix in Windows: http://mainlydata.kubadev.com/ec2/bellatrix-windows-users-two-things-to-remember/ Bellatrix provisioning commands: http://mainlydata.kubadev.com/ec2/bellatrix-provisioning-commands/ thanks Richard Shea! &#160;<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p>I just found here: <a href="http://mainlydata.kubadev.com" target="_blank">http://mainlydata.kubadev.com</a> two new Bellatrix posts:</p>
<ul>
<li>Bellatrix in Windows: <a href="http://mainlydata.kubadev.com/ec2/bellatrix-windows-users-two-things-to-remember/" target="_blank">http://mainlydata.kubadev.com/ec2/bellatrix-windows-users-two-things-to-remember/</a></li>
</ul>
<ul>
<li>Bellatrix provisioning commands: <a href="http://mainlydata.kubadev.com/ec2/bellatrix-provisioning-commands/" target="_blank">http://mainlydata.kubadev.com/ec2/bellatrix-provisioning-commands/</a></li>
</ul>
<p>thanks Richard Shea!</p>
<p>&nbsp;</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/bellatrix/a-couple-of-new-bellatrix-posts/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic setup of Django 1.4, NGinx and GUnicorn on EC2 using Bellatrix</title>
		<link>http://adrian.org.ar/python/automatic-setup-of-django-nginx-and-gunicorn-on-ec2</link>
		<comments>http://adrian.org.ar/python/automatic-setup-of-django-nginx-and-gunicorn-on-ec2#comments</comments>
		<pubDate>Mon, 02 Apr 2012 15:49:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[bellatrix]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[gunicorn]]></category>
		<category><![CDATA[jenkins]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=325</guid>
		<description><![CDATA[Some time ago I wrote some lengthy instructions on how to configure Django, NGinx and Green Unicorn on an brand new Ubuntu EC2 instance. Now, I want to show how to automate the same tasks using a command line tool called Bellatrix. We will also provide a Jenkins (formerly Hudson) pipeline so we have, if [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><a href="http://adrian.org.ar/wp-content/uploads/2012/04/jenkins_pipeline.png" target="_blank"><img src="http://adrian.org.ar/wp-content/uploads/2012/04/jenkins_pipeline-150x150.png" target="_blank" alt="" title="Jenkins pipeline" width="350" height="150" /></a></p>
<p><br class="blank" /></p>
<p>Some time ago I wrote some <a title="Setting up Django 1.3 + NGinx 1.0.5 + Green Unicorn 0.13 in an Ubuntu 11.10 EC2 instance" href="http://adrian.org.ar/python/django-nginx-green-unicorn-in-an-ubuntu-11-10-ec2-instance" target="_blank">lengthy instructions</a> on how to configure Django, NGinx and Green Unicorn on an brand new Ubuntu EC2 instance. Now, I want to show how to automate the same tasks using a command line tool called Bellatrix. We will also provide a Jenkins (formerly Hudson) pipeline so we have, if we want, a nice display for the UI.<br />
</br></br><br />
<span id="more-325"></span></p>
<h1>What is Bellatrix?</h1>
<p></br><br />
<a href="http://adrian.org.ar/wp-content/uploads/2012/04/250px-Bellatrix.jpg" target="_blank"><img src="http://adrian.org.ar/wp-content/uploads/2012/04/250px-Bellatrix-150x150.jpg" alt="" title="Bellatrix" width="150" height="150" /></a><br />
Bellatrix is a set of (magic) command line utilities for EC2. It wraps the boto library in order to provide a set of easy to use commands that will help you with the common EC2 operations (start, stop, list, provision, burn, etc.) You can find more information about Bellatrix on this <a href="http://bellatrix.readthedocs.org" target="_blank">link</a>.</p>
<p>We will use Bellatrix to help us provisioning a blank Ubuntu EC2 image (AMI) by using these commands:</p>
<ol>
<li>pip install bellatrix</li>
<li>bellatrix start ami</li>
<li>bellatrix provision ubuntu_django_nginx_gunicorn.py</li>
<li>bellatrix burn instance_id</li>
<li>bellatrix terminate instance_id</li>
</ol>
<p>&nbsp;<br />
</br></p>
<h1>1. Installing Bellatrix</h1>
<p></br><br />
First, install Bellatrix by typing:</p>
<pre>
pip install bellatrix
</pre>
<p>You can also install Bellatrix inside a <strong>virtualenv </strong> environment without modifying any of the following steps. Our Jenkins example (published at the end) uses virtualenv on every step.</p>
<p>Now that you have Bellatrix installed, you will need to provide the AWS EC2 credentials in the configuration directory. Please follow these instructions: <a href="http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#setting-your-aws-credentials" target="_blank">http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#setting-your-aws-credentials</a> in order to set your environment.</p>
<p>&nbsp;<br />
</br></p>
<h1>2. Starting an EC2 instance</h1>
<p></br><br />
We are ready to start an EC2 instance:</p>
<pre>

bellatrix start ami-baba68d3 ec2-keypair
</pre>
<p></br></p>
<h2>Parameters explanation</h2>
<p></br></p>
<ul>
<li><strong>ami-baba68d3</strong> is the last Ubuntu Oneiric AMI published in <http://cloud.ubuntu.com/ami">http://cloud.ubuntu.com/ami</a> Just in case you don&#8217;t know, an AMI (Amazon Machine Image) is just a snapshot of a pre-configured machine.</li>
<li><strong>ec2-keypair</strong> is the name of the key pair that Bellatrix (and you) will use to connect to your EC2 instance.</li>
</ul>
<p>&nbsp;<br />
<a href="http://adrian.org.ar/wp-content/uploads/2012/04/ubuntu_ami.png" target="_blank"><img src="http://adrian.org.ar/wp-content/uploads/2012/04/ubuntu_ami-150x150.png" alt="" title="Ubuntu Oneiric Ocelot AMI" width="150" height="150" /></a><br />
</br><br />
More information on the <strong>bellatrix start</strong> command can be found here: <a href="http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#starting-an-ec2-instance">http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#starting-an-ec2-instance</a></p>
<p>The above command will provide an output like this one:</p>
<pre>
bellatrix start ami-baba68d3 ec2-keypair
+ bellatrix start ami-baba68d3 key
2012-04-01 15:06:15,848 INFO starting EC2 instance...
2012-04-01 15:06:15,848 INFO ami:ami-baba68d3 type:t1.micro key_name:key security_groups:default new size:None
2012-04-01 15:06:17,017 INFO starting image: ami-baba68d3 key key type t1.micro shutdown_behavior terminate new size None
2012-04-01 15:06:17,709 INFO we got 1 instance (should be only one).
2012-04-01 15:06:17,709 INFO tagging instance:i-864c56e2 key:Name value:Bellatrix started me
2012-04-01 15:06:21,252 INFO instance:i-864c56e2 was successfully tagged with: key:Name value:Bellatrix started me
2012-04-01 15:06:21,252 INFO getting the dns name for instance: i-864c56e2 time out is: 300 seconds...
2012-04-01 15:06:41,216 INFO DNS name for i-864c56e2 is ec2-23-20-206-220.compute-1.amazonaws.com
2012-04-01 15:06:41,217 INFO waiting until instance: i-864c56e2 is ready. Time out is: 300 seconds...
2012-04-01 15:06:41,217 INFO Instance i-864c56e2 is running
</pre>
<p>Please note the DNS name: <strong>ec2-23-20-206-220.compute-1.amazonaws.com</strong> and the instance id: <strong>i-864c56e2</strong> from the output above. We will use both in the commands below. By the way, given the DNS name we can infer the (less verbose) public IP. In this case is <strong>23.20.206.220</strong>. I am sure you already got the rule.</p>
<p>&nbsp;<br />
</br></p>
<h1>3. bellatrix provision</h1>
<p></br></p>
<div style="clear:both;">
<a href="http://adrian.org.ar/wp-content/uploads/2012/04/provision.png" target="_blank"><img src="http://adrian.org.ar/wp-content/uploads/2012/04/provision-150x150.png" target="_blank" alt="" title="Provisioning commands" width="150" height="150" /></a>
</div>
<p>Once you have your instance up and running, it&#8217;s time to configure it! Automation here is the key to a reliable output. Our <strong>bellatrix provision</strong> command will set-up Django, Nginx, Green Unicorn and Upstart in your formerly blank Ubuntu.</p>
<p>First of all you need to get the provisioning configuration file:</p>
<pre>
wget https://bitbucket.org/deccico/bellatrix_configs/raw/tip/bellatrix_configs/ubuntu_django_nginx_gunicorn.py
</pre>
<p>If you are interested in getting also the Jenkins jobs for this article or looking at other provisioning examples you can instead clone the whole project:</p>
<pre>
hg clone ssh://hg@bitbucket.org/deccico/bellatrix_configs
</pre>
<p></br><br />
<strong>bellatrix provision</strong> executes a list of commands. Since every command is just a simple list of Python strings it&#8217;s very easy to add your own just by looking at the available ones. Bellatrix already provides an interesting set of generic, ready to use commands that cover the most common operations.</p>
<ul>
<li>Bellatrix commands: &#8211; <a href="https://bitbucket.org/adeccico/bellatrix/src/tip/bellatrix/lib/cmds.py">https://bitbucket.org/adeccico/bellatrix/src/tip/bellatrix/lib/cmds.py</a></li>
<li>bellatrix provision documentation: &#8211; <a href="http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#provisioning-an-ec2-instance-or-any-host">http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#provisioning-an-ec2-instance-or-any-host</a></li>
</ul>
<p></br></p>
<h2>Command Execution</h2>
<p>Now that you know more about the <strong>provision</strong> command, is time to execute it:</p>
<pre>
bellatrix provision ubuntu_django_nginx_gunicorn.py ubuntu 23.20.206.220 --private_key=~/.bellatrix/ec2.pk
</pre>
<p></br></p>
<h2>Parameters explanation</h2>
<ul>
<li><strong>ubuntu_django_nginx_gunicorn.py</strong> &#8211; Provisioning script. It is possible to execute a configuration inside a directory, so in case you cloned the whole project you can use  &#8220;bellatrix_configs/ubuntu_django_nginx_gunicorn.py&#8221; as this parameter.</li>
<li><strong>ubuntu</strong> &#8211; This is just the user name of the remote host.</li>
<li><strong>23.20.206.220</strong> &#8211; The host where we will execute the provisioning command. We can use the DNS name or the IP that we got in the second step.</li>
<li><strong>&#8211;private_key=~/.bellatrix/ec2.pk </strong>- The private key that correspond to the ec2-keypair specified in the <strong>start</strong> command.</li>
</ul>
<p>&nbsp;<br />
</br></p>
<h1>4. Saving your work into a new AMI</h1>
<p><a href="http://adrian.org.ar/wp-content/uploads/2012/04/burning.png" target="_blank"><img src="http://adrian.org.ar/wp-content/uploads/2012/04/burning-150x150.png" alt="" title="burning instance..." width="150" height="150"/></a><br />
</br><br />
Once the <strong>provision </strong>command performed its magic, we only need to save the current state into a new AMI, so every time we get a new instance from this new AMI the configuration will be ready to use. The command in this case will be:</p>
<pre>

bellatrix burn i-864c56e2  ubuntu_django_nginx_gunicorn_x64 --wait=true
</pre>
<p></br></p>
<h2>Parameters</h2>
<ul>
<li><strong>i-864c56e2</strong>  -  Instance id captured in the <strong>start</strong> command.</li>
<li><strong>ubuntu_django_nginx_gunicorn_x64</strong> &#8211; Name of the new AMI. Bellatrix will add a timestamp to it.</li>
<li><strong>&#8211;wait=true</strong> &#8211; Burning a instance takes some time. By default the <strong>burn</strong> command will finish in some seconds after it gets the new AMI code. Nevertheless the AMI won&#8217;t be ready until the burning process finishes so if we specify this option, this command will return only when we get the AMI code and the burning process is done .</li>
</ul>
<p>Documentation about the <strong>burn</strong> command: <a href="http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#saving-the-state-of-an-instance-into-a-new-amazon-ami">http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#saving-the-state-of-an-instance-into-a-new-amazon-ami</a></p>
<p></br><br />
</br></p>
<h1>5. Shutting the instance down</h1>
<p></br><br />
After we get the new AMI we can safely terminate the EC2 instance with this command:</p>
<pre>

bellatrix terminate i-864c56e2
</pre>
<p></br></p>
<p>As noticed <a href="http://bellatrix.readthedocs.org/en/latest/commands_use_tut.html#terminating-an-ec2-instance">here</a>, a terminated instance won&#8217;t generate any cost.</p>
<p>&nbsp;<br />
</br></p>
<h1>Bonus: Adding some Jenkins magic</h1>
<p></br><br />
<a href="http://adrian.org.ar/wp-content/uploads/2012/04/pipeline.png" target="_blank"><img src="http://adrian.org.ar/wp-content/uploads/2012/04/pipeline-150x150.png" alt="" title="Jenkins Pipeline" width="150" height="150"  /></a><br />
In case you plan to execute these commands more than once (like for any new Ubuntu release) you can find the Jenkins pipeline ready to be used <a href="https://bitbucket.org/deccico/bellatrix_configs/src/d74adf3aa956/jenkins_jobs" target="_blank">here</a>. Remember to copy the jobs to your Jenkins &#8220;jobs&#8221; directory and to restart Jenkins afterwards.</p>
<p>&nbsp;</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/python/automatic-setup-of-django-nginx-and-gunicorn-on-ec2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up Django 1.3 + NGinx 1.0.5 + Green Unicorn 0.13 in an Ubuntu 11.10 EC2 instance</title>
		<link>http://adrian.org.ar/python/django-nginx-green-unicorn-in-an-ubuntu-11-10-ec2-instance</link>
		<comments>http://adrian.org.ar/python/django-nginx-green-unicorn-in-an-ubuntu-11-10-ec2-instance#comments</comments>
		<pubDate>Tue, 27 Dec 2011 12:08:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[gunicorn]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=212</guid>
		<description><![CDATA[Django has become the de-facto web framework for Python. Although, since Django just specializes in dynamic content, you have to combine it (at least in production) with an HTTP server to serve static content such as css, javascript files and images files. In the past, the communication protocol between Python web applications was CGI, FastCGI [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p>Django has become the de-facto web framework for Python. Although, since Django just specializes in dynamic content, you have to combine it (at least in production) with an HTTP server to serve static content such as css, javascript files and images files. In the past, the communication protocol between Python web applications was CGI, FastCGI or mod_python. But after <a title="PEP-333" href="http://www.python.org/dev/peps/pep-0333/" target="_blank">PEP-333</a> was accepted the faster and more efficient WSGI became the <a href="http://stackoverflow.com/questions/3319545/mod-wsgi-mod-python-or-just-cgi" target="_blank">standard</a>.</p>
<p><a href="http://gunicorn.org/" target="_blank">Green Unicorn</a> is a Python WSGI HTTP Server for UNIX. Its combination with the high performance HTTP server NGinx is gaining lot of momentum in the Python community.</p>
<p>From &#8220;man gunicorn&#8221;&#8230;</p>
<blockquote><p>Green Unicorn (gunicorn) is an HTTP/WSGI server designed to serve<br />
fast clients or sleepy applications. That is to say; behind a<br />
buffering front-end server such as nginx or lighttpd.</p></blockquote>
<p>&nbsp;</p>
<p>We are describing here how to combine a Django application with Green Unicorn and Nginx within a pristine EC2 Ubuntu 11.10 image.<br />
<span id="more-212"></span></p>
<p><br/><br />
<br/></p>
<h1>Getting an Ubuntu instance</h1>
<div style="clear:both;">
<a href="http://adrian.org.ar/wp-content/uploads/2011/12/ami_locator1.png" target="_blank"><img class="alignleft size-medium wp-image-230" style="border: 10px solid white; margin-left: 10px; margin-right: 10px;" title="AMI locator" src="http://adrian.org.ar/wp-content/uploads/2011/12/ami_locator1-300x168.png" alt="" width="300" height="168" /></a>
</div>
<p style="clear:left;">
<p>
First of all we are going to <a href="http://cloud.ubuntu.com/ami/" target="_blank">http://cloud.ubuntu.com/ami/</a> to check the last released ami. As described in the image, we are looking for the last 64 bits, Ubuntu 11.10 EB2 image in the US-East region, which so far is <strong>ami-bf62a9d6</strong>.</p>
<ul>
<li>Why Ubuntu 11.10 ? Because is the last stable release.</li>
<li>Why EBS? Because is faster and with more options like on the fly snapshots or easy image resizing than instance-store.</li>
<li>Why US-EAST? Because is cheaper and usually with more features than the other regions.</li>
<li>We also choose 64 bits so we can eventually expand to a bigger instance.</li>
</ul>
<p>&nbsp;<br />
<br/><br />
<br/></p>
<h1>Starting your free EC2 instance</h1>
<p><br/><br />
So far there is a nice offer for new customers where you can get a <a href="http://aws.amazon.com/free/" target="_blank">free</a> EC2 Linux Micro Instance usage (613 MB of memory and 32-bit and 64-bit platform support) for one year.  Please open your account and then launch your instance as described in the following screen-shots:</p>
<div style="clear:both;">
<a href="http://adrian.org.ar/wp-content/uploads/2011/12/00-launching-instance.png"><img class="alignleft size-thumbnail wp-image-251" title="00 launching instance" src="http://adrian.org.ar/wp-content/uploads/2011/12/00-launching-instance-150x150.png" alt="" width="150" height="150" /></a>    <a href="http://adrian.org.ar/wp-content/uploads/2011/12/01-introducing-Ubuntu-ami.png"><img class="alignleft size-thumbnail wp-image-252" title="01 introducing Ubuntu ami" src="http://adrian.org.ar/wp-content/uploads/2011/12/01-introducing-Ubuntu-ami-150x150.png" alt="" width="150" height="150" /></a><a href="http://adrian.org.ar/wp-content/uploads/2011/12/02-availability-zone.png"><img class="alignleft size-thumbnail wp-image-253" title="02 availability zone" src="http://adrian.org.ar/wp-content/uploads/2011/12/02-availability-zone-150x150.png" alt="" width="150" height="150" /></a><a href="http://adrian.org.ar/wp-content/uploads/2011/12/03-name-tag.png"><img class="alignleft size-thumbnail wp-image-254" title="03 name tag" src="http://adrian.org.ar/wp-content/uploads/2011/12/03-name-tag-150x150.png" alt="" width="150" height="150" /></a><a href="http://adrian.org.ar/wp-content/uploads/2011/12/04-creating-a-new-key-pair.png"><img class="alignleft size-thumbnail wp-image-255" title="04 creating a new key-pair" src="http://adrian.org.ar/wp-content/uploads/2011/12/04-creating-a-new-key-pair-150x150.png" alt="" width="150" height="150" /></a><a href="http://adrian.org.ar/wp-content/uploads/2011/12/05-enabling-incoming-SSH-and-HTTP.png"><img class="alignleft size-thumbnail wp-image-256" title="05 enabling incoming SSH and HTTP" src="http://adrian.org.ar/wp-content/uploads/2011/12/05-enabling-incoming-SSH-and-HTTP-150x150.png" alt="" width="150" height="150" /></a><a href="http://adrian.org.ar/wp-content/uploads/2011/12/06-review.png"><img class="alignleft size-thumbnail wp-image-257" title="06 review" src="http://adrian.org.ar/wp-content/uploads/2011/12/06-review-150x150.png" alt="" width="150" height="150" /></a><a href="http://adrian.org.ar/wp-content/uploads/2011/12/07-instance-started.png"><img class="alignleft size-thumbnail wp-image-258" title="07 instance started" src="http://adrian.org.ar/wp-content/uploads/2011/12/07-instance-started-150x150.png" alt="" width="150" height="150" /></a>
</div>
<p style="clear:left;">
<p>&nbsp;<br />
<br/><br/><br/></p>
<h1>Launching and configuring your Ubuntu box</h1>
<p><br/><br />
At this point you should have your EC2 or your own Ubuntu box up and running. If you are using EC2 you should ssh into it with this command:</p>
<pre>
ssh -i you_private_key.pem ubuntu@DNS_NAME
</pre>
<p>Then, please follow this steps to start setting your environment:</p>
<pre>
#install Python Package Installer
sudo apt-get install python-pip
#upgrade PIP itself
sudo pip install pip --upgrade
#install Green Unicorn
#install Virtualenv to generate our own isolated environment
sudo pip install virtualenv
#Installing NGINX
sudo apt-get install nginx
#Creating our Virtualenv environment
virtualenv --no-site-packages django_app
cd django_app
#activating the environment
source bin/activate
#installing Green Unicorn and Django
pip install django gunicorn
#Creating a Django project
django-admin.py startproject app
cd app
#start Django application with Green Unicorn
gunicorn_django -b 0.0.0.0:8000
</pre>
<p>Now go to your browser and check if your application is working as expected:<br />
<br class="blank" /><br />
<a href="http://adrian.org.ar/wp-content/uploads/2011/12/testing-django-application.png" target="_blank"><img title="testing django application" src="http://adrian.org.ar/wp-content/uploads/2011/12/testing-django-application-150x150.png" alt="" width="150" height="150" /></a><br />
Finally, just Ctrl+C  and &#8220;deactivate&#8221; so you can continue with Nginx&#8230;<br class="blank" /><br class="blank" /><br class="blank" /></p>
<h1>Setting up Nginx</h1>
<p><br class="blank" /><br />
Now we will set up Nginx in order to have it listening in the port 80, serving static files and working with Gunicorn and Django in order to serve dynamic content.</p>
<pre>
#prepare directories
sudo mkdir -p /opt/django/logs/nginx/
#Create directories and softlinks for static content and templates
mkdir $HOME/django_app/static
mkdir $HOME/django_app/templates
sudo ln -s $HOME/django_app/static /opt/django
#download and set up Nginx configuration. Basically it will listen in port 80 and forward to port 8000 dynamic content
sudo mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.backup
wget https://bitbucket.org/deccico/django_gunicorn/raw/tip/server/etc/nginx/sites-available/default
sudo cp default /etc/nginx/sites-available/default
</pre>
<p>&nbsp;<br/></p>
<h1>Testing Static resources</h1>
<p><br/></p>
<h2>Configuring settings.py</h2>
<p><br/><br />
You need to tell Django where your templates are, for that reason, add your absolute &#8220;templates&#8221; directory to your /home/ubuntu/django_app/app/settings.py file</p>
<p>Now look for the TEMPLATE_DIRS section and add your template directory</p>
<pre>
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
'/home/ubuntu/django_app/templates',
)
</pre>
<p><br/><br/></p>
<h2>Configuring urls.py</h2>
<p><br/><br />
/home/ubuntu/django_app/app/urls.py will help us telling Django to return our template page when we introduce the /test_static request.</p>
<p>To make things easier we are using a dynamic view:</p>
<pre>
from django.conf.urls.defaults import patterns
from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
(r'^test_static/$',             direct_to_template, {'template': 'test_static.html'}),
)
</pre>
<p><br/><br/></p>
<h2>Preparing test template</h2>
<p><br/><br />
We need to prepare our template. Please create this file /home/ubuntu/django_app/templates/test_static.html with the following content:</p>
<pre>

&lt;!--Load static will recover the static prefix variable and saving it in STATIC_PREFIX. We do this only once.--&gt;

{% load static %}

{% get_static_prefix as STATIC_PREFIX %}

&lt;!--Here we are just showing how easy is to recover static resources . --&gt;
Test image
&lt;img src="{{ STATIC_PREFIX }}django.png" /&gt;
</pre>
<p>After creating the template file you will need an actual image <img src='http://adrian.org.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  You can download one from the same repo.</p>
<pre>

cd /home/ubuntu/django_app/static

wget https://bitbucket.org/deccico/django_gunicorn/raw/tip/static/django.png
</pre>
<p><br/><br/></p>
<h2>Restarting Nginx and voilà</h2>
<p><br/><br />
Finally, we just need to restart Nginx and test everything is working.</p>
<pre>

#First we restart Nginx

sudo service nginx restart
</pre>
<p>Now we will start our Django application again:</p>
<pre>
cd /home/ubuntu/django_app/app
#activating the environment
source ../bin/activate
#start Django application with Green Unicorn
gunicorn_django -b 0.0.0.0:8000
</pre>
<p>Then we just go to our browser and request test_static in port 80. In my case the full address is: http://ec2-107-20-88-133.compute-1.amazonaws.com/test_static</p>
<p><a href="http://adrian.org.ar/wp-content/uploads/2011/12/test_static.png"><img class="alignleft size-thumbnail wp-image-280" title="static test with Nginx" src="http://adrian.org.ar/wp-content/uploads/2011/12/test_static-150x150.png" alt="" width="150" height="150" /></a></p>
<p style="clear:left;">
<p>As you can see above, we got Nginx serving the image while Django give us the content. </p>
<p>Type &#8220;Ctrl + C&#8221; and then &#8220;deactivate&#8221; again so we can be ready for the next step&#8230; </p>
<p>&nbsp;<br/><br/></p>
<h1>Setting Green Unicorn automatic start</h1>
<p><br class="blank" /><br />
We will use <strong>Upstart</strong> so we don&#8217;t have to worry about starting our application whenever we need to restart the server. One more configuration file and a bootstrap script will do the job here:</p>
<p>In /home/ubuntu/django_app/run.sh we create:</p>
<pre>
#!/bin/bash
set -e
LOGFILE=/var/log/gunicorn/django_app.log
LOGDIR=$(dirname $LOGFILE)
NUM_WORKERS=3  #recommended formula here is 1 + 2 * NUM_CORES

#we don't want to run this as root..
USER=www-data
GROUP=www-data

cd /home/ubuntu/django_app
source bin/activate
cd app
test -d $LOGDIR || mkdir -p $LOGDIR
exec gunicorn_django -w $NUM_WORKERS \
  --log-level=debug \
  --log-file=$LOGFILE 2>>$LOGFILE \
  --user=$USER --group=$GROUP
</pre>
<p>After creating the file, please remember to execute chmod a+x /home/ubuntu/django_app/run.sh </p>
<p>On the other hand, Upstart configuration file have to be located in: <em>/etc/init/django_app.conf</em> with the following content:</p>
<pre>

description "Django Application"

start on runlevel [2345]

stop on runlevel [06]

respawn

respawn limit 10 5

exec /home/ubuntu/django_app/run.sh
</pre>
<p>Now we can control our application with</p>
<pre>
sudo start django_app

sudo stop django_app
</pre>
<h1></h1>
<p><br class="blank" /><br class="blank" /><br/></p>
<h1>To sum up</h1>
<p><br class="blank" /><br />
The puropose of this post is to provide a path to make the installation and configuration of this stack easier. While some things could be changed or improved the focus was to stress how easily we can configure everything from scratch rather than exploring or discussing different options. </p>
<p>The code and configuration files of this post can be found here: <a href="https://bitbucket.org/deccico/django_gunicorn">https://bitbucket.org/deccico/django_gunicorn</a> Have fun!</p>
<p>&nbsp;</p>
<h1>References</h1>
<p><br class="blank" /></p>
<ul>
<li><a href="https://docs.djangoproject.com/en/1.3/ref/generic-views/">https://docs.djangoproject.com/en/1.3/ref/generic-views/</a></li>
<li><a href="http://upstart.ubuntu.com/getting-started.html">http://upstart.ubuntu.com/getting-started.html</a></li>
<li><a href="http://senko.net/en/django-nginx-gunicorn/">http://senko.net/en/django-nginx-gunicorn/</a></li>
<li><a href="https://help.ubuntu.com/community/EC2StartersGuide">https://help.ubuntu.com/community/EC2StartersGuide</a></li>
<li><a href="https://help.ubuntu.com/community/UEC/Image">https://help.ubuntu.com/community/UEC/Image</a>s</li>
<li><a href="https://help.ubuntu.com/community/UbuntuCloudInfrastructure">https://help.ubuntu.com/community/UbuntuCloudInfrastructure</a></li>
<li><a href="http://cloud.ubuntu.com/ami/">http://cloud.ubuntu.com/ami/</a></li>
</ul>
<p></br> </br></p>
<p><strong>Update: these instructions are now automated in this new <a href="http://adrian.org.ar/python/automatic-setup-of-django-nginx-and-gunicorn-on-ec2" title="Automatic setup of Django, NGinx and GUnicorn on EC2 using Bellatrix">post</a></strong></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/python/django-nginx-green-unicorn-in-an-ubuntu-11-10-ec2-instance/feed</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Getting reTweets from Python</title>
		<link>http://adrian.org.ar/python/getting-retweets-from-python</link>
		<comments>http://adrian.org.ar/python/getting-retweets-from-python#comments</comments>
		<pubDate>Tue, 21 Sep 2010 23:06:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=197</guid>
		<description><![CDATA[In this snippet I will show how to use the Tweepy library to get statistics from Tweeter. The script will read a sample feed from the Twitter Streaming API (http://dev.twitter.com/pages/streaming_api) and perform the following actions: * Reads the sample feed * Notes the number of retweets seen * Tracks the number of times posts have [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://adrian.org.ar/wp-content/uploads/2010/09/retweet.jpg" alt="" title="retweet" width="275" height="183" class="alignleft size-full wp-image-199" /></p>
<p>In this snippet I will show how to use the Tweepy library to get statistics from Tweeter.</p>
<p>The script will read a  sample feed from the Twitter Streaming API (http://dev.twitter.com/pages/streaming_api) and perform the following actions:</p>
<p>* Reads the sample feed<br />
* Notes the number of retweets seen<br />
* Tracks the number of times posts have been retweeted, and<br />
* Produces an hourly report of the 20 most frequently retweeted posts</p>
<p><span id="more-197"></span></p>
<pre>
#!/usr/bin/env python

"""
Tweepy library proof of concept

@author: Adrian Deccico
"""

from getpass import getpass
import hashlib
import time
import re
import operator
import logging
import codecs
import tweepy

logging.basicConfig(level = logging.INFO)

class TweetListener(tweepy.StreamListener):

    #we use this pattern to decide if a post is a retweet or not, given that retweet fields of the feed don't work
    __retweet_pattern = "^(rt|retweet).*$"

    #statistics
    count = 0
    found = 0
    hour_ranking = {}
    retweets = {}

    #constants
    TOP_TWEETS = 20 #number of tweets to display in each hour

    def on_status(self, status):
        """callback that will process new tweets"""
        try:
            self.count += 1
            text = status.text
            #check wether we got a retweet or not
            logging.debug('count %s found %s - %s' % (self.count, self.found, text))
            if re.match(self.__retweet_pattern, text, re.IGNORECASE) == None:
                return

            self.found += 1

            if text not in self.retweets.keys():
                twitt_times = 1
            else:
                twitt_times = self.retweets[text] + 1

            self.retweets[text] = twitt_times

            hour = status.created_at.strftime("%Y%m%d%H")

            logging.info("hour: %s - times: %s - %s" % (hour, twitt_times, text))
            logging.info("Number of retweets found:%s" % self.found)

            if hour in self.hour_ranking.keys():
                if text in self.hour_ranking[hour].keys():
                    number = self.hour_ranking[hour][text] + 1
                else:
                    number = 1
            else:
                number = 1
                self.hour_ranking[hour] = {}

            logging.debug("adding %s to key %s" %(number,text))
            self.hour_ranking[hour][text] = number
            self.printHourlyReport() 

        except:
            logging.exception("error while analyzing tweets")

    def printHourlyReport(self):
        """Print an hourly statistic file in results.txt"""
        logging.debug("updating statistics file")
        with codecs.open("results.txt", "w", "utf-8") as f:
            for h in sorted(self.hour_ranking):
                logging.debug(h + " " + str(type(h)))
                f.write("Top %s tweets at: %s \n" % (self.TOP_TWEETS, h))
                count = self.TOP_TWEETS
                h_dict = self.hour_ranking[h]
                #sort retweets by times and then by text
                for t in sorted(h_dict, key=lambda k: (-h_dict[k], k)):
                    line = "%s time%s - %s \n" % (h_dict[t],"s" if h_dict[t]>1 else "",t)
                    f.write(line)
                    count -= 1
                    if count == 0:
                        break
                f.write("-------------------------------\n\n")

    def on_error(self, status_code):
        logging.error('An error has occured! Status code = %s' % status_code)
        return True  # keep stream alive

    def on_timeout(self):
        logging.info('Time out event')

def main():
    # Prompt for login credentials and setup stream object
    username = raw_input('Twitter username: ')
    password = getpass('Twitter password: ')
    stream = tweepy.Stream(username, password, TweetListener(), timeout=None)

    logging.info("Analyzing Tweeter sample feed. Results.txt will be updated in order to reflect the top 20 retweets of each hour.\n")
    stream.sample()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        logging.info('\nExecution finished!')
</pre>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/python/getting-retweets-from-python/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Concurrency in Hudson</title>
		<link>http://adrian.org.ar/ci/concurrency-in-hudson</link>
		<comments>http://adrian.org.ar/ci/concurrency-in-hudson#comments</comments>
		<pubDate>Wed, 25 Aug 2010 01:36:17 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[snippet.jenkins]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=137</guid>
		<description><![CDATA[How to organize and avoid concurrency problems in big projects, splitted in multiple jobs and chained to each other in Hudson? If you have a lengthy process, it will be a good practice to split it in multiple tasks, having each calling the next one, like in the (somewhat simplified) image on the left. Problem [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://adrian.org.ar/wp-content/uploads/2010/08/drawing-108x300.png" alt="" title="drawing" width="108" height="300" class="size-full wp-image-150 alignleft" /></p>
<blockquote><p>How to organize and avoid concurrency problems in big projects, splitted in multiple jobs and chained to each other in Hudson?</p></blockquote>
<p><br/>If you have a lengthy process, it will be a good practice to split it in multiple tasks, having each calling the next one, like in the (somewhat simplified) image on the left.</p>
<p>Problem number one: How to avoid <strong>Clean</strong> and <strong>Build</strong> (for instance) running at the same time? </p>
<p>As (almost) always, &#8220;you have a plugin for that&#8221; in Hudson. This time is <a href="http://wiki.hudson-ci.org/display/HUDSON/Locks+and+Latches+plugin"  target="_blank">Locks and Latches</a>, which will let you create a lock, shared by all the jobs you want. Only the job that has the lock, will be executed.</p>
<p>So far, so good, but, where is the problem?  </p>
<p><span id="more-137"></span></p>
<p>As you may guess, <strong>Clean</strong> could be called multiple times, while <strong>Build</strong>, <strong>Publish</strong>, or the same <strong>Clean</strong> are being executed. How could this happen? If you trigger <strong>Clean</strong> with a SCM (like SVN) this could be an expected situation, as you have no way to prioritize the jobs in Hudson. This is explained in <a href="http://issues.hudson-ci.org/browse/HUDSON-833" target="_blank">bug 833</a>.</p>
<p>The following Groovy script, checks if there is any other job waiting for an executor or being executed, preventing <strong>Clean</strong> to destroy the others jobs data. (Note: you will need the <a href="http://wiki.hudson-ci.org/display/HUDSON/Groovy+plugin" target="_blank">Groovy</a> plugin and then create a &#8220;system Groovy script&#8221;.) </p>
<pre>

//Jobs currently building or in the queue
jobs = hudson.model.Hudson.instance.items.findAll{job -> job.isBuilding()} + hudson.model.Hudson.instance.items.findAll{job -> job.isInQueue()}

//Keep only the names from the collected job objects
jobs = jobs.collect{x -> x.name}

//get current job name
currentJob = Thread.currentThread().executable.toString().split()[0]

//cut current job from the jobs list
jobs -= currentJob

//decide if there is any running (or waiting) job
res = true
if (jobs.size()  > 0)
{
    res = false
    println "The following jobs are being executed or waiting for an executor"
    jobs.each{println it}
}
else
{
    println "Concurrency OK"
}

return res
</pre>
<p>In case you have another jobs in your Hudson instance, that have nothing to do with our &#8220;<strong>Clean -> Build -> Publish</strong>&#8221; project, you can restrict to our project, the concurrency checking. You just have to do a slight modification to our Groovy script:</p>
<pre>
//Jobs currently building or in the queue
jobs = hudson.model.Hudson.instance.items.findAll{job -> job.isBuilding()} + hudson.model.Hudson.instance.items.findAll{job -> job.isInQueue()}

//Keep only the names from the collected job objects
jobs = jobs.collect{x -> x.name}

//list of jobs that belong to the same project
project_jobs = ["Compile", "Publish"]

//cut current job from the jobs list
jobs = project_jobs.intersect(jobs)

//decide if there is any running (or waiting) job
res = true
if (jobs.size()  > 0)
{
    res = false
    println "The following jobs are being executed or waiting for an executor"
    jobs.each{println it}
}
else
{
    println "Concurrency OK"
}

return res
</pre>
<p><img src="http://adrian.org.ar/wp-content/uploads/2010/08/concurrency-294x300.jpg" alt="" title="concurrency" width="150" height="150" class="size-full wp-image-95 alignleft" /></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/ci/concurrency-in-hudson/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Agile Spain 2010 links from Twitter</title>
		<link>http://adrian.org.ar/agile/agile-spain-2010-links-from-twitter</link>
		<comments>http://adrian.org.ar/agile/agile-spain-2010-links-from-twitter#comments</comments>
		<pubDate>Fri, 18 Jun 2010 16:13:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[regular expressions]]></category>
		<category><![CDATA[scrum]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=112</guid>
		<description><![CDATA[Hi, here are all the the links collected from #agilespain2010 posted in Twitter after applying this regex. ^(.*)(http://\S+)(.*)$ plus ordering + plus filtering within a small script. The complete list until Jun-18-2010: http://twitter.com/#search?q=%23agilespain2010 http://www.podgramando.es/uncategorized/cas2010-retrospectiva http://wp.me/pQAdW-3F http://twitpic.com/1xlowx http://twitgoo.com/zrb54 http://tinyurl.com/AgileSoftwareDevelopmentInF1 http://tinyurl.com/3yzamc2 http://tinyurl.com/3y84wlv http://tinyurl.com/33mqjwb http://ow.ly/1Yk5S http://ow.ly/1Yi7x http://ow.ly/1Y8Gc http://ow.ly/1Y8DO http://ow.ly/1XTja http://ow.ly/1XTi9 http://ow.ly/1XSSO http://ow.ly/1XMTJ http://ow.ly/1XGx2 http://isparade.jp/215173 http://is.gd/cLMy2 http://ht.ly/1XTZD http://groups.google.es/group/agile-spain/web/agilespain2010 http://groups.google.es/group/agile-spain-levante [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-medium wp-image-119" title="agile.v.230.largo_" src="http://adrian.org.ar/wp-content/uploads/2010/06/agile.v.230.largo_-300x44.png" alt="" width="300" height="44" /></p>
<p><br/>Hi, here are all the the links collected from #agilespain2010 posted in Twitter after applying this regex. ^(.*)(http://\S+)(.*)$ plus ordering + plus filtering within a small script.</p>
<p><span id="more-112"></span></p>
<p>The complete list until Jun-18-2010:</p>
<p>http://twitter.com/#search?q=%23agilespain2010</p>
<p><code></p>
<p>http://www.podgramando.es/uncategorized/cas2010-retrospectiva</p>
<p>http://wp.me/pQAdW-3F</p>
<p>http://twitpic.com/1xlowx</p>
<p>http://twitgoo.com/zrb54</p>
<p>http://tinyurl.com/AgileSoftwareDevelopmentInF1</p>
<p>http://tinyurl.com/3yzamc2</p>
<p>http://tinyurl.com/3y84wlv</p>
<p>http://tinyurl.com/33mqjwb</p>
<p>http://ow.ly/1Yk5S</p>
<p>http://ow.ly/1Yi7x</p>
<p>http://ow.ly/1Y8Gc</p>
<p>http://ow.ly/1Y8DO</p>
<p>http://ow.ly/1XTja</p>
<p>http://ow.ly/1XTi9</p>
<p>http://ow.ly/1XSSO</p>
<p>http://ow.ly/1XMTJ</p>
<p>http://ow.ly/1XGx2</p>
<p>http://isparade.jp/215173</p>
<p>http://is.gd/cLMy2</p>
<p>http://ht.ly/1XTZD</p>
<p>http://groups.google.es/group/agile-spain/web/agilespain2010</p>
<p>http://groups.google.es/group/agile-spain-levante</p>
<p>http://geeks.ms/blogs/ilanda/archive/2010/06/13/estuve-en-la-agile-spain-2010.aspx</p>
<p>http://bit.ly/cirkzT</p>
<p>http://bit.ly/cKr2ss</p>
<p>http://bit.ly/bqOqhu</p>
<p>http://bit.ly/agilespain</p>
<p>http://bit.ly/a0UNxo</p>
<p><iframe src="http://player.vimeo.com/video/12527839" width="500" height="375" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe></p>
<p></code></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/agile/agile-spain-2010-links-from-twitter/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Open ID login with Google App Engine + Django</title>
		<link>http://adrian.org.ar/google-app-engine/open-id-login-with-google-app-engine-django</link>
		<comments>http://adrian.org.ar/google-app-engine/open-id-login-with-google-app-engine-django#comments</comments>
		<pubDate>Wed, 16 Jun 2010 01:41:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[gae]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[open-id]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=98</guid>
		<description><![CDATA[Hi!, this a clean and simple sample test of a web app using Open ID login in Google App Engine + Django. http://bitbucket.org/deccico/djangoappengine-openid-sample This application combines with slight modifications, the following projects: Djangoappengine: http://www.allbuttonspressed.com/projects/djangoappengine Django-nonrel http://www.allbuttonspressed.com/projects/django-nonrel &#8211; Changes to Text fields to Chars, due to lack of filtering support in the firsts OpenID integration: https://launchpad.net/django-openid-auth [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-104" title="openid" src="http://adrian.org.ar/wp-content/uploads/2010/06/openid.png" alt="" width="200" height="66" /></p>
<p>Hi!, this a clean and simple sample test of a web app using Open ID login in Google App Engine + Django.</p>
<p><a href="http://bitbucket.org/deccico/djangoappengine-openid-sample" target="_blank">http://bitbucket.org/deccico/djangoappengine-openid-sample</a></p>
<p>This application combines with slight modifications, the following projects:</p>
<ul>
<li>Djangoappengine: http://www.allbuttonspressed.com/projects/djangoappengine</li>
<li>Django-nonrel http://www.allbuttonspressed.com/projects/django-nonrel &#8211; Changes to Text fields to Chars, due to lack of filtering support in the firsts</li>
<li>OpenID integration: https://launchpad.net/django-openid-auth &#8211; Small change in the login view template, in order to work with standard Cross site forgery protection</li>
<li>Python OpenID library: http://github.com/openid/python-openid</li>
</ul>
<p>Just remember to add {% csrf_token %} within the login form of your own view.</p>
<p>enjoy!</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/google-app-engine/open-id-login-with-google-app-engine-django/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to calculate the closest point to a segment</title>
		<link>http://adrian.org.ar/cplusplus/closest-point-to-a-segment</link>
		<comments>http://adrian.org.ar/cplusplus/closest-point-to-a-segment#comments</comments>
		<pubDate>Sun, 06 Jun 2010 16:23:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[c++]]></category>
		<category><![CDATA[geometry]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=83</guid>
		<description><![CDATA[Hi, below there is a little snippet that calculates the closest point to a segment. It is written in C++ but could be easily translated to any other language. Disclaimer: given its age, it use hungarian notation, and some names are in spanish, but it was deeply tested and works ok. //-------------------------------------------------------------------------------------------------------- //author: Adri&#225;n Deccico [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-95 alignleft" title="geometry" src="http://adrian.org.ar/wp-content/uploads/2010/06/geometry.jpg" alt="" width="85" height="78" /></p>
<p>Hi, below there is a little snippet that calculates the closest point to a segment. It is written in C++ but could be easily translated to any other language. Disclaimer: given its age, it use hungarian notation, and some names are in spanish, but it was deeply tested and works ok. <img src='http://adrian.org.ar/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
<span id="more-83"></span></p>
<pre>

//--------------------------------------------------------------------------------------------------------
//author: Adri&aacute;n Deccico - http://adrian.org.ar
/*
Description: calculate the closest point belonging to a given segment.
Parameters:
nSx1, nSy1 =  First point of the segment
nSx2, int nSy2 = Second point of the segment
nPx, int nPy = The point to analize
*nCercaX,  *nCercaY = The closest point to the given point (nPx,nPy) that belongs to the segment
Returns: The distance between the given point and the point found of the segment
*/
double ElPuntoMasCercanoAUnSegmento(double nSx1, double nSy1, double nSx2,
double nSy2, double nPx, double nPy,
double *nCercaX,  double *nCercaY)
{

//caracterizo la recta del segmento dado Y=m*X + b
double m, b;

bool bEsHorizontalOVertical = false;

//el segmento es vertical
if (nSx2 == nSx1){
    *nCercaX = nSx1;
    *nCercaY = nPy;
    bEsHorizontalOVertical = true;
}

//el segmento es horizontal
if (nSy2 == nSy1){
    *nCercaY = nSy1;
    *nCercaX = nPx;
    bEsHorizontalOVertical = true;
}

//el segmento est&aacute; caracterizado por una recta \&quot;AX + BY + C = 0\&quot; con
// A y B distintos de cero
if (!bEsHorizontalOVertical)
{
    m= (nSy2 - nSy1) / (nSx2 - nSx1);
    b = nSy1 - (nSx1 * m);

    //caracterizo la recta que une al punto dado con el punto m&aacute;s
    // cercano dentro del segmento Y=m1*X + b1
    double m1, b1;

    m1 = -1 / m;
    b1 = -m1 * nPx + nPy;

    //encuentro el punto de intersecci&oacute;n
    *nCercaX =  (b1 - b) / (m - m1);
    *nCercaY =  m * *nCercaX + b;
}

//verificar que el punto encontrado est&aacute; dentro del segmento
if (*nCercaX &amp;lt; min(nSx1,nSx2)
||  *nCercaX &amp;gt; max(nSx1,nSx2)
||  *nCercaY &amp;lt; min(nSy1,nSy2)
||  *nCercaY &amp;gt; max(nSy1,nSy2) )
{
    //el punto m&aacute;s cercano ser&aacute; uno de los dos extremos (el m&aacute;s cercano al punto)
    if (dDistanciaEntrePuntos(nSx1, nSy1, nPx, nPy) &lt;= dDistanciaEntrePuntos(nSx2, nSy2, nPx, nPy))
    {
        *nCercaX = nSx1;
        *nCercaY = nSy1;
    }
    else
    {
        *nCercaX = nSx2;
        *nCercaY = nSy2;
    }
}

return dDistanciaEntrePuntos(nPx, nPy, *nCercaX , *nCercaY);

}
//--------------------------------------------------------------------------------------------

//------------------------------------------------------------------------
//return the distance between thwo points in a x,y plane.
double dDistanciaEntrePuntos(double lOldX, double lOldY,
double lNewX, double lNewY)
{
    double x = lNewX - lOldX;
    double y = lNewY - lOldY;

    return sqrt(pow(x,2) + pow(y,2));
}
//------------------------------------------------------------------------
</pre>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/cplusplus/closest-point-to-a-segment/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making a simple html editor in C++ Builder</title>
		<link>http://adrian.org.ar/cplusplus/making-a-simple-html-in-c-builder</link>
		<comments>http://adrian.org.ar/cplusplus/making-a-simple-html-in-c-builder#comments</comments>
		<pubDate>Sun, 06 Jun 2010 13:00:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[c++]]></category>
		<category><![CDATA[c++ builder]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[windows api]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=63</guid>
		<description><![CDATA[Back in time, I had to make a simple html editor. It was very easy, by using a simple TCppWebBrowser (wb) and the IHTMLDocument2 interface. Hope it helps someone :)<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-129" title="c++" src="http://adrian.org.ar/wp-content/uploads/2010/06/c++-268x300.jpg" alt="" width="134" height="150" />Back in time, I had to make a simple html editor. It was very easy, by using a simple TCppWebBrowser (wb) and the IHTMLDocument2 interface. You will also need a TMemo (memo1) control. Here is the source code, hope it helps someone <img src='http://adrian.org.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
<span id="more-63"></span><br />
<br/><br />
<br/><br />
<br/></p>
<p><code></p>
<pre>
//---------------------------------------------------------------------------
//author: Adri&aacute;n Deccico - http://adrian.org.ar
//---------------------------------------------------------------------------

#include &lt;vcl.h&gt;
#pragma hdrstop
#include &quot;mshtml.h&quot;

#include &quot;Unit1.h&quot;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link &quot;SHDocVw_OCX&quot;
#pragma resource &quot;*.dfm&quot;
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnNavigateAndEditClick(TObject *Sender)
{
        wb-&gt;Navigate((WideString)&quot;www.google.com&quot;);
        while (wb-&gt;Busy)
                Application-&gt;ProcessMessages();

        if (wb-&gt;Document)
        {
                IHTMLDocument2 *html;
                wb-&gt;Document-&gt;QueryInterface&lt;IHTMLDocument2&gt;(&amp;html);
                html-&gt;put_designMode(L&quot;On&quot;);
                html-&gt;Release();
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnInsertImageClick(TObject *Sender)
{
    if (wb-&gt;Document)
    {
          IHTMLDocument2 *html;
          wb-&gt;Document-&gt;QueryInterface&lt;IHTMLDocument2&gt;(&amp;html);
          VARIANT var;
          VARIANT_BOOL receive;
          html-&gt;execCommand(L&quot;InsertImage&quot;,true,var, &amp;receive);
          html-&gt;Release();
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetHtmlClick(TObject *Sender)
{
        if (wb-&gt;Document)
        {
                IHTMLDocument2 *html;
                wb-&gt;Document-&gt;QueryInterface&lt;IHTMLDocument2&gt;(&amp;html);
                IHTMLElement *pElement;
                html-&gt;get_body(&amp;pElement);
                pElement-&gt;get_parentElement(&amp;pElement);
                wchar_t *tmp;
                pElement-&gt;get_outerHTML(&amp;tmp);
                Memo1-&gt;Lines-&gt;Text = tmp;
                pElement-&gt;Release();
                html-&gt;Release();
        }
}
//---------------------------------------------------------------------------
</pre>
<p></code></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/cplusplus/making-a-simple-html-in-c-builder/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to replace a substring using regex in Python</title>
		<link>http://adrian.org.ar/re/how-to-replace-a-substring-using-regex-in-python</link>
		<comments>http://adrian.org.ar/re/how-to-replace-a-substring-using-regex-in-python#comments</comments>
		<pubDate>Sat, 05 Jun 2010 23:55:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[regular expressions]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://adrian.org.ar/?p=57</guid>
		<description><![CDATA[The problem: You match a string with your regex, but you need to replace just a portion of it. How could we replace it? The trick is simple, put the text you want to replace within &#8220;()&#8221; which means &#8220;group&#8221; in regex language. If the regex worked, you could replace just that portion by using [...]<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></description>
			<content:encoded><![CDATA[<p>The problem: You match a string with your regex, but you need to replace just a portion of it. How could we replace it?<br />
The trick is simple, put the text you want to replace within &#8220;<strong>()</strong>&#8221; which means &#8220;<strong>group</strong>&#8221; in regex language. If the regex worked, you could replace just that portion by using Python match information, like in this example:</p>
<pre>
#the first group contains the expression we want to replace
pat = "word1\s(.*)\sword2"
test = "word1 will never be a word2"
repl = "replace"

import re
m = re.search(pat,test)

if m and m.groups() &gt; 0:
&nbsp;&nbsp;line = test[0:m.start(1)] + repl + test[m.end(1):len(test)]
&nbsp;&nbsp;print line
else:
&nbsp;&nbsp;print "the pattern didn't capture any text"
</pre>
<p>This will print: &#8216;<strong>word1 will never be a word2</strong><em>&#8216;</em></p>
<p><em>The group to be replaced could be located in any position of the string.</em></p>
<p><em> </em></p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-7834084966419238";
/* 468x15, created 6/5/10 */
google_ad_slot = "1365866500";
google_ad_width = 468;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://adrian.org.ar/re/how-to-replace-a-substring-using-regex-in-python/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

