Thursday, July 22, 2010

How to get Virtual Manager to work for a Xen host

So, continuing with the theme of Xen, Virtual Machine Manager or virt-manager for short, is a piece of software that I decided to check out because I wanted graphical access to my virtual machines. A more formal description as given on their website is:
"Virt-manager is a desktop user interface for managing virtual machines. It presents a summary view of running domains, their live performance & resource utilization statistics. The detailed view graphs performance & utilization over time. Wizards enable the creation of new domains, and configuration & adjustment of a domain's resource allocation & virtual hardware. An embedded VNC client viewer presents a full graphical console to the guest domain"
You need to download virt-manager on the machine from which you wish to access your virtual machines. I am using a machine running Ubuntu 10.04 which I will call the client machine in the description below.

My Virtual Machines (VMs) were created on top of Xen 3.2 hypervisor, Earlier I had some issues getting the network up and running on my VMs, the resolution of which I have described in an earlier post. My hypervisor machine which I will call my host machine is running kernel 2.6.24-24-xen.

So here is the procedure that I followed to get virt-manager to work:
  1. I used the Synaptic Package Manager (System->Administration->Synaptic Package Manager to download virt-manager and all the dependencies on my client machine. Alternatively, one could also do sudo apt-get install virt-manager

  2. On my host machine, I downloaded and installed libvirt-bin and ssh-askpass
    sudo apt-get install libvirt-bin
    sudo apt-get install ssh-askpass

  3. Now to access the virt-manager console from my client machine I used Application->System Tools->Virtual Machine Manager

  4. On my host machine, I started the libvirtd daemon:
    sudo libvirtd start

  5. At this point I tried to connect to my host machine using File->Add Connection...; I chose my specific hypervisor (Xen) and Connection as Remote Tunnel over SSH (I am not sure that this is the one that I was supposed to use, but it did work, eventually!)
    At this point, I got the following error on a pop-up on my client machine and on the console of my host machine:
    libvir: Xen Daemon error :internal error failed to connect to xend
    After some effort, the following fix worked:

    1. Open the xend configuration file
      sudo vim /etc/xen/xend-config.sxp

    2. In my previous post I had talked about adding a temporary bridge between physical network device and the virtual TAP device. I had to let the xend daemon become aware of this. So under the line:
      (network-script network-bridge)
      I added:
      (network-script 'network-bridge netdev=tmpbridge')
      (To recall what my network device is called, I did a ifconfig. It was the one whose description contains the domain-0's IP.

    3. I was not done with this file yet. I needed to add the following line somewhere in the file:
      (xend-unix-server yes)

    4. I saved and closed the file. Restarted the host machine's network (sudo /etc/init.d/networking restart), restarted the xend daemon (sudo xend restart), and finally restarted the libvirtd daemon( sudo libvirtd start)

    Now when I tried to add the connection using the setting mentioned above, it went through, asked me for a password and I would see a table giving the details of the CPU utilization and some other statistics of my VMs. Following is a screen shot of what I can see so far:


No network on Xen user domain

Today I installed Xen 3.2 for my work and created a guest VM using the this link as a guide. However I found that the network on my VM didn't work. The problem as Pierre explained was that the link between my physical network device and the virtual TAP device was not set up.

This was in spite of the fact that I re-started the xend daemon on my machine and used the static IP address method that was recommended in the blog mentioned above.So it seems that the xm create and xend scripts are not doing what they are supposed to do!

David Wolinsky came up with the following fix:
On the console of your control domain, do the following:
$ brctl addif tmpbridge eth0
$ ifup tmpbridge
$ ifconfig eth0 0.0.0.0 promisc
$ brctl show
$ dhclient tmpbridge

Now when you do an ifconfig on you domain-0, the tmpbridge interface should show up with the IP that was originally assigned to eth0.

And since eth0 is set to "promiscuous" mode, it will accept all network packages coming to it.

Now using the route command find the default gateway used by your domain-0. The following terminal snapshot is provided to clarify which IP I am talking about:

user@Domain0:~$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.5.144.0 * 255.255.240.0 U 0 0 0 tmpbridge
default 10.5.144.1 0.0.0.0 UG 0 0 0 tmpbridge


In the last line, the default gateway is highlighted in red. Make a note of this IP.
Now open the console of your user domain and check the route:

root@UserDomain:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.5.144.0 * 255.255.240.0 U 0 0 0 eth0

As you can see, in my case the default gateway was not set. To do so use the route add default gw command and the IP we obtained from the default gateway of domain-0.

root@UserDomain:~# route add default gw 10.5.144.1

Verify using route, and then try pinning something:

root@UserDomain:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.5.144.0 * 255.255.240.0 U 0 0 0 eth0
default 10.5.144.1 0.0.0.0 UG 0 0 0 eth0
root@UserDomain:~# ping google.com
PING google.com (72.14.253.104) 56(84) bytes of data.
64 bytes from mia04s03-in-f104.1e100.net (72.14.253.104): icmp_seq=1 ttl=56 time=15.5 ms
64 bytes from mia04s03-in-f104.1e100.net (72.14.253.104): icmp_seq=2 ttl=56 time=14.0 ms
64 bytes from mia04s03-in-f104.1e100.net (72.14.253.104): icmp_seq=3 ttl=56 time=13.9 ms



Dadaaa! Many thanks to Pierre and David!
As a side note, if you are adding more domains, you do not need to repeat all the commands on domain-0, as its interface is already in the "promiscuous" mode. Only run the dhclient again. You will however need to set up the default gateway in every new domain that you create.

Tuesday, May 25, 2010

Disable Sudo password prompts on Ubuntu

A simple trick to disable the sudo password prompts on Ubuntu (I have tested this on Ubuntu 9.10 Karmic Koala). A word of caution, be aware that by doing this you are sacrificing the security that sudo provides.

You basically need to edit the /etc/sudoers file. This file cannot be changed by any user. You need to sign in as root and then use the visudo command to start editing the file.

user@machine:~$ sudo su
[sudo] password for user:
root@machine:/home/user# visudo

In this file, right at the bottom you will find a line:
%admin ALL=(ALL) ALL

Replace it with:
%admin ALL=NOPASSWD: ALL

This will disable the requirement to enter the password every time you run a sudo command. Save and close (ESC, :wq, ENTER)

So you can now run a command like sudo reboot without having to enter the password:

user@machine:~$ sudo reboot

Broadcast message from user@machine
(/dev/pts/0) at 11:17 ...

The system is going down for reboot NOW!

Again, be careful and know what you are doing. Also, it might be a good idea to make a copy of your /etc/sudoers file before your make any changes to it.

One way to use this trick could be in a scenario where you want to run a sudo command through a script and do not want to use the -S option of sudo (-S option allows you to provide the password from the script itself; this can be dangerous if someone gets access to your script)


Thursday, May 20, 2010

Bash chit-sheet

Some simple tricks that can make bash scripting a breeze:
  1. To truncate a float to int:
    INT=${FLOAT/\.*}


  2. To split a string (of 2 words) into its components:
    FIRST_WORD=${STRING%% *},SECOND_WORD=${STRING#* }


  3. To do simple floating point arithmetic, use bc:
    AVERAGE=$(echo "scale=2; ($FLOAT1 + $FLOAT2 ) / 2" | bc )


  4. Conditional if statement:
    if [[ $INT1 -gt $INT2 ]]; then echo greater; fi


  5. To check the number of arguments for a bash script and to issue an error message if the number of arguments if insufficient, use the following code snippet at the top of the script:
    EXPECTED_ARGS=2
    E_BADARGS=65
    if [ $# -ne $EXPECTED_ARGS ]; then
    echo "Usage: ./script_name arg1 arg2"
    echo " Example: ./sum 1 2"
    exit $E_BADARGS
    fi



  6. To find the process ID of a running process, use pgrep:
    pgrep -fl PROCESS_NAME


  7. To kill a process using the process name instead of the process ID, use:
    kill $(ps -ef |grep PROCESS_NAME | grep -v grep | awk '{print $2}')


  8. Find files that contain a text string:
    grep -lir "text to find" *
    The -l switch outputs only the names of files in which the text occurs (instead of each line containing the text), the -i switch ignores the case, and the -r descends into subdirectories.


Wednesday, May 19, 2010

Clock source and NTP control

To view the available clocksource options for your machine, look into the /sys/devices/system/clocksource/clocksource0 directory. This directory also shows the current clock source that your machine is using. You will need sudo privileges to access this information:

user@machine:/sys/devices/system/clocksource/clocksource0$ sudo more available_clocksource
tsc hpet acpi_pm pit jiffies
user@machine:/sys/devices/system/clocksource/clocksource0$ sudo more current_clocksource
hpet

Usually, your machine will pick the "best" clock source from the available options at start up, but if you want to force the selection of a particular clock source, you can do this by including the desired option in the configuration file that the system uses at the time of start-up, namely /boot/grub/menu.lst

user@machine:/boot/grub$ sudo vim menu.lst

Add the clock source option at the end of the line declaring the kernel path, as shown below:

title Ubuntu 8.04.3 LTS, kernel 2.6.24-26-generic
root (hd0,0)
kernel /boot/vmlinuz-2.6.24-26-generic root=UUID=cea24a64-f038-469c-b716-226ab0da2f93 ro quiet splash clocksource=tsc
initrd /boot/initrd.img-2.6.24-26-generic
quiet

Save and restart your machine. The desired clock source should show up in the /sys/devices/system/clocksource/clocksource0/current_clocksource file.

To start/stop or restart the ntp demon on your machine from the command line, do:
user@machine$ sudo /etc/init.d/ntp stop
[sudo] password for user:
* Stopping NTP server ntpd [ OK ]

Thursday, May 6, 2010

Add commands to bash

This post is about adding user defined commands to bash so that you can run applications only using the command rather than specifying the whole path of the application executable.

The code provided here has been tested on Ubuntu 9.10 (Karmic Koala).

There are two ways to accomplish the mission, the first is to put your application is the default path that bash already looks into while trying to execute your command, and the second is to add another location as a path that bash must check.

For the first option, run $PATH in the terminal. Your terminal output would look something like

bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

If you put your scripts/executables in any of the above locations, bash will find it and execute it without you having to specify the whole path.

For the second option, you need to edit the ~/.bashrc file and add the location of the executable to the PATH locations. Suppose this location is /home/pbhat/bin/. Concatenate the following line to the end of ~/.bashrc file.

PATH=$PATH:/home/pbhat/bin
export PATH

Save and close the file and now run the following command in the terminal:
source ~.bashrc

Unless you run this command the updated path will not show up.

Inflate multiple files with one command

If you have many multiple archives which have been compressed using different encryptions (tar, tar.gz or zip) in one directory, you can use the script provided in this post to inflate them into the directories with the same name as the original archive, that is:

file1.zip will get inflated to file1/
file2.tar will get inflated to file2/
file3.tar.gz will get inflated to file3/

So here is the script:

#!/bin/bash

cd $1

for i in $(ls)
do
dir_name=$(echo $i | sed "s/\([^.]*\)[.].*/\1/")

if [[ "$i" =~ "zip" ]]; then
mkdir -p $dir_name
cd $dir_name;
unzip $i
cd ../
elif [[ "$i" =~ "tar.gz" ]]; then
mkdir -p $dir_name
cd $dir_name
tar -xzvf ../$i
cd ../
elif [[ "$i" =~ "tar" ]]; then
mkdir -p $dir_name
cd $dir_name
tar -xvf ../$i
cd ../
fi
done

The argument to this code is the full path of the directory that contains the archived files. Notice that the script searches for the strings, "tar", "zip" and "tar.gz" in the filenames. If you have other files in the directory which contain these strings in their names, they can get overwritten!

You can save the script using a name of your choice (I have named it open.sh, as indicated in the terminal output shown below)

terminal$ ls directory_path/
file1.tar file2.zip file3.tar.gz
terminal$ ./open.sh directory_path/
terminal$ ls directory_path/
file1 file1.tar file2 file2.zip file3 file3.tar.gz

I would like to thank Girish Venkatasubramanian for advice on this script.