<?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>jansipke.nl</title>
	<atom:link href="http://www.jansipke.nl/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jansipke.nl</link>
	<description>Technology Blog</description>
	<lastBuildDate>Sun, 29 Aug 2010 19:50:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Metering the meter cupboard</title>
		<link>http://www.jansipke.nl/metering-the-meter-cupboard</link>
		<comments>http://www.jansipke.nl/metering-the-meter-cupboard#comments</comments>
		<pubDate>Sun, 29 Aug 2010 19:44:48 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Meter]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1083</guid>
		<description><![CDATA[In this article we will look at my meter cupboard and the meters inside it. In future articles we will see how I used a microcontroller and some sensors to meter the meters (at the time of writing the electricity meter works). From left to right, these are the electricity, gas and water meter: Electricity [...]]]></description>
			<content:encoded><![CDATA[<p>In this article we will look at my meter cupboard and the meters inside it. In future articles we will see how I used a microcontroller and some sensors to meter the meters (at the time of writing the electricity meter works). From left to right, these are the electricity, gas and water meter:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/elec-gas-water.png"><img class="alignnone size-full wp-image-1084" title="elec-gas-water" src="http://www.jansipke.nl/wp-content/uploads/elec-gas-water.png" alt="" width="570" height="150" /></a><strong>Electricity</strong></p>
<p>The electricity meter is a relatively new one with a digital display and a flashing LED. This LED flashes one thousand times for each kWh consumed, i.e. once per Wh.</p>
<p><strong>Gas</strong></p>
<p>The gas meter doesn&#8217;t have a flashing LED or something comparable. There is hope however, because there is a reflective area on the digit &#8217;6&#8242; at the far right of the display, just left of the &#8216;m2&#8242;. It also looks like there is some magnetic material in one of the last two digits, so there are actually two ways to go with this meter.</p>
<p><strong>Water</strong></p>
<p>The water meter doesn&#8217;t have a flashing LED or a reflective area anywhere. It also doesn&#8217;t have a colored dial, which most commercial water meter detectors use. There is a tiny bit of hope in the hole below &#8216;PR&#8217;. Using a magnetic sensor, I found some fluctuation in the values, but nothing consistent so far. The orientation of the sensor seems to be important, so I will fiddle a bit more with this one in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/metering-the-meter-cupboard/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Model View Controller (MVC) with JSP and JSTL</title>
		<link>http://www.jansipke.nl/model-view-controller-mvc-with-jsp-and-jstl</link>
		<comments>http://www.jansipke.nl/model-view-controller-mvc-with-jsp-and-jstl#comments</comments>
		<pubDate>Tue, 20 Jul 2010 07:28:32 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JSP]]></category>
		<category><![CDATA[JSTL]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1069</guid>
		<description><![CDATA[In this article we will create a small web application that uses the Model View Controller (MVC) pattern with Java Server Pages (JSP) and JSP Standard Template Library (JSTL). A container like Tomcat is needed to run this combination. Thanks go out to the author of the JSP &#8211; MVC Tutorial, who thought of the [...]]]></description>
			<content:encoded><![CDATA[<p>In this article we will create a small web application that uses the <a href="http://en.wikipedia.org/wiki/Model-view-controller">Model View Controller (MVC)</a> pattern with <a href="http://java.sun.com/products/jsp/">Java Server Pages (JSP)</a> and <a href="http://java.sun.com/products/jsp/jstl/">JSP Standard Template Library (JSTL)</a>. A container like <a href="http://tomcat.apache.org/">Tomcat</a> is needed to run this combination.</p>
<p>Thanks go out to the author of the <a href="http://www.datadisk.co.uk/html_docs/jsp/jsp_mvc_tutorial.htm">JSP &#8211; MVC Tutorial</a>, who thought of the sample application that we will use here, the coffee advisor. The user is first presented with a choice in coffee taste she prefers. Pressing a button moves on to a page with advise about the type of coffee to drink based on that taste.</p>
<p>An MVC application has three parts:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/mvc.png"><img class="alignnone size-full wp-image-1081" title="mvc" src="http://www.jansipke.nl/wp-content/uploads/mvc.png" alt="" width="447" height="250" /></a></p>
<ul>
<li>Model. The model is the domain-specific representation of the data upon which  the application operates. In our case this is implemented in the <em>CoffeeExpert</em> class.</li>
<li>View. The view renders the model into a form suitable for interaction,  typically a user interface element. In our case this is implemented in a JSP file called <em>coffee.jsp</em>.</li>
<li>Controller. The controller receives input and initiates a response by making calls on model objects. In our case this is implemented in the <em>CoffeeSelect</em> class.</li>
</ul>
<p>In addition to these three file we need a <em>web.xml</em> file that tells the container how to map a URL (e.g. <em>/CoffeeSelect.do</em>) into a class to run (e.g. <em>com.example.web.CoffeeSelect</em>). We also need a start page for the user input, which we will call <em>coffee.html</em>. In total this means we should create a  <em>.war</em> file with the following structure:<br />
<a href="http://www.jansipke.nl/wp-content/uploads/coffee-advisor-war.png"><img class="alignnone size-full wp-image-1075" title="coffee-advisor-war" src="http://www.jansipke.nl/wp-content/uploads/coffee-advisor-war.png" alt="" width="243" height="198" /></a></p>
<p><strong>coffee.html</strong></p>
<blockquote>
<pre>&lt;html&gt;
    &lt;body&gt;
        &lt;h2&gt;Coffee Advisor Input&lt;/h2&gt;
        &lt;form method="POST" action="CoffeeSelect.do"&gt;
            &lt;select name="taste" size=1"&gt;
                &lt;option value="milky"&gt;Milky&lt;/option&gt;
                &lt;option value="froffy"&gt;Froffy&lt;/option&gt;
                &lt;option value="icey"&gt;Icey&lt;/option&gt;
                &lt;option value="strong"&gt;Spaced Out&lt;/option&gt;
            &lt;/select&gt;
            &lt;br/&gt;&lt;br/&gt;
            &lt;input type="Submit"/&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p><strong>CoffeeExpert.java</strong></p>
<blockquote>
<pre>package com.example.model;

import java.util.*;

public class CoffeeExpert {
    public List&lt;String&gt; getTypes(String taste) {
        List&lt;String&gt; result = new ArrayList&lt;String&gt;();
        if (taste.equals("milky")) {
            result.add("Latte");
            result.add("Cappuccino");
        } else if (taste.equals("froffy")) {
            result.add("Latte");
            result.add("Cappuccino");
            result.add("Frappuccino");
        } else if (taste.equals("icey")) {
            result.add("Frappuccino");
        } else if (taste.equals("strong")) {
            result.add("Espresso");
            result.add("Double espresso");
        } else {
            result.add("Vending machine");
        }
        return (result);
    }
}
</pre>
</blockquote>
<p><strong>CoffeeSelect.java</strong></p>
<blockquote>
<pre>package com.example.web;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.model.CoffeeExpert;

public class CoffeeSelect extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        List&lt;String&gt; types = new CoffeeExpert().getTypes(request.getParameter("taste"));
        request.setAttribute("types", types);
        RequestDispatcher view = request.getRequestDispatcher("coffee.jsp");
        view.forward(request, response);
    }
}
</pre>
</blockquote>
<p><strong>coffee.jsp</strong></p>
<blockquote>
<pre>&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;

&lt;html&gt;
    &lt;body&gt;
        &lt;h2&gt;Coffee Advisor Output&lt;/h2&gt;
        &lt;c:forEach var="type" items="${types}"&gt;
            &lt;c:out value="${type}"/&gt;
            &lt;br /&gt;
        &lt;/c:forEach&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p><strong>web.xml</strong></p>
<blockquote>
<pre>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4"&gt;

    &lt;servlet&gt;
        &lt;servlet-name&gt;Coffee&lt;/servlet-name&gt;
        &lt;servlet-class&gt;com.example.web.CoffeeSelect&lt;/servlet-class&gt;
    &lt;/servlet&gt;

    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;Coffee&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/CoffeeSelect.do&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/model-view-controller-mvc-with-jsp-and-jstl/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Changing CPU and memory settings on XenServer VMs</title>
		<link>http://www.jansipke.nl/changing-cpu-and-memory-settings-on-xenserver-vms</link>
		<comments>http://www.jansipke.nl/changing-cpu-and-memory-settings-on-xenserver-vms#comments</comments>
		<pubDate>Tue, 08 Jun 2010 15:33:18 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Cloud computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1057</guid>
		<description><![CDATA[You can change the CPU and memory settings of XenServer virtual machines using the API. XenServer allows you to set the priority of the virtual machine CPU (called weight), set a limit on the amount of CPU the virtual machine can use (called cap) and set the amount of memory the virtual machine gets. CPU [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/xenserver.png"><img class="alignnone size-full wp-image-940" title="xenserver" src="http://www.jansipke.nl/wp-content/uploads/xenserver.png" alt="" width="327" height="61" /></a></p>
<p>You can change the CPU and memory settings of XenServer virtual machines using the API. XenServer allows you to set the priority of the virtual machine CPU (called <em>weight</em>), set a limit on the amount of CPU the virtual machine can use (called <em>cap</em>) and set the amount of memory the virtual machine gets.</p>
<p><strong>CPU priority</strong></p>
<p>You can set the <em>weight</em> parameter to a number between 1 and 65536. The default value is 256, meaning normal priority. A virtual machine with a weight of 512 will get twice as much CPU as a virtual machine with a weight of 256 on a contended XenServer host. The following code sets the <em>weight</em> to 128, meaning that it will get half as much CPU as a normal virtual machine.</p>
<blockquote>
<pre>Map&lt;String, String&gt; vcpuParameters = new HashMap&lt;String, String&gt;();
vcpuParameters.put("weight", "128");
vm.setVCPUsParams(connection, vcpuParameters);
</pre>
</blockquote>
<p><strong>CPU limit</strong></p>
<p>You can set the <em>cap</em> parameter to a percentage number. The default value is 0, meaning there is no cap. The value 100 represents one virtual CPU, so half a virtual CPU can be set by using the value 50. The following code sets the <em>cap</em> to 35, meaning that it will not get more than 35 percent of one virtual CPU, even if the physical CPU is not used to its top.</p>
<blockquote>
<pre>Map&lt;String, String&gt; vcpuParameters = new HashMap&lt;String, String&gt;();
vcpuParameters.put("cap", "35");
vm.setVCPUsParams(connection, vcpuParameters);
</pre>
</blockquote>
<p><strong>Memory</strong></p>
<p>You can set the amount of memory assigned to a virtual machine in bytes. The following code sets the amount of memory to 1 GB (1,073,741,824 bytes).</p>
<blockquote>
<pre>vm.setMemoryStaticMax(connection, new Long(1073741824));
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/changing-cpu-and-memory-settings-on-xenserver-vms/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Increasing the size of an LVM volume</title>
		<link>http://www.jansipke.nl/increasing-the-size-of-an-lvm-volume</link>
		<comments>http://www.jansipke.nl/increasing-the-size-of-an-lvm-volume#comments</comments>
		<pubDate>Thu, 03 Jun 2010 14:58:27 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Storage]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[LVM]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1049</guid>
		<description><![CDATA[In a previous article we looked at LVM. This short article describes how to grow an existing volume by adding an extra disk to the system. Specifically, we use a XenServer guest VM with CentOS installed. The first disk of a XenServer guest VM is called xvda, the second disk (the one we added) is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/harddisk.jpg"><img class="alignnone size-full wp-image-604" title="harddisk" src="http://www.jansipke.nl/wp-content/uploads/harddisk.jpg" alt="" width="61" height="60" /></a></p>
<p>In a <a href="/an-introduction-to-logical-volume-management-lvm">previous article</a> we looked at LVM. This short article describes how to grow an existing volume by adding an extra disk to the system. Specifically, we use a XenServer guest VM with CentOS installed.</p>
<p>The first disk of a XenServer guest VM is called <em>xvda</em>, the second disk (the one we added) is called <em>xvdb</em>. We start with the creation of a Physical Volume (PV) on the extra disk.</p>
<blockquote>
<pre>pvcreate /dev/xvdb
</pre>
</blockquote>
<p>Then we extend the existing Volume Group (VG) called VolGroup00.</p>
<blockquote>
<pre>vgextend VolGroup00 /dev/xvdb
</pre>
</blockquote>
<p>Then we extend the Logical Volume (LV) by the size of the extra disk, in this case 8GB.</p>
<blockquote>
<pre>lvextend -L8G /dev/VolGroup00/LogVol00
</pre>
</blockquote>
<p>Finally we resize the filesystem that uses this LV.</p>
<blockquote>
<pre>resize2fs /dev/VolGroup00/LogVol00
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/increasing-the-size-of-an-lvm-volume/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing XenServer Tools on Ubuntu 10.04</title>
		<link>http://www.jansipke.nl/installing-xenserver-tools-on-ubuntu-10-04</link>
		<comments>http://www.jansipke.nl/installing-xenserver-tools-on-ubuntu-10-04#comments</comments>
		<pubDate>Tue, 01 Jun 2010 10:03:00 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Cloud computing]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1016</guid>
		<description><![CDATA[XenServer supports a lot of Linux and Windows operating systems out of the box, but Ubuntu isn&#8217;t one of them. This means that running Ubuntu is slower, because it uses HVM (hardware-assisted virtualisation) instead of PV (paravirtualization). This article will explain how to create a paravirtualized Ubuntu 10.04 VM with the XenServer Tools installed. Many [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/xenserver-ubuntu.png"><img class="alignnone size-full wp-image-1046" title="xenserver-ubuntu" src="http://www.jansipke.nl/wp-content/uploads/xenserver-ubuntu.png" alt="" width="381" height="46" /></a></p>
<p><a href="http://www.xensource.com/">XenServer</a> supports a lot of Linux and Windows operating systems out of the box, but <a href="http://www.ubuntu.com/">Ubuntu</a> isn&#8217;t one of them. This means that running Ubuntu is slower, because it uses HVM (<a href="http://en.wikipedia.org/wiki/Hardware-assisted_virtualization">hardware-assisted virtualisation</a>) instead of PV (<a href="http://en.wikipedia.org/wiki/Paravirtualization">paravirtualization</a>). This article will explain how to create a paravirtualized Ubuntu 10.04 VM with the XenServer Tools installed. Many thanks go to the author of the article <a href="http://www.bishopbarrington.net/wiki/howto/lucidonxenserver">Ubuntu 10.04 LTS paravirtualised on Citrix XenServer</a>.</p>
<p><strong>We start with creating and installing a VM with HVM.</strong></p>
<ul>
<li>Create a VM from the <em>Other install media</em> template</li>
<li>Attach the Ubuntu 10.04 ISO to the DVD drive of the VM</li>
<li>Start the VM</li>
<li>At the disk partitioning stage make sure to replace <em>Ext4</em> with <em>Ext3</em>, or create a specific boot partition with <em>Ext3</em></li>
<li>Select at least the <em>OpenSSH server</em> package to be able to log in to the VM remotely</li>
<li>Finish installation and boot the VM</li>
</ul>
<p><strong>We now create a new console and edit the boot settings.</strong></p>
<ul>
<li>Connect to the VM using SSH</li>
<li>Create a new console for Xen</li>
</ul>
<blockquote>
<pre>sudo cp /etc/init/tty1.conf /etc/init/hvc0.conf
sudo vi /etc/init/hvc0.conf
</pre>
</blockquote>
<ul>
<li>Replace all occurrences of <em>tty1</em> with <em>hvc0</em></li>
<li>Read <em>/boot/grub/grub.cfg</em></li>
</ul>
<blockquote>
<pre>sudo vi /boot/grub/grub.cfg
</pre>
</blockquote>
<ul>
<li>Copy the contents of <em>menuentry</em> near the bottom to a temporary text file, to be used as input for the <em>makepv.sh </em>script that we will use later on</li>
</ul>
<blockquote>
<pre>menuentry 'Ubuntu, with Linux 2.6.32-21-server' --class ubuntu --class gnu-linux --class gnu --class os {
        recordfail
        insmod ext2
        set root='(hd0,1)'
        search --no-floppy --fs-uuid --set 02899ea9-1876-4e7b-8ef8-2b09b598cedb
        linux   /boot/vmlinuz-2.6.32-21-server root=UUID=02899ea9-1876-4e7b-8ef8-2b09b598cedb ro quiet
        initrd  /boot/initrd.img-2.6.32-21-server
}
</pre>
</blockquote>
<ul>
<li>Make special note of <em>/boot/vmlinuz</em>&#8230;, <em>root=UUID=</em>&#8230; and <em>/boot/initrd.img</em>&#8230;</li>
<li>Shutdown the VM</li>
</ul>
<p><strong>We now convert the VM to PV.</strong></p>
<ul>
<li>Connect to the XenServer host with SSH</li>
<li>Copy the <em>makepv.sh</em> script (<a href="/res/xenserver/makepv.sh">download from here</a>) to the XenServer host and make it executable</li>
</ul>
<blockquote>
<pre>chmod +x makepv.sh
</pre>
</blockquote>
<ul>
<li>Run the <em>makepv.sh</em> script, replacing <em>my-vm-name</em> with the actual name of your VM</li>
</ul>
<blockquote>
<pre>makepv.sh my-vm-name
</pre>
</blockquote>
<p><strong>Finally we install the XenServer tools.</strong></p>
<ul>
<li>Boot the VM and log in with SSH</li>
<li>In XenCenter, attach<em> xs-tools.iso</em> to the DVD drive of the VM</li>
<li>Mount <em>xs-tools.iso</em>, install the correct XenServer Tools package (replace <em>amd64</em> with <em>i386</em> if necessary) and unmount <em>xs-tools.iso</em></li>
</ul>
<blockquote>
<pre>sudo mount /dev/cdrom1 /mnt
sudo dpkg -i /mnt/Linux/xe-guest-utilities_5.5.0-466_amd64.deb
sudo umount /mnt
</pre>
</blockquote>
<ul>
<li>In XenCenter, detach <em>xs-tools.iso</em> from the DVD drive of the VM (this ensures that XenServer does not complain about too many bootable devices)</li>
<li>Reboot the VM and log in with SSH</li>
<li>Make sure the services run at boot time</li>
</ul>
<blockquote>
<pre>sudo update-rc.d -f xe-linux-distribution remove
sudo update-rc.d xe-linux-distribution defaults
</pre>
</blockquote>
<ul>
<li>Reboot the VM for the last time</li>
<li>Restart XenCenter to be able to log in to the console of the VM</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/installing-xenserver-tools-on-ubuntu-10-04/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Installing Sun JDK 6 on Ubuntu 10.04</title>
		<link>http://www.jansipke.nl/installing-sun-jdk-6-on-ubuntu-10-04</link>
		<comments>http://www.jansipke.nl/installing-sun-jdk-6-on-ubuntu-10-04#comments</comments>
		<pubDate>Thu, 27 May 2010 13:21:32 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1005</guid>
		<description><![CDATA[The Sun JDK can be installed on Ubuntu by adding a repository and installing with apt-get. The following works with the latest versions of both at the time of writing: Sun JDK 6 update 20 Ubuntu 10.04 sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner" sudo apt-get update sudo apt-get install sun-java6-jdk If the command add-apt-repository is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/java-ubuntu.png"><img class="alignnone size-full wp-image-1013" title="java-ubuntu" src="http://www.jansipke.nl/wp-content/uploads/java-ubuntu.png" alt="" width="180" height="46" /></a></p>
<p>The Sun JDK can be installed on Ubuntu by adding a repository and installing with apt-get. The following works with the latest versions of both at the time of writing:</p>
<ul>
<li><a href="http://java.sun.com/javase/downloads/index.jsp">Sun JDK 6 update 20</a></li>
<li><a href="http://www.ubuntu.com/">Ubuntu 10.04</a></li>
</ul>
<blockquote>
<pre>sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk
</pre>
</blockquote>
<p>If the command <em>add-apt-repository</em> is missing, install it with the following command:</p>
<blockquote>
<pre>sudo apt-get install python-software-properties
</pre>
</blockquote>
<p>With the <em>alternatives</em> system in place, the Java executable is automatically available:</p>
<blockquote>
<pre>/usr/bin/java -&gt; /etc/alternatives/java
/etc/alternatives/java -&gt; /usr/lib/jvm/java-6-sun/jre/bin/java
</pre>
</blockquote>
<p>Setting up JAVA_HOME can now be done by editing <em>/etc/profile</em> and adding to the bottom:</p>
<blockquote>
<pre>export JAVA_HOME=/usr/lib/jvm/java-6-sun
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/installing-sun-jdk-6-on-ubuntu-10-04/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Getting CPU, memory, disk and network metrics from XenServer</title>
		<link>http://www.jansipke.nl/getting-cpu-memory-disk-and-network-metrics-from-xenserver</link>
		<comments>http://www.jansipke.nl/getting-cpu-memory-disk-and-network-metrics-from-xenserver#comments</comments>
		<pubDate>Sat, 08 May 2010 18:56:20 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Cloud computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=978</guid>
		<description><![CDATA[In a previous article we looked at getting CPU and memory metrics from XenServer. As noted in that article, as of version 5.5 of XenServer, the preferred way of getting virtual machine metrics is through HTTP calls to get RRD XML files. We showed how to revert to the old way of doing things, but [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/metrics1.png"><img class="alignnone size-full wp-image-1001" title="metrics" src="http://www.jansipke.nl/wp-content/uploads/metrics1.png" alt="" width="630" height="116" /></a></p>
<p>In a <a href="http://www.jansipke.nl/getting-xenserver-vm-metrics-in-java">previous article</a> we looked at getting CPU and memory metrics from XenServer. As noted in that article, as of version 5.5 of XenServer, the preferred way of getting virtual machine metrics is through HTTP calls to get RRD XML files. We showed how to revert to the old way of doing things, but in this article we will look into the new, preferred way. This has the added benefit that disk and network metrics are also available, along with a history of metrics.</p>
<p>The first thing to note is that the metrics are not available through the XenServer API. The RRD XML files are stored on the physical machines that currently host the virtual machines. For example, if you have two physical machines (P1 and P2) with two virtual machines running on each of them (V1a, V1b, V2a and V2b), you need to query P1 for the metrics of V1a and V1b and query P2 for the metrics of V2a and V2b. If a virtual machine is not running at the moment, you can get the (old) metrics from the master in the pool.</p>
<p>Each physical machine has an HTTP interface at the following location:</p>
<blockquote>
<pre>http://machine_name_or_ip/rrd_updates?start=1234567890
</pre>
</blockquote>
<p>The parameter <em>start</em> tells the server to only give metrics starting at this timestamp (seconds since January 1st 1970). The call requires a username and password, which will be asked if you connect through a webbrowser. The following code does this in Java:</p>
<blockquote>
<pre>Connection connection = new Connection(new URL(MASTER_HOST));
Session.loginWithPassword(connection, USERNAME, PASSWORD, APIVersion.latest().toString());

Map hostRecords = Host.getAllRecords(connection);
for (Host host : hostRecords.keySet()) {
    URL url = new URL("http://" + host.getAddress(connection) + "/rrd_updates?start=" + (System.currentTimeMillis() / 1000 - TIME_WINDOW));
    URLConnection urlConnection = url.openConnection();
    String encoding = new BASE64Encoder().encode((USERNAME + ":" + PASSWORD).getBytes());
    urlConnection.setRequestProperty ("Authorization", "Basic " + encoding);

    String rrdXportData = IOUtils.toString(urlConnection.getInputStream());
}
</pre>
</blockquote>
<p>The code needs two libraries:</p>
<ul>
<li><em>commons-io-1.4.jar</em>. This package contains the code to get a string containing the data of an inputstream.</li>
<li><em>xenserver-5.5.0-1.jar</em>. This package contains the code to connect to the XenServer pool.</li>
</ul>
<p>The following constants are used in this piece of code and need to be filled in:</p>
<ul>
<li><em>MASTER_HOST</em>. This is the IP address or hostname of the master host in the pool.</li>
<li><em>TIME_WINDOW</em>. XenServer will return RRD updates of the last <em>TIME_WINDOW</em> seconds.</li>
<li><em>USERNAME </em>and <em>PASSWORD</em>. These are the credentials for connecting to the master host and the other physical hosts in the pool.</li>
</ul>
<p>At the end of this piece of code we have the string <em>rrdXportData</em> containing the RRD XML data. Now we need to parse this data to get the metrics we want. The following listing contains the most important parts of this string (edited for clarity):</p>
<blockquote>
<pre>&lt;xport&gt;
   &lt;meta&gt;
      &lt;start&gt;1273342925&lt;/start&gt;
      &lt;step&gt;5&lt;/step&gt;
      &lt;end&gt;1273342980&lt;/end&gt;
      &lt;rows&gt;13&lt;/rows&gt;
      &lt;columns&gt;31&lt;/columns&gt;
      &lt;legend&gt;
         &lt;entry&gt;AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0&lt;/entry&gt;
         &lt;entry&gt;AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:vif_4_tx&lt;/entry&gt;
         ...
      &lt;/legend&gt;
   &lt;/meta&gt;
   &lt;data&gt;
      &lt;row&gt;
         &lt;t&gt;1273342980&lt;/t&gt;
         &lt;v&gt;0.0002&lt;/v&gt;
         &lt;v&gt;0.0&lt;/v&gt;
         ...
      &lt;/row&gt;
      &lt;row&gt;
         &lt;t&gt;1273342975&lt;/t&gt;
         &lt;v&gt;0.0003&lt;/v&gt;
         &lt;v&gt;0.0&lt;/v&gt;
         ...
      &lt;/row&gt;
      ...
   &lt;/data&gt;
&lt;/xport&gt;
</pre>
</blockquote>
<p>The following Java code will parse this RRD XML string and make it available in the four variables shown at the top. The variable <em>metricsTimelines</em> contains a hashmap of string to double[]. The string is the metric name (e.g. <em>AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0</em>) and the double[] contains the values for this metric from <em>startTime</em> to <em>endTime</em> with a step size of <em>step</em>. Note that the value at <em>endTime</em> is at position 0 and the value at  <em>startTime</em> is at the end of the array.</p>
<blockquote>
<pre>int endTime = 0;
HashMap&lt;String, double[]&gt; metricsTimelines = null;
int startTime = 0;
int step = 0;

try {
   DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
   domFactory.setNamespaceAware(true);
   DocumentBuilder builder = domFactory.newDocumentBuilder();
   StringReader stringReader = new StringReader(rrdXportData);
   InputSource inputSource = new InputSource(stringReader);
   Document doc = builder.parse(inputSource);
   stringReader.close();

   ArrayList&lt;ArrayList&lt;String&gt;&gt; dataRows = new ArrayList&lt;ArrayList&lt;String&gt;&gt;();
   ArrayList&lt;String&gt; legends = new ArrayList&lt;String&gt;();
   NodeList xportChildNodes = doc.getDocumentElement().getChildNodes();
   for (int i = 0; i &lt; xportChildNodes.getLength(); i++) {
      Node xportChildNode = xportChildNodes.item(i);
      if (xportChildNode.getNodeName().equals("meta")) {
         NodeList metaChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j &lt; metaChildNodes.getLength(); j++) {
            Node metaChildNode = metaChildNodes.item(j);
            if (metaChildNode.getNodeName().equals("step")) {
               step = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("start")) {
               startTime = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("end")) {
               endTime = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("legend")) {
               NodeList legendChildNodes = metaChildNode.getChildNodes();
               for (int k = 0; k &lt; legendChildNodes.getLength(); k++) {
                  Node legendChildNode = legendChildNodes.item(k);
                  legends.add(k, legendChildNode.getTextContent());
               }
            }
         }
      } else if (xportChildNode.getNodeName().equals("data")) {
         NodeList dataChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j &lt; dataChildNodes.getLength(); j++) {
            Node rowNode = dataChildNodes.item(j);
            NodeList rowChildNodes = rowNode.getChildNodes();
            ArrayList&lt;String&gt; dataRow = new ArrayList&lt;String&gt;();
            for (int k = 1; k &lt; rowChildNodes.getLength(); k++) {
               Node rowChildNode = rowChildNodes.item(k);
               dataRow.add(k - 1, rowChildNode.getTextContent());
            }
            dataRows.add(dataRow);
         }
      }
   }

   int nrDataRows = dataRows.size();
   int nrLegends = legends.size();

   metricsTimelines = new HashMap&lt;String, double[]&gt;();
   for (int i = 0; i &lt; nrLegends; i++) {
      metricsTimelines.put(legends.get(i), new double[nrDataRows]);
   }
   for (int i = 0; i &lt; nrLegends; i++) {
      for (int j = 0; j &lt; nrDataRows; j++) {
         double[] values = metricsTimelines.get(legends.get(i));
         values[j] = new Double(dataRows.get(j).get(i)).doubleValue();
      }
   }
} catch (Exception e) {
   e.printStackTrace();
}
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/getting-cpu-memory-disk-and-network-metrics-from-xenserver/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Google Visualization API with own data source</title>
		<link>http://www.jansipke.nl/using-google-visualization-api-with-own-data-source</link>
		<comments>http://www.jansipke.nl/using-google-visualization-api-with-own-data-source#comments</comments>
		<pubDate>Mon, 29 Mar 2010 18:18:18 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Google Visualization]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=946</guid>
		<description><![CDATA[The Google Visualization API allows you to create charts and maps based on data you provide. This data can be in a Google Spreadsheet or be something you provide yourself. The visualizations themselves are mostly written in Javascript, although there are some written in Flash. In this article we will create an HTML page with [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://code.google.com/apis/visualization/interactive_charts.html">Google Visualization API</a> allows you to create charts and maps based on data you provide. This data can be in a Google Spreadsheet or be something you provide yourself. The visualizations themselves are mostly written in Javascript, although there are some written in Flash.</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/visualization.png"><img class="alignnone size-full wp-image-963" title="visualization" src="http://www.jansipke.nl/wp-content/uploads/visualization.png" alt="" width="631" height="219" /></a></p>
<p>In this article we will create an <a href="http://www.jansipke.nl/res/visualization/index.html">HTML page with multiple charts in it</a> and a <a href="http://jansipke.nl/res/visualization/chart-data.py">data source that is generated by a Python program</a>. We start with the HTML page that has two named div&#8217;s in it (<em>visualization1</em> and <em>visualization2</em>), including the Javascript code that loads the two charts into these div&#8217;s.</p>
<blockquote>
<pre>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
   &lt;head&gt;
      &lt;meta http-equiv="content-type" content="text/html; charset=utf-8"/&gt;
      &lt;title&gt;
         Google Visualization API
      &lt;/title&gt;
      &lt;script type="text/javascript" src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
      &lt;script type="text/javascript"&gt;
         google.load('visualization', '1', {packages: ['columnchart', 'linechart']});
      &lt;/script&gt;
      &lt;script type="text/javascript"&gt;

         var query1, visualization1;
         var query2, visualization2;

         function initialize() {
            visualization1 = new google.visualization.ColumnChart(document.getElementById('visualization1'));
            query1 = new google.visualization.Query('http://jansipke.nl/res/visualization/chart-data.py');
            query1.setRefreshInterval(5);
            query1.send(drawVisualization1);

            visualization2 = new google.visualization.LineChart(document.getElementById('visualization2'));
            query2 = new google.visualization.Query('http://jansipke.nl/res/visualization/chart-data.py');
            query2.setRefreshInterval(5);
            query2.send(drawVisualization2);
         }

         function drawVisualization1(response) {
            if (response.isError()) {
               alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
               return;
            }
            visualization1.draw(response.getDataTable(), {legend: 'bottom', title: 'ColumnChart'});
         }

         function drawVisualization2(response) {
            if (response.isError()) {
               alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
               return;
            }
            visualization2.draw(response.getDataTable(), {legend: 'bottom', title: 'LineChart'});
         }

         google.setOnLoadCallback(initialize);
      &lt;/script&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;div&gt;
         &lt;div id="visualization1" style="height: 250px; width: 400px; border: 1px solid; float: left;" /&gt;
      &lt;/div&gt;
      &lt;div&gt;
         &lt;div id="visualization2" style="height: 250px; width: 400px; border: 1px solid; float: left; margin-left: 10px" /&gt;
      &lt;/div&gt;
   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>There are two things that you <strong>really</strong> need to do before this works correctly:</p>
<ul>
<li>Make sure that the parent node of the div that holds your chart, is not also the parent of one of the other div&#8217;s that holds a chart. In the HTML page above we surrounded the chart div with another div to accomplish this.</li>
<li>The chart is updated with new data every 5 seconds. It is a known bug of the Google Visualization API that the data needs to be fetched from another server then the one that is hosting the HTML page for the refresh to actually work. In the HTML page above the data source <em>chart-data.py</em> is therefore fetched from <em>jansipke.nl</em> and the HTML is fetched from <em>www.jansipke.nl</em>.</li>
</ul>
<p>We will create our own data source in Python. There is a description of how you should do this on the <a href="http://code.google.com/apis/visualization/documentation/dev/implementing_data_source.html">Writing Your Own Data Source</a> page from Google. One of the most common mistakes in writing these data sources is the need for the program to read the request identifier (<em>reqId</em>) and return this value in the response. The API needs this to distinguish between responses for different charts on the same page.</p>
<blockquote>
<pre>import cgi, random

def index(req):
   reqId = None
   if (req.args):
      for arg in req.args.split("&amp;"):
         (key, value) = arg.split("=")
         if (key == "tqx"):
            for parameter in value.split(";"):
               if (parameter.find("%3A") &gt; 0):
                  (par_key, par_value) = parameter.split("%3A")
               if (par_key == "reqId"):
                  reqId = par_value

   a = str(random.randint(1, 3))
   b = str(random.randint(1, 3))
   c = str(random.randint(1, 3))
   d = str(random.randint(1, 3))

   s = ""
   s += "google.visualization.Query.setResponse(\n"
   s += "{\n"
   if (reqId != None):
      s += "   reqId:'" + reqId + "',\n"
   s += "   status:'ok',\n"
   s += "   table:\n"
   s += "   {\n"
   s += "      cols:\n"
   s += "      [\n"
   s += "         {id:'Col1',label:'',type:'string'},\n"
   s += "         {id:'Col2',label:'Label1',type:'number'},\n"
   s += "         {id:'Col3',label:'Label2',type:'number'},\n"
   s += "         {id:'Col4',label:'Label3',type:'number'}\n"
   s += "      ],\n"
   s += "      rows:\n"
   s += "      [\n"
   s += "         {c:[{v:'a',f:'a'},{v:1.0,f:'1'},{v:1.0,f:'1'},{v:" + a + ",f:'1'}]},\n"
   s += "         {c:[{v:'b',f:'b'},{v:2.0,f:'2'},{v:1.5,f:'1'},{v:" + b + ",f:'1'}]},\n"
   s += "         {c:[{v:'c',f:'c'},{v:3.0,f:'3'},{v:2.5,f:'1'},{v:" + c + ",f:'1'}]},\n"
   s += "         {c:[{v:'d',f:'d'},{v:4.0,f:'1'},{v:2.0,f:'1'},{v:" + d + ",f:'1'}]}\n"
   s += "      ]\n"
   s += "   }\n"
   s += "});"

   return s
</pre>
</blockquote>
<p>We can test this data source by following the link without parameters and following the link with the <em>reqId</em> parameter present:</p>
<ul>
<li><a href="http://jansipke.nl/res/visualization/chart-data.py">http://jansipke.nl/res/visualization/chart-data.py</a></li>
</ul>
<ul>
<li><a href="http://jansipke.nl/res/visualization/chart-data.py?tqx=reqId%3A0">http://jansipke.nl/res/visualization/chart-data.py?tqx=reqId%3A0</a></li>
</ul>
<p>Notice that the first one does not have <em>reqId</em> present in the response, but the second one does.</p>
<p><strong>Update</strong>: it seems that the refreshing of data only happens correctly in Firefox and Opera. IE doesn&#8217;t refresh at all and Chrome only refreshes once. Oh joy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/using-google-visualization-api-with-own-data-source/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using XenServer in a routed IP network</title>
		<link>http://www.jansipke.nl/using-xenserver-in-a-routed-ip-network</link>
		<comments>http://www.jansipke.nl/using-xenserver-in-a-routed-ip-network#comments</comments>
		<pubDate>Sun, 28 Mar 2010 11:19:10 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Cloud computing]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=931</guid>
		<description><![CDATA[Hetzner is a hosting company in Germany where you can rent dedicated root servers per month. Using their KVM-over-IP setup, it is possible to install operating systems that are not available by default, such as XenServer by Citrix. With the machine, you get four public IP addresses. One of these addresses is given to you [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/xenserver.png"><img class="alignnone size-full wp-image-940" title="xenserver" src="http://www.jansipke.nl/wp-content/uploads/xenserver.png" alt="" width="327" height="61" /></a><br />
<a href="http://www.hetzner.de/">Hetzner</a> is a hosting company in Germany where you can rent dedicated root servers per month. Using their KVM-over-IP setup, it is possible to install operating systems that are not available by default, such as <a href="http://www.xensource.com/">XenServer</a> by <a href="http://www.citrix.com/">Citrix</a>. With the machine, you get four public IP addresses. One of these addresses is given to you when the machine is assigned to you, the other three are assigned to you on request.</p>
<p>There is a problem with the public IP addresses Hetzner gives you. Within the Hetzner network, there is a hard connection between the MAC address of your machine and the IP addresses you have been given. This is a problem for virtual machines that are bridged onto the network by the host machine. These virtual machines have their own MAC address and the Hetzner network will drop packets from these unknown MAC addresses.</p>
<p>There is a solution to this problem: have the host machine route IP packets from the virtual machines to the network and vice versa. We will use the following addresses in the example below:</p>
<table>
<tbody>
<tr>
<td>IP addresses</td>
<td>188.40.109.204 (host), 188.40.109.250 (VM)</td>
</tr>
<tr>
<td>Netmask</td>
<td>255.255.255.192</td>
</tr>
<tr>
<td>Gateway</td>
<td>188.40.109.193 (host)</td>
</tr>
<tr>
<td>DNS</td>
<td>213.133.100.100</td>
</tr>
</tbody>
</table>
<p>We start with the configuration of the host machine (running XenServer). The first file is the configuration file of eth0: /etc/sysconfig/network-scripts/ifcfg-eth0</p>
<blockquote>
<pre>XEMANAGED=yes
DEVICE=eth0
ONBOOT=no
TYPE=Ethernet
HWADDR=40:61:86:be:ce:88 (replace with MAC address of host)
BRIDGE=xenbr0
</pre>
</blockquote>
<p>Notice that this file does not contain any IP configuration. The second file is the configuration file of xenbr0: /etc/sysconfig/network-scripts/ifcfg-xenbr0</p>
<blockquote>
<pre>XEMANAGED=yes
DEVICE=xenbr0
ONBOOT=no
TYPE=Bridge
DELAY=0
STP=off
PIFDEV=eth0
BOOTPROTO=none
IPADDR=188.40.109.204 (replace with IP address of host)
NETMASK=255.255.255.192
GATEWAY=188.40.109.193 (replace with gateway of host)
DNS1=213.133.100.100
DNS2=213.133.99.99
DNS3=213.133.98.98
</pre>
</blockquote>
<p>Now we need to enable IP forwarding on the host machine. We start with the sysctl configuration file: /etc/sysctl.conf</p>
<blockquote>
<pre>net.ipv4.ip_forward=1
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv4.conf.xenbr0.send_redirects=0
</pre>
</blockquote>
<p>The first line tells the machine to perform IP forwarding. The four lines after that tell the machine to disable sending ICMP redirects. The last file we need to edit is the firewall configuration file: /etc/sysconfig/iptables. Add this text below the line -A RH-Firewall-1-INPUT -i lo -j ACCEPT:</p>
<blockquote>
<pre>-A RH-Firewall-1-INPUT -i xenbr0 -o xenbr0 -j ACCEPT
</pre>
</blockquote>
<p>Now reboot the machine and continue with the IP configuration of the virtual machine running on XenServer. There is only one file we need to edit here, which is the configuration file of eth0: /etc/sysconfig/network-scripts/ifcfg-eth0</p>
<blockquote>
<pre>DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
HWADDR=8e:35:1e:3b:12:aa (replace with MAC address of VM)
IPADDR=188.40.109.250 (replace with IP address of VM)
NETMASK=255.255.255.192
GATEWAY=188.40.109.204 (replace with IP address of host)
</pre>
</blockquote>
<p>The gateway in this configuration is crucial: it needs to be the IP address of the host itself, not the gateway of the host.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/using-xenserver-in-a-routed-ip-network/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating web charts using Open Flash Chart</title>
		<link>http://www.jansipke.nl/creating-web-charts-using-open-flash-chart</link>
		<comments>http://www.jansipke.nl/creating-web-charts-using-open-flash-chart#comments</comments>
		<pubDate>Wed, 24 Mar 2010 19:32:06 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Open Flash Chart]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=908</guid>
		<description><![CDATA[Open Flash Chart gives you the possibility to have Flash based charts on your website without the need to know Flash. All it takes is a JSON file that describes the chart. This JSON file can be a static file that you created yourself with a text editor or dynamically created by a program, e.g. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://teethgrinder.co.uk/open-flash-chart-2/">Open Flash Chart</a> gives you the possibility to have Flash based charts on your website without the need to know Flash. All it takes is a JSON file that describes the chart. This JSON file can be a static file that you created yourself with a text editor or dynamically created by a program, e.g. written in Java or Python.</p>
<p>There are several different types of charts that can be displayed. Some of them are shown here:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/charts1.png"><img class="alignnone size-full wp-image-925" title="charts1" src="http://www.jansipke.nl/wp-content/uploads/charts1.png" alt="" width="635" height="100" /></a><a href="http://www.jansipke.nl/wp-content/uploads/charts2.png"><img class="alignnone size-full wp-image-929" title="charts2" src="http://www.jansipke.nl/wp-content/uploads/charts2.png" alt="" width="617" height="100" /></a></p>
<p>We start by creating an HTML page that will contain the chart:</p>
<blockquote>
<pre>&lt;html&gt;
   &lt;head&gt;
      &lt;script type="text/javascript" src="<a href="view-source:http://www.jansipke.nl/tno/charts/swfobject.js">swfobject.js</a>"&gt;&lt;/script&gt;
      &lt;script type="text/javascript"&gt;
         swfobject.embedSWF("open-flash-chart.swf", "my_chart1", "600", "250",
                            "9.0.0", "expressInstall.swf", {"data-file":"chart1.data"});
      &lt;/script&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;div id="my_chart1"&gt;&lt;/div&gt;
   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>Then we create a JSON file called <em>chart1.data</em> that describes how the chart should look:</p>
<blockquote>
<pre>{
  "title":{
    "text":  "Bar Glass Chart",
    "style": "{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}"
  },

  "bg_colour": "#FFFFFF",

  "x_axis":
  {
    "stroke":      1,
    "tick_height": 10,
    "colour":      "#CCCCCC",
    "grid_colour": "#00ff00",
    "labels":
    {
      "labels": ["Server 1", "Server 2", "Server 3"]
    }
  },

  "y_axis":
  {
    "steps":       20,
    "tick_length": 100,
    "colour":      "#CCCCCC",
    "grid_colour": "#00FF00",
    "offset":      0,
    "max":         100
  },

  "elements":
  [
    {
      "type":      "bar_glass",
      "alpha":     0.5,
      "colour":    "#9933CC",
      "text":      "CPU load",
      "font-size": 10,
      "values" :   [90, 60, 70]
    },
    {
      "type":      "bar_glass",
      "alpha":     0.5,
      "colour":    "#CC9933",
      "text":      "Memory usage",
      "font-size": 10,
      "values" :   [60, 70, 90]
    }
  ]
}
</pre>
</blockquote>
<p>Copy the HTML file, the JSON file and the <em>open-flash-chart.swf</em> and <em>swfobject.js</em> files from the Open Flash Chart website to your own webserver and point your webbrowser to the HTML file. The result should look like the chart on <a href="/res/openflashchart/">this page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/creating-web-charts-using-open-flash-chart/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
