Showing posts with label image. Show all posts
Showing posts with label image. Show all posts

Monday, May 23, 2011

Perl script to "copy" a Rackspace image


I recently found myself putting together a perl script that performs an rsync of one server in the Rackspace cloud to another server on another account.  Why?  See my next post about restrictions found with Rackspace for details.  Long story short, I needed a way to copy an image from one account to another and Rackspace recommends using rsync.

Since I will be needing to do this at least once a month for my testing, I thought it best to write up a script using perl that does the rsync.  The first thing was to figure out to successfully do this rsync before putting things together in a script.  I followed the instructions and when I rebooted my new server with the files rsync'ed over, it failed to accept ssh anymore.  On a whim, I decided to go through the basic exclude file from the instructions to see if those directories/files really lived where the file says they would be.

Ah-ha! That was my problem. I'm not sure which distro was used to create the exclude file, but some of the recommended files/directories to be excluded were located in different places.

#Suggested by Rackspace
/etc/hostname

#Actual location on Fedora 14 64bit
/bin/hostname
 

#Suggested by Rackspace
/etc/modules 

#Actual location on Fedora 14 64bit
/etc/sysconfig/modules

What I did was to do a
find / -name [sometext]

Where [sometext] I started from the end of the path and worked my way in to find the location. It was definitely trial and error.  Here is what I have for my final exclude file for Fedora 14 64bit:

#exclude.txt
/proc
/sys
/tmp
/dev
/root/copyImage.log
/root/.ssh/
/var/lock
/etc/fstab
/etc/mtab
/etc/resolv.conf
/usr/share/dbus-1/interfaces
/etc/networks
/etc/sysconfig/network
/etc/sysconfig/network-scripts
/etc/sysconfig/iptables-config
/lib/modules/
/usr/share/selinux/devel/include/kernel
/bin/hostname
/usr/lib64/gettext/hostname
/etc/hosts
/etc/modprobe*
/etc/selinux/targeted/modules
/etc/selinux/targeted/modules/active/modules
/etc/sysconfig/modules
/etc/selinux/targeted/modules
/etc/selinux/targeted/modules/active/modules
/usr/lib64/gio/modules
/lib/udev/devices/net
/usr/lib/ruby/1.8/net
/etc/init/

So now that I have a working exclude file, the next thing was to code up a perl script to do this for me.  In order to automate this through the script I needed to be able to:
  • Create an ssh tunnel from the "sending" server to the "receiving" server and be able to generate an ssh key on the "receiving" server.
  • Add the "sending" server's public key to the "receiving" server's authorized_key file
    • In my case, as part of the image, there is an authorized_key file with some public keys in it, which I want available to all servers generated with the image. I added the "sending" server's public key to this file and rsync'ed this file over first
  • Rsync the "sending" server data to the "receiving" server.
Two of the largest hurdle is:
  1. Open the ssh connection to the "receiving" server
  2. Know when the "receiving" server is asking for the password and supply it
There are many many perl modules available that do just this in various ways. I didn't think to make a note of which ones I did try, unfortunately.  I ended up using Net::OpenSSH, it had the best documentation and did everything I needed.  I used this in conjunction with Expect module.


Neither of these modules are included with the Perl package that comes with Fedora 14 64 bit.  In trying to add these modules, I learned some more things.  For example, I learned about CPAN.  This is a little piece of software that manages installation and dependency resolution for perl modules.  Other benefits I found are:
  • Access to modules that may not be in repos yet, i.e. Net::OpenSSH is not available via yum on Fedora 14
  • Type in instmodsh at the command prompt and you can see a list of all installed modules and get information about the modules
    • If module is installed via yum install , will not show up in instmodsh
Here is a link describing how to install CPAN.  After you follow the instructions at that link, you should also check to see if gcc is installed.  In my case, it was also not included in my default Fedora 14 64bit installation.  It is needed to compile some of the modules (in this case, one of the dependencies for Expect).  The error I got before I installed it is:

ERROR: cannot run the configured compiler 'gcc'
(see conf/compilerok.log). Suggestions:
1) The complier 'gcc' is not in your PATH. Add it
   to the PATH and try again. OR
2) The compiler isn't installed on your system. Install it. OR
3) You only have a different compiler installed (e.g. 'gcc').
   Either fix the compiler config in the perl Config.pm
   or install a perl that was built with the right compiler
   (you could build perl yourself with the available compiler).

Note: this is a system-administration issue, please ask your local
admin for help. Thank you.

Warning: No success on command[/usr/bin/perl Makefile.PL]
'YAML' not installed, will not store persistent state
  TODDR/IO-Tty-1.10.tar.gz
  /usr/bin/perl Makefile.PL -- NOT OK
Could not read metadata file. Falling back to other methods to determine prerequisites
Failed during this command:
 TODDR/IO-Tty-1.10.tar.gz                     : writemakefile NO '/usr/bin/perl Makefile.PL' returned status 6400

Finally, my last hurdle for putting together this script is trouble using the open function in perl.

#DOES *NOT* WORK
open(CAT_FILE,"cat /root/test.txt >>/root/test2.txt ") || die "Failed: $!\n";

#DOES WORK
open(CAT_FILE,"| cat /root/test.txt >>/root/test2.txt ") || die "Failed: $!\n";

Can you spot the difference?
So apparently that "|" is required ... oops...guess the documentation was right. *insert chagrin here*.

So without further ado, please find below my full script to do the rsync step of copying an image to another server on Rackspace: