diff --git a/README b/README new file mode 100644 index 000000000..0696fd032 --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +xCAT - eXtreme Cloud Administration Toolkit + +xCAT is a toolkit for the deployment and administration of clusters. + +xCAT documentation is available at: http://xcat.sourceforge.net/ + +xCAT is made available as open source software under the EPL license: +http://www.opensource.org/licenses/eclipse-1.0.php + + + + + + diff --git a/build-ubunturepo b/build-ubunturepo index b2b4e0e31..d2d81d47d 100755 --- a/build-ubunturepo +++ b/build-ubunturepo @@ -86,7 +86,7 @@ if [ "$c_flag" -a "$d_flag" ];then exit 2 fi -uploader="bp-sawyers" +uploader="ligc" # Find where this script is located to set some build variables old_pwd=`pwd` cd `dirname $0` @@ -194,7 +194,7 @@ then if [ ! -d ../../$package_dir_name ];then mkdir -p "../../$package_dir_name" fi - packages="xCAT-client xCAT-genesis-scripts perl-xCAT xCAT-server xCAT-UI xCAT xCATsn xCAT-test xCAT-OpenStack" + packages="xCAT-client xCAT-genesis-scripts perl-xCAT xCAT-server xCAT-UI xCAT xCATsn xCAT-test xCAT-OpenStack xCAT-OpenStack-baremetal" for file in `echo $packages` do @@ -279,7 +279,7 @@ __EOF__ cat << '__EOF__' > mklocalrepo.sh . /etc/lsb-release cd `dirname $0` -echo deb file://"`pwd`" $DISTRIB_CODENAME main > /etc/apt/sources.list.d/xcat-core.list +echo deb [arch=amd64] file://"`pwd`" $DISTRIB_CODENAME main > /etc/apt/sources.list.d/xcat-core.list __EOF__ chmod 775 mklocalrepo.sh @@ -380,7 +380,7 @@ __EOF__ cat << '__EOF__' > mklocalrepo.sh . /etc/lsb-release cd `dirname $0` -echo deb file://"`pwd`" $DISTRIB_CODENAME main > /etc/apt/sources.list.d/xcat-dep.list +echo deb [arch=amd64] file://"`pwd`" $DISTRIB_CODENAME main > /etc/apt/sources.list.d/xcat-dep.list __EOF__ chmod 775 mklocalrepo.sh diff --git a/buildcore.sh b/buildcore.sh index 7548391a1..78fda6928 100755 --- a/buildcore.sh +++ b/buildcore.sh @@ -41,11 +41,13 @@ UPLOADUSER=bp-sawyers FRS=/home/frs/project/x/xc/xcat # These are the rpms that should be built for each kind of xcat build -ALLBUILD="perl-xCAT xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit xCAT xCATsn xCAT-genesis-scripts xCAT-OpenStack" +ALLBUILD="perl-xCAT xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit xCAT xCATsn xCAT-genesis-scripts xCAT-OpenStack xCAT-SoftLayer xCAT-OpenStack-baremetal" ZVMBUILD="perl-xCAT xCAT-server xCAT-UI" ZVMLINK="xCAT-client xCAT xCATsn" -PCMBUILD="xCAT" -PCMLINK="perl-xCAT xCAT-client xCAT-server xCAT-buildkit xCAT-genesis-scripts-x86_64" +# xCAT has PCM specific configuration - conserver-xcat, syslinux-xcat +# xCAT-server has PCM specific configuration - RESTAPI(perl-JSON) +PCMBUILD="xCAT xCAT-server" +PCMLINK="perl-xCAT xCAT-client xCAT-buildkit xCAT-genesis-scripts-x86_64" # Note: for FSM, the FlexCAT rpm is built separately from gsa/git FSMBUILD="perl-xCAT xCAT-client xCAT-server" FSMLINK="" @@ -237,10 +239,11 @@ if [ "$OSNAME" = "AIX" ]; then fi # Build the rest of the noarch rpms -for rpmname in xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit; do +for rpmname in xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit xCAT-SoftLayer; do #if [ "$EMBED" = "zvm" -a "$rpmname" != "xCAT-server" -a "$rpmname" != "xCAT-UI" ]; then continue; fi # for zvm embedded env only need to build server and UI if [[ " $EMBEDBUILD " != *\ $rpmname\ * ]]; then continue; fi if [ "$OSNAME" = "AIX" -a "$rpmname" = "xCAT-buildkit" ]; then continue; fi # do not build xCAT-buildkit on aix + if [ "$OSNAME" = "AIX" -a "$rpmname" = "xCAT-SoftLayer" ]; then continue; fi # do not build xCAT-SoftLayer on aix if $GREP $rpmname $GITUP || [ "$BUILDALL" == 1 ]; then UPLOAD=1 maker $rpmname @@ -272,19 +275,19 @@ if [ "$OSNAME" != "AIX" ]; then fi # Build the xCAT and xCATsn rpms for all platforms -for rpmname in xCAT xCATsn xCAT-OpenStack; do +for rpmname in xCAT xCATsn xCAT-OpenStack xCAT-OpenStack-baremetal; do #if [ "$EMBED" = "zvm" ]; then break; fi if [[ " $EMBEDBUILD " != *\ $rpmname\ * ]]; then continue; fi if [ $SOMETHINGCHANGED == 1 -o "$BUILDALL" == 1 ]; then # used to be: if $GREP -E "^[UAD] +$rpmname/" $GITUP; then UPLOAD=1 ORIGFAILEDRPMS="$FAILEDRPMS" if [ "$OSNAME" = "AIX" ]; then - if [ "$rpmname" = "xCAT-OpenStack" ]; then continue; fi # do not bld openstack on aix + if [ "$rpmname" = "xCAT-OpenStack" ] || [ "$rpmname" = "xCAT-OpenStack-baremetal" ]; then continue; fi # do not bld openstack on aix ./makerpm $rpmname "$EMBED" if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname"; fi else for arch in x86_64 ppc64 s390x; do - if [ "$rpmname" = "xCAT-OpenStack" -a "$arch" != "x86_64" ]; then continue; fi # only bld openstack for x86_64 for now + if [ "$rpmname" = "xCAT-OpenStack" -a "$arch" != "x86_64" ] || [ "$rpmname" = "xCAT-OpenStack-baremetal" -a "$arch" != "x86_64" ] ; then continue; fi # only bld openstack for x86_64 for now ./makerpm $rpmname $arch "$EMBED" if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname-$arch"; fi done @@ -496,6 +499,7 @@ if [ "$OSNAME" != "AIX" -a "$REL" = "devel" -a "$PROMOTE" != 1 -a -z "$EMBED" ]; rpm2cpio ../$XCATCORE/xCAT-test-*.$NOARCH.rpm | cpio -id '*.html' rpm2cpio ../$XCATCORE/xCAT-buildkit-*.$NOARCH.rpm | cpio -id '*.html' rpm2cpio ../$XCATCORE/xCAT-OpenStack-*.x86_64.rpm | cpio -id '*.html' + rpm2cpio ../$XCATCORE/xCAT-SoftLayer-*.$NOARCH.rpm | cpio -id '*.html' i=0 while [ $((i+=1)) -le 5 ] && ! rsync $verboseflag -r opt/xcat/share/doc/man1 opt/xcat/share/doc/man3 opt/xcat/share/doc/man5 opt/xcat/share/doc/man7 opt/xcat/share/doc/man8 $UPLOADUSER,xcat@web.sourceforge.net:htdocs/ do : ; done diff --git a/buildlocal.sh b/buildlocal.sh new file mode 100755 index 000000000..197f55f54 --- /dev/null +++ b/buildlocal.sh @@ -0,0 +1,160 @@ +####################################################################### +#build script for local usage +#used for Linux/AIX/Ubuntu +# +########################################################################### + + +OSNAME=$(uname) +NAMEALL=$(uname -a) + +for i in $*; do + # upper case the variable name + varstring=`echo "$i"|cut -d '=' -f 1|tr '[a-z]' '[A-Z]'`=`echo "$i"|cut -d '=' -f 2` + export $varstring +done + +if [ -z "$CURDIR" ]; then + echo "get current directory!" + CURDIR=$(pwd) +fi + +echo "CURDIR is $CURDIR" +echo "OSNAME is $OSNAME!" +echo "NAMEALL is $NAMEALL" + +grep -i 'SUSE' /etc/issue +if [ $? -eq 0 ]; then + echo "This is a SUSE system!" + OS="SUSE"; +fi + + +ls $CURDIR/makerpm + +if [ $? -gt 0 ]; then + echo "Error:no repo exist, exit 1." + exit 1 +fi + +# Get a lock, so can not do 2 builds at once +exec 8>/var/lock/xcatbld.lock +if ! flock -n 8; then + echo "Can't get lock /var/lock/xcatbld.lock. Someone else must be doing a build right now. Exiting...." + exit 1 +fi + +#delete old package if there is +rm -rf $CURDIR/build/ +cd $CURDIR + +echo "===============================================" +echo $NAMEALL | egrep "Ubuntu" + +#Check if it is an Ubuntu system +if [ $? -eq 0 ]; then + +echo "This is an Ubuntu system" + pkg_type="snap" + build_string="Snap_Build" + cur_date=`date +%Y%m%d` + short_ver=`cat Version|cut -d. -f 1,2` + pkg_version="${short_ver}-${pkg_type}${cur_date}" + + mkdir -p $CURDIR/build + + for rpmname in xCAT-client xCAT-genesis-scripts perl-xCAT xCAT-server xCAT xCATsn xCAT-test; do + rpmname_low=`echo $rpmname | tr '[A-Z]' '[a-z]'` + echo "============================================" + echo "$rpmname_low" + cd $rpmname + dch -v $pkg_version -b -c debian/changelog $build_string + dpkg-buildpackage -uc -us + rc=$? + if [ $rc -gt 0 ]; then + echo "Error: $rpmname build package failed exit code $rc" + fi + cd - + mv ${rpmname_low}* $CURDIR/build + + done + #delete all files except .deb file + find $CURDIR/build/* ! -name *.deb | xargs rm -f + +else +#This is not an Ubuntu system +echo "This is an $OSNAME system" + + if [ "$OS" = "SUSE" ]; then + rm -rf /usr/src/packages/RPMS/noarch/* + rm -rf /usr/src/packages/RPMS/x86_64/* + rm -rf /usr/src/packages/RPMS/ppc64/* + else + rm -rf /root/rpmbuild/RPMS/noarch/* + rm -rf /root/rpmbuild/RPMS/x86_64/* + rm -rf /root/rpmbuild/RPMS/ppc64/* + fi + + mkdir -p $CURDIR/build/ + + #always build perl-xCAT + $CURDIR/makerpm perl-xCAT + + + # Build the rest of the noarch rpms + for rpmname in xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-test xCAT-buildkit; do + if [ "$OSNAME" = "AIX" -a "$rpmname" = "xCAT-buildkit" ]; then continue; fi + $CURDIR/makerpm $rpmname + done + + #build xCAT-genesis-scripts if it is x86_64 platform + ARCH=$(uname -p) + if [ "$ARCH" = "x64_64" ]; then + $CURDIR/makerpm xCAT-genesis-scripts x86_64 + fi + + + # Build the xCAT and xCATsn rpms for all platforms + for rpmname in xCAT xCATsn; do + if [ "$OSNAME" = "AIX" ]; then + $CURDIR/makerpm $rpmname + if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname"; fi + else + for arch in x86_64 ppc64 s390x; do + $CURDIR/makerpm $rpmname $arch + if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname-$arch"; fi + done + fi + done + + if [ "$OS" = "SUSE" ]; then + cp /usr/src/packages/RPMS/noarch/* $CURDIR/build/ + cp /usr/src/packages/RPMS/x86_64/* $CURDIR/build/ + cp /usr/src/packages/RPMS/ppc64/* $CURDIR/build/ + else + cp /root/rpmbuild/RPMS/noarch/* $CURDIR/build/ + cp /root/rpmbuild/RPMS/x86_64/* $CURDIR/build/ + cp /root/rpmbuild/RPMS/ppc64/* $CURDIR/build/ + fi + + #begin to create repo for redhat platform + + grep -i 'Red' /etc/issue; + if [ "$OSNAME" != "AIX" -a $? -eq 0 ]; then + cat >$CURDIR/build/xCAT-core.repo << EOF +[xcat-2-core] +name=xCAT 2 Core packages +baseurl=file://$CURDIR/build +enabled=1 +gpgcheck=0 +EOF + + cp $CURDIR/build/xCAT-core.repo /etc/yum.repos.d/ + else + rm -f /etc/zypp/repos.d/xCAT-core.repo + zypper ar file://$CURDIR/build xCAT-core + fi + +fi + + diff --git a/makerpm b/makerpm index e5f184614..5fa58918a 100755 --- a/makerpm +++ b/makerpm @@ -53,6 +53,7 @@ function makexcat { tar -X /tmp/xcat-excludes -cf $RPMROOT/SOURCES/templates.tar templates gzip -f $RPMROOT/SOURCES/templates.tar cp xcat.conf $RPMROOT/SOURCES + cp xcat.conf.apach24 $RPMROOT/SOURCES cp xCATMN $RPMROOT/SOURCES else # xCATsn tar -X /tmp/xcat-excludes -cf $RPMROOT/SOURCES/license.tar LICENSE.html @@ -77,6 +78,7 @@ function makexcat { tar --exclude .svn -czf $RPMROOT/SOURCES/templates.tar.gz templates tar --exclude .svn -czf $RPMROOT/SOURCES/winpostscripts.tar.gz winpostscripts cp xcat.conf $RPMROOT/SOURCES + cp xcat.conf.apach24 $RPMROOT/SOURCES cp xCATMN $RPMROOT/SOURCES cd - >/dev/null elif [ "$RPMNAME" = "xCATsn" ]; then diff --git a/perl-xCAT/db2man b/perl-xCAT/db2man index 227372aef..f05cfb5b5 100755 --- a/perl-xCAT/db2man +++ b/perl-xCAT/db2man @@ -262,6 +262,12 @@ expression B<($1-1)%14+1> will evaluate to B<6>. See http://www.perl.com/doc/manual/html/pod/perlre.html for information on perl regular expressions. +=head2 Easy Regular Expressions + +As of xCAT 2.8.1, you can use a modified version of the regular expression support described in the previous section. You do not need to enter the node information (1st part of the expression), it will be derived from the input nodename. You only need to supply the 2nd part of the expression to determine the value to give the attribute. For examples, see + +https://sourceforge.net/apps/mediawiki/xcat/index.php?title=Listing_and_Modifying_the_Database#Easy_Regular_expressions + =head1 OBJECT DEFINITIONS Because it can get confusing what attributes need to go in what tables, the xCAT database can also diff --git a/perl-xCAT/modifyUtils b/perl-xCAT/modifyUtils index b96dd593e..bbad27bdb 100755 --- a/perl-xCAT/modifyUtils +++ b/perl-xCAT/modifyUtils @@ -1,20 +1,21 @@ #!/bin/sh # Put the version, svn revision #, and build date into the Version function in Version.pm -if [ -z "$1" ] +if [ -z "$2" ] then echo "modifyUtils: Error: must specify the xCAT version as an argument" >&2 exit fi VER=$1 +GITREF="git commit $2, " BUILDDATE=`date` #echo ". '(built $BUILDDATE)'" if [ "$(uname)" = "AIX" ] then - sed -e s/"#XCATVERSIONSUBHERE"/". '$VER'"/ -e s/"#XCATSVNBUILDSUBHERE"/". ' (built $BUILDDATE)'"/ xCAT/Version.pm >xCAT/Version.pm.new + sed -e s/"#XCATVERSIONSUBHERE"/". '$VER'"/ -e s/"#XCATSVNBUILDSUBHERE"/". ' (${GITREF}built $BUILDDATE)'"/ xCAT/Version.pm >xCAT/Version.pm.new mv xCAT/Version.pm.new xCAT/Version.pm else if [ -f "/etc/debian_version" ];then @@ -22,5 +23,5 @@ else else FILENAME="xCAT/Version.pm" fi - sed -i -e s/"#XCATVERSIONSUBHERE"/". '$VER'"/ -e s/"#XCATSVNBUILDSUBHERE"/". ' (built $BUILDDATE)'"/ $FILENAME + sed -i -e s/"#XCATVERSIONSUBHERE"/". '$VER'"/ -e s/"#XCATSVNBUILDSUBHERE"/". ' (${GITREF}built $BUILDDATE)'"/ $FILENAME fi diff --git a/perl-xCAT/perl-xCAT.spec b/perl-xCAT/perl-xCAT.spec old mode 100644 new mode 100755 index 914e09bb0..0cef475ee --- a/perl-xCAT/perl-xCAT.spec +++ b/perl-xCAT/perl-xCAT.spec @@ -23,6 +23,8 @@ Provides: perl-xCAT = %{epoch}:%{version} Provides perl xCAT libraries for core functionality. Required for all xCAT installations. Includes xCAT::Table, xCAT::NodeRange, among others. +%define gitinfo %(git log -n 1 | head -n 1 | cut -f 2 -d ' ') + %define zvm %(if [ "$zvm" = "1" ];then echo 1; else echo 0; fi) %define fsm %(if [ "$fsm" = "1" ];then echo 1; else echo 0; fi) @@ -36,7 +38,7 @@ Includes xCAT::Table, xCAT::NodeRange, among others. %if %fsm %else # Modify the Version() function in xCAT/Utils.pm to automatically have the correct version -./modifyUtils %{version} +./modifyUtils %{version} %{gitinfo} # Build the pod version of the man pages for each DB table. It puts them in the man5 and man7 subdirs. # Then convert the pods to man pages and html pages. diff --git a/perl-xCAT/xCAT/Client.pm b/perl-xCAT/xCAT/Client.pm index 99b84e489..66b4374c7 100644 --- a/perl-xCAT/xCAT/Client.pm +++ b/perl-xCAT/xCAT/Client.pm @@ -223,6 +223,7 @@ if (ref($request) eq 'HASH') { # the request is an array, not pure XML SSL_key_file => $keyfile, SSL_cert_file => $certfile, SSL_ca_file => $cafile, + SSL_verify_mode => SSL_VERIFY_PEER, SSL_use_cert => 1, Timeout => 0, ); diff --git a/perl-xCAT/xCAT/DBobjUtils.pm b/perl-xCAT/xCAT/DBobjUtils.pm index 5bf27c69e..19428d0e0 100755 --- a/perl-xCAT/xCAT/DBobjUtils.pm +++ b/perl-xCAT/xCAT/DBobjUtils.pm @@ -2747,7 +2747,7 @@ sub collapsenicsattr() # e.g nicips.eth0 # do not need to handle nic attributes without the postfix .ethx, # it will be overwritten by the attributes with the postfix .ethx, - if ($nodeattr =~ /^(nic\w+)\.(\w+)$/) + if ($nodeattr =~ /^(nic\w+)\.(.*)$/) { if ($1 && $2) { diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index 9b09140c5..9f5cc2ac9 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -598,7 +598,7 @@ sub _execute_dsh } else { - # LKV: This is where the output shows up + # HERE: This is where the output shows up #print STDOUT @{$output_buffers{$user_target}}; #print STDERR @{$error_buffers{$user_target}}; chomp(@{$output_buffers{$user_target}}); @@ -1020,6 +1020,7 @@ sub fork_fanout_dsh } } # save the original exports, we are going to add the unique node name below + my $firstpass=0; while (@$targets_waiting && (keys(%$targets_active) < $$options{'fanout'})) { @@ -1046,6 +1047,7 @@ sub fork_fanout_dsh } if ($$options{'environment'}) { + if ($firstpass ==0) { # do the servicenode stuff only once # if we are on a servicenode need to get the environment file # from the SNsyncfiledir, not local if (xCAT::Utils->isServiceNode()) { @@ -1068,8 +1070,10 @@ sub fork_fanout_dsh $rsp->{error}->[0] = "File $$options{'environment'} does not exist"; xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); } - # build the xdsh command - push @dsh_command, + $firstpass=1; + } + # build the xdsh command + push @dsh_command, "$exportnode$$options{'pre-command'} . $$options{'environment'} ; $$options{'command'}$$options{'post-command'}"; } @@ -3993,8 +3997,7 @@ sub parse_and_run_dsh { $options{'user'} = $ENV{'DSH_TO_USERID'}; } - - if ((!(defined(@$nodes))) && (!(defined($options{'rootimg'})))) + if ((!(defined($nodes))) && (!(defined($options{'rootimg'})))) { # no nodes and not -i option, error my $rsp = (); $rsp->{error}->[0] = "Unless using -i option, noderange is required."; @@ -4033,7 +4036,7 @@ sub parse_and_run_dsh { # from sinv, discard this name undef @$nodes; } - if (defined(@$nodes)) + if (@$nodes) { my $rsp = {}; $rsp->{error}->[0] = @@ -4405,7 +4408,7 @@ sub parse_and_run_dcp return; } } - if ((!(defined(@$nodes))) && (!(defined($options{'rootimg'})))) + if ((!(defined($nodes))) && (!(defined($options{'rootimg'})))) { # no nodes and not -i option, error my $rsp = {}; $rsp->{error}->[0] = "Unless using -i option, noderange is required."; @@ -4502,7 +4505,7 @@ sub parse_and_run_dcp # # build list of nodes my @nodelist; - if (defined(@$nodes)) + if (@$nodes) { # there are nodes @nodelist = @$nodes; $options{'nodes'} = join(',', @nodelist); @@ -4972,7 +4975,8 @@ sub parse_rsync_input_file_on_MN $::process_line = 0; my $destfileisdir; my $clause=0; - + my $addmergescript =0; + my $addappendscript =0; open(INPUTFILE, "< $input_file") || die "File $input_file does not exist\n"; while (my $line = ) { @@ -5013,12 +5017,16 @@ sub parse_rsync_input_file_on_MN # this triggers the running of the appendscript $::appendscript ="/opt/xcat/share/xcat/scripts/xdcpappend.sh"; } + # add the append script to the sync - my $appscript ="/opt/xcat/share/xcat/scripts/xdcpappend.sh"; - my $appendscriptline = "$appscript -> $appscript"; - $syncappendscript=1; # syncing the xdcpappend.sh script - &build_append_rsync($appendscriptline,$nodes, $options, $input_file,$rsyncSN, $syncdir,$nodesyncfiledir,$onServiceNode,$syncappendscript); - } + if ($addappendscript == 0) { # only add once + my $appscript ="/opt/xcat/share/xcat/scripts/xdcpappend.sh"; + my $appendscriptline = "$appscript -> $appscript"; + $syncappendscript=1; # syncing the xdcpappend.sh script + &build_append_rsync($appendscriptline,$nodes, $options, $input_file,$rsyncSN, $syncdir,$nodesyncfiledir,$onServiceNode,$syncappendscript); + $addappendscript=1; + } + } # end APPEND clause if ($clause =~ /MERGE:/) { # location of the base merge script # for MERGE we have to sync the mergescript and the @@ -5030,12 +5038,16 @@ sub parse_rsync_input_file_on_MN # this triggers the running of the mergescript $::mergescript ="/opt/xcat/share/xcat/scripts/xdcpmerge.sh"; } + # add the merge script to the sync - my $mergescript ="/opt/xcat/share/xcat/scripts/xdcpmerge.sh"; - my $mergescriptline = "$mergescript -> $mergescript"; - $syncmergescript=1; # syncing the xdcpmerge.sh script - &build_merge_rsync($mergescriptline,$nodes, $options, $input_file,$rsyncSN, $syncdir,$nodesyncfiledir,$onServiceNode,$syncmergescript); - } + if ($addmergescript == 0) { # only add once + my $mergescript ="/opt/xcat/share/xcat/scripts/xdcpmerge.sh"; + my $mergescriptline = "$mergescript -> $mergescript"; + $syncmergescript=1; # syncing the xdcpmerge.sh script + &build_merge_rsync($mergescriptline,$nodes, $options, $input_file,$rsyncSN, $syncdir,$nodesyncfiledir,$onServiceNode,$syncmergescript); + $addmergescript=1; + } + } # end MERGE clause } } else { # not processing EXECUTE, EXECUTEALWAYS or APPEND @@ -5199,6 +5211,7 @@ sub build_append_rsync push @::appendlines,$line; } my $src_file = $1; # append file left of arror + my $orig_src_file = $1; # append file left of arror # it will be sync'd to $nodesyncfiledir/$append_file my $dest_file = $nodesyncfiledir; $dest_file .= $src_file; @@ -5227,7 +5240,7 @@ sub build_append_rsync # to pick up files from /var/xcat/syncfiles... if ($onServiceNode == 1) { my $newsrcfile = $syncdir; # add SN syndir on front - $newsrcfile .= $src_file; + $newsrcfile .= $orig_src_file; $src_file=$newsrcfile; } # destination file name @@ -5310,7 +5323,8 @@ sub build_merge_rsync if ($syncmergescript == 0) { # don't add the xdcpmerge.sh line push @::mergelines,$line; } - my $src_file = $1; # merge file left of arror + my $src_file = $1; # merge file left of arrow + my $orig_src_file = $1; # it will be sync'd to $nodesyncfiledir/$merge_file my $dest_file = $nodesyncfiledir; $dest_file .= $src_file; @@ -5339,7 +5353,7 @@ sub build_merge_rsync # to pick up files from /var/xcat/syncfiles... if ($onServiceNode == 1) { my $newsrcfile = $syncdir; # add SN syndir on front - $newsrcfile .= $src_file; + $newsrcfile .= $orig_src_file; $src_file=$newsrcfile; } # destination file name @@ -6029,11 +6043,11 @@ sub run_always_rsync_postscripts # if on the service node need to add the $syncdir directory # to the path if (xCAT::Utils->isServiceNode()) { - my $tmpp=$syncdir . $ps; - $ps=$tmpp; + my $tmps=$syncdir . $ps; + push @args, $tmps; + } else{ + push @args, $ps; } - push @args, $ps; - push (@nodes, @{$$dshparms{'postscripts'}{$ps}}); $out=xCAT::Utils->runxcmd( { command => ['xdsh'], diff --git a/perl-xCAT/xCAT/DSHCore.pm b/perl-xCAT/xCAT/DSHCore.pm index 1ca50ba63..9e940ca01 100644 --- a/perl-xCAT/xCAT/DSHCore.pm +++ b/perl-xCAT/xCAT/DSHCore.pm @@ -253,64 +253,6 @@ use strict; -#--------------------------------------------------------------------------- - -=head3 - ifconfig_inet - - Builds a list of all IP Addresses bound to the local host and - stores them in a global list - - Arguments: - None - - Returns: - None - - Globals: - @local_inet - - Error: - None - - Example: - xCAT::DSHCore->ifconfig_inet; - - Comments: - Internal routine only - -=cut - -#--------------------------------------------------------------------------- - -sub ifconfig_inet -{ - my @local_inet = (); - - if ($^O eq 'aix') - { - my @ip_address = (); - my @output = `/usr/sbin/ifconfig -a`; - - foreach my $line (@output) - { - ($line =~ /inet ((\d{1,3}?\.){3}(\d){1,3})\s/o) - && (push @local_inet, $1); - } - } - - elsif ($^O eq 'linux') - { - my @ip_address = (); - my @output = `/sbin/ifconfig -a`; - - foreach my $line (@output) - { - ($line =~ /inet addr:((\d{1,3}?\.){3}(\d){1,3})\s/o) - && (push @local_inet, $1); - } - } -} #--------------------------------------------------------------------------- diff --git a/perl-xCAT/xCAT/FSPUtils.pm b/perl-xCAT/xCAT/FSPUtils.pm index eb1dda4b6..6072f6a25 100644 --- a/perl-xCAT/xCAT/FSPUtils.pm +++ b/perl-xCAT/xCAT/FSPUtils.pm @@ -67,7 +67,7 @@ sub getHcpAttribs } } - my @ps = $tabs->{ppc}->getAllNodeAttribs(['node','parent','nodetype','hcp']); + my @ps = $tabs->{ppc}->getAllNodeAttribs(['node','parent','nodetype','hcp','id']); for my $entry ( @ps ) { my $tmp_parent = $entry->{parent}; my $tmp_node = $entry->{node}; @@ -79,6 +79,9 @@ sub getHcpAttribs if (defined($tmp_node) && defined($tmp_type) && ($tmp_type eq "blade") && defined($entry->{hcp})) { push @{$ppchash{$tmp_node}{children}}, $entry->{hcp}; } + if (defined($tmp_node) && defined($entry->{id}) && defined($tmp_parent) && defined($tmp_type) && ($tmp_type eq "lpar")) { + $ppchash{$tmp_parent}{mapping}{$tmp_node} = $entry->{id}; + } #if(exists($ppchash{$tmp_node})) { # if( defined($tmp_type) ) { diff --git a/perl-xCAT/xCAT/FSPvm.pm b/perl-xCAT/xCAT/FSPvm.pm index 5e61e3f53..d76415c75 100644 --- a/perl-xCAT/xCAT/FSPvm.pm +++ b/perl-xCAT/xCAT/FSPvm.pm @@ -16,7 +16,7 @@ use xCAT::Usage; use xCAT::NodeRange; use xCAT::FSPUtils; use xCAT::VMCommon; -#use Data::Dumper; +use Data::Dumper; use xCAT::MsgUtils qw(verbose_message); ############################################## # Globals @@ -48,6 +48,15 @@ sub parse_args { ########################################################################## # Parse the chvm command line for options and operands ########################################################################## +my @query_array = (); +my %param_list_map = ( + 'vmcpus' => 'part_get_lpar_processing', + 'vmmemory' => 'part_get_lpar_memory', + 'vmphyslots' => 'part_get_all_io_bus_info', + 'vmnics' => 'part_get_all_vio_info', + 'vmstorage' => 'part_get_all_vio_info', + 'del_vadapter' => 'part_get_all_vio_info' +); sub chvm_parse_extra_options { my $args = shift; @@ -57,6 +66,7 @@ sub chvm_parse_extra_options { if (ref($args) ne 'ARRAY') { return "$args"; } + my %tmp_hash = (); foreach (@$args) { my ($cmd, $value) = split (/\=/, $_); if (!defined($value)) { @@ -75,14 +85,24 @@ sub chvm_parse_extra_options { # return "'$value' invalid"; # } } elsif (grep(/^$cmd$/, @support_ops)) { + if (exists($param_list_map{$cmd})) { + $tmp_hash{$param_list_map{$cmd}} = 1; + } if (exists($opt->{p775})) { return "'$cmd' doesn't work for Power 775 machines."; + } elsif ($cmd eq "del_vadapter") { + if ($value !~ /^\d+$/) { + return "Invalid param '$value', only one slot id can be specified"; + } + } elsif ($cmd eq "vmothersetting") { if ($value =~ /hugepage:\s*(\d+)/i) { $opt->{huge_page} = $1; + $tmp_hash{'get_huge_page'} = 1; } if ($value =~ /bsr:\s*(\d+)/i) { $opt->{bsr} = $1; + $tmp_hash{'get_cec_bsr'} = 1; } next; } elsif ($cmd eq "vmstorage") { @@ -103,6 +123,53 @@ sub chvm_parse_extra_options { return "'$value' is invalid, must be in form of 'Server_name:slotnum'"; } } + } elsif ($cmd eq "vmcpus") { + if ($value =~ /^(\d+)\/(\d+)\/(\d+)$/) { + unless ($1 <= $2 and $2 <= $3) { + return "'$value' is invalid, must be in order"; + } + } else { + return "'$value' is invalid, must be integer"; + } + } elsif ($cmd eq "vmmemory") { + if ($value =~ /^([\d|.]+)([G|M]?)\/([\d|.]+)([G|M]?)\/([\d|.]+)([G|M]?)$/i) { + my ($mmin, $mcur, $mmax); + if ($2 == "G" or $2 == '') { + $mmin = $1 * 1024; + } + if ($4 == "G" or $4 == '') { + $mcur = $3 * 1024; + } + if ($6 == "G" or $6 == '') { + $mmax = $5 * 1024; + } + unless ($mmin <= $mcur and $mcur <= $mmax) { + return "'$value' is invalid, must be in order"; + } + } else { + return "'$value' is invalid"; + } + } elsif ($cmd eq "vmphyslots") { + my @tmp_array = split ",",$value; + foreach (@tmp_array) { + unless (/(0x\w{8})/) { + return "'$_' is invalid"; + } + } + } elsif ($cmd eq "vmothersetting") { + my @tmp_array = split ",", $value; + foreach (@tmp_array) { + unless (/^(bsr|hugepage):\d+$/) { + return "'$_' is invalid"; + } + } + } elsif ($cmd eq "vmnics") { + my @tmp_array = split ",", $value; + foreach (@tmp_array) { + unless (/^vlan\d+$/i) { + return "'$_' is invalid"; + } + } } } else { @@ -110,6 +177,7 @@ sub chvm_parse_extra_options { } $opt->{$cmd} = $value; } + @query_array = keys(%tmp_hash); return undef; } @@ -672,7 +740,7 @@ sub lsvm_parse_args { $Getopt::Long::ignorecase = 0; Getopt::Long::Configure( "bundling" ); - if ( !GetOptions( \%opt, qw(V|verbose l|long p775) )) { + if ( !GetOptions( \%opt, qw(V|verbose l|long p775 updatedb) )) { return( usage() ); } if (exists($opt{l}) && !exists($opt{p775})) { @@ -711,11 +779,12 @@ sub modify { return op_extra_cmds ($request, $hash) if ($request->{opt}->{lparname} || $request->{opt}->{huge_page}); return ([["Error", "Miss argument\n".$usage_string, 1]]); } + sub do_op_extra_cmds { my $request = shift; my $hash = shift; my @values = (); - + my %lpar_hash = (); while (my ($mtms, $h) = each(%$hash)) { my $memhash; while (my($name, $d) = each(%$h)) { @@ -780,17 +849,17 @@ sub do_op_extra_cmds { if ($2 == "G" or $2 == '') { $min = $min * 1024; } - $min = $min/$memsize; + $min = int($min/$memsize); my $cur = $3; if ($4 == "G" or $4 == '') { $cur = $cur * 1024; } - $cur = $cur/$memsize; + $cur = int($cur/$memsize); my $max = $5; if ($6 == "G" or $6 == '') { $max = $max * 1024; } - $max = $max/$memsize; + $max = int($max/$memsize); $request->{opt}->{$op} ="$min/$cur/$max"; $param = $request->{opt}->{$op}; } else { @@ -823,8 +892,15 @@ sub do_op_extra_cmds { push @values, [$name, "Success", '0']; } } + my $rethash = query_cec_info_actions($request, $name, $d, 1, \@query_array); + # need to add update db here + $lpar_hash{$name} = $rethash; + $lpar_hash{$name}->{parent} = @$d[3]; } } + if (%lpar_hash) { + update_vm_db($request, \%lpar_hash); + } return \@values; } sub check_node_info { @@ -1605,6 +1681,7 @@ my @partition_query_actions = qw(part_get_partition_cap part_get_hyp_process_and sub parse_part_get_info { my $hash = shift; my $data = shift; + my $lparid = shift; my @array = split /\n/, $data; foreach my $line (@array) { chomp($line); @@ -1625,9 +1702,12 @@ sub parse_part_get_info { $hash->{bus}->{$3}->{cur_lparid} = $1; $hash->{bus}->{$3}->{bus_slot} = $2; $hash->{bus}->{$3}->{des} = $4; + if ($lparid and $lparid eq $1) { + push @{$hash->{lpar_phy_bus}}, $3; + } } elsif ($line =~ /Phy drc_index:(\w+), Port group: (\w+), Phy port id: (\w+)/) { $hash->{phy_drc_group_port}->{$1}->{$2}->{$3} = '1'; - } elsif ($line =~ /adapter_id=(\w+),lpar_id=([\d|-]+).*port_group=(\d+),phys_port_id=(\d+).*drc_index=(\w+),.*/) { + #} elsif ($line =~ /adapter_id=(\w+),lpar_id=([\d|-]+).*port_group=(\d+),phys_port_id=(\d+).*drc_index=(\w+),.*/) { if (($2 == -1) && ($4 == 255)) { $hash->{logic_drc_phydrc}->{$3}->{$5} = $1; #$hash->{logic_drc_phydrc}->{$5}->{$1} = [$2,$3,$4]; @@ -1640,12 +1720,49 @@ sub parse_part_get_info { $hash->{lpar0_used_mem} = $2; $hash->{phy_min_mem_req} = $3; #print "===>lpar0_used_mem:$hash->{lpar0_used_mem}.\n"; - } elsif ($line =~ /Curr Memory Req:[^\(]*\((\d+)\s*regions\)/) { - $hash->{lpar_used_regions} = $1; + } elsif ($line =~ /Curr Memory (Min|Req|Max):\s*([\d]*)[^\(]*\((\d+)\s*regions\)/) { + if ($1 eq 'Min') { + $hash->{lpar_mem_min} = $2 + } elsif ($1 eq 'Max') { + $hash->{lpar_mem_max} = $2; + } else { + $hash->{lpar_mem_req} = $2; + $hash->{lpar_used_regions} = $3; + } + } elsif ($line =~ /Curr Processor (Min|Req|Max):\s*(\d+)/) { + if ($1 eq 'Min') { + $hash->{lpar_cpu_min} = $2; + } elsif ($1 eq 'Max') { + $hash->{lpar_cpu_max} = $2; + } else { + $hash->{lpar_cpu_req} = $2; + } + } elsif ($line =~ /\s*lpar_id=(\d+),type=vSCSI,slot=(\d+),attr=(\d+).*remote_lpar_id=0x(\w+),remote_slot_num=0x(\w+)/) { + if ($3 eq '0') { + my $lparid = hex($4); + my $slotid = hex($5); + push @{$hash->{lpar_vmstorage_client}}, "$lparid:$slotid"; + } else { + if (exists($hash->{lpar_vmstorage_server})) { + $hash->{lpar_vmstorage_server}++; + } else { + $hash->{lpar_vmstorage_server} = 1; + } + } + } elsif ($line =~ /\s*lpar_id=(\d+),type=(vEth),slot=(\d+).*port_vlan_id=(\d+),mac_addr=(\w+)/) { + push @{$hash->{lpar_vmnics}}, "vlan$4"; } elsif ($line =~ /Available huge page memory\(in pages\):\s*(\d+)/) { $hash->{huge_page_avail} = $1; } elsif ($line =~ /Available BSR array:\s*(\d+)/) { $hash->{cec_bsr_avail} = $1; + } elsif ($line =~ /^\d+\/(\d+)\/\d+$/) { + if ($1 ne 0) { + push @{$hash->{lpar_othersetting}}, "hugepage:$1"; + } + } elsif ($line =~ /^(\d+)\.$/) { + if ($1 ne 0) { + push @{$hash->{lpar_othersetting}}, "bsr:$1"; + } } } } @@ -1656,6 +1773,7 @@ sub query_cec_info_actions { my $td = shift; my $usage = shift; my $action_array = shift; + my $lpar_hash = shift; my $lparid = @$td[0]; my $data; my @array = (); @@ -1670,12 +1788,16 @@ sub query_cec_info_actions { chomp(@$values[1]); #if ($action eq "part_get_partition_cap" and (@$values[1] =~ /Error:/i or @$values[2] ne 0)) { if (@$values[1] =~ /Error:/i or @$values[2] ne 0) { - return ([[@$values]]); + next; #return ([[@$values]]); } if (@$values[1] =~ /^$/) { next; } - if ($usage eq 0) { + if ($usage eq 1 or $usage eq 2) { + &parse_part_get_info(\%hash, @$values[1], $lparid); + } + + if ($usage eq 0 or $usage eq 2) { if ($lparid) { if ($action eq "lpar_lhea_mac") { my @output = split /\n/,@$values[1]; @@ -1730,18 +1852,72 @@ sub query_cec_info_actions { } #$data .= "@$values[1]\n\n"; push @array, [$name, @$values[1], @$values[2]]; - } else { - &parse_part_get_info(\%hash, @$values[1]); - } + } } - if ($usage eq 0) { + if ($usage eq 0 or $usage eq 2) { #return $data; + if ($usage eq 2) { + %$lpar_hash = %hash; + } return \@array; } else { return \%hash; } } +sub update_vm_db { + my $request = shift; + my $lpar_hash = shift; + my $vm_hd = xCAT::Table->new('vm'); + my %name_id_map = (); + my $commit = 0; + foreach (keys (%$lpar_hash)) { + my %db_update = (); + my $node_hash = $lpar_hash->{$_}; + if (exists($node_hash->{lpar_cpu_min})) { + $db_update{cpus} = "$node_hash->{lpar_cpu_min}/$node_hash->{lpar_cpu_req}/$node_hash->{lpar_cpu_max}"; + } + if (exists($node_hash->{lpar_mem_min})) { + $db_update{memory} = "$node_hash->{lpar_mem_min}/$node_hash->{lpar_mem_req}/$node_hash->{lpar_mem_max}"; + } + if (exists($node_hash->{lpar_vmstorage_server})) { + $db_update{storage} = $node_hash->{lpar_vmstorage_server}; + } elsif (exists($node_hash->{lpar_vmstorage_client})) { + my @tmp_array = (); + foreach (@{$node_hash->{lpar_vmstorage_client}}) { + if (/(\d+):(\d+)/) { + if (exists($name_id_map{$1})) { + push @tmp_array, "$name_id_map{$1}:$2"; + } else { + my $vios_name = &find_lpar_name($request, $node_hash->{parent}, $1); + if (defined($vios_name)) { + $name_id_map{$1} = $vios_name; + push @tmp_array, "$vios_name:$2"; + } + } + } + } + $db_update{storage} = join(",",@tmp_array); + } + if (exists($node_hash->{lpar_vmnics})) { + $db_update{nics} = join(",",@{$node_hash->{lpar_vmnics}}); + } + if (exists($node_hash->{lpar_phy_bus})) { + $db_update{physlots} = join(",",@{$node_hash->{lpar_phy_bus}}); + } + if (exists($node_hash->{lpar_othersetting})) { + $db_update{othersettings} = join(",",@{$node_hash->{lpar_othersetting}}); + } + if (%db_update) { + $vm_hd->setNodeAttribs($_,\%db_update); + $commit = 1; + } + } + if ($commit) { + $vm_hd->commit; + } +} + #my @partition_query_actions = qw(part_get_partition_cap part_get_num_of_lpar_slots part_get_hyp_config_process_and_mem part_get_hyp_avail_process_and_mem part_get_service_authority_lpar_id part_get_shared_processing_resource part_get_all_vio_info lpar_lhea_mac part_get_all_io_bus_info part_get_lpar_processing part_get_lpar_memory get_huge_page get_cec_bsr); sub query_cec_info { my $request = shift; @@ -1749,25 +1925,36 @@ sub query_cec_info { my $args = $request->{opt}; my @td = (); my @result = (); + my $usage = 0; + my %lpar_hash = (); #print Dumper($request); #print Dumper($hash); while (my ($mtms,$h) = each(%$hash) ) { while (my ($name, $d) = each (%$h)) { + my %tmp_hash = (); @td = @$d; if (@$d[0] == 0 && @$d[4] !~ /lpar|vios/) { last; } #my $rethash = query_cec_info_actions($request, $name, $d, 0, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_vio_info","lpar_lhea_mac","part_get_all_io_bus_info","get_huge_page","get_cec_bsr"]); - my $rethash = query_cec_info_actions($request, $name, $d, 0, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_io_bus_info","part_get_all_vio_info","get_huge_page","get_cec_bsr"]); + if ($args->{updatedb}) { + $usage = 2; + } + my $rethash = query_cec_info_actions($request, $name, $d, $usage, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_io_bus_info","part_get_all_vio_info","get_huge_page","get_cec_bsr"], \%tmp_hash); #push @result, [$name, $rethash, 0]; push @result, @$rethash; + $lpar_hash{$name} = \%tmp_hash; + $lpar_hash{$name}->{parent} = @$d[3]; } if (@td[0] == 0) { - my $rethash = query_cec_info_actions($request, @td[3],\@td, 0); + my $rethash = query_cec_info_actions($request, @td[3],\@td, $usage); #push @result, [@td[3], $rethash, 0]; push @result, @$rethash; } } + if ($args->{updatedb} and %lpar_hash) { + update_vm_db($request, \%lpar_hash); + } return \@result; } @@ -1859,7 +2046,8 @@ sub deal_with_avail_mem { } #xCAT::MsgUtils->verbose_message($request, "====****====used:$used_regions,avail:$cur_avail,($min:$cur:$max)."); if ($cur_avail < $min) { - return([$name, "Parse reserverd regions failed, no enough memory, available:$lparhash->{hyp_avail_mem}.", 1]); + my $cur_mem_in_G = $lparhash->{hyp_avail_mem} * $lparhash->{mem_region_size} * 1.0 / 1024; + return([$name, "Parse reserverd regions failed, no enough memory, available:$cur_mem_in_G GB.", 1]); } if ($cur > $cur_avail) { my $new_cur = $cur_avail; @@ -1883,6 +2071,19 @@ sub find_lpar_id { return undef; } +sub find_lpar_name { + my $request = shift; + my $parent = shift; + my $id = shift; + my %mapping = %{$request->{ppc}->{$parent}->{mapping}}; + foreach (keys %mapping) { + if ($mapping{$_} eq $id) { + return $_; + } + } + return undef; +} + sub create_lpar { my $request = shift; my $name = shift; @@ -1999,12 +2200,14 @@ sub create_lpar { } return ([$name, "Done", 0]); } + sub mkspeclpar { my $request = shift; my $hash = shift; my $opt = $request->{opt}; my $values; my @result = (); + my %lpar_hash = (); my $vmtab = xCAT::Table->new( 'vm'); unless($vmtab) { return([["Error","Cannot open vm table", 1]]); @@ -2044,6 +2247,75 @@ sub mkspeclpar { if (exists($opt->{vmnics})) { $tmp_ent->{nics} = $opt->{vmnics}; } + + + if (!defined($tmp_ent) ) { + return ([[$name, "Not find params", 1]]); + #} elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory}) || !exists($tmp_ent->{physlots})) { + } elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory})) { + return ([[$name, "The attribute 'vmcpus', 'vmmemory' are needed to be specified.", 1]]); + } + # FIX bug 3873 [FVT]DFM illegal action could work + # + + if ($tmp_ent->{cpus} =~ /^(\d+)\/(\d+)\/(\d+)$/) { + unless ($1 <= $2 and $2 <= $3) { + return([[$name, "Parameter for 'vmcpus' is invalid", 1]]); + } + } else { + return([[$name, "Parameter for 'vmcpus' is invalid", 1]]); + } + if ($tmp_ent->{memory} =~ /^([\d|.]+)([G|M]?)\/([\d|.]+)([G|M]?)\/([\d|.]+)([G|M]?)$/i) { + my ($mmin, $mcur, $mmax); + if ($2 == "G" or $2 == '') { + $mmin = $1 * 1024; + } + if ($4 == "G" or $4 == '') { + $mcur = $3 * 1024; + } + if ($6 == "G" or $6 == '') { + $mmax = $5 * 1024; + } + unless ($mmin <= $mcur and $mcur <= $mmax) { + return([[$name, "Parameter for 'vmmemory' is invalid", 1]]); + } + my $memsize = $memhash->{mem_region_size}; + $mmin = int(($mmin + $memsize - 1) / $memsize); + $mcur = int(($mcur + $memsize - 1) / $memsize); + $mmax = int(($mmax + $memsize - 1) / $memsize); + $tmp_ent->{memory} = "$mmin/$mcur/$mmax"; + $tmp_ent->{mem_region_size} = $memsize; + } else { + return([[$name, "Parameter for 'vmmemory' is invalid", 1]]); + } + + if (exists($tmp_ent->{physlots})) { + my @tmp_array = split ",",$tmp_ent->{physlots}; + foreach (@tmp_array) { + unless (/(0x\w{8})/i) { + return([[$name, "Parameter:$_ for 'vmphyslots' is invalid", 1]]); + } + } + } + if (exists($tmp_ent->{othersettings})) { + my @tmp_array = split ",",$tmp_ent->{othersettings}; + foreach (@tmp_array) { + unless (/^(bsr|hugepage):\d+$/) { + return([[$name, "Parameter:$_ for 'vmothersetting' is invalid", 1]]); + } + } + } + + if (exists($tmp_ent->{nics})) { + my @tmp_array = split ",",$tmp_ent->{nics}; + foreach (@tmp_array) { + unless (/^vlan\d+$/i) { + return([[$name, "Parameter:$_ for 'vmnics' is invalid", 1]]); + } + } + } + + if (exists($opt->{vios})) { if (!exists($tmp_ent->{physlots})) { my @phy_io_array = keys(%{$memhash->{bus}}); @@ -2060,66 +2332,59 @@ sub mkspeclpar { $tmp_ent->{storage} = \@array; } } else { - if (exists($tmp_ent->{storage}) and $tmp_ent->{storage} !~ /^[\w_-]*:\d+$/) { - return ([[$name, "Parameter for 'vmstorage' is invalid", 1]]); - } elsif (exists($tmp_ent->{storage})) { - if ($tmp_ent->{storage} =~ /([\w_-]*):(\d+)/) { - my $vios = &find_lpar_id($request, @$d[3], $1); - my $r_slotid = $2; - if (!defined($vios)) { - return ([[$name, "Cannot find lparid for Server lpar:$1"]]); + if (exists($tmp_ent->{storage})) { + my @tmp_array = split ",",$tmp_ent->{storage}; + my $storage_array = undef; + foreach (@tmp_array) { + if (/([\w_-]*):(\d+)/) { + my $vios = &find_lpar_id($request, @$d[3], $1); + my $r_slotid = $2; + if (defined($vios)) { + push @$storage_array, "0,$vios,$r_slotid"; + } else { + return ([[$name, "Cannot find lparid for Server lpar:$1"]]); + } + } else { + return ([[$name, "Parameter for 'vmstorage' is invalid", 1]]); } - $tmp_ent->{storage} = ["0,$vios,$r_slotid"]; } + $tmp_ent->{storage} = $storage_array; + } } - if (!defined($tmp_ent) ) { - return ([[$name, "Not find params", 1]]); - #} elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory}) || !exists($tmp_ent->{physlots})) { - } elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory})) { - return ([[$name, "The attribute 'vmcpus', 'vmmemory' are needed to be specified.", 1]]); - } - if ($tmp_ent->{memory} =~ /(\d+)([G|M]?)\/(\d+)([G|M]?)\/(\d+)([G|M]?)/i) { - my $memsize = $memhash->{mem_region_size}; - my $min = $1; - if ($2 == "G" or $2 == '') { - $min = $min * 1024; - } - $min = $min/$memsize; - my $cur = $3; - if ($4 == "G" or $4 == '') { - $cur = $cur * 1024; - } - $cur = $cur/$memsize; - my $max = $5; - if ($6 == "G" or $6 == '') { - $max = $max * 1024; - } - $max = $max/$memsize; - $tmp_ent->{memory} = "$min/$cur/$max"; - } + $tmp_ent->{hyp_config_mem} = $memhash->{hyp_config_mem}; $tmp_ent->{hyp_avail_mem} = $memhash->{hyp_avail_mem}; - $tmp_ent->{huge_page} = "0/0/0"; - $tmp_ent->{bsr_num} = "0"; if (exists($tmp_ent->{othersettings})) { my $setting = $tmp_ent->{othersettings}; if ($setting =~ /hugepage:(\d+)/) { my $tmp = $1; - $tmp_ent->{huge_page} = "1/".$tmp."/".$tmp; + if ($tmp >= 1) { + $tmp_ent->{huge_page} = "1/".$tmp."/".$tmp; + } } if ($setting =~ /bsr:(\d+)/) { - $tmp_ent->{bsr_num} = $1; + if ($1 >= 1) { + $tmp_ent->{bsr_num} = $1; + } } } $tmp_ent->{phy_hea} = $memhash->{phy_drc_group_port}; $tmp_ent->{logic_drc_phydrc} = $memhash->{logic_drc_phydrc}; $values = &create_lpar($request, $name, $d, $tmp_ent); push @result, $values; + #need to add update db here + my $rethash = query_cec_info_actions($request, $name, $d, 1, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_vio_info","part_get_all_io_bus_info","get_huge_page","get_cec_bsr"]); + $lpar_hash{$name} = $rethash; + $lpar_hash{$name}->{parent} = @$d[3]; + $name = undef; $d = undef; } } + if (%lpar_hash) { + update_vm_db($request, \%lpar_hash); + } return \@result; } diff --git a/perl-xCAT/xCAT/InstUtils.pm b/perl-xCAT/xCAT/InstUtils.pm index a795359a9..71c4a1785 100644 --- a/perl-xCAT/xCAT/InstUtils.pm +++ b/perl-xCAT/xCAT/InstUtils.pm @@ -1023,7 +1023,7 @@ sub dolitesetup $nrange = join(',',@nodel); } - my @flist = xCAT::Utils->runcmd("/opt/xcat/bin/litefile $nrange", -1); + @flist = xCAT::Utils->runcmd("/opt/xcat/bin/litefile $nrange", -1); if (scalar(@flist) > 0) { foreach my $l (@flist) { my ($j1, $j2, $file) = split /\s+/, $l; diff --git a/perl-xCAT/xCAT/NetworkUtils.pm b/perl-xCAT/xCAT/NetworkUtils.pm index 1511aa6f7..1bd6397e0 100755 --- a/perl-xCAT/xCAT/NetworkUtils.pm +++ b/perl-xCAT/xCAT/NetworkUtils.pm @@ -19,6 +19,7 @@ use File::Path; use Math::BigInt; use Socket; use xCAT::GlobalDef; +use Data::Dumper; use strict; use warnings "all"; my $socket6support = eval { require Socket6 }; @@ -696,19 +697,26 @@ sub get_nic_ip # Base address:0x2600 Memory:fbfe0000-fc0000080 # # eth1 ... + # Redhat7 + #eth0: flags=4163 mtu 1500 + # inet 10.1.0.178 netmask 255.255.0.0 broadcast 10.1.255.255 # ############################################################## my @adapter= split /\n{2,}/, $result; foreach ( @adapter ) { - if ( !($_ =~ /LOOPBACK / ) and - $_ =~ /UP / and - $_ =~ /$mode / ) { + if ( !($_ =~ /LOOPBACK/ ) and + $_ =~ /UP( |,|>)/ and + $_ =~ /$mode/ ) { my @ip = split /\n/; for my $ent ( @ip ) { if ($ent =~ /^(eth\d|ib\d|hf\d)\s+/) { $nic = $1; - } - if ( $ent =~ /^\s*inet addr:\s*(\d+\.\d+\.\d+\.\d+)/ ) { + } + if ($ent =~ /^(eth\d:|ib\d:|hf\d:)\s+/) { + $nic = $1; + } + $ent=~ s/addr://; # works for Redhat7 also + if ( $ent =~ /^\s*inet \s*(\d+\.\d+\.\d+\.\d+)/ ) { $iphash{$nic} = $1; next; } @@ -1620,8 +1628,10 @@ sub gethost_ips else { my ($inet, $addr1, $Bcast, $Mask) = split(" ", $addr); - @ip = split(":", $addr1); - push @ipaddress, $ip[1]; + #@ip = split(":", $addr1); + #push @ipaddress, $ip[1]; + $addr1 =~ s/.*://; + push @ipaddress, $addr1; } } else @@ -1981,6 +1991,108 @@ sub isIpaddr } } + +#------------------------------------------------------------------------------- +=head3 getSubnetGateway + Description: + Get gateway from the networks table of the specified net. + + Arguments: + net: the net, ie. the "net" field of the networks table + Returns: + Return a string, of the gateway + undef - Failed to get the gateway + Globals: + none + Error: + none + Example: + my $gateway = xCAT::NetworkUtils::getSubnetGateway('192.168.1.0'); + Comments: + none + +=cut +#------------------------------------------------------------------------------- +sub getSubnetGateway +{ + my $netname=shift; + if( $netname =~ /xCAT::NetworkUtils/) + { + $netname=shift; + } + + my $gateway=undef; + my $nettab = xCAT::Table->new("networks"); + unless($nettab) { die "No entry defined in networks"; } + my @nets = $nettab->getAllAttribs('net','gateway'); + foreach(@nets) + { + if("$_->{net}" eq "$netname") + { + $gateway = $_->{gateway}; + last; + } + } + + return $gateway; +} + + +#------------------------------------------------------------------------------- +=head3 getNodeNameservers + Description: + Get nameservers of specified nodes. + The priority: noderes.nameservers > networks.nameservers > site.nameservers + Arguments: + node: node name list + Returns: + Return a hash ref, of the $nameservers{$node} + undef - Failed to get the nameservers + Globals: + none + Error: + none + Example: + my $nameservers = xCAT::NetworkUtils::getNodeNameservers(\@node); + Comments: + none + +=cut +#------------------------------------------------------------------------------- +sub getNodeNameservers{ + my $nodes=shift; + if( $nodes =~ /xCAT::NetworkUtils/) + { + $nodes=shift; + } + my @nodelist = @$nodes; + my %nodenameservers; + my $nrtab = xCAT::Table->new('noderes',-create=>0); + my %nrhash = %{$nrtab->getNodesAttribs(\@nodelist,['nameservers'])}; + + my $nettab = xCAT::Table->new("networks"); + my %nethash = xCAT::DBobjUtils->getNetwkInfo( \@nodelist ); + + my @nameservers = xCAT::TableUtils->get_site_attribute("nameservers"); + my $sitenameservers=$nameservers[0]; + + + foreach my $node (@nodelist){ + if ($nrhash{$node} and $nrhash{$node}->[0] and $nrhash{$node}->[0]->{nameservers}) + { + $nodenameservers{$node}=$nrhash{$node}->[0]->{nameservers}; + }elsif($nethash{$node}{nameservers}) + { + $nodenameservers{$node}=$nethash{$node}{nameservers}; + }elsif($sitenameservers) + { + $nodenameservers{$node}=$sitenameservers; + } + } + + return \%nodenameservers; +} + #------------------------------------------------------------------------------- =head3 getNodeNetworkCfg @@ -2007,17 +2119,23 @@ sub isIpaddr sub getNodeNetworkCfg { my $node = shift; - + if( $node =~ /xCAT::NetworkUtils/) + { + $node =shift; + } + my $nets = xCAT::NetworkUtils::my_nets(); my $ip = xCAT::NetworkUtils->getipaddr($node); my $mask = undef; + my $gateway = undef; for my $net (keys %$nets) { my $netname; ($netname,$mask) = split /\//, $net; + $gateway=xCAT::NetworkUtils::getSubnetGateway($netname); last if ( xCAT::NetworkUtils::isInSameSubnet( $netname, $ip, $mask, 1)); } - return ($ip, $node, undef, xCAT::NetworkUtils::formatNetmask($mask,1,0)); + return ($ip, $node, $gateway, xCAT::NetworkUtils::formatNetmask($mask,1,0)); } #------------------------------------------------------------------------------- diff --git a/perl-xCAT/xCAT/NodeRange.pm b/perl-xCAT/xCAT/NodeRange.pm index 1a34b912b..f03a47518 100644 --- a/perl-xCAT/xCAT/NodeRange.pm +++ b/perl-xCAT/xCAT/NodeRange.pm @@ -149,7 +149,7 @@ sub nodesbycriteria { } if ($neednewcache) { if ($nodelist) { - $nodelist->_clear_cache(); + #$nodelist->_clear_cache(); $nodelist->_build_cache(\@cachedcolumns); } } diff --git a/perl-xCAT/xCAT/PPCcli.pm b/perl-xCAT/xCAT/PPCcli.pm index b76a34c4d..f625560bc 100644 --- a/perl-xCAT/xCAT/PPCcli.pm +++ b/perl-xCAT/xCAT/PPCcli.pm @@ -156,7 +156,7 @@ sub connect { # Shell prompt regexp based on HW Type ################################################## my %prompt = ( - hmc => "~> \$", + hmc => "~>\\s*\$", ivm => "\\\$ \$" ); ################################################## diff --git a/perl-xCAT/xCAT/ProfiledNodeUtils.pm b/perl-xCAT/xCAT/ProfiledNodeUtils.pm index d0e843799..96458c88e 100644 --- a/perl-xCAT/xCAT/ProfiledNodeUtils.pm +++ b/perl-xCAT/xCAT/ProfiledNodeUtils.pm @@ -265,6 +265,7 @@ sub rackformat_to_numricformat{ values are attributes of a specific nic, like: type : nic type hostnamesuffix: hostname suffix + hostnameprefix: hostname prefix customscript: custom script for this nic network: network name for this nic ip: ip address of this nic. @@ -276,7 +277,7 @@ sub get_nodes_nic_attrs{ my $nodes = shift; my $nicstab = xCAT::Table->new( 'nics'); - my $entry = $nicstab->getNodesAttribs($nodes, ['nictypes', 'nichostnamesuffixes', 'niccustomscripts', 'nicnetworks', 'nicips']); + my $entry = $nicstab->getNodesAttribs($nodes, ['nictypes', 'nichostnamesuffixes', 'nichostnameprefixes', 'niccustomscripts', 'nicnetworks', 'nicips']); my %nicsattrs; my @nicattrslist; @@ -308,6 +309,20 @@ sub get_nodes_nic_attrs{ } } + if($entry->{$node}->[0]->{'nichostnameprefixes'}){ + + @nicattrslist = split(",", $entry->{$node}->[0]->{'nichostnameprefixes'}); + foreach (@nicattrslist){ + my @nicattrs; + if ($_ =~ /!/) { + @nicattrs = split("!", $_); + } else { + @nicattrs = split(":", $_); + } + $nicsattrs{$node}{$nicattrs[0]}{'hostnameprefix'} = $nicattrs[1]; + } + } + if($entry->{$node}->[0]->{'niccustomscripts'}){ @nicattrslist = split(",", $entry->{$node}->[0]->{'niccustomscripts'}); foreach (@nicattrslist){ diff --git a/perl-xCAT/xCAT/RemoteShellExp.pm b/perl-xCAT/xCAT/RemoteShellExp.pm index 4d9b3d34d..90b15ed43 100755 --- a/perl-xCAT/xCAT/RemoteShellExp.pm +++ b/perl-xCAT/xCAT/RemoteShellExp.pm @@ -35,7 +35,7 @@ package xCAT::RemoteShellExp; node. DSH_TO_USERID - The userid on the node where the ssh keys will be updated. DSH_ENABLE_SSH - Node to node root passwordless ssh will be setup. - + DSH_ZONE_SSHKEYS - directory containing the zones root .ssh keys Usage: remoteshellexp [-t node list] test ssh connection to the node @@ -144,7 +144,7 @@ sub remoteshellexp } else { $from_userid="root"; } - # set User on the node where we will send the keys + # set User on the node where we will send the keys # this id can be a local id as well as root if ($ENV{'DSH_TO_USERID'}) { $to_userid=$ENV{'DSH_TO_USERID'}; @@ -154,18 +154,19 @@ sub remoteshellexp # set User home directory to find the ssh public key to send # For non-root ids information may not be in /etc/passwd # but elsewhere like LDAP + if ($ENV{'DSH_FROM_USERID_HOME'}) { - $home=$ENV{'DSH_FROM_USERID_HOME'}; + $home=$ENV{'DSH_FROM_USERID_HOME'}; } else { - $home=xCAT::Utils->getHomeDir($from_userid); + $home=xCAT::Utils->getHomeDir($from_userid); } - # This indicates we will generate new ssh keys for the user, # if they are not already there - my $key="$home/.ssh/id_rsa"; - my $key2="$home/.ssh/id_rsa.pub"; - # Check to see if empty - if (-z $key) { + # unless using zones + my $key="$home/.ssh/id_rsa"; + my $key2="$home/.ssh/id_rsa.pub"; + # Check to see if empty + if (-z $key) { my $rsp = {}; $rsp->{error}->[0] = "The $key file is empty. Remove it and rerun the command."; @@ -183,8 +184,7 @@ sub remoteshellexp } if (($flag eq "k") && (!(-e $key))) { - # if the file size of the id_rsa key is 0, tell them to remove it - # and run the command again + # updating keys and the key file does not exist $rc=xCAT::RemoteShellExp->gensshkeys($expecttimeout); } # send ssh keys to the nodes/devices, to setup passwordless ssh @@ -200,6 +200,9 @@ sub remoteshellexp if ($ssh_setup_cmd) { # setup ssh on devices $rc=xCAT::RemoteShellExp->senddeviceskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$ssh_setup_cmd,$nodes, $expecttimeout); } else { #setup ssh on nodes + if ($ENV{'DSH_ZONE_SSHKEYS'}) { # if using zones the override the location of the keys + $home= $ENV{'DSH_ZONE_SSHKEYS'}; + } $rc=xCAT::RemoteShellExp->sendnodeskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$nodes, $expecttimeout); } } @@ -495,11 +498,15 @@ sub sendnodeskeys # in $HOME/.ssh/tmp/authorized_keys # copy to the node to the temp directory # scp $HOME/.ssh/tmp/authorized_keys to_userid@:/tmp/$to_userid/.ssh + # scp $HOME/.ssh/id_rsa.pub to_userid@:/tmp/$to_userid/.ssh + # Note if using zones, the keys do not come from ~/.ssh but from the + # zone table, sshkeydir attribute. For zones the userid is always root # If you are going to enable ssh to ssh between nodes, then # scp $HOME/.ssh/id_rsa to that temp directory on the node # copy the script $HOME/.ssh/copy.sh to the node, it will do the # the work of setting up the user's ssh keys and clean up # ssh (run) copy.sh on the node + my @nodelist=split(/,/,$nodes); foreach my $node (@nodelist) { $sendkeys = new Expect; @@ -607,11 +614,11 @@ sub sendnodeskeys my $spawncopyfiles; if ($ENV{'DSH_ENABLE_SSH'}) { # we will enable node to node ssh $spawncopyfiles= - "$remotecopy $home/.ssh/id_rsa $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; + "$remotecopy $home/.ssh/id_rsa $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; } else { # no node to node ssh ( don't send private key) $spawncopyfiles= - "$remotecopy $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; + "$remotecopy $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; } # send copy command unless ($sendkeys->spawn($spawncopyfiles)) diff --git a/perl-xCAT/xCAT/SLP.pm b/perl-xCAT/xCAT/SLP.pm index e1ebae53b..0dfa25f69 100755 --- a/perl-xCAT/xCAT/SLP.pm +++ b/perl-xCAT/xCAT/SLP.pm @@ -110,6 +110,12 @@ sub dodiscover { my @servernodes; my @iprange = split /,/, $ipranges; foreach my $range (@iprange) { + send_message($args{reqcallback}, 0, "Processing range $range..."); + if ($range =~/\/(\d+)/){ + if ($1 < 16) { + send_message($args{reqcallback}, 0, "The rarge is too large and may be time consuming. Broadcast is recommended."); + } + } `/usr/bin/nmap $range -sn -PE -n --send-ip -T5 `; my $nmapres = `/usr/bin/nmap $range -PE -p 427 -n --send-ip -T5 `; foreach my $line (split(/\n\n/,$nmapres)) { @@ -233,7 +239,7 @@ sub dodiscover { close PWRITE; if (@servernodes) { my $miss = join(",", @servernodes); - send_message($args{reqcallback}, 0, "Warning: can't got attributes from these nodes' replies: $miss. Please re-send unicast to these nodes.") if ($args{reqcallback}); + send_message($args{reqcallback}, 0, "Warning: can't get attributes from these nodes' replies: $miss. Please re-send unicast to these nodes.") if ($args{reqcallback}); } }# end of parent process } else { diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 9cf6eb128..f4c6779a7 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -554,7 +554,7 @@ nodehm => { }, }, nodelist => { - cols => [qw(node groups status statustime appstatus appstatustime primarysn hidden updatestatus updatestatustime comments disable)], + cols => [qw(node groups status statustime appstatus appstatustime primarysn hidden updatestatus updatestatustime zonename comments disable)], keys => [qw(node)], tablespace =>'XCATTBS32K', table_desc => "The list of all the nodes in the cluster, including each node's current status and what groups it is in.", @@ -569,6 +569,7 @@ nodelist => { hidden => "Used to hide fsp and bpa definitions, 1 means not show them when running lsdef and nodels", updatestatus => "The current node update status. Valid states are synced out-of-sync,syncing,failed.", updatestatustime => "The date and time when the updatestatus was updated.", + zonename => "The name of the zone to which the node is currently assigned. If undefined, then it is not assigned to any zone. ", comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, @@ -598,7 +599,7 @@ noderes => { descriptions => { node => 'The node name or group name.', servicenode => 'A comma separated list of node names (as known by the management node) that provides most services for this node. The first service node on the list that is accessible will be used. The 2nd node on the list is generally considered to be the backup service node for this node when running commands like snmove.', - netboot => 'The type of network booting to use for this node. Valid values: pxe or xnba for x86* architecture, yaboot for POWER architecture.', + netboot => 'The type of network booting to use for this node. Valid values: pxe or xnba for x86* architecture, yaboot for POWER architecture, grub2 for RHEL7 on Power. Notice: yaboot is not supported from rhels7 on Power,use grub2 instead', tftpserver => 'The TFTP server for this node (as known by this node). If not set, it defaults to networks.tftpserver.', tftpdir => 'The directory that roots this nodes contents from a tftp and related perspective. Used for NAS offload by using different mountpoints.', nfsserver => 'The NFS or HTTP server for this node (as known by this node).', @@ -915,6 +916,11 @@ site => { " '0' value means include all the nodes in the subnet.\n\n". " pruneservices: Whether to enable service pruning when noderm is run (i.e.\n". " removing DHCP entries when noderm is executed)\n\n". + " managedaddressmode: The mode of networking configuration during node provision.\n". + " If set to 'static', the network configuration will be configured \n". + " in static mode based on the node and network definition on MN.\n". + " If set to 'dhcp', the network will be configured with dhcp protocol.\n". + " The default is 'dhcp'.\n\n". " ------------\n". "DNS ATTRIBUTES\n". " ------------\n". @@ -935,6 +941,12 @@ site => { " \"\" to mean the DNS server for each node should be the\n". " node that is managing it (either its service node or the management\n". " node).\n\n". + " externaldns: To specify that external dns is used. If externaldns is set to any value\n". + " then, makedns command will not start the local nameserver on xCAT MN. \n". + " Default is to start the local nameserver.\n\n". + " dnsupdaters: The value are \',\' separated string which will be added to the zone config\n". + " section. This is an interface for user to add configuration entries to\n". + " the zone sections in named.conf.\n\n". " -------------------------\n". "HARDWARE CONTROL ATTRIBUTES\n". " -------------------------\n". @@ -1051,7 +1063,8 @@ site => { " Set to NOGROUPS,if you do not wish to enabled any group of compute nodes.\n". " Service Nodes are not affected by this attribute\n". " they are always setup with\n". - " passwordless root access to nodes and other SN.\n\n". + " passwordless root access to nodes and other SN.\n". + " If using the zone table, this attribute in not used.\n\n". " -----------------\n". "SERVICES ATTRIBUTES\n". " -----------------\n". @@ -1089,6 +1102,10 @@ site => { " will not interfere.\n\n". " vmwarereconfigonpower: When set to no, the VMWare plugin will make no effort to\n". " push vm.cpus/vm.memory updates from xCAT to VMWare.\n\n". + " persistkvmguests: Keep the kvm definition on the kvm hypervisor when you power off\n". + " the kvm guest node. This is useful for you to manually change the \n". + " kvm xml definition file in virsh for debugging. Set anything means\n". + " enable.\n\n". " --------------------\n". "XCAT DAEMON ATTRIBUTES\n". " --------------------\n". @@ -1189,6 +1206,19 @@ performance => { disable => "Set to 'yes' or '1' to comment out this row.", }, }, +zone => { + cols => [qw(zonename sshkeydir sshbetweennodes defaultzone comments disable)], + keys => [qw(zonename)], + table_desc => 'Defines a cluster zone for nodes that share root ssh key access to each other.', + descriptions => { + zonename => 'The name of the zone.', + sshkeydir => 'Directory containing the shared root ssh RSA keys.', + sshbetweennodes => 'Indicates whether passwordless ssh will be setup between the nodes of this zone. Values are yes/1 or no/0. Default is yes. ', + defaultzone => 'If nodes are not assigned to any other zone, they will default to this zone. If value is set to yes or 1.', + comments => 'Any user-provided notes.', + disable => "Set to 'yes' or '1' to comment out this row.", + }, + }, eventlog => { cols => [qw(recid eventtime eventtype monitor monnode node application component id severity message rawdata comments disable)], @@ -1325,7 +1355,7 @@ firmware => { }, nics => { - cols => [qw(node nicips nichostnamesuffixes nictypes niccustomscripts nicnetworks nicaliases comments disable)], + cols => [qw(node nicips nichostnamesuffixes nichostnameprefixes nictypes niccustomscripts nicnetworks nicaliases comments disable)], keys => [qw(node)], tablespace =>'XCATTBS16K', table_desc => 'Stores NIC details.', @@ -1343,6 +1373,13 @@ nics => { !|,!|,..., for example, eth0!-eth0|-eth0-ipv6,ib0!-ib0|-ib0-ipv6. The xCAT object definition commands support to use nichostnamesuffixes. as the sub attributes. Note: According to DNS rules a hostname must be a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-),and period (.). When you are specifying "nichostnamesuffixes" or "nicaliases" make sure the resulting hostnames will conform to this naming convention', + nichostnameprefixes => 'Comma-separated list of hostname prefixes per NIC. + If only one ip address is associated with each NIC: + !,!,..., for example, eth0!eth0-,ib0!ib- + If multiple ip addresses are associcated with each NIC: + !|,!|,..., for example, eth0!eth0-|eth0-ipv6i-,ib0!ib-|ib-ipv6-. + The xCAT object definition commands support to use nichostnameprefixes. as the sub attributes. + Note: According to DNS rules a hostname must be a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-),and period (.). When you are specifying "nichostnameprefixes" or "nicaliases" make sure the resulting hostnames will conform to this naming convention', nictypes => 'Comma-separated list of NIC types per NIC. !,!, e.g. eth0!Ethernet,ib0!Infiniband. The xCAT object definition commands support to use nictypes. as the sub attributes.', niccustomscripts => 'Comma-separated list of custom scripts per NIC. !,!, e.g. eth0!configeth eth0, ib0!configib ib0. The xCAT object definition commands support to use niccustomscripts. as the sub attribute .', @@ -1535,8 +1572,20 @@ hwinv => { node => 'The node name or group name.', cputype => 'The cpu model name for the node.', cpucount => 'The number of cpus for the node.', - memory => 'The size of the memory for the node.', - disksize => 'The size of the disks for the node.', + memory => 'The size of the memory for the node in MB.', + disksize => 'The size of the disks for the node in GB.', + comments => 'Any user-provided notes.', + disable => "Set to 'yes' or '1' to comment out this row.", + }, +}, +token => { + cols => [qw(tokenid username expire comments disable)], + keys => [qw(tokenid)], + table_desc => 'The token of users for authentication.', + descriptions => { + tokenid => 'It is a UUID as an unified identify for the user.', + username => 'The user name.', + expire => 'The expire time for this token.', comments => 'Any user-provided notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, @@ -1618,6 +1667,7 @@ foreach my $tabname (keys(%xCAT::ExtTab::ext_tabspec)) { rack => { attrs => [], attrhash => {}, objkey => 'rackname' }, osdistro=> { attrs => [], attrhash => {}, objkey => 'osdistroname' }, osdistroupdate=> { attrs => [], attrhash => {}, objkey => 'osupdatename' }, + zone=> { attrs => [], attrhash => {}, objkey => 'zonename' }, ); @@ -2244,6 +2294,10 @@ my @nodeattrs = ( tabentry => 'nics.nichostnamesuffixes', access_tabentry => 'nics.node=attr:node', }, + {attr_name => 'nichostnameprefixes', + tabentry => 'nics.nichostnameprefixes', + access_tabentry => 'nics.node=attr:node', + }, {attr_name => 'nictypes', tabentry => 'nics.nictypes', access_tabentry => 'nics.node=attr:node', @@ -2588,6 +2642,10 @@ my @nodeattrs = ( {attr_name => 'updatestatustime', tabentry => 'nodelist.updatestatustime', access_tabentry => 'nodelist.node=attr:node', + }, + {attr_name => 'zonename', + tabentry => 'nodelist.zonename', + access_tabentry => 'nodelist.node=attr:node', }, {attr_name => 'usercomment', tabentry => 'nodelist.comments', @@ -3042,6 +3100,36 @@ push(@{$defspec{node}->{'attrs'}}, @nodeattrs); access_tabentry => 'rack.rackname=attr:rackname', }, ); +#################### +# zone table # +#################### +@{$defspec{zone}->{'attrs'}} = ( + {attr_name => 'zonename', + tabentry => 'zone.zonename', + access_tabentry => 'zone.zonename=attr:zonename', + }, + {attr_name => 'sshkeydir', + tabentry => 'zone.sshkeydir', + access_tabentry => 'zone.zonename=attr:zonename', + }, + {attr_name => 'sshbetweennodes', + tabentry => 'zone.sshbetweennodes', + access_tabentry => 'zone.zonename=attr:zonename', + }, + {attr_name => 'defaultzone', + tabentry => 'zone.defaultzone', + access_tabentry => 'zone.zonename=attr:zonename', + }, + {attr_name => 'usercomment', + tabentry => 'zone.comments', + access_tabentry => 'zone.zonename=attr:zonename', + }, + ); +######################### +# route data object # +######################### +# routes table # +######################### ######################### # route data object # ######################### diff --git a/perl-xCAT/xCAT/TableUtils.pm b/perl-xCAT/xCAT/TableUtils.pm old mode 100644 new mode 100755 index 9e3b452ad..69599d1fd --- a/perl-xCAT/xCAT/TableUtils.pm +++ b/perl-xCAT/xCAT/TableUtils.pm @@ -19,6 +19,7 @@ if ($^O =~ /^aix/i) { use lib "$::XCATROOT/lib/perl"; use strict; require xCAT::Table; +require xCAT::Zone; use File::Path; #----------------------------------------------------------------------- @@ -271,7 +272,7 @@ sub bldnonrootSSHFiles Error: 0=good, 1=error Example: - xCAT::TableUtils->setupSSH(@target_nodes); + xCAT::TableUtils->setupSSH(@target_nodes,$expecttimeout); Comments: Does not setup known_hosts. Assumes automatically setup by SSH ( ssh config option StrictHostKeyChecking no should @@ -335,21 +336,21 @@ sub setupSSH $::REMOTE_SHELL = "/usr/bin/ssh"; my $rsp = {}; + # Get the home directory my $home = xCAT::Utils->getHomeDir($from_userid); $ENV{'DSH_FROM_USERID_HOME'} = $home; - if ($from_userid eq "root") { - # make the directory to hold keys to transfer to the nodes if (!-d $SSHdir) { mkpath("$SSHdir", { mode => 0755 }); } - # generates new keys for root, if they do not already exist + # generates new keys for root, if they do not already exist ~/.ssh + # nodes not used on this option but in there to preserve the interface my $rc= xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL,$n_str,$expecttimeout); @@ -374,7 +375,10 @@ else fi mkdir -p \$dest_dir cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1 +cat /tmp/$to_userid/.ssh/id_rsa.pub >> \$home/.ssh/authorized_keys 2>&1 +rm -f \$home/.ssh/id_rsa 2>&1 cp /tmp/$to_userid/.ssh/id_rsa \$home/.ssh/id_rsa 2>&1 +cp /tmp/$to_userid/.ssh/id_rsa.pub \$home/.ssh/id_rsa.pub 2>&1 chmod 0600 \$home/.ssh/id_* 2>&1 rm -f /tmp/$to_userid/.ssh/* 2>&1 rmdir \"/tmp/$to_userid/.ssh\" @@ -386,6 +390,7 @@ rmdir \"/tmp/$to_userid\" \n"; my $auth_key2=0; if ($from_userid eq "root") { + # this will put the root/.ssh/id_rsa.pub key in the authorized keys file to put on the node my $rc = xCAT::TableUtils->cpSSHFiles($SSHdir); if ($rc != 0) { # error @@ -418,50 +423,46 @@ rmdir \"/tmp/$to_userid\" \n"; xCAT::TableUtils->bldnonrootSSHFiles($from_userid); } - # send the keys to the nodes for root or some other id - # - # This environment variable determines whether to setup - # node to node ssh - # The nodes must be checked against the site.sshbetweennodes attribute + # send the keys # For root user and not to devices only to nodes if (($from_userid eq "root") && (!($ENV{'DEVICETYPE'}))) { - my $enablenodes; - my $disablenodes; - my @nodelist= split(",", $n_str); - foreach my $n (@nodelist) + # Need to check if nodes are in a zone. + my @zones; + my $tab = xCAT::Table->new("zone"); + if ($tab) { - my $enablessh=xCAT::TableUtils->enablessh($n); - if ($enablessh == 1) { - $enablenodes .= $n; - $enablenodes .= ","; - } else { - $disablenodes .= $n; - $disablenodes .= ","; + # if we have zones, need to send the zone keys to each node in the zone + my @attribs = ("zonename"); + @zones = $tab->getAllAttribs(@attribs); + $tab->close(); + } else { + $rsp->{data}->[0] = "Could not open zone table.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + # check for zones, key send is different if zones defined or not + + if (@zones) { # we have zones defined + my $rc = xCAT::TableUtils->sendkeysTOzones($ref_nodes,$expecttimeout); + if ($rc != 0) + { + $rsp->{data}->[0] = "Error sending ssh keys to the zones.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + exit 1; + } - - } - my $cmd; - if ($enablenodes) { # node on list to setup nodetonodessh - chop $enablenodes; # remove last comma - $ENV{'DSH_ENABLE_SSH'} = "YES"; - my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes,$expecttimeout); + } else { # no zones + + # if no zone table defined, do it the old way , keys are in ~/.ssh + my $rc = xCAT::TableUtils->sendkeysNOzones($ref_nodes,$expecttimeout); if ($rc != 0) - { - $rsp->{data}->[0] = "remoteshellexp failed sending keys to enablenodes."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - - } - } - if ($disablenodes) { # node on list to setup nodetonodessh - chop $disablenodes; # remove last comma - my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes,$expecttimeout); - if ($rc != 0) - { - $rsp->{data}->[0] = "remoteshellexp failed sending keys to disablenodes."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + { + $rsp->{data}->[0] = "Error sending ssh keys to the nodes.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); } } + } else { # from user is not root or it is a device , always send private key $ENV{'DSH_ENABLE_SSH'} = "YES"; my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$n_str,$expecttimeout); @@ -503,6 +504,235 @@ rmdir \"/tmp/$to_userid\" \n"; #-------------------------------------------------------------------------------- +=head3 sendkeysNOzones + + Transfers the ssh keys + for the root id on the nodes no zones + key from ~/.ssh site.sshbetweennodes honored + + + Arguments: + Array of nodes + Timeout for expect call (optional) + Returns: + + Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD + the ssh keys are transferred from the $DSH_FROM_USERID to the $DSH_TO_USERID + on the node(s). The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID + must be obtained by + the calling script or from the xdsh client + + Globals: + $::XCATROOT , $::CALLBACK + Error: + 0=good, 1=error + Example: + xCAT::TableUtils->sendkeysNOzones($ref_nodes,$expecttimeout); + Comments: + Does not setup known_hosts. Assumes automatically + setup by SSH ( ssh config option StrictHostKeyChecking no should + be set in the ssh config file). + +=cut + +#-------------------------------------------------------------------------------- +sub sendkeysNOzones +{ + my ($class, $ref_nodes,$expecttimeout) = @_; + my @nodes=$ref_nodes; + my $enablenodes; + my $disablenodes; + my $n_str = $nodes[0]; + my @nodelist= split(",", $n_str); + my $rsp = (); + foreach my $n (@nodelist) + { + my $enablessh=xCAT::TableUtils->enablessh($n); + if ($enablessh == 1) { + $enablenodes .= $n; + $enablenodes .= ","; + } else { + $disablenodes .= $n; + $disablenodes .= ","; + } + + } + if ($enablenodes) { # node on list to setup nodetonodessh + chop $enablenodes; # remove last comma + $ENV{'DSH_ENABLE_SSH'} = "YES"; + # send the keys to the nodes + my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes,$expecttimeout); + if ($rc != 0) + { + $rsp->{data}->[0] = "remoteshellexp failed sending keys to enablenodes."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + + } + } + if ($disablenodes) { # node on list to disable nodetonodessh + chop $disablenodes; # remove last comma + # send the keys to the nodes + my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes,$expecttimeout); + if ($rc != 0) + { + $rsp->{data}->[0] = "remoteshellexp failed sending keys to disablenodes."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + + } + } +} +#-------------------------------------------------------------------------------- + +=head3 sendkeysTOzones + + Transfers the ssh keys + for the root id on the nodes using the zone table. + If in a zone, then root ssh keys for the node will be taken from the zones ssh keys not ~/.ssh + zones are only supported on nodes that are not a service node. + Also for the call to RemoteShellExp, we must group the nodes that are in the same zone + + + Arguments: + Array of nodes + Timeout for expect call (optional) + Returns: + + Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD + the ssh keys are transferred from the $DSH_FROM_USERID to the $DSH_TO_USERID + on the node(s). The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID + must be obtained by + the calling script or from the xdsh client + + Globals: + $::XCATROOT , $::CALLBACK + Error: + 0=good, 1=error + Example: + xCAT::TableUtils->sendkeysTOzones($ref_nodes,$expecttimeout); + Comments: + Does not setup known_hosts. Assumes automatically + setup by SSH ( ssh config option StrictHostKeyChecking no should + be set in the ssh config file). + +=cut + +#-------------------------------------------------------------------------------- +sub sendkeysTOzones +{ + my ($class, $ref_nodes,$expecttimeout) = @_; + my @nodes=$ref_nodes; + my $n_str = $nodes[0]; + @nodes= split(",", $n_str); + my $rsp = (); + my $cmd; + my $roothome = xCAT::Utils->getHomeDir("root"); + my $zonehash =xCAT::Zone->getzoneinfo($::CALLBACK,\@nodes); + foreach my $zonename (keys %$zonehash) { + # build list of nodes + my $zonenodelist=""; + foreach my $node (@{$zonehash->{$zonename}->{nodes}}) { + $zonenodelist .= $node; + $zonenodelist .= ","; + + } + $zonenodelist =~ s/,$//; # remove last comma + # if any nodes defined for the zone + if ($zonenodelist) { + # check to see if we enable passwordless ssh between the nodes + if (!(defined($zonehash->{$zonename}->{sshbetweennodes}))|| + (($zonehash->{$zonename}->{sshbetweennodes} =~ /^yes$/i ) + || ($zonehash->{$zonename}->{sshbetweennodes} eq "1"))) { + + $ENV{'DSH_ENABLE_SSH'} = "YES"; + } else { + delete $ENV{'DSH_ENABLE_SSH'}; # do not enable passwordless ssh + } + # point to the ssh keys to send for this zone + my $keydir = $zonehash->{$zonename}->{sshkeydir} ; + + # check to see if the id_rsa and id_rsa.pub key is in the directory + my $key="$keydir/id_rsa"; + my $key2="$keydir/id_rsa.pub"; + # Check to see if empty + if (!(-e $key)) { + my $rsp = {}; + $rsp->{error}->[0] = + "The $key file does not exist for $zonename. Need to use chzone to regenerate the keys."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return 1; + } + if (!(-e $key2)) { + my $rsp = {}; + $rsp->{error}->[0] = + "The $key2 file does not exist for $zonename. Need to use chzone to regenerate the keys."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return 1; + + } + + # now put copy.sh in the zone directory from ~/.ssh + my $rootkeydir="$roothome/.ssh"; + if ($rootkeydir ne $keydir) { # the zone keydir is not the same as ~/.ssh. + $cmd="cp $rootkeydir/copy.sh $keydir"; + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = + "Could not copy copy.sh to the zone key dir"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + } + # Also create $keydir/tmp and put root's id_rsa.pub (in authorized_keys) for the transfer + $cmd="mkdir -p $keydir/tmp"; + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = + "Could not mkdir the zone $keydir/tmp"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + # create authorized_keys file + if (xCAT::Utils->isMN()) { # if on Management Node + $cmd = " cp $roothome/.ssh/id_rsa.pub $keydir/tmp/authorized_keys"; + } else { # SN + $cmd = " cp $roothome/.ssh/authorized_keys $keydir/tmp/authorized_keys"; + } + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + } + else + { + chmod 0600, "$keydir/.ssh/tmp/authorized_keys"; + } + # strip off .ssh + my ($newkeydir,$ssh) = (split(/\.ssh/, $keydir)); + $ENV{'DSH_ZONE_SSHKEYS'} =$newkeydir ; + # send the keys to the nodes + my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh", + $zonenodelist,$expecttimeout); + if ($rc != 0) + { + $rsp = {}; + $rsp->{data}->[0] = "remoteshellexp failed sending keys to $zonename."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + + } + } # end nodes in the zone + + } # end for each zone + + return (0); +} +#-------------------------------------------------------------------------------- + =head3 cpSSHFiles Builds authorized_keyfiles for root @@ -947,7 +1177,9 @@ sub getAppStatus my ($class, $nodes_ref, $application) = @_; my @nodes = @$nodes_ref; - my $nltab = xCAT::Table->new('nodelist'); + # FIXME: why autocommit matters for a read-only subroutine getNodesAttribs? + # but could not get the appstatus without the autocommit=0 + my $nltab = xCAT::Table->new('nodelist', -autocommit => 0); my $nodeappstat = $nltab->getNodesAttribs(\@nodes,['appstatus']); my $ret_nodeappstat; @@ -1594,8 +1826,8 @@ sub enableSSH } else { # if not a service node we need to check, before enabling - if (defined($groups_hash)) { - if ($groups_hash->{ALLGROUPS} == 1) + if (keys %$groups_hash) { # not empty + if ($groups_hash->{ALLGROUPS} == 1) { $enablessh=1; } @@ -1769,7 +2001,7 @@ sub updatenodegroups { } } my ($ent) = $tabhd->getNodeAttribs($node, ['groups']); - my @list = qw(all); + my @list = (); if (defined($ent) and $ent->{groups}) { push @list, split(/,/,$ent->{groups}); } @@ -1783,5 +2015,54 @@ sub updatenodegroups { @list = keys %saw; $tabhd->setNodeAttribs($node, {groups=>join(",",@list)}); } +#----------------------------------------------------------------------------- + + +=head3 rmnodegroups + remove groups from the group attribute for the specified node + + Arguments: + node + tabhd: the handler of 'nodelist' table, + groups: the groups that need to be removed. + Can be an array or string. + Globals: + none + Error: + Example: + xCAT::TableUtils->rmnodegroups($node, $tab, $groups); + +=cut + +#----------------------------------------------------------------------------- + +sub rmnodegroups { + my ($class, $node, $tabhd, $groups) = @_; + my ($ent) = $tabhd->getNodeAttribs($node, ['groups']); + my @definedgroups; + my @removegroups; + my @newgroups; + if (defined($ent) and $ent->{groups}) { + push @definedgroups, split(/,/,$ent->{groups}); + } + if (ref($groups) eq 'ARRAY') { + push @removegroups, @$groups; + } else { + push @removegroups, split(/,/,$groups); + } + # take out any groups that match the input list of groups to remove + foreach my $dgrp (@definedgroups){ + if (grep(/^$dgrp$/, @removegroups)) { # is the group to be removed + next; + } else { # keep this group + push @newgroups,$dgrp; + } + } + my %saw; + @saw{@newgroups} = (); + @newgroups = keys %saw; + + $tabhd->setNodeAttribs($node, {groups=>join(",",@newgroups)}); +} 1; diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index cbf4ede50..7033510a3 100644 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -222,7 +222,7 @@ my %usage = ( lsvm [-a|--all] PPC (using Direct FSP Management) specific: lsvm [-l|--long] --p775 - lsvm + lsvm zVM specific: lsvm noderange lsvm noderange --getnetworknames diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index 2018d5ea0..e660b1da4 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -3416,4 +3416,104 @@ sub version_cmp { return ( $len_a <=> $len_b ) } + +#-------------------------------------------------------------------------------- + +=head3 fullpathbin + returns the full path of a specified binary executable file + Arguments: + string of the bin file name + Returns: + string of the full path name of the binary executable file + Globals: + none + Error: + string of the bin file name in the argument + Example: + my $CHKCONFIG = xCAT::Utils->fullpathbin("chkconfig"); + Comments: + none +=cut + +#-------------------------------------------------------------------------------- +sub fullpathbin +{ + my $bin=shift; + if( $bin =~ /xCAT::Utils/) + { + $bin=shift; + } + + my @paths= ("/bin","/usr/bin","/sbin","/usr/sbin"); + my $fullpath=$bin; + + foreach my $path (@paths) + { + if (-x $path.'/'.$bin) + { + $fullpath= $path.'/'.$bin; + last; + } + } + + return $fullpath; +} + +#-------------------------------------------------------------------------------- + +=head3 gettimezone + returns the name of the timezone defined on the Linux distro. + This routine was written to replace the use of /etc/sysconfig/clock which in no + longer supported on future Linux releases such as RHEL7. It is suppose to be a routine + that can find the timezone on any Linux OS or AIX. + Arguments: + none + Returns: + Name of timezone, for example US/Eastern + Globals: + none + Error: + None + Example: + my $timezone = xCAT::Utils->gettimezone(); + Comments: + none +=cut + +#-------------------------------------------------------------------------------- +sub gettimezone +{ + my ($class) = @_; + + my $tz; + if (xCAT::Utils->isAIX()) { + $tz= $ENV{'TZ'}; + } else { # all linux + my $localtime = "/etc/localtime"; + my $zoneinfo = "/usr/share/zoneinfo"; + my $cmd = "find $zoneinfo -type f -exec cmp -s $localtime {} \\; -print | grep -v posix | grep -v SystemV"; + my $zone_result = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + $tz="Could not determine timezone checksum"; + return $tz; + } + my @zones = split /\n/, $zone_result; + + $zones[0] =~ s/$zoneinfo\///; + if (!$zones[0]) { # if we still did not get one, then default + $tz = `cat /etc/timezone`; + chomp $tz; + } else { + $tz=$zones[0]; + } + + + } + return $tz; + + +} + + 1; diff --git a/perl-xCAT/xCAT/Zone.pm b/perl-xCAT/xCAT/Zone.pm new file mode 100644 index 000000000..0b8e7bd67 --- /dev/null +++ b/perl-xCAT/xCAT/Zone.pm @@ -0,0 +1,452 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT::Zone; + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} + +# if AIX - make sure we include perl 5.8.2 in INC path. +# Needed to find perl dependencies shipped in deps tarball. +if ($^O =~ /^aix/i) { + unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2)); +} + +use lib "$::XCATROOT/lib/perl"; +# do not put a use or require for xCAT::Table here. Add to each new routine +# needing it to avoid reprocessing of user tables ( ExtTab.pm) for each command call +use POSIX qw(ceil); +use File::Path; +use Socket; +use strict; +use Symbol; +use warnings "all"; + +#-------------------------------------------------------------------------------- + +=head1 xCAT::Zone + +=head2 Package Description + +This program module file, is a set of Zone utilities used by xCAT *zone commands. + +=cut + + +#-------------------------------------------------------------------------------- + +=head3 genSSHRootKeys + Arguments: + callback for error messages + directory in which to put the ssh RSA keys + zonename + rsa private key to use for generation ( optional) + Returns: + Error: 1 - key generation failure. + Example: + $rc =xCAT::Zone->genSSHRootKeys($callback,$keydir,$rsakey); +=cut + +#-------------------------------------------------------------------------------- +sub genSSHRootKeys +{ + my ($class, $callback, $keydir,$zonename,$rsakey) = @_; + + # + # create /keydir if needed + # + if (!-d $keydir) + { + my $cmd = "/bin/mkdir -m 700 -p $keydir"; + my $output = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = + "Could not create $keydir directory"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + + } + } + + + #need to gen a new rsa key for root for the zone + my $pubfile = "$keydir/id_rsa.pub"; + my $pvtfile = "$keydir/id_rsa"; + + # if exists, remove the old files + if (-r $pubfile) + { + + my $cmd = "/bin/rm $keydir/id_rsa*"; + my $output = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Could not remove id_rsa files from $keydir directory."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + + # gen new RSA keys + my $cmd; + my $output; + # if private key was input use it + if (defined ($rsakey)) { + $cmd="/usr/bin/ssh-keygen -y -f $rsakey > $pubfile"; + $output = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Could not generate $pubfile from $rsakey"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # now copy the private key into the directory + $cmd="cp $rsakey $keydir"; + $output = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Could not run $cmd"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } else { # generate all new keys + $cmd = "/usr/bin/ssh-keygen -t rsa -q -b 2048 -N '' -f $pvtfile"; + $output = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Could not generate $pubfile"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + #make sure permissions are correct + $cmd = "chmod 644 $pubfile;chown root $pubfile"; + $output = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Could set permission and owner on $pubfile"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } +} +#-------------------------------------------------------------------------------- + +=head3 getdefaultzone + Arguments: + None + Returns: + Name of the current default zone from the zone table + Example: + my $defaultzone =xCAT::Zone->getdefaultzone($callback); +=cut + +#-------------------------------------------------------------------------------- +sub getdefaultzone +{ + my ($class, $callback) = @_; + my $defaultzone; + # read all the zone table and find the defaultzone, if it exists + my $tab = xCAT::Table->new("zone"); + if ($tab){ + my @zones = $tab->getAllAttribs('zonename','defaultzone'); + foreach my $zone (@zones) { + # Look for the defaultzone=yes/1 entry + if ((defined($zone->{defaultzone})) && + (($zone->{defaultzone} =~ /^yes$/i ) + || ($zone->{defaultzone} eq "1"))) { + $defaultzone = $zone->{zonename}; + } + $tab->close(); + } + } else { + my $rsp = {}; + $rsp->{error}->[0] = + "Error reading the zone table. "; + xCAT::MsgUtils->message("E", $rsp, $callback); + + } + return $defaultzone; +} +#-------------------------------------------------------------------------------- + +=head3 iszonedefined + Arguments: + zonename + Returns: + 1 if the zone is already in the zone table. + Example: + xCAT::Zone->iszonedefined($zonename); +=cut + +#-------------------------------------------------------------------------------- +sub iszonedefined +{ + my ($class,$zonename) = @_; + # checks the zone table to see if input zonename already in the table + my $tab = xCAT::Table->new("zone"); + $tab->close(); + my $zonehash = $tab->getAttribs({zonename => $zonename},'sshkeydir'); + if ( keys %$zonehash) { + return 1; + }else{ + return 0; + } +} +#-------------------------------------------------------------------------------- + +=head3 getzonekeydir + Arguments: + zonename + Returns: + path to the root ssh keys for the zone /etc/xcat/sshkeys//.ssh + 1 - zone not defined + Example: + xCAT::Zone->getzonekeydir($zonename); +=cut + +#-------------------------------------------------------------------------------- +sub getzonekeydir +{ + my ($class,$zonename) = @_; + my $tab = xCAT::Table->new("zone"); + $tab->close(); + my $zonehash = $tab->getAttribs({zonename => $zonename},'sshkeydir'); + if ( keys %$zonehash) { + my $zonesshkeydir=$zonehash->{sshkeydir}; + return $zonesshkeydir; + }else{ + return 1; # this is a bad error zone not defined + } +} +#-------------------------------------------------------------------------------- + +=head3 getmyzonename + Arguments: + $node -one nodename + Returns: + $zonename + Example: + my $zonename=xCAT::Zone->getmyzonename($node); +=cut + +#-------------------------------------------------------------------------------- +sub getmyzonename +{ + my ($class,$node,$callback) = @_; + my @node; + push @node,$node; + my $zonename; + my $nodelisttab = xCAT::Table->new("nodelist"); + my $nodehash = $nodelisttab->getNodesAttribs(\@node, ['zonename']); + $nodelisttab->close(); + if ( defined ($nodehash->{$node}->[0]->{zonename})) { # it was defined in the nodelist table + $zonename=$nodehash->{$node}->[0]->{zonename}; + } else { # get the default zone + $zonename =xCAT::Zone->getdefaultzone($callback); + } + return $zonename; +} +#-------------------------------------------------------------------------------- + +=head3 enableSSHbetweennodes + Arguments: + zonename + Returns: + 1 if the sshbetweennodes attribute is yes/1 or undefined + 0 if the sshbetweennodes attribute is no/0 + Example: + xCAT::Zone->enableSSHbetweennodes($zonename); +=cut + +#-------------------------------------------------------------------------------- +sub enableSSHbetweennodes +{ + my ($class,$node,$callback) = @_; + # finds the zone of the node + my $enablessh = 1; # default + my $zonename=xCAT::Zone->getmyzonename($node); + # reads the zone table + my $tab = xCAT::Table->new("zone"); + $tab->close(); + # read both keys, want to know zone is in the zone table. If sshkeydir is not there + # it is either missing or invalid anyway + my $zonehash = $tab->getAttribs({zonename => $zonename},'sshbetweennodes','sshkeydir'); + if (! ( keys %$zonehash)) { + my $rsp = {}; + $rsp->{error}->[0] = + "$node has a zonename: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone. The generated mypostscript may not reflect the correct setting for ENABLESSHBETWEENNODES"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return $enablessh; + } + my $sshbetweennodes=$zonehash->{sshbetweennodes}; + if (defined ($sshbetweennodes)) { + if (($sshbetweennodes =~ /^no$/i) || ($sshbetweennodes eq "0")) { + $enablessh = 0; + } else { + $enablessh = 1; + } + } else { # not defined default yes + $enablessh = 1 ; # default + } + return $enablessh; +} +#-------------------------------------------------------------------------------- + +=head3 usingzones + Arguments: + none + Returns: + 1 if the zone table is not empty + 0 if empty + Example: + xCAT::Zone->usingzones; +=cut + +#-------------------------------------------------------------------------------- +sub usingzones +{ + my ($class) = @_; + # reads the zonetable + my $tab = xCAT::Table->new("zone"); + my @zone = $tab->getAllAttribs('zonename'); + $tab->close(); + if (@zone) { + return 1; + }else{ + return 0; + } +} +#-------------------------------------------------------------------------------- + +=head3 getzoneinfo + Arguments: + callback + An array of nodes + Returns: + Hash array by zonename point to the nodes in that zonename and sshkeydir + -> {nodelist} -> array of nodes in the zone + -> {sshkeydir} -> directory containing ssh RSA keys + -> {defaultzone} -> is it the default zone + Example: + my %zonehash =xCAT::Zone->getzoneinfo($callback,@nodearray); + Rules: + If the nodes nodelist.zonename attribute is a zonename, it is assigned to that zone + If the nodes nodelist.zonename attribute is undefined: + If there is a defaultzone in the zone table, the node is assigned to that zone + If there is no defaultzone in the zone table, the node is assigned to the ~.ssh keydir + $::GETZONEINFO_RC + 0 = good return + 1 = error occured +=cut + +#-------------------------------------------------------------------------------- +sub getzoneinfo +{ + my ($class, $callback,$nodes) = @_; + $::GETZONEINFO_RC=0; + my $zonehash; + my $defaultzone; + # read all the zone table + my $zonetab = xCAT::Table->new("zone"); + my @zones; + if ($zonetab){ + @zones = $zonetab->getAllAttribs('zonename','sshkeydir','sshbetweennodes','defaultzone'); + $zonetab->close(); + if (@zones) { + foreach my $zone (@zones) { + my $zonename=$zone->{zonename}; + $zonehash->{$zonename}->{sshkeydir}= $zone->{sshkeydir}; + $zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone}; + $zonehash->{$zonename}->{sshbetweennodes}= $zone->{sshbetweennodes}; + # find the defaultzone + if ((defined($zone->{defaultzone})) && + (($zone->{defaultzone} =~ /^yes$/i ) + || ($zone->{defaultzone} eq "1"))) { + $defaultzone = $zone->{zonename}; + } + } + } + } else { + my $rsp = {}; + $rsp->{error}->[0] = + "Error reading the zone table. "; + xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; + return; + + } + my $nodelisttab = xCAT::Table->new("nodelist"); + my $nodehash = $nodelisttab->getNodesAttribs(\@$nodes, ['zonename']); + # for each of the nodes, look up it's zone name and assign to the zonehash + # If the nodes nodelist.zonename attribute is a zonename, it is assigned to that zone + # If the nodes nodelist.zonename attribute is undefined: + # If there is a defaultzone in the zone table, the node is assigned to that zone + # If there is no defaultzone error out + + + foreach my $node (@$nodes) { + my $zonename; + $zonename=$nodehash->{$node}->[0]->{zonename}; + if (defined($zonename)) { # zonename explicitly defined in nodelist.zonename + # check to see if defined in the zone table + unless ( xCAT::Zone->iszonedefined($zonename)) { + my $rsp = {}; + $rsp->{error}->[0] = + "$node has a zonename: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; + return; + } + push @{$zonehash->{$zonename}->{nodes}},$node; + } else { # no explict zonename + if (defined ($defaultzone)) { # there is a default zone in the zone table, use it + push @{$zonehash->{$defaultzone}->{nodes}},$node; + } else { # if no default, this is an error + my $rsp = {}; + $rsp->{error}->[0] = + "There is no default zone defined in the zone table. There must be exactly one default zone. "; + xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; + return; + + } + } + } + return $zonehash; +} +#-------------------------------------------------------------------------------- + +=head3 getnodesinzone + Arguments: + callback + zonename + Returns: + Array of nodes + Example: + my @nodes =xCAT::Zone->getnodesinzone($callback,$zonename); +=cut + +#-------------------------------------------------------------------------------- +sub getnodesinzone +{ + my ($class, $callback,$zonename) = @_; + my @nodes; + my $nodelisttab = xCAT::Table->new("nodelist"); + my @nodelist=$nodelisttab->getAllAttribs('node','zonename'); + # build the array of nodes in this zone + foreach my $nodename (@nodelist) { + if ((defined($nodename->{'zonename'})) && ($nodename->{'zonename'} eq $zonename)) { + push @nodes,$nodename->{'node'}; + } + } + return @nodes; +} +1; diff --git a/perl-xCAT/xCAT/data/discinfo.pm b/perl-xCAT/xCAT/data/discinfo.pm index f7093026a..8e64a0165 100755 --- a/perl-xCAT/xCAT/data/discinfo.pm +++ b/perl-xCAT/xCAT/data/discinfo.pm @@ -14,9 +14,10 @@ require Exporter; %distnames = ( "1310229985.226287" => "centos6", - "1323560292.885204" => "centos6.2", - "1341569670.539525" => "centos6.3",#x86 - "1362445555.957609" => "centos6.4",#x86_64 + "1323560292.885204" => "centos6.2", + "1341569670.539525" => "centos6.3",#x86 + "1362445555.957609" => "centos6.4",#x86_64 + "1385726732.061157" => "centos6.5",#x86_64 "1176234647.982657" => "centos5", "1156364963.862322" => "centos4.4", "1178480581.024704" => "centos4.5", @@ -28,6 +29,7 @@ require Exporter; "1272326751.405938" => "centos5.5", "1330913492.861127" => "centos5.8",#x86_64 "1357930415.252042" => "centos5.9",#x86_64 + "1381776971.473332" => "centos5.10",#x86_64 "1195488871.805863" => "centos4.6", "1195487524.127458" => "centos4.6", "1301444731.448392" => "centos5.6", @@ -69,6 +71,7 @@ require Exporter; "1321545261.599847" => "rhelhpc6.2",#x86_64 "1339640148.070971" => "rhelhpc6.3",#x86_64 "1359576195.413831" => "rhelhpc6.4",#x86_64, RHEL ComputeNode + "1384196516.465862" => "rhelhpc6.5",#x86_64, RHEL ComputeNode "1194015916.783841" => "fedora8", "1194015385.299901" => "fedora8", "1210112435.291709" => "fedora9", diff --git a/perl-xCAT/xCAT/vboxService.pm b/perl-xCAT/xCAT/vboxService.pm index 606be99cd..fde7d06fd 100644 --- a/perl-xCAT/xCAT/vboxService.pm +++ b/perl-xCAT/xCAT/vboxService.pm @@ -1,3755 +1,917 @@ -# IBM(c) 2008 EPL license http://www.eclipse.org/legal/epl-v10.html -# Ver. 2.1 (3) - sf@mauricebrinkmann.de -#------------------------------------------------------- - -package xCAT::vboxService; -my %methods = ( -IVirtualBox_getExtraData => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getExtraData -ISerialPort_setHostMode => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'hostMode', type => 'vbox:PortMode', attr => {}), - ], # end parameters - }, # end ISerialPort_setHostMode -IHostFloppyDrive_getName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostFloppyDrive_getName -IVHDImage_getCreated => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVHDImage_getCreated -IFloppyDrive_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IFloppyDrive_setEnabled -IUSBDeviceFilter_getManufacturer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getManufacturer -IParallelPort_setIOBase => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'IOBase', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IParallelPort_setIOBase -ISystemProperties_getNetworkAdapterCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getNetworkAdapterCount -IMachine_getName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getName -IVRDPServer_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IVRDPServer_setEnabled -IHardDisk_setDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'description', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_setDescription -IVRDPServer_getNetAddress => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_getNetAddress -ISnapshot_getChildren => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getChildren -IMachine_getOSTypeId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getOSTypeId -IUSBDevice_getRevision => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getRevision -IVirtualDiskImage_deleteImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualDiskImage_deleteImage -IHardDisk_setType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'type', type => 'vbox:HardDiskType', attr => {}), - ], # end parameters - }, # end IHardDisk_setType -IVirtualBox_getHost => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getHost -IMachine_setCurrentSnapshot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_setCurrentSnapshot -IUSBDevice_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getId -IDVDDrive_getState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_getState -IISCSIHardDisk_getLun => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_getLun -IConsole_getSharedFolders => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getSharedFolders -IMachine_getVRAMSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getVRAMSize -IMachine_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getId -ISerialPort_setServer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'server', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end ISerialPort_setServer -ISnapshot_setName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_setName -IMachine_getPAEEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getPAEEnabled -IVirtualBox_getDVDImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getDVDImage -IUSBDevice_getProductId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getProductId -ISnapshot_getTimeStamp => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getTimeStamp -IVirtualBox_openFloppyImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openFloppyImage -IHost_getFloppyDrives => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getFloppyDrives -IMachine_getLogFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getLogFolder -IMachine_getBIOSSettings => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getBIOSSettings -ISystemProperties_getMinGuestVRAM => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getMinGuestVRAM -IVirtualBox_registerFloppyImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'image', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_registerFloppyImage -IHardDisk_getStorageType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getStorageType -INetworkAdapter_attachToInternalNetwork => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_attachToInternalNetwork -ISerialPort_getPath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getPath -ISATAController_getPortCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISATAController_getPortCount -IHardDisk_getLocation => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getLocation -IProgress_getResultCode => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getResultCode -ISystemProperties_getMaxBootPosition => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getMaxBootPosition -IMachine_getStateFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getStateFilePath -IUSBController_getDeviceFilters => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBController_getDeviceFilters -IVirtualBox_saveSettingsWithBackup => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_saveSettingsWithBackup -IMachine_attachHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'bus', type => 'vbox:StorageBus', attr => {}), - SOAP::Data->new(name => 'channel', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'device', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IMachine_attachHardDisk -IMachine_getSettingsFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSettingsFilePath -INetworkAdapter_setLineSpeed => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'lineSpeed', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setLineSpeed -IConsole_pause => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_pause -IMachine_getClipboardMode => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getClipboardMode -IVirtualBox_getMachines2 => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getMachines2 -ISerialPort_setIOBase => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'IOBase', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end ISerialPort_setIOBase -IMachine_setName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_setName -IMachine_getState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getState -ISerialPort_getSlot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getSlot -INetworkAdapter_setAdapterType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'adapterType', type => 'vbox:NetworkAdapterType', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setAdapterType -IConsole_takeSnapshot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'description', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_takeSnapshot -IVirtualDiskImage_createFixedImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IVirtualDiskImage_createFixedImage -IMachine_getCurrentSnapshot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getCurrentSnapshot -IConsole_getRemoteUSBDevices => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getRemoteUSBDevices -IVirtualBox_getFloppyImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getFloppyImage -INetworkAdapter_setTraceEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'traceEnabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setTraceEnabled -IProgress_getCompleted => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getCompleted -IISCSIHardDisk_setUserName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'userName', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_setUserName -ISystemProperties_getMaxVDISize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getMaxVDISize -IConsole_getUSBDevices => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getUSBDevices -IVRDPServer_getAuthType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_getAuthType -IMachine_discardSettings => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_discardSettings -IHost_getUSBDeviceFilters => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getUSBDeviceFilters -IParallelPort_setPath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'path', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IParallelPort_setPath -IParallelPort_setIRQ => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'IRQ', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IParallelPort_setIRQ -IMouse_getAbsoluteSupported => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMouse_getAbsoluteSupported -IUSBDeviceFilter_setRevision => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'revision', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setRevision -IFloppyDrive_getHostDrive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_getHostDrive -IMachine_getSerialPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'slot', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_getSerialPort -IMachine_detachHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'bus', type => 'vbox:StorageBus', attr => {}), - SOAP::Data->new(name => 'channel', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'device', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IMachine_detachHardDisk -IHardDisk_getRoot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getRoot -INetworkAdapter_detach => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_detach -ISession_getMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISession_getMachine -IMachine_getStatisticsUpdateInterval => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getStatisticsUpdateInterval -ISerialPort_setPath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'path', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_setPath -IKeyboard_putCAD => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IKeyboard_putCAD -IMachine_getParallelPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'slot', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_getParallelPort -ICustomHardDisk_setLocation => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'location', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_setLocation -IMachine_getMemoryBalloonSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getMemoryBalloonSize -IUSBDeviceFilter_setManufacturer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'manufacturer', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setManufacturer -IVHDImage_deleteImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVHDImage_deleteImage -IFloppyDrive_getState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_getState -IUSBController_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IUSBController_setEnabled -IMachine_getSnapshotCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSnapshotCount -IVRDPServer_getAllowMultiConnection => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_getAllowMultiConnection -IVirtualBox_getGuestOSTypes => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getGuestOSTypes -IMachine_createSharedFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'hostPath', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'writable', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IMachine_createSharedFolder -IVirtualBox_registerHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'hardDisk', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_registerHardDisk -ISession_close => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISession_close -IVRDPServer_setAuthType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'authType', type => 'vbox:VRDPAuthType', attr => {}), - ], # end parameters - }, # end IVRDPServer_setAuthType -ISerialPort_setIRQ => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'IRQ', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end ISerialPort_setIRQ -IMachine_getNetworkAdapter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'slot', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_getNetworkAdapter -IMachine_getSessionType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSessionType -IVMDKImage_deleteImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVMDKImage_deleteImage -IHost_createUSBDeviceFilter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_createUSBDeviceFilter -IVirtualBox_createHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'storageType', type => 'vbox:HardDiskStorageType', attr => {}), - ], # end parameters - }, # end IVirtualBox_createHardDisk -IHardDisk_getLastAccessError => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getLastAccessError -ISATAController_setPortCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'portCount', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end ISATAController_setPortCount -IISCSIHardDisk_setPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'port', type => 'xsd:unsignedShort', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_setPort -IVirtualDiskImage_getCreated => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualDiskImage_getCreated -IVirtualBox_unregisterHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_unregisterHardDisk -IFloppyDrive_mountImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'imageId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_mountImage -INetworkAdapter_getLineSpeed => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getLineSpeed -IConsole_getMouse => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getMouse -INetworkAdapter_getCableConnected => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getCableConnected -IVirtualBox_setExtraData => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'value', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_setExtraData -IVirtualBox_getSystemProperties => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getSystemProperties -IUSBController_getUSBStandard => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBController_getUSBStandard -IMachine_setPAEEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'PAEEnabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IMachine_setPAEEnabled -IFloppyImage_getAccessible => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyImage_getAccessible -IProgress_getOperation => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getOperation -IVirtualBox_getSettingsFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getSettingsFilePath -IHardDisk_getType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getType -IMachine_showConsoleWindow => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_showConsoleWindow -IConsole_detachUSBDevice => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_detachUSBDevice -IMachine_getSATAController => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSATAController -IUSBController_insertDeviceFilter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'position', type => 'xsd:unsignedInt', attr => {}), - SOAP::Data->new(name => 'filter', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBController_insertDeviceFilter -ISession_getState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISession_getState -IVirtualBox_unregisterDVDImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_unregisterDVDImage -ISystemProperties_getDefaultVDIFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getDefaultVDIFolder -IHost_getOperatingSystem => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getOperatingSystem -IHostDVDDrive_getName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostDVDDrive_getName -IMachine_getHWVirtExEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getHWVirtExEnabled -IMachine_setMemoryBalloonSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'memoryBalloonSize', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_setMemoryBalloonSize -IMachine_getLastStateChange => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getLastStateChange -IConsole_powerDown => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_powerDown -IAudioAdapter_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IAudioAdapter_getEnabled -IMachine_setMemorySize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'memorySize', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_setMemorySize -IUSBDevice_getAddress => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getAddress -IConsole_getKeyboard => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getKeyboard -INetworkAdapter_setTraceFile => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'traceFile', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setTraceFile -IProgress_getCancelable => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getCancelable -IConsole_reset => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_reset -IVirtualBox_registerDVDImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'image', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_registerDVDImage -IISCSIHardDisk_setServer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'server', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_setServer -IProgress_getCanceled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getCanceled -ISystemProperties_getParallelPortCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getParallelPortCount -INetworkAdapter_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getEnabled -IDVDImage_getSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDImage_getSize -IMachine_getSessionState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSessionState -ISession_getConsole => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISession_getConsole -INetworkAdapter_getAttachmentType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getAttachmentType -IMouse_putMouseEventAbsolute => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'x', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'y', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'dz', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'buttonState', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IMouse_putMouseEventAbsolute -IWebsessionManager_logon => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => 'username', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'password', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IWebsessionManager_logon -IParallelPort_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IParallelPort_getEnabled -INetworkAdapter_attachToHostInterface => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_attachToHostInterface -IParallelPort_getIRQ => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IParallelPort_getIRQ -IVirtualBox_openHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'location', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openHardDisk -IUSBDeviceFilter_getName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getName -IConsole_resume => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_resume -IFloppyImage_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyImage_getId -IVHDImage_setFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVHDImage_setFilePath -IHost_getDVDDrives => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getDVDDrives -IVirtualBox_registerMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'machine', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_registerMachine -IManagedObjectRef_release => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IManagedObjectRef_release -INetworkAdapter_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setEnabled -IMachine_setHWVirtExEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'HWVirtExEnabled', type => 'vbox:TSBool', attr => {}), - ], # end parameters - }, # end IMachine_setHWVirtExEnabled -IParallelPort_getIOBase => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IParallelPort_getIOBase -IISCSIHardDisk_getServer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_getServer -IConsole_adoptSavedState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'savedStateFile', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_adoptSavedState -IMachine_saveSettingsWithBackup => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_saveSettingsWithBackup -IVRDPServer_setAuthTimeout => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'authTimeout', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IVRDPServer_setAuthTimeout -IMachine_getHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'bus', type => 'vbox:StorageBus', attr => {}), - SOAP::Data->new(name => 'channel', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'device', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IMachine_getHardDisk -IVRDPServer_getAuthTimeout => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_getAuthTimeout -IISCSIHardDisk_setTarget => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'target', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_setTarget -IFloppyDrive_unmount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_unmount -IMachine_getFloppyDrive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getFloppyDrive -ISnapshot_setDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'description', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_setDescription -IUSBDeviceFilter_setProductId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'productId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setProductId -IUSBDevice_getPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getPort -IProgress_getOperationDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getOperationDescription -IVRDPServer_setNetAddress => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'netAddress', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_setNetAddress -IDVDDrive_setPassthrough => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'passthrough', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IDVDDrive_setPassthrough -IUSBDevice_getProduct => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getProduct -ISystemProperties_getMaxGuestRAM => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getMaxGuestRAM -IHost_removeUSBDeviceFilter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'position', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IHost_removeUSBDeviceFilter -IMachine_getHardDiskAttachments => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getHardDiskAttachments -IMachine_getSnapshotFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSnapshotFolder -IVirtualDiskImage_getFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualDiskImage_getFilePath -IConsole_discardCurrentState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_discardCurrentState -IFloppyDrive_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_getEnabled -IConsole_sleepButton => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_sleepButton -IMouse_putMouseEvent => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'dx', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'dy', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'dz', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'buttonState', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IMouse_putMouseEvent -IUSBDeviceFilter_setActive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'active', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setActive -IVirtualBox_openMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'settingsFile', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openMachine -IConsole_discardSnapshot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_discardSnapshot -ISystemProperties_setLogHistoryCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'LogHistoryCount', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end ISystemProperties_setLogHistoryCount -IHost_getUSBDevices => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getUSBDevices -IVirtualBox_unregisterFloppyImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_unregisterFloppyImage -IISCSIHardDisk_getUserName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_getUserName -IHost_insertUSBDeviceFilter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'position', type => 'xsd:unsignedInt', attr => {}), - SOAP::Data->new(name => 'filter', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_insertUSBDeviceFilter -IMachine_canShowConsoleWindow => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_canShowConsoleWindow -IUSBDeviceFilter_getProduct => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getProduct -ISnapshot_getMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getMachine -IParallelPort_getSlot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IParallelPort_getSlot -IConsole_discardSavedState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_discardSavedState -IMachine_saveSettings => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_saveSettings -ICustomHardDisk_deleteImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_deleteImage -ISerialPort_getIRQ => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getIRQ -IHardDisk_getChildren => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getChildren -IDVDDrive_captureHostDrive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'drive', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_captureHostDrive -IConsole_createSharedFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'hostPath', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'writable', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IConsole_createSharedFolder -IHardDisk_getMachineId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getMachineId -IMachine_getVRDPServer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getVRDPServer -IConsole_removeSharedFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_removeSharedFolder -IVMDKImage_getFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVMDKImage_getFilePath -IMachine_getSettingsFileVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSettingsFileVersion -IVirtualBox_createLegacyMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'settingsFile', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_createLegacyMachine -IVirtualBox_findVirtualDiskImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_findVirtualDiskImage -IVirtualBox_getFloppyImageUsage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'usage', type => 'vbox:ResourceUsage', attr => {}), - ], # end parameters - }, # end IVirtualBox_getFloppyImageUsage -IVirtualDiskImage_setFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualDiskImage_setFilePath -IUSBDeviceFilter_getRemote => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getRemote -INetworkAdapter_setMACAddress => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'MACAddress', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setMACAddress -ISystemProperties_getRemoteDisplayAuthLibrary => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getRemoteDisplayAuthLibrary -INetworkAdapter_setInternalNetwork => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'internalNetwork', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setInternalNetwork -IHardDisk_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getId -IDVDDrive_getImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_getImage -ICustomHardDisk_getFormat => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_getFormat -ISystemProperties_getSerialPortCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getSerialPortCount -ISATAController_GetIDEEmulationPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'devicePosition', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end ISATAController_GetIDEEmulationPort -INetworkAdapter_getTraceFile => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getTraceFile -ISystemProperties_getDefaultMachineFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getDefaultMachineFolder -IISCSIHardDisk_setLun => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'lun', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_setLun -IFloppyImage_getFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyImage_getFilePath -INetworkAdapter_getNATNetwork => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getNATNetwork -ISnapshot_getOnline => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getOnline -IVRDPServer_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_getEnabled -IManagedObjectRef_getInterfaceName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IManagedObjectRef_getInterfaceName -ICustomHardDisk_createFixedImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_createFixedImage -ISnapshot_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getId -IConsole_getRemoteDisplayInfo => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getRemoteDisplayInfo -IISCSIHardDisk_setPassword => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'password', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_setPassword -IHardDisk_getActualSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getActualSize -IVirtualBox_removeSharedFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_removeSharedFolder -IConsole_attachUSBDevice => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_attachUSBDevice -IISCSIHardDisk_getPassword => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_getPassword -IVirtualBox_getGuestOSType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getGuestOSType -ISnapshot_getName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getName -IHardDisk_getAccessible => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getAccessible -IParallelPort_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IParallelPort_setEnabled -IConsole_getPowerButtonHandled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getPowerButtonHandled -IAudioAdapter_getAudioDriver => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IAudioAdapter_getAudioDriver -ISerialPort_getHostMode => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getHostMode -IConsole_getState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getState -IMachine_setSnapshotFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'snapshotFolder', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_setSnapshotFolder -IVRDPServer_setPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'port', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IVRDPServer_setPort -IVirtualBox_waitForPropertyChange => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'what', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'timeout', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IVirtualBox_waitForPropertyChange -IVirtualBox_getSharedFolders => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getSharedFolders -ICustomHardDisk_createDynamicImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_createDynamicImage -IVirtualBox_getMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getMachine -IKeyboard_putScancode => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'scancode', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IKeyboard_putScancode -IMachine_deleteSettings => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_deleteSettings -IHostDVDDrive_getDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostDVDDrive_getDescription -IVirtualBox_findFloppyImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_findFloppyImage -ISATAController_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISATAController_getEnabled -ICustomHardDisk_getCreated => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_getCreated -IVirtualBox_openDVDImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openDVDImage -IFloppyDrive_getImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_getImage -IConsole_getDeviceActivity => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'type', type => 'vbox:DeviceType', attr => {}), - ], # end parameters - }, # end IConsole_getDeviceActivity -ISerialPort_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getEnabled -ISystemProperties_getLogHistoryCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getLogHistoryCount -ISnapshot_getParent => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getParent -IVirtualBox_getDVDImageUsage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'usage', type => 'vbox:ResourceUsage', attr => {}), - ], # end parameters - }, # end IVirtualBox_getDVDImageUsage -IConsole_powerButton => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_powerButton -IHost_getMemorySize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getMemorySize -IHardDisk_getDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getDescription -ISerialPort_getIOBase => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getIOBase -IMachine_setMonitorCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'MonitorCount', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_setMonitorCount -ISerialPort_getServer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISerialPort_getServer -IMachine_getCurrentStateModified => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getCurrentStateModified -IUSBDeviceFilter_setProduct => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'product', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setProduct -INetworkAdapter_setCableConnected => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'cableConnected', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setCableConnected -IMachine_getExtraData => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getExtraData -IVHDImage_createFixedImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IVHDImage_createFixedImage -IVHDImage_getFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVHDImage_getFilePath -IVirtualBox_openSession => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'machineId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openSession -IConsole_getMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_getMachine -IVirtualBox_unregisterMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_unregisterMachine -INetworkAdapter_setNATNetwork => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'NATNetwork', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setNATNetwork -IHost_getProcessorCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getProcessorCount -INetworkAdapter_attachToNAT => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_attachToNAT -IDVDImage_getFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDImage_getFilePath -IAudioAdapter_setAudioController => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'audioController', type => 'vbox:AudioControllerType', attr => {}), - ], # end parameters - }, # end IAudioAdapter_setAudioController -IVirtualBox_findDVDImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_findDVDImage -IMachine_setClipboardMode => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'clipboardMode', type => 'vbox:ClipboardMode', attr => {}), - ], # end parameters - }, # end IMachine_setClipboardMode -IHostFloppyDrive_getDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostFloppyDrive_getDescription -IUSBDeviceFilter_setName => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setName -IDVDDrive_getPassthrough => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_getPassthrough -IConsole_powerUp => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_powerUp -ISATAController_SetIDEEmulationPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'devicePosition', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'portNumber', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end ISATAController_SetIDEEmulationPort -IUSBDevice_getManufacturer => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getManufacturer -IProgress_getPercent => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getPercent -IDVDImage_getAccessible => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDImage_getAccessible -IVirtualBox_getFloppyImages => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getFloppyImages -IWebsessionManager_logoff => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => 'refIVirtualBox', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IWebsessionManager_logoff -IUSBDevice_getSerialNumber => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getSerialNumber -IProgress_getOperationPercent => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getOperationPercent -IVirtualDiskImage_createDynamicImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IVirtualDiskImage_createDynamicImage -IMachine_getNextExtraDataKey => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getNextExtraDataKey -IHost_getProcessorSpeed => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getProcessorSpeed -IVirtualBox_saveSettings => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_saveSettings -ISnapshot_getDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISnapshot_getDescription -INetworkAdapter_getMACAddress => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getMACAddress -IVirtualBox_findHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'location', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_findHardDisk -ISession_getType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISession_getType -IVirtualBox_getHardDisks => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getHardDisks -IUSBDeviceFilter_getVendorId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getVendorId -IUSBController_getEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBController_getEnabled -IDVDDrive_getHostDrive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_getHostDrive -IVRDPServer_setAllowMultiConnection => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'allowMultiConnection', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IVRDPServer_setAllowMultiConnection -IVRDPServer_getPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVRDPServer_getPort -IHostUSBDeviceFilter_setAction => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'action', type => 'vbox:USBDeviceFilterAction', attr => {}), - ], # end parameters - }, # end IHostUSBDeviceFilter_setAction -ISystemProperties_setHWVirtExEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'HWVirtExEnabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end ISystemProperties_setHWVirtExEnabled -IAudioAdapter_getAudioController => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IAudioAdapter_getAudioController -IVMDKImage_createFixedImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IVMDKImage_createFixedImage -IUSBDeviceFilter_setPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'port', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setPort -IVirtualBox_getVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getVersion -IUSBDevice_getPortVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getPortVersion -IUSBController_getEnabledEhci => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBController_getEnabledEhci -IISCSIHardDisk_getTarget => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_getTarget -IUSBDeviceFilter_getPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getPort -IMachine_getSnapshot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSnapshot -IFloppyDrive_captureHostDrive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'drive', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyDrive_captureHostDrive -IConsole_saveState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_saveState -IVirtualBox_findMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_findMachine -IParallelPort_getPath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IParallelPort_getPath -IVMDKImage_getCreated => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVMDKImage_getCreated -IMachine_setExtraData => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'value', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_setExtraData -IMachine_getAccessible => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getAccessible -IVirtualBox_getProgressOperations => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getProgressOperations -INetworkAdapter_getSlot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getSlot -IVirtualBox_openVirtualDiskImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openVirtualDiskImage -ISystemProperties_getMaxGuestVRAM => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getMaxGuestVRAM -IVirtualBox_openRemoteSession => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'machineId', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'type', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'environment', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openRemoteSession -IHostFloppyDrive_getUdi => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostFloppyDrive_getUdi -INetworkAdapter_getInternalNetwork => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getInternalNetwork -IVirtualBox_getNextExtraDataKey => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getNextExtraDataKey -IHost_getProcessorDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getProcessorDescription -IFloppyImage_getSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IFloppyImage_getSize -IMachine_getDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getDescription -IHardDisk_getParent => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getParent -ISystemProperties_setDefaultMachineFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'defaultMachineFolder', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_setDefaultMachineFolder -INetworkAdapter_getAdapterType => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getAdapterType -ISystemProperties_setDefaultVDIFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'defaultVDIFolder', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_setDefaultVDIFolder -IVirtualBox_getHomeFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getHomeFolder -IAudioAdapter_setAudioDriver => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'audioDriver', type => 'vbox:AudioDriverType', attr => {}), - ], # end parameters - }, # end IAudioAdapter_setAudioDriver -IUSBDeviceFilter_getActive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getActive -IHost_getUTCTime => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getUTCTime -IWebsessionManager_getSessionObject => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => 'refIVirtualBox', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IWebsessionManager_getSessionObject -IISCSIHardDisk_getPort => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IISCSIHardDisk_getPort -INetworkAdapter_setHostInterface => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'hostInterface', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_setHostInterface -IUSBDeviceFilter_setMaskedInterfaces => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'maskedInterfaces', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setMaskedInterfaces -IMachine_getMemorySize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getMemorySize -ISystemProperties_getMinGuestRAM => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getMinGuestRAM -IDVDDrive_unmount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_unmount -IVHDImage_createDynamicImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IVHDImage_createDynamicImage -IUSBDeviceFilter_getSerialNumber => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getSerialNumber -INetworkAdapter_getTraceEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getTraceEnabled -IHost_getOSVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getOSVersion -IUSBController_setEnabledEhci => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabledEhci', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IUSBController_setEnabledEhci -IUSBDeviceFilter_getMaskedInterfaces => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getMaskedInterfaces -IMachine_setBootOrder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'position', type => 'xsd:unsignedInt', attr => {}), - SOAP::Data->new(name => 'device', type => 'vbox:DeviceType', attr => {}), - ], # end parameters - }, # end IMachine_setBootOrder -IMachine_getAudioAdapter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getAudioAdapter -IMachine_getDVDDrive => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getDVDDrive -ISATAController_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end ISATAController_setEnabled -IMachine_removeSharedFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_removeSharedFolder -IUSBDevice_getRemote => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getRemote -INetworkAdapter_getHostInterface => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end INetworkAdapter_getHostInterface -IUSBDeviceFilter_setVendorId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'vendorId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setVendorId -IUSBDeviceFilter_setSerialNumber => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'serialNumber', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setSerialNumber -IMachine_getSettingsModified => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSettingsModified -IProgress_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getId -IVirtualBox_getSettingsFormatVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getSettingsFormatVersion -IUSBDeviceFilter_setRemote => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'remote', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_setRemote -ISerialPort_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end ISerialPort_setEnabled -IDVDDrive_mountImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'imageId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDDrive_mountImage -IProgress_getOperationCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getOperationCount -IMachine_setStatisticsUpdateInterval => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'statisticsUpdateInterval', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_setStatisticsUpdateInterval -IAudioAdapter_setEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IAudioAdapter_setEnabled -IVirtualBox_getDVDImages => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getDVDImages -IVMDKImage_setFilePath => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVMDKImage_setFilePath -ICustomHardDisk_getLocation => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ICustomHardDisk_getLocation -IHost_getMemoryAvailable => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHost_getMemoryAvailable -IMachine_getBootOrder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'order', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_getBootOrder -IKeyboard_putScancodes => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'scancodes', type => 'xsd:int', attr => {}), - SOAP::Data->new(name => 'count', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IKeyboard_putScancodes -IMachine_getParent => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getParent -IUSBDevice_getVendorId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getVendorId -IHostUSBDeviceFilter_getAction => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostUSBDeviceFilter_getAction -IProgress_waitForOperationCompletion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'operation', type => 'xsd:unsignedInt', attr => {}), - SOAP::Data->new(name => 'timeout', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IProgress_waitForOperationCompletion -IHardDisk_getSnapshotId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getSnapshotId -IDVDImage_getId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IDVDImage_getId -IMachine_getSharedFolders => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSharedFolders -IMachine_setDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'description', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_setDescription -IMachine_findSnapshot => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_findSnapshot -IUSBController_removeDeviceFilter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'position', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IUSBController_removeDeviceFilter -ISystemProperties_setWebServiceAuthLibrary => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'webServiceAuthLibrary', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_setWebServiceAuthLibrary -IHardDisk_getSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getSize -IProgress_cancel => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_cancel -IUSBController_createDeviceFilter => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBController_createDeviceFilter -IMachine_setVRAMSize => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'VRAMSize', type => 'xsd:unsignedInt', attr => {}), - ], # end parameters - }, # end IMachine_setVRAMSize -IMachine_setOSTypeId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'OSTypeId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_setOSTypeId -IProgress_getDescription => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IProgress_getDescription -IHardDisk_cloneToImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'filePath', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_cloneToImage -IVirtualBox_createSharedFolder => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'hostPath', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'writable', type => 'xsd:boolean', attr => {}), - ], # end parameters - }, # end IVirtualBox_createSharedFolder -IVirtualBox_getHardDisk => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getHardDisk -IVirtualBox_getMachines => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getMachines -ISystemProperties_getHWVirtExEnabled => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getHWVirtExEnabled -IMachine_getUSBController => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getUSBController -IVMDKImage_createDynamicImage => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'size', type => 'xsd:unsignedLong', attr => {}), - ], # end parameters - }, # end IVMDKImage_createDynamicImage -IHostDVDDrive_getUdi => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostDVDDrive_getUdi -IUSBDeviceFilter_getProductId => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getProductId -IHostUSBDevice_getState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHostUSBDevice_getState -IVirtualBox_getSettingsFileVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_getSettingsFileVersion -IUSBDeviceFilter_getRevision => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDeviceFilter_getRevision -IUSBDevice_getVersion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IUSBDevice_getVersion -ISystemProperties_setRemoteDisplayAuthLibrary => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'remoteDisplayAuthLibrary', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_setRemoteDisplayAuthLibrary -IMachine_getMonitorCount => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getMonitorCount -ISystemProperties_getWebServiceAuthLibrary => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end ISystemProperties_getWebServiceAuthLibrary -IHardDisk_getAllAccessible => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IHardDisk_getAllAccessible -IMachine_getSessionPid => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IMachine_getSessionPid -IConsole_discardCurrentSnapshotAndState => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IConsole_discardCurrentSnapshotAndState -IProgress_waitForCompletion => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'timeout', type => 'xsd:int', attr => {}), - ], # end parameters - }, # end IProgress_waitForCompletion -IVirtualBox_openExistingSession => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'machineId', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_openExistingSession -IVirtualBox_createMachine => { - endpoint => 'http://localhost:18083/', - soapaction => '', - namespace => 'http://www.virtualbox.org/', - parameters => [ - SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'baseFolder', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), - SOAP::Data->new(name => 'id', type => 'xsd:string', attr => {}), - ], # end parameters - }, # end IVirtualBox_createMachine -); # end my %methods - -#require SOAP::Lite; # vbox.pm requires SOAP::Lite before requiring vboxService.pm, so we can check for SOAP::Lite dynamically -require Exporter; -use Carp (); - -use vars qw(@ISA $AUTOLOAD @EXPORT_OK %EXPORT_TAGS); -@ISA = qw(Exporter SOAP::Lite); -@EXPORT_OK = (keys %methods); -%EXPORT_TAGS = ('all' => [@EXPORT_OK]); - -sub _call { - ####################################################################################################################################################### - # save the additional parameter "vboxhost" which contains an URL with Port information - my ($self, $method, $vboxhost) = (shift, shift, shift); - my $name = UNIVERSAL::isa($method => 'SOAP::Data') ? $method->name : $method; - my %method = %{$methods{$name}}; - ####################################################################################################################################################### - # set the proxy to $vboxhost instead of $method{endpoint} -> in future vboxhost could contain something like "[*P**P*]" - $self->proxy($vboxhost || Carp::croak "No server address (proxy) specified") - unless $self->proxy; - my @templates = @{$method{parameters}}; - my @parameters = (); - foreach my $param (@_) { - if (@templates) { - my $template = shift @templates; - my ($prefix,$typename) = SOAP::Utils::splitqname($template->type); - my $method = 'as_'.$typename; - # TODO - if can('as_'.$typename) {...} - my $result = $self->serializer->$method($param, $template->name, $template->type, $template->attr); - push(@parameters, $template->value($result->[2])); - } - else { - push(@parameters, $param); - } - } - ####################################################################################################################################################### - # set the endpoint to $vboxhost instead of $method{endpoint} -> in future vboxhost could contain something like "[*P**P*]" - $self->endpoint($vboxhost) - ->ns($method{namespace}) - ->on_action(sub{qq!"$method{soapaction}"!}); - $self->serializer->register_ns("urn:vbox","interface"); - $self->serializer->register_ns("http://www.virtualbox.org/","vbox"); - $self->serializer->register_ns("http://schemas.xmlsoap.org/wsdl/soap/","soap"); - my $som = $self->SUPER::call($method => @parameters); - if ($self->want_som) { - return $som; - } - UNIVERSAL::isa($som => 'SOAP::SOM') ? wantarray ? $som->paramsall : $som->result : $som; -} - -sub BEGIN { - no strict 'refs'; - for my $method (qw(want_som)) { - my $field = '_' . $method; - *$method = sub { - my $self = shift->new; - @_ ? ($self->{$field} = shift, return $self) : return $self->{$field}; - } - } -} -no strict 'refs'; -for my $method (@EXPORT_OK) { - my %method = %{$methods{$method}}; - *$method = sub { - my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) - ? ref $_[0] - ? shift # OBJECT - # CLASS, either get self or create new and assign to self - : (shift->self || __PACKAGE__->self(__PACKAGE__->new)) - # function call, either get self or create new and assign to self - : (__PACKAGE__->self || __PACKAGE__->self(__PACKAGE__->new)); - $self->_call($method, @_); - } -} - -sub AUTOLOAD { - my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); - return if $method eq 'DESTROY' || $method eq 'want_som'; - die "Unrecognized method '$method'. List of available method(s): @EXPORT_OK\n"; -} - -1; +package xCAT::vboxService; +# Generated by SOAP::Lite (v0.712) for Perl -- soaplite.com +# Copyright (C) 2000-2006 Paul Kulchenko, Byrne Reese +# -- generated at [Wed Mar 26 20:28:01 2014] +# -- generated from file:///home/vbox/tinderbox/4.3-sdk/out/linux.amd64/release/obj/webservice/vboxwebService.wsdl +# -- merged V3 API Methods at [Sun Apr 06 13:31:00 2014] +# -- manually added defintions for xCAT integration of both versions by Herbert Mehlhose, IBM +# -- reduce methods hash to the needed interface functionality needed for our purpose +my %methods = ( +IVirtualBox_getExtraData => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getExtraData +IMachine_getName => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getName +IProgress_getTimeout => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getTimeout +IVRDEServer_setVRDEProperty => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'value', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_setVRDEProperty +IConsole_powerDown => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_powerDown +IConsole_getPowerButtonHandled => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_getPowerButtonHandled +IManagedObjectRef_release => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IManagedObjectRef_release +IMachine_saveSettings => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_saveSettings +IMachine_getExtraData => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getExtraData +IProgress_getPercent => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getPercent +IProgress_getOperationPercent => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getOperationPercent +IVirtualBox_getAPIVersion => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getAPIVersion +IMachine_setExtraData => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'value', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_setExtraData +IVRDEServer_getEnabled => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_getEnabled +IProgress_waitForCompletion => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'timeout', type => 'xsd:int', attr => {}), + ], # end parameters + }, # end IProgress_waitForCompletion +IMachine_getState => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getState +IVirtualBox_getGuestOSTypes => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getGuestOSTypes +IMachine_launchVMProcess => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'type', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'environment', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_launchVMProcess +IMachine_getGuestProperty => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getGuestProperty +IVirtualBox_openMachine => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'settingsFile', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_openMachine +IVRDEServer_getAuthLibrary => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_getAuthLibrary +IVRDEServer_setAuthTimeout => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'authTimeout', type => 'xsd:unsignedInt', attr => {}), + ], # end parameters + }, # end IVRDEServer_setAuthTimeout +IProgress_setTimeout => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'timeout', type => 'xsd:unsignedInt', attr => {}), + ], # end parameters + }, # end IProgress_setTimeout +IConsole_getMachine => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_getMachine +IProgress_waitForAsyncProgressCompletion => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'pProgressAsync', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_waitForAsyncProgressCompletion +IConsole_powerUp => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_powerUp +ISession_getType => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_getType +IVirtualBox_getVersion => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getVersion +IMachine_setGuestProperty => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'property', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'value', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'flags', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_setGuestProperty +IVirtualBox_findMachine => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'nameOrId', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_findMachine +IVRDEServer_setAuthType => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'authType', type => 'vbox:AuthType', attr => {}), + ], # end parameters + }, # end IVRDEServer_setAuthType +IConsole_getDisplay => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_getDisplay +IConsole_getGuest => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_getGuest +IProgress_waitForOperationCompletion => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'operation', type => 'xsd:unsignedInt', attr => {}), + SOAP::Data->new(name => 'timeout', type => 'xsd:int', attr => {}), + ], # end parameters + }, # end IProgress_waitForOperationCompletion +IVirtualBox_getMachines => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getMachines +IProgress_getResultCode => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getResultCode +IProgress_getCompleted => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getCompleted +IMachine_lockMachine => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'lockType', type => 'vbox:LockType', attr => {}), + ], # end parameters + }, # end IMachine_lockMachine +IMachine_getSessionType => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getSessionType +IVirtualBox_getSystemProperties => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getSystemProperties +IProgress_getOperation => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getOperation +ISession_getState => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_getState +IVRDEServer_getVRDEProperties => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_getVRDEProperties +IConsole_reset => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_reset +IMachine_getSessionState => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getSessionState +IVRDEServer_getVRDEProperty => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'key', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_getVRDEProperty +IVirtualBox_getMachineStates => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'machines', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getMachineStates +IVRDEServer_getAuthType => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_getAuthType +IMachine_getVRDEServer => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getVRDEServer +IProgress_getErrorInfo => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getErrorInfo +ISystemProperties_getVRDEAuthLibrary => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISystemProperties_getVRDEAuthLibrary +IMachine_getId => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getId +ISession_getMachine => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_getMachine +IMachine_showConsoleWindow => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_showConsoleWindow +IProcess_getStatus => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProcess_getStatus +IVRDEServer_getVRDEExtPack => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_getVRDEExtPack +ISession_getConsole => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_getConsole +IWebsessionManager_logon => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => 'username', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'password', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IWebsessionManager_logon +IWebsessionManager_logoff => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => 'refIVirtualBox', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IWebsessionManager_logoff +IVRDEServer_setEnabled => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), + ], # end parameters + }, # end IVRDEServer_setEnabled +IConsole_powerButton => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_powerButton +IVRDEServer_setAuthLibrary => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'authLibrary', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDEServer_setAuthLibrary +ISession_unlockMachine => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_unlockMachine +IMachine_getDescription => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getDescription +ISystemProperties_setVRDEAuthLibrary => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'VRDEAuthLibrary', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISystemProperties_setVRDEAuthLibrary +IWebsessionManager_getSessionObject => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => 'refIVirtualBox', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IWebsessionManager_getSessionObject +IProgress_getId => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getId +IVirtualBox_getVersionNormalized => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_getVersionNormalized + +###################################################################### +### starting v3 additions for backward compatibility with vbox 3.2 ### +###################################################################### + +# findMachine - change in parameter name / nameOrId +IVirtualBox_findMachine_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'name', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_findMachine +IMachine_getState_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getState +IMachine_getId_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getId +IWebsessionManager_getSessionObject_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => 'refIVirtualBox', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IWebsessionManager_getSessionObject +IVirtualBox_openSession_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'machineId', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_openSession +ISession_getMachine_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_getMachine +IMachine_getVRDPServer_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getVRDPServer +IVRDPServer_getEnabled_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDPServer_getEnabled +IVRDPServer_setEnabled_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'enabled', type => 'xsd:boolean', attr => {}), + ], # end parameters + }, # end IVRDPServer_setEnabled +# from API version 3.0 to 3.1, the 'port' attribute has been changed to 'ports' +IVRDPServer_getPorts_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDPServer_getPorts +IVRDPServer_getPort_V30 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDPServer_getPort +IVRDPServer_setPorts_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'ports', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVRDPServer_setPorts +IVRDPServer_setPort_V30 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'port', type => 'xsd:unsignedInt', attr => {}), + ], # end parameters + }, # end IVRDPServer_setPort +IMachine_saveSettings_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_saveSettings +IManagedObjectRef_release_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IManagedObjectRef_release +ISession_close_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_close +IVirtualBox_openRemoteSession_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'machineId', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'type', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'environment', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_openRemoteSession +IProgress_waitForCompletion_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'timeout', type => 'xsd:int', attr => {}), + ], # end parameters + }, # end IProgress_waitForCompletion +IProgress_getCompleted_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IProgress_getCompleted +IMachine_getSessionState_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IMachine_getSessionState +IVirtualBox_openExistingSession_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'session', type => 'xsd:string', attr => {}), + SOAP::Data->new(name => 'machineId', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IVirtualBox_openExistingSession +ISession_getConsole_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end ISession_getConsole +IConsole_reset_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_reset +IConsole_powerButton_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_powerButton +IConsole_powerDown_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_powerDown +IConsole_getPowerButtonHandled_V3 => { + endpoint => 'http://localhost:18083/', + soapaction => '', + namespace => 'http://www.virtualbox.org/', + parameters => [ + SOAP::Data->new(name => '_this', type => 'xsd:string', attr => {}), + ], # end parameters + }, # end IConsole_getPowerButtonHandled +); # end my %methods + +use SOAP::Lite; # vbox.pm requires SOAP::Lite before requiring vboxService.pm, so we can check for SOAP::Lite dynamically +use Exporter; +use Carp (); + +use vars qw(@ISA $AUTOLOAD @EXPORT_OK %EXPORT_TAGS); +@ISA = qw(Exporter SOAP::Lite); +#L("Setting EXPORT_OK array..."); +@EXPORT_OK = (keys %methods); +#foreach(sort @EXPORT_OK) {L("M:$_");} +%EXPORT_TAGS = ('all' => [@EXPORT_OK]); + +sub _call { + ####################################################################################################################################################### + # save the additional parameter "vboxhost" which contains an URL with Port information + #my ($self, $method, $api, $vboxhost) = (shift, shift, shift, shift); + my ($self, $method, $vboxhost) = (shift, shift, shift); + my $name = UNIVERSAL::isa($method => 'SOAP::Data') ? $method->name : $method; + #L("Function: $name()"); + my %method = %{$methods{$name}}; + ####################################################################################################################################################### + # set the proxy to $vboxhost instead of $method{endpoint} -> in future vboxhost could contain something like "[*P**P*]" + $self->proxy($vboxhost || Carp::croak "No server address (proxy) specified") + unless $self->proxy; + my @templates = @{$method{parameters}}; + my @parameters = (); + foreach my $param (@_) { + if (@templates) { + #L("Parm(T): $param"); + my $template = shift @templates; + my ($prefix,$typename) = SOAP::Utils::splitqname($template->type); + my $method = 'as_'.$typename; + # TODO - if can('as_'.$typename) {...} + #L(Data::Dumper->Dump([$template], [qw(TMPL)])); + my $result = $self->serializer->$method($param, $template->name, $template->type, $template->attr); + #L(Data::Dumper->Dump([$result], [qw(RESULT)])); + #L("Parm: " . $template->name . " Type: " . $template->type . " Val: " . $result->[2]); + push(@parameters, $template->value($result->[2])); + } + else { + #L("Parm(nonT): $param"); + push(@parameters, $param); + } + } + ####################################################################################################################################################### + # set the endpoint to $vboxhost instead of $method{endpoint} -> in future vboxhost could contain something like "[*P**P*]" + $self->endpoint($vboxhost) + ->ns($method{namespace}) + ->on_action(sub{qq!"$method{soapaction}"!}); + $self->serializer->register_ns("urn:vbox","interface"); + $self->serializer->register_ns("http://www.virtualbox.org/","vbox"); + $self->serializer->register_ns("http://schemas.xmlsoap.org/wsdl/soap/","soap"); + # strip off possible version extensions '_Vx' at end of method name + $method =~ s/$\_V[0-9.]*//i; + #L("about to super call with stripped method $method.."); + my $som = $self->SUPER::call($method => @parameters); + if ($self->want_som) { + return $som; + } + UNIVERSAL::isa($som => 'SOAP::SOM') ? wantarray ? $som->paramsall : $som->result : $som; +} + +sub BEGIN { + no strict 'refs'; + for my $method (qw(want_som)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + @_ ? ($self->{$field} = shift, return $self) : return $self->{$field}; + } + } +} +no strict 'refs'; +for my $method (@EXPORT_OK) { + my %method = %{$methods{$method}}; + *$method = sub { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? ref $_[0] + ? shift # OBJECT + # CLASS, either get self or create new and assign to self + : (shift->self || __PACKAGE__->self(__PACKAGE__->new)) + # function call, either get self or create new and assign to self + : (__PACKAGE__->self || __PACKAGE__->self(__PACKAGE__->new)); + #L("CALL: $method"); + #foreach(@_) {L(" P:$_");} + $self->_call($method, @_); + } +} + +sub AUTOLOAD { + my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); + return if $method eq 'DESTROY' || $method eq 'want_som'; + die "Unrecognized method '$method'. List of available method(s): @EXPORT_OK\n"; +} + +#sub L { +# my $string=shift; +# open FILE, ">>/tmp/soapxcatlog.txt"; +# print FILE "LOG: $string\n"; +# close FILE; +#} + + +1; + diff --git a/perl-xCAT/xCAT/zvmUtils.pm b/perl-xCAT/xCAT/zvmUtils.pm index b37f84c8e..b5ee139fc 100644 --- a/perl-xCAT/xCAT/zvmUtils.pm +++ b/perl-xCAT/xCAT/zvmUtils.pm @@ -2405,7 +2405,7 @@ sub getFreeRepoSpace { if ($master eq $ip) { # If the master IP and node IP match, then it is the management node my $out = `$sudo /bin/df -h /install | sed 1d`; - $out =~ s/\h+/ /g; + # causing problems on other platforms $out =~ s/\h+/ /g; my @results = split(' ', $out); if ( $results[3] eq "0" ) { $results[3] = "0M"; diff --git a/xCAT-IBMhpc/share/xcat/IBMhpc/gpfs/gpfs_updates b/xCAT-IBMhpc/share/xcat/IBMhpc/gpfs/gpfs_updates index 1476c2216..6ab6eaabb 100755 --- a/xCAT-IBMhpc/share/xcat/IBMhpc/gpfs/gpfs_updates +++ b/xCAT-IBMhpc/share/xcat/IBMhpc/gpfs/gpfs_updates @@ -14,7 +14,7 @@ # postscript (stateful install) or with the otherpkgs processing of # genimage (stateless/statelite install). This script will install any # gpfs update rpms that exist on the xCAT management node in the -# /install/post/gpfs_updates directory. +# /install/post/otherpkgs/gpfs_updates directory. # This is necessary because the GPFS updates can ONLY be installed # after the base rpms have been installed, and the update rpms cannot # exist in any rpm repositories used by xCAT otherpkgs processing @@ -41,8 +41,8 @@ if [ $OS != "AIX" ]; then mkdir -p /tmp/gpfs_updates rm -f -R /tmp/gpfs_updates/* cd /tmp/gpfs_updates -# wget -l inf -N -r --waitretry=10 --random-wait --retry-connrefused -t 10 -T 60 -nH --cut-dirs=3 ftp://$SITEMASTER/$UPDATES_DIR/*.rpm 2> /tmp/wget.log - wget -l inf -N -r --waitretry=10 --random-wait --retry-connrefused -t 10 -T 60 -nH --cut-dirs=4 --reject "index.html*" --no-parent http://$SITEMASTER$INSTALL_DIR/$UPDATES_DIR/ 2> /tmp/wget.log +# wget -l inf -N -r --waitretry=10 --random-wait --retry-connrefused -t 10 -T 60 -nH --cut-dirs=3 ftp://$MASTER/$UPDATES_DIR/*.rpm 2> /tmp/wget.log + wget -l inf -N -r --waitretry=10 --random-wait --retry-connrefused -t 10 -T 60 -nH --cut-dirs=4 --reject "index.html*" --no-parent http://$MASTER$INSTALL_DIR/$UPDATES_DIR/ 2> /tmp/wget.log if [ -n "`ls *.rpm 2> /dev/null`" ] ; then rpm -Uvh *.rpm fi diff --git a/xCAT-OpenStack-baremetal/debian/README.Debian b/xCAT-OpenStack-baremetal/debian/README.Debian new file mode 100644 index 000000000..0d88c5231 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/README.Debian @@ -0,0 +1,6 @@ +xcat-openstack-baremetal for Debian +----------------------------------- + + + + -- root Wed, 12 Mar 2014 01:47:54 -0700 diff --git a/xCAT-OpenStack-baremetal/debian/README.source b/xCAT-OpenStack-baremetal/debian/README.source new file mode 100644 index 000000000..4ea5d6ff6 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/README.source @@ -0,0 +1,9 @@ +xcat-openstack-baremetal for Debian +----------------------------------- + + + + + + diff --git a/xCAT-OpenStack-baremetal/debian/changelog b/xCAT-OpenStack-baremetal/debian/changelog new file mode 100644 index 000000000..5502ea420 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/changelog @@ -0,0 +1,5 @@ +xcat-openstack-baremetal (2.8.4-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- root Wed, 12 Mar 2014 01:47:54 -0700 diff --git a/xCAT-OpenStack-baremetal/debian/compat b/xCAT-OpenStack-baremetal/debian/compat new file mode 100644 index 000000000..45a4fb75d --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/compat @@ -0,0 +1 @@ +8 diff --git a/xCAT-OpenStack-baremetal/debian/control b/xCAT-OpenStack-baremetal/debian/control new file mode 100644 index 000000000..e29fd97c5 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/control @@ -0,0 +1,14 @@ +Source: xcat-openstack-baremetal +Section: admin +Priority: extra +Maintainer: xCAT +Build-Depends: debhelper (>= 8.0.0) +Standards-Version: 3.9.4 +Homepage: http://xcat.sourceforge.net/ +#Vcs-Git: git://git.debian.org/collab-maint/xcat-openstack-baremetal.git +#Vcs-Browser: http://git.debian.org/?p=collab-maint/xcat-openstack-baremetal.git;a=summary + +Package: xcat-openstack-baremetal +Architecture: all +Depends: xCAT-client +Description: Executables and data of the xCAT baremetal driver for OpenStack diff --git a/xCAT-OpenStack-baremetal/debian/copyright b/xCAT-OpenStack-baremetal/debian/copyright new file mode 100644 index 000000000..152491524 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/copyright @@ -0,0 +1,38 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: xcat-openstack-baremetal +Source: + +Files: * +Copyright: + +License: + + + . + + +# If you want to use GPL v2 or later for the /debian/* files use +# the following clauses, or change it to suit. Delete these two lines +Files: debian/* +Copyright: 2014 root +License: GPL-2+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. +# Please avoid to pick license terms that are more restrictive than the +# packaged work, as it may make Debian's contributions unacceptable upstream. diff --git a/xCAT-OpenStack-baremetal/debian/dirs b/xCAT-OpenStack-baremetal/debian/dirs new file mode 100644 index 000000000..371ba01dc --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/dirs @@ -0,0 +1,7 @@ +opt/xcat/bin +opt/xcat/sbin +opt/xcat/lib/perl/xCAT_plugin +opt/xcat/lib/python/xcat/openstack/baremetal +opt/xcat/share/xcat/openstack/postscripts +opt/xcat/share/man/man1 +opt/xcat/share/doc/man1 diff --git a/xCAT-OpenStack-baremetal/debian/docs b/xCAT-OpenStack-baremetal/debian/docs new file mode 100644 index 000000000..e69de29bb diff --git a/xCAT-OpenStack-baremetal/debian/files b/xCAT-OpenStack-baremetal/debian/files new file mode 100644 index 000000000..0bf4353c0 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/files @@ -0,0 +1,2 @@ +xcat-openstack-baremetal_2.8.4-1_all.deb admin extra +xcat-openstack-baremetal_2.8.4-1_all.deb admin extra diff --git a/xCAT-OpenStack-baremetal/debian/install b/xCAT-OpenStack-baremetal/debian/install new file mode 100644 index 000000000..883d1f178 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/install @@ -0,0 +1,6 @@ +lib/* opt/xcat/lib/ +share/xcat/openstack/postscripts/* opt/xcat/share/xcat/openstack/postscripts/ +share/man/man1/* opt/xcat/share/man/man1/ +share/doc/man1/* opt/xcat/share/doc/man1/ + + diff --git a/xCAT-OpenStack-baremetal/debian/postinst b/xCAT-OpenStack-baremetal/debian/postinst new file mode 100644 index 000000000..f8997ea58 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/postinst @@ -0,0 +1,43 @@ +#!/bin/sh +# postinst script for xcat-openstack-baremetal +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) +#copy the postscripts under /installl/postscripts directory on MN only +if [ -f "/etc/xCATMN" ]; then + cp /opt/xcat/share/xcat/openstack/postscripts/* /install/postscripts/ +fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/xCAT-OpenStack-baremetal/debian/prerm b/xCAT-OpenStack-baremetal/debian/prerm new file mode 100644 index 000000000..5057be146 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/prerm @@ -0,0 +1,46 @@ +#!/bin/sh +# prerm script for xcat-openstack-baremetal +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + #remove postscripts under /installl/postscripts directory on MN only + if [ -f "/etc/xCATMN" ]; then + for fn in /opt/xcat/share/xcat/openstack/postscripts/* + do + bn=`basename $fn` + rm /install/postscripts/$bn + done + fi + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/xCAT-OpenStack-baremetal/debian/rules b/xCAT-OpenStack-baremetal/debian/rules new file mode 100755 index 000000000..c57f3dbf2 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/rules @@ -0,0 +1,44 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +build: + pwd + `pwd`/xpod2man + +clean: + dh_testdir + dh_testroot + dh_clean -d + +install: + pwd + dh_testdir + dh_testroot + dh_installdirs + dh_install -X".svn" + chmod 444 `pwd`/debian/xcat-openstack-baremetal/opt/xcat/share/man/man1/* + chmod 644 `pwd`/debian/xcat-openstack-baremetal/opt/xcat/share/doc/man1/* + dh_link + +binary-indep: build install + pwd + export + dh_installman + dh_compress + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +binary-arch: + pwd +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/xCAT-OpenStack-baremetal/debian/source/format b/xCAT-OpenStack-baremetal/debian/source/format new file mode 100644 index 000000000..d3827e75a --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/source/format @@ -0,0 +1 @@ +1.0 diff --git a/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.debhelper.log b/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.debhelper.log new file mode 100644 index 000000000..a151b91a0 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.debhelper.log @@ -0,0 +1,201 @@ +dh_installdirs +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb +dh_installdirs +dh_install +dh_link +dh_installman +dh_compress +dh_installdeb +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb diff --git a/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.links b/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.links new file mode 100644 index 000000000..293b8cc77 --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.links @@ -0,0 +1,4 @@ +opt/xcat/bin/xcatclient opt/xcat/sbin/deploy_ops_bm_node +opt/xcat/bin/xcatclient opt/xcat/sbin/cleanup_ops_bm_node +opt/xcat/bin/xcatclient opt/xcat/bin/opsaddbmnode +opt/xcat/bin/xcatclientnnr opt/xcat/bin/opsaddimage diff --git a/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.substvars b/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.substvars new file mode 100644 index 000000000..abd3ebebc --- /dev/null +++ b/xCAT-OpenStack-baremetal/debian/xcat-openstack-baremetal.substvars @@ -0,0 +1 @@ +misc:Depends= diff --git a/xCAT-OpenStack-baremetal/lib/perl/xCAT_plugin/openstack.pm b/xCAT-OpenStack-baremetal/lib/perl/xCAT_plugin/openstack.pm new file mode 100644 index 000000000..1496f5b56 --- /dev/null +++ b/xCAT-OpenStack-baremetal/lib/perl/xCAT_plugin/openstack.pm @@ -0,0 +1,965 @@ +# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT_plugin::openstack; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; +use xCAT::Utils; +use xCAT::TableUtils; +use xCAT::SvrUtils; +use xCAT::NetworkUtils; +use xCAT::Table; +use Data::Dumper; +use File::Path; +use File::Copy; +use Getopt::Long; +Getopt::Long::Configure("bundling"); +Getopt::Long::Configure("pass_through"); + + +sub handled_commands { + return { + opsaddbmnode => "openstack", #external command + opsaddimage => "openstack", #external command + deploy_ops_bm_node => "openstack", #internal command called from the baremetal driver + cleanup_ops_bm_node => "openstack", #internal command called from the baremetal driver + } +} + +sub process_request { + my $request = shift; + my $callback = shift; + my $doreq = shift; + my $command = $request->{command}->[0]; + + if ($command eq "opsaddbmnode") { + return opsaddbmnode($request, $callback, $doreq); + } elsif ($command eq "opsaddimage") { + return opsaddimage($request, $callback, $doreq); + } elsif ($command eq "deploy_ops_bm_node") { + return deploy_ops_bm_node($request, $callback, $doreq); + } elsif ($command eq "cleanup_ops_bm_node") { + return cleanup_ops_bm_node($request, $callback, $doreq); + } else { + $callback->({error=>["Unsupported command: $command."],errorcode=>[1]}); + return 1; + } +} + + +#------------------------------------------------------------------------------- + +=head3 opsaddbmnode + This function takes the xCAT nodes and register them + as the OpenStack baremetal nodes +=cut + +#------------------------------------------------------------------------------- +sub opsaddbmnode { + my $request = shift; + my $callback = shift; + my $doreq = shift; + + @ARGV = @{$request->{arg}}; + Getopt::Long::Configure("bundling"); + Getopt::Long::Configure("no_pass_through"); + + my $help; + my $version; + my $verbose; + my $host; + + if(!GetOptions( + 'h|help' => \$help, + 'v|version' => \$version, + 'V|verbose' => \$verbose, + 's=s' => \$host, + )) + { + &opsaddbmnode_usage($callback); + return 1; + } + # display the usage if -h or --help is specified + if ($help) { + &opsaddbmnode_usage($callback); + return 0; + } + # display the version statement if -v or --verison is specified + if ($version) + { + my $rsp={}; + $rsp->{data}->[0]= xCAT::Utils->Version(); + $callback->($rsp); + return 0; + } + + if (!$request->{node}) { + $callback->({error=>["Please specify at least one node."],errorcode=>[1]}); + return 1; + } + if (!$host) { + $callback->({error=>["Please specify the OpenStack compute host name with -s flag."],errorcode=>[1]}); + return 1; + } + + my $nodes = $request->{node}; + + #get node mgt + my $nodehmhash; + my $nodehmtab = xCAT::Table->new("nodehm"); + if ($nodehmtab) { + $nodehmhash = $nodehmtab->getNodesAttribs($nodes,['power', 'mgt']); + } + + #get bmc info for the nodes + my $ipmitab = xCAT::Table->new("ipmi", -create => 0); + my $tmp_ipmi; + if ($ipmitab) { + $tmp_ipmi = $ipmitab->getNodesAttribs($nodes, ['bmc','username', 'password'], prefetchcache=>1); + #print Dumper($tmp_ipmi); + } else { + $callback->({error=>["Cannot open the ipmi table."],errorcode=>[1]}); + return 1; + } + + #get mac for the nodes + my $mactab = xCAT::Table->new("mac", -create => 0); + my $tmp_mac; + if ($mactab) { + $tmp_mac = $mactab->getNodesAttribs($nodes, ['mac'], prefetchcache=>1); + #print Dumper($tmp_mac); + } else { + $callback->({error=>["Cannot open the mac table."],errorcode=>[1]}); + return 1; + } + + #get cpu, memory and disk info for the nodes + my $hwinvtab = xCAT::Table->new("hwinv", -create => 0); + my $tmp_hwinv; + if ($hwinvtab) { + $tmp_hwinv = $hwinvtab->getNodesAttribs($nodes, ['cpucount', 'memory', 'disksize'], prefetchcache=>1); + #print Dumper($tmp_hwinv); + } else { + $callback->({error=>["Cannot open the hwinv table."],errorcode=>[1]}); + return 1; + } + + #get default username and password for bmc + my $d_bmcuser; + my $d_bmcpasswd; + my $passtab = xCAT::Table->new('passwd'); + if ($passtab) { + ($tmp_passwd)=$passtab->getAttribs({'key'=>'ipmi'},'username','password'); + if (defined($tmp_passwd)) { + $d_bmcuser = $tmp_passwd->{username}; + $d_bmcpasswd = $tmp_passwd->{password}; + } + } + + #print "d_bmcuser=$d_bmcuser, d_bmcpasswd=$d_bmcpasswd \n"; + foreach my $node (@$nodes) { + #collect the node infomation needed for each node, some info + my $mgt; + my $ref_nodehm = $nodehmhash->{$node}->[0]; + if ($ref_nodehm) { + if ($ref_nodehm->{'power'}) { + $mgt = $ref_nodehm->{'power'}; + } elsif ($ref_nodehm->{'mgt'}) { + $mgt = $ref_nodehm->{'mgt'}; + } + } + + my ($bmc, $bmc_user, $bmc_password, $mac, $cpu, $memory, $disk); + if (($mgt) && ($mgt eq 'ipmi')) { + my $ref_ipmi = $tmp_ipmi->{$node}->[0]; + if ($ref_ipmi) { + if (exists($ref_ipmi->{bmc})) { + $bmc = $ref_ipmi->{bmc}; + } + if (exists($ref_ipmi->{username})) { + $bmc_user = $ref_ipmi->{username}; + if (exists($ref_ipmi->{password})) { + $bmc_password = $ref_ipmi->{password}; + } + } else { #take the default if they cannot be found on ipmi table + if ($d_bmcuser) { $bmc_user = $d_bmcuser; } + if ($d_bmcpasswd) { $bmc_password = $d_bmcpasswd; } + } + } + } # else { # for hardware control point other than ipmi, just fake it in OpenStack. + #$bmc = "0.0.0.0"; + #$bmc_user = "xCAT"; + #$bmc_password = "xCAT"; + #} + + my $ref_mac = $tmp_mac->{$node}->[0]; + if ($ref_mac) { + if (exists($ref_mac->{mac})) { + $mac = $ref_mac->{mac}; + } + } + + $ref_hwinv = $tmp_hwinv->{$node}->[0]; + if ($ref_hwinv) { + if (exists($ref_hwinv->{cpucount})) { + $cpu = $ref_hwinv->{cpucount}; + } + if (exists($ref_hwinv->{memory})) { + $memory = $ref_hwinv->{memory}; + #TODO: what if the unit is not in MB? We need to convert it to MB + $memory =~ s/MB|mb//g; + } + if (exists($ref_hwinv->{disksize})) { + #The format of the the disk size is: sda:250GB,sdb:250GB or just 250GB + #We need to get the size of the first one + $disk = $ref_hwinv->{disksize}; + my @a = split(',', $disk); + my @b = split(':', $a[0]); + if (@b > 1) { + $disk = $b[1]; + } else { + $disk = $b[0]; + } + #print "a=@a, b=@b\n"; + #TODO: what if the unit is not in GB? We need to convert it to MB + $disk =~ s/GB|gb//g; + } + } + + #some info are mendatory + if (!$mac) { + $callback->({error=>["Mac address is not defined in the mac table for node $node."],errorcode=>[1]}); + next; + } + if (!$cpu) { + #default cpu count is 1 + $cpu = 1; + } + if (!$memory) { + #default memory size is 1024MB=1GB + $memory = 1024; + } + if (!$disk) { + #default disk size is 1GB + $disk = 1; + } + + if ($verbose) { + my $rsp; + push @{$rsp->{data}}, "Attributes gathered from the xCAT database:"; + push @{$rsp->{data}}, " bmc=$bmc"; + push @{$rsp->{data}}, " bmc_user=$bmc_user"; + push @{$rsp->{data}}, " bmc_password=$bmc_password"; + push @{$rsp->{data}}, " mac=$mac"; + push @{$rsp->{data}}, " cpu=$cpu"; + push @{$rsp->{data}}, " memory=$memory"; + push @{$rsp->{data}}, " disk=$disk"; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + + #call OpenStack command to add the node into the OpenStack as + #a baremetal node. + my $cmd_tmp = "nova baremetal-node-create"; + if ($bmc) { + #make sure it is an ip address + if (($bmc !~ /\d+\.\d+\.\d+\.\d+/) && ($bmc !~ /:/)) { + $bmc = xCAT::NetworkUtils->getipaddr($bmc); + } + $cmd_tmp .= " --pm_address=$bmc"; + } + if ($bmc_user) { + $cmd_tmp .= " --pm_user=$bmc_user"; + } + if ($bmc_password) { + $cmd_tmp .= " --pm_password=$bmc_password"; + } + $cmd_tmp .= " $host $cpu $memory $disk $mac"; + + my $cmd = qq~$cmd_tmp~; + if ($verbose) { + my $rsp; + push @{$rsp->{data}}, "The command to run on $host:"; + push @{$rsp->{data}}, " $cmd"; + push @{$rsp->{data}}, " "; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + #print "cmd=$cmd\n"; + my $output = + xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$host], $cmd, 0); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "OpenStack creating baremetal node $node:"; + push @{$rsp->{data}}, "$output"; + push @{$rsp->{data}}, "The command was: $cmd"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } else { + if (($verbose) && ($output)) { + my $rsp; + push @{$rsp->{data}}, "$output"; + push @{$rsp->{data}}, " "; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } + + } +} + + +#------------------------------------------------------------------------------- + +=head3 opsaddimage + This function takes the xCAT nodes and register them + as the OpenStack baremetal nodes +=cut + +#------------------------------------------------------------------------------- +sub opsaddimage { + my $request = shift; + my $callback = shift; + my $doreq = shift; + + @ARGV = @{$request->{arg}}; + Getopt::Long::Configure("bundling"); + Getopt::Long::Configure("no_pass_through"); + + my $help; + my $version; + my $verbose; + #my $cloud; + my $ops_img_names; + my $controller; + + if(!GetOptions( + 'h|help' => \$help, + 'v|version' => \$version, + 'V|verbose' => \$verbose, + 'c=s' => \$controller, + 'n=s' => \$ops_img_names, + )) + { + &opsaddimage_usage($callback); + return 1; + } + # display the usage if -h or --help is specified + if ($help) { + &opsaddimage_usage($callback); + return 0; + } + # display the version statement if -v or --verison is specified + if ($version) + { + my $rsp={}; + $rsp->{data}->[0]= xCAT::Utils->Version(); + $callback->($rsp); + return 0; + } + + if (@ARGV ==0) { + $callback->({error=>["Please specify an image name or a list of image names."],errorcode=>[1]}); + return 1; + } + + #make sure the input cloud name is valid. + #if (!$cloud) { + # $callback->({error=>["Please specify the name of the cloud with -c flag."],errorcode=>[1]}); + # return 1; + #} else { + # my $cloudstab = xCAT::Table->new('clouds', -create => 0); + # my @et = $cloudstab->getAllAttribs('name', 'controller'); + # if(@et) { + # foreach my $tmp_et (@et) { + # if ($tmp_et->{name} eq $cloud) { + # if ($tmp_et->{controller}) { + # $controller = $tmp_et->{controller}; + # last; + # } else { + # $callback->({error=>["Please specify the controller in the clouds table for the cloud: $cloud."],errorcode=>[1]}); + # return 1; + # } + # } + # } + # } + + if (!$controller) { + $callback->({error=>["Please specify the OpenStack controller node name with -c."],errorcode=>[1]}); + return 1; + } + #} + + #make sure that the images from the command are valid image names + @images = split(',', $ARGV[0]); + @new_names = (); + if ($ops_img_names) { + @new_names = split(',', $ops_img_names); + } + #print "images=@images, new image names=@new_names, controller=$controller\n"; + + my $image_hash = {}; + my $osimgtab = xCAT::Table->new('osimage', -create => 0); + my @et = $osimgtab->getAllAttribs('imagename'); + if(@et) { + foreach my $tmp_et (@et) { + $image_hash->{$tmp_et->{imagename}}{'xCAT'} = 1; + } + } + my @bad_images; + foreach my $image (@images) { + if (!exists($image_hash->{$image})) { + push @bad_images, $image; + } + } + if (@bad_images > 0) { + $callback->({error=>["The following images cannot be found in xCAT osimage table:\n " . join("\n ", @bad_images) . "\n"],errorcode=>[1]}); + return 1; + } + + my $index=0; + foreach my $image (@images) { + my $new_name = shift(@new_names); + if (!$new_name) { + $new_name = $image; #the default new name is xCAT image name + } + my $cmd_tmp = "glance image-create --name $new_name --public --disk-format qcow2 --container-format bare --property xcat_image_name=\'$image\' < /tmp/$image.qcow2"; + + my $cmd = qq~touch /tmp/$image.qcow2;$cmd_tmp~; + if ($verbose) { + my $rsp; + push @{$rsp->{data}}, "The command to run on $controller:"; + push @{$rsp->{data}}, " $cmd"; + push @{$rsp->{data}}, " "; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + my $output = + xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$controller], $cmd, 0); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "OpenStack creating image $new_name:"; + push @{$rsp->{data}}, "$output"; + push @{$rsp->{data}}, "The command was: $cmd"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } else { + if (($verbose) && ($output)) { + my $rsp; + push @{$rsp->{data}}, "$output"; + push @{$rsp->{data}}, " "; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } + my $cmd1 = qq~rm /tmp/$image.qcow2~; + if ($verbose) { + my $rsp; + push @{$rsp->{data}}, "The command to run on $controller:"; + push @{$rsp->{data}}, " $cmd1"; + push @{$rsp->{data}}, " "; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + my $output1 = + xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$controller], $cmd1, 0); + if (($verbose) && ($output1)) { + my $rsp; + push @{$rsp->{data}}, "$output1"; + push @{$rsp->{data}}, " "; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } +} + +#------------------------------------------------------------------------------- + +=head3 deploy_ops_bm_node + This is a internel command called by OpenStack xCAT-baremetal driver. + It prepares the node by adding the config_ops_bm_node postbootscript + to the postscript table for the node, then call nodeset and then boot + the node up. +=cut + +#------------------------------------------------------------------------------- +sub deploy_ops_bm_node { + my $request = shift; + my $callback = shift; + my $doreq = shift; + + @ARGV = @{$request->{arg}}; + Getopt::Long::Configure("bundling"); + Getopt::Long::Configure("no_pass_through"); + + my $node = $request->{node}->[0]; + + my $help; + my $version; + my $img_name; + my $hostname; + my $fixed_ip; + my $netmask; + + if(!GetOptions( + 'h|help' => \$help, + 'v|version' => \$version, + 'image=s' => \$img_name, + 'host=s' => \$hostname, + 'ip=s' => \$fixed_ip, + 'mask=s' => \$netmask, + )) + { + &deploy_ops_bm_node_usage($callback); + return 1; + } + # display the usage if -h or --help is specified + if ($help) { + &deploy_ops_bm_node_usage($callback); + return 0; + } + # display the version statement if -v or --verison is specified + if ($version) + { + my $rsp={}; + $rsp->{data}->[0]= xCAT::Utils->Version(); + $callback->($rsp); + return 0; + } + #print "node=$node, image=$img_name, host=$hostname, ip=$fixed_ip, mask=$netmask\n"; + + #validate the image name + my $osimagetab = xCAT::Table->new('osimage', -create=>1); + my $ref = $osimagetab->getAttribs({imagename => $img_name}, 'imagename'); + if (!$ref) { + $callback->({error=>["Invalid image name: $img_name."],errorcode=>[1]}); + return 1; + } + + #check if the fixed ip is within the xCAT management network. + #get the master ip address for the node then check if the master ip and + #the OpenStack fixed_ip are on the same subnet. + #my $same_nw = 0; + #my $master = xCAT::TableUtils->GetMasterNodeName($node); + #my $master_ip = xCAT::NetworkUtils->toIP($master); + #if (xCAT::NetworkUtils::isInSameSubnet($master_ip, $fixed_ip, $netmask, 0)) { + # $same_nw = 1; + #} + + + #add config_ops_bm_node to the node's postbootscript + my $script = "config_ops_bm_node $hostname $fixed_ip $netmask"; + add_postscript($callback, $node, $script); + + #run nodeset + my $cmd = qq~osimage=$img_name~; + my $output = xCAT::Utils->runxcmd( + {command => ["nodeset"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "nodeset:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + #deploy the node now, supported nodehm.mgt values: ipmi, blade,fsp, hmc. + my $hmtab = xCAT::Table->new('nodehm'); + my $hment = $hmtab->getNodeAttribs($node,['mgt']); + if ($hment && $hment->{'mgt'}) { + my $mgt = $hment->{'mgt'}; + if ($mgt eq 'ipmi') { + deploy_bmc_node($callback, $doreq, $node); + } elsif (($mgt eq 'blade') || ($mgt eq 'fsp')) { + deploy_blade($callback, $doreq, $node); + } elsif ($mgt eq 'hmc') { + deploy_hmc_node($callback, $doreq, $node); + } else { + my $rsp; + push @{$rsp->{data}}, "Node $node: nodehm.mgt=$mgt is not supported in the OpenStack cloud."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } else { + #nodehm.mgt must setup for node + my $rsp; + push @{$rsp->{data}}, "Node $node: nodehm.mgt cannot be empty in order to deploy."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + +} + +# Deploy a rack-mounted node +sub deploy_bmc_node { + my $callback = shift; + my $doreq = shift; + my $node = shift; + + #set boot order + my $cmd = qq~net~; + my $output = xCAT::Utils->runxcmd( + {command => ["rsetboot"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rsetboot:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + + #reboot the node + my $cmd = qq~boot~; + my $output = xCAT::Utils->runxcmd( + {command => ["rpower"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rpower:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } +} + +# Deploy a blade or fsp controlled node +sub deploy_blade { + my $callback = shift; + my $doreq = shift; + my $node = shift; + + #set boot order + my $cmd = qq~net~; + my $output = xCAT::Utils->runxcmd( + {command => ["rbootseq"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rbootseq:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + + #reboot the node + my $cmd = qq~boot~; + my $output = xCAT::Utils->runxcmd( + {command => ["rpower"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rpower:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } +} + +# Deploy a node controlled by HMC +sub deploy_hmc_node { + my $callback = shift; + my $doreq = shift; + my $node = shift; + + my $output = xCAT::Utils->runxcmd( + {command => ["rnetboot"], + node => [$node]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rnetboot:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } +} + + +#------------------------------------------------------------------------------- + +=head3 cleanup_ops_bm_node + This is a internel command called by OpenStack xCAT-baremetal driver. + It undoes all the changes made by deploy_ops_bm_node command. It removes + the config_ops_bmn_ode postbootscript from the postscript table for the + node, removes the alias ip and then power off the node. +=cut + +#------------------------------------------------------------------------------- +sub cleanup_ops_bm_node { + my $request = shift; + my $callback = shift; + my $doreq = shift; + + @ARGV = @{$request->{arg}}; + Getopt::Long::Configure("bundling"); + Getopt::Long::Configure("no_pass_through"); + + my $node = $request->{node}->[0]; + + my $help; + my $version; + my $fixed_ip; + + if(!GetOptions( + 'h|help' => \$help, + 'v|version' => \$version, + 'ip=s' => \$fixed_ip, + )) + { + &cleanup_ops_bm_node_usage($callback); + return 1; + } + # display the usage if -h or --help is specified + if ($help) { + &cleanup_ops_bm_node_usage($callback); + return 0; + } + # display the version statement if -v or --verison is specified + if ($version) + { + my $rsp={}; + $rsp->{data}->[0]= xCAT::Utils->Version(); + $callback->($rsp); + return 0; + } + #print "node=$node, ip=$fixed_ip\n"; + + #removes the config_ops_bm_node postbootscript from the postscripts table + remove_postscript($callback, $node, "config_ops_bm_node"); + + + #run updatenode to remove the ip alias + my $cmd = qq~-P deconfig_ops_bm_node $fixed_ip~; + my $output = xCAT::Utils->runxcmd( + {command => ["updatenode"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "updatenode:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + + #turn the node power off + $ssh_ok = 0; + my $cmd = qq~stat~; + my $output = xCAT::Utils->runxcmd( + {command => ["rpower"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rpower:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } else { + if ($output !~ /: off/) { + #power off the node + my $cmd = qq~off~; + my $output = xCAT::Utils->runxcmd( + {command => ["rpower"], + node => [$node], + arg => [$cmd]}, + $doreq, -1, 1); + if ($::RUNCMD_RC != 0) { + my $rsp; + push @{$rsp->{data}}, "rpower:"; + push @{$rsp->{data}}, "$output"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + } +} + +#------------------------------------------------------- +=head3 add_postscript + + It adds the 'config_ops_bm_node' postbootscript to the + postscript table for the given node. + +=cut +#------------------------------------------------------- +sub add_postscript { + my $callback=shift; + my $node=shift; + my $script=shift; + #print "script=$script\n"; + + my $posttab=xCAT::Table->new("postscripts", -create =>1); + my %setup_hash; + my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]); + my $found=0; + if ($ref) { + if (exists($ref->{postscripts})) { + my @a = split(/,/, $ref->{postscripts}); + if (grep(/^config_ops_bm_node/, @a)) { + $found = 1; + if (!grep(/^$script$/, @a)) { + #not exact match, must replace it with the new script + for (@a) { + s/^config_ops_bm_node.*$/$script/; + } + my $new_post = join(',', @a); + $setup_hash{$node}={postscripts=>"$new_post"}; + } + } + } + + + if (exists($ref->{postbootscripts})) { + my $post=$ref->{postbootscripts}; + my @old_a=split(',', $post); + if (grep(/^config_ops_bm_node/, @old_a)) { + if (!grep(/^$script$/, @old_a)) { + #not exact match, will replace it with new script + for (@old_a) { + s/^config_ops_bm_node.*$/$script/; + } + my $new_postboot = join(',', @old_a); + $setup_hash{$node}={postbootscripts=>"$new_postboot"}; + } + } else { + if (! $found) { + $setup_hash{$node}={postbootscripts=>"$post,$script"}; + } + } + } else { + if (! $found) { + $setup_hash{$node}={postbootscripts=>"$script"}; + } + } + } else { + $setup_hash{$node}={postbootscripts=>"$script"}; + } + + if (keys(%setup_hash) > 0) { + $posttab->setNodesAttribs(\%setup_hash); + } + + return 0; +} + +#------------------------------------------------------- +=head3 remove_postscript + + It removes the 'config_ops_bm_node' postbootscript from + the postscript table for the given node. + +=cut +#------------------------------------------------------- +sub remove_postscript { + my $callback=shift; + my $node=shift; + my $script=shift; + + my $posttab=xCAT::Table->new("postscripts", -create =>1); + my %setup_hash; + my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]); + my $found=0; + if ($ref) { + if (exists($ref->{postscripts})) { + my @old_a = split(/,/, $ref->{postscripts}); + my @new_a = grep(!/^$script/, @old_a); + if (scalar(@new_a) != scalar(@old_a)) { + my $new_post = join(',', @new_a); + $setup_hash{$node}={postscripts=>"$new_post"}; + } + } + + if (exists($ref->{postbootscripts})) { + my @old_b = split(/,/, $ref->{postbootscripts}); + my @new_b = grep(!/^$script/, @old_b); + if (scalar(@new_b) != scalar(@old_b)) { + my $new_post = join(',', @new_b); + $setup_hash{$node}={postbootscripts=>"$new_post"}; + } + } + + } + + if (keys(%setup_hash) > 0) { + $posttab->setNodesAttribs(\%setup_hash); + } + + return 0; +} + + +#------------------------------------------------------------------------------- + +=head3 opsaddbmnode_usage + The usage text for opsaddbmnode command. +=cut + +#------------------------------------------------------------------------------- +sub opsaddbmnode_usage { + my $cb=shift; + my $rsp={}; + + $rsp->{data}->[0]= "Usage: opsaddbmnode -h"; + $rsp->{data}->[1]= " opsaddbmnode -v"; + $rsp->{data}->[2]= " opsaddbmnode -s [-V]"; + $cb->($rsp); +} + + +#------------------------------------------------------------------------------- + +=head3 opsaddimage_usage + The usage text for opsaddimage command. +=cut + +#------------------------------------------------------------------------------- +sub opsaddimage_usage { + my $cb=shift; + my $rsp={}; + + $rsp->{data}->[0]= "Usage: opsaddimage -h"; + $rsp->{data}->[1]= " opsaddimage -v"; + $rsp->{data}->[2]= " opsaddimage [-n -c [-V]"; + $cb->($rsp); +} + +#------------------------------------------------------------------------------- + +=head3 deploy_ops_bm_node_usage + The usage text for deploy_ops_bm_node command. +=cut + +#------------------------------------------------------------------------------- +sub deploy_ops_bm_node_usage { + my $cb=shift; + my $rsp={}; + + $rsp->{data}->[0]= "Usage: deploy_ops_bm_node -h"; + $rsp->{data}->[1]= " deploy_ops_bm_node -v"; + $rsp->{data}->[2]= " deploy_ops_bm_node --image --host --ip --mask "; + $cb->($rsp); +} + +#------------------------------------------------------------------------------- + +=head3 cleanup_ops_bm_node_usage + The usage text cleanup_ops_bm_node command. +=cut + +#------------------------------------------------------------------------------- +sub cleanup_ops_bm_node_usage { + my $cb=shift; + my $rsp={}; + + $rsp->{data}->[0]= "Usage: cleanup_ops_bm_node -h"; + $rsp->{data}->[1]= " cleanup_ops_bm_node -v"; + $rsp->{data}->[2]= " cleanup_ops_bm_node [--ip ]"; + $cb->($rsp); +} + +1; diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/__init__.py b/xCAT-OpenStack-baremetal/lib/python/xcat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/__init__.py b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/__init__.py b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/__init__.py new file mode 100644 index 000000000..b0997e201 --- /dev/null +++ b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2012 NTT DOCOMO, INC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from xcat.openstack.baremetal import driver + +BareMetalDriver = driver.xCATBareMetalDriver diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/driver.py b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/driver.py new file mode 100644 index 000000000..e42348be2 --- /dev/null +++ b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/driver.py @@ -0,0 +1,256 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# coding=utf-8 + +""" +A driver for Bare-metal platform. +""" + +from oslo.config import cfg + +from nova.compute import power_state +from nova import context as nova_context +from nova import exception +from nova.openstack.common import excutils +from nova.openstack.common.gettextutils import _ +from nova.openstack.common import importutils +from nova.openstack.common import jsonutils +from nova.openstack.common import log as logging +from nova.virt.baremetal import baremetal_states +from nova.virt.baremetal import db +from nova.virt.baremetal import driver as bm_driver +from nova.virt.baremetal import utils as bm_utils +from nova.virt import driver +from nova.virt import firewall +from nova.virt.libvirt import imagecache +from xcat.openstack.baremetal import xcat_driver +from xcat.openstack.baremetal import exception as xcat_exception +from xcat.openstack.baremetal import power_states + + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF +CONF.import_opt('use_ipv6', 'nova.netconf') + + +class xCATBareMetalDriver(bm_driver.BareMetalDriver): + """BareMetal hypervisor driver.""" + + def __init__(self, virtapi, read_only=False): + super(xCATBareMetalDriver, self).__init__(virtapi) + self.xcat = xcat_driver.xCAT() + + def _get_xCAT_image_name(self, image_meta): + prop = image_meta.get('properties') + xcat_image_name = prop.get('xcat_image_name') + if xcat_image_name: + return xcat_image_name + else: + raise xcat_exception.xCATInvalidImageError(image=image_meta.get('name')) + + def spawn(self, context, instance, image_meta, injected_files, + admin_password, network_info=None, block_device_info=None): + """ + Create a new instance/VM/domain on the virtualization platform. + + Once this successfully completes, the instance should be + running (power_state.RUNNING). + + If this fails, any partial instance should be completely + cleaned up, and the virtualization platform should be in the state + that it was before this call began. + + :param context: security context + :param instance: Instance object as returned by DB layer. + This function should use the data there to guide + the creation of the new instance. + :param image_meta: image object returned by nova.image.glance that + defines the image from which to boot this instance + :param injected_files: User files to inject into instance. + :param admin_password: Administrator password to set in instance. + :param network_info: + :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` + :param block_device_info: Information about block devices to be + attached to the instance. + """ + #import pdb + #pdb.set_trace() + node_uuid = self._require_node(instance) + node = db.bm_node_associate_and_update(context, node_uuid, + {'instance_uuid': instance['uuid'], + 'instance_name': instance['hostname'], + 'task_state': baremetal_states.BUILDING}) + + try: + self._plug_vifs(instance, network_info, context=context) + self._attach_block_devices(instance, block_device_info) + self._start_firewall(instance, network_info) + + macs = self.macs_for_instance(instance) + nodename = self.xcat.get_xcat_node_name(macs) + imagename = self._get_xCAT_image_name(image_meta) + hostname = instance.get('hostname') + + #get the network information for the new node + interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6) + if CONF.use_ipv6: + fixed_ip = interfaces[0].get('address_v6') + netmask = interfaces[0].get('netmask_v6') + gateway = interfaces[0].get('gateway_v6') + else: + fixed_ip = interfaces[0].get('address') + netmask = interfaces[0].get('netmask') + gateway = interfaces[0].get('gateway') + #convert netmask from IPAddress to unicode string + if netmask: + netmask = unicode(netmask) + + #let xCAT install it + bm_driver._update_state(context, node, instance, baremetal_states.DEPLOYING) + self.xcat.deploy_node(nodename, imagename, hostname, fixed_ip, netmask, gateway) + bm_driver._update_state(context, node, instance, baremetal_states.ACTIVE) + except Exception as e: + with excutils.save_and_reraise_exception(): + LOG.error(_("Error occured while deploying instance %(instance)s " + "on baremetal node %(node)s: %(error)s") % + {'instance': instance['uuid'], + 'node': node['uuid'], + 'error':str(e)}) + bm_driver._update_state(context, node, instance, baremetal_states.ERROR) + + def reboot(self, context, instance, network_info, reboot_type, + block_device_info=None, bad_volumes_callback=None): + """Reboot the specified instance. + + After this is called successfully, the instance's state + goes back to power_state.RUNNING. The virtualization + platform should ensure that the reboot action has completed + successfully even in cases in which the underlying domain/vm + is paused or halted/stopped. + + :param instance: Instance object as returned by DB layer. + :param network_info: + :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` + :param reboot_type: Either a HARD or SOFT reboot + :param block_device_info: Info pertaining to attached volumes + :param bad_volumes_callback: Function to handle any bad volumes + encountered + """ + try: + node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid']) + macs = self.macs_for_instance(instance) + nodename = self.xcat.get_xcat_node_name(macs) + self.xcat.reboot_node(nodename) + bm_driver._update_state(context, node, instance, baremetal_states.RUNNING) + except xcat_exception.xCATCommandError as e: + with excutils.save_and_reraise_exception(): + LOG.error(_("Error occured while rebooting instance %(instance)s " + "on baremetal node %(node)s: %(error)s") % + {'instance': instance['uuid'], + 'node': node['uuid'], + 'error':str(e)}) + bm_driver._update_state(context, node, instance, baremetal_states.ERROR) + + def destroy(self, instance, network_info, block_device_info=None, + context=None): + """Destroy (shutdown and delete) the specified instance. + + If the instance is not found (for example if networking failed), this + function should still succeed. It's probably a good idea to log a + warning in that case. + + :param context: security context + :param instance: Instance object as returned by DB layer. + :param network_info: + :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` + :param block_device_info: Information about block devices that should + be detached from the instance. + :param destroy_disks: Indicates if disks should be destroyed + """ + #import pdb + #pdb.set_trace() + context = nova_context.get_admin_context() + try: + node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid']) + + except exception.InstanceNotFound: + LOG.warning(_("Destroy function called on a non-existing instance %s") + % instance['uuid']) + return + + try: + macs = self.macs_for_instance(instance) + nodename = self.xcat.get_xcat_node_name(macs) + interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6) + fixed_ip=None + if interfaces and interfaces[0]: + if CONF.use_ipv6: + fixed_ip = interfaces[0].get('address_v6') + else: + fixed_ip = interfaces[0].get('address') + if fixed_ip: + self.xcat.cleanup_node(nodename, fixed_ip) + else: + self.xcat.cleanup_node(nodename) + except Exception as e: + #just log it and move on + LOG.warning(_("Destroy called with xCAT error:" + str(e))) + + try: + self._detach_block_devices(instance, block_device_info) + self._stop_firewall(instance, network_info) + self._unplug_vifs(instance, network_info) + + bm_driver._update_state(context, node, None, baremetal_states.DELETED) + except Exception as e: + with excutils.save_and_reraise_exception(): + LOG.error(_("Error occurred while destroying instance %s: %s") + % (instance['uuid'], str(e))) + bm_driver._update_state(context, node, instance, + baremetal_states.ERROR) + + def power_off(self, instance, node=None): + """Power off the specified instance.""" + macs = self.macs_for_instance(instance) + nodename = self.xcat.get_xcat_node_name(macs) + self.xcat.power_off_node(nodename) + + + def power_on(self, context, instance, network_info, block_device_info=None, + node=None): + """Power on the specified instance.""" + macs = self.macs_for_instance(instance) + nodename = self.xcat.get_xcat_node_name(macs) + self.xcat.power_on_node(nodename) + + + def get_console_output(self, instance): + pass + + def get_info(self, instance): + """Get the current status of an instance, by name (not ID!) + + Returns a dict containing: + :state: the running state, one of the power_state codes + :max_mem: (int) the maximum memory in KBytes allowed + :mem: (int) the memory in KBytes used by the domain + :num_cpu: (int) the number of virtual CPUs for the domain + :cpu_time: (int) the CPU time used in nanoseconds + """ + + node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid']) + macs = self.macs_for_instance(instance) + nodename = self.xcat.get_xcat_node_name(macs) + + ps = self.xcat.get_node_power_state(nodename) + if ps == power_states.ON: + pstate = power_state.RUNNING + elif ps == power_states.OFF: + pstate = power_state.SHUTDOWN + else: + pstate = power_state.NOSTATE + + return {'state': pstate, + 'max_mem': node['memory_mb'], + 'mem': node['memory_mb'], + 'num_cpu': node['cpus'], + 'cpu_time': 0} diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/exception.py b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/exception.py new file mode 100644 index 000000000..38ce5bf60 --- /dev/null +++ b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/exception.py @@ -0,0 +1,41 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +"""xCAT baremtal exceptions. +""" + +import functools +import sys + +from oslo.config import cfg +import webob.exc + +from nova.openstack.common import excutils +from nova.openstack.common.gettextutils import _ +from nova.openstack.common import log as logging +from nova import safe_utils +from nova import exception as nova_exception + +LOG = logging.getLogger(__name__) + +class xCATException(Exception): + errmsg = _("xCAT general exception") + + def __init__(self, errmsg=None, **kwargs): + if not errmsg: + errmsg = self.errmsg + errmsg = errmsg % kwargs + + super(xCATException, self).__init__(errmsg) + +class xCATCommandError(xCATException): + errmsg = _("Error returned when calling xCAT command %(cmd)s" + " for node %(node)s:%(error)s") + +class xCATInvalidImageError(xCATException): + errmsg = _("The image %(image)s is not an xCAT image") + +class xCATDeploymentFailure(xCATException): + errmsg = _("xCAT node deployment failed for node %(node)s:%(error)s") + +class xCATRebootFailure(xCATException): + errmsg = _("xCAT node rebooting failed for node %(node)s:%(error)s") diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/power_states.py b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/power_states.py new file mode 100644 index 000000000..47e153137 --- /dev/null +++ b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/power_states.py @@ -0,0 +1,9 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +""" +Possible xCAT node power states. +""" + +OFF = 'off' +ON = 'on' +ERROR = 'error' diff --git a/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/xcat_driver.py b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/xcat_driver.py new file mode 100644 index 000000000..b4068d92e --- /dev/null +++ b/xCAT-OpenStack-baremetal/lib/python/xcat/openstack/baremetal/xcat_driver.py @@ -0,0 +1,260 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# coding=utf-8 + + +""" +Baremetal xCAT power manager. +""" + +import os +import sys +import stat +from oslo.config import cfg +import datetime + +from nova import context as nova_context +from nova.virt.baremetal import baremetal_states +from nova.openstack.common.gettextutils import _ +from nova.openstack.common import log as logging +from nova.openstack.common import loopingcall +from nova.openstack.common import timeutils +from nova import paths +from nova import utils +from xcat.openstack.baremetal import exception +from xcat.openstack.baremetal import power_states + +LOG = logging.getLogger(__name__) + +# register configuration options +xcat_opts = [ + cfg.IntOpt('deploy_timeout', + help='Timeout for node deployment. Default: 0 second (unlimited)', + default=0), + cfg.IntOpt('reboot_timeout', + help='Timeout for rebooting a node. Default: 0 second (unlimited)', + default=0), + cfg.IntOpt('deploy_checking_interval', + help='Checking interval for node deployment. Default: 10 seconds', + default=10), + cfg.IntOpt('reboot_checking_interval', + help='Checking interval for rebooting a node. Default: 5 seconds', + default=5), + ] +xcat_group = cfg.OptGroup(name='xcat', + title='xCAT Options') +CONF = cfg.CONF +CONF.register_group(xcat_group) +CONF.register_opts(xcat_opts, xcat_group) + + +class xCAT(object): + """A driver that calls xCAT funcions""" + + def __init__(self): + #setup the path for xCAT commands + #xcatroot = os.getenv('XCATROOT', '/opt/xcat/') + #sys.path.append("%s/bin" % xcatroot) + #sys.path.append("%s/sbin" % xcatroot) + pass + + def _exec_xcat_command(self, command): + """Calls xCAT command.""" + args = command.split(" ") + out, err = utils.execute(*args, run_as_root=True) + LOG.debug(_("xCAT command stdout: '%(out)s', stderr: '%(err)s'"), + {'out': out, 'err': err}) + return out, err + + def get_xcat_node_name(self, macs): + """Get the xcat node name given mac addressed. + + It uses the mac address to search for the node name in xCAT. + """ + for mac in macs: + out, err = self._exec_xcat_command("lsdef -w mac=%s" % mac) + if out: + return out.split(" ")[0] + + errstr='No node found in xCAT with the following mac address: ' \ + + ','.join(macs) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + + + def deploy_node(self, nodename, imagename, hostname, fixed_ip, netmask, gateway): + """ + Install the node. + + It calls xCAT command deploy_ops_bmnode which prepares the node + by adding the config_ops_bm_node postbootscript to the postscript + table for the node, then call nodeset and then boot the node up. + """ + out, err = self._exec_xcat_command( + "deploy_ops_bm_node %(node)s --image %(image)s" + " --host %(host)s --ip %(ip)s --mask %(mask)s" + % {'node': nodename, + 'image': imagename, + 'host': hostname, + 'ip': fixed_ip, + 'mask': netmask, + }) + if err: + errstr = _("Error returned when calling xCAT deploy_ops_bm_node" + " command for node %s:%s") % (nodename, err) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + self._wait_for_node_deploy(nodename) + + def cleanup_node(self, nodename, fixed_ip=None): + """ + Undo all the changes made to the node by deploy_node function. + + It calls xCAT command cleanup_ops_bm_node which removes the + config_ops_bm_node postbootscript from the postscript table + for the node, removes the alias ip and then power the node off. + """ + cmd = "cleanup_ops_bm_node %s" % nodename + if fixed_ip: + cmd += " --ip %s" % fixed_ip + out, err = self._exec_xcat_command(cmd) + + if err: + errstr = _("Error returned when calling xCAT cleanup_ops_bm_node" + " command for node %s:%s") % (nodename, err) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + + def power_on_node(self, nodename): + """Power on the node.""" + state = self.get_node_power_state(nodename) + if state == power_states.ON: + LOG.warning(_("Powring on node called, but the node %s " + "is already on") % nodename) + out, err = self._exec_xcat_command("rpower %s on" % nodename) + if err: + errstr = _("Error returned when calling xCAT rpower on" + " for node %s:%s") % (nodename, err) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + else: + self._wait_for_node_reboot(nodename) + return power_states.ON + + def power_off_node(self, nodename): + """Power off the node.""" + state = self.get_node_power_state(nodename) + if state == power_states.OFF: + LOG.warning(_("Powring off node called, but the node %s " + "is already off") % nodename) + out, err = self._exec_xcat_command("rpower %s off" % nodename) + if err: + errstr = _("Error returned when calling xCAT rpower off" + " for node %s:%s") % (nodename, err) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + else: + return power_states.OFF + + def reboot_node(self, nodename): + """Reboot the node.""" + out, err = self._exec_xcat_command("rpower %s boot" % nodename) + if err: + errstr = _("Error returned when calling xCAT rpower boot" + " for node %s:%s") % (nodename, err) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + + self._wait_for_node_reboot(nodename) + return power_states.ON + + + def get_node_power_state(self, nodename): + out, err = self._exec_xcat_command("rpower %s stat" % nodename) + if err: + errstr = _("Error returned when calling xCAT rpower stat" + " for node %s:%s") % (nodename, err) + LOG.warning(errstr) + raise exception.xCATCommandError(errstr) + else: + state = out.split(":")[1] + if state: + state = state.strip() + if state == 'on': + return power_states.ON + elif state == 'off': + return power_states.OFF + + return power_states.ERROR + + def _wait_for_node_deploy(self, nodename): + """Wait for xCAT node deployment to complete.""" + locals = {'errstr':''} + + def _wait_for_deploy(): + out,err = self._exec_xcat_command("nodels %s nodelist.status" % nodename) + if err: + locals['errstr'] = _("Error returned when quering node status" + " for node %s:%s") % (nodename, err) + LOG.warning(locals['errstr']) + raise loopingcall.LoopingCallDone() + + if out: + node,status = out.split(": ") + status = status.strip() + if status == "booted": + LOG.info(_("Deployment for node %s completed.") + % nodename) + raise loopingcall.LoopingCallDone() + + if (CONF.xcat.deploy_timeout and + timeutils.utcnow() > expiration): + locals['errstr'] = _("Timeout while waiting for" + " deployment of node %s.") % nodename + LOG.warning(locals['errstr']) + raise loopingcall.LoopingCallDone() + + expiration = timeutils.utcnow() + datetime.timedelta( + seconds=CONF.xcat.deploy_timeout) + timer = loopingcall.FixedIntervalLoopingCall(_wait_for_deploy) + # default check every 10 seconds + timer.start(interval=CONF.xcat.deploy_checking_interval).wait() + + if locals['errstr']: + raise exception.xCATDeploymentFailure(locals['errstr']) + + + def _wait_for_node_reboot(self, nodename): + """Wait for xCAT node boot to complete.""" + locals = {'errstr':''} + + def _wait_for_reboot(): + out,err = self._exec_xcat_command("nodestat %s" % nodename) + if err: + locals['errstr'] = _("Error returned when quering node status" + " for node %s:%s") % (nodename, err) + LOG.warning(locals['errstr']) + raise loopingcall.LoopingCallDone() + + if out: + node,status = out.split(": ") + status = status.strip() + if status == "sshd": + LOG.info(_("Rebooting node %s completed.") + % nodename) + raise loopingcall.LoopingCallDone() + + if (CONF.xcat.reboot_timeout and + timeutils.utcnow() > expiration): + locals['errstr'] = _("Timeout while waiting for" + " rebooting node %s.") % nodename + LOG.warning(locals['errstr']) + raise loopingcall.LoopingCallDone() + + expiration = timeutils.utcnow() + datetime.timedelta( + seconds=CONF.xcat.reboot_timeout) + timer = loopingcall.FixedIntervalLoopingCall(_wait_for_reboot) + # default check every 5 seconds + timer.start(interval=CONF.xcat.reboot_checking_interval).wait() + + if locals['errstr']: + raise exception.xCATRebootFailure(locals['errstr']) diff --git a/xCAT-OpenStack-baremetal/pods/man1/opsaddbmnode.1.pod b/xCAT-OpenStack-baremetal/pods/man1/opsaddbmnode.1.pod new file mode 100644 index 000000000..39cf1f424 --- /dev/null +++ b/xCAT-OpenStack-baremetal/pods/man1/opsaddbmnode.1.pod @@ -0,0 +1,92 @@ +=head1 NAME + +B - It adds xCAT baremetal nodes to an OpenStack cloud. + +=head1 SYNOPSIS + +B I B<-s> I [B<-V>|B<--verbose>] + +B [B<-h>|B<--help>] + +B [B<-v>|B<--version>] + +=head1 DESCRIPTION + +The B command registers xCAT nodes to an OpenStack cloud. An OpenStack nova baremetal node registration command takes several node attributes: + +=over + +=item BMC ip addresss, user id and password + +=item Name of nova compute host which will control this baremetal node + +=item Number of CPUs in the node + +=item Memory in the node (MB) + +=item Local hard disk in the node (GB) + +=item MAC address to provision the node + +=back + +The opsaddbmnode command pulls the above baremetal node information from xCAT tables and calls "nova baremetal-node-create" to register the baremetal node with the OpenStack cloud. + +Please make sure the following xCAT tables are filled with correct information for the given nodes before calling this command. + +=over + +=item ipmi (for BMC ip addresss, user id and password) + +=item mac (for MAC address) + +=item hwinv (for CPU, memory and disk info.) + +=back + +=head1 Parameters + +I is a comma separated node or node group names. + + +=head1 OPTIONS + +=over 10 + +=item B<-s> The node name of the OpenStack compute host that hosts the baremetal nodes. + +=item B<-h|--help> Display usage message. + +=item B<-v|--version> The Command Version. + +=item B<-V|--verbose> Verbose output. + +=back + +=head1 RETURN VALUE + +0 The command completed successfully. + +1 An error has occurred. + +=head1 EXAMPLES + +=over 3 + +=item 1 + +To register node1, node2 and node3 to OpenStack, sv1 is the compute host. + + opsassbmnode node1,node2,node3 -s sv1 + + +=back + +=head1 FILES + +/opt/xcat/bin/opadddbmnode + +=head1 SEE ALSO + +L + diff --git a/xCAT-OpenStack-baremetal/pods/man1/opsaddimage.1.pod b/xCAT-OpenStack-baremetal/pods/man1/opsaddimage.1.pod new file mode 100644 index 000000000..511d68a0a --- /dev/null +++ b/xCAT-OpenStack-baremetal/pods/man1/opsaddimage.1.pod @@ -0,0 +1,67 @@ +=head1 NAME + +B - It adds or removes nodes for the vlan. + +=head1 SYNOPSIS + +B I B<-n> I [B<-c> I] [B<-V>|B<--verbose>] + +B [B<-h>|B<--help>] + +B [B<-v>|B<--version>] + +=head1 DESCRIPTION + +The B command adds a list of xCAT images into the OpenStack cloud. + +Under the cover, it creates a fake image and registers the fake image into OpenStack with command B. It sets the property in the image to indicate that this is an xCAT image and also stores the original xCAT image name in the property for further reference. + +The xCAT image names can be listed using B command. + +=head1 Parameters + +I a comma separated xCAT images names. + + +=head1 OPTIONS + +=over 10 + +=item B<-n> a comma separated new image names in the OpenStack. If omitted, the default is the original xCAT image nanme. + +=item B<-c> the node name of the OpenStack controller. This node must be an xCAT managed node. + +=item B<-h|--help> Display usage message. + +=item B<-v|--version> The Command Version. + +=item B<-V|--verbose> Verbose output. + +=back + +=head1 RETURN VALUE + +0 The command completed successfully. + +1 An error has occurred. + +=head1 EXAMPLES + +=over 3 + +=item 1. + +To register xCAT image rhels6.3-x86_64-install-compute into OpenStack. + + opsaddimage rhels6.3-x86_64-install-compute -c sv2 + +=back + +=head1 FILES + +/opt/xcat/bin/opsaddimage + +=head1 SEE ALSO + +L + diff --git a/xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/config_ops_bm_node b/xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/config_ops_bm_node new file mode 100755 index 000000000..e516a138a --- /dev/null +++ b/xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/config_ops_bm_node @@ -0,0 +1,215 @@ +#!/bin/sh +# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html + +# xCAT post script for configuring the openstack baremetal node. +# The format is: +# config_ops_bm_node ops_hostname ops_ip ops_netmask + + +get_os_type() +{ + #get os type + str_os_type=`uname | tr 'A-Z' 'a-z'` + str_temp='' + if [ "$str_os_type" = "linux" ];then + str_temp=`echo $OSVER | grep -E '(sles|suse)'` + if [ -f "/etc/debian_version" ];then + str_os_type="debian" + elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then + str_os_type="sles" + else + str_os_type="redhat" + fi + else + str_os_type="aix" + fi + echo "$str_os_type" +} + + +setup_ip() +{ + str_os_type=$1 + str_if_name=$2 + str_v4ip=$3 + str_v4mask=$4 + + ret=`ifconfig $str_if_name |grep "inet addr" 2>&1` + if [ $? -eq 0 ]; then + old_ip=`echo $ret|cut -d':' -f2 |cut -d' ' -f1` + old_mask=`echo $ret|cut -d':' -f4` + #echo "old ip = $old_ip, old mask=$old_mask" + if [ "$old_ip" == "$str_v4ip" -a "$old_mask" == "$str_v4mask" ]; then + #if nic is up and the address is the same, then donothing + #echo "do nothing" + exit 0 + else + #bring down the nic and reconstruct it. + #echo "bring down the old nic" + ifconfig $str_if_name del $old_ip + fi + fi + + if [ "$str_os_type" = "sles" ];then + str_conf_file="/etc/sysconfig/network/ifcfg-${str_if_name}" + if [ -f $str_conf_file ]; then + rm $str_conf_file + fi + echo "DEVICE=${str_if_name}" > $str_conf_file + echo "BOOTPROTO=static" >> $str_conf_file + echo "IPADDR=${str_v4ip}" >> $str_conf_file + echo "NETMASK=${str_v4mask}" >> $str_conf_file + echo "NETWORK=''" >> $str_conf_file + echo "STARTMODE=onboot" >> $str_conf_file + echo "USERCONTROL=no" >> $str_conf_file + ifup $str_if_name + #debian ubuntu + elif [ "$str_os_type" = "debian" ];then + str_conf_file="/etc/network/interfaces.d/${str_if_name}" + if [ -f $str_conf_file ]; then + rm $str_conf_file + fi + echo "auto ${str_if_name}" > $str_conf_file + echo "iface ${str_if_name} inet static" >> $str_conf_file + echo " address ${str_v4ip}" >> $str_conf_file + echo " netmask ${str_v4mask}" >> $str_conf_file + ifconfig $str_if_name up + else + # Write the info to the ifcfg file for redhat + str_conf_file="/etc/sysconfig/network-scripts/ifcfg-${str_if_name}" + if [ -f $str_conf_file ]; then + rm $str_conf_file + fi + echo "DEVICE=${str_if_name}" > $str_conf_file + echo "BOOTPROTO=static" >> $str_conf_file + echo "NM_CONTROLLED=no" >> $str_conf_file + echo "IPADDR=${str_v4ip}" >> $str_conf_file + echo "NETMASK=${str_v4mask}" >> $str_conf_file + echo "ONBOOT=yes" >> $str_conf_file + ifup $str_if_name + fi +} + +#change hostname permanently +change_host_name() +{ + str_os_type=$1 + str_hostname=$2 + + hostname $str_hostname + + if [ "$str_os_type" = "sles" ];then + echo "Persistently changing the hostname not implemented yet." + #debian ubuntu + elif [ "$str_os_type" = "debian" ];then + conf_file="/etc/hostname" + echo "$str_hostname" > $conf_file + else + conf_file="/etc/sysconfig/network" + if [ ! -f $conf_file ]; then + touch $conf_file + fi + grep 'HOSTNAME' $conf_file 2>&1 > /dev/null + if [ $? -eq 0 ]; then + sed -i "s/HOSTNAME=.*/HOSTNAME=$str_hostname/" $conf_file + else + echo "HOSTNAME=$str_hostname" >> $conf_file + fi + fi + +} + +str_os_type=$(get_os_type) +echo "os_type=$str_os_type" +if [ "$str_os_type" = "aix" ]; then + logger -t xcat "config_ops_bm_node dose not support AIX." + echo "config_ops_bm_node dose not support AIX." + exit 0 +fi + +#change the hostname +if [[ -n "$1" ]]; then + change_host_name $str_os_type $1 +fi + +#Add the openstack ip to the node +if [[ -n $2 ]]; then + ops_ip=$2 + + if [[ -z $3 ]]; then + logger -t xcat "config_ops_bm_node: Please specify the netmask." + echo "config_ops_bm_node: Please specify the netmask." + exit 1 + else + ops_mask=$3 + fi + + #figure out the install nic + if [[ -n $MACADDRESS ]]; then + pos=0 + #mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth1 + for x in `echo "$MACADDRESS" | tr "|" "\n"` + do + node="" + mac="" + pos=$((pos+1)) + i=`expr index $x !` + if [[ $i -gt 0 ]]; then + node=`echo ${x##*!}` + mac_tmp=`echo ${x%%!*}` + else + mac_tmp=$x + fi + + if [[ $pos -eq 1 ]]; then + mac1=$mac_tmp + fi + + if [[ "$PRIMARYNIC" = "$mac_tmp" ]]; then + mac=$mac_tmp + break + fi + + if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then + if [[ -z $node ]] || [[ "$node" = "$NODE" ]]; then + mac=$mac_tmp + break + fi + fi + done + + if [[ -z $mac ]]; then + if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then + mac=$mac1 #if nothing mathes, take the first mac + else + nic=$PRIMARYNIC #or the primary nic itself is the nic + fi + fi + else + logger -t xcat "config_ops_bm_node: no mac addresses are defined in the mac table for the node $NODE" + echo "config_ops_bm_node: no mac addresses are defined in the mac table for the node $NODE" + index=$((index+1)) + continue + fi + echo "mac=$mac" + + #find the nic that has the mac + if [[ -z $nic ]]; then + #go to each nic to match the mac address + ret=`ifconfig |grep -i $mac 2>&1`; + if [ $? -eq 0 ]; then + nic=`echo $ret |head -n1|cut -d' ' -f 1` + else + logger -t xcat "config_ops_bm_node: The mac address for the network for $NODE is not defined." + echo "config_ops_bm_node: The mac address for the network for $NODE is not defined." + fi + fi + echo "nic=$nic" + + #now setup the ip alias + setup_ip $str_os_type $nic:0 $ops_ip $ops_mask +fi + + + + diff --git a/xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/deconfig_ops_bm_node b/xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/deconfig_ops_bm_node new file mode 100755 index 000000000..da148f47e --- /dev/null +++ b/xCAT-OpenStack-baremetal/share/xcat/openstack/postscripts/deconfig_ops_bm_node @@ -0,0 +1,94 @@ +#!/bin/sh +# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html + +# xCAT post script for deconfiguring the openstack baremetal node. +# The format is: +# deconfig_ops_bm_node ops_ip + + +get_os_type() +{ + #get os type + str_os_type=`uname | tr 'A-Z' 'a-z'` + str_temp='' + if [ "$str_os_type" = "linux" ];then + str_temp=`echo $OSVER | grep -E '(sles|suse)'` + if [ -f "/etc/debian_version" ];then + str_os_type="debian" + elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then + str_os_type="sles" + else + str_os_type="redhat" + fi + else + str_os_type="aix" + fi + echo "$str_os_type" +} + +#change hostname permanently +change_host_name() +{ + str_os_type=$1 + str_hostname=$2 + + hostname $str_hostname + + if [ "$str_os_type" = "sles" ];then + echo "Persistently changing the hostname not implemented yet." + #debian ubuntu + elif [ "$str_os_type" = "debian" ];then + conf_file="/etc/hostname" + echo "$str_hostname" > $conf_file + else + conf_file="/etc/sysconfig/network" + if [ ! -f $conf_file ]; then + touch $conf_file + fi + grep 'HOSTNAME' $conf_file 2>&1 > /dev/null + if [ $? -eq 0 ]; then + sed -i "s/HOSTNAME=.*/HOSTNAME=$str_hostname/" $conf_file + else + echo "HOSTNAME=$str_hostname" >> $conf_file + fi + fi +} + + +str_os_type=$(get_os_type) +echo "os_type=$str_os_type" + +if [ $str_os_type == "aix" ]; then + logger -t xcat "deconfig_ops_bm_node dose not support AIX." + echo "deconfig_ops_bm_node dose not support AIX." + exit 0 +fi + +#change the hostname +#hostname $NODE +change_host_name $str_os_type $NODE + +#remove the openstack ip from the node +if [[ -n $1 ]]; then + ops_ip=$1 + nic=$(ip addr | grep $ops_ip | awk '{print $NF}') + echo "nic=$nic, ops_ip=$ops_ip" + + ifconfig $nic del $ops_ip + + #delete the configuration file + if [ "$str_os_type" = "sles" ]; then + str_conf_file="/etc/sysconfig/network/ifcfg-$nic" + elif [ "$str_os_type" = "debian" ]; then #debian ubuntu + str_conf_file="/etc/network/interfaces.d/$nic" + else #redhat + str_conf_file="/etc/sysconfig/network-scripts/ifcfg-$nic" + fi + if [ -f $str_conf_file ]; then + rm $str_conf_file + fi +fi + + + + diff --git a/xCAT-OpenStack-baremetal/xCAT-OpenStack-baremetal.spec b/xCAT-OpenStack-baremetal/xCAT-OpenStack-baremetal.spec new file mode 100644 index 000000000..8546e6ad1 --- /dev/null +++ b/xCAT-OpenStack-baremetal/xCAT-OpenStack-baremetal.spec @@ -0,0 +1,102 @@ +Summary: Executables and data of the xCAT baremetal driver for OpenStack +Name: xCAT-OpenStack-baremetal +Version: %(cat Version) +Release: snap%(date +"%Y%m%d%H%M") +Epoch: 4 +License: IBM +Group: Applications/System +Source: xCAT-OpenStack-baremetal-%{version}.tar.gz +Packager: IBM Corp. +Vendor: IBM Corp. +Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}} +Prefix: /opt/xcat +BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root + +%ifos linux +BuildArch: noarch +%endif + + +Provides: xCAT-OpenStack-baremetal = %{epoch}:%{version} + +Requires: xCAT-client + +%description +xCAT-OpenStack-baremetal provides the baremetal driver for OpenStack. + +%prep +%setup -q -n xCAT-OpenStack-baremetal +%build + +# Convert pods to man pages and html pages +./xpod2man + +%install +# The install phase puts all of the files in the paths they should be in when the rpm is +# installed on a system. The RPM_BUILD_ROOT is a simulated root file system and usually +# has a value like: /var/tmp/xCAT-OpenStack-baremetal-2.0-snap200802270932-root +rm -rf $RPM_BUILD_ROOT + +mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin +mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin +mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin +mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/python/xcat/openstack/baremetal +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/openstack/postscripts +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1 +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 + + +set +x + +cp -R lib/* $RPM_BUILD_ROOT/%{prefix}/lib +cp share/xcat/openstack/postscripts/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/openstack/postscripts + + +# These were built dynamically in the build phase +cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1 +chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/* + +# These were built dynamically during the build phase +cp share/doc/man1/* $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 +chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/man1/* + +# These links get made in the RPM_BUILD_ROOT/prefix area +ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/sbin/deploy_ops_bm_node +ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/sbin/cleanup_ops_bm_node +ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/opsaddbmnode +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/opsaddimage + +set -x + + +%clean +# This step does not happen until *after* the %files packaging below +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +#%doc LICENSE.html +# Just package everything that has been copied into RPM_BUILD_ROOT +%{prefix} + + +%changelog + +%post +#copy the postscripts under /installl/postscripts directory on MN only +if [ -f "/etc/xCATMN" ]; then + cp $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/* /install/postscripts/ +fi + +%preun +#remove postscripts under /installl/postscripts directory on MN only +if [ -f "/etc/xCATMN" ]; then + for fn in $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/* + do + bn=`basename $fn` + rm /install/postscripts/$bn + done +fi +exit 0 + + diff --git a/xCAT-OpenStack-baremetal/xpod2man b/xCAT-OpenStack-baremetal/xpod2man new file mode 100755 index 000000000..c885505bd --- /dev/null +++ b/xCAT-OpenStack-baremetal/xpod2man @@ -0,0 +1,214 @@ +#!/usr/bin/perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# First builds the xCAT summary man page from Synopsis of each man page. +# Then converts all of the pod man pages into html (including links to each other) + +# We assume that this script is run in the xCAT-vlan-2.0 dir, so everything is +# done relative to that. + +use strict; +#use lib '.'; +use Pod::Man; +use Pod::Html; + +my $poddir = 'pods'; +my $mandir = 'share/man'; +my $htmldir = 'share/doc'; +my $cachedir = '/tmp'; + +my @pods = getPodList($poddir); +#foreach (@pods) { print "$_\n"; } exit; + +# Build the cmd overview page. +#writesummarypage("$poddir/man1/xcat.1.pod", @pods); + +# Build the man page for each pod. +#mkdir($mandir) or die "Error: could not create $mandir.\n"; +print "Converting PODs to man pages...\n"; +foreach my $podfile (@pods) { + my $manfile = $podfile; + $manfile =~ s/^$poddir/$mandir/; # change the beginning of the path + $manfile =~ s/\.pod$//; # change the ending + my $mdir = $manfile; + $mdir =~ s|/[^/]*$||; # get rid of the basename part + if (system("mkdir -p $mdir")) { die "Error: could not create $mdir.\n"; } + my ($section) = $podfile =~ /\.(\d+)\.pod$/; + convertpod2man($podfile, $manfile, $section); +} + +my @dummyPods = createDummyPods($poddir, \@pods); + +# Build the html page for each pod. +#mkdir($htmldir) or die "Error: could not create $htmldir.\n"; +print "Converting PODs to HTML pages...\n"; +# have to clear the cache, because old entries can cause a problem +unlink("$cachedir/pod2htmd.tmp", "$cachedir/pod2htmi.tmp"); +foreach my $podfile (@pods) { + my $htmlfile = $podfile; + $htmlfile =~ s/^$poddir/$htmldir/; # change the beginning of the path + $htmlfile =~ s/\.pod$/\.html/; # change the ending + my $hdir = $htmlfile; + $hdir =~ s|/[^/]*$||; # get rid of the basename part + if (system("mkdir -p $hdir")) { die "Error: could not create $hdir.\n"; } + #print "$podfile, $htmlfile, $poddir, $htmldir\n"; + convertpod2html($podfile, $htmlfile, $poddir, $htmldir); +} + +# Remove the dummy pods +unlink @dummyPods; +rmdir "$poddir/man7"; + +exit; + + +# To enable linking between the cmd man pages and the db man pages, need to: +# grep thru the cmd pods searching for references (L<>) to any section 5 man page +# if that pod does not exist, create an empty one that will satisfy pod2html +# keep track of all dummy pods created, so they can be removed later +sub createDummyPods { + my ($poddir, $pods) = @_; + my $cmd = "grep -r -E 'L<.+\\([57]\\)\\|.+\\.[57]>' " . $poddir; + #print "Running cmd: ", $cmd, "\n"; + my @lines = `$cmd`; + if ($?) { print "Error running: $cmd\n"; print join('', @lines); } + #my @lines; + #system($cmd); + my @dummyPods; + foreach my $l (@lines) { + #print "$l\n"; + my @matches = $l =~ /L<([^\(]+)\(([57])\)\|\1\.[57]>/g; # get all the matches in the line + # The above line should create the array with every other entry being the man page name + # and every other entry is the section # (5 or 7) + my $cmd; + while ($cmd=shift @matches) { + #foreach my $m (@matches) { + my $section = shift @matches; + my $filename = "$poddir/man$section/$cmd.$section.pod"; + #print "$filename\n"; + if (!(grep /^$filename$/, @$pods) && !(grep /^$filename$/, @dummyPods)) { push @dummyPods, $filename; } + } + } + + + # Create these empty files + print "Creating empty linked-to files: ", join(', ', @dummyPods), "\n"; + mkdir "$poddir/man7"; + foreach my $d (@dummyPods) { + if (!open(TMP, ">>$d")) { warn "Could not create dummy pod file $d ($!)\n"; } + else { close TMP; } + } + + return @dummyPods; +} + +# Recursively get the list of pod man page files. +sub getPodList { + my $poddir = shift; + my @files; + + # 1st get toplevel dir listing + opendir(DIR, $poddir) or die "Error: could not read $poddir.\n"; + my @topdir = grep !/^\./, readdir(DIR); # / + close(DIR); + + # Now go thru each subdir (these are man1, man3, etc.) + foreach my $mandir (@topdir) { + opendir(DIR, "$poddir/$mandir") or die "Error: could not read $poddir/$mandir.\n"; + my @dir = grep !/^\./, readdir(DIR); # / + close(DIR); + foreach my $file (@dir) { + push @files, "$poddir/$mandir/$file"; + } + } + return sort @files; +} + + +# Create the xcat man page that gives a summary description of each xcat cmd. +# Not used. +sub writesummarypage { + my $file = shift; # relative path file name of the man page + # the rest of @_ contains the pod files that describe each cmd + + open(FILE, ">$file") or die "Error: could not open $file for writing.\n"; + + print FILE <<'EOS1'; +=head1 NAME + +B - extreme Cluster Administration Tool. + +=head1 DESCRIPTION + +Extreme Cluster Administration Toolkit (xCAT). xCAT is a scalable distributed computing management +and provisioning tool that provides a unified interface for hardware control, discovery, and +OS diskful/diskfree deployment. + + +=head1 XCAT DATABASE + +All of the cluster configuration information is in the xCAT database. See L for +descriptions of every table in the database. + +=head1 XCAT COMMANDS + +What follows is a short description of each xCAT command. To get more information about a particular +command, see its man page. Note that the commands are listed in alphabetical order B, +i.e. all the commands in section 1, then the commands in section 3, etc. + +=over 12 +EOS1 + +# extract the summary for each cmd from its man page +foreach my $manpage (@_) { + my ($sectionnum) = $manpage =~ /\.(\d+)\.pod$/; + # Suck in the whole file, then we will parse it. + open(MANPAGE, "$manpage") or die "Error: could not open $manpage for reading.\n"; + my @contents = ; + my $wholemanpage = join('', @contents); + close(MANPAGE); + # This regex matches: optional space, =head1, space, title, space, cmd, space, description, newline + my ($cmd, $description) = $wholemanpage =~ /^\s*=head1\s+\S+\s+(\S+)\s+(.+?)\n/si; + if (!defined($cmd)) { print "Warning: $manpage is not in a recognized structure. It will be ignored.\n"; next; } + if (!defined($description)) { print "Warning: $manpage does not have a description for $cmd. It will be ignored.\n"; next; } + $cmd =~ s/^.<(.+)>$/$1/; # if the cmd name has pod formatting around it, strip it off + $description =~ s/^-\s*//; # if the description has a leading hypen, strip it off + print FILE "\n=item L<$cmd($sectionnum)|$cmd.$sectionnum>\n\n".$description."\n"; +} + +# Artificially add the xcattest cmd, because the xCAT-test rpm will add this +print FILE "\n=item L\n\nRun automated xCAT test cases.\n"; + + print FILE <<"EOS3"; + +=back +EOS3 + + close FILE; +} + + +# Create the html page for one pod. +sub convertpod2html { + my ($podfile, $htmlfile, $poddir, $htmldir) = @_; + + #TODO: use --css= and --title= to make the pages look better + pod2html($podfile, + "--outfile=$htmlfile", + "--podpath=man1", + "--podroot=$poddir", + "--htmldir=$htmldir", + "--recurse", + "--cachedir=$cachedir", + ); + +} + + +# Create the man page for one pod. +sub convertpod2man { + my ($podfile, $manfile, $section) = @_; + + my $parser = Pod::Man->new(section => $section); + $parser->parse_from_file($podfile, $manfile); +} diff --git a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/object-server.rb b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/object-server.rb index 01bb15201..19f317d40 100644 --- a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/object-server.rb +++ b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/object-server.rb @@ -94,6 +94,17 @@ template "/etc/swift/object-server.conf" do notifies :restart, "service[swift-object-auditor]", :immediately end +%w[ /var/swift /var/swift/recon ].each do |path| + directory path do + # Create the swift recon cache directory and set its permissions. + owner "swift" + group "swift" + mode 00755 + + action :create + end +end + cron "swift-recon" do minute "*/5" command "swift-recon-cron /etc/swift/object-server.conf" diff --git a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/proxy-server.rb b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/proxy-server.rb index 23232b4bc..3075850e7 100644 --- a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/proxy-server.rb +++ b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/recipes/proxy-server.rb @@ -127,6 +127,19 @@ else authkey = swift_secrets['swift_authkey'] end +if node["swift"]["authmode"] == "keystone" + openstack_identity_bootstrap_token = secret "secrets", "openstack_identity_bootstrap_token" + %w[ /home/swift /home/swift/keystone-signing ].each do |path| + directory path do + owner "swift" + group "swift" + mode 00700 + + action :create + end + end +end + # create proxy config file template "/etc/swift/proxy-server.conf" do source "proxy-server.conf.erb" @@ -134,6 +147,7 @@ template "/etc/swift/proxy-server.conf" do group "swift" mode "0600" variables("authmode" => node["swift"]["authmode"], + "openstack_identity_bootstrap_token" => openstack_identity_bootstrap_token, "bind_host" => node["swift"]["network"]["proxy-bind-ip"], "bind_port" => node["swift"]["network"]["proxy-bind-port"], "authkey" => authkey, diff --git a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/proxy-server.conf.erb b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/proxy-server.conf.erb index 35d2d03a0..95da34f33 100644 --- a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/proxy-server.conf.erb +++ b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/proxy-server.conf.erb @@ -46,6 +46,7 @@ end workers = <%= [ node[:cpu][:total] - 1, 1 ].max %> bind_ip = <%= @bind_host %> bind_port = <%= @bind_port %> +user = swift <% if node[:swift][:statistics][:enabled] -%> log_statsd_host = localhost log_statsd_port = 8125 @@ -137,7 +138,10 @@ use = egg:swift#memcache # commas, as in: 10.1.2.3:11211,10.1.2.4:11211 # memcache_servers = 127.0.0.1:11211 ##### -memcache_servers = <%= @memcache_servers.join(",") %> +#memcache_servers = <%= @memcache_servers.join(",") %> +<% unless @memcache_servers.empty? -%> +memcache_servers = <%= @memcache_servers %> +<% end -%> [filter:ratelimit] use = egg:swift#ratelimit @@ -246,7 +250,7 @@ use = egg:swift#tempurl use = egg:swift#formpost [filter:keystoneauth] -operator_roles = Member,admin +operator_roles = Member,admin,swiftoperator use = egg:swift#keystoneauth [filter:proxy-logging] @@ -268,3 +272,24 @@ use = egg:swift#proxy_logging # not in this list will have "BAD_METHOD" for the portion of the metric. # log_statsd_valid_http_methods = GET,HEAD,POST,PUT,DELETE,COPY +[filter:authtoken] +<% case @authmode + +when "keystone" -%> + +paste.filter_factory = keystone.middleware.auth_token:filter_factory +# usage for anonymous referrers ('.r:*') +delay_auth_decision = true +# +signing_dir = /home/swift/keystone-signing +auth_protocol = http +auth_port = 35357 +auth_host = <%= node["swift"]["network"]["proxy-bind-ip"] %> +admin_token = <%= @openstack_identity_bootstrap_token %> +# the service tenant and swift userid and password created in Keystone +admin_tenant_name = service +admin_user = swift +admin_password = swift + +<% end -%> + diff --git a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/rsyncd.conf.erb b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/rsyncd.conf.erb index 5bd8526a1..3f101ba5b 100644 --- a/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/rsyncd.conf.erb +++ b/xCAT-OpenStack/chef-cookbooks/grizzly-xcat/cookbooks/openstack-object-storage/templates/default/rsyncd.conf.erb @@ -3,7 +3,7 @@ gid = swift log file = /var/log/rsyncd.log pid file = /var/run/rsyncd.pid -address = 0.0.0.0 +address = <%= @storage_local_net_ip %> [account] max connections = 10 diff --git a/xCAT-OpenStack/postscripts/loadclouddata b/xCAT-OpenStack/postscripts/loadclouddata index 7a140b1ad..f461c646b 100755 --- a/xCAT-OpenStack/postscripts/loadclouddata +++ b/xCAT-OpenStack/postscripts/loadclouddata @@ -182,7 +182,8 @@ then for client in $CFGCLIENTLIST do echo "Configuring the chef-client node $client on the chef-server $NODE." - c_fullname="$client.$DOMAIN" + #c_fullname="$client.$DOMAIN" + c_fullname=$client knife client delete -y $c_fullname > /dev/null 2>&1 knife node delete -y $c_fullname > /dev/null 2>&1 diff --git a/xCAT-OpenStack/templates/cloud_environment/grizzly_keystone_swift_allinone.rb.tmpl b/xCAT-OpenStack/templates/cloud_environment/grizzly_keystone_swift_allinone.rb.tmpl new file mode 100644 index 000000000..cf41f73af --- /dev/null +++ b/xCAT-OpenStack/templates/cloud_environment/grizzly_keystone_swift_allinone.rb.tmpl @@ -0,0 +1,178 @@ +# +# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html +# +# +# When using this template, you should change the proxy-cidr and object-cidr +# according to your actual network environment!!!!!!!! +# + +name "$CLOUD" +description "Grizzly keystone+swift allinone environment file." + +override_attributes( + "mysql" => { + "server_root_password" => "cluster", + "server_debian_password" => "cluster", + "server_repl_password" => "cluster", + "allow_remote_root" => true, + "root_network_acl" => "%" + }, + "swift" => { + "authmode" => "keystone", + "authkey" => "swift", + "proxy_server_chef_role"=>"os-object-storage", + "network" => { + "proxy-bind-ip" => "#TABLE:clouds:name=$CLOUD:hostip#", + "proxy-cidr" => "11.0.0.0/8", + "account-bind-ip" => "#TABLE:clouds:name=$CLOUD:hostip#", + "container-bind-ip" => "#TABLE:clouds:name=$CLOUD:hostip#", + "object-bind-ip" => "#TABLE:clouds:name=$CLOUD:hostip#", + "object-cidr" => "11.0.0.0/8" + } + }, + "openstack" => { + "developer_mode" => true, + "db"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#", + "compute"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "identity"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "image"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "network"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "volume"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "dashboard"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "metering"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + } + }, + + "mq"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#" + }, + "identity"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#", + "db"=>{ + "username"=>"keystone", + "password"=> "keystone" + } + }, + + "endpoints"=>{ + "identity-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "identity-admin"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "compute-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "compute-ec2-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "compute-ec2-admin"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "compute-xvpvnc"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "compute-novnc"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "network-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "image-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "image-registry"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "volume-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + }, + "metering-api"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#", + } + }, + + "image" => { + "api"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#" + }, + "registry"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#" + }, + "image_upload" => false, + "upload_images" => ["cirros"], + "upload_image" => { + "cirros" => "https://launchpad.net/cirros/trunk/0.3.0/+download/cirros-0.3.0-x86_64-disk.img" + }, + "identity_service_chef_role" => "allinone-compute" + }, + "block-storage" => { + "rabbit"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "keystone_service_chef_role" => "allinone-compute" + }, + "dashboard" => { + "keystone_service_chef_role" => "allinone-compute", + "use_ssl" => "false" + }, + "network" => { + "metadata"=>{ + "nova_metadata_ip"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "rabbit"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "api"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#" + }, + + "rabbit_server_chef_role" => "allinone-compute", + "l3"=>{ + "external_network_bridge_interface"=>"#TABLE:clouds:name=$CLOUD:pubinterface#" + }, + "openvswitch"=> { + "tenant_network_type"=>"vlan", + "network_vlan_ranges"=>"physnet1", + "bridge_mappings"=>"physnet1:br-#TABLE:clouds:name=$CLOUD:datainterface#" + } + }, + "compute" => { + "identity_service_chef_role" => "allinone-compute", + "rabbit"=>{ + "host"=>"#TABLE:clouds:name=$CLOUD:hostip#" + }, + "xvpvnc_proxy"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:pubinterface#" + }, + "novnc_proxy"=>{ + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:pubinterface#" + }, + "network" => { + "service_type" => "quantum" + }, + "config" => { + "ram_allocation_ratio" => 5.0 + }, + "libvirt" => { + "bind_interface"=>"#TABLE:clouds:name=$CLOUD:mgtinterface#", + "virt_type" => "#TABLE:clouds:name=$CLOUD:virttype#" + } + } + } + ) diff --git a/xCAT-SoftLayer/LICENSE.html b/xCAT-SoftLayer/LICENSE.html new file mode 100644 index 000000000..83d0eebb0 --- /dev/null +++ b/xCAT-SoftLayer/LICENSE.html @@ -0,0 +1,326 @@ + + + + + + + +Eclipse Public License - Version 1.0 + + + + + + +
+ +

Eclipse Public License - v 1.0 +

+ +

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER +THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, +REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE +OF THIS AGREEMENT.

+ +

1. DEFINITIONS

+ +

"Contribution" means:

+ +

a) +in the case of the initial Contributor, the initial code and documentation +distributed under this Agreement, and
+b) in the case of each subsequent Contributor:

+ +

i) +changes to the Program, and

+ +

ii) +additions to the Program;

+ +

where +such changes and/or additions to the Program originate from and are distributed +by that particular Contributor. A Contribution 'originates' from a Contributor +if it was added to the Program by such Contributor itself or anyone acting on +such Contributor's behalf. Contributions do not include additions to the +Program which: (i) are separate modules of software distributed in conjunction +with the Program under their own license agreement, and (ii) are not derivative +works of the Program.

+ +

"Contributor" means any person or +entity that distributes the Program.

+ +

"Licensed Patents " mean patent +claims licensable by a Contributor which are necessarily infringed by the use +or sale of its Contribution alone or when combined with the Program.

+ +

"Program" means the Contributions +distributed in accordance with this Agreement.

+ +

"Recipient" means anyone who +receives the Program under this Agreement, including all Contributors.

+ +

2. GRANT OF RIGHTS

+ +

a) +Subject to the terms of this Agreement, each Contributor hereby grants Recipient +a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly +display, publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and object code +form.

+ +

b) +Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free +patent license under Licensed Patents to make, use, sell, offer to sell, import +and otherwise transfer the Contribution of such Contributor, if any, in source +code and object code form. This patent license shall apply to the combination +of the Contribution and the Program if, at the time the Contribution is added +by the Contributor, such addition of the Contribution causes such combination +to be covered by the Licensed Patents. The patent license shall not apply to +any other combinations which include the Contribution. No hardware per se is +licensed hereunder.

+ +

c) +Recipient understands that although each Contributor grants the licenses to its +Contributions set forth herein, no assurances are provided by any Contributor +that the Program does not infringe the patent or other intellectual property +rights of any other entity. Each Contributor disclaims any liability to Recipient +for claims brought by any other entity based on infringement of intellectual +property rights or otherwise. As a condition to exercising the rights and +licenses granted hereunder, each Recipient hereby assumes sole responsibility +to secure any other intellectual property rights needed, if any. For example, +if a third party patent license is required to allow Recipient to distribute +the Program, it is Recipient's responsibility to acquire that license before +distributing the Program.

+ +

d) +Each Contributor represents that to its knowledge it has sufficient copyright +rights in its Contribution, if any, to grant the copyright license set forth in +this Agreement.

+ +

3. REQUIREMENTS

+ +

A Contributor may choose to distribute the +Program in object code form under its own license agreement, provided that: +

+ +

a) +it complies with the terms and conditions of this Agreement; and

+ +

b) +its license agreement:

+ +

i) +effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title +and non-infringement, and implied warranties or conditions of merchantability +and fitness for a particular purpose;

+ +

ii) +effectively excludes on behalf of all Contributors all liability for damages, +including direct, indirect, special, incidental and consequential damages, such +as lost profits;

+ +

iii) +states that any provisions which differ from this Agreement are offered by that +Contributor alone and not by any other party; and

+ +

iv) +states that source code for the Program is available from such Contributor, and +informs licensees how to obtain it in a reasonable manner on or through a +medium customarily used for software exchange.

+ +

When the Program is made available in source +code form:

+ +

a) +it must be made available under this Agreement; and

+ +

b) a +copy of this Agreement must be included with each copy of the Program.

+ +

Contributors may not remove or alter any +copyright notices contained within the Program.

+ +

Each Contributor must identify itself as the +originator of its Contribution, if any, in a manner that reasonably allows +subsequent Recipients to identify the originator of the Contribution.

+ +

4. COMMERCIAL DISTRIBUTION

+ +

Commercial distributors of software may +accept certain responsibilities with respect to end users, business partners +and the like. While this license is intended to facilitate the commercial use +of the Program, the Contributor who includes the Program in a commercial +product offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes the +Program in a commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages and +costs (collectively "Losses") arising from claims, lawsuits and other +legal actions brought by a third party against the Indemnified Contributor to +the extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor +to control, and cooperate with the Commercial Contributor in, the defense and +any related settlement negotiations. The Indemnified Contributor may participate +in any such claim at its own expense.

+ +

For example, a Contributor might include the +Program in a commercial product offering, Product X. That Contributor is then a +Commercial Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance claims and +warranties are such Commercial Contributor's responsibility alone. Under this +section, the Commercial Contributor would have to defend claims against the +other Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages.

+ +

5. NO WARRANTY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS +AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, +WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely +responsible for determining the appropriateness of using and distributing the +Program and assumes all risks associated with its exercise of rights under this +Agreement , including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs or +equipment, and unavailability or interruption of operations.

+ +

6. DISCLAIMER OF LIABILITY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS +AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF +THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES.

+ +

7. GENERAL

+ +

If any provision of this Agreement is invalid +or unenforceable under applicable law, it shall not affect the validity or +enforceability of the remainder of the terms of this Agreement, and without +further action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable.

+ +

If Recipient institutes patent litigation +against any entity (including a cross-claim or counterclaim in a lawsuit) +alleging that the Program itself (excluding combinations of the Program with +other software or hardware) infringes such Recipient's patent(s), then such +Recipient's rights granted under Section 2(b) shall terminate as of the date +such litigation is filed.

+ +

All Recipient's rights under this Agreement +shall terminate if it fails to comply with any of the material terms or +conditions of this Agreement and does not cure such failure in a reasonable +period of time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use and +distribution of the Program as soon as reasonably practicable. However, +Recipient's obligations under this Agreement and any licenses granted by +Recipient relating to the Program shall continue and survive.

+ +

Everyone is permitted to copy and distribute +copies of this Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The Agreement +Steward reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement Steward has +the right to modify this Agreement. The Eclipse Foundation is the initial +Agreement Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each new version +of the Agreement will be given a distinguishing version number. The Program +(including Contributions) may always be distributed subject to the version of +the Agreement under which it was received. In addition, after a new version of +the Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly stated +in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to +the intellectual property of any Contributor under this Agreement, whether +expressly, by implication, estoppel or otherwise. All rights in the Program not +expressly granted under this Agreement are reserved.

+ +

This Agreement is governed by the laws of the +State of New York and the intellectual property laws of the United States of +America. No party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each party waives +its rights to a jury trial in any resulting litigation.

+ +

 

+ +
+ + + + diff --git a/xCAT-SoftLayer/bin/getslnodes b/xCAT-SoftLayer/bin/getslnodes new file mode 100755 index 000000000..ae02b6642 --- /dev/null +++ b/xCAT-SoftLayer/bin/getslnodes @@ -0,0 +1,120 @@ +#!/usr/bin/perl + +# Query the softlayer account for info about all of the bare metal servers and +# put the info in mkdef stanza format, so the node can be defined in the xcat db +# so that xcat can manage/deploy them. + +use strict; +use Getopt::Long; +use Data::Dumper; +#$Data::Dumper::Maxdepth=2; + +# Globals - these are set once and then only read. +my $HELP; +my $VERBOSE; +my %CONFIG; # attributes read from config file + +my $usage = sub { + my $exitcode = shift @_; + print "Usage: getslnodes [-?|-h|--help] [-v|--verbose] []\n\n"; + if (!$exitcode) { + print "getslnodes queries your SoftLayer account and gets attributes for each\n"; + print "server. The attributes can be piped to 'mkdef -z' to define the nodes\n"; + print "in the xCAT DB so that xCAT can manage them. getslnodes\n"; + print "requires a .slconfig file in your home directory that contains your\n"; + print "SoftLayer userid, API key, and location of API perl module, in attr=val format.\n"; + } + exit $exitcode; +}; + +# Process the cmd line args +Getopt::Long::Configure("bundling"); +#Getopt::Long::Configure("pass_through"); +Getopt::Long::Configure("no_pass_through"); +if (!GetOptions('h|?|help' => \$HELP, 'v|verbose' => \$VERBOSE)) { $usage->(1); } + +if ($HELP) { $usage->(0); } +if (scalar(@ARGV)>1) { $usage->(1); } +my $hnmatch = $ARGV[0]; # if they specified a hostname match, only show svrs that start with that + +readconf("$ENV{HOME}/.slconfig"); # get the userid and api key from the config file +#my $api_username = 'SL276540'; +#my $api_key = '799d5d9267a927a330ec016f00bfe17e6fc532d203cf68b3b0d997b2d27a3ce1'; + +my $slinstalled = eval { push @INC, $CONFIG{apidir}; require SoftLayer::API::SOAP; }; +if (!$slinstalled) { die "Error: the SoftLayer::API::SOAP perl module is not installed. Download it using 'git clone https://github.com/softlayer/softlayer-api-perl-client' and put the directory in ~/.slconfig ."; } + +my $client = SoftLayer::API::SOAP->new('SoftLayer_Account', undef, $CONFIG{userid}, $CONFIG{apikey}); + +my $mask = "mask[operatingSystem.passwords,remoteManagementAccounts,remoteManagementComponent,backendNetworkComponents]"; +$client->setObjectMask($mask); + +#print $client->fault; +#print $client->faultstring; +#print "\n"; + +my $hw = $client->getHardware(); +my $servers = $hw->result; +foreach my $server (@$servers) { + if ($server->{fullyQualifiedDomainName} =~ m/$hnmatch/) { + print "\n".$server->{hostname}.":\n"; + print "\tobjtype=node\n"; + print "\tgroups=slnode,ipmi,all\n"; + print "\tmgt=ipmi\n"; + print "\tbmc=".$server->{remoteManagementComponent}->{ipmiIpAddress}."\n"; + print "\tbmcusername=".$server->{remoteManagementAccounts}->[0]->{username}."\n"; + print "\tbmcpassword=".$server->{remoteManagementAccounts}->[0]->{password}."\n"; + print "\tmac=".$server->{backendNetworkComponents}->[0]->{macAddress}."\n"; + print "\tip=".$server->{privateIpAddress}."\n"; + print "\tnetboot=xnba\n"; + print "\tarch=x86_64\n"; + print "\tusercomment=hostname:".$server->{fullyQualifiedDomainName}.", user:".$server->{operatingSystem}->{passwords}->[0]->{username}.", pw:".$server->{operatingSystem}->{passwords}->[0]->{password}."\n"; + + #print Dumper($server->{remoteManagementAccounts}); + #print "#Softlayer_account_info_for ".$server->{fullyQualifiedDomainName} . " Username: "; + #print $server->{operatingSystem}->{passwords}->[0]->{username} . " Password: "; + #print $server->{operatingSystem}->{passwords}->[0]->{password}. "\n"; + #print "nodeadd ".$server->{hostname}." groups=saptest ipmi.password=".$server->{remoteManagementAccounts}->[0]->{password}." ipmi.bmc=".$server->{remoteManagementComponent}->{ipmiIpAddress}; + #print " mac.mac=".$server->{backendNetworkComponents}->[0]->{macAddress}; + #print " hosts.ip=".$server->{privateIpAddress} ."\n"; + } +} +exit(0); + + +# Pring msg only if -v was specified +sub verbose { if ($VERBOSE) { print shift, "\n"; } } + + +# Read the config file. Format is attr=val on each line. Should contain at leas the userid and apikey. +# This function fills in the global %CONFIG hash. +sub readconf { + my $conffile = shift @_; + open(FILE, $conffile) || die "Error: can not open config file $conffile: $!\n"; + while () { + my $line = $_; + chomp($line); + if ($line =~ /^#/ || $line =~/^\s*$/) { next; } # skip comment lines + my ($key, $value) = split(/\s*=\s*/, $line, 2); + if (!defined($value)) { die "Error: line '$line' does not have format attribute=value\n"; } + $CONFIG{$key} = $value; + } + close FILE; + verbose('%CONFIG hash: ' . Dumper(\%CONFIG)); + + # the config file needs to contain at least the userid and api key + if (!defined($CONFIG{userid}) || !defined($CONFIG{apikey}) || !defined($CONFIG{apidir})) { + die "Error: the config file must contain values for userid, apikey, and apidir.\n"; + } +} + +#$mask = "mask[operatingSystem.passwords]"; +#$client->setObjectMask($mask); +#my $vs = $client->getVirtualGuests(); +#my $servers = $vs->result; +#foreach my $server (@$servers) { +# if ($server->{fullyQualifiedDomainName} eq "xcat1-sap.saptest.ibm.com") { +# print $server->{primaryIpAddress}."\n"; +# print $server->{operatingSystem}->{passwords}->[0]->{password}."\n"; +# } +#} diff --git a/xCAT-SoftLayer/bin/modifygrub b/xCAT-SoftLayer/bin/modifygrub new file mode 100755 index 000000000..a6d28407f --- /dev/null +++ b/xCAT-SoftLayer/bin/modifygrub @@ -0,0 +1,264 @@ +#!/usr/bin/perl + +# Modify the grub config file on the node to boot the specified kernel and initrd. +# This script is meant to be run on the node via xdsh -e. +# Currently requires that dns on the mn be configured and working to resolve the short node names. + +use strict; +use Getopt::Long; +use Data::Dumper; +use Socket; + +# Globals - these are set once and then only read. +my $HELP; +my $VERBOSE; +my $WAITTIME; +my $XCATNETBOOTTITLE = 'xCAT network boot kernel and initrd'; + +my $usage = sub { + my $exitcode = shift @_; + print "Usage: modifygrub [-?|-h|--help] [-v|--verbose] [-w ] \n\n"; + if (!$exitcode) { + print "Modify the grub config file on the node to boot the specified kernel and initrd.\n"; + } + exit $exitcode; +}; + +if (-f '/etc/os-release') { die "This script doesn't support ubuntu yet.\n"; } + +# Process the cmd line args +Getopt::Long::Configure("bundling"); +#Getopt::Long::Configure("pass_through"); +Getopt::Long::Configure("no_pass_through"); +if (!GetOptions('h|?|help' => \$HELP, 'v|verbose' => \$VERBOSE, 'w|waittime=s' => \$WAITTIME)) { $usage->(1); } + +if ($HELP) { $usage->(0); } +if (scalar(@ARGV) != 4) { $usage->(1); } +if (!defined($WAITTIME)) { $WAITTIME = 60; } # seconds to wait after configuring the nic (to let the switch handle the state change) +my %args; +$args{kernelpath} = $ARGV[0]; +$args{initrdpath} = $ARGV[1]; +$args{kernelparms} = $ARGV[2]; +$args{mnip} = $ARGV[3]; + +addKernelParms(\%args); # replace and add some parms to args{kernelparms} +updateGrub(\%args); # update the grub config with an entry filled with the info in args + +exit(0); + + +# Add ip and net info to the kernel parms. Modifies the kernelparms value of the args hash passed in. +sub addKernelParms { + my $args = shift @_; + + # replace '!myipfn!' with the mn ip + my $mnip = $args->{mnip}; + $args->{kernelparms} =~ s/!myipfn!/$mnip/g; + + # replace with the nodename + my $nodename = $ENV{NODE}; # this env var is set by xdsh + $args->{kernelparms} =~ s//$nodename/g; + + # get node ip and add it to the kernel parms + my ($nic, $ip, $netmask, $gateway) = getNodeIpInfo($args); + if (!$ip) { die "Error: could not find the NIC that would connect to the xCAT mgmt node's IP (".$args->{mnip}.").\n"; } + $args->{kernelparms} .= " hostip=$ip netmask=$netmask gateway=$gateway dns=$mnip hostname=$nodename netdevice=$nic netwait=$WAITTIME textmode=1"; +} + + +# get this nodes nic, ip, netmask, and gateway. Returns them in a 4 element array. +sub getNodeIpInfo { + my $args = shift @_; + my ($ipprefix) = $args->{mnip}=~m/^(\d+\.\d+)\./; #todo: this is a hack, just using the 1st 2 octets of the mn ip addr + verbose("using IP prefix $ipprefix"); + + # parse ip addr show output, looking for ipprefix, to determine nic and ip + my @output = runcmd("ip addr show"); + my ($nic, $ipandmask); + foreach my $line (@output) { + my ($nictmp, $iptmp); + if (($nictmp) = $line=~m/^\d+:\s+(\S+): /) { $nic = $nictmp; } # new stanza, remember it + if (($iptmp) = $line=~m/^\s+inet\s+($ipprefix\S+) /) { $ipandmask = $iptmp; last; } # got ip, we are done + } + my ($ip, $netmask) = convertIpAndMask($ipandmask); + + # if the nic is a bonded nic (common on sl), then find the 1st real nic that is part of it + my $realnic = $nic; + if ($nic =~ /^bond/) { + my @nics = grep(m/\s+master\s+$nic\s+/, @output); + if (!scalar(@nics)) { die "Error: can't find the NICs that are part of $nic.\n"; } + ($realnic) = $nics[0]=~m/^\d+:\s+(\S+): /; + } + + # finally, find the gateway + my $gateway; + my @output = runcmd("ip route"); + # we are looking for a line like: 10.0.0.0/8 via 10.54.51.1 dev bond0 + my @networks = grep(m/ via .* $nic\s*$/, @output); + if (scalar(@networks)) { ($gateway) = $networks[0]=~m/ via\s+(\S+)/; } + else { + # use the mn ip as a fall back + $gateway = $args->{mnip}; + verbose("using xCAT mgmt node IP as the fall back gateway."); + } + + verbose("IP info: realnic=$realnic, ip=$ip, netmask=$netmask, gateway=$gateway"); + return ($realnic, $ip, $netmask, $gateway); +} + + +# Convert an ip/mask in slash notation (like 10.0.0.1/26) to separate ip and netmask like 10.0.0.1 and 255.255.255.192 +sub convertIpAndMask { + my $ipandmask = shift @_; + my ($ip, $masknum) = split('/', $ipandmask); + my $netbin = oct("0b" . '1' x $masknum . '0' x (32-$masknum)); # create a str like '1111100', then convert to binary + my @netarr=unpack('C4',pack('N',$netbin)); # separate into the 4 octets + my $netmask=join('.',@netarr); # put them together into the normal looking netmask + return ($ip, $netmask); +} + + +# not used - resolve the hostname to an ip addr +sub getipaddr { + my $hostname = shift @_; + my $packed_ip; + $packed_ip = inet_aton($hostname); + if (!$packed_ip) { return undef; } + return inet_ntoa($packed_ip); +} + + +# Update the grub config file with a new stanza for booting our kernel and initrd +sub updateGrub { + my $args = shift @_; + + # how we specify the path for the kernel and initrd is different on redhat and suse + my $fileprefix; + if (isRedhat()) { $fileprefix = '/'; } + elsif (isSuse()) { $fileprefix = '/boot/'; } + else { die "Error: currently only support red hat or suse distros.\n"; } + + # open the grub file and see if it is in there or if we have to add it + my $grubfile = findGrubPath(); + verbose("reading $grubfile"); + open(FILE, $grubfile) || die "Error: can not open config file $grubfile for reading: $!\n"; + my @lines = ; + close FILE; + + # this is the entry we want in the grub file + my @rootlines = grep(/^\s+root\s+/, @lines); # copy one of the existing root lines + if (!scalar(@rootlines)) { die "Error: can't find an existing line for 'root' in the grub config file\n"; } + my ($rootline) = $rootlines[0] =~ m/^\s*(.*?)\s*$/; + my @entry = ( + "title $XCATNETBOOTTITLE\n", + "\t$rootline\n", + "\tkernel " . $fileprefix . $args->{kernelpath} . ' ' . $args->{kernelparms} . "\n", + "\tinitrd " . $fileprefix . $args->{initrdpath} . "\n", + ); + + my $needtowritefile = 1; + if (grep(/^title\s+$XCATNETBOOTTITLE/, @lines)) { $needtowritefile = updateGrubEntry(\@lines, \@entry); } # there is already an entry in there + else { addGrubEntry (\@lines, \@entry); } + + # write the file with the new/updated xcat entry + if ($needtowritefile) { + verbose("updating $grubfile"); + open(FILE, '>', $grubfile) || die "Error: can not open config file $grubfile for writing: $!\n"; + print FILE @lines; + close FILE; + } + else { print "Info: $grubfile did not need modifying. It was already up to date.\n"; } +} + + +# add our entry as the 1st one in the grub file +sub addGrubEntry { + my ($lines, $entry) = @_; + # find the index of the 1st stanza (it starts with 'title') + my $i; + for ($i=0; $i[$i] =~ m/^title\s+/) { verbose('adding xcat entry before:'.$lines->[$i]); last; } # found it + } + + # splice the entry right before the i-th line (which may also be 1 past the end) + splice(@$lines, $i, 0, @$entry); +} + + +# check the xcat entry in the grub file and see if it needs to be updated. Return 1 if it does. +sub updateGrubEntry { + my ($lines, $entry) = @_; + #print Dumper($lines), Dumper($entry); + # find the index of the xcat stanza + my $i; + for ($i=0; $i[$i] =~ m/^title\s+$XCATNETBOOTTITLE/) { last; } # found it + } + + # compare the next few lines with the corresponding line in @$entries and replace if different + my $replaced = 0; + for (my $j=0; $j[$i+$j], "\n ", $entry->[$j], "\n"; + if ($lines->[$i+$j] ne $entry->[$j]) { # this line was different + $lines->[$i+$j] = $entry->[$j]; + $replaced = 1; + } + } + + return $replaced; +} + + +# depending on the distro, find the correct grub file and return its path +sub findGrubPath { + # for rhel/centos it is /boot/grub/grub.conf, for sles it is /boot/grub/menu.lst + my @paths = qw(/boot/grub/grub.conf /boot/grub/menu.lst); + foreach my $p (@paths) { + if (-f $p) { return $p; } + } + + die "Error: Can't find grub config file.\n"; + + #todo: support ubuntu: you add an executable file in /etc/grub.d named 06_xcatnetboot that prints out the + # entry to add. Then run grub-mkconfig. +} + + +# Pring msg only if -v was specified +sub verbose { if ($VERBOSE) { print shift, "\n"; } } + +# Check the distro we are running on +sub isSuse { return (-e '/etc/SuSE-release'); } +sub isRedhat { return (-e '/etc/redhat-release' || -e '/etc/centos-release' || -e '/etc/fedora-release'); } # add chk for fedora + + + +# Run a command. If called in the context of return an array, it will capture the output +# of the cmd and return it. Otherwise, it will display the output to stdout. +# If the cmd has a non-zero rc, this function will die with a msg. +sub runcmd +{ + my ($cmd) = @_; + my $rc; + + $cmd .= ' 2>&1' ; + verbose($cmd); + + my @output; + if (wantarray) { + @output = `$cmd`; + $rc = $?; + } + else { + system($cmd); + $rc = $?; + } + + if ($rc) { + $rc = $rc >> 8; + if ($rc > 0) { die "Error: rc $rc return from cmd: $cmd\n"; } + else { die "Error: system error returned from cmd: $cmd\n"; } + } + elsif (wantarray) { return @output; } +} + diff --git a/xCAT-SoftLayer/bin/pushinitrd b/xCAT-SoftLayer/bin/pushinitrd new file mode 100755 index 000000000..7e3cd5a7e --- /dev/null +++ b/xCAT-SoftLayer/bin/pushinitrd @@ -0,0 +1,236 @@ +#!/usr/bin/perl + +# Copy the initrd, kernel, params, and static IP info to nodes, so they can net install +# even across vlans (w/o setting up pxe/dhcp broadcast relay). This assumes a working +# OS is on the node. This script is primarily meant to be used in the softlayer environment. + +#todo: site attr for using static ip? + +use strict; +use Getopt::Long; +use Data::Dumper; + +# Globals - these are set once and then only read. +my $HELP; +my $VERBOSE; +my $WAITTIME; +my $NOAUTOINST; + +my $usage = sub { + my $exitcode = shift @_; + print "Usage: pushinitrd [-?|-h|--help] [-v|--verbose] [-w ] \n\n"; + if (!$exitcode) { + print "Copy the initrd, kernel, params, and static IP info to nodes, so they can net install\n"; + print "even across vlans (w/o setting up pxe/dhcp broadcast relay). This assumes a working\n"; + print "OS is on the node, that you've run nodeset for these nodes, and that all of the nodes\n"; + print "are using the same osimage.\n"; + } + exit $exitcode; +}; + +# Process the cmd line args +Getopt::Long::Configure("bundling"); +#Getopt::Long::Configure("pass_through"); +Getopt::Long::Configure("no_pass_through"); +if (!GetOptions('h|?|help' => \$HELP, 'v|verbose' => \$VERBOSE, 'w|waittime=s' => \$WAITTIME, 'a|noautoinst' => \$NOAUTOINST)) { $usage->(1); } + +if ($HELP) { $usage->(0); } +if (scalar(@ARGV) != 1) { $usage->(1); } +if (!defined($WAITTIME)) { $WAITTIME = 75; } # seconds to wait after configuring the nic (to let the switch handle the state change) +my $noderange = $ARGV[0]; + +my %bootparms = getBootParms($noderange); + +copyFilesToNodes($noderange, \%bootparms); + +updateGrubOnNodes($noderange, \%bootparms); + +if (!$NOAUTOINST) { modifyAutoinstFiles($noderange, \%bootparms); } + +exit(0); + + +# Query the db for the kernel, initrd, and kcmdline attributes of the 1st node in the noderange +sub getBootParms { + my $nr = shift @_; + my %bootparms; + my @output = runcmd("nodels $nr bootparams.kernel bootparams.initrd bootparams.kcmdline"); + + # the attributes can be displayed in a different order than requested, so need to grep for them + my @gresults; + foreach my $a (qw(kernel initrd kcmdline)) { + my $attr = "bootparams.$a"; + @gresults = grep(/^\S+:\s+$attr:/, @output); + if (!scalar(@gresults)) { die "Error: attribute $attr not defined for the noderange. Did you run 'nodeset osimage=' ?\n"; } + # for now just pick the 1st one. They should all be the same, except for the node name in kcmdline + chomp($gresults[0]); + $gresults[0] =~ s/^\S+:\s+$attr:\s*//; + $bootparms{$a} = $gresults[0]; + if ($a eq 'kcmdline') { $bootparms{$a} =~ s|/install/autoinst/\S+|/install/autoinst/|; } + } + + # get the mgmt node cluster-facing ip addr + @output = runcmd('lsdef -t site -i master -c'); + chomp($output[0]); + my ($junk, $ip) = split(/=/, $output[0]); + $bootparms{mnip} = $ip; + + verbose(Dumper(\%bootparms)); + return %bootparms; +} + + +# Copy the kernel and initrd to the nodes +# Args: noderange, reference to the bootparms hash +sub copyFilesToNodes { + my $nr = shift @_; + my $bootparms = shift @_; + foreach my $a (qw(kernel initrd)) { + my $file = $bootparms->{$a}; + my $localfile = "/tftpboot/$file"; + # for the + my $remotefile = '/boot/' . remoteFilename($file); + print "Copying $localfile to $nr:$remotefile\n"; + runcmd("xdcp $nr -p $localfile $remotefile"); + } +} + + +# Form the remote file name, using the last 2 parts of the path, separated by "-" +sub remoteFilename { + my $f = shift @_; + $f =~ s|^.*/([^/]+)/([^/]+)$|$1-$2|; + return $f; +} + + +# Run the modifygrub script on the nodes to update the grub config file +# Args: noderange, reference to the bootparms hash +sub updateGrubOnNodes { + my $nr = shift @_; + my $bootparms = shift @_; + my $vtxt = ($VERBOSE ? '-v' : ''); + my @output = runcmd('which modifygrub'); + my $modifygrub = $output[0]; + chomp($modifygrub); + my $cmd = "xdsh $nr -e $modifygrub $vtxt -w $WAITTIME " . remoteFilename($bootparms->{kernel}) . ' ' . remoteFilename($bootparms->{initrd}) . ' '; + # we need to quote the kernel parms, both here when passing it to xdsh, and on the node + # when xdsh is passing it to modifygrub. The way to get single quotes inside single quotes + # is to quote each of the outer single quotes with double quotes. + $cmd .= q("'"') . $bootparms->{kcmdline} . q('"'"); + $cmd .= ' ' . $bootparms->{mnip}; + print "Running modifygrub on $nr to update the grub configuration.\n"; + runcmd($cmd); +} + + +# Hack the autoinst files to wait in a key spot to make them work even tho it takes +# the NICs almost a min before they can transmit after a state change. +#todo: this has only been tested with SLES nodes +sub modifyAutoinstFiles { + my $nr = shift @_; + my $bootparms = shift @_; + + # expand the noderange into a list of nodes + my @nodes = runcmd("nodels $nr"); + chomp(@nodes); + + # Edit each file to have chroot.sles insert a wait at the end of /etc/init.d/network + # this finds the end of boot.sh script (which is chroot.sles) + my $search = '\n\]\]>\s*\s*\s*'; + my $file = '/mnt/etc/init.d/network'; # at this point in the installation, the permanent file system is just mounted + #my $waitstring = 'echo Sleeping for 55s;sleep 55'; + # this is the string to insert in the nodes /etc/init.d/network script. It is a while loop pinging the mn, but some of the chars need to be escape for sed + my $waitstring = 'echo Waiting to reach xCAT mgmt node...;while \[ \$\(\(xcati+=1\)\) -le 60 \] \&\& ! ping -c2 -w3 ' . $bootparms->{mnip} .'; do echo i=\$xcati ; done; sleep 10'; + # this crazy sed string is from google. It gathers up the whole file into the hold buffer, and then the substitution is done on the whole file + my $sedstring = q|sed -n '1h;1!H;${;g;s/\(\t\treload_firewall\n\)\n/\1\t\t| . $waitstring . q(\n\n/g;p;}') . " $file > $file.new"; + # finally create the perl replace string that will be used to modify the autoinst file + my $replace = "$sedstring\nchmod 755 $file.new; mv -f $file.new $file"; + + # now actually update the file + print "Updating /install/autoinst files.\n"; + foreach my $n (@nodes) { + my $f = "/install/autoinst/$n"; + my $matches = sed($f, $search, $replace, mode=>'insertbefore'); + if (!$matches) { die "Error: could not find the right place in $f to insert the sed of the network wait.\n"; } + } +} + + +# this is like multi-line sed replace function +# Args: filename, search-string, replace-string +sub sed { + my ($file, $search, $replace, %options) = @_; + #my $opts = 's'; + #if ($options{global}) { $opts .= 'g'; } + + # open the file for reading + verbose("reading $file"); + open(FILE, $file) || die "Error: can not open file $file for reading: $!\n"; + my $lines; + while () { $lines .= $_; } + #verbose('file length is '.length($lines)); + close FILE; + + # we also need to look for this string 1st + my $replacecopy = $replace; # a search string can't have special chars in it + $replacecopy =~ s/(\W)/\\$1/g; # so escape all of the meta characters + #print "replacecopy=$replacecopy\n"; + # check to see if the replace string is already in the file + if ($lines =~ m/$replacecopy/s) { + print "$file did not need updating.\n"; + return 1; + } + + # search/replace and see if there were any matches + my $matches; + if ($options{mode} eq 'insertbefore') { $matches = $lines =~ s/($search)/\n$replace\n$1/s; } + elsif ($options{mode} eq 'insertafter') { $matches = $lines =~ s/($search)/$1\n$replace\n/s; } + elsif ($options{mode} eq 'replace') { $matches = $lines =~ s/$search/$replace/s; } + else { die "Internal error: don't suppor sed mode of $options{mode}.\n"; } + + + # write file if necessary + if ($matches) { + verbose("updating $file"); + open(FILE, '>', $file) || die "Error: can not open file $file for writing: $!\n"; + print FILE $lines; + close FILE; + } + return $matches; +} + + +# Pring msg only if -v was specified +sub verbose { if ($VERBOSE) { print shift, "\n"; } } + + + +# Run a command. If called in the context of return an array, it will capture the output +# of the cmd and return it. Otherwise, it will display the output to stdout. +# If the cmd has a non-zero rc, this function will die with a msg. +sub runcmd +{ + my ($cmd) = @_; + my $rc; + + $cmd .= ' 2>&1' ; + verbose($cmd); + + my @output; + if (wantarray) { + @output = `$cmd`; + $rc = $?; + } + else { + system($cmd); + $rc = $?; + } + + if ($rc) { + $rc = $rc >> 8; + if ($rc > 0) { die "Error: rc $rc return from cmd: $cmd\n"; } + else { die "Error: system error returned from cmd: $cmd\n"; } + } + elsif (wantarray) { return @output; } +} diff --git a/xCAT-SoftLayer/pods/man1/getslnodes.1.pod b/xCAT-SoftLayer/pods/man1/getslnodes.1.pod new file mode 100644 index 000000000..d9e3bbb1c --- /dev/null +++ b/xCAT-SoftLayer/pods/man1/getslnodes.1.pod @@ -0,0 +1,84 @@ +=head1 NAME + +B - queries your SoftLayer account and gets attributes for each server. + +=head1 SYNOPSIS + +B [B<-v>|B<--verbose>] [I] + +B [B<-?> | B<-h> | B<--help>] + +=head1 DESCRIPTION + +The B command queries your SoftLayer account and gets attributes for each +server. The attributes can be piped to 'mkdef -z' to define the nodes +in the xCAT DB so that xCAT can manage them. + +Before using this command, you must download and install the SoftLayer API perl module. +For example: + + cd /usr/local/lib + git clone https://github.com/softlayer/softlayer-api-perl-client.git + +You also need to follow these directions to get your SoftLayer API key: http://knowledgelayer.softlayer.com/procedure/retrieve-your-api-key + +B requires a .slconfig file in your home directory that contains your +SoftLayer userid, API key, and location of the SoftLayer API perl module, in attr=val format. +For example: + + # Config file used by the xcat cmd getslnodes + userid = joe_smith + apikey = 1234567890abcdef1234567890abcdef1234567890abcdef + apidir = /usr/local/lib/softlayer-api-perl-client + +=head1 OPTIONS + +=over 10 + +=item B<-?|-h|--help> + +Display usage message. + +=item B<-v|--version> + +Command Version. + +=back + +=head1 RETURN VALUE + +0 The command completed successfully. + +1 An error has occurred. + +=head1 EXAMPLES + +=over 3 + +=item 1. + +Display information about all of the nodes in your SoftLayer account: + + getslnodes + +=item 2. + +Display information about all of the nodes whose hostname starts with foo: + + getslnodes foo + +=item 3. + +Create xCAT node defintions in the xCAT DB for all of the nodes in your SoftLayer account: + + getslnodes | mkdef -z + +=back + +=head1 FILES + +/opt/xcat/bin/getslnodes + +=head1 SEE ALSO + +L diff --git a/xCAT-SoftLayer/pods/man1/pushinitrd.1.pod b/xCAT-SoftLayer/pods/man1/pushinitrd.1.pod new file mode 100644 index 000000000..45c6e0168 --- /dev/null +++ b/xCAT-SoftLayer/pods/man1/pushinitrd.1.pod @@ -0,0 +1,66 @@ +=head1 NAME + +B - queries your SoftLayer account and gets attributes for each server. + +=head1 SYNOPSIS + +B [B<-v>|B<--verbose>] [B<-w> I] [I] + +B [B<-?> | B<-h> | B<--help>] + +=head1 DESCRIPTION + +The B command copies the initrd, kernel, params, and static IP info to nodes, so they can be net installed +even across vlans (w/o setting up pxe/dhcp broadcast relay). This assumes a working +OS is on the nodes. Before running this command, you must run nodeset for these nodes. +All of the nodes given to one invocation of B must be using the same osimage. + +Before using this command, if will be most convenient if you exchange the ssh keys using: + + xdsh -K + +=head1 OPTIONS + +=over 10 + +=item B<-w> I + +The number of seconds the initrd should wait before trying to communicate over the network. +The default is 75. This translates into the netwait kernel parameter and is usually needed +in a SoftLayer environment because it can take a while for a NIC to be active after changing state. + +=item B<-?|-h|--help> + +Display usage message. + +=item B<-v|--version> + +Command Version. + +=back + +=head1 RETURN VALUE + +0 The command completed successfully. + +1 An error has occurred. + +=head1 EXAMPLES + +=over 3 + +=item 1. + +Configure nodes for net installing in a SoftLayer environment: + + pushinitrd + +=back + +=head1 FILES + +/opt/xcat/bin/pushinitrd + +=head1 SEE ALSO + +L diff --git a/xCAT-SoftLayer/postscripts/setdefaultroute b/xCAT-SoftLayer/postscripts/setdefaultroute new file mode 100755 index 000000000..6932b0d79 --- /dev/null +++ b/xCAT-SoftLayer/postscripts/setdefaultroute @@ -0,0 +1,6 @@ +#!/bin/bash + +# set the default route of the node to the ip address and nic passed in + +set -x +ip route replace to default via $1 dev $2 diff --git a/xCAT-SoftLayer/share/xcat/install/scripts/post.sles.softlayer.common b/xCAT-SoftLayer/share/xcat/install/scripts/post.sles.softlayer.common new file mode 100644 index 000000000..ded409aac --- /dev/null +++ b/xCAT-SoftLayer/share/xcat/install/scripts/post.sles.softlayer.common @@ -0,0 +1,20 @@ +#!/bin/sh + +# This is modified from the standard xcat post.sles.common in that it does not set up +# the ifcfg-eth0 file to do dhcp and it does not restart the network. It just leaves +# ifcfg-eth0 the way autoyast configured it, assuming we set it statically. + +# save what autoyast set network config to, to help with debugging +cp /etc/sysconfig/network/ifcfg-eth0 /tmp/ifcfg-eth0.orig +cp /etc/hosts /tmp/hosts.orig +cp /etc/resolv.conf /tmp/resolv.conf.orig +cp /etc/HOSTNAME /tmp/HOSTNAME.orig + +#cd /etc/sysconfig/network +perl -pi -e 's/^FIREWALL="yes"/FIREWALL="no"/' /etc/sysconfig/network/config + +# autoyast already set hostname correctly + +HOSTNAME=$(hostname -s) +echo $HOSTNAME + diff --git a/xCAT-SoftLayer/share/xcat/install/sles/compute.sles11.softlayer.tmpl b/xCAT-SoftLayer/share/xcat/install/sles/compute.sles11.softlayer.tmpl new file mode 100644 index 000000000..96bf8ed28 --- /dev/null +++ b/xCAT-SoftLayer/share/xcat/install/sles/compute.sles11.softlayer.tmpl @@ -0,0 +1,105 @@ + + + + + + + true + true + + false + false + mbr + + + + GMT + #TABLE:site:key=timezone:value# + + + english-us + + en_US + + false + false + false + true + + + non + + + true + true + true + + + + + + + XCATPARTITIONHOOK + true + all + + + + + + #INCLUDE_DEFAULT_PTRNLIST_S# + + + #INCLUDE_DEFAULT_PKGLIST_S# + + + + + + + root + #CRYPT:passwd:key=system,username=root:password# + true + + + + + + true + + #TABLE:site:key=domain:value# + #TABLE:nodelist:$NODE:node# + + #XCATVAR:XCATMASTER# + + + #TABLE:site:key=domain:value# + + + + false + + + + #INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/pre.sles# + #INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/chroot.sles# + + + + + + diff --git a/xCAT-SoftLayer/xCAT-SoftLayer.spec b/xCAT-SoftLayer/xCAT-SoftLayer.spec new file mode 100644 index 000000000..df514ddfb --- /dev/null +++ b/xCAT-SoftLayer/xCAT-SoftLayer.spec @@ -0,0 +1,74 @@ +Summary: Utilities to make xCAT work in a SoftLayer environment +Name: xCAT-SoftLayer +Version: %(cat Version) +Release: snap%(date +"%Y%m%d%H%M") +Epoch: 4 +License: EPL +Group: Applications/System +Source: xCAT-SoftLayer-%(cat Version).tar.gz +Packager: IBM Corp. +Vendor: IBM Corp. +Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}} +Prefix: /opt/xcat +BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root +%ifos linux +BuildArch: noarch +%endif +Requires: xCAT-server +#Requires: xCAT-server >= %{epoch}:%(cat Version|cut -d. -f 1,2) + +Provides: xCAT-SoftLayer = %{epoch}:%{version} + +%description +xCAT-SoftLayer provides Utilities to make xCAT work in a SoftLayer environment. This package should be installed on your management server + +# %define VERBOSE %(if [ "$VERBOSE" = "1" -o "$VERBOSE" = "yes" ];then echo 1; else echo 0; fi) +# %define NOVERBOSE %(if [ "$VERBOSE" = "1" -o "$VERBOSE" = "yes" ];then echo 0; else echo 1; fi) +# %define NOVERBOSE %{?VERBOSE:1}%{!?VERBOSE:0} + +%prep +# %if %NOVERBOSE +# echo NOVERBOSE is on +# set +x +# %elseif +# set -x +# %endif + +%setup -q -n xCAT-SoftLayer +%build +# Convert pods to man pages and html pages +./xpod2man + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/install +mkdir -p $RPM_BUILD_ROOT/install/postscripts +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/packages/xCAT-SoftLayer +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1 +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 + +cp -p -R share/xcat/install/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/install/ + +cp -d bin/* $RPM_BUILD_ROOT/%{prefix}/bin +chmod 755 $RPM_BUILD_ROOT/%{prefix}/bin/* + +cp -d postscripts/* $RPM_BUILD_ROOT/install/postscripts +chmod 755 $RPM_BUILD_ROOT/install/postscripts/* + +cp LICENSE.html $RPM_BUILD_ROOT/%{prefix}/share/doc/packages/xCAT-SoftLayer +chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/packages/xCAT-SoftLayer/* + +cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1 +chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/* +cp share/doc/man1/* $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 +chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/man1/* + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +#%doc LICENSE.html +%{prefix} +/install/postscripts diff --git a/xCAT-SoftLayer/xpod2man b/xCAT-SoftLayer/xpod2man new file mode 100755 index 000000000..c885505bd --- /dev/null +++ b/xCAT-SoftLayer/xpod2man @@ -0,0 +1,214 @@ +#!/usr/bin/perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# First builds the xCAT summary man page from Synopsis of each man page. +# Then converts all of the pod man pages into html (including links to each other) + +# We assume that this script is run in the xCAT-vlan-2.0 dir, so everything is +# done relative to that. + +use strict; +#use lib '.'; +use Pod::Man; +use Pod::Html; + +my $poddir = 'pods'; +my $mandir = 'share/man'; +my $htmldir = 'share/doc'; +my $cachedir = '/tmp'; + +my @pods = getPodList($poddir); +#foreach (@pods) { print "$_\n"; } exit; + +# Build the cmd overview page. +#writesummarypage("$poddir/man1/xcat.1.pod", @pods); + +# Build the man page for each pod. +#mkdir($mandir) or die "Error: could not create $mandir.\n"; +print "Converting PODs to man pages...\n"; +foreach my $podfile (@pods) { + my $manfile = $podfile; + $manfile =~ s/^$poddir/$mandir/; # change the beginning of the path + $manfile =~ s/\.pod$//; # change the ending + my $mdir = $manfile; + $mdir =~ s|/[^/]*$||; # get rid of the basename part + if (system("mkdir -p $mdir")) { die "Error: could not create $mdir.\n"; } + my ($section) = $podfile =~ /\.(\d+)\.pod$/; + convertpod2man($podfile, $manfile, $section); +} + +my @dummyPods = createDummyPods($poddir, \@pods); + +# Build the html page for each pod. +#mkdir($htmldir) or die "Error: could not create $htmldir.\n"; +print "Converting PODs to HTML pages...\n"; +# have to clear the cache, because old entries can cause a problem +unlink("$cachedir/pod2htmd.tmp", "$cachedir/pod2htmi.tmp"); +foreach my $podfile (@pods) { + my $htmlfile = $podfile; + $htmlfile =~ s/^$poddir/$htmldir/; # change the beginning of the path + $htmlfile =~ s/\.pod$/\.html/; # change the ending + my $hdir = $htmlfile; + $hdir =~ s|/[^/]*$||; # get rid of the basename part + if (system("mkdir -p $hdir")) { die "Error: could not create $hdir.\n"; } + #print "$podfile, $htmlfile, $poddir, $htmldir\n"; + convertpod2html($podfile, $htmlfile, $poddir, $htmldir); +} + +# Remove the dummy pods +unlink @dummyPods; +rmdir "$poddir/man7"; + +exit; + + +# To enable linking between the cmd man pages and the db man pages, need to: +# grep thru the cmd pods searching for references (L<>) to any section 5 man page +# if that pod does not exist, create an empty one that will satisfy pod2html +# keep track of all dummy pods created, so they can be removed later +sub createDummyPods { + my ($poddir, $pods) = @_; + my $cmd = "grep -r -E 'L<.+\\([57]\\)\\|.+\\.[57]>' " . $poddir; + #print "Running cmd: ", $cmd, "\n"; + my @lines = `$cmd`; + if ($?) { print "Error running: $cmd\n"; print join('', @lines); } + #my @lines; + #system($cmd); + my @dummyPods; + foreach my $l (@lines) { + #print "$l\n"; + my @matches = $l =~ /L<([^\(]+)\(([57])\)\|\1\.[57]>/g; # get all the matches in the line + # The above line should create the array with every other entry being the man page name + # and every other entry is the section # (5 or 7) + my $cmd; + while ($cmd=shift @matches) { + #foreach my $m (@matches) { + my $section = shift @matches; + my $filename = "$poddir/man$section/$cmd.$section.pod"; + #print "$filename\n"; + if (!(grep /^$filename$/, @$pods) && !(grep /^$filename$/, @dummyPods)) { push @dummyPods, $filename; } + } + } + + + # Create these empty files + print "Creating empty linked-to files: ", join(', ', @dummyPods), "\n"; + mkdir "$poddir/man7"; + foreach my $d (@dummyPods) { + if (!open(TMP, ">>$d")) { warn "Could not create dummy pod file $d ($!)\n"; } + else { close TMP; } + } + + return @dummyPods; +} + +# Recursively get the list of pod man page files. +sub getPodList { + my $poddir = shift; + my @files; + + # 1st get toplevel dir listing + opendir(DIR, $poddir) or die "Error: could not read $poddir.\n"; + my @topdir = grep !/^\./, readdir(DIR); # / + close(DIR); + + # Now go thru each subdir (these are man1, man3, etc.) + foreach my $mandir (@topdir) { + opendir(DIR, "$poddir/$mandir") or die "Error: could not read $poddir/$mandir.\n"; + my @dir = grep !/^\./, readdir(DIR); # / + close(DIR); + foreach my $file (@dir) { + push @files, "$poddir/$mandir/$file"; + } + } + return sort @files; +} + + +# Create the xcat man page that gives a summary description of each xcat cmd. +# Not used. +sub writesummarypage { + my $file = shift; # relative path file name of the man page + # the rest of @_ contains the pod files that describe each cmd + + open(FILE, ">$file") or die "Error: could not open $file for writing.\n"; + + print FILE <<'EOS1'; +=head1 NAME + +B - extreme Cluster Administration Tool. + +=head1 DESCRIPTION + +Extreme Cluster Administration Toolkit (xCAT). xCAT is a scalable distributed computing management +and provisioning tool that provides a unified interface for hardware control, discovery, and +OS diskful/diskfree deployment. + + +=head1 XCAT DATABASE + +All of the cluster configuration information is in the xCAT database. See L for +descriptions of every table in the database. + +=head1 XCAT COMMANDS + +What follows is a short description of each xCAT command. To get more information about a particular +command, see its man page. Note that the commands are listed in alphabetical order B, +i.e. all the commands in section 1, then the commands in section 3, etc. + +=over 12 +EOS1 + +# extract the summary for each cmd from its man page +foreach my $manpage (@_) { + my ($sectionnum) = $manpage =~ /\.(\d+)\.pod$/; + # Suck in the whole file, then we will parse it. + open(MANPAGE, "$manpage") or die "Error: could not open $manpage for reading.\n"; + my @contents = ; + my $wholemanpage = join('', @contents); + close(MANPAGE); + # This regex matches: optional space, =head1, space, title, space, cmd, space, description, newline + my ($cmd, $description) = $wholemanpage =~ /^\s*=head1\s+\S+\s+(\S+)\s+(.+?)\n/si; + if (!defined($cmd)) { print "Warning: $manpage is not in a recognized structure. It will be ignored.\n"; next; } + if (!defined($description)) { print "Warning: $manpage does not have a description for $cmd. It will be ignored.\n"; next; } + $cmd =~ s/^.<(.+)>$/$1/; # if the cmd name has pod formatting around it, strip it off + $description =~ s/^-\s*//; # if the description has a leading hypen, strip it off + print FILE "\n=item L<$cmd($sectionnum)|$cmd.$sectionnum>\n\n".$description."\n"; +} + +# Artificially add the xcattest cmd, because the xCAT-test rpm will add this +print FILE "\n=item L\n\nRun automated xCAT test cases.\n"; + + print FILE <<"EOS3"; + +=back +EOS3 + + close FILE; +} + + +# Create the html page for one pod. +sub convertpod2html { + my ($podfile, $htmlfile, $poddir, $htmldir) = @_; + + #TODO: use --css= and --title= to make the pages look better + pod2html($podfile, + "--outfile=$htmlfile", + "--podpath=man1", + "--podroot=$poddir", + "--htmldir=$htmldir", + "--recurse", + "--cachedir=$cachedir", + ); + +} + + +# Create the man page for one pod. +sub convertpod2man { + my ($podfile, $manfile, $section) = @_; + + my $parser = Pod::Man->new(section => $section); + $parser->parse_from_file($podfile, $manfile); +} diff --git a/xCAT-client/bin/genimage b/xCAT-client/bin/genimage index 2f210d811..0fb485fea 100755 --- a/xCAT-client/bin/genimage +++ b/xCAT-client/bin/genimage @@ -117,7 +117,7 @@ if ((!$imagename) && (!$profile) && (!$os) && (!$arch)) { if ($? == 0) { if (($tmpimgs) && ($tmpimgs !~ /^Could/)) { #Could is returned when the osimage table is empty my @images=split('\n', $tmpimgs); - print "Do you want to re-genarate an existing image from the osimage table? "; + print "Do you want to re-generate an existing image from the osimage table? "; print "[y/n] "; my $conf = ; chomp($conf); @@ -128,7 +128,7 @@ if ((!$imagename) && (!$profile) && (!$os) && (!$arch)) { foreach(sort @images){ print " $_\n"; } - # default is the first image cause in many cases + # default is the first image print "Which image do you want to re-generate? ["; print $images[0]; print "] "; @@ -294,13 +294,10 @@ if ($profile) { print " Profile: $profile\n"; } # get the interface if ((!$imagename) && (!$interface)){ while(1){ - print "Which network interface do you want the image to boot from? ["; - print "eth0"; - print "] "; + print "OPTIONAL: Which specific network interface will the image boot from? []"; $interface = ; chomp($interface); if($interface eq ""){ - $interface = "eth0"; last; }else{ print "You want your stateless machines to boot off of "; @@ -317,8 +314,9 @@ if ((!$imagename) && (!$interface)){ } } } + if ($interface) { print " Interface: $interface\n"; } + else { print " No interface specified. The interface will be determined at network boot time.\n"; } } -if ($interface) { print " Interface: $interface\n"; } diff --git a/xCAT-client/bin/getxcatdocs b/xCAT-client/bin/getxcatdocs index 1b35a99de..d9b1efaaf 100755 --- a/xCAT-client/bin/getxcatdocs +++ b/xCAT-client/bin/getxcatdocs @@ -23,7 +23,7 @@ use Cwd; # Update this list if you group any xcat docs on a separate page such that they are no longer linked from the # main doc page. -my @indexdocs = ('XCAT_Documentation', 'Power_775_Cluster_Documentation', 'Highly_Available_Management_Node', 'Mixed_Cluster_Support'); +my @indexdocs = ('XCAT_Documentation', 'Power_775_Cluster_Documentation', 'Highly_Available_Management_Node', 'Mixed_Cluster_Support','IBM_HPC_Stack_in_an_xCAT_Cluster'); #my $VERSION; my $HELP; diff --git a/xCAT-client/bin/mysqlsetup b/xCAT-client/bin/mysqlsetup index dd0711aac..fb782c4d7 100755 --- a/xCAT-client/bin/mysqlsetup +++ b/xCAT-client/bin/mysqlsetup @@ -205,10 +205,10 @@ if ($::osname eq 'AIX') &setulimits; } -# if not just odbc update and not already running mysql or mysqlsetup -u +# if not just odbc update and not already running mysql or mysqlsetup -u or -L # Get root and admin passwords # -if ((($odbconly == 0) && ( $::xcatrunningmysql == 0)) || $::UPDATE ) +if ((($odbconly == 0) && ( $::xcatrunningmysql == 0)) || $::UPDATE || $::SETUPLL ) { # not just updating the odbc if ($ENV{'XCATMYSQLADMIN_PW'}) # input env sets the password { diff --git a/xCAT-client/bin/pping b/xCAT-client/bin/pping index 49b383069..6b8ea11f6 100755 --- a/xCAT-client/bin/pping +++ b/xCAT-client/bin/pping @@ -66,7 +66,7 @@ else { # the normal case of the user running the cmd - expand the noderange us SSL_cert_file=> xCAT::Utils->getHomeDir()."/.xcat/client-cred.pem", SSL_ca_file => xCAT::Utils->getHomeDir()."/.xcat/ca.pem", SSL_use_cert => 1, - #SSL_verify_mode => 1, + SSL_verify_mode => 1, ); die "Connection failure: $!\n" unless ($client); my %cmdref = (command => 'noderange', noderange => $noderange); diff --git a/xCAT-client/podchecker b/xCAT-client/podchecker new file mode 100755 index 000000000..9bd3cd2da --- /dev/null +++ b/xCAT-client/podchecker @@ -0,0 +1,145 @@ +#!/usr/bin/perl + eval 'exec perl -S $0 "$@"' + if 0; +############################################################################# +# podchecker -- command to invoke the podchecker function in Pod::Checker +# +# Copyright (c) 1998-2000 by Bradford Appleton. All rights reserved. +# This file is part of "PodParser". PodParser is free software; +# you can redistribute it and/or modify it under the same terms +# as Perl itself. +############################################################################# + +use strict; +#use diagnostics; + +=head1 NAME + +podchecker - check the syntax of POD format documentation files + +=head1 SYNOPSIS + +B [B<-help>] [B<-man>] [B<-(no)warnings>] [IS< >...] + +=head1 OPTIONS AND ARGUMENTS + +=over 8 + +=item B<-help> + +Print a brief help message and exit. + +=item B<-man> + +Print the manual page and exit. + +=item B<-warnings> B<-nowarnings> + +Turn on/off printing of warnings. Repeating B<-warnings> increases the +warning level, i.e. more warnings are printed. Currently increasing to +level two causes flagging of unescaped "E,E" characters. + +=item I + +The pathname of a POD file to syntax-check (defaults to standard input). + +=back + +=head1 DESCRIPTION + +B will read the given input files looking for POD +syntax errors in the POD documentation and will print any errors +it find to STDERR. At the end, it will print a status message +indicating the number of errors found. + +Directories are ignored, an appropriate warning message is printed. + +B invokes the B function exported by B +Please see L for more details. + +=head1 RETURN VALUE + +B returns a 0 (zero) exit status if all specified +POD files are ok. + +=head1 ERRORS + +B returns the exit status 1 if at least one of +the given POD files has syntax errors. + +The status 2 indicates that at least one of the specified +files does not contain I POD commands. + +Status 1 overrides status 2. If you want unambiguous +results, call B with one single argument only. + +=head1 SEE ALSO + +L and L + +=head1 AUTHORS + +Please report bugs using L. + +Brad Appleton Ebradapp@enteract.comE, +Marek Rouchal Emarekr@cpan.orgE + +Based on code for B written by +Tom Christiansen Etchrist@mox.perl.comE + +=cut + + +use Pod::Checker; +use Pod::Usage; +use Getopt::Long; + +## Define options +my %options; + +## Parse options +GetOptions(\%options, qw(help man warnings+ nowarnings)) || pod2usage(2); +pod2usage(1) if ($options{help}); +pod2usage(-verbose => 2) if ($options{man}); + +if($options{nowarnings}) { + $options{warnings} = 0; +} +elsif(!defined $options{warnings}) { + $options{warnings} = 1; # default is warnings on +} + +## Dont default to STDIN if connected to a terminal +pod2usage(2) if ((@ARGV == 0) && (-t STDIN)); + +## Invoke podchecker() +my $status = 0; +@ARGV = qw(-) unless(@ARGV); +for my $podfile (@ARGV) { + if($podfile eq '-') { + $podfile = '<&STDIN'; + } + elsif(-d $podfile) { + warn "podchecker: Warning: Ignoring directory '$podfile'\n"; + next; + } + my $errors = + podchecker($podfile, undef, '-warnings' => $options{warnings}); + if($errors > 0) { + # errors occurred + $status = 1; + printf STDERR ("%s has %d pod syntax %s.\n", + $podfile, $errors, + ($errors == 1) ? 'error' : 'errors'); + } + elsif($errors < 0) { + # no pod found + $status = 2 unless($status); + print STDERR "$podfile does not contain any pod commands.\n"; + } + else { + print STDERR "$podfile pod syntax OK.\n"; + } +} +exit $status; + diff --git a/xCAT-client/pods/man1/chdef.1.pod b/xCAT-client/pods/man1/chdef.1.pod index 9ce41d3fa..273ff6a0a 100644 --- a/xCAT-client/pods/man1/chdef.1.pod +++ b/xCAT-client/pods/man1/chdef.1.pod @@ -11,7 +11,7 @@ B [B<-t> I] [B<-o> I] [B<-n> I] [I< B [B<-V>|B<--verbose>] [B<-t> I] [B<-o> I] [B<-d>|B<--dynamic>] [B<-p>|B<--plus>] [B<-m>|B<--minus>] [B<-z>|B<--stanza>] [[B<-w> I==I] [B<-w> I=~I] ...] [I] [I=I [I=I]] - [B<-u> B=|I|I> B= [I=I]] + [B<-u> [I=|I|I>] [I=] [I=I] [I=I]] =head1 DESCRIPTION @@ -83,9 +83,9 @@ Indicates that the file being piped to the command is in stanza format. See the =item B<-u> -This option only works for objtype B. +Fill in the attributes such as template file, pkglist file and otherpkglist file of osimage object based on the specified parameters. It will search "/install/custom/" directory first, and then "/opt/xcat/share/". -Updating the osimage attribute automatically. If osvers or osarch is not specified, the corresponding value of the management node will be used. +Note: this option only works for objtype B. =back diff --git a/xCAT-client/pods/man1/chvm.1.pod b/xCAT-client/pods/man1/chvm.1.pod index 664a5cfc6..d73aaa0dc 100644 --- a/xCAT-client/pods/man1/chvm.1.pod +++ b/xCAT-client/pods/man1/chvm.1.pod @@ -24,7 +24,9 @@ B I [B={B<*>|B}] B I [B] [B] [B] [B] - + [B [B>] [B<--vios>] + [B] + =head2 VMware/KVM specific: B I [B<-a> I] [B<-d> I] [B<-p> I] [B<--resize> B=I] [B<--cpus> I] [B<--mem> I] @@ -111,7 +113,7 @@ The administrator should use lsvm to get the profile content, and then edit the For normal power machine: -chvm could be used to modify the resources assigned to partitions. The admin shall specify the attributes with options I, I, I and/or I. If nothing specified, nothing will be returned. +chvm could be used to modify the resources assigned to partitions. The admin shall specify the attributes with options I, I, I, I, I and/or I. If nothing specified, nothing will be returned. =head2 VMware/KVM specific: @@ -199,6 +201,14 @@ Set LPAR name for the specified lpars. If '*' specified, it means to get names f To specify the parameters that will be modified. +=item B B [B<--vios>] + +To create new virtual adapter for the specified node. + +=item B + +To specify the slot id of the virtual adapter will be deleted. + =back =head2 VMware/KVM specific: diff --git a/xCAT-client/pods/man1/chzone.1.pod b/xCAT-client/pods/man1/chzone.1.pod new file mode 100644 index 000000000..2a91fad5a --- /dev/null +++ b/xCAT-client/pods/man1/chzone.1.pod @@ -0,0 +1,138 @@ +=head1 B + +B - Changes a zone defined in the cluster. + +=head1 B + +B [B<--defaultzone>] [-K] [B<-k> I] [B<-a> I | B<-r> I] [B<-g>] [B<-f>] [B<-s> I] [-V] + +B [B<-h> | B<-v>] + + +=head1 B + +The B command is designed to change the definition of a zone previous defined in the cluster. +The chzone command is only supported on Linux ( No AIX support). +The nodes are not updated with the new root ssh keys by chzone. You must run updatenode -k or xdsh -K to the nodes to update the root ssh keys to the new generated zone keys. This will also sync any service nodes with the zone keys, if you have a hierarchical cluster. +Note: if any zones in the zone table, there must be one and only one defaultzone. Otherwise, errors will occur. + +=head1 B + +=over 5 + +=item B<-h>|B<--help> + +Displays usage information. + +=item B<-v>|B<--version> + +Displays command version and build date. + +=item B<-k | --sshkeypath> I + +This is the path to the id_rsa key that will be used to build new root's ssh keys for the zone. If -k is used, it will generate the ssh public key from the input ssh RSA private key, and store both in /etc/xcat/sshkeys//.ssh directory. + +=item B<-K | --genkeys> + +Using this flag, will generate new ssh RSA private and public keys for the zone into the /etc/xcat/sshkeys//.ssh directory. +The nodes are not automatically updated with the new root ssh keys by chzone. You must run updatenode -k or xdsh -K to the nodes to update the root ssh keys to the new generated zone keys. This will also sync any service nodes with the zone keys, if you have a hierarchical cluster. + +=item B<--default> + +if --defaultzone is input, then it will set the zone defaultzone attribute to yes. +if --defaultzone is input and another zone is currently the default, +then the -f flag must be used to force a change to the new defaultzone. +If -f flag is not use an error will be returned and no change made. +Note: if any zones in the zone table, there must be one and only one defaultzone. Otherwise, errors will occur. + +=item B<-a | --addnoderange> I + +For each node in the noderange, it will set the zonename attribute for that node to the input zonename. +If the -g flag is also on the command, then +it will add the group name "zonename" to each node in the noderange. + +=item B<-r | --rmnoderange> I + +For each node in the noderange, if the node is a member of the input zone, it will remove the zonename attribute for that node. +If any of the nodes in the noderange is not a member of the zone, you will get an error and nothing will be changed. +If the -g flag is also on the command, then +it will remove the group name "zonename" from each node in the noderange. + + +=item B<-s| --sshbetweennodes> B + +If -s entered, the zone sshbetweennodes attribute will be set to yes or no based on the input. When this is set to yes, then ssh will be setup to allow passwordless root access between nodes. If no, then root will be prompted for a password when running ssh between the nodes in the zone. + +=item B<-f | --force> + +Used with the (--defaultzone) flag to override the current default zone. + +=item B<-g | --assigngroup> + +Used with the (-a or -r ) flag to add or remove the group zonename for all nodes in the input noderange. + +=item B<-V>|B<--Verbose> + +Verbose mode. + + +=back + + +=head1 B + +=over 3 + +=item * + +To chzone zone1 to the default zone, enter: + +B I --default -f + +=item * + +To generate new root ssh keys for zone2A using the ssh id_rsa private key in /root/.ssh: + +B I -k /root/.ssh + +Note: you must use xdsh -K or updatenode -k to update the nodes with the new keys + +=item * + +To generate new root ssh keys for zone2A, enter : + +B I -K + +Note: you must use xdsh -K or updatenode -k to update the nodes with the new keys + +=item * + +To add a new group of nodes (compute3) to zone3 and add zone3 group to the nodes, enter: + +B I -a compute3 -g + +=item * + +To remove a group of nodes (compute4) from zone4 and remove zone4 group from the nodes, enter: + +B I -r compute4 -g + +=item * + +To change the sshbetweennodes setting on the zone to not allow passwordless ssh between nodes, enter: + +B I -s no + +Note: you must use xdsh -K or updatenode -k to update the nodes with this new setting. + +=back + +B + +B + +Location of the chzone command. + +=head1 B + +L ,L ,L , L diff --git a/xCAT-client/pods/man1/genimage.1.pod b/xCAT-client/pods/man1/genimage.1.pod index 11a46e2c8..fdd3f5f88 100644 --- a/xCAT-client/pods/man1/genimage.1.pod +++ b/xCAT-client/pods/man1/genimage.1.pod @@ -6,10 +6,10 @@ B - Generates a stateless image to be used for a diskless install. B -B B<-o> I [B<-a> I] B<-p> I B<-i> I B<-n> I [B<--onlyinitrd>] [B<-r> I] [B<-k> I] [B<-g> I] [B<-m> I] [B<-l> I] [B<--permission> I] [B<--interactive>] [B<--dryrun>] - B [B<-o> I] [B<-a> I] [B<-p> I] [B<-i> I] [B<-n> I] [B<--onlyinitrd>] [B<-r> I] [B<-k> I] [B<-g> I] [B<-m> I] [B<-l> I] [B<--permission> I] [B<--interactive>] [B<--dryrun>] [B<--ignorekernelchk>] I +B B<-o> I [B<-a> I] B<-p> I B<-i> I B<-n> I [B<--onlyinitrd>] [B<-r> I] [B<-k> I] [B<-g> I] [B<-m> I] [B<-l> I] [B<--permission> I] [B<--interactive>] [B<--dryrun>] + B [B<-h> | B<--help> | B<-v> | B<--version>] @@ -17,43 +17,43 @@ B [B<-h> | B<--help> | B<-v> | B<--version>] =head1 DESCRIPTION Generates a stateless and a statelite image that can be used to boot xCAT nodes in a diskless mode. -If I is not specified, the default packages included -(and excluded) in the image are specified by +The I format of the command is recommended. When specified, genimage will use the osimage definition for information to generate this image. Additional options specified on the command line will override any corresponding previous osimage settings, and will be written back to the osimage definition. + +If I is not specified (old method): + - the default packages included (and excluded) in the image are specified by /opt/xcat/share/xcat/netboot//[.][.].pkglist and /opt/xcat/share/xcat/netboot//[.][.].exlist. -Additional packages that are not from the os distro can be specified in a + - Additional packages that are not from the os distro can be specified in a /opt/xcat/share/xcat/netboot//[.][.].otherpkgs.pkglist file. -Customized package list files can be specified under /install/custom/netboot/ directory. The generated image will be put in /install/netboot/// directory. + - Customized package list files will override these files and can be specified under /install/custom/netboot/ directory. + - The generated image will be put in /install/netboot/// directory. -The newly generated image names will have the following format: + - osimage definitions will be created in the I and I tables. The newly generated image names will have the following format: - for stateless: --netboot- + for stateless: --netboot- - for statelite: --statelite- + for statelite: --statelite- -B command will create them into I and I tables. - -If I is specified, the package list file names are read from the I table and I tables. If B runs on the management node, both the I table and I table will be updated with the given values from the options. The B command will generate two initial ramdisks for B and B, one is B, the other one is B. -After your image is created, you can chroot to the +After your image is generated, you can chroot to the image, install any additional software you would like, or make modifications to files, and then run the following command to prepare the image for deployment. for stateless: B for statelite: B -Becides prompting for the input for some paramters, the B command takes default quesses for the parameters not specified or not defined in the I and I tables. It also makes default answers for questions from yum/zypper command when installing rpms into the image. Please use --interactive flag if you want yum/zypper command to prompt you for the answers. +Besides prompting for some paramter values, the B command takes default guesses for the parameters not specified or not defined in the I and I tables. It also assumes default answers for questions from the yum/zypper command when installing rpms into the image. Please use --interactive flag if you want the yum/zypper command to prompt you for the answers. -If B<--onlyinitrd> is specified, only regenerates the initrd for a stateless image to be used for a diskless install. +If B<--onlyinitrd> is specified, genimage only regenerates the initrd for a stateless image to be used for a diskless install. The B command must be run on a system that is the same architecture and same distro with same major release version as the nodes it will be used on. If the management node is not the same architecture or same distro level, copy the contents of @@ -61,10 +61,9 @@ used on. If the management node is not the same architecture or same distro lev the management node to that system. Then change directory to /opt/xcat/share/xcat/netboot/ and run ./genimage. - =head1 Parameters -I specifies the name of a os image definition to be used. The specification for the image is storted in the I table and I table. +I specifies the name of an os image definition to be used. The specification for the image is stored in the I table and I table. =head1 OPTIONS @@ -88,7 +87,7 @@ the nodes' nodetype.profile attribute must be set to this same value. =item B<-i> I -The network interface the diskless node will boot over (e.g. eth0). +This argument is now optional, and allows you to specify the network boot interface to be configured in the image (e.g. eth0). If not specified, the interface will be determined and configured during the network boot process. =item B<-n> I @@ -183,46 +182,53 @@ To prompt the user for inputs: genimage =item 2 +To generate an image using information from an osimage definition: -To generate a fedora8 image for a compute node architecture + genimage myimagename + +=item 3 +To run genimage in test mode without actually generating an image: + + genimage --dryrun myimagename + +=item 4 +To generate an image and have yum/zypper prompt for responses: + + genimage myimagename --interactive + +=item 5 +To generate an image, replacing some values in the osimage definition: + + genimage -i eth0 -n tg3 myimagename + +=item 6 +(old method) To generate a fedora8 image for a compute node architecture x86_64 and place it in the /install/netboot/fedora8/x86_64/compute/rootimg directory: genimage -i eth0 -o fedora8 -p compute -=item 3 +=item 7 +(old method) genimage -i eth0 -r eth1,eth2 -n tg3,bnx2 -o centos5.1 -p compute -=item 4 +=item 8 +(old method) genimage -i eth0 -n tg3,bnx2 -o sles11 -p compute --interactive -=item 5 +=item 9 +(old method) genimage -i eth0 -n igb,e1000e,e1000,bnx2,tg3 -o centos5.4 -p nfsroot --permission 777 -=item 6 - - genimage -i eth0 -n tg3 myimagename - -=item 7 - - genimage myimagename - -=item 8 - - genimage myimagename --interactive - -=item 9 - -To regenerate the initrd for a fedora8 image for a compute node architecture x86_64 and place it in the /install/netboot/fedora8/x86_64/compute/rootimg directory: change directory to /opt/xcat/share/xcat/netboot/fedora and run: - - genimage --onlyinitrd -i eth0 -n tg3,bnx2 -o fedora8 -p compute - =item 10 +(old method) +To regenerate the initrd for a fedora8 image for a compute node architecture x86_64 and place it in the /install/netboot/fedora8/x86_64/compute/rootimg directory: - genimage --dryrun myimagename + cd /opt/xcat/share/xcat/netboot/fedora + ./genimage --onlyinitrd -i eth0 -n tg3,bnx2 -o fedora8 -p compute =back diff --git a/xCAT-client/pods/man1/geninitrd.1.pod b/xCAT-client/pods/man1/geninitrd.1.pod index ef328b917..9af58234a 100644 --- a/xCAT-client/pods/man1/geninitrd.1.pod +++ b/xCAT-client/pods/man1/geninitrd.1.pod @@ -1,6 +1,6 @@ =head1 NAME -B - Generate an initrd (initial ramfs) which to be used for statefull install or stateless netboot. +B - Generate an initrd (initial ramfs) which to be used for statefull install or stateless netboot. =head1 SYNOPSIS diff --git a/xCAT-client/pods/man1/mkdef.1.pod b/xCAT-client/pods/man1/mkdef.1.pod index d1f005e70..fb1f34d0f 100644 --- a/xCAT-client/pods/man1/mkdef.1.pod +++ b/xCAT-client/pods/man1/mkdef.1.pod @@ -9,7 +9,7 @@ B [B<-h>|B<--help>] [B<-t> I] B [B<-V>|B<--verbose>] [B<-t> I] [B<-o> I] [B<-z>|B<--stanza>] [B<-d>|B<--dynamic>] [B<-f>|B<--force>] [[B<-w> I==I] [B<-w> I=~I] ...] [I] [I=I [I=I]] - [B<-u> B=|I|I> B= [I=I]] + [B<-u> B=|I|I> B= [I=I] [I=I]] =head1 DESCRIPTION @@ -73,9 +73,10 @@ Indicates that the file being piped to the command is in stanza format. See the =item B<-u> -This option only works for objtype B. +Fill in the attributes such as template file, pkglist file and otherpkglist file of osimage object based on the specified parameters. It will search "/install/custom/" directory first, and then "/opt/xcat/share/". +The I and I must be specified. If I or I is not specified, the corresponding value of the management node will be used. -Fill in the osimage attribute automatically when define osimage. The I and I must be specified. If osvers or osarch is not specified, the corresponding value of the management node will be used. +Note: this option only works for objtype B. =back diff --git a/xCAT-client/pods/man1/mkvm.1.pod b/xCAT-client/pods/man1/mkvm.1.pod index 8bb5f2661..aba4ed6a2 100644 --- a/xCAT-client/pods/man1/mkvm.1.pod +++ b/xCAT-client/pods/man1/mkvm.1.pod @@ -24,6 +24,7 @@ B I [B<--full>] B I [B] [B] [B] [B] + [B [B>] [B<--vios>] =head2 For KVM: @@ -55,7 +56,7 @@ Please note that the mkvm command currently only supports creating standard LPAR With option I, a partition using all the resources on a normal power machine will be created. -If no option is specified, a partition using the parameters specified with attributes such as 'vmcpus', 'vmmory', 'vmphyslots', 'vmothersetting' will be created. Those attributes can either be specified with '*def' commands running before or be specified with this command. +If no option is specified, a partition using the parameters specified with attributes such as 'vmcpus', 'vmmory', 'vmphyslots', 'vmothersetting', 'vmnics', 'vmstorage' will be created. Those attributes can either be specified with '*def' commands running before or be specified with this command. =head2 For KVM and Vmware: @@ -89,9 +90,11 @@ The cpu count which will be created for the kvm/vmware virtual machine. Request to create a new full system partition for each CEC. -=item B B B B +=item B B B B B B [B<--vios>] -To specify the parameters which are used to create a partition. The I, I and I are necessay, and the value specified with this command have a more high priority. If the value of any of the three options is not specified, the corresponding value specified for the node object will be used. If any of the three attributes is neither specified with this command nor specified with the node object, error information will be returned. To reference to L for more information about 'drc_index' for I. +To specify the parameters which are used to create a partition. The I, I are necessay, and the value specified with this command have a more high priority. If the value of any of the three options is not specified, the corresponding value specified for the node object will be used. If any of the three attributes is neither specified with this command nor specified with the node object, error information will be returned. To reference to L for more information about 'drc_index' for I. + +The option I is used to specify the partition that will be created is a VIOS partition. If specified, the value for I shall be number which indicate the number of vSCSI server adapter will be created, and if no value specified for I, all the physical slot of the power machine will be asigned to VIOS partition. If not specified, it shall be in form of I to specify the vios and the virtual slot id of the vSCSI server adapter that will be connected from the Logical partition. =item B<-f|--force> @@ -318,6 +321,32 @@ The output is similar to: lpar1: 1/2/2 lpar1: 128. +10. To create a vios partition using some of the resources on normal power machine. + + mkvm viosnode vmcpus=1/4/16 vmmemory=1G/4G/32G vmphyslots=0x21010201,0x21010200 vmnics=vlan1 vmstorage=5 --vios + +The resouces for the node is similar to: + + viosnode: Lpar Processor Info: + Curr Processor Min: 1. + Curr Processor Req: 4. + Curr Processor Max: 16. + viosnode: Lpar Memory Info: + Curr Memory Min: 1.00 GB(4 regions). + Curr Memory Req: 4.00 GB(16 regions). + Curr Memory Max: 32.00 GB(128 regions). + viosnode: 1,513,U78AA.001.WZSGVU7-P1-T7,0x21010201,0xc03(USB Controller) + viosnode: 1,512,U78AA.001.WZSGVU7-P1-T9,0x21010200,0x104(RAID Controller) + viosnode: 1,0,U8205.E6B.0612BAR-V1-C,0x30000000,vSerial Server + viosnode: 1,1,U8205.E6B.0612BAR-V1-C1,0x30000001,vSerial Server + viosnode: 1,3,U8205.E6B.0612BAR-V1-C3,0x30000003,vEth (port_vlanid=1,mac_addr=4211509276a7) + viosnode: 1,5,U8205.E6B.0612BAR-V1-C5,0x30000005,vSCSI Server + viosnode: 1,6,U8205.E6B.0612BAR-V1-C6,0x30000006,vSCSI Server + viosnode: 1,7,U8205.E6B.0612BAR-V1-C7,0x30000007,vSCSI Server + viosnode: 1,8,U8205.E6B.0612BAR-V1-C8,0x30000008,vSCSI Server + viosnode: 1,9,U8205.E6B.0612BAR-V1-C9,0x30000009,vSCSI Server + viosnode: 0/0/0 + viosnode: 0. =head1 FILES diff --git a/xCAT-client/pods/man1/mkzone.1.pod b/xCAT-client/pods/man1/mkzone.1.pod new file mode 100644 index 000000000..e5a6310f7 --- /dev/null +++ b/xCAT-client/pods/man1/mkzone.1.pod @@ -0,0 +1,121 @@ +=head1 B + +B - Defines a new zone in the cluster. + +=head1 B + +B [B<--defaultzone>] [B<-k> I] [B<-a> I] [B<-g>] [B<-f>] [B<-s> I] [-V] + +B [B<-h> | B<-v>] + +=head1 B + +The B command is designed to divide the xCAT cluster into multiple zones. The nodes in each zone will share common root ssh keys. This allows the nodes in a zone to be able to as root ssh to each other without password, but cannot do the same to any node in another zone. All zones share a common xCAT Management Node and database including the site table, which defines the attributes of the entire cluster. +The mkzone command is only supported on Linux ( No AIX support). +The nodes are not updated with the new root ssh keys by mkzone. You must run updatenode -k or xdsh -K to the nodes to update the root ssh keys to the new generated zone keys. This will also sync any service nodes with the zone keys, if you have a hierarchical cluster. +Note: if any zones in the zone table, there must be one and only one defaultzone. Otherwise, errors will occur. + +=head1 B + +=over 5 + +=item B<-h>|B<--help> + +Displays usage information. + +=item B<-v>|B<--version> + +Displays command version and build date. + +=item B<-k | --sshkeypath> I + +This is the path to the id_rsa key that will be used to build root's ssh keys for the zone. If -k is used, it will generate the ssh public key from the input ssh RSA private key and store both in /etc/xcat/sshkeys//.ssh directory. +If -f is not used, then it will generate a set of root ssh keys for the zone and store them in /etc/xcat/sshkeys//.ssh. + +=item B<--default> + +if --defaultzone is input, then it will set the zone defaultzone attribute to yes; otherwise it will set to no. +if --defaultzone is input and another zone is currently the default, +then the -f flag must be used to force a change to the new defaultzone. +If -f flag is not use an error will be returned and no change made. +Note: if any zones in the zone table, there must be one and only one defaultzone. Otherwise, errors will occur. + +=item B<-a | --addnoderange> I + +For each node in the noderange, it will set the zonename attribute for that node to the input zonename. +If the -g flag is also on the command, then +it will add the group name "zonename" to each node in the noderange. + +=item B<-s| --sshbetweennodes> B + +If -s entered, the zone sshbetweennodes attribute will be set to yes or no. It defaults to yes. When this is set to yes, then ssh will be setup +to allow passwordless root access between nodes. If no, then root will be prompted for a password when running ssh between the nodes in the zone. + +=item B<-f | --force> + +Used with the (--defaultzone) flag to override the current default zone. + +=item B<-g | --assigngroup> + +Used with the (-a) flag to create the group zonename for all nodes in the input noderange. + +=item B<-V>|B<--Verbose> + +Verbose mode. + +=back + +=head1 B + +=over 3 + +=item * + +To make a new zone1 using defaults , enter: + +B I + +Note: with the first mkzone, you will automatically get the xcatdefault zone created as the default zone. This zone uses ssh keys from + /.ssh directory. + +=item * + +To make a new zone2 using defaults and make it the default zone enter: + +B I --defaultzone -f + +=item * + +To make a new zone2A using the ssh id_rsa private key in /root/.ssh: + +B I -k /root/.ssh + +=item * + +To make a new zone3 and assign the noderange compute3 to the zone enter: + +B I -a compute3 + +=item * + +To make a new zone4 and assign the noderange compute4 to the zone and add zone4 as a group to each node enter: + +B I -a compute4 -g + +=item * + +To make a new zone5 and assign the noderange compute5 to the zone and add zone5 as a group to each node but not allow passwordless ssh between the nodes enter: + +B I -a compute5 -g -s no + +=back + +B + +B + +Location of the mkzone command. + +=head1 B + +L, L, L, L diff --git a/xCAT-client/pods/man1/rmzone.1.pod b/xCAT-client/pods/man1/rmzone.1.pod new file mode 100644 index 000000000..18cfeed06 --- /dev/null +++ b/xCAT-client/pods/man1/rmzone.1.pod @@ -0,0 +1,84 @@ +=head1 B + +B - Removes a zone from the cluster. + +=head1 B + +B [B<-g>] [B<-f>] + +B [B<-h> | B<-v>] + + +=head1 B + +The B command is designed to remove a previously defined zone from the cluster. +It will remove the zone entry in the zone table. It will remove the zone from the zonename attributes on the nodes that were assigned to the zone. Optionally, it will remove the zonename group from the nodes that were assigned to the zone. +It will also remove the root ssh keys that were created for that zone on the Management Node. +The rmzone command is only supported on Linux ( No AIX support). +The nodes are not automatically updated with new root ssh keys by rmzone. You must run updatenode -k or xdsh -K to the nodes to update the root ssh keys. The nodes new ssh key will be assigned from the defaultzone in the zone table, or if no entries in the zone table, the keys will come from /root/.ssh. +Note: if any zones in the zone table, there must be one and only one defaultzone. Otherwise, errors will occur. + + +=head1 B + +=over 5 + +=item B<-h>|B<--help> + +Displays usage information. + +=item B<-v>|B<--version> + +Displays command version and build date. + +=item B<-f | --force> + +Used to remove a zone that is defined as current default zone. This should only be done if you are removing all zones, or you will +adding a new zone or changing an existing zone to be the default zone. + +=item B<-g | --assigngroup> + +Remove the assigned group named B from all nodes assigned to the zone being removed. + +=item B<-V>|B<--Verbose> + +Verbose mode. + + +=back + + +=head1 B + +=over 3 + +=item * + +To remove zone1 from the zone table and the zonename attribute on all it's assigned nodes , enter: + +B I + + +=item * + +To remove zone2 from the zone table, the zone2 zonename attribute, and the zone2 group assigned to all nodes that were in zone2, enter: + +B I -g + +=item * + +To remove zone3 from the zone table, all the node zone attributes and override the fact it is the defaultzone, enter: + +B I -g -f + +=back + +B + +B + +Location of the rmzone command. + +=head1 B + +L ,L ,L , L diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index 6c29906fd..7ff9dd453 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -119,6 +119,28 @@ Wake up the target nodes which is in B state. Don't try to run B against the 'on' state node, it would cause the node gets to 'off' state. +For some of xCAT hardware such as NeXtScale, it may need to enable S3 before using B. The following steps can be used to enable S3. Please reference L for "pasu" usage. + + [root@xcatmn home]# echo "set Power.S3Enable Enable" > power-setting + [root@xcatmn home]# pasu -b power-setting node01 + node01: Batch mode start. + node01: [set Power.S3Enable Enable] + node01: Power.S3Enable=Enable + node01: + node01: Beginning intermediate batch update. + node01: Waiting for command completion status. + node01: Command completed successfully. + node01: Completed intermediate batch update. + node01: Batch mode completed successfully. + + [root@xcatmn home]# pasu node01 show all|grep -i s3 + node01: IMM.Community_HostIPAddress3.1= + node01: IMM.Community_HostIPAddress3.2= + node01: IMM.Community_HostIPAddress3.3= + node01: IMM.DNS_IP_Address3=0.0.0.0 + node01: IMM.IPv6DNS_IP_Address3=:: + node01: Power.S3Enable=Enable + =item B|B Print the current power state/status. diff --git a/xCAT-client/pods/man1/updatenode.1.pod b/xCAT-client/pods/man1/updatenode.1.pod index 24ad11b11..bf758eaa9 100644 --- a/xCAT-client/pods/man1/updatenode.1.pod +++ b/xCAT-client/pods/man1/updatenode.1.pod @@ -8,6 +8,8 @@ B B [B<-V>|B<--verbose>] [B<-F>|B<--sync>] [B<-f>|B<--sns B B [B<-k>|B<--security>] [B<-t timeout>] +B B [B<-g>|B<--genmypost>] + B B [B<-V>|B<--verbose>] [B<-t timeout>] [B] B B [B<-V>|B<--verbose>] [B<-f>|B<--snsync>] @@ -327,6 +329,11 @@ For statelite installations to sync files, you should use the read-only option for files/directories listed in litefile table with source location specified in the litetree table. +=item B<-g|--genmypost> + +Will generate a new mypostscript file for the +nodes in the noderange, if site precreatemypostscripts is 1 or YES. + =item B<-h|--help> diff --git a/xCAT-client/pods/man1/xdsh.1.pod b/xCAT-client/pods/man1/xdsh.1.pod index 03b86bc09..c709bb383 100644 --- a/xCAT-client/pods/man1/xdsh.1.pod +++ b/xCAT-client/pods/man1/xdsh.1.pod @@ -435,6 +435,13 @@ Sets the command path to use on the targets. If B is not set, the default path defined in the profile of the remote I is used. +=item B + +If B is set to the password of the +userid (usually root) that will ssh to the node, then when +you use the -K flag, you will not be prompted for a password. + + =item B Specifies the shell syntax to use on remote targets; B or diff --git a/xCAT-client/pods/man8/makedns.8.pod b/xCAT-client/pods/man8/makedns.8.pod index 4d917ab22..3674161d7 100644 --- a/xCAT-client/pods/man8/makedns.8.pod +++ b/xCAT-client/pods/man8/makedns.8.pod @@ -28,7 +28,7 @@ A network B and B values must be provided either in the B that have a corresponding xCAT network definition will be added to DNS. -By default, B sets up the B service and updates the DNS records on the local system (mamagement node). If the -e flag is specified, it will also update the DNS records on any external DNS server that is listed in the /etc/resolv.conf on the management node. (Assuming the external DNS server can recognize the xCAT key as authentication.) +By default, B sets up the B service and updates the DNS records on the local system (management node). If the -e flag is specified, it will also update the DNS records on any external DNS server that is listed in the /etc/resolv.conf on the management node. (Assuming the external DNS server can recognize the xCAT key as authentication.) For more information on Cluster Name Resolution: https://sourceforge.net/apps/mediawiki/xcat/index.php?title=Cluster_Name_Resolution @@ -49,6 +49,8 @@ Remove the DNS records. Update DNS records to the external DNS server listed in /etc/resolv.conf. +Enabling the site attribute I means use 'external' DNS by default. If setting I to 1, you need NOT use B<-e> flag in every makedns call. + =item B A set of comma delimited node names and/or group names. See the "noderange" man page for details on additional supported formats. diff --git a/xCAT-client/pods/man8/mknb.8.pod b/xCAT-client/pods/man8/mknb.8.pod index 53dc293b4..05836f500 100644 --- a/xCAT-client/pods/man8/mknb.8.pod +++ b/xCAT-client/pods/man8/mknb.8.pod @@ -12,7 +12,12 @@ B I The B command is run by xCAT automatically, when xCAT is installed on the management node. It creates a network boot root image (used for node discovery, BMC programming, and flashing) for the same architecture that the management node is. So you normally do not need to run the B -command yourself. Presently, only the arch x86_64 is supported. +command yourself. + +If you do run B to add custom utilities to your boot root image, and you have an xCAT Hierarchical Cluster with service nodes that each have a local /tftpboot directory (site sharedtftp=0), you will also need to copy the generated root image to each service node. + + +Presently, only the arch x86_64 is supported. =head1 OPTIONS diff --git a/xCAT-client/pods/man8/tabprune.8.pod b/xCAT-client/pods/man8/tabprune.8.pod index 659b6eb4f..6f3339978 100644 --- a/xCAT-client/pods/man8/tabprune.8.pod +++ b/xCAT-client/pods/man8/tabprune.8.pod @@ -6,11 +6,13 @@ B - Deletes records from the eventlog,auditlog,isnm_perf,isnm_perf_sum B B [B<-V>] B<-i> I |B<-n> I | B<-p> I | B<-d> I | B<-a> +B B B<-a> + B [B<-h>|B<--help>] [B<-v>|B<--version>] =head1 DESCRIPTION -The tabprune command is used to delete records from the auditlog,eventlog,isnm_perf,isnm_perf_sum tables. As an option, the table header and all the rows pruned from the specified table will be displayed in CSV (comma separated values) format. +The tabprune command is used to delete records from the auditlog,eventlog,isnm_perf,isnm_perf_sum tables. As an option, the table header and all the rows pruned from the specified table will be displayed in CSV (comma separated values) format. The all records options (-a) can be used on any xCAT table. =head1 OPTIONS @@ -27,7 +29,7 @@ you want to redirect them to a file to archive them. =item B<-a> -Remove all records. +Remove all records from the input table name. This option can be used on any xCAT table. =item B<-i> I diff --git a/xCAT-client/xCAT-client.spec b/xCAT-client/xCAT-client.spec index a76dd8ef2..de9e92341 100644 --- a/xCAT-client/xCAT-client.spec +++ b/xCAT-client/xCAT-client.spec @@ -180,6 +180,9 @@ ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/monshow ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/sinv ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/rollupdate ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/runrollupdate +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/mkzone +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/chzone +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/rmzone ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/webrun ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/ilitefile ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/liteimg diff --git a/xCAT-genesis-builder/buildrpm b/xCAT-genesis-builder/buildrpm index a5214cc91..aa78cb3c8 100755 --- a/xCAT-genesis-builder/buildrpm +++ b/xCAT-genesis-builder/buildrpm @@ -25,6 +25,14 @@ if [ "$HOSTOS" = "mcp" ]; then sed -i 's/ kexec//' $DRACUTMODDIR/install sed -i 's/ klogd//' $DRACUTMODDIR/install sed -i 's/ mdadm//' $DRACUTMODDIR/install + + # These timezone files are not available in the latest mcp build + sed -i 's/dracut_install \/usr\/share\/zoneinfo\/posix\/Asia\/Riyadh87//' $DRACUTMODDIR/install + sed -i 's/dracut_install \/usr\/share\/zoneinfo\/posix\/Asia\/Riyadh88//' $DRACUTMODDIR/install + sed -i 's/dracut_install \/usr\/share\/zoneinfo\/posix\/Asia\/Riyadh89//' $DRACUTMODDIR/install + sed -i 's/dracut_install \/usr\/share\/zoneinfo\/posix\/Mideast\/Riyadh87//' $DRACUTMODDIR/install + sed -i 's/dracut_install \/usr\/share\/zoneinfo\/posix\/Mideast\/Riyadh88//' $DRACUTMODDIR/install + sed -i 's/dracut_install \/usr\/share\/zoneinfo\/posix\/Mideast\/Riyadh89//' $DRACUTMODDIR/install fi mkdir -p /tmp/xcatgenesis.$$/opt/xcat/share/xcat/netboot/genesis/`uname -m`/fs diff --git a/xCAT-genesis-builder/install b/xCAT-genesis-builder/install index 1ee268a35..62db3a414 100755 --- a/xCAT-genesis-builder/install +++ b/xCAT-genesis-builder/install @@ -253,9 +253,6 @@ dracut_install /usr/share/zoneinfo/posix/America/Knox_IN dracut_install /usr/share/zoneinfo/posix/America/Goose_Bay dracut_install /usr/share/zoneinfo/posix/EET dracut_install /usr/share/zoneinfo/posix/EST5EDT -dracut_install /usr/share/zoneinfo/posix/Mideast/Riyadh89 -dracut_install /usr/share/zoneinfo/posix/Mideast/Riyadh88 -dracut_install /usr/share/zoneinfo/posix/Mideast/Riyadh87 dracut_install /usr/share/zoneinfo/posix/MST dracut_install /usr/share/zoneinfo/posix/Iceland dracut_install /usr/share/zoneinfo/posix/Atlantic/Faeroe @@ -396,7 +393,6 @@ dracut_install /usr/share/zoneinfo/posix/NZ-CHAT dracut_install /usr/share/zoneinfo/posix/Asia/Istanbul dracut_install /usr/share/zoneinfo/posix/Asia/Kuwait dracut_install /usr/share/zoneinfo/posix/Asia/Saigon -dracut_install /usr/share/zoneinfo/posix/Asia/Riyadh89 dracut_install /usr/share/zoneinfo/posix/Asia/Urumqi dracut_install /usr/share/zoneinfo/posix/Asia/Brunei dracut_install /usr/share/zoneinfo/posix/Asia/Ujung_Pandang @@ -438,7 +434,6 @@ dracut_install /usr/share/zoneinfo/posix/Asia/Tokyo dracut_install /usr/share/zoneinfo/posix/Asia/Macao dracut_install /usr/share/zoneinfo/posix/Asia/Riyadh dracut_install /usr/share/zoneinfo/posix/Asia/Rangoon -dracut_install /usr/share/zoneinfo/posix/Asia/Riyadh88 dracut_install /usr/share/zoneinfo/posix/Asia/Jakarta dracut_install /usr/share/zoneinfo/posix/Asia/Aden dracut_install /usr/share/zoneinfo/posix/Asia/Calcutta @@ -476,7 +471,6 @@ dracut_install /usr/share/zoneinfo/posix/Asia/Tel_Aviv dracut_install /usr/share/zoneinfo/posix/Asia/Taipei dracut_install /usr/share/zoneinfo/posix/Asia/Kabul dracut_install /usr/share/zoneinfo/posix/Asia/Macau -dracut_install /usr/share/zoneinfo/posix/Asia/Riyadh87 dracut_install /usr/share/zoneinfo/posix/Asia/Choibalsan dracut_install /usr/share/zoneinfo/posix/Asia/Vientiane dracut_install /usr/share/zoneinfo/posix/Asia/Dacca diff --git a/xCAT-genesis-builder/installkernel b/xCAT-genesis-builder/installkernel index cfbfc0fd3..fbe7b4edb 100755 --- a/xCAT-genesis-builder/installkernel +++ b/xCAT-genesis-builder/installkernel @@ -1,6 +1,6 @@ #!/bin/bash instmods nfs sunrpc -instmods e1000 e1000e virtio_net igb enic ines sfc mlx4_en cxgb3 cxgb4 tg3 bnx2 bnx2x bna ixgb ixgbe qlge mptsas mpt2sas ata_piix megaraid_sas virtio_blk ahci ibmaem xhci-hcd sd_mod pmcraid be2net vfat ext3 ext4 btrfs reiserfs usb_storage scsi_wait_scan kvm kvm-intel kvm-amd ipmi_si ipmi_devintf +instmods e1000 e1000e virtio_net igb enic ines sfc mlx4_en cxgb3 cxgb4 tg3 bnx2 bnx2x bna ixgb ixgbe qlge mptsas mpt2sas mpt3sas ata_piix megaraid_sas virtio_blk ahci ibmaem xhci-hcd sd_mod pmcraid be2net vfat ext3 ext4 btrfs reiserfs usb_storage scsi_wait_scan kvm kvm-intel kvm-amd ipmi_si ipmi_devintf instmods macvlan macvtap 8021q bridge bonding vmxnet3 cpufreq_ondemand acpi-cpufreq powernow-k8 cdc_ether instmods mptctl #LSI firmware management requires this instmods mlx4_ib ib_umad #make the mellanox ib available enough to examine /sys diff --git a/xCAT-genesis-builder/xCAT-genesis-base.spec b/xCAT-genesis-builder/xCAT-genesis-base.spec old mode 100644 new mode 100755 index 6187e76e9..dff9dc327 --- a/xCAT-genesis-builder/xCAT-genesis-base.spec +++ b/xCAT-genesis-builder/xCAT-genesis-base.spec @@ -59,4 +59,4 @@ fi %Files %defattr(-,root,root) -/ +/opt/xcat/share/xcat/netboot/genesis/%{tarch} diff --git a/xCAT-genesis-builder/xcat-cmdline.sh b/xCAT-genesis-builder/xcat-cmdline.sh index c0ce5b519..0b60f30d9 100644 --- a/xCAT-genesis-builder/xcat-cmdline.sh +++ b/xCAT-genesis-builder/xcat-cmdline.sh @@ -5,6 +5,7 @@ clear echo PS1="'"'[xCAT Genesis running on \H \w]\$ '"'" > /.bashrc echo PS1="'"'[xCAT Genesis running on \H \w]\$ '"'" > /.bash_profile mkdir -p /etc/ssh +mkdir -p /var/tmp/ mkdir -p /var/empty/sshd echo root:x:0:0::/:/bin/bash >> /etc/passwd echo sshd:x:30:30:SSH User:/var/empty/sshd:/sbin/nologin >> /etc/passwd diff --git a/xCAT-genesis-scripts/bin/bmcsetup b/xCAT-genesis-scripts/bin/bmcsetup index eeac319af..79c46ee51 100755 --- a/xCAT-genesis-scripts/bin/bmcsetup +++ b/xCAT-genesis-scripts/bin/bmcsetup @@ -185,7 +185,7 @@ for bmcu in $BMCUS; do if [ "$bmcu" = "" ]; then continue; fi DISABLEUSERS="1 2 3 4" if [ ! -z "$LOCKEDUSERS" ]; then - USERSLOT=`ipmitool -d $idev user list $LANCHAN |grep -v ^ID|awk '{print $1 " " $2}'|grep " $BMCUS"|awk '{print $1}'` + USERSLOT=`ipmitool -d $idev user list $LANCHAN |grep -v ^ID|awk '{print $1 " " $2}'|grep -w "$BMCUS"|awk '{print $1}'` if [ -z "$USERSLOT" ]; then USERSLOT=4 fi @@ -220,7 +220,7 @@ done TRIES=0 # Last param in ipmitool user priv is the channel to set it on. # Penguin boxes are all channel 2 -CURRPRIV=`ipmitool -d $idev user list 1|grep ^$USERSLOT|awk '{print $6}'` +CURRPRIV=`ipmitool -d $idev user list $LANCHAN|grep ^$USERSLOT|awk '{print $6}'` if [ "$CURRPRIV" != "ADMINISTRATOR" ]; then while ! ipmitool -d $idev user priv $USERSLOT 4 $LANCHAN; do sleep 1 diff --git a/xCAT-genesis-scripts/bin/doxcat b/xCAT-genesis-scripts/bin/doxcat index af49141e3..4a383982f 100755 --- a/xCAT-genesis-scripts/bin/doxcat +++ b/xCAT-genesis-scripts/bin/doxcat @@ -103,7 +103,9 @@ done echo -n "Acquired IPv4 address on $bootnic: " ip addr show dev $bootnic|grep -v 'scope link'|grep -v 'dynamic'|grep -v inet6|grep inet|awk '{print $2}' ntpd -g -x -(while ! ntpq -c "rv 0 state"|grep 'state=4' > /dev/null; do sleep 1; done; hwclock --systohc) & +# rv 0 state does not work with the new ntp versions +#(while ! ntpq -c "rv 0 state"|grep 'state=4' > /dev/null; do sleep 1; done; hwclock --systohc) & +(while [ "`ntpq -c \"rv 0 offset\" | grep \"offset=\" | awk -F \"=\" '{print $2}' | awk -F \".\" '{print $1}' | sed s/-//`" -ge 1000 ]; do sleep 1; done; hwclock --systohc) & if dmidecode|grep IPMI > /dev/null; then modprobe ipmi_si modprobe ipmi_devintf diff --git a/xCAT-server/debian/control b/xCAT-server/debian/control index 64639f825..759807276 100644 --- a/xCAT-server/debian/control +++ b/xCAT-server/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.7.2 Package: xcat-server Architecture: all -Depends: ${perl:Depends}, perl-xcat (>= 2.5.0-1), xcat-client (>= 2.5.0-1), libsys-syslog-perl, libio-socket-ssl-perl, libxml-simple-perl, make, libdbd-sqlite3-perl, libexpect-perl, libnet-dns-perl, libsoap-lite-perl, libxml-libxml-perl, libsnmp-perl, debootstrap +Depends: ${perl:Depends}, perl-xcat (>= 2.5.0-1), xcat-client (>= 2.5.0-1), libsys-syslog-perl, libio-socket-ssl-perl, libxml-simple-perl, make, libdbd-sqlite3-perl, libexpect-perl, libnet-dns-perl, libsoap-lite-perl, libxml-libxml-perl, libsnmp-perl, debootstrap,libcrypt-rijndael-perl,libcrypt-cbc-perl Description: Server and configuration utilities of the xCAT management project xCAT-server provides the core server and configuration management components of xCAT. This package should be installed on your management server diff --git a/xCAT-server/etc/init.d/xcatd b/xCAT-server/etc/init.d/xcatd index 282f360a5..493582c2c 100755 --- a/xCAT-server/etc/init.d/xcatd +++ b/xCAT-server/etc/init.d/xcatd @@ -37,7 +37,12 @@ RHFailure() } MStatus() { - ps ax|grep -v grep|grep xcatd: > /dev/null 2>&1 + PID=`cat /var/run/xcatd.pid` + if [ -z "$PID" ]; then + echo "xCAT service is not running" + return 3 + fi + ps $PID|grep xcatd: > /dev/null 2>&1 if [ "$?" = "0" ]; then RVAL=0 echo "xCAT service is running" diff --git a/xCAT-server/lib/perl/xCAT/IPMI.pm b/xCAT-server/lib/perl/xCAT/IPMI.pm index 1d9ad78bd..3afb337cc 100644 --- a/xCAT-server/lib/perl/xCAT/IPMI.pm +++ b/xCAT-server/lib/perl/xCAT/IPMI.pm @@ -378,7 +378,6 @@ sub open_rmcpplus_request { 0,0,0,8,1,0,0,0, #table 13-17, request sha 1,0,0,8,1,0,0,0); #sha integrity push @payload,(2,0,0,8,1,0,0,0); # aes - } $self->{sessionestablishmentcontext} = STATE_OPENSESSION; $self->sendpayload(payload=>\@payload,type=>$payload_types{'rmcpplusopenreq'}); } diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 49f5fcd1c..4a96e9274 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -16,6 +16,7 @@ use xCAT::Utils; use xCAT::TableUtils; use xCAT::Template; use xCAT::SvrUtils; +use xCAT::Zone; #use Data::Dumper; use File::Basename; use Socket; @@ -186,10 +187,16 @@ sub makescript { if($entries[0]) { $installroot = $entries[0]; } + # Location of the customized template my $tmpl="$installroot/postscripts/mypostscript.tmpl"; - + + # if not customized template use the default unless ( -r $tmpl) { $tmpl="$::XCATROOT/share/xcat/templates/mypostscript/mypostscript.tmpl"; + } else { # using customized template + # need to update with new added exports for this release + addexports($tmpl,$callback); + } unless ( -r "$tmpl") { @@ -367,6 +374,16 @@ sub makescript { } $cloudinfo_hash = getcloudinfo($cloud_module_name, $cloud_exists); } + + # see if we are using zones. If we are then sshbetweennodes comes from the zone table not + # from the site table + my $usingzones; + if (xCAT::Zone->usingzones) { + $usingzones=1; + } else { + $usingzones=0; + } + foreach my $n (@$nodes ) { $node = $n; @@ -477,9 +494,21 @@ sub makescript { # for #INCLUDE_POSTBOOTSCRIPTS_LIST# my $postbootscripts; $postbootscripts = getPostbootScripts($node, $osimgname, $script_hash); + + # if using zones then must go to the zone.sshbetweennodes + # else go to site.sshbetweennodes + my $enablesshbetweennodes; + my $zonename="\'\'"; + if ($usingzones) { + $enablesshbetweennodes = enableSSHbetweennodeszones($node,$callback); + my $tmpzonename = xCAT::Zone->getmyzonename($node,$callback); + $zonename="\'"; + $zonename .= $tmpzonename; + $zonename .="\'"; - my $enablesshbetweennodes = enableSSHbetweennodes($node, \%::GLOBAL_SN_HASH, $groups_hash); - + } else { + $enablesshbetweennodes = enableSSHbetweennodes($node, \%::GLOBAL_SN_HASH, $groups_hash); + } my @clients; my $cfgres; my $cloudres; @@ -512,6 +541,7 @@ sub makescript { $inc =~ s/#CLOUDINFO_EXPORT#/$cloudres/eg; $inc =~ s/\$ENABLESSHBETWEENNODES/$enablesshbetweennodes/eg; + $inc =~ s/\$ZONENAME/$zonename/eg; $inc =~ s/\$NSETSTATE/$nodesetstate/eg; #$inc =~ s/#COMMAND:([^#]+)#/command($1)/eg; @@ -566,6 +596,69 @@ sub makescript { } } +#---------------------------------------------------------------------------- + +=head3 addexports + + + As we change the default mypostscript.tmpl, this routine will update + and existing customized template with the information + addexports($tmpl, $callback); + + +=cut + +#----------------------------------------------------------------------------- +sub addexports +{ + + my $tmplfile = shift; + my $callback = shift; + # check for ZONENAME + my $cmd="cat $tmplfile \| grep ZONENAME"; + my $result = xCAT::Utils->runcmd($cmd, -1); + if ($::RUNCMD_RC != 0) { # ZONENAME not in the customized template + $cmd = "cp $tmplfile $tmplfile.backup"; # backup the original + xCAT::Utils->runcmd($cmd, -1); + my $insertstr='ZONENAME=$ZONENAME'; + my $insertstr2="export ZONENAME"; + + $cmd = "awk '{gsub(\"export ENABLESSHBETWEENNODES\",\"export ENABLESSHBETWEENNODES\\n$insertstr\\n$insertstr2 \"); print}' $tmplfile > $tmplfile.xcat"; + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + + my $rsp; + $rsp->{data}->[0] = + " Update of the $tmplfile file failed."; + xCAT::MsgUtils->message("SE", $rsp, $callback); + return 1; + } + $cmd = "cp -p $tmplfile.xcat $tmplfile "; # copy back the modified file + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + + my $rsp; + $rsp->{data}->[0] = + " $cmd failed."; + xCAT::MsgUtils->message("SE", $rsp, $callback); + return 1; + } + $cmd = "rm $tmplfile.xcat "; + xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + + my $rsp; + $rsp->{data}->[0] = + " $cmd failed."; + xCAT::MsgUtils->message("SE", $rsp, $callback); + } + + } + return 0; +} sub getservicenode { # reads all nodes from the service node table @@ -792,7 +885,7 @@ sub getsshbetweennodes Error: none Example: - my $enable = xCAT::TableUtils->enableSSH($node); + my $enable = xCAT::TableUtils->enableSSHbetweennodes($node,$sn_hash, $groups_hash); Comments: =cut @@ -818,6 +911,48 @@ sub enableSSHbetweennodes } +#------------------------------------------------------------------------------- + +=head3 enableSSHbetweennodeszones + Description: return how to fill in the ENABLESSHBETWEENNODES export in the mypostscript file + based on the setting in the zone table sshbetweennodes attribute + Arguments: + $node + $callback + Returns: + 1 = enable ssh + 0 = do not enable ssh + Globals: + none + Error: + none + Example: + my $enable = xCAT::TableUtils->enableSSHbetweennodeszones($node); + Comments: + +=cut + +#----------------------------------------------------------------------------- + +sub enableSSHbetweennodeszones +{ + + my $node = shift; + my $callback = shift; + my $result; + + my $enablessh=xCAT::Zone->enableSSHbetweennodes($node,$callback); + if ($enablessh == 1) { + $result = "'YES'"; + } else { + $result = "'NO'"; + } + + return $result; +} + + + @@ -1259,7 +1394,9 @@ sub collect_all_attribs_for_tables_in_template $::GLOBAL_TAB_HASH{$tabname}{$node}{$attrib} = $ent->{$node}->[0]->{$attrib}; #for noderes.xcatmaster - if ($tabname =~ /^noderes$/ && $attrib =~ /^xcatmaster$/ && ! exists($::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster})) + if ($tabname =~ /^noderes$/ && $attrib =~ /^xcatmaster$/ && + ( ! exists($::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster}) || + $::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster} == "" ) ) { my $value; $value = xCAT::NetworkUtils->my_ip_facing($node); diff --git a/xCAT-server/lib/perl/xCAT/RShellAPI.pm b/xCAT-server/lib/perl/xCAT/RShellAPI.pm index 44de8b1f5..e6fbdad1a 100644 --- a/xCAT-server/lib/perl/xCAT/RShellAPI.pm +++ b/xCAT-server/lib/perl/xCAT/RShellAPI.pm @@ -115,6 +115,7 @@ sub run_remote_shell_api { my $rc=1; if ($t) { #Wait for command prompt + $t->print("\t"); my ($prematch, $match) = $t->waitfor(Match => '/login[: ]*$/i', Match => '/username[: ]*$/i', Match => '/password[: ]*$/i', diff --git a/xCAT-server/lib/perl/xCAT/SvrUtils.pm b/xCAT-server/lib/perl/xCAT/SvrUtils.pm index 7193ac58f..483b80a18 100644 --- a/xCAT-server/lib/perl/xCAT/SvrUtils.pm +++ b/xCAT-server/lib/perl/xCAT/SvrUtils.pm @@ -662,7 +662,7 @@ sub update_tables_with_templates #get the pkglist file my $pkglistfile=get_pkglist_file_name($cuspath, $profile, $osver, $arch); - if (!$pkglistfile) { $pkglistfile=get_pkglist_file_name($defpath, $profile, $osver, $arch);} + if (!$pkglistfile) { $pkglistfile=get_pkglist_file_name($defpath, $profile, $osver, $arch,$genos);} #now update the db if (!$osimagetab) { diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index 0f86bab18..3ba3117c4 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -14,6 +14,7 @@ use xCAT::ADUtils; #to allow setting of one-time machine passwords use xCAT::Utils; use xCAT::TableUtils; use xCAT::NetworkUtils; +use XML::Simple; BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; @@ -103,6 +104,8 @@ sub subvars { $ENV{NODESTATUS}=$tmp; } + + #replace the env with the right value so that correct include files can be found $inc =~ s/#ENV:([^#]+)#/envvar($1)/eg; @@ -229,6 +232,7 @@ sub subvars { $inc =~ s/#CRYPT:([^:]+):([^:]+):([^#]+)#/crydb($1,$2,$3)/eg; $inc =~ s/#COMMAND:([^#]+)#/command($1)/eg; $inc =~ s/#KICKSTARTNET#/kickstartnetwork()/eg; + $inc =~ s/#YAST2NET#/yast2network()/eg; $inc =~ s/#ESXIPV6SETUP#/esxipv6setup()/eg; $inc =~ s/#WINTIMEZONE#/xCAT::TZUtils::get_wintimezone()/eg; $inc =~ s/#WINPRODKEY:([^#]+)#/get_win_prodkey($1)/eg; @@ -239,6 +243,7 @@ sub subvars { $inc =~ s/#WINDISABLENULLADMIN#/windows_disable_null_admin()/eg; $inc =~ s/#MANAGEDADDRESSMODE#/managed_address_mode()/eg; $inc =~ s/#HOSTNAME#/$node/g; + $inc =~ s/#GETNODEDOMAIN:([^#]+)#/get_node_domain($1)/eg; my $nrtab = xCAT::Table->new("noderes"); my $tftpserver = $nrtab->getNodeAttribs($node, ['tftpserver']); @@ -271,7 +276,9 @@ sub subvars { my $tempstr = "%include /tmp/partitionfile\n"; $inc =~ s/#XCAT_PARTITION_START#[\s\S]*#XCAT_PARTITION_END#/$tempstr/; #modify the content in the file, and write into %pre part - $partcontent = "cat > /tmp/partscript << EOFEOF\n" . $partcontent . "\nEOFEOF\n"; + #$partcontent = "cat > /tmp/partscript << EOFEOF\n" . $partcontent . "\nEOFEOF\n"; + $partcontent = "echo " . "'". $partcontent . "'" . ">/tmp/partscript\n"; + $partcontent .= "chmod 755 /tmp/partscript\n"; $partcontent .= "/tmp/partscript\n"; #replace the #XCA_PARTITION_SCRIPT# @@ -281,7 +288,8 @@ sub subvars { elsif ($inc =~ //){ my $tempstr = "XCATPARTITIONTEMP"; $inc =~ s/[\s\S]*/$tempstr/; - $partcontent = "cat > /tmp/partscript << EOFEOF\n" . $partcontent . "\nEOFEOF\n"; + #$partcontent = "cat > /tmp/partscript << EOFEOF\n" . $partcontent . "\nEOFEOF\n"; + $partcontent = "echo " . "'". $partcontent . "'" . ">/tmp/partscript\n"; $partcontent .= "chmod 755 /tmp/partscript\n"; $partcontent .= "/tmp/partscript\n"; $inc =~ s/#XCA_PARTITION_SCRIPT#/$partcontent/; @@ -607,6 +615,22 @@ sub get_win_prodkey { sub managed_address_mode { return $::XCATSITEVALS{managedaddressmode}; } + + +sub get_node_domain { + my $lcnode=shift; + if ( $lcnode eq 'THISNODE' ){ + $lcnode=$node; + } + + my $nd = xCAT::NetworkUtils->getNodeDomains([$lcnode]); + my %nodedomains = %$nd; + my $domain=$nodedomains{$lcnode}; + + return $domain; + +} + sub esxipv6setup { if (not $::XCATSITEVALS{managedaddressmode} or $::XCATSITEVALS{managedaddressmode} =~ /v4/) { return ""; } # blank line for ipv4 schemes my $v6addr; @@ -632,9 +656,12 @@ sub esxipv6setup { return 'esxcfg-vmknic -i '.$v6addr.'/64 "Management Network"'." #ESXISTATICV6\n"; } + + + sub kickstartnetwork { - my $line = "network --onboot=yes --bootproto="; - my $hoststab; + my $line = "network --onboot=yes --bootproto="; + my $hoststab; my $mactab = xCAT::Table->new('mac',-create=>0); unless ($mactab) { die "mac table should always exist prior to template processing when doing autoula"; } my $ent = $mactab->getNodeAttribs($node,['mac'],prefetchcache=>1); @@ -648,12 +675,258 @@ sub kickstartnetwork { $hoststab->setNodeAttribs($node,{ip=>$ulaaddr}); $line .= $ulaaddr; } elsif ($::XCATSITEVALS{managedaddressmode} =~ /static/) { - return "#KSNET static unsupported"; + my ($ipaddr,$hostname,$gateway,$netmask)=xCAT::NetworkUtils->getNodeNetworkCfg($node); + unless($ipaddr) { die "cannot resolve the network configuration of $node"; } + + if($gateway eq ''){ + $gateway = xCAT::NetworkUtils->my_ip_facing($ipaddr); + } + + $line .="static --device=$suffix --ip=$ipaddr --netmask=$netmask --gateway=$gateway --hostname=$hostname "; + + my %nameservers=%{xCAT::NetworkUtils->getNodeNameservers([$node])}; + my @nameserverARR=split (",",$nameservers{$node}); + my @nameserversIP; + foreach (@nameserverARR) + { + my $ip; + if($_ eq ''){ + $ip = xCAT::NetworkUtils->my_ip_facing($gateway); + }else{ + (undef,$ip) = xCAT::NetworkUtils->gethostnameandip($_); + } + push @nameserversIP, $ip; + + } + #there is no network option to set dns search domain in kickstart, it will be set in %post + if (scalar @nameserversIP) { + $line .=" --nameserver=". join(",",@nameserversIP); + } + + + #return "#KSNET static unsupported"; } else { $line .= "dhcp --device=$suffix"; } return $line; } + + +sub yast2network { + my $line; + my $hoststab; + my $mactab = xCAT::Table->new('mac',-create=>0); + unless ($mactab) { die "mac table should always exist prior to template processing when doing autoula"; } + my $ent = $mactab->getNodeAttribs($node,['mac'],prefetchcache=>1); + unless ($ent and $ent->{mac}) { die "missing mac data for $node"; } + my $suffix = $ent->{mac}; + $suffix = lc($suffix); + if ($::XCATSITEVALS{managedaddressmode} eq "autoula") { + #TODO + return "#YAST2NET autoula unsupported" + } elsif ($::XCATSITEVALS{managedaddressmode} =~ /static/) { + my ($ipaddr,$hostname,$gateway,$netmask)=xCAT::NetworkUtils->getNodeNetworkCfg($node); + unless($ipaddr) { die "cannot resolve the network configuration of $node"; } + + if($gateway eq ''){ + $gateway = xCAT::NetworkUtils->my_ip_facing($ipaddr); + } + + my %nameservers=%{xCAT::NetworkUtils->getNodeNameservers([$node])}; + + my @nameserverARR=split (",",$nameservers{$node}); + + my @nameserversIP; + foreach (@nameserverARR) + { + my $ip; + if($_ eq ''){ + $ip = xCAT::NetworkUtils->my_ip_facing($gateway); + }else{ + (undef,$ip) = xCAT::NetworkUtils->gethostnameandip($_); + } + push @nameserversIP, $ip; + + } + + # get the domains for each node - one call for all nodes in hosts file + my $nd = xCAT::NetworkUtils->getNodeDomains([$node]); + my %nodedomains = %$nd; + my $domain=$nodedomains{$node}; + my $networkhash={ + 'networking' => [ + { + 'dns' => [ + { + 'domain' => [ + "$domain" + ], + 'dhcp_hostname' => [ + { + 'content' => 'false', + 'config:type' => 'boolean' + } + ], + 'dhcp_resolv' => [ + { + 'content' => 'false', + 'config:type' => 'boolean' + } + ], + 'nameservers' => [ + { + 'config:type' => 'list', + 'nameserver' => [@nameserversIP] + } + ], + 'hostname' => [ + $hostname + ], + 'searchlist' => [ + { + 'search' => [ + $domain + ], + 'config:type' => 'list' + } + ] + } + ], + 'interfaces' => [ + { + 'interface' => [ + { + 'bootproto' => [ + 'static' + ], + 'startmode' => [ + 'onboot' + ], + 'netmask' => [ + $netmask + ], + 'device' => [ + 'eth0' + ], + 'ipaddr' => [ + $ipaddr + ] + } + ], + 'config:type' => 'list' + } + ], + 'routing' => [ + { + 'ip_forward' => [ + { + 'content' => 'false', + 'config:type' => 'boolean' + } + ], + 'routes' => [ + { + 'route' => [ + { + 'destination' => [ + 'default' + ], + 'gateway' => [ + $gateway + ], + 'netmask' => [ + '-' + ], + 'device' => [ + '-' + ] + } + ], + 'config:type' => 'list' + } + ] + } + ] + } + ] + }; + my $xml = new XML::Simple(KeepRoot => 1); + $line=$xml->XMLout($networkhash); + + #return "#KSNET static unsupported"; + } else { + + my $networkhash={ + 'networking' => [ + { + 'dns' => [ + { + 'domain' => [ + 'local' + ], + 'dhcp_hostname' => [ + { + 'content' => 'true', + 'config:type' => 'boolean' + } + ], + 'hostname' => [ + 'linux' + ], + 'dhcp_resolv' => [ + { + 'content' => 'true', + 'config:type' => 'boolean' + } + ] + } + ], + 'interfaces' => [ + { + 'interface' => [ + { + 'startmode' => [ + 'onboot' + ], + 'bootproto' => [ + 'dhcp' + ], + 'device' => [ + 'eth0' + ] + } + ], + 'config:type' => 'list' + } + ], + 'routing' => [ + { + 'ip_forward' => [ + { + 'content' => 'false', + 'config:type' => 'boolean' + } + ], + 'routes' => [ + { + 'config:type' => 'list' + } + ] + } + ] + } + ] + }; + + + my $xml = new XML::Simple(KeepRoot => 1); + $line=$xml->XMLout($networkhash); + + } + + return $line; +} + sub autoulaaddress { my $suffix = shift; my $prefix = $::XCATSITEVALS{autoulaprefix}; diff --git a/xCAT-server/lib/perl/xCAT/xcatd.pm b/xCAT-server/lib/perl/xCAT/xcatd.pm index ed76310dc..6dae1b684 100644 --- a/xCAT-server/lib/perl/xCAT/xcatd.pm +++ b/xCAT-server/lib/perl/xCAT/xcatd.pm @@ -10,6 +10,7 @@ use xCAT::Table; use xCAT::MsgUtils; use Data::Dumper; use xCAT::NodeRange; +use xCAT::Utils; #-------------------------------------------------------------------------------- =head1 xCAT::XCATD @@ -270,4 +271,67 @@ sub validate { xCAT::MsgUtils->message("S","Request matched no policy rule: peername=$peername, peerhost=$peerhost ".$request->{command}->[0]); return 0; } + +my $tokentimeout = 86400; # one day +# this subroutine search the token table +# 1. find the existed token entry for the user and reset the expire time +# 1.1. if not find existed token, create a new one and add it to token table +# 2. clean up the expired token +# +# this subroutine is called after the account has been authorized +sub gettoken { + my $class=shift; + my $req = shift; + + my $user = $req->{gettoken}->[0]->{username}->[0]; + my $tokentb = xCAT::Table->new('token'); + unless ($tokentb) { + return undef; + } + my $tokens = $tokentb->getAllEntries; + my $expiretime = time() + $tokentimeout; + foreach my $token (@{$tokens}) { + if ($token->{username} eq $user) { + #delete old token + $tokentb->delEntries({'tokenid'=>$token->{tokenid}}); + } else { + #clean the expired token + if ($token->{expire} > $expiretime) { + $tokentb->delEntries({'tokenid'=>$token->{tokenid}}); + } + } + } + + # create a new token for this request + my $uuid = xCAT::Utils->genUUID(); + $tokentb->setAttribs({tokenid=>$uuid, username => $user}, {expire => $expiretime}); + $tokentb->close(); + + return ($uuid, $expiretime); +} + +# verify the token has correct entry in token table and expire time is not exceeded. +sub verifytoken { + my $class=shift; + my $req = shift; + + my $tokenid = $req->{tokens}->[0]->{tokenid}->[0]; + my $tokentb = xCAT::Table->new('token'); + unless ($tokentb) { + return undef; + } + my $token = $tokentb->getAttribs({'tokenid' => $tokenid}, ('username', 'expire')); + if (defined ($token) && defined ($token->{'username'}) && defined ($token->{'expire'})) { + my $expiretime = time() + $tokentimeout; + if ($token->{'expire'} < time()) { + $tokentb->delEntries({'tokenid'=>$token->{tokenid}}); + return undef; + } else { + return $token->{'username'}; + } + } else { + return undef; + } +} + 1; diff --git a/xCAT-server/lib/xcat/plugins/AAsn.pm b/xCAT-server/lib/xcat/plugins/AAsn.pm index cebb2aea7..f06ded0b0 100755 --- a/xCAT-server/lib/xcat/plugins/AAsn.pm +++ b/xCAT-server/lib/xcat/plugins/AAsn.pm @@ -1215,6 +1215,7 @@ sub setup_TFTP push @{$netmethods{$hmhash{$_}->[0]->{netboot}}}, $_; } } + $::DISABLENODESETWARNING=1; # stop the warnings about using install/netboot etc $cmdref->{command}->[0] = "nodeset"; $cmdref->{inittime}->[0] = "1"; $cmdref->{arg}->[0] = "enact"; diff --git a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm index db8657ec3..b9c2f3364 100755 --- a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm +++ b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm @@ -380,7 +380,7 @@ sub processArgs { my $gotattrs = 0; - if (defined(@{$::args})) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } else { if ($::command eq "lsdef") { @@ -391,8 +391,9 @@ sub processArgs return 2; } } - if ( scalar(@{$::args}) eq 1 and $::args->[0] eq '-S') - { + if ( defined ($::args) && @{$::args} ) { + if ( scalar(@{$::args}) eq 1 and $::args->[0] eq '-S') + { if ($::command eq "lsdef") { push @ARGV, "-t"; push @ARGV, "node"; @@ -400,6 +401,7 @@ sub processArgs } else { return 2; } + } } if ($::command eq "lsdef") { @@ -538,7 +540,7 @@ sub processArgs # --nics is the equivalent of -i nicips,nichostnamesuffixes... if ($::opt_nics) { - $::opt_i="nicips,nichostnamesuffixes,nictypes,niccustomscripts,nicnetworks,nicaliases"; + $::opt_i="nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases"; } # -i and -s cannot be used together @@ -622,7 +624,8 @@ sub processArgs # if it has an "=" sign its an attr=val - we hope # - this will handle "attr= " - my ($attr, $value) = $a =~ /^\s*(\S+?)\s*=\s*(\S*.*)$/; + # The attribute itself might contain "space", like "nics.Local Connection Adapter 1" on windows + my ($attr, $value) = $a =~ /^\s*(.*?)\s*=\s*(\S*.*)$/; if (!defined($attr) || !defined($value)) { my $rsp; @@ -644,7 +647,7 @@ sub processArgs my $nicattrs = 0; foreach my $kattr (keys %::ATTRS) { - if ($kattr =~ /^nic\w+\.\w+$/) + if ($kattr =~ /^nic\w+\..*$/) { $nicattrs = 1; } @@ -850,7 +853,7 @@ sub processArgs foreach my $dattr (@dispattrs) { # lsdef -t node -h -i nicips.eth0 - if($dattr =~ /^(nic\w+)\.\w+$/) + if($dattr =~ /^(nic\w+)\..*$/) { $dattr = $1; } @@ -1148,7 +1151,7 @@ sub processArgs my $i = 0; for ($i=0; $i < (scalar @::AttrList) ; $i++ ) { - if($::AttrList[$i] =~ /^(nic\w+)\.(\w+)$/) + if($::AttrList[$i] =~ /^(nic\w+)\.(.*)$/) { $::AttrList[$i] = $1; push @{$::NicsAttrHash{$::AttrList[$i]}}, $2; @@ -1306,7 +1309,7 @@ sub defmk { my $attrorig = $attr; # nicips.eth0 => nicips - if ($attr =~ /^(nic\w+)\.\w+$/) + if ($attr =~ /^(nic\w+)\..*$/) { $attr = $1; } @@ -1950,7 +1953,7 @@ sub defch { my $attrorig = $attr; # nicips.eth0 => nicips - if ($attr =~ /^(nic\w+)\.\w+$/) + if ($attr =~ /^(nic\w+)\..*$/) { $attr = $1; } @@ -2465,15 +2468,21 @@ sub defch # give results my $rsp; - $rsp->{data}->[0] = - "The database was updated for the following objects:"; - xCAT::MsgUtils->message("I", $rsp, $::callback); + my $nodenum = scalar(keys %::FINALATTRS); + if ($nodenum) { + $rsp->{data}->[0] = + "The database was updated for the following objects:"; + xCAT::MsgUtils->message("I", $rsp, $::callback); - my $n = 1; - foreach my $o (sort(keys %::FINALATTRS)) - { - $rsp->{data}->[$n] = "$o\n"; - $n++; + my $n = 1; + foreach my $o (sort(keys %::FINALATTRS)) + { + $rsp->{data}->[$n] = "$o\n"; + $n++; + } + } else { + $rsp->{data}->[0] = + "No database was updated"; } xCAT::MsgUtils->message("I", $rsp, $::callback); } @@ -2481,8 +2490,13 @@ sub defch { my $rsp; my $nodenum = scalar(keys %::FINALATTRS); - $rsp->{data}->[0] = - "$nodenum object definitions have been created or modified."; + if ($nodenum) { + $rsp->{data}->[0] = + "$nodenum object definitions have been created or modified."; + } else { + $rsp->{data}->[0] = + "No object definitions have been created or modified."; + } xCAT::MsgUtils->message("I", $rsp, $::callback); if (scalar(keys %newobjects) > 0) { @@ -2630,6 +2644,9 @@ sub setFINALattrs { # special case for the nic* attributes # merge nic*.eth0, nic*.eth1 + unless(exists($::CLIATTRS{$objname})) { + next; + } if ($::CLIATTRS{$objname}{objtype} eq 'node') { # Even if only the nicips.eth0 is specified with CLI, @@ -2638,7 +2655,7 @@ sub setFINALattrs my %tmphash = (); foreach my $nodeattr (keys %{$::CLIATTRS{$objname}}) { - if ($nodeattr =~ /^(nic\w+)\.\w+$/) + if ($nodeattr =~ /^(nic\w+)\..*$/) { my $tmpnicattr = $1; if (!defined($tmphash{$tmpnicattr})) @@ -3411,7 +3428,7 @@ sub defls my $rsp; $rsp->{data}->[0] = "Could not find an object named \'$obj\' of type \'$type\'."; - xCAT::MsgUtils->message("I", $rsp, $::callback); + xCAT::MsgUtils->message("E", $rsp, $::callback); next; } } @@ -4027,7 +4044,7 @@ sub defmk_usage $rsp->{data}->[4] = " [-f | --force] [noderange] [attr=val [attr=val...]]"; $rsp->{data}->[5] = - " [-u provmethod= profile= [attr=value]]\n"; + " [-u provmethod= profile= [osvers=value] [osarch=value]]\n"; $rsp->{data}->[6] = "\nThe following data object types are supported by xCAT.\n"; my $n = 7; @@ -4077,7 +4094,7 @@ sub defch_usage $rsp->{data}->[5] = " [-w attr==val [-w attr=~val] ... ] [noderange] [attr=val [attr=val...]]\n"; $rsp->{data}->[6] = - " [-u [provmethod=]|[profile=]|[attr=value]]"; + " [-u [provmethod=]|[profile=]|[osvers=value]|[osarch=value]]"; $rsp->{data}->[7] = "\nThe following data object types are supported by xCAT.\n"; my $n = 8; diff --git a/xCAT-server/lib/xcat/plugins/FIP.pm b/xCAT-server/lib/xcat/plugins/FIP.pm index 144de0c9c..343b64a80 100644 --- a/xCAT-server/lib/xcat/plugins/FIP.pm +++ b/xCAT-server/lib/xcat/plugins/FIP.pm @@ -232,8 +232,7 @@ sub parse_args my $args = $request->{arg}; my $gotattrs = 0; my %opt =(); - - if (defined(@{$args})) { + if ( defined ($args) && @{$args}) { @ARGV = @{$args}; } else { return 2; diff --git a/xCAT-server/lib/xcat/plugins/aixinstall.pm b/xCAT-server/lib/xcat/plugins/aixinstall.pm index 04b45dff4..bc678607b 100644 --- a/xCAT-server/lib/xcat/plugins/aixinstall.pm +++ b/xCAT-server/lib/xcat/plugins/aixinstall.pm @@ -154,6 +154,13 @@ sub preprocess_request # - either the NIMprime attr of the site table or the management node my $nimprime = xCAT::InstUtils->getnimprime(); chomp $nimprime; + if (!defined($nimprime)) + { + my $rsp={}; + $rsp->{error}->[0] = "Could not determine nimprime. Check if nimprime defined in site table or site table master is not resolvable to the MN name."; + xCAT::MsgUtils->message("E", $rsp, $cb,1); + return undef; + } my $nimprimeip = xCAT::NetworkUtils->getipaddr($nimprime); if ($nimprimeip =~ /:/) #IPv6 { @@ -617,7 +624,7 @@ sub nimnodeset my $Sname = xCAT::InstUtils->myxCATname(); - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -1793,7 +1800,7 @@ sub chkosimage my $image_name; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -2260,7 +2267,7 @@ sub mknimimage my $dump_name; my $install_dir = xCAT::TableUtils->getInstallDir(); - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -5698,7 +5705,7 @@ sub prermnimimage my @servicenodes = (); # pass back list of service nodes my %imagedef; # pass back image def hash - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -6208,7 +6215,7 @@ sub rmnimimage %allsn = %{$nodehash}; } - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -7815,7 +7822,7 @@ sub prenimnodecust @nodelist = @$nodes; } - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -8053,7 +8060,7 @@ sub nimnodecust @nodelist = @$nodes; } - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -8210,7 +8217,7 @@ sub prenimnodeset my $subreq = shift; my $error = 0; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -9937,7 +9944,7 @@ sub define_SN_resource } my %attrs; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -10976,7 +10983,7 @@ sub mkdsklsnode # - just set global for now $::callback = $callback; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -12986,7 +12993,7 @@ sub make_SN_resource } my %attrs; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -13646,7 +13653,7 @@ sub prermdsklsnode { my $callback = shift; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -13756,7 +13763,7 @@ sub rmdsklsnode # - just set global for now $::callback = $callback; - if (defined(@{$::args})) + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } diff --git a/xCAT-server/lib/xcat/plugins/anaconda.pm b/xCAT-server/lib/xcat/plugins/anaconda.pm index 27921c8f5..87ce47bee 100644 --- a/xCAT-server/lib/xcat/plugins/anaconda.pm +++ b/xCAT-server/lib/xcat/plugins/anaconda.pm @@ -63,7 +63,7 @@ sub preprocess_request my @ents = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $site_ent = $ents[0]; unless ( defined($site_ent) - and ($site_ent =~ /no/i or $site_ent =~ /0/)) + and ($site_ent eq "no" or $site_ent eq "NO" or $site_ent eq "0")) { #unless requesting no sharedtftp, don't make hierarchical call @@ -257,6 +257,7 @@ sub mknetboot my $site_ent = $ents[0]; if (!defined($site_ent) || ($site_ent =~ /no/i) || ($site_ent =~ /0/)) { + if (!defined($::DISABLENODESETWARNING)) { # set by AAsn.pm $callback->( { warning => ["The options \"install\", \"netboot\", and \"statelite\" have been deprecated. They should continue to work in this release, but have not been tested as carefully, and some new functions are not available with these options. For full function and support, use \"nodeset osimage=\" instead."], @@ -264,6 +265,7 @@ sub mknetboot ); # Do not print this warning message multiple times last; + } } } } @@ -930,10 +932,6 @@ sub mknetboot ); } - #my $rc = xCAT::TableUtils->create_postscripts_tar(); - #if ( $rc != 0 ) { - # xCAT::MsgUtils->message( "S", "Error creating postscripts tar file." ); - #} } sub mkinstall @@ -1001,6 +999,7 @@ sub mkinstall my $site_ent = $ents[0]; if (!defined($site_ent) || ($site_ent =~ /no/i) || ($site_ent =~ /0/)) { + if (!defined($::DISABLENODESETWARNING)) { # set by AAsn.pm $callback->( { warning => ["The options \"install\", \"netboot\", and \"statelite\" have been deprecated. They should continue to work in this release, but have not been tested as carefully, and some new functions are not available with these options. For full function and support, use \"nodeset osimage=\" instead."], @@ -1008,6 +1007,7 @@ sub mkinstall ); # Do not print this warning message multiple times last; + } } } } @@ -1377,12 +1377,19 @@ sub mkinstall $instserver=$ent->{nfsserver}; } + if ($::XCATSITEVALS{managedaddressmode} =~ /static/){ + unless($instserver eq '!myipfn!'){ + my($host,$ip)=xCAT::NetworkUtils->gethostnameandip($instserver); + $instserver=$ip; + } + } my $httpprefix=$pkgdir; if ($installroot =~ /\/$/) { $httpprefix =~ s/^$installroot/\/install\//; } else { $httpprefix =~ s/^$installroot/\/install/; } + my $kcmdline = "quiet repo=$httpmethod://$instserver:$httpport$httpprefix ks=$httpmethod://" . $instserver . ":". $httpport @@ -1434,7 +1441,51 @@ sub mkinstall if($esxi){ $ksdev =~ s/eth/vmnic/g; } - $kcmdline .= " ksdevice=" . $ksdev; + unless ($ksdev eq "bootif" and $os =~ /7/) { + $kcmdline .= " ksdevice=" . $ksdev; + } + + #if site.managedaddressmode=static, specify the network configuration as kernel options + #to avoid multicast dhcp + if($::XCATSITEVALS{managedaddressmode} =~ /static/){ + my ($ipaddr,$hostname,$gateway,$netmask)=xCAT::NetworkUtils->getNodeNetworkCfg($node); + unless($ipaddr) { + $callback->( + { + error => [ + "cannot resolve the ip address of $node" + ], + errorcode => [1] + } + ); + } + + if($gateway eq ''){ + $gateway = xCAT::NetworkUtils->my_ip_facing($ipaddr); + } + + $kcmdline .=" ip=$ipaddr netmask=$netmask gateway=$gateway hostname=$hostname "; + + + my %nameservers=%{xCAT::NetworkUtils->getNodeNameservers([$node])}; + my @nameserverARR=split (",",$nameservers{$node}); + my @nameserversIP; + foreach (@nameserverARR) + { + my $ip; + if($_ eq ''){ + $ip = xCAT::NetworkUtils->my_ip_facing($gateway); + }else{ + (undef,$ip) = xCAT::NetworkUtils->gethostnameandip($_); + } + push @nameserversIP, $ip; + + } + + if(scalar @nameserversIP){ + $kcmdline .=" dns=".join(",",@nameserversIP); + } + } #TODO: dd= for driver disks if (defined($sent->{serialport})) @@ -1575,6 +1626,7 @@ sub mksysclone my $site_ent = $ents[0]; if (!defined($site_ent) || ($site_ent =~ /no/i) || ($site_ent =~ /0/)) { + if (!defined($::DISABLENODESETWARNING)) { # set by AAsn.pm $callback->( { warning => ["The options \"install\", \"netboot\", and \"statelite\" have been deprecated. They should continue to work in this release, but have not been tested as carefully, and some new functions are not available with these options. For full function and support, use \"nodeset osimage=\" instead."], @@ -1582,6 +1634,7 @@ sub mksysclone ); # Do not print this warning message multiple times last; + } } } } @@ -2025,6 +2078,18 @@ sub copycd $distname = "ol$1.$2"; } } + elsif ($desc =~ /^RHEL-(\d)\.(\d) ([^.]*)\./) { + my $edition = ""; + my $version = "$1.$2"; + my %editionmap = ( + "Server" => "s", + ); + $edition = $editionmap{$3}; + unless ($distname) + { + $distname = "rhel$edition$version"; + } + } elsif ($desc =~ /^Red Hat Enterprise Linux (\d)\.(\d)/) { my $edition; diff --git a/xCAT-server/lib/xcat/plugins/blade.pm b/xCAT-server/lib/xcat/plugins/blade.pm index 0a6e91568..a9fcc666a 100644 --- a/xCAT-server/lib/xcat/plugins/blade.pm +++ b/xCAT-server/lib/xcat/plugins/blade.pm @@ -4423,7 +4423,7 @@ sub process_request { if ($request->{mtm} and $request->{mtm} =~ /^(\w{4})/) { my $group = xCAT::data::ibmhwtypes::parse_group($request->{mtm}); if (defined($group)) { - xCAT::TableUtils->updatenodegroups($node, $group); + xCAT::TableUtils->updatenodegroups($node, $group.",all"); } } if ($mac) { diff --git a/xCAT-server/lib/xcat/plugins/copycds.pm b/xCAT-server/lib/xcat/plugins/copycds.pm index fa6062d09..92177972d 100644 --- a/xCAT-server/lib/xcat/plugins/copycds.pm +++ b/xCAT-server/lib/xcat/plugins/copycds.pm @@ -43,6 +43,7 @@ sub process_request { my $path=undef; my $noosimage=undef; my $nonoverwrite=undef; + my $specific=undef; $identified=0; $::CDMOUNTPATH="/var/run/xcat/mountpoint"; @@ -58,6 +59,7 @@ sub process_request { 'i|inspection' => \$inspection, 'p|path=s' => \$path, 'o|noosimage' => \$noosimage, + 's|specific' => \$specific, 'w|nonoverwrite' => \$nonoverwrite, ); if ($help) { @@ -143,6 +145,10 @@ sub process_request { { push @{$newreq->{arg}},("-p",$path); } + if($specific) + { + push @{$newreq->{arg}},("-s"); + } if($inspection) { diff --git a/xCAT-server/lib/xcat/plugins/credentials.pm b/xCAT-server/lib/xcat/plugins/credentials.pm index bc4f3c397..fcf3ebef8 100644 --- a/xCAT-server/lib/xcat/plugins/credentials.pm +++ b/xCAT-server/lib/xcat/plugins/credentials.pm @@ -28,6 +28,7 @@ use strict; use xCAT::Table; use Data::Dumper; use xCAT::NodeRange; +use xCAT::Zone; use IO::Socket::INET; use Time::HiRes qw(sleep); @@ -112,34 +113,71 @@ sub process_request } else { $root = "/root"; } + + foreach my $parm (@params_to_return) { + + # if paramter is ssh_root_key or ssh_root_pub_key then + # we need to see if a zonename is attached + # it comes in as ssh_root_key:zonename + # if zonename then we need to read the keys from the zone table sshkeydir attribute + + my $errorfindingkeys=0; + my $foundkeys=0; + my $sshrootkeydir="$root/.ssh"; # old default + if ((($parm =~ /^ssh_root_key/) || ($parm =~ /^ssh_root_pub_key/)) && ($foundkeys==0)){ + my ($rootkeyparm,$zonename) = split(/:/,$parm); + if ($zonename) { + $parm=$rootkeyparm; # take the zone off + `logger -t xCAT -p local4.info "credentials: The node is asking for zone:$zonename sshkeys ."`; + $sshrootkeydir = xCAT::Zone->getzonekeydir($zonename); + if ($sshrootkeydir == 1) { # error return + `logger -t xCAT -p local4.info "credentials: The node is asking for zone:$zonename sshkeys and the $zonename is not defined."`; + } else { + $foundkeys=1; # don't want to read the zone data twice + } + } + } - foreach (@params_to_return) { - - if (/ssh_root_key/) { - unless (-r "$root/.ssh/id_rsa") { + if ($parm =~ /ssh_root_key/) { + unless (-r "$sshrootkeydir/id_rsa") { push @{$rsp->{'error'}},"Unable to read root's private ssh key"; `logger -t xCAT -p local4.info "credentials: Unable to read root's private ssh key"` ; next; } - $tfilename = "$root/.ssh/id_rsa"; + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; + $tfilename = "$sshrootkeydir/id_rsa"; + `logger -t xCAT -p local4.info "credentials: The ssh root private key is in $tfilename."`; - } elsif (/xcat_server_cred/) { + } elsif ($parm =~ /ssh_root_pub_key/) { + unless (-r "$sshrootkeydir/id_rsa.pub") { + push @{$rsp->{'error'}},"Unable to read root's public ssh key"; + `logger -t xCAT -p local4.info "credentials: Unable to read root's public ssh key"` ; + next; + } + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; + $tfilename = "$sshrootkeydir/id_rsa.pub"; + `logger -t xCAT -p local4.info "credentials: The ssh root public key is in $tfilename."`; + + } elsif ($parm =~ /xcat_server_cred/) { unless (-r "/etc/xcat/cert/server-cred.pem") { push @{$rsp->{'error'}},"Unable to read xcat_server_cred"; `logger -t xCAT -p local4.info "credentials: Unable to read xcat_server_cred"` ; next; } + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; $tfilename = "/etc/xcat/cert/server-cred.pem"; - } elsif (/xcat_client_cred/ or /xcat_root_cred/) { + } elsif (($parm =~ /xcat_client_cred/) or ($parm =~ /xcat_root_cred/)) { unless (-r "$root/.xcat/client-cred.pem") { push @{$rsp->{'error'}},"Unable to read xcat_client_cred or xcat_root_cred"; `logger -t xCAT -p local4.info "credentials: Unable to read xcat_client_cred or xcat_root_cred"` ; next; } + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; $tfilename = "$root/.xcat/client-cred.pem"; - } elsif (/ssh_dsa_hostkey/) { + } elsif ($parm =~ /ssh_dsa_hostkey/) { + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; if (-r "/etc/xcat/hostkeys/$client/ssh_host_dsa_key") { $tfilename="/etc/xcat/hostkeys/$client/ssh_host_dsa_key"; } elsif (-r "/etc/xcat/hostkeys/ssh_host_dsa_key") { @@ -149,7 +187,8 @@ sub process_request `logger -t xCAT -p local4.info "credentials: Unable to read private DSA key"` ; next; } - } elsif (/ssh_rsa_hostkey/) { + } elsif ($parm =~ /ssh_rsa_hostkey/) { + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; if (-r "/etc/xcat/hostkeys/$client/ssh_host_rsa_key") { $tfilename="/etc/xcat/hostkeys/$client/ssh_host_rsa_key"; } elsif (-r "/etc/xcat/hostkeys/ssh_host_rsa_key") { @@ -159,7 +198,8 @@ sub process_request `logger -t xCAT -p local4.info "credentials: Unable to read private RSA key"` ; next; } - } elsif (/xcat_cfgloc/) { + } elsif ($parm =~ /xcat_cfgloc/) { + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; unless (-r "/etc/xcat/cfgloc") { push @{$rsp->{'error'}},"Unable to read /etc/xcat/cfgloc "; `logger -t xCAT -p local4.info "credentials: Unable to read /etc/xcat/cfgloc"` ; @@ -167,7 +207,8 @@ sub process_request } $tfilename = "/etc/xcat/cfgloc"; - } elsif (/krb5_keytab/) { #TODO: MUST RELAY TO MASTER + } elsif ($parm =~ /krb5_keytab/) { #TODO: MUST RELAY TO MASTER + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; my $princsuffix=$request->{'_xcat_clientfqdn'}->[0]; $ENV{KRB5CCNAME}="/tmp/xcat/krb5cc_xcat_$$"; system('kinit -S kadmin/admin -k -t /etc/xcat/krb5_pass xcat/admin'); @@ -188,10 +229,11 @@ sub process_request while (read($keytab,$buf,1140)) { $tabdata.=MIME::Base64::encode_base64($buf); } - push @{$rsp->{'data'}},{content=>[$tabdata],desc=>[$_]}; + push @{$rsp->{'data'}},{content=>[$tabdata],desc=>[$parm]}; unlink "/tmp/xcat/keytab.$$"; next; - } elsif (/x509cert/) { + } elsif ($parm =~ /x509cert/) { + `logger -t xCAT -p local4.info "credentials: sending $parm"` ; my $csr = $request->{'csr'}->[0]; my $csrfile; my $oldumask = umask 0077; @@ -243,7 +285,7 @@ sub process_request close($csrfile); unlink "/tmp/xcat/client.cert.$$"; my $certcontents = join('',@certdata); - push @{$rsp->{'data'}},{content=>[$certcontents],desc=>[$_]}; + push @{$rsp->{'data'}},{content=>[$certcontents],desc=>[$parm]}; } else { next; } @@ -253,7 +295,7 @@ sub process_request @filecontent=<$tmpfile>; close($tmpfile); $retdata = "\n".join('',@filecontent); - push @{$rsp->{'data'}},{content=>[$retdata],desc=>[$_]}; + push @{$rsp->{'data'}},{content=>[$retdata],desc=>[$parm]}; $retdata=""; @filecontent=(); } @@ -261,6 +303,7 @@ sub process_request if (defined $rsp->{data}->[0]) { #if we got the data from the file, send the data message to the client xCAT::MsgUtils->message("D", $rsp, $callback, 0); + return; }else { #if the file doesn't exist, send the error message to the client delete $rsp->{'data'}; diff --git a/xCAT-server/lib/xcat/plugins/ddns.pm b/xCAT-server/lib/xcat/plugins/ddns.pm index ee048d0ad..5d7f90473 100755 --- a/xCAT-server/lib/xcat/plugins/ddns.pm +++ b/xCAT-server/lib/xcat/plugins/ddns.pm @@ -51,7 +51,7 @@ sub getzonesfornet { die "Not supporting having a mask like $mask on an ipv6 network like $net"; } my $netnum= getipaddr($net,GetNumber=>1); - unless ($netnum) { return (); } + unless ($netnum) { return (); } $netnum->brsft(128-$maskbits); my $prefix=$netnum->as_hex(); my $nibbs=$maskbits/4; @@ -228,6 +228,9 @@ sub process_request { return; } } + if ($::XCATSITEVALS{externaldns}) { + $external=1; + } if ($help) { @@ -282,7 +285,6 @@ sub process_request { xCAT::SvrUtils::sendmsg([0,"Warning:SELINUX is not disabled. The makedns command will not be able to generate a complete DNS setup. Disable SELINUX and run the command again."], $callback); } - my @entries = xCAT::TableUtils->get_site_attribute("nameservers"); my $sitens = $entries[0]; unless ( defined($site_entry)) { @@ -295,7 +297,6 @@ sub process_request { unless ($networkstab) { xCAT::SvrUtils::sendmsg([1,'Unable to enumerate networks, try to run makenetworks'], $callback); } my @networks = $networkstab->getAllAttribs('net','mask','ddnsdomain','domain','nameservers'); - # exclude the net if it is using an external dns server. foreach my $net (@networks) { @@ -324,72 +325,73 @@ sub process_request { if ($allnodes) { #read all nodelist specified nodes } else { - if (not $request->{node} and $deletemode) { - #when this was permitted, it really ruined peoples' days - xCAT::SvrUtils::sendmsg([1,"makedns -d without noderange or -a is not supported"],$callback); - umask($oldmask); - return; - } - my @contents; - my $domain; - if ($request->{node}) { #leverage makehosts code to flesh out the options - require xCAT_plugin::hosts; - my @content1; - my @content2; - xCAT_plugin::hosts::add_hosts_content(nodelist=>$request->{node},callback=>$callback,hostsref=>\@content1); - xCAT_plugin::hosts::donics(nodes=>$request->{node},callback=>$callback,hostsref=>\@content2); + if (not $request->{node} and $deletemode) { + #when this was permitted, it really ruined peoples' days + xCAT::SvrUtils::sendmsg([1,"makedns -d without noderange or -a is not supported"],$callback); + umask($oldmask); + return; + } + my @contents; + my $domain; + if ($request->{node}) { #leverage makehosts code to flesh out the options + require xCAT_plugin::hosts; + my @content1; + my @content2; + xCAT_plugin::hosts::add_hosts_content(nodelist=>$request->{node},callback=>$callback,hostsref=>\@content1); + xCAT_plugin::hosts::donics(nodes=>$request->{node},callback=>$callback,hostsref=>\@content2); @contents = (@content1, @content2); - } else { - #legacy behavior, read from /etc/hosts - my $hostsfile; - open($hostsfile,"<","/etc/hosts"); - flock($hostsfile,LOCK_SH); - @contents = <$hostsfile>; - flock($hostsfile,LOCK_UN); - close($hostsfile); - } + } else { + #legacy behavior, read from /etc/hosts + my $hostsfile; + open($hostsfile,"<","/etc/hosts"); + flock($hostsfile,LOCK_SH); + @contents = <$hostsfile>; + flock($hostsfile,LOCK_UN); + close($hostsfile); + } my $addr; my $name; my $canonical; my $aliasstr; my @aliases; my $names; - my @hosts; - my %nodehash; - + my @hosts; + my %nodehash; + foreach (@contents) { - chomp; #no newline - s/#.*//; #strip comments; - s/^[ \t\n]*//; #remove leading whitespace - next unless ($_); #skip empty lines - ($addr,$names) = split /[ \t]+/,$_,2; + chomp; #no newline + s/#.*//; #strip comments; + s/^[ \t\n]*//; #remove leading whitespace + next unless ($_); #skip empty lines + ($addr,$names) = split /[ \t]+/,$_,2; + + if ($addr !~ /^\d+\.\d+\.\d+\.\d+$/ and $addr !~ /^[abcdef0123456789:]+$/) { + xCAT::SvrUtils::sendmsg(":Ignoring line $_ in /etc/hosts, address seems malformed.", $callback); + next; + } + unless ($names =~ /^[a-z0-9\. \t\n-]+$/i) { + xCAT::SvrUtils::sendmsg(":Ignoring line $_ in /etc/hosts, names $names contain invalid characters (valid characters include a through z, numbers and the '-', but not '_'", $callback); + next; + } + + my ($host, $ip) = xCAT::NetworkUtils->gethostnameandip($addr); + push @hosts, $host; + $nodehash{$addr}{names}=$names; + $nodehash{$addr}{host}=$host; + } - if ($addr !~ /^\d+\.\d+\.\d+\.\d+$/ and $addr !~ /^[abcdef0123456789:]+$/) { - xCAT::SvrUtils::sendmsg(":Ignoring line $_ in /etc/hosts, address seems malformed.", $callback); - next; - } - unless ($names =~ /^[a-z0-9\. \t\n-]+$/i) { - xCAT::SvrUtils::sendmsg(":Ignoring line $_ in /etc/hosts, names $names contain invalid characters (valid characters include a through z, numbers and the '-', but not '_'", $callback); - next; - } - - my ($host, $ip) = xCAT::NetworkUtils->gethostnameandip($addr); - push @hosts, $host; - $nodehash{$addr}{names}=$names; - $nodehash{$addr}{host}=$host; - } - - # get the domains for each node - one call for all nodes in hosts file - my $nd = xCAT::NetworkUtils->getNodeDomains(\@hosts); - my %nodedomains = %$nd; - - foreach my $n (keys %nodehash) { - $addr=$n; - $names=$nodehash{$n}{names}; - # - need domain for this node - my $host = $nodehash{$n}{host}; - $domain=$nodedomains{$host}; - unless ($domain =~ /^\./) { $domain = '.'.$domain; } + # get the domains for each node - one call for all nodes in hosts file + my $nd = xCAT::NetworkUtils->getNodeDomains(\@hosts); + my %nodedomains = %$nd; + + foreach my $n (keys %nodehash) { + $addr=$n; + $names=$nodehash{$n}{names}; + # - need domain for this node + my $host = $nodehash{$n}{host}; + $domain=$nodedomains{$host}; + # remove the first . at domain name since it's not accepted by high dns parser + if ($domain =~ /^\./) { $domain =~ s/^\.//;; } ($canonical,$aliasstr) = split /[ \t]+/,$names,2; if ($aliasstr) { @@ -403,13 +405,13 @@ sub process_request { xCAT::SvrUtils::sendmsg(":Handling $node in /etc/hosts.", $callback); unless ($canonical =~ /$domain/) { - $canonical.=$domain; + $canonical.=".".$domain; } - # for only the sake of comparison, ensure consistant dot suffix + # for only the sake of comparison, ensure consistant dot suffix unless ($canonical =~ /\.\z/) { $canonical .= '.' } foreach my $alias (@aliases) { unless ($alias =~ /$domain/) { - $alias .= $domain; + $alias .= ".".$domain; } unless ($alias =~ /\.\z/) { $alias .= '.'; @@ -417,13 +419,13 @@ sub process_request { if ($alias eq $canonical) { next; } - # remember alias for CNAM records later + # remember alias for CNAM records later $ctx->{aliases}->{$node}->{$alias}=1; } - + # exclude the nodes not belong to any nets defined in networks table # because only the nets defined in networks table will be add - # zones later. + # zones later. my $found = 0; foreach (@networks) { @@ -504,13 +506,15 @@ sub process_request { $ctx->{slaves}=\@slave_ips; } + $ctx->{domain} =~ s/^\.//; # remove . if it's the first char of domain name $ctx->{zonestotouch}->{$ctx->{domain}}=1; - foreach (@networks) { - if ($_->{domain}) { - $ctx->{zonestotouch}->{$_->{domain}}=1; - } - } - + foreach (@networks) { + if ($_->{domain}) { + $_->{domain} =~ s/^\.//; # remove . if it's the first char of domain name + $ctx->{zonestotouch}->{$_->{domain}}=1; + } + } + xCAT::SvrUtils::sendmsg("Getting reverse zones, this may take several minutes for a large cluster.", $callback); foreach (@nodes) { @@ -524,10 +528,10 @@ sub process_request { xCAT::SvrUtils::sendmsg("Completed getting reverse zones.", $callback); if (1) { - #TODO: function to detect and return 1 if the master server is - # DNS SOA for all the zones we care about here, we are examining + #TODO: function to detect and return 1 if the master server is + # DNS SOA for all the zones we care about here, we are examining # files to assure that our key is in named.conf, the zones we - # care about are there, and that if active directory is in use, + # care about are there, and that if active directory is in use, # allow the domain controllers to update specific zones @entries = xCAT::TableUtils->get_site_attribute("directoryprovider"); $site_entry = $entries[0]; @@ -537,13 +541,13 @@ sub process_request { if ( defined($site_entry)) { my @dservers = split /[ ,]/,$site_entry; $ctx->{adservers} = \@dservers; - - ############################ - # - should this include all domains? - # - multi-domains not supported with activedirectory - # - TODO in future release - ################### - + + ############################ + # - should this include all domains? + # - multi-domains not supported with activedirectory + # - TODO in future release + ################### + $ctx->{adzones} = { "_msdcs.". $ctx->{domain} => 1, "_sites.". $ctx->{domain} => 1, @@ -552,50 +556,109 @@ sub process_request { }; } } - + @entries = xCAT::TableUtils->get_site_attribute("dnsupdaters"); $site_entry = $entries[0]; if ( defined($site_entry) ) { - my @nservers = split /[ ,]/,$site_entry; - $ctx->{dnsupdaters} = \@nservers; + my @nservers = split /[ ,]/,$site_entry; + $ctx->{dnsupdaters} = \@nservers; } - if ($zapfiles || $slave) { #here, we unlink all the existing files to start fresh - if (xCAT::Utils->isAIX()) + unless ($external) { # only generate the named.conf and zone files for xCAT dns when NOT using external dns + if ($zapfiles || $slave) { #here, we unlink all the existing files to start fresh + if (xCAT::Utils->isAIX()) + { + system("/usr/bin/stopsrc -s $service"); + } + else + { + system("service $service stop"); #named may otherwise hold on to stale journal filehandles + } + my $conf = get_conf(); + unlink $conf; + my $DBDir = get_dbdir(); + foreach (<$DBDir/db.*>) { + unlink $_; + } + } + #We manipulate local namedconf + $ctx->{dbdir} = get_dbdir(); + $ctx->{zonesdir} = get_zonesdir(); + chmod 0775, $ctx->{dbdir}; # assure dynamic dns can actually execute against the directory + + update_namedconf($ctx, $slave); + + unless ($slave) { - system("/usr/bin/stopsrc -s $service"); + update_zones($ctx); } - else - { - system("service $service stop"); #named may otherwise hold on to stale journal filehandles - } - my $conf = get_conf(); - unlink $conf; - my $DBDir = get_dbdir(); - foreach (<$DBDir/db.*>) { - unlink $_; - } - } - #We manipulate local namedconf - $ctx->{dbdir} = get_dbdir(); - $ctx->{zonesdir} = get_zonesdir(); - chmod 0775, $ctx->{dbdir}; # assure dynamic dns can actually execute against the directory - - update_namedconf($ctx, $slave); - - unless ($slave) - { - update_zones($ctx); - } - if ($ctx->{restartneeded}) { - xCAT::SvrUtils::sendmsg("Restarting $service", $callback); + if ($ctx->{restartneeded}) { + xCAT::SvrUtils::sendmsg("Restarting $service", $callback); + + if (xCAT::Utils->isAIX()) + { + #try to stop named + my $cmd = "/usr/bin/stopsrc -s $service"; + my @output=xCAT::Utils->runcmd($cmd, 0); + + $cmd = "/usr/bin/startsrc -s $service"; + @output=xCAT::Utils->runcmd($cmd, 0); + my $outp = join('', @output); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Command failed: $cmd. Error message: $outp.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return; + } + } + else + { + my $cmd = "service $service stop"; + my @output=xCAT::Utils->runcmd($cmd, 0); + my $outp = join('', @output); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Command failed: $cmd. Error message: $outp.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return; + } + + $cmd = "service $service start"; + @output=xCAT::Utils->runcmd($cmd, 0); + $outp = join('', @output); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Command failed: $cmd. Error message: $outp.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return; + } + } + + xCAT::SvrUtils::sendmsg("Restarting named complete", $callback); + } + } + } else { + unless ($ctx->{privkey}) { + xCAT::SvrUtils::sendmsg([1,"Unable to update DNS due to lack of credentials in passwd to communicate with remote server"], $callback); + } + } + + if ($slave) + { + return; + } - if (xCAT::Utils->isAIX()) + # check if named is active before update dns records. + unless ($external) { # only start xCAT local dns when NOT using external dns + if (xCAT::Utils->isAIX()) + { + my $cmd = "/usr/bin/lssrc -s $service |grep active"; + my @output=xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) { - #try to stop named - my $cmd = "/usr/bin/stopsrc -s $service"; - my @output=xCAT::Utils->runcmd($cmd, 0); - $cmd = "/usr/bin/startsrc -s $service"; @output=xCAT::Utils->runcmd($cmd, 0); my $outp = join('', @output); @@ -607,10 +670,15 @@ sub process_request { return; } } - else + } + else + { + my $cmd = "service $service status|grep running"; + my @output=xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) { - my $cmd = "service $service stop"; - my @output=xCAT::Utils->runcmd($cmd, 0); + $cmd = "service $service start"; + @output=xCAT::Utils->runcmd($cmd, 0); my $outp = join('', @output); if ($::RUNCMD_RC != 0) { @@ -619,79 +687,19 @@ sub process_request { xCAT::MsgUtils->message("E", $rsp, $callback); return; } - - $cmd = "service $service start"; - @output=xCAT::Utils->runcmd($cmd, 0); - $outp = join('', @output); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Command failed: $cmd. Error message: $outp.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); - return; - } - } - - xCAT::SvrUtils::sendmsg("Restarting named complete", $callback); - } - } else { - unless ($ctx->{privkey}) { - xCAT::SvrUtils::sendmsg([1,"Unable to update DNS due to lack of credentials in passwd to communicate with remote server"], $callback); - } - } - - if ($slave) - { - return; - } - - # check if named is active before update dns records. - if (xCAT::Utils->isAIX()) - { - my $cmd = "/usr/bin/lssrc -s $service |grep active"; - my @output=xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) - { - $cmd = "/usr/bin/startsrc -s $service"; - @output=xCAT::Utils->runcmd($cmd, 0); - my $outp = join('', @output); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Command failed: $cmd. Error message: $outp.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); - return; } } } - else - { - my $cmd = "service $service status|grep running"; - my @output=xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) - { - $cmd = "service $service start"; - @output=xCAT::Utils->runcmd($cmd, 0); - my $outp = join('', @output); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Command failed: $cmd. Error message: $outp.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); - return; - } - } - } - + #now we stick to Net::DNS style updates, with TSIG if possible. TODO: kerberized (i.e. Windows) DNS server support, maybe needing to use nsupdate -g.... if ($external) { - # based on /etc/resolv.conf + # based on /etc/resolv.conf $ctx->{resolver} = Net::DNS::Resolver->new(); } else { - # default to localhost + # default to localhost $ctx->{resolver} = Net::DNS::Resolver->new(nameservers=>['127.0.0.1']); } @@ -709,9 +717,9 @@ sub get_zonesdir { my @entries = xCAT::TableUtils->get_site_attribute("bindzones"); my $site_entry = $entries[0]; - if ( defined($site_entry) ) { - $ZonesDir= $site_entry; - } + if ( defined($site_entry) ) { + $ZonesDir= $site_entry; + } return "$ZonesDir"; } @@ -720,16 +728,16 @@ sub get_conf { my $conf="/etc/named.conf"; # is this ubuntu ? - if ( $distro =~ /ubuntu.*/i || $distro =~ /debian.*/i ){ + if ( $distro =~ /ubuntu.*/i || $distro =~ /debian.*/i ){ $conf="/etc/bind/named.conf"; } my @entries = xCAT::TableUtils->get_site_attribute("bindconf"); my $site_entry = $entries[0]; - if ( defined($site_entry) ) { - $conf= $site_entry; - } + if ( defined($site_entry) ) { + $conf= $site_entry; + } return "$conf"; } @@ -739,9 +747,9 @@ sub get_dbdir { my @entries = xCAT::TableUtils->get_site_attribute("binddir"); my $site_entry = $entries[0]; - if ( defined($site_entry) ) { - $DBDir = $site_entry; - } + if ( defined($site_entry) ) { + $DBDir = $site_entry; + } if ( -d "$DBDir" ) { return "$DBDir" @@ -782,21 +790,21 @@ sub update_zones { my $name = hostname; my $node = $name; - # get the domain for the node - which is the local hostname - my ($host, $nip) = xCAT::NetworkUtils->gethostnameandip($node); - my @hosts; - push (@hosts, $host); - my $nd = xCAT::NetworkUtils->getNodeDomains(\@hosts); - my %nodedomains = %$nd; - my $domain = $nodedomains{$host}; + # get the domain for the node - which is the local hostname + my ($host, $nip) = xCAT::NetworkUtils->gethostnameandip($node); + my @hosts; + push (@hosts, $host); + my $nd = xCAT::NetworkUtils->getNodeDomains(\@hosts); + my %nodedomains = %$nd; + my $domain = $nodedomains{$host}; xCAT::SvrUtils::sendmsg("Updating zones.", $callback); - unless ($domain =~ /^\./) { - $domain = '.'.$domain; + if ($domain =~ /^\./) { # remove . if it's the first char of domain name + $domain =~ s/^\.//; } unless ($name =~ /\./) { - $name .= $domain; + $name .= ".".$domain; } unless ($name =~ /\.\z/) { $name .= '.'; @@ -822,7 +830,7 @@ sub update_zones { my $serial = ($mday * 100) + (($mon + 1) * 10000) + (($year + 1900) * 1000000); foreach $currzone (@neededzones) { - my $zonefilename = $currzone; + my $zonefilename = $currzone; if ($currzone =~ /IN-ADDR\.ARPA/) { $currzone =~ s/\.IN-ADDR\.ARPA.*//; my @octets = split/\./,$currzone; @@ -846,7 +854,7 @@ sub update_zones { } flock($zonehdl,LOCK_UN); close($zonehdl); - if ( $distro =~ /ubuntu.*/i || $distro =~ /debian.*/i ){ + if ( $distro =~ /ubuntu.*/i || $distro =~ /debian.*/i ){ chown(scalar(getpwnam('root')),scalar(getgrnam('bind')),$dbdir."/db.$zonefilename"); } else{ @@ -882,7 +890,7 @@ sub update_namedconf { $gotoptions=1; my $skip=0; do { - #push @newnamed,"\t\t//listen-on-v6 { any; };\n"; + #push @newnamed,"\t\t//listen-on-v6 { any; };\n"; if ($ctx->{forwarders} and $line =~ /forwarders {/) { push @newnamed,"\tforwarders \{\n"; $skip=1; @@ -998,11 +1006,11 @@ sub update_namedconf { } } unless ($gotoptions) { - push @newnamed,"options {\n"; + push @newnamed,"options {\n"; unless ($slave && xCAT::Utils->isLinux()) { push @newnamed,"\tdirectory \"".$ctx->{zonesdir}."\";\n"; } - push @newnamed,"\t\t//listen-on-v6 { any; };\n"; + push @newnamed,"\t\t//listen-on-v6 { any; };\n"; if ($ctx->{forwarders}) { push @newnamed,"\tforwarders {\n"; foreach (@{$ctx->{forwarders}}) { @@ -1030,6 +1038,7 @@ sub update_namedconf { } push @newnamed,"};\n\n"; } + unless ($slave) { unless ($gotkey) { unless ($ctx->{privkey}) { #need to generate one @@ -1120,7 +1129,7 @@ sub update_namedconf { for my $l (@newnamed) { print $newnameconf $l; } flock($newnameconf,LOCK_UN); close($newnameconf); - if ( $distro =~ /ubuntu.*/i || $distro =~ /debian.*/i ){ + if ( $distro =~ /ubuntu.*/i || $distro =~ /debian.*/i ){ chown (scalar(getpwnam('root')),scalar(getgrnam('bind')),$namedlocation); } else{ @@ -1148,9 +1157,9 @@ sub add_or_delete_records { $ctx->{nsmap} = {}; #will store a map to known NS records to avoid needless redundant queries to sort nodes into domains $ctx->{updatesbyzone}={}; #sort all updates into their respective zones for bulk update for fewer DNS transactions - # get node domains - my $nd = xCAT::NetworkUtils->getNodeDomains(\@{$ctx->{nodes}}); - my %nodedomains = %{$nd}; + # get node domains + my $nd = xCAT::NetworkUtils->getNodeDomains(\@{$ctx->{nodes}}); + my %nodedomains = %{$nd}; foreach $node (@{$ctx->{nodes}}) { my $name = $node; @@ -1160,18 +1169,18 @@ sub add_or_delete_records { next; } - my $domain = $nodedomains{$node}; - unless ($domain =~ /^\./) { $domain = '.'.$domain; } + my $domain = $nodedomains{$node}; + if ($domain =~ /^\./) { $domain =~ s/^\.//; } # remove . if it's the first char of domain name - unless ($name =~ /$domain/) { $name .= $domain } # $name needs to represent fqdn, but must preserve $node as a nodename for cfg lookup + unless ($name =~ /$domain/) { $name .= ".".$domain } # $name needs to represent fqdn, but must preserve $node as a nodename for cfg lookup if ($ctx->{hoststab} and $ctx->{hoststab}->{$node} and $ctx->{hoststab}->{$node}->[0]->{ip}) { @ips = ($ctx->{hoststab}->{$node}->[0]->{ip}); } else { @ips = getipaddr($node,GetAllAddresses=>1); - if (not @ips and keys %{$ctx->{nodeips}->{$node}}) { - @ips = keys %{$ctx->{nodeips}->{$node}}; - } + if (not @ips and keys %{$ctx->{nodeips}->{$node}}) { + @ips = keys %{$ctx->{nodeips}->{$node}}; + } if (!defined($ips[0])) { xCAT::SvrUtils::sendmsg([1,"Unable to find an IP for $node in hosts table or via system lookup (i.e. /etc/hosts)"], $callback); next; @@ -1206,11 +1215,12 @@ sub add_or_delete_records { } my $zone; foreach $zone (keys %{$ctx->{updatesbyzone}}) { - my $ip = xCAT::NetworkUtils->getipaddr($ctx->{nsmap}->{$zone}); + my $ip = xCAT::NetworkUtils->getipaddr($ctx->{nsmap}->{$zone}); if( !defined $ip) { - xCAT::SvrUtils::sendmsg([1,"Please make sure $ctx->{nsmap}->{$zone} exist in /etc/hosts or DNS."], $callback); + xCAT::SvrUtils::sendmsg([1,"Please make sure $ctx->{nsmap}->{$zone} exist either in /etc/hosts or DNS."], $callback); return 1; } + my $resolver = Net::DNS::Resolver->new(nameservers=>[$ip]); my $entry; my $numreqs = 300; # limit to 300 updates in a payload, something broke at 644 on a certain sample, choosing 300 for now @@ -1287,9 +1297,9 @@ sub find_nameserver_for_dns { } if (defined $ctx->{aliases}->{$node}) { - foreach (keys %{$ctx->{aliases}->{$node}}) { - push @rrcontent, "$_ IN CNAME $name"; - } + foreach (keys %{$ctx->{aliases}->{$node}}) { + push @rrcontent, "$_ IN CNAME $name"; + } } if ($ctx->{deletemode}) { push @rrcontent,"$name TXT"; @@ -1302,7 +1312,7 @@ sub find_nameserver_for_dns { unless (defined $ctx->{nsmap}->{$zone}) { #ok, we already thought about this zone and made a decision if ($zone =~ /^\.*192.IN-ADDR.ARPA\.*/ or $zone =~ /^\.*172.IN-ADDR.ARPA\.*/ or $zone =~ /127.IN-ADDR.ARPA\.*/ or $zone =~ /^\.*IN-ADDR.ARPA\.*/ or $zone =~ /^\.*ARPA\.*/) { $ctx->{nsmap}->{$zone} = 0; #ignore zones that are likely to appear, but probably not ours - } elsif ($::XCATSITEVALS{ddnsserver}) { + } elsif ($::XCATSITEVALS{ddnsserver}) { $ctx->{nsmap}->{$zone} = $::XCATSITEVALS{ddnsserver}; } else { my $reply = $ctx->{resolver}->query($zone,'NS'); @@ -1383,9 +1393,9 @@ sub get_dns_slave foreach my $sn (@ents) { if ($sn->{'nameserver'} == 2) - { + { push @sns, $sn->{'node'}; - } + } } @slaves = xCAT::NodeRange::noderange(join(',',@sns)); diff --git a/xCAT-server/lib/xcat/plugins/debian.pm b/xCAT-server/lib/xcat/plugins/debian.pm index 10beafa0d..07b78f8e7 100644 --- a/xCAT-server/lib/xcat/plugins/debian.pm +++ b/xCAT-server/lib/xcat/plugins/debian.pm @@ -75,9 +75,9 @@ sub preprocess_request my $stab = xCAT::Table->new('site'); my $sent; ($sent) = $stab->getAttribs({key => 'sharedtftp'}, 'value'); - unless ( $sent - and defined($sent->{value}) - and ($sent->{value} =~ /no/i or $sent->{value} =~ /0/)) + unless ( $sent + and defined($sent->{value}) + and ($sent->{value} eq "no" or $sent->{value} eq "NO" or $sent->{value} eq "0")) { #unless requesting no sharedtftp, don't make hierarchical call diff --git a/xCAT-server/lib/xcat/plugins/destiny.pm b/xCAT-server/lib/xcat/plugins/destiny.pm index d4c290b9d..983598deb 100755 --- a/xCAT-server/lib/xcat/plugins/destiny.pm +++ b/xCAT-server/lib/xcat/plugins/destiny.pm @@ -285,6 +285,23 @@ sub setdestiny { } } + + #if the postscripts directory exists then make sure it is + # world readable and executable by root; otherwise wget fails + my $installdir = xCAT::TableUtils->getInstallDir(); + my $postscripts = "$installdir/postscripts"; + if (-e $postscripts) + { + my $cmd = "chmod -R a+r $postscripts"; + xCAT::Utils->runcmd($cmd, 0); + my $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $callback->({info=>"$cmd failed"}); + + } + + } #print Dumper($req); # if precreatemypostscripts=1, create each mypostscript for each node @@ -309,7 +326,9 @@ sub setdestiny { noupdateinitrd=>$noupdateinitrd, ignorekernelchk=>$ignorekernelchk,}, \&relay_response); if ($errored) { - $callback->({error=>"Some nodes failed to set up $state resources, aborting"}); + my @myself = xCAT::NetworkUtils->determinehostname(); + my $myname = $myself[(scalar @myself)-1]; + $callback->({error=>"Some nodes failed to set up $state resources on server $myname, aborting"}); return; } diff --git a/xCAT-server/lib/xcat/plugins/dhcp.pm b/xCAT-server/lib/xcat/plugins/dhcp.pm index 617f4557b..22c6dcdb6 100755 --- a/xCAT-server/lib/xcat/plugins/dhcp.pm +++ b/xCAT-server/lib/xcat/plugins/dhcp.pm @@ -881,6 +881,42 @@ sub check_options xCAT::MsgUtils->message("I", $rsp, $callback, 0); return 0; } + # if not help and not -n, dhcpd needs to be running + if (!($opt->{h})&& (!($opt->{n}))) { + if (xCAT::Utils->isLinux()) { + my $DHCPSERVER="dhcpd"; + if( -e "/etc/init.d/isc-dhcp-server" ){ + $DHCPSERVER="isc-dhcp-server"; + } + + my @output = xCAT::Utils->runcmd("service $DHCPSERVER status", -1); + if ($::RUNCMD_RC != 0) { # not running + my $rsp = {}; + $rsp->{data}->[0] = "$DHCPSERVER is not running. Run service $DHCPSERVER start and rerun your command."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + return 1; + } + } else { # AIX + my @output = xCAT::Utils->runcmd("lssrc -s dhcpsd ", -1); + if ($::RUNCMD_RC != 0) { # not running + my $rsp = {}; + $rsp->{data}->[0] = "dhcpsd is not running. Run startsrc -s dhcpsd and rerun your command."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + return 1; + } else { # check the status + # the return output varies, sometime status is the third sometimes the 4th col + if (grep /inoperative/, @output) + { + my $rsp = {}; + $rsp->{data}->[0] = "dhcpsd is not running. Run startsrc -s dhcpsd and rerun your command."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + return 1; + + } + } + } + } + # check to see if -q is listed with any other options which is not allowed if ($opt->{q} and ($opt->{a} || $opt->{d} || $opt->{n} || $opt->{r} || $opt->{l} || $statements)) { @@ -956,7 +992,7 @@ sub preprocess_request if ( $rc ) { return []; } - + my $snonly=0; my @entries = xCAT::TableUtils->get_site_attribute("disjointdhcps"); my $t_entry = $entries[0]; @@ -1442,7 +1478,7 @@ sub process_request next; } } - if ($ent[1] =~ m/(remote|ipoib|ib|vlan|bond|eth|myri|man|wlan|en\d+|em\d+)/) + if ($ent[1] =~ m/(remote|ipoib|ib|vlan|bond|eth|myri|man|wlan|en\S*\d+|em\S*\d+)/) { #Mask out many types of interfaces, like xCAT 1.x $activenics{$ent[1]} = 1; } diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index 90384d9db..fcc28f2f8 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -4141,10 +4141,12 @@ sub copycd { } #} @ARGV = @{$request->{arg}}; + my $includeupdate = 0; GetOptions( 'n=s' => \$distname, 'a=s' => \$arch, - 'm=s' => \$path + 'm=s' => \$path, + 's' => \$includeupdate ); # run a few tests to see if the copycds should use this plugin unless ($path){ @@ -4236,6 +4238,34 @@ sub copycd { } } close(LINE); + } elsif (-r $path . "/upgrade/metadata.xml") { + open(LINE,$path."/upgrade/metadata.xml"); + my $detectdistname; + while () { + if (/esxVersion>([^<]*)([^<]*)) { diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm new file mode 100644 index 000000000..04650a69d --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -0,0 +1,630 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT_plugin::grub2; +use Data::Dumper; +use Sys::Syslog; +use xCAT::Scope; +use xCAT::Utils; +use xCAT::TableUtils; +use xCAT::ServiceNodeUtils; +use xCAT::NetworkUtils; +use xCAT::MsgUtils; +use File::Path; +use Socket; +use Getopt::Long; +use xCAT::Table; + +my $request; +my %breaknetbootnodes; +our %normalnodes; +my %tftpserverip; +my $callback; +my $sub_req; +my $globaltftpdir = xCAT::TableUtils->getTftpDir(); + + +my %usage = ( + "nodeset" => "Usage: nodeset [install|shell|boot|runcmd=bmcsetup|netboot|iscsiboot|osimage[=]|offline]", +); +sub handled_commands { + return { + nodeset => "noderes:netboot" + } +} + +sub check_dhcp { + return 1; + #TODO: omapi magic to do things right + my $node = shift; + my $dhcpfile; + open ($dhcpfile,$dhcpconf); + while (<$dhcpfile>) { + if (/host $node\b/) { + close $dhcpfile; + return 1; + } + } + close $dhcpfile; + return 0; +} + +sub _slow_get_tftpdir { #make up for paths where tftpdir is not passed in + my $node=shift; + my $nrtab = xCAT::Table->new('noderes',-create=>0); #in order to detect per-node tftp directories + unless ($nrtab) { return $globaltftpdir; } + my $ent = $nrtab->getNodeAttribs($node,["tftpdir"]); + if ($ent and $ent->{tftpdir}) { + return $ent->{tftpdir}; + } else { + return $globaltftpdir; + } +} +sub getstate { + my $node = shift; + my $tftpdir = shift; + unless ($tftpdir) { $tftpdir = _slow_get_tftpdir($node); } + if (check_dhcp($node)) { + if (-r $tftpdir . "/boot/grub2/".$node) { + my $fhand; + open ($fhand,$tftpdir . "/boot/grub2/".$node); + my $headline = <$fhand>; + close $fhand; + $headline =~ s/^#//; + chomp($headline); + return $headline; + } else { + return "boot"; + } + } else { + return "discover"; + } +} + +sub setstate { +=pod + + This function will manipulate the grub structure to match what the noderes/chain tables indicate the node should be booting. + +=cut + my $node = shift; + my %bphash = %{shift()}; + my %chainhash = %{shift()}; + my %machash = %{shift()}; + my $tftpdir = shift; + my %nrhash = %{shift()}; + my $linuximghash = shift(); + my $kern = $bphash{$node}->[0]; #$bptab->getNodeAttribs($node,['kernel','initrd','kcmdline']); + if ($kern->{kcmdline} =~ /!myipfn!/) { + my $ipfn = xCAT::NetworkUtils->my_ip_facing($node); + unless ($ipfn) { + my $servicenodes = $nrhash{$node}->[0]; + if ($servicenodes and $servicenodes->{servicenode}) { + my @sns = split /,/, $servicenodes->{servicenode}; + foreach my $sn ( @sns ) { + # We are in the service node pools, print error if no facing ip. + if (xCAT::InstUtils->is_me($sn)) { + my @myself = xCAT::NetworkUtils->determinehostname(); + my $myname = $myself[(scalar @myself)-1]; + $::callback->( + { + error => [ + "$myname: Unable to determine the image server for $node on service node $sn" + ], + errorcode => [1] + } + ); + return; + } + } + } else { + $::callback->( + { + error => [ + "$myname: Unable to determine the image server for $node" + ], + errorcode => [1] + } + ); + return; + } + } else { + $kern->{kcmdline} =~ s/!myipfn!/$ipfn/g; + } + } + if ($kern->{addkcmdline}) { + $kern->{kcmdline} .= " ".$kern->{addkcmdline}; + } + + if($linuximghash and $linuximghash->{'addkcmdline'}) + { + unless($linuximghash->{'boottarget'}) + { + $kern->{kcmdline} .= " ".$linuximghash->{'addkcmdline'}; + } + } + + my $pcfg; + unless (-d "$tftpdir/boot/grub2") { + mkpath("$tftpdir/boot/grub2"); + } + my $nodemac; + my %client_nethash = xCAT::DBobjUtils->getNetwkInfo( [$node] ); + + open($pcfg,'>',$tftpdir."/boot/grub2/".$node); + my $cref=$chainhash{$node}->[0]; #$chaintab->getNodeAttribs($node,['currstate']); + if ($cref->{currstate}) { + print $pcfg "#".$cref->{currstate}."\n"; + } + print $pcfg "set timeout=5\n"; + + $normalnodes{$node}=1; #Assume a normal netboot (well, normal dhcp, + #which is normally with a valid 'filename' field, + #but the typical ppc case will be 'special' makedhcp + #to clear the filename field, so the logic is a little + #opposite + + if ($cref and $cref->{currstate} eq "boot") { + $breaknetbootnodes{$node}=1; + delete $normalnodes{$node}; #Signify to omit this from one makedhcp command + close($pcfg); + } elsif ($kern and $kern->{kernel}) { + #It's time to set grub configuration for this node to boot the kernel.. + #get tftpserver + my $tftpserver; + if (defined ($nrhash{$node}->[0]) && $nrhash{$node}->[0]->{'tftpserver'}) { + $tftpserver = $nrhash{$node}->[0]->{'tftpserver'}; + } elsif (defined ($nrhash{$node}->[0]) && $nrhash{$node}->[0]->{'xcatmaster'}) { + $tftpserver = $nrhash{$node}->[0]->{'xcatmaster'}; + } else { + my @master = xCAT::TableUtils->get_site_attribute("master"); + $tftpserver = $master[0]; + } + my $serverip; + if (defined ($tftpserverip{$tftpserver})) { + $serverip = $tftpserverip{$tftpserver}; + } else { + $serverip = xCAT::NetworkUtils->getipaddr($tftpserver); + unless ($serverip) { + syslog("local1|err","xCAT unable to resolve $tftpserver"); + return; + } + $tftpserverip{$tftpserver} = $serverip; + } + print $pcfg "set default=\"xCAT OS Deployment\"\n"; + print $pcfg "menuentry \"xCAT OS Deployment\" {\n"; + print $pcfg " insmod http\n"; + print $pcfg " insmod tftp\n"; + print $pcfg " set root=http,$serverip\n"; + print $pcfg " echo Loading Install kernel ...\n"; + if ($kern and $kern->{kcmdline}) { + print $pcfg " linux $tftpdir/$kern->{kernel} $kern->{kcmdline}\n"; + } else { + print $pcfg " linux $tftpdir/$kern->{kernel}\n"; + } + print $pcfg " echo Loading initial ramdisk ...\n"; + if ($kern and $kern->{initrd}) { + print $pcfg " initrd $tftpdir/$kern->{initrd}\n"; + } + + print $pcfg "}"; + close($pcfg); + my $inetn = xCAT::NetworkUtils->getipaddr($node); + unless ($inetn) { + syslog("local1|err","xCAT unable to resolve IP for $node in grub2 plugin"); + return; + } + } else { + close($pcfg); + } + my $ip = xCAT::NetworkUtils->getipaddr($node); + unless ($ip) { + syslog("local1|err","xCAT unable to resolve IP in grub2 plugin"); + return; + } + my $mactab = xCAT::Table->new('mac'); + my %ipaddrs; + $ipaddrs{$ip} = 1; + if ($mactab) { + my $ment = $machash{$node}->[0]; #$mactab->getNodeAttribs($node,['mac']); + if ($ment and $ment->{mac}) { + my @macs = split(/\|/,$ment->{mac}); + foreach (@macs) { + $nodemac = $_; + if (/!(.*)/) { + my $ipaddr = xCAT::NetworkUtils->getipaddr($1); + if ($ipaddr) { + $ipaddrs{$ipaddr} = 1; + } + } + } + } + } + # Do not use symbolic link, p5 does not support symbolic link in /tftpboot + # my $hassymlink = eval { symlink("",""); 1 }; + foreach $ip (keys %ipaddrs) { + my @ipa=split(/\./,$ip); + my $pname = "grub.cfg-" . sprintf("%02x%02x%02x%02x",@ipa); + unlink($tftpdir."/boot/grub2/".$pname); + link($tftpdir."/boot/grub2/".$node,$tftpdir."/boot/grub2/".$pname); + } + + if ($nodemac =~ /:/) { + my $tmp = $nodemac; + $tmp =~ s/(..):(..):(..):(..):(..):(..)/$1-$2-$3-$4-$5-$6/g; + my $pname = "grub.cfg-01-" . $tmp; + unlink($tftpdir."/boot/grub2/".$pname); + link($tftpdir."/boot/grub2/".$node,$tftpdir."/boot/grub2/".$pname); + } + return; +} + +my $errored = 0; +sub pass_along { + my $resp = shift; + + $callback->($resp); + if ($resp and ($resp->{errorcode} and $resp->{errorcode}->[0]) or ($resp->{error} and $resp->{error}->[0])) { + $errored=1; + } + foreach (@{$resp->{node}}) { + if ($_->{error} or $_->{errorcode}) { + $errored=1; + } + } +} + + +sub preprocess_request { + my $req = shift; + if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + + my $callback1 = shift; + my $command = $req->{command}->[0]; + my $sub_req = shift; + my @args=(); + if (ref($req->{arg})) { + @args=@{$req->{arg}}; + } else { + @args=($req->{arg}); + } + @ARGV = @args; + my $nodes = $req->{node}; + #use Getopt::Long; + Getopt::Long::Configure("bundling"); + Getopt::Long::Configure("pass_through"); + if (!GetOptions('h|?|help' => \$HELP, 'v|version' => \$VERSION) ) { + if($usage{$command}) { + my %rsp; + $rsp{data}->[0]=$usage{$command}; + $callback1->(\%rsp); + } + return; + } + + if ($HELP) { + if($usage{$command}) { + my %rsp; + $rsp{data}->[0]=$usage{$command}; + $callback1->(\%rsp); + } + return; + } + + if ($VERSION) { + my $ver = xCAT::Utils->Version(); + my %rsp; + $rsp{data}->[0]="$ver"; + $callback1->(\%rsp); + return; + } + + if (@ARGV==0) { + if($usage{$command}) { + my %rsp; + $rsp{data}->[0]=$usage{$command}; + $callback1->(\%rsp); + } + return; + } + + + #Assume shared tftp directory for boring people, but for cool people, help sync up tftpdirectory contents when + #if they specify no sharedtftp in site table + my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); + my $t_entry = $entries[0]; + + if ( defined($t_entry) and ($t_entry eq "0" or $t_entry eq "no" or $t_entry eq "NO")) { + # check for computenodes and servicenodes from the noderange, if so error out + my @SN; + my @CN; + xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN); + unless (($args[0] eq 'stat') or ($args[0] eq 'enact')) { + if ((@SN > 0) && (@CN >0 )) { # there are both SN and CN + my $rsp; + $rsp->{data}->[0] = + "Nodeset was run with a noderange containing both service nodes and compute nodes. This is not valid. You must submit with either compute nodes in the noderange or service nodes. \n"; + xCAT::MsgUtils->message("E", $rsp, $callback1); + return; + + } + } + + $req->{'_disparatetftp'}=[1]; + if ($req->{inittime}->[0]) { + return [$req]; + } + if (@CN >0 ) { # if compute nodes broadcast to all servicenodes + return xCAT::Scope->get_broadcast_scope($req,@_); + } + } + return [$req]; +} + +sub process_request { + $request = shift; + $callback = shift; + $::callback=$callback; + $sub_req = shift; + my $command = $request->{command}->[0]; + %breaknetbootnodes=(); + %normalnodes=(); + + my @args; + my @nodes; + my @rnodes; + if (ref($request->{node})) { + @rnodes = @{$request->{node}}; + } else { + if ($request->{node}) { @rnodes = ($request->{node}); } + } + unless (@rnodes) { + if ($usage{$request->{command}->[0]}) { + $callback->({data=>$usage{$request->{command}->[0]}}); + } + return; + } + + #if not shared tftpdir, then filter, otherwise, set up everything + if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + @nodes = (); + foreach (@rnodes) { + if (xCAT::NetworkUtils->nodeonmynet($_)) { + push @nodes,$_; + } else { + xCAT::MsgUtils->message("S", "$_: grub2 netboot: stop configuration because of none sharedtftp and not on same network with its xcatmaster."); + } + } + } else { + @nodes = @rnodes; + } + + # return directly if no nodes in the same network + unless (@nodes) { + xCAT::MsgUtils->message("S", "xCAT: grub2 netboot: no valid nodes. Stop the operation on this server."); + return; + } + + if (ref($request->{arg})) { + @args=@{$request->{arg}}; + } else { + @args=($request->{arg}); + } + + #now run the begin part of the prescripts + unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + $errored=0; + if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + $sub_req->({command=>['runbeginpre'], + node=>\@nodes, + arg=>[$args[0], '-l']},\&pass_along); + } else { #nodeset did not distribute to the service node, here we need to let runednpre to distribute the nodes to their masters + $sub_req->({command=>['runbeginpre'], + node=>\@rnodes, + arg=>[$args[0]]},\&pass_along); + } + if ($errored) { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="Failed in running begin prescripts.\n"; + $callback->($rsp); + return; + } + } + + #back to normal business + my $inittime=0; + if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (!$inittime) { $inittime=0;} + $errored=0; + unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + $sub_req->({command=>['setdestiny'], + node=>\@nodes, + inittime=>[$inittime], + arg=>\@args},\&pass_along); + } + if ($errored) { return; } + + my $bptab=xCAT::Table->new('bootparams',-create=>1); + my $bphash = $bptab->getNodesAttribs(\@nodes,['kernel','initrd','kcmdline','addkcmdline']); + my $chaintab=xCAT::Table->new('chain',-create=>1); + my $chainhash=$chaintab->getNodesAttribs(\@nodes,['currstate']); + my $noderestab=xCAT::Table->new('noderes',-create=>1); + my $nodereshash=$noderestab->getNodesAttribs(\@nodes,['tftpdir']); + my $mactab=xCAT::Table->new('mac',-create=>1); + my $machash=$mactab->getNodesAttribs(\@nodes,['mac']); + my $nrtab=xCAT::Table->new('noderes',-create=>1); + my $nrhash=$nrtab->getNodesAttribs(\@nodes,['servicenode','tftpserver','xcatmaster']); + my $typetab=xCAT::Table->new('nodetype',-create=>1); + my $typehash=$typetab->getNodesAttribs(\@nodes,['os','provmethod','arch','profile']); + my $linuximgtab=xCAT::Table->new('linuximage',-create=>1); + my $osimagetab=xCAT::Table->new('osimage',-create=>1); + + my $rc; + my $errstr; + + my $tftpdir; + foreach (@nodes) { + my %response; + if ($nodereshash->{$_} and $nodereshash->{$_}->[0] and $nodereshash->{$_}->[0]->{tftpdir}) { + $tftpdir = $nodereshash->{$_}->[0]->{tftpdir}; + } else { + $tftpdir = $globaltftpdir; + } + $response{node}->[0]->{name}->[0]=$_; + if ($args[0] eq 'stat') { + $response{node}->[0]->{data}->[0]= getstate($_,$tftpdir); + $callback->(\%response); + } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate + my $ent = $typehash->{$_}->[0]; + my $osimgname = $ent->{'provmethod'}; + my $linuximghash=undef; + unless($osimgname =~ /^(install|netboot|statelite)$/){ + $linuximghash = $linuximgtab->getAttribs({imagename => $osimgname}, 'boottarget', 'addkcmdline'); + } + + ($rc,$errstr) = setstate($_,$bphash,$chainhash,$machash,$tftpdir,$nrhash,$linuximghash); + if ($rc) { + $response{node}->[0]->{errorcode}->[0]= $rc; + $response{node}->[0]->{errorc}->[0]= $errstr; + $callback->(\%response); + } + } + }# end of foreach node + + my @normalnodeset = keys %normalnodes; + my @breaknetboot=keys %breaknetbootnodes; + #print "grub2 :inittime=$inittime; normalnodeset=@normalnodeset; breaknetboot=@breaknetboot\n"; + my %osimagenodehash; + for my $nn (@normalnodeset){ + #record the os version for node + my $ent = $typehash->{$nn}->[0]; + my $osimage=$ent->{'provmethod'}; + if($osimage =~ /^(install|netboot|statelite)$/){ + $osimage=($ent->{'os'}).'-'.($ent->{'arch'}).'-'.($ent->{'provmethod'}).'-'.($ent->{'profile'}); + } + push @{$osimagenodehash{$osimage}}, $nn; + } + + my $do_dhcpsetup=1; + my @entries = xCAT::TableUtils->get_site_attribute("dhcpsetup"); + my $t_entry = $entries[0]; + if (defined($t_entry) ) { + if ($t_entry =~ /0|n|N/) { $do_dhcpsetup=0; } + } + + #Don't bother to try dhcp binding changes if sub_req not passed, i.e. service node build time + unless (($args[0] eq 'stat') || ($inittime) || ($args[0] eq 'offline')) { + foreach my $osimage (keys %osimagenodehash) { + #TOTO check the existence of grub2 executable files for corresponding arch + my $osimgent = $osimagetab->getAttribs({imagename => $osimage },'osarch'); + my $validarch=undef; + if($osimgent and $osimgent->{'osarch'}) + { + $validarch = $osimgent->{'osarch'}; + } + if ($validarch =~ /ppc64/i) + { + $validarch="ppc" + } + my $grub2 = "/boot/grub2/grub2.".$validarch; + my $tftppath = $tftpdir . $grub2; + unless (-e "$tftppath") { + my $rsp; + push @{$rsp->{data}}, + "stop configuration, missing $tftppath.\n"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return; + } + if ($do_dhcpsetup) { + if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + $sub_req->({command=>['makedhcp'], + node=>\@{$osimagenodehash{$osimage}}, + arg=>['-l','-s','filename = \"'.$grub2.'\";']},$callback); + } else { + $sub_req->({command=>['makedhcp'], + node=>\@{$osimagenodehash{$osimage}}, + arg=>['-s','filename = \"'.$grub2.'\";']},$callback); + } + } + } #end of foreach osimagenodehash + if ($do_dhcpsetup) { + if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + $sub_req->({command=>['makedhcp'], + node=>\@breaknetboot, + arg=>['-l','-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback); + } else { + $sub_req->({command=>['makedhcp'], + node=>\@breaknetboot, + arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback); + } + } + } + + #now run the end part of the prescripts + unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') + $errored=0; + if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + $sub_req->({command=>['runendpre'], + node=>\@nodes, + arg=>[$args[0], '-l']},\&pass_along); + } else { #nodeset did not distribute to the service node, here we need to let runednpre to distribute the nodes to their masters + $sub_req->({command=>['runendpre'], + node=>\@rnodes, + arg=>[$args[0]]},\&pass_along); + } + if ($errored) { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="Failed in running end prescripts\n"; + $callback->($rsp); + return; + } + } +} + +#---------------------------------------------------------------------------- +=head3 getNodesetStates + returns the nodeset state for the given nodes. The possible nodeset + states are: netboot, install, boot and discover. + Arguments: + nodes --- a pointer to an array of nodes + states -- a pointer to a hash table. This hash will be filled by this + function.The key is the nodeset status and the value is a pointer + to an array of nodes. + Returns: + (return code, error message) +=cut +#----------------------------------------------------------------------------- +sub getNodesetStates { + my $noderef=shift; + if ($noderef =~ /xCAT_plugin::grub2/) { + $noderef=shift; + } + my @nodes=@$noderef; + my $hashref=shift; + my $noderestab = xCAT::Table->new('noderes'); #in order to detect per-node tftp directories + my %nrhash = %{$noderestab->getNodesAttribs(\@nodes,[qw(tftpdir)])}; + + if (@nodes>0) { + foreach my $node (@nodes) { + my $tftpdir; + if ($nrhash{$node}->[0] and $nrhash{$node}->[0]->{tftpdir}) { + $tftpdir = $nrhash{$node}->[0]->{tftpdir}; + } else { + $tftpdir = $globaltftpdir; + } + my $tmp=getstate($node, $tftpdir); + my @a=split(' ', $tmp); + $stat = $a[0]; + if (exists($hashref->{$stat})) { + my $pa=$hashref->{$stat}; + push(@$pa, $node); + } + else { + $hashref->{$stat}=[$node]; + } + } + } + return (0, ""); +} + +1; diff --git a/xCAT-server/lib/xcat/plugins/hosts.pm b/xCAT-server/lib/xcat/plugins/hosts.pm index 609c6028b..963f9c868 100755 --- a/xCAT-server/lib/xcat/plugins/hosts.pm +++ b/xCAT-server/lib/xcat/plugins/hosts.pm @@ -122,6 +122,10 @@ sub build_line my $othernames = shift; my @o_names = (); my @n_names = (); + + # Trim spaces from the beginning and end from $othernames + $othernames =~ s/^\s+|\s+$//g; + if (defined $othernames) { # the "hostnames" attribute can be a list delimited by @@ -284,13 +288,20 @@ sub add_hosts_content { { addnode $callback, $nodename, $ip, $ref->{hostnames}, $domain; } - else - { - my $rsp; - push @{$rsp->{data}}, "Invalid IP Addr \'$ref->{ip}\' for node \'$ref->{node}\'."; - xCAT::MsgUtils->message("E", $rsp, $callback); - } - + else + { + my $rsp; + if (!$ip) + { + push @{$rsp->{data}}, "Ignoring node \'$nodename\', it can not be resolved."; + } + else + { + push @{$rsp->{data}}, "Ignoring node \'$nodename\', its ip address \'$ip\' is not valid."; + } + xCAT::MsgUtils->message("W", $rsp, $callback); + } + if (defined($ref->{otherinterfaces})) { addotherinterfaces $callback, $nodename, $ref->{otherinterfaces}, $domain; @@ -564,6 +575,7 @@ sub donics $node, [ 'nicips', 'nichostnamesuffixes', + 'nichostnameprefixes', 'nicnetworks', 'nicaliases' ] ); @@ -609,6 +621,7 @@ sub donics } my @nicandsufx = split(',', $et->{'nichostnamesuffixes'}); + my @nicandprfx = split(',', $et->{'nichostnameprefixes'}); foreach (@nicandsufx) { @@ -630,12 +643,32 @@ sub donics $nich->{$nicname}->{nicsufx}->[0] = $nicsufx; } } + foreach (@nicandprfx) + { + my ($nicname, $nicprfx); + if ($_ =~ /!/) { + ($nicname, $nicprfx) = split('!', $_); + } else { + ($nicname, $nicprfx) = split(':', $_); + } + + if ( $nicprfx =~ /\|/) { + my @prfs = split( /\|/, $nicprfx); + my $index=0; + foreach my $prf (@prfs) { + $nich->{$nicname}->{nicprfx}->[$index] = $prf; + $index++; + } + } else { + $nich->{$nicname}->{nicprfx}->[0] = $nicprfx; + } + } # see if we need to fill in a default suffix # nich has all the valid nics - ie. that have IPs provided! foreach my $nic (keys %{$nich}) { for (my $i = 0; $i < $nicindex{$nic}; $i++ ){ - if (!$nich->{$nic}->{nicsufx}->[$i]) { + if (!$nich->{$nic}->{nicsufx}->[$i] && !$nich->{$nic}->{nicprfx}->[$i]) { # then we have no suffix at all for this # so set a default $nich->{$nic}->{nicsufx}->[$i] = "-$nic"; @@ -706,6 +739,7 @@ sub donics my $nicip = $nich->{$nic}->{nicip}->[$i]; my $nicsuffix = $nich->{$nic}->{nicsufx}->[$i]; + my $nicprefix = $nich->{$nic}->{nicprfx}->[$i]; my $nicnetworks = $nich->{$nic}->{netwrk}->[$i]; my $nicaliases = $nich->{$nic}->{nicaliases}->[$i]; @@ -714,7 +748,7 @@ sub donics } # construct hostname for nic - my $nichostname = "$shorthost$nicsuffix"; + my $nichostname = "$nicprefix$shorthost$nicsuffix"; # get domain from network def provided by nic attr my $nt = $nettab->getAttribs({ netname => "$nicnetworks"}, 'domain'); diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index 2834af3e6..b2aaeb0f3 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -1332,7 +1332,7 @@ sub fpc_firmxfer_watch { return; } my $percent = 0; - if ($rsp->{data} and (length(@{$rsp->{data}}) > 0)) { + if ($rsp->{data} and (scalar(@{$rsp->{data}}) > 0)) { $percent = $rsp->{data}->[0]; } #$callback->({sinfo=>"$percent%"}); @@ -2971,12 +2971,13 @@ sub parsefru { my $currsize; if ($bytes->[$curridx] <= 5) { #don't even try to parse unknown stuff #some records don't comply to any SPEC - while (not $last) { + while (not $last and $curridx < (scalar @$bytes)) { if ($bytes->[$curridx+1] & 128) { $last=1; } $currsize=$bytes->[$curridx+2]; - push @{$fruhash->{extra}},$bytes->[$curridx..$curridx+4+$currsize-1]; + push @{$fruhash->{extra}},@{$bytes}[$curridx..$curridx+4+$currsize-1]; + $curridx += 5 + $currsize; } } } @@ -6318,13 +6319,17 @@ sub preprocess_request { if ($command eq "rpower") { my $subcmd=$exargs[0]; if($subcmd eq ''){ - $callback->({data=>["Please enter an action (eg: boot,off,on, etc)", $usage_string]}); + #$callback->({data=>["Please enter an action (eg: boot,off,on, etc)", $usage_string]}); + #Above statement will miss error code, so replaced by the below statement + $callback->({errorcode=>[1],data=>["Please enter an action (eg: boot,off,on, etc)", $usage_string]}); $request = {}; return 0; } if ( ($subcmd ne 'reseat') && ($subcmd ne 'stat') && ($subcmd ne 'state') && ($subcmd ne 'status') && ($subcmd ne 'on') && ($subcmd ne 'off') && ($subcmd ne 'softoff') && ($subcmd ne 'nmi')&& ($subcmd ne 'cycle') && ($subcmd ne 'reset') && ($subcmd ne 'boot') && ($subcmd ne 'wake') && ($subcmd ne 'suspend')) { - $callback->({data=>["Unsupported command: $command $subcmd", $usage_string]}); + #$callback->({data=>["Unsupported command: $command $subcmd", $usage_string]}); + #Above statement will miss error code, so replaced by the below statement + $callback->({errorcode=>[1],data=>["Unsupported command: $command $subcmd", $usage_string]}); $request = {}; return; } diff --git a/xCAT-server/lib/xcat/plugins/kit.pm b/xCAT-server/lib/xcat/plugins/kit.pm index ab46f7d58..0d6912c54 100644 --- a/xCAT-server/lib/xcat/plugins/kit.pm +++ b/xCAT-server/lib/xcat/plugins/kit.pm @@ -3563,8 +3563,7 @@ sub create_error_response { #----------------------------------------------------------------------------- sub lskit_processargs { - - if ( defined( @{$::args} ) ) { + if ( defined ($::args) && @{$::args} ){ @ARGV = @{$::args}; } @@ -3665,7 +3664,7 @@ sub lskit_processargs { #----------------------------------------------------------------------------- sub lskitcomp_processargs { - if ( defined( @{$::args} ) ) { + if ( defined ($::args) && @{$::args} ){ @ARGV = @{$::args}; } @@ -3758,7 +3757,7 @@ sub lskitcomp_processargs { #----------------------------------------------------------------------------- sub lskitdeployparam_processargs { - if ( defined( @{$::args} ) ) { + if ( defined ($::args) && @{$::args} ){ @ARGV = @{$::args}; } diff --git a/xCAT-server/lib/xcat/plugins/kmodules.pm b/xCAT-server/lib/xcat/plugins/kmodules.pm index 15a769427..3b350ae2f 100644 --- a/xCAT-server/lib/xcat/plugins/kmodules.pm +++ b/xCAT-server/lib/xcat/plugins/kmodules.pm @@ -192,7 +192,7 @@ sub lskmodules_usage { #----------------------------------------------------------------------------- sub processArgs { - if ( defined( @{$::args} ) ) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } diff --git a/xCAT-server/lib/xcat/plugins/lsslp.pm b/xCAT-server/lib/xcat/plugins/lsslp.pm old mode 100644 new mode 100755 index d233fedea..5953cb3e7 --- a/xCAT-server/lib/xcat/plugins/lsslp.pm +++ b/xCAT-server/lib/xcat/plugins/lsslp.pm @@ -368,7 +368,7 @@ sub parse_args { ################################### my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; if ( scalar(@octets) != 4 ) { - return( [1,"Invalid IP address: $ip"] ); + return( usage("Invalid IP address: $ip") ); } foreach my $octet ( @octets ) { if (( $octet < 0 ) or ( $octet > 255 )) { diff --git a/xCAT-server/lib/xcat/plugins/makeknownhosts.pm b/xCAT-server/lib/xcat/plugins/makeknownhosts.pm index 478ba8fd9..f2b03d281 100644 --- a/xCAT-server/lib/xcat/plugins/makeknownhosts.pm +++ b/xCAT-server/lib/xcat/plugins/makeknownhosts.pm @@ -239,7 +239,7 @@ sub add_known_host xCAT::MsgUtils->message("E", $rsp, $callback, 1); return 1; } - chop($output[0]); + chomp($output[0]); my ($hostname,$ip_address) = xCAT::NetworkUtils->gethostnameandip($node); if (!$hostname || !$ip_address) { diff --git a/xCAT-server/lib/xcat/plugins/mic.pm b/xCAT-server/lib/xcat/plugins/mic.pm index 1037c69b3..6da7c7395 100644 --- a/xCAT-server/lib/xcat/plugins/mic.pm +++ b/xCAT-server/lib/xcat/plugins/mic.pm @@ -612,7 +612,25 @@ sub rflash { # run the cmd on the host to flash the mic my @args = ("-s", "-v", "-e"); push @args, "$::XCATROOT/sbin/flashmic"; - my $master = $request->{'_xcatdest'}; + # assume that all hosts are on the same network connected to this master + # (otherwise, will need to move this call into loop above for each host + # and build separate miccfg calls for each unique returned value from + # my_ip_facing) + my $ipfn = xCAT::NetworkUtils->my_ip_facing(@hosts[0]); + if ($ipfn) { + $master = $ipfn; + } else { + my $hostname = ""; + my $hostnamecmd = "/bin/hostname"; + my @thostname = xCAT::Utils->runcmd($hostnamecmd, 0); + if ($::RUNCMD_RC = 0) { + $hostname = "from server $thostname[0]"; + } + xCAT::MsgUtils->message("E", {error=>["Cannot detect an active network interface $hostname to @hosts[0]."], errorcode=>["1"]}, $callback); + return; + } + +} push @args, ("-m", "$master"); push @args, ("-p", "$tftpdir/xcat/miccfg"); @@ -912,7 +930,23 @@ sub nodeset { # run the cmd on the host to configure the mic my @args = ("-s", "-v", "-e"); push @args, "$::XCATROOT/sbin/configmic"; - my $master = $request->{'_xcatdest'}; + # assume that all hosts are on the same network connected to this master + # (otherwise, will need to move this call into loop above for each host + # and build separate miccfg calls for each unique returned value from + # my_ip_facing) + my $ipfn = xCAT::NetworkUtils->my_ip_facing(@hosts[0]); + if ($ipfn) { + $master = $ipfn; + } else { + my $hostname = ""; + my $hostnamecmd = "/bin/hostname"; + my @thostname = xCAT::Utils->runcmd($hostnamecmd, 0); + if ($::RUNCMD_RC = 0) { + $hostname = "from server $thostname[0]"; + } + xCAT::MsgUtils->message("E", {error=>["Cannot detect an active network interface $hostname to @hosts[0]."], errorcode=>["1"]}, $callback); + return; + } push @args, ("-m", "$master"); push @args, ("-p", "$tftpdir/xcat/miccfg"); diff --git a/xCAT-server/lib/xcat/plugins/networks.pm b/xCAT-server/lib/xcat/plugins/networks.pm index 256a93f16..c21c7f852 100644 --- a/xCAT-server/lib/xcat/plugins/networks.pm +++ b/xCAT-server/lib/xcat/plugins/networks.pm @@ -26,8 +26,7 @@ sub preprocess_request my @requests = ({%$req}); #first element is local instance $::args = $req->{arg}; - - if (defined(@{$::args})) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } @@ -88,7 +87,7 @@ sub process_request $::args = $request->{arg}; - if (defined(@{$::args})) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } diff --git a/xCAT-server/lib/xcat/plugins/nimol.pm b/xCAT-server/lib/xcat/plugins/nimol.pm index 7491d6c09..afc2a9336 100644 --- a/xCAT-server/lib/xcat/plugins/nimol.pm +++ b/xCAT-server/lib/xcat/plugins/nimol.pm @@ -190,16 +190,17 @@ sub copycd { 'n=s' => \$distname, ); unless($distname && $file && $mntpath && $arch) { - $callback->({error=>"distname, file or mntpath not specified, $distname, $file, $mntpath"}); + #$callback->({error=>"distname, file or mntpath not specified, $distname, $file, $mntpath"}); return ; } if ($distname && $distname !~ /^vios/i) { - $callback->({error=>"distname incorrect"}); + #$callback->({error=>"distname incorrect"}); return ; } elsif ($arch !~ /^ppc64/i) { - $callback->({error=>"arch incorrect"}); + #$callback->({error=>"arch incorrect"}); + return ; } elsif (!$file) { - $callback->({error=>"Only suport to use the iso file vios"}); + #$callback->({error=>"Only suport to use the iso file vios"}); return; } #print __LINE__."=====>vios=====.\n"; @@ -411,13 +412,13 @@ sub create_imgconf_file { my $rootpw = undef; my $passwdtab = xCAT::Table->new('passwd'); if ($passwdtab) { - my $et = $passwdtab->getAttribs({key => 'system', username => 'root'}, 'password'); + my $et = $passwdtab->getAttribs({key => 'vios', username => 'padmin'}, 'password'); if ($et and defined ($et->{'password'})) { $rootpw = $et->{'password'}; } } unless (defined($rootpw)) { - return "Unable to find requested password from passwd, with key=system,username=root"; + return "Unable to find requested password from passwd, with key=vios,username=padmin"; } unless (-e $bootimg_root."/viobootimg") { return "Unable to find VIOS bootimg file"; diff --git a/xCAT-server/lib/xcat/plugins/profilednodes.pm b/xCAT-server/lib/xcat/plugins/profilednodes.pm index de0e3980c..1dbb7f141 100644 --- a/xCAT-server/lib/xcat/plugins/profilednodes.pm +++ b/xCAT-server/lib/xcat/plugins/profilednodes.pm @@ -54,6 +54,7 @@ my $command; my $args; # Put arguments in a hash. my %args_dict; +my %general_arg; #------------------------------------------------------- @@ -100,6 +101,8 @@ sub process_request { $command = $request->{command}->[0]; $args = $request->{arg}; + my $gereral_arg = get_general_args(); + # There is no need to acquire lock for command nodediscoverstatus, nodediscoverls and noderegenips. if ($command eq "nodediscoverstatus"){ nodediscoverstatus(); @@ -112,7 +115,11 @@ sub process_request { return; } - my $lock = xCAT::Utils->acquire_lock("nodemgmt", 1); + my $non_block = 1; + if ( $general_arg{'blockmode'} == 1) { + $non_block = 0; + } + my $lock = xCAT::Utils->acquire_lock("nodemgmt", $non_block); if (! $lock){ setrsp_errormsg("Cannot acquire lock, another process is already running."); return; @@ -131,7 +138,7 @@ sub process_request { ); setrsp_errormsg("Cannot $errormsg_dict{$command} while node discovery is running."); - xCAT::Utils->release_lock($lock, 1); + xCAT::Utils->release_lock($lock, $non_block); return; } } @@ -156,7 +163,32 @@ sub process_request { nodechmac(); } - xCAT::Utils->release_lock($lock, 1); + xCAT::Utils->release_lock($lock, $non_block); +} + +sub get_general_args +{ + my ($help, $ver, $blockmode); + %general_arg = (); + @ARGV = (); + if($args) { + @ARGV = @$args; + } + GetOptions( + 'h|help' => \$help, + 'v|version' => \$ver, + 'b|block' => \$blockmode, + ); + + if($help){ + $general_arg{'help'} = 1; + } + if($ver){ + $general_arg{'version'} = 1; + } + if ($blockmode) { + $general_arg{'blockmode'} = 1; + } } #------------------------------------------------------- @@ -202,37 +234,21 @@ sub validate_args{ my $enabledparamsref = shift; my $mandatoryparamsref = shift; - # The -h -v are handled by seqdiscovery.pm - # -t -u -l only works for nodediscoverls, and them only handled by seqdiscovery.pm - my ($help, $ver, $type, $uuid, $long); + if ($general_arg{'help'} == 1){ + my %process_help_commands = ( + 'nodediscoverstart' => 1, + 'nodediscoverstop' => 1, + 'nodediscoverls' => 1, + 'nodediscoverstatus' => 1, + ); - @ARGV = (); - if($args) { - @ARGV = @$args; - } - GetOptions( - 'h|help' => \$help, - 'v|version' => \$ver, - 't=s' => \$type, - 'u=s' => \$uuid, - 'l' => \$long, - ); - - if($help){ - # just return to make sequential discovery to handle it - return 0; + # do not process help message for these noddiscover* commands, cover them in seqdiscovery.pm + unless ($process_help_commands{$command} == 1) { + setrsp_infostr($helpmsg); + return 0; + } } - if($ver){ - # just return to make sequential discovery to handle it - return 0; - } - - if ($type || $uuid || $long) { - # these args for general discovery, return directly - return 0; - } - my $parseret = parse_args(); if ($parseret){ setrsp_errormsg($parseret); @@ -482,6 +498,8 @@ Usage: $warnstr = "Warning: failed to import some nodes."; setrsp_progress($warnstr); } + # setup node provisioning status. + xCAT::Utils->runxcmd({command=>["updatenodestat"], node=>\@nodelist, arg=>['defined']}, $request_command, -1, 2); setrsp_progress("Configuring nodes..."); my $retref = xCAT::Utils->runxcmd({command=>["kitnodeadd"], node=>\@nodelist, sequential=>[1], macflag=>[$mac_addr_mode]}, $request_command, 0, 2); @@ -726,9 +744,6 @@ Usage: # Update nodes' attributes foreach (@$nodes) { $updatenodeshash{$_}{'groups'} .= $profile_groups; - if ($profile_status){ - $updatenodeshash{$_}{'status'} = $profile_status; - } } #update DataBase. @@ -737,6 +752,11 @@ Usage: $nodetab->setNodesAttribs(\%updatenodeshash); $nodetab->close(); + #update node's status: + if($profile_status eq "defined"){ + xCAT::Utils->runxcmd({command=>["updatenodestat"], node=>$nodes, arg=>['defined']}, $request_command, -1, 2); + } + my $retref; my $retstrref; # Call update plugins first. @@ -1154,17 +1174,7 @@ Usage: # Update node's status. setrsp_progress("Updating node status..."); - my $nodelisttab = xCAT::Table->new('nodelist',-create=>1); - my ( - $sec, $min, $hour, $mday, $mon, - $year, $wday, $yday, $isdst - ) = localtime(time); - my $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d", - $mon + 1, $mday, $year + 1900, - $hour, $min, $sec); - - $nodelisttab->setNodeAttribs($hostname, {status=>'defined', statustime=>$currtime}); - $nodelisttab->close(); + xCAT::Utils->runxcmd({command=>["updatenodestat"], node=>[$hostname], arg=>['defined']}, $request_command, -1, 2); setrsp_progress("Updated MAC address."); } @@ -1440,7 +1450,9 @@ Usage: my $mactab = xCAT::Table->new("mac"); my $macsref = $mactab->getNodesAttribs(\@nodes, ['mac']); my $nodelisttab = xCAT::Table->new("nodelist"); - my $statusref = $nodelisttab->getNodesAttribs(\@nodes, ['status']); + # Get node current provisioning status. + my $provisionapp = "provision"; + my $provision_status = xCAT::TableUtils->getAppStatus(\@nodes,$provisionapp); my $rspentry; my $i = 0; @@ -1461,8 +1473,8 @@ Usage: } } - if ($statusref->{$_}->[0]){ - $rspentry->{node}->[$i]->{"status"} = $statusref->{$_}->[0]->{status}; + if ($provision_status->{$_}){ + $rspentry->{node}->[$i]->{"status"} = $provision_status->{$_}; } else{ $rspentry->{node}->[$i]->{"status"} = "defined"; } @@ -1626,13 +1638,19 @@ sub findme{ } my @nodelist = keys %hostinfo_dict; + # setup node provisioning status. + xCAT::Utils->runxcmd({command=>["updatenodestat"], node=>\@nodelist, arg=>['defined']}, $request_command, -1, 2); + # call makehosts to get the IP by resolving the name + my $retref = xCAT::Utils->runxcmd({command=>["makehosts"], node=>\@nodelist, sequential=>[1]}, $request_command, 0, 2); + # call discover to notify client. xCAT::MsgUtils->message('S', "Call discovered request.\n"); $request->{"command"} = ["discovered"]; $request->{"node"} = \@nodelist; $request->{discoverymethod} = ['profile']; - my $retref = xCAT::Utils->runxcmd($request, $request_command, 0, 2); + $retref = ""; + $retref = xCAT::Utils->runxcmd($request, $request_command, 0, 2); my $retstrref = parse_runxcmd_ret($retref); xCAT::MsgUtils->message('S', "Call nodemgmt plugins.\n"); diff --git a/xCAT-server/lib/xcat/plugins/pxe.pm b/xCAT-server/lib/xcat/plugins/pxe.pm index 0e69e63d7..b9fbb2066 100644 --- a/xCAT-server/lib/xcat/plugins/pxe.pm +++ b/xCAT-server/lib/xcat/plugins/pxe.pm @@ -11,9 +11,6 @@ use Getopt::Long; require xCAT::Utils; require xCAT::TableUtils; use xCAT::ServiceNodeUtils; -my $addkcmdlinehandled; -my $request; -my $callback; my $dhcpconf = "/etc/dhcpd.conf"; my $globaltftpdir = xCAT::TableUtils->getTftpDir(); #my $dhcpver = 3; @@ -93,7 +90,7 @@ sub setstate { my $imgaddkcmdline=($linuximghash{'boottarget'})? undef:$linuximghash{'addkcmdline'}; my $kern = $bphash{$node}->[0]; #$bptab->getNodeAttribs($node,['kernel','initrd','kcmdline']); - if (not $addkcmdlinehandled->{$node} and ($kern->{addkcmdline} or ($imgaddkcmdline))) { + if (not $::PXE_addkcmdlinehandled->{$node} and ($kern->{addkcmdline} or ($imgaddkcmdline))) { #Implement the kcmdline append here for #most generic, least code duplication @@ -129,7 +126,7 @@ sub setstate { $kcmdlinehack =~ s/#TABLE:([^:#]+):([^:#]+):([^:#]+)#/$naval/; } else { my $msg = "Table key of $2 not yet supported by boottarget mini-template"; - $::callback->({ + $::PXE_callback->({ error => ["$msg"], errorcode => [1] }); @@ -148,7 +145,7 @@ sub setstate { unless ($ipfn) { my @myself = xCAT::NetworkUtils->determinehostname(); my $myname = $myself[(scalar @myself)-1]; - $::callback->( + $::PXE_callback->( { error => [ "$myname: Unable to determine or reasonably guess the image server for $node" @@ -263,11 +260,11 @@ sub pass_along { $errored=1; } if ($_->{_addkcmdlinehandled}) { - $addkcmdlinehandled->{$_->{name}->[0]}=1; + $::PXE_addkcmdlinehandled->{$_->{name}->[0]}=1; return; #Don't send back to client this internal hint } } - $callback->($resp); + $::PXE_callback->($resp); } @@ -328,7 +325,7 @@ sub preprocess_request { #my $sent = $stab->getAttribs({key=>'sharedtftp'},'value'); my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $t_entry = $entries[0]; - if ( defined($t_entry) and ($t_entry == 0 or $t_entry =~ /no/i)) { + if ( defined($t_entry) and ($t_entry eq "0" or $t_entry eq "no" or $t_entry eq "NO")) { # check for computenodes and servicenodes from the noderange, if so error out my @SN; my @CN; @@ -356,28 +353,28 @@ sub preprocess_request { } sub process_request { - $request = shift; - $callback = shift; + $::PXE_request = shift; + $::PXE_callback = shift; my $sub_req = shift; - $::callback=$callback; + undef $::PXE_addkcmdlinehandled; my @args; my @nodes; my @rnodes; - if (ref($request->{node})) { - @rnodes = @{$request->{node}}; + if (ref($::PXE_request->{node})) { + @rnodes = @{$::PXE_request->{node}}; } else { - if ($request->{node}) { @rnodes = ($request->{node}); } + if ($::PXE_request->{node}) { @rnodes = ($::PXE_request->{node}); } } unless (@rnodes) { - if ($usage{$request->{command}->[0]}) { - $callback->({data=>$usage{$request->{command}->[0]}}); + if ($usage{$::PXE_request->{command}->[0]}) { + $::PXE_callback->({data=>$usage{$::PXE_request->{command}->[0]}}); } return; } #if not shared, then help sync up - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::PXE_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); foreach (@rnodes) { if (xCAT::NetworkUtils->nodeonmynet($_)) { @@ -396,16 +393,16 @@ sub process_request { return; } - if (ref($request->{arg})) { - @args=@{$request->{arg}}; + if (ref($::PXE_request->{arg})) { + @args=@{$::PXE_request->{arg}}; } else { - @args=($request->{arg}); + @args=($::PXE_request->{arg}); } #now run the begin part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::PXE_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runbeginpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -418,7 +415,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running begin prescripts\n"; - $callback->($rsp); + $::PXE_callback->($rsp); return; } } @@ -426,7 +423,7 @@ sub process_request { #end prescripts code if (! -r "$tftpdir/pxelinux.0") { unless (-r "/usr/lib/syslinux/pxelinux.0" or -r "/usr/share/syslinux/pxelinux.0") { - $callback->({error=>["Unable to find pxelinux.0 "],errorcode=>[1]}); + $::PXE_callback->({error=>["Unable to find pxelinux.0 "],errorcode=>[1]}); return; } if (-r "/usr/lib/syslinux/pxelinux.0") { @@ -437,14 +434,14 @@ sub process_request { chmod(0644,"$tftpdir/pxelinux.0"); } unless ( -r "$tftpdir/pxelinux.0" ) { - $callback->({errror=>["Unable to find pxelinux.0 from syslinux"],errorcode=>[1]}); + $::PXE_callback->({errror=>["Unable to find pxelinux.0 from syslinux"],errorcode=>[1]}); return; } $errored=0; my $inittime=0; - if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (exists($::PXE_request->{inittime})) { $inittime= $::PXE_request->{inittime}->[0];} if (!$inittime) { $inittime=0;} unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $sub_req->({command=>['setdestiny'], @@ -476,7 +473,7 @@ sub process_request { $response{node}->[0]->{name}->[0]=$_; if ($args[0] eq 'stat') { $response{node}->[0]->{data}->[0]= getstate($_,$tftpdir); - $callback->(\%response); + $::PXE_callback->(\%response); } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate my $ent = $nthash{$_}->[0]; my $osimgname = $ent->{'provmethod'}; @@ -488,13 +485,13 @@ sub process_request { if ($rc) { $response{node}->[0]->{errorcode}->[0]= $rc; $response{node}->[0]->{errorc}->[0]= $errstr; - $callback->(\%response); + $::PXE_callback->(\%response); } } } my $inittime=0; - if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (exists($::PXE_request->{inittime})) { $inittime= $::PXE_request->{inittime}->[0];} if (!$inittime) { $inittime=0;} #dhcp stuff -- inittime is set when xcatd on sn is started @@ -511,12 +508,12 @@ sub process_request { #} if ($do_dhcpsetup) { - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::PXE_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command $sub_req->({command=>['makedhcp'],arg=>['-l'], - node=>\@nodes},$callback); + node=>\@nodes},$::PXE_callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@nodes},$callback); + node=>\@nodes},$::PXE_callback); } } @@ -568,7 +565,7 @@ sub process_request { #now run the end part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::PXE_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runendpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -581,7 +578,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running end prescripts\n"; - $callback->($rsp); + $::PXE_callback->($rsp); return; } } diff --git a/xCAT-server/lib/xcat/plugins/rollupdate.pm b/xCAT-server/lib/xcat/plugins/rollupdate.pm index c038d371b..52f4d49ce 100644 --- a/xCAT-server/lib/xcat/plugins/rollupdate.pm +++ b/xCAT-server/lib/xcat/plugins/rollupdate.pm @@ -250,7 +250,7 @@ sub runrollupdate_usage { sub processArgs { my $gotattrs = 0; - if ( defined( @{$::args} ) ) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } else { diff --git a/xCAT-server/lib/xcat/plugins/route.pm b/xCAT-server/lib/xcat/plugins/route.pm index 8ec31df6c..1da3055f8 100644 --- a/xCAT-server/lib/xcat/plugins/route.pm +++ b/xCAT-server/lib/xcat/plugins/route.pm @@ -449,7 +449,7 @@ sub process_makeroutes { delete_route($callback, $route_hash->{net}, $route_hash->{mask}, $gw_ip, $gw_name, $route_hash->{ifname}); } else { - set_route($callback, $route_hash->{net}, $route_hash->{mask}, $gw_ip, $gw_name,$route_hash->{ifname}); + set_route($callback, $route_hash->{net}, $route_hash->{mask}, $gw_ip, $gw_name, $route_hash->{ifname}); } } } @@ -526,6 +526,7 @@ sub route_exists { my $mask = shift; my $gw_ip = shift; my $gw=shift; + my $ifname = shift; my $islinux=xCAT::Utils->isLinux(); @@ -557,7 +558,8 @@ sub route_exists { my $net1=$a[0]; my $mask1=$a[2]; my $gw1=$a[1]; - if (($net1 eq $net) && ($mask1 eq $mask) && (($gw1 eq $gw) || ($gw1 eq $gw_ip))) { + my $ifname1=$a[7]; + if (($net1 eq $net) && ($mask1 eq $mask) && (($gw1 eq $gw) || ($gw1 eq $gw_ip) || ($ifname1 eq $ifname))) { return 1; } } @@ -602,19 +604,27 @@ sub set_route { #print "set_route get called\n"; my $result; - if (!route_exists($net, $mask, $gw_ip, $gw)) { + if (!route_exists($net, $mask, $gw_ip, $gw, $ifname)) { #set temporay route my $cmd; # ipv6 network if ($net =~ /:/) { if (xCAT::Utils->isLinux()) { - $cmd="ip -6 route add $net/$mask via $gw_ip"; + if ( $gw_ip == "" || $gw_ip == "::" ) { + $cmd="ip -6 route add $net/$mask dev $ifname"; + } else { + $cmd="ip -6 route add $net/$mask via $gw_ip"; + } } else { # AIX TODO } } else { if (xCAT::Utils->isLinux()) { - $cmd="route add -net $net netmask $mask gw $gw_ip"; + if ( $gw_ip == "" || $gw_ip == "0.0.0.0" ) { + $cmd="route add -net $net netmask $mask dev $ifname"; + } else { + $cmd="route add -net $net netmask $mask gw $gw_ip"; + } } else { $cmd="route add -net $net -netmask $mask $gw_ip"; } @@ -676,18 +686,26 @@ sub delete_route { #print "delete_route get called\n"; my $result; - if (route_exists($net, $mask, $gw_ip, $gw)) { + if (route_exists($net, $mask, $gw_ip, $gw, $ifname)) { #delete route temporarily my $cmd; if ($net =~ /:/) { if (xCAT::Utils->isLinux()) { - $cmd = "ip -6 route delete $net/$mask via $gw_ip"; + if ( $gw_ip == "" || $gw_ip == "::" ) { + $cmd = "ip -6 route delete $net/$mask dev $ifname"; + } else { + $cmd = "ip -6 route delete $net/$mask via $gw_ip"; + } } else { # AIX TODO } } else { if (xCAT::Utils->isLinux()) { - $cmd="route delete -net $net netmask $mask gw $gw_ip"; + if ( $gw_ip == "" || $gw_ip == "0.0.0.0" ) { + $cmd="route delete -net $net netmask $mask dev $ifname"; + } else { + $cmd="route delete -net $net netmask $mask gw $gw_ip"; + } } else { $cmd="route delete -net $net -netmask $mask $gw_ip"; } @@ -827,14 +845,22 @@ sub addPersistentRoute_Sles { #print "old output=" . join("\n", @output) . "\n"; my $hasConfiged=0; if (@output && (@output > 0)) { - $hasConfiged=checkConfig_Sles($net, $mask, $gw_ip, $gw, \@output); + $hasConfiged=checkConfig_Sles($net, $mask, $gw_ip, $gw, $ifname, \@output); } #print "hasConfiged=$hasConfiged\n"; my $new_config; if ($net =~ /:/) { - $new_config = "$net/$mask $gw_ip - -\n"; + if ( $gw_ip == "" || $gw_ip == "::" ) { + $new_config = "$net/$mask :: - $ifname\n"; + } else { + $new_config = "$net/$mask $gw_ip - -\n"; + } } else { - $new_config="$net $gw_ip $mask $ifname\n"; + if ( $gw_ip == "" || $gw_ip == "0.0.0.0" ) { + $new_config="$net 0.0.0.0 $mask $ifname\n"; + } else { + $new_config="$net $gw_ip $mask $ifname\n"; + } } if (!$hasConfiged) { push(@output, $new_config); @@ -872,7 +898,7 @@ sub deletePersistentRoute_Sles { my @new_output=(); my $bigfound=0; foreach my $tmp_conf (@output) { - my $found = checkConfig_Sles($net, $mask, $gw_ip, $gw, [$tmp_conf]); + my $found = checkConfig_Sles($net, $mask, $gw_ip, $gw, $ifname, [$tmp_conf]); if (!$found) { push(@new_output, $tmp_conf); } else { @@ -909,13 +935,18 @@ sub checkConfig_Sles { my $mask = shift; my $gw_ip = shift; my $gw=shift; + my $ifname=shift; my $output=shift; + # Format: + # DESTINATION GATEWAY NETMASK INTERFACE + # DESTINATION/PREFIXLEN GATEWAY - INTERFACE + # ipv4 format: 192.168.0.0 207.68.156.51 255.255.0.0 eth1 # ipv6 format: fd59::/64 fd57:faaf:e1ab:336:21a:64ff:fe01:1 - - foreach my $line (@$output) { my @a=split(' ', $line); - my ($net1,$mask1,$gw1); + my ($net1,$mask1,$gw1,$ifname1); if ($net =~ /:/) { if (@a>0) { my $ipv6net = $a[0]; @@ -925,6 +956,10 @@ sub checkConfig_Sles { $gw1=$a[1]; if ($gw1 eq '-') { $gw1=$gw_ip; } } + if (@a>3) { + $ifname1=$a[3]; + if ($ifname1 eq '-') { $ifname1=$ifname;} + } } else { if (@a>0) { @@ -939,10 +974,14 @@ sub checkConfig_Sles { $mask1=$a[2]; if ($mask1 eq '-') { $mask1=$mask;} } + if (@a>3) { + $ifname1=$a[3]; + if ($ifname1 eq '-') { $ifname1=$ifname;} + } } - #print "net=$net1,$net mask=$mask1,$mask gw=$gw1,$gw_ip\n"; - if (($net1 && $net1 eq $net) && ($mask1 && $mask1 eq $mask) && (($gw1 && $gw1 eq $gw) || ($gw1 && $gw1 eq $gw_ip))) { + #print "net=$net1,$net mask=$mask1,$mask gw=$gw1,$gw_ip ifname=$ifname1\n"; + if (($net1 && $net1 eq $net) && ($mask1 && $mask1 eq $mask) && (($gw1 && $gw1 eq $gw) || ($gw1 && $gw1 eq $gw_ip) || ($ifname1 && $ifname1 eq $ifname))) { return 1; } } @@ -972,7 +1011,7 @@ sub addPersistentRoute_RH { #print "old output=" . join("\n", @output) . "\n"; my $hasConfiged=0; if (@output && (@output > 0)) { - $hasConfiged=checkConfig_RH($net, $mask, $gw_ip, $gw, \@output); + $hasConfiged=checkConfig_RH($net, $mask, $gw_ip, $gw, $ifname, \@output); } #print "hasConfiged=$hasConfiged\n"; my $new_config; @@ -987,7 +1026,11 @@ sub addPersistentRoute_RH { $new_config="$ifname $net/$mask $gw_ip"; } else { - $new_config="any net $net netmask $mask gw $gw_ip $ifname\n"; + if ( $gw_ip == "" || $gw_ip == "0.0.0.0" ) { + $new_config="any net $net netmask $mask dev $ifname\n"; + } else { + $new_config="any net $net netmask $mask gw $gw_ip\n"; + } } if (!$hasConfiged) { push(@output, $new_config); @@ -1031,7 +1074,7 @@ sub deletePersistentRoute_RH { my @new_output=(); my $bigfound=0; foreach my $tmp_conf (@output) { - my $found = checkConfig_RH($net, $mask, $gw_ip, $gw, [$tmp_conf]); + my $found = checkConfig_RH($net, $mask, $gw_ip, $gw, $ifname, [$tmp_conf]); if (!$found) { push(@new_output, $tmp_conf); } else { @@ -1065,14 +1108,16 @@ sub checkConfig_RH { my $mask = shift; my $gw_ip = shift; my $gw=shift; + my $ifname=shift; my $output=shift; foreach my $line (@$output) { my @a=split(' ', $line); #The format is: any net 172.16.0.0 netmask 255.240.0.0 gw 192.168.0.1 eth0 # ipv6 format: eth1 fd60::/64 fd57::214:5eff:fe15:1 - my ($net1,$mask1,$gw1); + my ($net1,$mask1,$gw1,$ifname1); if ($net =~ /:/) { + $ifname1 = $a[0]; if (@a>1) { my $ipv6net = $a[1]; ($net1,$mask1) = split("/",$ipv6net); @@ -1090,13 +1135,18 @@ sub checkConfig_RH { if ($mask1 eq '-') { $mask1=$mask;} } if (@a>6) { - $gw1=$a[6]; - if ($gw1 eq '-') { $gw1=$gw_ip; } + if ( $a[5] eq 'dev' ) { + $ifname1=$a[6]; + if ($ifname1 eq '-') { $ifname1=$ifname;} + } else { + $gw1=$a[6]; + if ($gw1 eq '-') { $gw1=$gw_ip; } + } } } - #print "net=$net1,$net mask=$mask1,$mask gw=$gw1,$gw_ip\n"; - if (($net1 && $net1 eq $net) && ($mask1 && $mask1 eq $mask) && (($gw1 && $gw1 eq $gw) || ($gw1 && $gw1 eq $gw_ip))) { + #print "net=$net1,$net mask=$mask1,$mask gw=$gw1,$gw_ip ifname=$ifname1,ifname\n"; + if (($net1 && $net1 eq $net) && ($mask1 && $mask1 eq $mask) && (($gw1 && $gw1 eq $gw) || ($gw1 && $gw1 eq $gw_ip) || ($ifname1 && $ifname1 eq $ifname))) { return 1; } } @@ -1120,12 +1170,21 @@ sub addPersistentRoute_Debian{ #ipv6 if ( $net =~ /:/){ - $cmd = "grep \"$net/$mask gw $gw_ip\" $conf_file"; - $route_conf = " up route -A inet6 add $net/$mask gw $gw_ip \n down route -A inet6 del $net/$mask gw $gw_ip \n"; + if ( $gw_ip == "" || $gw_ip == "::" ) { + $cmd = "grep \"$net/$mask dev $ifname\" $conf_file"; + $route_conf = " up route -A inet6 add $net/$mask dev $ifname \n down route -A inet6 del $net/$mask dev $ifname \n"; + } else { + $cmd = "grep \"$net/$mask gw $gw_ip\" $conf_file"; + $route_conf = " up route -A inet6 add $net/$mask gw $gw_ip \n down route -A inet6 del $net/$mask gw $gw_ip \n"; + } } else { #ipv4 $cmd = "grep \"-net $net netmask $mask gw $gw_ip\" $conf_file"; - $route_conf = " up route add -net $net netmask $mask gw $gw_ip \n down route del -net $net netmask $mask gw $gw_ip \n"; + if ( $gw_ip == "" || $gw_ip == "0.0.0.0" ) { + $route_conf = " up route add -net $net netmask $mask dev $ifname \n down route del -net $net netmask $mask dev $ifname \n"; + } else { + $route_conf = " up route add -net $net netmask $mask gw $gw_ip \n down route del -net $net netmask $mask gw $gw_ip\n"; + } } #fine the corresponding config in the config file @@ -1183,10 +1242,18 @@ sub deletePersistentRoute_Debian{ preParse_Debian(); #ipv6 if ( $net =~ /:/){ - $match = "$net/$mask gw $gw_ip"; + if ( $gw_ip == "" || $gw_ip == "::" ) { + $match = "$net/$mask dev $ifname"; + } else { + $match = "$net/$mask gw $gw_ip"; + } } else { - $match = "net $net netmask $mask gw $gw_ip"; + if ( $gw_ip == "" || $gw_ip == "0.0.0.0" ) { + $match = "net $net netmask $mask dev $ifname"; + } else { + $match = "net $net netmask $mask gw $gw_ip"; + } } open(FH, "<", $conf_file); diff --git a/xCAT-server/lib/xcat/plugins/sles.pm b/xCAT-server/lib/xcat/plugins/sles.pm old mode 100644 new mode 100755 index 85570f62b..786dcbfd0 --- a/xCAT-server/lib/xcat/plugins/sles.pm +++ b/xCAT-server/lib/xcat/plugins/sles.pm @@ -957,6 +957,8 @@ sub mkinstall my $tmppkgdir=$pkgdir; my @srcdirs = split(",", $pkgdir); $pkgdir = $srcdirs[0]; + # trim the "/" in /install/sles11.3/x86_64/ + $pkgdir =~ s/\/$//; if( $pkgdir =~/^($installroot\/$os\/$arch)$/) { $srcdirs[0]="$pkgdir/1"; $tmppkgdir=join(",", @srcdirs); @@ -1073,6 +1075,14 @@ sub mkinstall { $netserver = $ent->{nfsserver}; } + + if ($::XCATSITEVALS{managedaddressmode} =~ /static/){ + unless($netserver eq '!myipfn!'){ + my($host,$ip)=xCAT::NetworkUtils->gethostnameandip($netserver); + $netserver=$ip; + } + } + my $httpprefix = $pkgdir; if ($installroot =~ /\/$/) { #must prepend /install/ $httpprefix =~ s/^$installroot/\/install\//; @@ -1137,6 +1147,56 @@ sub mkinstall $kcmdline .= " dud=file:/cus_driverdisk/$_"; } + #if site.managedaddressmode=static, specify the network configuration as kernel options + #to avoid multicast dhcp + if($::XCATSITEVALS{managedaddressmode} =~ /static/){ + my ($ipaddr,$hostname,$gateway,$netmask)=xCAT::NetworkUtils->getNodeNetworkCfg($node); + unless($ipaddr) { + $callback->( + { + error => [ + "cannot resolve the ip address of $node" + ], + errorcode => [1] + } + ); + } + if($gateway eq ''){ + $gateway = xCAT::NetworkUtils->my_ip_facing($ipaddr); + } + $kcmdline .=" hostip=$ipaddr netmask=$netmask gateway=$gateway hostname=$hostname "; + + + my %nameservers=%{xCAT::NetworkUtils->getNodeNameservers([$node])}; + my @nameserverARR=split (",",$nameservers{$node}); + my @nameserversIP; + foreach (@nameserverARR) + { + my $ip; + if($_ eq ''){ + $ip = xCAT::NetworkUtils->my_ip_facing($gateway); + }else{ + (undef,$ip) = xCAT::NetworkUtils->gethostnameandip($_); + } + push @nameserversIP, $ip; + + } + + if(scalar @nameserversIP){ + $kcmdline .=" Nameserver=".join(",",@nameserversIP); + } + + my $nd = xCAT::NetworkUtils->getNodeDomains([$node]); + my %nodedomains = %$nd; + my $domain=$nodedomains{$node}; + + $kcmdline .=" Domain=$domain "; + } + + + + + if (defined $sent->{serialport}) { unless ($sent->{serialspeed}) diff --git a/xCAT-server/lib/xcat/plugins/tabutils.pm b/xCAT-server/lib/xcat/plugins/tabutils.pm index 0d94c60fb..3001c0546 100644 --- a/xCAT-server/lib/xcat/plugins/tabutils.pm +++ b/xCAT-server/lib/xcat/plugins/tabutils.pm @@ -957,7 +957,7 @@ sub tabprune push @{$rsp{data}}, " tabprune [-V] -d <# of days>"; push @{$rsp{data}}, " tabprune [-h|--help]"; push @{$rsp{data}}, " tabprune [-v|--version]"; - push @{$rsp{data}}, " tables supported:eventlog,auditlog"; + push @{$rsp{data}}, " tables supported:eventlog,auditlog,unless -a which supports all tables"; push @{$rsp{data}}, " -d option only supported for eventlog,auditlog"; if ($exitcode) { $rsp{errorcode} = $exitcode; } $cb->(\%rsp); @@ -997,7 +997,7 @@ sub tabprune } $table=~ s/\s*//g; # remove blanks - if (($table ne "eventlog") && ($table ne "auditlog") && ($table ne "isnm_perf") && ($table ne "isnm_perf_sum") ) { + if (($table ne "eventlog") && ($table ne "auditlog") && ($table ne "isnm_perf") && ($table ne "isnm_perf_sum") && (! $ALL)) { my %rsp; $rsp{data}->[0] = "Table $table not supported, see tabprune -h for supported tables."; $rsp{errorcode} = 1; @@ -2654,7 +2654,7 @@ sub getTablesNodesAttribs my %noderecs; my $recs; # build the table name record - @{$noderecs{table}->[0]->{tablename}} = $tablename; + #@{$noderecs{table}->[0]->{tablename}} = $tablename; # if request for ALL attributes if (grep (/ALL/,@attrs)) { # read the schema and build array of all attrs @attrs=(); @@ -2681,6 +2681,7 @@ sub getTablesNodesAttribs } } + @{$noderecs{table}->[0]->{tablename}} = $tablename; push @{$rsp{"table"}}, @{$noderecs{table}}; } # end of all table processing # for checkin XML created @@ -2752,9 +2753,9 @@ sub getTablesAllRowAttribs my $attr = $tabhash->{attr}; my @attrs=@$attr; my $tab=xCAT::Table->new($tablename); - my %noderecs; + my %tblrecs; # build the table name record - @{$noderecs{table}->[0]->{tablename}} = $tablename; + @{$tblrecs{table}->[0]->{tablename}} = $tablename; # if request for ALL attributes if (grep (/ALL/,@attrs)) { # read the schema and build array of all attrs @attrs=(); @@ -2767,7 +2768,6 @@ sub getTablesAllRowAttribs } # read all the attributes in this table my @recs = $tab->getAllAttribs(@attrs); - my %tblrecs; foreach my $rec (@recs) { my %datseg=(); foreach my $key (keys %$rec) { @@ -2975,6 +2975,21 @@ sub getAttribs # This is a comment # # +# +# +#PCM +#setAttribs +#networks
+# +# 10.0.1.0 +# 255.255.255.0 +# +# +# mynet +# 10.0.1.254 +# +#
+ sub setAttribs { my $request = shift; diff --git a/xCAT-server/lib/xcat/plugins/toolscenter.pm b/xCAT-server/lib/xcat/plugins/toolscenter.pm index a8ef36118..70c500605 100644 --- a/xCAT-server/lib/xcat/plugins/toolscenter.pm +++ b/xCAT-server/lib/xcat/plugins/toolscenter.pm @@ -68,9 +68,10 @@ sub preprocess_request my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $t_entry = $entries[0]; unless ( defined($t_entry) - and ($t_entry =~ /no/i or $t_entry =~ /0/)) + and ($t_entry eq "no" or $t_entry eq "NO" or $t_entry eq "0")) { + #unless requesting no sharedtftp, don't make hierarchical call return [$req]; } diff --git a/xCAT-server/lib/xcat/plugins/updatenode.pm b/xCAT-server/lib/xcat/plugins/updatenode.pm index bf0143272..2861206e3 100644 --- a/xCAT-server/lib/xcat/plugins/updatenode.pm +++ b/xCAT-server/lib/xcat/plugins/updatenode.pm @@ -14,6 +14,7 @@ use xCAT::Schema; use Data::Dumper; use xCAT::Utils; use xCAT::SvrUtils; +use xCAT::Scope; use xCAT::Usage; use Storable qw(dclone); use xCAT::TableUtils; @@ -188,6 +189,7 @@ sub preprocess_updatenode my @requests = (); my $installdir = xCAT::TableUtils->getInstallDir(); + my $localhost = hostname(); # subroutine to display the usage sub updatenode_usage @@ -251,20 +253,40 @@ sub preprocess_updatenode $callback->($rsp); return; } - # Just generate mypostscripts file and get out + + # preprocess generate mypostscripts files (-g) for hierarchy + # if no sharedtftp then we need to broadcast this updatenode -g to all service nodes inorder + # to be able to support service node pools + # if ($::GENMYPOST) { + # precreatemypostscript has to be yes/1 or do nothing my @entries = xCAT::TableUtils->get_site_attribute("precreatemypostscripts"); if ($entries[0] ) { $entries[0] =~ tr/a-z/A-Z/; if ($entries[0] =~ /^(1|YES)$/ ) { - - my $notmpfiles=1; - my $nofiles=0; - xCAT::Postage::create_mypostscript_or_not($request, $callback, $subreq,$notmpfiles,$nofiles); - my $rsp = {}; - $rsp->{data}->[0] = "Generated new mypostscript files"; - $callback->($rsp); + # now check if sharedtftp = 0, if it is we need to broadcast to all the servicenode + # if there are service nodes + my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); + my $t_entry = $entries[0]; + if ( defined($t_entry) and ($t_entry eq "0" or $t_entry eq "no" or $t_entry eq "NO")) { + # see if there are any servicenodes. If so then run updatenode -g on all of them + my @SN; + my @CN; + my $nodes = $request->{node}; + xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN); + if (@CN >0 ) { # if compute nodes broadcast to all servicenodes + return xCAT::Scope->get_broadcast_scope($request,@_); + } + } else { # sharedtftp=yes, just run on MN + my $notmpfiles=1; + my $nofiles=0; + xCAT::Postage::create_mypostscript_or_not($request, $callback, $subreq,$notmpfiles,$nofiles); + my $rsp = {}; + $rsp->{data}->[0] = "Generated new mypostscript files on $localhost"; + $callback->($rsp); + return 0; + } } else { # not valid unless precreatemypostscripts enabled my $rsp = {}; $rsp->{error}->[0] = @@ -273,7 +295,7 @@ sub preprocess_updatenode $callback->($rsp); return ; } - } else { # not in the site table + } else { # precreatemypostscripts not in the site table my $rsp = {}; $rsp->{error}->[0] = "This option is only valid if site table precreatemypostscripts attribute is 1 or YES"; @@ -281,8 +303,9 @@ sub preprocess_updatenode $callback->($rsp); return ; } - return 0; - } + } # end GENMYPOST + + # -c must work with -S for AIX node if ($::CMDLINE && !$::SWMAINTENANCE) @@ -1010,27 +1033,6 @@ sub updatenode } - #create each /tftpboot/mypostscript/mypostscript. for each node - # This first removes the old one if precreatemypostscripts =0 or undefined - # call create files but no tmp files - my $notmpfiles=1; - my $nofiles=0; - #my $nofiles=1; - xCAT::Postage::create_mypostscript_or_not($request, $callback, $subreq,$notmpfiles,$nofiles); - - # convert the hashes back to the way they were passed in - my $flatreq = xCAT::InstUtils->restore_request($request, $callback); - my $imgdefs; - my $updates; - if ($flatreq->{imagedef}) - { - $imgdefs = $flatreq->{imagedef}; - } - if ($flatreq->{updateinfo}) - { - $updates = $flatreq->{updateinfo}; - } - # get the NIM primary server name my $nimprime = xCAT::InstUtils->getnimprime(); chomp $nimprime; @@ -1043,6 +1045,7 @@ sub updatenode 'A|updateallsw' => \$::ALLSW, 'c|cmdlineonly' => \$::CMDLINE, 'd=s' => \$::ALTSRC, + 'g|genmypost' => \$::GENMYPOST, 'h|help' => \$::HELP, 'v|version' => \$::VERSION, 'V|verbose' => \$::VERBOSE, @@ -1085,6 +1088,60 @@ sub updatenode $::attrres{$attr} = $value; } } + # Just generate mypostscripts file and get out + if ($::GENMYPOST) + { + my @entries = xCAT::TableUtils->get_site_attribute("precreatemypostscripts"); + if ($entries[0] ) { + $entries[0] =~ tr/a-z/A-Z/; + if ($entries[0] =~ /^(1|YES)$/ ) { + + my $notmpfiles=1; + my $nofiles=0; + xCAT::Postage::create_mypostscript_or_not($request, $callback, $subreq,$notmpfiles,$nofiles); + my $rsp = {}; + $rsp->{data}->[0] = "Generated new mypostscript files on $localhostname"; + $callback->($rsp); + } else { # not valid unless precreatemypostscripts enabled + my $rsp = {}; + $rsp->{error}->[0] = + "This option is only valid if site table precreatemypostscripts attribute is 1 or YES"; + $rsp->{errorcode}->[0] =1; + $callback->($rsp); + return ; + } + } else { # not in the site table + my $rsp = {}; + $rsp->{error}->[0] = + "This option is only valid if site table precreatemypostscripts attribute is 1 or YES"; + $rsp->{errorcode}->[0] =1; + $callback->($rsp); + return ; + } + return 0; + } + + #create each /tftpboot/mypostscript/mypostscript. for each node + # This first removes the old one if precreatemypostscripts =0 or undefined + # call create files but no tmp files + my $notmpfiles=1; + my $nofiles=0; + #my $nofiles=1; + xCAT::Postage::create_mypostscript_or_not($request, $callback, $subreq,$notmpfiles,$nofiles); + + # convert the hashes back to the way they were passed in + my $flatreq = xCAT::InstUtils->restore_request($request, $callback); + my $imgdefs; + my $updates; + if ($flatreq->{imagedef}) + { + $imgdefs = $flatreq->{imagedef}; + } + if ($flatreq->{updateinfo}) + { + $updates = $flatreq->{updateinfo}; + } + # if not just using the -k flag, then set all nodes to syncing in # nodelist updatestatus for the other updatenode options if (!($::SECURITY)) { diff --git a/xCAT-server/lib/xcat/plugins/vbox.pm b/xCAT-server/lib/xcat/plugins/vbox.pm index 475aded2c..30b542e1c 100644 --- a/xCAT-server/lib/xcat/plugins/vbox.pm +++ b/xCAT-server/lib/xcat/plugins/vbox.pm @@ -1,12 +1,14 @@ # IBM(c) 2008 EPL license http://www.eclipse.org/legal/epl-v10.html # Ver. 2.1 (4) - sf@mauricebrinkmann.de +# Ver. 3.0 - Herbert Mehlhose, IBM - add support of VirtualBox V4 +# #------------------------------------------------------- =head1 xCAT plugin package to handle VirtualBox machines Supported command: - rpower + rpower =cut @@ -25,11 +27,9 @@ use Getopt::Long; use strict; use warnings; -my $cmd = 'clienttest'; - #------------------------------------------------------- -=head3 handled_commands +=head3 handled_commands Return list of commands handled by this plugin @@ -39,12 +39,12 @@ Return list of commands handled by this plugin sub handled_commands { - return {rpower => 'nodehm:power,mgt'}; + return {rpower => 'nodehm:power,mgt'}; } #------------------------------------------------------- -=head3 preprocess_request +=head3 preprocess_request Check and setup for hierarchy @@ -53,39 +53,37 @@ sub handled_commands #------------------------------------------------------- sub preprocess_request { - my $req = shift; - my $cb = shift; - if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } - #exit if preprocessed - my $nodes = $req->{node}; - my $service = "xcat"; + my $req = shift; + my $cb = shift; + if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + #exit if preprocessed + my $nodes = $req->{node}; + my $service = "xcat"; - # find service nodes for requested nodes - # build an individual request for each service node - my $sn = xCAT::ServiceNodeUtils->get_ServiceNode($nodes, $service, "MN"); + # find service nodes for requested nodes + # build an individual request for each service node + my $sn = xCAT::ServiceNodeUtils->get_ServiceNode($nodes, $service, "MN"); my @requests = (); - # build each request for each service node - - foreach my $snkey (keys %$sn) - { + # build each request for each service node + foreach my $snkey (keys %$sn) { my $n=$sn->{$snkey}; print "snkey=$snkey, nodes=@$n\n"; - my $reqcopy = {%$req}; - $reqcopy->{node} = $sn->{$snkey}; - $reqcopy->{'_xcatdest'} = $snkey; - $reqcopy->{_xcatpreprocessed}->[0] = 1; - push @requests, $reqcopy; + my $reqcopy = {%$req}; + $reqcopy->{node} = $sn->{$snkey}; + $reqcopy->{'_xcatdest'} = $snkey; + $reqcopy->{_xcatpreprocessed}->[0] = 1; + push @requests, $reqcopy; - } - return \@requests; + } + return \@requests; } #------------------------------------------------------- -=head3 process_request +=head3 process_request Process the command @@ -95,445 +93,595 @@ sub preprocess_request sub process_request { - my $request = shift; - our $callback = shift; - my $nodes = $request->{node}; - my $command = $request->{command}->[0]; - my $args = $request->{arg}; - my $envs = $request->{env}; + my $request = shift; + our $callback = shift; + my $nodes = $request->{node}; + my $command = $request->{command}->[0]; + my $args = $request->{arg}; + my $envs = $request->{env}; our $rsp; my $node; my $soapsupport = eval { require SOAP::Lite; }; unless ($soapsupport) { #Still no SOAP::Lite module - $callback->({error=>"SOAP::Lite perl module missing, unable to fulfill Virtual Box plugin requirements",errorcode=>[42]}); - return []; + $callback->({error=>"SOAP::Lite perl module missing, unable to fulfill Virtual Box plugin requirements",errorcode=>[42]}); + return []; } require xCAT::vboxService; - my @nodes=@$nodes; + my @nodes=@$nodes; - PROCESSNODES: foreach $node (@nodes) ###################################### - { - # Load node information from xCAT tables - my ($error, $url, $username, $password, $vmname, $vncport) = getInfo($node); - next PROCESSNODES if ($error == 1); - last PROCESSNODES if ($error == 2); - - # Create connection to VirtualBox web service and check for errors - my $vbox = getWebService($url, $username, $password, $node); - next PROCESSNODES if (!$vbox); - - # Get the machine - my $machine = getMachine($url, $vbox, $vmname, $node); - if ($machine) - { - - # Command differentiation #------------------------------------ - - if ($command eq "rpower" and @$args > 0) - { - powerCtrl($url, $vbox, $machine, $vmname, $node, $vncport, $args); - } - - #else # unrecognized command - #{ - # addError("$node: $command unsupported on vm"); - #} - - # End Command differentiation #-------------------------------- - - } # /existing $machine reference - - xCAT::vboxService->IWebsessionManager_logoff($url, $vbox); - - } # /for each $node in @nodes - continue - { - # print out status before waiting for others and others and .. - printMessages(); - - # yield??? - } - - # last chance to print remaining messages - printMessages(); - - return; - - - sub addMessage ############################################################ - { - push @{$rsp->{data}}, shift; - - } # /addMessage - - sub addError ############################################################## - { - push @{$rsp->{error}}, shift; - - } # /addError - - - sub printMessages ######################################################### - { - if (defined($rsp->{data}) or defined($rsp->{error})) - { - if (defined($rsp->{error})) - { - push @{$rsp->{errorcode}}, 1; - xCAT::MsgUtils->message("E", $rsp, $callback, 0); - } - else - { - xCAT::MsgUtils->message("I", $rsp, $callback, 0); - } - } - - } # /printMessages - - - sub powerCtrl ############################################################# - { - my ($url, $vbox, $machine, $vmname, $node, $vncport, $args) = - (shift, shift, shift, shift, shift, shift, shift); - - # Get state of the machine first - my $vmstate = xCAT::vboxService->IMachine_getState($url, $machine); - - # Check if there is anything to do - if (!$vmstate) - { - addError("$node: Can not determine vm's state!"); - return; - } - elsif ($vmstate =~ m/^PoweredOff|^Aborted|^Saved/) - { - if ($args->[0] eq "off") - { - addMessage("$node: off"); - return; - } - elsif ($args->[0] =~ m/^reset|^boot/) - { - # if machine is off: turn on when reset was choosen - $args->[0] = "on reset"; - } - elsif ($args->[0] =~ m/^stat/) - { - # addMessage("$node: off ($vmstate)"); - addMessage("$node: off"); - return; - } - } - else - { - if ($args->[0] eq "on") - { - addMessage("$node: on"); - return; - } - elsif ($args->[0] =~ m/^stat/) - { - # addMessage("$node: on ($vmstate)"); - addMessage("$node: on"); - return; - } - } - - # Determine machine's UUID - Should work since we got the state - my $uuid = xCAT::vboxService->IMachine_getId($url, $machine); - - # Open Session - my $session = getSession($url, $vbox, $node, $vmname); - if ($session) - { - # Decide what to do - if ($args->[0] =~ m/^on/) - { - powerOn($url, $vbox, $session, $uuid, $node, $vncport, $args); - } - else - { - powerOff($url, $vbox, $session, $machine, $uuid, $node, $args); - } - - xCAT::vboxService->ISession_close($url, $session); - } # /existing $session - - return; - - - sub powerOn #********************************************************** - { - my ($url, $vbox, $session, $uuid, $node, $vncport, $args) = - (shift, shift, shift, shift, shift, shift, shift); - - ########################## - xCAT::vboxService->IVirtualBox_openSession( - $url, $vbox, $session, $uuid); - - my $directmachine = xCAT::vboxService->ISession_getMachine($url, $session); - if (!$directmachine) - { - addError("$node: Could not access mutable machine"); - } - else - { - my $vrdp = xCAT::vboxService->IMachine_getVRDPServer( - $url, $directmachine); - - my $portno = xCAT::vboxService->IVRDPServer_getPort($url, $vrdp); - if ($vncport and ($vncport != $portno)) - { - # If port is specified but different: Update machine settings - xCAT::vboxService->IVRDPServer_setPort($url, $vrdp, $vncport); - xCAT::vboxService->IMachine_saveSettings($url, $directmachine); - } - elsif (!$vncport) - { - # If not specified yet: Save port to xCAT db - $vncport = $portno; - my $vmTab = openTable('vm'); - $vmTab->setNodeAttribs($node,{vncport=>$vncport}); - $vmTab->close(); - } - xCAT::vboxService->IManagedObjectRef_release($url, $vrdp); - xCAT::vboxService->IManagedObjectRef_release($url, $directmachine); + PROCESSNODES: foreach $node (@nodes) ###################################### + { + # Load node information from xCAT tables + my ($error, $url, $username, $password, $vmname, $vncport) = getInfo($node); + next PROCESSNODES if ($error == 1); + last PROCESSNODES if ($error == 2); + + # Create connection to VirtualBox web service + my $api; # we assume V4 as default API + my $vbox = getWebService($url, $username, $password, $node); + next PROCESSNODES if (!$vbox); + + # get version + my $vboxvers = xCAT::vboxService->IVirtualBox_getVersion($url, $vbox); + #$callback->({info=>"$node: Vbox version: '$vboxvers', requested vncport via xCAT 'vm' table: '$vncport'"}); + if ($vboxvers =~ "^3.0" and $vncport =~ ",") + { + addError("$node: VirtualBox version 3.0 does only support a single RDP port, please correct entry vncport='$vncport' in table 'vm' for this node."); + next PROCESSNODES; + } + if($vboxvers =~ "^3.") { + $api="3"; # There is no getAPIVersion in Version 3, set to 3 + } elsif($vboxvers =~ "^4.0") { + $api="4_0"; # There is no getAPIVersion in Version 4.0 set to 4_0 + } else { + $api = xCAT::vboxService->IVirtualBox_getAPIVersion($url, $vbox); + } + # Get the machine + my $machine = getMachine($api, $url, $vbox, $vmname, $node); + if ($machine) { + + # Command differentiation #------------------------------------ + + if ($command eq "rpower" and @$args > 0) { + powerCtrl($vboxvers, $api, $url, $vbox, $machine, $vmname, $node, $vncport, $args); } - xCAT::vboxService->ISession_close($url, $session); - ############################## - - my $progress = xCAT::vboxService->IVirtualBox_openRemoteSession( - $url, $vbox, $session, $uuid, "vrdp", ""); - - if (!$progress) - { - addError("$node: Can not open remote session"); - } - else # existing $progress - { - xCAT::vboxService->IProgress_waitForCompletion( - $url, $progress, -1); - - if (xCAT::vboxService->IProgress_getCompleted( - $url, $progress)) - { - addMessage("$node: $args->[0]"); - } - else # not successfully completed - { - addError("$node: Power on failed"); - } - - } # /existing $progress - - return; - - } # /powerOn - - - sub powerOff #********************************************************* - { - my ($url, $vbox, $session, $machine, $uuid, $node, $args) = - (shift, shift, shift, shift, shift, shift, shift); - - # Lock session with machine - my $vmsessionstate = xCAT::vboxService->IMachine_getSessionState( - $url, $machine); - - if ($vmsessionstate eq "Open") - { - xCAT::vboxService->IVirtualBox_openExistingSession( - $url, $vbox, $session, $uuid); - } - elsif ($vmsessionstate eq "Closed") - { - xCAT::vboxService->IVirtualBox_openSession( - $url, $vbox, $session, $uuid); - } - else # !$vmsessionstate - { - addError("$node: No direct session to machine"); - } - + #else # unrecognized command + #{ + # addError("$node: $command unsupported on vm"); + #} + + # End Command differentiation #-------------------------------- + + } # /existing $machine reference + + xCAT::vboxService->IWebsessionManager_logoff($url, $vbox); + + } # /for each $node in @nodes + continue + { + # print out status before waiting for others and others and .. + printMessages(); + + # yield??? + } + + # last chance to print remaining messages + printMessages(); + + return; + + + sub addMessage ############################################################ + { + push @{$rsp->{data}}, shift; + + } # /addMessage + + sub addError ############################################################## + { + push @{$rsp->{error}}, shift; + + } # /addError + + + sub printMessages ######################################################### + { + if (defined($rsp->{data}) or defined($rsp->{error})) { + if (defined($rsp->{error})) { + push @{$rsp->{errorcode}}, 1; + xCAT::MsgUtils->message("E", $rsp, $callback, 0); + } else { + xCAT::MsgUtils->message("I", $rsp, $callback, 0); + } + } + + } # /printMessages + + + sub powerCtrl ############################################################# + { + my ($vboxvers, $api, $url, $vbox, $machine, $vmname, $node, $vncport, $args) = + (shift, shift, shift, shift, shift, shift, shift, shift, shift); + + # Get state of the machine first + my $cmd = "IMachine_getState"; + if($api eq "3") { + $cmd=$cmd . "_V3"; + } + my $vmstate = xCAT::vboxService->$cmd($url, $machine); + + # Check if there is anything to do + if (!$vmstate) { + addError("$node: Can not determine vm's state!"); + return; + } elsif ($vmstate =~ m/^PoweredOff|^Aborted|^Saved/) { + if ($args->[0] eq "off") { + addMessage("$node: off"); + return; + } elsif ($args->[0] =~ m/^reset|^boot/) { + # if machine is off: turn on when reset was choosen + $args->[0] = "on reset"; + } elsif ($args->[0] =~ m/^stat/) { + # addMessage("$node: off ($vmstate)"); + addMessage("$node: off"); + return; + } + } else { + if ($args->[0] eq "on") { + addMessage("$node: on"); + return; + } elsif ($args->[0] =~ m/^stat/) { + # addMessage("$node: on ($vmstate)"); + addMessage("$node: on"); + return; + } + } + + # Determine machine's UUID - Should work since we got the state + $cmd = "IMachine_getId"; + if($api eq "3") {$cmd=$cmd . "_V3";} + my $uuid = xCAT::vboxService->$cmd($url, $machine); + + # Open Session + my $session = getSession($api, $url, $vbox, $node, $vmname); + if ($session) { + # Decide what to do + if ($args->[0] =~ m/^on/) { + if($api eq "3") { + powerOn_V3($vboxvers, $url, $vbox, $machine, $session, $uuid, $node, $vncport, $args); + } else { + powerOn($url, $vbox, $machine, $session, $uuid, $node, $vncport, $args); + } + } else { + if($api eq "3") { + powerOff_V3($url, $vbox, $session, $machine, $uuid, $node, $args); + } else { + powerOff($url, $vbox, $session, $machine, $uuid, $node, $args); + } + } + + xCAT::vboxService->ISession_unlockMachine($url,$session); + } # /existing $session + + return; + + + sub powerOn #********************************************************** + { + my ($url, $vbox, $machine, $session, $uuid, $node, $vncport, $args) = + (shift, shift, shift, shift, shift, shift, shift, shift); + + my $locktype="Write"; + xCAT::vboxService->IMachine_lockMachine($url,$machine,$session,$locktype); + + my $directmachine = xCAT::vboxService->ISession_getMachine($url, $session); + if (!$directmachine) { + addError("$node: Could not access mutable machine"); + } else { + my $vrde = xCAT::vboxService->IMachine_getVRDEServer($url, $directmachine); + + # 'Oracle VM VirtualBox Extension Pack' needs to be installed on vbox server + # to be able to use RDP + my $extpack; + my @VRDEextpack = xCAT::vboxService->IVRDEServer_getVRDEExtPack($url, $vrde); + foreach(@VRDEextpack) { + if($_ eq "Oracle VM VirtualBox Extension Pack") { + $extpack=1; + } + } + + if($extpack) { + my $hasVRDE = xCAT::vboxService->IVRDEServer_getEnabled($url, $vrde); + + my $prop="TCP/Ports"; + my $portno = xCAT::vboxService->IVRDEServer_getVRDEProperty($url, $vrde, $prop); + + if ($vncport) { # vncport determines, if rdp will be enabled + my $change; + # If port is specified but different: Update machine settings + if($hasVRDE eq "false") { + $hasVRDE="true"; + xCAT::vboxService->IVRDEServer_setEnabled($url, $vrde, $hasVRDE); + $change=1; + } + if($vncport ne $portno) { + xCAT::vboxService->IVRDEServer_setVRDEProperty($url, $vrde, $prop, $vncport); + $change=1; + } + if($change) { + xCAT::vboxService->IMachine_saveSettings($url, $directmachine); + } + } elsif (!$vncport and $hasVRDE eq "true") { + # If not specified: disable RDP for the guest + $hasVRDE="false"; + xCAT::vboxService->IVRDEServer_setEnabled($url, $vrde, $hasVRDE); + xCAT::vboxService->IMachine_saveSettings($url, $directmachine); + } + #xCAT::vboxService->IMachine_saveSettings($url, $directmachine); + xCAT::vboxService->IManagedObjectRef_release($url, $directmachine); + } else { + if($vncport) { + addMessage("Warning: for VirtualBox Version 4 and above, RDP needs the VRDE Extension Pack to be installed on the VirtualBox host system. Either install this package to use RDP with the guest machine or remove the 'vncport' from xCAT vm table for '$node' to avoid this warning message to appear. Starting without RDP for now."); + } + } + } + + xCAT::vboxService->ISession_unlockMachine($url,$session); + + my $progress = xCAT::vboxService->IMachine_launchVMProcess($url, $machine, $session, "headless", ""); #gui + + if (!$progress) { + addError("$node: Can not open remote session"); + } else { # existing $progress + xCAT::vboxService->IProgress_waitForCompletion($url, $progress, -1); + + if (xCAT::vboxService->IProgress_getCompleted($url, $progress)) { + addMessage("$node: $args->[0]"); + } else { # not successfully completed + addError("$node: Power on failed"); + } + + } # /existing $progress + + return; + + } # /powerOn + + + sub powerOn_V3 #********************************************************** + { + my ($vboxvers, $url, $vbox, $machine, $session, $uuid, $node, $vncport, $args) = + (shift, shift, shift, shift, shift, shift, shift, shift, shift); + + xCAT::vboxService->IVirtualBox_openSession_V3($url, $vbox, $session, $uuid); + + my $directmachine = xCAT::vboxService->ISession_getMachine_V3($url, $session); + my $hasVRDP; + if (!$directmachine) { + addError("$node: Could not access mutable machine"); + } else { + my $vrdp = xCAT::vboxService->IMachine_getVRDPServer_V3($url, $directmachine); + $hasVRDP = xCAT::vboxService->IVRDPServer_getEnabled_V3($url, $vrdp); + my $portno; + my $vncportmismatch; # current rdp port differs from vm table vncport definition + if($vboxvers =~ "^3.0") { # returns single port as unsigned long + $portno = xCAT::vboxService->IVRDPServer_getPort_V30($url, $vrdp); + if ($vncport and ($vncport != $portno)) { + $vncportmismatch=1; + } + } else { # returns one or more ports as string + $portno = xCAT::vboxService->IVRDPServer_getPorts_V3($url, $vrdp); + if ($vncport and ($vncport ne $portno)) { + $vncportmismatch=1; + } + } + my $change; + if($vncport and ($hasVRDP eq "false")) { + $hasVRDP="true"; + xCAT::vboxService->IVRDPServer_setEnabled_V3($url, $vrdp, $hasVRDP); + $change=1; + } + if ($vncportmismatch) { + if($vboxvers =~ "^3.0") { # returns single port as unsigned long + xCAT::vboxService->IVRDPServer_setPort_V30($url, $vrdp, $vncport); + } else { + xCAT::vboxService->IVRDPServer_setPorts_V3($url, $vrdp, $vncport); + } + $change=1; + } + if (!$vncport and $hasVRDP eq "true") { + $hasVRDP="false"; + xCAT::vboxService->IVRDPServer_setEnabled_V3($url, $vrdp, $hasVRDP); + $change=1; + } + if ($change) { + xCAT::vboxService->IMachine_saveSettings_V3($url, $directmachine); + } + xCAT::vboxService->IManagedObjectRef_release_V3($url, $vrdp); + xCAT::vboxService->IManagedObjectRef_release_V3($url, $directmachine); + } + + xCAT::vboxService->ISession_close_V3($url, $session); + my $v3session; + if ($hasVRDP eq "true") { + $v3session="vrdp"; #vrdp + } else { + # found "headles" to be undocumented in SDK ref, but this allows to open a headless session w/o VRDP + # and thus we can disable rdp without being forced to launch the gui. This allows to follow + # the logic, that an empty vncport in the vm table will disable rdp, and having a value in + # table vm will define the port and enable rdp. + $v3session="headless"; # gui + } + #my $progress = xCAT::vboxService->IVirtualBox_openRemoteSession_V3($url, $vbox, $session, $uuid, "vrdp", ""); + my $progress = xCAT::vboxService->IVirtualBox_openRemoteSession_V3($url, $vbox, $session, $uuid, $v3session, ""); + + if (!$progress) { + addError("$node: Can not open remote session"); + } else { # existing $progress + xCAT::vboxService->IProgress_waitForCompletion_V3($url, $progress, -1); + + if (xCAT::vboxService->IProgress_getCompleted_V3($url, $progress)) { + addMessage("$node: $args->[0]"); + } else { # not successfully completed + addError("$node: Power on failed"); + } + + } # /existing $progress + + return; + } # /powerOn_V3 + + sub powerOff #********************************************************* + { + my ($url, $vbox, $session, $machine, $uuid, $node, $args) = + (shift, shift, shift, shift, shift, shift, shift); + + # Lock session with machine + my $vmsessionstate = xCAT::vboxService->IMachine_getSessionState($url, $machine); + my $vmsessiontype = xCAT::vboxService->IMachine_getSessionType($url, $machine); + + if ($vmsessionstate eq "Locked") { + my $locktype="Shared"; + xCAT::vboxService->IMachine_lockMachine($url,$machine,$session,$locktype); + } elsif ($vmsessionstate eq "Unlocked") { + my $locktype="Write"; + xCAT::vboxService->IMachine_lockMachine($url,$machine,$session,$locktype); + } else { # !$vmsessionstate + addError("$node: No direct session to machine"); + } + + # just test: check sessiontype - it turns out, that this needs a lock from traces + #my $teste = xCAT::vboxService->ISession_getType($url, $session); + #addError("$node: sessiontype =$teste"); + # The session is now locked with the machine, now its direct session or console can be optained and manipulated - # Now get the console for the mutable machine - my $console = xCAT::vboxService->ISession_getConsole($url, $session); - if (!$console) - { - addError("$node: No console for mutable machine"); - } - else # existing $console - { - - if ($args->[0] =~ m/^reset|^boot/) - { - xCAT::vboxService->IConsole_reset($url, $console); - xCAT::vboxService->IManagedObjectRef_release($url, $console); - addMessage("$node: on reset"); - - xCAT::vboxService->IManagedObjectRef_release($url, $console); - return; - } - else - { - xCAT::vboxService->IConsole_powerButton($url, $console); - unless (xCAT::vboxService->IConsole_getPowerButtonHandled( - $url, $console) eq "true") - { + # Now get the console for the mutable machine + my $console = xCAT::vboxService->ISession_getConsole($url, $session); + if (!$console) { + addError("$node: No console for mutable machine"); + } else { # existing $console + if ($args->[0] =~ m/^reset|^boot/) { + xCAT::vboxService->IConsole_reset($url, $console); + xCAT::vboxService->IManagedObjectRef_release($url, $console); + addMessage("$node: on reset"); + #xCAT::vboxService->IManagedObjectRef_release($url, $console); + return; + } else { + xCAT::vboxService->IConsole_powerButton($url, $console); + unless (xCAT::vboxService->IConsole_getPowerButtonHandled($url, $console) eq "true") { # In case of no reaction: force to power down machine xCAT::vboxService->IConsole_powerDown($url, $console); - } - addMessage("$node: off"); - } - - xCAT::vboxService->IManagedObjectRef_release($url, $console); - - } # /existing $console - - return; - - } # /powerOff - - - } # /powerCtrl - - - sub getSession ############################################################ - { - my $sess; - my ($url, $vbox, $node, $vmname) = (shift, shift, shift, shift); - - eval { - $sess = xCAT::vboxService->IWebsessionManager_getSessionObject($url, $vbox); - }; - - return $sess if ($sess and not $@); - - addError("$node: No session for $vmname on web service @ $url."); - return undef; - } # /getSession - - - sub getMachine ############################################################ - { - my $machine; - my ($url, $vbox, $vmname, $node) = (shift, shift, shift, shift); - - eval { - $machine = xCAT::vboxService->IVirtualBox_findMachine($url, $vbox, $vmname); - }; - - return $machine if ($machine and not $@); - - addError("$node: VM $vmname not known by the web service @ $url."); - return undef; - } # /getMachine - - - sub getWebService ######################################################### - { - my $ws; - my ($url, $user, $passwd, $node) = (shift, shift, shift, shift); - - eval { - $ws = xCAT::vboxService->IWebsessionManager_logon($url, $user, $passwd); - }; - - return $ws if ($ws and not $@); - - addError("$node: No connection to the web service @ $url."); - return undef; - } # /getWebService - - - sub getInfo ############################################################### - { - my $node = shift; - - # Open tables first, return in case of a critical error = 2 - my $hostsTab = openTable('hosts'); - return (2, undef, undef, undef, undef) if (!$hostsTab); - - my $vmTab = openTable('vm'); - return (2, undef, undef, undef, undef) if (!$vmTab); - - my $websrvTab = openTable('websrv'); - return (2, undef, undef, undef, undef) if (!$websrvTab); - - # Load attributes, return in case of missing information error = 1 - my $values; + } addMessage("$node: off"); + } + + xCAT::vboxService->IManagedObjectRef_release($url, $console); + + } # /existing $console + + return; + + } # /powerOff - my @attributes = ('host','vncport','comments'); - $values = loadValues($vmTab, $node, \@attributes); - return (1, undef, undef, undef, undef) if (!defined($values)); - - my $hostname = $values->{host}; - my $vncport = $values->{vncport}; - my $comments = $values->{comments}; + sub powerOff_V3 #********************************************************* + { + my ($url, $vbox, $session, $machine, $uuid, $node, $args) = + (shift, shift, shift, shift, shift, shift, shift); + + # Lock session with machine + my $vmsessionstate = xCAT::vboxService->IMachine_getSessionState_V3($url, $machine); + + if ($vmsessionstate eq "Open") { + xCAT::vboxService->IVirtualBox_openExistingSession_V3($url, $vbox, $session, $uuid); + } elsif ($vmsessionstate eq "Closed") { + xCAT::vboxService->IVirtualBox_openSession_V3($url, $vbox, $session, $uuid); + } else { + addError("$node: No direct session to machine"); + } + + # Now get the console for the mutable machine + my $console = xCAT::vboxService->ISession_getConsole_V3($url, $session); + if (!$console) { + addError("$node: No console for mutable machine"); + } else { # existing $console + if ($args->[0] =~ m/^reset|^boot/) { + xCAT::vboxService->IConsole_reset_V3($url, $console); + xCAT::vboxService->IManagedObjectRef_release_V3($url, $console); + addMessage("$node: on reset"); + #xCAT::vboxService->IManagedObjectRef_release_V3($url, $console); + return; + } else { + xCAT::vboxService->IConsole_powerButton_V3($url, $console); + unless (xCAT::vboxService->IConsole_getPowerButtonHandled_V3($url, $console) eq "true") { + # In case of no reaction: force to power down machine + xCAT::vboxService->IConsole_powerDown_V3($url, $console); + } addMessage("$node: off"); + } + + xCAT::vboxService->IManagedObjectRef_release_V3($url, $console); + + } # /existing $console + + return; + } # /powerOff_V3 + + } # /powerCtrl + + + sub getSession ############################################################ + { + my $sess; + my ($api, $url, $vbox, $node, $vmname) = (shift, shift, shift, shift, shift); + + my $cmd = "IWebsessionManager_getSessionObject"; + if($api eq "3") {$cmd=$cmd . "_V3";} + + eval { + $sess = xCAT::vboxService->$cmd($url, $vbox); + }; + + return $sess if ($sess and not $@); + + addError("$node: No session for $vmname on web service @ $url."); + return undef; + } # /getSession + + + sub getMachine ############################################################ + { + my $machine; + my ($api, $url, $vbox, $vmname, $node) = (shift, shift, shift, shift, shift); + + my $cmd = "IVirtualBox_findMachine"; + if($api eq "3") {$cmd=$cmd . "_V3";} + + eval { + $machine = xCAT::vboxService->$cmd($url, $vbox, $vmname); + }; + return $machine if ($machine and not $@); + + addError("$node: VM $vmname not known by the web service @ $url."); + return undef; + } # /getMachine + + + sub getWebService ######################################################### + { + my $ws; + my ($url, $user, $passwd, $node) = (shift, shift, shift, shift); + + my $cmd = "IWebsessionManager_logon"; + eval { + $ws = xCAT::vboxService->$cmd($url, $user, $passwd); + }; + + return $ws if ($ws and not $@); + + addError("$node: No connection to the web service @ $url."); + return undef; + } # /getWebService + + + sub getInfo ############################################################### + { + my $node = shift; + + # Open tables first, return in case of a critical error = 2 + my $hostsTab = openTable('hosts'); + return (2, undef, undef, undef, undef) if (!$hostsTab); + + my $vmTab = openTable('vm'); + return (2, undef, undef, undef, undef) if (!$vmTab); + + my $websrvTab = openTable('websrv'); + return (2, undef, undef, undef, undef) if (!$websrvTab); + + # Load attributes, return in case of missing information error = 1 + my $values; + + my @attributes = ('host','vncport','comments'); + $values = loadValues($vmTab, $node, \@attributes); + return (1, undef, undef, undef, undef) if (!defined($values)); + + my $hostname = $values->{host}; + my $vncport = $values->{vncport}; + my $comments = $values->{comments}; my $vmname = undef; - if ($comments =~ m/vmname:(.+)!/) { - $vmname = $1; + if ($comments =~ m/vmname:(.+)!/) { + $vmname = $1; } else { - $vmname = $node; + $vmname = $node; } - - @attributes = ('port','username', 'password'); - $values = loadValues($websrvTab, $hostname, \@attributes); - return (1, undef, undef, undef, undef) if (!defined($values)); - - my $port = $values->{port}; - my $username = $values->{username}; - my $password = $values->{password}; - - @attributes = ('ip'); - $values = loadValues($hostsTab, $hostname, \@attributes); - return (1, undef, undef, undef, undef) if (!defined($values)); - - my $ipaddr = $values->{ip}; - my $url = "http://$ipaddr:$port/"; - - return (0, $url, $username, $password, $vmname, $vncport); - - - sub loadValues #******************************************************* - { - my ($table, $node, $attributes) = (shift, shift, shift); - my ($values) = $table->getAttribs({'node'=>$node}, @$attributes); - $table->close; - - addError("$node: Missing information: @$attributes") - if (!defined($values)); - - return $values; - - } # /loadValues - - - sub openTable #******************************************************** - { - my $tabname = shift; - my $table = xCAT::Table->new($tabname); - - # try to create vbox tables if they don't exist yet - if (!$table and $tabname =~ m/websrv/) - { - $table = xCAT::Table->new( $tabname, -create=>1, -autocommit=>1 ); - $table->close; - addMessage("[xCAT] Info: The table $tabname has been created."); - $table = xCAT::Table->new($tabname); - } - - addError("[xCAT] Can not open table: $tabname. Command aborted.") - if (!$table); - - return $table; - - } # /loadValues - - } # /getInfo + + @attributes = ('port','username', 'password'); + $values = loadValues($websrvTab, $hostname, \@attributes); + return (1, undef, undef, undef, undef) if (!defined($values)); + + my $port = $values->{port}; + my $username = $values->{username}; + my $password = $values->{password}; + + @attributes = ('ip'); + $values = loadValues($hostsTab, $hostname, \@attributes); + return (1, undef, undef, undef, undef) if (!defined($values)); + + my $ipaddr = $values->{ip}; + my $url = "http://$ipaddr:$port/"; + + return (0, $url, $username, $password, $vmname, $vncport); + + + sub loadValues #******************************************************* + { + my ($table, $node, $attributes) = (shift, shift, shift); + my ($values) = $table->getAttribs({'node'=>$node}, @$attributes); + $table->close; + + addError("$node: Missing information: @$attributes") + if (!defined($values)); + + return $values; + + } # /loadValues + + + sub openTable #******************************************************** + { + my $tabname = shift; + my $table = xCAT::Table->new($tabname); + + # try to create vbox tables if they don't exist yet + if (!$table and $tabname =~ m/websrv/) + { + $table = xCAT::Table->new( $tabname, -create=>1, -autocommit=>1 ); + $table->close; + addMessage("[xCAT] Info: The table $tabname has been created."); + $table = xCAT::Table->new($tabname); + } + + addError("[xCAT] Can not open table: $tabname. Command aborted.") + if (!$table); + + return $table; + + } # /openTable + + } # /getInfo +} + +# see Lite.pm for other serializer code, e.g. as_string +sub SOAP::Serializer::as_LockType +{ + my ($self, $value, $name, $type, $attr) = @_; + die "String value expected instead of @{[ref $value]} reference\n" + if ref $value; + return [ + $name, + {'xsi:type' => 'vbox:LockType', %$attr}, + SOAP::Utils::encode_data($value) + ]; } 1; diff --git a/xCAT-server/lib/xcat/plugins/vsmppxe.pm b/xCAT-server/lib/xcat/plugins/vsmppxe.pm index 89e7b1485..6e310fa7b 100644 --- a/xCAT-server/lib/xcat/plugins/vsmppxe.pm +++ b/xCAT-server/lib/xcat/plugins/vsmppxe.pm @@ -11,9 +11,6 @@ use Getopt::Long; use xCAT::MsgUtils; use xCAT::ServiceNodeUtils; use xCAT::TableUtils; -my $addkcmdlinehandled; -my $request; -my $callback; my $dhcpconf = "/etc/dhcpd.conf"; my $tftpdir = "/tftpboot/vsmp"; #my $dhcpver = 3; @@ -75,7 +72,7 @@ sub setstate { my %chainhash = %{shift()}; my %machash = %{shift()}; my $kern = $bphash{$node}->[0]; #$bptab->getNodeAttribs($node,['kernel','initrd','kcmdline']); - if (not $addkcmdlinehandled->{$node} and $kern->{addkcmdline}) { #Implement the kcmdline append here for + if (not $::VSMPPXE_addkcmdlinehandled->{$node} and $kern->{addkcmdline}) { #Implement the kcmdline append here for #most generic, least code duplication $kern->{kcmdline} .= " ".$kern->{addkcmdline}; } @@ -84,7 +81,7 @@ sub setstate { unless ($ipfn) { my @myself = xCAT::NetworkUtils->determinehostname(); my $myname = $myself[(scalar @myself)-1]; - $callback->( + $::VSMPPXE_callback->( { error => [ "$myname: Unable to determine or reasonably guess the image server for $node" @@ -189,11 +186,11 @@ sub pass_along { $errored=1; } if ($_->{_addkcmdlinehandled}) { - $addkcmdlinehandled->{$_->{name}->[0]}=1; + $::VSMPPXE_addkcmdlinehandled->{$_->{name}->[0]}=1; return; #Don't send back to client this internal hint } } - $callback->($resp); + $::VSMPPXE_callback->($resp); } @@ -260,7 +257,7 @@ sub preprocess_request { my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $t_entry = $entries[0]; - if ( defined($t_entry) and ($t_entry == 0 or $t_entry =~ /no/i)) { + if ( defined($t_entry) and ($t_entry eq "0" or $t_entry eq "no" or $t_entry eq "NO")) { # check for computenodes and servicenodes from the noderange, if so error out my @SN; my @CN; @@ -288,29 +285,30 @@ sub preprocess_request { } sub process_request { - $request = shift; - $callback = shift; + $::VSMPPXE_request = shift; + $::VSMPPXE_callback = shift; my $sub_req = shift; + undef $::VSMPPXE_addkcmdlinehandled; my @args; my @nodes; my @rnodes; - if (ref($request->{node})) { - @rnodes = @{$request->{node}}; + if (ref($::VSMPPXE_request->{node})) { + @rnodes = @{$::VSMPPXE_request->{node}}; } else { - if ($request->{node}) { - @rnodes = ($request->{node}); + if ($::VSMPPXE_request->{node}) { + @rnodes = ($::VSMPPXE_request->{node}); } } unless (@rnodes) { - if ($usage{$request->{command}->[0]}) { - $callback->({data=>$usage{$request->{command}->[0]}}); + if ($usage{$::VSMPPXE_request->{command}->[0]}) { + $::VSMPPXE_callback->({data=>$usage{$::VSMPPXE_request->{command}->[0]}}); } return; } #if not shared, then help sync up - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::VSMPPXE_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); foreach (@rnodes) { if (xCAT::NetworkUtils->nodeonmynet($_)) { @@ -329,17 +327,17 @@ sub process_request { return; } - if (ref($request->{arg})) { - @args=@{$request->{arg}}; + if (ref($::VSMPPXE_request->{arg})) { + @args=@{$::VSMPPXE_request->{arg}}; } else { - @args=($request->{arg}); + @args=($::VSMPPXE_request->{arg}); } #now run the begin part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::VSMPPXE_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runbeginpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -352,7 +350,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running begin prescripts\n"; - $callback->($rsp); + $::VSMPPXE_callback->($rsp); return; } } @@ -375,7 +373,7 @@ sub process_request { if (! -r "$tftpdir/pxelinux.0") { unless (-r "/usr/lib/syslinux/pxelinux.0" or -r "/usr/share/syslinux/pxelinux.0") { - $callback->({error=>["Unable to find pxelinux.0 "],errorcode=>[1]}); + $::VSMPPXE_callback->({error=>["Unable to find pxelinux.0 "],errorcode=>[1]}); return; } if (-r "/usr/lib/syslinux/pxelinux.0") { @@ -386,14 +384,14 @@ sub process_request { chmod(0644,"$tftpdir/pxelinux.0"); } unless ( -r "$tftpdir/pxelinux.0" ) { - $callback->({errror=>["Unable to find pxelinux.0 from syslinux"],errorcode=>[1]}); + $::VSMPPXE_callback->({errror=>["Unable to find pxelinux.0 from syslinux"],errorcode=>[1]}); return; } $errored=0; my $inittime=0; - if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (exists($::VSMPPXE_request->{inittime})) { $inittime= $::VSMPPXE_request->{inittime}->[0];} if (!$inittime) { $inittime=0;} unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $sub_req->({command=>['setdestiny'], @@ -414,19 +412,19 @@ sub process_request { $response{node}->[0]->{name}->[0]=$_; if ($args[0] eq 'stat') { $response{node}->[0]->{data}->[0]= getstate($_); - $callback->(\%response); + $::VSMPPXE_callback->(\%response); } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate ($rc,$errstr) = setstate($_,\%bphash,\%chainhash,\%machash); if ($rc) { $response{node}->[0]->{errorcode}->[0]= $rc; $response{node}->[0]->{errorc}->[0]= $errstr; - $callback->(\%response); + $::VSMPPXE_callback->(\%response); } } } my $inittime=0; - if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (exists($::VSMPPXE_request->{inittime})) { $inittime= $::VSMPPXE_request->{inittime}->[0];} if (!$inittime) { $inittime=0;} #dhcp stuff -- inittime is set when xcatd on sn is started @@ -443,12 +441,12 @@ sub process_request { #} if ($do_dhcpsetup) { - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::VSMPPXE_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command $sub_req->({command=>['makedhcp'],arg=>['-l'], - node=>\@nodes},$callback); + node=>\@nodes},$::VSMPPXE_callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@nodes},$callback); + node=>\@nodes},$::VSMPPXE_callback); } } @@ -456,7 +454,7 @@ sub process_request { #now run the end part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::VSMPPXE_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runendpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -469,7 +467,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running end prescripts\n"; - $callback->($rsp); + $::VSMPPXE_callback->($rsp); return; } } diff --git a/xCAT-server/lib/xcat/plugins/windows.pm b/xCAT-server/lib/xcat/plugins/windows.pm index 7592b9854..d76f863e6 100644 --- a/xCAT-server/lib/xcat/plugins/windows.pm +++ b/xCAT-server/lib/xcat/plugins/windows.pm @@ -412,7 +412,7 @@ sub mkinstall $custmplpath = "$installroot/custom/install/hyperv"; $tmplpath = "$::XCATROOT/share/xcat/install/hyperv"; } - my $tmplfile=xCAT::SvrUtils::get_tmpl_file_name($custmplpath, $profile, $os, $arch); + $tmplfile=xCAT::SvrUtils::get_tmpl_file_name($custmplpath, $profile, $os, $arch); if (! $tmplfile) { $tmplfile=xCAT::SvrUtils::get_tmpl_file_name($tmplpath, $profile, $os, $arch); } } @@ -736,6 +736,12 @@ sub copycd $darch = "x86_64"; } elsif (/BuildBranch=win7_rtm/){ $distname = "win7"; + } elsif (/BuildBranch=winblue_rtm/){ + if (-r $mntpath . "/sources/background_svr.bmp") { + if (! -r $mntpath . "/sources/EI.CFG") { + $distname = "win2012r2"; + } + } } elsif (/BuildBranch=win8_rtm/){ if (-r $mntpath . "/sources/background_cli.bmp") { $distname = "win8"; diff --git a/xCAT-server/lib/xcat/plugins/xcat2nim.pm b/xCAT-server/lib/xcat/plugins/xcat2nim.pm index f1ea2b4cc..38c72cbc7 100644 --- a/xCAT-server/lib/xcat/plugins/xcat2nim.pm +++ b/xCAT-server/lib/xcat/plugins/xcat2nim.pm @@ -199,7 +199,7 @@ sub prexcat2nim my @nodelist=(); # pass back list of nodes - if applicable my @servicenodes=(); # pass back list of service nodes - if applicable - if (defined(@{$::args})) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } else { &xcat2nim_usage($callback); @@ -359,7 +359,7 @@ sub processArgs my $gotattrs = 0; - if (defined(@{$::args})) { + if ( defined ($::args) && @{$::args} ) { @ARGV = @{$::args}; } else { return 3; diff --git a/xCAT-server/lib/xcat/plugins/xdsh.pm b/xCAT-server/lib/xcat/plugins/xdsh.pm index 06286de6b..e08d985a7 100644 --- a/xCAT-server/lib/xcat/plugins/xdsh.pm +++ b/xCAT-server/lib/xcat/plugins/xdsh.pm @@ -19,6 +19,7 @@ use POSIX; require xCAT::Table; require xCAT::Utils; +require xCAT::Zone; require xCAT::TableUtils; require xCAT::ServiceNodeUtils; require xCAT::MsgUtils; @@ -111,8 +112,9 @@ sub preprocess_request $req = &parse_xdcp_cmd($req); } # if xdsh need to make sure request has full path to input files + # also process -K flag and use of zones if ($command eq "xdsh") { - $req = &parse_xdsh_cmd($req); + $req = &parse_xdsh_cmd($req,$cb,$sub_req); } # there are nodes in the xdsh command, not xdsh to an image @@ -421,7 +423,10 @@ sub parse_xdcp_cmd sub parse_xdsh_cmd { my $req=shift; + my $cb=shift; + my $sub_req=shift; my $args=$req->{arg}; # argument + my $nodes = $req->{node}; my $currpath=$req->{cwd}->[0]; # current path when command was executed my $orgargarraySize = @{$args}; # get the size of the arg array @ARGV = @{$args}; # get arguments @@ -498,6 +503,45 @@ sub parse_xdsh_cmd } # end -e option + + # if -k options and there are zones and service nodes, we cannot allow + # servicenodes and compute nodes in the noderange. The /etc/xcat/sshkeys directory must be sync'd + # to the service nodes first. So they must run xdsh -K to the service nodes and then to the compute + # nodes. + + if (defined($options{'ssh-setup'})) { + if (xCAT::Zone->usingzones) { + # check to see if service nodes and compute nodes in node range + my @SN; + my @CN; + xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN); + if ((@SN > 0) && (@CN >0 )) { # there are both SN and CN + my $rsp; + $rsp->{data}->[0] = + "xdsh -K was run with a noderange containing both service nodes and compute nodes. This is not valid if using zones. You must run xdsh -K to the service nodes first to setup the service node to be able to run xdsh -K to the compute nodes. \n"; + xCAT::MsgUtils->message("E", $rsp, $cb); + exit 1; + } + # if servicenodes for the node range this will force the update of + # the servicenode with /etc/xcat/sshkeys dir first + # if servicenodes and xdsh -K and using zones and we are on the Management Node + # then we need to sync + # /etc/xcat/sshkeys to the service nodes + # get list of all servicenodes + if (xCAT::Utils->isMN()) { # on the MN + my @snlist; + foreach my $sn (xCAT::ServiceNodeUtils->getSNList()) { + if (xCAT::NetworkUtils->thishostisnot($sn)) { # if it is not me, the MN + push @snlist, $sn; + } + } + if (@snlist) { + &syncSNZoneKeys($req, $cb, $sub_req, \@snlist); + } + } + + } # not using zones + } # not -k flag return $req; } @@ -992,6 +1036,107 @@ sub process_nodes return $newSNreq; } +#------------------------------------------------------- + +=head3 syncSNZoneKeys + Build the xdcp command to send the zone keys to the service nodes + Return an array of servicenodes that do not have errors + Returns error code: + if = 0, good return continue to process the + nodes. + if = 1, global error need to quit + +=cut + +#------------------------------------------------------- +sub syncSNZoneKeys +{ + + my $req = shift; + my $callback = shift; + my $sub_req = shift; + my $sn = shift; + my @snodes = @$sn; + $::RUNCMD_RC = 0; + my $file="/tmp/xcatzonesynclist"; + # Run xdcp -F /tmp/xcatzonesynclist + # can leave it , never changes and is built each time + my $content= "\"/etc/xcat/sshkeys/ -> /etc/xcat/sshkeys/\""; + `echo $content > $file`; + + # xdcp rsync the file + + my @sn = (); + #build the array of all service nodes + foreach my $node (@snodes) + { + + # handle multiple servicenodes for one node + my @sn_list = split ',', $node; + foreach my $snode (@sn_list) { + push @sn, $snode; + } + } + + @::good_SN = @sn; # initialize all good + + # run the command to the servicenodes + # xdcp -o "--delete" -F + my $addreq; + $addreq->{'_xcatdest'} = $::mnname; + $addreq->{node} = \@sn; + $addreq->{noderange} = \@sn; + # check input request for --nodestatus + my $args=$req->{arg}; # argument + if (grep(/^--nodestatus$/, @$args)) { + push (@{$addreq->{arg}},"--nodestatus"); # return nodestatus + } + push (@{$addreq->{arg}},"-v"); + push (@{$addreq->{arg}},"-o"); + push (@{$addreq->{arg}},"--delete"); # will cleanup the directory if zones are removed + push (@{$addreq->{arg}},"-F"); + push (@{$addreq->{arg}},$file); + $addreq->{command}->[0] = "xdcp"; # input command is xdsh, but we need to run xdcp -F + $addreq->{cwd}->[0] = $req->{cwd}->[0]; + $addreq->{env} = $req->{env}; + &process_request($addreq, $callback, $sub_req); + + if ($::FAILED_NODES == 0) + { + @::good_SN = @sn; # all servicenodes were sucessful + } + else + { + @::bad_SN = @::DCP_NODES_FAILED; + # remove all failing nodes from the good list + my @tmpgoodnodes; + foreach my $gnode (@::good_SN) { + if (!grep(/$gnode/,@::bad_SN )) # if not a bad node + { + push @tmpgoodnodes, $gnode; + } + } + @::good_SN = @tmpgoodnodes; + } + + # report bad service nodes + if (@::bad_SN) + { + my $rsp = {}; + my $badnodes; + foreach my $badnode (@::bad_SN) + { + $badnodes .= $badnode; + $badnodes .= ", "; + } + chop $badnodes; + my $msg = + "\nThe following servicenodes: $badnodes have errors and cannot be updated\n Until the error is fixed, xdcp will not work to nodes serviced by these service nodes."; + $rsp->{data}->[0] = $msg; + xCAT::MsgUtils->message("D", $rsp, $callback); + } + return (0); +} #------------------------------------------------------- diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 776c2fb2e..38e85fdbe 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -11,9 +11,7 @@ use Getopt::Long; use xCAT::Utils; use xCAT::TableUtils; use xCAT::ServiceNodeUtils; -my $addkcmdlinehandled; -my $request; -my $callback; + my $dhcpconf = "/etc/dhcpd.conf"; #my $tftpdir = "/tftpboot"; my $globaltftpdir = xCAT::TableUtils->getTftpDir(); @@ -102,7 +100,7 @@ sub setstate { if (ref $linuximghashref) { %linuximghash = %{$linuximghashref}; } my $imgaddkcmdline=($linuximghash{'boottarget'})? undef:$linuximghash{'addkcmdline'}; my $kern = $bphash{$node}->[0]; #$bptab->getNodeAttribs($node,['kernel','initrd','kcmdline']); - unless ($addkcmdlinehandled->{$node}) { #Tag to let us know the plugin had a special syntax implemented for addkcmdline + unless ($::XNBA_addkcmdlinehandled->{$node}) { #Tag to let us know the plugin had a special syntax implemented for addkcmdline if ($kern->{addkcmdline} or ($imgaddkcmdline)) { #Implement the kcmdline append here for @@ -138,7 +136,7 @@ sub setstate { $kcmdlinehack =~ s/#TABLE:([^:#]+):([^:#]+):([^:#]+)#/$naval/; } else { my $msg = "Table key of $2 not yet supported by boottarget mini-template"; - $callback->({ + $::XNBA_callback->({ error => ["$msg"], errorcode => [1] }); @@ -279,11 +277,11 @@ sub pass_along { $errored=1; } if ($_->{_addkcmdlinehandled}) { - $addkcmdlinehandled->{$_->{name}->[0]}=1; + $::XNBA_addkcmdlinehandled->{$_->{name}->[0]}=1; return; #Don't send back to client this internal hint } } - $callback->($resp); + $::XNBA_callback->($resp); } @@ -348,7 +346,7 @@ sub preprocess_request { #they specify no sharedtftp in site table my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $t_entry = $entries[0]; - if ( defined($t_entry) and ($t_entry == 0 or $t_entry =~ /no/i)) { + if ( defined($t_entry) and ($t_entry eq "0" or $t_entry eq "no" or $t_entry eq "NO")) { # check for computenodes and servicenodes from the noderange, if so error out my @SN; my @CN; @@ -376,27 +374,28 @@ sub preprocess_request { } sub process_request { - $request = shift; - $callback = shift; + $::XNBA_request = shift; + $::XNBA_callback = shift; my $sub_req = shift; + undef $::XNBA_addkcmdlinehandled; # clear out any previous value my @args; my @nodes; my @rnodes; - if (ref($request->{node})) { - @rnodes = @{$request->{node}}; + if (ref($::XNBA_request->{node})) { + @rnodes = @{$::XNBA_request->{node}}; } else { - if ($request->{node}) { @rnodes = ($request->{node}); } + if ($::XNBA_request->{node}) { @rnodes = ($::XNBA_request->{node}); } } unless (@rnodes) { - if ($usage{$request->{command}->[0]}) { - $callback->({data=>$usage{$request->{command}->[0]}}); + if ($usage{$::XNBA_request->{command}->[0]}) { + $::XNBA_callback->({data=>$usage{$::XNBA_request->{command}->[0]}}); } return; } #if not shared, then help sync up - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::XNBA_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); foreach (@rnodes) { if (xCAT::NetworkUtils->nodeonmynet($_)) { @@ -415,16 +414,16 @@ sub process_request { return; } - if (ref($request->{arg})) { - @args=@{$request->{arg}}; + if (ref($::XNBA_request->{arg})) { + @args=@{$::XNBA_request->{arg}}; } else { - @args=($request->{arg}); + @args=($::XNBA_request->{arg}); } #now run the begin part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::XNBA_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runbeginpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -437,7 +436,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running begin prescripts.\n"; - $callback->($rsp); + $::XNBA_callback->($rsp); return; } } @@ -445,21 +444,21 @@ sub process_request { #back to normal business if (! -r "$globaltftpdir/xcat/pxelinux.0") { unless (-r $::XCATROOT."/share/xcat/netboot/syslinux/pxelinux.0") { - $callback->({error=>["Unable to find pxelinux.0 at ".$::XCATROOT."/share/xcat/netboot/syslinux/pxelinux.0"],errorcode=>[1]}); + $::XNBA_callback->({error=>["Unable to find pxelinux.0 at ".$::XCATROOT."/share/xcat/netboot/syslinux/pxelinux.0"],errorcode=>[1]}); return; } copy($::XCATROOT."/share/xcat/netboot/syslinux/pxelinux.0","$globaltftpdir/xcat/pxelinux.0"); chmod(0644,"$globaltftpdir/xcat/pxelinux.0"); } unless ( -r "$globaltftpdir/xcat/pxelinux.0" ) { - $callback->({error=>["Unable to find pxelinux.0 from syslinux"],errorcode=>[1]}); + $::XNBA_callback->({error=>["Unable to find pxelinux.0 from syslinux"],errorcode=>[1]}); return; } my $inittime=0; - if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (exists($::XNBA_request->{inittime})) { $inittime= $::XNBA_request->{inittime}->[0];} if (!$inittime) { $inittime=0;} $errored=0; unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { @@ -499,7 +498,7 @@ sub process_request { $response{node}->[0]->{name}->[0]=$_; if ($args[0] eq 'stat') { $response{node}->[0]->{data}->[0]= getstate($_,$tftpdir); - $callback->(\%response); + $::XNBA_callback->(\%response); } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate my $rc; my $errstr; @@ -514,7 +513,7 @@ sub process_request { #if ($rc) { # $response{node}->[0]->{errorcode}->[0]= $rc; # $response{node}->[0]->{errorc}->[0]= $errstr; - # $callback->(\%response); + # $::XNBA_callback->(\%response); #} if($args[0] eq 'offline') { unlink($tftpdir."/xcat/xnba/nodes/".$_); @@ -540,12 +539,12 @@ sub process_request { #} if ($do_dhcpsetup) { - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::XNBA_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command $sub_req->({command=>['makedhcp'],arg=>['-l'], - node=>\@nodes},$callback); + node=>\@nodes},$::XNBA_callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@nodes},$callback); + node=>\@nodes},$::XNBA_callback); } } } @@ -553,7 +552,7 @@ sub process_request { #now run the end part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::XNBA_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runendpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -566,7 +565,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running end prescripts.\n"; - $callback->($rsp); + $::XNBA_callback->($rsp); return; } } diff --git a/xCAT-server/lib/xcat/plugins/yaboot.pm b/xCAT-server/lib/xcat/plugins/yaboot.pm index b90c6df25..f76f29927 100644 --- a/xCAT-server/lib/xcat/plugins/yaboot.pm +++ b/xCAT-server/lib/xcat/plugins/yaboot.pm @@ -13,11 +13,8 @@ use Socket; use Getopt::Long; use xCAT::Table; -my $request; my %breaknetbootnodes; our %normalnodes; -my $callback; -my $sub_req; my $dhcpconf = "/etc/dhcpd.conf"; my $globaltftpdir = xCAT::TableUtils->getTftpDir(); #my $dhcpver = 3; @@ -104,7 +101,7 @@ sub setstate { if (xCAT::InstUtils->is_me($sn)) { my @myself = xCAT::NetworkUtils->determinehostname(); my $myname = $myself[(scalar @myself)-1]; - $::callback->( + $::YABOOT_callback->( { error => [ "$myname: Unable to determine the image server for $node on service node $sn" @@ -116,7 +113,7 @@ sub setstate { } } } else { - $::callback->( + $::YABOOT_callback->( { error => [ "$myname: Unable to determine the image server for $node" @@ -177,7 +174,7 @@ sub setstate { delete $normalnodes{$node}; #Signify to omit this from one makedhcp command #$sub_req->({command=>['makedhcp'], #batched elsewhere, this code is stale, hopefully # node=>[$node], - # arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback); + # arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$::YABOOT_callback); print $pcfg "bye\n"; close($pcfg); } elsif ($kern and $kern->{kernel}) { @@ -231,13 +228,13 @@ sub setstate { #to clear the filename field, so the logic is a little #opposite # $sub_req->({command=>['makedhcp'], #This is currently batched elswhere - # node=>[$node]},$callback); #It hopefully will perform correctly + # node=>[$node]},$::YABOOT_callback); #It hopefully will perform correctly if ($cref and $cref->{currstate} eq "boot") { $breaknetbootnodes{$node}=1; delete $normalnodes{$node}; #Signify to omit this from one makedhcp command #$sub_req->({command=>['makedhcp'], #batched elsewhere, this code is stale, hopefully # node=>[$node], - # arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback); + # arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$::YABOOT_callback); print $pcfg "bye\n"; close($pcfg); } elsif ($kern and $kern->{kernel}) { @@ -309,7 +306,7 @@ sub pass_along { # print Dumper($resp); - $callback->($resp); + $::YABOOT_callback->($resp); if ($resp and ($resp->{errorcode} and $resp->{errorcode}->[0]) or ($resp->{error} and $resp->{error}->[0])) { $errored=1; } @@ -379,7 +376,8 @@ sub preprocess_request { #if they specify no sharedtftp in site table my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $t_entry = $entries[0]; - if ( defined($t_entry) and ($t_entry == 0 or $t_entry =~ /no/i)) { + + if ( defined($t_entry) and ($t_entry eq "0" or $t_entry eq "no" or $t_entry eq "NO")) { # check for computenodes and servicenodes from the noderange, if so error out my @SN; my @CN; @@ -408,31 +406,30 @@ sub preprocess_request { sub process_request { - $request = shift; - $callback = shift; - $::callback=$callback; - $sub_req = shift; - my $command = $request->{command}->[0]; + $::YABOOT_request = shift; + $::YABOOT_callback = shift; + my $sub_req = shift; + my $command = $::YABOOT_request->{command}->[0]; %breaknetbootnodes=(); %normalnodes=(); my @args; my @nodes; my @rnodes; - if (ref($request->{node})) { - @rnodes = @{$request->{node}}; + if (ref($::YABOOT_request->{node})) { + @rnodes = @{$::YABOOT_request->{node}}; } else { - if ($request->{node}) { @rnodes = ($request->{node}); } + if ($::YABOOT_request->{node}) { @rnodes = ($::YABOOT_request->{node}); } } unless (@rnodes) { - if ($usage{$request->{command}->[0]}) { - $callback->({data=>$usage{$request->{command}->[0]}}); + if ($usage{$::YABOOT_request->{command}->[0]}) { + $::YABOOT_callback->({data=>$usage{$::YABOOT_request->{command}->[0]}}); } return; } #if not shared tftpdir, then filter, otherwise, set up everything - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); foreach (@rnodes) { if (xCAT::NetworkUtils->nodeonmynet($_)) { @@ -451,16 +448,16 @@ sub process_request { return; } - if (ref($request->{arg})) { - @args=@{$request->{arg}}; + if (ref($::YABOOT_request->{arg})) { + @args=@{$::YABOOT_request->{arg}}; } else { - @args=($request->{arg}); + @args=($::YABOOT_request->{arg}); } #now run the begin part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runbeginpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -473,14 +470,14 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running begin prescripts.\n"; - $callback->($rsp); + $::YABOOT_callback->($rsp); return; } } #back to normal business my $inittime=0; - if (exists($request->{inittime})) { $inittime= $request->{inittime}->[0];} + if (exists($::YABOOT_request->{inittime})) { $inittime= $::YABOOT_request->{inittime}->[0];} if (!$inittime) { $inittime=0;} $errored=0; unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { @@ -520,7 +517,7 @@ sub process_request { $response{node}->[0]->{name}->[0]=$_; if ($args[0] eq 'stat') { $response{node}->[0]->{data}->[0]= getstate($_,$tftpdir); - $callback->(\%response); + $::YABOOT_callback->(\%response); } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate my $ent = $typehash->{$_}->[0]; my $osimgname = $ent->{'provmethod'}; @@ -533,7 +530,7 @@ sub process_request { if ($rc) { $response{node}->[0]->{errorcode}->[0]= $rc; $response{node}->[0]->{errorc}->[0]= $errstr; - $callback->(\%response); + $::YABOOT_callback->(\%response); } } }# end of foreach node @@ -570,7 +567,16 @@ sub process_request { $osn = $2; $osm = 0; } - + + #Redhat recommend to use grub2 instead of yaboot for rhels7 provision + if ( $osv =~ /rh/ and int($osn) == 7 ){ + my $rsp; + push @{$rsp->{data}}, + "stop configuration because yaboot DOES NOT work for $os provision, please change noderes.netboot=grub2 instead.\n"; + xCAT::MsgUtils->message("E", $rsp, $::YABOOT_callback); + return; + } + if (($osv =~ /rh/ and int($osn) < 6) or ($osv =~ /sles/ and int($osn) < 11)) { # check if yaboot-xcat installed @@ -579,7 +585,7 @@ sub process_request { my $rsp; push @{$rsp->{data}}, "stop configuration because yaboot-xcat need to be installed for $os.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); + xCAT::MsgUtils->message("E", $rsp, $::YABOOT_callback); return; } } elsif (($osv =~ /rh/ and int($osn) >= 6) or @@ -590,7 +596,7 @@ sub process_request { my $rsp; push @{$rsp->{data}}, "stop configuration because rsync does not exist or is not executable.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); + xCAT::MsgUtils->message("E", $rsp, $::YABOOT_callback); return; } my $yabootpath = $tftpdir."/yb/".$os; @@ -612,7 +618,7 @@ sub process_request { my $rsp; push @{$rsp->{data}}, "stop configuration because Unable to find the os shipped yaboot file.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); + xCAT::MsgUtils->message("E", $rsp, $::YABOOT_callback); return; } @@ -623,7 +629,7 @@ sub process_request { my $rsp; push @{$rsp->{data}}, "stop configuration because $synccmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $callback); + xCAT::MsgUtils->message("E", $rsp, $::YABOOT_callback); return; } } @@ -665,42 +671,42 @@ sub process_request { if (($osv =~ /rh/ and int($osn) >= 6) or ($osv =~ /sles/ and int($osn) >= 11)) { my $fpath = "/yb/". $osentry."/yaboot"; - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command $sub_req->({command=>['makedhcp'], node=>\@{$osimagenodehash{$osimage}}, - arg=>['-l','-s','filename = \"'.$fpath.'\";']},$callback); + arg=>['-l','-s','filename = \"'.$fpath.'\";']},$::YABOOT_callback); } else { $sub_req->({command=>['makedhcp'], node=>\@{$osimagenodehash{$osimage}}, - arg=>['-s','filename = \"'.$fpath.'\";']},$callback); + arg=>['-s','filename = \"'.$fpath.'\";']},$::YABOOT_callback); } } else { - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command, only change local settings if already farmed + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command, only change local settings if already farmed $sub_req->({command=>['makedhcp'],arg=>['-l'], - node=>\@{$osimagenodehash{$osimage}}},$callback); + node=>\@{$osimagenodehash{$osimage}}},$::YABOOT_callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@{$osimagenodehash{$osimage}}},$callback); + node=>\@{$osimagenodehash{$osimage}}},$::YABOOT_callback); } } } } else { - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command, only change local settings if already farmed + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command, only change local settings if already farmed $sub_req->({command=>['makedhcp'],arg=>['-l'], - node=>\@normalnodeset},$callback); + node=>\@normalnodeset},$::YABOOT_callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@normalnodeset},$callback); + node=>\@normalnodeset},$::YABOOT_callback); } } - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command $sub_req->({command=>['makedhcp'], node=>\@breaknetboot, - arg=>['-l','-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback); + arg=>['-l','-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$::YABOOT_callback); } else { $sub_req->({command=>['makedhcp'], node=>\@breaknetboot, - arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$callback); + arg=>['-s','filename = \"xcat/nonexistant_file_to_intentionally_break_netboot_for_localboot_to_work\";']},$::YABOOT_callback); } } } @@ -708,7 +714,7 @@ sub process_request { #now run the end part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') $errored=0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::YABOOT_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children $sub_req->({command=>['runendpre'], node=>\@nodes, arg=>[$args[0], '-l']},\&pass_along); @@ -721,7 +727,7 @@ sub process_request { my $rsp; $rsp->{errorcode}->[0]=1; $rsp->{error}->[0]="Failed in running end prescripts\n"; - $callback->($rsp); + $::YABOOT_callback->($rsp); return; } } diff --git a/xCAT-server/lib/xcat/plugins/zone.pm b/xCAT-server/lib/xcat/plugins/zone.pm new file mode 100644 index 000000000..0ccfbffc2 --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/zone.pm @@ -0,0 +1,964 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +#------------------------------------------------------- + +=head1 + xCAT plugin package to handle mkzone,chzone,Input rmzone commands + + Supported command: + mkzone,chzone,rmzone - manage xcat cluster zones + +=cut + +#------------------------------------------------------- +package xCAT_plugin::zone; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; +} + +use strict; +require xCAT::Utils; +require xCAT::Zone; +require xCAT::MsgUtils; +require xCAT::Table; +use xCAT::NodeRange; +use xCAT::NodeRange qw/noderange abbreviate_noderange/; + +use Getopt::Long; + + +#------------------------------------------------------- + +=head3 handled_commands + +Return list of commands handled by this plugin + +=cut + +#------------------------------------------------------- + +sub handled_commands +{ + return {mkzone => "zone", + chzone => "zone", + rmzone => "zone", + }; +} + + + +#------------------------------------------------------- + +=head3 process_request + + Process the command, this only runs on the management node + +=cut + +#------------------------------------------------------- +sub process_request +{ + + my $request = shift; + my $callback = shift; + my $sub_req = shift; + $::CALLBACK = $callback; + my $command = $request->{command}->[0]; + my $rc=0; + # the directory which will contain the zone keys + my $keydir="/etc/xcat/sshkeys/"; + + # check if Management Node, if not error + unless (xCAT::Utils->isMN()) + { + my $rsp = {}; + $rsp->{error}->[0] = "The $command may only be run on the Management Node."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + return 1; + + } + # you may not run on AIX + if (xCAT::Utils->isAIX()) { + my $rsp = {}; + $rsp->{error}->[0] = "The $command may only be run on a Linux Cluster."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + return 1; + } + # test to see if any parms + if (scalar($request->{arg} == 0)) { + my $rsp = {}; + $rsp->{error}->[0] = + "No parameters input to the $command command, see man page for syntax."; + xCAT::MsgUtils->message("E", $rsp, $callback); + exit 1; + } + + my $args = $request->{arg}; + @ARGV = @{$args}; # get arguments + # Get the zonename if it is in the input + my @SaveARGV = @ARGV; + my $zonename; + my $arg= @SaveARGV[0]; + if (!($arg =~ /-h/) && (!($arg =~ /-v/))) { # if not -h -v,then it must be a zone name + $zonename = @SaveARGV[0]; # here is the zonename, if there is one + if ($zonename) { # take zonename off the argument list so it will parse correctly + my $tmp = shift(@SaveARGV); + @ARGV = @SaveARGV; + } + } + Getopt::Long::Configure("posix_default"); + Getopt::Long::Configure("no_gnu_compat"); + Getopt::Long::Configure("bundling"); + my %options = (); + + if ( + !GetOptions( + 'a|noderange=s' => \$options{'addnoderange'}, + 'r|noderange=s' => \$options{'rmnoderange'}, + 'defaultzone|defaultzone' => \$options{'defaultzone'}, + 'g|assigngrp' => \$options{'assigngroup'}, + 'f|force' => \$options{'force'}, + 'h|help' => \$options{'help'}, + 'k|sshkeypath=s' => \$options{'sshkeypath'}, + 'K|genkeys' => \$options{'gensshkeys'}, + 's|sshbetweennodes=s' => \$options{'sshbetweennodes'}, + 'v|version' => \$options{'version'}, + 'V|Verbose' => \$options{'verbose'}, + ) + ) + { + + &usage($callback,$command); + exit 1; + } + # if the ARGS still have data we have invalid input + if (@ARGV) { + my $args=join(',', @ARGV); + my $rsp = {}; + $rsp->{error}->[0] = + "The input to the command: $command contained invalid arguments: $args."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + exit 1; + } + + if ($options{'help'}) + { + &usage($callback,$command); + exit 0; + } + if ($options{'version'}) + { + my $version = xCAT::Utils->Version(); + my $rsp = {}; + $rsp->{data}->[0] = $version; + xCAT::MsgUtils->message("I", $rsp, $callback); + exit 0; + } + # test to see if the zonename was input + if (!$zonename) { + my $rsp = {}; + $rsp->{error}->[0] = + "zonename not specified, it is required for this command."; + xCAT::MsgUtils->message("E", $rsp, $callback); + exit 1; + } else { + $request->{zonename} = $zonename; + } + # if -s entered must be yes/1 or no/0 + if ($options{'sshbetweennodes'}) { + if ($options{'sshbetweennodes'}=~ /^yes$/i || $options{'sshbetweennodes'} eq "1") { + $options{'sshbetweennodes'}= "yes"; + } else { + if ($options{'sshbetweennodes'}=~ /^no$/i || $options{'sshbetweennodes'} eq "0") { + $options{'sshbetweennodes'}= "no"; + } else { + my $rsp = {}; + $rsp->{error}->[0] = + "The input on the -s flag $options{'sshbetweennodes'} is not valid."; + xCAT::MsgUtils->message("E", $rsp, $callback); + exit 1; + } + } + } + # cannot enter -K and -k + if (($options{'sshkeypath'}) && ($options{'gensshkeys'})) { + my $rsp = {}; + $rsp->{error}->[0] = + "The input of -k and -K is not valid on the command : $command."; + xCAT::MsgUtils->message("E", $rsp, $callback); + exit 1; + } + + # check for site.sshbetweennodes attribute, put out a warning it will not be used as long + # as zones are defined in the zone table. + my @entries = xCAT::TableUtils->get_site_attribute("sshbetweennodes"); + if ($entries[0]) { + my $rsp = {}; + $rsp->{info}->[0] = + "The site table sshbetweennodes attribute is set to $entries[0]. It is not used when zones are defined. To get rid of this warning, remove the site table sshbetweennodes attribute."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + # -a and -r flags cannot be used together + if (($options{'addnoderange'}) && ($options{'rmnoderange'})) { + my $rsp = {}; + $rsp->{error}->[0] = + "You may not use the -a flag to add nodes and the -r flag to remove nodes on one command."; + xCAT::MsgUtils->message("E", $rsp, $callback); + exit 1; + + } + # save input noderange to add nodes + if ($options{'addnoderange'}) { + + # check to see if Management Node is in the noderange, if so error + $request->{noderange}->[0] = $options{'addnoderange'}; + my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]); + my @mname = xCAT::Utils->noderangecontainsMn(@nodes); + if (@mname) + { # MN in the nodelist + my $nodes=join(',', @mname); + my $rsp = {}; + $rsp->{error}->[0] = + "You must not run $command and include the management node: $nodes."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + exit 1; + } + + + } + # save input noderange to remove nodes + if ($options{'rmnoderange'}) { + + # check to see if Management Node is in the noderange, if so error + $request->{noderange}->[0] = $options{'rmnoderange'}; + my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]); + my @mname = xCAT::Utils->noderangecontainsMn(@nodes); + if (@mname) + { # MN in the nodelist + my $nodes=join(',', @mname); + my $rsp = {}; + $rsp->{error}->[0] = + "You must not run $command and include the management node: $nodes."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + exit 1; + } + + + } + if ($options{'verbose'}) + { + $::VERBOSE = "yes"; + } + + if ($command eq "mkzone") + { + $rc=mkzone($request, $callback,\%options,$keydir); + } + if ($command eq "chzone") + { + $rc=chzone($request, $callback,\%options,$keydir); + } + if ($command eq "rmzone") + { + $rc=rmzone($request, $callback,\%options); + } + my $rsp = {}; + if ($rc ==0) { + $rsp->{info}->[0] = "The $command ran successfully."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } else { + $rsp->{error}->[0] = "The $command had errors."; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + return $rc; + +} + +#------------------------------------------------------- + +=head3 + + Parses and runs mkzone + Input + request + callback + Input arguments from the GetOpts + zone ssh key dir + +=cut + +#------------------------------------------------------- +sub mkzone +{ + my ($request, $callback,$options,$keydir) = @_; + my $rc=0; + # already checked but lets do it again, need a zonename, it is the only required parm + if (!($request->{zonename})) { + + my $rsp = {}; + $rsp->{error}->[0] = + "zonename not specified The zonename is required."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # test for -g, if no noderange this is an error + if (( ! defined($$options{'addnoderange'})) && ($$options{'assigngroup'})) { + my $rsp = {}; + $rsp->{error}->[0] = + " The -g flag requires a noderange ( -a)."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # test for -r, not valid + if ($$options{'rmnoderange'}) { + my $rsp = {}; + $rsp->{error}->[0] = + " The -r flag Is not valid for mkzone. Use chzone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # check to see if the input zone already exists + if (xCAT::Zone->iszonedefined($request->{zonename})) { + my $rsp = {}; + $rsp->{error}->[0] = + " zonename: $request->{zonename} already defined, use chzone or rmzone to change or remove it."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + # Create path to generated ssh keys + # keydir comes in set to /etc/xcat/sshkeys + $keydir .= $request->{zonename}; + $keydir .= "/.ssh"; + + + # add new zones to the zone table + $rc=addtozonetable($request, $callback,$options,$keydir); + if ($rc == 0) { # zone table setup is ok + # test for a noderange, if(-a) not supplied nothing to do + if (defined($$options{'addnoderange'})) { + $rc=addnodestozone($request, $callback,$options,$keydir); + } + if ($rc == 0) { # zone table setup is ok + # generate root ssh keys + $rc=gensshkeys($request, $callback,$options,$keydir); + if ($rc != 0) { + return 1; + } + } + } + + + return $rc; + +} +#------------------------------------------------------- + +=head3 + + Parses and runs chzone + Input + request + callback + Input arguments from the GetOpts + + +=cut + +#------------------------------------------------------- +sub chzone +{ + my ($request, $callback,$options,$keydir) = @_; + my $rc=0; + # Create default path to generated ssh keys + # keydir comes in set to /etc/xcat/sshkeys + $keydir .= $request->{zonename}; + $keydir .= "/.ssh"; + my $zonename=$request->{zonename}; + # already checked but lets do it again, need a zonename + if (!($request->{zonename})) { + + my $rsp = {}; + $rsp->{error}->[0] = + "zonename not specified The zonename is required."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # see if they asked to do anything + if ((!($$options{'sshkeypath'})) && (!($$options{'gensshkeys'})) && + (!( $$options{'addnoderange'})) && (!( $$options{'rmnoderange'})) && + (!( $$options{'defaultzone'})) && + (!($$options{'assigngroup'} )) && (!($$options{'sshbetweennodes'}))) { + my $rsp = {}; + $rsp->{info}->[0] = + "chzone was run but nothing to do."; + xCAT::MsgUtils->message("I", $rsp, $callback); + return 0; + } + # test for -g, if no noderange (-r or -a) this is an error + if ((( ! defined($$options{'addnoderange'}))&& ( ! defined($$options{'rmnoderange'}))) && ($$options{'assigngroup'})) { + my $rsp = {}; + $rsp->{error}->[0] = + " The -g flag requires a noderange using the -a or -r option."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + # if -r remove nodes from zone, check to see that they are a member of the zone + # if not a member of the zone, error out and do nothing + if ($$options{'rmnoderange'}){ + my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]); + + foreach my $node (@nodes) { + my $nodezonename=xCAT::Zone->getmyzonename($node); + if ($nodezonename ne $zonename) { + my $rsp = {}; + $rsp->{error}->[0] = + " $node does not belong to the zone:$zonename. Rerun the chzone -r command with only nodes in the noderange that are currently assigned to the zone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + } + } + # get the zone ssh key directory. We don't have a good zone without it. + my $sshrootkeydir = xCAT::Zone->getzonekeydir($zonename); + if ($sshrootkeydir == 1) { # error return + #if we have been requested to regenerated the ssh keys continue + if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) { + my $rsp = {}; + $rsp->{info}->[0] = + " sshkeydir attribute not defined for $zonename. The zone sshkeydir will be regenerated."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } else { # sshkeydir is missing and they did not request to regenerate, that is an error + my $rsp = {}; + $rsp->{error}->[0] = + " sshkeydir attribute not defined for $zonename. The zone sshkeydir must be regenerated. Rerun this command with -k or -K options"; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } else { # we got a sshkeydir from the database, use it + $keydir=$sshrootkeydir; + } + # do we regenerate keys (-k or -K) + if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) { + $rc=gensshkeys($request, $callback,$options,$keydir); + if ($rc != 0) { + return 1; + } + } + + # update the zone table + $rc=updatezonetable($request, $callback,$options,$keydir); + if ($rc == 0) { # zone table setup is ok + # update the nodelist table + if (defined($$options{'addnoderange'})) { + $rc=addnodestozone($request, $callback,$options,$keydir); + } else { # note -a and -r are not allowed on one chzone + if (defined($$options{'rmnoderange'})) { + $rc=rmnodesfromzone($request, $callback,$options,$keydir); + } + } + } + + + return $rc; +} +#------------------------------------------------------- + +=head3 + + Parses and runs rmzone + Input + request + callback + Input arguments from the GetOpts + + +=cut + +#------------------------------------------------------- +sub rmzone +{ + my ($request, $callback,$options) = @_; + + # already checked but lets do it again, need a zonename, it is the only required parm + if (!($request->{zonename})) { + + my $rsp = {}; + $rsp->{error}->[0] = + "zonename not specified The zonename is required."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # see if they input invalid flags + if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'}) || + ( $$options{'addnoderange'}) || ( $$options{'rmnoderange'}) || + ( $$options{'defaultzone'}) || + ($$options{'sshbetweennodes'})) { + + my $rsp = {}; + $rsp->{error}->[0] = + "The following flags are not valid input for the rmzone command: -k,-K,-a,-r,-f,-s "; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # check to see if the input zone already exists + # cannot remove it if it is not defined + my $zonename=$request->{zonename}; + if (!(xCAT::Zone->iszonedefined($zonename))) { + my $rsp = {}; + $rsp->{error}->[0] = + " zonename: $zonename is not defined. You cannot remove it."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # is this zone is the default zone you must force the delete + my $defaultzone =xCAT::Zone->getdefaultzone($callback); + if (($defaultzone eq $zonename) && (!($$options{'force'}))) { + my $rsp = {}; + $rsp->{error}->[0] = + " You are removing the default zone: $zonename. You must define another default zone before deleting or use the -f flag to force the removal."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + # get the zone ssh key directory + my $sshrootkeydir = xCAT::Zone->getzonekeydir($zonename); + if ($sshrootkeydir == 1) { # error return + my $rsp = {}; + $rsp->{info}->[0] = + " sshkeydir attribute not defined for $zonename. Cannot remove it."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } else { # remove the keys unless it is /root/.ssh + my $roothome = xCAT::Utils->getHomeDir("root"); + $roothome .="\/.ssh"; + if ($sshrootkeydir eq $roothome) { # will not delete /root/.ssh + my $rsp = {}; + $rsp->{info}->[0] = + " $zonename sshkeydir is $roothome. This will not be deleted."; + xCAT::MsgUtils->message("I", $rsp, $callback); + } else { # not roothome/.ssh + # check to see if id_rsa.pub is there. I don't want to remove the + # wrong directory + # if id_rsa.pub exists remove the files + # then remove the directory + if ( -e "$sshrootkeydir/id_rsa.pub") { + my $cmd= "rm -rf $sshrootkeydir"; + xCAT::Utils->runcmd($cmd,0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Command: $cmd failed"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + my ($zonedir,$ssh)= split(/\.ssh/, $sshrootkeydir); + $cmd= "rmdir $zonedir"; + xCAT::Utils->runcmd($cmd,0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{error}->[0] = "Command: $cmd failed"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } else { # no id_rsa.pub key will not remove the files + my $rsp = {}; + $rsp->{info}->[0] = "$sshrootkeydir did not contain an id_rsa.pub key, will not remove files"; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + } + + } + + # open zone table and remove this entry + my $tab = xCAT::Table->new("zone"); + if (!defined($tab)) { + my $rsp = {}; + $rsp->{error}->[0] = + " Failure opening the zone table."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + # remove the table entry + $tab->delEntries({zonename=>$zonename}); + + # remove zonename and possibly group name (-g flag) from any nodes defined in this zone + my $rc=rmnodesfromzone($request, $callback,$options,"ALL"); + + return $rc; + + + +} +#------------------------------------------------------------------------------- + +=head3 + usage + + puts out zone command usage message + + Arguments: + None + + Returns: + + Globals: + + + Error: + None + + +=cut + +#------------------------------------------------------------------------------- + +sub usage +{ + my ($callback, $command) = @_; + my $usagemsg1=""; + my $usagemsg2=""; + if ($command eq "mkzone") { + $usagemsg1 = " mkzone -h \n mkzone -v \n"; + $usagemsg2 = " mkzone [-V] [--defaultzone] [-k ] \n [-a ] [-g] [-f] [-s ]"; + } else { + if ($command eq "chzone") { + $usagemsg1 = " chzone -h \n chzone -v \n"; + $usagemsg2 = " chzone [-V] [--defaultzone] [-k ] \n [-K] [-a ] [-r ] [-g] [-s ]"; + } else { + if ($command eq "rmzone") { + $usagemsg1 = " rmzone -h \n rmzone -v \n"; + $usagemsg2 = " rmzone [-g]"; + } + } + } + my $usagemsg .= $usagemsg1 .= $usagemsg2 ; + if ($callback) + { + my $rsp = {}; + $rsp->{data}->[0] = $usagemsg; + xCAT::MsgUtils->message("I", $rsp, $callback); + } + else + { + xCAT::MsgUtils->message("I", $usagemsg); + } + return; +} +#------------------------------------------------------- + +=head3 + + generate the ssh keys and store them in /etc/xcat/sshkeys//.ssh + + +=cut + +#------------------------------------------------------- +sub gensshkeys +{ + my ($request, $callback,$options,$keydir) = @_; + my $rc=0; + # generate root ssh keys + # Did they input a path to existing RSA keys + my $rsakey; + my $zonename=$request->{zonename}; + if ($$options{'sshkeypath'}) { + # check to see if RSA keys exists + $rsakey= $$options{'sshkeypath'} .= "/id_rsa"; + if (!(-e $rsakey)){ # if it does not exist error out + my $rsp = {}; + $rsp->{error}->[0] = + "Input $rsakey does not exist. Cannot generate the ssh root keys for the zone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + + $rc =xCAT::Zone->genSSHRootKeys($callback,$keydir, $zonename,$rsakey); + if ($rc !=0) { + my $rsp = {}; + $rsp->{error}->[0] = + " Failure generating the ssh root keys for the zone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + return $rc; + +} +#------------------------------------------------------- + +=head3 + addtozonetable + Add the new zone to the zone table, check if already there and + error - use either chzone or -f to override default + + + +=cut + +#------------------------------------------------------- +sub addtozonetable +{ + my ($request, $callback,$options,$keydir) = @_; + my $rc=0; + my $zoneentry; + my $tab = xCAT::Table->new("zone"); + if ($tab) + { + # read a record from the zone table, if it is empty then add + # the xcatdefault entry + my @zones = $tab->getAllAttribs('zonename'); + if (!(@zones)) { # table empty + my %xcatdefaultzone; + $xcatdefaultzone{defaultzone} ="yes"; + $xcatdefaultzone{sshbetweennodes} ="yes"; + my $roothome = xCAT::Utils->getHomeDir("root"); + $roothome .="\/.ssh"; + $xcatdefaultzone{sshkeydir} =$roothome; + $tab->setAttribs({zonename => "xcatdefault"}, \%xcatdefaultzone); + } + + # now add the users zone + my %tb_cols; + $tb_cols{sshkeydir} = $keydir; # key directory + # set sshbetweennodes attribute from -s flag or default to yes + if ( $$options{'sshbetweennodes'}) { + $tb_cols{sshbetweennodes} = $$options{'sshbetweennodes'}; + } else { + $tb_cols{sshbetweennodes} = "yes"; + } + my $zonename=$request->{zonename}; + if ( $$options{'defaultzone'}) { # set the default + # check to see if a default already defined + my $curdefaultzone = xCAT::Zone->getdefaultzone($callback); + if (!(defined ($curdefaultzone))) { # no default defined + $tb_cols{defaultzone} ="yes"; + $tab->setAttribs({zonename => $zonename}, \%tb_cols); + $tab->commit(); + $tab->close(); + } else { # already a default + if ($$options{'force'}) { # force the default + $tb_cols{defaultzone} ="yes"; + $tab->setAttribs({zonename => $zonename}, \%tb_cols); + # now change the old default zone to not be the default + my %tb1_cols; + $tb1_cols{defaultzone} ="no"; + $tab->setAttribs({zonename => $curdefaultzone}, \%tb1_cols); + $tab->commit(); + $tab->close(); + } else { # no force this is an error + my $rsp = {}; + $rsp->{error}->[0] = + " Failure setting default zone. The defaultzone $curdefaultzone already exists. Use the -f flag if you want to override the current default zone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + } else { # not a default zone + $tb_cols{defaultzone} ="no"; + $tab->setAttribs({zonename => $zonename}, \%tb_cols); + $tab->commit(); + $tab->close(); + } + } else { + my $rsp = {}; + $rsp->{error}->[0] = + " Failure opening the zone table."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + + + return $rc; + +} +#------------------------------------------------------- + +=head3 + updatezonetable + change either the sshbetweennodes or defaultzone attribute + or generate new keys ( -k -K) + + +=cut + +#------------------------------------------------------- +sub updatezonetable +{ + my ($request, $callback,$options,$keydir) = @_; + my $zoneentry; + my $zonename=$request->{zonename}; + # check for changes + if (($$options{'sshbetweennodes'}) || ( $$options{'defaultzone'}) || + ($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) { + + my $tab = xCAT::Table->new("zone"); + if($tab) { + + # now add the users changes + my %tb_cols; + # generated keys ( -k or -K) + if (($$options{'sshkeypath'}) || ($$options{'gensshkeys'})) { + $tb_cols{sshkeydir} = $keydir; # key directory + } + # set sshbetweennodes attribute from -s flag + if ( $$options{'sshbetweennodes'}) { + $tb_cols{sshbetweennodes} = $$options{'sshbetweennodes'}; + } + # if --defaultzone + if ( $$options{'defaultzone'}) { # set the default + # check to see if a default already defined + my $curdefaultzone = xCAT::Zone->getdefaultzone($callback); + if (!(defined ($curdefaultzone))) { # no default defined + $tb_cols{defaultzone} ="yes"; + $tab->setAttribs({zonename => $zonename}, \%tb_cols); + $tab->commit(); + $tab->close(); + } else { # already a default + if ($$options{'force'}) { # force the default + $tb_cols{defaultzone} ="yes"; + $tab->setAttribs({zonename => $zonename}, \%tb_cols); + # now change the old default zone to not be the default + my %tb1_cols; + $tb1_cols{defaultzone} ="no"; + $tab->setAttribs({zonename => $curdefaultzone}, \%tb1_cols); + $tab->commit(); + $tab->close(); + } else { # no force this is an error + my $rsp = {}; + $rsp->{error}->[0] = + " Failure setting default zone. The defaultzone $curdefaultzone already exists. Use the -f flag if you want to override the current default zone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + } else { # not a default zone change, just commit the other changes + $tab->setAttribs({zonename => $zonename}, \%tb_cols); + $tab->commit(); + $tab->close(); + } + } else { + my $rsp = {}; + $rsp->{error}->[0] = + " Failure opening the zone table."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + + + return 0; + +} +#------------------------------------------------------- + +=head3 + addnodestozone + Add the new zonename attribute to any nodes in the noderange ( if a noderange specified) + Add zonename group to nodes in the noderange if -g flag. + + + +=cut + +#------------------------------------------------------- +sub addnodestozone +{ + my ($request, $callback,$options,$keydir) = @_; + my $rc=0; + my $zonename=$request->{zonename}; + # if -g add zonename group also + my @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]); + # check to see if noderange expanded + if (!(scalar @nodes)) { + my $rsp = {}; + $rsp->{error}->[0] = + " The noderange $request->{noderange}->[0] is not valid. The nodes are not defined."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + my $tab = xCAT::Table->new("nodelist"); + if ($tab) + { + # if -g then add the zonename to the group attribute on each node + if ($$options{'assigngroup'}){ + foreach my $node (@nodes) { + xCAT::TableUtils->updatenodegroups($node,$tab,$zonename); + } + } + # set the nodelist zonename attribute to the zonename for all nodes in the range + $tab-> setNodesAttribs(\@nodes, { zonename => $zonename }); + $tab->commit(); + $tab->close(); + } else { + my $rsp = {}; + $rsp->{error}->[0] = + " Failure opening the nodelist table."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + return $rc; + +} +#------------------------------------------------------- + +=head3 + rmnodesfromzone + removes the zonename from all nodes with their zonename the input zone or + the noderange supplied on the -r flag + if -g, removes zonename group from all nodes defined with their zonename the input zone. + Note if $ALL is input it removes all nodes from the zone, + otherwise $request->{noderange} points to the noderange + + +=cut + +#------------------------------------------------------- +sub rmnodesfromzone +{ + my ($request, $callback,$options,$ALL) = @_; + my $zonename=$request->{zonename}; + my $tab = xCAT::Table->new("nodelist"); + if ($tab) + { + # read all the nodes with zonename + my @nodes; + if ($ALL) { # do all nodes + @nodes = xCAT::Zone->getnodesinzone($callback,$zonename); + } else { # the nodes in the noderange ( -r ) + @nodes = xCAT::NodeRange::noderange($request->{noderange}->[0]); + # check to see if noderange expanded + if (!(scalar @nodes)) { + my $rsp = {}; + $rsp->{error}->[0] = + " The noderange $request->{noderange}->[0] is not valid. The nodes are not defined."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + } + # if -g then remove the zonename group attribute on each node + if ($$options{'assigngroup'}){ + foreach my $node (@nodes) { + xCAT::TableUtils->rmnodegroups($node,$tab,$zonename); + } + } + # set the nodelist zonename to nothing + my $nozonename=""; + $tab-> setNodesAttribs(\@nodes, { zonename => $nozonename }); + $tab->commit(); + $tab->close(); + } else { + my $rsp = {}; + $rsp->{error}->[0] = + " Failure opening the nodelist table."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } + return 0; + +} + + +1; diff --git a/xCAT-server/sbin/configmic b/xCAT-server/sbin/configmic index b6fcdddb2..5a3b62d49 100755 --- a/xCAT-server/sbin/configmic +++ b/xCAT-server/sbin/configmic @@ -71,6 +71,9 @@ my ($rc, $output) = runsyscmd ($cmd); if ($rc) { $cmd = "wget -N --waitretry=10 --random-wait -T 60 http://$master/$cfgpath/miccfg.$nodename -P $tmppath"; runsyscmd ($cmd, "Error: failed to download mic configuration file from $master\n", 3); +} else { + # use the correct short hotname in $nodename_short + $nodename=$nodename_short; } unless (-r "$tmppath/miccfg.$nodename") { diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index 327fac71d..cf004dd61 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -540,11 +540,16 @@ if ($::INITIALINSTALL || $::FORCE) elsif(-f "/etc/redhat-release") { $fwserv = "iptables"; + if( -f "/usr/sbin/firewalld" ) + { + $fwserv = "firewalld"; + } } else { #Ubuntu: FIXME } + if($fwserv) { my $cmd = "service $fwserv stop"; @@ -855,19 +860,21 @@ sub settunables { # tuning ARP on Linux # set for right now - my $cmd = "/bin/echo '1024' >/proc/sys/net/ipv4/neigh/default/gc_thresh1"; + + my $ECHO=xCAT::Utils->fullpathbin("echo"); + my $cmd = "$ECHO '1024' >/proc/sys/net/ipv4/neigh/default/gc_thresh1"; my $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) { xCAT::MsgUtils->message( 'E', "Could not run $cmd."); } - $cmd = "/bin/echo '4096' >/proc/sys/net/ipv4/neigh/default/gc_thresh2"; + $cmd = "$ECHO '4096' >/proc/sys/net/ipv4/neigh/default/gc_thresh2"; my $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) { xCAT::MsgUtils->message( 'E', "Could not run $cmd."); } - $cmd = "/bin/echo '8192' >/proc/sys/net/ipv4/neigh/default/gc_thresh3"; + $cmd = "$ECHO '8192' >/proc/sys/net/ipv4/neigh/default/gc_thresh3"; my $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) { @@ -1257,7 +1264,7 @@ sub initDB $chtabcmds .= "$::XCATROOT/sbin/chtab key=vsftp site.value=n;"; $chtabcmds .= "$::XCATROOT/sbin/chtab key=cleanupxcatpost site.value=no;"; $chtabcmds .= "$::XCATROOT/sbin/chtab key=dhcplease site.value=43200;"; - $chtabcmds .= "$::XCATROOT/sbin/chtab key=useflowcontrol site.value=yes;"; + #$chtabcmds .= "$::XCATROOT/sbin/chtab key=useflowcontrol site.value=yes;"; # need to fix 4031 if ($::osname eq 'AIX') { @@ -1853,10 +1860,11 @@ sub setupLinuxexports # restart nfs my $cmd; my $os = xCAT::Utils->osver(); + my $SERVICE = xCAT::Utils->fullpathbin("service"); if ($os =~ /sles/) { - $cmd = "/sbin/service nfsserver restart"; + $cmd = "$SERVICE nfsserver restart"; } else { - $cmd = "/sbin/service nfs restart"; + $cmd = "$SERVICE nfs restart"; } my $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) @@ -1868,10 +1876,11 @@ sub setupLinuxexports xCAT::MsgUtils->message('I', "NFS has been restarted."); } + my $CHKCONFIG=xCAT::Utils->fullpathbin("chkconfig"); if ($os =~ /sles/) { - $cmd = "/sbin/chkconfig nfsserver on"; + $cmd = "$CHKCONFIG nfsserver on"; } else { - $cmd = "/sbin/chkconfig nfs on"; + $cmd = "$CHKCONFIG nfs on"; } $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) @@ -1969,10 +1978,14 @@ sub setuphttp { #for sles/ubuntu $cmd = "/etc/init.d/apache2 stop; /etc/init.d/apache2 start"; } - else + elsif (-e "/etc/init.d/httpd") { $cmd = "/etc/init.d/httpd stop; /etc/init.d/httpd start"; } + else + { + $cmd = "service httpd stop; service httpd start"; + } my $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) @@ -1996,10 +2009,26 @@ sub setuphttp $cmd = "/sbin/chkconfig apache2 on"; } } +# elsif (-e "/sbin/chkconfig") +# { +# $cmd = "/sbin/chkconfig httpd on"; +# } +# elsif (-e "/usr/sbin/chkconfig") +# { +# $cmd = "/usr/sbin/chkconfig httpd on"; +# } +# else +# { +# $cmd = "chkconfig httpd on"; +# } else { - $cmd = "/sbin/chkconfig httpd on"; + my $CHKCONFIG = xCAT::Utils->fullpathbin("chkconfig"); + $cmd = "$CHKCONFIG httpd on"; } + + + $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) { diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 83f863fb9..b971854c6 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -323,35 +323,42 @@ sleep 0.05; #up to 50 ms outage possible my $conn; next unless $conn = $socket->accept; -my @clients; -if ($inet6support) { - @clients = gethostbyaddr($conn->peeraddr,AF_INET6); - unless (@clients) { @clients = gethostbyaddr($conn->peeraddr,AF_INET); } -} else { - @clients = gethostbyaddr($conn->peeraddr,AF_INET); -} + my $client_name; + my $client_aliases; + my @clients; + if ($inet6support) { + ($client_name,$client_aliases) = gethostbyaddr($conn->peeraddr,AF_INET6); + unless ($client_name) { ($client_name,$client_aliases) = gethostbyaddr($conn->peeraddr,AF_INET); } + } else { + ($client_name,$client_aliases) = gethostbyaddr($conn->peeraddr,AF_INET); + } + + $clients[0] = $client_name; + if ($client_aliases) { + push @clients, split(/\s+/,$client_aliases); + } my $validclient=0; my $node; my $domain; - my $nd = xCAT::NetworkUtils->getNodeDomains(\@clients); - my %nodedomains = %{$nd}; - foreach my $client (@clients) { - $domain = $nodedomains{$client}; + my @ndn = ($client); + my $nd = xCAT::NetworkUtils->getNodeDomains(\@ndn); + my %nodedomains = %{$nd}; + $domain = $nodedomains{$client}; + $client =~ s/\..*//; + if ($domain) { + $client =~ s/\.$domain//; + } else { $client =~ s/\..*//; - if ($domain) { - $client =~ s/\.$domain//; - } else { - $client =~ s/\..*//; - } - #ensure this is coming from a node IP at least - ($node) = noderange($client); - if ($node) { #Means the source isn't valid - $validclient=1; - last; - } + } + #ensure this is coming from a node IP at least + ($node) = noderange($client); + if ($node) { #Means the source isn't valid + $validclient=1; + last; + } } unless ($validclient) { @@ -1974,6 +1981,40 @@ sub service_connection { delete($req->{becomeuser}); #Remove it to keep it from view } + # If the request is to aquire a token for a specific account + if (defined $req->{gettoken}) { + # authencitate the username:password + $peername=becomeuser($req->{gettoken}->[0]->{username}->[0], + $req->{gettoken}->[0]->{password}->[0]); + my $resp; + if ($peername) { + # for a valid account, get a token + my ($tokenid, $exptime) = xCAT::xcatd->gettoken($req); + my ($sec,$min,$hour,$mday,$mon,$year) = localtime($exptime); + $year += 1900; + my $htime = "$year-$mon-$mday $hour:$min:$sec"; + $resp = {data=>[{token => [{id => $tokenid, expire => $htime}]}]}; + } else { + $resp={error=>["Authentication failure"],errorcode=>[1]}; + } + $resp->{serverdone}=[ undef ] ; + print $sock XMLout($resp,RootName => 'xcatresponse',NoAttr=>1); + return; + } + + # If user trying to use 'token' to authenticate + if (defined $req->{tokens}) { + # get the valid user name by the token id + $peername = xCAT::xcatd->verifytoken($req); + unless (defined $peername) { + my $resp={error=>["Authentication failure"],errorcode=>[1]}; + $resp->{serverdone}=[ undef ] ; + print $sock XMLout($resp,RootName => 'xcatresponse',NoAttr=>1); + return; + } + delete($req->{tokenid}); + } + #we have a full request.. #printf $request."\n"; $request=""; diff --git a/xCAT-server/share/xcat/cons/ipmi b/xCAT-server/share/xcat/cons/ipmi index ed0510b6c..2160556a0 100755 --- a/xCAT-server/share/xcat/cons/ipmi +++ b/xCAT-server/share/xcat/cons/ipmi @@ -98,10 +98,10 @@ my $ipmitool = "ipmitool"; if (-x "$XCATROOT/bin/ipmitool-xcat") { $ipmitool = "$XCATROOT/bin/ipmitool-xcat"; } -my @mcinfo=`$ipmitool -I lan -U $username -P $password -H $bmc mc info`;#| grep 'Manufacturer ID : 343' > /dev/null 2>&1"; +my @mcinfo=`$ipmitool -I lan -U $username -P '$password' -H $bmc mc info`;#| grep 'Manufacturer ID : 343' > /dev/null 2>&1"; $rc = $?; if ($rc) { #some shoddy vendors ignore the IPMI 2.0 requirement to support IPMI 1.5 formats for BMC capability determination, attempt IPMI 2.0 even without the ability to confirm IPMI 2.0 support. Though SOL was not baked in prior IPMI 2.0, this script supports pre-2.0 'ISOL' on older devices, hence why we are checking for 1.5/2.0 before proceeding normally - @mcinfo=`$ipmitool -I lanplus -U $username -P $password -H $bmc mc info`; + @mcinfo=`$ipmitool -I lanplus -U $username -P '$password' -H $bmc mc info`; $rc = $?; } while ($rc != 0) { @@ -109,10 +109,10 @@ while ($rc != 0) { print "Failure to reach IPMI device, retrying in $sleepint seconds (Hit Ctrl-E,c,o to skip)\n"; exec("sleep $sleepint"); #sleep $sleepint; - @mcinfo=`$ipmitool -I lan -U $username -P $password -H $bmc mc info`;#| grep 'Manufacturer ID : 343' > /dev/null 2>&1"; + @mcinfo=`$ipmitool -I lan -U $username -P '$password' -H $bmc mc info`;#| grep 'Manufacturer ID : 343' > /dev/null 2>&1"; $rc = $?; if ($rc) { #repeat workaround for shoddy vendors - @mcinfo=`$ipmitool -I lanplus -U $username -P $password -H $bmc mc info`; + @mcinfo=`$ipmitool -I lanplus -U $username -P '$password' -H $bmc mc info`; $rc = $?; } } @@ -130,9 +130,9 @@ if ($isintel) { $inteloption=" -o intelplus"; } if ($iface eq "lanplus") { - system "$ipmitool -I lanplus $inteloption -U $username -P $password -H $bmc $solcom deactivate"; #Stop any active session + system "$ipmitool -I lanplus $inteloption -U $username -P '$password' -H $bmc $solcom deactivate"; #Stop any active session } -exec "$ipmitool -I $iface $inteloption -U $username -P $password -H $bmc $solcom activate"; +exec "$ipmitool -I $iface $inteloption -U $username -P '$password' -H $bmc $solcom activate"; diff --git a/xCAT-server/share/xcat/install/rh/compute.rhel7.pkglist b/xCAT-server/share/xcat/install/rh/compute.rhel7.pkglist new file mode 100644 index 000000000..8ce3030c3 --- /dev/null +++ b/xCAT-server/share/xcat/install/rh/compute.rhel7.pkglist @@ -0,0 +1,9 @@ +#Please make sure there is a space between @ and group name +wget +ntp +nfs-utils +net-snmp +rsync +yp-tools +openssh-server +util-linux-ng diff --git a/xCAT-server/share/xcat/install/rh/compute.rhel7.tmpl b/xCAT-server/share/xcat/install/rh/compute.rhel7.tmpl new file mode 100644 index 000000000..b32f1f01d --- /dev/null +++ b/xCAT-server/share/xcat/install/rh/compute.rhel7.tmpl @@ -0,0 +1,154 @@ +# +#cmdline + +lang en_US +#KICKSTARTNET# + +# +# Where's the source? +# nfs --server hostname.of.server or IP --dir /path/to/RH/CD/image +# +#nfs --server #XCATVAR:INSTALL_NFS# --dir #XCATVAR:INSTALL_SRC_DIR# + +%include /tmp/repos + +#device ethernet e100 +keyboard "us" + +# +# Clear the MBR +# +zerombr + +# +# Wipe out the disk +# +clearpart --all --initlabel +#clearpart --linux +#key --skip + +# +# Customize to fit your needs +# + +#XCAT_PARTITION_START# +#No RAID +#/boot really significant for this sort of setup nowadays? +#part /boot --size 50 --fstype ext3 +%include /tmp/partitioning +#part swap --size 1024 +#part / --size 1 --grow --fstype ext4 +#XCAT_PARTITION_END# + +#RAID 0 /scr for performance +#part / --size 1024 --ondisk sda +#part swap --size 512 --ondisk sda +#part /var --size 1024 --ondisk sdb +#part swap --size 512 --ondisk sdb +#part raid.01 --size 1 --grow --ondisk sda +#part raid.02 --size 1 --grow --ondisk sdb +#raid /scr --level 0 --device md0 raid.01 raid.02 + +#Full RAID 1 Sample +#part raid.01 --size 50 --ondisk sda +#part raid.02 --size 50 --ondisk sdb +#raid /boot --level 1 --device md0 raid.01 raid.02 +# +#part raid.11 --size 1024 --ondisk sda +#part raid.12 --size 1024 --ondisk sdb +#raid / --level 1 --device md1 raid.11 raid.12 +# +#part raid.21 --size 1024 --ondisk sda +#part raid.22 --size 1024 --ondisk sdb +#raid /var --level 1 --device md2 raid.21 raid.22 +# +#part raid.31 --size 1024 --ondisk sda +#part raid.32 --size 1024 --ondisk sdb +#raid swap --level 1 --device md3 raid.31 raid.32 +# +#part raid.41 --size 1 --grow --ondisk sda +#part raid.42 --size 1 --grow --ondisk sdb +#raid /scr --level 1 --device md4 raid.41 raid.42 + +# +# bootloader config +# --append +# --useLilo +# --md5pass +# +bootloader + +# +# install or upgrade +# +install + +# +# text mode install (default is graphical) +# +text + +# +# firewall +# +firewall --disabled + +# +# Select a zone +# Add the --utc switch if your hardware clock is set to GMT +# +#timezone US/Hawaii +#timezone US/Pacific +#timezone US/Mountain +#timezone US/Central +#timezone US/Eastern +timezone --utc "#TABLE:site:key=timezone:value#" + +# +# Don't do X +# +skipx + + +# +# To generate an encrypted root password use: +# +# perl -e 'print crypt("blah","Xa") . "\n";'p +# openssl passwd -apr1 -salt xxxxxxxx password +# +# where "blah" is your root password. +# +#rootpw --iscrypted XaLGAVe1C41x2 +#rootpw XaLGAVe1C41x2 --iscrypted +rootpw --iscrypted #CRYPT:passwd:key=system,username=root:password# + +# +# NIS setup: auth --enablenis --nisdomain sensenet +# --nisserver neptune --useshadow --enablemd5 +# +# OR +auth --useshadow --enablemd5 + + +# +# SE Linux +# +selinux --disabled + +# +# Reboot after installation +# +reboot + +# +#end of section +# +%packages +#INCLUDE_DEFAULT_PKGLIST# +%end +%pre +#INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/pre.rh.rhel7# +%end +%post +#INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/post.xcat# +%end diff --git a/xCAT-server/share/xcat/install/rh/compute.rhels6.ppc64.tmpl b/xCAT-server/share/xcat/install/rh/compute.rhels6.ppc64.tmpl index 348677731..d05dec9f7 100644 --- a/xCAT-server/share/xcat/install/rh/compute.rhels6.ppc64.tmpl +++ b/xCAT-server/share/xcat/install/rh/compute.rhels6.ppc64.tmpl @@ -1,7 +1,8 @@ # lang en_US -network --bootproto dhcp +#network --bootproto dhcp +#KICKSTARTNET# # # Where's the source? diff --git a/xCAT-server/share/xcat/install/rh/compute.rhels6.x86_64.tmpl b/xCAT-server/share/xcat/install/rh/compute.rhels6.x86_64.tmpl index 9f0fddf60..c77177ae7 100644 --- a/xCAT-server/share/xcat/install/rh/compute.rhels6.x86_64.tmpl +++ b/xCAT-server/share/xcat/install/rh/compute.rhels6.x86_64.tmpl @@ -3,6 +3,7 @@ #cmdline lang en_US +#KICKSTARTNET# # # Where's the source? diff --git a/xCAT-server/share/xcat/install/scripts/post.rh.common b/xCAT-server/share/xcat/install/scripts/post.rh.common index f34fe6e5d..79bc733a7 100644 --- a/xCAT-server/share/xcat/install/scripts/post.rh.common +++ b/xCAT-server/share/xcat/install/scripts/post.rh.common @@ -2,6 +2,8 @@ # Setup hostname # echo "post scripts" >/root/post.log + + export PRINIC=#TABLEBLANKOKAY:noderes:THISNODE:primarynic# if [ "$PRINIC" == "mac" ] then diff --git a/xCAT-server/share/xcat/install/scripts/post.sles.common b/xCAT-server/share/xcat/install/scripts/post.sles.common index ec6e89437..ae6db1e24 100644 --- a/xCAT-server/share/xcat/install/scripts/post.sles.common +++ b/xCAT-server/share/xcat/install/scripts/post.sles.common @@ -1,6 +1,10 @@ #!/bin/sh +export MANAGEDADDRESSMODE=#MANAGEDADDRESSMODE# cd /etc/sysconfig/network + +if [ "$MANAGEDADDRESSMODE" != "static" ] +then rm -f ifcfg-eth-id* rm -f ifcfg-myri* cat >ifcfg-eth0 <> ifcfg-$PRINIC fi fi + +if [ "$MANAGEDADDRESSMODE" != "static" ] +then echo "DHCLIENT_PRIMARY_DEVICE=yes" >> ifcfg-$PRINIC +fi + perl -pi -e 's/^FIREWALL="yes"/FIREWALL="no"/' /etc/sysconfig/network/config /etc/init.d/network restart diff --git a/xCAT-server/share/xcat/install/scripts/post.xcat b/xCAT-server/share/xcat/install/scripts/post.xcat old mode 100644 new mode 100755 index add65c92c..61dbd8379 --- a/xCAT-server/share/xcat/install/scripts/post.xcat +++ b/xCAT-server/share/xcat/install/scripts/post.xcat @@ -39,8 +39,6 @@ do export USEOPENSSLFORXCAT XCATSERVER=$i:3001 export XCATSERVER - mv $i/postscripts /xcatpost - rm -rf $i # If mypostscript doesn't exist, we will get it through getpostscript.awk if [ ! -x /xcatpost/mypostscript ]; then @@ -184,9 +182,10 @@ addsiteyum /xcatpost/mypostscript sed -i 's/^serial/#serial/' /boot/grub/grub.conf sed -i 's/^terminal/#terminal/' /boot/grub/grub.conf -if [ -z "$NODESTATUS" ] || [ "$NODESTATUS" != "0" -a "$NODESTATUS" != "N" -a "$NODESTATUS" != "n" ]; then - updateflag.awk $MASTER 3002 -fi + +#the following command should always be run to prevent infinite installation loops +updateflag.awk $MASTER 3002 + cd / #rm -Rf /xcatpost #rm -f /xcatpost/mypostscript diff --git a/xCAT-server/share/xcat/install/scripts/pre.rh b/xCAT-server/share/xcat/install/scripts/pre.rh index 03d591e80..346b6de73 100644 --- a/xCAT-server/share/xcat/install/scripts/pre.rh +++ b/xCAT-server/share/xcat/install/scripts/pre.rh @@ -14,6 +14,17 @@ if [ -r /tmp/updates/etc/pki/tls/certs/ca-bundle.crt ]; then fi +#there is no boot option to set dns search domain in kickstart file, +#the search domain in /etc/resolv.conf is set in the pre installation script +export MANAGEDADDRESSMODE=#MANAGEDADDRESSMODE# +export SEARCHDOMAIN=#GETNODEDOMAIN:THISNODE# + +if [ "$MANAGEDADDRESSMODE" == "static" ]; then + echo "#appended by %pre " >> /etc/resolv.conf + echo "search $SEARCHDOMAIN" >> /etc/resolv.conf +fi + + cat >/tmp/baz.py <> /tmp/partitioning fi if [ -d /sys/firmware/efi ]; then + echo 'bootloader --driveorder='$instdisk >> /tmp/partitioning echo 'part /boot/efi --size 50 --ondisk '$instdisk' --fstype vfat' >> /tmp/partitioning +else + echo 'bootloader' >> /tmp/partitioning fi #TODO: ondisk detection, /dev/disk/by-id/edd-int13_dev80 for legacy maybe, and no idea about efi. at least maybe blacklist SAN if mptsas/mpt2sas/megaraid_sas seen... diff --git a/xCAT-server/share/xcat/install/scripts/pre.rh.rhel7 b/xCAT-server/share/xcat/install/scripts/pre.rh.rhel7 new file mode 100644 index 000000000..09203dfc6 --- /dev/null +++ b/xCAT-server/share/xcat/install/scripts/pre.rh.rhel7 @@ -0,0 +1,218 @@ +if grep n8r /proc/cmdline > /dev/null 2>&1; +then + stty crtscts +fi +for x in 0 1 2 3 4 5 6 7 8 +do + mknod /dev/vcs$x c 7 $x + mknod /dev/vcsa$x c 7 $[$x+128] +done +chmod 644 /dev/vcs* +chown root /dev/vcs* +if [ -r /tmp/updates/etc/pki/tls/certs/ca-bundle.crt ]; then + cp -f /tmp/updates/etc/pki/tls/certs/ca-bundle.crt /etc/pki/tls/certs/ +fi + + + +cat >/tmp/baz.py </tmp/foo.py </foo.log 2>&1 & + + + +#time to ascertain fstype and PReP/UEFI/legacy +#also, find first available block device (sda or vda likely) +#TODO: pick a likely non-SAN target if possible +shopt -s nullglob +for disk in /dev/vd*[^0-9];do + if [ -z "$firstdirectdisk" ]; then firstdirectdisk=$disk; fi #remember first disk as a guess of medium resort + eddname=$(/lib/udev/edd_id $disk 2> /dev/null) + if [ ! -z "$eddname" -a "$eddname" = "int13_dev80" ]; then + instdisk=$disk + break + fi +done + +if [ -z "$instdisk" ]; then + for disk in /dev/sd*[^0-9]; do + eddname=$(/lib/udev/edd_id $disk 2> /dev/null) + if [ ! -z "$eddname" -a "$eddname" = "int13_dev80" ]; then + instdisk=$disk + break + fi + currdriver=`udevadm info --attribute-walk --name $disk |grep DRIVERS|grep -v '""'|grep -v '"sd"'|head -n 1|sed -e 's/[^"]*"//' -e 's/"//'` + case "$currdriver" in + "ata_piix4"|"PMC MaxRAID"|"ahci"|"megaraid_sas") #certainly direct + if [ -z "$firstdirectdisk" ]; then firstdirectdisk=$disk; fi #remember first disk as a guess of medium resort + ;; + "mptsas"|"mpt2sas"|"mpt3sas") #*PROBABLY* not SAN, but SAS SAN is possible + if [ -z "$probablyfirstdirectdisk" ]; then probablyfirstdirectdisk=$disk; fi #remember first disk as a guess of medium resort + ;; + *) + if [ -z "$firstdisk" ]; then firstdisk=$disk; fi #remember first disk as a guess of medium resort + ;; + esac + done +fi + +if [ -z "$instdisk" ]; then + if [ ! -z "$firstdirectdisk" ]; then + instdisk=$firstdirectdisk + elif [ ! -z "$probablyfirstdirectdisk" ]; then + instdisk=$probablyfirstdirectdisk + elif [ ! -z "$firstdisk" ]; then + instdisk=$firstdisk + fi +fi + + +modprobe ext4 >& /dev/null +modprobe ext4dev >& /dev/null +if grep ext4dev /proc/filesystems > /dev/null; then + FSTYPE=ext3 +elif grep ext4 /proc/filesystems > /dev/null; then + FSTYPE=ext4 +else + FSTYPE=ext3 +fi + +if [ `uname -m` = "ppc64" ]; then + echo 'part None --fstype "PPC PReP Boot" --ondisk '$instdisk' --size 8' >> /tmp/partitioning +fi +if [ -d /sys/firmware/efi ]; then + echo 'part /boot/efi --size 50 --ondisk '$instdisk' --fstype vfat' >> /tmp/partitioning +fi + +#TODO: ondisk detection, /dev/disk/by-id/edd-int13_dev80 for legacy maybe, and no idea about efi. at least maybe blacklist SAN if mptsas/mpt2sas/megaraid_sas seen... +echo "part /boot --size 256 --fstype ext3 --ondisk $instdisk" >> /tmp/partitioning +echo "part swap --recommended --ondisk $instdisk" >> /tmp/partitioning +echo "part / --size 1 --grow --ondisk $instdisk --fstype $FSTYPE" >> /tmp/partitioning + +#XCA_PARTITION_SCRIPT# + + +# The following code is to generate the repository for the installation +cat /proc/cmdline + +NEXTSERVER=`cat /proc/cmdline | grep http | head -n 1` +NEXTSERVER=${NEXTSERVER#*http://} +NEXTSERVER=${NEXTSERVER%%:*} + +export nextserver=$NEXTSERVER +#INSTALL_SOURCES_IN_PRE# + + diff --git a/xCAT-server/share/xcat/install/scripts/pre.sles b/xCAT-server/share/xcat/install/scripts/pre.sles index 6c616c9e8..82337a568 100644 --- a/xCAT-server/share/xcat/install/scripts/pre.sles +++ b/xCAT-server/share/xcat/install/scripts/pre.sles @@ -145,7 +145,7 @@ if [ -z "$instdisk" ]; then "ata_piix4"|"PMC MaxRAID"|"ahci"|"megaraid_sas") #certainly direct if [ -z "$firstdirectdisk" ]; then firstdirectdisk=$disk; fi #remember first disk as a guess of medium resort ;; - "mptsas"|"mpt2sas") #*PROBABLY* not SAN, but SAS SAN is possible + "mptsas"|"mpt2sas"|"mpt3sas") #*PROBABLY* not SAN, but SAS SAN is possible if [ -z "$probablyfirstdirectdisk" ]; then probablyfirstdirectdisk=$disk; fi #remember first disk as a guess of medium resort ;; *) diff --git a/xCAT-server/share/xcat/install/sles/compute.sles11.tmpl b/xCAT-server/share/xcat/install/sles/compute.sles11.tmpl index 64819cafa..b343a4fbe 100644 --- a/xCAT-server/share/xcat/install/sles/compute.sles11.tmpl +++ b/xCAT-server/share/xcat/install/sles/compute.sles11.tmpl @@ -63,25 +63,7 @@ - - - true - true - local - linux - - - - dhcp - eth0 - onboot - - - - false - - - + #YAST2NET# #INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/pre.sles# #INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/chroot.sles# diff --git a/xCAT-server/share/xcat/netboot/add-on/stateless/stateless b/xCAT-server/share/xcat/netboot/add-on/stateless/stateless deleted file mode 100755 index 1c7fd6646..000000000 --- a/xCAT-server/share/xcat/netboot/add-on/stateless/stateless +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/sh -# -# stateless -# -# chkconfig: 345 11 99 -# description: action stateless -# -# Source the library functions -. /etc/rc.d/init.d/functions - - -ZONE="US/Mountain" - -case "$1" in - start) - echo -n "Starting stateless configuration: " - - if [ -r /etc/stateless_done ] - then - echo_failure - echo - echo " already run!" - exit $? - fi - -#initrd=xcat/netboot/fedora8/x86_64/compute/initrd.gz imgurl=nfs://rro000/install/netboot/fedora8/x86_64/compute/rootimg console=ttyS1,19200n8r BOOT_IMAGE=xcat/netboot/fedora8/x86_64/compute/kernel - cat /proc/cmdline | grep imgurl >/dev/null 2>&1 - - if [ "$?" != "0" ] - then - echo_failure - echo - echo " imgurl missing from /proc/cmdline, i.e. stateful!" - exit $? - fi - - for i in $(cat /proc/cmdline) - do - KEY=$(echo $i | awk -F= '{print $1}') - VALUE=$(echo $i | awk -F= '{print $2}') - - if [ "$KEY" = "imgurl" ] - then - SERVER=$(echo $VALUE | awk -F/ '{print $3}') - fi - done - - if [ -z "$SERVER" ] - then - echo_failure - echo - echo "bogus server in imgurl" - exit $? - fi - - echo - echo " Universal Server: $SERVER" - - echo -n " Syslog: " - echo "*.* @$SERVER" >/etc/rsyslog.conf - echo_success - echo - - if [ -r /etc/rc.d/init.d/ntpd ] - then - echo -n " NTP: " - if [ ! -r /etc/sysconfig/clock ] - then - echo "ZONE=\"$ZONE\" -UTC=true -ARC=false" >/etc/sysconfig/clock - fi - - echo "server $SERVER -driftfile /etc/ntp/drift -multicastclient -broadcastdelay 0.008 -disable auth -keys /etc/ntp/keys -trustedkey 65535 -requestkey 65535 -controlkey 65535" >/etc/ntp.conf - - echo "$SERVER" >/etc/ntp/step-tickers - - echo_success - echo - fi - - if [ -r /etc/ldap.conf -a -r /etc/resolv.conf ] - then - echo -n " LDAP: " - - DC=$( - cat /etc/resolv.conf | \ - egrep '(domain|search)' | \ - head -1 | \ - awk '{print $2}' | \ - sed 's/\./,dc=/g' | \ - sed 's/^/dc=/' - ) - - echo "host $SERVER -base $DC -nss_base_passwd ou=People,$DC -nss_base_shadow ou=People,$DC -nss_base_group ou=Group,$DC -timelimit 120 -bind_timelimit 120 -idle_timelimit 3600 -nss_initgroups_ignoreusers root,ldap,named,avahi,haldaemon,dbus,radvd,tomcat,radiusd,news,mailman,nscd -ssl no -tls_cacertdir /etc/openldap/cacerts -pam_password md5" >/etc/ldap.conf - - echo "URI ldap://$SERVER -BASE $DC -TLS_CACERTDIR /etc/openldap/cacerts" >/etc/openldap/ldap.conf - - cd /etc - cp nsswitch.conf nsswitch.conf.ORIG - sed -r 's/^((passwd|shadow|group):.*)/\1 ldap/' nsswitch.conf - - cd /etc/pam.d - cp system-auth system-auth.ORIG - sed -r 's/(account\s+required\s+pam_unix.so)/account sufficient pam_ldap.so\n\1/' system-auth - - echo_success - echo - fi - touch /etc/stateless_done - ;; - stop) - ;; - *) - echo "Usage: stateless {start|stop}" - exit 1 -esac diff --git a/xCAT-server/share/xcat/netboot/centos/mkhpcimage.example b/xCAT-server/share/xcat/netboot/centos/mkhpcimage.example deleted file mode 100755 index f2d3f9a2b..000000000 --- a/xCAT-server/share/xcat/netboot/centos/mkhpcimage.example +++ /dev/null @@ -1,170 +0,0 @@ -################################################################################ -# Create a generic HPC image -# This script is an example of how to create an HPC image with xCAT stateless. -# in this example you may need to change some of the parameters. In the future -# we should probably place this in the database... -# All good sys admins can reproduce their environments. Creating a stateless -# image should be reproducable. Doing this with a script is a good idea. -# -################################################################################ - - -# specify the OS stuff. You'll probably want to change this. If you do then you'll -# need to make sure there is a *.pkglist and *.exlist -PROFILE=compute -ARCH=x86_64 -OS=centos5.3 - -# this is where the OS image will reside -IMGROOT=/install/netboot/$OS/$ARCH/$PROFILE/rootimg - -# remove the old image if it exists. -rm -rf /install/netboot/$OS/$ARCH/$PROFILE - -# generate the base image -# for IBM: tg3 in older blades, bnx in newer stuff, and igb in the nehalem based products. -/opt/xcat/share/xcat/netboot/centos/genimage -i eth0 -n libphy,tg3,bnx2,igb -o $OS -p $PROFILE - -# update the yum database in the image -rm -rf $IMGROOT/etc/yum.repos.d -yum --installroot=$IMGROOT clean all -cp -a /etc/yum.repos.d/ $IMGROOT/etc/ -rm -rf $IMGROOT/etc/yum.repos.d/xCAT-* - -# no selinux!! -echo SELINUX=disabled > $IMGROOT/etc/sysconfig/selinux - -# fix respawns -cp $IMGROOT/etc/inittab $IMGROOT/etc/inittab.ORIG -grep -v 38400 $IMGROOT/etc/inittab.ORIG > $IMGROOT/etc/inittab - -# filesystem setup, you'll want to customize this. We have swap and scratch -# configured here. But if you don't have disks then this may not help. -# we name our / partition the image name (compute by default) plus a timestamp. - -TIME=`date +%s` -cp $IMGROOT/etc/fstab $IMGROOT/etc/fstab.ORIG -echo "proc /proc proc rw 0 0 -sysfs /sys sysfs rw 0 0 -devpts /dev/pts devpts rw,gid=5,mode=620 0 0 -$PROFILE-$TIME / tmpfs rw 0 1 -#/dev/sda1 swap swap defaults 0 0 -#/dev/sda2 /scratch ext3 defaults 0 0 -" > $IMGROOT/etc/fstab -mkdir $IMGROOT/scratch - -### get ntp to start on boot -chroot $IMGROOT chkconfig --level 345 ntpd on - -#### user stuff so that we can do some work #### -cp /etc/shadow $IMGROOT/etc/ -cp /etc/group $IMGROOT/etc/ -cp /etc/passwd $IMGROOT/etc/ -cp /etc/hosts $IMGROOT/etc/ - -### scaling fixes ##### -echo "# increase TCP max buffer size -net.core.rmem_max = 33554432 -net.core.wmem_max = 33554432 -net.core.rmem_default = 65536 -net.core.wmem_default = 65536 -# increase Linux autotuning TCP buffer limits -# min, default, and max number of bytes to use -net.ipv4.tcp_rmem = 4096 33554432 33554432 -net.ipv4.tcp_wmem = 4096 33554432 33554432 -net.ipv4.tcp_mem= 33554432 33554432 33554432 -net.ipv4.route.flush=1 -net.core.netdev_max_backlog=1500 - -#GPFS / NFS Tuning -net.ipv4.conf.all.arp_filter = 1 -net.ipv4.conf.all.rp_filter = 1 -net.ipv4.neigh.default.gc_thresh1 = 1024 -net.ipv4.neigh.default.gc_thresh2 = 4096 -net.ipv4.neigh.default.gc_thresh3 = 8192 -net.ipv4.neigh.default.gc_stale_time = 24" >> $IMGROOT/etc/sysctl.conf - -## Limits: need to make sure users can have unlimited memory (ulimit -l unlimited) -cp /etc/security/limits.conf $IMGROOT/etc/security/ - -### add torque ### -/opt/xcat/share/xcat/netboot/add-on/torque/add_torque $IMGROOT mgt /opt/torque / local - -# update the limit on pegged memory limit and if they have old xCAT then make sure -# it says torque instead of pbs in the paths of the config file. -perl -pi -e 's/ulimit -n 20000/ulimit -n 20000; ulimit -l unlimited/g' $IMGROOT/etc/init.d/pbs_mom -perl -pi -e 's/spool\/pbs/spool\/torque/g' $IMGROOT/etc/init.d/pbs_mom -perl -pi -e 's/spool\/pbs/spool\/torque/g' $IMGROOT/etc/init.d/pbs_mom -perl -pi -e 's/PBS_HOME=\/var\/spool\/pbs/PBS_HOME=\/var\/spool\/torque/g' $IMGROOT/var/spool/torque/mom_priv/epilogue -perl -pi -e 's/PBS_HOME=\/var\/spool\/pbs/PBS_HOME=\/var\/spool\/torque/g' $IMGROOT/var/spool/torque/mom_priv/prologue -perl -pi -e 's/PBS_HOME=\/var\/spool\/pbs/PBS_HOME=\/var\/spool\/torque/g' $IMGROOT/var/spool/torque/mom_priv/takedownnode - -### stateless init script does NTP, syslog, etc. #### -cp /etc/localtime $IMGROOT/etc/ -cp /opt/xcat/share/xcat/netboot/add-on/stateless/stateless $IMGROOT/etc/init.d/ -perl -pi -e 's!Mountain!Mexico/General!g' $IMGROOT/etc/init.d/stateless -perl -pi -e 's/driftfile \/etc\/ntp/driftfile \/var\/lib\/ntp/g' $IMGROOT/etc/init.d/stateless -perl -pi -e 's/keys \/etc\/ntp/keys \/var\/lib\/ntp/g' $IMGROOT/etc/init.d/stateless -rm -rf $IMGROOT/etc/sysconfig/clock -chroot $IMGROOT chkconfig --level 345 stateless on -chroot $IMGROOT chkconfig --level 345 rsyslog on - -### make sure dhcp boot protocol is set to none ### -perl -pi -e 's/dhcp/none/g' $IMGROOT/etc/sysconfig/network-scripts/ifcfg-eth0 - -#### add GPFS stuff ### -# this is an example of a stateless GPFS implementation. Uncomment the below if you -# want GPFS. Make sure you have the GPFS RPMs to do this. -#GPFSSRCDIR=/install/GPFS -#yum --installroot=$IMGROOT -y install glibc ksh compat-libstdc++-33 binutils rsh -#rpm -ivh --root=$IMGROOT $GPFSSRCDIR/gpfs.base*rpm -#rpm -ivh --root=$IMGROOT $GPFSSRCDIR/gpfs.gpl*rpm -#rpm -ivh --root=$IMGROOT $GPFSSRCDIR/gpfs.msg*rpm -#rpm -Uivh --root=$IMGROOT $GPFSSRCDIR/updates/gpfs.base*rpm -#rpm -Uivh --root=$IMGROOT $GPFSSRCDIR/updates/gpfs.gpl*rpm -#rpm -Uivh --root=$IMGROOT $GPFSSRCDIR/updates/gpfs.msg*rpm -## -#AUTOGPFSDIR=/opt/xcat/share/xcat/netboot/add-on/autogpfs -#cp $AUTOGPFSDIR/autogpfsc.pl $IMGROOT/usr/sbin -#cp $AUTOGPFSDIR/autogpfsc $IMGROOT/etc/init.d/ -#echo "SERVERS=mgt -#PORT=3003 -#BLOCK=no" >> $IMGROOT/etc/sysconfig/autogpfsc -# -#chroot $IMGROOT chkconfig --level 345 autogpfsc on -#cp $GPFSSRCDIR/2.6.18-128.el5/* $IMGROOT/usr/lpp/mmfs/bin/ -#cp /etc/profile.d/gpfs.sh $IMGROOT/etc/profile.d/ -### End GPFS Stuff #### - - -### IB Stuff #### -# if you have InfiniBand on your machines then you probably have an OFED distribution you -# need to add. Here is an example of how to add it. -#echo "Adding InfiniBand" -#yum --installroot=$IMGROOT -y install bind-utils which rpm tcl tk glibc-devel.i386 pciutils expat libgfortran.x86_64 libgomp.x86_64 tcsh -# -#IBROOT=/install/voltaire/VoltaireOFED-1.4.2_2-k2.6.18-128.el5-x86_64 -#mount -o bind /proc $IMGROOT/proc -#mount -o bind /sys $IMGROOT/sys -#mount -o bind $IBROOT $IMGROOT/mnt -#chroot $IMGROOT /mnt/install.sh --without-mpi -#umount $IMGROOT/mnt -#umount $IMGROOT/sys -#umount $IMGROOT/proc -# configure IB IP address -#echo "IP=\`host \$HOSTNAME-ib0 | awk '{ print \$4 }' | head -1\`" >> $IMGROOT/etc/rc.d/rc.local -#echo "ifconfig ib0 \$IP" >> $IMGROOT/etc/rc.d/rc.local -#echo "ifconfig ib0 netmask 255.255.0.0" >> $IMGROOT/etc/rc.d/rc.local -### End IB Stuff #### - -# configure name resolution -# change this to what you want it to be. (this is in site.tab as the domain and nameservers) -echo "search cluster.foo -nameserver 172.20.0.1" >$IMGROOT/etc/resolv.conf - - -### uniq-i-fy Torque OS name -echo "opsys compute_centos5.3" >> $IMGROOT/var/spool/torque/mom_priv/config - -packimage -p $PROFILE -a $ARCH -o $OS -echo "Image $PROFILE-$TIME created" diff --git a/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.exlist b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.exlist new file mode 100755 index 000000000..ccad8b8c8 --- /dev/null +++ b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.exlist @@ -0,0 +1,35 @@ +./boot* +./usr/share/wallpapers/RHEL6/contents/images* +./usr/include* +./usr/lib/locale* +./usr/lib64/perl5/Encode/CN* +./usr/lib64/perl5/Encode/JP* +./usr/lib64/perl5/Encode/TW* +./usr/lib64/perl5/Encode/KR* +./lib/kbd/keymaps/i386* +./lib/kbd/keymaps/mac* +./lib/kdb/keymaps/include* +./usr/local/include* +./usr/local/share/man* +./usr/share/man* +./usr/share/cracklib* +./usr/share/doc* +./usr/share/doc/packages/cyrus-sasl/doc* +./usr/share/gnome* +./usr/share/i18n* ++./usr/share/i18n/en_US* +./usr/share/info* +./usr/share/locale/* ++./usr/share/locale/en_US* ++./usr/share/locale/C* ++./usr/share/locale/locale.alias ++./usr/lib/locale/locale-archive ++./usr/lib/locale/en* +./usr/share/man* +./usr/share/omf* +./usr/share/vim/site/doc* +./usr/share/vim/vim72/doc* +./usr/share/zoneinfo* +./var/cache/man* +./var/lib/yum* + diff --git a/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.pkglist b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.pkglist new file mode 100644 index 000000000..452804038 --- /dev/null +++ b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.pkglist @@ -0,0 +1,27 @@ +bash +nfs-utils +openssl +dhclient +kernel +openssh-server +openssh-clients +busybox +wget +rsyslog +dash +vim-minimal +ntp +rsyslog +rpm +rsync +ppc64-utils +iputils +dracut +dracut-network +e2fsprogs +bc +lsvpd +irqbalance +procps +parted +net-tools diff --git a/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.postinstall b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.postinstall new file mode 100755 index 000000000..ad071c87c --- /dev/null +++ b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.ppc64.postinstall @@ -0,0 +1,46 @@ +#!/bin/sh +#-- Do not remove following line if you want to make use of CVS version tracking +#-- $Id: compute.postinstall,v 1.21 2008/09/04 12:05:45 sikorsky Exp $ +#-- jurij.sikorsky@t-systems.cz +#-- +#-- this script is run after all packages from $profile.pkglist are installed +#-- +#-- it gets these arguments: +#-- +#-- $1 = install root (chroot directory for profile) +#-- $2 = OS version +#-- $3 = architecture +#-- $4 = profile name +#-- $5 = work dir (where genimage is located) +#-- +#-- +installroot=$1 +osver=$2 +arch=$3 +profile=$4 +workdir=$5 + +#-- Example how /etc/fstab can be automatically generated during image generation: +cat <$installroot/etc/fstab +proc /proc proc rw 0 0 +sysfs /sys sysfs rw 0 0 +devpts /dev/pts devpts rw,gid=5,mode=620 0 0 +${profile}_${arch} / tmpfs rw 0 1 +none /tmp tmpfs defaults,size=10m 0 2 +none /var/tmp tmpfs defaults,size=10m 0 2 +END + + +#-- Uncomment the line contains "cons" in /etc/inittab +#cons:12345:respawn:/sbin/smart_agetty -L 38400 console +echo "co:2345:respawn:/sbin/agetty -L 38400 console" >> $installroot/etc/inittab + + +#-- Example of booted image versioning +#-- We want to know, with what configuration (version of the image) each node was booted. +#-- Hence, we keep image definition files and postscripts in CVS. During image generation we create file /etc/IMGVERSION and fill it with CVS "$Id$" of files with image definition (.pkglist, .exlist, .repolist, .postinstall). Then, during boot, each "CVS enabled" postscript (see /install/postscripts/cvs_template.sh and /install/postscripts/cvs_template.pl) adds one line to /etc/IMGVERSION. Then you can determine in any time what image you are running and what postscipts in which versions were run. +#cat /dev/null > $installroot/etc/IMGVERSION +#for ext in pkglist exlist postinstall repolist; do +# [ -r $workdir/$profile.$ext ] && cat $workdir/$profile.$ext | grep -E '^[[:space:]]*#.*[[:space:]]\$Id' >> $installroot/etc/IMGVERSION +#done + diff --git a/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.exlist b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.exlist new file mode 100755 index 000000000..ccad8b8c8 --- /dev/null +++ b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.exlist @@ -0,0 +1,35 @@ +./boot* +./usr/share/wallpapers/RHEL6/contents/images* +./usr/include* +./usr/lib/locale* +./usr/lib64/perl5/Encode/CN* +./usr/lib64/perl5/Encode/JP* +./usr/lib64/perl5/Encode/TW* +./usr/lib64/perl5/Encode/KR* +./lib/kbd/keymaps/i386* +./lib/kbd/keymaps/mac* +./lib/kdb/keymaps/include* +./usr/local/include* +./usr/local/share/man* +./usr/share/man* +./usr/share/cracklib* +./usr/share/doc* +./usr/share/doc/packages/cyrus-sasl/doc* +./usr/share/gnome* +./usr/share/i18n* ++./usr/share/i18n/en_US* +./usr/share/info* +./usr/share/locale/* ++./usr/share/locale/en_US* ++./usr/share/locale/C* ++./usr/share/locale/locale.alias ++./usr/lib/locale/locale-archive ++./usr/lib/locale/en* +./usr/share/man* +./usr/share/omf* +./usr/share/vim/site/doc* +./usr/share/vim/vim72/doc* +./usr/share/zoneinfo* +./var/cache/man* +./var/lib/yum* + diff --git a/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.pkglist b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.pkglist new file mode 100644 index 000000000..18ceb3e33 --- /dev/null +++ b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.pkglist @@ -0,0 +1,23 @@ +bash +dracut-network +nfs-utils +openssl +dhclient +kernel +openssh-server +openssh-clients +busybox +dash +iputils +bc +irqbalance +procps +wget +vim-minimal +ntp +rpm +rsync +rsyslog +e2fsprogs +parted +net-tools diff --git a/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.postinstall b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.postinstall new file mode 100755 index 000000000..f157e7421 --- /dev/null +++ b/xCAT-server/share/xcat/netboot/rh/compute.rhels7.x86_64.postinstall @@ -0,0 +1,45 @@ +#!/bin/sh +#-- Do not remove following line if you want to make use of CVS version tracking +#-- $Id: compute.postinstall,v 1.21 2008/09/04 12:05:45 sikorsky Exp $ +#-- jurij.sikorsky@t-systems.cz +#-- +#-- this script is run after all packages from $profile.pkglist are installed +#-- +#-- it gets these arguments: +#-- +#-- $1 = install root (chroot directory for profile) +#-- $2 = OS version +#-- $3 = architecture +#-- $4 = profile name +#-- $5 = work dir (where genimage is located) +#-- +#-- +installroot=$1 +osver=$2 +arch=$3 +profile=$4 +workdir=$5 + +#-- Example how /etc/fstab can be automatically generated during image generation: +cat <$installroot/etc/fstab +proc /proc proc rw 0 0 +sysfs /sys sysfs rw 0 0 +devpts /dev/pts devpts rw,gid=5,mode=620 0 0 +${profile}_${arch} / tmpfs rw 0 1 +none /tmp tmpfs defaults,size=10m 0 2 +none /var/tmp tmpfs defaults,size=10m 0 2 +END + +#-- Uncomment the line contains "cons" in /etc/inittab +#cons:12345:respawn:/sbin/smart_agetty -L 38400 console +#echo "co:2345:respawn:/sbin/agetty -L 38400 console" >> $installroot/etc/inittab + + +#-- Example of booted image versioning +#-- We want to know, with what configuration (version of the image) each node was booted. +#-- Hence, we keep image definition files and postscripts in CVS. During image generation we create file /etc/IMGVERSION and fill it with CVS "$Id$" of files with image definition (.pkglist, .exlist, .repolist, .postinstall). Then, during boot, each "CVS enabled" postscript (see /install/postscripts/cvs_template.sh and /install/postscripts/cvs_template.pl) adds one line to /etc/IMGVERSION. Then you can determine in any time what image you are running and what postscipts in which versions were run. +#cat /dev/null > $installroot/etc/IMGVERSION +#for ext in pkglist exlist postinstall repolist; do +# [ -r $workdir/$profile.$ext ] && cat $workdir/$profile.$ext | grep -E '^[[:space:]]*#.*[[:space:]]\$Id' >> $installroot/etc/IMGVERSION +#done + diff --git a/xCAT-server/share/xcat/netboot/rh/genimage b/xCAT-server/share/xcat/netboot/rh/genimage index 52fd168ff..37eadfd8f 100755 --- a/xCAT-server/share/xcat/netboot/rh/genimage +++ b/xCAT-server/share/xcat/netboot/rh/genimage @@ -577,13 +577,13 @@ foreach my $dn (@ndrivers) { @ndrivers = @fulldrivers; unlink "/tmp/genimage.$$.yum.conf"; -if (-d "$rootimg_dir/usr/share/dracut") { +if ( (-d "$rootimg_dir/usr/share/dracut") or (-d "$rootimg_dir/usr/lib/dracut") ) { $dracutmode = 1; # get dracut version my $dracutver = `rpm --root $rootimg_dir -qi dracut | grep Version | awk -F' ' '{print \$3}'`; chomp($dracutver); if ($dracutver =~ /^\d\d\d$/) { - if ($dracutver >= "009") { + if (($dracutver >= "009") and ($dracutver < "033")) { $dracutdir = "dracut_009"; } else { $dracutdir = "dracut"; # The default directory @@ -813,7 +813,14 @@ sub getlibs { sub mkinitrd_dracut { my ($mode) = @_; # the mode is for statelite or stateless - my $dracutmpath = "$rootimg_dir/usr/share/dracut/modules.d/97xcat"; + + my $dracutmoduledir="$rootimg_dir/usr/share/dracut/modules.d/"; + if ( (! -d $dracutmoduledir) and (-d "$rootimg_dir/usr/lib/dracut/modules.d/")) + { + $dracutmoduledir="$rootimg_dir/usr/lib/dracut/modules.d/"; + } + + my $dracutmpath = $dracutmoduledir."97xcat/"; mkpath($dracutmpath); my $perm = (stat("$fullpath/$dracutdir/check"))[2]; @@ -857,7 +864,7 @@ sub mkinitrd_dracut { #update etc/dracut.conf open($DRACUTCONF, '>', "$rootimg_dir/etc/dracut.conf"); - if (-d glob("$rootimg_dir/usr/share/dracut/modules.d/[0-9]*fadump")){ + if (-d glob($dracutmoduledir."[0-9]*fadump")){ print $DRACUTCONF qq{dracutmodules+="xcat nfs base network kernel-modules fadump"\n}; } else{ @@ -896,7 +903,7 @@ sub mkinitrd_dracut { # update etc/dracut.conf open($DRACUTCONF, '>', "$rootimg_dir/etc/dracut.conf"); - if (-d glob("$rootimg_dir/usr/share/dracut/modules.d/[0-9]*fadump")){ + if (-d glob($dracutmoduledir."[0-9]*fadump")){ print $DRACUTCONF qq{dracutmodules+="xcat nfs base network kernel-modules fadump"\n}; } else{ diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index 6746625ee..daedcca5a 100755 --- a/xCAT-server/share/xcat/netboot/sles/genimage +++ b/xCAT-server/share/xcat/netboot/sles/genimage @@ -177,7 +177,7 @@ if ($netdriver) { # Add the default driver list if ($arch eq 'x86' or $arch eq 'x86_64') { - push @ndrivers, qw/tg3 bnx2 bnx2x e1000 e1000e igb mlx_en be2net/; + push @ndrivers, qw/tg3 bnx2 bnx2x e1000 e1000e virtio_net virtio_balloon igb mlx_en be2net/; } elsif ($arch eq 'ppc64') { push @ndrivers, qw/tg3 e1000 e1000e igb ibmveth ehea be2net/; } elsif ($arch eq "s390x") { diff --git a/xCAT-server/share/xcat/netboot/ubuntu/genimage b/xCAT-server/share/xcat/netboot/ubuntu/genimage index 2a0bd3f3b..4b2868e81 100755 --- a/xCAT-server/share/xcat/netboot/ubuntu/genimage +++ b/xCAT-server/share/xcat/netboot/ubuntu/genimage @@ -241,7 +241,8 @@ unless ($onlyinitrd) { my $aptgetcmd = "chroot $rootimg_dir apt-get update && chroot $rootimg_dir apt-get $non_interactive "; my $aptcachecmd = "chroot $rootimg_dir apt-get update && chroot $rootimg_dir apt-cache $non_interactive "; my $aptcmd1 = "debootstrap"; - my $aptcmd2 = "--arch $uarch $dist $rootimg_dir file://$installroot/$osver/$arch/"; + #my $aptcmd2 = "--arch $uarch $dist $rootimg_dir file://$installroot/$osver/$arch/"; + my $aptcmd2 = "--verbose --arch $uarch $dist $rootimg_dir http://archive.ubuntu.com/ubuntu/"; mkpath("$rootimg_dir/var/lib/dpkg"); mkpath("$rootimg_dir/var/lib/apt"); @@ -1012,6 +1013,7 @@ fi export IFACE=\$IFACE +ifconfig \$IFACE up netstart \$IFACE while ! ifconfig | grep 'inet addr'; do echo -e "\${RED}Failed to acquire address, retrying \${RESET}" @@ -1287,8 +1289,8 @@ EOMS close($inifile); open($inifile,">"."/tmp/xcatinitrd.$$/bin/netstart"); - print $inifile "#!/sbin/sh\n"; - print $inifile "udhcpc -n -q -i \${1}\n"; + print $inifile "#!/bin/bash\n"; + print $inifile "udhcpc -n -q -i \${1} -s /usr/share/udhcpc/default.script\n"; close($inifile); open($inifile,">"."/tmp/xcatinitrd.$$/usr/share/udhcpc/default.script"); @@ -1458,6 +1460,13 @@ EOMS #system("cp -r $rootimg_dir/lib64/* /tmp/xcatinitrd.$$/lib64"); #system("mkdir -p /tmp/xcatinitrd.$$/var/run/netreport"); symlink("busybox","/tmp/xcatinitrd.$$/bin/pivot_root"); + symlink("busybox", "/tmp/xcatinitrd.$$/bin/udhcpc"); + symlink("busybox", "/tmp/xcatinitrd.$$/sbin/ifconfig"); + symlink("busybox", "/tmp/xcatinitrd.$$/bin/hostname"); + symlink("busybox", "/tmp/xcatinitrd.$$/bin/route"); + symlink("bash", "/tmp/xcatinitrd.$$/bin/sh"); + symlink("bash", "/tmp/xcatinitrd.$$/sbin/sh"); + #copy("$rootimg_dir/lib/modules/*d","/tmp/xcatinitrd.$$/$_"); system("cd /tmp/xcatinitrd.$$;find .|cpio -H newc -o|gzip -9 -c - > $destdir/initrd-$mode.gz"); diff --git a/xCAT-server/xCAT-server.spec b/xCAT-server/xCAT-server.spec index 51a1421be..2b6ee0988 100644 --- a/xCAT-server/xCAT-server.spec +++ b/xCAT-server/xCAT-server.spec @@ -16,6 +16,11 @@ BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root AutoReqProv: no %endif +%define fsm %(if [ "$fsm" = "1" ];then echo 1; else echo 0; fi) + +%define pcm %(if [ "$pcm" = "1" ];then echo 1; else echo 0; fi) +%define notpcm %(if [ "$pcm" = "1" ];then echo 0; else echo 1; fi) + # AIX will build with an arch of "ppc" # also need to fix Requires for AIX %ifos linux @@ -24,7 +29,15 @@ Requires: perl-IO-Socket-SSL perl-XML-Simple perl-XML-Parser Obsoletes: atftp-xcat %endif -%define fsm %(if [ "$fsm" = "1" ];then echo 1; else echo 0; fi) +# The aix rpm cmd forces us to do this outside of ifos type stmts +%if %notpcm +%ifos linux +%ifnarch s390x +# PCM does not use or ship grub2-xcat +#Requires: grub2-xcat +%endif +%endif +%endif %if %fsm # nothing needed here @@ -152,7 +165,7 @@ rm $RPM_BUILD_ROOT/%{prefix}/sbin/stopstartxcatd #rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/blade.pm rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/hpblade.pm rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/hpilo.pm -#rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/ipmi.pm +rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/ipmi.pm rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/nodediscover.pm #rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/switch.pm rm $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/xen.pm @@ -308,14 +321,24 @@ mkdir -p $RPM_BUILD_ROOT/%{prefix}/ws mkdir -p $RPM_BUILD_ROOT/etc/apache2/conf.d mkdir -p $RPM_BUILD_ROOT/etc/httpd/conf.d cp xCAT-wsapi/* $RPM_BUILD_ROOT/%{prefix}/ws +# PCM does not need xcatws.cgi +# xcatws.cgi causes xCAT-server requires perl-JSON, which is not shipped with PCM +%if %pcm +rm -f $RPM_BUILD_ROOT/%{prefix}/ws/xcatws.cgi +%endif + %if %fsm %else echo "ScriptAlias /xcatrhevh %{prefix}/ws/xcatrhevh.cgi" > $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat-ws.conf +%if %notpcm echo "ScriptAlias /xcatws %{prefix}/ws/xcatws.cgi" >> $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat-ws.conf +%endif cat $RPM_BUILD_ROOT/%{prefix}/ws/xcat-ws.conf.apache2 >> $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat-ws.conf echo "ScriptAlias /xcatrhevh %{prefix}/ws/xcatrhevh.cgi" > $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat-ws.conf +%if %notpcm echo "ScriptAlias /xcatws %{prefix}/ws/xcatws.cgi" >> $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat-ws.conf +%endif cat $RPM_BUILD_ROOT/%{prefix}/ws/xcat-ws.conf.httpd >> $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat-ws.conf %endif rm -f $RPM_BUILD_ROOT/%{prefix}/ws/xcat-ws.conf.apache2 diff --git a/xCAT-server/xCAT-wsapi/genrestapidoc.pm b/xCAT-server/xCAT-wsapi/genrestapidoc.pm new file mode 100755 index 000000000..144071f0c --- /dev/null +++ b/xCAT-server/xCAT-wsapi/genrestapidoc.pm @@ -0,0 +1,321 @@ +#! /usr/bin/perl + +package genrestapidoc; + +my @apigroups = ( + { + groupname => 'tokens', + header => "Token Resources", + desc => "The URI list which can be used to create tokens for account .", + resources => ['tokens'], + }, + { + groupname => 'nodes', + header => "Node Resources", + desc => "The URI list which can be used to create, query, change and manage node objects.", + resources => ['allnode', 'nodeallattr', 'nodeattr', 'nodehost', 'nodedns', 'nodedhcp', 'nodestat', 'subnodes', + 'power', 'energy', 'energyattr', 'serviceprocessor', 'nextboot', 'bootstate', + 'vitals', 'vitalsattr', 'inventory', 'inventoryattr', 'eventlog', 'beacon', + 'updating','filesyncing','software_maintenance','postscript', 'nodeshell', 'nodecopy', + ] + }, + { + groupname => 'osimages', + header => "Osimage resources", + desc => "URI list which can be used to query, create osimage resources.", + resources => ['osimage', 'osimage_allattr', 'osimage_attr', 'osimage_op'] + }, + { + groupname => 'networks', + header => "Network Resources", + desc => "The URI list which can be used to create, query, change and manage network objects.", + resources => ['allnetwork', 'network_allattr','network_attr'] + + }, + { + groupname => 'policy', + header => "Policy Resources", + desc => "The URI list which can be used to create, query, change and manage policy entries.", + resources => ['policy', 'policy_allattr', 'policy_attr'] + }, + { + groupname => 'groups', + header => "Group Resources", + desc => "The URI list which can be used to create, query, change and manage group objects.", + resources => ['all_groups','group_allattr','group_attr', + ] + }, + { + groupname => 'globalconf', + header => "Global Configuration Resources", + desc => "The URI list which can be used to create, query, change global configuration.", + resources => ['all_site', 'site'] + }, + { + groupname => 'services', + header => "Service Resources", + desc => "The URI list which can be used to manage the host, dns and dhcp services on xCAT MN.", + resources => ['dns','dhcp','host', 'slpnodes', 'specific_slpnodes',] + }, + { + groupname => 'tables', + header => "Table Resources", + desc => "URI list which can be used to create, query, change table entries.", + resources => ['table_nodes', 'table_nodes_attrs', 'table_all_rows', 'table_rows', 'table_rows_attrs'] + }, +); + +my %formathdl = ( + text => \&outtext, + wiki => \&outwiki, +); + + +my @errmsg; + +sub outtext { + my $def = shift; + my $opt = shift; + my $res = shift; + + if ($res) { + if (defined ($res->{'desc'})) { + print "\n$res->{'desc'}\n"; + } + foreach (1..10) { + if (defined ($res->{'desc'.$_})) { + print $res->{'desc'.$_}."\n"; + } + } + } + + + my $postfix = "?userName=root&password=cluster&pretty=1"; + + if (defined ($def->{desc})) { + print " $opt - $def->{desc}\n"; + } + foreach (1..10) { + if (defined ($def->{'desc'.$_})) { + print " ".$def->{'desc'.$_}."\n"; + } + } + + if (defined ($def->{usage})) { + my @parts = split ('\|', $def->{usage}); + if ($parts[1]) { + print " Parameters: $parts[1]\n"; + } + if ($parts[2]) { + print " Returns: $parts[2]\n"; + } + } + my @example_array = (); + if (defined($def->{example})) { + push @example_array, $def->{example}; + } else { + foreach (1..10) { + if (defined($def->{'example'.$_})) { + push @example_array, $def->{'example'.$_}; + } + } + } + if (@example_array) { + foreach my $line (@example_array) { + my @parts = split ('\|', $line); + print " Example:\n"; + + if ($parts[1]) { + print " $parts[1]\n"; + } else { + push @errmsg, "Error format in:[".$def->{desc}."]\n"; + } + + if ($parts[2] && $parts[3] && ($parts[4] || $opt ne "GET")) { + my ($uri, $data); + if ($parts[3] =~ /\s+/) { + ($uri, $data) = split(/ /, $parts[3]); + print " #curl -X $parts[2] -k \'https://127.0.0.1/xcatws$uri$postfix\' -H Content-Type:application/json --data \'$data\'\n"; + } else { + print " #curl -X $parts[2] -k \'https://127.0.0.1/xcatws$parts[3]$postfix\'\n"; + } + $parts[4] =~ s/\n/\n /g; + print " $parts[4]\n"; + } else { + push @errmsg, "Error format in:[".$def->{desc}."]\n"; + } + } + } else { + push @errmsg, "Error format in:[".$def->{desc}."]\n"; + } +} + +sub outwiki { + my $def = shift; + my $opt = shift; + my $res = shift; + + if ($res) { + if (defined ($res->{'desc'})) { + print "===$res->{'desc'}===\n"; + } + foreach (1..10) { + if (defined ($res->{'desc'.$_})) { + print $res->{'desc'.$_}."\n\n"; + } + } + } + + my $postfix = "?userName=root&password=cluster&pretty=1"; + + if (defined ($def->{desc})) { + print "===='''$opt - $def->{desc}'''====\n"; + } + foreach (1..10) { + if (defined ($def->{'desc'.$_})) { + print $def->{'desc'.$_}."\n\n"; + } + } + + if (defined ($def->{cmd})) { + my $manpath = search_manpage($def->{cmd}); + + if ($manpath) { + print "Refer to the man page:[http://xcat.sourceforge.net".$manpath.".html ".$def->{cmd}."]\n\n"; + } else { + print "Refer to the man page of ".$def->{cmd}." command.\n\n"; + } + + } + + if (defined ($def->{usage})) { + my @parts = split ('\|', $def->{usage}); + if ($parts[1]) { + print "'''Parameters:'''\n\n*$parts[1]\n"; + } + if ($parts[2]) { + print "'''Returns:'''\n\n*$parts[2]\n"; + } + } + + my @example_array = (); + if (defined($def->{example})) { + push @example_array, $def->{example}; + } else { + foreach (1..10) { + if (defined($def->{'example'.$_})) { + push @example_array, $def->{'example'.$_}; + } + } + } + + if (@example_array) { + foreach my $line (@example_array) { + my @parts = split ('\|', $line); + print "'''Example:'''\n\n"; + + if ($parts[1]) { + print "$parts[1]\n"; + } else { + push @errmsg, "Error format for:[".$def->{desc}."]\n"; + } + + if ($parts[2] && $parts[3] && ($parts[4] || $opt ne "GET")) { + my ($uri, $data); + if ($parts[3] =~ /\s+/) { + ($uri, $data) = split(/ /, $parts[3]); + print " #curl -X $parts[2] -k \'https://127.0.0.1/xcatws$uri$postfix\' -H Content-Type:application/json --data \'$data\'\n"; + } else { + print " #curl -X $parts[2] -k \'https://127.0.0.1/xcatws$parts[3]$postfix\'\n"; + } + $parts[4] =~ s/\n/\n /g; + print " $parts[4]\n"; + } else { + push @errmsg, "Error format for:[".$def->{desc}."]\n"; + } + } + } else { + push @errmsg, "Error format for:[".$def->{desc}."]\n"; + } +} + + +sub search_manpage { + my $cmd = shift; + + if (-d "/opt/xcat/share/man") { + my $run = "cd /opt/xcat/share/man; find . | grep \'$cmd\\.\'"; + my @output = `$run`; + if (@output) { + $output[0] =~ s/^\.//; + chomp($output[0]); + return $output[0]; + } + } + + return undef; +} + +sub gendoc { + my $URIdef = shift; + my $format = shift; + + unless ($format) { + $format = "text"; + } + + + foreach my $group (@apigroups) { + my $groupname = $group->{'groupname'}; + if (defined ($URIdef->{$groupname})) { + # display the head of resource group + if ($format eq "text") { + print "############################################\n"; + print "##########".$group->{'header'}."\n"; + print $group->{'desc'}."\n"; + print "############################################\n"; + } elsif ($format eq "wiki") { + print "==".$group->{'header'}."==\n"; + print $group->{'desc'}."\n"; + } + foreach my $res (@{$group->{'resources'}}) { + if (defined ($URIdef->{$groupname}->{$res})) { + my $headdone; + if (defined ($URIdef->{$groupname}->{$res}->{GET})) { + $formathdl{$format}->($URIdef->{$groupname}->{$res}->{GET}, "GET", $URIdef->{$groupname}->{$res}); + $headdone = 1; + } + if (defined ($URIdef->{$groupname}->{$res}->{PUT})) { + if ($headdone) { + $formathdl{$format}->($URIdef->{$groupname}->{$res}->{PUT}, "PUT"); + } else { + $formathdl{$format}->($URIdef->{$groupname}->{$res}->{PUT}, "PUT", $URIdef->{$groupname}->{$res}); + } + $headdone = 1; + } + if (defined ($URIdef->{$groupname}->{$res}->{POST})) { + if ($headdone) { + $formathdl{$format}->($URIdef->{$groupname}->{$res}->{POST}, "POST"); + } else { + $formathdl{$format}->($URIdef->{$groupname}->{$res}->{POST}, "POST", $URIdef->{$groupname}->{$res}); + } + } + if (defined ($URIdef->{$groupname}->{$res}->{DELETE})) { + $formathdl{$format}->($URIdef->{$groupname}->{$res}->{DELETE}, "DELETE"); + } + } else { + push @errmsg, "Cannot find the definition for resource [$res]\n"; + } + } + } else { + push @errmsg, "Cannot find the definition for resource group [$groupname]\n"; + } + } + + if (@errmsg) { + print "\n\n\n================= Error Messages ===================\n"; + print @errmsg; + } +} + +1; diff --git a/xCAT-server/xCAT-wsapi/xcatws-test.sh b/xCAT-server/xCAT-wsapi/xcatws-test.sh new file mode 100755 index 000000000..cbf8ebb4f --- /dev/null +++ b/xCAT-server/xCAT-wsapi/xcatws-test.sh @@ -0,0 +1,197 @@ +#! /bin/sh + + +# Get all the parameters +for i in $@ +do + if [ "$paramname" = "USER" ]; then + USER=$i + paramname= + fi + if [ "$paramname" = "PW" ]; then + PW=$i + paramname= + fi + if [ "$paramname" = "HOST" ]; then + HOST=$i + paramname= + fi + + if [ $i = '-u' ]; then + paramname=USER + fi + if [ $i = '-p' ]; then + paramname=PW + fi + if [ $i = '-h' ]; then + paramname=HOST + fi + if [ $i = '-c' ]; then + cert=yes + fi + if [ $i = '-t' ]; then + token=yes + fi + +done + +# display the usage message +function usage { + echo "Usage:" + echo " xcatws-test.sh -u -p [-t]" + echo " xcatws-test.sh -u -p -h [-c] [-t]" + echo " -u The username of xCAT user which is used to access xCAT resource" + echo " -p The password of username" + echo " The fully qualified hostname of xCAT management node. It can be an IP if using -k." + echo " -c Check the server identity. The server certificate authentication must be enabled." + echo " -t Using token authentication method." +} + +if [ "$USER" = "" ] || [ "$PW" = "" ]; then + echo "Error: Miss username or password" + usage + exit 1 +fi + +if [ "$cert" = "yes" ] && [ "$HOST" = "" ]; then + echo "Error: -c must be used with -h that user needs specify the FQDN of xCAT MN" + usage + exit 1 +fi + +if [ "$HOST" = "" ]; then + HOST="127.0.0.1" +fi + + +ctype='-H Content-Type:application/json' + +# Perform the REST API request +function REST { + METHOD=$1 # it should be GET/PUT/POST/DELETE + SRC=$2 # The resource path like /nodes/node1 + DATA=$3 # The operation data for PUT/POST/DELETE + if [ "$DATA" != "" ]; then + datamsg="$ctype -d $DATA" + fi + if [ "$cert" = "yes" ]; then + if [ "$token" = "yes" ]; then + CMD="curl -X $METHOD --cacert /tmp/ca-cert.pem -H X-Auth-Token:$TOKENID $datamsg https://$HOST/xcatws$SRC?pretty=1" + else + CMD="curl -X $METHOD --cacert /tmp/ca-cert.pem $datamsg https://$HOST/xcatws$SRC?pretty=1&userName=$USER&password=$PW" + fi + else + if [ "$token" = "yes" ]; then + CMD="curl -X $METHOD -k -H X-Auth-Token:$TOKENID $datamsg https://$HOST/xcatws$SRC?pretty=1" + else + CMD="curl -X $METHOD -k $datamsg https://$HOST/xcatws$SRC?pretty=1&userName=$USER&password=$PW" + fi + fi + + echo "-------------------------------------------------------------------------------" + echo "Run: [$RESTMSG]" + echo " $CMD" + echo "Output:" + `$CMD 2>/dev/null >/tmp/xcatws-test.log` + cat "/tmp/xcatws-test.log" + echo "" + + ERROR=`grep "errorcode" "/tmp/xcatws-test.log"` + if [ "$ERROR" != "" ]; then + echo "FAILED to continue. See the error message in 'error' section." + echo "" + exit 2 + fi +} + +function PUT { + SRC=$1 +} + +# echo debug message +echo "***********************************************************" +echo "** Username: $USER" +echo "** Password: $PW" +echo "** Hostname: $HOST" + + +# get the CA of server certificate +if [ "$cert" = "yes" ]; then + rm -f /tmp/ca-cert.pem + cd /tmp + wget http://$HOST/install/postscripts/ca/ca-cert.pem 2>1 1>/dev/null + echo "** Using CA /tmp/ca-cert.pem for server certificate checking" +fi + +# get a token +if [ "$token" = "yes" ]; then + TOKENID=$(curl -X POST -k "https://$HOST/xcatws/tokens?pretty=1" -H Content-Type:application/json --data "{\"userName\":\"$USER\",\"password\":\"$PW\"}" 2>/dev/null | grep '"id"' | awk -F: {'print $2'} | awk -F \" {'print $2'}) + echo "** Using Token: $TOKENID to authenticate" +fi + +echo "***********************************************************" +echo "" + +# clean the env +rmdef -t node restapinode[1-9] 1>/dev/null 2>1 +rmdef -t group restapi 1>/dev/null 2>1 + +# get all resources +RESTMSG="Get all available resource" +REST GET "/" + +# test global conf +RESTMSG="Get all global configuration resource" +REST GET "/globalconf" + +RESTMSG="Change the global configuration domain to cluster.com" +REST PUT "/globalconf/attrs/domain" '{"domain":"cluster.com"}' + +RESTMSG="Get the global configuration domain" +REST GET "/globalconf/attrs/domain" + +# test node create/change/list/delete +RESTMSG="Create node restapinode1" +REST POST "/nodes/restapinode1" '{"groups":"restapi","arch":"x86_64","mgt":"ipmi","netboot":"xnba"}' + +RESTMSG="Display the node restapinode1" +REST GET "/nodes/restapinode1" + +RESTMSG="Change the attributes for node restapinode1" +REST PUT "/nodes/restapinode1" '{"mgt":"fsp","netboot":"yaboot"}' + +RESTMSG="Display the node restapinode1" +REST GET "/nodes/restapinode1" + +RESTMSG="Delete node restapinode1" +REST DELETE "/nodes/restapinode1" + +# test multiple nodes manipulation +RESTMSG="Create node restapinode1 and restapinode2" +REST POST "/nodes/restapinode1,restapinode2" '{"groups":"restapi","arch":"x86_64","mgt":"ipmi","netboot":"xnba"}' + +RESTMSG="Display the node restapinode1 and restapinode2" +REST GET "/nodes/restapinode1,restapinode2" + +RESTMSG="Change the attributes for node restapinode1 and restapinode2" +REST PUT "/nodes/restapinode1,restapinode2" '{"mgt":"hmc","netboot":"grub2"}' + +RESTMSG="Display the node restapinode1 and restapinode2" +REST GET "/nodes/restapinode1,restapinode2" + +RESTMSG="Display all the nodes in the cluster" +REST GET "/nodes" + +# test group +RESTMSG="Display the group restapi" +REST GET "/groups/restapi" + +RESTMSG="Change attributes for group restapi" +REST PUT "/groups/restapi" '{"os":"rh7"}' + +RESTMSG="Display the group restapi" +REST GET "/groups/restapi" + +RESTMSG="Display the nodes in group restapi" +REST GET "/nodes/restapi" + diff --git a/xCAT-server/xCAT-wsapi/xcatws.cgi b/xCAT-server/xCAT-wsapi/xcatws.cgi index 0694bbc94..c63a2b164 100755 --- a/xCAT-server/xCAT-wsapi/xcatws.cgi +++ b/xCAT-server/xCAT-wsapi/xcatws.cgi @@ -1,35 +1,1115 @@ #!/usr/bin/perl +# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html use strict; -use CGI qw/:standard/; -use JSON; # require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON +use CGI qw/:standard/; #todo: remove :standard when the code only uses object oriented interface use Data::Dumper; -#added the line: -#ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi -#to /etc/httpd/conf/httpd.conf to hid the cgi-bin and .cgi extension in the uri +#talk to the server +use Socket; +use IO::Socket::INET; +use IO::Socket::SSL; + +# The hash %URIdef defines all the xCAT resources which can be access from Web Service. +# This script will be called when a https request with the URI started with /xcatws/ is sent to xCAT Web Service +# Inside this script: +# 1. The main body parses the URI and parameters +# 2. Base on the URI, go through the %URIdef to find the matched resource by the 'matcher' which is defined for each resource +# 3. Call the 'fhandler' which is defined in the resource to communicate with xcatd and get the xml response +# 3.1 The 'fhandler' generates the xml request base on the resource, parameters and http method 'GET|PUT|POST|DELETE', sends to xcatd and then get the xml response +# 4. Call the 'outhdler' which is defined in the resource to parse the xml response and translate it to JSON format +# 5. Output the http response to STDOUT # -# also upgraded CGI to 3.52 +# Refer to the $URIdef{node}->{allnode} and $URIdef{node}->{nodeallattr} for your new created resource definition. +# +# |--node - Resource Group +# | `--allnode - Resource Name +# | `--desc - Description for the Resource +# | `--desc[1..10] - Additional description for the Resource +# | `--matcher - The matcher which is used to match the URI to the Resource +# | `--GET - The info is used to handle the GET request +# | `--desc - Description for the GET operation +# | `--desc[1..10] - Additional description for the GET operation +# | `--usage - Usage message. The format must be '|Parameters for the GET request|Returns for the GET request|'. The message in the '|' can be black, but the delimiter '|' must be kept. +# | `--example - Example message. The format must be '|Description|GET|URI PUT/POST_data|Return Msg|'. The messages in the four sections must be completed. +# | `--cmd - The xCAT command line coammnd which will be used to complete the request. It's not a must have attribute. +# | `--fhandler - The call back subroutine which is used to handle the GET request. Generally, it parses the parameters from request and then call xCAT command. This subroutine can be exclusive or shared. +# | `--outhdler - The call back subroutine which is used to handle the GET request. Generally, it parses the xml output from the 'fhandler' and then format the output to JSON. This subroutine can be exclusive or shared. +# | `--PUT - The info is used to handle the PUT request +# | `--POST - The info is used to handle the POST request +# | `--DELETE - The info is used to handle the DELETE request -#take the JSON or XML and put it into a data structure -#all data input will be done from the common structure +# The common messages which can be used in the %URIdef +my %usagemsg = ( + objreturn => "Json format: An object which includes multiple \' : {att:value, attr:value ...}\' pairs.", + objchparam => "Json format: An object which includes multiple \'att:value\' pairs.", + non_getreturn => "No output when execution is successfull. Otherwise output the error information in the Standard Error Format: {error:[msg1,msg2...],errocode:errornum}." +); -#turn on or off the debugging output -my $DEBUGGING = 0; -my $VERSION = "2.8"; +my %URIdef = ( + #### definition for node resources + nodes => { + allnode => { + desc => "[URI:/nodes] - The node list resource.", + desc1 => "This resource can be used to display all the nodes which have been defined in the xCAT database.", + matcher => '^/nodes$', + GET => { + desc => "Get all the nodes in xCAT.", + desc1 => "The attributes details for the node will not be displayed.", + usage => "||Json format: An array of node names.|", + example => "|Get all the node names from xCAT database.|GET|/nodes|[\n \"node1\",\n \"node2\",\n \"node3\",\n]|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout_remove_appended_type, + } + }, + nodeallattr => { + desc => "[URI:/nodes/{noderange}] - The node resource", + matcher => '^/nodes/[^/]*$', + GET => { + desc => "Get all the attibutes for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the attibutes for node \'node1\'.|GET|/nodes/node1|{\n \"node1\":{\n \"profile\":\"compute\",\n \"netboot\":\"xnba\",\n \"arch\":\"x86_64\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\",\n ...\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + PUT => { + desc => "Change the attibutes for the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Change the attributes mgt=dfm and netboot=yaboot.|PUT|/nodes/node1 {\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + POST => { + desc => "Create the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Create a node with attributes groups=all, mgt=dfm and netboot=yaboot|POST|/nodes/node1 {\"groups\":\"all\",\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||", + cmd => "mkdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the node {noderange}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete the node node1|DELETE|/nodes/node1||", + cmd => "rmdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + }, + nodeattr => { + desc => "[URI:/nodes/{noderange}/attrs/{attr1,attr2,attr3 ...}] - The attributes resource for the node {noderange}", + matcher => '^/nodes/[^/]*/attrs/\S+$', + GET => { + desc => "Get the specific attributes for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the attributes {groups,mgt,netboot} for node node1|GET|/nodes/node1/attrs/groups,mgt,netboot|{\n \"node1\":{\n \"netboot\":\"xnba\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + PUT_backup => { + desc => "Change attributes for the node {noderange}. DataBody: {attr1:v1,att2:v2,att3:v3 ...}.", + usage => "||An array of node objects.|", + example => "|Get the attributes {groups,mgt,netboot} for node node1|GET|/nodes/node1/attrs/groups;mgt;netboot||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + } + }, + nodestat => { + desc => "[URI:/nodes/{noderange}/nodestat}] - The attributes resource for the node {noderange}", + matcher => '^/nodes/[^/]*/nodestat$', + GET => { + desc => "Get the running status for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the running status for node node1|GET|/nodes/node1/nodestat|x|", + cmd => "nodestat", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + }, + nodehost => { + desc => "[URI:/nodes/{noderange}/host] - The mapping of ip and hostname for the node {noderange}", + matcher => '^/nodes/[^/]*/host$', + POST => { + desc => "Create the mapping of ip and hostname record for the node {noderange}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Create the mapping of ip and hostname record for node \'node1\'.|POST|/nodes/node1/host||", + cmd => "makehosts", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + }, + nodedns => { + desc => "[URI:/nodes/{noderange}/dns] - The dns record resource for the node {noderange}", + matcher => '^/nodes/[^/]*/dns$', + POST => { + desc => "Create the dns record for the node {noderange}.", + desc1 => "The prerequisite of the POST operation is the mapping of ip and noderange for the node has been added in the /etc/hosts.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Create the dns record for node \'node1\'.|POST|/nodes/node1/dns||", + cmd => "makedns", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the dns record for the node {noderange}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete the dns record for node node1|DELETE|/nodes/node1/dns||", + cmd => "makedns", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + }, + nodedhcp => { + desc => "[URI:/nodes/{noderange}/dhcp] - The dhcp record resource for the node {noderange}", + matcher => '^/nodes/[^/]*/dhcp$', + POST => { + desc => "Create the dhcp record for the node {noderange}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Create the dhcp record for node \'node1\'.|POST|/nodes/node1/dhcp||", + cmd => "makedhcp", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the dhcp record for the node {noderange}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete the dhcp record for node node1|DELETE|/nodes/node1/dhcp||", + cmd => "makedhcp", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + }, + power => { + desc => "[URI:/nodes/{noderange}/power] - The power resource for the node {noderange}", + matcher => '^/nodes/[^/]*/power$', + GET => { + desc => "Get the power status for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the power status.|GET|/nodes/node1/power|{\n \"node1\":{\n \"power\":\"on\"\n }\n}|", + cmd => "rpower", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT => { + desc => "Change power status for the node {noderange}.", + usage => "|Json Formatted DataBody: {action:on/off/reset ...}.|$usagemsg{non_getreturn}|", + example => "|Change the power status to on|PUT|/nodes/node1/power {\"action\":\"on\"}||", + cmd => "rpower", + fhandler => \&actionhdl, + outhdler => \&noout, + } + }, + energy => { + desc => "[URI:/nodes/{noderange}/energy] - The energy resource for the node {noderange}", + matcher => '^/nodes/[^/]*/energy$', + GET => { + desc => "Get all the energy status for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the energy attributes.|GET|/nodes/node1/energy|{\n \"node1\":{\n \"cappingmin\":\"272.3 W\",\n \"cappingmax\":\"354.0 W\"\n ...\n }\n}|", + cmd => "renergy", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT => { + desc => "Change energy attributes for the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {powerattr:value}.|$usagemsg{non_getreturn}|", + example => "|Turn on the cappingstatus to [on]|PUT|/nodes/node1/energy {\"cappingstatus\":\"on\"}||", + cmd => "renergy", + fhandler => \&actionhdl, + outhdler => \&noout, + } + }, + energyattr => { + disable => 1, + desc => "[URI:/nodes/{noderange}/energy/{cappingmaxmin,cappingstatus,cappingvalue ...}] - The specific energy attributes resource for the node {noderange}", + matcher => '^/nodes/[^/]*/energy/\S+$', + GET => { + desc => "Get the specific energy attributes cappingmaxmin,cappingstatus,cappingvalue ... for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the energy attributes which are specified in the URI.|GET|/nodes/node1/energy/cappingmaxmin,cappingstatus|{\n \"node1\":{\n \"cappingmin\":\"272.3 W\",\n \"cappingmax\":\"354.0 W\"\n }\n}|", + cmd => "renergy", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT_backup => { + desc => "Change energy attributes for the node {noderange}. ", + usage => "|$usagemsg{objchparam} DataBody: {powerattr:value}.|$usagemsg{non_getreturn}|", + example => "|Turn on the cappingstatus to [on]|PUT|/nodes/node1/energy {\"cappingstatus\":\"on\"}||", + cmd => "renergy", + fhandler => \&actionhdl, + outhdler => \&noout, + } + }, + serviceprocessor => { + disable => 1, + desc => "[URI:/nodes/{noderange}/sp/{community|ip|netmask|...}] - The attribute resource of service processor for the node {noderange}", + matcher => '^/nodes/[^/]*/sp/\S+$', + GET => { + desc => "Get the specific attributes for service processor resource.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the snmp community for the service processor of node1.|GET|/nodes/node1/sp/community|{\n \"node1\":{\n \"SP SNMP Community\":\"public\"\n }\n}|", + cmd => "rspconfig", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT => { + desc => "Change the specific attributes for the service processor resource. ", + usage => "|$usagemsg{objchparam} DataBody: {community:public}.|$usagemsg{non_getreturn}|", + example => "|Set the snmp community to [mycommunity].|PUT|/nodes/node1/sp/community {\"value\":\"mycommunity\"}||", + cmd => "rspconfig", + fhandler => \&actionhdl, + outhdler => \&noout, + } + }, + macaddress => { + disable => 1, + desc => "[URI:/nodes/{noderange}/mac] - The mac address resource for the node {noderange}", + matcher => '^/nodes/[^/]*/mac$', + GET => { + desc => "Get the mac address for the node {noderange}. Generally, it also updates the mac attribute of the node.", + cmd => "getmacs", + fhandler => \&common, + }, + }, + nextboot => { + desc => "[URI:/nodes/{noderange}/nextboot] - The temporary bootorder resource in next boot for the node {noderange}", + matcher => '^/nodes/[^/]*/nextboot$', + GET => { + desc => "Get the next bootorder.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the bootorder for the next boot. (It's only valid after setting.)|GET|/nodes/node1/nextboot|{\n \"node1\":{\n \"nextboot\":\"Network\"\n }\n}|", + cmd => "rsetboot", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT => { + desc => "Change the next boot order. ", + usage => "|$usagemsg{objchparam} DataBody: {order:net/hd}.|$usagemsg{non_getreturn}|", + example => "|Set the bootorder for the next boot.|PUT|/nodes/node1/nextboot {\"order\":\"net\"}||", + cmd => "rsetboot", + fhandler => \&actionhdl, + outhdler => \&noout, + } + }, + bootorder => { + desc => "[URI:/nodes/{noderange}/bootorder] - The permanent bootorder resource for the node {noderange}", + matcher => '^/nodes/[^/]*/bootorder$', + GET => { + desc => "Get the permanent boot order.", + usage => "|?|?|", + example => "|Get the permanent bootorder for the node1.|GET|/nodes/node1/bootorder|?|", + cmd => "rbootseq", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT => { + desc => "Change the boot order. DataBody: {\"order\":\"net,hd\"}.", + usage => "|Put data: Json formatted order:value pair.|?|", + example => "|Set the permanent bootorder for the node1.|PUT|/nodes/node1/bootorder|?|", + cmd => "rbootseq", + fhandler => \&actionhdl, + outhdler => \&noout, + } + }, + vitals => { + desc => "[URI:/nodes/{noderange}/vitals] - The vitals resources for the node {noderange}", + matcher => '^/nodes/[^/]*/vitals$', + GET => { + desc => "Get all the vitals attibutes.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the vitails attributes for the node1.|GET|/nodes/node1/vitals|{\n \"node1\":{\n \"SysBrd Fault\":\"0\",\n \"CPUs\":\"0\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Drive 15\":\"0\",\n \"SysBrd Vol Fault\":\"0\",\n \"nvDIMM Flash\":\"0\",\n \"Progress\":\"0\"\n ...\n }\n}|", + cmd => "rvitals", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + }, + vitalsattr => { + disable => 1, + desc => "[URI:/nodes/{noderange}/vitals/{temp|voltage|wattage|fanspeed|power|leds...}] - The specific vital attributes for the node {noderange}", + matcher => '^/nodes/[^/]*/vitals/\S+$', + GET => { + desc => "Get the specific vitals attibutes.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the \'fanspeed\' vitals attribute.|GET|/nodes/node1/vitals/fanspeed|{\n \"node1\":{\n \"Fan 1A Tach\":\"3219 RPM\",\n \"Fan 4B Tach\":\"2688 RPM\",\n \"Fan 3B Tach\":\"2560 RPM\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Fan 2A Tach\":\"3293 RPM\",\n \"Fan 1B Tach\":\"2592 RPM\",\n \"Fan 3A Tach\":\"3182 RPM\",\n \"Fan 2B Tach\":\"2592 RPM\"\n }\n}|", + cmd => "rvitals", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + }, + inventory => { + desc => "[URI:/nodes/{noderange}/inventory] - The inventory attributes for the node {noderange}", + matcher => '^/nodes/[^/]*/inventory$', + GET => { + desc => "Get all the inventory attibutes.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the inventory attributes for node1.|GET|/nodes/node1/inventory|{\n \"node1\":{\n \"DIMM 21 \":\"8GB PC3-12800 (1600 MT/s) ECC RDIMM\",\n \"DIMM 1 Manufacturer\":\"Hyundai Electronics\",\n \"Power Supply 2 Board FRU Number\":\"94Y8105\",\n \"DIMM 9 Model\":\"HMT31GR7EFR4C-PB\",\n \"DIMM 8 Manufacture Location\":\"01\",\n \"DIMM 13 Manufacturer\":\"Hyundai Electronics\",\n \"DASD Backplane 4\":\"Not Present\",\n ...\n }\n}|", + cmd => "rinv", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + }, + inventoryattr => { + desc => "[URI:/nodes/{noderange}/inventory/{pci|model...}] - The specific inventory attributes for the node {noderange}", + matcher => '^/nodes/[^/]*/inventory/\S+$', + GET => { + desc => "Get the specific inventory attibutes.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the \'model\' inventory attribute for node1.|GET|/nodes/node1/inventory/model|{\n \"node1\":{\n \"System Description\":\"System x3650 M4\",\n \"System Model/MTM\":\"7915C2A\"\n }\n}|", + cmd => "rinv", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + }, + eventlog => { + desc => "[URI:/nodes/{noderange}/eventlog] - The eventlog resource for the node {noderange}", + matcher => '^/nodes/[^/]*/eventlog$', + GET => { + desc => "Get all the eventlog for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the eventlog for node1.|GET|/nodes/node1/eventlog|{\n \"node1\":{\n \"eventlog\":[\n \"03/19/2014 15:17:58 Event Logging Disabled, Log Area Reset/Cleared (SEL Fullness)\"\n ]\n }\n}|", + cmd => "reventlog", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + DELETE => { + desc => "Clean up the event log for the node {noderange}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete all the event log for node1.|DELETE|/nodes/node1/eventlog|[\n {\n \"eventlog\":[\n \"SEL cleared\"\n ],\n \"name\":\"node1\"\n }\n]|", + cmd => "reventlog", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + }, + beacon => { + desc => "[URI:/nodes/{noderange}/beacon] - The beacon resource for the node {noderange}", + matcher => '^/nodes/[^/]*/beacon$', + GET_backup => { + desc => "Get the beacon status for the node {noderange}.", + cmd => "rbeacon", + fhandler => \&common, + }, + PUT => { + desc => "Change the beacon status for the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {action:on/off/blink}.|$usagemsg{non_getreturn}|", + example => "|Turn on the beacon.|PUT|/nodes/node1/beacon {\"action\":\"on\"}|[\n {\n \"name\":\"node1\",\n \"beacon\":\"on\"\n }\n]|", + cmd => "rbeacon", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + }, + virtualization => { + desc => "[URI:/nodes/{noderange}/virtualization] - The virtualization resource for the node {noderange}", + matcher => '^/nodes/[^/]*/virtualization$', + GET => { + desc => "Get the vm status for the node {noderange}.", + cmd => "lsvm", + fhandler => \&common, + }, + PUT => { + desc => "Change the vm status for the node {noderange}. DataBody: {new:1|clone:1|migrate:1 ...}. new=1 means to run mkvm; clone=1 means to run rclone; migrate=1 means to run rmigrate.", + cmd => "", + fhandler => \&common, + }, + DELETE => { + desc => "Remove the vm node {noderange}.", + cmd => "rmvm", + fhandler => \&common, + }, + }, + updating => { + desc => "[URI:/nodes/{noderange}/updating] - The updating resource for the node {noderange}", + matcher => '^/nodes/[^/]*/updating$', + POST => { + desc => "Update the node with file syncing, software maintenance and rerun postscripts.", + usage => "||An array of messages for performing the node updating.|", + example => "|Initiate an updatenode process.|POST|/nodes/node2/updating|[\n \"There were no syncfiles defined to process. File synchronization has completed.\",\n \"Performing software maintenance operations. This could take a while, if there are packages to install.\n\",\n \"node2: Wed Mar 20 15:01:43 CST 2013 Running postscript: ospkgs\",\n \"node2: Running of postscripts has completed.\"\n]|", + cmd => "updatenode", + fhandler => \&actionhdl, + outhdler => \&infoout, + }, + }, + filesyncing => { + desc => "[URI:/nodes/{noderange}/filesyncing] - The filesyncing resource for the node {noderange}", + matcher => '^/nodes/[^/]*/filesyncing$', + POST => { + desc => "Sync files for the node {noderange}.", + usage => "||An array of messages for performing the file syncing for the node.|", + example => "|Initiate an file syncing process.|POST|/nodes/node2/filesyncing|[\n \"There were no syncfiles defined to process. File synchronization has completed.\"\n]|", + cmd => "updatenode", + fhandler => \&actionhdl, + outhdler => \&infoout, + }, + }, + software_maintenance => { + desc => "[URI:/nodes/{noderange}/sw] - The software maintenance for the node {noderange}", + matcher => '^/nodes/[^/]*/sw$', + POST => { + desc => "Perform the software maintenance process for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Initiate an software maintenance process.|POST|/nodes/node2/sw|{\n \"node2\":[\n \" Wed Apr 3 09:05:42 CST 2013 Running postscript: ospkgs\",\n \" Unable to read consumer identity\",\n \" Postscript: ospkgs exited with code 0\",\n \" Wed Apr 3 09:05:44 CST 2013 Running postscript: otherpkgs\",\n \" ./otherpkgs: no extra rpms to install\",\n \" Postscript: otherpkgs exited with code 0\",\n \" Running of Software Maintenance has completed.\"\n ]\n}|", + cmd => "updatenode", + fhandler => \&actionhdl, + outhdler => \&infoout, + }, + }, + postscript => { + desc => "[URI:/nodes/{noderange}/postscript] - The postscript resource for the node {noderange}", + matcher => '^/nodes/[^/]*/postscript$', + POST => { + desc => "Run the postscripts for the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {scripts:[p1,p2,p3,...]}.|$usagemsg{objreturn}|", + example => "|Initiate an updatenode process.|POST|/nodes/node2/postscript {\"scripts\":[\"syslog\",\"remoteshell\"]}|{\n \"node2\":[\n \" Wed Apr 3 09:01:33 CST 2013 Running postscript: syslog\",\n \" Shutting down system logger: [ OK ]\",\n \" Starting system logger: [ OK ]\",\n \" Postscript: syslog exited with code 0\",\n \" Wed Apr 3 09:01:33 CST 2013 Running postscript: remoteshell\",\n \" Stopping sshd: [ OK ]\",\n \" Starting sshd: [ OK ]\",\n \" Postscript: remoteshell exited with code 0\",\n \" Running of postscripts has completed.\"\n ]\n}|", + cmd => "updatenode", + fhandler => \&actionhdl, + outhdler => \&infoout, + }, + }, + nodeshell => { + desc => "[URI:/nodes/{noderange}/nodeshell] - The nodeshell resource for the node {noderange}", + matcher => '^/nodes/[^/]*/nodeshell$', + POST => { + desc => "Run the command in the shell of the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {command:[cmd1,cmd2]}.|$usagemsg{objreturn}|", + example => "|Run the \'data\' command on the node2.|POST|/nodes/node2/nodeshell {\"command\":[\"date\",\"ls\"]}|{\n \"node2\":[\n \" Wed Apr 3 08:30:26 CST 2013\",\n \" testline1\",\n \" testline2\"\n ]\n}|", + cmd => "xdsh", + fhandler => \&actionhdl, + outhdler => \&infoout, + }, + }, + nodecopy => { + desc => "[URI:/nodes/{noderange}/nodecopy] - The nodecopy resource for the node {noderange}", + matcher => '^/nodes/[^/]*/nodecopy$', + POST => { + desc => "Copy files to the node {noderange}.", + usage => "|$usagemsg{objchparam} DataBody: {src:[file1,file2],target:dir}.|$usagemsg{non_getreturn}|", + example => "|Copy files /tmp/f1 and /tmp/f2 from xCAT MN to the node2:/tmp.|POST|/nodes/node2/nodecopy {\"src\":[\"/tmp/f1\",\"/tmp/f2\"],\"target\":\"/tmp\"}|no output for succeeded copy.|", + cmd => "xdcp", + fhandler => \&actionhdl, + outhdler => \&infoout, + }, + }, + subnodes => { + desc => "[URI:/nodes/{noderange}/subnodes] - The sub-nodes resources for the node {noderange}", + matcher => '^/nodes/[^/]*/subnodes$', + GET => { + desc => "Return the Children nodes for the node {noderange}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the children nodes for node \'node1\'.|GET|/nodes/node1/subnodes|{\n \"cmm01node09\":{\n \"mpa\":\"ngpcmm01\",\n \"parent\":\"ngpcmm01\",\n \"serial\":\"1035CDB\",\n \"mtm\":\"789523X\",\n \"cons\":\"fsp\",\n \"hwtype\":\"blade\",\n \"objtype\":\"node\",\n \"groups\":\"blade,all,p260\",\n \"mgt\":\"fsp\",\n \"nodetype\":\"ppc,osi\",\n \"slotid\":\"9\",\n \"hcp\":\"10.1.9.9\",\n \"id\":\"1\"\n },\n ...\n}|", + cmd => "rscan", + fhandler => \&actionhdl, + outhdler => \&defout, + }, + # the put should be implemented by customer that using GET to get all the resources and define it with PUT /nodes/ + PUT_bak => { + desc => "Update the Children node for the node {noderange}.", + cmd => "rscan", + fhandler => \&common, + }, + }, + bootstate => { + desc => "[URI:/nodes/{noderange}/bootstate] - The boot state resource for node {noderange}.", + matcher => '^/nodes/[^/]*/bootstate$', + GET => { + desc => "Get boot state.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the next boot state for the node1.|GET|/nodes/node1/bootstate|{\n \"node1\":{\n \"bootstat\":\"boot\"\n }\n}|", + cmd => "nodeset", + fhandler => \&actionhdl, + outhdler => \&actionout, + }, + PUT => { + desc => "Set the boot state.", + usage => "|$usagemsg{objchparam} DataBody: {osimage:xxx}/{state:offline}.|$usagemsg{non_getreturn}|", + example => "|Set the next boot state for the node1.|PUT|/nodes/node1/bootstate {\"osimage\":\"rhels6.4-x86_64-install-compute\"}||", + cmd => "nodeset", + fhandler => \&actionhdl, + outhdler => \&noout, + }, + }, -my $q = CGI->new; -my $url = $q->url; -my $pathInfo = $q->path_info; -my $requestType = $ENV{'REQUEST_METHOD'}; -my $queryString = $ENV{'QUERY_STRING'}; -my %queryhash; -my @path = split(/\//, $pathInfo); -shift(@path); -my $resource = $path[0]; -my $pageContent = ''; -my $request = {clienttype => 'ws'}; -#error status codes + # TODO: rflash + }, + + #### definition for group resources + groups => { + all_groups => { + desc => "[URI:/groups] - The group list resource.", + desc1 => "This resource can be used to display all the groups which have been defined in the xCAT database.", + matcher => '^/groups$', + GET => { + desc => "Get all the groups in xCAT.", + desc1 => "The attributes details for the group will not be displayed.", + usage => "||Json format: An array of group names.|", + example => "|Get all the group names from xCAT database.|GET|/groups|[\n \"__mgmtnode\",\n \"all\",\n \"compute\",\n \"ipmi\",\n \"kvm\",\n]|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout_remove_appended_type, + } + }, + group_allattr => { + desc => "[URI:/groups/{groupname}] - The group resource", + matcher => '^/groups/[^/]*$', + GET => { + desc => "Get all the attibutes for the group {groupname}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the attibutes for group \'all\'.|GET|/groups/all|{\n \"all\":{\n \"members\":\"zxnode2,nodexxx,node1,node4\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + PUT => { + desc => "Change the attibutes for the group {groupname}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Change the attributes mgt=dfm and netboot=yaboot.|PUT|/groups/all {\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + }, + group_attr => { + desc => "[URI:/groups/{groupname}/attrs/{attr1,attr2,attr3 ...}] - The attributes resource for the group {groupname}", + matcher => '^/groups/[^/]*/attrs/\S+$', + GET => { + desc => "Get the specific attributes for the group {groupname}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the attributes {mgt,netboot} for group all|GET|/groups/all/attrs/mgt,netboot|{\n \"all\":{\n \"netboot\":\"yaboot\",\n \"mgt\":\"dfm\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + }, + }, + + #### definition for services resources: dns, dhcp, hostname + services => { + host => { + desc => "[URI:/services/host] - The hostname resource.", + matcher => '^/services/host$', + POST => { + desc => "Create the ip/hostname records for all the nodes to /etc/hosts.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Create the ip/hostname records for all the nodes to /etc/hosts.|POST|/services/host||", + cmd => "makehosts", + fhandler => \&nonobjhdl, + outhdler => \&noout, + } + }, + dns => { + desc => "[URI:/services/dns] - The dns service resource.", + matcher => '^/services/dns$', + POST => { + desc => "Initialize the dns service.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Initialize the dns service.|POST|/services/dns||", + cmd => "makedns", + fhandler => \&nonobjhdl, + outhdler => \&noout, + } + }, + dhcp => { + desc => "[URI:/services/dhcp] - The dhcp service resource.", + matcher => '^/services/dhcp$', + POST => { + desc => "Create the dhcpd.conf for all the networks which are defined in the xCAT Management Node.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Create the dhcpd.conf and restart the dhcpd.|POST|/services/dhcp||", + cmd => "makedhcp", + fhandler => \&nonobjhdl, + outhdler => \&noout, + } + }, + # todo: for slpnode, we need use the query attribute to specify the network parameter for lsslp command + slpnodes => { + desc => "[URI:/services/slpnodes] - The nodes which support SLP in the xCAT cluster", + matcher => '^/services/slpnodes', + GET => { + desc => "Get all the nodes which support slp protocol in the network.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the nodes which support slp in the network.|GET|/services/slpnodes|{\n \"ngpcmm01\":{\n \"mpa\":\"ngpcmm01\",\n \"otherinterfaces\":\"10.1.9.101\",\n \"serial\":\"100037A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"2\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"5c:f3:fc:25:da:99\"\n },\n ...\n}|", + cmd => "lsslp", + fhandler => \&nonobjhdl, + outhdler => \&defout, + }, + PUT_bakcup => { + desc => "Update the discovered nodes to database.", + cmd => "lsslp", + fhandler => \&common, + }, + }, + specific_slpnodes => { + desc => "[URI:/services/slpnodes/{CEC|FRAME|MM|IVM|RSA|HMC|CMM|IMM2|FSP...}] - The slp nodes with specific service type in the xCAT cluster", + matcher => '^/services/slpnodes/[^/]*$', + GET => { + desc => "Get all the nodes with specific slp service type in the network.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the CMM nodes which support slp in the network.|GET|/services/slpnodes/CMM|{\n \"ngpcmm01\":{\n \"mpa\":\"ngpcmm01\",\n \"otherinterfaces\":\"10.1.9.101\",\n \"serial\":\"100037A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"2\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"5c:f3:fc:25:da:99\"\n },\n \"Server--SNY014BG27A01K\":{\n \"mpa\":\"Server--SNY014BG27A01K\",\n \"otherinterfaces\":\"10.1.9.106\",\n \"serial\":\"100CF0A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"1\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"34:40:b5:df:0a:be\"\n }\n}|", + cmd => "lsslp", + fhandler => \&nonobjhdl, + outhdler => \&defout, + }, + PUT_backup => { + desc => "Update the discovered nodes to database.", + cmd => "lsslp", + fhandler => \&common, + }, + }, + }, + + #### definition for network resources + networks => { + allnetwork => { + desc => "[URI:/networks] - The network list resource.", + desc1 => "This resource can be used to display all the networks which have been defined in the xCAT database.", + matcher => '^\/networks$', + GET => { + desc => "Get all the networks in xCAT.", + desc1 => "The attributes details for the networks will not be displayed.", + usage => "||Json format: An array of networks names.|", + example => "|Get all the networks names from xCAT database.|GET|/networks|[\n \"network1\",\n \"network2\",\n \"network3\",\n]|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout_remove_appended_type, + }, + POST => { + desc => "Create the networks resources base on the network configuration on xCAT MN.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Create the networks resources base on the network configuration on xCAT MN.|POST|/networks||", + cmd => "makenetworks", + fhandler => \&actionhdl, + }, + }, + network_allattr => { + desc => "[URI:/networks/{netname}] - The network resource", + matcher => '^\/networks\/[^\/]*$', + GET => { + desc => "Get all the attibutes for the network {netname}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the attibutes for network \'network1\'.|GET|/networks/network1|{\n \"network1\":{\n \"gateway\":\"\",\n \"mask\":\"255.255.255.0\",\n \"mgtifname\":\"eth2\",\n \"net\":\"10.0.0.0\",\n \"tftpserver\":\"10.0.0.119\",\n ...\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + PUT => { + desc => "Change the attibutes for the network {netname}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Change the attributes mgtifname=eth0 and net=10.1.0.0.|PUT|/networks/network1 {\"mgtifname\":\"eth0\",\"net\":\"10.1.0.0\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + POST => { + desc => "Create the network {netname}. DataBody: {attr1:v1,att2:v2...}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Create a network with attributes gateway=10.1.0.1, mask=255.255.0.0 |POST|/networks/network1 {\"gateway\":\"10.1.0.1\",\"mask\":\"255.255.0.0\"}||", + cmd => "mkdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the network {netname}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete the network network1|DELETE|/networks/network1||", + cmd => "rmdef", + fhandler => \&defhdl, + outhdler => \&noout + }, + }, + network_attr => { + desc => "[URI:/networks/{netname}/attrs/attr1,attr2,...] - The attributes resource for the network {netname}", + matcher => '^\/networks\/[^\/]*/attrs/\S+$', + GET => { + desc => "Get the specific attributes for the network {netname}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the attributes {groups,mgt,netboot} for network network1|GET|/networks/network1/attrs/gateway,mask,mgtifname,net,tftpserver|{\n \"network1\":{\n \"gateway\":\"9.114.34.254\",\n \"mask\":\"255.255.255.0\",\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + PUT__backup => { + desc => "Change attributes for the network {netname}. DataBody: {attr1:v1,att2:v2,att3:v3 ...}.", + usage => "||An array of network objects.|", + example => "|Get the attributes {gateway,mask,mgtifname,net,tftpserver} for networks network1|GET|/networks/network1/attrs/gateway;mask;net||", + cmd => "chdef", + fhandler => \&noout, + } + }, + + }, + + #### definition for osimage resources + osimages => { + osimage => { + desc => "[URI:/osimages] - The osimage resource.", + matcher => '^\/osimages$', + GET => { + desc => "Get all the osimage in xCAT.", + usage => "||Json format: An array of osimage names.|", + example => "|Get all the osimage names.|GET|/osimages|[\n \"sles11.2-x86_64-install-compute\",\n \"sles11.2-x86_64-install-iscsi\",\n \"sles11.2-x86_64-install-iscsiibft\",\n \"sles11.2-x86_64-install-service\"\n]|", + + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout_remove_appended_type, + }, + POST => { + desc => "Create the osimage resources base on the parameters specified in the Data body.", + #usage => "|$usagemsg{objchparam} DataBody: {iso:isoname\\file:filename\\node:noderange,params:[{attr1:value1,attr2:value2}]}|$usagemsg{non_getreturn}|", + usage => "|$usagemsg{objchparam} DataBody: {iso:isoname\\file:filename,params:[{attr1:value1,attr2:value2}]}|$usagemsg{non_getreturn}|", + example1 => "|Create osimage resources based on the ISO specified|POST|/osimages {\"iso\":\"/iso/RHEL6.4-20130130.0-Server-ppc64-DVD1.iso\"}||", + example2 => "|Create osimage resources based on an xCAT image or configuration file|POST|/osimages {\"file\":\"/tmp/sles11.2-x86_64-install-compute.tgz\"}||", + # TD: the imgcapture need to be moved to nodes/.*/osimages + # example3 => "|Create a image based on the specified Linux diskful node|POST|/osimages {\"node\":\"rhcn1\"}||", + cmd => "copycds", + fhandler => \&imgophdl, + outhdler => \&noout, + }, + }, + osimage_allattr => { + desc => "[URI:/osimages/{imgname}] - The osimage resource", + matcher => '^\/osimages\/[^\/]*$', + GET => { + desc => "Get all the attibutes for the osimage {imgname}.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the attributes for the specified osimage.|GET|/osimages/sles11.2-x86_64-install-compute|{\n \"sles11.2-x86_64-install-compute\":{\n \"provmethod\":\"install\",\n \"profile\":\"compute\",\n \"template\":\"/opt/xcat/share/xcat/install/sles/compute.sles11.tmpl\",\n \"pkglist\":\"/opt/xcat/share/xcat/install/sles/compute.sles11.pkglist\",\n \"osvers\":\"sles11.2\",\n \"osarch\":\"x86_64\",\n \"osname\":\"Linux\",\n \"imagetype\":\"linux\",\n \"otherpkgdir\":\"/install/post/otherpkgs/sles11.2/x86_64\",\n \"osdistroname\":\"sles11.2-x86_64\",\n \"pkgdir\":\"/install/sles11.2/x86_64\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + + POST => { + desc => "Create the osimage {imgname}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2]|$usagemsg{non_getreturn}|", + example => "|Create a osimage obj with the specified parameters.|POST|/osimages/sles11.3-ppc64-install-compute {\"osvers\":\"sles11.3\",\"osarch\":\"ppc64\",\"osname\":\"Linux\",\"provmethod\":\"install\",\"profile\":\"compute\"}||", + cmd => "mkdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + PUT => { + desc => "Change the attibutes for the osimage {imgname}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2...}|$usagemsg{non_getreturn}|", + example => "|Change the 'osvers' and 'osarch' attributes for the osiamge.|PUT|/osimages/sles11.2-ppc64-install-compute/ {\"osvers\":\"sles11.3\",\"osarch\":\"x86_64\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the osimage {imgname}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete the specified osimage.|DELETE|/osimages/sles11.3-ppc64-install-compute||", + cmd => "rmdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + }, + osimage_attr => { + desc => "[URI:/osimages/{imgname}/attrs/attr1,attr2,attr3 ...] - The attributes resource for the osimage {imgname}", + matcher => '^\/osimages\/[^\/]*/attrs/\S+$', + GET => { + desc => "Get the specific attributes for the osimage {imgname}.", + usage => "||Json format: An array of attr:value pairs for the specified osimage.|", + example => "|Get the specified attributes.|GET|/osimages/sles11.2-ppc64-install-compute/attrs/imagetype,osarch,osname,provmethod|{\n \"sles11.2-ppc64-install-compute\":{\n \"provmethod\":\"install\",\n \"osname\":\"Linux\",\n \"osarch\":\"ppc64\",\n \"imagetype\":\"linux\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + # TD, the implementation may need to be change. + PUT_backup => { + desc => "Change the attibutes for the osimage {imgname}.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2...}|$usagemsg{non_getreturn}|", + example => "|Change the 'osvers' and 'osarch' attributes for the osiamge.|PUT|/osimages/sles11.2-ppc64-install-compute/attrs/osvers;osarch {\"osvers\":\"sles11.3\",\"osarch\":\"x86_64\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + + }, + osimage_op => { + desc => "[URI:/osimages/{imgname}/instance] - The instance for the osimage {imgname}", + matcher => '^\/osimages\/[^\/]*/instance$', + POST => { + desc => "Operate the instance of the osimage {imgname}.", + usage => "|$usagemsg{objchparam} DataBody: {action:gen\\pack\\export,params:[{attr1:value1,attr2:value2...}]}|$usagemsg{non_getreturn}|", + example1 => "|Generates a stateless image based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"gen\"}||", + example2 => "|Packs the stateless image from the chroot file system based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"pack\"}||", + example3 => "|Exports an xCAT image based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"export\"}||", + cmd => "", + fhandler => \&imgophdl, + }, + DELETE => { + desc => "Delete the stateless or statelite image instance for the osimage {imgname} from the file system", + usage => "||$usagemsg{non_getreturn}", + example => "|Delete the stateless image for the specified osimage|DELETE|/osimages/sles11.2-x86_64-install-compute/instance||", + cmd => "rmimage", + fhandler => \&imgophdl, + }, + }, + + # todo: genimage, packimage, imagecapture, imgexport, imgimport + }, + + #### definition for policy resources + policy => { + policy => { + desc => "[URI:/policy] - The policy resource.", + matcher => '^\/policy$', + GET => { + desc => "Get all the policies in xCAT.", + desc1 => "It will dislplay all the policy resource.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the policy objects.|GET|/policy|[\n \"1\",\n \"1.2\",\n \"2\",\n \"4.8\"\n]|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout_remove_appended_type, + }, + }, + policy_allattr => { + desc => "[URI:/policy/{policy_priority}] - The policy resource", + matcher => '^\/policy\/[^\/]*$', + GET => { + desc => "Get all the attibutes for a policy {policy_priority}.", + desc1 => "It will display all the policy attributes for one policy resource.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the attribute for policy 1.|GET|/policy/1|{\n \"1\":{\n \"name\":\"root\",\n \"rule\":\"allow\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + PUT => { + desc => "Change the attibutes for the policy {policy_priority}.", + desc1 => "It will change one or more attributes for a policy.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Set the name attribute for policy 3.|PUT|/policy/3 {\"name\":\"root\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + POST => { + desc => "Create the policy {policyname}. DataBody: {attr1:v1,att2:v2...}.", + desc1 => "It will creat a new policy resource.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Create a new policy 10.|POST|/policy/10 {\"name\":\"root\",\"commands\":\"rpower\"}||", + cmd => "chdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the policy {policy_priority}.", + desc1 => "Remove one or more policy resource.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Delete the policy 10.|DELETE|/policy/10||", + cmd => "rmdef", + fhandler => \&defhdl, + outhdler => \&noout, + }, + }, + policy_attr => { + desc => "[URI:/policy/{policyname}/attrs/{attr1,attr2,attr3,...}] - The attributes resource for the policy {policy_priority}", + matcher => '^\/policy\/[^\/]*/attrs/\S+$', + GET => { + desc => "Get the specific attributes for the policy {policy_priority}.", + desc1 => "It will get one or more attributes of a policy.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the name and rule attributes for policy 1.|GET|/policy/1/attrs/name,rule|{\n \"1\":{\n \"name\":\"root\",\n \"rule\":\"allow\"\n }\n}|", + cmd => "lsdef", + fhandler => \&defhdl, + outhdler => \&defout, + }, + }, + }, + #### definition for global setting resources + globalconf => { + all_site => { + desc => "[URI:/globalconf] - The global configuration resource.", + desc1 => "This resource can be used to display all the global configuration which have been defined in the xCAT database.", + matcher => '^\/globalconf$', + GET => { + desc => "Get all the xCAT global configuration.", + desc1=> "It will display all the global attributes.", + usage => "||$usagemsg{objreturn}|", + example => "|Get all the global configuration|GET|/globalconf|{\n \"clustersite\":{\n \"xcatconfdir\":\"/etc/xcat\",\n \"tftpdir\":\"/tftpboot\",\n ...\n }\n}|", + cmd => "lsdef", + fhandler => \&sitehdl, + outhdler => \&defout, + }, + POST_backup => { + desc => "Add the site attributes. DataBody: {attr1:v1,att2:v2...}.", + desc1 => "One or more global attributes could be added/modified.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Add one or more attributes to xCAT database|POST|/globalconf {\"domain\":\"cluster.com\",\"mydomain\":\"mycluster.com\"}||", + cmd => "chdef", + fhandler => \&sitehdl, + }, + }, + site => { + desc => "[URI:/globalconf/attrs/{attr1,attr2 ...}] - The specific global configuration resource.", + matcher => '^\/globalconf/attrs/\S+$', + GET => { + desc => "Get the specific configuration in global.", + desc1 => "It will display one or more global attributes.", + usage => "||$usagemsg{objreturn}|", + example => "|Get the \'master\' and \'domain\' configuration.|GET|/globalconf/attrs/master,domain|{\n \"clustersite\":{\n \"domain\":\"cluster.com\",\n \"master\":\"192.168.1.15\"\n }\n}|", + cmd => "lsdef", + fhandler => \&sitehdl, + outhdler => \&defout, + }, + PUT => { + desc => "Change the global attributes.", + desc1 => "It can be used for changing/adding global attributes.", + usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => "|Change/Add the domain attribute.|PUT|/globalconf/attrs/domain {\"domain\":\"cluster.com\"}||", + cmd => "chdef", + fhandler => \&sitehdl, + outhdler => \&noout, + }, + POST_backup => { + desc => "Create the global configuration entry. DataBody: {name:value}.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Create the domain attribute|POST|/globalconf/attrs/domain {\"domain\":\"cluster.com\"}|?|", + cmd => "chdef", + fhandler => \&sitehdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Remove the site attributes.", + desc1 => "Used for femove one or more global attributes.", + usage => "||$usagemsg{non_getreturn}|", + example => "|Remove the domain configure.|DELETE|/globalconf/attrs/domain||", + cmd => "chdef", + fhandler => \&sitehdl, + outhdler => \&noout, + }, + }, + }, + + #### definition for database/table resources + tables => { + table_nodes => { + desc => "[URI:/tables/{tablelist}/nodes/{noderange}] - The node table resource", + desc1 => "For a large number of nodes, this API call can be faster than using the corresponding nodes resource. The disadvantage is that you need to know the table names the attributes are stored in.", + matcher => '^/tables/[^/]+/nodes/[^/]+$', + GET => { + desc => "Get attibutes of tables for a noderange.", + usage => "||An object containing each table. Within each table object is an array of node objects containing the attributes.|", + example1 => qq(|Get all the columns from table nodetype for node1 and node2.|GET|/tables/nodetype/nodes/node1,node2|{\n \"nodetype\":[\n {\n \"provmethod\":\"rhels6.4-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"provmethod\":\"rhels6.3-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|), + example2 => qq(|Get all the columns from tables nodetype and noderes for node1 and node2.|GET|/tables/nodetype,noderes/nodes/node1,node2|{\n \"noderes\":[\n {\n \"installnic\":\"mac\",\n \"netboot\":\"xnba\",\n \"name\":\"node1\",\n \"nfsserver\":\"192.168.1.15\"\n },\n {\n \"installnic\":\"mac\",\n \"netboot\":\"pxe\",\n \"name\":\"node2\",\n \"proxydhcp\":\"no\"\n }\n ],\n \"nodetype\":[\n {\n \"provmethod\":\"rhels6.4-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"provmethod\":\"rhels6.3-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|), + fhandler => \&tablenodehdl, + outhdler => \&tableout, + }, + PUT => { + desc => "Change the node table attibutes for {noderange}.", + usage => "|A hash of table names and attribute objects. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|", + example => '|Change the nodetype.arch and noderes.netboot attributes for nodes node1,node2.|PUT|/tables/nodetype,noderes/nodes/node1,node2 {"nodetype":{"arch":"x86_64"},"noderes":{"netboot":"xnba"}}||', + fhandler => \&tablenodeputhdl, + outhdler => \&noout, + }, + }, + table_nodes_attrs => { + desc => "[URI:/tables/{tablelist}/nodes/nodes/{noderange}/{attrlist}] - The node table attributes resource", + desc1 => "For a large number of nodes, this API call can be faster than using the corresponding nodes resource. The disadvantage is that you need to know the table names the attributes are stored in.", + matcher => '^/tables/[^/]+/nodes/[^/]+/[^/]+$', + GET => { + desc => "Get table attibutes for a noderange.", + usage => "||An object containing each table. Within each table object is an array of node objects containing the attributes.|", + example => qq(|Get OS and ARCH attributes from nodetype table for node1 and node2.|GET|/tables/nodetype/nodes/node1,node2/os,arch|{\n \"nodetype\":[\n {\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|), + fhandler => \&tablenodehdl, + outhdler => \&tableout, + }, + PUT_backup => { + desc => "[URI:/tables/nodes/{noderange}] - Change the node table attibutes for the {noderange}.", + usage => "|A hash of table names and attribute objects. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|", + example => '|Change the nodehm.mgmt and noderes.netboot attributes for nodes node1-node5.|PUT|/tables/nodes/node1-node5 {"nodehm":{"mgmt":"ipmi"},"noderes":{"netboot":"xnba"}}||', + fhandler => \&tablenodeputhdl, + outhdler => \&noout, + }, + }, + table_all_rows => { + desc => "[URI:/tables/{tablelist}/rows] - The non-node table resource", + desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.", + matcher => '^/tables/[^/]+/rows$', + GET => { + desc => "Get all rows from non-node tables.", + usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|", + example => qq(|Get all rows from networks table.|GET|/tables/networks/rows|{\n \"networks\":[\n {\n \"netname\":\"192_168_13_0-255_255_255_0\",\n \"gateway\":\"192.168.13.254\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.13.0\",\n \"mask\":\"255.255.255.0\"\n },\n {\n \"netname\":\"192_168_12_0-255_255_255_0\",\n \"gateway\":\"192.168.12.254\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.12.0\",\n \"mask\":\"255.255.255.0\"\n },\n ]\n}|), + fhandler => \&tablerowhdl, + outhdler => \&tableout, + }, + }, + table_rows => { + desc => "[URI:/tables/{tablelist}/rows/{keys}] - The non-node table rows resource", + desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.", + desc2 => "{keys} should be the name=value pairs which are used to search table. e.g. {keys} should be [net=192.168.1.0,mask=255.255.255.0] for networks table query since the net and mask are the keys of networks table.", + matcher => '^/tables/[^/]+/rows/[^/]+$', + GET => { + desc => "Get attibutes for rows from non-node tables.", + usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|", + example => qq(|Get row which net=192.168.1.0,mask=255.255.255.0 from networks table.|GET|/tables/networks/rows/net=192.168.1.0,mask=255.255.255.0|{\n \"networks\":[\n {\n \"mgtifname\":\"eth0\",\n \"netname\":\"192_168_1_0-255_255_255_0\",\n \"tftpserver\":\"192.168.1.15\",\n \"gateway\":\"192.168.1.100\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.1.0\",\n \"mask\":\"255.255.255.0\"\n }\n ]\n}|), + fhandler => \&tablerowhdl, + outhdler => \&tableout, + }, + PUT => { + desc => "Change the non-node table attibutes for the row that matches the {keys}.", + usage => "|A hash of attribute names and values. DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + example => '|Create a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet {"net":"10.0.1.0","mask":"255.255.255.0","gateway":"10.0.1.254","ifname":"eth1"}||', + fhandler => \&tablerowputhdl, + outhdler => \&noout, + }, + DELETE => { + desc => "Delete rows from a non-node table that have the attribute values specified in {keys}.", + usage => "||$usagemsg{non_getreturn}|", + example => '|Delete a route row which routename=privnet in the routes table.|DELETE|/tables/routes/rows/routename=privnet||', + fhandler => \&tablerowdelhdl, + outhdler => \&noout, + }, + }, + table_rows_attrs => { + desc => "[URI:/tables/{tablelist}/rows/{keys}/{attrlist}] - The non-node table attributes resource", + desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.", + matcher => '^/tables/[^/]+/rows/[^/]+/[^/]+$', + GET => { + desc => "Get specific attibutes for rows from non-node tables.", + usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|", + example => qq(|Get attributes mgtifname and tftpserver which net=192.168.1.0,mask=255.255.255.0 from networks table.|GET|/tables/networks/rows/net=192.168.1.0,mask=255.255.255.0/mgtifname,tftpserver|{\n \"networks\":[\n {\n \"mgtifname\":\"eth0\",\n \"tftpserver\":\"192.168.1.15\"\n }\n ]\n}|), + fhandler => \&tablerowhdl, + outhdler => \&tableout, + }, + }, + }, + + #### definition for tokens resources + tokens => { + tokens => { + desc => "[URI:/tokens] - The authentication token resource.", + matcher => '^\/tokens', + POST => { + desc => "Create a token.", + usage => "||An array of all the global configuration list.|", + example => "|Aquire a token for user \'root\'.|POST|/tokens {\"userName\":\"root\",\"password\":\"cluster\"}|{\n \"token\":{\n \"id\":\"a6e89b59-2b23-429a-b3fe-d16807dd19eb\",\n \"expire\":\"2014-3-8 14:55:0\"\n }\n}|", + fhandler => \&nonobjhdl, + outhdler => \&tokenout, + }, + POST_backup => { + desc => "Add the site attributes. DataBody: {attr1:v1,att2:v2...}.", + usage => "|?|?|", + example => "|?|?|?|?|", + cmd => "chdef", + fhandler => \&sitehdl, + }, + }, + }, +); + +# supported formats +my %formatters = ( + 'json' => \&wrapJson, + #'html' => \&wrapHtml, + #'xml' => \&wrapXml +); + +# error status codes my $STATUS_BAD_REQUEST = "400 Bad Request"; my $STATUS_UNAUTH = "401 Unauthorized"; my $STATUS_FORBIDDEN = "403 Forbidden"; @@ -41,21 +1121,1355 @@ my $STATUS_EXPECT_FAILED = "417 Expectation Failed"; my $STATUS_TEAPOT = "418 I'm a teapot"; my $STATUS_SERVICE_UNAVAILABLE = "503 Service Unavailable"; -#good status codes +# good status codes my $STATUS_OK = "200 OK"; my $STATUS_CREATED = "201 Created"; -#default format -my $format = 'html'; +# Development notes: +# - added this line to /etc/httpd/conf/httpd.conf to hide the cgi-bin and .cgi extension in the uri: +# ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi +# - also upgraded CGI to 3.52 +# - If "Internal Server Error" is returned, look at /var/log/httpd/ssl_error_log +# - can run your cgi script from the cli: http://perldoc.perl.org/CGI.html#DEBUGGING +# This is how the parameters come in: +# GET: url parameters come $q->url_param. There is no put/post data. +# PUT: url parameters come $q->url_param. Put data comes in q->param(PUTDATA). +# POST: url parameters come $q->url_param. Post data comes in q->param(POSTDATA). +# DELETE: ?? + +# Notes from http://perldoc.perl.org/CGI.html: +# %params = $q->Vars; # same as $q->param() except put it in a hash +# @foo = split("\0",$params{'foo'}); +# my $error = $q->cgi_error; #todo: check for errors that occurred while processing user input +# print $q->end_html; #todo: add the tags +# $q->url_param() # gets url options, even when there is put/post data (unlike q->param) + + + +#### Main procedure to handle the REST request + +# To get the HTTP elements through perl CGI module +my $q = CGI->new; +my $pathInfo = $q->path_info; # the resource specification, i.e. everything in the url after xcatws +my $requestType = $q->request_method(); # GET, PUT, POST, PATCH, DELETE +my $userAgent = $q->user_agent(); # the client program: curl, etc. +my @path = split(/\//, $pathInfo); # The uri path like /nodes/node1/... + +# Define the golbal variables which will be used through the handling process +my $pageContent = ''; # Global var containing the ouptut back to the rest client +my $request = {clienttype => 'ws'}; # Global var that holds the request to send to xcatd +my $format = 'json'; # The output format for a request invoke +my $xmlinstalled; # Global var to speicfy whether the xml modules have been loaded + +# To easy the perl debug, this script can be run directly with 'perl -d' +# This script also support to generate the rest api doc automatically. +# Following part of code will not be run when this script is called by http server +my $dbgdata; +sub dbgusage { print "Usage:\n $0 -h\n $0 -g [wiki] (generate document)\n $0 {GET|PUT|POST|DELETE} URI user:password \'{data}\'\n"; } + +if ($ARGV[0] eq "-h") { + dbgusage(); + exit 0; +} elsif ($ARGV[0] eq "-g") { + # generate the document + require genrestapidoc; + if (defined ($ARGV[1])) { + genrestapidoc::gendoc(\%URIdef, $ARGV[1]); + } else { + genrestapidoc::gendoc(\%URIdef); + } + exit 0; +} elsif ($ARGV[0] eq "-d") { + displayUsage(); + exit 0; +} elsif ($ARGV[0] =~ /(GET|PUT|POST|DELETE)/) { + # parse the parameters when run this script locally + $requestType = $ARGV[0]; + $pathInfo= $ARGV[1]; + + unless ($pathInfo) { dbgusage(); exit 1; } + + if ($ARGV[2] =~ /(.*):(.*)/) { + $ENV{userName} = $1; + $ENV{password} = $2; + } else { + dbgusage(); + exit 0; + } + $dbgdata = $ARGV[3] if defined ($ARGV[3]); +} elsif (defined ($ARGV[0])) { + dbgusage(); + exit 1; +} + +my $JSON; # global ptr to the json object. Its set by loadJSON() +# Since the json is the only supported format, load it at beginning +# need to do this early, so we can fetch the PUT/POST params +loadJSON(); + +# the input parameters from both the url and put/post data will be combined and then +# separated into the general params (not specific to the api call) and params specific to the call +# Note: some of the values of the params in the hash can be arrays +# $generalparams - the general parameters like 'debug=1', 'pretty=1' +# $paramhash - all parameters that come from the url or put/post data except the ones that are put in $generalparams +my ($generalparams, $paramhash) = fetchParameters(); + +my $DEBUGGING = $generalparams->{debug}; # turn on or off the debugging output by setting debug=1 (or 2) in the url string +if ($DEBUGGING) { + displaydebugmsg(); +} + +# The filter flag is used to group the nodes which have the same output +my $XCOLL = $generalparams->{xcoll}; + +# Process the format requested +$format = $generalparams->{format} if (defined ($generalparams->{format})); + +# Remove the last '/' in the pathInfo +$pathInfo =~ s/\/$//; + +# Get the payload format from the end of URI +#if ($pathInfo =~ /\.json$/) { +# $format = "json"; +# $pathInfo =~ s/\.json$//; +#} elsif ($pathInfo =~ /\.json.pretty$/) { +# $format = "json"; +# $pretty = 1; +# $pathInfo =~ s/\.json.pretty$//; +#} elsif ($pathInfo =~ /\.xml$/) { +# $format = "xml"; +# $pathInfo =~ s/\.xml$//; +#} elsif ($pathInfo =~ /\.html$/) { +# $format = "html"; +# $pathInfo =~ s/\.html$//; +#} + +#if (!exists $formatters{$format}) { +# error("The format '$format' is not supported",$STATUS_BAD_REQUEST); +#} + +if ($format eq 'json') { + # make the output to be readable if 'pretty=1' is specified + if ($generalparams->{pretty}) { $JSON->indent(1); } +} + +# we need XML all the time to send request to xcat, even if thats not the return format requested by the user +loadXML(); + +# The first layer of resource URI. It should be 'nodes' for URI '/nodes/node1' +my $uriLayer1; + +# Get all the layers in the URI +my @layers = split('\/', $pathInfo); +shift (@layers); + +if ($#layers < 0) { + # If no resource was specified, list all the resource groups which have been defined in the %URIdef + my $json; + foreach (sort keys %URIdef) { + push @{$json}, $_; + } + if ($json) { + addPageContent($JSON->encode($json)); + } + sendResponseMsg($STATUS_OK); # this will also exit +} else { + $uriLayer1 = $layers[0]; +} + +# set the user and password to access xcatd +$request->{becomeuser}->[0]->{username}->[0] = $ENV{userName} if (defined($ENV{userName})); +$request->{becomeuser}->[0]->{username}->[0] = $generalparams->{userName} if (defined($generalparams->{userName})); +$request->{becomeuser}->[0]->{password}->[0] = $ENV{password} if (defined($ENV{password})); +$request->{becomeuser}->[0]->{password}->[0] = $generalparams->{password} if (defined($generalparams->{password})); + +# use the token if it is specified with X_AUTH_TOKEN head +$request->{tokens}->[0]->{tokenid}->[0] = $ENV{'HTTP_X_AUTH_TOKEN'} if (defined($ENV{'HTTP_X_AUTH_TOKEN'})); + +# find and invoke the correct handler and output handler functions +my $outputdata; +my $handled; +if (defined ($URIdef{$uriLayer1})) { + # Make sure the resource has been defined + foreach my $res (keys %{$URIdef{$uriLayer1}}) { + my $matcher = $URIdef{$uriLayer1}->{$res}->{matcher}; + if ($pathInfo =~ m|$matcher|) { + # matched to a resource + unless (defined ($URIdef{$uriLayer1}->{$res}->{$requestType})) { + error("request method '$requestType' is not supported on resource '$pathInfo'", $STATUS_NOT_ALLOWED); + } + if (defined ($URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler})) { + my $params; + + $params->{'cmd'} = $URIdef{$uriLayer1}->{$res}->{$requestType}->{cmd} if (defined ($URIdef{$uriLayer1}->{$res}->{$requestType}->{cmd})); + $params->{'outputhdler'} = $URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler} if (defined ($URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler})); + $params->{'layers'} = \@layers; + $params->{'resourcegroup'} = $uriLayer1; + $params->{'resourcename'} = $res; + # Call the handler subroutine which specified in 'fhandler' to send request to xcatd and get the response + $outputdata = $URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler}->($params); + # Filter the output data from the response + $outputdata = filterData ($outputdata); + # Restructure the output data with the subroutine which is specified in 'outhdler' + if (defined ($URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler})) { + $outputdata = $URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler}->($outputdata, $params); + } else { + # Call the appropriate formatting function stored in the formatters hash as default output handler + if (exists $formatters{$format}) { + $formatters{$format}->($outputdata); + } + } + + $handled = 1; + last; + } + } + } +} else { + # not matches to any resource group. Check the 'resource group' to improve the performance + error("Unspported resource.",$STATUS_NOT_FOUND); +} + +# the URI cannot match to any resources which are defined in %URIdef +unless ($handled) { + error("Unspported resource.",$STATUS_NOT_FOUND); +} + + +# all output has been added into the global varibale pageContent, call the response funcion to generate HTTP reply and exit + +if (isPost()) { + sendResponseMsg($STATUS_CREATED); +} +else { + sendResponseMsg($STATUS_OK); +} + +#### End of the Main Program + + + + + +#=========================================================== +# Subrutines +sub isGET { return uc($requestType) eq "GET"; } +sub isPost { return uc($requestType) eq "POST"; } +sub isPut { return uc($requestType) eq "PUT"; } +sub isPost { return uc($requestType) eq "POST"; } +sub isPatch { return uc($requestType) eq "PATCH"; } +sub isDelete { return uc($requestType) eq "DELETE"; } + + +#handle the output for def command and rscan +#handle the input like +# ===raw xml input +# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n' +# $d->{data}->[msg list] +# +# ===msg format +# Object name: +# attr=value +#OR +# : +# attr=value +# --- +#TO +# --- +# { : { +# attr : value +# ... +# } ... } +sub defout { + my $data = shift; + + my $json; + foreach my $d (@$data) { + my $nodename; + my $lines; + my @alldata; + if (defined ($d->{info})) { + foreach (@{$d->{info}}) { + push @alldata, split ('\n', $_); + } + $lines = \@alldata; + } elsif (defined ($d->{data})) { + foreach (@{$d->{data}}) { + push @alldata, split ('\n', $_); + } + $lines = \@alldata; + } + foreach my $l (@$lines) { + if ($l =~ /^Object name: / || $l =~ /^\S+:$/) { # start new node + if ($l =~ /^Object name:\s+(\S+)/) { # handle the output of lsdef -t + $nodename = $1; + } + if ($l =~ /^(\S+):$/) { # handle the output for stanza format '-z' + $nodename = $1; + } + } + else { # just an attribute of the current node + if (! $nodename) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); } + my ($attr, $val) = $l =~ /^\s*(\S+)=(.*)$/; + if (!defined($attr)) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); } + $json->{$nodename}->{$attr} = $val; + } + } + } + if ($json) { + addPageContent($JSON->encode($json), 1); + } +} + +#handle the output for lsdef -t command +#handle the input like +# ===raw xml input +# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n' +# +# ===msg format +# node1 (node) +# node2 (node) +# node3 (node) +# --- +#TO +# --- +# node1 +# node2 +# node3 +sub defout_remove_appended_type { + my $data = shift; + + my $json; + foreach my $d (@$data) { + my $jsonnode; + my $lines = $d->{info}; + foreach my $l (@$lines) { + if ($l =~ /^(\S*)\s+\(.*\)$/) { # start new node + push @{$json}, $1; + } + } + } + if ($json) { + addPageContent($JSON->encode($json), 1); + } +} + +# hanlde the output which has the node irrelevant message (e.g. the output for updatenode command) +# handle the input like +# ===raw xml input +# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n' +# $d->{data}->[msg list] +# $d->{data}->{contents}->[msg list] +# +# ===msg format +# "There were no syncfiles defined to process. File synchronization has completed.", +# "Performing software maintenance operations. This could take a while, if there are packages to install.", +# "node2: Tue Apr 2 15:55:57 CST 2013 Running postscript: ospkgs", +# --- +#TO +# --- +# [ +# "There were no syncfiles defined to process. File synchronization has completed.", +# "Performing software maintenance operations. This could take a while, if there are packages to install.", +# "node2: Tue Apr 2 15:55:57 CST 2013 Running postscript: ospkgs", +# ] +# +# An exception is to handle the output of 'xdsh'(nodeshell). Since each msg has a : head, split the head out and group +# the msg with the name in the head. + +sub infoout { + my $data = shift; + my $param =shift; + + my $json; + foreach my $d (@$data) { + if (defined ($d->{info})) { + foreach (@{$d->{info}}) { + push @{$json}, split ('\n', $_); + } + } + if (defined ($d->{data})) { + if (ref($d->{data}->[0]) ne "HASH") { + foreach (@{$d->{data}}) { + push @{$json}, split ('\n', $_); + } + } else { + if (defined($d->{data}->[0]->{contents})) { + push @{$json}, @{$d->{data}->[0]->{contents}}; + } + } + } + if (defined ($d->{error})) { + push @{$json}, @{$d->{error}}; + } + } + + # for nodeshell (xdsh), group msg with node name + if ($param->{'resourcename'} =~ /(nodeshell|postscript|software_maintenance)/) { + my $jsonnode; + foreach (@{$json}) { + if (/^(\S+):(.*)$/) { + push @{$jsonnode->{$1}}, $2 if ($2 !~ /^\s*$/); + } + } + addPageContent($JSON->encode($jsonnode), 1) if ($jsonnode); + return; + } + if ($json) { + addPageContent($JSON->encode($json), 1); + } +} + +# hanlde the output which is node relevant (rpower, rinv, rvitals ...) +# the output must be grouped with 'node' as key +# handle the input like +# ===raw xml input +# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg +# $d->{node}->{data}->[msg] +#OR +# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg +# $d->{node}->{data}->{contents}->[msg] +#OR +# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg +# $d->{node}->{data}->{contents}->[msg] +# $d->{node}->{data}->{desc}->[msg] +# +# Note: if does not have '$d->{node}->{data}->{desc}', use the resource name as the name of attribute. +# e.g. Get /node/node1/power, the record is '"power":"off"' +# +# ===msg format +# +# +# 1.41 (VVE128GUS 2013/07/22) +# UEFI Version +# +# node1 +# +# --- +#TO +# --- +# { +# "node1":{ +# "UEFI Version":"1.41 (VVE128GUS 2013/07/22)", +# } +# } +sub actionout { + my $data = shift; + my $param =shift; + + my $jsonnode; + foreach my $d (@$data) { + unless (defined ($d->{node}->[0]->{name})) { + next; + } + if (defined ($d->{node}->[0]->{data}) && (ref($d->{node}->[0]->{data}->[0]) ne "HASH" || ! defined($d->{node}->[0]->{data}->[0]->{contents}))) { + # no $d->{node}->{data}->{contents} or $d->{node}->[0]->{data} is not hash + $jsonnode->{$d->{node}->[0]->{name}->[0]}->{$param->{'resourcename'}} = $d->{node}->[0]->{data}->[0]; + } elsif (defined ($d->{node}->[0]->{data}->[0]->{contents})) { + if (defined($d->{node}->[0]->{data}->[0]->{desc})) { + # has $d->{node}->{data}->{desc} + $jsonnode->{$d->{node}->[0]->{name}->[0]}->{$d->{node}->[0]->{data}->[0]->{desc}->[0]} = $d->{node}->[0]->{data}->[0]->{contents}->[0]; + } else { + # use resourcename as the record name + if ($param->{'resourcename'} eq "eventlog") { + push @{$jsonnode->{$d->{node}->[0]->{name}->[0]}->{$param->{'resourcename'}}}, $d->{node}->[0]->{data}->[0]->{contents}->[0]; + } else { + $jsonnode->{$d->{node}->[0]->{name}->[0]}->{$param->{'resourcename'}} = $d->{node}->[0]->{data}->[0]->{contents}->[0]; + } + } + } + } + + addPageContent($JSON->encode($jsonnode), 1) if ($jsonnode); +} + +# hanlde the output which has the token id +# handle the input like +# ===raw xml input +# $d->{data}->{token}->{id} +# $d->{data}->{token}->{expire} +sub tokenout { + my $data = shift; + + my $json; + foreach my $d (@$data) { + if (defined ($d->{data}) && defined ($d->{data}->[0]->{token})) { + $json->{token}->{id} = $d->{data}->[0]->{token}->[0]->{id}->[0]; + $json->{token}->{expire} = $d->{data}->[0]->{token}->[0]->{expire}->[0]; + } + } + + if ($json) { + addPageContent($JSON->encode($json)); + } +} + +# This is the general callback subroutine for PUT/POST/DELETE methods +# when this subroutine is called, that means the operation has been done successfully +# The correct output is 'null' +sub noout { + return; +### for debugging + my $data = shift; + + addPageContent(qq(\n\n\n=======================================================\nDebug: Following message is just for debugging. It will be removed in the GAed version.\n)); + + my $json; + if ($data) { + addPageContent($JSON->encode($data)); + } + + addPageContent(qq(["Debug: the operation has been done successfully"])); +### finish the debugging +} + +# The operation callback subroutine for def related resource (lsdef, chdef ...) +# assembe the xcat request, send it to xcatd and get response +sub defhdl { + my $params = shift; + + my @args; + my @urilayers = @{$params->{'layers'}}; + + # set the command name + $request->{command} = $params->{'cmd'}; + + # push the -t args for *def command + my $resrctype = $params->{'resourcegroup'}; + $resrctype =~ s/s$//; # remove the last 's' as the type of object + push @args, ('-t', $resrctype); + + # push the object name - node/noderange + if (defined ($urilayers[1])) { + push @args, ('-o', $urilayers[1]); + } + + # For the put/post which specifies attributes like mgt=ipmi groups=all + foreach my $k (keys(%$paramhash)) { + push @args, "$k=$paramhash->{$k}" if ($k); + } + + if ($params->{'resourcename'} eq "allnode") { + push @args, '-s'; + } elsif ($params->{'resourcename'} =~ /(nodeattr|osimage_attr|group_attr|policy_attr|network_attr)/) { + # if /nodes/node1/attrs/attr1,att2 is specified, for get request, + # use 'lsdef -i' to specify the attribute list + my $attrs = $urilayers[3]; + $attrs =~ s/;/,/g; + + if (isGET()) { + push @args, ('-i', $attrs); + } + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + my $responses = sendRequest($req); + + return $responses; +} + +# The operation callback subroutine for any node related resource (power, energy ...) +# assembe the xcat request, send it to xcatd and get response +sub actionhdl { + my $params = shift; + + my @args; + my @urilayers = @{$params->{'layers'}}; + + # set the command name + $request->{command} = $params->{'cmd'}; + + # push the object name - node/noderange + if (defined ($urilayers[1])) { + $request->{noderange} = $urilayers[1]; + } + + if ($params->{'resourcename'} eq "power") { + if (isGET()) { + push @args, 'stat'; + } elsif ($paramhash->{'action'}) { + #my @v = keys(%$paramhash); + push @args, $paramhash->{'action'}; + } else { + error("Missed Action.",$STATUS_NOT_FOUND); + } + } elsif ($params->{'resourcename'} =~ /(energy|energyattr)/) { + if (isGET()) { + if ($params->{'resourcename'} eq "energy") { + push @args, 'all'; + } elsif ($params->{'resourcename'} eq "energyattr") { + my @attrs = split(',', $urilayers[3]); + push @args, @attrs; + } + } elsif ($paramhash) { + my @params = keys(%$paramhash); + push @args, "$params[0]=$paramhash->{$params[0]}"; + } else { + error("Missed Action.",$STATUS_NOT_FOUND); + } + } elsif ($params->{'resourcename'}eq "bootstate") { + if (isGET()) { + push @args, 'stat'; + } elsif ($paramhash->{'action'}) { + push @args, $paramhash->{'action'}; + } elsif ($paramhash) { + my @params = keys(%$paramhash); + if ($params[0] eq "state") { + # hanlde the {state:offline} + push @args, $paramhash->{$params[0]}; + } else { + # handle the {osimage:imagename} + push @args, "$params[0]=$paramhash->{$params[0]}"; + } + } else { + error("Missed Action.",$STATUS_NOT_FOUND); + } + } elsif ($params->{'resourcename'} eq "nextboot") { + if (isGET()) { + push @args, 'stat'; + } elsif ($paramhash->{'order'}) { + push @args, $paramhash->{'order'}; + } else { + error("Missed Action.",$STATUS_NOT_FOUND); + } + } elsif ($params->{'resourcename'} =~ /(vitals|vitalsattr|inventory|inventoryattr)/) { + if (defined($urilayers[3])) { + my @attrs = split(';', $urilayers[3]); + push @args, @attrs; + } + } elsif ($params->{'resourcename'} eq "serviceprocessor") { + if (isGET()) { + push @args, $urilayers[3]; + } elsif ($paramhash->{'value'}) { + push @args, $urilayers[3]."=".$paramhash->{'value'}; + } + } elsif ($params->{'resourcename'} eq "eventlog") { + if (isGET()) { + push @args, 'all'; + } elsif (isDelete()) { + push @args, 'clear'; + } + } elsif ($params->{'resourcename'} eq "beacon") { + if (isPut()) { + push @args, $paramhash->{'action'}; + } + } elsif ($params->{'resourcename'} eq "filesyncing") { + push @args, '-F'; + } elsif ($params->{'resourcename'} eq "software_maintenance") { + push @args, '-S'; + } elsif ($params->{'resourcename'} eq "postscript") { + push @args, '-P'; + if (defined ($paramhash->{'scripts'})) { + push @args, join (',', @{$paramhash->{'scripts'}}); + } + } elsif ($params->{'resourcename'} eq "nodeshell") { + if (defined ($paramhash->{'command'})) { + if (ref($paramhash->{'command'}) eq "ARRAY") { + push @args, join (';', @{$paramhash->{'command'}}); + } else { + push @args, $paramhash->{'command'}; + } + } else { + error ("Lack of operation data.",$STATUS_BAD_REQUEST,3); + } + } elsif ($params->{'resourcename'} eq "nodecopy") { + if (defined ($paramhash->{'src'})) { + push @args, @{$paramhash->{'src'}}; + } + if (defined ($paramhash->{'target'})) { + push @args, $paramhash->{'target'}; + } + } elsif ($params->{'resourcename'} =~ /(dns|dhcp)/) { + if (isDelete()) { + push @args, '-d'; + } + } elsif ($params->{'resourcename'} eq "subnodes") { + if (isGET()) { + push @args, '-z'; + } + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + my $responses = sendRequest($req); + + return $responses; +} + +# The operation callback subroutine for node irrelevant commands like makedns -n and makedhcp -n +# assembe the xcat request, send it to xcatd and get response +sub nonobjhdl { + my $params = shift; + + my @args; + my @urilayers = @{$params->{'layers'}}; + + # set the command name + $request->{command} = $params->{'cmd'}; + if ($params->{'resourcename'} =~ /(dns|dhcp)/) { + push @args, '-n'; + } elsif ($params->{'resourcename'} eq "slpnodes") { + if (isGET()) { + push @args, '-z'; + } + } elsif ($params->{'resourcename'} eq "specific_slpnodes") { + if (isGET()) { + push @args, "-z"; + push @args, "-s"; + push @args, $urilayers[2]; + } + } elsif ($params->{'resourcename'} eq "tokens") { + $request->{gettoken}->[0]->{username}->[0] = $generalparams->{userName} if (defined($generalparams->{userName})); + $request->{gettoken}->[0]->{password}->[0] = $generalparams->{password} if (defined($generalparams->{password})); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + my $responses = sendRequest($req); + + return $responses; +} + + +# operate image instance for a osimage +sub imgophdl { + my $params = shift; + my @args = (); + if (isPost()) { + if ($params->{'resourcename'} eq "osimage_op") { + my $action = $paramhash->{'action'}; + unless ($action) { + error("Missed Action.",$STATUS_NOT_FOUND); + } elsif ($action eq "gen") { + $params->{'cmd'} = "genimage"; + } elsif ($action eq "pack") { + $params->{'cmd'} = "packimage"; + } elsif ($action eq "export") { + $params->{'cmd'} = "imgexport"; + } else { + error("Incorrect action:$action.",$STATUS_BAD_REQUEST); + } + } elsif ($params->{'resourcename'} eq "osimage") { + if (exists($paramhash->{'iso'})) { + $params->{'cmd'} = "copycds"; + push @{$params->{layers}}, $paramhash->{'iso'}; + } elsif (exists($paramhash->{'file'})) { + $params->{'cmd'} = "imgimport"; + push @{$params->{layers}}, $paramhash->{'file'}; + } elsif (exists($paramhash->{'node'})) { + $params->{'cmd'} = "imgcapture"; + #push @{$params->{layers}}, $paramhash->{'node'}; + push @{$request->{noderange}}, $paramhash->{'node'}; + } else { + error("Invalid source.",$STATUS_NOT_FOUND); + } + } + } + $request->{command} = $params->{'cmd'}; + push @args, $params->{layers}->[1]; + if (exists($paramhash->{'params'})) { + foreach (keys %{$paramhash->{'params'}->[0]}) { + push @args, ($_, $paramhash->{'params'}->[0]->{$_}); + } + } + push @{$request->{arg}}, @args; + my $req = genRequest(); + my $responses = sendRequest($req); + return $responses; +} + +sub sitehdl { + my $params = shift; + my @args; + my @urilayers = @{$params->{'layers'}}; + + # set the command name + $request->{command} = $params->{'cmd'}; + # push the -t args + push @args, '-t'; + push @args, 'site'; + if (isGET()) { + push @args, 'clustersite'; + } + if (defined ($urilayers[2])){ + if (isGET()) { + push @args, ('-i', $urilayers[2]); + } + } + if (isDelete()) { + if (defined ($urilayers[2])){ + push @args, "$urilayers[2]="; + } + } + foreach my $k (keys(%$paramhash)) { + push @args, "$k=$paramhash->{$k}" if ($k); + } + push @{$request->{arg}}, @args; + my $req = genRequest(); + my $responses = sendRequest($req); + + return $responses; +} + + +# get attrs of tables for a noderange +sub tablenodehdl { + my $params = shift; + + my @args; + my @urilayers = @{$params->{'layers'}}; + # the array elements for @urilayers are: + # 0 - 'table' + # 1 - + # 2 - 'nodes' + # 3 - (optional) + # 4 - (optional) + + # set the command name + my @tables = split(/,/, $urilayers[1]); + + if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLNODES') { + $request->{command} = 'getTablesAllNodeAttribs'; + } else { + $request->{command} = 'getTablesNodesAttribs'; + $request->{noderange} = $urilayers[3]; + } + + # For both getTablesAllNodeAttribs and getTablesNodesAttribs, the rest of the request strucutre looks like this: + # table => [ + # { + # tablename => nodehm, + # attr => [ + # mgmt, + # cons + # ] + # }, + # { + # tablename => ipmi, + # attr => [ + # ALL + # ] + # } + # ] + + # if they specified attrs, sort/group them by table + my $attrlist = $urilayers[4]; + if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes + my @attrs = split(/,/, $attrlist); + my %attrhash; + foreach my $a (@attrs) { + if ($a =~ /\./) { + my ($table, $attr) = split(/\./, $a); + push @{$attrhash{$table}}, $attr; + } + else { # the attr doesn't have a table qualifier so apply to all tables + foreach my $t (@tables) { push @{$attrhash{$t}}, $a; } + } + } + + # deal with all of the tables and the attrs for each table + foreach my $tname (@tables) { + my $table = { tablename => $tname }; + if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; } + else { $table->{attr} = 'ALL'; } + push @{$request->{table}}, $table; + } + + + my $req = genRequest(); + # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute + # out of the node hash and make it the key + my $responses = sendRequest($req, {SuppressEmpty => undef, ForceArray => 0, KeyAttr => []}); + + return $responses; +} + + +# get attrs of tables for keys +sub tablerowhdl { + my $params = shift; + + my @args; + my @urilayers = @{$params->{'layers'}}; + # the array elements for @urilayers are: + # 0 - 'table' + # 1 - + # 2 - 'rows' + # 3 - (optional) + # 4 - (optional) + + # do stuff that is common between getAttribs and getTablesAllRowAttribs + my @tables = split(/,/, $urilayers[1]); + my $attrlist = $urilayers[4]; + if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes + my @attrs = split(/,/, $attrlist); + + # get all rows for potentially multiple tables + if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLROWS') { + $request->{command} = 'getTablesAllRowAttribs'; + # For getTablesAllRowAttribs, the rest of the request strucutre needs to look like this: + # table => [ + # { + # tablename => nodehm, + # attr => [ + # mgmt, + # cons + # ] + # }, + # { + # tablename => ipmi, + # attr => [ + # ALL + # ] + # } + # ] + + # if they specified attrs, sort/group them by table + my %attrhash; + foreach my $a (@attrs) { + if ($a =~ /\./) { + my ($table, $attr) = split(/\./, $a); + push @{$attrhash{$table}}, $attr; + } + else { # the attr doesn't have a table qualifier so apply to all tables + foreach my $t (@tables) { push @{$attrhash{$t}}, $a; } + } + } + + # deal with all of the tables and the attrs for each table + foreach my $tname (@tables) { + my $table = { tablename => $tname }; + if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; } + else { $table->{attr} = 'ALL'; } + push @{$request->{table}}, $table; + } + } + + # for 1 table, get just one row based on the keys given + else { + if (scalar(@tables) > 1) { error('currently you can only specify keys for a single table.', $STATUS_BAD_REQUEST); } + $request->{command} = 'getAttribs'; + # For getAttribs, the rest of the request strucutre needs to look like this: + # { + # table => networks, + # keys => { + # net => 11.35.0.0, + # mask => 255.255.0.0 + # } + # attr => [ + # netname, + # dhcpserver + # ] + # }, + $request->{table} = $tables[0]; + if (defined($urilayers[3])) { + my @keyvals = split(/,/, $urilayers[3]); + foreach my $kv (@keyvals) { + my ($key, $value) = split(/\s*=\s*/, $kv, 2); + $request->{keys}->{$key} = $value; + } + } + foreach my $a (@attrs) { push @{$request->{attr}}, $a; } + } + + my $req = genRequest(); + # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute + # out of the node hash and make it the key + my $responses = sendRequest($req, {SuppressEmpty => undef, ForceArray => 0, KeyAttr => []}); + + return $responses; +} + +# parse the output of all attrs of tables for the GET calls. This is used for both node-oriented tables +# and non-node-oriented tables. +#todo: investigate a converter straight from xml to json +sub tableout { + my $data = shift; + my $json = {}; + # For the table get calls, we turned off ForceArray and KeyAttr for XMLin(), so the output is a little + # different than usual. Each element is a hash with key "table" that is either a hash or array of hashes. + # Each element of that is a hash with 2 keys called "tablename" and "node". The latter has either: an array of node hashes, + # or (if there is only 1 node returned) the node hash directly. + # We are producing json that is a hash of table name keys that each have an array of node objects. + foreach my $d (@$data) { + my $table = $d->{table}; + if (!defined($table)) { # special case for the getAttribs cmd + $json->{$request->{table}}->[0] = $d; + last; + } + #debug(Dumper($d)); debug (Dumper($jsonnode)); + if (ref($table) eq 'HASH') { $table = [$table]; } # if a single table, make it a 1 element array of tables + foreach my $t (@$table) { + my $jsonnodes = []; # start an array of node objects for this table + my $tabname = $t->{tablename}; + if (!defined($tabname)) { $tabname = 'unknown' . $::i++; } #todo: have lissa fix this bug + $json->{$tabname} = $jsonnodes; # add it into the top level hash + my $node = $t->{node}; + if (!defined($node)) { $node = $t->{row}; } + #debug(Dumper($d)); debug (Dumper($jsonnode)); + if (ref($node) eq 'HASH') { $node = [$node]; } # if a single node, make it a 1 element array of nodes + foreach my $n (@$node) { push @$jsonnodes, $n; } + } + } + addPageContent($JSON->encode($json)); +} + +# set attrs of nodes in tables +sub tablenodeputhdl { + my $params = shift; + + # from the %URIdef: + # desc => "[URI:/tables/nodes/{noderange}] - Change the table attibutes for the {noderange}.", + # usage => "|An array of table objects. Each table object contains the table name and an object of attribute values. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|", + # example => '|Change the nodehm.mgmt and noderes.netboot attributes for nodes node1-node5.|PUT|/tables/nodes/node1-node5 {"nodehm":{"mgmt":"ipmi"},"noderes":{"netboot":"xnba"}}||', + + my @args; + my @urilayers = @{$params->{'layers'}}; + # the array elements for @urilayers are: + # 0 - 'table' + # 1 - + # 2 - 'nodes' + # 3 - + + # set the command name + $request->{command} = 'setNodesAttribs'; + $request->{noderange} = $urilayers[3]; + + # For setNodesAttribs, the rest of the request strucutre looks like this: + # arg => { + # table => [ + # { + # name => nodehm, + # attr => { + # mgmt => ipmi + # } + # }, + # { + # name => noderes, + # attr => { + # netboot => xnba + # } + # } + # ] + # } + + # Get table list in the URI + my @uritbs = split(/,/, $urilayers[1]); + + # Go thru the list of tables (which are the top level keys in paramhash) + my $tables = []; + $request->{arg}->{table} = $tables; + foreach my $k (keys(%$paramhash)) { + my $intable = $k; + # Check the validity of tables + if (! grep(/^$intable$/, @uritbs)) { + error("The table $intable is NOT in the URI.", $STATUS_BAD_REQUEST); + } + my $attrhash = $paramhash->{$k}; + my $outtable = { name=>$intable, attr=>$attrhash }; + push @$tables, $outtable; + } + + my $req = genRequest(); + # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute + # out of the node hash and make it the key + my $responses = sendRequest($req, {SuppressEmpty => undef, ForceArray => 1, KeyAttr => []}); + + return $responses; +} + +# set attrs of a row in a non-node table +sub tablerowputhdl { + my $params = shift; + + # from %URIdef: + # desc => "[URI:/tables/{table}/rows/{keys}] - Change the non-node table attibutes for the row that matches the {keys}.", + # usage => "|A hash of attribute names and values. DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", + # example => '|Creat a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet {"net":"10.0.1.0","mask":"255.255.255.0","gateway":"10.0.1.254","ifname":"eth1"}||', + + my @args; + my @urilayers = @{$params->{'layers'}}; + # the array elements for @urilayers are: + # 0 - 'table' + # 1 - + # 2 - 'rows' + # 3 - + + # set the command name + $request->{command} = 'setAttribs'; + + # For setAttribs, the rest of the xml request strucutre looks like this: + # routes
+ # + # foo + # + # + # 10.0.1.0 + # This is a test + # + + # set the table name and keys + $request->{table} = $urilayers[1]; + my @keyvals = split(/,/, $urilayers[3]); + foreach my $kv (@keyvals) { + my ($key, $value) = split(/\s*=\s*/, $kv, 2); + $request->{keys}->{$key} = $value; + } + + # the attribute/value hash is already in paramhash + $request->{attr} = $paramhash; + + my $req = genRequest(); + # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute + # out of the node hash and make it the key + my $responses = sendRequest($req, {SuppressEmpty => undef, ForceArray => 1, KeyAttr => []}); + + return $responses; +} + +# delete rows in a non-node table +sub tablerowdelhdl { + my $params = shift; + + # from %URIdef: + # desc => "[URI:/tables/{table}/rows/{attrvals}] - Delete rows from a non-node table that have the attribute values specified in {attrvals}.", + # usage => "||$usagemsg{non_getreturn}|", + # example => '|Delete a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet||', + + my @args; + my @urilayers = @{$params->{'layers'}}; + # the array elements for @urilayers are: + # 0 - 'table' + # 1 - + # 2 - 'rows' + # 3 - + + # set the command name + $request->{command} = 'delEntries'; + + # For delEntries, the rest of the xml request strucutre looks like this: + # + # nodelist + # + # compute1,lissa + # down + # + #
+ + # set the table name and attr/vals + my $table = {}; # will hold the name and attr/vals + $request->{table}->[0] = $table; #todo: the xcat delEntries cmd supports multiple tables in 1 request. We could support this if the attr names were table.attr + $table->{name} = $urilayers[1]; + my @attrvals = split(/,/, $urilayers[3]); + foreach my $av (@attrvals) { + my ($attr, $value) = split(/\s*=\s*/, $av, 2); + $table->{attr}->{$attr} = $value; + } + + my $req = genRequest(); + # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute + # out of the node hash and make it the key + my $responses = sendRequest($req, {SuppressEmpty => undef, ForceArray => 1, KeyAttr => []}); + + return $responses; +} + + +# display the resource list when run 'xcatws.cgi -d' +sub displayUsage { + foreach my $group (keys %URIdef) { + print "Resource Group: $group\n"; + foreach my $res (keys %{$URIdef{$group}}) { + print " Resource: $res\n"; + print " $URIdef{$group}->{$res}->{desc}\n"; + if (defined ($URIdef{$group}->{$res}->{GET})) { + print " GET: $URIdef{$group}->{$res}->{GET}->{desc}\n"; + } + if (defined ($URIdef{$group}->{$res}->{PUT})) { + print " PUT: $URIdef{$group}->{$res}->{PUT}->{desc}\n"; + } + if (defined ($URIdef{$group}->{$res}->{POST})) { + print " POST: $URIdef{$group}->{$res}->{POST}->{desc}\n"; + } + if (defined ($URIdef{$group}->{$res}->{DELETE})) { + print " DELETE: $URIdef{$group}->{$res}->{DELETE}->{desc}\n"; + } + } + } +} + + +# This handles and removes serverdone and error tags in the perl data structure that is from the xml that xcatd returned +#bmp: is there a way to avoid make a copy of the whole response? For big output that could be time consuming. +# For the error tag, you don't have to bother copying the response, because you are going to exit anyway. +# Maybe this function could just verify there is a serverdone and handle any error, and then +# let each specific output handler ignore the serverdone tag? + +# Filter out the error message +# If has 'error' message in the output data, push them all to one list +# If has 'errorcode' in the output data, set it to be the errorcode of response. Otherwise, the errorcode to '1' +# When get the 'serverdone' identifer +# If 'errorcode' has been set, return the error message and error code like {error:[msg1,msg2...], errorcode:num} +# Otherwise, pass the output to the outputhandler for the specific resource + +sub filterData { + my $data = shift; + #debugandexit(Dumper($data)); + + my $outputdata; + my $outputerror; + my @errmsgindata; # put the out->{data} for error message output + + #trim the serverdone message off + foreach (@{$data}) { + if (defined($_->{error})) { + if (ref($_->{error}) eq 'ARRAY') { + foreach my $msg (@{$_->{error}}) { + if ($msg =~ /(Permission denied|Authentication failure)/) { + # return 401 Unauthorized + sendResponseMsg($STATUS_UNAUTH); + } else { + push @{$outputerror->{error}}, $msg; + } + } + } else { + push @{$outputerror->{error}}, $_->{error}; + } + + if (defined ($_->{errorcode})) { + if (ref($_->{errorcode}) eq 'ARRAY') { + $outputerror->{errorcode} = $_->{errorcode}->[0]; + } else { + $outputerror->{errorcode} = $_->{errorcode}; + } + } else { + # set the default errorcode to '1' + $outputerror->{errorcode} = '1'; + } + } elsif (defined($_->{errorcode}) && $_->{errorcode}->[0] ne "0") { # defined errorcode, but not define the error msg + $outputerror->{errorcode} = $_->{errorcode}->[0]; + if (defined ($_->{data}) && ref($_->{data}->[0]) ne "HASH") { + # to get the message in data for the case that errorcode is set but no 'error' attr + push @errmsgindata, $_->{data}->[0]; + } + if (@errmsgindata) { + push @{$outputerror->{error}}, @errmsgindata; + } else { + push @{$outputerror->{error}}, "Failed with unknown reason."; + } + } + + # handle the output like + # + # node1 + # Unable to identify plugin for this command, check relevant tables: nodehm.power,mgt;nodehm.mgt + # 1 + # + if (defined($_->{node}) && defined ($_->{node}->[0]->{error})) { + if (defined ($_->{node}->[0]->{name})) { + push @{$outputerror->{error}}, "$_->{node}->[0]->{name}->[0]: ".$_->{node}->[0]->{error}->[0]; + } + if (defined ($_->{node}->[0]->{errorcode})) { + $outputerror->{errorcode} = $_->{node}->[0]->{errorcode}->[0]; + } else { + # set the default errorcode to '1' + $outputerror->{errorcode} = '1'; + } + } + + + if (exists($_->{serverdone})) { + if (defined ($outputerror->{error}) || defined ($outputerror->{error})) { + addPageContent($JSON->encode($outputerror)); + #return the default http error code to be 403 forbidden + sendResponseMsg($STATUS_FORBIDDEN); + #} else { + #otherwise, ignore the 'servicedone' data + # next; + } else { + delete ($_->{serverdone}); + if (scalar(keys %{$_}) > 0) { + push @{$outputdata}, $_; + } + } + } else { + if (defined ($_->{data}) && ref($_->{data}->[0]) ne "HASH") { + # to get the message in data for the case that errorcode is set but no 'error' attr + push @errmsgindata, $_->{data}->[0]; + } + push @{$outputdata}, $_; + } + } + + return $outputdata; +} + +# Structure the response perl data structure into well-formed json. Since the structure of the +# xml output that comes from xcatd is inconsistent and not very structured, we have a lot of work to do. +sub wrapJson { + # this is an array of responses from xcatd. Often all the output comes back in 1 response, but not always. + my $data = shift; + + addPageContent($JSON->encode($data)); + return; + + + # put, delete, and patch usually just give a short msg, if anything + if (isPut() || isDelete() || isPatch()) { + addPageContent($JSON->encode($data)); + return; + } +} + +# Append content to the global var holding the output to go back to the rest client +# 1st param - The output message +# 2nd param - A flag to specify the format of 1st param: 1 - json formatted standard xcat output data sub addPageContent { my $newcontent = shift; + my $userdata = shift; + + if ($userdata && $XCOLL) { + my $group; + my $hash = $JSON->decode($newcontent); + if (ref($hash) eq "HASH") { + foreach my $node (keys %{$hash}) { + if (ref($hash->{$node}) eq "HASH") { + my $value; + foreach (sort (keys %{$hash->{$node}})) { + $value .= "$_$hash->{$node}->{$_}"; + } + push @{$group->{$value}->{node}}, $node; + $group->{$value}->{orig} = $hash->{$node}; + } elsif (ref($hash->{$node}) eq "ARRAY") { + my $value; + foreach (sort (@{$hash->{$node}})) { + $value .= "$_"; + } + push @{$group->{$value}->{node}}, $node; + $group->{$value}->{orig} = $hash->{$node}; + } + } + } + my $groupout; + foreach my $value (keys %{$group}) { + if (defined $group->{$value}->{node}) { + my $nodes = join(',', @{$group->{$value}->{node}}); + if (defined ($group->{$value}->{orig})) { + $groupout->{$nodes} = $group->{$value}->{orig}; + } + } + } + $newcontent = $JSON->encode($groupout) if ($groupout); + } + $pageContent .= $newcontent; } -#send the response to client side -#the http only return once in each request, so all content shoudl save in a global variable, -#create the response header by status +# send the response to client side, then exit +# with http there is only one return for each request, so all content should be in pageContent global variable when you call this +# create the response header by status code and format sub sendResponseMsg { my $code = shift; my $tempFormat = ''; @@ -69,2188 +2483,29 @@ sub sendResponseMsg { $tempFormat = 'text/html'; } print $q->header(-status => $code, -type => $tempFormat); + if ($pageContent) { $pageContent .= "\n"; } # if there is any content, append a newline print $pageContent; exit(0); } -sub unsupportedRequestType { - addPageContent("request method '$requestType' is not supported on resource '$resource'"); - sendResponseMsg($STATUS_NOT_ALLOWED); -} - -use XML::Simple; -$XML::Simple::PREFERRED_PARSER = 'XML::Parser'; - +# Convert xcat request to xml for sending to xcatd sub genRequest { - if ($DEBUGGING) { - addPageContent($q->p("request " . Dumper($request))); - } - my $xml = XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []); + my $xml = XML::Simple::XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []); } -#data formatters. To add one simple copy the format of an existing one -# and add it to this hash -my %formatters = ( - 'html' => \&wrapHtml, - 'json' => \&wrapJson, - 'xml' => \&wrapXml,); - -fetchParameter($queryString); - -if ($queryhash{'format'}) { - $format = $queryhash{'format'}->[0]; - if (!exists $formatters{$format}) { - addPageContent("The format '$format' is not valid"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if ($format eq 'json') { - # require JSON dynamically and let them know if it is not installed - my $jsoninstalled = eval { require JSON; }; - unless ($jsoninstalled) { - addPageContent('{"data":"JSON perl module missing. Install perl-JSON before using the xCAT REST web services API."}'); - sendResponseMsg($STATUS_SERVICE_UNAVAILABLE); - } - } -} - -my $XCAT_PATH = '/opt/xcat/bin'; - -#resource handlers -my %resources = ( - groups => \&groupsHandler, - images => \&imagesHandler, - logs => \&logsHandler, - monitors => \&monitorsHandler, - networks => \&networksHandler, - nodes => \&nodesHandler, - notifications => \¬ificationsHandler, - policies => \&policiesHandler, - site => \&siteHandler, - tables => \&tablesHandler, - accounts => \&accountsHandler, - objects => \&objectsHandler, - vms => \&vmsHandler, - debug => \&debugHandler, - hypervisor => \&hypervisorHandler, - version => \&versionHandler); - -#if no resource was specified -if ($pathInfo =~ /^\/$/ || $pathInfo =~ /^$/) { - addPageContent($q->p("This is the root page for the xCAT Rest Web Service. Available resources are:")); - foreach (sort keys %resources) { - addPageContent($q->p($_)); - } - sendResponseMsg($STATUS_OK); -} - -sub doesResourceExist { - my $res = shift; - return exists $resources{$res}; -} - -if ($DEBUGGING) { - if (defined $q->param('PUTDATA')) { - addPageContent("put data " . $q->p($q->param('PUTDATA') . "\n")); - } elsif (isPut()) { - my $entries = JSON::decode_json($q->param('PUTDATA')); - if (scalar(@$entries) >= 1) { - addPageContent("put data \n"); - foreach (@$entries) { - addPageContent("$_\n"); - } - } - } - - if (defined $q->param('POSTDATA')) { - addPageContent("post data " . $q->p($q->param('POSTDATA') . "\n")); - } elsif (isPost()) { - my $entries = JSON::decode_json($q->param('POSTDATA')); - if (scalar(@$entries) >= 1) { - addPageContent("post data \n"); - foreach (@$entries) { - addPageContent("$_\n"); - } - } - } - - addPageContent($q->p("Parameters ")); - my @params = $q->param; - foreach (@params) { - addPageContent("$_ = " . join(',', $q->param($_)) . "\n"); - } - addPageContent($q->p("Query String $queryString" . "\n")); - addPageContent($q->p("Query parameters from the Query String" . Dumper(\%queryhash) . "\n")); - addPageContent($q->p("HTTP Method $requestType" . "\n")); - addPageContent($q->p("URI $url" . "\n")); - addPageContent($q->p("path " . Dumper(@path) . "\n")); -} - -#when use put and post, can not fetch the url-parameter, so add this sub to support all kinks of method -sub fetchParameter { - my $parstr = shift; - unless ($parstr) { - return; - } - - my @pairs = split(/&/, $parstr); - foreach my $pair (@pairs) { - my ($key, $value) = split(/=/, $pair, 2); - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg; - push @{$queryhash{$key}}, $value; - } -} - -#extract the put data or post data into perl hash, easy for retrieve -sub extractData { - my $temphash = shift; - my $parArray = shift; - my $key; - my $value; - my $position; - - #traversal all element in the array - foreach (@$parArray) { - $position = index($_, '='); - if ($position < 0) { - $key = $_; - $value = 1; - } - else { - $key = substr $_, 0, $position; - $value = substr $_, $position + 1; - } - $temphash->{$key} = $value; - - if ($DEBUGGING) { - addPageContent($q->p("The parameter extract from put/post data:
" . Dumper($temphash))); - } - } -} - -my $userName=http('userName'); -my $password=http('password'); - -sub handleRequest { - if (defined $queryhash{'userName'}) { - $userName = $queryhash{'userName'}->[0]; - } - if (defined $queryhash{'password'}) { - $password = $queryhash{'password'}->[0]; - } - if ($userName && $password) { - $request->{becomeuser}->[0]->{username}->[0] = $userName; - $request->{becomeuser}->[0]->{password}->[0] = $password; - } - my @data = $resources{$resource}->(); - wrapData(\@data); -} - -my @groupFields = ('groupname', 'grouptype', 'members', 'wherevals', 'comments', 'disable'); - -#get is done -#post and delete are done but not tested -#groupfiles4dsh is done but not tested -sub groupsHandler { - my @responses; - my @args; - my $groupName; - - #is the group name in the URI? - if (defined $path[1]) { - $groupName = $path[1]; - } - - #in the query string? - else { - $groupName = $q->param('groupName'); - } - - if (isGet()) { - if (defined $groupName) { - $request->{command} = 'tabget'; - push @args, "groupname=$groupName"; - if (defined $q->param('field')) { - foreach ($q->param('field')) { - push @args, "nodegroup.$_"; - } - } - else { - foreach (@groupFields) { - push @args, "nodegroup.$_"; - } - } - } - else { - $request->{command} = 'tabdump'; - push @args, 'nodegroup'; - } - } - - #does it make sense to even have this? - elsif (isPost()) { - my $nodeRange = $q->param('nodeRange'); - if ((defined $groupName) && (defined $nodeRange)) { - $request->{command} = 'mkdef'; - push @args, '-t'; - push @args, 'group'; - push @args, '-o'; - push @args, $groupName; - push @args, "members=$nodeRange"; - } - else { - addPageContent("A node range and group name must be specified for creating a group"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - elsif (isPut()) { - - #handle groupfiles4dsh -p /tmp/nodegroupfiles - if ($q->param('command') eq "4dsh") { - if ($q->param('path')) { - $request->{command} = 'groupfiles4dsh'; - push @args, "p=$q->param('path')"; - } - else { - addPageContent("The path must be specified for creating directories for dsh"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - if (defined $groupName && defined $q->param('fields')) { - $request->{command} = 'nodegrpch'; - push @args, $groupName; - push @args, $q->param('field'); - } - else { - addPageContent("The group and fields must be specified to update groups"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - } - elsif (isDelete()) { - if (defined $groupName) { - $request->{command} = 'rmdef'; - push @args, '-d'; - push @args, 'group'; - push @args, '-o'; - push @args, $groupName; - } - else { - addPageContent("The group must be specified to delete a group"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -my @imageFields = ( - 'imagename', 'profile', 'imagetype', 'provmethod', 'osname', 'osvers', - 'osdistro', 'osarch', 'synclists', 'comments', 'disable'); - -#get is done, nothing else -sub imagesHandler { - my @responses; - my @args; - my $image; - my $subResource; - - if (defined($path[1])) { - $image = $path[1]; - } - - if (isGet()) { - $request->{command} = 'lsdef'; - push @args, '-t', 'osimage'; - if (defined $image) { - push @args, '-o', $image; - } - if (defined($q->param('field'))) { - push @args, '-i'; - push @args, join(',', $q->param('field')); - } - if (defined($q->param('criteria'))) { - foreach ($q->param('criteria')) { - push @args, '-w', "$_"; - } - } - } - elsif (isPost()) { - my $operationname = $image; - my $entries; - my %entryhash; - - #check the post data - unless (defined($q->param('POSTDATA'))) { - addPageContent("Invalid Parameters"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - $entries = JSON::decode_json($q->param('POSTDATA')); - if (scalar(@$entries) < 1) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - extractData(\%entryhash, $entries); - - #for image capture - if ($operationname eq 'capture') { - $request->{command} = 'imgcapture'; - if (defined($entryhash{'nodename'})) { - $request->{noderange} = $entryhash{'nodename'}; - } - else { - addPageContent('No node range.'); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if (defined($entryhash{'profile'})) { - push @args, '-p'; - push @args, $entryhash{'profile'}; - } - if (defined($entryhash{'osimage'})) { - push @args, '-o'; - push @args, $entryhash{'osimage'}; - } - if (defined($entryhash{'bootinterface'})) { - push @args, '-i'; - push @args, $entryhash{'bootinterface'}; - } - if (defined($entryhash{'netdriver'})) { - push @args, '-n'; - push @args, $entryhash{'netdriver'}; - } - if (defined($entryhash{'device'})) { - push @args, '-d'; - push @args, $entryhash{'device'}; - } - } - elsif ($operationname eq 'export') { - $request->{command} = 'imgexport'; - if (defined($entryhash{'osimage'})) { - push @args, $entryhash{'osimage'}; - } - else { - addPageContent('No image specified'); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if (defined($entryhash{'destination'})) { - push @args, $entryhash{'destination'}; - } - if (defined($entryhash{'postscripts'})) { - push @args, '-p'; - push @args, $entryhash{'postscripts'}; - } - if (defined($entryhash{'extra'})) { - push @args, '-e'; - push @args, $entryhash{'extra'}; - } - if (defined($entryhash{'remotehost'})) { - push @args, '-R'; - push @args, $entryhash{'remotehost'}; - } - if (defined($entryhash{'verbose'})) { - push @args, '-v'; - } - } - elsif ($operationname eq 'import') { - $request->{command} = 'imgimport'; - if (defined($entryhash{'osimage'})) { - push @args, $entryhash{'osimage'}; - } - else { - addPageContent('No image specified'); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if (defined($entryhash{'profile'})) { - push @args, '-f'; - push @args, $entryhash{'profile'}; - } - if (defined($entryhash{'remotehost'})) { - push @args, '-R'; - push @args, $entryhash{'remotehost'}; - } - if (defined($entryhash{'postscripts'})) { - push @args, '-p'; - push @args, $entryhash{'postscripts'}; - } - - if (defined($entryhash{'verbose'})) { - push @args, '-v'; - } - } - } - elsif (isPut()) { - - #check the operation type - unless (defined $path[2]) { - addPageContent("The subResource $subResource does not exist"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - $subResource = $path[2]; - - #check the image name - unless (defined $image) { - addPageContent("The image name is required to clean an os image"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if ($subResource eq 'check') { - $request->{command} = 'chkosimage'; - if (defined($q->param('PUTDATA'))) { - push @args, '-c'; - } - push @args, $image; - } - else { - addPageContent("The subResource $subResource does not exist"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - elsif (isDelete()) { - if (defined $image) { - $request->{command} = 'rmimage'; - if (defined $q->param('verbose')) { - push @args, '-v'; - } - push @args, $image; - } - elsif (defined $q->param('os') && defined $q->param('arch') && defined $q->param('profile')) { - push @args, '-o'; - push @args, $q->param('os'); - push @args, '-a'; - push @args, $q->param('arch'); - push @args, '-p'; - push @args, $q->param('profile'); - } - else { - addPageContent( - "Either the image name or the os, architecture and profile must be specified to remove an image"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -#complete -sub logsHandler { - my @responses; - my @args; - my $logType; - - if (defined $path[1]) { - $logType = $path[1]; - } - - #in the query string? - else { - $logType = $q->param('logType'); - } - my $nodeRange = $q->param('nodeRange'); - - #no real output unless the log type is defined - if (!defined $logType) { - addPageContent("Current logs available are auditlog and eventlog"); - sendResponseMsg($STATUS_BAD_REQUEST); - exit(0); - } - - if (isGet()) { - if ($logType eq "reventLog") { - if (defined $nodeRange) { - $request->{command} = 'reventlog'; - push @args, $nodeRange; - if (defined $q->param('count')) { - push @args, $q->param('count'); - } - } - else { - addPageContent("nodeRange must be specified to GET remote event logs"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - $request->{command} = 'tabdump'; - push @args, $logType; - } - } - - #this clears the log - elsif (isPut()) { - if ($logType eq "reventlog") { - if (defined $nodeRange) { - $request->{command} = 'reventlog'; - push @args, $nodeRange; - push @args, 'clear'; - } - else { - addPageContent("nodeRange must be specified to clean remote event logs"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - - #should it return the removed entries? - if (defined $q->param('showRemoved')) { - push @args, '-V'; - } - if (defined $q->param('count') || defined $q->param('percent') || defined $q->param('lastRecord')) { - - #remove some of the entries - $request->{command} = 'tabprune'; - - #remove a certain number of records - if (defined $q->param('count')) { - push @args, ('-n', $q->param('count')); - } - - #remove a percentage of the records - if (defined $q->param('percent')) { - push @args, ('-p', $q->param('percent')); - } - - #remove all records before this record - if (defined $q->param('lastRecord')) { - push @args, ('-i', $q->param('lastRecord')); - } - } - else { - $request->{command} = 'tabprune'; - - #-a removes all - push @args, '-a'; - } - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -#complete -sub monitorsHandler { - my @responses; - my @args; - my $monitor; - - if (defined $path[1]) { - $monitor = $path[1]; - } - - #in the query string? - elsif (defined $q->param('monitor')) { - push @args, $q->param('monitor'); - } - if (defined $monitor) { - push @args, $monitor; - } - - if (isGet()) { - $request->{command} = 'monls'; - } - elsif (isPost()) { - $request->{command} = 'monadd'; - if ($q->param('nodeStatMon')) { - push @args, '-n'; - } - - #get the plug-in specific settings array - foreach ($q->param('pluginSetting')) { - push @args, '-s'; - push @args, $_; - } - } - elsif (isDelete()) { - $request->{command} = 'monrm'; - } - elsif (isPut() || isPatch()) { - my $action = $q->param('action'); - if ($action eq "start") { - $request->{command} = 'monstart'; - } - elsif ($action eq "stop") { - $request->{command} = 'monstop'; - } - elsif ($action eq "config") { - $request->{command} = 'moncfg'; - } - elsif ($action eq "deconfig") { - $request->{command} = 'mondeconfig'; - } - else { - unsupportedRequestType(); - } - if (!defined $q->param('nodeRange')) { - - #error - } - else { - push @args, $q->param('nodeRange'); - } - if (defined $q->param('remote')) { - push @args, '-r'; - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -sub networksHandler { - my @responses; - my @args; - my $netname = ''; - - if (isGet()) { - $request->{command} = 'lsdef'; - push @{$request->{arg}}, '-t', 'network'; - if (defined($path[1])) { - push @{$request->{arg}}, '-o', $path[1]; - } - my @temparray = $q->param('field'); - - #add the field name to get - if (scalar(@temparray) > 0) { - push @{$request->{arg}}, '-i'; - push @{$request->{arg}}, join(',', @temparray),; - } - } - elsif (isPut() || isPost()) { - my $entries; - my $iscommand = 0; - if (isPut()) { - $request->{command} = 'chdef'; - if (defined($path[1])) { - if ($path[1] eq "makehosts" || $path[1] eq "makedns") { - # Issue makehost/makedns directly - $request->{command} = $path[1]; - $iscommand = 1; - } - } - } - else { - $request->{command} = 'mkdef'; - } - - if (!$iscommand) { - if (defined $path[1]) { - $netname = $path[1]; - } - - if ($netname eq '') { - addPageContent('A network name must be specified.'); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - push @{$request->{arg}}, '-t', 'network', '-o', $netname; - - if (defined($q->param('PUTDATA'))) { - $entries = JSON::decode_json($q->param('PUTDATA')); - } - elsif (defined($q->param('POSTDATA'))) { - $entries = JSON::decode_json($q->param('POSTDATA')); - } - else { - addPageContent("No Field and Value map was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if (scalar($entries) < 1) { - addPageContent("No Field and Value map was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - foreach (@$entries) { - push @{$request->{arg}}, $_; - } - } - } - elsif (isDelete()) { - $request->{command} = 'rmdef'; - - if (defined $path[1]) { - $netname = $path[1]; - } - if ($netname eq '') { - addPageContent('A network name must be specified.'); - sendResponseMsg($STATUS_BAD_REQUEST); - } - push @{$request->{arg}}, '-t', 'network', '-o', $netname; - } - else { - unsupportedRequestType(); - exit(0); - } - @responses = sendRequest(genRequest()); - - return @responses; -} - -sub nodesHandler { - my @responses; - my @args; - my $noderange; - my @envs; - - if (defined $path[1]) { - $noderange = $path[1]; - } - - if (isGet()) { - my $subResource; - if (defined $path[2]) { - $subResource = $path[2]; - unless (defined($noderange)) { - addPageContent("Invalid nodes and/or groups in noderange"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - $request->{noderange} = $noderange; - - #use the corresponding command by the subresource name - if ($subResource eq "power") { - $request->{command} = 'rpower'; - push @args, 'stat'; - } - elsif ($subResource eq "energy") { - $request->{command} = 'renergy'; - - #no fields will default to 'all' - if (defined $q->param('field')) { - push @args, $q->param('field'); - } - else { - push @args, 'all'; - } - } - elsif ($subResource eq "status") { - $request->{command} = 'nodestat'; - } - elsif ($subResource eq "inventory") { - $request->{command} = 'rinv'; - if (defined $q->param('field')) { - push @args, $q->param('field'); - } - else { - push @args, 'all'; - } - } - elsif ($subResource eq "vitals") { - $request->{command} = 'rvitals'; - if (defined $q->param('field')) { - push @args, $q->param('field'); - } - else { - push @args, 'all'; - } - } - elsif ($subResource eq "scan") { - $request->{command} = 'rscan'; - if (defined $q->param('field')) { - push @args, $q->param('field'); - } - } - else { - addPageContent("Unspported operation on nodes object."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - $request->{command} = 'lsdef'; - push @args, "-t", "node"; - - #add the nodegroup into args - if (defined($noderange)) { - push @args, "-o", $noderange; - } - - #maybe it's specified in the parameters - my @temparray = $q->param('field'); - if (scalar(@temparray) > 0) { - push @args, "-i"; - push @args, join(',', @temparray); - } - } - } - elsif (isPut()) { - my $subResource; - my @entries; - my $entrydata; - - unless (defined($noderange)) { - addPageContent("Invalid nodes and/or groups in noderange"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - $request->{noderange} = $noderange; - - unless ($q->param('PUTDATA')) { - #temporary allowance for the put data to be contained in the queryString - unless ($queryhash{'putData'}) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - else { - foreach my $put (@{$queryhash{'putData'}}) { - my ($key, $value) = split(/=/, $put, 2); - if ($key eq 'field' && $value) { - push @entries, $value; - } - } - } - } - else { - @entries = JSON::decode_json($q->param('PUTDATA')); - if (scalar(@entries) < 1) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - - if (defined $path[2]) { - $subResource = $path[2]; - - if (($subResource ne "dsh") && ($subResource ne "dcp")) { - # For any function other than "dsh" or "dcp", - # move all operands to the argument list. - foreach (@entries) { - if (ref($_) eq 'ARRAY') { - foreach (@$_) { - push @args, $_; - } - } else { - push @args, $_; - } - } - } - if ($subResource eq "power") { - $request->{command} = "rpower"; - my %elements; - extractData(\%elements, @entries); - - unless (scalar(%elements)) { - addPageContent("No power operands were supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - elsif ($subResource eq "energy") { - $request->{command} = "renergy"; - } - elsif ($subResource eq "bootstat" or $subResource eq "bootstate") { - $request->{command} = "nodeset"; - } - elsif ($subResource eq "bootseq") { - $request->{command} = "rbootseq"; - } - elsif ($subResource eq "setboot") { - $request->{command} = "rsetboot"; - } - elsif ($subResource eq "migrate") { - $request->{command} = "rmigrate"; - } - elsif ($subResource eq "dsh") { - $request->{command} = "xdsh"; - my %elements; - extractData(\%elements, @entries); - if (defined($elements{'devicetype'})) { - push @args, '--devicetype'; - push @args, $elements{'devicetype'}; - } - if (defined($elements{'execute'})) { - push @args, '-e'; - } - if (defined($elements{'environment'})) { - push @args, '-E'; - push @args, $elements{'environment'}; - } - if (defined($elements{'fanout'})) { - push @args, '-f'; - push @args, $elements{'fanout'}; - } - if (defined($elements{'nolocale'})) { - push @args, '-L'; - } - if (defined($elements{'userid'})) { - push @args, '-l'; - push @args, $elements{'userid'}; - } - if (defined($elements{'monitor'})) { - push @args, '-m'; - } - if (defined($elements{'options'})) { - push @args, '-o'; - push @args, $elements{'options'}; - } - if (defined($elements{'showconfig'})) { - push @args, '-q'; - } - if (defined($elements{'silent'})) { - push @args, '-Q'; - } - if (defined($elements{'remoteshell'})) { - push @args, '-r'; - push @args, $elements{'remoteshell'}; - } - if (defined($elements{'syntax'})) { - push @args, '-S'; - push @args, $elements{'syntax'}; - } - if (defined($elements{'timeout'})) { - push @args, '-t'; - push @args, $elements{'timeout'}; - } - if (defined($elements{'envlist'})) { - push @args, '-X'; - push @args, $elements{'envlist'}; - } - if (defined($elements{'sshsetup'})) { - push @args, '-K'; - push @args, $elements{'sshsetup'}; - } - if (defined($elements{'rootimg'})) { - push @args, '-i'; - push @args, $elements{'rootimg'}; - } - if (defined($elements{'command'})) { - push @args, $elements{'command'}; - } - if (defined($elements{'remotepasswd'})) { - push @envs, 'DSH_REMOTE_PASSWORD=' . $elements{'remotepasswd'}; - push @envs, 'DSH_FROM_USERID=root'; - push @envs, 'DSH_TO_USERID=root'; - } - } - elsif ($subResource eq "dcp") { - $request->{command} = "xdcp"; - my %elements; - extractData(\%elements, @entries); - if (defined($elements{'fanout'})) { - push @args, '-f'; - push @args, $elements{'fanout'}; - } - if (defined($elements{'rootimg'})) { - push @args, '-i'; - push @args, $elements{'rootimg'}; - } - if (defined($elements{'options'})) { - push @args, '-o'; - push @args, $elements{'options'}; - } - if (defined($elements{'rsyncfile'})) { - push @args, '-F'; - push @args, $elements{'rsyncfile'}; - } - if (defined($elements{'preserve'})) { - push @args, '-p'; - } - if (defined($elements{'pull'})) { - push @args, '-P'; - } - if (defined($elements{'showconfig'})) { - push @args, '-q'; - } - if (defined($elements{'remotecopy'})) { - push @args, '-r'; - push @args, $elements{'remotecopy'}; - } - if (defined($elements{'recursive'})) { - push @args, '-R'; - } - if (defined($elements{'timeout'})) { - push @args, '-t'; - push @args, $elements{'timeout'}; - } - if (defined($elements{'source'})) { - push @args, $elements{'source'}; - } - if (defined($elements{'target'})) { - push @args, $elements{'target'}; - } - } - } - else { - my %elements; - my $name; - my $val; - - $request->{command} = "tabch"; - push @args, "node=" . $request->{noderange}; - - extractData(\%elements, @entries); - while (($name, $val) = each (%elements)) { - push @args, $name . "=" . $val; - } - } - } - elsif (isPost()) { - $request->{command} = 'mkdef'; - push @args, "-t", "node"; - - unless (defined($noderange)) { - addPageContent("No nodename was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - push @args, "-o", $noderange; - - if ($q->param('POSTDATA')) { - my $entries = JSON::decode_json($q->param('POSTDATA')); - if (scalar($entries) < 1) { - addPageContent("No Field and Value map was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - foreach (@$entries) { - push @args, $_; - } - } - } - elsif (isDelete()) { - - #FYI: the nodeRange for delete has to be specified in the URI - $request->{command} = 'rmdef'; - push @args, "-t", "node"; - unless (defined($noderange)) { - addPageContent("No nodename was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - push @args, "-o", $noderange; - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - if (@envs) { - push @{$request->{env}}, @envs; - } - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -my @notificationFields = ('filename', 'tables', 'tableops', 'comments', 'disable'); - -#complete, unless there is some way to alter existing notifications -sub notificationsHandler { - my @responses; - my @args; - - #does not support using the notification fileName in the URI - - if (isGet()) { - if (defined $q->param('fileName')) { - $request->{command} = 'gettab'; - push @args, "filename" . $q->param('fileName'); - - #if they specified the fields, just get those - if (defined $q->param('field')) { - foreach ($q->param('field')) { - push @args, $_; - } - } - - #else show all of the fields - else { - foreach (@notificationFields) { - push @args, "notification.$_"; - } - } - } - else { - $request->{command} = 'tabdump'; - push @args, "notification"; - } - } - elsif (isPost()) { - $request->{command} = 'regnotif'; - if (!defined $q->param('fileName') || !defined $q->param('table') || !defined $q->param('operation')) { - addPageContent("fileName, table and operation must be specified for a POST on /notifications"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - else { - push @args, $q->param('fileName'); - my $tables; - foreach ($q->param('table')) { - $tables .= "$_,"; - } - - #get rid of the extra comma - chop($tables); - push @args, $tables; - push @args, '-o'; - my $operations; - foreach ($q->param('operation')) { - $operations .= "$_,"; - } - - #get rid of the extra comma - chop($operations); - push @args, $q->param('operation'); - } - } - elsif (isDelete()) { - $request->{command} = 'unregnotif'; - if (defined $q->param('fileName')) { - push @args, $q->param('fileName'); - } - else { - addPageContent("fileName must be specified for a DELETE on /notifications"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - addPageContent("request is " . Dumper($request)); - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -my @policyFields = - ('priority', 'name', 'host', 'commands', 'noderange', 'parameters', 'time', 'rule', 'comments', 'disable'); - -#complete -sub policiesHandler { - my @responses; - my @args; - my $priority; - - #does it specify the prioirty in the URI? - if (defined $path[1]) { - $priority = $path[1]; - } - - #in the query string? - elsif (defined $q->param('priority')) { - $priority = $q->param('priority'); - } - - if (isGet()) { - if (defined $priority) { - $request->{command} = 'gettab'; - push @args, "priority=$priority"; - my @fields = $q->param('field'); - - #if they specified fields to retrieve - if (@fields) { - push @args, @fields; - } - - #give them everything if nothing is specified - else { - foreach (@policyFields) { - push @args, "policy.$_"; - } - } - } - else { - $request->{command} = 'tabdump'; - push @args, 'policy'; - } - } - elsif (isPost()) { - if (defined $priority) { - $request->{command} = 'tabch'; - push @args, "priority=$priority"; - for ($q->param) { - if ($_ ne /priority/) { - push @args, "policy.$_=" . $q->param($_); - } - } - } - - #some response about the priority being required - else { - addPageContent("The priority must be specified when creating a policy"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - elsif (isDelete()) { - - #just allowing a delete by priority at the moment, could expand this to anything - if (defined $priority) { - $request->{command} = 'tabch'; - push @args, '-d'; - push @args, "priority=$priority"; - push @args, "policy"; - } - } - elsif (isPut() || isPatch()) { - if (defined $priority) { - $request->{command} = 'tabch'; - push @args, "priority=$priority"; - for ($q->param) { - if ($_ ne /priority/) { - push @args, "policy.$_=" . $q->param($_); - } - } - } - - #some response about the priority being required - else { - addPageContent("The priority must be specified when updating a policy"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - addPageContent("request is " . Dumper($request)); - my $req = genRequest(); - @responses = sendRequest($req); - - return @responses; -} - -#complete -sub siteHandler { - my @data; - my @responses; - my @args; - - if (isGet()) { - $request->{command} = 'lsdef'; - push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite'; - my @temparray = $q->param('field'); - - #add the field name to get - if (scalar(@temparray) > 0) { - push @{$request->{arg}}, '-i'; - push @{$request->{arg}}, join(',', @temparray); - } - } - elsif (isPut()) { - $request->{command} = 'chdef'; - push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite'; - unless ($q->param('PUTDATA')) { - #temporary allowance for the put data to be contained in the queryString - unless ($queryhash{'putData'}) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - else { - foreach my $put (@{$queryhash{'putData'}}) { - my ($key, $value) = split(/=/, $put, 2); - if ($key eq 'field' && $value) { - push @{$request->{arg}}, $value; - } - } - } - } else { - if ($q->param('PUTDATA')) { - my $entries = JSON::decode_json($q->param('PUTDATA')); - foreach (@$entries) { - push @{$request->{arg}}, $_; - } - } - else { - addPageContent("No Field and Value map was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - } - else { - unsupportedRequestType(); - } - - my $req = genRequest(); - @responses = sendRequest($req); - return @responses; -} - -my $formatType; - -#provide direct table access -#complete and tested on the site table -#use of the actual DELETE doesn't seem to fit here, since a resource would not be deleted -#using PUT or PATCH instead, though it doesn't feel all that correct either -sub tablesHandler { - my @responses; - my $table; - my @args; - - #is the table name specified in the URI? - if (defined $path[1]) { - $table = $path[1]; - } - - #handle all gets - if (isGet()) { - - #table was specified - if (defined $table) { - if (defined($q->param('col'))) { - $request->{command} = 'gettab'; - push @args, $q->param('col') . '=' . $q->param('value'); - my @temparray = $q->param('attribute'); - foreach (@temparray) { - push @args, $table . '.' . $_; - } - } - else { - $request->{command} = 'tabdump'; - push @args, $table; - if (!defined $q->param('desc')) { - $formatType = 'splitCommas'; - } - } - } - else { - $request->{command} = 'tabdump'; - } - } - elsif (isPut() || isPatch()) { - my $condition = $q->param('condition'); - my @vals; - my $entries; - if (!defined $condition) { - unless ($q->param('PUTDATA')) { - foreach my $put (@{$queryhash{'putData'}}) { - my ($key, $value) = split(/=/, $put, 2); - if ($key eq 'condition' && $value) { - $condition = $value; - } - } - foreach my $put (@{$queryhash{'putData'}}) { - my ($key, $value) = split(/=/, $put, 2); - if ($key eq 'value') { - push(@vals, $value); - } - } - } - else { - $entries = JSON::decode_json($q->param('PUTDATA')); - if (scalar(@$entries) < 1) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - } - - if (!defined $table || !defined $condition) { - if (scalar(@$entries) < 1) { - addPageContent("The table and condition must be specified when adding, changing or deleting an entry"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - $request->{command} = 'tabch'; - my $del; - if (!defined $q->param('delete')) { - foreach my $put (@{$queryhash{'putData'}}) { - my ($key, $value) = split(/=/, $put, 2); - if ($key eq 'delete') { - $del = 1; - } - } - } - - if (defined $q->param('delete') || defined $del) { - push @args, '-d'; - push @args, $condition; - push @args, $table; - } - elsif (defined $condition) { - push @args, $condition; - if ($q->param('value')) { - for ($q->param('value')) { - push @args, "$table.$_"; - } - } - else { - @args = (@args, @vals); - } - } - else { - foreach (@$entries) { - push @args, split(/ /,$_); - } - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - return @responses; -} - -my @accountFields = ('key', 'username', 'password', 'cryptmethod', 'comments', 'disable'); - -#done aside from being able to change cluster users, which xcat can't do yet -sub accountsHandler { - my @responses; - my @args; - my $key = $q->param('key'); - - if (isGet()) { - - #passwd table - if (!defined $q->param('clusterUser')) { - if (defined $key) { - $request->{command} = 'tabget'; - push @args, "key=$key"; - if (defined $q->param('field')) { - foreach ($q->param('field')) { - push @args, "passwd.$_"; - } - } - else { - foreach (@accountFields) { - push @args, "passwd.$_"; - } - } - } - else { - $request->{command} = 'tabdump'; - push @args, 'passwd'; - } - } - - #cluster user list - else { - $request->{command} = 'xcatclientnnr'; - push @args, 'clusteruserlist'; - push @args, '-p'; - } - } - elsif (isPost()) { - if (!defined $q->param('clusterUser')) { - if (defined $key) { - $request->{command} = 'tabch'; - push @args, "key=$key"; - for ($q->param) { - if ($_ !~ /key/) { - push @args, "passwd.$_=" . $q->param($_); - } - } - } - else { - addPageContent("The key must be specified when creating a non-cluster user"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - - #active directory user - else { - if (defined $q->param('userName') && defined $q->param('userPass')) { - $request->{command} = 'xcatclientnnr'; - push @args, 'clusteruseradd'; - push @args, $q->param('userName'); - push @{$request->{arg}}, @args; - $request->{environment} = {XCAT_USERPASS => $q->param('userPass')}; - } - else { - addPageContent("The key must be specified when creating a cluster user"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - } - elsif (isDelete()) { - if (!defined $q->param('clusterUser')) { - - #just allowing a delete by key at the moment, could expand this to anything - if (defined $key) { - $request->{command} = 'tabch'; - push @args, '-d'; - push @args, "key=$key"; - push @args, "passwd"; - } - else { - addPageContent("The key must be specified when deleting a non-cluster user"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - else { - if (defined $q->param('userName')) { - $request->{command} = 'xcatclientnnr'; - push @args, 'clusteruserdel'; - push @args, $q->param('userName'); - } - else { - addPageContent("The userName must be specified when deleting a cluster user"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - } - elsif (isPut() || isPatch()) { - if (!defined $q->param('clusterUser')) { - if (defined $key) { - $request->{command} = 'tabch'; - push @args, "key=$key"; - for ($q->param) { - if ($_ !~ /key/) { - push @args, "passwd.$_=" . $q->param($_); - } - } - } - else { - addPageContent("The key must be specified when updating a non-cluster user"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - - #TODO: there isn't currently a way to update cluster users - else { - - } - } - else { - unsupportedRequestType(); - exit(0); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - return @responses; -} - -sub objectsHandler { - my @responses; - my @args; - my @objectTypeList = ( - "auditlog", "boottarget", "eventlog", "firmware", "group", "monitoring", - "network", "node", "notification", "osimage", "policy", "route", - "site"); - - #my %objectTypes; - #foreach my $item (@objectTypeList) { $objectTypes{$item} = 1 } - my @objectTypes; - my @objects; - if (defined $path[1]) { - $objectTypes[0] = $path[1]; - if (defined $path[2]) { - $objects[0] = $path[2]; - } - } - if (defined $q->param('objectType')) { - @objectTypes = $q->param('objectType'); - } - if (defined $q->param('object')) { - @objects = $q->param('object'); - } - - if ($q->param('verbose')) { - push @args, '-v'; - } - - if (isGet()) { - if (defined $objectTypes[0]) { - $request->{command} = 'lsdef'; - push @args, '-l'; - push @args, '-t'; - push @args, join(',', @objectTypes); - if (defined $objects[0]) { - push @args, '-o'; - push @args, join(',', @objects); - } - if ($q->param('info')) { - push @args, '-h'; - } - } - else { - if ($q->param('info')) { - push @args, '-h'; - } - else { - - #couldn't find a way to do this through xcatd, so shortcutting the request - my %resp = (data => \@objectTypeList); - return (\%resp); - } - } - } - elsif (isPut()) { - $request->{command} = 'chdef'; - if ($q->param('verbose')) { - push @args, '-v'; - } - if (!defined $q->param('objectType')) { - addPageContent("The object must be specified."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - else { - push @args, '-t'; - push @args, join(',', $q->param('objectType')); - } - if ($q->param('objectName')) { - push @args, join(',', $q->param('objectName')); - } - if ($q->param('dynamic')) { - push @args, '-d'; - } - if ($q->param('minus')) { - push @args, '-m'; - } - if ($q->param('plus')) { - push @args, '-p'; - } - if (defined $q->param('field')) { - foreach ($q->param('field')) { - - #if it has ==, !=. =~ or !~ operators in the field, use the -w option - if (/==|!=|=~|!~/) { - push @args, '-w'; - } - push @args, $_; - } - } - if ($q->param('nodeRange')) { - push @args, $q->param('nodeRange'); - } - - } - elsif (isPost()) { - $request->{command} = 'mkdef'; - if ($q->param('verbose')) { - push @args, '-v'; - } - if (!defined $q->param('objectType')) { - addPageContent("The object must be specified."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - else { - push @args, '-t'; - push @args, join(',', $q->param('objectType')); - } - if ($q->param('objectName')) { - push @args, join(',', $q->param('objectName')); - } - if ($q->param('dynamic')) { - push @args, '-d'; - } - if ($q->param('force')) { - push @args, '-f'; - } - if (defined $q->param('field')) { - foreach ($q->param('field')) { - - #if it has ==, !=. =~ or !~ operators in the field, use the -w option - if (/==|!=|=~|!~/) { - push @args, '-w'; - } - push @args, $_; - } - } - if ($q->param('nodeRange')) { - push @args, $q->param('nodeRange'); - } - - } - elsif (isDelete()) { - $request->{command} = 'rmdef'; - if (defined $q->param('info')) { - push @args, '-h'; - } - elsif (defined $q->param('all')) { - push @args, '-a'; - } - elsif (defined $objectTypes[0]) { - push @args, '-t'; - push @args, join(',', @objectTypes); - if (defined $objects[0]) { - push @args, '-o'; - push @args, join(',', @objects); - } - } - else { - addPageContent( -"Either the help info must be requested or the object must be specified or the flag that indicates everything should be removed." - ); - sendResponseMsg($STATUS_BAD_REQUEST); - } - if (defined $q->param('nodeRange')) { - push @args, $q->param('nodeRange'); - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - return @responses; -} - -#complete i think, tho chvm could handle args better -sub vmsHandler { - my @args; - my $noderange; - my $subResource; - if (defined $path[1]) { - $noderange = $path[1]; - $request->{noderange} = $noderange; - } - else { - addPageContent("Invalid nodes and/or groups in noderange"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if (isGet()) { - $request->{command} = 'lsvm'; - if (defined $q->param('all')) { - push @args, '-a'; - } - - # for z/VM - if (defined $q->param('networknames')) { - push @args, '--getnetworknames'; - } - - if (defined $q->param('network')) { - push @args, '--getnetwork'; - push @args, $q->param('getnetwork'); - } - - if (defined $q->param('diskpoolnames')) { - push @args, '--diskpoolnames'; - } - - if (defined $q->param('diskpool')) { - push @args, '--diskpool'; - push @args, $q->param('diskpool'); - } - } - elsif (isPost()) { - my $entries; - my %entryhash; - my $position; - $request->{command} = 'mkvm'; - unless ($q->param('POSTDATA')) { - addPageContent("Invalid Parameters"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - #collect all parameters from the postdata - my $entries = JSON::decode_json($q->param('POSTDATA')); - if (scalar(@$entries) < 1) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - extractData(\%entryhash, $entries); - - #for system p - if (defined $entryhash{'cec'}) { - push @args, '-c'; - push @args, $entryhash{'cec'}; - } - - if (defined $entryhash{'startId'}) { - push @args, '-i'; - push @args, $entryhash{'startId'}; - } - - if (defined $entryhash{'source'}) { - push @args, '-l'; - push @args, $entryhash{'source'}; - } - - if (defined $entryhash{'profile'}) { - push @args, '-p'; - push @args, $entryhash{'profile'}; - } - - if (defined $entryhash{'full'}) { - push @args, '--full'; - } - - #for KVM & Vmware - if (defined $entryhash{'master'}) { - push @args, '-m'; - push @args, $entryhash{'master'}; - } - - if (defined $entryhash{'disksize'}) { - push @args, '-s'; - push @args, $entryhash{'disksize'}; - } - - if (defined $entryhash{'memory'}) { - push @args, '--mem'; - push @args, $entryhash{'memory'}; - } - - if (defined $entryhash{'cpu'}) { - push @args, '--cpus'; - push @args, $entryhash{'cpu'}; - } - - if (defined $entryhash{'force'}) { - push @args, '-f'; - } - - # for z/VM - if (defined $entryhash{'userid'}) { - push @args, '--userid'; - push @args, $entryhash{'userid'}; - } - - if (defined $entryhash{'size'}) { - push @args, '--size'; - push @args, $entryhash{'size'}; - } - - if (defined $entryhash{'password'}) { - push @args, '--password'; - push @args, $entryhash{'password'}; - } - - if (defined $entryhash{'privilege'}) { - push @args, '--privilege'; - push @args, $entryhash{'privilege'}; - } - - if (defined $entryhash{'diskpool'}) { - push @args, '--diskpool'; - push @args, $entryhash{'diskpool'}; - } - - if (defined $entryhash{'diskvdev'}) { - push @args, '--diskVdev'; - push @args, $entryhash{'diskvdev'}; - } - } - elsif (isPut()) { - $request->{command} = 'chvm'; - if ($q->param('PUTDATA')) { - my $entries = JSON::decode_json($q->param('PUTDATA')); - if (scalar(@$entries) < 1) { - addPageContent("No Field and Value map was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - foreach (@$entries) { - # Handle blank delimited parameters - push @args, split(/ /,$_); - } - } - else { - addPageContent("No Field and Value map was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - } - elsif (isDelete()) { - $request->{command} = 'rmvm'; - if (defined $q->param('retain')) { - push @args, '-r'; - } - if (defined $q->param('service')) { - push @args, '--service'; - } - } - else { - unsupportedRequestType(); - exit(); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - my @responses = sendRequest($req); - return @responses; -} - -sub versionHandler { - addPageContent($q->p("API version is $VERSION")); - sendResponseMsg($STATUS_OK); - exit(0); -} - -#for operations that take a 'long' time to finish, this will provide the interface to check their status -sub jobsHandler { - -} - -sub hypervisorHandler { - my @responses; - my @args; - if (isPut()) { - my %entryhash; - if (defined $path[1]) { - $request->{noderange} = $path[1]; - } - else { - addPageContent("Invalid nodes and/or groups in node in noderange"); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - if (defined $path[2]) { - $request->{command} = $path[2]; - } - else { - $request->{command} = 'chhypervisor'; - } - my $entries = JSON::decode_json( $q->param('PUTDATA') ); - if (scalar(@$entries) < 1) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - foreach (@$entries) { - push @args, split(/ /,$_); - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - return @responses; - } -} - -sub debugHandler { - my @responses; - my @args; - if (isPut()) { - my %entryhash; - $request->{command} = 'xcatclientnnr xcatdebug'; - - #push @args, 'xcatdebug'; - my $entries = JSON::decode_json( $q->param('PUTDATA') ); - if (scalar(@$entries) < 1) { - addPageContent("No set attribute was supplied."); - sendResponseMsg($STATUS_BAD_REQUEST); - } - - foreach (@$entries) { - push @{$request->{arg}}, $_; - } - - push @{$request->{arg}}, @args; - my $req = genRequest(); - @responses = sendRequest($req); - return @responses; - } -} - -#all data wrapping and writing is funneled through here -sub wrapData { - my $data = shift; - my $errorInformation = ''; - - #trim the serverdone message off - if (exists $data->[0]->{serverdone} && exists $data->[0]->{error}) { - $errorInformation = $data->[0]->{error}->[0]; - addPageContent($q->p($errorInformation)); - if (($errorInformation =~ /Permission denied/) || ($errorInformation =~ /Authentication failure/)) { - sendResponseMsg($STATUS_UNAUTH); - } - else { - sendResponseMsg($STATUS_FORBIDDEN); - } - exit 1; - } - else { - pop @{$data}; - } - if (exists $formatters{$format}) { - $formatters{$format}->($data); - } - - #all information were add into the global varibale, call the response funcion - if (exists $data->[0]->{info} && $data->[0]->{info}->[0] =~ /Could not find an object/) { - sendResponseMsg($STATUS_NOT_FOUND); - } - elsif (isPost()) { - sendResponseMsg($STATUS_CREATED); - } - else { - sendResponseMsg($STATUS_OK); - } -} - -sub wrapJson { - my $data = shift; - my $json; - $json->{'data'} = $data; - addPageContent(JSON::to_json($json)); -} - -sub wrapHtml { - my $item; - my $response = shift; - my $baseUri = $url . $pathInfo; - if ($baseUri !~ /\/^/) { - $baseUri .= "/"; - } - - foreach my $element (@$response) { - - #foreach my $element (@$data){ - #if($element->{error}){ - if ($element->{node}) { - addPageContent(""); - foreach $item (@{$element->{node}}) { - - #my $url = $baseUri.$item->{name}[0]; - addPageContent(""); - if (exists $item->{data} && exists $item->{data}[0]) { - if (ref($item->{data}[0]) eq 'HASH') { - if (exists $item->{data}[0]->{desc} && exists $item->{data}[0]->{desc}[0]) { - addPageContent(""); - } - if (ref($item->{data}[0]) eq 'HASH' && exists $item->{data}[0]->{contents}[0]) { - addPageContent(""); - } - } - else { - addPageContent(""); - } - } - elsif (exists $item->{error}) { - addPageContent(""); - } - addPageContent(""); - } - addPageContent("
$item->{name}[0]$item->{data}[0]->{desc}[0]$item->{data}[0]->{contents}[0]$item->{data}[0]$item->{error}[0]
"); - } - if ($element->{data}) { - addPageContent(""); - foreach $item (@{$element->{data}}) { - my @values = split(/:/, $item, 2); - addPageContent(""); - foreach (@values) { - if ($formatType =~ /splitCommas/) { - my @fields = split(/,/, $_, -1); - foreach (@fields) { - addPageContent(""); - } - } - else { - addPageContent(""); - } - } - addPageContent("\n"); - } - addPageContent("
$_$_
"); - } - if ($element->{info}) { - addPageContent(""); - foreach $item (@{$element->{info}}) { - addPageContent(""); - my $fieldname = ''; - my $fieldvalue = ''; - - #strip whitespace in the string - $item =~ s/^\s+//; - $item =~ s/\s+$//; - if ($item =~ /Object/) { - ($fieldname, $fieldvalue) = split(/:/, $item); - } - elsif ($item =~ /.*=.*/) { - my $position = index $item, '='; - $fieldname = substr $item, 0, $position; - $fieldvalue = substr $item, $position + 1; - } - else { - $fieldname = $item; - } - addPageContent(""); - if ($fieldvalue ne '') { - addPageContent(""); - } - addPageContent("\n"); - } - addPageContent("
" . $fieldname . "" . $fieldvalue . "
"); - } - if ($element->{error}) { - addPageContent(""); - foreach $item (@{$element->{error}}) { - addPageContent(""); - } - addPageContent("
" . $item . "
"); - } - } -} - -sub wrapXml { - my @data = shift; - foreach (@data) { - foreach (@$_) { - addPageContent(XMLout($_, RootName => '', NoAttr => 1, KeyAttr => [])); - } - } -} - -#general tests for valid requests and responses with HTTP codes here -if (!doesResourceExist($resource)) { - addPageContent("Resource '$resource' does not exist"); - sendResponseMsg($STATUS_NOT_FOUND); -} -else { - if ($DEBUGGING) { - addPageContent($q->p("resource is $resource")); - } - handleRequest(); -} - -#talk to the server -use Socket; -use IO::Socket::INET; -use IO::Socket::SSL; -use lib "/opt/xcat/lib/perl"; -use xCAT::Table; - -# The database initialization may take some time in the system boot scenario -# wait for a while for the database initialization -#do we really need to do this for the web service? +# Send the request to xcatd and read the response. The request passed in has already been converted to xml. +# The response returned to the caller of this function has already been converted from xml to perl structure. sub sendRequest { my $request = shift; + my $xmlinoptions = shift; # optional arg to not set ForceArray on the XMLin() call my $sitetab; my $retries = 0; - if ($DEBUGGING) { + if ($DEBUGGING == 2) { my $preXml = $request; - - #$preXml =~ s/< /g; - #$preXml =~ s/>/>
/g; - addPageContent($q->p("request XML
" . $preXml)); + $preXml =~ s/< /g; + $preXml =~ s/>/>
/g; + addPageContent($q->p("DEBUG: request XML: " . $request . "\n")); } #hardcoded port for now @@ -2280,20 +2535,19 @@ sub sendRequest { } unless ($client) { if ($@ =~ /SSL Timeout/) { - addPageContent("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat"); - sendResponseMsg($STATUS_TIMEOUT); + error("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat",$STATUS_TIMEOUT); } else { - addPageContent("Connection failurexx: $@"); - sendResponseMsg($STATUS_SERVICE_UNAVAILABLE); + error("Connection failurexx: $@",$STATUS_SERVICE_UNAVAILABLE); } } + debug("request xml=$request"); print $client $request; my $response; my $rsp; - my @fullResponse; + my $fullResponse = []; my $cleanexit = 0; while (<$client>) { $response .= $_; @@ -2301,12 +2555,16 @@ sub sendRequest { #replace ESC with xxxxESCxxx because XMLin cannot handle it if ($DEBUGGING) { - addPageContent($response . "\n"); + #addPageContent("DEBUG: response from xcatd: " . $response . "\n"); } $response =~ s/\e/xxxxESCxxxx/g; + debug("response xml=$response"); - #print "responseXML is ".$response; - $rsp = XMLin($response, SuppressEmpty => undef, ForceArray => 1); + #bmp: i added the $xmlinoptions var because for the table output it saved me processing if everything + # wasn't forced into arrays. Consider if that could save you processing on other api calls too. + if (!$xmlinoptions) { $xmlinoptions = {SuppressEmpty => undef, ForceArray => 1}; } + $rsp = XML::Simple::XMLin($response, %$xmlinoptions); + #debug(Dumper($rsp)); #add ESC back foreach my $key (keys %$rsp) { @@ -2322,57 +2580,162 @@ sub sendRequest { } $response = ''; - push(@fullResponse, $rsp); - if ($rsp->{serverdone}) { + push(@$fullResponse, $rsp); + if (exists($rsp->{serverdone})) { $cleanexit = 1; last; } } } unless ($cleanexit) { - addPageContent("ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely"); - sendResponseMsg($STATUS_SERVICE_UNAVAILABLE); - exit(0); + error("communication with the xCAT server seems to have been ended prematurely",$STATUS_SERVICE_UNAVAILABLE); } - if ($DEBUGGING) { - addPageContent($q->p("response " . Dumper(@fullResponse))); + if ($DEBUGGING == 2) { + addPageContent($q->p("DEBUG: full response from xcatd: " . Dumper($fullResponse))); } - return @fullResponse; + return $fullResponse; } -sub isGet { - return uc($requestType) eq "GET"; -} +# Put input parameters from both $q->url_param and put/post data (if it exists) into generalparams and paramhash for all to use +# 1st output param - The params which are listed in @generalparamlis as a general parameters like 'debug=1, pretty=1' +# 2nd output param - All the params from url params and 'PUTDATA'/'POSTDATA' except the ones in @generalparamlis +sub fetchParameters { + my @generalparamlist = qw(userName password pretty debug xcoll); + # 1st check for put/post data and put that in the hash + my $pdata; + if (isPut()) { + $pdata = $q->param('PUTDATA'); + # in the sles 11.x, the 'PUTDATA' param is not supported for PUT method + # so we have to work around it by getting it by myself + unless ($pdata) { + if (-f "/etc/SuSE-release") {# SUSE os + if ($ENV{'CONTENT_TYPE'} =~ /json/) { + $q->read_from_client(\$pdata, $ENV{'CONTENT_LENGTH'}); + } + } + } + } + elsif (isPost()) { $pdata = $q->param('POSTDATA'); } + if ($dbgdata) { + $pdata = $dbgdata; + } + my $genparms = {}; + my $phash; + if ($pdata) { + $phash = eval { $JSON->decode($pdata); }; + if ($@) { + # remove the code location information to make the output looks better + if ($@ =~ m/ at \//) { + $@ =~ s/ at \/.*$//; + } + error("$@",$STATUS_BAD_REQUEST); + } + #debug("phash=" . Dumper($phash)); + if (ref($phash) ne 'HASH') { error("put or post data must be a json object (hash/dict).", $STATUS_BAD_REQUEST); } -sub isPut { - return uc($requestType) eq "PUT"; -} + # if any general parms are in the put/post data, move them to genparms + foreach my $k (keys %$phash) { + if (grep(/^$k$/, @generalparamlist)) { + $genparms->{$k} = $phash->{$k}; + delete($phash->{$k}); + } + } + } + else { $phash = {}; } -sub isPost { - return uc($requestType) eq "POST"; -} - -sub isPatch { - return uc($requestType) eq "PATCH"; -} - -sub isDelete { - return uc($requestType) eq "DELETE"; -} - -#check to see if this is a valid user. userName and password are already set -sub isAuthenticUser { - $request->{command} = 'authcheck'; - my $req = genRequest(); - my @responses = sendRequest($req); - if ($responses[0]->{data}[0] eq "Authenticated") { - - #user is authenticated - return 1; + # now get params from the url (if any of the keys overlap, the url value will overwrite the put/post value) + foreach my $p ($q->url_param) { + my @a = $q->url_param($p); # this could be a single value or an array, have to figure it out + my $value; + if (scalar(@a) > 1) { $value = [@a]; } # convert it to a reference to an array + else { $value = $a[0]; } + if (grep(/^$p$/, @generalparamlist)) { $genparms->{$p} = $value; } + else { $phash->{$p} = $value; } } - #authentication failure - addPageContent($responses[0]->{error}[0]); - sendResponseMsg($STATUS_UNAUTH); + return ($genparms, $phash); } + +# Load the XML::Simple module +sub loadXML { + if ($xmlinstalled) { return; } + + $xmlinstalled = eval { require XML::Simple; }; + unless ($xmlinstalled) { + error('The XML::Simple perl module is missing. Install perl-XML-Simple before using the xCAT REST web services API with this format."}',$STATUS_SERVICE_UNAVAILABLE); + } + $XML::Simple::PREFERRED_PARSER = 'XML::Parser'; +} + +# Load the JSON perl module, if not already loaded. Sets the $JSON global var. +sub loadJSON { + if ($JSON) { return; } # already loaded + # require JSON dynamically and let them know if it is not installed + my $jsoninstalled = eval { require JSON; }; + unless ($jsoninstalled) { + error("JSON perl module missing. Install perl-JSON before using the xCAT REST web services API.", $STATUS_SERVICE_UNAVAILABLE); + } + $JSON = JSON->new(); +} + +# add a error msg to the output in the correct format and end this request +sub error { + my ($errmsg, $httpcode, $errorcode) = @_; + my $json; + $json->{error} = $errmsg; + $json->{errorcode} = '2'; + if ($errorcode) { + $json->{errorcode} = $errorcode; + } + + addPageContent($JSON->encode($json)); + sendResponseMsg($httpcode); +} + + +# if debugging, output the given string +sub debug { + if (!$DEBUGGING) { return; } + addPageContent($q->p("DEBUG: $_[0]\n")); +} + +# when having bugs that cause this cgi to not produce any output, output something and then exit. +sub debugandexit { + debug("$_[0]\n"); + sendResponseMsg($STATUS_OK); +} + +sub displaydebugmsg { + addPageContent($q->p("DEBUG: generalparams:". Dumper($generalparams))); + addPageContent($q->p("DEBUG: paramhash:". Dumper($paramhash))); + addPageContent($q->p("DEBUG: q->request_method: $requestType\n")); + #addPageContent($q->p("DEBUG: q->user_agent: $userAgent\n")); + addPageContent($q->p("DEBUG: pathInfo: $pathInfo\n")); + #addPageContent($q->p("DEBUG: path " . Dumper(@path) . "\n")); + #foreach (keys(%ENV)) { addPageContent($q->p("DEBUG: ENV{$_}: $ENV{$_}\n")); } + #addPageContent($q->p("DEBUG: userName=".$paramhash->{userName}.", password=".$paramhash->{password}."\n")); + #addPageContent($q->p("DEBUG: http() values:\n" . http() . "\n")); + #if ($pdata) { addPageContent($q->p("DEBUG: pdata: $pdata\n")); } + addPageContent("\n"); + if ($DEBUGGING == 3) { + sendResponseMsg($STATUS_OK); # this will also exit + } +} + + +# push flags (options) onto the xcatd request. Arguments: request args array, flags array. +# Format of flags array: +# Use this function for cmds with a lot of flags like xdcp and xdsh +sub pushFlags { + my ($args, $flags) = @_; + foreach my $f (@$flags) { + my ($key, $flag, $arg) = @$f; + if (defined($paramhash->{$key})) { + push @$args, $flag; + if ($arg) { push @$args, $paramhash->{$key}; } + } + } +} + + diff --git a/xCAT-test/autotest/testcase/chdef/cases0 b/xCAT-test/autotest/testcase/chdef/cases0 index 1b2a35d09..f3ad24b73 100644 --- a/xCAT-test/autotest/testcase/chdef/cases0 +++ b/xCAT-test/autotest/testcase/chdef/cases0 @@ -22,21 +22,6 @@ cmd:rmdef -t node testnode check:rc==0 end -start:chdef_group_p -cmd:chdef abcnode1 -p groups=abc -check:rc==0 -cmd:chdef abcnode2 -p groups=abcabc -check:rc==0 -cmd:chdef -t group abc members=abcnode2 -check:rc==0 -cmd:nodels abc -check:output!~abcnode1 -check:output=~abcnode2 -cmd:rmdef abcnode1 -cmd:rmdef abcnode2 -end - - start:chdef_t_network description:chdef -t network cmd:chdef -t network -o testnetwork net=111.222.33.0 mask=255.255.255.254 @@ -130,6 +115,23 @@ cmd:rmdef -t node -o testnode1-testnode4 check:rc==0 end + +start:chdef_group_p +cmd:chdef abcnode1 -p groups=abc +check:rc==0 +cmd:chdef abcnode2 -p groups=abcabc +check:rc==0 +cmd:chdef -t group abc members=abcnode2 +check:rc==0 +cmd:nodels abc +check:output!~abcnode1 +check:output=~abcnode2 +cmd:rmdef abcnode1 +cmd:rmdef abcnode2 +end + + + start:chdef_dynamic_group description:chdef with dynamic node group cmd:mkdef -t node -o testnode1-testnode2 mgt=hmc cons=hmc groups=all,systemp diff --git a/xCAT-test/autotest/testcase/installation/linux_cn_with_sn_diskless_installation_x86_64_redhat b/xCAT-test/autotest/testcase/installation/linux_cn_with_sn_diskless_installation_x86_64_redhat index f653f99be..d0a67d785 100644 --- a/xCAT-test/autotest/testcase/installation/linux_cn_with_sn_diskless_installation_x86_64_redhat +++ b/xCAT-test/autotest/testcase/installation/linux_cn_with_sn_diskless_installation_x86_64_redhat @@ -30,6 +30,8 @@ cmd:xdsh $$SN df|grep /install;if [ $? -ne 0 ] ;then xdsh $$SN mount $$MN:/insta check:rc==0 cmd:nodeset $$CNWITHSN osimage=__GETNODEATTR($$CNWITHSN,os)__-__GETNODEATTR($$CNWITHSN,arch)__-netboot-compute check:rc==0 +cmd:rsetboot $$CNWITHSN net +check:rc==0 cmd:rpower $$CNWITHSN reset check:rc==0 cmd:sleep 200 @@ -52,6 +54,8 @@ check:rc==0 check:output=~\d\d:\d\d:\d\d cmd:nodeset $$CNWITHSN netboot check:rc==0 +cmd:rsetboot $$CNWITHSN net +check:rc==0 cmd:rpower $$CNWITHSN reset check:rc==0 cmd:sleep 200 diff --git a/xCAT-test/autotest/testcase/installation/linux_diskless_installation b/xCAT-test/autotest/testcase/installation/linux_diskless_installation index d1b2bea77..8665f6588 100644 --- a/xCAT-test/autotest/testcase/installation/linux_diskless_installation +++ b/xCAT-test/autotest/testcase/installation/linux_diskless_installation @@ -2,7 +2,7 @@ start:Linux_diskless_installation_flat_ppc64 os:Linux cmd:rscan __GETNODEATTR($$CN,hcp)__ -w check:rc==0 -cmd:makedns -n +cmd:makedns check:rc==0 cmd:service named restart check:rc==0 @@ -25,7 +25,7 @@ cmd:copycds $$ISO check:rc==0 cmd:genimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute check:rc==0 -cmd:packimage -o __GETNODEATTR($$CN,os)__ -p compute -a __GETNODEATTR($$CN,arch)__ +cmd:packimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute check:rc==0 cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/linux_diskless_installation_x86_64_sles b/xCAT-test/autotest/testcase/installation/linux_diskless_installation_x86_64_sles new file mode 100644 index 000000000..17a87bdf9 --- /dev/null +++ b/xCAT-test/autotest/testcase/installation/linux_diskless_installation_x86_64_sles @@ -0,0 +1,55 @@ +start:Linux_diskless_installation_flat_x86_64_sles +os:Linux +cmd:makedns -n +check:rc==0 +cmd:service named restart +check:rc==0 +cmd:makeconservercf $$CN +check:rc==0 +cmd:cat /etc/conserver.cf | grep $$CN +check:output=~$$CN +cmd:sleep 60 +cmd:makedhcp -n +check:rc==0 +cmd:makedhcp -a +check:rc==0 +cmd:service dhcpd restart +check:rc==0 +cmd:cat /var/lib/dhcp/db/dhcpd.leases| grep $$CN +check:output=~$$CN +cmd:if [ ! -d /install/custom/netboot/sles ]; then mkdir -p /install/custom/netboot/sles; fi +check:rc==0 +cmd:if [ ! -e /install/custom/netboot/sles/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/sles/compute.synclist; fi +check:rc==0 +cmd:chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-__GETNODEATTR($$CN,provmethod)__-__GETNODEATTR($$CN,profile)__ synclists=/install/custom/netboot/sles/compute.synclist +cmd:rm -rf /install/netboot/__GETNODEATTR($$CN,os)__/x86_64/compute +check:rc==0 +cmd:genimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute +check:rc==0 +cmd:packimage -o __GETNODEATTR($$CN,os)__ -p compute -a __GETNODEATTR($$CN,arch)__ +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute +check:rc==0 +cmd:rsetboot $$CN net +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 200 +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:nodeset $$CN osimage +check:rc==0 +cmd:rsetboot $$CN net +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 200 +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +end diff --git a/xCAT-test/autotest/testcase/installation/linux_full_installation b/xCAT-test/autotest/testcase/installation/linux_full_installation index 7c0850c8a..3a404c656 100644 --- a/xCAT-test/autotest/testcase/installation/linux_full_installation +++ b/xCAT-test/autotest/testcase/installation/linux_full_installation @@ -2,7 +2,7 @@ start:Linux_full_installation_flat_ppc64 os:Linux cmd:rscan __GETNODEATTR($$CN,hcp)__ -w check:rc==0 -cmd:makedns -n +cmd:makedns check:rc==0 cmd:service named restart check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/linux_full_installation_x86_64_sles b/xCAT-test/autotest/testcase/installation/linux_full_installation_x86_64_sles new file mode 100644 index 000000000..a14c5da1a --- /dev/null +++ b/xCAT-test/autotest/testcase/installation/linux_full_installation_x86_64_sles @@ -0,0 +1,48 @@ +start:Linux_full_installation_flat_x86_64_sles +os:Linux +cmd:makedns -n +check:rc==0 +cmd:service named restart +check:rc==0 +cmd:makeconservercf $$CN +check:rc==0 +cmd:cat /etc/conserver.cf | grep $$CN +check:output=~$$CN +cmd:sleep 60 +cmd:makedhcp -n +check:rc==0 +cmd:makedhcp -a +check:rc==0 +cmd:service dhcpd restart +check:rc==0 +cmd:chdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute synclists=/install/custom/install/sles/compute.synclist +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rsetboot $$CN net +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 2000 +cmd:ping $$CN -c 3 +check:output=~64 bytes from $$CN +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:nodeset $$CN osimage +check:rc==0 +cmd:rsetboot $$CN net +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 2000 +cmd:ping $$CN -c 3 +check:output=~64 bytes from $$CN +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +end diff --git a/xCAT-test/autotest/testcase/installation/linux_sn_installation_x86_64_redhat b/xCAT-test/autotest/testcase/installation/linux_sn_installation_x86_64_redhat new file mode 100644 index 000000000..66815d00e --- /dev/null +++ b/xCAT-test/autotest/testcase/installation/linux_sn_installation_x86_64_redhat @@ -0,0 +1,53 @@ +#first define +start:Linux_sn_installation_flat_x86_64_redhat +os:Linux +cmd:makedns -n +check:rc==0 +cmd:chdef $$SN groups=service,all +check:rc==0 +cmd:chdef -t group service arch=__GETNODEATTR($$SN,arch)__ os=__GETNODEATTR($$SN,os)__ profile=service netboot=xnba primarynic=eth0 +check:rc==0 +cmd:chdef -t group -o service setupnfs=1 setupdhcp=1 setuptftp=1 setupnameserver=1 setupconserver=1 +check:rc==0 +cmd:chdef $$SN nfsserver=$$MN tftpserver=$$MN xcatmaster=$$MN +check:rc==0 +cmd:makeconservercf +check:rc==0 +cmd:cat /etc/conserver.cf | grep $$SN +check:output=~$$SN +cmd:sleep 60 +cmd:makedhcp -n +cmd:makedhcp -a +check:rc==0 +cmd:service dhcpd restart +check:rc==0 +cmd:chdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-service synclists=/install/custom/install/rh/service.synclist +check:rc==0 +cmd:chdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-service otherpkglist=/opt/xcat/share/xcat/install/rh/service.rhels6.x86_64.otherpkgs.pkglist +check:rc==0 +cmd:mkdir -p /install/post/otherpkgs/__GETNODEATTR($$CN,os)__/x86_64/xcat/ +check:rc==0 +cmd:cp -rf /xcat-core /install/post/otherpkgs/__GETNODEATTR($$CN,os)__/x86_64/xcat/ +check:rc==0 +cmd:createrepo /install/post/otherpkgs/__GETNODEATTR($$CN,os)__/x86_64/xcat/xcat-core +check:rc==0 +cmd:for i in mysql-server mysql mysql-bench mysql-devel mysql-connector-odbc; do cat /opt/xcat/share/xcat/install/rh/service.rhels6.x86_64.pkglist|grep "$i$";if [ $? -ne 0 ] ; then echo "$i" >> /opt/xcat/share/xcat/install/rh/service.rhels6.x86_64.pkglist; fi done +cmd:chtab node=service postscripts.postscripts="servicenode,odbcsetup" +check:rc==0 +cmd:nodeset $$SN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-service +check:rc==0 +cmd:rsetboot $$SN net +check:rc==0 +cmd:rpower $$SN reset +check:rc==0 +cmd:sleep 700 +cmd:ping $$SN -c 3 +check:output=~64 bytes from $$SN +cmd:lsdef -l $$SN | grep status +check:output=~booted +cmd:xdsh $$SN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:xdsh $$SN nodels +check:rc==0 +end diff --git a/xCAT-test/autotest/testcase/installation/linux_sn_installation_x86_64_sles b/xCAT-test/autotest/testcase/installation/linux_sn_installation_x86_64_sles new file mode 100644 index 000000000..74600f1e7 --- /dev/null +++ b/xCAT-test/autotest/testcase/installation/linux_sn_installation_x86_64_sles @@ -0,0 +1,53 @@ +#first define +start:Linux_sn_installation_flat_x86_64_sles +os:Linux +cmd:makedns -n +check:rc==0 +cmd:chdef $$SN groups=ipmi,service,all +check:rc==0 +cmd:chdef -t group service arch=__GETNODEATTR($$SN,arch)__ os=__GETNODEATTR($$SN,os)__ profile=service netboot=xnba primarynic=eth0 +check:rc==0 +cmd:chdef -t group -o service setupnfs=1 setupdhcp=1 setuptftp=1 setupnameserver=1 setupconserver=1 +check:rc==0 +cmd:chdef $$SN nfsserver=$$MN tftpserver=$$MN xcatmaster=$$MN +check:rc==0 +cmd:makeconservercf +check:rc==0 +cmd:cat /etc/conserver.cf | grep $$SN +check:output=~$$SN +cmd:sleep 60 +cmd:makedhcp -n +cmd:makedhcp -a +check:rc==0 +cmd:service dhcpd restart +check:rc==0 +cmd:chdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-service synclists=/install/custom/install/sles/service.synclist +check:rc==0 +cmd:chdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-service otherpkglist=/opt/xcat/share/xcat/install/sles/service.sles11.x86_64.otherpkgs.pkglist +check:rc==0 +cmd:mkdir -p /install/post/otherpkgs/sles11.2/x86_64/xcat/ +check:rc==0 +cmd:cp -rf /xcat-core /install/post/otherpkgs/sles11.2/x86_64/xcat/ +check:rc==0 +cmd:createrepo /install/post/otherpkgs/sles11.2/x86_64/xcat/xcat-core +check:rc==0 +cmd:for i in mysql-client libmysqlclient_r15 libqt4-sql-mysql libmysqlclient15 perl-DBD-mysql mysql iscsi-initiator-utils bridge-utils kvm perl-Sys-Virt; do cat /opt/xcat/share/xcat/install/sles/service.sles11.pkglist|grep "$i$";if [ $? -ne 0 ] ; then echo "$i" >> /opt/xcat/share/xcat/install/sles/service.sles11.pkglist; fi done +cmd:chtab node=service postscripts.postscripts="servicenode,odbcsetup" +check:rc==0 +cmd:nodeset $$SN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-service +check:rc==0 +cmd:rsetboot $$SN net +check:rc==0 +cmd:rpower $$SN reset +check:rc==0 +cmd:sleep 3000 +cmd:ping $$SN -c 3 +check:output=~64 bytes from $$SN +cmd:lsdef -l $$SN | grep status +check:output=~booted +cmd:xdsh $$SN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:xdsh $$SN nodels +check:rc==0 +end diff --git a/xCAT-test/autotest/testcase/makedns/cases0 b/xCAT-test/autotest/testcase/makedns/cases0 index a29e768a4..79f63c786 100644 --- a/xCAT-test/autotest/testcase/makedns/cases0 +++ b/xCAT-test/autotest/testcase/makedns/cases0 @@ -7,71 +7,1192 @@ check:rc==0 check:output=~Usage end -start:makedns_v -description:version -cmd:makedns -v -check:rc==0 -check:output=~Version -end - start:makedns_d_node -description:makedns -d nodename -cmd:makedns -n +description:makedns -d noderange +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 check:rc==0 -cmd:nslookup $$CN -check:output!~(server can't find $$CN) -cmd:makedns -d $$CN +cmd:chdef -t node -o dnstestnode groups=all ip=100.100.100.1 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:makedns dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:makedns -d dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:rmdef -t node dnstestnode +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n check:rc==0 -check:output=~(Completed updating zones) -check:output=~(DNS setup is completed) -cmd:nslookup $$CN -check:output=~(server can't find $$CN) end start:makedns_node -description:makedns nodename -cmd:makedns -d $$CN -check:rc=0 -cmd:nslookup $$CN -check:output=~(server can't find $$CN) -cmd:makedns $$CN +description:makedns noderange +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:chdef -t node -o dnstestnode groups=all ip=100.100.100.1 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:makedns dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:makedns -d dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:rmdef -t node dnstestnode +check:rc==0 +cmd:chtab -d netname=testnetwork networks check:rc==0 -check:output=~(Completed updating zones) -check:output=~(DNS setup is completed) -cmd:nslookup $$CN -check:output!~(server can't find $$CN) -end - - - -start:makedns_n -description:makedns -cmd:makedns -d $$CN -cmd:nslookup $$CN -check:output=~(server can't find $$CN) cmd:makedns -n check:rc==0 -check:output=~(Completed updating zones) -check:output=~(DNS setup is completed) -cmd:nslookup $$CN -check:output!~(server can't find $$CN) end +start:makedns_n +description:makedns -n +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +end start:makedns description:makedns -os:Linux -cmd:makedns -d $$CN +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:rm -f /tmp/makedns_named_conf.org /tmp/makedns_named_conf.new +check:rc==0 +cmd:cat /etc/named.conf > /tmp/makedns_named_conf.org +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts check:rc==0 -cmd:nslookup $$CN -check:output=~(server can't find $$CN) cmd:makedns check:rc==0 -check:output=~(Completed updating zones) -check:output=~(DNS setup is completed) -cmd:service named stop -cmd:service named start -cmd:nslookup $$CN -check:output!~(server can't find $$CN) +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:cat /etc/named.conf > /tmp/makedns_named_conf.old +check:rc==0 +cmd:diff /tmp/makedns_named_conf.org /tmp/makedns_named_conf.old +check:rc==0 +check:output~= +cmd:rm -f /tmp/makedns_named_conf.org /tmp/makedns_named_conf.new +check:rc==0 +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) end +#------------------------------------ +start:makedns_environment_check_forworder_mode +description:check basic environment of makedns in hierarchical arch and sn acts forworder +os:rhels +cmd:chtab key=nameservers site.value="" +check:rc==0 +cmd:chdef service setupnameserver=1 setupdhcp=1 +check:rc==0 +cmd:tabdump servicenode +check:rc==0 +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +cmd:more /etc/resolv.conf |grep nameserver +cmd:xdsh $$SN "more /etc/resolv.conf |grep nameserver" +cmd:xdsh $$CN "more /etc/resolv.conf |grep nameserver" +cmd:more /etc/dhcp/dhcpd.conf |grep domain-name-servers +cmd:xdsh $$SN "more /etc/dhcp/dhcpd.conf|grep domain-name-servers" +cmd:tabdump site|grep nameservers +cmd:tabdump networks +cmd:lsdef $$SN -i setupnameserver |grep setupnameserver +check:rc==0 +check:output~=1 +cmd:lsdef $$SN -i setupdhcp |grep setupdhcp +check:rc==0 +check:output~=1 +cmd:service named status +check:rc==0 +check:output~=running +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:xdsh $$SN "more /etc/named.conf" +check:rc==0 +check:output~=forward only +cmd:nslookup $$SN $$MN +check:output~=Server: $$MN +check:output!~(server can't find $$SN) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +end + +start:makedns_environment_check_forworder_mode +description:check basic environment of makedns in hierarchical arch and sn acts forworder +os:sles +cmd:chtab key=nameservers site.value="" +check:rc==0 +cmd:chdef service setupnameserver=1 setupdhcp=1 +check:rc==0 +cmd:tabdump servicenode +check:rc==0 +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +cnd:output~=running +cmd:more /etc/resolv.conf |grep nameserver +cmd:xdsh $$SN "more /etc/resolv.conf |grep nameserver" +cmd:xdsh $$CN "more /etc/resolv.conf |grep nameserver" +cmd:more /etc/dhcpd.conf|grep domain-name-servers +cmd:xdsh $$SN "more /etc/dhcpd.conf|grep domain-name-servers" +cmd:tabdump site|grep nameservers +cmd:tabdump networks +cmd:lsdef $$SN -i setupnameserver|grep setupnameserver +check:rc==0 +check:output~=1 +cmd:lsdef $$SN -i setupdhcp|grep setupdhcp +check:rc==0 +check:output~=1 +cmd:service named status +check:rc==0 +check:output~=running +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:xdsh $$SN "more /etc/named.conf" +check:rc==0 +check:output~=forward only +cmd:nslookup $$SN $$MN +check:output~=Server: $$MN +check:output!~(server can't find $$SN) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +end + + +start:makedns_environment_check_forworder_mode +description:check basic environment of makedns in hierarchical arch and sn acts forworder +os:AIX +cmd:chtab key=nameservers site.value="" +check:rc==0 +cmd:chdef service setupnameserver=1 setupdhcp=1 +check:rc==0 +cmd:tabdump servicenode +check:rc==0 +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:more /etc/resolv.conf|grep nameserver +check:rc==0 +cmd:xdsh $$SN "more /etc/resolv.conf|grep nameserver" +check:rc==0 +cmd:xdsh $$CN "more /etc/resolv.conf|grep nameserver" +cmd:tabdump site|grep nameservers +check:rc==0 +cmd:tabdump networks +check:rc==0 +cmd:lsdef $$SN -i setupnameserver|grep setupnameserver +check:rc==0 +check:output~=1 +cmd:lsdef $$SN -i setupdhcp|grep setupdhcp +check:rc==0 +check:output~=1 +cmd:lssrc -s named +check:output~=active +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "lssrc -s named" +check:output~=active +cmd:xdsh $$SN "more /etc/named.conf" +check:rc==0 +check:output~=forward only +cmd:nslookup $$SN $$MN +check:output~=Server: $$MN +check:output!~(server can't find $$SN) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +end + + +start:makedns_environment_check_master_slave_mode +description:check basic environment of makedns in hierarchical arch and sn acts slave +os:rhels +cmd:chtab key=nameservers site.value=",$$MNIP" +check:rc==0 +cmd:chdef service setupnameserver=2 setupdhcp=1 +check:rc==0 +cmd:tabdump servicenode +check:rc==0 +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +cmd:more /etc/resolv.conf|grep nameserver +check:rc==0 +cmd:xdsh $$SN "more /etc/resolv.conf|grep nameserver" +check:rc==0 +cmd:xdsh $$CN "more /etc/resolv.conf|grep nameserver" +cmd:more /etc/dhcp/dhcpd.conf |grep domain-name-servers +check:rc==0 +cmd:xdsh $$SN "more /etc/dhcp/dhcpd.conf|grep domain-name-servers" +check:rc==0 +cmd:tabdump site|grep nameservers +check:rc==0 +cmd:tabdump networks +check:rc==0 +cmd:lsdef $$SN -i setupnameserver|grep setupnameserver +check:rc==0 +check:output~=2 +cmd:lsdef $$SN -i setupdhcp|grep setupdhcp +check:rc==0 +check:output~=1 +cmd:service named status +check:output~=running +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named status" +check:output~=running +cmd:xdsh $$SN "more /etc/named.conf" +check:rc==0 +check:output~=type slave +cmd:nslookup $$SN $$MN +check:output~=Server: $$MN +check:output!~(server can't find $$SN) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +end + +start:makedns_environment_check_master_slave_mode +description:check basic environment of makedns in hierarchical arch and sn acts slave +os:sles +cmd:chtab key=nameservers site.value=",$$MNIP" +check:rc==0 +cmd:chdef service setupnameserver=2 setupdhcp=1 +check:rc==0 +cmd:tabdump servicenode +check:rc==0 +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +cmd:more /etc/resolv.conf|grep nameserver +check:rc==0 +cmd:xdsh $$SN "more /etc/resolv.conf|grep nameserver" +check:rc==0 +cmd:xdsh $$CN "more /etc/resolv.conf|grep nameserver" +cmd:more /etc/dhcpd.conf|grep domain-name-servers +check:rc==0 +cmd:xdsh $$SN "more /etc/dhcpd.conf|grep domain-name-servers" +check:rc==0 +cmd:tabdump site|grep nameservers +check:rc==0 +cmd:tabdump networks +check:rc==0 +cmd:lsdef $$SN -i setupnameserver|grep setupnameserver +check:rc==0 +check:output~=2 +cmd:lsdef $$SN -i setupdhcp|grep setupdhcp +check:rc==0 +check:output~=1 +cmd:service named status +check:output~=running +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named status" +check:output~=running +cmd:xdsh $$SN "more /etc/named.conf" +check:rc==0 +check:output~=type slave +cmd:nslookup $$SN $$MN +check:output~=Server: $$MN +check:output!~(server can't find $$SN) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +end + +start:makedns_environment_check_master_slave_mode +description:check basic environment of makedns in hierarchical arch and sn acts slave +os:AIX +cmd:chtab key=nameservers site.value=",$$MNIP" +check:rc==0 +cmd:chdef service setupnameserver=2 setupdhcp=1 +check:rc==0 +cmd:tabdump servicenode +check:rc==0 +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:more /etc/resolv.conf|grep nameserver +check:rc==0 +cmd:xdsh $$SN "more /etc/resolv.conf|grep nameserver" +check:rc==0 +cmd:xdsh $$CN "more /etc/resolv.conf|grep nameserver" +cmd:tabdump site|grep nameservers +check:rc==0 +cmd:tabdump networks +check:rc==0 +cmd:lsdef $$SN -i setupnameserver|grep setupnameserver +check:rc==0 +check:output~=2 +cmd:lsdef $$SN -i setupdhcp|grep setupdhcp +check:rc==0 +check:output~=1 +cmd:lssrc -s named +check:output~=active +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "lssrc -s named" +check:output~=active +cmd:xdsh $$SN "more /etc/named.conf" +check:rc==0 +check:output~=type slave +cmd:nslookup $$SN $$MN +check:output~=Server: $$MN +check:output!~(server can't find $$SN) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +end +#--------------------------------------------------------------------- + +start:makedns_when_nameserver_on_mn_down +description:when nameserver on mn down, nameserver on sn should provide service +os:rhels +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:rc==0 +check:output~=running +cmd:nslookup dnstestnode $$MN +check:rc==0 +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:rc==0 +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:service named stop +check:rc==0 +cmd:service named status +check:output~=stopped +cmd:nslookup dnstestnode $$MN +check:rc!=0 +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:rc==0 +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:service named start +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +end + +start:makedns_when_nameserver_on_mn_down +description:when nameserver on mn down, nameserver on sn should provide service +os:sles +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:rc==0 +check:output~=running +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:service named stop +check:rc==0 +cmd:service named status +check:output~=unused +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:service named start +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:output~=running +end + +start:makedns_when_nameserver_on_mn_down +description:when nameserver on mn down, nameserver on sn should provide service +os:AIX +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:lssrc -s named +check:output~=active +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:sleep 5 +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:stopsrc -s named +check:rc==0 +cmd:sleep 3 +cmd:lssrc -s named +check:output~=inoperative +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:sleep 5 +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:startsrc -s named +check:rc==0 +cmd:lssrc -a |grep named +check:rc==0 +check:output~=active +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +end + +start:makedns_when_nameserver_on_sn_down +description:when nameserver on sn down, nameserver on mn should provide service +os:rhels +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:rc==0 +check:output~=running +cmd:nslookup dnstestnode $$MN +check:rc==0 +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:rc==0 +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named stop" +check:rc==0 +cmd:xdsh $$SN "service named status" +check:rc!=0 +check:output~=stopped +cmd:nslookup dnstestnode $$MN +check:rc==0 +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:rc!=0 +check:output~=Server: $$SN +check:output~=(server can't find dnstestnode) +cmd:xdsh $$SN "service named start" +check:rc==0 +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:rc==0 +check:output~=running +end + +start:makedns_when_nameserver_on_sn_down +description:when nameserver on sn down, nameserver on mn should provide service +os:sles +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:rc==0 +check:output~=running +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named stop" +check:rc==0 +cmd:xdsh $$SN "service named status" +check:output~=unused +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output~=(server can't find dnstestnode) +cmd:xdsh $$SN "service named start" +check:rc==0 +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "service xcatd status" +check:rc==0 +check:output~=running +end + + +start:makedns_when_nameserver_on_sn_down +description:when nameserver on sn down, nameserver on mn should provide service +os:AIX +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.testbak +check:rc==0 +cmd:echo "100.100.100.1 dnstestnode" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:lssrc -s named +check:output~=active +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:sleep 10 +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "stopsrc -s named" +check:rc==0 +cmd:xdsh $$SN "lssrc -s named" +check:rc==0 +check:output~=inoperative +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:sleep 5 +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output~=(server can't find dnstestnode) +cmd:xdsh $$SN "startsrc -s named" +check:rc==0 +cmd:xdsh $$SN "lssrc -s named" +check:rc==0 +check:output~=active +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.testbak /etc/hosts +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +end + +#999999999999999999999999999 +start:makedns_nameserver_on_sn_sync_db +description:when nameserver's db on mn was changed, nameserver's db on sn should be synchronized +os:Linux +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:chdef -t node -o dnstestnode groups=all ip=100.100.100.2 +check:rc==0 +cmd:makedns dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:rc==0 +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:sleep 2 +cmd:nslookup dnstestnode $$SN +check:rc==0 +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:makedns -d dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:sleep 2 +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output~=(server can't find dnstestnode) +cmd:rmdef -t node dnstestnode +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +end + + +start:makedns_nameserver_on_sn_sync_db +description:when nameserver's db on mn was changed, nameserver's db on sn should be synchronized +os:AIX +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:chdef -t node -o dnstestnode groups=all ip=100.100.100.2 +check:rc==0 +cmd:makedns dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:rc==0 +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:sleep 2 +cmd:nslookup dnstestnode $$SN +check:rc==0 +check:output~=Server: $$SN +check:output!~(server can't find dnstestnode) +cmd:makedns -d dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:output~=Server: $$MN +check:output~=(server can't find dnstestnode) +cmd:sleep 2 +cmd:nslookup dnstestnode $$SN +check:output~=Server: $$SN +check:output~=(server can't find dnstestnode) +cmd:rmdef -t node dnstestnode +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active + +end + +start:makedns_nameserver_on_sn_sync_conf +description:when nameserver's conf file on mn was changed, nameserver's conf file on sn should be synchronized when xcatd restart +os:Linux +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "service xcatd restart" +check:rc==0 +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output!~=zone "100.100.100.IN-ADDR.ARPA." +end + +start:makedns_nameserver_on_sn_sync_conf +description:when nameserver's conf file on mn was changed, nameserver's conf file on sn should be synchronized when xcatd restart +os:AIX +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:chtab -d netname=testnetwork networks +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:cat /etc/named.conf +check:rc==0 +check:output!~zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output~=zone "100.100.100.IN-ADDR.ARPA." +cmd:xdsh $$SN "stopsrc -s xcatd" +check:rc==0 +cmd:sleep 5 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=inoperative +cmd:xdsh $$SN "startsrc -s xcatd" +check:rc==0 +cmd:sleep 10 +cmd:xdsh $$SN "lssrc -s xcatd" +check:output~=active +cmd:xdsh $$SN "cat /etc/named.conf" +check:rc==0 +check:output!~=zone "100.100.100.IN-ADDR.ARPA." +end + +start:makedns_nameserver_on_sn_sync_db_when_sn_down +description:when nameserver's db on mn was changed and name server on SN down at the same time, when name server on SN restart, it should sync the latest name server db on MN +os:rhels +cmd:makedns -n +check:rc==0 +cmd:service named status +check:rc==0 +check:output~=running +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:chtab netname=testnetwork networks.net=100.100.100.0 networks.mask=255.255.255.0 networks.mgtifname=eth0 networks.gateway=100.100.100.254 +check:rc==0 +cmd:chdef -t node -o dnstestnode groups=all ip=100.100.100.2 +check:rc==0 +cmd:xdsh $$SN "service named stop" +check:rc==0 +cmd:makedns dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:rc==0 +check:output~=Server: $$MN +check:output!~(server can't find dnstestnode) +cmd:xdsh $$SN "service named start" +check:rc==0 +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:sleep 2 +cmd:nslookup dnstestnode $$SN +check:rc==0 +check:output~=Server: $$SN +check:output!~(server can't find $$CN) +cmd:xdsh $$SN "service named stop" +check:rc==0 +cmd:makedns -d dnstestnode +check:rc==0 +cmd:nslookup dnstestnode $$MN +check:rc!=0 +check:output~=Server: $$MN +check:output~=(server can't find $$CN) +cmd:xdsh $$SN "service named start" +check:rc==0 +cmd:xdsh $$SN "service named status" +check:rc==0 +check:output~=running +cmd:sleep 2 +cmd:nslookup dnstestnode $$SN +check:rc!=0 +cmd:rmdef -t node dnstestnode +check:rc==0 +cmd:chtab -d netname=testnetwork networks +check:rc==0 +end + + + + + + + + + diff --git a/xCAT-test/autotest/testcase/makeroutes/cases0 b/xCAT-test/autotest/testcase/makeroutes/cases0 new file mode 100644 index 000000000..b15b4fa4a --- /dev/null +++ b/xCAT-test/autotest/testcase/makeroutes/cases0 @@ -0,0 +1,89 @@ +start:makeroutes_h +cmd:makeroutes -h +check:rc==0 +check:output=~Usage +end + +start:makeroutes_v +cmd:makeroutes -v +check:rc==0 +check:output=~Version +end + +start:makeroutes_r_d_node +cmd:chtab routename=testr routes.net=10.1.0.0 routes.mask=255.255.0.0 routes.gateway=10.1.254.254 +check:rc==0 +cmd: makeroutes $$CN -r testr +check:rc==0 +cmd:xdsh $$CN route +check:rc==0 +check:output=~10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd: makeroutes $$CN -d -r testr +check:rc==0 +cmd:xdsh $$CN route +check:rc==0 +check:output!=10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd:chtab -d routename=testr routes +check:rc==0 +end + + +start:makeroutes_r_d +cmd:chtab routename=testr routes.net=10.1.0.0 routes.mask=255.255.0.0 routes.gateway=10.1.254.254 +check:rc==0 +cmd: makeroutes -r testr +check:rc==0 +cmd:route +check:rc==0 +check:output=~10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd: makeroutes -d -r testr +check:rc==0 +cmd:route +check:rc==0 +check:output!=10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd:chtab -d routename=testr routes +check:rc==0 +end + + +start:makeroutes_use_site_mnroutenames +cmd:chtab routename=testr routes.net=10.1.0.0 routes.mask=255.255.0.0 routes.gateway=10.1.254.254 +check:rc==0 +cmd:chtab key=mnroutenames site.value=testr +check:rc==0 +cmd: makeroutes +check:rc==0 +cmd:route +check:rc==0 +check:output=~10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd: makeroutes -d +check:rc==0 +cmd:route +check:rc==0 +check:output!=10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd:chtab -d key=mnroutenames site +check:rc==0 +cmd:chtab -d routename=testr routes +check:rc==0 +end + +start:makeroutes_use_noderes_routenames +cmd:chtab routename=testr routes.net=10.1.0.0 routes.mask=255.255.0.0 routes.gateway=10.1.254.254 +check:rc==0 +cmd:chtab node=$$CN noderes.routenames=testr +check:rc==0 +cmd: makeroutes $$CN +check:rc==0 +cmd:xdsh $$CN route +check:rc==0 +check:output=~10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd: makeroutes $$CN -d +check:rc==0 +cmd:xdsh $$CN route +check:rc==0 +check:output!=10.1.0.0\s*10.1.254.254\s*255.255.0.0 +cmd:chtab node=$$CN noderes.routenames= +check:rc==0 +cmd:chtab -d routename=testr routes +check:rc==0 +end diff --git a/xCAT-test/autotest/testcase/ppping/cases0 b/xCAT-test/autotest/testcase/ppping/cases0 new file mode 100644 index 000000000..133c6240a --- /dev/null +++ b/xCAT-test/autotest/testcase/ppping/cases0 @@ -0,0 +1,100 @@ +start:ppping_h +cmd:ppping -h +check:rc==0 +check:output=~Usage +end + +start:ppping_v +cmd:ppping -v +check:rc==0 +check:output=~Version +end + +start:ppping_node +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:ppping $$CN +check:rc==0 +check:output=~$$CN: pinged all nodes successfully +end + +start:ppping_V_node +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:ppping -V $$CN +check:rc==0 +check:output=~$$CN: $$CN: ping +end + +start:ppping_q_node +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:ppping -q $$CN +check:rc==0 +check:output=~ +end + +start:ppping_d_node +cmd:ppping -d $$CN +check:rc==0 +check:output=~[start] +check:output=~[stop] +end + +start:ppping_i_node +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:cp /etc/hosts /etc/hosts.bak +check:rc==0 +cmd:a=`cat /etc/hosts |grep ' $$CN.'|awk '{print $1}'`;b=`cat /etc/resolv.conf |grep search|awk '{print $2}'`;echo "$a $$CN-eth0.$b $$CN-eth0" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:ppping $$CN -i eth0 +check:rc==0 +check:output=~$$CN: pinged all nodes successfully on interface eth0 +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.bak /etc/hosts +check:rc==0 +end + +start:ppping_nodes +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:ping -c 3 $$SN > /dev/null 2>&1 +check:rc==0 +cmd:ppping $$SN,$$CN +check:rc==0 +check:output=~$$SN: pinged all nodes successfully +check:output=~$$CN: pinged all nodes successfully +end + +start:ppping_V_nodes +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:ping -c 3 $$SN > /dev/null 2>&1 +check:rc==0 +cmd:ppping -V $$SN,$$CN +check:rc==0 +check:output=~$$CN: $$CN: ping +check:output=~$$CN: $$SN: ping +check:output=~$$SN: $$SN: ping +check:output=~$$SN: $$CN: ping +end + + + +start:ppping_V_s_nodes +cmd:ping -c 3 $$CN > /dev/null 2>&1 +check:rc==0 +cmd:ping -c 3 $$SN > /dev/null 2>&1 +check:rc==0 +cmd:ppping -V -s $$SN,$$CN +check:rc==0 +check:output=~$$SN: $$SN: ping*\n$$SN: $$CN: ping*\n$$CN: $$SN: ping*\n$$CN: $$CN: ping +end + + + + diff --git a/xCAT-test/autotest/testcase/prsync/cases0 b/xCAT-test/autotest/testcase/prsync/cases0 new file mode 100644 index 000000000..babccfcf1 --- /dev/null +++ b/xCAT-test/autotest/testcase/prsync/cases0 @@ -0,0 +1,52 @@ +start:prsync_h +cmd:prsync -h +check:rc==0 +check:output=~Usage +end + +start:prsync_v +cmd:prsync -v +check:rc==0 +check:output=~Version +end + +start:prsync_dir_node +cmd: mkdir -p /tmp/pscp +check:rc==0 +cmd:echo "test" > /tmp/pscp/pscp.tmp +check:rc==0 +cmd:prsync -o "crz" /tmp/pscp $$CN:/tmp/ +check:rc==0 +check:$$CN: done +cmd:xdsh $$CN "ls -l /tmp |grep pscp" +check:rc==0 +check:output=~pscp +cmd:xdsh $$CN "ls -l /tmp/pscp |grep pscp.tmp" +check:rc==0 +check:output=~pscp.tmp +cmd:xdsh $$CN "cat /tmp/pscp/pscp.tmp" +check:rc==0 +check:output=~test +cmd:xdsh $$CN "rm -rf /tmp/pscp" +check:rc==0 +cmd:rm -rf /tmp/pscp +check:rc==0 +end + +start:prsync_file_node +cmd: echo "prsync-test" > prsync.test +check:rc==0 +cmd:prsync prsync.test $$CN:/tmp/ +check:rc==0 +check:$$CN: done +cmd:xdsh $$CN "ls -l /tmp |grep prsync.test" +check:rc==0 +check:output=~prsync.test +cmd:xdsh $$CN "cat /tmp/prsync.test" +check:rc==0 +check:output=~prsync-test +cmd:xdsh $$CN "rm -rf /tmp/prsync.test" +check:rc==0 +cmd:rm -rf prsync.test +check:rc==0 +end diff --git a/xCAT-test/autotest/testcase/pscp/cases0 b/xCAT-test/autotest/testcase/pscp/cases0 new file mode 100644 index 000000000..2d1e02b1a --- /dev/null +++ b/xCAT-test/autotest/testcase/pscp/cases0 @@ -0,0 +1,84 @@ +start:pscp_h +cmd:pscp -h +check:rc==0 +check:output=~Usage +end + +start:pscp_v +cmd:pscp -v +check:rc==0 +check:output=~Version +end + +#copy single file +start:pscp_node +cmd:echo "test" > /tmp/pscp.tmp +check:rc==0 +cmd:pscp /tmp/pscp.tmp $$CN:/tmp/ +check:rc==0 +check:$$CN: done +cmd:xdsh $$CN "ls -l /tmp |grep pscp.tmp" +check:rc==0 +check:output=~pscp.tmp +cmd:xdsh $$CN "cat /tmp/pscp.tmp" +check:rc==0 +check:output=~test +cmd:xdsh $$CN "rm -f /tmp/pscp.tmp" +check:rc==0 +cmd:rm -f /tmp/pscp.tmp +check:rc==0 +end + +#copy a directory +start:pscp_r_node +cmd: mkdir -p /tmp/pscp +check:rc==0 +cmd:echo "test" > /tmp/pscp/pscp.tmp +check:rc==0 +cmd:pscp -r /tmp/pscp $$CN:/tmp/ +check:rc==0 +check:$$CN: done +cmd:xdsh $$CN "ls -l /tmp |grep pscp" +check:rc==0 +check:output=~pscp +cmd:xdsh $$CN "ls -l /tmp/pscp |grep pscp.tmp" +check:rc==0 +check:output=~pscp.tmp +cmd:xdsh $$CN "cat /tmp/pscp/pscp.tmp" +check:rc==0 +check:output=~test +cmd:xdsh $$CN "rm -rf /tmp/pscp" +check:rc==0 +cmd:rm -rf /tmp/pscp +check:rc==0 +end + + +start:pscp_i_node +cmd:cp /etc/hosts /etc/hosts.bak +check:rc==0 +cmd:a=`cat /etc/hosts |grep ' $$CN.'|awk '{print $1}'`;b=`cat /etc/resolv.conf |grep search|awk '{print $2}'`;echo "$a $$CN-eth0.$b $$CN-eth0" >> /etc/hosts +check:rc==0 +cmd:makedns -n +check:rc==0 +cmd:echo "pscp" > /tmp/pscp.tmp +check:rc==0 +cmd:pscp -i eth0 /tmp/pscp.tmp $$CN:/tmp +check:rc==0 +check:output=~$$CN-eth0: done +cmd:xdsh $$CN "ls -l /tmp |grep pscp.tmp" +check:rc==0 +check:output=~pscp.tmp +cmd:xdsh $$CN "cat /tmp/pscp.tmp" +check:rc==0 +check:output=~pscp +cmd:xdsh $$CN "rm -rf /tmp/pscp.tmp" +check:rc==0 +cmd:rm -rf /tmp/pscp.tmp +check:rc==0 +cmd:rm -f /etc/hosts +check:rc==0 +cmd:mv /etc/hosts.bak /etc/hosts +check:rc==0 +end + diff --git a/xCAT-test/autotest/testcase/sysclone/cases0 b/xCAT-test/autotest/testcase/sysclone/cases0 new file mode 100644 index 000000000..f09bf7b0b --- /dev/null +++ b/xCAT-test/autotest/testcase/sysclone/cases0 @@ -0,0 +1,104 @@ +start:sysclone +cmd:makedns -n +check:rc==0 +cmd:makedhcp -n +check:rc==0 +cmd:makedhcp -a +check:rc==0 +cmd:makeconservercf $$GOLDEN_CLIENT +check:rc==0 +cmd:makeconservercf $$TARGET_NODE +check:rc==0 +cmd:copycds $$ISO +check:rc==0 + +cmd:yum -y install systemimager-server +check:rc==0 +cmd:lsdef +check:output=~$$GOLDEN_CLIENT +check:output=~$$TARGET_NODE +cmd:rpm -qa|grep perl-AppConfig +check:output=~perl-AppConfig[0-9.-]*noarch +cmd:rpm -qa|grep systemconfigurator +check:output=~systemconfigurator[0-9.-]*noarch +cmd:rpm -qa|grep systemimager-common +check:output=~systemimager-common[0-9.-]*noarch +cmd:rpm -qa|grep genisoimage +check:output=~genisoimage[0-9.-]*el6.x86_64 +cmd:rpm -qa|grep systemimager-server +check:output=~systemimager-server[0-9.-]*noarch + + +cmd:mkdir -p $$OTHERPKGDIR/xcat +check:rc==0 +cmd:cp $$XCAT_DEP_TARBALL_PATH/$$XCAT_DEP_TARBALL $$OTHERPKGDIR/xcat +check:rc==0 +cmd:cd $$OTHERPKGDIR/xcat && tar xvf $$XCAT_DEP_TARBALL +check:rc==0 +cmd:chdef -t osimage -o $$GOS-x86_64-install-compute -p otherpkgdir=$$OTHERPKGDIR +check:rc==0 +cmd:chdef -t osimage -o $$GOS-x86_64-install-compute otherpkglist=$$OTHERPKGLIST +check:rc==0 + +cmd:nodeset $$GOLDEN_CLIENT osimage=$$GOS-x86_64-install-compute +check:rc==0 +cmd:rsetboot $$GOLDEN_CLIENT net +check:rc==0 +cmd:rpower $$GOLDEN_CLIENT reset +check:rc==0 + +cmd:sleep 500 +cmd:a=0;while ! `lsdef -l $$GOLDEN_CLIENT|grep status|grep booted >/dev/null`; do sleep 10;((a++));if [ $a -gt 200 ];then break;fi done + +cmd:ping $$GOLDEN_CLIENT -c 3 +check:output=~64 bytes from $$GOLDEN_CLIENT +cmd:lsdef -l $$GOLDEN_CLIENT | grep status +check:output=~booted +cmd:xdsh $$GOLDEN_CLIENT date +check:rc==0 +check:output=~\d\d:\d\d:\d\d + + +cmd:xdsh $$GOLDEN_CLIENT "rpm -qa|grep systemimager-client" +check:output=~$$GOLDEN_CLIENT: systemimager-client* +cmd:xdsh $$GOLDEN_CLIENT "rpm -qa|grep perl-AppConfig" +check:output=~$$GOLDEN_CLIENT: perl-AppConfig* +cmd:xdsh $$GOLDEN_CLIENT "rpm -qa|grep systemconfigurator" +check:output=~$$GOLDEN_CLIENT: systemconfigurator* +cmd:xdsh $$GOLDEN_CLIENT "rpm -qa|grep systemimager-common" +check:output=~$$GOLDEN_CLIENT: systemimager-common* + +cmd:xdsh $$GOLDEN_CLIENT "cd /home && >test.file" +check:rc==0 +cmd:imgcapture $$GOLDEN_CLIENT -t sysclone -o goldenclient-osimage-$$GOS-$$MODE -V +check:rc==0 +cmd:lsdef -t osimage goldenclient-osimage-$$GOS-$$MODE| grep provmethod +check:output=~sysclone + +cmd:nodeset $$TARGET_NODE osimage=goldenclient-osimage-$$GOS-$$MODE +check:rc==0 +cmd:rsetboot $$TARGET_NODE net +check:rc==0 +cmd:rpower $$TARGET_NODE reset +check:rc==0 + +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$TARGET_NODE|grep status|grep booted >/dev/null`; do sleep 10;((a++));if [ $a -gt 60 ];then break;fi done + + +cmd:ping $$TARGET_NODE -c 3 +check:output=~64 bytes from $$TARGET_NODE +cmd:lsdef -l $$TARGET_NODE | grep status +check:output=~booted +cmd:xdsh $$TARGET_NODE date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:xdsh $$TARGET_NODE "ls -l /home" +check:output=~test.file +cmd:xdsh $$TARGET_NODE "hostname" +check:output=~$$TARGET_NODE: $$TARGET_NODE + +end + + + diff --git a/xCAT-test/autotest/testcase/xdcp/cases0 b/xCAT-test/autotest/testcase/xdcp/cases0 index c8bd2976e..102e14c1d 100644 --- a/xCAT-test/autotest/testcase/xdcp/cases0 +++ b/xCAT-test/autotest/testcase/xdcp/cases0 @@ -1,3 +1,15 @@ +start:xdcp_h +cmd:xdcp -h +check:rc==0 +check:output=~Usage +end + +start:xdcp_V +cmd:xdcp -V +check:rc==0 +check:output=~Version +end + start:xdcp_src_dst cmd:xdsh $$CN rm -f /tmp/hosts cmd:xdcp $$CN /etc/hosts /tmp/hosts @@ -9,7 +21,8 @@ check:rc==0 cmd:xdsh $$CN rm -f /tmp/hosts cmd:rm -f /tmp/hosts end -start:xdcp_P + +start:xdcp_P_src_dst cmd:xdcp $$CN -P /etc/inittab /tmp/ check:rc==0 cmd:xdsh $$CN cat /etc/inittab > /tmp/inittab1 @@ -18,3 +31,181 @@ cmd:diff /tmp/inittab._$$CN /tmp/inittab1 check:rc==0 cmd:rm -f /tmp/inittab._$$CN /tmp/inittab1 end + + +start:xdcp_RP +cmd:xdsh $$CN "mkdir -p /tmp/xdcp/test1" +check:rc==0 +cmd:xdsh $$CN "echo "test1" > /tmp/xdcp/test1/test1.txt" +check:rc==0 +cmd:xdsh $$CN "mkdir -p /tmp/xdcp/test2" +check:rc==0 +cmd:xdsh $$CN "echo "test2" > /tmp/xdcp/test2/test2.txt" +check:rc==0 +cmd:xdcp $$CN -RP /tmp/xdcp /tmp +check:rc==0 +cmd:ls -l /tmp/xdcp._$$CN +check:output=~test1 +check:output=~test2 +cmd:ls -l /tmp/xdcp._$$CN/test1 +check:output=~test1.txt +cmd:ls -l /tmp/xdcp._$$CN/test2 +check:output=~test2.txt +cmd:cat /tmp/xdcp._$$CN/test1/test1.txt +check:output=~test1 +cmd:cat /tmp/xdcp._$$CN/test2/test2.txt +check:output=~test2 +cmd:xdsh $$CN "rm -rf /tmp/xdcp" +check:rc==0 +cmd:rm -rf /tmp/xdcp._$$CN +check:rc==0 +end + +start:xdcp_R +cmd:mkdir -p /tmp/xdcp/test1 +check:rc==0 +cmd:echo "test1" > /tmp/xdcp/test1/test1.txt +check:rc==0 +cmd:mkdir -p /tmp/xdcp/test2 +check:rc==0 +cmd:echo "test2" > /tmp/xdcp/test2/test2.txt +check:rc==0 +cmd:xdcp $$CN -R /tmp/xdcp /tmp +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp" +check:output=~xdcp +cmd:xdsh $$CN "ls -l /tmp/xdcp" +check:output=~test1 +check:output=~test2 +cmd:xdsh $$CN "ls -l /tmp/xdcp/test1" +check:output=~test1.txt +cmd:xdsh $$CN "ls -l /tmp/xdcp/test2" +check:output=~test2.txt +cmd:xdsh $$CN "cat /tmp/xdcp/test1/test1.txt" +check:output=~test1 +cmd:xdsh $$CN "cat /tmp/xdcp/test2/test2.txt" +check:output=~test2 +cmd:xdsh $$CN "rm -rf /tmp/xdcp" +check:rc==0 +cmd:rm -rf /tmp/xdcp +check:rc==0 +end + +start:xdcp_all_files_of_dir +cmd:mkdir -p /tmp/xdcp/ +check:rc==0 +cmd:echo "test1" > /tmp/xdcp/test1.txt +check:rc==0 +cmd:echo "test2" > /tmp/xdcp/test2.txt +check:rc==0 +cmd:xdcp $$CN /tmp/xdcp/* /tmp +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp" +check:output=~test1.txt +check:output=~test2.txt +cmd:xdsh $$CN "ls -l /tmp/test1.txt" +check:output=~test1 +cmd:xdsh $$CN "ls -l /tmp/test2.txt" +check:output=~test2 +cmd:xdsh $$CN "rm -rf /tmp/test1.txt /tmp/test2.txt" +check:rc==0 +cmd:rm -rf /tmp/xdcp +check:rc==0 +end + + +start:xdcp_rsync +cmd:mkdir -p /tmp/xdcp/ +check:rc==0 +cmd:echo "test1" > /tmp/xdcp/test1.txt +check:rc==0 +cmd:echo "test2" > /tmp/xdcp/test2.txt +check:rc==0 +cmd:xdcp $$CN -r /usr/bin/rsync -o "-t" /tmp/xdcp/test1.txt /tmp/xdcp/test2.txt /tmp +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp" +check:output=~test1.txt +check:output=~test2.txt +cmd:xdsh $$CN "ls -l /tmp/test1.txt" +check:output=~test1 +cmd:xdsh $$CN "ls -l /tmp/test2.txt" +check:output=~test2 +cmd:xdsh $$CN "rm -rf /tmp/test1.txt /tmp/test2.txt" +check:rc==0 +cmd:rm -rf /tmp/xdcp +check:rc==0 +end + + +start:xdcp_rsyncfile_single_file +cmd:mkdir -p /tmp/xdcp/ +check:rc==0 +cmd:echo "test1" > /tmp/xdcp/test1.txt +check:rc==0 +cmd:echo "/tmp/xdcp/test1.txt -> /tmp/" > /tmp/myrsync +check:rc==0 +cmd:xdcp $$CN -F /tmp/myrsync +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp" +check:output=~test1.txt +cmd:xdsh $$CN "ls -l /tmp/test1.txt" +check:output=~test1 +cmd:xdsh $$CN "rm -rf /tmp/test1.txt" +check:rc==0 +cmd:rm -rf /tmp/xdcp /tmp/myrsync +check:rc==0 +end + + +start:xdcp_rsyncfile_files +cmd:mkdir -p /tmp/xdcp/ +check:rc==0 +cmd:echo "test1" > /tmp/xdcp/test1.txt +check:rc==0 +cmd:echo "test2" > /tmp/xdcp/test2.txt +check:rc==0 +cmd:echo "/tmp/xdcp/* -> /tmp/" > /tmp/myrsync +check:rc==0 +cmd:xdcp $$CN -F /tmp/myrsync +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp" +check:output=~test1.txt +check:output=~test2.txt +cmd:xdsh $$CN "ls -l /tmp/test1.txt" +check:output=~test1 +cmd:xdsh $$CN "ls -l /tmp/test2.txt" +check:output=~test2 +cmd:xdsh $$CN "rm -rf /tmp/test1.txt /tmp/test2.txt" +check:rc==0 +cmd:rm -rf /tmp/xdcp /tmp/myrsync +check:rc==0 +end + + +start:xdcp_rsyncfile_files_changename +cmd:mkdir -p /tmp/xdcp/ +check:rc==0 +cmd:echo "test1" > /tmp/xdcp/test1.txt +check:rc==0 +cmd:echo "test2" > /tmp/xdcp/test2.txt +check:rc==0 +cmd:echo "/tmp/xdcp/test1.txt -> /tmp/testx.txt" > /tmp/myrsync +check:rc==0 +cmd:echo "/tmp/xdcp/test2.txt -> /tmp/testy.txt" >> /tmp/myrsync +check:rc==0 +cmd:xdcp $$CN -F /tmp/myrsync +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp" +check:output=~testx.txt +check:output=~testy.txt +cmd:xdsh $$CN "cat /tmp/testx.txt" +check:output=~test1 +cmd:xdsh $$CN "cat /tmp/testy.txt" +check:output=~test2 +cmd:xdsh $$CN "rm -rf /tmp/testx.txt /tmp/testy.txt" +check:rc==0 +cmd:rm -rf /tmp/xdcp /tmp/myrsync +check:rc==0 +end + + diff --git a/xCAT-test/autotest/testcase/xdsh/cases0 b/xCAT-test/autotest/testcase/xdsh/cases0 new file mode 100644 index 000000000..52eabc602 --- /dev/null +++ b/xCAT-test/autotest/testcase/xdsh/cases0 @@ -0,0 +1,140 @@ +start:xdsh_h +cmd:xdsh -h +check:rc==0 +check:output=~Usage +end + +start:xdsh_V +cmd:xdsh -V +check:rc==0 +check:output=~Version +end + +start:xdsh_regular_command +cmd:xdsh $$CN "ps -ef" +check:rc==0 +check:output=~$$CN: UID PID PPID C STIME TTY TIME CMD +end + +start:xdsh_Q_command +cmd:xdsh $$CN -Q "ps -ef" +check:rc==0 +check:output=~ +end + +start:xdsh_c_sn +cmd:xdsh $$SN "ls -l /var/xcat/syncfiles" > /dev/null 2>&1; if [ "$?" -ne "0" ]; then xdsh $$SN "mkdir -p /var/xcat/syncfiles";fi +check:rc==0 +cmd: xdsh $$SN "echo 'test' > /var/xcat/syncfiles/xdsh_c.tmp" +check:rc==0 +cmd: xdsh $$SN -c +check:rc==0 +cmd:xdsh $$SN "ls -l /var/xcat/syncfiles" +check:rc==0 +check:output=~ +end + +start:xdsh_c_cn +cmd:xdsh $$CN "ls -l /var/xcat/node/syncfiles" > /dev/null 2>&1; if [ "$?" -ne "0" ]; then xdsh $$CN "mkdir -p /var/xcat/node/syncfiles";fi +check:rc==0 +cmd: xdsh $$CN "echo 'test' > /var/xcat/node/syncfiles/xdsh_c.tmp" +check:rc==0 +cmd: xdsh $$CN -c +check:rc==0 +cmd:xdsh $$CN "ls -l /var/xcat/node" +check:rc==0 +check:output=~ +end + +start:xdsh_e_filename +cmd:echo "echo 'xdsh_e_filename test' > /tmp/xdsh_e_filename.txt" > /tmp/xdsh_script.sh +check:rc==0 +cmd:chmod +x /tmp/xdsh_script.sh +check:rc==0 +cmd:xdsh $$CN -e /tmp/xdsh_script.sh +check:rc==0 +cmd:xdsh $$CN "ls -l /tmp |grep xdsh_e_filename.txt" +check:output=~xdsh_e_filename.txt +cmd:xdsh $$CN "cat /tmp/xdsh_e_filename.txt" +check:output=~xdsh_e_filename test +cmd:xdsh $$CN "rm -r /tmp/xdsh_e_filename.txt" +check:rc==0 +cmd:rm -r /tmp/xdsh_script.sh +check:rc==0 +end + +start:xdsh_E +cmd:echo 'export DSH_FANOUT=8' > /tmp/xdsh.test +check:rc==0 +cmd:xdsh $$CN -E /tmp/xdsh.test "export |grep DSH_FANOUT" +check:rc==0 +check:output=$$CN: declare -x DSH_FANOUT="8" +cmd:rm -r /tmp/xdsh.test +check:rc==0 +end + +start:xdsh_i_linux +cmd:copycds $$ISO +check:rc==0 +cmd:genimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute +check:rc==0 +cmd:xdsh -i /install/netboot/__GETNODEATTR($$CN,os)__/__GETNODEATTR($$CN,arch)__/compute/rootimg "rpm -qa|grep uuid" +check:rc==0 +check:output=~libuuid +end + + +start:xdsh_t +cmd:date +%s > /tmp/start.txt +check:rc==0 +cmd:xdsh $$CN -t 5 "ssh 1.1.1.1" +check:rc!=0 +check:output=~Error: Caught SIGINT - terminating the child processes. +cmd:date +%s > /tmp/end.txt +check:rc==0 +cmd:a=`cat /tmp/start.txt`;b=`cat /tmp/end.txt`;c=$[$b-$a];echo $c +check:rc==0 +check:output<7 +cmd:rm -f /tmp/start.txt /tmp/end.txt +end + +start:xdsh_q +cmd:xdsh $$CN -q +check:rc==0 +check:output=~DSH:DSH_FANOUT= +end + +start:xdsh_T +cmd:xdsh $$CN -T "hostname" +check:rc==0 +check:output=~TRACE:Default context is XCAT +check:output=~$$CN: $$CN +end + +start:xdsh_o +cmd:xdsh $$CN -o "-v" date +check:rc==0 +check:output=~$$CN: OpenSSH +check:output=~$$CN: debug +end + + + + + + + + + + + + + + + + + + + + + diff --git a/xCAT-test/restapitest b/xCAT-test/restapitest new file mode 100755 index 000000000..1e0682fc2 --- /dev/null +++ b/xCAT-test/restapitest @@ -0,0 +1,507 @@ +#!/usr/bin/env perl +############################################################################### +# This script is used for rest-api automation test +# Flags are used for test input: +# -m method. Should be GET, POST, PUT, DELETE +# -r resource +# -t token +# -h host +# -u user +# -p passwd +# -P port (BC) +# -d data +# -c cert +# -n hostname +# Flags are used for check output: +# -o expected output +# -O logical operator +# +# Expected result format is '{ANY:{ANY:content}}' +# These steps are used to explain how to scan result +# step 1. go through to see if content can be found +# step 2. compare content if found +# options are used as followed: +# == returns 0 if found and equal, returns 1 if not found or found but not equal +# != returns 0 if found, returns 1 if not found +# =~ returns 0 if match, returns 1 if not match +# !=~ returns 0 if not match, returns 1 if match +################################################################################ +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use Getopt::Long qw{:config bundling no_ignore_case}; +use Data::Dumper; +use strict; +my $help; +my $method; +my $token; +my $resource; +my $host; +my $user; +my $passwd; +my $port; +my $data; +my $cert; +my $hostname; +my $output; +my $loperator; +my $debug; +my $defaulthash; +my $defaulthttpresult = 0; +my $outputfile = "/tmp/testrestapiresult"; + +if ( + !GetOptions("h|?" => \$help, + "m=s" => \$method, + "t=s" => \$token, + "r=s" => \$resource, + "h=s" => \$host, + "u=s" => \$user, + "p=s" => \$passwd, + "P=s" => \$port, + "d=s" => \$data, + "c=s" => \$cert, + "n=s" => \$hostname, + "o=s" => \$output, + "O=s" => \$loperator, + "debug" => \$debug, + ) + ) { + &usage; + exit 1; +} + +############################################################## +# check result +############################################################## +if ($output) { + if ($method or $resource) { + &usage; + exit 1; + } + + my $res = check_result($output,$loperator,$outputfile); + print_debug( "check result runs with $output and $loperator, result is $res\n" ); + exit $res; +} +############################################################## +# return help +############################################################## +if ($help) { + &usage; + exit 0; +} +############################################################## +# Give default values for optional vars. +############################################################### +my $rootdir = "$::XCATROOT/share/xcat/tools/autotest"; +my $resultdir = "$rootdir/result"; +my $logfile = "$rootdir/result/restapitest.log"; #/opt/xcat/share/xcat/tools/autotest/result/restapitest.log +my $cert1 = "/root/ca-cert.pem"; +# get token +my $gettoken = `curl -X POST -k 'https://127.0.0.1/xcatws/tokens?userName=root&password=cluster' -H Content-Type:application/json --data '{"userName":"root","password":"cluster"}' 2>/dev/null`; +my $reshash = parse_json($gettoken); +my $token1 = $$reshash{token}{id}; + + +# get hostname +unless ($hostname) { + $hostname = `hostname`; + chomp($hostname); + +} + +# keey default test result for save +my $res = run_restapi($method, $resource, $data, "", $port, "127.0.0.1", "root", "cluster"); +$defaulthash = parse_json($res); +$defaulthttpresult = check_errcode(); + +# debug info +print_debug( "get token $token1. \n" ); +print_debug( "get hostname $hostname.\n"); +print_debug( "default result is $res. \n" ); +print_debug( "default resulthash is: \n" ); +print_debug($defaulthash); +print_debug( "default errcode is $defaulthttpresult \n" ); + + +#################################################### +# Begin to run test cases +#################################################### +my @users = ("root","wsuser", $user); +my @passwds = ("cluster","cluster", $passwd); +my @tokens = ("", $token1, $token); +my @certs = ("", $cert1, $cert); +unless ($host) { + $host = "127.0.0.1"; +} +log_me("**************begin restapi test***************"); +my $i = 0; +for my $u (@users) { + next unless($u); + my $p = $passwds[$i]; + $i++; + for my $t (@tokens) { + for my $c (@certs){ + my $res = run_restapi($method, $resource, $data, $c, $port, $host, $u, $p, $t); + if($res){ + my $reshash = parse_json($res); + print_debug("parse curl result and got:\n"); + print_debug($reshash); + if (%$reshash != %$defaulthash) { + log_me("restapi test cases run different result"); + print_debug( "restapi test cases run different result with $method, $resource, $data, $c, $port, $host, $u, $p, $t\n" ); + exit 1; + } + } + my $errcode = check_errcode(); + print_debug("get curl error code: $errcode\n"); + if ($errcode != $defaulthttpresult) { + log_me("restapi test cases run different errcode"); + print_debug( "restapi test cases run different error code with $method, $resource, $data, $c, $port, $host, $u, $p, $t\n" ); + exit 1; + } + } + } +} +exit $defaulthttpresult; + +################################################ +# begin subroutine +################################################ + +########## +# usage # +########## +sub usage +{ + print "Usage:testrestapi - Run xcat test cases.\n"; + print " testrestapi [-?|-h]\n"; + print " testrestapi [-m method] [-r resource] [-t tocken]\n"; + print " [-h host] [-P port][-u user] [-p passwd]\n"; + print " [-d data] [-c cert] [-n hostname]\n"; + print " [-o expect_output] [-O logical_operator] \n"; + print " [--debug]\n"; + print "\n"; + return; +} + +############### +# record log # +############### +sub log_me +{ + my $msg = shift; + open (LOG, ">>$logfile") + or return 1; + my $date = `date`; + print LOG "$date\: $msg\n"; +} + +##################### +# print debug infor # +##################### +sub print_debug +{ + my $msg = shift; + return 0 unless($debug); + if(ref($msg) eq 'HASH') { + print Dumper($msg); + } elsif( ref($msg) eq 'ARRAY') { + print Dumper($msg); + } else { + print "$msg"; + } +} +######################### +# run rest-api command # +######################### +sub run_restapi +{ + my ($m,$r,$d,$c,$p,$h,$u,$a,$t) = @_; + my $cmd = "curl"; + $cmd .= " -X $m"; + unless ($c) { + $cmd .= " -k "; + }else { + $cmd .= " --cacert $c"; + } + if($t){ + $cmd .= " -H X-Auth-Token:$t "; + } + if($t or $c){ + $cmd .= " 'https://$hostname"; + } else { + $cmd .= " 'https://$h"; + } + if ($p) { + $cmd .= ":$p"; + } + $cmd .= "/xcatws"; + $cmd .= "$r?"; + unless($t){ + $cmd .= "userName=$u&password=$a'"; + }else { + $cmd .= "'"; + } + if($d) { + $cmd .= " -H Content-Type:application/json --data '$d'"; + } + $cmd .= " -D /tmp/err.log"; + log_me("Begin to run restapi test with $cmd"); + my $res = `$cmd 2>/dev/null`; + print_debug("run curl: $cmd\n"); + print_debug("result is $res\n"); + if (!open (RESULT, ">$outputfile")) { + log_me("wirte outputfile error"); + } + print RESULT $res; + close RESULT; + return $res; +} + +############################ +# transfer json into hash # +############################ +sub parse_json +{ + my $input = shift; + my %hash; + if ($input =~ /:/) { + # for those who look like: + # {"networks":[{"mgtifname":"eth1","mask":"255.255.255.0"},{"mgtifname":"eth1","mask":"255.255.255.0"}]} + if ($input =~ /^\[(.*)\]$/s) { + my $content = $1; + print "[:] content is $content \n" if($debug); + parse_json($content); + } + # for those who look like + # {"clustersite":{"domain":"cluster.com","master":"192.168.1.15"}} + elsif ($input =~ /^\s*{(.*)}\s*$/s) { + my $content = $1; + print "{} content is $content \n" if($debug); + parse_json($content); + } + # for those who look like + # "domain":"cluster.com","master":"192.168.1.15" + elsif ($input =~ /,/ and !($input =~ /}/)) { + my @contents = split /,/, $input; + my @reval; + # record result + foreach my $t (@contents) { + print ", content is $t \n" if($debug); + my $re = parse_json($t); + push @reval, $re; + } + # merge hash + foreach my $t (@reval) { + if(ref($t) =~ "HASH") { + foreach my $k (keys %$t){ + $hash{$k} = $$t{$k}; + } + } + } + return \%hash; + + } + # for those who look like: + # "clustersite":{"domain":"cluster.com","master":"192.168.1.15"} + # "domain":"cluster.com" + elsif ($input =~ /\"(\S+?)\":(.+)/s) { + my $key = $1; + my $value = $2; + if ($value =~ /{/) { + # "clustersite":{"domain":"cluster.com","master":"192.168.1.15"} + print "{ content is $value \n" if($debug); + $hash{$key} = parse_json($value, $key); + return \%hash; + } else { + # "domain":"cluster.com" + $value =~ /\"(\S+)\"/; + $hash{$key} = $1; + return \%hash; + } + } + } + # for those who look like + # ["10.1.255.250","192.168.200.16","192.168.200.19","192.168.200.22"] + else { + if ($input =~ /^\[(.*)\]/s) { + my $content = $1; + print "[] content is $content \n" if($debug); + my @all = split /,/, $content; + foreach my $n (@all) { + $n =~ /\"(.*)\"/; + $hash{$1} = "restapiarray"; + } + return \%hash; + } + } +} + +############################ +# check curl running code # +############################ +sub check_errcode +{ + if(!open (ERRLOG, "){ + if (/HTTP\/\w*\.*\w* (\w+) (\w+)/) { + $num = $1; + last; + } + } + close ERRLOG; + print_debug("can't get errorcode\n") unless($num); + return $num; +} + +############################ +# check curl return result # +############################ +sub check_result +{ + my $data = shift; + my $opterator = shift; + my $output = shift; + if ( !open (OUTPUT, "<$output")) { + log_me("can't read output file"); + return 1; + } + my $res; + while () { + $res .= $_; + } + close OUTPUT; + + + my $expects = transf_hash(parse_json($data)); # one entry + my $actuals = transf_hash(parse_json($res)); # serval entries + + print_debug("expected result is:\n"); + print_debug($expects); + print_debug("testcase run result is \n"); + print_debug($actuals); + + my $flag = 0; + my %flaghash; + my $expect = $$expects[0]; # $expect = ANY:ANY:x86_64 + + my @expectvalue = split /:/, $expect; #@expectvalue = ANY, ANY, x86_64 + $flag = 0; + foreach my $expval (@expectvalue) { # $expval = ANY + foreach my $actual (@$actuals) { # $actual = nodetype:arch:x86_64 + if($flaghash{$actual} eq "none"){ + next; + } + my @actualvalue = split /:/, $actual; # @actualvalue = nodetype, arch, x86_64 + print_debug("begin to compare $expval and $actualvalue[$flag]"); + + if(($expval eq "restapiarray" ) and ($actualvalue[$flag] eq "restapiarray")){ + next; + } + + if(($expval eq $actualvalue[$flag]) or ($expval eq "ANY")) { #ANY =~ nodetype + $flaghash{$actual} = "eq"; + } elsif (($actualvalue[$flag] =~ $expval) or ($expval eq "ANY")) { + $flaghash{$actual} = "match"; + } else { + $flaghash{$actual} = "none"; + } + print_debug(", compare result is $flaghash{$actual}\n"); + } + $flag++; + } + print_debug("search result is \n"); + print_debug(\%flaghash); + + if ($opterator eq "!="){ + foreach my $val (keys %flaghash) { + if ($flaghash{$val} eq "eq") { + print_debug("compare result: failed\n"); + return 1; # fail + } + } + print_debug("compare result: succeed\n"); + return 0; #succeed + } + if ($opterator eq "=="){ + foreach my $val (keys %flaghash) { + if ($flaghash{$val} eq "eq") { + print_debug("compare result: succeed\n"); + return 0; # succeed + } + } + print_debug("compare result: failed\n"); + return 1; #fail + } + + if ($opterator eq "=~"){ + foreach my $val (keys %flaghash) { + if ($flaghash{$val} eq "match") { + print_debug("compare result: succeed\n"); + return 0; # succeed + } + } + print_debug("compare result: failed\n"); + return 1; #fail + } + if ($opterator eq "!=~"){ + foreach my $val (keys %flaghash) { + if ($flaghash{$val} eq "match") { + print_debug("compare result: failed\n"); + return 1; # fail + } + } + print_debug("compare result: succeed\n"); + return 0; #succeed + } + +} + +#################################### +# help to transfer hash into array # +#################################### +sub find_key +{ + my $input = shift; + my $en = shift; + my $ou = shift; + if( ref($input) =~ "HASH") { + foreach my $val (keys %$input) { + my $tmp = $$en; # keey head + $$en .= "$val:"; + my $t1 = find_key($$input{$val}, $en, $ou); + if ($$en == ""){ + $$en = $tmp; #restore head + } + } + } else { + $$en .= $input; + push @$ou, $$en; + $$en = ""; # clear entry; + } +} + +############################ +# transfer hash into array # +############################ +sub transf_hash +{ + my $input = shift; + my $entry; + my @array; + find_key($input, \$entry, \@array); + return \@array; +} + + + + + + diff --git a/xCAT-test/xCAT-test.spec b/xCAT-test/xCAT-test.spec index 5672ed42f..2aa2bcc4c 100644 --- a/xCAT-test/xCAT-test.spec +++ b/xCAT-test/xCAT-test.spec @@ -39,6 +39,7 @@ pod2html pods/man1/xcattest.1.pod > share/doc/man1/xcattest.1.html rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin +mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/tools/autotest mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1 mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 @@ -46,6 +47,9 @@ mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1 cp xcattest $RPM_BUILD_ROOT/%{prefix}/bin chmod 755 $RPM_BUILD_ROOT/%{prefix}/bin/* +cp restapitest $RPM_BUILD_ROOT/%{prefix}/sbin +chmod 755 $RPM_BUILD_ROOT/%{prefix}/sbin/* + # These were built dynamically in the build phase cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1 chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/* diff --git a/xCAT-test/xcattest b/xCAT-test/xcattest index 511fcfb43..a4cff3ae3 100755 --- a/xCAT-test/xcattest +++ b/xCAT-test/xcattest @@ -25,10 +25,10 @@ my $string1 = undef; if ( !GetOptions("h|?" => \$needhelp, "f=s" => \$configfile, - "b=s" => \$bundle_list, - "t=s" => \$case_list, - "c=s" => \$cmd_list, - "l" => \$needshow, + "b=s" => \$bundle_list, + "t=s" => \$case_list, + "c=s" => \$cmd_list, + "l" => \$needshow, "restore"=>\$restore) ) { @@ -221,7 +221,7 @@ sub getConfig } } } - + if(exists $config{object}){ foreach my $type (keys %{$config{object}}){ foreach my $name (keys %{$config{object}{$type}}){ @@ -344,7 +344,7 @@ sub init log_this("No compute node defined,can't get ARCH of compute node"); } else { $config{var}{ARCH} = getnodeattr($config{var}{CN},"arch"); - if($config{var}{ARCH} =~ /ppc/){ + if($config{var}{ARCH} =~ /ppc/){ $config{var}{ARCH} = 'ppc'; }elsif($config{var}{ARCH}=~/86/){ $config{var}{ARCH} = 'x86'; @@ -432,7 +432,7 @@ sub loadcase my $j = -1; my $z = 0; my $skip = 0; - + my @caserange = (); my @rightcase = (); my @notrightcase = (); @@ -452,7 +452,7 @@ sub loadcase } } if($case_list){ - @caserange = split /,/, $case_list; + @caserange = split /,/, $case_list; } foreach $file (@files){ if(!open(FILE, "<$file")){ @@ -477,10 +477,11 @@ sub loadcase $j = -1; $cases[$i]={}; $cases[$i]->{name}=$name; - $cases[$i]->{filename}=$file; + $cases[$i]->{filename}=$file; if(!$needshow){ $cases[$i]->{cmd}=[]; $cases[$i]->{check}=[]; + $cases[$i]->{cmdcheck}=[]; push(@rightcase, $name); }else{ $skip = 1; @@ -497,13 +498,13 @@ sub loadcase $cases[$i]->{os}=$string1; } - + if($cases[$i]->{os} !~ /$config{var}{OS}/){ push(@notrightcase, $cases[$i]->{name}); pop(@rightcase); $skip = 1; } - + }elsif($line =~ /^arch\s*:\s*(\w[\w\,]+)/){ next if $skip; $cases[$i]->{arch}=$1; @@ -545,6 +546,14 @@ sub loadcase return 1; } $z = $z + 1; + }elsif($line =~ /^cmdcheck\s*:\s*(\w.+)/){ + next if $skip; + $cases[$i]->{cmdcheck}->[$j][$z] = &getvar($1); + if($cases[$i]->{cmdcheck}->[$j][$z] eq ''){ + close(FILE); + return 1; + } + $z = $z + 1; }elsif($line =~ /^end/){ next if $skip; $i = $i + 1; @@ -622,7 +631,7 @@ sub getfunc $func = $1; $parameter = $2; @para = split /\s*,\s*/, trim($parameter); - if($func eq "GETNODEATTR"){ + if($func eq "GETNODEATTR"){ $value= getnodeattr(@para); if($value eq "Unknown"){ $value = ''; @@ -660,9 +669,9 @@ sub runcase my $time1=gmtime $now1; log_this("------START:$$case{name}::Time:$time1------"); push @record, "------START:$$case{name}::Time:$time1------"; - push @record, "FILENAME:$$case{filename}"; + push @record, "FILENAME:$$case{filename}"; foreach my $cmd (@{$$case{cmd}}){ - $cmd = getfunc($cmd); + $cmd = getfunc($cmd); #by my $runstart=timelocal(localtime()); @@ -675,10 +684,10 @@ sub runcase my $diffduration=$runstop-$runstart; log_this("\n[$cmd] Running Time:$diffduration sec"); push(@record,("\n[$cmd] Running Time:$diffduration sec")); - + log_this("RETURN: rc = $rc","OUTPUT:",@output); push(@record,("RETURN rc = $rc","OUTPUT:",@output)); - + foreach my $check (@{$$case{check}->[$j]}){ if($failed){ @@ -756,6 +765,19 @@ sub runcase } } } + foreach my $cmdcheck (@{$$case{cmdcheck}->[$j]}){ + if($cmdcheck) { + &runcmd($cmdcheck); + $rc = $::RUNCMD_RC; + if($rc == 1) { + log_this("CMDCHECK:output $cmdcheck\t[Failed]"); + push(@record, "CHECK:output $cmdcheck\t[Failed]"); + } elsif ($rc == 0) { + log_this("CMDCHECK:output $cmdcheck\t[Pass]"); + push(@record, "CHECK:output $cmdcheck\t[Pass]"); + } + } + } $j = $j + 1; } my $now2=timelocal(localtime()); @@ -786,6 +808,7 @@ sub runcmd if ($?) { $rc = $? ; + $rc = $rc >> 8; $::RUNCMD_RC = $rc; } chomp(@$outref); @@ -823,3 +846,5 @@ sub getreport close(FD); close(STDOUT); } + + diff --git a/xCAT/debian/dirs b/xCAT/debian/dirs index ef4317183..7fed8339e 100644 --- a/xCAT/debian/dirs +++ b/xCAT/debian/dirs @@ -5,4 +5,5 @@ install/prescripts install/kdump opt/xcat/share/xcat etc/apache2/conf.d +etc/apache2/conf-enabled opt/xcat/share/doc/packages/xCAT diff --git a/xCAT/debian/install b/xCAT/debian/install index edd37eb13..ab485abda 100644 --- a/xCAT/debian/install +++ b/xCAT/debian/install @@ -1,5 +1,5 @@ xcat.conf etc/apache2/conf.d/ -xcat.conf.apach24 etc/apache2/conf.d/ +xcat.conf.apach24 etc/apache2/conf-enabled LICENSE.html opt/xcat/share/doc/packages/xCAT postscripts/* install/postscripts/ prescripts/* install/prescripts/ diff --git a/xCAT/debian/postinst b/xCAT/debian/postinst index bf457cc40..6e6d4cebc 100644 --- a/xCAT/debian/postinst +++ b/xCAT/debian/postinst @@ -40,12 +40,10 @@ case "$1" in else xcatconfig -i -d -s fi - ver=$(cat /etc/issue |awk '{print $2}') - num=${ver%.*} - file="xcat.conf.apach24" - if [ $num -gt 12 ];then - mv /etc/apache2/conf.d/xcat.conf.apach24 /etc/apache2/conf-enabled/xcat.conf - fi + +# [ -e /etc/apache2/conf-enabled/xcat.conf ] && rm /etc/apache2/conf-enabled/xcat.conf +# mv /etc/apache2/conf-enabled/xcat.conf.apach24 /etc/apache2/conf-enabled/xcat.conf + /etc/init.d/apache2 restart ;; diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index c9e73068c..85994e869 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -27,6 +27,10 @@ function configipv4(){ echo "NETWORK_${num_v4num}=${str_v4net}" >> $str_conf_file echo "LABEL_${num_v4num}=${num_v4num}" >> $str_conf_file fi + + if [[ ${str_if_name} == [a-zA-Z0-9]*.[0-9]* ]]; then + echo "VLAN=yes" >> $str_conf_file + fi #debian ubuntu elif [ "$str_os_type" = "debian" ];then str_conf_file="/etc/network/interfaces.d/${str_if_name}" @@ -40,6 +44,10 @@ function configipv4(){ echo " address ${str_v4ip}" >> $str_conf_file echo " netmask ${str_v4mask}" >> $str_conf_file echo " network ${str_v4net}" >> $str_conf_file + if [[ ${str_if_name} == [a-zA-Z0-9]*.[0-9]* ]]; then + parent_device=`echo ${str_if_name} | sed -e 's/\([a-zA-Z0-9]*\)\.[0-9]*/\1/g'` + echo " vlan-raw-device ${parent_device}" >> $str_conf_file + fi else # Write the info to the ifcfg file for redhat str_conf_file="" @@ -56,6 +64,9 @@ function configipv4(){ echo "IPADDR=${str_v4ip}" >> $str_conf_file echo "NETMASK=${str_v4mask}" >> $str_conf_file echo "ONBOOT=yes" >> $str_conf_file + if [[ ${str_if_name} == [a-zA-Z0-9]*.[0-9]* ]]; then + echo "VLAN=yes" >> $str_conf_file + fi fi } diff --git a/xCAT/postscripts/configib b/xCAT/postscripts/configib index f9bdda48b..da721559e 100755 --- a/xCAT/postscripts/configib +++ b/xCAT/postscripts/configib @@ -286,9 +286,9 @@ do if [ -f /etc/sysctl.conf ] then - TMP1=`sed "/net.ipv4.conf.$nic.arp_filter=1/d" /etc/sysctl.conf 2>&1 1>/dev/null` + TMP1=`sed "/net.ipv4.conf.$nic.arp_filter=1/d" /etc/sysctl.conf` echo "$TMP1" > /etc/sysctl.conf - TMP2=`sed "/net.ipv4.conf.$nic.arp_ignore=1/d" /etc/sysctl.conf 2>&1 1>/dev/null` + TMP2=`sed "/net.ipv4.conf.$nic.arp_ignore=1/d" /etc/sysctl.conf` echo "$TMP2" > /etc/sysctl.conf cfg="net.ipv4.conf.$nic.arp_filter=1" grep "$cfg" /etc/sysctl.conf 2>&1 1>/dev/null diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index aef830cd4..bcfbe3cbd 100755 --- a/xCAT/postscripts/confignics +++ b/xCAT/postscripts/confignics @@ -282,7 +282,7 @@ do else if [ `echo $key | grep -E '(eth|en)[0-9]+'` ];then str_nic_type="ethernet" - elif [ `echo $KEY | grep -E 'ib[0-9]+'` ];then + elif [ `echo $key | grep -E 'ib[0-9]+'` ];then str_nic_type="infiniband" else logger -t xcat -p local4.info "confignics: unknown nic type for $key: $str_value ." diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index ea7492a16..928e7bcf5 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -100,7 +100,7 @@ getcredentials.awk ssh_dsa_hostkey | grep -E -v '|' /tmp/ssh_dsa_hostkey if [ $? -ne 0 ]; then #the message received is the data - cat /tmp/ssh_dsa_hostkey | grep -E -v '||' >/etc/ssh/ssh_host_dsa_key + cat /tmp/ssh_dsa_hostkey | grep -E -v '|/{0,1}data>||' >/etc/ssh/ssh_host_dsa_key logger -t xCAT -p local4.info "remoteshell: getting ssh_host_dsa_key" MAX_RETRIES=10 RETRY=0 @@ -164,7 +164,7 @@ getcredentials.awk ssh_rsa_hostkey | grep -E -v '|' /tmp/ssh_rsa_hostkey if [ $? -ne 0 ]; then #the message received is the data we request - cat /tmp/ssh_rsa_hostkey | grep -E -v '||' >/etc/ssh/ssh_host_rsa_key + cat /tmp/ssh_rsa_hostkey | grep -E -v '|/{0,1}data>||' >/etc/ssh/ssh_host_rsa_key logger -t xCAT -p local4.info ssh_rsa_hostkey MYCONT=`cat /etc/ssh/ssh_host_rsa_key` MAX_RETRIES=10 @@ -216,12 +216,88 @@ if [[ $NTYPE = service ]]; then cp /etc/ssh/ssh* /etc/xcat/hostkeys/. fi - -umask 0077 - +umask 0077 +# This is where we start getting root ssh keys +# This tells credentials.pm where to get the root .ssh keys. If no zone then old path of ~.ssh +#rootsshpvtkey=ssh_root_key:$zonename mkdir -p /root/.ssh/ +# this is for obtaining non-zone keys +rootsshpvtkey=ssh_root_key +rootsshpubkey=ssh_root_pub_key +if [ $ZONENAME ]; +then +# This tells credentials.pm where to get the root .ssh keys. If no zone then old path of ~/.ssh + zonename=$ZONENAME + rootsshpvtkey=ssh_root_key:$zonename + rootsshpubkey=ssh_root_pub_key:$zonename + logger -t xCAT -p local4.info "remoteshell: gathering root ssh keys for $zonename" + +fi + +# always get the id_rsa.pub key for the node and put in authorized_keys +if [ $useflowcontrol = "1" ]; then + #first contact daemon xcatflowrequest 3001 + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi +fi + + getcredentials.awk $rootsshpubkey | grep -E -v '|'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /tmp/ssh_root_pub_key + + logger -t xCAT -p local4.info "remoteshell: gathering $rootsshpubkey " + #check whether the message is an error or not + grep -E '' /tmp/ssh_root_pub_key +if [ $? -ne 0 ]; then + #The message contains the data we request + cat /tmp/ssh_root_pub_key | grep -E -v '|||' > /root/.ssh/id_rsa.pub + # no add to authorized_keys, so the node can ssh to itself + cat /tmp/ssh_root_pub_key | grep -E -v '|||' >> /root/.ssh/authorized_keys + logger -t xCAT -p local4.info ssh_root_pub_key + MYCONT=`cat /root/.ssh/id_rsa.pub` + MAX_RETRIES=10 + RETRY=0 + while [ -z "$MYCONT" ]; do + if [ $useflowcontrol = "0" ]; then + let SLI=$RANDOM%10 + let SLI=SLI+10 + sleep $SLI + fi + RETRY=$(($RETRY+1)) + if [ $RETRY -eq $MAX_RETRIES ] + then + break + fi + if [ $useflowcontrol = "1" ]; then + #first contact daemon xcatflowrequest 3001 + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi + fi + getcredentials.awk $rootsshpubkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /root/.ssh/id_rsa.pub + getcredentials.awk $rootsshpubkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" >> /root/.ssh/authorized_keys + MYCONT=`cat /root/.ssh/id_rsa.pub` + done +else + #This is an error message + ERR_MSG=`sed -n 's%.*\(.*\).*%\1%p' /tmp/ssh_root_pub_key` + logger -t xCAT -p local4.err $rootsshpubkey Error: $ERR_MSG +fi +rm /tmp/ssh_root_pub_key + +# if sshbetweennodes is enabled then we get id_rsa ( private key) if [ $ENABLESSHBETWEENNODES = "YES" ]; # want nodes to be able to ssh to each other without password then + logger -t xCAT -p local4.info "remoteshell:sshbetweennodes is yes" if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" @@ -233,13 +309,14 @@ then useflowcontrol=0 fi fi - getcredentials.awk ssh_root_key | grep -E -v '|'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /tmp/ssh_root_key + getcredentials.awk $rootsshpvtkey | grep -E -v '|'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /tmp/ssh_root_key + logger -t xCAT -p local4.info "remoteshell: gathering $rootsshpvtkey " #check whether the message is an error or not grep -E '' /tmp/ssh_root_key if [ $? -ne 0 ]; then #The message contains the data we request - cat /tmp/ssh_root_key | grep -E -v '||' > /root/.ssh/id_rsa + cat /tmp/ssh_root_key | grep -E -v '|/{0,1}data>||' > /root/.ssh/id_rsa logger -t xCAT -p local4.info ssh_root_key MYCONT=`cat /root/.ssh/id_rsa` MAX_RETRIES=10 @@ -266,21 +343,25 @@ then useflowcontrol=0 fi fi - getcredentials.awk ssh_root_key | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /root/.ssh/id_rsa + getcredentials.awk $rootsshpvtkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /root/.ssh/id_rsa MYCONT=`cat /root/.ssh/id_rsa` done else #This is an error message ERR_MSG=`sed -n 's%.*\(.*\).*%\1%p' /tmp/ssh_root_key` - logger -t xCAT -p local4.err ssh_root_key Error: $ERR_MSG + logger -t xCAT -p local4.err $rootsshpvtkey Error: $ERR_MSG fi rm /tmp/ssh_root_key if ! grep "PRIVATE KEY" /root/.ssh/id_rsa > /dev/null 2>&1 ; then rm /root/.ssh/id_rsa fi - if [ -r /root/.ssh/id_rsa ]; then + # if public key does not exist then generate one from the private key + if [ ! -f /root/.ssh/id_rsa.pub ]; then + if [ -r /root/.ssh/id_rsa ]; then ssh-keygen -y -f /root/.ssh/id_rsa > /root/.ssh/id_rsa.pub + logger -t xCAT -p local4.err remoteshell:transfer of the id_rsa.pub key failed. Had to generate a public key. + fi fi fi diff --git a/xCAT/postscripts/routeop b/xCAT/postscripts/routeop index 7260a033a..2cf80a3f1 100755 --- a/xCAT/postscripts/routeop +++ b/xCAT/postscripts/routeop @@ -107,7 +107,8 @@ route_exists() net1=`echo $x|cut -d',' -f1` gw1=`echo $x|cut -d',' -f2` mask1=`echo $x|cut -d',' -f3` - if [ "$net" = "$net1" ] && [ "$mask" = "$mask1" ] && [ "$gw" = "$gw1" ]; then + ifname1=`echo $x|cut -d',' -f8` + if [ "$net" = "$net1" ] && [ "$mask" = "$mask1" ] && [ "$gw" = "$gw1" ] && [ "$ifname" = "$ifname1" ]; then ret=1 break fi @@ -174,11 +175,21 @@ add_persistent_route() filename="/etc/sysconfig/network/routes"; if echo $net | grep : 2>&1 1>/dev/null then - route="$net/$mask $gw - -" - route1="$net\/$mask $gw - -"; + if [ $gw_ip = "" -o $gw_ip = "::" ] ; then + route="$net/$mask :: - $ifname" + route1="$net\/$mask :: - $ifname"; + else + route="$net/$mask $gw - -" + route1="$net\/$mask $gw - -"; + fi else - route="$net $gw $mask $ifname"; - route1="$net $gw $mask $ifname"; + if [ $gw_ip = "" -o $gw_ip = "0.0.0.0" ] ; then + route="$net 0.0.0.0 $mask $ifname"; + route1="$net 0.0.0.0 $mask $ifname"; + else + route="$net $gw $mask $ifname"; + route1="$net $gw $mask $ifname"; + fi fi if [ -f $filename ]; then grep "$route" $filename 2>&1 1>/dev/null @@ -221,10 +232,18 @@ add_persistent_route() echo $net | grep : 2>&1 1>/dev/null #ipv6 if [ $? -eq 0 ];then - matchstr="$net/$mask gw $gw" + if [ "$gw" = "" -o "$gw" = "::" ] ; then + matchstr="$net/$mask dev $ifname" + else + matchstr="$net/$mask gw $gw" + fi v6flag=1 else - matchstr="net $net netmask $mask gw $gw" + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + matchstr="net $net netmask $mask dev $ifname" + else + matchstr="net $net netmask $mask gw $gw" + fi fi grep "$matchstr" $filename 2>&1 1>/dev/null @@ -237,11 +256,21 @@ add_persistent_route() if [ $? -eq 0 -a $foundflag -eq 1 ];then foundflag=0 if [ $v6flag -eq 1 ];then - echo " up route -A inet6 add $net/$mask gw $gw" >> $tempfile - echo " down route -A inet6 del $net/$mask gw $gw" >> $tempfile + if [ "$gw" = "" -o "$gw" = "::" ] ; then + echo " up route -A inet6 add $net/$mask dev $ifname" >> $tempfile + echo " down route -A inet6 del $net/$mask dev $ifname" >> $tempfile + else + echo " up route -A inet6 add $net/$mask gw $gw" >> $tempfile + echo " down route -A inet6 del $net/$mask gw $gw" >> $tempfile + fi else - echo " up route add -net $net netmask $mask gw $gw" >> $tempfile - echo " down route del -net $net netmask $mask gw $gw" >> $tempfile + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + echo " up route add -net $net netmask $mask dev $ifname" >> $tempfile + echo " down route del -net $net netmask $mask dev $ifname" >> $tempfile + else + echo " up route add -net $net netmask $mask gw $gw" >> $tempfile + echo " down route del -net $net netmask $mask gw $gw" >> $tempfile + fi fi fi echo $LINE | grep "iface $ifname " 2>&1 1>/dev/null @@ -255,11 +284,21 @@ add_persistent_route() #the insert place is the last line of the config file if [ $foundflag -eq 1 ];then if [ $v6flag -eq 1 ];then - echo " up route -A inet6 add $net/$mask gw $gw" >> $tempfile - echo " down route -A inet6 del $net/$mask gw $gw" >> $tempfile + if [ "$gw" = "" -o "$gw" = "::" ] ; then + echo " up route -A inet6 add $net/$mask dev $ifname" >> $tempfile + echo " down route -A inet6 del $net/$mask dev $ifname" >> $tempfile + else + echo " up route -A inet6 add $net/$mask gw $gw" >> $tempfile + echo " down route -A inet6 del $net/$mask gw $gw" >> $tempfile + fi else - echo " up route add -net $net netmask $mask gw $gw" >> $tempfile - echo " down route del -net $net netmask $mask gw $gw" >> $tempfile + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + echo " up route add -net $net netmask $mask dev $ifname" >> $tempfile + echo " down route del -net $net netmask $mask dev $ifname" >> $tempfile + else + echo " up route add -net $net netmask $mask gw $gw" >> $tempfile + echo " down route del -net $net netmask $mask gw $gw" >> $tempfile + fi fi fi mv -f $tempfile $filename @@ -273,14 +312,22 @@ add_persistent_route() # ipv6 net if echo $net | grep : 2>&1 1>/dev/null then + if [ "$gw" = "" ] ; then + $gw = "::"; + fi filename="/etc/sysconfig/static-routes-ipv6"; route="$ifname $net/$mask $gw"; # $net/mask does not work with sed cmd route1="$ifname $net\/$mask $gw"; else filename="/etc/sysconfig/static-routes"; - route="any net $net netmask $mask gw $gw $ifname"; - route1="any net $net netmask $mask gw $gw $ifname"; + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + route="any net $net netmask $mask dev $ifname"; + route1="any net $net netmask $mask dev $ifname"; + else + route="any net $net netmask $mask gw $gw $ifname"; + route1="any net $net netmask $mask gw $gw $ifname"; + fi fi if [ -f $filename ]; then grep "$route" $filename 2>&1 1>/dev/null @@ -340,15 +387,23 @@ rm_persistent_route() # ipv6 net if echo $net | grep : 2>&1 1>/dev/null then - route="$net/$mask $gw - -"; - route1="$net\/$mask $gw - -"; + if [ $gw = "" -o $gw = "::" ] ; then + route="$net/$mask :: - $ifname"; + route1="$net\/$mask :: - $ifname"; + else + route="$net/$mask $gw - -"; + route1="$net\/$mask $gw - -"; + fi else + if [ $gw = "" ] ; then + $gw = "0.0.0.0"; + fi if [ -n "$ifname" ]; then route="$net $gw $mask $ifname"; route1="$net $gw $mask $ifname"; else - route="$net $gw $mask"; - route1="$net $gw $mask"; + route="$net $gw $mask -"; + route1="$net $gw $mask -"; fi fi if [ -f $filename ]; then @@ -376,10 +431,18 @@ rm_persistent_route() echo $net | grep : 2>&1 1>/dev/null #ipv6 if [ $? -eq 0 ];then - matchstr="$net/$mask gw $gw" + if [ $gw = "" -o $gw = "::" ] ; then + matchstr="$net/$mask dev $ifname" + else + matchstr="$net/$mask gw $gw" + fi v6flag=1 else - matchstr="net $net netmask $mask gw $gw" + if [ $gw = "" -o $gw = "0.0.0.0" ] ; then + matchstr="net $net netmask $mask dev $ifname" + else + matchstr="net $net netmask $mask gw $gw" + fi fi grep "$matchstr" $filename @@ -397,12 +460,22 @@ rm_persistent_route() then filename="/etc/sysconfig/static-routes-ipv6"; # $net/$mask does not work with sed - route="$ifname $net\/$mask $gw" - route1="$ifname $net/$mask $gw" + if [ "$gw" = "" -o "$gw" = "::" ] ; then + route="$ifname $net\/$mask ::" + route1="$ifname $net/$mask ::" + else + route="$ifname $net\/$mask $gw" + route1="$ifname $net/$mask $gw" + fi else filename="/etc/sysconfig/static-routes"; - route="any net $net netmask $mask gw $gw $ifname"; - route1="any net $net netmask $mask gw $gw $ifname"; + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + route="any net $net netmask $mask dev $ifname"; + route1="any net $net netmask $mask dev $ifname"; + else + route="any net $net netmask $mask gw $gw $ifname"; + route1="any net $net netmask $mask gw $gw $ifname"; + fi fi if [ -f $filename ]; then grep "$route" $filename 2>&1 1>/dev/null @@ -431,14 +504,22 @@ if [ "$op" = "add" ]; then if echo $net | grep : 2>&1 1>/dev/null then if [ "$(uname -s)" = "Linux" ]; then - cmd="ip -6 route add $net/$mask via $gw" + if [ "$gw" = "" -o "$gw" = "::" ] ; then + cmd="ip -6 route add $net/$mask dev $ifname" + else + cmd="ip -6 route add $net/$mask via $gw" + fi else # AIX TODO cmd="ip -6 route add $net/$mask via $gw" fi else if [ "$(uname -s)" = "Linux" ]; then - cmd="route add -net $net netmask $mask gw $gw" + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + cmd="route add -net $net netmask $mask dev $ifname" + else + cmd="route add -net $net netmask $mask gw $gw" + fi else cmd="route add -net $net -netmask $mask $gw" fi @@ -472,14 +553,22 @@ elif [ "$op" = "delete" ]; then if echo $net | grep : 2>&1 1>/dev/null then if [ "$(uname -s)" = "Linux" ]; then - cmd="ip -6 route delete $net/$mask via $gw" + if [ "$gw" = "" -o "$gw" = "::" ] ; then + cmd="ip -6 route delete $net/$mask dev $ifname" + else + cmd="ip -6 route delete $net/$mask via $gw" + fi else # AIX TODO cmd="ip -6 route delete $net/$mask via $gw" fi else if [ "$(uname -s)" = "Linux" ]; then - cmd="route delete -net $net netmask $mask gw $gw" + if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then + cmd="route delete -net $net netmask $mask dev $ifname" + else + cmd="route delete -net $net netmask $mask gw $gw" + fi else cmd="route delete -net $net -netmask $mask $gw" fi diff --git a/xCAT/postscripts/runxcatpost b/xCAT/postscripts/runxcatpost index 83284ca55..508c13f14 100644 --- a/xCAT/postscripts/runxcatpost +++ b/xCAT/postscripts/runxcatpost @@ -68,6 +68,4 @@ echo "$TMP" > /tmp/xcatenv . /tmp/xcatenv /xcatpost/addsiteyum -if [ -z "$NODESTATUS" ] || [ "$NODESTATUS" != "0" -a "$NODESTATUS" != "N" -a "$NODESTATUS" != "n" ]; then - /xcatpost/updateflag.awk $MASTER 3002 -fi +/xcatpost/updateflag.awk $MASTER 3002 diff --git a/xCAT/postscripts/setupnfsv4replication b/xCAT/postscripts/setupnfsv4replication index 092007aef..663fcd1cf 100755 --- a/xCAT/postscripts/setupnfsv4replication +++ b/xCAT/postscripts/setupnfsv4replication @@ -10,7 +10,7 @@ # Change these two parameters according to your requirements $::NFSRETRIES = 3; -$::NFSTIMEO = 10; +$::NFSTIMEO = 50; # Candidate commands: mount, df, lsfs, nfs4cl showfs # Only the mount command could list all file systems diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index a26b5660d..4bed671bf 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -42,12 +42,16 @@ download_postscripts() return 1; fi - if [ -f /opt/xcat/xcatinfo ]; then - INSTALLDIR=`grep 'INSTALLDIR' /opt/xcat/xcatinfo |cut -d= -f2` - fi + # Do not override the parameter --installdir if [ -z "$INSTALLDIR" ]; then - INSTALLDIR="/install" + if [ -f /opt/xcat/xcatinfo ]; then + INSTALLDIR=`grep 'INSTALLDIR' /opt/xcat/xcatinfo |cut -d= -f2` + fi + if [ -z "$INSTALLDIR" ]; then + INSTALLDIR="/install" + fi fi + max_retries=5 retry=0 rc=1 # this is a fail return diff --git a/xCAT/templates/mypostscript/mypostscript.tmpl b/xCAT/templates/mypostscript/mypostscript.tmpl index eaecb4670..70d6bc4b0 100755 --- a/xCAT/templates/mypostscript/mypostscript.tmpl +++ b/xCAT/templates/mypostscript/mypostscript.tmpl @@ -9,6 +9,9 @@ ENABLESSHBETWEENNODES=$ENABLESSHBETWEENNODES export ENABLESSHBETWEENNODES +ZONENAME=$ZONENAME +export ZONENAME + ## tabdump() is used to get all the information ## in the table ## The should only be non-"node key" table diff --git a/xCAT/xCAT.spec b/xCAT/xCAT.spec index 00384f49c..11a2c55ae 100644 --- a/xCAT/xCAT.spec +++ b/xCAT/xCAT.spec @@ -20,6 +20,8 @@ Source4: prescripts.tar.gz Source6: winpostscripts.tar.gz %endif +Source7: xcat.conf.apach24 + Provides: xCAT = %{version} Conflicts: xCATsn Requires: xCAT-server xCAT-client perl-DBD-SQLite @@ -29,6 +31,9 @@ Requires: xCAT-server xCAT-client perl-DBD-SQLite %ifos linux Requires: httpd nfs-utils nmap bind perl(CGI) +# on RHEL7, need to specify it explicitly +Requires: net-tools +Requires: /usr/bin/killall # On RHEL this pulls in dhcp, on SLES it pulls in dhcp-server Requires: /usr/sbin/dhcpd # On RHEL this pulls in openssh-server, on SLES it pulls in openssh @@ -147,8 +152,10 @@ chmod 755 $RPM_BUILD_ROOT/install/postscripts/* rm LICENSE.html mkdir -p postscripts/hostkeys cd - -cp %{SOURCE1} $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat.conf -cp %{SOURCE1} $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat.conf +cp %{SOURCE1} $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat.conf.apach22 +cp %{SOURCE7} $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat.conf.apach24 +cp %{SOURCE1} $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat.conf.apach22 +cp %{SOURCE7} $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat.conf.apach24 cp %{SOURCE5} $RPM_BUILD_ROOT/etc/xCATMN mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/packages/xCAT @@ -156,6 +163,31 @@ cp LICENSE.html $RPM_BUILD_ROOT/%{prefix}/share/doc/packages/xCAT %post +%ifos linux +#Apply the correct httpd/apache configuration file according to the httpd/apache version +if [ -n "$(httpd -v 2>&1 |grep -e '^Server version\s*:.*\/2.4')" ] +then + rm -rf /etc/httpd/conf.d/xcat.conf + cp /etc/httpd/conf.d/xcat.conf.apach24 /etc/httpd/conf.d/xcat.conf +elif [ -n "$(apachectl -v 2>&1 |grep -e '^Server version\s*:.*\/2.4')" ] +then + rm -rf /etc/httpd/conf.d/xcat.conf + cp /etc/apache2/conf.d/xcat.conf.apach24 /etc/apache2/conf.d/xcat.conf +else + rm -rf /etc/httpd/conf.d/xcat.conf + cp /etc/httpd/conf.d/xcat.conf.apach22 /etc/httpd/conf.d/xcat.conf + + rm -rf /etc/apache2/conf.d/xcat.conf + cp /etc/apache2/conf.d/xcat.conf.apach22 /etc/apache2/conf.d/xcat.conf +fi + +rm -rf /etc/apache2/conf.d/xcat.conf.apach22 +rm -rf /etc/apache2/conf.d/xcat.conf.apach24 +rm -rf /etc/httpd/conf.d/xcat.conf.apach22 +rm -rf /etc/httpd/conf.d/xcat.conf.apach24 + +%endif + # create dir for the current pid mkdir -p /var/run/xcat @@ -184,11 +216,15 @@ exit 0 %clean + %files %{prefix} # one for sles, one for rhel. yes, it's ugly... -/etc/httpd/conf.d/xcat.conf -/etc/apache2/conf.d/xcat.conf +/etc/apache2/conf.d/xcat.conf.apach22 +/etc/apache2/conf.d/xcat.conf.apach24 +/etc/httpd/conf.d/xcat.conf.apach22 +/etc/httpd/conf.d/xcat.conf.apach24 + /etc/xCATMN /install/postscripts /install/prescripts @@ -198,7 +234,11 @@ exit 0 %defattr(-,root,root) %postun + + if [ "$1" = "0" ]; then + + %ifnos linux if grep "^xcatd" /etc/inittab >/dev/null then