<?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>Connecting the dots... &#187; rp</title>
	<atom:link href="http://blog.rajatpandit.com/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rajatpandit.com</link>
	<description>Thoughts on Web Development, Infrastructure and Application Scalability</description>
	<lastBuildDate>Thu, 29 Dec 2011 13:21:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Notes on Git Part I / Quickstart Guide to Git</title>
		<link>http://blog.rajatpandit.com/2011/12/27/notes-on-git-part-i-quickstart-guide-to-git/</link>
		<comments>http://blog.rajatpandit.com/2011/12/27/notes-on-git-part-i-quickstart-guide-to-git/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 12:25:46 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=753</guid>
		<description><![CDATA[Git stores all the information locally, commit logs, versions etc so there is very little you can&#8217;t do if you are offline everything is check summed before it enters the...]]></description>
			<content:encoded><![CDATA[<ul>
<li>Git stores all the information locally, commit logs, versions etc so there is very little you can&#8217;t do if you are offline</li>
<li>everything is check summed before it enters the repo, it uses SHA-1 hash which is a 40 character string composed  of hex and calculated based on a file or directory structure in Git.</li>
<li>files have three states
<ul>
<li>committed: data is safely stored in the local database</li>
<li>modified: the file is modified but not committed</li>
<li>staged: marked a file in its current version to go into your next commit snapshot.</li>
</ul>
</li>
<li>Three main sections of a git project
<ul>
<li>working directory: single check-out of one version of the project</li>
<li>staging area: is a simple file that stores information of what will go in the next commit. its referred to an index </li>
<li>git directory (repo) where all the metadata and the object database for your project is stored.</li>
</ul>
</li>
<li>define your git identity:
<pre class="brush: plain; title: ; notranslate">
$ git config --global user.name 'Rajat Pandit'
$ git config --global user.email 'rajat@virajsolutions.com'
</pre>
</li>
<li>define the editor
<pre class="brush: plain; title: ; notranslate">
$ git config --global core.editor vim
$ git config --global merge.tool vimdiff
</pre>
</li>
<li>checking the settings <code>$ git config --list</code>
</li>
<li>Initialize a git repo.<code>$ git init </code></li>
<li>add files to the repo<code>$ git add *.</code></li>
<li>commit message:<code>$ git commit -m '<your message goes here>';</code></li>
<li>cloning a repo: this is not the same as svn&#8217;s checkout. every version of every file is brought down. infect if the server crashes, any of the cloned copies can be used to bring the server back to the state in was in when it was cloned.
<li>$ git clone git://bla.com/morebla.git mybladir</li>
</li>
<li>git has a number of transfer protocols
<ul>
<li>git://</li>
<li>http(s)://</li>
<li>user@server:/path.git (ssh protocol)</li>
</ul
</li>
<li>files are either
<ul>
<li>tracked: (modified, unmodified or staged)</li>
<li>untracked: (any files in the working directory which are not present in the last snapshot and not in your staging area)</li>
</ul>
</li>
<li>checking the status of files<code>$ git status</code></li>
<li>revert a file change<code>$ git reset HEAD <file> # to upstage the command</code></li>
<li>if you do a <code>"git add"</code> and the modify the file and commit it the changes at the point of last <code>'git add'</code> will get committed. if the new changes need to be added as well the file has to be <code>'git add''ed </code>again&#8217;</li>
<li>defining ignore files by adding them to the .gitignore files. The following rules for the pattern work
<ul>
<li>blank lines or lines starting with # are ignored</li>
<li>standard glob patters work</li>
<li>patterns can be ended with a / to specify a directory</li>
<li>you can negate a pattern by starting it with a !</li>
</ul>
</li>
<li>to see what will go in the next commit:
<pre class="brush: plain; title: ; notranslate">
$ git diff --staged
$ git diff (will only show untagged changes)
$ git diff --staged (will show the diff for the staged files)
</pre>
</li>
<li>to remove a file<code>$ git rm <filename></code>It removes it from the staging area and also physically moves to file to ensure that it doesn&#8217;t appear as a tracked file.</li>
<li>To remove a file from staging area but not form the file system.<code>$ git rm --cached readme.txt</code>
<p>This is useful particularly in case where you possibly forgot to add it in the .gitignore file and it got pushed to the staging area and then had to be taken out but not removed from the filesystem.
</li>
<li>To use the glob patterns, stuff needs to be escaped.
<pre class="brush: plain; title: ; notranslate">
$ git rm log/\*.log
$ git rm \*~
</pre>
</li>
<li>moving files around:<code>$ git mv file_from file_to</code></li>
<li>git status will show this as a file renamed. its the equivalent of renaming the file first, git rm the first file and then git add the new one</li>
<li>git has no meta data that tells you later that you had renamed the file. </li>
<li> viewing history using git log
<pre class="brush: plain; title: ; notranslate">
$ git log -p -2
-p shows the diff
-2 limits the entries to 2 by default shows the most recent commit first.
$ git log --stat
--stat shows the abbreviated stats for all the changes that happened
$ git log --stat --pretty=&lt;online|full|fuller&gt;
$ git log --stat --pretty=format:&quot;%h - %an, %ar : %s&quot;
(ref: http://progit.org/book/ch2-4.html)

$ git log --pretty=format:&quot;%h %s&quot; --graph

(adds a nice little ASCII graph showing your branch and merge history)
$ git log --since=2.weeks
$ git log --author=&lt;name of author&gt; --grep=&quot;search in commit messages&quot; to make both of them count you also need to pass --all-match option
</pre>
</li>
<li>git understands the difference between author and patcher.
<ul>
<li>author: who created originally wrote the work</li>
<li>committer: who applied the last of the work.</li>
</ul>
</li>
<li>Amend a commit, in case you forgot to put a file in stage then you can put it as a second step:
<pre class="brush: plain; title: ; notranslate">
$ git commit -m 'intial commit'
$ git add forgotten_file
$ git commit --amend
</pre>
</li>
<li>in case you have staged two files but want them to be committed in separate commits, how do you &#8216;upstage&#8217; your files.
<pre class="brush: plain; title: ; notranslate">
	$ git add * # staged all the changes
	$ git reset HEAD benchmarks.rb # keeps the file modified but takes it out of the staging area
</pre>
</li>
<li>reverting local modification <code>$ git checkout -- benchmarks.rb</code></li>
<li>get the info about the remote git repo. if you have more than one remote repo then the command lists all of them
<pre class="brush: plain; title: ; notranslate">
$ git remote -v
</pre>
</li>
<li>adding a remote repo
<pre class="brush: plain; title: ; notranslate">
$ git remote add [shortname] [url]
$ git remote add pb git://github.com/paulboone/ticgit.git
</pre>
</li>
<li>now you can fetch all the changes in pb that are not in origin<br />
	<code>$ git fetch pb </code><br />
	this will check out the changes in pb/master you can then merge it in to one of your branches or checkout a local branch at this  point if you want to inspect it.
</li>
<li>update your current code from the remote repo <code>$ git pull # automatically pulls from the origin)</code>
</li>
<li>pushing changes to the report server
<pre class="brush: plain; title: ; notranslate">
$ git push [remote-name] [branch-name]
$ git push origin master
</pre>
<p><b>note:</b> push will only work only if no one else has pushed their changes, if that&#8217;s the case, your push will be rejected and you will have to pull to bring your code to the most recent state.
</li>
<li>inspecting a remote <code>$ git remote show [remote-name]</code><br />
	shows the branches on the remote and also the branch the pull is associated with.
</li>
<li>git tagging <code>$ git tag # list the number of tags n your code</code></li>
<li>git uses two main types of tags: <code>lightweight</code> and <code>annotated</code>. A lightweight tag is very much like a branch that doesn&#8217;t change &#8211; its just a pointer to a specific commit. Annotated tags, however are stored as full objects in the git database.The annotated tags are checksummed, contain a tagger name, email and date; have a tagging message and can be signed and verified with GNU privacy Guard. its generally recommended that you create annotated tags so that you can have all this information; but if you want a temporary tag or for some reason don&#8217;t want to keep the other information then keep the other information, lightweight tags are also available.</li>
<li>create and show new annotated tag
<pre class="brush: plain; title: ; notranslate">
$ git tag -a v1.0 -m 'bla bla bla bla'
$ git show v1.0
$ git tag # lists all the tags on the code also create a signed tag
$ git tag -s v1.5 -m 'my super signed tag'
</pre>
</li>
<li>creating a light weight:
<pre class="brush: plain; title: ; notranslate">
$ git tag v1.4
$ git tag
lists all the tag along with annotated, signed or lightweight tags
$ git show v1.4
* verifying a signed tag:
$ git tag -v v1..4
</pre>
<p>	you require to have the public key installed to verify that the tag is from the right author
</li>
<li>you can also tag later by specifying commit checksum or part of it.<code>$ git tag -a v1.2 9fceb02</code>
</li>
<li>sharing tags, by default the tags are not transferred to the remote server when using git push,they have to be explicity pushed though<br />
	<code>$ git push origin [tagname]</code><br />
	if you have lots of tags and want to push all of them at the same time.<br />
	<code>$ git push origin --tags</code>
</li>
</ul>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/27/notes-on-git-part-i-quickstart-guide-to-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes on VirtualBox / Quickstart guide to VirtualBox</title>
		<link>http://blog.rajatpandit.com/2011/12/23/notes-on-virtualbox-quickstart-guide-to-virtualbox/</link>
		<comments>http://blog.rajatpandit.com/2011/12/23/notes-on-virtualbox-quickstart-guide-to-virtualbox/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 14:32:04 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=745</guid>
		<description><![CDATA[General Notes &#8220;hosted&#8221; hypervisor or type 2 hypervisor where as a &#8220;bare-metal&#8221; or &#8220;type 1&#8243; hypervisor would run directly on the hardware open virtualization format (OVF) VirtualBox Remote Desktop Extension...]]></description>
			<content:encoded><![CDATA[<h3>General Notes</h3>
<ul>
<li>&#8220;hosted&#8221; hypervisor or type 2 hypervisor where as a &#8220;bare-metal&#8221; or &#8220;type 1&#8243; hypervisor would run directly on the hardware</li>
<li>open virtualization format (OVF)</li>
<li>VirtualBox Remote Desktop Extension (VRDE) &#8211; also support for full client USB Support</li>
<li>Extensible RDP authentication</li>
<li>USB Over RDP</li>
<li>Extension packs available
<ul>
<li>the virtual USB 2.0 (EHCI) device</li>
<li>virtual boc remote desktop protocol</li>
<li>Intel PXE boot RPM with support for E1000 network card</li>
</ul>
</li>
<li>fixed sized hard disk image is faster and has less overheads compared to an expanding overhead</li>
<li>different kinds of disks:
<ul>
<li>VDI</li>
<li>VMDK</li>
<li>VHD</li>
<li>HDD</li>
</ul>
</li>
<li>Two importable formats:
<ul>
<li>VMDK with a file in an XML Dialect with an .ovf extension. These files must reside in the same directory for the VirtualBox to be able to import them.</li>
<li>Everything in a single archive called the .ova extension. its an archive file with a variant of the TAR archive format)</li>
</ul>
</li>
<li>Commmands in the virtualbox package
<ul>
<li>VirtualBox &#8211; virtualbox manager</li>
<li>VBoxManage is a command line manager fro very detailed control</li>
<li>VBoxSDL for simple graphical frontend</li>
<li>VBoxHeadLess is yet another frontend to produce no visible output on the host at all.</li>
</ul>
</li>
<li>Dynamic Kernal Module Support requires to be installed, this framework helps with building and upgrading kernel modules.</li>
<li>if the kernel of your linux host was updated and DKMS is not installed, in that case the kernel module will need to be reinstalled by executing (as root)
<pre class="brush: plain; title: ; notranslate">
$ /etc/init.d/vboxdrv setup
</pre>
</li>
<li>virtualbox now not only supports PIIX3 but also the ICH9 chipset for latest operating systems like macosx</li>
<li>Auto mounting: linux guests automounted shared folders are mounted into /media directory align with the prefix sf_. for example, the shared folder mayflies would be mounted to <code>/media/sf_myfiles</code> on linux. The sf_ is controlled by the property <code>/VirtualBox/GuestAdd/SharedFolders/MountPrefix</code> </li>
<li>access to the automounted folders is only granted to members of the user vboxsf</li>
<li>listing the virtualbox guest property
<pre class="brush: plain; title: ; notranslate">$ VBoxManage guestproperty enumerate &quot;Windows Vista&quot; </pre>
<p>or listing a specific property</p>
<pre class="brush: plain; title: ; notranslate">$VBoxManage guestproperty get &quot;windows vita&quot; &quot;/VirtualBox/GuestInfo/OS/Product&quot;</pre>
</li>
<li>to change values use <code>$ VBoxControl guestproperty enumerate</code></li>
<li>VBoxManage guest-control to run commands inside the guest from the host machine</li>
<li>Memory ballooning is used to share memory associated with a vm with another vm. This is used for memory over commitment. </li>
<li>VBoxManage controlvm &#8220;VM Name? guestmemoryballoon <n> where n is the memory  the memory to allocate the guest vm. the guest additions software must be installed for this to run.</li>
<li>Virtual box dedups the page duplication by using PageFusion you can only turn it on when a vm is turned off</li>
<li><code>VBoxManage modifyvm "VM Name" --pagefusion</code> on<br />
you can observe page fusion operation using metrics RAM/VMM/Shared shows the total amount of fused pages, whereas the per-vm metric guest/RAM/Usage/Shared will return the amount of fused memory for a given VM.</li>
<li>Virtualbox allows you to manage the size of the disk even after the disk creation, even after data has been written to  it.</li>
<li>Virtualbox disk format:
<ul>
<li>normally by default for a new image, the format it uses is called Virtual Disk Image (VDI). </li>
<li>VirtualBox also fully supports the popular and open VMDK contrainer format that is used by many popular virtualization softwares like VMWare.</li>
<li>Alsofully supports the VHD format from microsoft.</li>
<li>Image files from Parallers version 2 (HDD format) also supported. newer formats 3, and 4 are not supported however you can convert them into older format (version 2) by using tools provided by parallels.</li>
</ul>
</li>
<li>Do not simply make copies of virtual disk images. if you import such a second copy into a virtual machine, virtualbox will complain with an error, since VirtualBox assigns a unique identifier (UUID) to each disk image to make sure it is only used once. </li>
<li>
Disk modes:</p>
<ul>
<li>normal mode, allows you to take snapshots and restore from it.</li>
<li>write-through hard disks: are completely unaffected by snapshots. their states are not taken and not restores when snapshots are restored.</li>
<li>shareable hard disks: works the same as write-though hard disks however they can be used to be shared across multiple VMS writing to it directly. standard filesystem is not setup to be written by multiple file systems at the same time.only fixed size images can be used in this way, and dynamically growing images are rejected.</li>
<li>immutable images only remember write access temporarily while virtual machines are running. so the approach is create a new &#8216;normal&#8217; image and once you are happy with the setup and deem its contents useful then mark it &#8216;immutable&#8217;;</li>
<li>if you take a snapshot of a machine with immutable images, then on every machine power-up those images are reset to the state of the last (current) snapshot (instead of the state of the original immutable image)</li>
<li>As a result the same immutable image can be used by several virtual machines without restrictions. (Also looking at the &#8216;enabling the differencing disks&#8217; that with auto-reset turned to off so that the vm&#8217;s sharing the immutable disk don&#8217;t forget the settings.</li>
</ul>
</li>
<li>An image in &#8216;multi-attach mode&#8217; an be attached to more than one virtual machine at the same time, even if these machines are running simultaneously. For each virtual m aching to which an image is attached, a differencing image is c reared. As a result data that is written to such a virtual disk by one machine is not seen by the other machines to which the image is attached. each machine creates its own  history of the multi-attach image. </li>
<li>The standard approach would be &#8216;one immutable disk for the operating system&#8217; and one &#8216;write-though&#8217; for your data files. </li>
<li>Networking: virtualbox providers up to eight virtual PCI ethernet cards for each virtual machine. for each such card, you can individually select:
<ul>
<li>The hardware that will be virtualised as well as</li>
<li>The virtualization mode that the virtual card will be operating in with respect to your physical networking hardware on the host.</li>
</ul>
</li>
<li>
Networking modes:</p>
<ul>
<li>Not attached: in this mode the virtualbox reports to the guest that a network card is present but there is no connection, as if no ethernet cable was plugged into the card.
<li>NAT: default mode, only required to browse the web, download files and view email inside the guests. certain limitations when windows file sharing. </li>
<li>Bridged network: more advanced needs such as network simulations and running servers in a guest. when enabled virtual box connects to on our installed network cards and exchanges network packets directly, circumventing your host operating system&#8217;s network stack.</li>
<li>Internal networking: visible to only certain software based networking (selected virtual machine) but not to applications running on the host or the outside world. Internal networking is the same as bridged networking as that it lets the vm speak to the outside world except that the outside world is the other vm&#8217;s on the same host.</li>
<li>Host-only networking: create a networking containing the host and a set of virtual machines without the need of the host&#8217;s physical network interface. instead a virtual network interface (similar to loopback interface) is created on the host, providing connectivity among virtual machines and the host.</li>
<li>VDE (virtual distributed ethernet) networking: </li>
</ul>
</li>
<li>port forwarding
<pre class="brush: plain; title: ; notranslate">
VBoxManage modifyvm &quot;VM name&quot; --natpf1 &quot;guestssh,tcp,,2222,,22&quot;
natpf1 denotes the network card
2222 is the port on the host
22 is the port on the guest
guestssh is purely description and will be auto-generated if not present
</pre>
</li>
<li>to remove the same rule:<br />
<code>VBoxManage modifyvm "VM name" --natpf1 delete "guestssh"</code></p>
<p>NOTE: it is not possible to configure incoming NAT connections while the VM is running. However, you can change the settings for a VM which is currently saved (or powered off at a snapshot)
</li>
<li>bridged networking: with bridged networking, virtualbox uses a device driver on your host system that filters data from your physical network adapter. this driver is therefore called &#8216;net filter&#8217; driver. this allows virtualbox to intercept data from the physical network and inject data into it, effectively creating a new network interface in software. When a guest is using such a new software interface, it looks to the host system to the host system as though the guest were physically connected to the interface using a network cable. the host can send data to the guest though that interface and receive data from it. thismeans that yo can setup routing and bridging between the guest and the rest of your network.</li>
<li>running virtualbox as headless
<pre class="brush: plain; title: ; notranslate">VBoxManage startvm &quot;VM Name&quot; --type headless</pre>
<p>the extra &#8211;type option causes VirtualBox to use VBoxHeadless as the front-end to the internal virtualization engine instead of the qt-front-end<br />
the alternate syntax is:</p>
<pre class="brush: plain; title: ; notranslate">VBoxHeadless --startvm &lt;uuid|name&gt;</pre>
</li>
</ul>
<h2>Steps to install a vm headless server</h2>
<p>create a new virtual machine</p>
<pre class="brush: plain; title: ; notranslate">
VBoxManage creative --name &quot;Windows XP&quot; --ostype WindowsXP --register

--registervm is optional, doing it now saves you from having to do that manually later.
--ostype is also optional but selecting this upfront results in some default options to be selected.
[/cpde]

To get the complete list

&lt;code&gt;VBoxManage list ostypes&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;make sure that the vm is configured the guest operating system.
	1VBoxManage modifyvm &quot;Windows XP&quot; --memory 256 --acpi on --boot1 dvd --nic1 nat</pre>
</li>
<li>Create a virtual hard disk for the vm (10GB)
<pre class="brush: plain; title: ; notranslate">VBoxManage createhd --filename &quot;WinXP.vdi&quot; --size 10000</pre>
</li>
<li>Add an IDE controller to the new VM
<pre class="brush: plain; title: ; notranslate">VBoxManage storagectl &quot;Windows XP&quot; --name &quot;IDE Controller&quot; --add ide --controller PIIX4</pre>
</li>
<li>set the VDI created above as the first virtual disk of the new VM
<pre class="brush: plain; title: ; notranslate">VBoxManage storageattach &quot;Windows XP&quot; --storagectl &quot;IDE Controller&quot; --port 0 --device 0 --type hdd --medium &quot;WinXP.vdi&quot;</pre>
</li>
<li>attach the ISO file that contains the operating system
<pre class="brush: plain; title: ; notranslate">VBoxManage storageattach &quot;Windows XP&quot; --storagectl &quot;IDE Controller&quot; --port 0 --device 1 </pre>
</li>
<li>type
<pre class="brush: plain; title: ; notranslate">dvddrive --medium /full/path/to/iso.iso</pre>
</li>
<li>Start the virtual machine
<pre class="brush: plain; title: ; notranslate">VBoxHeadless --startvm &quot;Windows XP&quot;</pre>
</li>
</ul>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/23/notes-on-virtualbox-quickstart-guide-to-virtualbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes on MongoDB / Quickstart Guide to MongoDB</title>
		<link>http://blog.rajatpandit.com/2011/12/23/notes-on-mongodb-quickstart-guide-to-mongodb/</link>
		<comments>http://blog.rajatpandit.com/2011/12/23/notes-on-mongodb-quickstart-guide-to-mongodb/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 11:56:00 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[document store]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[NOSQL]]></category>
		<category><![CDATA[schema-less]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=737</guid>
		<description><![CDATA[large system (multi-shards, config servers and mongo routers) data model database holds collections collection holds documents document is a set of fields field is a key-value pair key is a...]]></description>
			<content:encoded><![CDATA[<ul>
<li>large system (multi-shards, config servers and mongo routers)</li>
<li>data  model
<ul>
<li>database holds collections</li>
<li>collection holds documents</li>
<li>document is a set of fields</li>
<li>field is a key-value pair</li>
<li>key is a name</li>
<li>value is:
<ul>
<li>basic type </li>
<li>a document</li>
<li>or an array of values</li>
</ul>
</li>
</ul>
</li>
<li>mongo query language</li>
<li>BSON is a binary encoded serialization of JSON like documents. BSON was designed to be lightweight, traversable and efficient. BSON like JSON supports embedding of objects and arrays within other objects and arrays.</li>
<li>MongoDB uses BSON as a data storage and network transfer format for &#8220;documents&#8221;
<pre class="brush: plain; title: ; notranslate">
$bson = bson_encode(null);
$bson = bson_encode(array('a' =&gt; 10));
</pre>
</li>
<li>using a database
<pre class="brush: plain; title: ; notranslate">
	&gt; use mydb
</pre>
<p>	switched to db mydb
</li>
<li>Insert data inside a collection
<pre class="brush: plain; title: ; notranslate">
	&gt; j = {name: 'mongo'}
	&gt; db.things.save(j);
	&gt; db.things.find();
</pre>
</li>
<li>no collection was predefined, it appeared lazily	</li>
<li>no structure for the document to store</li>
<li>mongo addeds an objectID in the field _id</li>
<li>do stuff in a loop
<pre class="brush: plain; title: ; notranslate">
	&gt; for(var i=1;i&lt;=20;i++) db.things.save({x:4, j:i});
	&gt; db.things.find();
</pre>
</li>
<li>find returns back a cursor, navigation between results is possible using the &#8216;it&#8217; command
<pre class="brush: plain; title: ; notranslate">
c = db.things.find();
	&gt; while (c.hasNext()) printjson(c.next());
	&gt; db.things.find().foreach(printjson);
</pre>
</li>
<li>
<pre class="brush: plain; title: ; notranslate">
  &gt; var c = db.things.find()
  &gt; printjson(c[4]);
</pre>
<p>will show the 5th record, not right because it will load all the results unto 4 in the memory which can have scalability issues
</li>
<li>
<pre class="brush: plain; title: ; notranslate">
&gt; db.things.find().toArray();
</pre>
</li>
<li>more queries
<pre class="brush: plain; title: ; notranslate">
select * from things where name = &quot;mongo&quot;
&gt; db.things.find({name: 'mongo'}).forEach(printjson);
select * from things where x = 4;
&gt; db.things.find({x:4}).forEach(printjson);
NOTE: that the _id field is always returned
</pre>
</li>
<li>allows returning only partial documents as well. for exam for name: &#8216;rajat&#8217; return only the key j
<pre class="brush: plain; title: ; notranslate">
	db.things.find({x:4}), {j:true}.foreach(printjson);
&gt; findOne() - syntactic sugar
	&gt;printjson(db.things.findOne({name: 'mongo'});
this is the same as
	&gt;find({name: 'mongo'}).limit(1);
&gt;printjson
function(x) {
	print(tojson(x));
}
</pre>
</li>
<li>mongo is full javascript shell, so any javascript function, syntax or class  can be used in the shell.besides it defines some of its own globals like (b etc). you can see the full api at. <a href="http://api.mongodb.org/js/">http://api.mongodb.org/js/</a></li>
<li>
<pre class="brush: plain; title: ; notranslate">
select * from users where age=33 order by name
db.users.find({age: 33}).sort({name: true});

select * from users where age&gt;33
db.users.find({'age': {$gt: 33}})
or $lt

select * from users where name like '%joe%';
db.users.find({name:/Joe/});
&quot;Joe%&quot; = {name:/^Joe/};
$lt = less than , $lte = less than equal to

sort order desc = .sort({name: -1});

create index myindexname on users(name);
db.users.ensureIndex({name: true});

create index myindex on users(name, ts desc)
db.users.ensureIndex({name:1, ts:-1});

select * from users where a=1 or b = 2
db.users.find({$or: [{a:1}, {b:2}]});

explain select * from users where z=2;
db.users.find({z:2}).explain();

select distinct last_name from users;
db.users.disctinct('last_name');

select count(*) from users;
db.users.count();

select count(age) from users;
db.users.find(age: {$exists: true}).count();
</pre>
</li>
<li>Commands:<br />
the mongo db has a concept of a database command as a way to perform special operations, or to request information about its current operational status.<br />
A command is sent to the database as a query to a special collection namespace called $cmd. The database will return a single document with the command results &#8211; user findOne(0 for that if your driver has it.<br />
the general syntax is:</p>
<pre class="brush: plain; title: ; notranslate">
db.$cmd.findOne({&lt;commandname&gt;: &lt;value&gt;[, options]});
the shell provides a helper function for this:
db.runCommand({&lt;commandname&gt;: &lt;value&gt;[, options]);
</pre>
<p>for example to check our database current&#8217; profile level eating<br />
privileged commands:</p>
<pre class="brush: plain; title: ; notranslate">
&gt; use admin
&gt; db.runCommand('shutdown');
</pre>
<p>getting help info for a command</p>
<pre class="brush: plain; title: ; notranslate">
&gt; db.commandHelp('datasize');
</pre>
</li>
<li>Clone Database
<pre class="brush: plain; title: ; notranslate">
// copy the entire database from one name to one server
db.copyDatabase(&lt;from-db&gt;, &lt;to-db&gt;, &lt;from-hostname&gt;);
</pre>
</li>
<li>Lock, Snapshot and unlock<br />
sync command supports a lock option that allows to sa fely snapshot the database datafiles. while locked, all write operations are blocked, although read operations are still allowed. after snapshotting, use the unlock command to unlock the database an allows locks again.</p>
<pre class="brush: plain; title: ; notranslate">
&gt; use admin
&gt; db.runCommand({sync: true, lock: 1});
unlock command:
db.$cmd.sys.unlock.findOne();
</pre>
<p>while the database can be read while locked for snapshoting, if a write is attempted, this will block readers due to the database&#8217;s use of read/write lock. (issues 1423);
</li>
<li>Index related commands:ensureIndex() is a helper function. its implementation creates an index by adding its into into the system.indexes collection
<pre class="brush: plain; title: ; notranslate">
&gt; use test
&gt; db.mycollection.ensureIndex(&lt;keypattern&gt;);
// same as
&gt; db.system.indexes.insert({name: 'name', ns: 'namespaceToIndex', key: &lt;keypatter&gt;});
</pre>
</li>
<li>you can query system.indexes to see all indexes for a collection foo in db test.
<pre class="brush: plain; title: ; notranslate">
&gt; db.system.indexes.find({ns: 'test.foo'});
</pre>
</li>
<li>dropping indexes
<pre class="brush: plain; title: ; notranslate">
db.mycollection.dropIndex(&lt;name_or_pattern&gt;);
db.mycollection.dropIndexes(); &lt;-- drops all the indexes
e.g.
t.dropIndex({name: true});
</pre>
</li>
<li>index namespace:<br />
each index has a namespace of its own for the btree bucket. the namespace is:<br />
&lt;collectionamespace&gt;.$&lt;indexname&gt;<br />
this is an internal namespace that cannot be queried directly.
</li>
<li>Last error commands:Since mongodb doesn&#8217;t wait for a response by default when writing to the database, a couple of commands exist for ensuring that these operations have succeeded. these commands can be invoked automatically with many of the drivers when saving and updating in the &#8216;safe&#8217; mode.
<pre class="brush: plain; title: ; notranslate">
db.$cmd.findOne({getlasterror:1});
or
db.runCommand('getlaterror');
or helper
db.getLastError();
</pre>
</li>
<li>
getlaterror is primarily useful for write operation (although it is set after a command or query to) write operations by default do not have a return code. this saves the client from waiting for client/server turnarounds during write operations. one can always call getlasterror if one wants to return a code.</li>
<li>
db.restError(); removes error that might have happened in the past, gets called before any comand is executed.</li>
<li>stats for a collection
<pre class="brush: plain; title: ; notranslate">
&gt; use comedy
&gt; db.cartoon.validate();
</pre>
<p>returns stats about the collection along with the number of records etc
</li>
<li>Mongo Metadata:<br />
The &lt;dbname&gt;.system.* namespace in mongoDB are special and contain database specific information. the systems include:</p>
<ul>
<li>system.namespcaes list all namespaces</li>
<li>system.indexes lists all indexes</li>
<li>system.profile stores database profiling information.</li>
<li>system.users lists users who may access the database</li>
<li>local.sources stores replica slave configuration data and state.</li>
<li>information on the structure of a stored object is stored within the object itself.</li>
</ul>
</li>
<li>
Collections:<br />
mongo collections are essentially named grouping of documents. you can think of them roughly equivalent to relational database tables. It is a collection of a BSON documents.<br />
- collection name should begin with letters and underscore. $ is reserved.<br />
the max size of a collection name is 128 char</li>
</ul>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/23/notes-on-mongodb-quickstart-guide-to-mongodb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PuppetConf 2011 &#8211; Architecting for the Cloud: AWS Cloud Formation and Puppet &#8211; Jinesh Varia</title>
		<link>http://blog.rajatpandit.com/2011/12/23/puppetconf-2011-architecting-for-the-cloud-aws-cloud-formation-and-puppet-jinesh-varia/</link>
		<comments>http://blog.rajatpandit.com/2011/12/23/puppetconf-2011-architecting-for-the-cloud-aws-cloud-formation-and-puppet-jinesh-varia/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 11:02:45 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=733</guid>
		<description><![CDATA[Excellent presentation, wish I had seen this before, For me slide 60 was pretty much the summary of the various cloud implementation routes, rest of it usually is just means...]]></description>
			<content:encoded><![CDATA[<p>Excellent presentation, wish I had seen this before, For me slide 60 was pretty much the summary of the various cloud implementation routes, rest of it usually is just means of getting to it. Best use of your next 45mins.</p>
<p><iframe width="560" height="315" src="http://www.youtube-nocookie.com/embed/xpsEKC0tTGk" frameborder="0" allowfullscreen></iframe></p>
<div style="width:425px" id="__ss_9398955"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/AmazonWebServices/aws-cloudformation-and-puppet-at-puppetconf-jinesh-varia" title="AWS CloudFormation and Puppet at PuppetConf - Jinesh Varia" target="_blank">AWS CloudFormation and Puppet at PuppetConf &#8211; Jinesh Varia</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9398955" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more presentations from <a href="http://www.slideshare.net/AmazonWebServices" target="_blank">Amazon Web Services</a> </div>
</p></div>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/23/puppetconf-2011-architecting-for-the-cloud-aws-cloud-formation-and-puppet-jinesh-varia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes on Puppet DSL</title>
		<link>http://blog.rajatpandit.com/2011/12/23/notes-on-puppet-dsl/</link>
		<comments>http://blog.rajatpandit.com/2011/12/23/notes-on-puppet-dsl/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 09:58:03 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Devops]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[infrastructure]]></category>
		<category><![CDATA[puppet]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=727</guid>
		<description><![CDATA[Every time I start writing some puppet code, I have to re-read the documentation to remind myself of the syntax. I have some notes of what I usually refer to...]]></description>
			<content:encoded><![CDATA[<p>Every time I start writing some puppet code, I have to re-read the documentation to remind myself of the syntax. I have some notes of what I usually refer to so that someone else who has a similar problem like me can refer to it.</p>
<pre class="brush: plain; title: ; notranslate">
Structure of a resource
user {'dave':
	ensure =&gt; present,
	uid =&gt; '507',
	gid =&gt; 'admin',
	home =&gt; '/home/admin',
	managehome =&gt; true,
}
# details about current resource instance
$ puppet resource user root
# reading up documentation about a resource type
$ puppet describe -s user

# resource declaration and application to test snippet
#/root/training-manifests/1.file.pp
file {'testfile':
	path =&gt; '/tmp/testfile',
	ensure =&gt; present,
	mode =&gt; 0640,
	content &gt; 'i am a test file',
}
#and call apply
$puppet apply 1.file.pp

# notify user
notify {&quot;this is a notice message&quot;}

# Controlling order of execution
file {'/tmp/test1':
	ensrue =&gt; present,
	content =&gt; 'hi',
}
notify {'/tmp/test1 ahs already been synced':
	require =&gt; File['/tmp/test1']
}

#but along from require there are:
#- before
#- require
#- notify
#- subscribe

# Chaining:
file {&quot;/tmp/test1&quot;:
	ensure =&gt; present,
	content =&gt; 'h1',
}
notify {'after':
	message =&gt; '/tmp/tesst1'
}
File['/tmp/test1'] -&gt; Notify['after']

ssh example:
# /root/learning-manifests/break_ssh.pp, again
file { '/etc/ssh/sshd_config':
	ensure =&gt; file,
	mode =&gt; 600,
	source =&gt; '/root/learning-manifests/sshd_config',
}
service { 'sshd':
	ensure =&gt; running,
	enable =&gt; true,
	hasrestart =&gt; true,
	hasstatus =&gt; true,
	# FYI, those last two attributes default to false, since
	# bad init scripts are more or less endemic.
	subscribe =&gt; File['/etc/ssh/sshd_config'],
}

# /root/learning-manifests/break_ssh.pp
package { 'openssh-server':
	ensure =&gt; present,
	before =&gt; File['/etc/ssh/sshd_config'],
}
file { '/etc/ssh/sshd_config':
	ensure =&gt; file,
	mode =&gt; 600,
	source =&gt; '/root/learning-manifests/sshd_config',
}
service { 'sshd':
	ensure =&gt; running,
	enable =&gt; true,
	hasrestart =&gt; true,
	hasstatus =&gt; true,
	subscribe =&gt; File['/etc/ssh/sshd_config'],
}

Variables:
$variables always start with a dollar sign
can hold strings, numbers, value like undef etc
fully qualified variables look like $scope::variable top level variables are the same, but their scope is nameless $::top_scope_variable
you can only assign a variable once in a given scope

if condition {
    block of code
} elsif condition {
    block of code
} else {
    block of code
}

if $is_virtual {
    service {'ntpd':
    ensure =&gt; stopped,
    enable =&gt; false,
  }
} else {
    service { 'ntpd':
    name =&gt; 'ntpd',
    ensure =&gt; running,
    enable =&gt; true,
    hasrestart =&gt; true,
    require =&gt; Package['ntp'],
  }
}

case $operatingsystem {
    centos: { $apache = &quot;httpd&quot; }
    # Note that these matches are case-insensitive.
        redhat: { $apache = &quot;httpd&quot; }
        debian: { $apache = &quot;apache2&quot; }
        ubuntu: { $apache = &quot;apache2&quot; }
        default: { fail(&quot;Unrecognized operating system for webserver&quot;)
    }
    # &quot;fail&quot; is a function. We'll get to those later.
}
package {'apache':
    name =&gt; $apache,
    ensure =&gt; latest,
}

Modules and Classes
class {'security_base': }
class {'webserver_base': }
class {'appserver': }

Classes are singleton collections of resources that puppet can apply as a unie. you can think of them as blocks of code that can be turned on or off. 

class ntp {
	package {'ntp':
		ensure =&gt; installed,
	}
}

But to use the class you need to define the class then declare it
class {'ntp': }

# puppet apply --verbose ntp-class.pp
there's there way to declare classes, but it behaves a little bit differently

include ntp
include ntp
include ntp

The include function will declare a classs if it hasn't already been declared, and will do nothing if it has. This means that we can use it safely multiple times, whereas the resource syntax can be used only once. The drawback is that include can't currently be used with parameterized classes, on which more later.

Module Structure:
{module}/
	files/
	lib/
	manifests/
		init.pp
		{class}.pp
		{defined type}.pp
		{namespace}/
			{class}.pp
			{class}.pp
		{templates}/
		{tests}/

- the main directory should be named after the module
- all of the manifests go in the manifests directory
- init.pp that holds the modules main class.
- modules are very useful as they allow for namespacing and grouping of classes

foo/
	manifests/
		init.pp
		bar.pp
		bar/
			baz.pp
init.pp would contain class foo {}
bar.pp would contain class foo::bar {}
baz.pp should contain class foo:bar::baz {}

puppet:///module/testing/test.txt
	will go in {puppet}/modules/{$module}/files

~/.bashrc file
mkmod() {
	mkdir &quot;$1&quot;
	mkdir &quot;$1/files&quot; &quot;$1/lib&quot; &quot;$1/manifests&quot; &quot;$1/templates&quot; &quot;$1/tests&quot;
}

rendering from a template:
file {'/etc/foo.conf':
	ensure =&gt; file,
	require =&gt; Package['foo'],
	content =&gt; template('foo/foo.conf.erb'),
}

if you pass more than one template then it will evaluate both of them and concat the output

template('foo/one.erb', 'foo/two.erb');

Parameterized classes:

class mysql($user, $port) {}
class paramclassexample($value, $value2 = 'default value') {
	notify {'value 1 is ${value1: }
}
</pre>
<p>More examples/details available here <a href="http://docs.puppetlabs.com/guides/language_guide.html">http://docs.puppetlabs.com/guides/language_guide.html</a></p>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/23/notes-on-puppet-dsl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a custom repository in RHEL 5.x</title>
		<link>http://blog.rajatpandit.com/2011/12/23/create-a-custom-repository-in-rhel-5-x/</link>
		<comments>http://blog.rajatpandit.com/2011/12/23/create-a-custom-repository-in-rhel-5-x/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 09:38:10 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Devops]]></category>
		<category><![CDATA[redhat]]></category>
		<category><![CDATA[repository]]></category>
		<category><![CDATA[rpm]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=723</guid>
		<description><![CDATA[Another note-to-self kind of post. Creating a custom repo on RedHat. Now adding this repo details to the repo-register. You can also serve the base url over http in which...]]></description>
			<content:encoded><![CDATA[<p>Another note-to-self kind of post. Creating a custom repo on RedHat.</p>
<pre class="brush: plain; title: ; notranslate">

[root@localhost ~]# yum install createrepo
[root@localhost ~]# mkdir -p /opt/acc/repo
[root@localhost ~]# createrepo /opt/acc/repo/

Saving Primary metadata
Saving file lists metadata
Saving other metadata

[root@localhost ~]# tree /opt/acc/repo/
/opt/acc/repo/
`-- repodata
    |-- filelists.xml.gz
    |-- other.xml.gz
    |-- primary.xml.gz
    `-- repomd.xml
</pre>
<p>Now adding this repo details to the repo-register.</p>
<pre class="brush: plain; title: ; notranslate">
[localrepo]
name=Fedora Core $releasever - My Local Repo
baseurl=file:///mnt/fc_local_repo/
enabled=1
gpgcheck=0
#gpgkey=file:///path/to/you/RPM-GPG-KEY
</pre>
<p>You can also serve the base url over http in which case the protocol would change from <code>file:///</code> to <code>http://</code> or <code>https:///</code></p>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/23/create-a-custom-repository-in-rhel-5-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up Trac, SVN and Agilo on RHEL 5.x</title>
		<link>http://blog.rajatpandit.com/2011/12/23/setting-up-trac-svn-and-agilo-on-rhel-5-x/</link>
		<comments>http://blog.rajatpandit.com/2011/12/23/setting-up-trac-svn-and-agilo-on-rhel-5-x/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 09:06:14 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Devops]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[agilo]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[trac]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=709</guid>
		<description><![CDATA[As part of yet another transformational project I am about to start from the very scratch. This time right from setting up the agile project management tools. I decided to...]]></description>
			<content:encoded><![CDATA[<p>As part of yet another transformational project I am about to start from the very scratch. This time right from setting up the agile project management tools. I decided to go with <a href="http://trac.edgewall.org">trac</a> (running <a href="http://www.agilofortrac.com/">agilo</a> on top of it) for the agile delivery, svn for code versioning. This combination works very well together because:</p>
<ul>
<li>You can have your product backlog, sprint backlog and tasks all in one place</li>
<li>Agilo manage your backlogs and provide fancy metrics of how your sprint is doing</li>
<li>SVN ties well into trac which means you can tie commits back into sprint tasks, which means you have a traceability matrix of the tasks/defects and the code changes made to close it</li>
<li>Trac also helps you manage a milestone so you can have a high-level view of how you are doing against your deadlines to meet a milestone</li>
</ul>
<p>You can read more about them here <a href="http://www.agilofortrac.com/en/features/">Agilo</a> and <a href="http://trac.edgewall.org/wiki/TracFeatures">Trac</a><br />
<a href="http://blog.rajatpandit.com/wp-content/uploads/2011/12/Agilo_for_Scrum_Open_Source_Scrum_Tool.jpg"><img src="http://blog.rajatpandit.com/wp-content/uploads/2011/12/Agilo_for_Scrum_Open_Source_Scrum_Tool-300x296.jpg" alt="" title="Agilo_for_Scrum_Open_Source_Scrum_Tool" width="300" height="296" class="alignleft size-medium wp-image-715" /></a><br />
You first need to enable repoforge for your RHEL install and then install the required packages</p>
<pre class="brush: plain; title: ; notranslate">
[root@localhost ~]# rpm -Uhv http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS//rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm
[root@localhost ~]# yum -y install subversion trac mod_dav_svn mod_python
</pre>
<p>Now you need to create the directories for svn repos, trac project and auth directory. I choose <code>/var/www/</code> but you can choose anything else you want.</p>
<pre class="brush: plain; title: ; notranslate">
[root@localhost ~]# mkdir -p /var/www/svn/svnrepos #holds the svn repos
[root@localhost ~]# mkdir -p /var/www/trac #trac base folder
[root@localhost ~]# mkdir -p /var/www/svn/auth #holds the htaccess files
[root@localhost ~]# htpasswd -c /var/www/svn/auth/svn.htpasswd svnuser
[root@localhost ~]# svnadmin create /var/www/svn/svnrepos/secret-project #create svn repo
</pre>
<p>Now create the initial svn folders/files in the repo</p>
<pre class="brush: plain; title: ; notranslate">
[root@localhost ~]# svn mkdir file:///var/www/svn/svnrepos/secret-project/branches  \
file:///var/www/svn/svnrepos/secret-project/tags  \
file:///var/www/svn/svnrepos/secret-project/trunk  \
-m 'creating directories for initial import'

Committed revision 1.
</pre>
<p>Now create your first trac project</p>
<pre class="brush: plain; title: ; notranslate">
[root@localhost ~]# trac-admin /var/www/trac/secret-project \
permission add tracuser TRAC_ADMIN
</pre>
<p>You will need then require to go the settings of trac to give it the svn repo patch and then using trac-admin to call resync.</p>
<pre class="brush: plain; title: ; notranslate">
[root@localhost ~]# trac-admin $ENV repository resync &quot;secret-project&quot;
</pre>
<p>You would also require a post commit hook to ensure that trac gets updated every time a new commit is made. There is plenty of information available on <a href="http://trac.edgewall.org/wiki/CommitTicketUpdater">http://trac.edgewall.org/wiki/CommitTicketUpdater</a>, but basically you need is an svn post commit hook which calls <code>trac-admin $ENV changeset added 'secret-project'</code>.</p>
<p>Installing Agilo can be done using a plugin. If you have <code>easy_install</code> installed even better. Just follow the instructions as follows</p>
<pre class="brush: plain; title: ; notranslate">
[root@localhost ~]# easy_install &lt;agilo&gt;.egg
[root@localhost ~]# cd /var/www/trac/britebill-holepunch/conf
[root@localhost conf]# trac-admin /var/www/trac/secret-project/ upgrade #upgrade trac post plugin install
Creating Product Backlog...
Creating Sprint Backlog...
Upgrade done.
[root@localhost conf]# trac-admin /var/www/trac/britebill-holepunch/ wiki upgrade #upgrade trac wiki as well
</pre>
<p><a href="http://blog.rajatpandit.com/wp-content/uploads/2011/12/screenshot_A_11.png"><img src="http://blog.rajatpandit.com/wp-content/uploads/2011/12/screenshot_A_11-300x179.png" alt="" title="screenshot_A_1" width="300" height="179" class="alignleft size-medium wp-image-713" /></a></p>
<p>Now you can use the web interface to configure the project even more, adding your backlogs, tickets etc. Agilo also allows you to import your backlog from an xls sheet which is great as most product managers are still stuck in the xls era and refuse to let it go.</p>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/23/setting-up-trac-svn-and-agilo-on-rhel-5-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making custom AMI and distributing it safely</title>
		<link>http://blog.rajatpandit.com/2011/12/22/making-custom-ami-and-distributing-it-safely/</link>
		<comments>http://blog.rajatpandit.com/2011/12/22/making-custom-ami-and-distributing-it-safely/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 14:24:01 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Devops]]></category>
		<category><![CDATA[AMI]]></category>
		<category><![CDATA[aws]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=697</guid>
		<description><![CDATA[There are many different ways of managing your infrastructure on aws right from bringing up stalk ec2 instances and customizing them using a configuration management system like puppet which take...]]></description>
			<content:encoded><![CDATA[<p>There are many different ways of managing your infrastructure on aws right from bringing up stalk ec2 instances and customizing them using a configuration management system like <a title="Puppet Labs" href="http://puppetlabs.org">puppet</a> which take a reasonable amount of time to come online to customizing your AMI fully in a ready-to-go state and saving that as AMI for future use. Also depending on the kind of customization required you can also have the entire application stack pre-configured on a EBS snapshot and attach that your ec2 instance and with a little bit of tweaks you could have a fully functional box up and running. Whichever approach you take based on your needs you would still need to build your AMIs. As mentioned in my previous post, there is nothing special in this post other than notes for myself(and anyone else) on how to create an AMI from an per-exsistant image and sharing it safely.</p>
<p>Note: This post assumes you are working on an ubuntu instance but the same rules applies for any other unix variant as long as you have the right tools installed. The method of installing the tools might vary based on the distribution available</p>
<p>You need to have the following available before you start:</p>
<ul>
<li>An EC2 public key (public part of the keypair) to access your instance</li>
<li>A X.509 cert and private key (<a href="http://blog.rajatpandit.com/2011/12/22/setting-up-local-environment-to-work-with-amazons-ec2-infrastructure/">see previous post for more details</a>)</li>
<li>Your aws access id/key and secret key</li>
<li>Packages ec2-api-tools and ec2-ami-tools installed in the customized ami</li>
</ul>
<p>In case you don&#8217;t have the ec2 installed, you need to enable the repos by uncommenting the following lines in <code>/etc/apt/sources.list</code></p>
<pre class="brush: plain; title: ; notranslate">
#deb http://gb.archive.ubuntu.com/ubuntu/ maverick multiverse
#deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick multiverse
#deb http://gb.archive.ubuntu.com/ubuntu/ maverick-updates multiverse
#deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick-updates multiverse
</pre>
<p>On the ec2 instance, run the following command to ensure that its fully updated and have the required packages installed. This assumes that the required customization have been done at this stage.</p>
<pre class="brush: plain; title: ; notranslate">
ubuntu@ip-20-56-39-198:~$ sudo apt-get update &amp;&amp; sudo apt-get install ec2-ami-tools ec2-api-tools
</pre>
<p>SCP you x.509 and private key to the ec2 instance at this stage and move it to <code>/mnt/certs</code> you would need to create the directory as its not already present.</p>
<pre class="brush: plain; title: ; notranslate">
rp@localhost$ scp -i ec2-keypair-key.pem aws-x509-cert.pem private-key.pem ubuntu@ec2-20-56-39-198.compute-1.amazonaws.com:~/
</pre>
<p>Just so that you know <code>/mnt</code> is a mounted block device which means that anything you put it in isn&#8217;t part of the AMI (unless of-course you explicitly ask for it). This is the reason why we would store the bundled image in the /mnt directory instead. You can also verify this by running <code>$ sudo fdisk -l</code> to see the list of all block devices and their partitions.</p>
<p>Before you start bundling your images there are a couple of things that would be worth looking into to ensure that your AMI is safe and you are not inadvertently giving anyone access to the ec2 instances that would be launched using the AMI.</p>
<ul>
<li>Disable password based logins for root (or for accounts in the admin group if using ubuntu). Modify <code>/etc/ssh/sshd_config</code>.
<pre class="brush: plain; title: ; notranslate">
#PermitRootLogin yes
PermitRootLogin without-password
</pre>
</li>
<li>Randomize the root password at boot time to ensure the password can&#8217;t be guessed (additional security following the previous point. A script in rc.local can do the trick</li>
<li>Remove ssh host key pairs to ensure new ones get generated for each instance of the AMI. Especially useful when using with puppet. Delete all <code>ssh_host_*</code> files in <code>/etc/ssh/<code>.</code></code></li>
<li>Disable sshd dns checks. This doesn&#8217;t make it any more safe, just ensures that even if the DNS isn&#8217;t working the ssh server can still let you connect. It would otherwise try and do a reverse lookup before establishing connection. Disabling it also speeds up the process of connecting.<br />
Modify <code><code>/etc/ssh/sshd_config<br />
</code></code>
<pre class="brush: plain; title: ; notranslate">
#UseDNS yes
UseDNS no
</pre>
</li>
<li>Remove all entries in the <code>~/.ssh/authorized_keys</code> and for other user accounts that were configured to work in that manner as well. This would ensure that the instances from the AMI don&#8217;t give access to users who had the orig. keypair when creating the customized AMI</li>
<li>Clear the following files <code>.bash_history</code>, <code>.viminfo</code> and any other files that store information about your current session of usage.</li>
<li>Remove passwords for all user accounts that are allowed login
<pre class="brush: plain; title: ; notranslate">
 ssh passwd -l
</pre>
</li>
<li>Modify sshd to allow only public key authentication, modify <code>/etc/ssh/sshd_config</code>
<pre class="brush: plain; title: ; notranslate">
PubKeyAuthentication yes
PasswordAuthentication no
</pre>
</li>
<li>Delete all shell history, system lot etc that might contain sensitive information</li>
</ul>
<p>To bundle the AMI, run the following command</p>
<pre class="brush: plain; title: ; notranslate">
$sudo ec2-bundle-vol -k /mnt/certs/private-key.pem \
 -c /mnt/certs/aws-x509-cert.pem \
 -u  \
 -d /mnt/instance-store/ \
 -r i386
</pre>
<p>You need to create a s3 bucket to store this for future use. Lets say that bucket is called <code>my-ami</code><br />
Now upload the bundle to the s3 bucket</p>
<pre class="brush: plain; title: ; notranslate">
$ ec2-upload-bundle -b my-ami \
  -m instance-store/image.manifest.xml \
  -a your-account-access-key \
  -s your-account-secret-key
  --region us-west-1
</pre>
<p>The <code>--region</code> is optional and is sometimes required if your bucket is in a different region.</p>
<p>and then the last part is to register the AMI, this process will give you an AMI id which you can then use to launch instances that are a copy of the AMI.</p>
<pre class="brush: plain; title: ; notranslate">
$ ec2-register my-ami/my-prefix.manifest.xml \
  --name my-ami \
  --description 'Describe the type of server here'  \
  -K  /mnt/certs/private-key.pem\
  -C /mnt/certs/aws-x509-cert.pem \
  -a i386
</pre>
<p>This command would return back an AMI id.</p>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/22/making-custom-ami-and-distributing-it-safely/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up local environment to work with Amazon&#8217;s EC2 Infrastructure</title>
		<link>http://blog.rajatpandit.com/2011/12/22/setting-up-local-environment-to-work-with-amazons-ec2-infrastructure/</link>
		<comments>http://blog.rajatpandit.com/2011/12/22/setting-up-local-environment-to-work-with-amazons-ec2-infrastructure/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 12:22:41 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Devops]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[IAM]]></category>
		<category><![CDATA[infrastructure]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=687</guid>
		<description><![CDATA[This post doesn&#8217;t contain anything that&#8217;s not available in the aws docs. Just this more like a note to self to remind me of the steps as everytime I have...]]></description>
			<content:encoded><![CDATA[<p>This post doesn&#8217;t contain anything that&#8217;s not available in the aws docs. Just this more like a note to self to remind me of the steps as everytime I have to setup an environment instead of digging in the documentation, I could use this a single point of information. Feel free to use it for yours a well.</p>
<ul>
<li>Create an account alias using IAM even if you are the only single user using the aws account. Helps scale out to bigger teams when you need to with better granular access controls. You can read more about it here <a href="http://aws.amazon.com/documentation/iam/">http://aws.amazon.com/documentation/iam/</a><a href="http://blog.rajatpandit.com/wp-content/uploads/2011/12/aws-account-lias.png"><img class="size-full wp-image-691 alignleft" style="margin: 10px;" title="aws-account-lias" src="http://blog.rajatpandit.com/wp-content/uploads/2011/12/aws-account-lias.png" alt="" width="444" height="166" /></a></li>
<li>The process of creating the user will generate Access Id, Secret and also the password that will be used to login to the new Alias url</li>
<li>Login via the newly created account on the account alias url and start a new project</li>
<li>IAM doesn&#8217;t create your x.509 certificates for you, so you would need to do that yourself and upload it</li>
<li>Use the following commands to generate a key for yourself
<pre class="brush: plain; title: ; notranslate">
$ openssl genrsa 1024 &gt; private-key.pem #generate private key
$ openssl req -new -key private-key.pem -out cert.pem #generate csr
$ openssl x509 -req -days 365 -in cert.pem -signkey private-key.pem -out project-cert.crt #generate the final certificate
</pre>
<p><a href="http://blog.rajatpandit.com/wp-content/uploads/2011/12/manage-signing-cert.png"><img class="alignleft  wp-image-692" style="margin: 10px;" title="manage-signing-cert" src="http://blog.rajatpandit.com/wp-content/uploads/2011/12/manage-signing-cert.png" alt="" width="491" height="290" /></a></p>
<p>From the definition in the documentation:</p>
<ul>
<li><strong>Access keys</strong>: symmetric key encryption. These are for making requests to AWS product REST or Query API. Can be obtained/regenerated from the access keys tab on the was security credentials page</li>
<li><strong>X.509 certificates</strong>: public key encryption. use x.509 certificates to make secure SOAP protocol requests to AWS service API. These are the credentials you will use when using the command-line ec2 API tools. can be obtained/regenerated from the x.509 certificates tab on the AWS Security credentials page.</li>
<li><strong>Key pairs</strong>: SSH key pairs when you create an intense amazon inserts the public key of your ssh key pairs into your new instance so that you can log in using your private key. you can add new ssh key-pairs though the AWS management console by clicking on Key Pairs.</li>
</ul>
</li>
<li>Upload the content of the crt in the popup that shows up when you click on &#8216;Managing Signing Certificates&#8217;. When finished it will give you a certificate id that can be used to reference certificates if you have more than one.</li>
<li>Update the <code>.bash_profile</code> with the new variables that the tools would use.
<pre class="brush: plain; title: ; notranslate">
export EC2_KEYPAIR=$HOME/.ec2/sa/sa-aws-keypair.pem #this is the keypair you generate/download
export EC2_PRIVATE_KEY=$HOME/.ec2/sa/private-key.pem #this is the private key used to generate the cert
export EC2_CERT=$HOME/.ec2/sa/aws-sa.crt #this is the cert you generated and uploaded
export JAVA_HOME=/usr/lib/jvm/java-6-sun
</pre>
<p>and then update your shell with the new shell variables</p>
<pre class="brush: plain; title: ; notranslate">
$source ~/.bash_profile
</pre>
</li>
<li>Obviously then you need to install the tools if you don&#8217;t have it installed already. In you are using ubuntu you need to enable some repositories. Edit <code>/etc/apt/sources.list</code> and uncomment the following lines:
<pre class="brush: plain; title: ; notranslate">
#deb http://gb.archive.ubuntu.com/ubuntu/ maverick multiverse
#deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick multiverse
#deb http://gb.archive.ubuntu.com/ubuntu/ maverick-updates multiverse
#deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick-updates multiverse
</pre>
<p>and then update and install</p>
<pre class="brush: plain; title: ; notranslate">
rp@supernova:~$ sudo apt-get update &amp;&amp; sudo apt-get install ec2-ami-tools ec2-api-tools
</pre>
</li>
<li>Now test the configuration
<pre class="brush: plain; title: ; notranslate">
$ ec2-describe-images -o amazon
</pre>
<p>if you see some results come back you are pretty much setup.</li>
</ul>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/22/setting-up-local-environment-to-work-with-amazons-ec2-infrastructure/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Automation for packaging websites</title>
		<link>http://blog.rajatpandit.com/2011/12/21/automation-for-packaging-websites/</link>
		<comments>http://blog.rajatpandit.com/2011/12/21/automation-for-packaging-websites/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 00:24:55 +0000</pubDate>
		<dc:creator>rp</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blog.rajatpandit.com/?p=678</guid>
		<description><![CDATA[For the ones who are following up my earlier blog post about packaging up website code, I had written about how you could also automate the process using phing/ant. I...]]></description>
			<content:encoded><![CDATA[<p>For the ones who are following up my earlier blog post about <a href="http://blog.rajatpandit.com/2011/12/19/packaging-up-websites-for-easy-deployment/">packaging up website code</a>, I had written about how you could also automate the process using phing/ant. I have committed a sample script up on github for anyone who is interested in looking at a sample implementation.</p>
<p>In order to use the phing script you would require to do the following:</p>
<ul>
<li>Clone/download the code from <code>git@github.com:rajatpandit/phing-website-packaging.git</code></li>
<li>Copy the <code>debian</code> folder across to your project</li>
<li>Tweak the files in there to match your projects requirements</li>
<li>The file names ending in .in are the template files that the phing script will take and modify before actually building the package for you</li>
<li>The phing script modifies the files based on two arguments that you provide <code>build.project</code> and <code>build.version</code></li>
<li>The other file you need to look out for for is the <code>install.in</code> which contains the &#8220;from&#8221; and &#8220;to&#8221; locations of the files which will get deployed when the package is installed</li>
<li>The other files would required to be tweaked accordingly</li>
<li>Once you are happy with the changes, copy the package.xml file at the same level as the <code>debian</code> folder and ensure that the required packages are installed (refer to my previous post to know about the names of the packages</li>
<li>Execute the phing script as follows e.g.
<pre class="brush: plain; title: ; notranslate">
$phing -f package.xml -Dbuild.version=1.0 -Dbuild.project=top-secret-project
</pre>
</li>
</ul>
<p>In addition to the basic targets, it also has some additional target to rebuild the meta-information about your local repo. In case you don&#8217;t need one or use one, feel free to take the targets out.</p>
<p>Any questions, suggestions recommendations etc, as always please leave a comment.</p>
<div id="in_post_ad_bottom_1" style="clear:both;margin:0;padding:0;"><div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-bp */
google_ad_slot = "7787511801";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="brp-bp-234">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-4254382394977039";
/* brp-234x60-BP-1 */
google_ad_slot = "9111022353";
google_ad_width = 234;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><div style='clear:both'></div>]]></content:encoded>
			<wfw:commentRss>http://blog.rajatpandit.com/2011/12/21/automation-for-packaging-websites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

