Wednesday, March 25, 2009

Virtual Box - Resetting Virtual Hard Drive UUID

I wanted to create two RHEL5 VMs with VBox. So installed and setup one virtual machine and then remembering what I used to do with MS Virtual Machine, copied the virtual hard disk of the newly created VM to another location. Then from the VBox GUI I tried to add a new virtual machine by pointing it into an existing hard disk ( which is the newly copied VHD). And then I got this pop-up message:

Failed to open the hard disk D:\VirtualMachines\V-Cent5-3\Cent5-3.vdi.
Cannot register the hard disk 'D:\VirtualMachines\V-Cent5-3\Cent5-3.vdi' with UUID {5eaa4ad6-2742-480b-88f1-364b82c63c3d} because a hard disk 'D:\VirtualMachines\V-Cent5-2\Cent5-2.vdi' with UUID {5eaa4ad6-2742-480b-88f1-364b82c63c3d} already exists in the media registry ('C:\Documents and Settings\safeer\.VirtualBox\VirtualBox.xml').


Result Code: E_INVALIDARG (0x80070057)
Component: VirtualBox
Interface: IVirtualBox {779264f4-65ed-48ed-be39-518ca549e296}


A quick look into the vbox's xml configuration file told me that it keeps a unique id for each hard disk, and this is set within the virtual hard disk. So I started looking for a solution. The first one that came across while googling was to rgenerate the UUID of the newly copied hard disk as follows.

C:\Program Files\Sun\xVM VirtualBox>VBoxManage internalcommands setvdiuuid "D:\VirtualMachines\V-Cent5-3\Cent5-3.vdi"
VirtualBox Command Line Management Interface Version 2.2.0
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.


UUID changed to: 5eaa4ad6-2742-480b-88f1-364b82c63c3d

I just did this and voila, VBox accepted my copied hard disk without complaints. :) That did the trick, but later in another forum post I found out a better method of cloning an existing VHD, it will not only copy the generated hard disk to a specified location, but will also generate a new UUID for the disk.


C:\Program Files\Sun\xVM VirtualBox>VBoxManage clonehd "D:\VirtualMachines\V-Cent5-3\Cent5-3.vdi" "D:\VirtualMachines\V-Cent5-3\Cent5-4.vdi"
VirtualBox Command Line Management Interface Version 2.2.0
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.


0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone hard disk created in format 'VDI'. UUID: 7934dd80-0ce6-4530-b471-835af980190a


This looks more straight forward approach. But ofcourse the choice is yours.

Tuesday, March 24, 2009

Configuring NTP client for Cisco devices

Lot many things in Cisco devices depend on time, like certificates, time based ACLs and syslog messages. When it comes to time sources, Cisco devices are pretty much same as Computers. Most of them have a hardware clock as well as a software clock. We are concerned here only about the software clock as that is the time source used in the above mentioned scenarios.

We can manually set the time of hardware and software clocks in Cisco. To know about it, see my post about setting time in Cisco devices.

Here we would see how we can set an NTP server as the time source for a Cisco device.

R0(config)#ntp server 202.55.1.1

This will set the cisco device as a client of the NTP server 202.55.1.1, but there are a few more thing to configure if you want you network to be safe and efficient.

Authentication.

To prevent malicius/accidental setting of incorrect time from an unwanted NTP server, you should use NTP authentication using NTP "keys". There will be keys configured on the NTP server, which are basically string with a maximum length of 8 characters. The encryption scheme used to protect the key exchange is MD5.

Now enable NTP authentication first:

R0(config)#ntp authenticate
Now define the NTP server authentication key(s)
R0(config)#ntp authentication-key 1 md5 SeCrEt
R0(config)#ntp authentication-key 2 md5 TeRcEs

Here 1 and 2 are arbitrary numbers used as identifiers for each different keys. MD5 is the protocol used and the last argument of the command is the key itself ( This will be matching with the keys configured on the NTP server).

R0(config)#ntp trusted-key 1

This tells the device that the key "SeCrEt" that is stored locally is a trusted key which can be used for NTP authentication. Only trusted keys can be associated with an NTP server.

R0(config)#ntp server 202.55.1.1 key 1

This command associates the server 202.55.1.1 with the key "1" (SeCrEt).

This should be enough to set the authentication.

Reliability

What will happen if this NTP server goes down for a while? To deal with such a scenario you need additional NTP server which you can configure using the same command as above ( the key part may differ
though, depending on the key configured on that server).

So we introduce another server 202.55.2.1 which has and MD5 key "TeRcEs" configured.

R0(config)#ntp trusted-key 2
R0(config)#ntp server 202.55.2.2 key 2

Now we have a fail-over NTP server. But what if we need the NTP traffic to be served by 202.55.1.1 as long as it is up and running? and use the other one only if this host is down? You can specify a preferred server, which in this case will be 202.55.1.1

R0(config)#ntp server 202.55.1.1 key 1 prefer

This will make 202.55.1.1 preferred over the other NTP servers.

There are many more security features that you can configure to secure NTP, like enabling NTP messages to be received on selected interfaces and NTP access-group ACLs. I will detail them in another post.

Saturday, March 21, 2009

Perl Regular Expressions - Searching Array Without Loops

Iterating through arrays always require using of loops.  Array elements will be processed for many things but the most common one is searching for a particular element in an array.  If your purpose is to check whether a particular word is in the array elements, you can avoid using loops the following way.

The first thing to learn is a feature of perl arrays, ie;  if you enclose a perl array variable within double quotes it will be equivalent to a string containing all elements of the array separated by spaces.
Like this:

safeer@enjoyfast-lx:~/Scripts$ perl -e '@words=("tom","jerry","atom");print "@words\n"';
tom jerry atom

Now we have a string containing all the elements in the array.  All we need to do is match it against the search string.  If your seach term can be a substring of an array element,things are pretty easy.  You can directly match it agains the string converted array.
Like this:

if ( "$@words" =~ "jer" )
This will match the element jerry and the search will be successfull.  But if you are looking for an exact match of your search string with an array element, you will have to use a bit of regular expression techniques.  In this case we will have four different patterns.

1)  Array has multiple elements and the search string is the firrst element, in this case left hand side of the element will be begining of string ( denoted by "^") and the right hand side a space ( denoted by "\s").
2) Array has multiple elements and the search string is the last element, in this case left hand side of the element will be a space ( denoted by "\s") and  the right hand side be end of the string ( denoted by "$").
3) Array has multiple elements (>2)and the search string is somwhere in the middle of the string, in this case both side of the element will be space ("\s")
4) If the array has a single element, LHS of element will be start of string ("^") and RHS will be end of string ("$").

So a matching expression will look like:

if ( "@words" =~ /(^|\s)$searchterm(\s|$)/ )

Lets write a full script and try some options.  This script will accept search pattern from command line.

safeer@enjoyfast-lx:~/Scripts$ cat regex-search.pl
#!/usr/bin/perl -w
@words=("tom","jerry","atom");
if (defined $ARGV[0])
{
if ( "@words" =~ /(^|\s)$ARGV[0](\s|$)/)
{
print "Match!! \n";
}
else
{
print "No Match \n";
}
}
else
{
print "Provide a Search Term\n";
}

safeer@enjoyfast-lx:~/Scripts$ ./regex-search.pl tom
Match!!
safeer@enjoyfast-lx:~/Scripts$ ./regex-search.pl jerry
Match!!
safeer@enjoyfast-lx:~/Scripts$ ./regex-search.pl atom
Match!!
safeer@enjoyfast-lx:~/Scripts$ ./regex-search.pl jerr
No Match
safeer@enjoyfast-lx:~/Scripts$ ./regex-search.pl to
No Match


The flip side of this approach is that the search will fail if an array element has whitespace included in it.

Setting time in Cisco devices

Cisco devices have two clocks, one hardware and one software. By default the software clock is synced from the hardware one. But there are many things thing that we can modify for our environment.

To view the current time configured:

R0#show clock
*23:21:08.907 UTC Sun May 24 200

R0#show clock detail
*23:21:26.111 UTC Sun May 24 2009
Time source is hardware calendar

Set the software clock time:

R0#clock set 11:26:30 24 MAY 2009
R0#show clock
11:26:32.839 GMT Sun May 24 2009

To change your timezone:

R0(config)#clock timezone IST +5 30
R0(config)#do show clock
11:39:08.535 IST Sun May 24 2009

If you want to set the daylight savings, use command "clock summer-time" with correct options. See "clock summer-time ?"

To sync hardware and software clocks:

R0#clock read-calendar - Read the hardware calendar into the clock
R0#clock update-calendar - Update the hardware calendar from the clock

To view and set the hardware clock:

R0#show calendar
00:40:37 GMT Mon May 25 2009
R0#calendar set 11:45:30 24 MAY 2009

To set time via NTP, see my post about Cisco NTP client configuration