<?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>Server Cobra</title>
	<atom:link href="http://www.servercobra.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.servercobra.com</link>
	<description>Ubuntu, Servers, Python, and Django</description>
	<lastBuildDate>Thu, 02 May 2013 22:38:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Programming for Real Time: TriviaStats.com</title>
		<link>http://www.servercobra.com/programming-for-real-time-triviastats-com/</link>
		<comments>http://www.servercobra.com/programming-for-real-time-triviastats-com/#comments</comments>
		<pubDate>Tue, 23 Apr 2013 21:41:41 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Logging]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[TriviaStats]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=946</guid>
		<description><![CDATA[I recently deployed a website called TriviaStats.com for the world’s largest trivia contested. Each year, 90FM in Stevens Point (the UW-Stevens Point radio station) hosts an over the radio trivia contest. Teams listen to 8 questions an hour and call <a class="more-link" href="http://www.servercobra.com/programming-for-real-time-triviastats-com/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p dir="ltr">I recently deployed a website called <a href="http://TriviaStats.com">TriviaStats.com</a> for the world’s largest trivia contested. Each year, <a href="http://90fmtrivia.org">90FM in Stevens Point</a> (the UW-Stevens Point radio station) hosts an over the radio trivia contest. Teams listen to 8 questions an hour and call in answers for points. There are also other events for points, such as a driving scavenger hunt, a running scavenger hunt, and 1-2 second clips of songs that must be identified. There were 376 teams this year and tens of thousands of total players. Scores are posted on the website about 2 hours after the hour ends. So the scores for hour 2 get posted at the end of hour 4. The website isn’t very easy to use, and you have to constantly check to keep track of your scores. I thought I could make it much easier. I wrote my site to scrape the score page and save the scores for each hour. I then set up a form for people to register their email/phone number and team name. When new scores were scraped, it would notify them with their place and score. I also set up team pages that let you see all your scores for this and past years at a glance, rather than going through 50 pages to find the changes.</p>
<p dir="ltr">The main issue with writing a site like this is deal with scraping the score page. It changes minorly every year, and the scraping must be changed to meet it. Since this is a real time event, with players hungry to find out their scores, it is a bit hard to fully test and be ready for all the curveballs. Last year the site didn’t work, and I gave up after a couple hours. It is very hard to play the trivia contest, program, and drink all at the same time! Here are the things I think made this year a success and things that could have been done better:</p>
<h3 dir="ltr">Logging!</h3>
<p dir="ltr">I would have had a much harder time diagnosing and fixing the site if I wasn’t using a lot of logging and Sentry. Sentry is a server that you can send all your logs to and easily sort and view the messages via a web page. I was able to notice issues much faster and deal with them much more easily because of Sentry. Also, seeing minor errors popping up is reassuring. It is much more likely I made a small mistake somewhere than I made no mistakes anywhere and there are no error logs being generated. Even just shooting off an info logging message is reassuring.</p>
<h3 dir="ltr">Test like the event is happening</h3>
<p dir="ltr">Your tests should mirror the entire event, not just points in the event. For example, a lot of my testing focused on getting past years data, where all scores were available. The testing should have been in stages, like “only hour 1 posted”, “hours 1 and 2 posted”, “hours 1 and 3 posted, 2 is missing”, etc.</p>
<h3>Things are going to go wrong</h3>
<p dir="ltr">In recent years, 90FM created a new page with something like “resultsXX.html”, where XX was the hour number. This year, they only had a results.html with all the scores that got changed each hour. That means there will be no archival like past years, which allowed me to get past years if there was a problem. I made an assumption that I could use the XX in the page name to figure out which hour was posted. That was easier than parsing “RESULTS FOR HOUR XX” at the top of the page. Once the first scores got posted, I realized my mistake, and fixed it in a few minutes. I’m very happy it was an easy fix, or I could have lost an hour worth of scores!</p>
<h3 dir="ltr">You made a mistake somewhere</h3>
<p dir="ltr">The assumption above lead me to an edge case that I had properly tested. Because I had to change how the numbering worked, it messed up which hours were getting emailed out as scores got posted. When hour 1 was up, it emailed out hour 1. When hour 2 was up, it still emailed out hour 1. Same for hour 3, which is when I realized and started fixing it. Once you start getting curveballs thrown at you, all those little bugs in your code are going to be much more apparent. Proper testing that really keys in on edge cases will help avoid this, but you never know when something is going to go horribly wrong.</p>
<h3 dir="ltr">Replay</h3>
<p dir="ltr">If you hit an unexpected issue in your code, everything could break. For example, if there was a problem while notifying players that I didn’t catch, all subsequent notifications will be lost. I could go delete all the scores for that hour, re-scrape them, and then hope notifications don’t fail again. However, that isn’t elegant. Having checkpoints in your code where you can replay an event as if it just happened makes life much easier after you fix the issue. A smart way to do this would be saving a small log object to the database, representing a successful notification, or adding a field to each subscriber for “last hour notified”. Another option is adding a command to re-send notifications for a certain team/hour combo. I went for the even easier version: resend all notifications. My thought was that it was more likely that the whole thing would break rather than just sometimes breaking for certain users. I created a Django management command for notifications and a debugging flag to test the notifications before actually sending them. In the end, it worked fairly well. A few people missed the first few hours because they put in the wrong team name, so they got no notification (which I manually corrected).</p>
<p dir="ltr">Another possible replay would have been downloading the page and running the scraper against that. If there was an issue, I’d at least have the page still around. If something had gone totally wrong and I didn’t fix it before the next hour went up, I could have lost those scores forever.</p>
<h3 dir="ltr">Conclusion</h3>
<p dir="ltr">Overall, TriviaStats.com has 477 unique visitors (with 376 total teams) and over 15k page view during the contest. A lot of people were very interested and appreciative. Needless to say, I’m excited to improve it for next year.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/programming-for-real-time-triviastats-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Changes To Cellphone Unlocking</title>
		<link>http://www.servercobra.com/changes-to-cellphone-unlocking/</link>
		<comments>http://www.servercobra.com/changes-to-cellphone-unlocking/#comments</comments>
		<pubDate>Sat, 26 Jan 2013 20:07:29 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=933</guid>
		<description><![CDATA[The Library of Congress and U.S. Copyright Office recently decided that unlocking your phone is will now be against the law. Previous to this decision, it was legal under the Digital Millenium Copyright Act to unlock a phone so that <a class="more-link" href="http://www.servercobra.com/changes-to-cellphone-unlocking/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>The Library of Congress and U.S. Copyright Office recently decided that unlocking your phone is will now be against the law. Previous to this decision, it was legal under the Digital Millenium Copyright Act to unlock a phone so that it could be moved to a different cell phone business, such as from T-Mobile to AT&#038;T. This was great for consumers, because once a consumer’s contract was up, or they paid their early termination fee, they could move to a new company. It was bad for businesses, because people could switch to a new company without buying a new phone, which is often very costly. <span id="more-933"></span></p>
<p>If you do unlock your phone, you may face a civil suit from your cell phone provider. It is also possible to face a criminal suit if you unlock phones for commercial gain, such as setting up a company to unlock phones. If you, as a company, do find yourself in a civil or criminal suit, you will find <a href="http://allisonspinner.net">Ms. Allison B. Spinner </a> to be helpful. A civil suit could cost you up to $2500. A criminal suit carries a potential of a $500,000 fine, and possibly prison time. </p>
<p>Some companies have been defending this practice, because they subsidize the cost of expensive cell phones with a slightly higher bill. This is a bad argument at best. The cell phone companies will charge you the same amount whether you are have a subsidized phone or not. This means people who bring their own phone (such as phones that were sold unlocked) are still paying extra for nonexistent subsidies. Also, if you leave the company early, you will be hit with an early termination fee. This fee is to pay back the company for the subsidies you didn’t pay over your contract. If you go past your contract and don’t get a new one, you’ll pay the same fee, meaning you continue paying the subsidy rate, even though you already paid off the phone. </p>
<p>The Electronic Frontier Foundation (EFF) does not agree with the ruling. It is possible they will be challenging the result in court. They have previously challenged many other rulings that do not promote software and hardware freedom, patent disputes, and a whole host of other things.</p>
<p>Even when this ruling takes effect, some manufacturers will sell unlocked phones. However, they will be very expensive and you will still have to pay the subsidy built into most contracts. An unlocked iPhone 5, for example, is $649.</p>
<p>The ruling will be revisited in 2015, hopefully with a more consumer-friendly decision.</p>
<p>To find out more, please contact <a href="http://www.lookuppage.com/users/allisonspinner/">Ms. Allison B. Spinner </a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/changes-to-cellphone-unlocking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Performance Tuning</title>
		<link>http://www.servercobra.com/django-performance-tuning/</link>
		<comments>http://www.servercobra.com/django-performance-tuning/#comments</comments>
		<pubDate>Mon, 10 Dec 2012 01:19:11 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=917</guid>
		<description><![CDATA[After one of my latest updates to SwoopSrch.com, all the sudden requests were taking up to 11 seconds. Swoop works by making a set of all the apartments that meet at least one criteria the user types in (usually thousands), <a class="more-link" href="http://www.servercobra.com/django-performance-tuning/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>After one of my latest updates to <a href="http://swoopsrch.com">SwoopSrch.com</a>, all the sudden requests were taking up to 11 seconds. Swoop works by making a set of all the apartments that meet at least one criteria the user types in (usually thousands), applying a weighting algorithm, sorting them, and returning the top 100 values for display. Through some performance tuning, I was able to get the requests down to about 1 second on average by applying some simple techniques.</p>
<h3>Profile, Profile, Profile</h3>
<p>Your app is slow. But why? Which functions? Is a function getting called too many times? Is one function way too slow? You won&#8217;t know until you profile it. In your views.py, you can add a profile decorator that will print out all your queries and a lot of data about functions (how many times they are called, cumulative time taken, time per call, module/line number, etc). Look for the highest cumulative time, ones being called more than the length of your QuerySets, etc. Also check that you aren&#8217;t making too many queries to your database. I currently make about 7 after optimization. I could get this down to about 3 with some clever reworking, but none of the calls take very much time (less than 0.001 seconds), so I left them as they are. At one point, it was making over 1000. That is a problem.</p>
<p>To install and use Django Profiler and start profiling views:</p>
<pre class="brush: python; title: ; notranslate">
pip install django-profiler

# In views.py
from profiling import profile, Profiler

# On top of the view
@profile(stats=True)
</pre>
<p>If you just want to see your queries, Django gives you an easier way to check them.</p>
<pre class="brush: python; title: ; notranslate">
from django.db import connection
from django.conf import settings

if settings.DEBUG == True:
    print connection.queries
</pre>
<p>You can also print the .query attribute of any QuerySet to see what queries created it.</p>
<h3>Use Querysets Effectively</h3>
<p>You need to understand when Querysets are executed. For example, intersecting QuerySets with the &#8216;|&#8217; operator does not execute a search, but accessing the values does. If you then add more filters later, you&#8217;ll execute another search. Organizing your data flow is hugely important. To get a better understanding, read When <a href="https://docs.djangoproject.com/en/1.1/ref/models/querysets/#when-querysets-are-evaluated">QuerySets Are Evaluated</a> and <a href="https://docs.djangoproject.com/en/1.1/topics/db/optimization/">Database Access Optimization</a> in the Django documentation. A big one is using ManyToMany fields properly. If used improperly, you can get thousands of database calls, and horrifying performance. Reconfiguring our database to not require access to ManyToMany fields for normal queries shaved off about 5 seconds on its own. That was kind of shocking.</p>
<h3>model_to_dict() or values()?</h3>
<p>In my case, I needed all 100 of the Apartment objects to be a dictionary before passing them back to the frontend as JSON. At first, I tried using model_to_dict() on the complete object just before returning them. At first, I was converting all of the objects to dicts with model_to_dict(), but that was causing about a 0.3 second slow down. Even after moving it, I was still getting a slow down of about 1/10 of that, which isn&#8217;t unbearable. Instead, I switched to calling <a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.values">.values()</a> at the end of my query.</p>
<p>You need to be careful with this. If you have model functions, they will be unavailable after you run .values(). For Swoop, Apartment objects have a .address() function, combining the various address parts (house number, street, etc) into a standard looking address for display. I moved this function into a utility function, and experienced no more slow downs. Good.</p>
<h3>Defer When Possible</h3>
<p>Using <a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.defer">defer()</a> is great if you have fields that are very large or ManyToMany fields, you can defer them from getting retreived from the database by listing them in defer() at the end of your query. A subtle note is that the Django ORM tries to fill up its QuerySet cache, and part of that is using <a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related">select_related()</a>. select_related() prevents you from needing to hit the database again if you follow a ForeignKey, but if you have too many objects, this can massively slow down your queries. This accounted for about half of the time.</p>
<p>As a user on reddit pointed out, you can also use <a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.only">only()</a> if you only need a couple columns. Instead of excluding columns listed in defer, it only grabs the ones you specify. In my case, there were about 12 columns I need for every object, so defer made more sense. Your mileage may vary.</p>
<h3>Decimals Are Slow</h3>
<p>I originally stored the number of beds and baths as a DecimalField in the database. When pulling them out of the database, they have to be converted by the decimal module. According to <a href="http://stackoverflow.com/questions/195116/python-decimal">this StackOverflow article</a>, decimal is about 100 times slower than the float builtin. I changed the fields in models.py to FloatFields, and issued an alter table to the database, &#8220;alter table TABLE modify COLUMN double precision;&#8221;. If you need Decimals, you can instead try to defer out those fields when not needed. A minor change, but it saved about 0.2 seconds. Nice.</p>
<h3>Dates Are Slow</h3>
<p>Running a datetime conversion when bringing objects out of a database is slow when run a couple thousand times. Our database keeps track of when apartments are available for rent (sometimes needed for searches), when they were added to the database, and the last time they were updated (to prioritize updates). The added and updated fields never need to be shown to a user, so they are automatically added to the defer list. If the available date isn&#8217;t required, it is also deferred. This saved around 0.1 second again. Yay!</p>
<h3>Trim The Queryset Before Doing Expensive Operations</h3>
<p>Some of our semi-expensive operations, include some map preprocessing and other backend preprocessing, were being applied before we trimmed down the Queryset. Simply moving the trimming to 100 to much earlier saved about 0.1 second. Awesome.</p>
<h3>Slower Production vs Dev</h3>
<p>We are running on Amazon servers, with our MySQL database on a separate server than our app servers. In development, we use sqlite3 for our database, and it is local. Also, the Amazon servers use slower, using 2007 Opterons, where my laptop has a quad core Ivy Bridge. Obviously, everything is going to act much faster on my laptop, and this initially lulled me into believing the app would perform much better when deployed. This is very hard to account for, but that is why you use development and staging servers that mirror your production environment as close as possible.</p>
<h3>Caching</h3>
<p>One thing I have not implemented yet is a Memcache server. From what I read, it is great for improving performance, but since Swoop uses a custom weighting system for each search, I don&#8217;t know that many queries will be improved. Your app might be different, and Memcache might be the first place to look for performance increases.</p>
<p>I hope these tips help you improve your app. This is not an exhaustive list by any means. If you have more tips, add them in the comments and I&#8217;ll add them to the main article. Also, if you have any corrections, please note them in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/django-performance-tuning/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using Git to Manage Server Configuration</title>
		<link>http://www.servercobra.com/using-git-to-manage-server-configuration/</link>
		<comments>http://www.servercobra.com/using-git-to-manage-server-configuration/#comments</comments>
		<pubDate>Tue, 04 Sep 2012 18:02:41 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=905</guid>
		<description><![CDATA[All servers should have their configuration saved into version control somewhere. Many people use Puppet or Chef to manage their configuration. That is a little more power than I need for a few home servers, so I use git. I&#8217;m <a class="more-link" href="http://www.servercobra.com/using-git-to-manage-server-configuration/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>All servers should have their configuration saved into version control somewhere. Many people use Puppet or Chef to manage their configuration. That is a little more power than I need for a few home servers, so I use git. I&#8217;m very familiar with it, and it works great. If I make a change and it breaks something, I can just rollback the changes to a known working state. This article outlines a basic way to host your configuration files on BitBucket, which provides unlimited free, private repositories. You could also host them on your own server, but this was much easier for me. I create one repository per server (or set of servers).<br />
<span id="more-905"></span><br />
To follow this article, <a href="https://bitbucket.org/account/signup">please sign up for a BitBucket account</a> and create a repository.</p>
<p>First, we need to create SSH keys to save to BitBucket for authentication. You can skip the second line if you already created SSH keys.</p>
<pre class="brush: bash; title: ; notranslate">
sudo su
ssh-keygen -t rsa
# Copy this output to BitBucket as a new SSH key
cat ~/.ssh/id_rsa.pub
</pre>
<p>Now we need to install git, and create a folder to save all our configurations in. We&#8217;ll do this by symlinking the files we&#8217;re using to a folder as root.</p>
<pre class="brush: bash; title: ; notranslate">
sudo apt-get install git-core
mkdir ~/git
cd ~/git
git init
# Create an account and repository at BitBucket, sub in your own username/repo name
git remote add origin ssh://git@bitbucket.org/USERNAME/REPO.git
</pre>
<p>Now that we have the repository set up, let&#8217;s add our first file. I&#8217;m going to add my NFS exports file. You&#8217;ll need to do this for each file. You can commit separately, or symlink all the files then do the commits at the end.</p>
<pre class="brush: bash; title: ; notranslate">
# Repository is set up. Now let's add some stuff and commit it.
mkdir ~/git/etc
# Symlink
ln -s /etc/exports etc/exports
# Add everything
git add -A
# Commit with a commit message
git commit -am &quot;Adding NFS exports&quot;
# Push the master branch to the origin server (BitBucket)
git push origin master
</pre>
<p>Finally, to help myself remember to commit, I am adding a reminder to my bashrc. Every time I log in as root, I will receive a message if there are uncommited files my git directory.</p>
<pre class="brush: bash; title: ; notranslate">
nano ~/.bashrc
-----
# Add this to the end of the file
# Check git status
cd /root/git
DIRTY=$(git status --porcelain 2&gt;/dev/null| grep &quot;^??&quot; | wc -l)
if [ $DIRTY != 0 ]; then
        echo -e '\E[47;31m'&quot;&#92;&#48;33[1mGit changes in /root/git need to be commited.&#92;&#48;33[0m&quot;
fi
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/using-git-to-manage-server-configuration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Standard Python Project .gitignore</title>
		<link>http://www.servercobra.com/standard-python-project-gitignore/</link>
		<comments>http://www.servercobra.com/standard-python-project-gitignore/#comments</comments>
		<pubDate>Sun, 15 Jul 2012 05:07:52 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=890</guid>
		<description><![CDATA[I write a lot of Python projects and store them all in Git version control. Each time, I find myself rewriting the .gitignore file, so my repositories aren&#8217;t cluttered with .pyc files, temporary files, files from pip/virtualenv, and others. So <a class="more-link" href="http://www.servercobra.com/standard-python-project-gitignore/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I write a lot of Python projects and store them all in Git version control. Each time, I find myself rewriting the .gitignore file, so my repositories aren&#8217;t cluttered with .pyc files, temporary files, files from pip/virtualenv, and others. So here is my current base .gitignore, partly so it can help you, the reader, and partly so I know where it is. I&#8217;ll update it as I find other troublesome files. What do your .gitignores look like?</p>
<pre class="brush: bash; title: ; notranslate">
# Python compiled files
*.py[co1]

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox

#Translations
*.mo

#Mr Developer
.mr.developer.cfg

# Logging
*output.log

#Kate editor
*kate-swp*

#Ubuntu One (if also stored for syncing)
*u1conflict*

#Mercurial
*/.hg/

#Additional editor
*~
*.save
</pre>
<p>Post your .gitignore additions in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/standard-python-project-gitignore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu LXC Port Forwarding</title>
		<link>http://www.servercobra.com/ubuntu-lxc-port-forwarding/</link>
		<comments>http://www.servercobra.com/ubuntu-lxc-port-forwarding/#comments</comments>
		<pubDate>Fri, 29 Jun 2012 01:37:34 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[LXC]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=887</guid>
		<description><![CDATA[So you have a service running in an LXC container behind a bridge, and you need ports forwarded for that service. In this case, we&#8217;ll use Minecraft as an example, which runs on port 25565. Our container&#8217;s IP is 10.0.3.116.]]></description>
				<content:encoded><![CDATA[<p>So you have a service running in an LXC container behind a bridge, and you need ports forwarded for that service. In this case, we&#8217;ll use Minecraft as an example, which runs on port 25565. Our container&#8217;s IP is 10.0.3.116.</p>
<pre class="brush: bash; title: ; notranslate">
sudo iptables -t nat -I PREROUTING -p tcp -d $PUBLICIP --dport 25565 -j DNAT --to 10.0.3.116:25565
sudo iptables -A FORWARD -p tcp -d 10.0.3.116 --dport 25565 -j ACCEPT
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/ubuntu-lxc-port-forwarding/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ubuntu LXC and UFW</title>
		<link>http://www.servercobra.com/ubuntu-lxc-and-ufw/</link>
		<comments>http://www.servercobra.com/ubuntu-lxc-and-ufw/#comments</comments>
		<pubDate>Thu, 28 Jun 2012 23:00:25 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[LXC]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[UFW]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=885</guid>
		<description><![CDATA[I am working on setting up my own cloud servers using Linux Containers (LXC). These cloud containers allow me to build one image, replicated it, configure it, and have a new server online in seconds. I was having trouble getting <a class="more-link" href="http://www.servercobra.com/ubuntu-lxc-and-ufw/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I am working on setting up my own cloud servers using Linux Containers (LXC). These cloud containers allow me to build one image, replicated it, configure it, and have a new server online in seconds. </p>
<p>I was having trouble getting access to the Internet from containers whenever I enabled UFW on the host machine. I tried a thousand different rules, but none worked. After much digging, I found the solution. UFW defaults to dropping forwarded packets. All my containers interact with the Internet via forwarding over a bridge (lxcbr0 in 12.04), so this is a big problem. Basically, with UFW enabled, the LXC containers could not talk to the internet. To solve the problem:</p>
<pre class="brush: bash; title: ; notranslate">
sudo nano /etc/default/ufw
----
# Change:
# DEFAULT_FORWARD_POLICY=&quot;DROP&quot;
# to
DEFAULT_FORWARD_POLICY=&quot;ACCEPT&quot;
</pre>
<p>Once I changed the rules, I just reload UFW, and all was well.</p>
<pre class="brush: bash; title: ; notranslate">
ufw reload
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/ubuntu-lxc-and-ufw/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Automated Load Balancing with Amazon EC2 and RightScale</title>
		<link>http://www.servercobra.com/automated-load-balancing-with-amazon-ec2-and-rightscale/</link>
		<comments>http://www.servercobra.com/automated-load-balancing-with-amazon-ec2-and-rightscale/#comments</comments>
		<pubDate>Sun, 29 Apr 2012 06:49:25 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[BASH]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[EC2]]></category>
		<category><![CDATA[RightScale]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=877</guid>
		<description><![CDATA[If you have a scalable infrastructure on Amazon, you are probably using Elastic Load Balancers on Amazon&#8217;s AWS to manage mulitple EC2 instances. Scaling by hand is soooooo last decade! We have added 3 scripts to our servers to allow <a class="more-link" href="http://www.servercobra.com/automated-load-balancing-with-amazon-ec2-and-rightscale/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>If you have a scalable infrastructure on Amazon, you are probably using Elastic Load Balancers on Amazon&#8217;s AWS to manage mulitple EC2 instances. Scaling by hand is soooooo last decade! We have added 3 scripts to our servers to allow them to add themselves and remove themselves our load balancer. These machines are usually web servers or other application servers. You can use RightScale to manage the expansion with auto scaling, or you can have a custom server monitoring your cluster&#8217;s load. With these boot and decommission scripts, the servers will automatically add and take themselves out of the cluster when they are told to start/stop.<span id="more-877"></span></p>
<p>The first Rightscript installs the Amazon EC2 API tools and passes all your credentials into the AMI through RightScale&#8217;s platform. You can fill in the inputs on a server by simply selecting the drop down next to them, selecting &#8220;Cred&#8221; and then changing the next drop down to match the label for that input. For example, match &#8220;AWS_ACCESS_KEY_ID&#8221; with &#8220;AWS_ACCESS_KEY_ID&#8221;. This script was originally from the RightScale documentation. This script should be assigned as a boot script to your server template as the 2nd to last script (with the ELB Registration script as the last).</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
# installs ec2inst script that allows running ec2commands from the shell

echo &quot;$AWS_X509_CERT&quot; &gt; /root/cert.pem
echo &quot;$AWS_X509_KEY&quot; &gt; /root/key.pem

echo 'export AWS_ACCESS_KEY_ID='$AWS_ACCESS_KEY_ID &gt; /root/ec2inst
echo 'export AWS_SECRET_ACCESS_KEY='$AWS_SECRET_ACCESS_KEY &gt;&gt; /root/ec2inst
echo 'export AWS_ACCOUNT_NUMBER='$AWS_ACCOUNT_NUMBER &gt;&gt; /root/ec2inst
echo 'export EC2_CERT=/root/cert.pem' &gt;&gt; /root/ec2inst
echo 'export EC2_PRIVATE_KEY=/root/key.pem' &gt;&gt; /root/ec2inst
echo 'export EC2_HOME=/root/ec2' &gt;&gt; /root/ec2inst
echo 'export JAVA_HOME=/usr/java/default' &gt;&gt; /root/ec2inst

chmod 700 /root/ec2inst

cd /root
wget http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip
unzip ec2-api-tools.zip
chmod +x ec2-api-tools-1.3-46266/bin/*
ln -s ec2-api-tools-1.3-46266 ec2 
</pre>
<p>The next script should be assigned as a boot script for your server template as the last script. It need to have the previous script run before it can run. It installs the AWS ELB API tools, saves the pertinent data to files for the decommission script, and then notifies the ELB there is a new instance available. Its sole input is the name of the Elastic Load Balancer you want it assigned to.</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
echo &quot;Beginning ELB Registration for load balancer $LOAD_BALANCER.&quot;
source /root/ec2inst
export EC2_INSTANCE_ID=&quot;$( wget -q -O - http://169.254.169.254/latest/meta-data/instance-id )&quot;

wget -O /root/ElasticLoadBalancing.zip http://ec2-downloads.s3.amazonaws.com/ElasticLoadBalancing.zip
unzip -o /root/ElasticLoadBalancing.zip -d /root
export AWS_ELB_HOME=~/ElasticLoadBalancing-1.0.15.1
echo 'export EC2_INSTANCE_ID='$EC2_INSTANCE_ID &gt; /root/ec2elb
echo 'export AWS_ELB_HOME='$AWS_ELB_HOME &gt;&gt; /root/ec2elb

$AWS_ELB_HOME/bin/elb-register-instances-with-lb $LOAD_BALANCER --instances $EC2_INSTANCE_ID
echo &quot;ELB Registration for load balancer $LOAD_BALANCER finished with exit code $?&quot;
</pre>
<p>The final script should be added as one of the first decommission scripts in your server template. It will notify the load balancer to stop sending requests to this instance. Its sole input is the name of the Elastic Load Balancer you want it assigned to.</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
echo &quot;Starting ELB Deregistering.&quot;
source /root/ec2inst
source /root/ec2elb

$AWS_ELB_HOME/bin/elb-deregister-instances-from-lb $LOAD_BALANCER --instance $EC2_INSTANCE_ID
echo &quot;ELB Deregistration finished with exit code $?&quot;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/automated-load-balancing-with-amazon-ec2-and-rightscale/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Dictionary-Based Logging Outside Django</title>
		<link>http://www.servercobra.com/using-dictionary-based-logging-outside-django/</link>
		<comments>http://www.servercobra.com/using-dictionary-based-logging-outside-django/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 19:40:05 +0000</pubDate>
		<dc:creator>Josh Gachnang</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=867</guid>
		<description><![CDATA[If you haven&#8217;t checked out Django&#8217;s logging facilities, do check them out. They are invaluable! One place the Django test server fails at is passing print statements to the console. Most production servers aren&#8217;t going to make print output available <a class="more-link" href="http://www.servercobra.com/using-dictionary-based-logging-outside-django/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>If you haven&#8217;t checked out <a href="https://docs.djangoproject.com/en/dev/topics/logging/">Django&#8217;s logging facilities</a>, do check them out. They are invaluable! One place the Django test server fails at is passing print statements to the console. Most production servers aren&#8217;t going to make print output available (or readily available), and too much debugging code relies on print statements, instead of logging. You can get the same effect as a print statement, along with logging to a file, pretty easily.<span id="more-867"></span></p>
<p>However, when you&#8217;re writing code outside of Django, or code that is portable outside of Django (like some of my utility scripts), you need these same abilities without the Django settings file. DictConfig allows you to use Django-style logging, outside Django, but it was only introduced in Python 2.7. Many servers are still on Python 2.6. Luckily, you can just drop one extra file into your directory, and you&#8217;re good to go!</p>
<p>First, <a href="https://bitbucket.org/vinay.sajip/dictconfig/src/53b3c32dea46/src/dictconfig.py">download dictconfig.py</a>. Put it into your project directory or somewhere on your path.</p>
<p>Next, we&#8217;ll configure a logger. We&#8217;re going to have it capture all message levels, and log them to both the console and a file in our directory. This is the best combination and makes migrating to a production server much easier.</p>
<pre class="brush: python; title: ; notranslate">
import os
import logging
import dictconfig

# PROJECT_ROOT is the folder you'll be logging to.
PROJECT_ROOT='/home/josh/programming/project/'

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {

        'file_log': {                 # define and name a second handler
            'level': 'DEBUG',
            'class': 'logging.FileHandler', # set the logging class to log to a file
            'formatter': 'verbose',         # define the formatter to associate
            'filename': os.path.join(PROJECT_ROOT, 'output.log')  # log file
        },
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
            'formatter': 'simple'
        },
    },
    'loggers': {
        'logger': {               # define another logger
            'handlers': ['file_log', 'console'],  # associate a different handler
            'level': 'DEBUG',                 # specify the logging level
            'propagate': True,
        },
    }
}

dictconfig.dictConfig(LOGGING)
</pre>
<p>Now when we want to log something, instead of &#8220;print &#8216;Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.&#8217;&#8221;, we just do:</p>
<pre class="brush: python; title: ; notranslate">
logging.critical('Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.')
logging.error('Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.')
logging.warning('Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.')
logging.info('Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.')
logging.debug('Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.')
# Only within an exception handler:
logging.exception('Fire, exclamation mark. Fire, exclamation mark. Help me, exclamation mark.')

</pre>
<p>There you go! Logging is easy!<br />
Note: The Fire quote is from The IT Crowd, a hilarious TV show that you should definitely check out. It is on Netflix!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/using-dictionary-based-logging-outside-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3D Apps for Tablets</title>
		<link>http://www.servercobra.com/3d-apps-for-tablet/</link>
		<comments>http://www.servercobra.com/3d-apps-for-tablet/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 17:11:53 +0000</pubDate>
		<dc:creator>GuestPost</dc:creator>
				<category><![CDATA[Articles]]></category>

		<guid isPermaLink="false">http://www.servercobra.com/?p=850</guid>
		<description><![CDATA[With larger screens and more powerful graphics processors, tablet computers have taken the industry by storm. No longer is Apple the only contender. Manufacturers have stepped up, creating multiple Android tablets, even apps with BlackBerry have entered the market with <a class="more-link" href="http://www.servercobra.com/3d-apps-for-tablet/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>With larger screens and more powerful graphics processors, tablet computers have taken the industry by storm. No longer is Apple the only contender. Manufacturers have stepped up, creating multiple Android tablets, even <a href="http://us.blackberry.com/apps-software/appworld/">apps with BlackBerry</a> have entered the market with its Playbook tablet. The <a href="http://developer.android.com/sdk/android-3.0-highlights.html#graphics">advances in technology</a> enables tablets to display even high-definition 3D graphics without lagging. Software developers are eager to take advantage of this new market with some cool apps.<span id="more-850"></span><br />
For instance, WMB 3D is a digital magazine that is photographed and designed in 3D. It features 3D images of nature, women and cars. All the galleries are in three dimensions, as is the WMB 3D store. This application is available for free on the Android market for compatible 3D devices.</p>
<p>Some of the BlackBerry apps that are available in 3D include Need for Speed Shift 3D. This mobile version of the racing game uses dynamic camera angles to make the viewer appear as though he is actually racing the car. Eight different vehicles are available for driving, and the user can participate in challenges in Chicago London, Italy and Dubai, for a varied experience. This app is available for $5 from BlackBerry App World.</p>
<p>Not to be outdone, developers have released 3D games for the Android platform. Larger tablet screens enable users to control even small on-screen objects with finesse. Dungeon Defenders: Second Wave has been rated over 18,000 times, making it one of the popular games on the Android Market. With its epic plot line, this action/RPG game allows the player to participate in campaigns solo or with up to three friends.</p>
<p>Apple&#8217;s iPad offers several 3D apps as well. For example, iGlass is a game that will distract the user for hours. It allows the user to virtually blow molten glass with the tablet&#8217;s touch screen. At the end of the simulation, the user can rotate the glass creation to view it from every angle and even take screenshots to display the creation. Another similar app is iDough, a sculpting virtualization to create 3D sculptures. Hobbyists can play with a new medium, without all the mess, while professionals can hone their skills at any time.</p>
<p>Finally, 3D wallpapers are among the newest trends on mobile devices. Deep space vistas such as the one offered by Starfield 3D Live Wallpaper display in 3D, and the user can touch the screen to move through the stars.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.servercobra.com/3d-apps-for-tablet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
