CentOS Cassandra init (start / stop) script

For CentOS I created an init script to start it at boot time and shut it down for rebooting or power off. If you want to use this init script for your own machine please look through the script and change the necessary parameters, e.g. CASSANDRA_HOME.

Please also note that in the stop function it decommissions the node from the cluster. This is probably not what you want in production environments.

#!/bin/bash
# chkconfig: 2345 99 01
# description: Cassandra

. /etc/rc.d/init.d/functions

CASSANDRA_HOME=/opt/apache-cassandra-0.7.4
CASSANDRA_BIN=$CASSANDRA_HOME/bin/cassandra
CASSANDRA_NODETOOL=$CASSANDRA_HOME/bin/nodetool
CASSANDRA_LOG=$CASSANDRA_HOME/log/cassandra.log
CASSANDRA_PID=/var/run/cassandra.pid
CASSANDRA_LOCK=/var/lock/subsys/cassandra
PROGRAM="cassandra"

if [ ! -f $CASSANDRA_BIN ]; then
  echo "File not found: $CASSANDRA_BIN"
  exit 1
fi

RETVAL=0

start() {
  if [ -f $CASSANDRA_PID ] && checkpid `cat $CASSANDRA_PID`; then
    echo "Cassandra is already running."
    exit 0
  fi
  echo -n $"Starting $PROGRAM: "
  daemon $CASSANDRA_BIN -p $CASSANDRA_PID >> $CASSANDRA_LOG 2>&1
  usleep 500000
  RETVAL=$?
  if [ $RETVAL -eq 0 ]; then
    touch $CASSANDRA_LOCK
    echo_success
  else
    echo_failure
  fi
  echo
  return $RETVAL
}

stop() {
  if [ ! -f $CASSANDRA_PID ]; then
    echo "Cassandra is already stopped."
    exit 0
  fi
  echo -n $"Stopping $PROGRAM: "
  $CASSANDRA_NODETOOL -h 127.0.0.1 decommission
  if kill `cat $CASSANDRA_PID`; then
    RETVAL=0
    rm -f $CASSANDRA_LOCK
    echo_success
  else
    RETVAL=1
    echo_failure
  fi
  echo
  [ $RETVAL = 0 ]
}

status_fn() {
  if [ -f $CASSANDRA_PID ] && checkpid `cat $CASSANDRA_PID`; then
    echo "Cassandra is running."
    exit 0
  else
    echo "Cassandra is stopped."
    exit 1
  fi
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status_fn
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo $"Usage: $PROGRAM {start|stop|restart|status}"
    RETVAL=3
esac

exit $RETVAL

If all looks alright, name the script cassandra and place it in /etc/init.d/
After that run the following commands:

mkdir /opt/apache-cassandra-0.7.4/log
chmod +x /etc/init.d/cassandra
chkconfig --add cassandra
service cassandra start

Deleting XenServer templates


Sometimes XenServer doesn’t allow you to delete templates from the XenCenter GUI or even the CLI. Here is how to delete templates from the CLI in three steps:

  • Tell XenServer the template is not a default template
  • Convert the template to a VM
  • Delete the VM
xe template-param-set other-config:default_template=false uuid=[uuid]
xe template-param-set is-a-template=false uuid=[uuid]
xe vm-destroy uuid=[uuid]

where [uuid] is the UUID of the template you want to delete.

Creating backups of running VMs in XenServer

With XenServer it is possible to create backups of VMs, even if they are running. The process is as follows:

  • Search for the uuid of the VMs to backup
  • Create a snapshot of each (running) VM
  • Save the snapshot to file
  • Remove the created snapshot

First look for the uuid of the VMs to backup. We don’t want to backup the control domain itself, so we add is-control-domain=false to the vm-list command:

xe vm-list is-control-domain=false

Now we create a snapshot of the VMs we want to backup, replacing the uuid one by one with the ones we found with the previous command. Also replace the name of the snapshot if desired:

xe vm-snapshot uuid=d61bfc1a-33b2-5406-7ea5-76e4f7113220 new-name-label=snapshotname

This command has a return value: the uuid of the created snapshot. Then we transform the snapshot into a VM to be able to save it to a file, replacing uuid with the return value of the previous command:

xe template-param-set is-a-template=false ha-always-run=false uuid=b759625c-eab5-4e0f-be5e-a05bcbad869a

In the next step we save the snapshot to a file, replacing uuid with the snapshot uuid and providing a meaningful filename:

xe vm-export vm=b759625c-eab5-4e0f-be5e-a05bcbad869a filename=filename.xva

In the final step we delete the snapshot:

xe vm-uninstall uuid=b759625c-eab5-4e0f-be5e-a05bcbad869a force=true

Python is installed by default on XenServer hosts, so the following script will work out of the box. Download the script from this location to save it to your XenServer host, replacing the .txt extension with .py.

#!/usr/bin/python

import commands, time

def get_backup_vms():
   result = []

   cmd = "xe vm-list is-control-domain=false"
   output = commands.getoutput(cmd)

   for vm in output.split("nnn"):
      lines = vm.split("n")
      uuid = lines[0].split(":")[1][1:]
      name = lines[1].split(":")[1][1:]
      result += [(uuid, name)]

   return result

def backup_vm(uuid, filename, timestamp):
   cmd = "xe vm-snapshot uuid=" + uuid + " new-name-label=" + timestamp
   snapshot_uuid = commands.getoutput(cmd)

   cmd = "xe template-param-set is-a-template=false ha-always-run=false uuid=" +
   snapshot_uuid
   commands.getoutput(cmd)

   filename = filename.replace(" ", " ")
   filename = filename.replace("(", "(")
   filename = filename.replace(")", ")")
   cmd = "xe vm-export vm=" + snapshot_uuid + " filename=" + filename
   commands.getoutput(cmd)

   cmd = "xe vm-uninstall uuid=" + snapshot_uuid + " force=true"
   commands.getoutput(cmd)

for (uuid, name) in get_backup_vms():
   timestamp = time.strftime("%Y%m%d-%H%M", time.gmtime())
   print timestamp, uuid, name
   filename = timestamp + " " + name + ".xva"
   backup_vm(uuid, filename, timestamp)

Assigning more than 8 virtual CPUs in XenServer


With the XenServer Windows client called XenCenter it is possible to manage multiple XenServer hosts, create virtual machines, watch the console of virtual machines, etc. One of the limitations I recently ran into (this is a luxury problem, I know) is that it doesn’t allow you to assign more than 8 virtual CPUs (vCPUs) to a single VM.

However, on the command line you can increase this value to 32 for Linux VMs. First, let’s see which uuid is assigned to the VM we want to give more than 8 vCPUs:

xe vm-list

Now make sure that the VM is halted and then use this uuid in the following commands:

xe vm-param-set VCPUs-max=32 uuid=replace_with_uuid
xe vm-param-set VCPUs-at-startup=32 uuid=replace_with_uuid

If you want to increase the memory size beyond 16GB as well, e.g. to 32GB, add the following commands:

xe vm-param-set memory-static-max=34359738368 uuid=replace_with_uuid
xe vm-param-set memory-dynamic-max=34359738368 uuid=replace_with_uuid
xe vm-param-set memory-dynamic-min=34359738368 uuid=replace_with_uuid
xe vm-param-set memory-static-min=34359738368 uuid=replace_with_uuid

Restart the VM and enjoy! For a quick look if everything worked out, watch the output of this command inside the VM:

cat /proc/cpuinfo | grep processor | wc -l

Changing CPU and memory settings on XenServer VMs

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 priority

You can set the weight 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 weight to 128, meaning that it will get half as much CPU as a normal virtual machine.

Map<String, String> vcpuParameters = new HashMap<String, String>();
vcpuParameters.put("weight", "128");
vm.setVCPUsParams(connection, vcpuParameters);

CPU limit

You can set the cap 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 cap 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.

Map<String, String> vcpuParameters = new HashMap<String, String>();
vcpuParameters.put("cap", "35");
vm.setVCPUsParams(connection, vcpuParameters);

Memory

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).

vm.setMemoryStaticMax(connection, new Long(1073741824));

Installing XenServer Tools on Ubuntu 10.04

XenServer supports a lot of Linux and Windows operating systems out of the box, but Ubuntu isn’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 thanks go to the author of the article “Ubuntu 10.04 LTS paravirtualised on Citrix XenServer” (link no longer available).

We start with creating and installing a VM with HVM.

  • Create a VM from the Other install media template
  • Attach the Ubuntu 10.04 ISO to the DVD drive of the VM
  • Start the VM
  • At the disk partitioning stage make sure to replace Ext4 with Ext3, or create a specific boot partition with Ext3
  • Select at least the OpenSSH server package to be able to log in to the VM remotely
  • Finish installation and boot the VM

We now create a new console and edit the boot settings.

  • Connect to the VM using SSH
  • Create a new console for Xen
sudo cp /etc/init/tty1.conf /etc/init/hvc0.conf
sudo vi /etc/init/hvc0.conf
  • Replace all occurrences of tty1 with hvc0
  • Read /boot/grub/grub.cfg
sudo vi /boot/grub/grub.cfg
  • Copy the contents of menuentry near the bottom to a temporary text file, to be used as input for the makepv.sh script that we will use later on
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
}
  • Make special note of /boot/vmlinuz…, root=UUID=… and /boot/initrd.img
  • Shutdown the VM

As an extra precaution, please create a snapshot of the current VM. If the next steps fail – for some people they do – you can revert easily to the VM you now have.

We now convert the VM to PV.

  • Connect to the XenServer host with SSH
  • Copy the makepv.sh script (download from here) to the XenServer host and make it executable
chmod +x makepv.sh
  • Run the makepv.sh script, replacing my-vm-name with the actual name of your VM
makepv.sh my-vm-name

Finally we install the XenServer tools.

  • Boot the VM and log in with SSH
  • In XenCenter, attach xs-tools.iso to the DVD drive of the VM
  • Mount xs-tools.iso, install the correct XenServer Tools package (replace amd64 with i386 if necessary) and unmount xs-tools.iso
sudo mount /dev/cdrom1 /mnt
sudo dpkg -i /mnt/Linux/xe-guest-utilities_5.5.0-466_amd64.deb
sudo umount /mnt
  • In XenCenter, detach xs-tools.iso from the DVD drive of the VM (this ensures that XenServer does not complain about too many bootable devices)
  • Reboot the VM and log in with SSH
  • Make sure the services run at boot time
sudo update-rc.d -f xe-linux-distribution remove
sudo update-rc.d xe-linux-distribution defaults
  • Reboot the VM for the last time
  • Restart XenCenter to be able to log in to the console of the VM

Getting CPU, memory, disk and network metrics from XenServer

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 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.

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.

Each physical machine has an HTTP interface at the following location:

http://machine_name_or_ip/rrd_updates?start=1234567890

The parameter start 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:

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());
}

The code needs two libraries:

  • commons-io-1.4.jar. This package contains the code to get a string containing the data of an inputstream.
  • xenserver-5.5.0-1.jar. This package contains the code to connect to the XenServer pool.

The following constants are used in this piece of code and need to be filled in:

  • MASTER_HOST. This is the IP address or hostname of the master host in the pool.
  • TIME_WINDOW. XenServer will return RRD updates of the last TIME_WINDOW seconds.
  • USERNAME and PASSWORD. These are the credentials for connecting to the master host and the other physical hosts in the pool.

At the end of this piece of code we have the string rrdXportData 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):

<xport>
   <meta>
      <start>1273342925</start>
      <step>5</step>
      <end>1273342980</end>
      <rows>13</rows>
      <columns>31</columns>
      <legend>
         <entry>AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0</entry>
         <entry>AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:vif_4_tx</entry>
         ...
      </legend>
   </meta>
   <data>
      <row>
         <t>1273342980</t>
         <v>0.0002</v>
         <v>0.0</v>
         ...
      </row>
      <row>
         <t>1273342975</t>
         <v>0.0003</v>
         <v>0.0</v>
         ...
      </row>
      ...
   </data>
</xport>

The following Java code will parse this RRD XML string and make it available in the four variables shown at the top. The variable metricsTimelines contains a hashmap of string to double[]. The string is the metric name (e.g. AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0) and the double[] contains the values for this metric from startTime to endTime with a step size of step. Note that the value at endTime is at position 0 and the value at  startTime is at the end of the array.

int endTime = 0;
HashMap<String, double[]> 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<ArrayList<String>> dataRows = new ArrayList<ArrayList<String>>();
   ArrayList<String> legends = new ArrayList<String>();
   NodeList xportChildNodes = doc.getDocumentElement().getChildNodes();
   for (int i = 0; i < xportChildNodes.getLength(); i++) {
      Node xportChildNode = xportChildNodes.item(i);
      if (xportChildNode.getNodeName().equals("meta")) {
         NodeList metaChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j < 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 < 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 < dataChildNodes.getLength(); j++) {
            Node rowNode = dataChildNodes.item(j);
            NodeList rowChildNodes = rowNode.getChildNodes();
            ArrayList<String> dataRow = new ArrayList<String>();
            for (int k = 1; k < 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<String, double[]>();
   for (int i = 0; i < nrLegends; i++) {
      metricsTimelines.put(legends.get(i), new double[nrDataRows]);
   }
   for (int i = 0; i < nrLegends; i++) {
      for (int j = 0; j < nrDataRows; j++) {
         double[] values = metricsTimelines.get(legends.get(i));
         values[j] = new Double(dataRows.get(j).get(i)).doubleValue();
      }
   }
} catch (Exception e) {
   e.printStackTrace();
}

Using XenServer in a routed IP network


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 when the machine is assigned to you, the other three are assigned to you on request.

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.

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:

IP addresses 188.40.109.204 (host), 188.40.109.250 (VM)
Netmask 255.255.255.192
Gateway 188.40.109.193 (host)
DNS 213.133.100.100

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

XEMANAGED=yes
DEVICE=eth0
ONBOOT=no
TYPE=Ethernet
HWADDR=40:61:86:be:ce:88 (replace with MAC address of host)
BRIDGE=xenbr0

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

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

Now we need to enable IP forwarding on the host machine. We start with the sysctl configuration file: /etc/sysctl.conf

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

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:

-A RH-Firewall-1-INPUT -i xenbr0 -o xenbr0 -j ACCEPT

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

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)

The gateway in this configuration is crucial: it needs to be the IP address of the host itself, not the gateway of the host.

Getting XenServer VM metrics in Java

XenServer is a product of Citrix that can run virtual machines on a set of physical hosts called a pool. There is an API that allows you to create programs that interact with the XenServer pool. There are some function calls that return metrics of the virtual machines and the physical hosts.

Let us have a look at retrieving the CPU load of a virtual machine (VM). This can be accomplished with the following API call (assuming that vm is of type com.xensource.xenapi.VM and connection is of type com.xensource.xenapi.Connection):

vm.getMetrics(connection).getVCPUsUtilisation(connection)

However, as many have noted, the answer is always 0.0. As of XenServer version 5.5, the way these metrics are stored has changed. The preferred way to get VM metrics now, is to make a direct HTTP call to the physical hosts. This call will return RRD XML files. This makes things more difficult because now there are multiple calls to make, one to the XenServer API and one call per physical host machine. And one needs to dig into these files to get the CPU load, instead of having the value returned in a single call.

There is a way to make the XenServer API behave like it did in version 5.0 and prior. We start by logging into the console of a physical machine and entering:

xe host-list

Note the UUID values of all the physical host machines. Now enter the following command for each UUID:

xe host-param-set uuid=<uuid found in previous command> other-config:rrd_update_interval=1

Now reboot all physical host machines and the VM metric command will work like a charm.

Top cloud computing providers

Although there are lots of different letters you can put in front of “as a service”, there are typically three that everybody agrees about. The following picture sums these up:

In this article we will look into some of the top providers in these three areas.

Infrastructure as a Service (IaaS) providers

Amazon

One of the biggest and most well known in this category is Amazon with its Elastic Compute Cloud (EC2). It of course started out as a company selling books, CD’s and DVD’s through the internet, but they realized that a lot of their computing resources were doing nothing most of the time, just waiting for the holiday season to hit its peak. Renting this capacity to others through the internet turned out to be a very good business model. Their current portfolio is really big and diverse, which makes it a bit daunting to start using it.

Rackspace

Another big player in this area is Rackspace. They started out as a regular hosting provider, renting out space in their racks, providing managed hosting and dedicated servers. In the last year they have moved into the cloud business as well and are doing just fine. One of the things might just be that their offering is more understandable than Amazon’s and their lowest prices are a lot better as well.

Joyent

Third on our list is Joyent. This company has been delivering cloud computing services even before the term was there to describe it. Their portfolio is quite big, and it is not limited to IaaS either. They do seem to lack in public relations, because they are not as well known as the first two IaaS players.

GoGrid

Fourth on our list is GoGrid. Like the other IaaS providers, GoGrid offers virtual machines to be rented by the hour, but they also offer dedicated servers for specific tasks that tend to be slow on virtual machines, such as databases. They call this setup a hybrid cloud, but this seems to be confusing because this term is also used for a mixture of a private and a public cloud.

Terremark

The final name on our list of IaaS providers is Terremark. They target two different types of users: the type that wants to have resources available quickly without a lot of hassle, and the type that wants to have a solid and secure environment that can run enterprise applications. For the second type of user, they provide dedicated resource pools and integration with private networks.

Platform as a Service (PaaS) providers

Google

The company with probably the biggest cloud of its own, also provides cloud services in the form of PaaS. Google App Engine is a framework that allows you to build software in Python or Java that is automatically distributed and scaled as necessary on the cloud. If you have the luxury of writing new applications in one of these two languages and want to adhere to the Google way of programming, this is one to take a look at.

Microsoft

Another really big name in this area is Microsoft. With their Azure platform, they want to give Visual Studio programmers the ability to build software for the cloud as easily as for real servers in the datacenter. There are currently two types of cloud service: Windows Azure, the operating system as an online service, and SQL Azure, a fully relational cloud database solution. If you are familiar with the Microsoft development tools and want to take the cloud for a spin, this is where yo start.

Force.com

Last on our list of PaaS providers is force.com. Created by salesforce.com, the company that grew big by providing software on demand. They started out with subscription fees, but are moving to a pay-as-you-go model. Force.com is a development platform that allows users to build business applications in the cloud. If you are willing to create software that only works in the force.com cloud, this is a simple start into cloud computing.

Software as a Service (SaaS) providers

Google

First on our list is Google Apps, not because they have the widest range of applications, but because they are probably the best known for their web-based offerings. These include of course their e-mail service, calendar, document editor, spreadsheet, and some others.

Salesforce.com

Second on our list is salesforce.com. They provide CRM software on-demand and started out with subscription fees, but are moving to a pay-as-you-go model. Currently they offer two SaaS services: Sales cloud and Service cloud. The first contains accounts, contacts,  leads, quotes, etc. The second contains a customer portal, knowledge base, analytics, etc.

Zoho

Last on our list is zoho.com. This company might be less known than Google and salesforce.com, but they offer much more types of applications that you can try out for free. These include an e-mail service, document editor, presentation tool, invoicing, reporting, applicant tracking, and many more. You only start paying for these services when you want to use the more advanced features.