Archive
Tags
android (3)
ant (2)
beautifulsoup (1)
debian (1)
decorators (1)
django (9)
dovecot (1)
encryption (1)
fix (4)
gotcha (2)
hobo (1)
htmlparser (1)
imaplib (2)
java (1)
json (2)
kerberos (2)
linux (7)
lxml (5)
markdown (4)
mechanize (6)
multiprocessing (1)
mysql (2)
nagios (2)
new_features (3)
open_source (5)
optparse (2)
parsing (1)
perl (2)
postgres (1)
preseed (1)
pxe (4)
pyqt4 (1)
python (41)
raid (1)
rails (1)
red_hat (1)
reportlab (4)
request_tracker (2)
rt (2)
ruby (1)
scala (1)
screen_scraping (7)
shell_scripting (8)
soap (1)
solaris (3)
sql (2)
sqlalchemy (2)
tips_and_tricks (1)
twitter (2)
ubuntu (1)
vmware (2)
windows (1)
zimbra (2)

In the middle of last year, I had a short post detailing booting the ESXi installer. Tom recently asked how one would PXE boot and kickstart the ESX installer. This is not much different than any other Red Hat Kickstart. I am going to assume you already have a working PXE booting environment using pxelinux and a FTP server set up to host the install media plus kickstart configurations.

The first thing to do is copy the contents of the install media to a location on your FTP server. If you have the install media in ISO form, it is as easy as this:

mkdir /mnt/esxinstall
mount -o loop /path/to/esx.iso /mnt/esxinstall
cp -r /mnt/esxinstall /var/ftp/pub
umount /mnt/esxinstall
rm -r /mnt/esxinstall

Verify that you can navigate the contents via FTP on another machine before continuing. Now that the media is accessible, we need the kernel and initial ram disk to boot from pxelinux. You will find both in the contents of the install media, in images/pxeboot, with the names vmlinuz and initrd.img. Copy these files somewhere in your tftpboot directory like so:

cd /var/ftp/pub/esxinstall/images/pxeboot
cp vmlinuz initrd.img /var/lib/tftpboot/esx

Note that /var/lib/tftpboot is where tftpboot resides on Fedora 10, the distribution I am hosting everything in this example on. This may be different on your system. The next step is to make your kickstart configuration. The easiest way to get a starting point on this is to install ESX normally. After install, ESX stores a kickstart config based on the install in /root/anaconda-ks.cfg, like every other Red Hat derivative. ESX features some special kickstart options for VMware specific functions, like service console memory and virtual networking. Here is a minimal headless kickstart for ESX:

install
lang en_US.UTF-8
langsupport --default en_US.UTF-8
keyboard us
mouse genericwheelps/2 --device psaux
skipx
vmaccepteula
# DHCP if you are doing multiple
network --device eth0 --bootproto dhcp --addvmportgroup=1 --vlanid=0
rootpw this_is_too_easy
firewall --enabled
authconfig --enableshadow --enablemd5
timezone --utc America/Denver
bootloader --location=mbr
clearpart --exceptvmfs --drives=sda
part /boot --fstype ext3 --size=100 --ondisk=sda --asprimary
part / --fstype ext3 --size=1800 --grow --maxsize=5000 --ondisk=sda
part swap --size=544 --grow --maxsize=544 --ondisk=sda
part /var/log --fstype ext3 --size=500 --grow --maxsize=2000 --ondisk=sda
part local --size 1 --ondisk=sda --fstype vmfs2 --grow

%packages
grub

%post
# Put whatever commands you would like to run at the end here,
# Just like in other Kickstarts

Put your kickstart somewhere available from your FTP, like /var/ftp/pub/esxinstall/headless.cfg. For the final ordeal, we need to add a entry in pxelinux.cfg/default or similar, so our machines can PXE boot. Here is what it might look like:

label esx
  kernel esx/vmlinuz
  append initrd=esx/initrd.img ramdisk_size=7268  ksdevice=eth0 ip=dhcp \
    method=ftp://yourftpserver/esxinstall ks=ftp://yourftpserver/esxinstall/headless.cfg

This will give you headless installs. NOTE: Do not include the backslashes and line breaks in your append line of your pxelinux entry. These are only here for readability's sake. Here is an explanation of the append options.

  • ksdevice If you have multiple nics, you can tell anaconda which to use during the first install phase.
  • ip Tell anaconda how to configure networking for this install.
  • method = URL to your media.
  • ks = URL to your kickstart configuration.
Posted by Tyler Lesmann on March 14, 2009 at 15:59 and commented on 5 times
Tagged as: pxe red_hat vmware

There is this really nice plugin for WordPress called sociable that makes it easy to make links to various social bookmarking sites. There did not seem to be anything similar in Django, so I made a clone. It does not do everything that the sociable plugin does yet, but it is incredibly flexible. This code is licensed under LGPL.

You can get the latest version here or you can get the whole repository with mercurial:

hg clone http://code.tylerlesmann.com/django-sociable

You will probably want the sociable images also. You can get them from here.

Install is like many other python packages:

python setup.py install

Using django-sociable is easy. After install, edit your settings.py. You will need to specify a MEDIA_URL, if you have not already. Now add SOCIABLE_IMAGE_PATH, which is the path relative to the MEDIA_URL to find the sociable images. The last thing to add is put sociable into your INSTALLED_APPS.

The next step is defining a Site because django-sociable uses this to construct your submission link. You do not want it pointing to example.com. The easiest way to do this is from the Django admin site.

You are ready to use the django-sociable templatetags in your templates. Here's an example of its use from this very blog:

<div>
{% load sociable_tags %}
{% get_sociable Reddit Digg as sociable_links with url=object.get_absolute_url title=object.headline %}
{% for link in sociable_links %}
    <a href="{{ link.link }}">
        <img alt="{{ link.site }}" title="{{ link.site }}" src="{{ link.image }}" />
    </a>
{% endfor %}
</div>

Load sociable_tags. Use the get_sociable tag to get the information you need to build the links. Specify the sites to target, then the variable to map the information to, and finally the arguments. The only required argument is url, which should be a context variable containing link to submit. You can also submit title, excerpt, and source. Use the list of information from get_sociable in whatever way you like. Each element of the list has three attributes. The site attribute is the name of the target site. The link contains the full submission link. The image is the absolute path to the image corresponding to the site.

Here is a full list of the acceptable target sites:

BarraPunto blinkbits BlinkList BlogMemes blogmarks Blogsvine blogtercimlap Faves Book.mark.hu Bumpzee co.mments connotea del.icio.us De.lirio.us Digg DotNetKicks DZone eKudos email Facebook Fark feedmelinks Furl Fleck GeenRedactie Google Gwar Haohao HealthRanker Hemidemi IndianPad Internetmedia kick.ie Kirtsy laaik.it Leonaut LinkArena LinkaGoGo LinkedIn Linkter Live Ma.gnolia Meneame MisterWong MisterWong.DE Mixx muti MyShare MySpace N4G Netvibes NewsVine Netvouz NuJIJ Ping.fm PlugIM Pownce ppnow Print Propeller Ratimarks Rec6 Reddit SalesMarks Scoopeo scuttle Segnalo Shadows Simpy Slashdot Smarking Socialogs Spurl SphereIt Sphinn StumbleUpon Symbaloo Taggly Technorati TailRank ThisNext Tipd Tumblr TwitThis Upnews Webnews.de Webride Wikio Wists Wykop Xerpi YahooBuzz YahooMyWeb YCombinator Yigg

Posted by Tyler Lesmann on March 9, 2009 at 18:16 and commented on 9 times
Tagged as: django new_features open_source python

In my earlier post, I walked you through the process I took to adapt this blog, with its existing data, to include tagging under the hood. In this post, I will cover the process of making the tags useful to your visitors.

The first thing to do is make a view to filter your model, or queryset, by tag. You have it easy because django-tagging includes a view built on top of django.views.generic.list_detail.object_list. You can add a tag filtered list as easily as adding a line like this to the urlpatterns in your urls.py:

(r'^tag/(?P<tag>[^/]+)/$', 'tagging.views.tagged_object_list',
    dict(queryset_or_model=MyModel)),

Going to http://yourdjangosite/tag/python/ would now bring up a list of MyModel instances featuring a python tag, assuming you have a myapp/mymodel_list.html template written up. How will your users navigate to this view? On this blog, I first have a collection of links under each post. These are simple to make. The code is something like this in the template:

{% load tagging_tags %}
<div>
    Tagged as:
    {% for tag in object.tags %}
        <a href="/tag/{{ tag }}/">{{ tag }}</a>
    {% endfor %}
</div>

On this blog, I also have a nice list of tags on the right with the count of posts bearing each tag. Here is the code for this:

{% load tagging_tags %}
<div class="header">Tags</div>
<div class="indent">
{% tags_for_model blog.Entry as entry_tags with counts %}
{% for entry_tag in entry_tags %}
    <div>
        <a href="/tag/{{ entry_tag }}/">{{ entry_tag }}</a>
        <span class="tag_count">({{ entry_tag.count }})</span></div>
{% endfor %}
</div>

That is just too easy, but maybe you want a tag cloud, like the one on my other site. Here is the code for the tag cloud from that very site:

{% load tagging_tags %}
<div class="tagbox">
    <div class="header">Filter by Tag:</div>
    <div class="group">
        {% tag_cloud_for_model deltad.Entry as entry_tags with steps=10 min_count=1 distribution=log %}
        {% for tag in entry_tags %}
            <a class="tag{{ tag.font_size }}" href="/tag/{{ tag }}/">{{ tag }}</a>
        {% endfor %}
    </div>
</div>

The tag_cloud_for_model tag gives me a entry_tags object with 10 levels of size distributed in logarithmic order as long as there is at least one entry bearing the tag. If you look carefully, you will notice that I am using the tag.font_size to classify my anchors. You can do whatever you want with this number. I just like to keep all appearance information in CSS.

Posted by Tyler Lesmann on March 9, 2009 at 8:17 and commented on 5 times
Tagged as: django python

Adding tagging to your Django application is easy, but can have some complications if you have existing data. In this post, I will cover how I accomplished it on this blog.

The first thing to do is install django-tagging. I am using Django 1.0, so I have to get the code from their subversion repository. You will not have to do this once version 0.3 comes out. Once django-tagging is installed, we can add tagging to our INSTALLED_APPS in our settings.py and do a ./manage.py syncdb. That's all you have to do for basic functionality in django-tagging. You will want more than basic functionality, am I right?

The next step you will want to take is registering your models with tagging.register as shown below.

import tagging
from django.db import models

class Entry(models.Model):
    # Imagine the rest of your Entry model here
    pass

try:
    tagging.register(Entry)
except tagging.AlreadyRegistered:
    # You might wonder what is going on here.
    # This is a bug in the svn release.  For some reason, the authors' cannot handle
    # re-registering gracefully, so we have to.
    # This should be fixed in later releases, but your code will still work here after it is.
    pass

After your model is registered, you will have access to several convenience methods and attributes, like yourmodelinstance.tags. It makes handling tags in your views and templates a dream.

What about Django's awesome admin though? It is a pain in the butt with just this to attach tags to a model instance. You have go to Tagged Objects, select the tag to apply to your model instance, select the model to be tagged, and finally the id of the instance. You do not want to do that. There is a smarter and faster way. We first need to add a TagField to our model like so.

import tagging
from django.db import models
from tagging.fields import TagField

class Entry(models.Model):
    # Imagine your other model fields preceded this
    tags_string = TagField()
    # Don't name this tags as it will conflict with the tags attribute gained
    # through registering the model with tagging

try:
    tagging.register(Entry)
except tagging.AlreadyRegistered:
    pass

If this is a fresh application without real data, you are done. You may not be so lucky, like myself. You will have to alter the database table yourself because Django, as great as it is, does not do this...yet. Here is something like commands you would run to alter your table, assuming your database is called yourdb, your application is called yourapp, your model is called yourmodel, and the last field of your model before tags_string is called last_field:

ALTER TABLE yourdb.yourapp_yourmodel ADD tags_string VARCHAR(255) AFTER last_field;
UPDATE yourdb.yourapp_yourmodel SET tags_string = '';
ALTER TABLE yourdb.yourapp_yourmodel MODIFY COLUMN tags_string VARCHAR(255) NOT NULL;

You can inject this into mysql easily by running something like this:

mysql -u root -p < file_the_earlier_sql_in

Now, your table is just like a fresh one, schema-wise. Your data is the same with a blank tags_string field. Tags can be added from the model edit page in Django admin now. I will cover adding tags to your views and templates in the next post.

Posted by Tyler Lesmann on March 6, 2009 at 9:26 and commented on 3 times
Tagged as: django mysql python sql

I have added tagging functionality to this blog. You can expect a post on how I accomplished this very soon.

Posted by Tyler Lesmann on March 5, 2009 at 18:27
Tagged as: new_features