#!/usr/bin/env perl # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html # ##################################################### # # This script will read the CSM database and build # xCAT stanza files to be input into an xCAT database # using the chdef command # example node.stanza | chdef -z # ##################################################### use strict; use warnings; use Getopt::Long; use Data::Dumper; my $needhelp = 0; my $directory = "/tmp/csm2xcat"; if ( !GetOptions("help" => \$needhelp, "dir=s" => \$directory,) ) { &usage; exit 1; } if ($needhelp) { &usage; exit 0; } #Create the users choice directory mkdir $directory unless -d $directory; # create a log open(LOG, ">$directory/conversion.log") or die "Can't open logfile for writing: $!"; &log_this("Conversion started at " . scalar(localtime())); # build the stanza files for the site table # rsh/rcp attribute not longer supported. Leave logic here # incase we decide there are other attribute needed #&getSiteinfo; # build the stanza files for the node &getNodeinfo; # build the stanza files for the devices &getDevinfo; log_this("Conversion finished at " . scalar(localtime())); print "Conversion finished, please carefully review $directory/conversion.log and check results in the $directory stanza files before using chdef -z to update the database!\n"; close(LOG); exit 0; # end main # # logger # sub log_this { print LOG join('', @_), "\n"; } # # write to stanza files # sub write_stanza { print STANZA @_; } # # runs csmconfig or uses the csmconfig.output file # and builds site table stanza file # sub getSiteinfo { log_this("Reading Site information\n"); print "Running csmconfg to read site info!\n"; # open the site stanza file my $stanzafile = "$directory/site.stanza"; open(STANZA, ">$stanzafile") or die "Can't open $stanzafile for writing: $!"; write_stanza("# <xCAT data object stanza file>\n\n"); write_stanza("clustersite:\n"); write_stanza(" objtype=site\n"); my @results; my $cmd; # use of file is for debug my $csmconfiginfofile = "$directory/csmconfigdebug.output"; if (-e $csmconfiginfofile) { # use the imported file $cmd = "cat $csmconfiginfofile"; log_this("Reading $csmconfiginfofile information\n"); @results = runcmd($cmd); } else { # run the command $cmd = "/opt/csm/bin/csmconfig"; @results = runcmd($cmd); } if ($::RUNCMD_RC != 0) { my $msg = "Error processing csmconfig information\n"; log_this($msg); print "$msg"; close(STANZA); return; } foreach my $line (@results) { my $xcatline; $line =~ s/\s*//g; #remove extra blanks my ($attr, $value) = split(/=/, $line); if ($attr eq "RemoteShell") { if ($value) { $xcatline = " rsh="; $xcatline .= "$value\n"; } } if ($attr eq "RemoteCopyCmd") { if ($value) { $xcatline = " rcp="; $xcatline .= "$value\n"; } } if ($xcatline) { write_stanza($xcatline); } } close(STANZA); return 0; } # # runs lsnodes -l and build node stanza file # sub getNodeinfo { # open the node stanza file my $stanzafile = "$directory/node.stanza"; open(STANZA, ">$stanzafile") or die "Can't open $stanzafile for writing: $!"; write_stanza("# <xCAT data object stanza file\n"); log_this("Reading Node information\n"); print "Running lsnode -l for node info!\n"; my $OS = ""; my $GRP = ""; my $ARCH = ""; my $DISTNAME = ""; my @results; my $cmd; my $lsnodefile = "$directory/lsnodedebug.output"; # use of file is for debug if (-e $lsnodefile) { # use the imported file log_this("Reading $lsnodefile information\n"); $cmd = "cat $lsnodefile"; @results = runcmd($cmd); } else { # run the command $cmd = "/opt/csm/bin/lsnode -l"; @results = runcmd($cmd); } if ($::RUNCMD_RC != 0) { my $msg = "Error processing lsnode information\n"; log_this($msg); print "$msg"; close(STANZA); return; } # # build hash of lsnode info # my $output = buildNodehash(\@results); my %nodehash = %$output; my %attrhash; my $nodename; my $attributes; # my $test = $nodehash{"c55n03.ppd.pok.ibm.com"}{"PowerStatus"}; while (($nodename, $attributes) = each %nodehash) { # # build commonly needed attributes # %attrhash = %$attributes; # get osname, distribution name for later $OS = $attrhash{"InstallOSName"}; my $tmpname = $attrhash{"InstallDistributionName"}; $DISTNAME = lc($tmpname); my $pkgarch = $attrhash{"InstallPkgArchitecture"}; if ($pkgarch) { if ($OS eq "LINUX") { $ARCH = $pkgarch; # save arch } else { #AIX $ARCH = "ppc64"; } } # # first process the nodename # my $value; my $xcatline; my $attr; my $grplist = get_groups($nodename); if (!(grep /compute/, $grplist)) { $grplist .= ",compute"; } if (!(grep /all/, $grplist)) { $grplist .= ",all"; } $GRP = $grplist; # save for setting up other tables my $shortnodename = get_shortname($nodename); $xcatline = "$shortnodename:\n"; # write node name $xcatline .= " objtype=node\n"; if ($grplist) { $xcatline .= " groups=$grplist\n"; $xcatline .= " profile=compute\n"; } $xcatline .= " status=defined\n"; if ($xcatline) { write_stanza($xcatline); $xcatline = ""; } #now process all the attributes associated with the nodename #my $test = $attrhash{"InstallServer"}; #my $test1 = $attrhash{"Mode"}; while (($attr, $value) = each %$attributes) { #if ($attr eq "InstallServer") #{ # if ($value) # { # $xcatline = " xcatmaster=$value\n"; # $xcatline .= " servicenode=$value\n"; #} #} # since we are suggesting that the xCAT MN is a different machine # than the CSM MS, we will not use the Management Server value #if ($attr eq "ManagementServer") #{ # my $installserver = $attrhash{"InstallServer"}; # if ($installserver eq "") # if no install server, use MN # { # if ($value) # { # $xcatline = " xcatmaster=$value\n"; # } # } #} if ($attr eq "InstallOSName") { if ($value) { if ($value eq "AIX") { $xcatline = " os=$value\n"; $xcatline .= " arch=ppc64\n"; } } } if ($attr eq "InstallDistributionVersion") { if ( $value && $DISTNAME) # put together DistributeName and Version { $xcatline = " os=$DISTNAME"; $xcatline .= "$value\n"; } } if ($attr eq "InstallPkgArchitecture") # filled in for Linux { if ($value) { if ($OS eq "LINUX") { $xcatline = " arch=$value\n"; if ($value =~ /86/) { $xcatline .= " netboot=pxe\n"; } if ($value =~ /ppc/) { $xcatline .= " netboot=yaboot\n"; } } } } if ($attr eq "HWControlPoint") { if ($value) { $xcatline = " hcp=$value\n"; } } if ($attr eq "LParID") { if ($ARCH =~ /ppc/) { if ($value) { # this is an LPAR $xcatline = " id=$value\n"; $xcatline .= " nodetype=lpar\n"; } } } if ($attr eq "ConsoleMethod") { if ($value) { $xcatline = " cons=$value\n"; } } if ($attr eq "ConsolePortNum") { if ($value) { $xcatline = " termport=$value\n"; } } if ($attr eq "PowerMethod") { if ($value) { if ($value eq "xseries") { $value = "ipmi"; } $xcatline = " power=$value\n"; $xcatline .= " mgt=$value\n"; } } if ($attr eq "InstallAdapterMacaddr") { if ($value) { $xcatline = " mac=$value\n"; } } if ($attr eq "HWSerialNum") { if ($value) { $xcatline = " serial=$value\n"; } } if ($attr eq "ConsoleSerialSpeed") { if ($value) { $xcatline = " serialspeed=$value\n"; $xcatline .= " serialflow=hard\n"; # hardcoded } } if ($attr eq "ConsoleSerialDevice") { if ($value) { $xcatline = " serialport=$value\n"; } } if ($attr eq "ConsoleServerName") { if ($value) { $xcatline = " termserver=$value\n"; } } if ($xcatline) { write_stanza($xcatline); $xcatline = ""; } } $xcatline = "\n"; write_stanza($xcatline); $xcatline = ""; } close(STANZA); return 0; } # # runs lshwdev -l stanza file and builds node stanza file for xCAT # sub getDevinfo { # open the node stanza file my $stanzafile = "$directory/device.stanza"; open(STANZA, ">$stanzafile") or die "Can't open $stanzafile for writing: $!"; write_stanza("# <xCAT data object stanza file\n"); log_this("Reading Device information\n"); print "Running lshwdev -l for device info!\n"; my $MN; my $OS; my $hwmodel; my @results; my $cmd; my $HWMODEL = ""; # use of file is for debug my $lshwdevfile = "$directory/lshwdevdebug.output"; if (-e $lshwdevfile) { # use the imported file log_this("Reading $lshwdevfile information\n"); $cmd = "cat $lshwdevfile"; @results = runcmd($cmd); } else { # run the command $cmd = "/opt/csm/bin/lshwdev -l"; @results = runcmd($cmd); } if ($::RUNCMD_RC != 0) { my $msg = "Error processing lshwdev information\n"; log_this($msg); print "$msg"; close(STANZA); return; } # # build hash of lshwdev info # my $output = buildNodehash(\@results); my %nodehash = %$output; my %attrhash; my $nodename; my $attributes; while (($nodename, $attributes) = each %nodehash) { # # build commonly needed attributes # %attrhash = %$attributes; $HWMODEL = $attrhash{"HWModel"}; # # first process the devicename # my $value; my $xcatline; my $attr; my $grplist = get_dev_groups($nodename); my $shortnodename = get_shortname($nodename); $xcatline = "$shortnodename:\n"; # write node name $xcatline .= " objtype=node\n"; if ($grplist) { $xcatline .= " groups=$grplist\n"; } $xcatline .= " status=defined\n"; if ($xcatline) { write_stanza($xcatline); $xcatline = ""; } #now process all the attributes associated with the device while (($attr, $value) = each %$attributes) { if ($attr eq "DeviceType") { if ($value) { my $lcvalue = lc($value); $xcatline = " nodetype=$lcvalue\n"; if ($lcvalue eq "hmc") { $xcatline .= " mgt=$lcvalue\n"; } } } if ($attr eq "HWType") # put Model and type together { if ($value) { $xcatline = " mtm=$HWMODEL"; $xcatline .= "-"; $xcatline .= "$value\n"; } } if ($attr eq "HWSerialNum") { if ($value) { $xcatline = " serial=$value\n"; } } if ($attr eq "PhysicalLocation") { if ($value) { $xcatline = " room=$value\n"; } } if ($attr eq "Macaddr") { if ($value) { $xcatline = " mac=$value\n"; } } if ($xcatline) { write_stanza($xcatline); $xcatline = ""; } } $xcatline = "\n"; write_stanza($xcatline); $xcatline = ""; } close(STANZA); return 0; } # # change to short hostname for xCAT # if ip address, just return it # sub get_shortname { my $hostname = shift(); # if not ip address if ($hostname !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { my @shorthost = split(/\./, $hostname); return $shorthost[0]; } else { # return ip address return $hostname; } } # # get list of groups for input hostname # sub get_groups { my $hostname = shift(); my $grouplist; my @results; my $cmd; # use of file is for debug my $groupfile = "$directory/nodegrpdebug.output"; if (-e $groupfile) { # use the imported file $cmd = "cat $groupfile"; @results = runcmd($cmd); } else { # run the command $cmd = "/opt/csm/bin/nodegrp -s $hostname"; @results = runcmd($cmd); } foreach my $line (@results) { $grouplist .= $line; $grouplist .= ","; } chop $grouplist; # get rid of last comma return $grouplist; } # # get list of groups for input device # sub get_dev_groups { my $devname = shift(); my $grouplist; my $cmd; my @results; my $hwgroupfile = "$directory/hwdevgrpdebug.output"; if (-e $hwgroupfile) { # use the imported file $cmd = "cat $hwgroupfile"; @results = runcmd($cmd); } else { # run the command $cmd = "/opt/csm/bin/hwdevgrp -s $devname"; @results = runcmd($cmd); } foreach my $line (@results) { $grouplist .= $line; $grouplist .= ","; } chop $grouplist; # get rid of last comma return $grouplist; } # # build node hash. Build a hash of hashes, each entry # nodex=> { # attribute=>value # attribute=>value # . # # sub buildNodehash { my ($info) = @_; my @nodeinfo = @$info; my %nodehash; my $nodename; foreach my $line (@nodeinfo) { $line =~ s/\s*//g; #remove extra blanks my ($attr, $value) = split(/=/, $line); if (($attr eq "Hostname") || ($attr eq "Name")) { $nodename = $value; # set the hash key } else { # all other lines are part of hash $nodehash{$nodename}{$attr} = $value; } } return \%nodehash; } # # runs the input command and handles the errors. Returns the output # sub runcmd { my ($cmd) = @_; my $rc = 0; $::RUNCMD_RC = 0; my $outref = []; @$outref = `$cmd`; if ($?) { $rc = $? ; $::RUNCMD_RC = $rc; if ($rc > 0) { my $msg = "$cmd returned rc=$rc @$outref\n"; log_this($msg); print "$msg"; } } chomp(@$outref); return @$outref; } sub usage { print "CSM database to xCAT stanza files migration utility.\n"; print "Reads the CSM database and creates xCAT stanza files that \ncan be imported using the chdef command into the xCAT database.\n"; print "Usage:\n"; print "\t--help - usage\n"; print "\t--dir - output directory for stanza files.\n Default is /tmp/csm2xcat.\n"; print "\n"; return; }