From f926e81c1cd27c68a2ed7f8b8214efc4860764b6 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 20 Jun 2016 06:14:42 -0400 Subject: [PATCH 001/187] add package test case --- xCAT-test/autotest/testcase/pkg/cases0 | 128 +++++++++----- xCAT-test/autotest/testcase/pkg/pkgtest.pl | 187 +++++++++++++++++++++ 2 files changed, 272 insertions(+), 43 deletions(-) create mode 100755 xCAT-test/autotest/testcase/pkg/pkgtest.pl diff --git a/xCAT-test/autotest/testcase/pkg/cases0 b/xCAT-test/autotest/testcase/pkg/cases0 index c959e7974..bf2ba6663 100644 --- a/xCAT-test/autotest/testcase/pkg/cases0 +++ b/xCAT-test/autotest/testcase/pkg/cases0 @@ -1,69 +1,111 @@ start:del_ospkg descreption:del ospkg -cmd:if cat /etc/*-release | grep SUSE >/dev/null; then ver=`echo "$$os" |awk -F "." '{print $1}'`; cp /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.bak; `cat /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist |sed 's/ntp/-ntp/g' >> /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.1`;`yes | cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.1 /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist` ;updatenode $$CN -S;elif cat /etc/*release |grep "Red Hat" >/dev/null;then ver=`echo "$$os" |awk -F "." '{print $1}'`;cp /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.bak;`cat /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist |sed 's/ntp/-ntp/g' >>/opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.1`;`yes |cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.1 /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist` ;updatenode $$CN -S;fi +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s $$osimage pkglist __GETNODEATTR($$CN,os)__ check:rc==0 -cmd:rm -rf /opt/xcat/share/xcat/install/rh/compute.*.pkglist.1 -cmd:xdsh $$CN rpm -qa |grep ntp-4.2 -check:rc!=0 -cmd:if cat /etc/*-release | grep SUSE >/dev/null; then ver=`echo "$$os" |awk -F "." '{print $1}'`; `yes| cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.bak /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist`;elif cat /etc/*release |grep "Red Hat" >/dev/null;then ver=`echo "$$os" |awk -F "." '{print $1}'`;`yes |cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.bak /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist`;fi -#cmd:rm -rf /opt/xcat/share/xcat/install/rh/compute.*.pkglist.1 -cmd:rm -rf /opt/xcat/share/xcat/install/rh/compute.*.pkglist.bak -end -start:add_ospkg -descreption:add ospkg -cmd:if cat /etc/*-release | grep SUSE >/dev/null; then ver=`echo "$$os" |awk -F "." '{print $1}'`; cp /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.bak; `cat /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist |sed 's/ntp/-ntp/g' >> /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.1`;`yes | cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.1 /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist` ;updatenode $$CN -S;elif cat /etc/*release |grep "Red Hat" >/dev/null;then ver=`echo "$$os" |awk -F "." '{print $1}'`;cp /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.bak;`cat /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist |sed 's/ntp/-ntp/g' >>/opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.1`;`yes |cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.1 /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist` ;updatenode $$CN -S;fi -cmd:rm -rf /opt/xcat/share/xcat/install/rh/compute.*.pkglist.1 -check:rc==0 -cmd:xdsh $$CN rpm -qa |grep ntp-4.2 -check:rc!=0 -cmd:if cat /etc/*-release | grep SUSE >/dev/null; then ver=`echo "$$os" |awk -F "." '{print $1}'`; `yes| cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist.bak /opt/xcat/share/xcat/install/sles/compute.$ver.pkglist`;elif cat /etc/*release |grep "Red Hat" >/dev/null;then ver=`echo "$$os" |awk -F "." '{print $1}'`;`yes |cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist.bak /opt/xcat/share/xcat/install/rh/compute.$ver.pkglist`;fi -#cmd:rm -rf /opt/xcat/share/xcat/install/rh/compute.*.pkglist.1 cmd:updatenode $$CN -S check:rc==0 -cmd:xdsh $$CN rpm -qa |grep ntp-4.2 -check:output=~ntp-4.2 -cmd:rm -rf /opt/xcat/share/xcat/install/rh/compute.*.pkglist.bak +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM" ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r $$osimage pkglist __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:updatenode $$CN -S +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm" |grep "package manager for RPM";else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc!=0 +cmd:copycds $$ISO +check:rc==0 +end +start:add_ospkg_updatenode +descreption:add ospkg +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s $$osimage pkglist __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:updatenode $$CN -S +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM";else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r rpm; else xdsh $$CN rpm -e xCAT-test; fi +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM" ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc!=0 +cmd:copycds $$ISO +check:rc==0 +end +start:add_includeospkg_updatenode +descreption:add include ospkg list +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -i $$osimage pkglist __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:updatenode $$CN -S +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM" ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r rpm; else xdsh $$CN rpm -e xCAT-test; fi +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM" ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc!=0 +cmd:copycds $$ISO +check:rc==0 end start:add_other_pkg descreption:add other pkg -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`mkdir -p /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat/xcat-core`;cp -r /xcat-core/build/* /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat/xcat-core ;`cp -r /xcat-dep /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat ` ;`cd /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat && createrepo .`;`echo "xcat/xcat-core/xCAT" >> /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;`echo "xcat/xcat-dep/$ver/__GETNODEATTR($$CN,arch)__/conserver-xcat" >> /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist `;`echo "xcat/xcat-dep/$ver/__GETNODEATTR($$CN,arch)__/perl-Net-Telnet" >> /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;`echo "xcat/xcat-dep/sles/__GETNODEATTR($$CN,arch)__/perl-Expect" >> /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist` ;chdef -t osimage -o $ver-__GETNODEATTR($$CN,arch)__-install-compute otherpkglist=/opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist;elif echo "$$os" |grep "rhels7" >/dev/null;then ver=`echo "$$os" |awk -F "." '{print $1}'`;`mkdir -p /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat/xcat-core`;cp -r /xcat-core/build/* /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat/xcat-core ;`cp -r /xcat-dep /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat ` ;`cd /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat && createrepo .`;`echo "xcat/xcat-core/xCAT" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;`echo "xcat/xcat-dep/rh7/ppc64/conserver-xcat" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist `;`echo "xcat/xcat-dep/rh7/ppc64/perl-Net-Telnet" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;`echo "xcat/xcat-dep/rh7/ppc64/perl-Expect" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;chdef -t osimage -o $ver-__GETNODEATTR($$CN,arch)__-install-compute otherpkglist=opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist;elif echo "$$os" |grep "rhels6" >/dev/null;then ver=`echo "$$os" |awk -F "." '{print $1}'`;`mkdir -p /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat/xcat-core`;`cp -r /xcat-core/build/* /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat/xcat-core `;`cp -r /xcat-dep /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat ` ;`cd /install/post/otherpkgs/$$ver/__GETNODEATTR($$CN,arch)__/xcat && createrepo .`;`echo "xcat/xcat-core/xCAT" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;`echo "xcat/xcat-dep/rh6/__GETNODEATTR($$CN,arch)__/conserver-xcat" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist `;`echo "xcat/xcat-dep/rh6/__GETNODEATTR($$CN,arch)__/perl-Net-Telnet" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;`echo "xcat/xcat-dep/rh6/__GETNODEATTR($$CN,arch)__/perl-Expect" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;chdef -t osimage -o $ver-__GETNODEATTR($$CN,arch)__-install-compute otherpkglist=/opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist;fi -check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ cmd:updatenode $$CN -S check:rc==0 -cmd:xdsh $$CN lsdef +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r xcat-test; else xdsh $$CN rpm -e xCAT-test; fi +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc!=0 +cmd:copycds $$ISO check:rc==0 end + start:del_other_pkg descreption:del other pkg -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`cp /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.bak`;elif echo "$$os" |grep "rhels"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`cp /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.bak`;fi - -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`echo "xcat/xcat-core/xCAT-test" >> /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;elif echo "$$os" |grep "rhels";then ver=`echo "$$os" |awk -F "." '{print $1}'`;`echo "xcat/xcat-core/xCAT-test" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;fi -cmd:cd /install/post/otherpkgs/rhels7/__GETNODEATTR($$CN,arch)__/xcat && createrepo . -cmd:updatenode $$CN -S -check:rc==0 -cmd:xdsh $$CN yum repolist all -cmd:xdsh $$CN rpm -qa |grep xCAT-test -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`yes |cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.bak /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;elif echo "$$os" |grep "rhels"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`yes |cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.bak /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;fi -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;echo "-xCAT-test" >>/opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.1;`yes | cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.1 /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;elif echo "$$os" |grep "rhels"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;echo "-xCAT-test" >>/opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.1;`yes | cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.1 /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;fi +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 -cmd:xdsh $$CN rpm -qa |grep xCAT-test +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:updatenode $$CN -S +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc!=0 -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`yes |cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.bak /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;rm -rf /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.bak;rm -rf /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.1;elif echo "$$os" |grep "rhels"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`yes |cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.bak /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;rm -rf /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.bak;rm -rf /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.1;fi +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:copycds $$ISO +check:rc==0 end -start:add_other_pkg_afterinstall -descreption:add other pkg after install -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;`echo "xcat/xcat-core/xCAT-test" >> /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;elif echo "$$os" |grep "rhels";then ver=`echo "$$os" |awk -F "." '{print $1}'`;`echo "xcat/xcat-core/xCAT-test" >> /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;fi -cmd:updatenode $$CN -S -check:rc==0 -cmd:if echo "$$os" |grep "sles11"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;cat /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist |sed 's/xCAT-test/--xCAT-test/g' >>/opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.1;`yes | cp -f /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist.1 /opt/xcat/share/xcat/install/sles/compute.$ver.otherpkg.pkglist`;elif echo "$$os" |grep "rhels"; then ver=`echo "$$os" |awk -F "." '{print $1}'`;cat /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist |sed 's/xCAT-test/--xCAT-test/g' >>/opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.1;`yes | cp -f /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist.1 /opt/xcat/share/xcat/install/rh/compute.$ver.otherpkg.pkglist`;fi +start:add_other_pkg_include +descreption:add other pkg include other list +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -i -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 -cmd:xdsh $$CN rpm -qa |grep xCAT-test +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:xdsh $$CN lsdef +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage __GETNODEATTR($$CN,os)__ +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r xcat-test; else xdsh $$CN rpm -e xCAT-test; fi +check:rc==0 +cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi +check:rc!=0 +cmd:copycds $$ISO check:rc==0 end diff --git a/xCAT-test/autotest/testcase/pkg/pkgtest.pl b/xCAT-test/autotest/testcase/pkg/pkgtest.pl new file mode 100755 index 000000000..bf845e4dd --- /dev/null +++ b/xCAT-test/autotest/testcase/pkg/pkgtest.pl @@ -0,0 +1,187 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +use strict; +use warnings; +use Getopt::Long; +use Data::Dumper; +use Term::ANSIColor; +use Time::Local; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; +} +use lib "$::XCATROOT/lib/perl"; +my $osver; +my $log="/tmp/pkg.log"; +my $needhelp = 0; +my $setupenv = 0; +my $clearenv = 0; +my $setupenvinclude = 0; +my $removerpm = 0; +my $ospkg = 0; +my $int; +if ( + !GetOptions("h|?" => \$needhelp, + "s" => \$setupenv, + "c"=>\$clearenv, + "i"=>\$setupenvinclude, + "r"=>\$removerpm, + "o"=>\$ospkg) + ) +{ + &usage; + exit 1; +} + +sub usage +{ + print "Usage:pkg - Run xcat pkg test cases.\n"; + print " pkg [-?|-h]\n"; + print " pkgtest [-s] [osimage] [attribute] [os] set up package test environment \n"; + print " pkgtest [-i] [osimage] [attribute] [os] set up package test environment using include package list\n"; + print " pkgtest [-r] [osimage] [attribute] [os] remove package \n"; + print " pkgtest [-c] [osimage] [attribute] [os] clear package test environment \n"; + print " pkgtest [-o] [osimage] [attribute] [os] other package test \n"; + print "\n"; + return; +} + +sub getimgattr +{ + my @output = `lsdef -t osimage -o $ARGV[0] -i $ARGV[1]`; + my $pkglistvalue; + print " output is @output \n"; + if($?){ + print "unkonw"; + return "Unknown"; + } + if($? == 0){ + foreach my $output1 (@output){ + if($output1 =~ /$ARGV[1]=(.*)/){ + print "output1 is $output1 ,attrs is $ARGV[1] value is $1 \n"; + $pkglistvalue = $1 ; + } + } } + return $pkglistvalue; +} + +sub setupenv +{ + my $int = shift; + if ($ospkg){ + `mkdir -p $int`; + `cp -rf /xcat-core $int`; + }else{ + `cp $int /tmp/pkgtest.bak`; + } + if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + `echo "rpm" >>/tmp/pkgtest.bak `; + }else{ + `echo "xCAT-test" >>/tmp/pkgtest.bak `; + } +} +sub clearenv +{ + my $int = shift; + if ($ospkg ==0){ + `rm -rf /tmp/pkgtest.* `; + `rm -rf /install/pkgtest`; + }else{ + `rm -rf /tmp/pkgtest.* `; + `rm -rf $int`; + } +} + +sub setupenvinclude +{ + my $int = shift; + if ($ospkg){ + `mkdir -p $int`; + `cp -rf /xcat-core $int`; + }else{ + ` cp $int /tmp/pkgtest.bak`; + } + if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + `echo "rpm" >>/tmp/pkgtest.bak `; + }else{ + `echo "xCAT-test" >> /tmp/pkgtest.includelist `; + } + `echo "#INCLUDE:/tmp/pkgtest.includelist#">>/tmp/pkgtest.bak `; +} +sub removerpm +{ + my $int = shift; + if ($ospkg){ + `mkdir -p $int`; + `cp -rf /xcat-core $int`; + }else{ + ` cp $int /tmp/pkgtest.bak`; + } + if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + `echo "-rpm" >>/tmp/pkgtest.bak `; + }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg !=0)){ + `echo "-xcat-test">>/tmp/pkgtest.bak`; + }else{ + `echo "-xCAT-test" >>/tmp/pkgtest.bak`; + } +} + +if ($needhelp) +{ + &usage; + exit 0; +} + +$int = getimgattr; +if ( ($setupenv) || ($setupenvinclude) ||($removerpm)) +{ + if (! -f "/tmp/int"){ + `echo $int >> /tmp/int`; + }else{ + print "please clear the pkg test environment first \n"; + exit 1; + } +} +if ($setupenv) +{ + &setupenv($int); +} +if ($setupenvinclude) +{ + &setupenvinclude($int); +} +if ($removerpm) +{ + &removerpm($int); +} +if ($clearenv) +{ + if (-f "/tmp/int"){ + my $int=`cat /tmp/int`; + &clearenv($int); + `rm -rf /tmp/int`; + exit 0; + }else{ + print "please set the pkg test environment first \n"; + exit 1; + } +} +if (($setupenv) || ($setupenvinclude) ||($removerpm)) +{ + `mkdir -p /install/pkgtest`; + `cp -rf /xcat-core/* /install/pkgtest`; + if (($ARGV[2] !~ /ubuntu/)&&($ospkg ==0)){ + `chdef -t osimage -o $ARGV[0] pkgdir=/install/pkgtest pkglist=/tmp/pkgtest.bak `; + }elsif (($ARGV[2] !~ /ubuntu/)&&($ospkg !=0)){ + `chdef -t osimage -o $ARGV[0] otherpkglist=/tmp/pkgtest.bak`; + }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg !=0)){ + `chdef -t osimage -o $ARGV[0] otherpkglist="/tmp/pkgtest.bak" otherpkgdir="http://xcat.org/files/xcat/repos/apt/2.12/xcat-core trusty main"`; + }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + `chdef -t osimage -o $ARGV[0] pkglist=/tmp/pkgtest.bak`; + } +} +if ($?) +{ + return 0; +} From 6e7b7e20dc3e503aba267db8215847319d9c00d1 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Wed, 22 Jun 2016 05:31:25 -0400 Subject: [PATCH 002/187] modify pkg testcase --- xCAT-test/autotest/testcase/pkg/cases0 | 10 ++++- xCAT-test/autotest/testcase/pkg/pkgtest.pl | 46 +++++++++++----------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/xCAT-test/autotest/testcase/pkg/cases0 b/xCAT-test/autotest/testcase/pkg/cases0 index bf2ba6663..c38a9fa81 100644 --- a/xCAT-test/autotest/testcase/pkg/cases0 +++ b/xCAT-test/autotest/testcase/pkg/cases0 @@ -8,6 +8,8 @@ cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN check:rc==0 cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ check:rc==0 +cmd:copycds $$ISO +check:rc==0 cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r $$osimage pkglist __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S @@ -60,7 +62,7 @@ cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r xcat-test; else xdsh $$CN rpm -e xCAT-test; fi check:rc==0 @@ -76,10 +78,14 @@ cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o $$osi check:rc==0 cmd:updatenode $$CN -S check:rc==0 +cmd:sleep 10 +check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ check:rc==0 +cmd:copycds $$ISO +check:rc==0 cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S @@ -99,7 +105,7 @@ cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r xcat-test; else xdsh $$CN rpm -e xCAT-test; fi check:rc==0 diff --git a/xCAT-test/autotest/testcase/pkg/pkgtest.pl b/xCAT-test/autotest/testcase/pkg/pkgtest.pl index bf845e4dd..bd91ff631 100755 --- a/xCAT-test/autotest/testcase/pkg/pkgtest.pl +++ b/xCAT-test/autotest/testcase/pkg/pkgtest.pl @@ -53,15 +53,15 @@ sub getimgattr my $pkglistvalue; print " output is @output \n"; if($?){ - print "unkonw"; + print "unkonw"; return "Unknown"; } if($? == 0){ foreach my $output1 (@output){ - if($output1 =~ /$ARGV[1]=(.*)/){ + if($output1 =~ /$ARGV[1]=(.*)/){ print "output1 is $output1 ,attrs is $ARGV[1] value is $1 \n"; - $pkglistvalue = $1 ; - } + $pkglistvalue = $1 ; + } } } return $pkglistvalue; } @@ -71,15 +71,15 @@ sub setupenv my $int = shift; if ($ospkg){ `mkdir -p $int`; - `cp -rf /xcat-core $int`; + `cp -rf /xcat-core/* $int`; }else{ - `cp $int /tmp/pkgtest.bak`; + `cat "$int" >> /tmp/pkgtest.bak`; } - if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ - `echo "rpm" >>/tmp/pkgtest.bak `; - }else{ - `echo "xCAT-test" >>/tmp/pkgtest.bak `; - } + if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + `echo "rpm" >>/tmp/pkgtest.bak `; + }else{ + `echo "xCAT-test" >>/tmp/pkgtest.bak `; + } } sub clearenv { @@ -98,15 +98,15 @@ sub setupenvinclude my $int = shift; if ($ospkg){ `mkdir -p $int`; - `cp -rf /xcat-core $int`; - }else{ - ` cp $int /tmp/pkgtest.bak`; - } + `cp -rf /xcat-core/* $int`; + }else{ + ` cat $int >> /tmp/pkgtest.bak`; + } if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ - `echo "rpm" >>/tmp/pkgtest.bak `; - }else{ - `echo "xCAT-test" >> /tmp/pkgtest.includelist `; - } + `echo "rpm" >>/tmp/pkgtest.bak `; + }else{ + `echo "xCAT-test" >> /tmp/pkgtest.includelist `; + } `echo "#INCLUDE:/tmp/pkgtest.includelist#">>/tmp/pkgtest.bak `; } sub removerpm @@ -114,10 +114,10 @@ sub removerpm my $int = shift; if ($ospkg){ `mkdir -p $int`; - `cp -rf /xcat-core $int`; - }else{ - ` cp $int /tmp/pkgtest.bak`; - } + `cp -rf /xcat-core/* $int`; + }else{ + `cat "$int" >> /tmp/pkgtest.bak`; + } if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ `echo "-rpm" >>/tmp/pkgtest.bak `; }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg !=0)){ From 0691b8a5bbdb30658033960faeec9885e8d55ff7 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 18 Jul 2016 06:38:05 -0400 Subject: [PATCH 003/187] modify pkg testcase according to comments --- xCAT-test/autotest/testcase/pkg/cases0 | 48 ++++++++++------ xCAT-test/autotest/testcase/pkg/pkgtest.pl | 66 ++++++++++++++-------- 2 files changed, 73 insertions(+), 41 deletions(-) diff --git a/xCAT-test/autotest/testcase/pkg/cases0 b/xCAT-test/autotest/testcase/pkg/cases0 index c38a9fa81..47f81c176 100644 --- a/xCAT-test/autotest/testcase/pkg/cases0 +++ b/xCAT-test/autotest/testcase/pkg/cases0 @@ -1,35 +1,40 @@ start:del_ospkg descreption:del ospkg -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:copycds $$ISO +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM" ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ cmd:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm" |grep "package manager for RPM";else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc!=0 cmd:copycds $$ISO check:rc==0 end + start:add_ospkg_updatenode descreption:add ospkg -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:copycds $$ISO +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM";else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r rpm; else xdsh $$CN rpm -e xCAT-test; fi check:rc==0 @@ -38,15 +43,18 @@ check:rc!=0 cmd:copycds $$ISO check:rc==0 end + start:add_includeospkg_updatenode descreption:add include ospkg list -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -i $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:copycds $$ISO +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -i -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep "ii rpm"|grep "package manager for RPM" ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c $$osimage pkglist __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -g $$osimage -t pkglist -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r rpm; else xdsh $$CN rpm -e xCAT-test; fi check:rc==0 @@ -55,14 +63,17 @@ check:rc!=0 cmd:copycds $$ISO check:rc==0 end + start:add_other_pkg descreption:add other pkg -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:copycds $$ISO +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r xcat-test; else xdsh $$CN rpm -e xCAT-test; fi check:rc==0 @@ -74,7 +85,9 @@ end start:del_other_pkg descreption:del other pkg -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:copycds $$ISO +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -s -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 @@ -82,30 +95,33 @@ cmd:sleep 10 check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -r -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc!=0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:copycds $$ISO check:rc==0 end + start:add_other_pkg_include descreption:add other pkg include other list -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -i -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:copycds $$ISO +check:rc==0 +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -i -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:updatenode $$CN -S check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -l |grep xcat ;else xdsh $$CN rpm -qa |grep xCAT-test; fi check:rc==0 -cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o $$osimage otherpkgdir __GETNODEATTR($$CN,os)__ +cmd:perl /opt/xcat/share/xcat/tools/autotest/testcase/pkg/pkgtest.pl -c -o -g $$osimage -t otherpkgdir -v __GETNODEATTR($$CN,os)__ check:rc==0 cmd:if echo "__GETNODEATTR($$CN,os)__" | grep ubuntu >/dev/null; then xdsh $$CN dpkg -r xcat-test; else xdsh $$CN rpm -e xCAT-test; fi check:rc==0 diff --git a/xCAT-test/autotest/testcase/pkg/pkgtest.pl b/xCAT-test/autotest/testcase/pkg/pkgtest.pl index bd91ff631..b1f9ca2e4 100755 --- a/xCAT-test/autotest/testcase/pkg/pkgtest.pl +++ b/xCAT-test/autotest/testcase/pkg/pkgtest.pl @@ -4,7 +4,7 @@ use strict; use warnings; use Getopt::Long; -use Data::Dumper; +use Data::Dumper; use Term::ANSIColor; use Time::Local; BEGIN @@ -20,6 +20,8 @@ my $clearenv = 0; my $setupenvinclude = 0; my $removerpm = 0; my $ospkg = 0; +my $osimg; +my $attr; my $int; if ( !GetOptions("h|?" => \$needhelp, @@ -27,7 +29,10 @@ if ( "c"=>\$clearenv, "i"=>\$setupenvinclude, "r"=>\$removerpm, - "o"=>\$ospkg) + "o"=>\$ospkg, + "g=s"=>\$::OSIMG, + "t=s"=>\$::ATTR, + "v=s"=>\$::OSVERSION) ) { &usage; @@ -36,20 +41,20 @@ if ( sub usage { - print "Usage:pkg - Run xcat pkg test cases.\n"; - print " pkg [-?|-h]\n"; - print " pkgtest [-s] [osimage] [attribute] [os] set up package test environment \n"; - print " pkgtest [-i] [osimage] [attribute] [os] set up package test environment using include package list\n"; - print " pkgtest [-r] [osimage] [attribute] [os] remove package \n"; - print " pkgtest [-c] [osimage] [attribute] [os] clear package test environment \n"; - print " pkgtest [-o] [osimage] [attribute] [os] other package test \n"; + print "Usage:pkgtest.pl - Run xcat pkg test cases.\n"; + print " pkgtest.pl [-?|-h]\n"; + print " pkgtest.pl [-s] [-g osimage] [-t attribute] [-v os] set up package test environment \n"; + print " pkgtest.pl [-i] [-g osimage] [-t attribute] [-v os] set up package test environment using include package list\n"; + print " pkgtest.pl [-r] [-g osimage] [-t attribute] [-v os] remove package \n"; + print " pkgtest.pl [-c] [-g osimage] [-t attribute] [-v os] clear package test environment \n"; + print " pkgtest.pl [-o] [-g osimage] [-t attribute] [-v os] other package test \n"; print "\n"; return; } sub getimgattr { - my @output = `lsdef -t osimage -o $ARGV[0] -i $ARGV[1]`; + my @output = `lsdef -t osimage -o $osimg -i $attr`; my $pkglistvalue; print " output is @output \n"; if($?){ @@ -58,8 +63,8 @@ sub getimgattr } if($? == 0){ foreach my $output1 (@output){ - if($output1 =~ /$ARGV[1]=(.*)/){ - print "output1 is $output1 ,attrs is $ARGV[1] value is $1 \n"; + if($output1 =~ /$attr=(.*)/){ + print "output1 is $output1 ,attrs is value is $1 \n"; $pkglistvalue = $1 ; } } } @@ -75,7 +80,7 @@ sub setupenv }else{ `cat "$int" >> /tmp/pkgtest.bak`; } - if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + if (($osver =~ /ubuntu/)&&($ospkg ==0)){ `echo "rpm" >>/tmp/pkgtest.bak `; }else{ `echo "xCAT-test" >>/tmp/pkgtest.bak `; @@ -102,7 +107,7 @@ sub setupenvinclude }else{ ` cat $int >> /tmp/pkgtest.bak`; } - if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + if (($osver =~ /ubuntu/)&&($ospkg ==0)){ `echo "rpm" >>/tmp/pkgtest.bak `; }else{ `echo "xCAT-test" >> /tmp/pkgtest.includelist `; @@ -118,9 +123,9 @@ sub removerpm }else{ `cat "$int" >> /tmp/pkgtest.bak`; } - if (($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ + if (($osver =~ /ubuntu/)&&($ospkg ==0)){ `echo "-rpm" >>/tmp/pkgtest.bak `; - }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg !=0)){ + }elsif(($osver =~ /ubuntu/)&&($ospkg !=0)){ `echo "-xcat-test">>/tmp/pkgtest.bak`; }else{ `echo "-xCAT-test" >>/tmp/pkgtest.bak`; @@ -132,7 +137,18 @@ if ($needhelp) &usage; exit 0; } - +if($::OSIMG) +{ + $osimg = $::OSIMG; +} +if($::ATTR) +{ + $attr = $::ATTR; +} +if($::OSVERSION) +{ + $osver = $::OSVERSION; +} $int = getimgattr; if ( ($setupenv) || ($setupenvinclude) ||($removerpm)) { @@ -171,14 +187,14 @@ if (($setupenv) || ($setupenvinclude) ||($removerpm)) { `mkdir -p /install/pkgtest`; `cp -rf /xcat-core/* /install/pkgtest`; - if (($ARGV[2] !~ /ubuntu/)&&($ospkg ==0)){ - `chdef -t osimage -o $ARGV[0] pkgdir=/install/pkgtest pkglist=/tmp/pkgtest.bak `; - }elsif (($ARGV[2] !~ /ubuntu/)&&($ospkg !=0)){ - `chdef -t osimage -o $ARGV[0] otherpkglist=/tmp/pkgtest.bak`; - }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg !=0)){ - `chdef -t osimage -o $ARGV[0] otherpkglist="/tmp/pkgtest.bak" otherpkgdir="http://xcat.org/files/xcat/repos/apt/2.12/xcat-core trusty main"`; - }elsif(($ARGV[2] =~ /ubuntu/)&&($ospkg ==0)){ - `chdef -t osimage -o $ARGV[0] pkglist=/tmp/pkgtest.bak`; + if (($osver !~ /ubuntu/)&&($ospkg ==0)){ + `chdef -t osimage -o $osimg pkgdir=/install/pkgtest pkglist=/tmp/pkgtest.bak `; + }elsif (($osver !~ /ubuntu/)&&($ospkg !=0)){ + `chdef -t osimage -o $osimg otherpkglist=/tmp/pkgtest.bak`; + }elsif(($osver =~ /ubuntu/)&&($ospkg !=0)){ + `chdef -t osimage -o $osimg otherpkglist="/tmp/pkgtest.bak" otherpkgdir="http://xcat.org/files/xcat/repos/apt/2.12/xcat-core trusty main"`; + }elsif(($osver =~ /ubuntu/)&&($ospkg ==0)){ + `chdef -t osimage -o $osimg pkglist=/tmp/pkgtest.bak`; } } if ($?) From a5f39f972f29745c2b910695757610fb02a20833 Mon Sep 17 00:00:00 2001 From: Arif Ali Date: Fri, 20 Jan 2017 11:17:23 +0000 Subject: [PATCH 004/187] Update rcons, so that it detects conserver --- xCAT-client/bin/rcons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-client/bin/rcons b/xCAT-client/bin/rcons index 1f6eadd74..d939c7add 100755 --- a/xCAT-client/bin/rcons +++ b/xCAT-client/bin/rcons @@ -73,7 +73,7 @@ fi if [ $USE_CONFLUENT == "1" ] && ([ -x "/opt/confluent/bin/confetty" ] || [ -x "/usr/bin/confetty" ] || [ -x "/usr/local/bin/confetty" ]); then # use confluent, make sure conserver is not also running - CONSERVER_RC=`service conserver status >> /dev/null; echo $?` + CONSERVER_RC=`pidof conserver >> /dev/null; echo $?` if [[ ${CONSERVER_RC} == 0 ]]; then echo "Error: consoleservice is set to 'confluent' but conserver is running. Stop conserver, run makeconfluentcfg, and retry..." exit 1 From 603c7785f7911ed97ced3efca63aefc9462c87f4 Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Fri, 10 Feb 2017 13:38:22 -0800 Subject: [PATCH 005/187] MTM: add support for other vendors, in the form of vendor::model --- xCAT-genesis-scripts/bin/dodiscovery | 9 +++++++++ xCAT-server/lib/xcat/plugins/bmcdiscover.pm | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/xCAT-genesis-scripts/bin/dodiscovery b/xCAT-genesis-scripts/bin/dodiscovery index f1af844ff..8461c9f2b 100755 --- a/xCAT-genesis-scripts/bin/dodiscovery +++ b/xCAT-genesis-scripts/bin/dodiscovery @@ -72,6 +72,15 @@ if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86 MTM=VMware else MTM=`cat /sys/devices/virtual/dmi/id/product_name|awk -F'[' '{print $2}'|awk -F']' '{print $1}'` + if [ -z "$MTM" ]; then + SYS=`cat /sys/devices/virtual/dmi/id/sys_vendor` + PRD=`cat /sys/devices/virtual/dmi/id/product_name` + if [ ! -z "$SYS" ]; then + MTM=${SYS^^}":"${PRD^^} + else + MTM=${PRD^^} + fi + fi SERIAL=`cat /sys/devices/virtual/dmi/id/product_serial` fi CPUCOUNT=`cat /proc/cpuinfo |grep "model name"|wc -l` diff --git a/xCAT-server/lib/xcat/plugins/bmcdiscover.pm b/xCAT-server/lib/xcat/plugins/bmcdiscover.pm index 18e3a09e2..8b4faf6b3 100644 --- a/xCAT-server/lib/xcat/plugins/bmcdiscover.pm +++ b/xCAT-server/lib/xcat/plugins/bmcdiscover.pm @@ -921,6 +921,13 @@ sub bmcdiscovery_ipmi { $serial = $2; last; } + + if (($fru_output =~ /Product Manufacturer\s+:\s+(.*?)\s+P.*?roduct Name\s+:\s+(.*?)\s+P.*?roduct Serial\s+:\s+(\S+)/)) { + $mtm = $1.":".$2; + $serial = $3; + last; + } + } } From 4bfdf4d90826b2d133ab2a6ad536bd56b6538abb Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Fri, 10 Feb 2017 14:10:06 -0800 Subject: [PATCH 006/187] bmcdiscover: normalize nodename if mtm or serial contain unauthorized characters --- xCAT-server/lib/xcat/plugins/bmcdiscover.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-server/lib/xcat/plugins/bmcdiscover.pm b/xCAT-server/lib/xcat/plugins/bmcdiscover.pm index 8b4faf6b3..b593236fb 100644 --- a/xCAT-server/lib/xcat/plugins/bmcdiscover.pm +++ b/xCAT-server/lib/xcat/plugins/bmcdiscover.pm @@ -946,6 +946,7 @@ sub bmcdiscovery_ipmi { if ($mtm and $serial) { $node = "node-$mtm-$serial"; $node =~ s/(.*)/\L$1/g; + $node =~ s/[\s:\._]/-/g; } } elsif ($output =~ /error : unauthorized name/) { xCAT::MsgUtils->message("E", { data => ["BMC username is incorrect for $ip"] }, $::CALLBACK); From c0c6082b138ba3c1d6f54247f70ff0c518d28e9b Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Mon, 13 Feb 2017 10:57:26 -0800 Subject: [PATCH 007/187] dodiscovery: use information from FRU instead of DMI for MTM Don't use information from DMI to populate the MTM field, as there is no guarantee it will match with what's in the FRU pages. Since `bmcdiscover` uses FRU information, use it in `dosdiscovery` too so they will match for MTMS discovery. --- xCAT-genesis-scripts/bin/dodiscovery | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/xCAT-genesis-scripts/bin/dodiscovery b/xCAT-genesis-scripts/bin/dodiscovery index 8461c9f2b..5bb3bb894 100755 --- a/xCAT-genesis-scripts/bin/dodiscovery +++ b/xCAT-genesis-scripts/bin/dodiscovery @@ -73,14 +73,11 @@ if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86 else MTM=`cat /sys/devices/virtual/dmi/id/product_name|awk -F'[' '{print $2}'|awk -F']' '{print $1}'` if [ -z "$MTM" ]; then - SYS=`cat /sys/devices/virtual/dmi/id/sys_vendor` - PRD=`cat /sys/devices/virtual/dmi/id/product_name` - if [ ! -z "$SYS" ]; then - MTM=${SYS^^}":"${PRD^^} - else - MTM=${PRD^^} - fi - fi + FRU=`ipmitool fru print 0` + if [ $? -eq 0 ]; then + MTM=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {m=$2} /Product Name/ {n=$2} END {print m":"n}'` + fi + fi SERIAL=`cat /sys/devices/virtual/dmi/id/product_serial` fi CPUCOUNT=`cat /proc/cpuinfo |grep "model name"|wc -l` From ecde363c82405d8e5a8a2cf4a9b7c61cdea0b34c Mon Sep 17 00:00:00 2001 From: caomengmeng Date: Mon, 20 Feb 2017 02:33:00 -0500 Subject: [PATCH 008/187] completed --- .../autotest/bundle/rhels7.2_ppc64.bundle | 8 ++ .../autotest/bundle/rhels7.2_ppc64le.bundle | 121 ++++++++++++++++-- .../autotest/bundle/rhels7.3_ppc64.bundle | 12 ++ .../autotest/bundle/rhels7.3_ppc64le.bundle | 113 +++++++++++++++- 4 files changed, 236 insertions(+), 18 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle index 3d27a17b1..fe2dee644 100644 --- a/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle @@ -4,6 +4,10 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 +makehosts_h +makehosts_help +makehosts_n +makehosts_n_noderange updatenode_h updatenode_v updatenode_diskful_syncfiles @@ -261,6 +265,7 @@ xdsh_Q_command xdsh_c_cn xdsh_e_filename xdsh_E +xdsh_i_linux xdsh_t xdsh_q xdsh_T @@ -282,6 +287,9 @@ switchdiscover_range_r switchdiscover_range_x switchdiscover_range_z switchdiscover_range_z_V +nodeset_shell +nodeset_cmdline +nodeset_runimg makentp_v makentp_h nodeset_check_warninginfo diff --git a/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle index 72e0bfe20..9b299d8e5 100644 --- a/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle @@ -10,8 +10,36 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +updatenode_h +updatenode_v +updatenode_diskful_syncfiles +updatenode_diskful_syncfiles_rename +updatenode_diskful_syncfiles_dir +updatenode_diskful_syncfiles_multi_files +updatenode_syncfile_EXECUTE +updatenode_syncfile_EXECUTEALWAYS +updatenode_syncfile_APPEND +updatenode_syncfile_MERGE +updatenode_P_script1 +updatenode_P_script2 +updatenode_f_incompatible_flags +updatenode_k_incompatible_flags +updatenode_diskful_syncfiles_P_script1 +updatenode_script3 +updatenode_P_script1_script2 +updatenode_without_flag + chdef_null +chdef_t_node +chdef_t_network +chdef_p +chdef_m chdef_z +chdef_group +chdef_group_p +chdef_dynamic_group +chdef_multiple_keys +chdef_n chdef_t_o_error chtab_null chtab_d @@ -19,16 +47,16 @@ chtab_modify_node chtab_modify_key chtab_h chtab_v +copycds_iso +copycds_n +copycds_a +copycds_n_a +copycds_a_err +copycds_n_err packimage_o_p_a_m packimage_imagename packimage_h packimage_v -packimage_m_cpio_c_gzip -packimage_m_cpio_c_xz -packimage_m_tar_c_gzip -packimage_m_tar_c_xz -packimage_m_invalid_archive_method -packimage_m_invalid_compress_method pping_h pping_v pping_node @@ -44,6 +72,9 @@ lsdef_t lsdef_t_i_o lsdef_t_w lsdef_t_err +lslite_i +lslite_noderange +lslite_h makeconservercf_null makeconservercf_noderange makeconservercf_d @@ -100,6 +131,7 @@ nodels_tablevalue_tablecolumn nodels_noderange_tablecolumn nodels_h nodels_v +xcatstanzafile_normal xcatstanzafile_colon xcatstanzafile_attribute xcatstanzafile_objtype @@ -117,7 +149,22 @@ nodestat_err_node rinv_noderange_err rmdef_null rmdef_t_err +rpower_off +rpower_stat +rpower_boot +rpower_on +rpower_reset +rpower_noderange +rpower_noderange_nodeps rpower_err_noderange +rscan_noderange +rscan_x +rscan_z +rscan_w +rscan_x_w +rscan_z_w +rvitals_lcds +rvitals_all rvitals_noderange_err tabdump_table tabdump_d @@ -138,6 +185,7 @@ tabprune_h tabprune_v tabprune_a_eventlog tabprune_V_a_eventlog +tabprune_p_auditlog tabprune_i_auditlog tabprune_V_n_auditlog tabgrep_node @@ -175,13 +223,35 @@ lsxcatd_null lsxcatd_h lsxcatd_d lsxcatd_a +makehosts_h +makehosts_help +makehosts_null +makehosts_l +makehosts_d +makehosts_n +makehosts_n_noderange +xdcp_src_dst +makedns_h makedns_d_node makedns_n makedns -copycds_iso -copycds_n -copycds_a -copycds_n_a +noderange_individual_node +noderange_individual_grp +noderange_node01-node10 +noderange_group1-group3 +noderange_10-20 +noderange_XCAT_NODE_PREFIX +noderange_XCAT_NODE_SUFFIX +noderange_exclusion +noderange_group_intersection +confignics_config_one_port_single_value +confignics_config_multiple_ports_single_value +confignics_config_multiple_ports_multiple_value +confignics_config_multiple_port_withnichostnamesuffixes_multiple_value +confignics_config_multiple_port_withnicaliases_multiple_value +confignics_disable_set_to_yes +confignics_disable_set_to_1 +confignics_s xdsh_h xdsh_V xdsh_regular_command @@ -214,13 +284,40 @@ switchdiscover_range_z_V nodeset_shell nodeset_cmdline nodeset_runimg -redhat_migration1 -redhat_migration2 +makentp_v +makentp_h +nodeset_check_warninginfo +runcmdinstaller_h +runcmdinstaller_command +get_xcat_postscripts_loginfo +updatenode_postscripts_loginfo +bmcdiscover_h +bmcdiscover_nmap_range +bmcdiscover_v +bmcdiscover_check_paswd +bmcdiscover_check_passwd_wrong +bmcdiscover_get_ipsource +bmcdiscover_range_w +bmcdiscover_range_z +xcatd_start +xcatd_stop +xcatd_restart +run_command_with_XCATBYPASS +disable_root_permission_in_policy_table +assign_certain_command_permission xcatconfig_u_check_xcatsslversion_rhels_sles +packimage_m_cpio_c_gzip +packimage_m_cpio_c_xz +packimage_m_tar_c_gzip +packimage_m_tar_c_xz +packimage_m_invalid_archive_method +packimage_m_invalid_compress_method reg_linux_statelite_installation_flat SN_setup_case reg_linux_diskfull_installation_hierarchy reg_linux_diskless_installation_hierarchy reg_linux_statelite_installation_hierarchy_by_ramdisk reg_linux_statelite_installation_hierarchy_by_nfs +redhat_migration1 +redhat_migration2 clean_up_env diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle index 3d27a17b1..d679521ca 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle @@ -4,6 +4,10 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 +makehosts_h +makehosts_help +makehosts_n +makehosts_n_noderange updatenode_h updatenode_v updatenode_diskful_syncfiles @@ -254,6 +258,10 @@ confignics_config_multiple_port_withnicaliases_multiple_value confignics_disable_set_to_yes confignics_disable_set_to_1 confignics_s +copycds_iso +copycds_n +copycds_a +copycds_n_a xdsh_h xdsh_V xdsh_regular_command @@ -261,6 +269,7 @@ xdsh_Q_command xdsh_c_cn xdsh_e_filename xdsh_E +xdsh_i_linux xdsh_t xdsh_q xdsh_T @@ -282,6 +291,9 @@ switchdiscover_range_r switchdiscover_range_x switchdiscover_range_z switchdiscover_range_z_V +nodeset_shell +nodeset_cmdline +nodeset_runimg makentp_v makentp_h nodeset_check_warninginfo diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index 1b3103b19..4a8e312bb 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -10,8 +10,35 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +updatenode_h +updatenode_v +updatenode_diskful_syncfiles +updatenode_diskful_syncfiles_rename +updatenode_diskful_syncfiles_dir +updatenode_diskful_syncfiles_multi_files +updatenode_syncfile_EXECUTE +updatenode_syncfile_EXECUTEALWAYS +updatenode_syncfile_APPEND +updatenode_syncfile_MERGE +updatenode_P_script1 +updatenode_P_script2 +updatenode_f_incompatible_flags +updatenode_k_incompatible_flags +updatenode_diskful_syncfiles_P_script1 +updatenode_script3 +updatenode_P_script1_script2 +updatenode_without_flag chdef_null +chdef_t_node +chdef_t_network +chdef_p +chdef_m chdef_z +chdef_group +chdef_group_p +chdef_dynamic_group +chdef_multiple_keys +chdef_n chdef_t_o_error chtab_null chtab_d @@ -19,16 +46,17 @@ chtab_modify_node chtab_modify_key chtab_h chtab_v +copycds_iso +copycds_n +copycds_a +copycds_n_a +copycds_a_err +copycds_n_err packimage_o_p_a_m packimage_imagename packimage_h packimage_v -packimage_m_cpio_c_gzip -packimage_m_cpio_c_xz -packimage_m_tar_c_gzip -packimage_m_tar_c_xz -packimage_m_invalid_archive_method -packimage_m_invalid_compress_method + pping_h pping_v pping_node @@ -44,6 +72,9 @@ lsdef_t lsdef_t_i_o lsdef_t_w lsdef_t_err +lslite_i +lslite_noderange +lslite_h makeconservercf_null makeconservercf_noderange makeconservercf_d @@ -100,6 +131,7 @@ nodels_tablevalue_tablecolumn nodels_noderange_tablecolumn nodels_h nodels_v +xcatstanzafile_normal xcatstanzafile_colon xcatstanzafile_attribute xcatstanzafile_objtype @@ -117,7 +149,22 @@ nodestat_err_node rinv_noderange_err rmdef_null rmdef_t_err +rpower_off +rpower_stat +rpower_boot +rpower_on +rpower_reset +rpower_noderange +rpower_noderange_nodeps rpower_err_noderange +rscan_noderange +rscan_x +rscan_z +rscan_w +rscan_x_w +rscan_z_w +rvitals_lcds +rvitals_all rvitals_noderange_err tabdump_table tabdump_d @@ -138,6 +185,7 @@ tabprune_h tabprune_v tabprune_a_eventlog tabprune_V_a_eventlog +tabprune_p_auditlog tabprune_i_auditlog tabprune_V_n_auditlog tabgrep_node @@ -175,9 +223,35 @@ lsxcatd_null lsxcatd_h lsxcatd_d lsxcatd_a +makehosts_h +makehosts_help +makehosts_null +makehosts_l +makehosts_d +makehosts_n +makehosts_n_noderange +xdcp_src_dst +makedns_h makedns_d_node makedns_n makedns +noderange_individual_node +noderange_individual_grp +noderange_node01-node10 +noderange_group1-group3 +noderange_10-20 +noderange_XCAT_NODE_PREFIX +noderange_XCAT_NODE_SUFFIX +noderange_exclusion +noderange_group_intersection +confignics_config_one_port_single_value +confignics_config_multiple_ports_single_value +confignics_config_multiple_ports_multiple_value +confignics_config_multiple_port_withnichostnamesuffixes_multiple_value +confignics_config_multiple_port_withnicaliases_multiple_value +confignics_disable_set_to_yes +confignics_disable_set_to_1 +confignics_s copycds_iso copycds_n copycds_a @@ -214,7 +288,34 @@ switchdiscover_range_z_V nodeset_shell nodeset_cmdline nodeset_runimg +makentp_v +makentp_h +nodeset_check_warninginfo +runcmdinstaller_h +runcmdinstaller_command +get_xcat_postscripts_loginfo +updatenode_postscripts_loginfo +bmcdiscover_h +bmcdiscover_nmap_range +bmcdiscover_v +bmcdiscover_check_paswd +bmcdiscover_check_passwd_wrong +bmcdiscover_get_ipsource +bmcdiscover_range_w +bmcdiscover_range_z +xcatd_start +xcatd_stop +xcatd_restart +run_command_with_XCATBYPASS +disable_root_permission_in_policy_table +assign_certain_command_permission xcatconfig_u_check_xcatsslversion_rhels_sles +packimage_m_cpio_c_gzip +packimage_m_cpio_c_xz +packimage_m_tar_c_gzip +packimage_m_tar_c_xz +packimage_m_invalid_archive_method +packimage_m_invalid_compress_method reg_linux_statelite_installation_flat SN_setup_case reg_linux_diskfull_installation_hierarchy From cb153a7e8bde2a70601647eada791e9a3f569d23 Mon Sep 17 00:00:00 2001 From: caomengmeng Date: Wed, 22 Feb 2017 03:27:22 -0500 Subject: [PATCH 009/187] completed --- xCAT-test/autotest/testcase/rinv/cases1 | 70 ++++++++++++++++++++++ xCAT-test/autotest/testcase/rvitals/cases1 | 61 +++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 xCAT-test/autotest/testcase/rinv/cases1 create mode 100644 xCAT-test/autotest/testcase/rvitals/cases1 diff --git a/xCAT-test/autotest/testcase/rinv/cases1 b/xCAT-test/autotest/testcase/rinv/cases1 new file mode 100644 index 000000000..292e9b915 --- /dev/null +++ b/xCAT-test/autotest/testcase/rinv/cases1 @@ -0,0 +1,70 @@ +start:rinv_serial +arch:ppc64le +hcp:ipmi +cmd:rinv $$CN serial +check:rc==0 +check:output=~NODE 1 Chassis Serial Number:\s*\w{7} +end + +start:rinv_model +arch:ppc64le +hcp:ipmi +cmd:rinv $$CN model +check:rc==0 +check:output=~NODE 1 Chassis Part Number\s*:\s*\w{4}-\w{3} +end + +start:rinv_firm +arch:ppc64le +hcp:ipmi +cmd:rinv $$CN firm +check:rc==0 +check:output=~BMC Firmware\s*:\s*\w+.\w+ +end + +start:rinv_deviceid +hcp:ipmi +arch:ppc64le +cmd:rinv $$CN deviceid +check:rc==0 +check:output=~Device ID:\s*\w+ +check:output=~Product ID:\s*\w+ +check:output=~Manufacturer ID:\s*\w+ +end + + +start:rinv_vpd +hcp:ipmi +arch:ppc64le +cmd:rinv $$CN vpd +check:rc==0 +check:output=~Manufacturer ID:\s*\w+ +check:output=~Device ID:\s*\w+ +check:output=~BMC Firmware:\s*\w+.\w+ +check:output=~NODE 1 Chassis Serial Number:\s*\w{7} +check:output=~NODE 1 Chassis Part Number\s*:\s*\w{4}-\w{3} +end + + +start:rinv_all +hcp:ipmi +arch:ppc64le +cmd:rinv $$CN all +check:rc==0 +check:output=~BMC Firmware:\s*\w+.\w+ +check:output=~BMCCARD Board Part Number:\s*\w{7} +check:output=~UUID/GUID:\s*\w+-\w+-\w+-\w+-\w+ +check:output=~Product ID:\s*\d+ +check:output=~Manufacturer ID:\s*\d+ +check:output=~Device ID:\s*\d+ +check:output=~BMCCARD Board Serial Number:\s*\w+ +end + +start:rinv_noderange_err +hcp:ipmi +arch:ppc64le +cmd:rinv testnode +check:rc!=0 +check:output=~Error +end + diff --git a/xCAT-test/autotest/testcase/rvitals/cases1 b/xCAT-test/autotest/testcase/rvitals/cases1 new file mode 100644 index 000000000..8a43aedb6 --- /dev/null +++ b/xCAT-test/autotest/testcase/rvitals/cases1 @@ -0,0 +1,61 @@ +start:rvitals_temp +arch:ppc64le +hcp:ipmi +cmd:rvitals $$CN temp +check:rc==0 +check:output=~Ambient Temp +end + +start:rvitals_disktemp +arch:ppc64le +hcp:ipmi +cmd:rvitals $$CN disktemp +check:rc==0 +check:output=~Ambient Temp +end + +start:rvitals_cputemp +arch:ppc64le +hcp:ipmi +cmd:rvitals $$CN cputemp +check:rc==0 +check:output=~Ambient Temp +end + +start:rvitals_fanspeed +arch:ppc64le +hcp:ipmi +cmd:rvitals $$CN fanspeed +check:rc==0 +check:output=~Fan\s*\d:\s*\w+\s*RPM +end + +start:rvitals_voltage +arch:ppc64le +hcp:ipmi +cmd:rvitals $$CN voltage +check:rc==0 +check:output=~CPU VDD Volt +end + +start:rvitals_all +arch:ppc64le +hcp:ipmi +cmd:rvitals $$CN all +check:rc==0 +check:output=~Power Status +check:output=~Power Overload +check:output=~Power Interlock +check:output=~Power Fault +check:output=~Power Control Fault +check:output=~Power Restore Policy +check:output=~Ambient Temp +end + +start:rvitals_noderange_err +arch:ppc64le +hcp:ipmi +cmd:rvitals testnode +check:rc!=0 +check:output=~Error +end From 34908bb59ac6999030bf313e31d873ac09dc3faa Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Wed, 22 Feb 2017 16:29:34 -0500 Subject: [PATCH 010/187] update bonding configuration instructions --- .../common/deployment/cfg_network.rst | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst index aa0e78f03..5c8e1e42b 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst @@ -19,6 +19,8 @@ The following example set the xCAT properties for compute node ``cn1`` to achiev Define attributes in the ``nics`` table --------------------------------------- +Chose one of three methods described below: + #. Using the ``mkdef`` or ``chdef`` commands a. Compute node ``cn1`` has two physical NICs: ``eth2`` and ``eth3`` :: @@ -30,7 +32,7 @@ Define attributes in the ``nics`` table chdef cn1 nictypes.bond0=bond \ nicdevices.bond0="eth2|eth3" - c. Fom ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` :: + c. From ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` :: chdef cn1 nictypes.bond0.1=vlan \ nictypes.bond0.2=vlan \ @@ -102,6 +104,11 @@ Use the ``chdef`` command to add/modify the networks in the ``networks`` table : chdef -t network net10 net=10.0.0.0 mask=255.0.0.0 mgtifname=eth0 chdef -t network net20 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 +For bonding add :: + + chdef -t network net40 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 + chdef cn1 nicnetworks.bond0=net40 + Add ``confignetwork`` into the node's postscripts list ------------------------------------------------------ @@ -110,12 +117,19 @@ Using below command to add ``confignetwork`` into the node's postscripts list :: chdef cn1 -p postscripts=confignetwork -During OS deployment on compute node, ``confignetwork`` will be run in postscript. -If the compute node has OS, use ``updatenode`` command to run ``confignetwork`` :: +During OS deployment on compute node, ``confignetwork`` postscript will be executed. +If the compute node is already running, use ``updatenode`` command to run ``confignetwork`` postscript without rebooting the node:: updatenode cn1 -P confignetwork +Verify bonding mode +------------------- +Login to compute node and check bonding options in ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file :: + BONDING_OPTS="mode=802.3ad xmit_hash_policy=layer2+3" +The ``mode=802.3ad`` requires additional configuration on the switch. ``mode=2`` can be used for bonding without additional switch configuration. If changes are made to ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file, restart network service :: + + systemctl restart network.service From e36cce018a63ea9e64ce8ecba1c825052a0d7abb Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Thu, 23 Feb 2017 13:25:03 +0800 Subject: [PATCH 011/187] Add PostgreSQL support in test case pre_deploy_sn --- .../testcase/installation/pre_deploy_sn | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/xCAT-test/autotest/testcase/installation/pre_deploy_sn b/xCAT-test/autotest/testcase/installation/pre_deploy_sn index 4ef510174..d46f49564 100755 --- a/xCAT-test/autotest/testcase/installation/pre_deploy_sn +++ b/xCAT-test/autotest/testcase/installation/pre_deploy_sn @@ -16,11 +16,24 @@ sub runcmd { } } -$cmd = "XCATMYSQLADMIN_PW=12345 XCATMYSQLROOT_PW=12345 /opt/xcat/bin/mysqlsetup -i -V"; -runcmd("$cmd"); +if ($ENV{XCAT_DATABASE} eq "PostgreSQL") { + $cmd = "XCATPGPW=12345 /opt/xcat/bin/pgsqlsetup -i -V"; + runcmd("$cmd"); -$cmd = "echo \"GRANT ALL on xcatdb.* TO xcatadmin@\'%\' IDENTIFIED BY \'12345\'\;\" | mysql -u root -p12345"; -runcmd("$cmd"); + open(my $fh, '>>', '/var/lib/pgsql/data/pg_hba.conf') or die; + print $fh "host all all 0.0.0.0/0 md5\n"; + print $fh "host all all ::0/0 md5\n"; + close $fh; + + $cmd = "service postgresql restart" + runcmd("$cmd"); +} else { + $cmd = "XCATMYSQLADMIN_PW=12345 XCATMYSQLROOT_PW=12345 /opt/xcat/bin/mysqlsetup -i -V"; + runcmd("$cmd"); + + $cmd = "echo \"GRANT ALL on xcatdb.* TO xcatadmin@\'%\' IDENTIFIED BY \'12345\'\;\" | mysql -u root -p12345"; + runcmd("$cmd"); +} my $xcatballpath = "/install/post/otherpkgs/$os/$arch/xcat"; $cmd = "mkdir -p $xcatballpath/xcat-core && cp -r /xcat-core/* $xcatballpath/xcat-core && cp -r /xcat-dep $xcatballpath"; From 8b393fda869d4af7cb89499d8262937703eeaf71 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Thu, 23 Feb 2017 14:11:06 +0800 Subject: [PATCH 012/187] Patch SN_setup_case for PostgreSQL support --- xCAT-test/autotest/testcase/installation/SN_setup_case | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/SN_setup_case b/xCAT-test/autotest/testcase/installation/SN_setup_case index 1873a0efd..ac693c267 100644 --- a/xCAT-test/autotest/testcase/installation/SN_setup_case +++ b/xCAT-test/autotest/testcase/installation/SN_setup_case @@ -2,7 +2,7 @@ start:SN_setup_case os:Linux stop:yes -cmd:/opt/xcat/share/xcat/tools/autotest/testcase/installation/pre_deploy_sn __GETNODEATTR($$SN,os)__ __GETNODEATTR($$SN,arch)__ +cmd:XCAT_DATABASE=$$XCAT_DATABASE /opt/xcat/share/xcat/tools/autotest/testcase/installation/pre_deploy_sn __GETNODEATTR($$SN,os)__ __GETNODEATTR($$SN,arch)__ check:rc==0 cmd:chtab key=nameservers site.value="" From 00ebd014c17dfeadbe7fe25ce117fb0e5458f2b3 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Thu, 23 Feb 2017 01:54:16 -0500 Subject: [PATCH 013/187] update cases for pdu support --- xCAT-test/autotest/linux.conf.template | 5 + xCAT-test/autotest/testcase/pdu/case0 | 158 +++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 xCAT-test/autotest/testcase/pdu/case0 diff --git a/xCAT-test/autotest/linux.conf.template b/xCAT-test/autotest/linux.conf.template index ecb158ad5..e54bf8c9b 100644 --- a/xCAT-test/autotest/linux.conf.template +++ b/xCAT-test/autotest/linux.conf.template @@ -115,6 +115,11 @@ bmcusername=USERID bmcpasswd=PASSW0RD #For bmc case u need to set username and passwd first #End +#For pdu support +PDU=f5pdu3 +PDUIP=50.0.0.8 +PORT=6 +#End [Custom] #commands run before test diff --git a/xCAT-test/autotest/testcase/pdu/case0 b/xCAT-test/autotest/testcase/pdu/case0 new file mode 100644 index 000000000..07bfbed10 --- /dev/null +++ b/xCAT-test/autotest/testcase/pdu/case0 @@ -0,0 +1,158 @@ +start:lsdef_pdu_object +description:list pdu object and it's attribute +cmd:lsdef -h +check:output=~pdu +cmd:mkdef $$PDU mgt=pdu nodetype=pdu groups=pdu +check:rc==0 +cmd:lsdef -t pdu +check:rc==0 +check:output=~$$PDU +check:output=~pdu +cmd:tabdump pdu +check:rc==0 +check:output=~$$PDU +cmd:rmdef $$PDU +check:rc==0 +end + +start:mkdef_pdu_object +description:create a pdu object and list it's attribute +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:lsdef -t pdu +check:rc==0 +check:output=~$$PDU +check:output=~pdu +cmd:rmdef $$PDU +check:rc==0 +cmd:lsdef $$PDU +check:rc!=0 +check:output=~Error: Could not find an object named '$$PDU' +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:chdef $$PDU machinetype=1u +check:rc==0 +cmd:lsdef $$PDU +check:output=~1u +cmd:rmdef $$PDU +check:rc==0 +end + +start:noderm_pdu_object +description:create a pdu object and use noderm to remove it +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:lsdef -t pdu +check:rc==0 +check:output=~$$PDU +check:output=~pdu +cmd:tabdump pdu +check:rc==0 +check:output=~$$PDU +cmd:noderm $$PDU +check:rc==0 +cmd:nodels +check:output!~$$PDU +cmd:tabdump pdu +check:output!~$$PDU +end + +start:pdu_communication +description:Verify a pdu snmp communication +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:lsdef -t pdu +check:rc==0 +cmd:makehosts $$PDU +check:rc==0 +cmd:grep $$PDUIP /etc/hosts +check:rc==0 +cmd:snmpwalk -v1 -cpublic -mALL $$PDU .1.3.6.1.2.1.1 +check:rc==0 +check:output=~PDU +check:output=~$$PDU +cmd:rmdef $$PDU +check:rc==0 +end + +start:pdu_rinv +description:Verify rinv works for pdu object +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:makehosts $$PDU +check:rc==0 +cmd:grep $$PDUIP /etc/hosts +check:rc==0 +cmd:snmpwalk -v1 -cpublic -mALL $$PDU .1.3.6.1.2.1.1 +check:rc==0 +cmd:rinv $$PDU +check:rc==0 +check:output=~$$PDU +cmd:rmdef $$PDU +check:rc==0 +end + +start:pdu_rpower +description:Verify rpower works for pdu object +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:makehosts $$PDU +check:rc==0 +cmd:grep $$PDUIP /etc/hosts +check:rc==0 +cmd:snmpwalk -v1 -cpublic -mALL $$PDU .1.3.6.1.2.1.1 +check:rc==0 +cmd:rpower $$PDU off +check:rc==0 +check:output=~$$PDU +check:output=~off +check:output!~on +cmd:rpower $$PDU on +check:rc==0 +check:output=~$$PDU +check:output=~on +check:output!~off +cmd:rpower $$PDU stat +check:rc==0 +check:output=~$$PDU +check:output=~on +check:output!~off +cmd:rmdef $$PDU +check:rc==0 +end + +start:pdu_node_operation +description:Verify operate node's pdu attribute could operate pdu +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:makehosts $$PDU +check:rc==0 +cmd:grep $$PDUIP /etc/hosts +check:rc==0 +cmd:snmpwalk -v1 -cpublic -mALL $$PDU .1.3.6.1.2.1.1 +check:rc==0 +cmd:lsdef $$CN |grep pdu|awk -F= '{print $2}' > /tmp/pduvalue +cmd:oldpdu=`lsdef $$CN |grep pdu|awk -F= '{print $2}'`;chdef $$CN pdu=$$PDU:$$PORT,$oldpdu +check:rc==0 +cmd:lsdef $$CN -i pdu +check:rc==0 +cmd:rpower $$CN pdustat +check:rc==0 +check:output=~$$CN: $$PDU outlet $$PORT is +cmd:rpower $$CN pduoff +check:rc==0 +check:output=~$$CN: $$PDU outlet $$PORT is off +cmd:rpower $$CN pduon +check:rc==0 +check:output=~$$CN: $$PDU outlet $$PORT is on +cmd:oldpdu=`cat /tmp/pduvalue`;chdef $$CN pdu=$oldpdu +cmd:rmdef $$PDU +check:rc==0 +cmd:rm -rf /tmp/pduvalue +end + + + + + + From 5006290b623d1984b993da1dea5dd60e6f85177f Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Thu, 23 Feb 2017 14:25:45 -0500 Subject: [PATCH 014/187] Refactor adapter bonding instructions --- .../common/deployment/cfg_network.rst | 135 +----------------- .../common/deployment/cfg_network_bond.rst | 55 +++++++ .../common/deployment/cfg_network_vlan.rst | 118 +++++++++++++++ .../common/deployment/cfg_second_adapter.rst | 9 +- 4 files changed, 182 insertions(+), 135 deletions(-) create mode 100644 docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst create mode 100644 docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst index 5c8e1e42b..0c3d779c2 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst @@ -1,135 +1,8 @@ Advanced Networking Configuration ================================= -The ``confignetwork`` postscript can be used to configure the network interfaces on the compute nodes to support VLAN, BONDs, and BRIDGES. In order to use the ``confignetwork`` postscript, the following attributes must be configured for the node in the ``nics`` table: +.. toctree:: + :maxdepth: 2 - * ``nicips`` - * ``nictypes`` - * ``nicnetworks`` - * ``nicdevices`` - resolves the relationship among the physical network intereface devices - -The following example set the xCAT properties for compute node ``cn1`` to achieve the following network configuration using the ``confignetwork`` postscript: - - * Compute node ``cn1`` has two physical NICs: eth2 and eth3 - * Bond eth2 and eth3 as ``bond0`` - * From ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` - * Make bridge ``br1`` using ``bond0.1`` with IP (10.0.0.1) - * Make bridge ``br2`` using ``bond0.2`` with IP (20.0.0.1) - -Define attributes in the ``nics`` table ---------------------------------------- - -Chose one of three methods described below: - -#. Using the ``mkdef`` or ``chdef`` commands - - a. Compute node ``cn1`` has two physical NICs: ``eth2`` and ``eth3`` :: - - chdef cn1 nictypes.eth2=ethernet nictypes.eth3=ethernet - - b. Define ``bond0`` and bond ``eth2`` and ``eth3`` as ``bond0`` :: - - chdef cn1 nictypes.bond0=bond \ - nicdevices.bond0="eth2|eth3" - - c. From ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` :: - - chdef cn1 nictypes.bond0.1=vlan \ - nictypes.bond0.2=vlan \ - nicdevices.bond0.1=bond0 \ - nicdevices.bond0.2=bond0 - - d. Create bridge ``br1`` using ``bond0.1`` with IP (10.0.0.1) :: - - chdef cn1 nictypes.br1=bridge \ - nicdevices.br1=bond0.1 \ - nicips.br1=10.0.0.1 \ - nicnetworks.br1="net10" - - e. Create bridge ``br2`` using ``bond0.2`` with IP (20.0.0.1) :: - - chdef cn1 nictypes.br2=bridge \ - nicdevices.br2=bond0.2 \ - nicips.br2=20.0.0.1 \ - nicnetworks.br2="net20" - -#. Using an xCAT stanza file - - - Prepare a stanza file ``.stanza`` with content similiar to the following: :: - - # - cn1: - objtype=node - arch=x86_64 - groups=kvm,vm,all - nicdevices.br1=bond0.1 - nicdevices.br2=bond0.2 - nicdevices.bond0.1=bond0 - nicdevices.bond0.2=bond0 - nicdevices.bond0=eth2|eth3 - nictypes.eth2=ethernet - nictypes.eth3=ethernet - nictypes.bond0=bond - nictypes.bond0.1=vlan - nictypes.bond0.2=vlan - nictypes.br1=bridge - nictypes.br2=bridge - nicips.br1=10.0.0.1 - nicips.br2=20.0.0.1 - nicnetworks.br1=net10 - nicnetworks.br2=net20 - - - Using the ``mkdef -z`` option, define the stanza file to xCAT: :: - - cat .stanza | mkdef -z - -#. Using ``tabedit`` to edit the ``nics`` database table directly - - The ``tabedit`` command opens the specified xCAT database table in a ``vi`` like editor and allows the user to edit any text and write the changes back to the database table. - - After changing the content of the ``nics`` table, here is the result from ``tabdump nics`` :: - - # tabdump nics - #node,nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases,nicextraparams,nicdevices,comments,disable - "cn1","br1!10.0.0.1,br2!20.0.0.1",,,"br1!bridge,eth2!ethernet,eth3!ethernet,bond0.2!vlan,bond0!bond,br2!bridge,bond0.1!vlan",,"br1!net10,br2!net20",,,"br1!bond0.1,bond0!eth2|eth3,bond0.2!bond0,bond0.1!bond0,br2!bond0.2",, - -Add network object into the networks table ------------------------------------------- - -The ``nicnetworks`` attribute only defines the nic that uses the IP address. -Other information about the network should be defined in the ``networks`` table. - -Use the ``chdef`` command to add/modify the networks in the ``networks`` table :: - - chdef -t network net10 net=10.0.0.0 mask=255.0.0.0 mgtifname=eth0 - chdef -t network net20 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 - -For bonding add :: - - chdef -t network net40 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 - chdef cn1 nicnetworks.bond0=net40 - -Add ``confignetwork`` into the node's postscripts list ------------------------------------------------------- - -Using below command to add ``confignetwork`` into the node's postscripts list :: - - chdef cn1 -p postscripts=confignetwork - - -During OS deployment on compute node, ``confignetwork`` postscript will be executed. -If the compute node is already running, use ``updatenode`` command to run ``confignetwork`` postscript without rebooting the node:: - - updatenode cn1 -P confignetwork - - -Verify bonding mode -------------------- - -Login to compute node and check bonding options in ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file :: - - BONDING_OPTS="mode=802.3ad xmit_hash_policy=layer2+3" - -The ``mode=802.3ad`` requires additional configuration on the switch. ``mode=2`` can be used for bonding without additional switch configuration. If changes are made to ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file, restart network service :: - - systemctl restart network.service +.. include:: ../../../common/deployment/cfg_network_vlan.rst +.. include:: ../../../common/deployment/cfg_network_bond.rst diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst new file mode 100644 index 000000000..ad3bdd89c --- /dev/null +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst @@ -0,0 +1,55 @@ +Configure Two Bonded Adapters +----------------------------- + +The following example set the xCAT properties for compute node ``cn1`` to create: + + * Compute node ``cn1`` has two physical NICs: eth2 and eth3 + * Bond eth2 and eth3 as ``bond0`` + +Define attributes in the ``nics`` table +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +#. Using the ``mkdef`` or ``chdef`` commands + + a. Compute node ``cn1`` has two physical NICs: ``eth2`` and ``eth3`` :: + + chdef cn1 nictypes.eth2=ethernet nictypes.eth3=ethernet + + b. Define ``bond0`` and bond ``eth2`` and ``eth3`` as ``bond0`` :: + + chdef cn1 nictypes.bond0=bond \ + nicdevices.bond0="eth2|eth3" + +Add network object into the networks table +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use the ``chdef`` command to add/modify the networks in the ``networks`` table :: + + chdef -t network net40 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 + chdef cn1 nicnetworks.bond0=net40 + +Add ``confignetwork`` into the node's postscripts list +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use command below to add ``confignetwork`` into the node's postscripts list :: + + chdef cn1 -p postscripts=confignetwork + + +During OS deployment on compute node, ``confignetwork`` postscript will be executed. +If the compute node is already running, use ``updatenode`` command to run ``confignetwork`` postscript without rebooting the node:: + + updatenode cn1 -P confignetwork + + +Verify bonding mode +~~~~~~~~~~~~~~~~~~~ + +Login to compute node cn1 and check bonding options in ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file :: + + BONDING_OPTS="mode=802.3ad xmit_hash_policy=layer2+3" + +The ``mode=802.3ad`` requires additional configuration on the switch. ``mode=2`` can be used for bonding without additional switch configuration. If changes are made to ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file, restart network service :: + + systemctl restart network.service diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst new file mode 100644 index 000000000..a4d637634 --- /dev/null +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst @@ -0,0 +1,118 @@ +Configure BOND, VLAN and BRIDGES +-------------------------------- + +The ``confignetwork`` postscript can be used to configure the network interfaces on the compute nodes to support VLAN, BONDs, and BRIDGES. In order to use the ``confignetwork`` postscript, the following attributes must be configured for the node in the ``nics`` table: + + * ``nicips`` + * ``nictypes`` + * ``nicnetworks`` + * ``nicdevices`` - resolves the relationship among the physical network intereface devices + +The following example set the xCAT properties for compute node ``cn1`` to achieve the following network configuration using the ``confignetwork`` postscript: + + * Compute node ``cn1`` has two physical NICs: eth2 and eth3 + * Bond eth2 and eth3 as ``bond0`` + * From ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` + * Make bridge ``br1`` using ``bond0.1`` with IP (10.0.0.1) + * Make bridge ``br2`` using ``bond0.2`` with IP (20.0.0.1) + +Define attributes in the ``nics`` table +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Chose one of three methods described below: + +#. Using the ``mkdef`` or ``chdef`` commands + + a. Compute node ``cn1`` has two physical NICs: ``eth2`` and ``eth3`` :: + + chdef cn1 nictypes.eth2=ethernet nictypes.eth3=ethernet + + b. Define ``bond0`` and bond ``eth2`` and ``eth3`` as ``bond0`` :: + + chdef cn1 nictypes.bond0=bond \ + nicdevices.bond0="eth2|eth3" + + c. From ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` :: + + chdef cn1 nictypes.bond0.1=vlan \ + nictypes.bond0.2=vlan \ + nicdevices.bond0.1=bond0 \ + nicdevices.bond0.2=bond0 + + d. Create bridge ``br1`` using ``bond0.1`` with IP (10.0.0.1) :: + + chdef cn1 nictypes.br1=bridge \ + nicdevices.br1=bond0.1 \ + nicips.br1=10.0.0.1 \ + nicnetworks.br1="net10" + + e. Create bridge ``br2`` using ``bond0.2`` with IP (20.0.0.1) :: + + chdef cn1 nictypes.br2=bridge \ + nicdevices.br2=bond0.2 \ + nicips.br2=20.0.0.1 \ + nicnetworks.br2="net20" + +#. Using an xCAT stanza file + + - Prepare a stanza file ``.stanza`` with content similiar to the following: :: + + # + cn1: + objtype=node + arch=x86_64 + groups=kvm,vm,all + nicdevices.br1=bond0.1 + nicdevices.br2=bond0.2 + nicdevices.bond0.1=bond0 + nicdevices.bond0.2=bond0 + nicdevices.bond0=eth2|eth3 + nictypes.eth2=ethernet + nictypes.eth3=ethernet + nictypes.bond0=bond + nictypes.bond0.1=vlan + nictypes.bond0.2=vlan + nictypes.br1=bridge + nictypes.br2=bridge + nicips.br1=10.0.0.1 + nicips.br2=20.0.0.1 + nicnetworks.br1=net10 + nicnetworks.br2=net20 + + - Using the ``mkdef -z`` option, define the stanza file to xCAT: :: + + cat .stanza | mkdef -z + +#. Using ``tabedit`` to edit the ``nics`` database table directly + + The ``tabedit`` command opens the specified xCAT database table in a ``vi`` like editor and allows the user to edit any text and write the changes back to the database table. + + After changing the content of the ``nics`` table, here is the result from ``tabdump nics`` :: + + # tabdump nics + #node,nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases,nicextraparams,nicdevices,comments,disable + "cn1","br1!10.0.0.1,br2!20.0.0.1",,,"br1!bridge,eth2!ethernet,eth3!ethernet,bond0.2!vlan,bond0!bond,br2!bridge,bond0.1!vlan",,"br1!net10,br2!net20",,,"br1!bond0.1,bond0!eth2|eth3,bond0.2!bond0,bond0.1!bond0,br2!bond0.2",, + +Add network object into the networks table +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``nicnetworks`` attribute only defines the nic that uses the IP address. +Other information about the network should be defined in the ``networks`` table. + +Use the ``chdef`` command to add/modify the networks in the ``networks`` table :: + + chdef -t network net10 net=10.0.0.0 mask=255.0.0.0 mgtifname=eth0 + chdef -t network net20 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 + +Add ``confignetwork`` into the node's postscripts list +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Using below command to add ``confignetwork`` into the node's postscripts list :: + + chdef cn1 -p postscripts=confignetwork + +During OS deployment on compute node, ``confignetwork`` postscript will be executed. +If the compute node is already running, use ``updatenode`` command to run ``confignetwork`` postscript without rebooting the node:: + + updatenode cn1 -P confignetwork + diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst index a6abdd3e9..76475cf02 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst @@ -47,7 +47,7 @@ There are 3 ways to complete this operation. The ``tabedit`` command opens the specified xCAT database table in a vi like editor and allows the user to edit any text and write the changes back to the database table. - *WARNING* Using the ``tabedit`` command is not the recommended method because it is tedious and error prone. + *WARNING:* Using the ``tabedit`` command is not the recommended method because it is tedious and error prone. After changing the content of the ``nics`` table, here is the result from ``tabdump nics`` :: @@ -70,7 +70,7 @@ After you have defined the configuration information in any of the ways above, r Add confignics into the node's postscripts list ----------------------------------------------- -Using below command to add confignics into the node's postscripts list :: +Use command below to add confignics into the node's postscripts list :: chdef cn1 -p postscripts=confignics @@ -78,7 +78,7 @@ By default, confignics does not configure the install nic. if need, using flag " chdef cn1 -p prostscripts="confignics -s" -Option "-s" write the install nic's information into configuration file for persistance. All install nic's data defined in nics table will be written also. +Option "-s" writes the install nic's information into configuration file for persistance. All install nic's data defined in nics table will be written also. Add network object into the networks table @@ -103,6 +103,7 @@ Option -r to remove the undefined NICS If the compute node's nics were configured by ``confignics`` and the nics configuration changed in the nics table, user the ``confignics -r`` to remove the undefined nic. For example, if on a compute node the ``eth0``, ``eth1``, and ``eth2`` nics were configured: :: + # ifconfig eth0 Link encap:Ethernet HWaddr 00:14:5e:d9:6c:e6 ... @@ -114,7 +115,7 @@ For example, if on a compute node the ``eth0``, ``eth1``, and ``eth2`` nics were Delete the eth2 definition in nics table using the ``chdef`` command. Then run the following to remove the undefined ``eth2`` nic on the compute node: :: - # updatenode -P "confignics -r" + updatenode -P "confignics -r" The result should have ``eth2`` disabled: :: From 04444e63a21ad9ec36a276f457913981ec83262f Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Thu, 23 Feb 2017 13:46:44 -0800 Subject: [PATCH 015/187] fix salve/slave typo --- xCAT/postscripts/configbond | 2 +- xCAT/postscripts/confignics | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xCAT/postscripts/configbond b/xCAT/postscripts/configbond index f80aee336..f2567193a 100755 --- a/xCAT/postscripts/configbond +++ b/xCAT/postscripts/configbond @@ -242,7 +242,7 @@ fi # add bonding driver alias for echo "alias $str_bond_name bonding" > /etc/modprobe.d/$str_bond_name.conf -# Bring down the salve devices first +# Bring down the slave devices first for slave in ${str_bond_name} ${array_bond_slaves[*]}; do $(ifdown $slave &>/dev/null) done diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index c651ecc1c..6ffb7600f 100755 --- a/xCAT/postscripts/confignics +++ b/xCAT/postscripts/confignics @@ -236,9 +236,9 @@ fi #do not configure the loopback nic if [ $bool_remove -eq 1 ];then if [ "$str_os_type" = "aix" ];then - str_temp=`ifconfig -a | grep flags | grep -vi loopback | grep -v SALVE | grep -v MASTER | awk -F: {'print $1'}` + str_temp=`ifconfig -a | grep flags | grep -vi loopback | grep -v SLAVE | grep -v MASTER | awk -F: {'print $1'}` else - str_temp=`ip link show | grep -v link | grep -vi loopback | grep -v SALVE | grep -v MASTER | awk {'print $2'} | sed s/://` + str_temp=`ip link show | grep -v link | grep -vi loopback | grep -v SLAVE | grep -v MASTER | awk {'print $2'} | sed s/://` fi old_ifs=$IFS IFS=$'\n' From 401f264df9777d192fbc68b4176cc51bc35a2fe6 Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Thu, 23 Feb 2017 14:52:35 -0800 Subject: [PATCH 016/187] confignics: fix regexp for Ethernet checks --- xCAT/postscripts/confignics | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index c651ecc1c..f754b2a2e 100755 --- a/xCAT/postscripts/confignics +++ b/xCAT/postscripts/confignics @@ -202,7 +202,7 @@ if [ "$str_temp" = "mac" ];then else str_inst_nic=`ip -o link | grep -i "$MACADDRESS" | awk '{print $2;}' | sed s/://` fi -elif [ `echo $str_temp | grep -E "e(n|th)[0-9a-z]+"` ];then +elif [ `echo $str_temp | grep -E "e(n|th|m)[0-9a-zA-Z]+"` ];then str_inst_nic=$str_temp fi @@ -247,7 +247,7 @@ if [ $bool_remove -eq 1 ];then for str_temp_nic in ${array_nics_temp[@]} do #the nic type should be ethernet - echo $str_temp_nic | grep -E "e(n|th)[0-9a-z]+" + echo $str_temp_nic | grep -E "e(n|th|m)[0-9a-zA-Z]+" if [ $? -ne 0 ];then continue fi From 0ac134a07efea78cdbefc0734b6c9202bea7c7b0 Mon Sep 17 00:00:00 2001 From: Arif Ali Date: Fri, 24 Feb 2017 01:54:15 +0000 Subject: [PATCH 017/187] revert: use df instead of mount, and check for the disk that /boot is on, rather than / I thought this was a problem last time, but I was wrong, so reverting the df concept here --- xCAT/postscripts/configefi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xCAT/postscripts/configefi b/xCAT/postscripts/configefi index 2ab49bdfa..2473d9c0b 100644 --- a/xCAT/postscripts/configefi +++ b/xCAT/postscripts/configefi @@ -21,7 +21,7 @@ if [ "$arch" = "x86_64" ]; then elif [ -f "/boot/efi/EFI/redhat/grubx64.efi" ];then efibootmgr -c -l \\EFI\\redhat\\grubx64.efi -L syscloneLinux - boot_root=`df /boot | awk '{print $1}' | tail -n 1` + boot_root=`mount | grep -E ' on\s+/ type ' | awk '{print $1}'` sed -i 's| root=\S*| root='$boot_root' net.ifnames=0|' /boot/efi/EFI/redhat/grub.cfg blkid -c /dev/null |grep UUID|while read str_line @@ -52,10 +52,10 @@ if [ "$arch" = "x86_64" ]; then boot_device='' if [ -f "/etc/systemconfig/systemconfig.conf" ];then #boot_root=`cat /etc/systemconfig/systemconfig.conf | grep ROOTDEV | awk '{print $3}'` - boot_root=`df /boot | awk '{print $1}' | tail -n 1` + boot_root=`mount | grep -E ' on\s+/ type ' | awk '{print $1}'` boot_device=`cat /etc/systemconfig/systemconfig.conf | grep BOOTDEV | awk '{print $3}'` else - boot_root=`df /boot | awk '{print $1}' | tail -n 1` + boot_root=`mount | grep -E ' on\s+/ type ' | awk '{print $1}'` boot_device=`echo $boot_root | sed -e 's/[0-9]*$//'` #str_temp=`mount | awk '{print $1","$3}'` From 7a330f00f924b6007638531d6a49ad9cb7dd65a0 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Fri, 24 Feb 2017 02:47:55 -0500 Subject: [PATCH 018/187] Update version to 2.13.3 --- Version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version b/Version index 0e83a9a9c..a1a4224dd 100644 --- a/Version +++ b/Version @@ -1 +1 @@ -2.13.2 +2.13.3 From 1ed721920886702e394852f3fe963fd1cfab23a7 Mon Sep 17 00:00:00 2001 From: zet809 Date: Fri, 24 Feb 2017 16:46:41 +0800 Subject: [PATCH 019/187] Update README.rst --- README.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 883a8aeb8..d7f1ae9f6 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ Documentation xCAT documentation is available at: http://xcat-docs.readthedocs.io/en/latest/ -|docs_latest| |docs_2131| |docs_2130| |docs_212| |docs_211| +|docs_latest| |docs_2132| |docs_2131| |docs_2130| |docs_212| |docs_211| Open Source License ------------------- @@ -22,6 +22,11 @@ Developers Developers and prospective contributors are encouraged to read the `Developers Guide `_ In particular the `GitHub `_ related subsection. +.. |docs_2132| image:: https://readthedocs.org/projects/xcat-docs/badge/?version=2.13.2 + :alt: 2.13.2 documentation status + :scale: 100% + :target: http://xcat-docs.readthedocs.io/en/2.13.2/ + .. |docs_2131| image:: https://readthedocs.org/projects/xcat-docs/badge/?version=2.13.1 :alt: 2.13.1 documentation status :scale: 100% From 16d259dae52ab28249acfd992f778b1101bf549a Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Fri, 24 Feb 2017 08:34:27 -0500 Subject: [PATCH 020/187] Added missing chdef statement --- .../manage_clusters/common/deployment/cfg_network_bond.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst index ad3bdd89c..d7360b127 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst @@ -5,6 +5,7 @@ The following example set the xCAT properties for compute node ``cn1`` to create * Compute node ``cn1`` has two physical NICs: eth2 and eth3 * Bond eth2 and eth3 as ``bond0`` + * Assign ip ``40.0.0.1`` to the bonded interface ``bond0`` Define attributes in the ``nics`` table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -18,15 +19,15 @@ Define attributes in the ``nics`` table b. Define ``bond0`` and bond ``eth2`` and ``eth3`` as ``bond0`` :: - chdef cn1 nictypes.bond0=bond \ - nicdevices.bond0="eth2|eth3" + chdef cn1 nictypes.bond0=bond nicdevices.bond0="eth2|eth3" + chdef cn1 nicips.bond0=40.0.0.1 Add network object into the networks table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the ``chdef`` command to add/modify the networks in the ``networks`` table :: - chdef -t network net40 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 + chdef -t network net40 net=40.0.0.0 mask=255.0.0.0 mgtifname=eth1 chdef cn1 nicnetworks.bond0=net40 Add ``confignetwork`` into the node's postscripts list From 01a5551ea74b7501c7c83ed960116a2a0c0a26cb Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Fri, 24 Feb 2017 13:15:42 -0500 Subject: [PATCH 021/187] Update manage.rst Clarify the option to clear the previous configuration for ONIE enabled switches --- .../advanced/networks/onie_switches/os_cumulus/manage.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/advanced/networks/onie_switches/os_cumulus/manage.rst b/docs/source/advanced/networks/onie_switches/os_cumulus/manage.rst index 5634eeaea..0f3ce1184 100644 --- a/docs/source/advanced/networks/onie_switches/os_cumulus/manage.rst +++ b/docs/source/advanced/networks/onie_switches/os_cumulus/manage.rst @@ -16,11 +16,12 @@ There may be occasions where a re-install of the OS is required. Assuming the * **[use xCAT]** ``xdsh`` can be used to invoke the reinstall of the OS: :: + # to clear out all the previous configuration, use the -k option (optional) + xdsh "/usr/cumulus/bin/onie-select -k + + # to invoke the reinstall of the OS xdsh "/usr/cumulus/bin/onie-select -i -f;reboot" - # to clear out all the previous configuration, use the -k option - xdsh "/usr/cumulus/bin/onie-select -k -f;reboot" - * **[manually]** Log into the Cumulus OS switch and run the following commands: :: sudo onie-select -i From 0cda7b5d02fde841fe3144d5683b6f072c84214f Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Fri, 24 Feb 2017 13:05:40 -0800 Subject: [PATCH 022/187] Fix double logging of postscript output in /var/log/xcat/xcat.log --- xCAT-server/share/xcat/install/scripts/post.xcat | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/xCAT-server/share/xcat/install/scripts/post.xcat b/xCAT-server/share/xcat/install/scripts/post.xcat index 2d6cffec7..2179b2f82 100755 --- a/xCAT-server/share/xcat/install/scripts/post.xcat +++ b/xCAT-server/share/xcat/install/scripts/post.xcat @@ -202,7 +202,6 @@ run_ps () { fi if [ -f \$1 ]; then - echo \"\`date\` Running \$scriptype: \$1\" msgutil_r \"\$MASTER_IP\" \"info\" "\"\`date\` Running \$scriptype: \$1\"" \"\$logfile\" if [ \"\$XCATDEBUGMODE\" = \"1\" ] || [ \"\$XCATDEBUGMODE\" = \"2\" ]; then local compt=\$(file \$1) @@ -211,21 +210,19 @@ run_ps () { bash -x ./\$@ 2>&1 ret_local=\$? else - ./\$@ 2>&1 | tee -a \$logfile | logger -t xcat -p debug + ./\$@ 2>&1 | logger -t xcat -p debug ret_local=\${PIPESTATUS[0]} fi else - ./\$@ 2>&1 | tee -a \$logfile + ./\$@ 2>&1 ret_local=\${PIPESTATUS[0]} fi if [ \"\$ret_local\" -ne \"0\" ]; then return_value=\$ret_local fi - echo \"\$scriptype: \$1 exited with code \$ret_local\" msgutil_r \"\$MASTER_IP\" \"info\" "\"\`date\` \$scriptype \$1 return with \$ret_local\"" \"\$logfile\" else - echo \"\`date\` \$scriptype \$1 does NOT exist.\" msgutil_r \"\$MASTER_IP\" \"info\" "\"\`date\` \$scriptype \$1 does NOT exist.\"" \"\$logfile\" return_value=-1 fi From 9b5b7a6ae3d8a3f7e31a607c0113d382fab356e3 Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Fri, 24 Feb 2017 15:11:55 -0800 Subject: [PATCH 023/187] PasswordUtils.pm: don't crypt already hashed passwords --- xCAT-server/lib/perl/xCAT/PasswordUtils.pm | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/PasswordUtils.pm b/xCAT-server/lib/perl/xCAT/PasswordUtils.pm index d9647deec..e17ac14a5 100644 --- a/xCAT-server/lib/perl/xCAT/PasswordUtils.pm +++ b/xCAT-server/lib/perl/xCAT/PasswordUtils.pm @@ -149,16 +149,21 @@ sub crypt_system_password { "ERROR: Unable to get password from database table $table, key=$key"); return undef; } - $cryptmethod = $data->{'cryptmethod'}; - if (!$cryptmethod) { - # Use sha256 crypt method by default - $result = crypt($password, $CRYPT_METHOD{'sha256'} . xCAT::Utils::genpassword(8)); - } elsif( defined($CRYPT_METHOD{$cryptmethod})) { - $result = crypt($password, - $CRYPT_METHOD{$cryptmethod} . xCAT::Utils::genpassword(8)); + if (($password =~ /^\$1\$/) || ($password =~ /^\$5\$/) || ($password =~ /^\$6\$/)) { + # $password is already hashed + $result = $password; } else { - xCAT::MsgUtils->message("S", "Unsupported crypt method $cryptmethod"); - return undef; + $cryptmethod = $data->{'cryptmethod'}; + if (!$cryptmethod) { + # Use sha256 crypt method by default + $result = crypt($password, $CRYPT_METHOD{'sha256'} . xCAT::Utils::genpassword(8)); + } elsif( defined($CRYPT_METHOD{$cryptmethod})) { + $result = crypt($password, + $CRYPT_METHOD{$cryptmethod} . xCAT::Utils::genpassword(8)); + } else { + xCAT::MsgUtils->message("S", "Unsupported crypt method $cryptmethod"); + return undef; + } } return $result; } From 0e5bb69678b419463b5841559307a71fbdf5c9d1 Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Fri, 24 Feb 2017 15:32:30 -0800 Subject: [PATCH 024/187] Clarifies the purpose of the cryptmethod field, to match what the code does --- docs/source/guides/admin-guides/references/man5/passwd.5.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man5/passwd.5.rst b/docs/source/guides/admin-guides/references/man5/passwd.5.rst index 3438aa4b6..4123a9258 100644 --- a/docs/source/guides/admin-guides/references/man5/passwd.5.rst +++ b/docs/source/guides/admin-guides/references/man5/passwd.5.rst @@ -50,13 +50,13 @@ passwd Attributes: \ **password**\ - The default password for this type of component + The default password for this type of component. On Linux, a crypted form could be provided. Hashes starting with $1$, $5$ and $6$ (md5, sha256 and sha512 respectively) are supported. \ **cryptmethod**\ - Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default. + Indicates the method to use to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default to encrypt plain-text passwords. From d3da969e52767be8e059e725424b10b7ed2d1d14 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 27 Feb 2017 06:26:34 -0500 Subject: [PATCH 025/187] modify all os's flat diskfull and diskless install --- .../installation/reg_linux_diskfull_installation_flat | 11 ++++++++--- .../installation/reg_linux_diskless_installation_flat | 10 +++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat index 89f9d73d8..e96f78bc3 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat @@ -3,6 +3,8 @@ os:Linux stop:yes cmd:if ping -c 1 $$SN > /dev/null;then rpower $$SN off > /dev/null;fi +cmd:MINIISO=NUll;if [[ "__GETNODEATTR($$CN,os)__" =~ "ubuntu" ]] && [[ "__GETNODEATTR($$CN,arch)__" =~ "ppc64le" ]];then mkdir /tmp/iso; mount -o loop $$MINIISO /tmp/iso ; mkdir -p /install/__GETNODEATTR($$CN,os)__/__GETNODEATTR($$CN,arch)__/install/netboot; cp /tmp/iso/install/initrd.gz /install/__GETNODEATTR($$CN,os)__/__GETNODEATTR($$CN,arch)__/install/netboot;umount /tmp/iso; rmdir /tmp/iso; fi +check:rc==0 cmd:chdef -t node -o $$CN servicenode= monserver=$$MN nfsserver=$$MN tftpserver=$$MN xcatmaster=$$MN check:rc==0 @@ -13,7 +15,7 @@ check:rc==0 cmd:cat /etc/conserver.cf | grep $$CN check:output=~$$CN cmd:sleep 20 -cmd:if [ "__GETNODEATTR($$CN,arch)__" = "ppc64" -a "__GETNODEATTR($$CN,mgt)__" != "ipmi" ]; then getmacs -D $$CN; fi +cmd:if [[ "__GETNODEATTR($$CN,arch)__" = "ppc64" ]] && [[ "__GETNODEATTR($$CN,mgt)__" != "ipmi" ]]; then getmacs -D $$CN; fi check:rc==0 cmd:chtab key=extntpservers site.value="" check:rc==0 @@ -30,7 +32,7 @@ cmd:a=0;while true; do [ $a -eq 100 ] && exit 1;output=$(makedhcp -q $$CN);[ $? check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:if [ "__GETNODEATTR($$CN,os)__" != "sles12.1" ];then chdef -t node -o $$CN postscripts=setupntp; fi +cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]];then chdef -t node -o $$CN postscripts=setupntp; fi cmd:lsdef -l $$CN check:rc==0 cmd:rinstall $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute @@ -53,9 +55,12 @@ cmd:xdsh $$CN mount check:rc==0 cmd:sleep 120 #comment for further discussion -#cmd:xdsh $$CN service ntpd status +#cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]];then xdsh $$CN service ntpd status;fi #check:rc==0 #check:output=~running +cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]];then chdef -t node -o $$CN postscripts=" "; fi +cmd:lsdef -l $$CN +check:rc==0 cmd:ping $$CN -c 3 check:rc==0 check:output=~64 bytes from $$CN diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat index 227085f4a..99c2e6773 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat @@ -12,7 +12,7 @@ check:rc==0 cmd:cat /etc/conserver.cf | grep $$CN check:output=~$$CN cmd:sleep 20 -cmd:if [[ "__GETNODEATTR($$CN,arch)__" =~ "ppc64" ]]; then getmacs -D $$CN; fi +cmd:if [[ "__GETNODEATTR($$CN,arch)__" = "ppc64" ]] && [[ "__GETNODEATTR($$CN,mgt)__" != "ipmi" ]]; then getmacs -D $$CN; fi check:rc==0 cmd:makedhcp -n check:rc==0 @@ -24,14 +24,14 @@ check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:rootimgdir=`lsdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute|grep rootimgdir|awk -F'=' '{print $2}'`; if [ -d $rootimgdir ]; then mv $rootimgdir $rootimgdir.regbak -f;fi +cmd:rootimgdir=`lsdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute|grep rootimgdir|awk -F'=' '{print $2}'`; if [ -d $rootimgdir ]; then `mv $rootimgdir $rootimgdir.regbak -f`;fi check:rc==0 -cmd:if cat /etc/*release |grep SUSE >/dev/null;then if [ ! -d /install/custom/netboot/sles ]; then mkdir -p /install/custom/netboot/sles; fi; elif cat /etc/*release |grep "Red Hat" >/dev/null;then if [ ! -d /install/custom/netboot/rh ]; then mkdir -p /install/custom/netboot/rh; fi;fi +cmd:if cat /etc/*release |grep SUSE >/dev/null;then if [ ! -d /install/custom/netboot/sles ]; then mkdir -p /install/custom/netboot/sles; fi; elif cat /etc/*release |grep "Red Hat" >/dev/null;then if [ ! -d /install/custom/netboot/rh ]; then mkdir -p /install/custom/netboot/rh; fi; elif cat /etc/*release |grep "Ubuntu" >/dev/null;then if [ ! -d /install/custom/netboot/ubuntu ]; then mkdir -p /install/custom/netboot/ubuntu; fi; fi check:rc==0 -cmd:if cat /etc/*release |grep SUSE >/dev/null;then if [ ! -e /install/custom/netboot/sles/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/sles/compute.synclist; fi; elif cat /etc/*release |grep "Red Hat" >/dev/null;then if [ ! -e /install/custom/netboot/rh/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/rh/compute.synclist; fi;fi +cmd:if cat /etc/*release |grep SUSE >/dev/null;then if [ ! -e /install/custom/netboot/sles/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/sles/compute.synclist; fi; elif cat /etc/*release |grep "Red Hat" >/dev/null;then if [ ! -e /install/custom/netboot/rh/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/rh/compute.synclist; fi; elif cat /etc/*release |grep "Ubuntu" >/dev/null;then if [ ! -e /install/custom/netboot/ubuntu/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/ubuntu/compute.synclist;fi; fi check:rc==0 -cmd:if cat /etc/*release |grep SUSE >/dev/null;then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/sles/compute.synclist; elif cat /etc/*release |grep "Red Hat" >/dev/null;then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/rh/compute.synclist;fi +cmd:if cat /etc/*release |grep SUSE >/dev/null;then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/sles/compute.synclist; elif cat /etc/*release |grep "Red Hat" >/dev/null;then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/rh/compute.synclist;elif cat /etc/*release |grep "Ubuntu" >/dev/null; then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/ubuntu/compute.synclist;fi check:rc==0 cmd:if [ ! -d /tmp/mountoutput ]; then mkdir -p /tmp/mountoutput; fi From 3e32b3be3c44f2503650982f3cf39de2373cd8d9 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Mon, 27 Feb 2017 11:31:30 -0500 Subject: [PATCH 026/187] Modify hardeths portscripts for Cumulus Linux Switch OS --- xCAT/postscripts/hardeths | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/xCAT/postscripts/hardeths b/xCAT/postscripts/hardeths index a7c8d01b2..cde4cc211 100755 --- a/xCAT/postscripts/hardeths +++ b/xCAT/postscripts/hardeths @@ -106,7 +106,21 @@ for nic in `ip link |grep "BROADCAST" |awk '{print $2}' | sed s/://`; do gateway_line="" fi # add info to interfaces file on ubuntu, TBD does unbuntu change to systemd, this will not exist - cat >>/etc/network/interfaces <>/etc/network/interfaces <>/etc/network/interfaces < Date: Mon, 27 Feb 2017 16:40:46 -0500 Subject: [PATCH 027/187] Small doc formatting changes --- docs/source/advanced/hierarchy/provision/diskful_sn.rst | 2 +- docs/source/guides/admin-guides/references/man1/pping.1.rst | 4 ++-- docs/source/guides/admin-guides/references/man1/xdsh.1.rst | 3 +-- xCAT-client/pods/man1/pping.1.pod | 4 ++-- xCAT-client/pods/man1/xdsh.1.pod | 3 +-- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/source/advanced/hierarchy/provision/diskful_sn.rst b/docs/source/advanced/hierarchy/provision/diskful_sn.rst index 1574c2104..972a81712 100644 --- a/docs/source/advanced/hierarchy/provision/diskful_sn.rst +++ b/docs/source/advanced/hierarchy/provision/diskful_sn.rst @@ -9,7 +9,7 @@ Any cluster using statelite compute nodes must use a stateful (diskful) Service **Note:** All xCAT Service Nodes must be at the exact same xCAT version as the xCAT Management Node. Configure ``otherpkgdir`` and ``otherpkglist`` for service node osimage ----------------------------------------------------------------------- +----------------------------------------------------------------------- * Create a subdirectory ``xcat`` under a path specified by ``otherpkgdir`` attribute of the service node os image, selected during the :doc:`../define_service_nodes` step. diff --git a/docs/source/guides/admin-guides/references/man1/pping.1.rst b/docs/source/guides/admin-guides/references/man1/pping.1.rst index 3d0763566..92e680380 100644 --- a/docs/source/guides/admin-guides/references/man1/pping.1.rst +++ b/docs/source/guides/admin-guides/references/man1/pping.1.rst @@ -25,7 +25,7 @@ DESCRIPTION \ **pping**\ is a utility used to ping a list of nodes in parallel. \ **pping**\ will return an unsorted list of nodes with a ping or noping status. -\ **pping**\ front-ends nmap or fping if available. +\ **pping**\ front-ends \ **nmap**\ or \ **fping**\ if available. This command does not support the xcatd client/server communication. It must be run on the management node. @@ -48,7 +48,7 @@ OPTIONS \ **-f | -**\ **-use_fping**\ - Use fping instead of nmap + Use \ **fping**\ instead of \ **nmap**\ diff --git a/docs/source/guides/admin-guides/references/man1/xdsh.1.rst b/docs/source/guides/admin-guides/references/man1/xdsh.1.rst index fb84e802b..51f71f74d 100644 --- a/docs/source/guides/admin-guides/references/man1/xdsh.1.rst +++ b/docs/source/guides/admin-guides/references/man1/xdsh.1.rst @@ -527,8 +527,7 @@ running commands, are terminated (SIGTERM). \ **DSH_TIMEOUT**\ Specifies the time, in seconds, to wait for output from - each remote target. This variable is overridden by the \ **-t**\ - flag. + each remote target. This variable is overridden by the \ **-t**\ flag. diff --git a/xCAT-client/pods/man1/pping.1.pod b/xCAT-client/pods/man1/pping.1.pod index 8e563ed41..93eac03f4 100644 --- a/xCAT-client/pods/man1/pping.1.pod +++ b/xCAT-client/pods/man1/pping.1.pod @@ -16,7 +16,7 @@ B {B<-v>|B<--version>} B is a utility used to ping a list of nodes in parallel. B will return an unsorted list of nodes with a ping or noping status. -B front-ends nmap or fping if available. +B front-ends B or B if available. This command does not support the xcatd client/server communication. It must be run on the management node. @@ -34,7 +34,7 @@ If more than one interface is specified, each interface will be combined with th =item B<-f>|B<--use_fping> -Use fping instead of nmap +Use B instead of B =item B<-h>|B<--help> diff --git a/xCAT-client/pods/man1/xdsh.1.pod b/xCAT-client/pods/man1/xdsh.1.pod index 72d3ede24..a9d06a6c4 100644 --- a/xCAT-client/pods/man1/xdsh.1.pod +++ b/xCAT-client/pods/man1/xdsh.1.pod @@ -442,8 +442,7 @@ variable is overridden by the B<-S> flag. =item B Specifies the time, in seconds, to wait for output from -each remote target. This variable is overridden by the B<-t> -flag. +each remote target. This variable is overridden by the B<-t> flag. =back From c61d356d1cba530f247151858c607bd1cd57dc3f Mon Sep 17 00:00:00 2001 From: Andy Wray Date: Tue, 28 Feb 2017 10:28:42 -0500 Subject: [PATCH 028/187] Changed colors in wcons to improve readability --- xCAT-client/bin/wcons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-client/bin/wcons b/xCAT-client/bin/wcons index 321e87634..13dd44849 100755 --- a/xCAT-client/bin/wcons +++ b/xCAT-client/bin/wcons @@ -17,7 +17,7 @@ unless ($ENV{DISPLAY}) { my $mydir = dirname($0); my $sb; my $tilefact; -my $xrm = "-xrm xterm.mainMenu.*.font:fixed -xrm xterm.vtMenu.*.font:fixed -xrm xterm.fontMenu.*.font:fixed -xrm xterm -xrm xterm.vt100.font6:grvga.737"; +my $xrm = "-xrm xterm.mainMenu.*.font:fixed -xrm xterm.vtMenu.*.font:fixed -xrm xterm.fontMenu.*.font:fixed -xrm xterm -xrm xterm.vt100.font6:grvga.737 -xrm xterm.vt100.color0:#000000 -xrm xterm.vt100.color1:#AA0000 -xrm xterm.vt100.color2:#00AA00 -xrm xterm.vt100.color3:#AA5500 -xrm xterm.vt100.color4:#0000AA -xrm xterm.vt100.color5:#AA00AA -xrm xterm.vt100.color6:#00AAAA -xrm xterm.vt100.color7:#AAAAAA -xrm xterm.vt100.color8:#555555 -xrm xterm.vt100.color9:#FF5555 -xrm xterm.vt100.color10:#55FF55 -xrm xterm.vt100.color11:#FFFF55 -xrm xterm.vt100.color12:#5555FF -xrm xterm.vt100.color13:#FF55FF -xrm xterm.vt100.color14:#55FFFF -xrm xterm.vt100.color15:#FFFFFF"; my $font = "5x7"; my $sizegeometry; GetOptions( From 55e6978e65f0f04564aec4ce14acaad50b59be4c Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Tue, 28 Feb 2017 14:05:13 -0500 Subject: [PATCH 029/187] Remove hard code of community and protocol value for snmp configuration --- .../lib/xcat/plugins/switchdiscover.pm | 20 ++-- xCAT-server/share/xcat/scripts/configBNT | 100 ++++++++++++++---- 2 files changed, 92 insertions(+), 28 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/switchdiscover.pm b/xCAT-server/lib/xcat/plugins/switchdiscover.pm index 4966a24ff..a188d0775 100644 --- a/xCAT-server/lib/xcat/plugins/switchdiscover.pm +++ b/xCAT-server/lib/xcat/plugins/switchdiscover.pm @@ -23,6 +23,7 @@ use Socket; use Expect; #global variables for this module +my $community; my %globalopt; my @filternodes; my @iprange; @@ -949,6 +950,13 @@ sub snmp_scan { send_msg($request, 0, "$result\n" ); } my @lines = split /\n/, $result; + + #set community string for switch + $community = "public"; + my @snmpcs = xCAT::TableUtils->get_site_attribute("snmpc"); + my $tmp = $snmpcs[0]; + if (defined($tmp)) { $community = $tmp } + foreach my $line (@lines) { my @array = split / /, $line; @@ -1008,8 +1016,8 @@ sub get_snmpvendorinfo { #Ubuntu only takes OID - #my $ccmd = "snmpwalk -Os -v1 -c public $ip sysDescr.0"; - my $ccmd = "snmpwalk -Os -v1 -c public $ip 1.3.6.1.2.1.1.1"; + #get sysDescr.0"; + my $ccmd = "snmpwalk -Os -v1 -c $community $ip 1.3.6.1.2.1.1.1"; if (exists($globalopt{verbose})) { send_msg($request, 0, "Process command: $ccmd\n"); } @@ -1047,8 +1055,8 @@ sub get_snmpmac { my $mac; #Ubuntu only takes OID - #my $ccmd = "snmpwalk -Os -v1 -c public $ip ipNetToMediaPhysAddress | grep $ip"; - my $ccmd = "snmpwalk -Os -v1 -c public $ip 1.3.6.1.2.1.4.22.1.2 | grep $ip"; + #get ipNetToMediaPhysAddress; + my $ccmd = "snmpwalk -Os -v1 -c $community $ip 1.3.6.1.2.1.4.22.1.2 | grep $ip"; if (exists($globalopt{verbose})) { send_msg($request, 0, "Process command: $ccmd\n"); @@ -1091,8 +1099,8 @@ sub get_snmphostname { my $hostname; #Ubuntu only takes OID - #my $ccmd = "snmpwalk -Os -v1 -c public $ip sysName"; - my $ccmd = "snmpwalk -Os -v1 -c public $ip 1.3.6.1.2.1.1.5"; + #get sysName info; + my $ccmd = "snmpwalk -Os -v1 -c $community $ip 1.3.6.1.2.1.1.5"; if (exists($globalopt{verbose})) { send_msg($request, 0, "Process command: $ccmd\n"); } diff --git a/xCAT-server/share/xcat/scripts/configBNT b/xCAT-server/share/xcat/scripts/configBNT index 23e81e656..3b31b975b 100755 --- a/xCAT-server/share/xcat/scripts/configBNT +++ b/xCAT-server/share/xcat/scripts/configBNT @@ -67,17 +67,37 @@ if ($::HELP) exit(0); } +my $switchestab; +my $switchhash; +my $passwdtab; +my @passwd_ent; + if ($::SWITCH) { my @filternodes = xCAT::NodeRange::noderange( $::SWITCH ); if (nodesmissed) { my $nodenotdefined = join(',', nodesmissed); xCAT::MsgUtils->message("I","The following nodes are not defined in xCAT: $nodenotdefined"); } - # check switch type - my $switchestab = xCAT::Table->new('switches'); - my $switches_hash = $switchestab->getNodesAttribs(\@filternodes,['switchtype']); + # check switch attributes + $switchestab = xCAT::Table->new('switches'); + $switchhash = $switchestab->getNodesAttribs(\@filternodes,['switchtype','sshusername','sshpassword','protocol']); + + # get switch username and password from passwd + $passwdtab = xCAT::Table->new('passwd'); + @passwd_ent = $passwdtab->getAttribs({ key => "switch" }, [ 'username', 'password' ]); + foreach my $fsw (@filternodes) { - if (($switches_hash->{$fsw}->[0]->{switchtype}) =~ /BNT/) { + if (($switchhash->{$fsw}->[0]->{switchtype}) =~ /BNT/) { + # use switches table first + if ((!defined($switchhash->{$fsw}->[0]->{sshusername})) && + (!defined($switchhash->{$fsw}->[0]->{sshpassword})) ) { + if (defined($passwd_ent[0]->{username})) { + $switchhash->{$fsw}->[0]->{sshusername} = $passwd_ent[0]->{username}; + } + if (defined($passwd_ent[0]->{password})) { + $switchhash->{$fsw}->[0]->{sshpassword} = $passwd_ent[0]->{password}; + } + } push @nodes, $fsw; } else { xCAT::MsgUtils->message("E","The $fsw is not BNT switch, will not config"); @@ -97,6 +117,12 @@ if ($::SWITCH) { my $mactab = xCAT::Table->new("mac"); my $machash = $mactab->getNodesAttribs(\@nodes,['mac']); +#set community string for switch +my $community = "public"; +my @snmpcs = xCAT::TableUtils->get_site_attribute("snmpc"); +my $tmp = $snmpcs[0]; +if (defined($tmp)) { $community = $tmp } + my $switches = join(",",@nodes); my $cmd; my $vlan; @@ -177,7 +203,7 @@ sub config_ip { $ip_str =~ s/\./\-/g; $dswitch = "switch-$ip_str"; } - $cmd = "chdef -t node -o $dswitch groups=switch ip=$dip switchtype=BNT username=root password=admin protocol=telnet nodetype=switch"; + $cmd = "chdef -t node -o $dswitch groups=switch ip=$dip switchtype=BNT username=root password=admin nodetype=switch"; $rc= xCAT::Utils->runcmd($cmd, 0); $cmd = "makehosts $dswitch"; $rc= xCAT::Utils->runcmd($cmd, 0); @@ -275,7 +301,6 @@ sub config_hostname { } } - #setup secure SNMP v3 sub config_snmp { my $snmp_user; @@ -302,10 +327,32 @@ sub config_snmp { foreach my $switch (@nodes) { my $mysw; + my $username; + my $passwd; + my $protocol; + + my $login_cmd; + + $username = $switchhash->{$switch}->[0]->{sshusername}; + $passwd = $switchhash->{$switch}->[0]->{sshpassword}; + $protocol = $switchhash->{$switch}->[0]->{protocol}; + if ($protocol =~ /telnet/) { + $login_cmd = "telnet $switch\r"; + } else { + $login_cmd = "ssh $username\@$switch\r"; + } + + #get hostname on the switch in case hostname is different + my $ccmd = "snmpwalk -Os -v1 -c $community $switch 1.3.6.1.2.1.1.5"; + my $result = xCAT::Utils->runcmd($ccmd, 0); + my ($desc,$switchhost) = split /: /, $result; + if (!$switchhost) { + $switchhost=$switch; + } my $mac= $machash->{$switch}->[0]->{mac}; if ($mac =~ /6c\:ae\:8b/i){ - my $rc = config_G8264($switch,$snmp_user,$snmp_passwd,$snmp_group); + my $rc = config_G8264($switch,$login_cmd, $passwd, $snmp_user,$snmp_passwd,$snmp_group); if ($rc == 0){ push (@config_switches, $switch); } @@ -316,17 +363,17 @@ sub config_snmp { my $config_cmd="configure terminal\r"; my $exit_cmd="exit\r"; - my $pwd_prompt = "password: "; - my $sw_prompt = "$switch>"; - my $enable_prompt="$switch#"; + my $user_prompt = "username: "; + my $pwd_prompt = "assword: "; + my $sw_prompt = "$switchhost>"; + my $enable_prompt="$switchhost#"; my $config_prompt="^.*\\\(config\\\)\#"; $mysw = new Expect; my $timeout = 20; - my $login_cmd = "telnet $switch\r"; - my $passwd = "admin\r"; + #my $login_cmd = "telnet $switch\r"; - print "Setup SNMP server for $switch\n"; + print "Setup SNMP server for $switch, $username, $passwd\n"; #create a SNMP user my $cfg_user1="snmp-server user 5 name $snmp_user\r"; my $cfg_user2="snmp-server user 5 authentication-protocol sha authentication-password\r"; @@ -351,19 +398,20 @@ sub config_snmp { my @result = $mysw->expect( $timeout, [ - $pwd_prompt, + $user_prompt, sub { $mysw->clear_accum(); - $mysw->send("$passwd\r"); + $mysw->send("$username\r"); $mysw->clear_accum(); $mysw->exp_continue(); } ], [ - "-re", $sw_prompt, + $pwd_prompt, sub { $mysw->clear_accum(); - $mysw->send($enable_cmd); + $mysw->send("$passwd\r"); + $mysw->clear_accum(); $mysw->exp_continue(); } ], @@ -381,7 +429,7 @@ sub config_snmp { $mysw->clear_accum(); $mysw->send($cfg_user1); $mysw->send($cfg_user2); - $mysw->send($passwd); + $mysw->send("$passwd\r"); $mysw->send($snmp_passwd); $mysw->send($snmp_passwd); sleep 1; @@ -401,6 +449,14 @@ sub config_snmp { $mysw->send($exit_cmd); } ], + [ + "-re", $sw_prompt, + sub { + $mysw->clear_accum(); + $mysw->send($enable_cmd); + $mysw->exp_continue(); + } + ], ); ########################################## # Expect error - report and quit @@ -425,6 +481,8 @@ sub config_snmp { sub config_G8264 { my $switch = shift; + my $login_cmd = shift; + my $passwd = shift; my $snmp_user = shift; my $snmp_passwd = shift; my $snmp_group = shift; @@ -437,9 +495,7 @@ sub config_G8264 { #use expect to set password my $mysw = new Expect; my $timeout = 20; - my $login_cmd = "telnet $switch\r"; - my $passwd = "admin\r"; - my $pwd_prompt = "password: "; + my $pwd_prompt = "assword: "; my $main_prompt="Main#"; my $authpw_cmd = "/cfg/sys/ssnmp/snmpv3/usm 5/authpw\r"; @@ -467,7 +523,7 @@ sub config_G8264 { sub { $mysw->clear_accum(); $mysw->send($authpw_cmd); - $mysw->send($passwd); + $mysw->send("$passwd\r"); $mysw->send($snmp_passwd); $mysw->send($snmp_passwd); sleep 1; From 3d657a6b75426e6051c0292d94fe97fe41cb21eb Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Wed, 1 Mar 2017 15:34:07 +0800 Subject: [PATCH 030/187] Fix github issue #2560, fix the exit code of postscript `syncfiles` --- xCAT/postscripts/syncfiles | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT/postscripts/syncfiles b/xCAT/postscripts/syncfiles index 0875a5388..ebf34a7cc 100644 --- a/xCAT/postscripts/syncfiles +++ b/xCAT/postscripts/syncfiles @@ -38,6 +38,7 @@ xcatpostdir="/xcatpost" logger -t xcat -p local4.info "$0: the OS name = $osname" quit="no" count=5 +returncode=0 while [ $quit = "no" ]; do if [ $osname = "Linux" ] then @@ -66,5 +67,4 @@ else logger -t xcat -p local4.err "$0: Perform Syncing File action encountered error" fi -exit 0 - +[ $returncode -eq 0 ] From 4cd248313eddbc5a2d865386afd6b00b7dcef618 Mon Sep 17 00:00:00 2001 From: bybai Date: Wed, 1 Mar 2017 04:06:13 -0500 Subject: [PATCH 031/187] confignics support MTU --- xCAT/postscripts/configeth | 51 ++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index 94b3fea5e..c9feade5a 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html # Internal script used by confignics only. # It configs the Ethernet adpaters on the node @@ -15,11 +15,12 @@ function configipv4(){ str_v4mask=$4 num_v4num=$5 str_extra_params=$6 + str_nic_mtu=$7 #parse the extra parameters if [ "$str_extra_params" != "$str_default_token" ]; then parse_nic_extra_params "$str_extra_params" - fi + fi if [ "$str_os_type" = "sles" ];then str_conf_file="/etc/sysconfig/network/ifcfg-${str_if_name}" @@ -32,7 +33,9 @@ function configipv4(){ echo "STARTMODE=onboot" >> $str_conf_file echo "USERCONTROL=no" >> $str_conf_file echo "_nm_name=static-0" >> $str_conf_file - + if [ "$str_nic_mtu" != "$str_default_token" ]; then + echo "MTU=${str_nic_mtu}" >> $str_conf_file + fi #add extra params i=0 while [ $i -lt ${#array_extra_param_names[@]} ] @@ -48,7 +51,9 @@ function configipv4(){ echo "NETMASK_${num_v4num}=${str_v4mask}" >> $str_conf_file echo "NETWORK_${num_v4num}=${str_v4net}" >> $str_conf_file echo "LABEL_${num_v4num}=${num_v4num}" >> $str_conf_file - + if [ "$str_nic_mtu" != "$str_default_token" ]; then + echo "MTU_${num_v4num}=${str_nic_mtu}" >> $str_conf_file + fi #add extra params i=0 while [ $i -lt ${#array_extra_param_names[@]} ] @@ -77,7 +82,9 @@ 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_nic_mtu" != "$str_default_token" ]; then + echo " mtu ${str_nic_mtu}" >> $str_conf_file + fi #add extra params i=0 while [ $i -lt ${#array_extra_param_names[@]} ] @@ -109,6 +116,10 @@ function configipv4(){ echo "IPADDR=${str_v4ip}" >> $str_conf_file echo "NETMASK=${str_v4mask}" >> $str_conf_file echo "ONBOOT=yes" >> $str_conf_file + if [ "$str_nic_mtu" != "$str_default_token" ]; then + echo "MTU=${str_nic_mtu}" >> $str_conf_file + fi + if [[ ${str_if_name} == [a-zA-Z0-9]*.[0-9]* ]]; then echo "VLAN=yes" >> $str_conf_file fi @@ -408,6 +419,19 @@ elif [ "$1" = "-s" ];then str_inst_ip='' str_inst_mask='' str_inst_gateway='' + str_inst_mtu='' + str_inst_network=`echo $NICNETWORKS |awk -F${str_inst_nic}'!' '{print $2}' | awk -F'|' '{print $1}'` + num_index=1 + while [ $num_index -le $NETWORKS_LINES ];do + eval str_tmp=\$NETWORKS_LINE$num_index + str_tmp_name=`echo $str_tmp | awk -F'netname=' '{print $2}' | awk -F'|' '{print $1}'` + if [ "$str_tmp_name" = "$str_inst_network" ];then + str_inst_mtu=`echo $str_tmp | awk -F'mtu=' '{print $2}' | awk -F'|' '{print $1}'` + break + fi + num_index=$((num_index+1)) + done + if [ "$str_os_type" = "aix" ];then logger -t xcat -p local4.err "configeth: aix does not support -s flag" @@ -512,6 +536,7 @@ elif [ "$1" = "-s" ];then echo " address ${str_inst_ip}" >> $str_conf_file echo " netmask ${str_inst_mask}" >> $str_conf_file echo " hwaddress ether ${str_inst_mac}" >> $str_conf_file + echo " mtu ${str_inst_mtu}" >> $str_conf_file if [ -n "$str_inst_gateway" ];then echo " gateway $str_inst_gateway" >> $str_conf_file fi @@ -535,6 +560,7 @@ elif [ "$1" = "-s" ];then echo "IPADDR=${str_inst_ip}" >> $str_conf_file echo "NETMASK=${str_inst_mask}" >> $str_conf_file echo "HWADDR=${str_inst_mac}" >> $str_conf_file + echo "MTU=${str_inst_mtu}" >> $str_conf_file echo "STARTMODE=onboot" >> $str_conf_file if [ -n "$str_inst_gateway" ];then grep -i "default" /etc/sysconfig/network/routes @@ -567,6 +593,7 @@ elif [ "$1" = "-s" ];then echo "BOOTPROTO=static" >> $str_conf_file echo "ONBOOT=yes" >> $str_conf_file echo "HWADDR=${str_inst_mac}" >> $str_conf_file + echo "MTU=${str_inst_mtu}" >> $str_conf_file if [ -n "$str_inst_gateway" ];then grep -i "GATEWAY" /etc/sysconfig/network if [ $? -eq 0 ];then @@ -639,6 +666,7 @@ declare -a array_nic_network_config declare -a array_nic_subnet declare -a array_nic_netmask declare -a array_nic_gateway +declare -a array_nic_mtu #get extra configration parameters for each nic get_nic_extra_params $str_nic_name "$NICEXTRAPARAMS" @@ -696,7 +724,8 @@ while [ $num_index -lt ${#array_nic_ips[*]} ];do str_subnet=`echo $str_line | awk -F'net=' '{print $2}' | awk -F'|' '{print $1}'` str_netmask=`echo $str_line | awk -F'mask=' '{print $2}' | awk -F'|' '{print $1}' | sed 's:^/::'` str_gateway=`echo $str_line | awk -F'gateway=' '{print $2}' | awk -F'|' '{print $1}'` - + str_mtu=`echo $str_line | awk -F'mtu=' '{print $2}' | awk -F'|' '{print $1}'` + if [ ! $str_subnet -o ! $str_netmask ];then logger -t xcat -p local4.err "configeth: subnet or netmask is not defined in network object $str_netname." echo "configeth on $NODE: subnet or netmask is not defined in network object $str_netname." @@ -707,6 +736,7 @@ while [ $num_index -lt ${#array_nic_ips[*]} ];do array_nic_subnet[$num_index]=$str_subnet array_nic_netmask[$num_index]=$str_netmask array_nic_gateway[$num_index]=$str_gateway + array_nic_mtu[$num_index]=$str_mtu echo "$str_gateway" | grep ':' if [ $? -eq 0 ];then str_ipv6_gateway=$str_gateway @@ -945,6 +975,7 @@ else str_subnet=${array_nic_subnet[$num_index]} str_netmask=${array_nic_netmask[$num_index]} str_gateway=${array_nic_gateway[$num_index]} + str_mtu=${array_nic_mtu[$num_index]} if [ $num_index -lt ${#array_nic_params[@]} ]; then str_extra_params=${array_nic_params[$num_index]} else @@ -955,7 +986,11 @@ else if [[ -z "$str_gateway" ]]; then str_gateway=$str_default_token fi - + + if [[ -z "$str_mtu" ]]; then + str_mtu=$str_default_token + fi + if [ ! $str_subnet -o ! $str_netmask ];then num_index=$((num_index+1)) continue @@ -963,7 +998,7 @@ else if [ `echo $str_ip | grep -E '^([0-9]{1,3}\.){3}[0-9]{1,3}$'` ];then - configipv4 $str_nic_name $str_ip $str_subnet $str_netmask $num_ipv4_index "$str_extra_params" + configipv4 $str_nic_name $str_ip $str_subnet $str_netmask $num_ipv4_index "$str_extra_params" $str_mtu num_ipv4_index=$((num_ipv4_index+1)) elif [ `echo $str_ip | grep -E ":"` ];then configipv6 $str_nic_name $str_ip $str_subnet $str_netmask $num_ipv6_index $num_ipv4_index $str_gateway "$str_extra_params" From 8cdc0e50d3c1877212ce62db9a780d1f823e89b1 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 1 Mar 2017 09:56:54 -0500 Subject: [PATCH 032/187] Fix import of mp data to confluent The plugin was incorrectly attempting to pull in fields from the nodepos table rather than mp. --- xCAT-server/lib/xcat/plugins/confluent.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/confluent.pm b/xCAT-server/lib/xcat/plugins/confluent.pm index 09fcaeb48..595d00bf6 100644 --- a/xCAT-server/lib/xcat/plugins/confluent.pm +++ b/xCAT-server/lib/xcat/plugins/confluent.pm @@ -226,6 +226,7 @@ sub makeconfluentcfg { # Get db info for the nodes related to console my $hmtab = xCAT::Table->new('nodehm'); my $nodepostab = xCAT::Table->new('nodepos'); + my $mptab = xCAT::Table->new('mp'); my @cfgents1; # = $hmtab->getAllNodeAttribs(['cons','serialport','mgt','conserver','termserver','termport']); my @cfgents2; my @cfgents3; @@ -234,7 +235,7 @@ sub makeconfluentcfg { $explicitnodes = 1; @cfgents1 = $hmtab->getNodesAttribs($nodes, [ 'node', 'cons', 'mgt', 'conserver', 'termserver', 'termport', 'consoleondemand' ]); @cfgents2 = $nodepostab->getNodesAttribs($nodes, [ 'node', 'rack', 'u', 'chassis', 'slot', 'room' ]); - @cfgents3 = $nodepostab->getNodesAttribs($nodes, [ 'node', 'mpa', 'id' ]); + @cfgents3 = $mptab->getNodesAttribs($nodes, [ 'node', 'mpa', 'id' ]); # Adjust the data structure to make the result consistent with the getAllNodeAttribs() call we make if a noderange was not specified my @tmpcfgents1; From c26a67e61e519d209222af9e81a681dab301fe4a Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Wed, 1 Mar 2017 15:58:10 -0500 Subject: [PATCH 033/187] Update after review --- .../common/deployment/cfg_network.rst | 4 ++-- .../common/deployment/cfg_network_bond.rst | 6 ++++-- .../common/deployment/cfg_network_vlan.rst | 17 +++++++++-------- .../common/deployment/cfg_second_adapter.rst | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst index 0c3d779c2..c36c0e3c2 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst @@ -1,5 +1,5 @@ -Advanced Networking Configuration -================================= +Advanced Networking Configuration - confignetwork +================================================= .. toctree:: :maxdepth: 2 diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst index d7360b127..5bf46b9db 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst @@ -51,6 +51,8 @@ Login to compute node cn1 and check bonding options in ``/etc/sysconfig/network- BONDING_OPTS="mode=802.3ad xmit_hash_policy=layer2+3" -The ``mode=802.3ad`` requires additional configuration on the switch. ``mode=2`` can be used for bonding without additional switch configuration. If changes are made to ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file, restart network service :: - systemctl restart network.service +* ``mode=802.3ad`` requires additional configuration on the switch. +* ``mode=2`` can be used for bonding without additional switch configuration. + +If changes are made to ``/etc/sysconfig/network-scripts/ifcfg-bond0`` file, restart network service. diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst index a4d637634..a245ff172 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst @@ -1,17 +1,17 @@ Configure BOND, VLAN and BRIDGES -------------------------------- -The ``confignetwork`` postscript can be used to configure the network interfaces on the compute nodes to support VLAN, BONDs, and BRIDGES. In order to use the ``confignetwork`` postscript, the following attributes must be configured for the node in the ``nics`` table: +The ``confignetwork`` postscript can be used to configure the network interfaces on the compute nodes to support VLAN, BONDs, and BRIDGES. In order for the ``confignetwork`` postscript to run successfully, the following attributes must be configured for the node in the ``nics`` table: * ``nicips`` * ``nictypes`` * ``nicnetworks`` - * ``nicdevices`` - resolves the relationship among the physical network intereface devices + * ``nicdevices`` - resolves the relationship among the physical network interface devices The following example set the xCAT properties for compute node ``cn1`` to achieve the following network configuration using the ``confignetwork`` postscript: - * Compute node ``cn1`` has two physical NICs: eth2 and eth3 - * Bond eth2 and eth3 as ``bond0`` + * Compute node ``cn1`` has two physical NICs: ``eth2`` and ``eth3`` + * Bond ``eth2`` and ``eth3`` as ``bond0`` * From ``bond0``, create 2 VLANs: ``bond0.1`` and ``bond0.2`` * Make bridge ``br1`` using ``bond0.1`` with IP (10.0.0.1) * Make bridge ``br2`` using ``bond0.2`` with IP (20.0.0.1) @@ -93,8 +93,10 @@ Chose one of three methods described below: #node,nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases,nicextraparams,nicdevices,comments,disable "cn1","br1!10.0.0.1,br2!20.0.0.1",,,"br1!bridge,eth2!ethernet,eth3!ethernet,bond0.2!vlan,bond0!bond,br2!bridge,bond0.1!vlan",,"br1!net10,br2!net20",,,"br1!bond0.1,bond0!eth2|eth3,bond0.2!bond0,bond0.1!bond0,br2!bond0.2",, -Add network object into the networks table -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Define the additional networks to xCAT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If this is a new network being created on the compute nodes, an entry needs to be created into the xCAT database. The ``nicnetworks`` attribute only defines the nic that uses the IP address. Other information about the network should be defined in the ``networks`` table. @@ -107,11 +109,10 @@ Use the ``chdef`` command to add/modify the networks in the ``networks`` table : Add ``confignetwork`` into the node's postscripts list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Using below command to add ``confignetwork`` into the node's postscripts list :: +Use the following command to add ``confignetwork`` into postscript list to execute on reboot: :: chdef cn1 -p postscripts=confignetwork -During OS deployment on compute node, ``confignetwork`` postscript will be executed. If the compute node is already running, use ``updatenode`` command to run ``confignetwork`` postscript without rebooting the node:: updatenode cn1 -P confignetwork diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst index 76475cf02..492361fc5 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_second_adapter.rst @@ -1,5 +1,5 @@ -Configure Additional Network Interfaces -======================================= +Configure Additional Network Interfaces - confignics +==================================================== The **nics** table and the **confignics** postscript can be used to automatically configure additional network interfaces (mutltiple ethernets adapters, InfiniBand, etc) on the nodes as they are being deployed. From 39c4f68285e52084d005f42c9ca3c9170e1aed66 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Wed, 1 Mar 2017 16:45:30 -0500 Subject: [PATCH 034/187] update switch definition if -w or --setup option is specified --- xCAT-server/lib/xcat/plugins/switchdiscover.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/switchdiscover.pm b/xCAT-server/lib/xcat/plugins/switchdiscover.pm index a188d0775..ebc6cb61b 100644 --- a/xCAT-server/lib/xcat/plugins/switchdiscover.pm +++ b/xCAT-server/lib/xcat/plugins/switchdiscover.pm @@ -1423,7 +1423,10 @@ sub matchPredefineSwitch { send_msg($request, 0, "Switch discovered and matched: $dswitch to $node" ); - xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$node,"otherinterfaces=$ip",'status=Matched',"mac=$mac","switchtype=$stype","usercomment=$vendor"] }, $sub_req, 0, 1); + # only write to xcatdb if -w or --setup option specified + if ( (exists($globalopt{w})) || (exists($globalopt{setup})) ) { + xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$node,"otherinterfaces=$ip",'status=Matched',"mac=$mac","switchtype=$stype","usercomment=$vendor"] }, $sub_req, 0, 1); + } push (@{$configswitch->{$stype}}, $node); } From 74babfcedec4961dd5dc7704cc9ce523d34eb5d8 Mon Sep 17 00:00:00 2001 From: bybai Date: Wed, 1 Mar 2017 22:13:51 -0500 Subject: [PATCH 035/187] fix issue 2572 makedns fails with a noderange error --- xCAT-server/lib/xcat/plugins/ddns.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/ddns.pm b/xCAT-server/lib/xcat/plugins/ddns.pm index 9291488b1..de6085e27 100755 --- a/xCAT-server/lib/xcat/plugins/ddns.pm +++ b/xCAT-server/lib/xcat/plugins/ddns.pm @@ -622,7 +622,7 @@ sub process_request { } else { # this host string might be a xcat group, try to test each node in the group - foreach my $host (noderange($hosts)) { + foreach my $host (xCAT::NodeRange->noderange($hosts)) { unless (xCAT::NetworkUtils->thishostisnot($host)) { $listenonifs = $dnsif; last; From f153cbd23fec82da97bbeba2d9ca185a349d67f8 Mon Sep 17 00:00:00 2001 From: bybai Date: Wed, 1 Mar 2017 23:31:34 -0500 Subject: [PATCH 036/187] remove -x --- xCAT/postscripts/configeth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index c9feade5a..c891f8137 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash # IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html # Internal script used by confignics only. # It configs the Ethernet adpaters on the node From dbf5c23c8fee7c6a70082a49ee119408b0c9c533 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Thu, 2 Mar 2017 16:27:12 +0800 Subject: [PATCH 037/187] [go-xcat] Fix github issue #2543, better error handling for wget --- xCAT-server/share/xcat/tools/go-xcat | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/xCAT-server/share/xcat/tools/go-xcat b/xCAT-server/share/xcat/tools/go-xcat index 5acda794c..c6a6df662 100755 --- a/xCAT-server/share/xcat/tools/go-xcat +++ b/xCAT-server/share/xcat/tools/go-xcat @@ -2,7 +2,7 @@ # # go-xcat - Install xCAT automatically. # -# Version 1.0.13 +# Version 1.0.14 # # Copyright (C) 2016 International Business Machines # Eclipse Public License, Version 1.0 (EPL-1.0) @@ -636,7 +636,29 @@ function download_file() type wget >/dev/null 2>&1 || return 255 local url="$1" local local_file="$2" - wget -U "${user_agent}" -q "${url}" -O "${local_file}" + local log_file="${TMP_DIR}/wget.log.${RANDOM}" + local -i rc=0 + wget -U "${user_agent}" -nv "${url}" -O "${local_file}" -o "${log_file}" + rc="$?" + if [[ "${rc}" -ne "0" ]] + then + while read -r ; do echo "${REPLY}" ; done <"${log_file}" + echo -n "${script}: \`wget' exited with an error: (exit code ${rc}, " + case "${rc}" in + 1) echo -n "generic error" ;; + 2) echo -n "parse error" ;; + 3) echo -n "file I/O error" ;; + 4) echo -n "network failure" ;; + 5) echo -n "SSL verification failure" ;; + 6) echo -n "username/password authentication failure" ;; + 7) echo -n "protocol errors" ;; + 8) echo -n "server issued an error response" ;; + *) echo -n "unknown error" ;; + esac + echo ")" + echo " ... while downloading \`${url}'" + fi >&2 + [[ "${rc}" -eq "0" ]] } # $1 repo file From 040ab4c0cbf2332cedcc50807292bafea95c25a5 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Thu, 2 Mar 2017 10:50:19 -0500 Subject: [PATCH 038/187] Remove Error message for rpower command when node has pdu attributes --- xCAT-server/lib/xcat/plugins/pdu.pm | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/pdu.pm b/xCAT-server/lib/xcat/plugins/pdu.pm index 7e107d529..b24adf3eb 100644 --- a/xCAT-server/lib/xcat/plugins/pdu.pm +++ b/xCAT-server/lib/xcat/plugins/pdu.pm @@ -131,9 +131,12 @@ sub process_request return powerstat($noderange, $callback); }elsif ($command eq "rpower") { my $subcmd = $exargs[0]; - if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat')){ + if (($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){ + #if one day, pdu node have pdu attribute, handle in this section too + return powerpduoutlet($noderange, $subcmd, $callback); + } else { #------------------------------------------- - #there are 2 cases will enter this black + #there are 2 cases will enter this block #one is if node's mgt is pdu #another is if node has pdu attribute but mgt isn't pdu #if the node has pdu attribute but mgt isn't pdu, @@ -144,15 +147,14 @@ sub process_request my $nodehmhash = $nodehm->getNodesAttribs($noderange, ['mgt']); foreach my $node (@$noderange) { if($nodehmhash->{$node}->[0]->{mgt} eq 'pdu'){ - push @allpdunodes, $node; + if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat')){ + push @allpdunodes, $node; + } else { + $callback->({ errorcode => [1],error => "The input $command is not support for pdu"}); + } } } return powerpdu(\@allpdunodes, $subcmd, $callback); - }elsif(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){ - #if one day, pdu node have pdu attribute, handle in this section too - return powerpduoutlet($noderange, $subcmd, $callback); - }else{ - $callback->({ errorcode => [1],error => "The input command $subcmd is not support for pdu"}); } }elsif($command eq "nodeset") { $callback->({ errorcode => [1],error => "The input $command is not support for pdu"}); @@ -185,6 +187,9 @@ sub powerpdu { foreach my $node (@$noderange) { my $session = connectTopdu($node,$callback); + if (!$session) { + next; + } my $count = $session->get("$outletnum"); my $value; my $statstr; @@ -244,6 +249,9 @@ sub powerpduoutlet { foreach my $pdu_outlet (@pdus) { my ($pdu, $outlet) = split /:/, $pdu_outlet; my $session = connectTopdu($pdu,$callback); + if (!$session) { + next; + } my $cmd; if ($subcmd eq "pdustat") { $statstr=outletstat($session, $outlet); @@ -307,6 +315,9 @@ sub powerstat { my $outletnum = ".1.3.6.1.4.1.2.6.223.8.2.1.0"; foreach my $pdu (@$noderange) { my $session = connectTopdu($pdu,$callback); + if (!$session) { + next; + } my $count = $session->get("$outletnum"); for (my $outlet =1; $outlet <= $count; $outlet++) { From 88323b74009e1b1dfd33732f97f6a76bd973b13d Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Thu, 2 Mar 2017 14:05:11 -0500 Subject: [PATCH 039/187] Final review changes --- .../common/deployment/cfg_network.rst | 2 ++ .../common/deployment/cfg_network_bond.rst | 2 +- .../common/deployment/cfg_network_vlan.rst | 16 +++------------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst index c36c0e3c2..e11d21d67 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network.rst @@ -1,6 +1,8 @@ Advanced Networking Configuration - confignetwork ================================================= +**Note:** ``confignetwork`` postscript is only supported on RHEL releases. + .. toctree:: :maxdepth: 2 diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst index 5bf46b9db..b4c31a981 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_bond.rst @@ -27,7 +27,7 @@ Add network object into the networks table Use the ``chdef`` command to add/modify the networks in the ``networks`` table :: - chdef -t network net40 net=40.0.0.0 mask=255.0.0.0 mgtifname=eth1 + chdef -t network net40 net=40.0.0.0 mask=255.0.0.0 chdef cn1 nicnetworks.bond0=net40 Add ``confignetwork`` into the node's postscripts list diff --git a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst index a245ff172..3ddd9606f 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/deployment/cfg_network_vlan.rst @@ -19,7 +19,7 @@ The following example set the xCAT properties for compute node ``cn1`` to achiev Define attributes in the ``nics`` table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Chose one of three methods described below: +Chose one of two methods described below: #. Using the ``mkdef`` or ``chdef`` commands @@ -83,16 +83,6 @@ Chose one of three methods described below: cat .stanza | mkdef -z -#. Using ``tabedit`` to edit the ``nics`` database table directly - - The ``tabedit`` command opens the specified xCAT database table in a ``vi`` like editor and allows the user to edit any text and write the changes back to the database table. - - After changing the content of the ``nics`` table, here is the result from ``tabdump nics`` :: - - # tabdump nics - #node,nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases,nicextraparams,nicdevices,comments,disable - "cn1","br1!10.0.0.1,br2!20.0.0.1",,,"br1!bridge,eth2!ethernet,eth3!ethernet,bond0.2!vlan,bond0!bond,br2!bridge,bond0.1!vlan",,"br1!net10,br2!net20",,,"br1!bond0.1,bond0!eth2|eth3,bond0.2!bond0,bond0.1!bond0,br2!bond0.2",, - Define the additional networks to xCAT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -103,8 +93,8 @@ Other information about the network should be defined in the ``networks`` table. Use the ``chdef`` command to add/modify the networks in the ``networks`` table :: - chdef -t network net10 net=10.0.0.0 mask=255.0.0.0 mgtifname=eth0 - chdef -t network net20 net=20.0.0.0 mask=255.0.0.0 mgtifname=eth1 + chdef -t network net10 net=10.0.0.0 mask=255.0.0.0 + chdef -t network net20 net=20.0.0.0 mask=255.0.0.0 Add ``confignetwork`` into the node's postscripts list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From ecb4f32d4c094efb4ed40b1cf91dc64ce0613eb3 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Thu, 2 Mar 2017 20:48:00 -0500 Subject: [PATCH 040/187] add rhels6.9 support --- .../autotest/bundle/rhels6.9_ppc64.bundle | 320 ++++++++++++++++++ .../autotest/bundle/rhels6.9_x86_64.bundle | 230 +++++++++++++ 2 files changed, 550 insertions(+) create mode 100644 xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle create mode 100644 xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle diff --git a/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle b/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle new file mode 100644 index 000000000..3d02946bd --- /dev/null +++ b/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle @@ -0,0 +1,320 @@ +reg_linux_diskfull_installation_flat +go_xcat_local_repo_case7 +go_xcat_noinput +go_xcat_with_x +go_xcat_with_xcat-version-1 +go_xcat_online_repo_case6 +updatenode_h +updatenode_v +updatenode_diskful_syncfiles +updatenode_diskful_syncfiles_rename +updatenode_diskful_syncfiles_dir +updatenode_diskful_syncfiles_multi_files +updatenode_syncfile_EXECUTE +updatenode_syncfile_EXECUTEALWAYS +updatenode_syncfile_APPEND +updatenode_syncfile_MERGE +updatenode_P_script1 +updatenode_P_script2 +updatenode_f_incompatible_flags +updatenode_k_incompatible_flags +updatenode_diskful_syncfiles_P_script1 +updatenode_script3 +updatenode_P_script1_script2 +updatenode_without_flag +chdef_null +chdef_t_node +chdef_t_network +chdef_p +chdef_m +chdef_z +chdef_group +chdef_group_p +chdef_dynamic_group +chdef_multiple_keys +chdef_n +chdef_t_o_error +chtab_null +chtab_d +chtab_modify_node +chtab_modify_key +chtab_h +chtab_v +copycds_iso +copycds_n +copycds_a +copycds_n_a +copycds_a_err +copycds_n_err +packimage_o_p_a_m +packimage_imagename +packimage_h +packimage_v +pping_h +pping_v +pping_node +getmacs_noderange +getmacs_d +getmacs_f_D +gettab_key_table +gettab_H +gettab_err +gettab_h +lsdef_null +lsdef_a +lsdef_t_o_l +lsdef_t_o_l_z +lsdef_t +lsdef_t_i_o +lsdef_t_w +lsdef_t_err +lslite_i +lslite_noderange +lslite_h +makeconservercf_null +makeconservercf_noderange +makeconservercf_d +makedhcp_n +makedhcp_a +makedhcp_a_d +makedhcp_d +mkdef_null +mkdef_z +mkdef_t_o_error +nodeadd_noderange +nodeadd_err_symbol +nodeadd_null +nodeadd_noderange_nodetype +nodeadd_v +nodeadd_h +nodegrpch_v +nodegrpch_h +nodegrpch_groups +nodegrpch_err +nodech_noderange_table +nodech_noderange_table_comma +nodech_noderange_table_arrow +nodech_noderanage_table_at +nodech_delete +nodech_error_node +nodech_error_table +nodech_h +nodech_v +nodech_noderange_table_include +nodech_noderange_table_uninclude +nodech_noderange_table_equal +nodech_noderange_table_unequal +nodech_noderange_shortname_groups +nodech_noderange_shortname_tags +nodech_noderange_shortname_mgt +nodels_null +nodels_H +nodels_noderange +nodels_err_symbol +nodels_err_noderange +nodels_noderange_shortname_groups +nodels_noderange_shortname_tags +nodels_noderange_shortname_mgt +nodels_table_include +nodels_noderange_table_uninclude +nodels_noderange_table_equal +nodels_noderange_table_unequal +nodels_b +nodels_S +nodels_noderange_table +nodels_tablevalue +nodels_tablevalue_tablecolumn +nodels_noderange_tablecolumn +nodels_h +nodels_v +xcatstanzafile_normal +xcatstanzafile_colon +xcatstanzafile_attribute +xcatstanzafile_objtype +xcatstanzafile_tab +xcatstanzafile_multattr +xcatstanzafile_defaultvalue +xcatstanzafile_specificvalue +noderm_noderange +noderm_h +noderm_null +noderm_err_node +nodeset_stat +nodeset_noderange +nodestat_err_node +rinv_bus +rinv_config +rinv_serial +rinv_model +rinv_firm +rinv_all +rinv_noderange_err +rmdef_null +rmdef_t_err +rpower_off +rpower_stat +rpower_boot +rpower_on +rpower_reset +rpower_noderange +rpower_noderange_nodeps +rpower_err_noderange +rscan_noderange +rscan_x +rscan_z +rscan_w +rscan_x_w +rscan_z_w +rvitals_lcds +rvitals_all +rvitals_noderange_err +tabdump_table +tabdump_d +tabdump_v +tabdump_h +tabdump_help +tabdump_w_match +tabdump_w_equal +tabdump_w_ne +tabdump_w_notmatch +tabdump_w_gt +tabdump_w_ge +tabdump_w_lt +tabdump_w_le +tabdump_f_d +tabdump_d_nodehm +tabprune_h +tabprune_v +tabprune_a_eventlog +tabprune_V_a_eventlog +tabprune_p_auditlog +tabprune_i_auditlog +tabprune_V_n_auditlog +tabgrep_node +tabgrep_null +tabgrep_h +tabgrep_err +tabrestore_table +tabrestore_null +tabrestore_h +tabrestore_err +dumpxCATdb_h +dumpxCATdb_v +dumpxCATdb_p_nullskiptables +dumpxCATdb_a_p_nullskiptables +dumpxCATdb_p_skiptables +dumpxCATdb_a_p_skiptables +dumpxCATdb_p_nullskiptables_V +dumpxCATdb_a_p_nullskiptables_V +dumpxCATdb_p_V +restorexCAT_h +restorexCATdb_v +restorexCATdb_p_V +restorexCATdb_a_p_V +restorexCATdb_wrongpath +regnotif_null +regnotif_o +regnotif_err +regnotif_h +regnotif_v +unregnotif_null +unregnotif_f +unregnotif_h +unregnotif_v +lsxcatd_null +lsxcatd_h +lsxcatd_d +lsxcatd_a +makehosts_h +makehosts_help +makehosts_null +makehosts_l +makehosts_d +makehosts_n +makehosts_n_noderange +xdcp_src_dst +makedns_h +makedns_d_node +makedns_n +makedns +noderange_individual_node +noderange_individual_grp +noderange_node01-node10 +noderange_group1-group3 +noderange_10-20 +noderange_XCAT_NODE_PREFIX +noderange_XCAT_NODE_SUFFIX +noderange_exclusion +noderange_group_intersection +confignics_config_one_port_single_value +confignics_config_multiple_ports_single_value +confignics_config_multiple_ports_multiple_value +confignics_config_multiple_port_withnichostnamesuffixes_multiple_value +confignics_config_multiple_port_withnicaliases_multiple_value +confignics_disable_set_to_yes +confignics_disable_set_to_1 +confignics_s +xdsh_h +xdsh_V +xdsh_regular_command +xdsh_Q_command +xdsh_c_cn +xdsh_e_filename +xdsh_E +xdsh_t +xdsh_q +xdsh_T +xdsh_o +psh_h +psh_v +psh_node_cmd_linux +psh_l +psh_i +prsync_h +prsync_v +prsync_dir_node +prsync_file_node +switchdiscover_range_default +switchdiscover_h +switchdiscover_range_s +switchdiscover_range_default_w +switchdiscover_range_r +switchdiscover_range_x +switchdiscover_range_z +switchdiscover_range_z_V +makentp_v +makentp_h +nodeset_check_warninginfo +runcmdinstaller_h +runcmdinstaller_command +get_xcat_postscripts_loginfo +updatenode_postscripts_loginfo +bmcdiscover_h +bmcdiscover_nmap_range +bmcdiscover_v +bmcdiscover_check_paswd +bmcdiscover_check_passwd_wrong +bmcdiscover_get_ipsource +bmcdiscover_range_w +bmcdiscover_range_z +xcatd_start +xcatd_stop +xcatd_restart +run_command_with_XCATBYPASS +disable_root_permission_in_policy_table +assign_certain_command_permission +xcatconfig_u_check_xcatsslversion_rhels_sles +reg_linux_diskless_installation_flat +packimage_m_cpio_c_gzip +packimage_m_cpio_c_xz +packimage_m_tar_c_gzip +packimage_m_tar_c_xz +packimage_m_invalid_archive_method +packimage_m_invalid_compress_method +reg_linux_statelite_installation_flat +SN_setup_case +reg_linux_diskfull_installation_hierarchy +reg_linux_diskless_installation_hierarchy +reg_linux_statelite_installation_hierarchy_by_ramdisk +reg_linux_statelite_installation_hierarchy_by_nfs +clean_up_env diff --git a/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle b/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle new file mode 100644 index 000000000..bd2907ad7 --- /dev/null +++ b/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle @@ -0,0 +1,230 @@ +setup_vm +reg_linux_diskfull_installation_flat +go_xcat_local_repo_case7 +go_xcat_noinput +go_xcat_with_x +go_xcat_with_xcat-version-1 +go_xcat_online_repo_case6 +makehosts_h +makehosts_help +makehosts_n +makehosts_n_noderange +chdef_null +chdef_z +chdef_t_o_error +chtab_null +chtab_d +chtab_modify_node +chtab_modify_key +chtab_h +chtab_v +packimage_o_p_a_m +packimage_imagename +packimage_h +packimage_v +pping_h +pping_v +pping_node +gettab_key_table +gettab_H +gettab_err +gettab_h +lsdef_null +lsdef_a +lsdef_t_o_l +lsdef_t_o_l_z +lsdef_t +lsdef_t_i_o +lsdef_t_w +lsdef_t_err +lslite_i +lslite_noderange +lslite_h +makeconservercf_null +makeconservercf_noderange +makeconservercf_d +makedhcp_n +makedhcp_a +makedhcp_a_d +makedhcp_d +mkdef_null +mkdef_z +mkdef_t_o_error +nodeadd_noderange +nodeadd_err_symbol +nodeadd_null +nodeadd_noderange_nodetype +nodeadd_v +nodeadd_h +nodegrpch_v +nodegrpch_h +nodegrpch_groups +nodegrpch_err +nodech_noderange_table +nodech_noderange_table_comma +nodech_noderange_table_arrow +nodech_noderanage_table_at +nodech_delete +nodech_error_node +nodech_error_table +nodech_h +nodech_v +nodech_noderange_table_include +nodech_noderange_table_uninclude +nodech_noderange_table_equal +nodech_noderange_table_unequal +nodech_noderange_shortname_groups +nodech_noderange_shortname_tags +nodech_noderange_shortname_mgt +nodels_null +nodels_H +nodels_noderange +nodels_err_symbol +nodels_err_noderange +nodels_noderange_shortname_groups +nodels_noderange_shortname_tags +nodels_noderange_shortname_mgt +nodels_table_include +nodels_noderange_table_uninclude +nodels_noderange_table_equal +nodels_noderange_table_unequal +nodels_b +nodels_S +nodels_noderange_table +nodels_tablevalue +nodels_tablevalue_tablecolumn +nodels_noderange_tablecolumn +nodels_h +nodels_v +xcatstanzafile_normal +xcatstanzafile_colon +xcatstanzafile_attribute +xcatstanzafile_objtype +xcatstanzafile_tab +xcatstanzafile_multattr +xcatstanzafile_defaultvalue +xcatstanzafile_specificvalue +noderm_noderange +noderm_h +noderm_null +noderm_err_node +nodeset_stat +nodeset_noderange +nodestat_noderange +nodestat_err_node +rinv_noderange_err +rmdef_null +rmdef_t_err +rpower_err_noderange +rvitals_noderange_err +tabdump_table +tabdump_d +tabdump_v +tabdump_h +tabdump_help +tabdump_w_match +tabdump_w_equal +tabdump_w_ne +tabdump_w_notmatch +tabdump_w_gt +tabdump_w_ge +tabdump_w_lt +tabdump_w_le +tabdump_f_d +tabdump_d_nodehm +tabprune_h +tabprune_v +tabprune_a_eventlog +tabprune_V_a_eventlog +tabprune_i_auditlog +tabprune_V_n_auditlog +tabgrep_node +tabgrep_null +tabgrep_h +tabgrep_err +tabrestore_table +tabrestore_null +tabrestore_h +tabrestore_err +dumpxCATdb_h +dumpxCATdb_v +dumpxCATdb_p_nullskiptables +dumpxCATdb_a_p_nullskiptables +dumpxCATdb_p_skiptables +dumpxCATdb_a_p_skiptables +dumpxCATdb_p_nullskiptables_V +dumpxCATdb_a_p_nullskiptables_V +dumpxCATdb_p_V +restorexCAT_h +restorexCATdb_v +restorexCATdb_p_V +restorexCATdb_a_p_V +restorexCATdb_wrongpath +regnotif_null +regnotif_o +regnotif_err +regnotif_h +regnotif_v +unregnotif_null +unregnotif_f +unregnotif_h +unregnotif_v +lsxcatd_null +lsxcatd_h +lsxcatd_d +lsxcatd_a +makedns_d_node +makedns_n +makedns +copycds_iso +copycds_n +copycds_a +copycds_n_a +xdsh_h +xdsh_V +xdsh_regular_command +xdsh_Q_command +xdsh_c_cn +xdsh_e_filename +xdsh_E +xdsh_i_linux +xdsh_t +xdsh_q +xdsh_T +xdsh_o +psh_h +psh_v +psh_node_cmd_linux +psh_l +psh_i +prsync_h +prsync_v +prsync_dir_node +prsync_file_node +switchdiscover_range_default +switchdiscover_h +switchdiscover_range_s +switchdiscover_range_default_w +switchdiscover_range_r +switchdiscover_range_x +switchdiscover_range_z +switchdiscover_range_z_V +nodeset_shell +nodeset_cmdline +nodeset_runimg +nodeset_check_warninginfo +xcatconfig_u_check_xcatsslversion_rhels_sles +reg_linux_diskless_installation_flat +packimage_m_cpio_c_gzip +packimage_m_cpio_c_xz +packimage_m_tar_c_gzip +packimage_m_tar_c_xz +packimage_m_invalid_archive_method +packimage_m_invalid_compress_method +reg_linux_statelite_installation_flat +SN_setup_case +reg_linux_diskfull_installation_hierarchy +reg_linux_diskless_installation_hierarchy +reg_linux_statelite_installation_hierarchy_by_ramdisk +reg_linux_statelite_installation_hierarchy_by_nfs +clean_up_env From 8bbe879d5380383d1d0826eee11ad3c98dc7db2e Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Thu, 2 Mar 2017 21:03:24 -0500 Subject: [PATCH 041/187] remove stop lable to have a full regression --- .../testcase/installation/Diskless_installation_flat_p8_le | 1 - .../autotest/testcase/installation/Full_installation_flat_p8_le | 1 - .../testcase/installation/reg_linux_diskfull_installation_flat | 1 - .../testcase/installation/reg_linux_diskless_installation_flat | 1 - .../testcase/installation/reg_linux_statelite_installation_flat | 1 - 5 files changed, 5 deletions(-) diff --git a/xCAT-test/autotest/testcase/installation/Diskless_installation_flat_p8_le b/xCAT-test/autotest/testcase/installation/Diskless_installation_flat_p8_le index 532a4f0d8..95cfd0751 100644 --- a/xCAT-test/autotest/testcase/installation/Diskless_installation_flat_p8_le +++ b/xCAT-test/autotest/testcase/installation/Diskless_installation_flat_p8_le @@ -1,6 +1,5 @@ start:Diskless_installation_flat_p8_le os:Linux -stop:yes cmd:copycds $$ISO check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/Full_installation_flat_p8_le b/xCAT-test/autotest/testcase/installation/Full_installation_flat_p8_le index 9722176aa..c7d72b166 100644 --- a/xCAT-test/autotest/testcase/installation/Full_installation_flat_p8_le +++ b/xCAT-test/autotest/testcase/installation/Full_installation_flat_p8_le @@ -1,6 +1,5 @@ start:Full_installation_flat_p8_le os:Linux -stop:yes cmd:copycds $$ISO check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat index 89f9d73d8..76231d47f 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat @@ -1,6 +1,5 @@ start:reg_linux_diskfull_installation_flat os:Linux -stop:yes cmd:if ping -c 1 $$SN > /dev/null;then rpower $$SN off > /dev/null;fi diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat index 227085f4a..42556e6f6 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat @@ -1,6 +1,5 @@ start:reg_linux_diskless_installation_flat os:Linux -stop:yes cmd:chdef -t node -o $$CN servicenode= monserver=$$MN nfsserver=$$MN tftpserver=$$MN xcatmaster=$$MN check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_flat index e36a65826..fe31a9c33 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_flat @@ -1,6 +1,5 @@ start:reg_linux_statelite_installation_flat os:Linux -stop:yes cmd:chdef -t node -o $$CN servicenode= monserver=$$MN nfsserver=$$MN tftpserver=$$MN xcatmaster=$$MN check:rc==0 From b35ce9a148160548939bfeeb93db5277dddd2cbf Mon Sep 17 00:00:00 2001 From: chenglch Date: Fri, 3 Mar 2017 11:06:01 +0800 Subject: [PATCH 042/187] Fix regex issue that duplicate the node name close-issue: #2582 --- perl-xCAT/xCAT/Table.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/perl-xCAT/xCAT/Table.pm b/perl-xCAT/xCAT/Table.pm index 5f1714f50..576598ef9 100644 --- a/perl-xCAT/xCAT/Table.pm +++ b/perl-xCAT/xCAT/Table.pm @@ -2358,6 +2358,10 @@ sub transRegexAttrs undef $@; #extract_bracketed would have set $@ if it didn't return, undef $@ $retval = $node; $retval =~ s/$parts[0]/$parts[1]/; + if ($retval =~ /^$/) { + return undef; + } + return $retval; } while ($curr) { From 9f27be5b67bc40bd4f0833bdc6cae083ed33cf1d Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Fri, 3 Mar 2017 11:06:32 +0800 Subject: [PATCH 043/187] Testcase for smoke test of `updatenodes -S` --- xCAT-test/autotest/testcase/updatenode/cases2 | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 xCAT-test/autotest/testcase/updatenode/cases2 diff --git a/xCAT-test/autotest/testcase/updatenode/cases2 b/xCAT-test/autotest/testcase/updatenode/cases2 new file mode 100644 index 000000000..ef55f2615 --- /dev/null +++ b/xCAT-test/autotest/testcase/updatenode/cases2 @@ -0,0 +1,6 @@ +start:updatenode_S +check:rc==0 +cmd:updatenode $$CN -S >/tmp/updatenode.S.out +cmd:grep 'Running of Software Maintenance has completed' /tmp/updatenode.S.out +check:rc==0 +end From 972e7605d3db995f834bc0e8d79b7a7fcfa80a48 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Fri, 3 Mar 2017 01:34:09 -0500 Subject: [PATCH 044/187] work around bug 2586 --- xCAT-test/autotest/testcase/installation/SN_setup_case | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xCAT-test/autotest/testcase/installation/SN_setup_case b/xCAT-test/autotest/testcase/installation/SN_setup_case index 1873a0efd..03b800f30 100644 --- a/xCAT-test/autotest/testcase/installation/SN_setup_case +++ b/xCAT-test/autotest/testcase/installation/SN_setup_case @@ -71,6 +71,9 @@ check:output=~booted cmd:xdsh $$SN date check:rc==0 check:output=~\d\d:\d\d:\d\d +#after bug 2586 is fixed, following 2 lines should be removed. +cmd:if [[ "__GETNODEATTR($$SN,os)__" =~ "sles" ]];then xdsh $$SN service xcatd restart; fi +check:rc==0 cmd:xdsh $$SN "ps -ef |grep xcatd" check:rc==0 check:output=~xcatd: From 965cc8081c958a9156b27d3730f082d1431e0a64 Mon Sep 17 00:00:00 2001 From: bybai Date: Fri, 3 Mar 2017 01:54:37 -0500 Subject: [PATCH 045/187] polish code --- xCAT/postscripts/configeth | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index c891f8137..2409b61ce 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -536,7 +536,9 @@ elif [ "$1" = "-s" ];then echo " address ${str_inst_ip}" >> $str_conf_file echo " netmask ${str_inst_mask}" >> $str_conf_file echo " hwaddress ether ${str_inst_mac}" >> $str_conf_file - echo " mtu ${str_inst_mtu}" >> $str_conf_file + if [ -n "${str_inst_mtu}" ];then + echo " mtu ${str_inst_mtu}" >> $str_conf_file + fi if [ -n "$str_inst_gateway" ];then echo " gateway $str_inst_gateway" >> $str_conf_file fi @@ -560,7 +562,9 @@ elif [ "$1" = "-s" ];then echo "IPADDR=${str_inst_ip}" >> $str_conf_file echo "NETMASK=${str_inst_mask}" >> $str_conf_file echo "HWADDR=${str_inst_mac}" >> $str_conf_file - echo "MTU=${str_inst_mtu}" >> $str_conf_file + if [ -n "${str_inst_mtu}" ];then + echo "MTU=${str_inst_mtu}" >> $str_conf_file + fi echo "STARTMODE=onboot" >> $str_conf_file if [ -n "$str_inst_gateway" ];then grep -i "default" /etc/sysconfig/network/routes @@ -593,7 +597,9 @@ elif [ "$1" = "-s" ];then echo "BOOTPROTO=static" >> $str_conf_file echo "ONBOOT=yes" >> $str_conf_file echo "HWADDR=${str_inst_mac}" >> $str_conf_file - echo "MTU=${str_inst_mtu}" >> $str_conf_file + if [ -n "${str_inst_mtu}" ];then + echo "MTU=${str_inst_mtu}" >> $str_conf_file + fi if [ -n "$str_inst_gateway" ];then grep -i "GATEWAY" /etc/sysconfig/network if [ $? -eq 0 ];then From 061fbb012b335ae020e310263c6024d2f1e780f6 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Fri, 3 Mar 2017 15:02:50 +0800 Subject: [PATCH 046/187] [go-xcat] Better Linux distro version detection --- xCAT-server/share/xcat/tools/go-xcat | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xCAT-server/share/xcat/tools/go-xcat b/xCAT-server/share/xcat/tools/go-xcat index c6a6df662..b445b04a8 100755 --- a/xCAT-server/share/xcat/tools/go-xcat +++ b/xCAT-server/share/xcat/tools/go-xcat @@ -2,7 +2,7 @@ # # go-xcat - Install xCAT automatically. # -# Version 1.0.14 +# Version 1.0.15 # # Copyright (C) 2016 International Business Machines # Eclipse Public License, Version 1.0 (EPL-1.0) @@ -370,7 +370,9 @@ function check_linux_version() local ver="$(source /etc/os-release >/dev/null 2>&1 && echo "${VERSION_ID}")" [[ -z "${ver}" && -f /etc/redhat-release ]] && - ver="$(awk '{ print $(NF - 1) }' /etc/redhat-release)" + # Need gawk to do this trick + ver="$(awk '{ match($0, /([.0-9]+)/, a); print substr($0, a[1, "start"], a[1, "length"]); }' \ + /etc/redhat-release)" [[ -z "${ver}" && -f /etc/SuSE-release ]] && ver="$(awk '/VERSION/ { print $NF }' /etc/SuSE-release)" echo "${ver}" From ac4d9da56abb1983c3035928bfbf5bee162850c1 Mon Sep 17 00:00:00 2001 From: bybai Date: Fri, 3 Mar 2017 02:44:01 -0500 Subject: [PATCH 047/187] fix 2579 syncfile is in default node definition, but statelite does not support syncfile --- xCAT/postscripts/syncfiles | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xCAT/postscripts/syncfiles b/xCAT/postscripts/syncfiles index ebf34a7cc..5ce495dc2 100644 --- a/xCAT/postscripts/syncfiles +++ b/xCAT/postscripts/syncfiles @@ -7,6 +7,13 @@ # ##################################################### +#statelite does not support syncfiles +if [ -d /.statelite ]; then + echo "Statelite does not support syncfiles, nothing to do..." + logger -t xcat -p local4.info "Statelite does not support syncfiles, nothing to do..." + exit 0 +fi + if cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then #TODO echo "Cumulus OS is not supported yet, nothing to do..." From 72a0a2b5a9b928d58a5269f203e5cf5562ba0bb7 Mon Sep 17 00:00:00 2001 From: XuWei Date: Wed, 1 Mar 2017 08:23:31 -0500 Subject: [PATCH 048/187] [DO NOT MERGER] framwork for openbmc support --- perl-xCAT/xCAT/Schema.pm | 35 +- xCAT-server/lib/perl/xCAT/OPENBMC.pm | 46 ++ xCAT-server/lib/xcat/plugins/openbmc.pm | 599 ++++++++++++++++++++++++ 3 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 xCAT-server/lib/perl/xCAT/OPENBMC.pm create mode 100644 xCAT-server/lib/xcat/plugins/openbmc.pm diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 8a0639ea4..f99e74ac3 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -443,6 +443,19 @@ passed as argument rather than by table value', disable => "Set to 'yes' or '1' to comment out this row.", }, }, + openbmc => { + cols => [qw(node bmc username password comments disable)], + keys => [qw(node)], + table_desc => 'Setting for nodes that are controlled by an on-board OpenBmc.', + descriptions => { + node => 'The node name or group name.', + bmc => 'The hostname of the BMC adapter.', + username => 'The BMC userid.', + password => 'The BMC password.', + comments => 'Any user-written notes.', + disable => "Set to 'yes' or '1' to comment out this row.", + }, + }, iscsi => { cols => [qw(node server target lun iname file userid passwd kernel kcmdline initrd comments disable)], keys => [qw(node)], @@ -586,7 +599,7 @@ passed as argument rather than by table value', descriptions => { node => 'The node name or group name.', power => 'The method to use to control the power of the node. If not set, the mgt attribute will be used. Valid values: ipmi, blade, hmc, ivm, fsp, kvm, esx, rhevm. If "ipmi", xCAT will search for this node in the ipmi table for more info. If "blade", xCAT will search for this node in the mp table. If "hmc", "ivm", or "fsp", xCAT will search for this node in the ppc table.', - mgt => 'The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details.', + mgt => 'The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: openbmc, ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details.', cons => 'The console method. If nodehm.serialport is set, this will default to the nodehm.mgt setting, otherwise it defaults to unused. Valid values: cyclades, mrv, or the values valid for the mgt attribute.', termserver => 'The hostname of the terminal server.', termport => 'The port number on the terminal server that this node is connected to.', @@ -2447,6 +2460,26 @@ my @nodeattrs = ( tabentry => 'mpa.urlpath', access_tabentry => 'mpa.mpa=attr:node', }, + +######################### + # openbmc table # +########################## + { attr_name => 'bmc', + only_if => 'mgt=openbmc', + tabentry => 'openbmc.bmc', + access_tabentry => 'openbmc.node=attr:node', + }, + { attr_name => 'bmcusername', + only_if => 'mgt=openbmc', + tabentry => 'openbmc.username', + access_tabentry => 'openbmc.node=attr:node', + }, + { attr_name => 'bmcpassword', + only_if => 'mgt=openbmc', + tabentry => 'openbmc.password', + access_tabentry => 'openbmc.node=attr:node', + }, + ###################### # nodepos table # ###################### diff --git a/xCAT-server/lib/perl/xCAT/OPENBMC.pm b/xCAT-server/lib/perl/xCAT/OPENBMC.pm new file mode 100644 index 000000000..424f83c36 --- /dev/null +++ b/xCAT-server/lib/perl/xCAT/OPENBMC.pm @@ -0,0 +1,46 @@ +#!/usr/bin/perl +## IBM(c) 2107 EPL license http://www.eclipse.org/legal/epl-v10.html + +package xCAT::OPENBMC; + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; +use strict; +use warnings "all"; + +use HTTP::Async; +use HTTP::Request; +use HTTP::Headers; +use HTTP::Cookies; +use Data::Dumper; + +my $header = HTTP::Headers->new('Content-Type' => 'application/json'); + +sub new { + my $async = shift; + $async = shift if (($async) && ($async =~ /OPENBMC/)); + my $url = shift; + my $content = shift; + my $method = 'POST'; + + my $id = send_request( $async, $method, $url, $content ); + + return $id; +} + +sub send_request { + my $async = shift; + $async = shift if (($async) && ($async =~ /OPENBMC/)); + my $method = shift; + my $url = shift; + my $content = shift; + + my $request = HTTP::Request->new( $method, $url, $header, $content ); + my $id = $async->add_with_opts($request, {}); + return $id; +} + +1; diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm new file mode 100644 index 000000000..31bec809a --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -0,0 +1,599 @@ +#!/usr/bin/perl +## IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +package xCAT_plugin::openbmc; + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; +use strict; +use warnings "all"; + +use HTTP::Async; +use HTTP::Cookies; +use xCAT::OPENBMC; +use xCAT::Utils; +use xCAT::Table; +use xCAT::Usage; +use xCAT::SvrUtils; +use File::Basename; +use Data::Dumper; +use JSON; + +#------------------------------------------------------- + +=head3 handled_commands + + Return list of commands handled by this plugin + +=cut + +#------------------------------------------------------- +sub handled_commands { + return { + rpower => 'nodehm:mgt', + rinv => 'nodehm:mgt', + }; +} + +#------------------------------------------------------- + +# The hash table to store method and url for request, +# process function for response + +#------------------------------------------------------- +my %status_info = ( + LOGIN_REQUEST => { + method => "POST", + init_url => "/login", + }, + LOGIN_RESPONSE => { + process => \&login_response, + }, + + RPOWER_ON_REQUEST => { + method => "POST", + init_url => "/power/on", + }, + RPOWER_ON_RESPONSE => { + process => \&rpower_response, + }, + RPOWER_OFF_REQUEST => { + method => "POST", + init_url => "/power/off", + }, + RPOWER_OFF_RESPONSE => { + process => \&rpower_response, + }, + RPOWER_RESET_REQUEST => { + method => "POST", + init_url => "/power/reset", + }, + RPOWER_RESET_RESPONSE => { + process => \&rpower_response, + }, + RPOWER_STATUS_REQUEST => { + method => "GET", + init_url => "/org/openbmc/settings/host0", + }, + RPOWER_STATUS_RESPONSE => { + process => \&rpower_response, + }, + + RINV_MTHBRD_REQUEST => { + method => "GET", + init_url => "/org/openbmc/inventory/system/chassis/motherboard", + }, + RINV_MTHBRD_RESPONSE => { + process => \&rinv_response, + }, + RINV_CPU_REQUEST => { + method => "GET", + init_url => "/org/openbmc/inventory/system/chassis/motherboard/", + }, + RINV_CPU_RESPONSE => { + process => \&rinv_response, + }, + RINV_DIMM_REQUEST => { + method => "GET", + init_url => "/org/openbmc/inventory/system/chassis/motherboard/", + }, + RINV_DIMM_RESPONSE => { + process => \&rinv_response, + }, +); + + +#----------------------------- + +=head3 %node_info + + $node_info = ( + $node => { + bmc => "x.x.x.x", + username => "username", + password => "password", + cur_status => "LOGIN_REQUEST", + cur_url => "", + method => "", + back_urls => (), + $src => "", + }, + ); + + 'cur_url', 'method', 'back_urls' used for path has a trailing-slash + +=cut + +#----------------------------- +my %node_info = (); + +my %next_status = (); + +my %handle_id_node = (); + +my $wait_node_num; + +my $async; + +my $cookie_jar; + +my $callback; + +#------------------------------------------------------- + +=head3 preprocess_request + + preprocess the command + +=cut + +#------------------------------------------------------- +sub preprocess_request { + my $request = shift; + if (defined $request->{_xcatpreprocessed}->[0] and $request->{_xcatpreprocessed}->[0] == 1) { + return [$request]; + } + + $callback = shift; + + my $command = $request->{command}->[0]; + my $noderange = $request->{node}; + my $extrargs = $request->{arg}; + my @exargs = ($request->{arg}); + my @requests; + + if (ref($extrargs)) { + @exargs = @$extrargs; + } + my $usage_string = xCAT::Usage->parseCommand($command, @exargs); + if ($usage_string) { + $callback->({ data => [$usage_string] }); + $request = {}; + return; + } + + my $parse_result = parse_args($command, $extrargs); + if (ref($parse_result) eq 'ARRAY') { + $callback->({ error => $parse_result->[1], errorcode => $parse_result->[0] }); + $request = {}; + return; + } + + my $sn = xCAT::ServiceNodeUtils->get_ServiceNode($noderange, "xcat", "MN"); + foreach my $snkey (keys %$sn) { + my $reqcopy = {%$request}; + $reqcopy->{node} = $sn->{$snkey}; + $reqcopy->{'_xcatdest'} = $snkey; + $reqcopy->{_xcatpreprocessed}->[0] = 1; + push @requests, $reqcopy; + } + + return \@requests; +} + +#------------------------------------------------------- + +=head3 process_request + + Process the command + +=cut + +#------------------------------------------------------- +sub process_request { + my $request = shift; + my $noderange = $request->{node}; + + parse_node_info($noderange); + + $cookie_jar = HTTP::Cookies->new({}); + $async = HTTP::Async->new( + cookie_jar => $cookie_jar, + ssl_options => { + SSL_verify_mode => 0, + }, + ); + + my $bmcip; + my $login_url; + my $handle_id; + my $content; + $wait_node_num = keys %node_info; + + foreach my $node (keys %node_info) { + $bmcip = $node_info{$node}{bmc}; + $login_url = "https://$bmcip/login"; + $content = '{"data": [ "' . $node_info{$node}{username} .'", "' . $node_info{$node}{password} . '" ] }'; + $handle_id = xCAT::OPENBMC->new($async, $login_url, $content); + $handle_id_node{$handle_id} = $node; + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + } + + while (1) { + last unless ($wait_node_num); + while (my ($response, $handle_id) = $async->wait_for_next_response) { + deal_with_response($handle_id, $response); + } + } + + return; +} + +#------------------------------------------------------- + +=head3 parse_args + + Parse the command line options and operands + +=cut + +#------------------------------------------------------- +sub parse_args { + my $command = shift; + my $extrargs = shift; + + $next_status{LOGIN_REQUEST} = "LOGIN_RESPONSE"; + + if ($command eq "rpower") { + if (!defined($extrargs)) { + return ([ 1, "No option specified for rpower" ]); + } + + if (scalar(@ARGV) > 1) { + return ([ 1, "Only one option is supportted at the same time" ]); + } + + my $subcommand = $ARGV[0]; + +# now, only support status, delete when other command supported +if ($subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat") { + return ([ 1, "Only support status check currently" ]) +} +#---------------------------------------------------------------- + + if ($subcommand eq "on") { + $next_status{LOGIN_RESPONSE} = "RPOWER_ON_REQUEST"; + $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; + } elsif ($subcommand eq "off") { + $next_status{LOGIN_RESPONSE} = "RPOWER_OFF_REQUEST"; + $next_status{RPOWER_OFF_REQUEST} = "RPOWER_OFF_RESPONSE"; + } elsif ($subcommand eq "status" or $subcommand eq "state" or $subcommand eq "stat") { + $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; + $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; + } elsif ($subcommand eq "boot") { + $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; + $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; + $next_status{RPOWER_STATUS_RESPONSE}{OFF} = "RPOWER_ON_REQUEST"; + $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; + $next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST"; + $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; + } else { + return ([ 1, "$subcommand is not supported for rpower" ]); + } + } + + if ($command eq "rinv") { + if (!defined($extrargs)) { + return ([ 1, "No option specified for rpower" ]); + } + + if (scalar(@ARGV) > 1) { + return ([ 1, "Only one option is supportted at the same time" ]); + } + + my $subcommand = $ARGV[0]; + + if ($subcommand eq "cpu") { + $next_status{LOGIN_RESPONSE} = "RINV_CPU_REQUEST"; + $next_status{RINV_CPU_REQUEST} = "RINV_CPU_RESPONSE"; + } elsif ($subcommand eq "dimm") { + $next_status{LOGIN_RESPONSE} = "RINV_DIMM_REQUEST"; + $next_status{RINV_DIMM_REQUEST} = "RINV_DIMM_RESPONSE"; + } elsif ($subcommand eq "all") { + $next_status{LOGIN_RESPONSE} = "RINV_MTHBRD_REQUEST"; + $next_status{RINV_MTHBRD_REQUEST} = "RINV_MTHBRD_RESPONSE"; + $next_status{RINV_MTHBRD_RESPONSE} = "RINV_CPU_REQUEST"; + $next_status{RINV_CPU_REQUEST} = "RINV_CPU_RESPONSE"; + $next_status{RINV_CPU_RESPONSE} = "RINV_DIMM_REQUEST"; + $next_status{RINV_DIMM_REQUEST} = "RINV_DIMM_RESPONSE"; + } else { + return ([ 1, "Only 'cpu','dimm','all' are supportted at the same time" ]); + } + } + + print Dumper(%next_status) . "\n"; + + return; +} + + +#------------------------------------------------------- + +=head3 parse_node_info + + Parse the node information: bmc, username, password + +=cut + +#------------------------------------------------------- +sub parse_node_info { + my $noderange = shift; + + my $table = xCAT::Table->new('openbmc'); + my $tablehash = $table->getNodesAttribs(\@$noderange, ['bmc', 'username', 'password']); + + foreach my $node (@$noderange) { + if (defined($tablehash->{$node}->[0])) { + if ($tablehash->{$node}->[0]->{'bmc'}) { + $node_info{$node}{bmc} = $tablehash->{$node}->[0]->{'bmc'}; + } else { + xCAT::SvrUtils::sendmsg("Unable to get attribute bmc", $callback, $node); + next; + } + + if ($tablehash->{$node}->[0]->{'username'}) { + $node_info{$node}{username} = $tablehash->{$node}->[0]->{'username'}; + } else { + xCAT::SvrUtils::sendmsg("Unable to get attribute username", $callback, $node); + delete $node_info{$node}; + next; + } + + if ($tablehash->{$node}->[0]->{'password'}) { + $node_info{$node}{password} = $tablehash->{$node}->[0]->{'password'}; + } else { + xCAT::SvrUtils::sendmsg("Unable to get attribute password", $callback, $node); + delete $node_info{$node}; + next; + } + + $node_info{$node}{cur_status} = "LOGIN_REQUEST"; + } else { + xCAT::SvrUtils::sendmsg("Unable to get information from openbmc table", $callback, $node); + next; + } + } + + print Dumper(%node_info) ."\n"; + + return; +} + +#------------------------------------------------------- + +=head3 gen_send_request + + Generate request's information + If the node has method itself, use it as request's method. + If not, use method %status_info defined. + If the node has cur_url, check whether also has sub_urls. + If has, request's url is join cur_url and one in sub_urls(use one at once to check which is needed). + If not, use method %status_info defined. + use xCAT::OPENBMC->send_request send request + store handle_id and mapping node + Input: + $node: nodename of current node + +=cut + +#------------------------------------------------------- +sub gen_send_request { + my $node = shift; + my $method; + my $request_url; + my $content; + + if ($node_info{$node}{method}) { + $method = $node_info{$node}{method}; + } else { + $method = $status_info{ $node_info{$node}{cur_status} }{method}; + } + + if ($node_info{$node}{cur_url}) { + $request_url = $node_info{$node}{cur_url}; + } else { + $request_url = $status_info{ $node_info{$node}{cur_status} }{init_url}; + } + $request_url = "https://" . $node_info{$node}{bmc} . $request_url; + + my $handle_id = xCAT::OPENBMC->send_request($async, $method, $request_url, $content); + $handle_id_node{$handle_id} = $node; + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + + return; +} + +#------------------------------------------------------- + +=head3 deal_with_response + + Check response's status_line and + Input: + $handle_id: Async return ID with response + $response: Async return response + +=cut + +#------------------------------------------------------- +sub deal_with_response { + my $handle_id = shift; + my $response = shift; + my $node = $handle_id_node{$handle_id}; + + if ($response->status_line ne "200 OK") { + my $response_info = decode_json $response->content; + xCAT::SvrUtils::sendmsg($response_info->{'data'}->{'description'}, $callback, $node); + $wait_node_num--; + return; + } + + delete $handle_id_node{$handle_id}; + $status_info{ $node_info{$node}{cur_status} }->{process}->($node, $response); + + return; +} + +#------------------------------------------------------- + +=head3 login_response + + Deal with response of login + Input: + $node: nodename of current response + $response: Async return response + +=cut + +#------------------------------------------------------- +sub login_response { + my $node = shift; + my $response = shift; + + if ($next_status{ $node_info{$node}{cur_status} }) { + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + gen_send_request($node); + } + + return; +} + +#------------------------------------------------------- + +=head3 rpower_response + + Deal with response of rpower command + Input: + $node: nodename of current response + $response: Async return response + +=cut + +#------------------------------------------------------- +sub rpower_response { + my $node = shift; + my $response = shift; + + my $response_info = decode_json $response->content; + + if ($node_info{$node}{cur_status} eq "RPOWER_ON_RESPONSE") { + xCAT::SvrUtils::sendmsg("on", $callback, $node); + } + + if ($node_info{$node}{cur_status} eq "RPOWER_OFF_RESPONSE") { + xCAT::SvrUtils::sendmsg("off", $callback, $node); + } + + if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") { + xCAT::SvrUtils::sendmsg($response_info->{'data'}->{system_state}, $callback, $node); + } + + if ($next_status{ $node_info{$node}{cur_status} }) { + if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") { + if ($response_info->{'data'}->{system_state} =~ /HOST_POWERED_ON/) { + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{ON}; + } else { + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{OFF}; + } + } else { + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + } + gen_send_request($node); + + } else { + $wait_node_num--; + } + + return; +} + +sub rinv_response { + my $node = shift; + my $response = shift; + + my $response_info = decode_json $response->content; + + my %rinv_response = ( + RINV_CPU_RESPONSE => { + map_str => "cpu", + repeat => "RINV_CPU_REQUEST", + }, + RINV_DIMM_RESPONSE => { + map_str => "dimm", + repeat => "RINV_DIMM_REQUEST", + }, + + ); + + my $grep_string = $rinv_response{$node_info{$node}{cur_status}}{map_str}; + my $repeat_status = $rinv_response{$node_info{$node}{cur_status}}{repeat}; + + if ($node_info{$node}{cur_status} ne "RINV_MTHBRD_RESPONSE") { + if (ref($response_info->{data}) eq "ARRAY") { + foreach my $rsp_url (@{$response_info->{data}}) { + if ($rsp_url =~ /\/$grep_string/) { + push @{ $node_info{$node}{back_urls} }, $rsp_url; + } + } + + $node_info{$node}{cur_url} = shift @{ $node_info{$node}{back_urls} }; + $node_info{$node}{cur_status} = $repeat_status; + $node_info{$node}{src} = basename $node_info{$node}{cur_url}; + gen_send_request($node); + } elsif (ref($response_info->{data}) eq "HASH") { + my $cpu_info; + foreach my $key (keys %{$response_info->{data}}) { + $cpu_info = uc ($node_info{$node}{src}) . " " . $key . " : " . ${$response_info->{data}}{$key}; + xCAT::SvrUtils::sendmsg("$cpu_info", $callback, $node); + } + + if (@{ $node_info{$node}{back_urls} }) { + $node_info{$node}{cur_url} = shift @{ $node_info{$node}{back_urls} }; + $node_info{$node}{cur_status} = $repeat_status; + $node_info{$node}{src} = basename $node_info{$node}{cur_url}; + gen_send_request($node); + } else { + if ($next_status{ $node_info{$node}{cur_status} }) { + delete $node_info{$node}{cur_url}; + delete $node_info{$node}{src}; + gen_send_request($node); + } else { + $wait_node_num--; + } + } + } + } + + #print Dumper(%node_info) ."\n"; + return; +} + + +1; + + + + + From 2f21fea0443e94fdea413ef6e5049dd3956dee0b Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Fri, 3 Mar 2017 09:13:15 -0500 Subject: [PATCH 049/187] modify changes from weihua's comments --- xCAT-server/lib/xcat/plugins/pdu.pm | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/pdu.pm b/xCAT-server/lib/xcat/plugins/pdu.pm index b24adf3eb..578733ed6 100644 --- a/xCAT-server/lib/xcat/plugins/pdu.pm +++ b/xCAT-server/lib/xcat/plugins/pdu.pm @@ -147,18 +147,20 @@ sub process_request my $nodehmhash = $nodehm->getNodesAttribs($noderange, ['mgt']); foreach my $node (@$noderange) { if($nodehmhash->{$node}->[0]->{mgt} eq 'pdu'){ - if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat')){ - push @allpdunodes, $node; - } else { - $callback->({ errorcode => [1],error => "The input $command is not support for pdu"}); - } + push @allpdunodes, $node; + } + } + if(@allpdunodes) { + if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat') || ($subcmd eq 'state')){ + return powerpdu(\@allpdunodes, $subcmd, $callback); + } else { + my $pdunodes = join (",", @allpdunodes); + $callback->({ errorcode => [1],error => "The option $subcmd is not support for pdu node(s) $pdunodes."}); } } - return powerpdu(\@allpdunodes, $subcmd, $callback); } }elsif($command eq "nodeset") { - $callback->({ errorcode => [1],error => "The input $command is not support for pdu"}); - + $callback->({ errorcode => [1],error => "The input $command is not support for pdu"}); }else{ #reserve for other new command in future } @@ -181,7 +183,7 @@ sub powerpdu { my $callback = shift; my $outletnum = ".1.3.6.1.4.1.2.6.223.8.2.1.0"; - if ($subcmd eq "stat") { + if (($subcmd eq "stat") || ($subcmd eq "state")){ return powerstat($noderange, $callback); } From 355828607e41499ae01ee5ccf24b08eb21568dbd Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Fri, 3 Mar 2017 10:16:18 -0500 Subject: [PATCH 050/187] Modify servce node instructions --- docs/source/advanced/hierarchy/define_service_nodes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/source/advanced/hierarchy/define_service_nodes.rst b/docs/source/advanced/hierarchy/define_service_nodes.rst index aa9b64171..d35427e73 100644 --- a/docs/source/advanced/hierarchy/define_service_nodes.rst +++ b/docs/source/advanced/hierarchy/define_service_nodes.rst @@ -28,6 +28,11 @@ The following table illustrates the cluster being used in this example: | | r2n10 | +----------------------+----------------------+ + +#. Modify ``site`` table attribute to include **service** group's postscripts in compute node definition: :: + + chdef -t site hierarchicalattrs="postscripts" + #. Select the compute nodes that will become service nodes The first node in each rack, ``r1n01`` and ``r2n01``, is selected to become the xCAT service nodes and manage the compute nodes in that rack From ed27765bf12978d5d98f9cacfe9a698abf5ba223 Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Fri, 3 Mar 2017 09:30:28 -0800 Subject: [PATCH 051/187] fix indentation (tabs instead of spaces) --- xCAT-genesis-scripts/bin/dodiscovery | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xCAT-genesis-scripts/bin/dodiscovery b/xCAT-genesis-scripts/bin/dodiscovery index 5bb3bb894..6d20ba9da 100755 --- a/xCAT-genesis-scripts/bin/dodiscovery +++ b/xCAT-genesis-scripts/bin/dodiscovery @@ -73,10 +73,10 @@ if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86 else MTM=`cat /sys/devices/virtual/dmi/id/product_name|awk -F'[' '{print $2}'|awk -F']' '{print $1}'` if [ -z "$MTM" ]; then - FRU=`ipmitool fru print 0` - if [ $? -eq 0 ]; then - MTM=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {m=$2} /Product Name/ {n=$2} END {print m":"n}'` - fi + FRU=`ipmitool fru print 0` + if [ $? -eq 0 ]; then + MTM=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {m=$2} /Product Name/ {n=$2} END {print m":"n}'` + fi fi SERIAL=`cat /sys/devices/virtual/dmi/id/product_serial` fi From 97057c3224f6a5833c1d09ffb0e6fa733324a277 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Mon, 13 Feb 2017 16:07:09 -0500 Subject: [PATCH 052/187] Add instructions for when compute nodes are services and replaced --- .../compute_node/index.rst | 1 + .../compute_node/replace/index.rst | 7 ++++ .../compute_node/replace/openpower.rst | 38 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 docs/source/advanced/cluster_maintenance/compute_node/replace/index.rst create mode 100644 docs/source/advanced/cluster_maintenance/compute_node/replace/openpower.rst diff --git a/docs/source/advanced/cluster_maintenance/compute_node/index.rst b/docs/source/advanced/cluster_maintenance/compute_node/index.rst index 6199699e6..87bc1c733 100644 --- a/docs/source/advanced/cluster_maintenance/compute_node/index.rst +++ b/docs/source/advanced/cluster_maintenance/compute_node/index.rst @@ -5,3 +5,4 @@ Compute Node :maxdepth: 2 changing_hostname_ip.rst + replace/index.rst diff --git a/docs/source/advanced/cluster_maintenance/compute_node/replace/index.rst b/docs/source/advanced/cluster_maintenance/compute_node/replace/index.rst new file mode 100644 index 000000000..7346fb246 --- /dev/null +++ b/docs/source/advanced/cluster_maintenance/compute_node/replace/index.rst @@ -0,0 +1,7 @@ +Replacing Nodes +=============== + +.. toctree:: + :maxdepth: 2 + + openpower.rst diff --git a/docs/source/advanced/cluster_maintenance/compute_node/replace/openpower.rst b/docs/source/advanced/cluster_maintenance/compute_node/replace/openpower.rst new file mode 100644 index 000000000..6e17f9947 --- /dev/null +++ b/docs/source/advanced/cluster_maintenance/compute_node/replace/openpower.rst @@ -0,0 +1,38 @@ +OpenPower Nodes +=============== + + +When compute nodes are physically replaced in the frame, leverage xCAT to re-discover the compute nodes. The following guide can be used for: + + * IBM OpenPower S822LC for HPC + + +#. Identify the machine(s) to be replaced: ``frame10cn02``. + +#. [**Optional**] It's recommended to set the BMC IP address back to DHCP, if it was set to STATIC. :: + + rspconfig frame10cn02 ip=dhcp + +#. Set the outgoing machine to ``offline`` and remove attributes of the machine: :: + + nodeset frame10cn02 offline + chdef frame10cn02 mac="" + +#. If using **MTMS**-based discovery, fill in the Model-Type and Serial Number for the machine: :: + + chdef frame10cn02 mtm=8335-GTB serial= + +#. If using **SWITCH**-based discovery, go on to the next step. The ``switch`` and ``switch-port`` should already be set in the compute node definition. + + Node attributes will be replaced during the discovery process (mtm, serial, mac, etc.) + +#. Search for the new BMC in the open range: :: + + bmcdiscover --range -w -z + +#. When the BMC is found, start the discovery with the following commands: :: + + rsetboot /node-8335.* net + rpower /node-8335.* boot + + From 1755412bb05e503d57008f3e479afd63976b2995 Mon Sep 17 00:00:00 2001 From: chenglch Date: Mon, 6 Mar 2017 11:02:08 +0800 Subject: [PATCH 053/187] Add work aroud to replace sendmsg which is undefine method This is a techenique debet that the callback is not transfered to the Template library correctly, this fix just print error message to syslog. temp-fix: #2557 --- xCAT-server/lib/perl/xCAT/Template.pm | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index 2b72c6e39..06dc55b2b 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -16,6 +16,7 @@ use xCAT::Utils; use xCAT::TableUtils; use xCAT::NetworkUtils; use xCAT::PasswordUtils; +use xCAT::MsgUtils; use XML::Simple; BEGIN @@ -852,7 +853,10 @@ sub windows_join_data { } unless ($adminuser and $adminpass) { my $passtab = xCAT::Table->new('passwd', -create => 0); - unless ($passtab) { sendmsg([ 1, "Error authenticating to Active Directory" ], $node); return; } + unless ($passtab) { + xCAT::MsgUtils->message("SE", "[ERROR]$node: Error authenticating to Active Directory"); + return; + } my @adpents = $passtab->getAttribs({ key => 'activedirectory' }, [ 'username', 'password', 'authdomain' ]); my $adpent; foreach $adpent (@adpents) { @@ -1411,7 +1415,10 @@ sub machinepassword { $ENV{KRB5CCNAME} = "/tmp/xcat/krbcache.$realm.$$"; unless ($loggedrealms{$realm}) { my $passtab = xCAT::Table->new('passwd', -create => 0); - unless ($passtab) { sendmsg([ 1, "Error authenticating to Active Directory" ], $node); return; } + unless ($passtab) { + xCAT::MsgUtils->message("SE", "[ERROR]$node: Error authenticating to Active Directory"); + return; + } my @adpents = $passtab->getAttribs({ key => 'activedirectory' }, [ 'username', 'password', 'authdomain' ]); my $adpent; my $username; @@ -1452,7 +1459,7 @@ sub machinepassword { } } unless ($server) { - sendmsg([ 1, "Unable to determine a directory server to communicate with, try site.directoryserver" ]); + xCAT::MsgUtils->message("SE", "[ERROR]Unable to determine a directory server to communicate with, try site.directoryserver"); return; } } @@ -1589,7 +1596,7 @@ sub crydb $kp{$k} = $v if defined($k); } return \%kp if %kp; - sendmsg([ 1, "Unable to parse password parameters $key" ]); + xCAT::MsgUtils->message("SE", "[ERROR]Unable to parse password parameters $key"); return undef; }; $kp = $get_query_map->($key); From 7dc91e22f80bd78aad727ec74dfc83e5ecc7e117 Mon Sep 17 00:00:00 2001 From: XuWei Date: Mon, 6 Mar 2017 03:09:24 -0500 Subject: [PATCH 054/187] change rinv link and response --- xCAT-server/lib/xcat/plugins/openbmc.pm | 127 +++++++----------------- 1 file changed, 37 insertions(+), 90 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 31bec809a..aa807a266 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -34,10 +34,11 @@ use JSON; sub handled_commands { return { rpower => 'nodehm:mgt', - rinv => 'nodehm:mgt', + rinv => 'nodehm:mgt', }; } +my $pre_url = "/org/openbmc"; #------------------------------------------------------- # The hash table to store method and url for request, @@ -76,31 +77,17 @@ my %status_info = ( }, RPOWER_STATUS_REQUEST => { method => "GET", - init_url => "/org/openbmc/settings/host0", + init_url => "$pre_url/settings/host0", }, RPOWER_STATUS_RESPONSE => { process => \&rpower_response, }, - RINV_MTHBRD_REQUEST => { + RINV_REQUEST => { method => "GET", - init_url => "/org/openbmc/inventory/system/chassis/motherboard", + init_url => "$pre_url/inventory/enumerate", }, - RINV_MTHBRD_RESPONSE => { - process => \&rinv_response, - }, - RINV_CPU_REQUEST => { - method => "GET", - init_url => "/org/openbmc/inventory/system/chassis/motherboard/", - }, - RINV_CPU_RESPONSE => { - process => \&rinv_response, - }, - RINV_DIMM_REQUEST => { - method => "GET", - init_url => "/org/openbmc/inventory/system/chassis/motherboard/", - }, - RINV_DIMM_RESPONSE => { + RINV_RESPONSE => { process => \&rinv_response, }, ); @@ -119,7 +106,6 @@ my %status_info = ( cur_url => "", method => "", back_urls => (), - $src => "", }, ); @@ -268,11 +254,11 @@ sub parse_args { my $subcommand = $ARGV[0]; -# now, only support status, delete when other command supported -if ($subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat") { - return ([ 1, "Only support status check currently" ]) -} -#---------------------------------------------------------------- + # now, only support status, delete when other command supported + if ($subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat") { + return ([ 1, "Only support status check currently" ]) + } + #---------------------------------------------------------------- if ($subcommand eq "on") { $next_status{LOGIN_RESPONSE} = "RPOWER_ON_REQUEST"; @@ -306,21 +292,12 @@ if ($subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat" my $subcommand = $ARGV[0]; - if ($subcommand eq "cpu") { - $next_status{LOGIN_RESPONSE} = "RINV_CPU_REQUEST"; - $next_status{RINV_CPU_REQUEST} = "RINV_CPU_RESPONSE"; - } elsif ($subcommand eq "dimm") { - $next_status{LOGIN_RESPONSE} = "RINV_DIMM_REQUEST"; - $next_status{RINV_DIMM_REQUEST} = "RINV_DIMM_RESPONSE"; - } elsif ($subcommand eq "all") { - $next_status{LOGIN_RESPONSE} = "RINV_MTHBRD_REQUEST"; - $next_status{RINV_MTHBRD_REQUEST} = "RINV_MTHBRD_RESPONSE"; - $next_status{RINV_MTHBRD_RESPONSE} = "RINV_CPU_REQUEST"; - $next_status{RINV_CPU_REQUEST} = "RINV_CPU_RESPONSE"; - $next_status{RINV_CPU_RESPONSE} = "RINV_DIMM_REQUEST"; - $next_status{RINV_DIMM_REQUEST} = "RINV_DIMM_RESPONSE"; + if ($subcommand eq "cpu" or $subcommand eq "dimm" or $subcommand eq "bios" or $subcommand eq "all") { + $next_status{LOGIN_RESPONSE} = "RINV_REQUEST"; + $next_status{RINV_REQUEST} = "RINV_RESPONSE"; + $status_info{RINV_RESPONSE}{argv} = "$subcommand"; } else { - return ([ 1, "Only 'cpu','dimm','all' are supportted at the same time" ]); + return ([ 1, "Only 'cpu','dimm', 'bios','all' are supportted at the same time" ]); } } @@ -535,65 +512,35 @@ sub rinv_response { my $response_info = decode_json $response->content; - my %rinv_response = ( - RINV_CPU_RESPONSE => { - map_str => "cpu", - repeat => "RINV_CPU_REQUEST", - }, - RINV_DIMM_RESPONSE => { - map_str => "dimm", - repeat => "RINV_DIMM_REQUEST", - }, - - ); + my $grep_string = $status_info{RINV_RESPONSE}{argv}; + my $src; + my $content_info; - my $grep_string = $rinv_response{$node_info{$node}{cur_status}}{map_str}; - my $repeat_status = $rinv_response{$node_info{$node}{cur_status}}{repeat}; - - if ($node_info{$node}{cur_status} ne "RINV_MTHBRD_RESPONSE") { - if (ref($response_info->{data}) eq "ARRAY") { - foreach my $rsp_url (@{$response_info->{data}}) { - if ($rsp_url =~ /\/$grep_string/) { - push @{ $node_info{$node}{back_urls} }, $rsp_url; - } - } - - $node_info{$node}{cur_url} = shift @{ $node_info{$node}{back_urls} }; - $node_info{$node}{cur_status} = $repeat_status; - $node_info{$node}{src} = basename $node_info{$node}{cur_url}; - gen_send_request($node); - } elsif (ref($response_info->{data}) eq "HASH") { - my $cpu_info; - foreach my $key (keys %{$response_info->{data}}) { - $cpu_info = uc ($node_info{$node}{src}) . " " . $key . " : " . ${$response_info->{data}}{$key}; - xCAT::SvrUtils::sendmsg("$cpu_info", $callback, $node); - } - - if (@{ $node_info{$node}{back_urls} }) { - $node_info{$node}{cur_url} = shift @{ $node_info{$node}{back_urls} }; - $node_info{$node}{cur_status} = $repeat_status; - $node_info{$node}{src} = basename $node_info{$node}{cur_url}; - gen_send_request($node); + foreach my $key_url (keys %{$response_info->{data}}) { + if ($grep_string eq "all" or $key_url =~ /\/$grep_string/) { + if ($key_url =~ /\/(cpu\d*)\/(\w+)/) { + $src = "$1 $2"; } else { - if ($next_status{ $node_info{$node}{cur_status} }) { - delete $node_info{$node}{cur_url}; - delete $node_info{$node}{src}; - gen_send_request($node); - } else { - $wait_node_num--; - } + $src = basename $key_url; + } + + my %content = %{ ${ $response_info->{data} }{$key_url} }; + foreach my $key (keys %content) { + $content_info = uc ($src) . " " . $key . " : " . $content{$key}; + xCAT::SvrUtils::sendmsg("$content_info", $callback, $node); } } + } + + if ($next_status{ $node_info{$node}{cur_status} }) { + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + gen_send_request($node); + } else { + $wait_node_num--; } - #print Dumper(%node_info) ."\n"; return; } 1; - - - - - From c2454c0133779b5e7f36856cc95ccd0ab0c4ed96 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Mon, 6 Mar 2017 10:59:36 -0500 Subject: [PATCH 055/187] Add --system when creating user and group --- xCAT-server/sbin/xcatconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index fe6244c3b..04b4e6e2f 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -1542,7 +1542,7 @@ sub genCredentials my ($cmd, $outref, $rc); $rc = getgrnam($user); if (!$rc) { - $cmd = "groupadd $user"; + $cmd = "groupadd --system $user"; $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) { xCAT::MsgUtils->message('E', "$cmd failed"); @@ -1551,7 +1551,7 @@ sub genCredentials } $rc = getpwnam($user); if (!$rc) { - $cmd = "useradd -g $user -s /bin/bash -d /home/$user -m $user"; + $cmd = "useradd --system -g $user -s /bin/bash -d /home/$user -m $user"; $outref = xCAT::Utils->runcmd("$cmd", 0); if ($::RUNCMD_RC != 0) { xCAT::MsgUtils->message('E', "$cmd failed"); From e2ebc6a04968038e9e69c6fcd0ae43707c001387 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Tue, 7 Mar 2017 13:02:52 +0800 Subject: [PATCH 056/187] Add testcase for actual package installation testing against `updatenode -S` --- xCAT-test/autotest/testcase/updatenode/cases2 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/updatenode/cases2 b/xCAT-test/autotest/testcase/updatenode/cases2 index ef55f2615..06201a066 100644 --- a/xCAT-test/autotest/testcase/updatenode/cases2 +++ b/xCAT-test/autotest/testcase/updatenode/cases2 @@ -1,6 +1,18 @@ start:updatenode_S -check:rc==0 cmd:updatenode $$CN -S >/tmp/updatenode.S.out cmd:grep 'Running of Software Maintenance has completed' /tmp/updatenode.S.out check:rc==0 end + +start:updatenode_S_gcc +cmd:lsdef $$CN -i provmethod | tail -n 1 | cut -d= -f2 | xargs lsdef -t osimage -i pkglist | tail -n 1 | cut -d= -f2 >/tmp/pkglist.filename +cmd:mv `cat /tmp/pkglist.filename` `cat /tmp/pkglist.filename`.save +cmd:cp `cat /tmp/pkglist.filename`.save `cat /tmp/pkglist.filename` +cmd:echo gcc >>`cat /tmp/pkglist.filename` +cmd:updatenode $$CN -S >/tmp/updatenode.S.out +cmd:grep 'postscript: ospkgs exited with code 0' /tmp/updatenode.S.out +check:rc==0 +cmd:grep 'Running of Software Maintenance has completed' /tmp/updatenode.S.out +check:rc==0 +cmd:mv `cat /tmp/pkglist.filename`.save `cat /tmp/pkglist.filename` +end From 190b218cba9cd295957aca06ff34cc6db6a553c8 Mon Sep 17 00:00:00 2001 From: XuWei Date: Tue, 7 Mar 2017 00:57:56 -0500 Subject: [PATCH 057/187] add more print message --- xCAT-server/lib/xcat/plugins/openbmc.pm | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index aa807a266..e9c96ad21 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -105,7 +105,7 @@ my %status_info = ( cur_status => "LOGIN_REQUEST", cur_url => "", method => "", - back_urls => (), + back_urls => (), }, ); @@ -216,6 +216,7 @@ sub process_request { $handle_id = xCAT::OPENBMC->new($async, $login_url, $content); $handle_id_node{$handle_id} = $node; $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + print "$node: POST $login_url -d $content\n"; } while (1) { @@ -399,6 +400,7 @@ sub gen_send_request { my $handle_id = xCAT::OPENBMC->send_request($async, $method, $request_url, $content); $handle_id_node{$handle_id} = $node; $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; + print "$node: $method $request_url\n"; return; } @@ -420,14 +422,23 @@ sub deal_with_response { my $response = shift; my $node = $handle_id_node{$handle_id}; + delete $handle_id_node{$handle_id}; + if ($response->status_line ne "200 OK") { my $response_info = decode_json $response->content; - xCAT::SvrUtils::sendmsg($response_info->{'data'}->{'description'}, $callback, $node); + my $error; + if ($response_info->{'data'}->{'description'} =~ /path or object not found: (.+)/) { + $error = "path or object not found $1"; + } else { + $error = $response_info->{'data'}->{'description'}; + } + xCAT::SvrUtils::sendmsg([1, $error], $callback, $node); $wait_node_num--; return; } - delete $handle_id_node{$handle_id}; + print "$node: " . lc ($node_info{$node}{cur_status}) . " " . $response->status_line . "\n"; + $status_info{ $node_info{$node}{cur_status} }->{process}->($node, $response); return; From 02d3816dfd705afa146fd2a69933e9a93a04a7ee Mon Sep 17 00:00:00 2001 From: bybai Date: Tue, 7 Mar 2017 01:35:53 -0500 Subject: [PATCH 058/187] find mtu from networks table --- xCAT/postscripts/configeth | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index 2409b61ce..51631a977 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -420,18 +420,6 @@ elif [ "$1" = "-s" ];then str_inst_mask='' str_inst_gateway='' str_inst_mtu='' - str_inst_network=`echo $NICNETWORKS |awk -F${str_inst_nic}'!' '{print $2}' | awk -F'|' '{print $1}'` - num_index=1 - while [ $num_index -le $NETWORKS_LINES ];do - eval str_tmp=\$NETWORKS_LINE$num_index - str_tmp_name=`echo $str_tmp | awk -F'netname=' '{print $2}' | awk -F'|' '{print $1}'` - if [ "$str_tmp_name" = "$str_inst_network" ];then - str_inst_mtu=`echo $str_tmp | awk -F'mtu=' '{print $2}' | awk -F'|' '{print $1}'` - break - fi - num_index=$((num_index+1)) - done - if [ "$str_os_type" = "aix" ];then logger -t xcat -p local4.err "configeth: aix does not support -s flag" @@ -518,7 +506,20 @@ elif [ "$1" = "-s" ];then exit 0 fi - #get extra configration parameters for each nic + str_inst_net=$(v4calcnet $str_inst_ip $str_inst_mask) + num_index=1 + while [ $num_index -le $NETWORKS_LINES ];do + eval str_tmp=\$NETWORKS_LINE$num_index + str_tmp_name=`echo $str_tmp | awk -F'net=' '{print $2}' | awk -F'|' '{print $1}'` + if [ "$str_tmp_name" = "$str_inst_net" ];then + str_inst_mtu=`echo $str_tmp | awk -F'mtu=' '{print $2}' | awk -F'|' '{print $1}'` + break + fi + num_index=$((num_index+1)) + done + + + #get extra configration parameters for each nic #echo "str_inst_nic=$str_inst_nic, str_inst_ip=$str_inst_ip" get_nic_extra_params $str_inst_nic "$NICEXTRAPARAMS" if [ ${#array_nic_params[@]} -gt 0 ]; then @@ -632,7 +633,9 @@ elif [ "$1" = "-s" ];then fi fi fi + ifup $str_inst_nic + exit 0 fi From 833654d0ffbdec26634224e3c3fa7efc65b0b43c Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Tue, 7 Mar 2017 09:40:40 -0500 Subject: [PATCH 059/187] Add security bulleting for 02/16/17 openssl advisory --- .../source/security/2017/20170216_openssl.rst | 25 +++++++++++++++++++ docs/source/security/2017/index.rst | 1 + 2 files changed, 26 insertions(+) create mode 100644 docs/source/security/2017/20170216_openssl.rst diff --git a/docs/source/security/2017/20170216_openssl.rst b/docs/source/security/2017/20170216_openssl.rst new file mode 100644 index 000000000..9f430f713 --- /dev/null +++ b/docs/source/security/2017/20170216_openssl.rst @@ -0,0 +1,25 @@ +2017-02-16 - OpenSSL Vulnerabilities +==================================== + +*Feb 16, 2017*, OpenSSL announced the following security advisories: https://www.openssl.org/news/secadv/20170216.txt + + +Advisory CVEs +------------- + +* CVE-2017-3733 - **Encrypt-Then-Mac renegotiation crash** (Severity:High) + + OpenSSL 1.1.0 users should upgrade to 1.1.0e + + This issue does not affect OpenSSL version 1.0.2. + +Please see the security bulletin above for patch, upgrade, or suggested work around information. + +Action +------ + +xCAT uses OpenSSL for client-server communication but **does not** ship it. + +It is highly recommended to keep your OpenSSL levels up-to-date with the indicated versions in the security bulletins to prevent any potential security threats. Obtain the updated software packages from your Operating system distribution channels. + + diff --git a/docs/source/security/2017/index.rst b/docs/source/security/2017/index.rst index 7c5b764ff..588d8c30e 100644 --- a/docs/source/security/2017/index.rst +++ b/docs/source/security/2017/index.rst @@ -4,4 +4,5 @@ .. toctree:: :maxdepth: 1 + 20170216_openssl.rst 20170126_openssl.rst From 6beecc62f527f9dfaa2858878ff2756296a9dd37 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Wed, 8 Mar 2017 03:56:22 -0500 Subject: [PATCH 060/187] modify osdeploy test cases --- xCAT-test/autotest/testcase/osdeploy/cases0 | 255 ++++++++++++++++++++ 1 file changed, 255 insertions(+) diff --git a/xCAT-test/autotest/testcase/osdeploy/cases0 b/xCAT-test/autotest/testcase/osdeploy/cases0 index bb76c2f3b..dded53d44 100644 --- a/xCAT-test/autotest/testcase/osdeploy/cases0 +++ b/xCAT-test/autotest/testcase/osdeploy/cases0 @@ -68,5 +68,260 @@ check:rc==0 cmd:rm -rf /tmp/osdeploy.test check:rc==0 end +start:osdeploy_n_invalidnode +description: osdeploy -n node invalid +cmd:test=`lsdef test_node`;if [ $test eq 0 ]; then lsdef -l test_node -z >/tmp/node.standa ;rmdef test_node;fi +check:rc==0 +cmd:xcatprobe osdeploy -n test_node +check:rc==1 +check:output~=without node definition +cmd:if [ -e /tmp/node.standa ]; then cat /tmp/node.standa | mkdef -z; rm -rf /tmp/node.standa; fi +check:rc==0 +end +start:osdeploy_n_p_invalid +description:osdeploy -n node -p invalid parameter +cmd:xcatprobe osdeploy -n $$CN -p dsdf +check:rc==1 +check:output~=Usage: +check:output~="'compact': Elapsed time of provision for each node." +check:output~="'phase' : Elapsed time for DHCP, INSTALL, POSTSCRIPTS and POSTBOOTSCRIPTS stages, and time for whole provis" +check:output~="'origin' : Show origin start time of each stage." +end + +start:osdeploy_n_r_invalid +description:osdeploy -n node -r invalid parameter +cmd:xcatprobe osdeploy -n $$CN -r dadf +check:rc==1 +check:output~=Usage: +check:output~="'compact': Elapsed time of provision for each node." +check:output~="'phase' : Elapsed time for DHCP, INSTALL, POSTSCRIPTS and POSTBOOTSCRIPTS stages, and time for whole provis" +check:output~="'origin' : Show origin start time of each stage." +end + +start:osdeploy_n_t_invalid +description:osdeploy -n node -t invalid parameter +cmd:xcatprobe osdeploy -n $$CN -t dadf +check:rc==1 +check:output~=Usage: +check:output~="'compact': Elapsed time of provision for each node." +check:output~="'phase' : Elapsed time for DHCP, INSTALL, POSTSCRIPTS and POSTBOOTSCRIPTS stages, and time for whole provis" +check:output~="'origin' : Show origin start time of each stage." +end + +start:osdeploy_n_p_origin +description: osdeploy -n -p origin node to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:xcatprobe osdeploy -n $$CN -p origin >> /tmp/osdeploy.test & +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep OK +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Start Time for Stage" +check:rc==0 +cmd:cat /tmp/osdeploy.test | awk '{print $4}'|grep RPOWER && cat /tmp/osdeploy.test | awk '{print $6}'|grep DHCP && cat /tmp/osdeploy.test | awk '{print $8}'|grep BOOTLOADER && cat /tmp/osdeploy.test | awk '{print $10}'|grep KERNEL && cat /tmp/osdeploy.test | awk '{print $12}' |grep INITRD && cat /tmp/osdeploy.test | awk '{print $14}' |grep INSTALL && cat /tmp/osdeploy.test | awk '{print $16}' |grep POST && cat /tmp/osdeploy.test | awk '{print $18}' |grep POSTBOOT && cat /tmp/osdeploy.test | awk '{print $20}' |grep COMPLET +check:rc==0 +cmd:cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end +start:osdeploy_n_p_origin_r +description: osdeploy -n node -p origin -r to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep OK +check:rc==0 +cmd:xcatprobe osdeploy -n $$CN -p origin -r 1h >> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Start Time for Stage" +check:rc==0 +cmd:cat /tmp/osdeploy.test | awk '{print $4}'|grep RPOWER && cat /tmp/osdeploy.test | awk '{print $6}'|grep DHCP && cat /tmp/osdeploy.test | awk '{print $8}'|grep BOOTLOADER && cat /tmp/osdeploy.test | awk '{print $10}'|grep KERNEL && cat /tmp/osdeploy.test | awk '{print $12}' |grep INITRD && cat /tmp/osdeploy.test | awk '{print $14}' |grep INSTALL && cat /tmp/osdeploy.test | awk '{print $1 +6}' |grep POST && cat /tmp/osdeploy.test | awk '{print $18}' |grep POSTBOOT && cat /tmp/osdeploy.test | awk '{print $20}' |grep COMPLET +check:rc==0 +cmd:cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $4}' |grep -v NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end +start:osdeploy_n_p_origin_r_error +description: osdeploy -n node -p origin -r 1m to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:cat /tmp/osdeploy.test |grep "Without provision process during rollback time window" +check:rc==0 +cmd:xcatprobe osdeploy -n $$CN -p origin -r 1m >> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Without provision process during rollback time window" +check:rc==0 +cmd:cat /tmp/osdeploy.test | awk '{print $4}'|grep RPOWER && cat /tmp/osdeploy.test | awk '{print $6}'|grep DHCP && cat /tmp/osdeploy.test | awk '{print $8}'|grep BOOTLOADER && cat /tmp/osdeploy.test | awk '{print $10}'|grep KERNEL && cat /tmp/osdeploy.test | awk '{print $12}' |grep INITRD && cat /tmp/osdeploy.test | awk '{print $14}' |grep INSTALL && cat /tmp/osdeploy.test | awk '{print $1 +6}' |grep POST && cat /tmp/osdeploy.test | awk '{print $18}' |grep POSTBOOT && cat /tmp/osdeploy.test | awk '{print $20}' |grep COMPLET +check:rc==0 +cmd:cat /tmp/osdeploy.t |grep $$CN |grep -v FAIL |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |grep -v FAIL | awk '{print $6}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |grep -v FAIL |awk '{print $8}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN | grep -v FAIL|awk '{print $10}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |grep -v FAIL |awk '{print $12}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN|grep -v FAIL |awk '{print $14}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |grep -v FAIL|awk '{print $16}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |grep -v FAIL |awk '{print $18}' |grep -v NULL && cat /tmp/osdeploy.t |grep $$CN |awk '{print $20}' |grep -v NULL +check:rc==1 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end + +start:osdeploy_n_p_compact +description: osdeploy -n -p compact node to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:xcatprobe osdeploy -n $$CN -p compact >> /tmp/osdeploy.test & +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep OK +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Provision Time" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep NODE |awk '{print $4}' |grep ELAPSED +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep $$CN |awk '{print $4}' |grep -v NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end +start:osdeploy_n_p_compact_r +description: osdeploy -n -p compact -r node to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:xcatprobe osdeploy -n $$CN -p compact -r 30m >> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep OK +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Provision Time" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep NODE |awk '{print $4}' |grep ELAPSED +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep $$CN |awk '{print $4}' |grep -v NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end +start:osdeploy_n_p_compact_r_error +description: osdeploy -n -p compact -r node error to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:xcatprobe osdeploy -n $$CN -p compact -r 3m >> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Without provision process during rollback time window" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Provision Time" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep NODE |awk '{print $4}' |grep ELAPSED +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep $$CN |grep -v FAIL |awk '{print $4}' |grep NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end + +start:osdeploy_n_p_phase +description: osdeploy -n -p phase node to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:xcatprobe osdeploy -n $$CN -p phase >> /tmp/osdeploy.test & +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep OK +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Time for Phases" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep NODE |awk '{print $4}'|grep SVRBOOT && cat /tmp/osdeploy.test |grep NODE |awk '{print $6}'|grep INSTALL && cat /tmp/osdeploy.test |grep NODE |awk '{print $8}'|grep POST && cat /tmp/osdeploy.test |grep NODE |awk '{print $10}'|grep POSTBOOT && cat /tmp/osdeploy.test |grep NODE |awk '{print $12}'|grep ELAPSED +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $6}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $8}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $10}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $12}' |grep -v NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end +start:osdeploy_n_p_phase_r +description: osdeploy -n -p phase node -r to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:xcatprobe osdeploy -n $$CN -p phase -r 1h >> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep OK +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Time for Phases" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep NODE |awk '{print $4}'|grep SVRBOOT && cat /tmp/osdeploy.test |grep NODE |awk '{print $6}'|grep INSTALL && cat /tmp/osdeploy.test |grep NODE |awk '{print $8}'|grep POST && cat /tmp/osdeploy.test |grep NODE |awk '{print $10}'|grep POSTBOOT && cat /tmp/osdeploy.test |grep NODE |awk '{print $12}'|grep ELAPSED +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep $$CN |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $6}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $8}' +|grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $10}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |awk '{print $12}' |grep -v NULL +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end + +start:osdeploy_n_p_phase_r_error +description: osdeploy -n -p phase node -r error to probe osdeploy +cmd:if [ -e /tmp/osdeploy.test ];then rm -rf /tmp/osdeploy.test*;fi +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN boot +check:rc==0 +cmd:sleep 300 +cmd:a=0;while ! `lsdef -l $$CN|grep status|grep booted >/dev/null`; do sleep 20;((a++));if [ $a -gt 300 ];then break;fi done +cmd:xcatprobe osdeploy -n $$CN -p phase -r 3m >> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Without provision process during rollback time window" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "Time for Phases" +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep NODE |awk '{print $4}'|grep SVRBOOT && cat /tmp/osdeploy.test |grep NODE |awk '{print $6}'|grep INSTALL && cat /tmp/osdeploy.test |grep NODE |awk '{print $8}'|grep POST && cat /tmp/osdeploy.test |grep NODE |awk '{print $10}'|grep POSTBOOT && cat /tmp/osdeploy.test |grep NODE |awk '{print $12}'|grep ELAPSED +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep $$CN |grep -v FAIL |awk '{print $4}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |grep -v FAIl|awk '{print $6}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |grep -v FAIl |awk '{print $8}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |grep -v FAIL |awk '{print $10}' |grep -v NULL && cat /tmp/osdeploy.test |grep $$CN |grep -v FAIL |awk '{print $12}' |grep -v NULL +check:rc==1 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 +end From f9f442a85b0b36e64c2f1170066b31d3f66e9bf5 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Wed, 8 Mar 2017 12:02:22 -0500 Subject: [PATCH 061/187] add support to auto detect beta pegas iso files --- xCAT-server/lib/xcat/plugins/anaconda.pm | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/anaconda.pm b/xCAT-server/lib/xcat/plugins/anaconda.pm index 0fc2da096..237a4e8b7 100644 --- a/xCAT-server/lib/xcat/plugins/anaconda.pm +++ b/xCAT-server/lib/xcat/plugins/anaconda.pm @@ -2218,7 +2218,8 @@ sub copycd unless ($distname) { - print "INFO - Could not find ID=$did in the discinfo database for OS=$desc ARCH=$darch NUM=$dno, attempt to auto-detect...\n"; + print "INFO - Could not find ID=$did in the discinfo database for OS=$desc ARCH=$darch NUM=$dno\n"; + print "INFO - Attempting to auto-detect...\n"; if ($desc =~ /IBM_PowerKVM/) { # check for PowerKVM support @@ -2232,7 +2233,15 @@ sub copycd # RHEL 7.3 description is: Red Hat Enterprise Linux 7.3 # my @rhel_version = split / /, $desc; - $distname = "rhels" . $rhel_version[4]; + # + # auto-detect pegas beta ISOs + # + if ( $rhel_version[4] =~ "Pegas") { + $distname = "rhels" . $rhel_version[5] . "-pegas"; + } + else { + $distname = "rhels" . $rhel_version[4]; + } open($dinfo, $mntpath . "/.treeinfo"); while (<$dinfo>) { chomp($_); @@ -2297,7 +2306,7 @@ sub copycd ); return; } - + print "INFO - detected distname=$distname, arch=$arch\n"; %{$request} = (); #clear request we've got it. my $disccopiedin = 0; From 6c789d24736e1b2d23878a7a64733868374f8fdb Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Wed, 8 Mar 2017 20:28:33 -0500 Subject: [PATCH 062/187] remove stop label in test cases --- xCAT-test/autotest/testcase/installation/SN_setup_case | 1 - .../installation/reg_linux_diskfull_installation_hierarchy | 1 - .../installation/reg_linux_diskless_installation_hierarchy | 1 - 3 files changed, 3 deletions(-) diff --git a/xCAT-test/autotest/testcase/installation/SN_setup_case b/xCAT-test/autotest/testcase/installation/SN_setup_case index 03b800f30..851b06d05 100644 --- a/xCAT-test/autotest/testcase/installation/SN_setup_case +++ b/xCAT-test/autotest/testcase/installation/SN_setup_case @@ -1,6 +1,5 @@ start:SN_setup_case os:Linux -stop:yes cmd:/opt/xcat/share/xcat/tools/autotest/testcase/installation/pre_deploy_sn __GETNODEATTR($$SN,os)__ __GETNODEATTR($$SN,arch)__ check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy index 86ac6d80f..abba79cee 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy @@ -1,6 +1,5 @@ start:reg_linux_diskfull_installation_hierarchy os:Linux -stop:yes cmd:chdef -t node -o $$CN servicenode=$$SN monserver=$$SN nfsserver=$$SN tftpserver=$$SN xcatmaster=$$SN check:rc==0 diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy index 83d12c37a..0bb2aa173 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy @@ -1,6 +1,5 @@ start:reg_linux_diskless_installation_hierarchy os:Linux -stop:yes cmd:chdef -t node -o $$CN servicenode=$$SN monserver=$$SN nfsserver=$$SN tftpserver=$$SN xcatmaster=$$SN check:rc==0 From ab1d1ba5522bdd393acaa8bf24b5cebb8f6cc6f3 Mon Sep 17 00:00:00 2001 From: chenglch Date: Wed, 8 Mar 2017 21:48:53 -0500 Subject: [PATCH 063/187] Update man page for password cryptmethod close-issue: #2558 related-patch: #2559 --- perl-xCAT/xCAT/Schema.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 8a0639ea4..c6617baa2 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -845,8 +845,8 @@ passed as argument rather than by table value', descriptions => { key => 'The type of component this user/pw is for. Valid values: blade (management module), ipmi (BMC), system (nodes), omapi (DHCP), hmc, ivm, cec, frame, switch.', username => 'The default userid for this type of component', - password => 'The default password for this type of component', - cryptmethod => 'Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default.', + password => 'The default password for this type of component. On Linux, a crypted form could be provided. Hashes starting with $1$, $5$ and $6$ (md5, sha256 and sha512 respectively) are supported.', + cryptmethod => 'Indicates the method to use to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default to encrypt plain-text passwords.', authdomain => 'The domain in which this entry has meaning, e.g. specifying different domain administrators per active directory domain', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", From 96f40904e3072d27b5f66ab452391b300373d268 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Thu, 9 Mar 2017 01:24:18 -0500 Subject: [PATCH 064/187] update for comments --- xCAT-test/autotest/testcase/pdu/case0 | 41 +++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/xCAT-test/autotest/testcase/pdu/case0 b/xCAT-test/autotest/testcase/pdu/case0 index 07bfbed10..6e4bb26c2 100644 --- a/xCAT-test/autotest/testcase/pdu/case0 +++ b/xCAT-test/autotest/testcase/pdu/case0 @@ -1,5 +1,5 @@ start:lsdef_pdu_object -description:list pdu object and it's attribute +degscription:list pdu object and it's attribute cmd:lsdef -h check:output=~pdu cmd:mkdef $$PDU mgt=pdu nodetype=pdu groups=pdu @@ -136,6 +136,8 @@ cmd:oldpdu=`lsdef $$CN |grep pdu|awk -F= '{print $2}'`;chdef $$CN pdu=$$PDU:$$PO check:rc==0 cmd:lsdef $$CN -i pdu check:rc==0 +cmd:rpower $$CN stat |awk -F: '{print $2}' > /tmp/cnstat +check:rc==0 cmd:rpower $$CN pdustat check:rc==0 check:output=~$$CN: $$PDU outlet $$PORT is @@ -146,13 +148,40 @@ cmd:rpower $$CN pduon check:rc==0 check:output=~$$CN: $$PDU outlet $$PORT is on cmd:oldpdu=`cat /tmp/pduvalue`;chdef $$CN pdu=$oldpdu +cmd:if grep on /tmp/cnstat; then rpower $$CN on;fi +check:rc==0 cmd:rmdef $$PDU check:rc==0 cmd:rm -rf /tmp/pduvalue +cmd:rm -rf /tmp/cnstat end - - - - - +start:pdu_bad_config +description:test bad config with pdu +cmd:mkdef $$PDU groups=pdu ip=$$PDUIP mgt=pdu nodetype=pdu +check:rc==0 +cmd:makehosts $$PDU +check:rc==0 +cmd:grep $$PDUIP /etc/hosts +check:rc==0 +cmd:snmpwalk -v1 -cpublic -mALL $$PDU .1.3.6.1.2.1.1 +check:rc==0 +cmd:lsdef $$CN |grep pdu|awk -F= '{print $2}' > /tmp/pduvalue +cmd:chdef $$CN pdu=$$PDU:1000 +check:rc==0 +cmd:lsdef $$CN -i pdu +cmd:rpower $$CN pdustat +check:rc!=0 +check:output=~Error +cmd:rpower $$CN pduon +check:rc!=0 +check:output=~Error +cmd:rpower $$CN pduoff +check:rc!=0 +check:output=~Error +cmd:oldpdu=`cat /tmp/pduvalue`;chdef $$CN pdu=$oldpdu +cmd:rpower $$CN pduof +check:rc!=0 +check:outpu=~Unsupported command +cmd:rmdef $$PDU +end From d46bbb37e507fa73eeec9a89ef6a99ffb78d0c0c Mon Sep 17 00:00:00 2001 From: XuWei Date: Thu, 9 Mar 2017 03:18:56 -0500 Subject: [PATCH 065/187] add power on/off --- xCAT-server/lib/xcat/plugins/openbmc.pm | 52 ++++++++++++++----------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index e9c96ad21..45e1c28d2 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -56,14 +56,14 @@ my %status_info = ( RPOWER_ON_REQUEST => { method => "POST", - init_url => "/power/on", + init_url => "$pre_url/control/chassis0/action/powerOn", }, RPOWER_ON_RESPONSE => { process => \&rpower_response, }, RPOWER_OFF_REQUEST => { method => "POST", - init_url => "/power/off", + init_url => "$pre_url/control/chassis0/action/powerOff", }, RPOWER_OFF_RESPONSE => { process => \&rpower_response, @@ -77,6 +77,7 @@ my %status_info = ( }, RPOWER_STATUS_REQUEST => { method => "GET", + #init_url => "$pre_url/state/host0", init_url => "$pre_url/settings/host0", }, RPOWER_STATUS_RESPONSE => { @@ -216,7 +217,7 @@ sub process_request { $handle_id = xCAT::OPENBMC->new($async, $login_url, $content); $handle_id_node{$handle_id} = $node; $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; - print "$node: POST $login_url -d $content\n"; + print "$node: DEBUG POST $login_url -d $content\n"; } while (1) { @@ -255,12 +256,6 @@ sub parse_args { my $subcommand = $ARGV[0]; - # now, only support status, delete when other command supported - if ($subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat") { - return ([ 1, "Only support status check currently" ]) - } - #---------------------------------------------------------------- - if ($subcommand eq "on") { $next_status{LOGIN_RESPONSE} = "RPOWER_ON_REQUEST"; $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; @@ -270,13 +265,13 @@ sub parse_args { } elsif ($subcommand eq "status" or $subcommand eq "state" or $subcommand eq "stat") { $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; - } elsif ($subcommand eq "boot") { - $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; - $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; - $next_status{RPOWER_STATUS_RESPONSE}{OFF} = "RPOWER_ON_REQUEST"; - $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; - $next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST"; - $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; + # } elsif ($subcommand eq "boot") { + # $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; + # $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; + # $next_status{RPOWER_STATUS_RESPONSE}{OFF} = "RPOWER_ON_REQUEST"; + # $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; + # $next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST"; + # $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; } else { return ([ 1, "$subcommand is not supported for rpower" ]); } @@ -382,7 +377,7 @@ sub gen_send_request { my $node = shift; my $method; my $request_url; - my $content; + my $content = '{"data": [] }';; if ($node_info{$node}{method}) { $method = $node_info{$node}{method}; @@ -400,7 +395,14 @@ sub gen_send_request { my $handle_id = xCAT::OPENBMC->send_request($async, $method, $request_url, $content); $handle_id_node{$handle_id} = $node; $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; - print "$node: $method $request_url\n"; + + my $debug_info; + if ($method eq "GET") { + $debug_info = "$node: DEBUG $method $request_url"; + } else { + $debug_info = "$node: DEBUG $method $request_url -d $content"; + } + print "$debug_info\n"; return; } @@ -425,19 +427,23 @@ sub deal_with_response { delete $handle_id_node{$handle_id}; if ($response->status_line ne "200 OK") { - my $response_info = decode_json $response->content; my $error; - if ($response_info->{'data'}->{'description'} =~ /path or object not found: (.+)/) { - $error = "path or object not found $1"; + if ($response->status_line eq "503 Service Unavailable") { + $error = "Service Unavailable"; } else { - $error = $response_info->{'data'}->{'description'}; + my $response_info = decode_json $response->content; + if ($response_info->{'data'}->{'description'} =~ /path or object not found: (.+)/) { + $error = "path or object not found $1"; + } else { + $error = $response_info->{'data'}->{'description'}; + } } xCAT::SvrUtils::sendmsg([1, $error], $callback, $node); $wait_node_num--; return; } - print "$node: " . lc ($node_info{$node}{cur_status}) . " " . $response->status_line . "\n"; + print "$node: DEBUG " . lc ($node_info{$node}{cur_status}) . " " . $response->status_line . "\n"; $status_info{ $node_info{$node}{cur_status} }->{process}->($node, $response); From a2b365dc75d428635a36f08f876f534226a4abcb Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 9 Mar 2017 04:12:47 -0500 Subject: [PATCH 066/187] fix hostname linux in statelite sles12.2 --- .../share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh b/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh index 5b5aaf109..e1c7f40d8 100755 --- a/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh +++ b/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh @@ -134,12 +134,7 @@ function getdevfrommac() { done } - -for lf in /tmp/dhclient.*.lease; do - netif=${lf#*.} - netif=${netif%.*} - cp $lf "$NEWROOT/var/lib/dhclient/dhclient-$netif.leases" -done +echo `hostname -s` > $NEWROOT/etc/HOSTNAME if [ ! -z "$ifname" ]; then MACX=${ifname#*:} From 97018513c1eef7dda20e67c74153cf2cb481476d Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 9 Mar 2017 04:27:52 -0500 Subject: [PATCH 067/187] polish code --- .../xcat/netboot/sles/dracut_033/xcat-prepivot.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh b/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh index e1c7f40d8..c68ced041 100755 --- a/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh +++ b/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh @@ -134,7 +134,15 @@ function getdevfrommac() { done } -echo `hostname -s` > $NEWROOT/etc/HOSTNAME +for lf in /tmp/dhclient.*.lease; do + netif=${lf#*.} + netif=${netif%.*} + cp $lf "$NEWROOT/var/lib/dhclient/dhclient-$netif.leases" +done + +if [ -f $NEWROOT/etc/HOSTNAME ]; then + echo `hostname -s` > $NEWROOT/etc/HOSTNAME +fi if [ ! -z "$ifname" ]; then MACX=${ifname#*:} From b647f0b53f83227c1fe6ac5fe15c9e10b6e40ae8 Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 9 Mar 2017 05:17:21 -0500 Subject: [PATCH 068/187] change HOSTNAME to hostname --- .../share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh b/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh index c68ced041..b5114ef43 100755 --- a/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh +++ b/xCAT-server/share/xcat/netboot/sles/dracut_033/xcat-prepivot.sh @@ -140,8 +140,8 @@ for lf in /tmp/dhclient.*.lease; do cp $lf "$NEWROOT/var/lib/dhclient/dhclient-$netif.leases" done -if [ -f $NEWROOT/etc/HOSTNAME ]; then - echo `hostname -s` > $NEWROOT/etc/HOSTNAME +if [ -f $NEWROOT/etc/hostname ]; then + echo `hostname -s` > $NEWROOT/etc/hostname fi if [ ! -z "$ifname" ]; then From 5fccdec63e99fd0d395e14e3f26b4a9a20354296 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Thu, 9 Mar 2017 06:41:15 -0500 Subject: [PATCH 069/187] modify osdeploy testcases --- xCAT-test/autotest/testcase/osdeploy/cases0 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xCAT-test/autotest/testcase/osdeploy/cases0 b/xCAT-test/autotest/testcase/osdeploy/cases0 index dded53d44..e1b366cdc 100644 --- a/xCAT-test/autotest/testcase/osdeploy/cases0 +++ b/xCAT-test/autotest/testcase/osdeploy/cases0 @@ -53,6 +53,12 @@ cmd:cat /tmp/osdeploy.test |grep "Without provision process during rollback time check:rc==0 cmd:rm -rf /tmp/osdeploy.test check:rc==0 +cmd:xcatprobe osdeploy -n $$CN -r 2h5m>> /tmp/osdeploy.test +check:rc==0 +cmd:cat /tmp/osdeploy.test |grep "All nodes provisioned successfully"|grep "OK" +check:rc==0 +cmd:rm -rf /tmp/osdeploy.test +check:rc==0 end start:osdeploy_n_t From 973d71517b2a8309e24867ba5488474c9ebed697 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Tue, 7 Mar 2017 11:47:59 -0500 Subject: [PATCH 070/187] Make running nodeset offline optional for rmdef --- .../admin-guides/references/man1/rmdef.1.rst | 16 +++--- xCAT-client/pods/man1/rmdef.1.pod | 14 ++--- xCAT-server/lib/xcat/plugins/DBobjectdefs.pm | 55 +++++++++++++------ 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man1/rmdef.1.rst b/docs/source/guides/admin-guides/references/man1/rmdef.1.rst index 4b1d4cb5a..f520916bc 100644 --- a/docs/source/guides/admin-guides/references/man1/rmdef.1.rst +++ b/docs/source/guides/admin-guides/references/man1/rmdef.1.rst @@ -22,7 +22,7 @@ SYNOPSIS \ **rmdef**\ [\ **-h | -**\ **-help**\ ] [\ **-t**\ \ *object-types*\ ] \ **rmdef**\ [\ **-V | -**\ **-verbose**\ ] [\ **-a | -**\ **-all**\ ] [\ **-t**\ \ *object-types*\ ] [\ **-o**\ \ *object-names*\ ] -[\ **-f | -**\ **-force**\ ] [\ *noderange*\ ] +[\ **-f | -**\ **-force**\ ] [\ **-C | -**\ **-cleanup**\ ] [\ *noderange*\ ] *********** @@ -41,17 +41,13 @@ OPTIONS \ **-a|-**\ **-all**\ - Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option. Once all the data is removed the xCAT daemon will no longer work. Most xCAT commands will fail. - In order to use xCAT commands again, you have two options. You can restore your database from your backup by switching to bypass mode, and running the restorexCATdb command. - You switch to bypass mode by setting the XCATBYPASS environmant variable. (ex. "export XCATBYPASS=yes") - A second option is to run xcatconfig -d. This will restore the initial setup of the database as when xCAT was initially installed. - You can then restart xcatd and run xCAT commands. + Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option. Once all the data is removed the xCAT daemon will no longer work. Most xCAT commands will fail. In order to use xCAT commands again, you have two options. You can restore your database from your backup by switching to bypass mode, and running the \ **restorexCATdb**\ command. You can switch to bypass mode by setting the XCATBYPASS environmant variable. (ex. "export XCATBYPASS=yes") A second option is to run \ **xcatconfig -d**\ . This will restore the initial setup of the database as when xCAT was initially installed. You can then restart xcatd and run xCAT commands. \ **-f|-**\ **-force**\ - Use this with the all option as an extra indicator that ALL definitions are to be removed. + Use this with the \ **-**\ **-all**\ option as an extra indicator that ALL definitions are to be removed. @@ -79,6 +75,12 @@ OPTIONS +\ **-C|-**\ **-cleanup**\ + + Perform additional cleanup by running \ **nodeset offline**\ on the objects specified in the \ *noderange*\ . + + + \ **-V|-**\ **-verbose**\ Verbose mode. diff --git a/xCAT-client/pods/man1/rmdef.1.pod b/xCAT-client/pods/man1/rmdef.1.pod index e226fe80c..be44ccc73 100644 --- a/xCAT-client/pods/man1/rmdef.1.pod +++ b/xCAT-client/pods/man1/rmdef.1.pod @@ -8,7 +8,7 @@ B - Use this command to remove xCAT data object definitions. B [B<-h>|B<--help>] [B<-t> I] B [B<-V>|B<--verbose>] [B<-a>|B<--all>] [B<-t> I] [B<-o> I] -[B<-f>|B<--force>] [I] +[B<-f>|B<--force>] [B<-C>|B<--cleanup>] [I] =head1 DESCRIPTION @@ -22,15 +22,11 @@ This command is used to remove xCAT object definitions that are stored in the xC =item B<-a|--all> -Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option. Once all the data is removed the xCAT daemon will no longer work. Most xCAT commands will fail. -In order to use xCAT commands again, you have two options. You can restore your database from your backup by switching to bypass mode, and running the restorexCATdb command. -You switch to bypass mode by setting the XCATBYPASS environmant variable. (ex. "export XCATBYPASS=yes") -A second option is to run xcatconfig -d. This will restore the initial setup of the database as when xCAT was initially installed. -You can then restart xcatd and run xCAT commands. +Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option. Once all the data is removed the xCAT daemon will no longer work. Most xCAT commands will fail. In order to use xCAT commands again, you have two options. You can restore your database from your backup by switching to bypass mode, and running the B command. You can switch to bypass mode by setting the XCATBYPASS environmant variable. (ex. "export XCATBYPASS=yes") A second option is to run B. This will restore the initial setup of the database as when xCAT was initially installed. You can then restart xcatd and run xCAT commands. =item B<-f|--force> -Use this with the all option as an extra indicator that ALL definitions are to be removed. +Use this with the B<--all> option as an extra indicator that ALL definitions are to be removed. =item B<-h|--help> @@ -48,6 +44,10 @@ A set of comma delimited object names. A set of comma delimited object types. +=item B<-C|--cleanup> + +Perform additional cleanup by running B on the objects specified in the I. + =item B<-V|--verbose> Verbose mode. diff --git a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm index d91d51c3e..f263fdfe4 100755 --- a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm +++ b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm @@ -468,6 +468,7 @@ sub processArgs undef $::opt_nics; undef $::opt_setattr; undef $::opt_template; + undef $::opt_cleanup; # parse the options - include any option from all 4 cmds Getopt::Long::Configure("no_pass_through"); @@ -497,6 +498,7 @@ sub processArgs 'nics' => \$::opt_nics, 'u' => \$::opt_setattr, 'template:s' => \$::opt_template, + 'C|cleanup' => \$::opt_cleanup, ) ) { @@ -513,6 +515,13 @@ sub processArgs return 2; } + if (defined($::opt_cleanup) && ($::command ne "rmdef")) { + my $rsp; + $rsp->{data}->[0] = "Option \'-C\' can not be used with $::command."; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 2; + } + if (defined($::opt_setattr)) { if (!$::opt_t && !$::filedata) { $::opt_t = 'osimage'; @@ -4015,6 +4024,9 @@ sub defrm # process the command line my $rc = &processArgs; + # Issue info message if more than cleanup_msg_trigger nodes are being removed with --cleanup option + my $cleanup_msg_trigger = 100; + if ($rc != 0) { @@ -4258,24 +4270,33 @@ sub defrm } } - # Call nodeset offline on each node to cleanup its boot configuration files from /tftpboot directory - if ($doreq) { - # Go through each object and make sure it is a node type - my @allnodes; - foreach my $single_object (keys %objhash) { - if ($objhash{$single_object} eq "node") { - # build a list of nodes to offline - push @allnodes, $single_object; + if ($::opt_cleanup) { + # Call nodeset offline on each node to cleanup its boot configuration files from /tftpboot directory + if ($doreq) { + # Go through each object and make sure it is a node type + my @allnodes; + foreach my $single_object (keys %objhash) { + if ($objhash{$single_object} eq "node") { + # build a list of nodes to offline + push @allnodes, $single_object; + } } + # If cleaning up (issuing nodeset offline) for more than cleanup_msg_trigger node, + # issue info message + if (@allnodes > $cleanup_msg_trigger) { + my $rsp; + $rsp->{data}->[0] = "Performing configuration cleanup. This might take a some time."; + xCAT::MsgUtils->message("I", $rsp, $::callback); + } + # Run nodeset offline and capture output. + # But the output can be ignored since we do not want to prevent user from doing rmdef if + # nodeset returns some error. + my @output = xCAT::Utils->runxcmd({ + command => ['nodeset'], + node => [@allnodes], + arg => ['offline'], + }, $doreq, 0 ,1); } - # Run nodeset offline and capture output. - # But the output can be ignored since we do not want to prevent user from doing rmdef if - # nodeset returns some error. - my @output = xCAT::Utils->runxcmd({ - command => ['nodeset'], - node => [@allnodes], - arg => ['offline'], - }, $doreq, 0 ,1); } # remove the objects @@ -4488,7 +4509,7 @@ sub defrm_usage $rsp->{data}->[0] = "\nUsage: rmdef - Remove xCAT data object definitions.\n"; $rsp->{data}->[1] = " rmdef [-h | --help ] [-t object-types]\n"; $rsp->{data}->[2] = " rmdef [-V | --verbose] [-t object-types] [-a | --all] [-f | --force]"; - $rsp->{data}->[3] = " [-o object-names] [-w attr=val,[attr=val...] [noderange]\n"; + $rsp->{data}->[3] = " [-o object-names] [-C | --cleanup] [noderange]\n"; $rsp->{data}->[4] = "\nThe following data object types are supported by xCAT.\n"; my $n = 5; From 6a5b8b3bbc7ff73225b5508cd7ba95ce940750cb Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Thu, 9 Mar 2017 17:26:35 -0500 Subject: [PATCH 071/187] Handle bad return code from pdu commands --- .../admin-guides/references/man5/passwd.5.rst | 4 +- .../admin-guides/references/man5/pdu.5.rst | 28 ++++-- .../admin-guides/references/man5/xcatdb.5.rst | 4 + .../admin-guides/references/man7/group.7.rst | 10 ++- .../admin-guides/references/man7/node.7.rst | 10 ++- .../admin-guides/references/man7/pdu.7.rst | 85 +++++++++++++++++++ perl-xCAT/xCAT/Schema.pm | 26 +++--- xCAT-server/lib/xcat/plugins/pdu.pm | 61 ++++++++++--- 8 files changed, 189 insertions(+), 39 deletions(-) create mode 100644 docs/source/guides/admin-guides/references/man7/pdu.7.rst diff --git a/docs/source/guides/admin-guides/references/man5/passwd.5.rst b/docs/source/guides/admin-guides/references/man5/passwd.5.rst index 4123a9258..3438aa4b6 100644 --- a/docs/source/guides/admin-guides/references/man5/passwd.5.rst +++ b/docs/source/guides/admin-guides/references/man5/passwd.5.rst @@ -50,13 +50,13 @@ passwd Attributes: \ **password**\ - The default password for this type of component. On Linux, a crypted form could be provided. Hashes starting with $1$, $5$ and $6$ (md5, sha256 and sha512 respectively) are supported. + The default password for this type of component \ **cryptmethod**\ - Indicates the method to use to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default to encrypt plain-text passwords. + Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default. diff --git a/docs/source/guides/admin-guides/references/man5/pdu.5.rst b/docs/source/guides/admin-guides/references/man5/pdu.5.rst index a77ea0b32..5d5076cfb 100644 --- a/docs/source/guides/admin-guides/references/man5/pdu.5.rst +++ b/docs/source/guides/admin-guides/references/man5/pdu.5.rst @@ -19,7 +19,7 @@ SYNOPSIS ******** -\ **pdu Attributes:**\ \ *pdu*\ , \ *machinetype*\ , \ *modelnum*\ , \ *serialnum*\ , \ *outletCount*\ , \ *comments*\ , \ *disable*\ +\ **pdu Attributes:**\ \ *node*\ , \ *nodetype*\ , \ *outlet*\ , \ *machinetype*\ , \ *modelnum*\ , \ *serialnum*\ , \ *comments*\ , \ *disable*\ *********** @@ -36,12 +36,24 @@ pdu Attributes: -\ **pdu**\ +\ **node**\ The hostname/address of the pdu to which the settings apply +\ **nodetype**\ + + The node type should be pdu + + + +\ **outlet**\ + + The pdu outlet count + + + \ **machinetype**\ The pdu machine type @@ -60,16 +72,16 @@ pdu Attributes: -\ **outletCount**\ - - - \ **comments**\ - + + Any user-written notes. + \ **disable**\ - + + Set to 'yes' or '1' to comment out this row. + diff --git a/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst b/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst index e95ece5c8..4f8be2d93 100644 --- a/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst +++ b/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst @@ -288,6 +288,10 @@ osimage(7)|osimage.7 +pdu(7)|pdu.7 + + + policy(7)|policy.7 diff --git a/docs/source/guides/admin-guides/references/man7/group.7.rst b/docs/source/guides/admin-guides/references/man7/group.7.rst index 4a9954df5..7e42304f6 100644 --- a/docs/source/guides/admin-guides/references/man7/group.7.rst +++ b/docs/source/guides/admin-guides/references/man7/group.7.rst @@ -19,7 +19,7 @@ SYNOPSIS ******** -\ **group Attributes:**\ \ *addkcmdline*\ , \ *arch*\ , \ *authdomain*\ , \ *bmc*\ , \ *bmcpassword*\ , \ *bmcport*\ , \ *bmcusername*\ , \ *bmcvlantag*\ , \ *cfgmgr*\ , \ *cfgmgtroles*\ , \ *cfgserver*\ , \ *chain*\ , \ *chassis*\ , \ *cmdmapping*\ , \ *cons*\ , \ *conserver*\ , \ *consoleondemand*\ , \ *cpucount*\ , \ *cputype*\ , \ *currchain*\ , \ *currstate*\ , \ *dhcpinterfaces*\ , \ *disksize*\ , \ *displayname*\ , \ *dockercpus*\ , \ *dockerflag*\ , \ *dockerhost*\ , \ *dockermemory*\ , \ *dockernics*\ , \ *domainadminpassword*\ , \ *domainadminuser*\ , \ *domaintype*\ , \ *getmac*\ , \ *groupname*\ , \ *grouptype*\ , \ *hcp*\ , \ *height*\ , \ *hostcluster*\ , \ *hostinterface*\ , \ *hostmanager*\ , \ *hostnames*\ , \ *hosttype*\ , \ *hwtype*\ , \ *id*\ , \ *initrd*\ , \ *installnic*\ , \ *interface*\ , \ *ip*\ , \ *iscsipassword*\ , \ *iscsiserver*\ , \ *iscsitarget*\ , \ *iscsiuserid*\ , \ *kcmdline*\ , \ *kernel*\ , \ *linkports*\ , \ *mac*\ , \ *machinetype*\ , \ *membergroups*\ , \ *members*\ , \ *memory*\ , \ *mgt*\ , \ *micbridge*\ , \ *michost*\ , \ *micid*\ , \ *miconboot*\ , \ *micpowermgt*\ , \ *micvlog*\ , \ *migrationdest*\ , \ *modelnum*\ , \ *monserver*\ , \ *mpa*\ , \ *mtm*\ , \ *nameservers*\ , \ *netboot*\ , \ *nfsdir*\ , \ *nfsserver*\ , \ *nicaliases*\ , \ *niccustomscripts*\ , \ *nicdevices*\ , \ *nicextraparams*\ , \ *nichostnameprefixes*\ , \ *nichostnamesuffixes*\ , \ *nicips*\ , \ *nicnetworks*\ , \ *nicsadapter*\ , \ *nictypes*\ , \ *nimserver*\ , \ *nodetype*\ , \ *ondiscover*\ , \ *os*\ , \ *osvolume*\ , \ *otherinterfaces*\ , \ *ou*\ , \ *outletcount*\ , \ *parent*\ , \ *passwd.HMC*\ , \ *passwd.admin*\ , \ *passwd.celogin*\ , \ *passwd.general*\ , \ *passwd.hscroot*\ , \ *password*\ , \ *pdu*\ , \ *postbootscripts*\ , \ *postscripts*\ , \ *power*\ , \ *pprofile*\ , \ *prescripts-begin*\ , \ *prescripts-end*\ , \ *primarynic*\ , \ *productkey*\ , \ *profile*\ , \ *protocol*\ , \ *provmethod*\ , \ *rack*\ , \ *room*\ , \ *routenames*\ , \ *serial*\ , \ *serialflow*\ , \ *serialnum*\ , \ *serialport*\ , \ *serialspeed*\ , \ *servicenode*\ , \ *setupconserver*\ , \ *setupdhcp*\ , \ *setupftp*\ , \ *setupipforward*\ , \ *setupldap*\ , \ *setupnameserver*\ , \ *setupnfs*\ , \ *setupnim*\ , \ *setupntp*\ , \ *setupproxydhcp*\ , \ *setuptftp*\ , \ *sfp*\ , \ *side*\ , \ *slot*\ , \ *slotid*\ , \ *slots*\ , \ *snmpauth*\ , \ *snmppassword*\ , \ *snmpprivacy*\ , \ *snmpusername*\ , \ *snmpversion*\ , \ *storagcontroller*\ , \ *storagetype*\ , \ *supernode*\ , \ *supportedarchs*\ , \ *supportproxydhcp*\ , \ *switch*\ , \ *switchinterface*\ , \ *switchport*\ , \ *switchtype*\ , \ *switchvlan*\ , \ *syslog*\ , \ *termport*\ , \ *termserver*\ , \ *tftpdir*\ , \ *tftpserver*\ , \ *unit*\ , \ *urlpath*\ , \ *usercomment*\ , \ *userid*\ , \ *username*\ , \ *vmbeacon*\ , \ *vmbootorder*\ , \ *vmcfgstore*\ , \ *vmcluster*\ , \ *vmcpus*\ , \ *vmhost*\ , \ *vmmanager*\ , \ *vmmaster*\ , \ *vmmemory*\ , \ *vmnicnicmodel*\ , \ *vmnics*\ , \ *vmothersetting*\ , \ *vmphyslots*\ , \ *vmstorage*\ , \ *vmstoragecache*\ , \ *vmstorageformat*\ , \ *vmstoragemodel*\ , \ *vmtextconsole*\ , \ *vmvirtflags*\ , \ *vmvncport*\ , \ *webport*\ , \ *wherevals*\ , \ *xcatmaster*\ +\ **group Attributes:**\ \ *addkcmdline*\ , \ *arch*\ , \ *authdomain*\ , \ *bmc*\ , \ *bmcpassword*\ , \ *bmcport*\ , \ *bmcusername*\ , \ *bmcvlantag*\ , \ *cfgmgr*\ , \ *cfgmgtroles*\ , \ *cfgserver*\ , \ *chain*\ , \ *chassis*\ , \ *cmdmapping*\ , \ *cons*\ , \ *conserver*\ , \ *consoleondemand*\ , \ *cpucount*\ , \ *cputype*\ , \ *currchain*\ , \ *currstate*\ , \ *dhcpinterfaces*\ , \ *disksize*\ , \ *displayname*\ , \ *dockercpus*\ , \ *dockerflag*\ , \ *dockerhost*\ , \ *dockermemory*\ , \ *dockernics*\ , \ *domainadminpassword*\ , \ *domainadminuser*\ , \ *domaintype*\ , \ *getmac*\ , \ *groupname*\ , \ *grouptype*\ , \ *hcp*\ , \ *height*\ , \ *hostcluster*\ , \ *hostinterface*\ , \ *hostmanager*\ , \ *hostnames*\ , \ *hosttype*\ , \ *hwtype*\ , \ *id*\ , \ *initrd*\ , \ *installnic*\ , \ *interface*\ , \ *ip*\ , \ *iscsipassword*\ , \ *iscsiserver*\ , \ *iscsitarget*\ , \ *iscsiuserid*\ , \ *kcmdline*\ , \ *kernel*\ , \ *linkports*\ , \ *mac*\ , \ *machinetype*\ , \ *membergroups*\ , \ *members*\ , \ *memory*\ , \ *mgt*\ , \ *micbridge*\ , \ *michost*\ , \ *micid*\ , \ *miconboot*\ , \ *micpowermgt*\ , \ *micvlog*\ , \ *migrationdest*\ , \ *modelnum*\ , \ *monserver*\ , \ *mpa*\ , \ *mtm*\ , \ *nameservers*\ , \ *netboot*\ , \ *nfsdir*\ , \ *nfsserver*\ , \ *nicaliases*\ , \ *niccustomscripts*\ , \ *nicdevices*\ , \ *nicextraparams*\ , \ *nichostnameprefixes*\ , \ *nichostnamesuffixes*\ , \ *nicips*\ , \ *nicnetworks*\ , \ *nicsadapter*\ , \ *nictypes*\ , \ *nimserver*\ , \ *nodetype*\ , \ *ondiscover*\ , \ *os*\ , \ *osvolume*\ , \ *otherinterfaces*\ , \ *ou*\ , \ *outlet*\ , \ *parent*\ , \ *passwd.HMC*\ , \ *passwd.admin*\ , \ *passwd.celogin*\ , \ *passwd.general*\ , \ *passwd.hscroot*\ , \ *password*\ , \ *pdu*\ , \ *postbootscripts*\ , \ *postscripts*\ , \ *power*\ , \ *pprofile*\ , \ *prescripts-begin*\ , \ *prescripts-end*\ , \ *primarynic*\ , \ *productkey*\ , \ *profile*\ , \ *protocol*\ , \ *provmethod*\ , \ *rack*\ , \ *room*\ , \ *routenames*\ , \ *serial*\ , \ *serialflow*\ , \ *serialnum*\ , \ *serialport*\ , \ *serialspeed*\ , \ *servicenode*\ , \ *setupconserver*\ , \ *setupdhcp*\ , \ *setupftp*\ , \ *setupipforward*\ , \ *setupldap*\ , \ *setupnameserver*\ , \ *setupnfs*\ , \ *setupnim*\ , \ *setupntp*\ , \ *setupproxydhcp*\ , \ *setuptftp*\ , \ *sfp*\ , \ *side*\ , \ *slot*\ , \ *slotid*\ , \ *slots*\ , \ *snmpauth*\ , \ *snmppassword*\ , \ *snmpprivacy*\ , \ *snmpusername*\ , \ *snmpversion*\ , \ *storagcontroller*\ , \ *storagetype*\ , \ *supernode*\ , \ *supportedarchs*\ , \ *supportproxydhcp*\ , \ *switch*\ , \ *switchinterface*\ , \ *switchport*\ , \ *switchtype*\ , \ *switchvlan*\ , \ *syslog*\ , \ *termport*\ , \ *termserver*\ , \ *tftpdir*\ , \ *tftpserver*\ , \ *unit*\ , \ *urlpath*\ , \ *usercomment*\ , \ *userid*\ , \ *username*\ , \ *vmbeacon*\ , \ *vmbootorder*\ , \ *vmcfgstore*\ , \ *vmcluster*\ , \ *vmcpus*\ , \ *vmhost*\ , \ *vmmanager*\ , \ *vmmaster*\ , \ *vmmemory*\ , \ *vmnicnicmodel*\ , \ *vmnics*\ , \ *vmothersetting*\ , \ *vmphyslots*\ , \ *vmstorage*\ , \ *vmstoragecache*\ , \ *vmstorageformat*\ , \ *vmstoragemodel*\ , \ *vmtextconsole*\ , \ *vmvirtflags*\ , \ *vmvncport*\ , \ *webport*\ , \ *wherevals*\ , \ *xcatmaster*\ *********** @@ -663,10 +663,14 @@ group Attributes: -\ **nodetype**\ (nodetype.nodetype) +\ **nodetype**\ (nodetype.nodetype, pdu.nodetype) A comma-delimited list of characteristics of this node. Valid values: ppc, blade, vm (virtual machine), osi (OS image), mm, mn, rsa, switch. + or + + The node type should be pdu + \ **ondiscover**\ (chain.ondiscover) @@ -707,7 +711,7 @@ group Attributes: -\ **outletcount**\ (pdu.outletcount) +\ **outlet**\ (pdu.outlet) The pdu outlet count diff --git a/docs/source/guides/admin-guides/references/man7/node.7.rst b/docs/source/guides/admin-guides/references/man7/node.7.rst index b06375b96..f1ae11918 100644 --- a/docs/source/guides/admin-guides/references/man7/node.7.rst +++ b/docs/source/guides/admin-guides/references/man7/node.7.rst @@ -19,7 +19,7 @@ SYNOPSIS ******** -\ **node Attributes:**\ \ *addkcmdline*\ , \ *appstatus*\ , \ *appstatustime*\ , \ *arch*\ , \ *authdomain*\ , \ *bmc*\ , \ *bmcpassword*\ , \ *bmcport*\ , \ *bmcusername*\ , \ *bmcvlantag*\ , \ *cfgmgr*\ , \ *cfgmgtroles*\ , \ *cfgserver*\ , \ *chain*\ , \ *chassis*\ , \ *cmdmapping*\ , \ *cons*\ , \ *conserver*\ , \ *consoleondemand*\ , \ *cpucount*\ , \ *cputype*\ , \ *currchain*\ , \ *currstate*\ , \ *dhcpinterfaces*\ , \ *disksize*\ , \ *displayname*\ , \ *dockercpus*\ , \ *dockerflag*\ , \ *dockerhost*\ , \ *dockermemory*\ , \ *dockernics*\ , \ *domainadminpassword*\ , \ *domainadminuser*\ , \ *domaintype*\ , \ *getmac*\ , \ *groups*\ , \ *hcp*\ , \ *height*\ , \ *hidden*\ , \ *hostcluster*\ , \ *hostinterface*\ , \ *hostmanager*\ , \ *hostnames*\ , \ *hosttype*\ , \ *hwtype*\ , \ *id*\ , \ *initrd*\ , \ *installnic*\ , \ *interface*\ , \ *ip*\ , \ *iscsipassword*\ , \ *iscsiserver*\ , \ *iscsitarget*\ , \ *iscsiuserid*\ , \ *kcmdline*\ , \ *kernel*\ , \ *linkports*\ , \ *mac*\ , \ *machinetype*\ , \ *memory*\ , \ *mgt*\ , \ *micbridge*\ , \ *michost*\ , \ *micid*\ , \ *miconboot*\ , \ *micpowermgt*\ , \ *micvlog*\ , \ *migrationdest*\ , \ *modelnum*\ , \ *monserver*\ , \ *mpa*\ , \ *mtm*\ , \ *nameservers*\ , \ *netboot*\ , \ *nfsdir*\ , \ *nfsserver*\ , \ *nicaliases*\ , \ *niccustomscripts*\ , \ *nicdevices*\ , \ *nicextraparams*\ , \ *nichostnameprefixes*\ , \ *nichostnamesuffixes*\ , \ *nicips*\ , \ *nicnetworks*\ , \ *nicsadapter*\ , \ *nictypes*\ , \ *nimserver*\ , \ *node*\ , \ *nodetype*\ , \ *ondiscover*\ , \ *os*\ , \ *osvolume*\ , \ *otherinterfaces*\ , \ *ou*\ , \ *outletcount*\ , \ *parent*\ , \ *passwd.HMC*\ , \ *passwd.admin*\ , \ *passwd.celogin*\ , \ *passwd.general*\ , \ *passwd.hscroot*\ , \ *password*\ , \ *pdu*\ , \ *postbootscripts*\ , \ *postscripts*\ , \ *power*\ , \ *pprofile*\ , \ *prescripts-begin*\ , \ *prescripts-end*\ , \ *primarynic*\ , \ *primarysn*\ , \ *productkey*\ , \ *profile*\ , \ *protocol*\ , \ *provmethod*\ , \ *rack*\ , \ *room*\ , \ *routenames*\ , \ *serial*\ , \ *serialflow*\ , \ *serialnum*\ , \ *serialport*\ , \ *serialspeed*\ , \ *servicenode*\ , \ *setupconserver*\ , \ *setupdhcp*\ , \ *setupftp*\ , \ *setupipforward*\ , \ *setupldap*\ , \ *setupnameserver*\ , \ *setupnfs*\ , \ *setupnim*\ , \ *setupntp*\ , \ *setupproxydhcp*\ , \ *setuptftp*\ , \ *sfp*\ , \ *side*\ , \ *slot*\ , \ *slotid*\ , \ *slots*\ , \ *snmpauth*\ , \ *snmppassword*\ , \ *snmpprivacy*\ , \ *snmpusername*\ , \ *snmpversion*\ , \ *status*\ , \ *statustime*\ , \ *storagcontroller*\ , \ *storagetype*\ , \ *supernode*\ , \ *supportedarchs*\ , \ *supportproxydhcp*\ , \ *switch*\ , \ *switchinterface*\ , \ *switchport*\ , \ *switchtype*\ , \ *switchvlan*\ , \ *syslog*\ , \ *termport*\ , \ *termserver*\ , \ *tftpdir*\ , \ *tftpserver*\ , \ *unit*\ , \ *updatestatus*\ , \ *updatestatustime*\ , \ *urlpath*\ , \ *usercomment*\ , \ *userid*\ , \ *username*\ , \ *vmbeacon*\ , \ *vmbootorder*\ , \ *vmcfgstore*\ , \ *vmcluster*\ , \ *vmcpus*\ , \ *vmhost*\ , \ *vmmanager*\ , \ *vmmaster*\ , \ *vmmemory*\ , \ *vmnicnicmodel*\ , \ *vmnics*\ , \ *vmothersetting*\ , \ *vmphyslots*\ , \ *vmstorage*\ , \ *vmstoragecache*\ , \ *vmstorageformat*\ , \ *vmstoragemodel*\ , \ *vmtextconsole*\ , \ *vmvirtflags*\ , \ *vmvncport*\ , \ *webport*\ , \ *xcatmaster*\ , \ *zonename*\ +\ **node Attributes:**\ \ *addkcmdline*\ , \ *appstatus*\ , \ *appstatustime*\ , \ *arch*\ , \ *authdomain*\ , \ *bmc*\ , \ *bmcpassword*\ , \ *bmcport*\ , \ *bmcusername*\ , \ *bmcvlantag*\ , \ *cfgmgr*\ , \ *cfgmgtroles*\ , \ *cfgserver*\ , \ *chain*\ , \ *chassis*\ , \ *cmdmapping*\ , \ *cons*\ , \ *conserver*\ , \ *consoleondemand*\ , \ *cpucount*\ , \ *cputype*\ , \ *currchain*\ , \ *currstate*\ , \ *dhcpinterfaces*\ , \ *disksize*\ , \ *displayname*\ , \ *dockercpus*\ , \ *dockerflag*\ , \ *dockerhost*\ , \ *dockermemory*\ , \ *dockernics*\ , \ *domainadminpassword*\ , \ *domainadminuser*\ , \ *domaintype*\ , \ *getmac*\ , \ *groups*\ , \ *hcp*\ , \ *height*\ , \ *hidden*\ , \ *hostcluster*\ , \ *hostinterface*\ , \ *hostmanager*\ , \ *hostnames*\ , \ *hosttype*\ , \ *hwtype*\ , \ *id*\ , \ *initrd*\ , \ *installnic*\ , \ *interface*\ , \ *ip*\ , \ *iscsipassword*\ , \ *iscsiserver*\ , \ *iscsitarget*\ , \ *iscsiuserid*\ , \ *kcmdline*\ , \ *kernel*\ , \ *linkports*\ , \ *mac*\ , \ *machinetype*\ , \ *memory*\ , \ *mgt*\ , \ *micbridge*\ , \ *michost*\ , \ *micid*\ , \ *miconboot*\ , \ *micpowermgt*\ , \ *micvlog*\ , \ *migrationdest*\ , \ *modelnum*\ , \ *monserver*\ , \ *mpa*\ , \ *mtm*\ , \ *nameservers*\ , \ *netboot*\ , \ *nfsdir*\ , \ *nfsserver*\ , \ *nicaliases*\ , \ *niccustomscripts*\ , \ *nicdevices*\ , \ *nicextraparams*\ , \ *nichostnameprefixes*\ , \ *nichostnamesuffixes*\ , \ *nicips*\ , \ *nicnetworks*\ , \ *nicsadapter*\ , \ *nictypes*\ , \ *nimserver*\ , \ *node*\ , \ *nodetype*\ , \ *ondiscover*\ , \ *os*\ , \ *osvolume*\ , \ *otherinterfaces*\ , \ *ou*\ , \ *outlet*\ , \ *parent*\ , \ *passwd.HMC*\ , \ *passwd.admin*\ , \ *passwd.celogin*\ , \ *passwd.general*\ , \ *passwd.hscroot*\ , \ *password*\ , \ *pdu*\ , \ *postbootscripts*\ , \ *postscripts*\ , \ *power*\ , \ *pprofile*\ , \ *prescripts-begin*\ , \ *prescripts-end*\ , \ *primarynic*\ , \ *primarysn*\ , \ *productkey*\ , \ *profile*\ , \ *protocol*\ , \ *provmethod*\ , \ *rack*\ , \ *room*\ , \ *routenames*\ , \ *serial*\ , \ *serialflow*\ , \ *serialnum*\ , \ *serialport*\ , \ *serialspeed*\ , \ *servicenode*\ , \ *setupconserver*\ , \ *setupdhcp*\ , \ *setupftp*\ , \ *setupipforward*\ , \ *setupldap*\ , \ *setupnameserver*\ , \ *setupnfs*\ , \ *setupnim*\ , \ *setupntp*\ , \ *setupproxydhcp*\ , \ *setuptftp*\ , \ *sfp*\ , \ *side*\ , \ *slot*\ , \ *slotid*\ , \ *slots*\ , \ *snmpauth*\ , \ *snmppassword*\ , \ *snmpprivacy*\ , \ *snmpusername*\ , \ *snmpversion*\ , \ *status*\ , \ *statustime*\ , \ *storagcontroller*\ , \ *storagetype*\ , \ *supernode*\ , \ *supportedarchs*\ , \ *supportproxydhcp*\ , \ *switch*\ , \ *switchinterface*\ , \ *switchport*\ , \ *switchtype*\ , \ *switchvlan*\ , \ *syslog*\ , \ *termport*\ , \ *termserver*\ , \ *tftpdir*\ , \ *tftpserver*\ , \ *unit*\ , \ *updatestatus*\ , \ *updatestatustime*\ , \ *urlpath*\ , \ *usercomment*\ , \ *userid*\ , \ *username*\ , \ *vmbeacon*\ , \ *vmbootorder*\ , \ *vmcfgstore*\ , \ *vmcluster*\ , \ *vmcpus*\ , \ *vmhost*\ , \ *vmmanager*\ , \ *vmmaster*\ , \ *vmmemory*\ , \ *vmnicnicmodel*\ , \ *vmnics*\ , \ *vmothersetting*\ , \ *vmphyslots*\ , \ *vmstorage*\ , \ *vmstoragecache*\ , \ *vmstorageformat*\ , \ *vmstoragemodel*\ , \ *vmtextconsole*\ , \ *vmvirtflags*\ , \ *vmvncport*\ , \ *webport*\ , \ *xcatmaster*\ , \ *zonename*\ *********** @@ -669,10 +669,14 @@ node Attributes: -\ **nodetype**\ (nodetype.nodetype) +\ **nodetype**\ (nodetype.nodetype, pdu.nodetype) A comma-delimited list of characteristics of this node. Valid values: ppc, blade, vm (virtual machine), osi (OS image), mm, mn, rsa, switch. + or + + The node type should be pdu + \ **ondiscover**\ (chain.ondiscover) @@ -713,7 +717,7 @@ node Attributes: -\ **outletcount**\ (pdu.outletcount) +\ **outlet**\ (pdu.outlet) The pdu outlet count diff --git a/docs/source/guides/admin-guides/references/man7/pdu.7.rst b/docs/source/guides/admin-guides/references/man7/pdu.7.rst new file mode 100644 index 000000000..1e2397a42 --- /dev/null +++ b/docs/source/guides/admin-guides/references/man7/pdu.7.rst @@ -0,0 +1,85 @@ + +##### +pdu.7 +##### + +.. highlight:: perl + + +**** +NAME +**** + + +\ **pdu**\ - a logical object definition in the xCAT database. + + +******** +SYNOPSIS +******** + + +\ **pdu Attributes:**\ \ *machinetype*\ , \ *modelnum*\ , \ *node*\ , \ *nodetype*\ , \ *outlet*\ , \ *serialnum*\ + + +*********** +DESCRIPTION +*********** + + +Logical objects of this type are stored in the xCAT database in one or more tables. Use the following commands +to manipulate the objects: \ **mkdef**\ , \ **chdef**\ , \ **lsdef**\ , and \ **rmdef**\ . These commands will take care of +knowing which tables the object attributes should be stored in. The attribute list below shows, in +parentheses, what tables each attribute is stored in. + + +*************** +pdu Attributes: +*************** + + + +\ **machinetype**\ (pdu.machinetype) + + The pdu machine type + + + +\ **modelnum**\ (pdu.modelnum) + + The pdu model number + + + +\ **node**\ (pdu.node) + + The hostname/address of the pdu to which the settings apply + + + +\ **nodetype**\ (pdu.nodetype) + + The node type should be pdu + + + +\ **outlet**\ (pdu.outlet) + + The pdu outlet count + + + +\ **serialnum**\ (pdu.serialnum) + + The pdu serial number + + + + +******** +SEE ALSO +******** + + +\ **mkdef(1)**\ , \ **chdef(1)**\ , \ **lsdef(1)**\ , \ **rmdef(1)**\ + diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 8a0639ea4..0e6852fc0 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -679,17 +679,19 @@ passed as argument rather than by table value', }, }, pdu => { - cols => [qw(node nodetype machinetype modelnum serialnum outletCount comments disable)], + cols => [qw(node nodetype outlet machinetype modelnum serialnum comments disable)], keys => [qw(node)], nodecol => "node", table_desc => 'Parameters to use when interrogating pdus', descriptions => { node => 'The hostname/address of the pdu to which the settings apply', nodetype => 'The node type should be pdu ', + outlet => 'The pdu outlet count', machinetype => 'The pdu machine type', modelnum => 'The pdu model number', serialnum => 'The pdu serial number', - outletcount => 'The pdu outlet count', + comments => 'Any user-written notes.', + disable => "Set to 'yes' or '1' to comment out this row.", }, }, switches => { @@ -2859,6 +2861,11 @@ my @nodeattrs = ( tabentry => 'pdu.nodetype', access_tabentry => 'pdu.node=attr:node', }, + { attr_name => 'outlet', + only_if => 'nodetype=pdu', + tabentry => 'pdu.outlet', + access_tabentry => 'pdu.node=attr:node', + }, { attr_name => 'machinetype', only_if => 'nodetype=pdu', tabentry => 'pdu.machinetype', @@ -2874,11 +2881,6 @@ my @nodeattrs = ( tabentry => 'pdu.serialnum', access_tabentry => 'pdu.node=attr:node', }, - { attr_name => 'outletcount', - only_if => 'nodetype=pdu', - tabentry => 'pdu.outletcount', - access_tabentry => 'pdu.node=attr:node', - }, ######################### ## switches table # @@ -4100,6 +4102,11 @@ push(@{ $defspec{group}->{'attrs'} }, @nodeattrs); tabentry => 'pdu.nodetype', access_tabentry => 'pdu.node=attr:node', }, + { attr_name => 'outlet', + only_if => 'nodetype=pdu', + tabentry => 'pdu.outlet', + access_tabentry => 'pdu.node=attr:node', + }, { attr_name => 'machinetype', only_if => 'nodetype=pdu', tabentry => 'pdu.machinetype', @@ -4115,11 +4122,6 @@ push(@{ $defspec{group}->{'attrs'} }, @nodeattrs); tabentry => 'pdu.serialnum', access_tabentry => 'pdu.node=attr:node', }, - { attr_name => 'outletcount', - only_if => 'nodetype=pdu', - tabentry => 'pdu.outletcount', - access_tabentry => 'pdu.node=attr:node', - }, ); diff --git a/xCAT-server/lib/xcat/plugins/pdu.pm b/xCAT-server/lib/xcat/plugins/pdu.pm index 578733ed6..92d3c3350 100644 --- a/xCAT-server/lib/xcat/plugins/pdu.pm +++ b/xCAT-server/lib/xcat/plugins/pdu.pm @@ -40,6 +40,10 @@ use SNMP; my $VERBOSE = 0; my %allerrornodes = (); my $callback; +my $pdutab; +my @pduents; +my $pdunodes; + #------------------------------------------------------- @@ -126,6 +130,11 @@ sub process_request @exargs = @$extrargs; } + #fill in the total outlet count for each pdu + $pdutab = xCAT::Table->new('pdu'); + @pduents = $pdutab->getAllNodeAttribs(['node', 'outlet']); + fill_outletCount(\@pduents, $callback); + if( $command eq "rinv") { #for higher performance, handle node in batch return powerstat($noderange, $callback); @@ -154,8 +163,8 @@ sub process_request if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat') || ($subcmd eq 'state')){ return powerpdu(\@allpdunodes, $subcmd, $callback); } else { - my $pdunodes = join (",", @allpdunodes); - $callback->({ errorcode => [1],error => "The option $subcmd is not support for pdu node(s) $pdunodes."}); + my $pdunode = join (",", @allpdunodes); + $callback->({ errorcode => [1],error => "The option $subcmd is not support for pdu node(s) $pdunode."}); } } } @@ -168,6 +177,31 @@ sub process_request return; } +sub fill_outletCount { + my $pduentries = shift; + my $callback = shift; + my $outletoid = ".1.3.6.1.4.1.2.6.223.8.2.1.0"; + my $pdutab = xCAT::Table->new('pdu'); + + foreach my $pdu (@$pduentries) { + my $cur_pdu = $pdu->{node}; + my $count = $pdu->{outlet}; + #get total outlet number for the pdu + if (!$count) { + my $session = connectTopdu($cur_pdu,$callback); + #will not log this error to output + if (!$session) { + next; + } + $count = $session->get("$outletoid"); + if ($count) { + $pdutab->setNodeAttribs($cur_pdu, {outlet => $count}); + } + } + $pdunodes->{$cur_pdu}->{outlet}=$count; + } +} + #------------------------------------------------------- =head3 powerpdu @@ -181,7 +215,6 @@ sub powerpdu { my $noderange = shift; my $subcmd = shift; my $callback = shift; - my $outletnum = ".1.3.6.1.4.1.2.6.223.8.2.1.0"; if (($subcmd eq "stat") || ($subcmd eq "state")){ return powerstat($noderange, $callback); @@ -190,9 +223,10 @@ sub powerpdu { foreach my $node (@$noderange) { my $session = connectTopdu($node,$callback); if (!$session) { + $callback->({ errorcode => [1],error => "Couldn't connect to $node"}); next; } - my $count = $session->get("$outletnum"); + my $count = $pdunodes->{$node}->{outlet}; my $value; my $statstr; if ($subcmd eq "off") { @@ -207,7 +241,7 @@ sub powerpdu { { outletpower($session, $outlet, $value); if ($session->{ErrorStr}) { - $callback->({ error => "$session->{ErrorStr}"}); + $callback->({ errorcode => [1],error => "Failed to get outlet status for $node"}); } else { my $output = " outlet $outlet is $statstr"; xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes); @@ -252,6 +286,11 @@ sub powerpduoutlet { my ($pdu, $outlet) = split /:/, $pdu_outlet; my $session = connectTopdu($pdu,$callback); if (!$session) { + $callback->({ errorcode => [1],error => "Couldn't connect to $pdu"}); + next; + } + if ($outlet > $pdunodes->{$pdu}->{outlet} ) { + $callback->({ errorcode => [1],error => "outlet number $outlet is invalid for $pdu"}); next; } my $cmd; @@ -270,7 +309,7 @@ sub powerpduoutlet { } if ($session->{ErrorStr}) { - $callback->({ error => "$session->{ErrorStr}"}); + $callback->({ errorcode => [1],error => "$session->{ErrorStr} for $pdu outlet $outlet"}); } else { $output = "$pdu outlet $outlet is $statstr"; xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes); @@ -314,13 +353,13 @@ sub powerstat { my $callback = shift; my $output; - my $outletnum = ".1.3.6.1.4.1.2.6.223.8.2.1.0"; foreach my $pdu (@$noderange) { my $session = connectTopdu($pdu,$callback); if (!$session) { + $callback->({ errorcode => [1],error => "Couldn't connect to $pdu"}); next; } - my $count = $session->get("$outletnum"); + my $count = $pdunodes->{$pdu}->{outlet}; for (my $outlet =1; $outlet <= $count; $outlet++) { my $statstr = outletstat($session, $outlet); @@ -350,8 +389,10 @@ sub outletstat { $output = $session->get("$oid.$outlet"); if ($output eq 1) { $statstr = "on"; - } else { + } elsif ($output eq 0) { $statstr = "off"; + } else { + return; } return $statstr; } @@ -381,8 +422,6 @@ sub connectTopdu { UseSprintValue => 1, ); unless ($session) { - $msg = "Failed to connect to $pdu"; - xCAT::SvrUtils::sendmsg($msg, $callback, $pdu, %allerrornodes); return; } return $session; From 2a483a80512fa8772cdbbea0ff4d721e6b2a617c Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 9 Mar 2017 21:06:47 -0500 Subject: [PATCH 072/187] update sles example --- .../manage_clusters/ppc64le/statelite/config_statelite.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst b/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst index 9e8a9c312..bdb243214 100644 --- a/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst +++ b/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst @@ -76,6 +76,7 @@ This is the minimal list of files needed, you can add additional files to the li "ALL","/etc/ntp.conf","tmpfs",, "ALL","/etc/ntp.conf.org","tmpfs",, "ALL","/etc/resolv.conf","tmpfs",, + "ALL","/etc/hostname","tmpfs",, "ALL","/etc/ssh/","tmpfs",, "ALL","/etc/sysconfig/","tmpfs",, "ALL","/etc/syslog-ng/","tmpfs",, From 78e4f4deb41e2d976e909831b2ddc3e5775f6b24 Mon Sep 17 00:00:00 2001 From: chenglch Date: Fri, 10 Mar 2017 12:21:46 +0800 Subject: [PATCH 073/187] Fix addkcmdline issue which can not customise the boot params close-issue: #2614 --- xCAT-server/lib/xcat/plugins/destiny.pm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/destiny.pm b/xCAT-server/lib/xcat/plugins/destiny.pm index 54a7804c7..c411b79e1 100755 --- a/xCAT-server/lib/xcat/plugins/destiny.pm +++ b/xCAT-server/lib/xcat/plugins/destiny.pm @@ -114,6 +114,17 @@ sub setdestiny { my $state = $ARGV[0]; my $reststates; + my $bptab = xCAT::Table->new('bootparams', -create => 1); + my %tempbh = %{ $bptab->getNodesAttribs(\@nodes, [qw(addkcmdline)]) }; + while(my ($key, $value) = each(%tempbh)) { + if ($value && $value->[0]->{"addkcmdline"}) { + my $addkcmdline = $value->[0]->{"addkcmdline"}; + # $key is node name + $bphash->{$key}->[0]->{"addkcmdline"} = $addkcmdline; + } + } + $bptab->close(); + # to support the case that the state could be runimage=xxx,runimage=yyy,osimage=xxx ($state, $reststates) = split(/,/, $state, 2); my %nstates; From 66f8c5309baec238d42b975764e9059052944a82 Mon Sep 17 00:00:00 2001 From: XuWei Date: Fri, 10 Mar 2017 01:17:13 -0500 Subject: [PATCH 074/187] fix issue 2540, check noderange validity --- xCAT-probe/subcmds/osdeploy | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xCAT-probe/subcmds/osdeploy b/xCAT-probe/subcmds/osdeploy index e6b4f1f51..1b23044cc 100755 --- a/xCAT-probe/subcmds/osdeploy +++ b/xCAT-probe/subcmds/osdeploy @@ -115,6 +115,19 @@ unless ($noderange) { exit 1; } +my @nodes = split (",", $noderange); +my @error_nodes; +foreach my $node (@nodes) { + if ($node =~ /^-/) { + push @error_nodes, $node; + } +} +if (@error_nodes) { + my $error = join (",", @error_nodes); + probe_utils->send_msg("stdout", "f", "[$error]: Wrong node definition."); + exit 1; +} + if ($rollforward_time_of_replay) { if (($rollforward_time_of_replay !~ /(\d+)h(\d+)m/i) && ($rollforward_time_of_replay !~ /^(\d+)h*$/i) && ($rollforward_time_of_replay !~ /^(\d+)m$/i)) { probe_utils->send_msg("stdout", "f", "Unsupported time format for option '-r'"); From d07b55ff2d200bcc6d33e14b881058f49fdfc082 Mon Sep 17 00:00:00 2001 From: XuWei Date: Fri, 10 Mar 2017 03:02:12 -0500 Subject: [PATCH 075/187] update rpower url and add reset --- xCAT-server/lib/xcat/plugins/openbmc.pm | 82 +++++++++++++++++-------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 45e1c28d2..a784d54e4 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -55,30 +55,32 @@ my %status_info = ( }, RPOWER_ON_REQUEST => { - method => "POST", - init_url => "$pre_url/control/chassis0/action/powerOn", + method => "PUT", + init_url => "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition", + data => "xyz.openbmc_project.State.Host.Transition.On", }, RPOWER_ON_RESPONSE => { process => \&rpower_response, }, RPOWER_OFF_REQUEST => { - method => "POST", - init_url => "$pre_url/control/chassis0/action/powerOff", + method => "PUT", + init_url => "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition", + data => "xyz.openbmc_project.State.Host.Transition.Off", }, RPOWER_OFF_RESPONSE => { process => \&rpower_response, }, RPOWER_RESET_REQUEST => { - method => "POST", - init_url => "/power/reset", + method => "PUT", + init_url => "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition", + data => "xyz.openbmc_project.State.Host.Transition.Reboot", }, RPOWER_RESET_RESPONSE => { process => \&rpower_response, }, RPOWER_STATUS_REQUEST => { method => "GET", - #init_url => "$pre_url/state/host0", - init_url => "$pre_url/settings/host0", + init_url => "/xyz/openbmc_project/state/host0", }, RPOWER_STATUS_RESPONSE => { process => \&rpower_response, @@ -262,16 +264,19 @@ sub parse_args { } elsif ($subcommand eq "off") { $next_status{LOGIN_RESPONSE} = "RPOWER_OFF_REQUEST"; $next_status{RPOWER_OFF_REQUEST} = "RPOWER_OFF_RESPONSE"; + } elsif ($subcommand eq "reset") { + $next_status{LOGIN_RESPONSE} = "RPOWER_RESET_REQUEST"; + $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; } elsif ($subcommand eq "status" or $subcommand eq "state" or $subcommand eq "stat") { $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; - # } elsif ($subcommand eq "boot") { - # $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; - # $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; - # $next_status{RPOWER_STATUS_RESPONSE}{OFF} = "RPOWER_ON_REQUEST"; - # $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; - # $next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST"; - # $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; + } elsif ($subcommand eq "boot") { + $next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST"; + $next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE"; + $next_status{RPOWER_STATUS_RESPONSE}{OFF} = "RPOWER_ON_REQUEST"; + $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; + $next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST"; + $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; } else { return ([ 1, "$subcommand is not supported for rpower" ]); } @@ -377,7 +382,7 @@ sub gen_send_request { my $node = shift; my $method; my $request_url; - my $content = '{"data": [] }';; + my $content; if ($node_info{$node}{method}) { $method = $node_info{$node}{method}; @@ -385,6 +390,10 @@ sub gen_send_request { $method = $status_info{ $node_info{$node}{cur_status} }{method}; } + if ($status_info{ $node_info{$node}{cur_status} }{data}) { + $content = '{"data":"' . $status_info{ $node_info{$node}{cur_status} }{data} . '"}'; + } + if ($node_info{$node}{cur_url}) { $request_url = $node_info{$node}{cur_url}; } else { @@ -432,7 +441,9 @@ sub deal_with_response { $error = "Service Unavailable"; } else { my $response_info = decode_json $response->content; - if ($response_info->{'data'}->{'description'} =~ /path or object not found: (.+)/) { + if ($response->status_line eq "500 Internal Server Error") { + $error = $response_info->{'data'}->{'exception'}; + } elsif ($response_info->{'data'}->{'description'} =~ /path or object not found: (.+)/) { $error = "path or object not found $1"; } else { $error = $response_info->{'data'}->{'description'}; @@ -493,29 +504,38 @@ sub rpower_response { my $response_info = decode_json $response->content; if ($node_info{$node}{cur_status} eq "RPOWER_ON_RESPONSE") { - xCAT::SvrUtils::sendmsg("on", $callback, $node); + if ($response_info->{'message'} eq "200 OK") { + xCAT::SvrUtils::sendmsg("on", $callback, $node); + } } if ($node_info{$node}{cur_status} eq "RPOWER_OFF_RESPONSE") { - xCAT::SvrUtils::sendmsg("off", $callback, $node); + if ($response_info->{'message'} eq "200 OK") { + xCAT::SvrUtils::sendmsg("off", $callback, $node); + } } - if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") { - xCAT::SvrUtils::sendmsg($response_info->{'data'}->{system_state}, $callback, $node); + if ($node_info{$node}{cur_status} eq "RPOWER_RESET_RESPONSE") { + if ($response_info->{'message'} eq "200 OK") { + xCAT::SvrUtils::sendmsg("reset", $callback, $node); + } + } + + if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") { + xCAT::SvrUtils::sendmsg($response_info->{'data'}->{CurrentHostState}, $callback, $node); } if ($next_status{ $node_info{$node}{cur_status} }) { if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") { - if ($response_info->{'data'}->{system_state} =~ /HOST_POWERED_ON/) { - $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{ON}; - } else { + if ($response_info->{'data'}->{CurrentHostState} =~ /Off$/) { $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{OFF}; + } else { + $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{ON}; } } else { $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; } gen_send_request($node); - } else { $wait_node_num--; } @@ -523,6 +543,18 @@ sub rpower_response { return; } +#------------------------------------------------------- + +=head3 rinv_response + + Deal with response of rinv command + Input: + $node: nodename of current response + $response: Async return response + +=cut + +#------------------------------------------------------- sub rinv_response { my $node = shift; my $response = shift; From 2be6b6e91e65c339a8a7558da26f5247842e79e3 Mon Sep 17 00:00:00 2001 From: bybai Date: Fri, 10 Mar 2017 03:24:44 -0500 Subject: [PATCH 076/187] fix rw rootimg for sles12.2 --- xCAT-server/lib/xcat/plugins/statelite.pm | 33 ++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/statelite.pm b/xCAT-server/lib/xcat/plugins/statelite.pm index 4b5667648..774ccad92 100644 --- a/xCAT-server/lib/xcat/plugins/statelite.pm +++ b/xCAT-server/lib/xcat/plugins/statelite.pm @@ -181,6 +181,8 @@ sub process_request { system("mkdir -p $rootimg_dir/xcatpost"); system("cp -r $installroot/postscripts/* $rootimg_dir/xcatpost/"); + # update rw to ro for sles + updateFstab($rootimg_dir,$profile,$arch); #get the root password for the node my $pass = xCAT::PasswordUtils::crypt_system_password(); @@ -258,7 +260,6 @@ sub process_request { return; } - # now get the files for the node my @synclist = xCAT::Utils->runcmd("ilitefile $imagename", 0, 1); unless (@synclist) { @@ -569,6 +570,8 @@ sub process_request { system("rm -f $xcat_packimg_tmpfile"); } chdir($oldpath); + + } sub liteMe { @@ -968,5 +971,33 @@ sub liteItem { } } +=head3 + updateFstab +=cut + +sub updateFstab { + + $rootimg_dir = shift; + $profile = shift; + $arch = shift; + + my $rootfs_name = $profile . "_" . $arch; + + my $tfstab; + open($tfstab, "<", "$rootimg_dir/etc/fstab"); + my @fsdents = <$tfstab>; + close($tfstab); + + open($tfstab, ">", "$rootimg_dir/etc/fstab"); + foreach my $line (@fsdents) { + if ( $line =~ /^$rootfs_name/ ) { + $line =~ s/rw/ro/; + } + print $tfstab $line; + } + close($tfstab); + +} + 1; From ef0b1fdce692ab26ea2576b2a48619097f5a582e Mon Sep 17 00:00:00 2001 From: bybai Date: Fri, 10 Mar 2017 03:58:15 -0500 Subject: [PATCH 077/187] polish code --- xCAT-server/lib/xcat/plugins/statelite.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/statelite.pm b/xCAT-server/lib/xcat/plugins/statelite.pm index 774ccad92..daed8b6e6 100644 --- a/xCAT-server/lib/xcat/plugins/statelite.pm +++ b/xCAT-server/lib/xcat/plugins/statelite.pm @@ -991,7 +991,7 @@ sub updateFstab { open($tfstab, ">", "$rootimg_dir/etc/fstab"); foreach my $line (@fsdents) { if ( $line =~ /^$rootfs_name/ ) { - $line =~ s/rw/ro/; + $line =~ s/\brw\b/ro/; } print $tfstab $line; } From 87d870f1bcbfc68f89112372792fe408b8145a3a Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Fri, 10 Mar 2017 14:03:39 -0500 Subject: [PATCH 078/187] Update man page based on comments --- .../admin-guides/references/man1/rmdef.1.rst | 71 +++++++++++-------- xCAT-client/pods/man1/rmdef.1.pod | 12 +++- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man1/rmdef.1.rst b/docs/source/guides/admin-guides/references/man1/rmdef.1.rst index f520916bc..06e4c474d 100644 --- a/docs/source/guides/admin-guides/references/man1/rmdef.1.rst +++ b/docs/source/guides/admin-guides/references/man1/rmdef.1.rst @@ -41,49 +41,62 @@ OPTIONS \ **-a|-**\ **-all**\ - Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option. Once all the data is removed the xCAT daemon will no longer work. Most xCAT commands will fail. In order to use xCAT commands again, you have two options. You can restore your database from your backup by switching to bypass mode, and running the \ **restorexCATdb**\ command. You can switch to bypass mode by setting the XCATBYPASS environmant variable. (ex. "export XCATBYPASS=yes") A second option is to run \ **xcatconfig -d**\ . This will restore the initial setup of the database as when xCAT was initially installed. You can then restart xcatd and run xCAT commands. + Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option as the xCAT daemons will no longer work once cleared. - - -\ **-f|-**\ **-force**\ + To restore: - Use this with the \ **-**\ **-all**\ option as an extra indicator that ALL definitions are to be removed. - - -\ **-h|-**\ **-help**\ + 1. \ **export XCATBYPASS=1**\ and run the \ **restorexCATdb**\ command. + + or + - Display a usage message. - - -\ *noderange*\ + 2. Run \ **xcatconfig -d**\ which initializes the database the same as when xCAT was installed. - A set of comma delimited node names and/or group names. See the "noderange" man page for details on supported formats. - - -\ **-o**\ \ *object-names*\ - A set of comma delimited object names. + \ **-f|-**\ **-force**\ + + Use this with the \ **-**\ **-all**\ option as an extra indicator that ALL definitions are to be removed. + - - -\ **-t**\ \ *object-types*\ - A set of comma delimited object types. + \ **-h|-**\ **-help**\ + + Display a usage message. + - - -\ **-C|-**\ **-cleanup**\ - Perform additional cleanup by running \ **nodeset offline**\ on the objects specified in the \ *noderange*\ . + \ *noderange*\ + + A set of comma delimited node names and/or group names. See the "noderange" man page for details on supported formats. + - - -\ **-V|-**\ **-verbose**\ - Verbose mode. + \ **-o**\ \ *object-names*\ + + A set of comma delimited object names. + + + + \ **-t**\ \ *object-types*\ + + A set of comma delimited object types. + + + + \ **-C|-**\ **-cleanup**\ + + Perform additional cleanup by running \ **nodeset offline**\ on the objects specified in the \ *noderange*\ . + + + + \ **-V|-**\ **-verbose**\ + + Verbose mode. + + diff --git a/xCAT-client/pods/man1/rmdef.1.pod b/xCAT-client/pods/man1/rmdef.1.pod index be44ccc73..0c3e8d58a 100644 --- a/xCAT-client/pods/man1/rmdef.1.pod +++ b/xCAT-client/pods/man1/rmdef.1.pod @@ -22,7 +22,17 @@ This command is used to remove xCAT object definitions that are stored in the xC =item B<-a|--all> -Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option. Once all the data is removed the xCAT daemon will no longer work. Most xCAT commands will fail. In order to use xCAT commands again, you have two options. You can restore your database from your backup by switching to bypass mode, and running the B command. You can switch to bypass mode by setting the XCATBYPASS environmant variable. (ex. "export XCATBYPASS=yes") A second option is to run B. This will restore the initial setup of the database as when xCAT was initially installed. You can then restart xcatd and run xCAT commands. +Clear the whole xCAT database. A backup of the xCAT definitions should be saved before using this option as the xCAT daemons will no longer work once cleared. + +To restore: + +=over 5 + +=item 1. B and run the B command. + +or + +=item 2. Run B which initializes the database the same as when xCAT was installed. =item B<-f|--force> From e265d5401de6c595dbad215d4fe419be0327ff52 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Fri, 10 Mar 2017 14:33:55 -0500 Subject: [PATCH 079/187] Handle purging block or raw VM disks when removing a VM --- xCAT-server/lib/xcat/plugins/kvm.pm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index 7e83f850f..17d1a66b0 100755 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -1775,6 +1775,14 @@ sub rmvm { foreach $disk (@purgedisks) { my $disktype = $disk->parentNode()->getAttribute("device"); if ($disktype eq "cdrom") { next; } + + my @driver = $disk->parentNode()->findnodes("driver"); + my $drivertype = $driver[0]->getAttribute("type"); + if (($drivertype eq "raw") || ($disktype eq "block")) { + #For raw or block devices, do not remove, even if purge was specified. Log info message. + xCAT::MsgUtils->trace(0, "i", "Not purging raw or block storage device: $disk"); + next; + } my $file = $disk->getAttribute("file"); # try to check the existence first, if cannot find, do nothing. From bc913e0464a1a51fb76e655cc45ee3eb12579216 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Fri, 10 Mar 2017 15:54:32 -0500 Subject: [PATCH 080/187] checking if /etc/os-release/ file is existed --- xCAT/postscripts/hardeths | 2 +- xCAT/postscripts/otherpkgs | 2 +- xCAT/postscripts/remoteshell | 2 +- xCAT/postscripts/syncfiles | 2 +- xCAT/postscripts/syslog | 4 +++- 5 files changed, 7 insertions(+), 5 deletions(-) mode change 100644 => 100755 xCAT/postscripts/syncfiles diff --git a/xCAT/postscripts/hardeths b/xCAT/postscripts/hardeths index cde4cc211..0d51de150 100755 --- a/xCAT/postscripts/hardeths +++ b/xCAT/postscripts/hardeths @@ -46,7 +46,7 @@ network_ipv4calc () echo $NETWORK } -if (cat /etc/os-release |grep -i '^NAME=[ "]*Cumulus Linux[ "]*$' >/dev/null 2>&1); then +if [ -f /etc/os-release ] && (cat /etc/os-release |grep -i '^NAME=[ "]*Cumulus Linux[ "]*$' >/dev/null 2>&1); then osver="cumulus" fi diff --git a/xCAT/postscripts/otherpkgs b/xCAT/postscripts/otherpkgs index d39334f64..aa2a21684 100755 --- a/xCAT/postscripts/otherpkgs +++ b/xCAT/postscripts/otherpkgs @@ -25,7 +25,7 @@ #enable debug #set -x -if cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then +if [ -f /etc/os-release ] && cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then #TODO echo "Cumulus OS is not supported yet, nothing to do..." logger -t xcat -p local4.info "Cumulus OS is not supported yet, nothing to do..." diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index c2023426a..690ff2e97 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -12,7 +12,7 @@ # # if on the Management Node, exit -if cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then +if [ -f /etc/os-release ] && cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then #TODO echo "Cumulus OS is not supported yet, nothing to do..." logger -t xcat -p local4.info "Cumulus OS is not supported yet, nothing to do..." diff --git a/xCAT/postscripts/syncfiles b/xCAT/postscripts/syncfiles old mode 100644 new mode 100755 index 5ce495dc2..1074fe389 --- a/xCAT/postscripts/syncfiles +++ b/xCAT/postscripts/syncfiles @@ -14,7 +14,7 @@ if [ -d /.statelite ]; then exit 0 fi -if cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then +if [ -f /etc/os-release ] && cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then #TODO echo "Cumulus OS is not supported yet, nothing to do..." logger -t xcat -p local4.info "Cumulus OS is not supported yet, nothing to do..." diff --git a/xCAT/postscripts/syslog b/xCAT/postscripts/syslog index d55364e00..8705aa168 100755 --- a/xCAT/postscripts/syslog +++ b/xCAT/postscripts/syslog @@ -149,7 +149,9 @@ config_rsyslog_V8() remoteconf="/etc/rsyslog.d/remote.conf" #for Cumulus OS inside ONIE switches - cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 && remoteconf="/etc/rsyslog.d/99-syslog.conf" + if [ -f /etc/os-release ]; then + cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 && remoteconf="/etc/rsyslog.d/99-syslog.conf" + fi # If this is a Management Node or Service Node, then it will be receiving syslog entries from the # compute nodes. Management Node is receiving from Service Nodes and possibly compute nodes. From 6a2164b6cbc4f418eae6ef95e14dfe5e3b322f39 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Fri, 10 Mar 2017 16:15:14 -0500 Subject: [PATCH 081/187] Extra checking --- xCAT-server/lib/xcat/plugins/kvm.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index 17d1a66b0..6a8433e37 100755 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -1777,6 +1777,7 @@ sub rmvm { if ($disktype eq "cdrom") { next; } my @driver = $disk->parentNode()->findnodes("driver"); + unless ($driver[0]) { next; } my $drivertype = $driver[0]->getAttribute("type"); if (($drivertype eq "raw") || ($disktype eq "block")) { #For raw or block devices, do not remove, even if purge was specified. Log info message. @@ -1784,6 +1785,7 @@ sub rmvm { next; } my $file = $disk->getAttribute("file"); + unless ($file) { next; } # try to check the existence first, if cannot find, do nothing. # we do retry because we found sometimes the delete might fail From 96e453ee7af2c99f77f31014a76e9e15f753478f Mon Sep 17 00:00:00 2001 From: XuWei Date: Mon, 13 Mar 2017 01:47:41 -0400 Subject: [PATCH 082/187] add environment variable OPENBMC_DEVEL --- xCAT-server/lib/xcat/plugins/openbmc.pm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index a784d54e4..ba3217b29 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -22,6 +22,8 @@ use File::Basename; use Data::Dumper; use JSON; +$::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; + #------------------------------------------------------- =head3 handled_commands @@ -148,6 +150,13 @@ sub preprocess_request { $callback = shift; +#------------------------------------------------------- + if ($::OPENBMC_DEVEL ne "YES") { + #xCAT::SvrUtils::sendmsg("OPENBMC_DEVEL is $::OPENBMC_DEVEL", $callback); + return; + } +#------------------------------------------------------- + my $command = $request->{command}->[0]; my $noderange = $request->{node}; my $extrargs = $request->{arg}; From 3acbdf064b1d10e568720149d5565b149acca78e Mon Sep 17 00:00:00 2001 From: immarvin Date: Mon, 13 Mar 2017 02:25:53 -0400 Subject: [PATCH 083/187] fix issue copycds issues when using -p path option #2630 --- xCAT-server/lib/xcat/plugins/copycds.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/copycds.pm b/xCAT-server/lib/xcat/plugins/copycds.pm index 0a4ff32d5..90a20c151 100644 --- a/xCAT-server/lib/xcat/plugins/copycds.pm +++ b/xCAT-server/lib/xcat/plugins/copycds.pm @@ -145,8 +145,11 @@ sub process_request { if ($path) { - $path=Cwd::realpath($path); - unless(substr($path,0,length("/install")) eq "/install"){ + + if(-e $path) { + $path=Cwd::realpath($path); + } + unless((substr($path,0,length("/install/")) eq "/install/") or ($path eq "/install")){ $callback->({ warning => "copycds: the specified path \"$path\" is not a subdirectory under /install. Make sure this path is configured for httpd/apache, otherwise, the provisioning with this iso will fail!" }); } push @{ $newreq->{arg} }, ("-p", $path); From 7b4fd3a4bed5ee954ed50d61c2b49e772f8f9a41 Mon Sep 17 00:00:00 2001 From: immarvin Date: Thu, 23 Feb 2017 09:24:43 +0800 Subject: [PATCH 084/187] add description of xCAT certs and their usage in xCAT SSL communication --- docs/source/advanced/security/certs.rst | 63 +++++++++++++++++++ docs/source/advanced/security/imgs/certs.png | Bin 0 -> 223096 bytes docs/source/advanced/security/security.rst | 19 +----- 3 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 docs/source/advanced/security/certs.rst create mode 100644 docs/source/advanced/security/imgs/certs.png diff --git a/docs/source/advanced/security/certs.rst b/docs/source/advanced/security/certs.rst new file mode 100644 index 000000000..f23fe1a83 --- /dev/null +++ b/docs/source/advanced/security/certs.rst @@ -0,0 +1,63 @@ +The SSL Certificates in xCAT +---------------------------- + + +The xCAT daemon on the management node and service node listens on a SSL socket on port 3001, the communications on the SSL socket include: + + 1. the xCAT requests from xCAT Clients + 2. the xCAT requests forwarded from other xCAT daemons, for example, the requests forwarded between xCAT daemons on management node and service nodes + 3. some special xCAT requests from compute nodes, such as ``getcredentials``, ``getpostscript``, ``litefile``, etc. + +xCAT creates 1 CA certificate and 2 credentials (private key and certificate pairs): + + 1. xCAT CA certificate(ca.pem): + + * a self-signed certificate used as Certificate Authority in xcatd SSL communication; + * generated by ``/opt/xcat/share/xcat/scripts/setup-xcat-ca.sh`` script on xCAT installation; + * will be generated (or updated) on xCAT management node when: + * install or update xCAT when "/etc/xcat/ca" directory does not exist + * or run ``xcatconfig -f|--force`` + * or run ``xcatconfig -c|--credentials`` + * files on management node: + * ``/etc/xcat/ca/ca-cert.pem`` + * ``/etc/xcat/cert/ca.pem`` ,copied by ``/opt/xcat/share/xcat/scripts/setup-server-cert.sh`` + * ``/root/.xcat/ca.pem`` ,copied by ``/opt/xcat/share/xcat/scripts/setup-local-client.sh`` + * file on service node: ``/root/.xcat/ca.pem`` + * distribution path: + **/etc/xcat/cert/ca.pem (MN)** ===(run ``xcatconfig`` command)===> **/install/postscripts/_xcat/ca.pem (MN)** ===(node provision/updatenode)==> **/xcatpost/_xcat/ca.pem (SN and CN)** ==(run "servicenode" postscript)==> **/root/.xcat/ca.pem (SN)** + + 2. xCAT server credential(server-cred.pem): + + * a concatenation of server private key and certificate(signed with xCAT CA certificate) + * generated by ``/opt/xcat/share/xcat/scripts/setup-server-cert.sh`` on xCAT installation; + * will be generated (or updated) on xCAT management node when: + * install or update xCAT when ``/etc/xcat/cert`` directory does not exist + * or run ``xcatconfig -f|--force`` + * or run ``xcatconfig -c|--credentials`` + * file on management node: ``/etc/xcat/cert/server-cred.pem`` + * file on service node: ``/etc/xcat/cert/server-cred.pem`` + * distribution path: + **/etc/xcat/cert/server-cred.pem (MN)** ==(run ``xcatserver`` script called by ``servicenode`` postscript)===> **/etc/xcat/cert/server-cred.pem(SN)** + + 3. xCAT client credential(client-cred.pem): + + * a concatenation of client private key and certificate (signed with xCAT CA certificate) + * generated by ``/opt/xcat/share/xcat/scripts/setup-local-client.sh`` on xCAT installation + * will be generated (or updated) on xCAT management node when: + * install or update xCAT when ``/root/.xcat/client-key.pem`` does not exist; + * or run ``xcatconfig -f|--force`` + * or run ``xcatconfig -c|--credentials`` + * file on management node: ``/root/.xcat/client-cred.pem`` + * file on service node: ``/root/.xcat/client-cred.pem`` + * distribution path: + **/root/.xcat/client-cred.pem (MN)** ===(run ``xcatclient`` script called by ``servicenode`` postscript")===> **/root/.xcat/client-cred.pem(SN)** + +The usage of the credentials in the xCAT SSL communication is: + + .. image:: ./imgs/certs.png + :height: 500 px + :width: 600 px + :scale: 100 % + :alt: alternate text + :align: center + diff --git a/docs/source/advanced/security/imgs/certs.png b/docs/source/advanced/security/imgs/certs.png new file mode 100644 index 0000000000000000000000000000000000000000..4f727c5d7d28d252bc1b52e6e5642209ae8e0241 GIT binary patch literal 223096 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 literal 0 HcmV?d00001 diff --git a/docs/source/advanced/security/security.rst b/docs/source/advanced/security/security.rst index a0be534ed..7f2e4ab3b 100644 --- a/docs/source/advanced/security/security.rst +++ b/docs/source/advanced/security/security.rst @@ -4,23 +4,10 @@ Transmission Channel The xCAT daemon uses SSL to only allow authorized users to run xCAT commands. All xCAT commands are initiated as an xCAT **client**, even when run commands from the xCAT management node. This **client** opens an SSL socket to the xCAT daemon, sends the command and receives responses through this one socket. xCAT has configured the certificate for root, if you nee to authorize other users, refer to the section below. -Create SSL Certificate So That User Can Be Authenticated By xCAT -```````````````````````````````````````````````````````````````` - -Running the following command on the Management node as root: :: - - /opt/xcat/share/xcat/scripts/setup-local-client.sh - -By running this command you'll see SSL certificates are creating, enter ``yes`` where prompted and take the defaults. - -This will create the following files in the 's ``$HOME/.xcat`` directory: :: - - ca.pem - client-cert.pem - client-cred.pem - client-key.pem - client-req.pem +.. toctree:: + :maxdepth: 2 + certs.rst Commands Access Control ----------------------- From 9763c34e7590aaffae3ca318299ea37af33ef2ea Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Mon, 13 Mar 2017 10:06:40 -0400 Subject: [PATCH 085/187] Added a warning message --- xCAT-server/lib/xcat/plugins/kvm.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index 6a8433e37..becd4c557 100755 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -1785,7 +1785,10 @@ sub rmvm { next; } my $file = $disk->getAttribute("file"); - unless ($file) { next; } + unless ($file) { + xCAT::MsgUtils->trace(0, "w", "Not able to find 'file' attribute value for: $disk"); + next; + } # try to check the existence first, if cannot find, do nothing. # we do retry because we found sometimes the delete might fail From e944e7fd2206ff39e9e5015471629e1b2cabeb73 Mon Sep 17 00:00:00 2001 From: immarvin Date: Mon, 13 Mar 2017 23:08:39 -0400 Subject: [PATCH 086/187] fix issue xcat command returns 0 when cmd fails due authorization #2636 --- xCAT-server/lib/xcat/plugins/nodestat.pm | 9 +++++++-- xCAT-server/sbin/xcatd | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/nodestat.pm b/xCAT-server/lib/xcat/plugins/nodestat.pm index 14d33f507..94c2969f2 100644 --- a/xCAT-server/lib/xcat/plugins/nodestat.pm +++ b/xCAT-server/lib/xcat/plugins/nodestat.pm @@ -152,7 +152,7 @@ sub preprocess_request 'h|help' => \$::HELP, 'v|version' => \$::VERSION)) { - &usage($cb); + &usage($cb,1); return (1); } if ($::HELP) { @@ -169,7 +169,7 @@ sub preprocess_request my $nodes = $req->{node}; if (!$nodes) { - &usage($cb); + &usage($cb,1); return (1); } @@ -914,6 +914,7 @@ sub process_request { } + if ($command eq "nodestat_internal") { #if ( -x '/usr/bin/nmap' ) { @@ -1210,10 +1211,14 @@ sub process_request { sub usage { my $cb = shift; + my $retcode=shift; my $rsp = {}; $rsp->{data}->[0] = "Usage:"; $rsp->{data}->[1] = " nodestat [noderange] [-m|--usemon] [-p|powerstat] [-u|--updatedb]"; $rsp->{data}->[2] = " nodestat [-h|--help|-v|--version]"; + if($retcode){ + $rsp->{errorcode}->[0]=$retcode; + } xCAT::MsgUtils->message("I", $rsp, $cb); } diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 4b21cd981..2bc097027 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -2843,6 +2843,7 @@ sub service_connection { } } else { my %resp = (error => "Permission denied for request"); + $resp{errorcode}=1; $resp{serverdone} = [undef]; if ($req->{transid}) { $resp{transid} = $req->{transid}->[0]; From db05a2fa5259ec4af433b5b21b911f6fc0db4eef Mon Sep 17 00:00:00 2001 From: XuWei Date: Mon, 13 Mar 2017 21:50:17 -0400 Subject: [PATCH 087/187] modified depending on commments --- xCAT-server/lib/xcat/plugins/openbmc.pm | 28 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index ba3217b29..d25dbb218 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -150,13 +150,6 @@ sub preprocess_request { $callback = shift; -#------------------------------------------------------- - if ($::OPENBMC_DEVEL ne "YES") { - #xCAT::SvrUtils::sendmsg("OPENBMC_DEVEL is $::OPENBMC_DEVEL", $callback); - return; - } -#------------------------------------------------------- - my $command = $request->{command}->[0]; my $noderange = $request->{node}; my $extrargs = $request->{arg}; @@ -254,6 +247,11 @@ sub parse_args { my $command = shift; my $extrargs = shift; + my $check = unsupported($callback); + if (ref($check) eq "ARRAY") { + return $check; + } + $next_status{LOGIN_REQUEST} = "LOGIN_RESPONSE"; if ($command eq "rpower") { @@ -307,16 +305,26 @@ sub parse_args { $next_status{RINV_REQUEST} = "RINV_RESPONSE"; $status_info{RINV_RESPONSE}{argv} = "$subcommand"; } else { - return ([ 1, "Only 'cpu','dimm', 'bios','all' are supportted at the same time" ]); + return ([ 1, "Only 'cpu','dimm', 'bios','all' are supportted currently" ]); } } - print Dumper(%next_status) . "\n"; + print Dumper(\%next_status) . "\n"; return; } +sub unsupported { + my $callback = shift; + if ($::OPENBMC_DEVEL ne "YES") { + return ([ 1, "This function is currently not supported" ]); + } else { + xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk\n", $callback); + return; + } +} + #------------------------------------------------------- =head3 parse_node_info @@ -364,7 +372,7 @@ sub parse_node_info { } } - print Dumper(%node_info) ."\n"; + print Dumper(\%node_info) ."\n"; return; } From 850a7e65a2ef97d8c64cc089b14d7a09154c4a7a Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Tue, 14 Mar 2017 11:27:56 -0400 Subject: [PATCH 088/187] Fix .pod error that broke the build --- .gitignore | 3 + .../admin-guides/references/man1/rmdef.1.rst | 56 +++++++++---------- xCAT-client/pods/man1/rmdef.1.pod | 2 + 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 893951706..4767b51c3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ docs/build # Ignore the temporary file for creating the Release version Release.save* +# ignore the old generated man pages and html pages +xCAT-client/share/man +xCAT-client/share/doc diff --git a/docs/source/guides/admin-guides/references/man1/rmdef.1.rst b/docs/source/guides/admin-guides/references/man1/rmdef.1.rst index 06e4c474d..3655a78b5 100644 --- a/docs/source/guides/admin-guides/references/man1/rmdef.1.rst +++ b/docs/source/guides/admin-guides/references/man1/rmdef.1.rst @@ -56,47 +56,47 @@ OPTIONS - \ **-f|-**\ **-force**\ - - Use this with the \ **-**\ **-all**\ option as an extra indicator that ALL definitions are to be removed. - + + +\ **-f|-**\ **-force**\ + Use this with the \ **-**\ **-all**\ option as an extra indicator that ALL definitions are to be removed. - \ **-h|-**\ **-help**\ - - Display a usage message. - + + +\ **-h|-**\ **-help**\ + Display a usage message. - \ *noderange*\ - - A set of comma delimited node names and/or group names. See the "noderange" man page for details on supported formats. - + + +\ *noderange*\ + A set of comma delimited node names and/or group names. See the "noderange" man page for details on supported formats. - \ **-o**\ \ *object-names*\ - - A set of comma delimited object names. - + + +\ **-o**\ \ *object-names*\ + A set of comma delimited object names. - \ **-t**\ \ *object-types*\ - - A set of comma delimited object types. - + + +\ **-t**\ \ *object-types*\ + A set of comma delimited object types. - \ **-C|-**\ **-cleanup**\ - - Perform additional cleanup by running \ **nodeset offline**\ on the objects specified in the \ *noderange*\ . - + + +\ **-C|-**\ **-cleanup**\ + Perform additional cleanup by running \ **nodeset offline**\ on the objects specified in the \ *noderange*\ . - \ **-V|-**\ **-verbose**\ - - Verbose mode. - + + +\ **-V|-**\ **-verbose**\ + Verbose mode. diff --git a/xCAT-client/pods/man1/rmdef.1.pod b/xCAT-client/pods/man1/rmdef.1.pod index 0c3e8d58a..95b4358b1 100644 --- a/xCAT-client/pods/man1/rmdef.1.pod +++ b/xCAT-client/pods/man1/rmdef.1.pod @@ -34,6 +34,8 @@ or =item 2. Run B which initializes the database the same as when xCAT was installed. +=back + =item B<-f|--force> Use this with the B<--all> option as an extra indicator that ALL definitions are to be removed. From ea315cbfc4170f1a8fd7b03ac6fd2e102dd1af63 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 14 Mar 2017 11:50:05 -0400 Subject: [PATCH 089/187] Have esx.pm support the on-parameter passing of bootparams --- xCAT-server/lib/xcat/plugins/esx.pm | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index ece31bb02..d705ca81e 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -5131,14 +5131,10 @@ sub mkcommonboot { - $bptab->setNodeAttribs( - $node, - { - kernel => $kernel, - initrd => "", - kcmdline => $append - } - ); + my $bootparams = ${$req->{bootparams}}; + $bootparams->{$node}->[0]->{kernel} = $kernel; + $bootparams->{$node}->[0]->{kcmdline} = $append; + $bootparams->{$node}->[0]->{initrd} = ""; } # end of node loop } From f3853d7c5294b66c572c2ce7158e88cde9c732d6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 14 Mar 2017 13:11:15 -0400 Subject: [PATCH 090/187] Have windows plugin pass bootparams on request --- xCAT-server/lib/xcat/plugins/windows.pm | 46 +++++++------------------ 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/windows.pm b/xCAT-server/lib/xcat/plugins/windows.pm index 5e0f61d51..141949332 100644 --- a/xCAT-server/lib/xcat/plugins/windows.pm +++ b/xCAT-server/lib/xcat/plugins/windows.pm @@ -175,15 +175,10 @@ sub winshell { } else { mkwinlinks($node, $oshash->{$node}->[0]); } - my $bptab = xCAT::Table->new('bootparams', -create => 1); - $bptab->setNodeAttribs( - $node, - { - kernel => "Boot/pxeboot.0", - initrd => "", - kcmdline => "" - } - ); + my $bootparams = ${$request->{bootparams}}; + $bootparams->{$node}->[0]->{kernel} = "Boot/pxeboot.0"; + $bootparams->{$node}->[0]->{kcmdline} = ""; + $bootparams->{$node}->[0]->{initrd} = ""; } } @@ -245,7 +240,7 @@ sub mkinstall my $node; my $ostab = xCAT::Table->new('nodetype'); my %doneimgs; - my $bptab = xCAT::Table->new('bootparams', -create => 1); + my $bootparams = ${$request->{bootparams}}; my $hmtab = xCAT::Table->new('nodehm'); my $vpdtab = xCAT::Table->new('vpd'); my $vpdhash = $vpdtab->getNodesAttribs(\@nodes, ['uuid']); @@ -365,16 +360,11 @@ sub mkinstall } else { mkwinlinks($node, $ent); } + $bootparams->{$node}->[0]->{kcmdline} = ""; + $bootparams->{$node}->[0]->{initrd} = ""; if ($arch =~ /x86_64/) { - $bptab->setNodeAttribs( - $node, - { - kernel => "Boot/pxeboot.0", - initrd => "", - kcmdline => "" - } - ); + $bootparams->{$node}->[0]->{kernel} = "Boot/pxeboot.0"; } elsif ($arch =~ /x86/) { unless (-r "$tftpdir/Boot/pxeboot32.0") { my $origpxe; @@ -402,14 +392,7 @@ sub mkinstall print $bootmgr $_; } } - $bptab->setNodeAttribs( - $node, - { - kernel => "Boot/pxeboot32.0", - initrd => "", - kcmdline => "" - } - ); + $bootparams->{$node}->[0]->{kernel} = "Boot/pxeboot32.0"; } next; } @@ -500,14 +483,9 @@ sub mkinstall } elsif (-r $installroot . "/$os/$arch/sources/install.wim") { if ($arch =~ /x86/) { - $bptab->setNodeAttribs( - $node, - { - kernel => "$winpepath" . "Boot/pxeboot.0", - initrd => "", - kcmdline => "" - } - ); + $bootparams->{$node}->[0]->{kcmdline} = ""; + $bootparams->{$node}->[0]->{initrd} = ""; + $bootparams->{$node}->[0]->{kernel} = "Boot/pxeboot.0"; } } else From 38d9914d353d75d874e5ef7d4b7d07ad6eaf1b3f Mon Sep 17 00:00:00 2001 From: ertaozh Date: Thu, 9 Mar 2017 01:45:05 -0500 Subject: [PATCH 091/187] Have ntp sync up waiting for 1 minute in case sync up failed --- xCAT-genesis-scripts/bin/doxcat | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xCAT-genesis-scripts/bin/doxcat b/xCAT-genesis-scripts/bin/doxcat index 0f39e1e89..434252519 100755 --- a/xCAT-genesis-scripts/bin/doxcat +++ b/xCAT-genesis-scripts/bin/doxcat @@ -266,8 +266,9 @@ ip addr show dev $bootnic|grep -v 'scope link'|grep -v 'dynamic'|grep -v inet6| logger -s -t $log_label -p local4.info "Starting ntpd..." ntpd -g -x -logger -s -t $log_label -p local4.info "Waiting for ntpd to synchronize..." -ntp-wait -n 1999 -s 1 -v +NTP_WAIT_SECONDS=60 +logger -s -t $log_label -p local4.info "Waiting $NTP_WAIT_SECONDS seconds for ntpd to synchronize..." +ntp-wait -n $NTP_WAIT_SECONDS -s 1 -v if [ $? -ne 0 ] then logger -s -t $log_label -p local4.info "... ntpd did not synchronize." From b425feb4941d930efad1f9a8d14edbb3133dac92 Mon Sep 17 00:00:00 2001 From: ertaozh Date: Fri, 3 Mar 2017 04:09:20 -0500 Subject: [PATCH 092/187] fix issue 2362: If packimage is not run, osimage in the chain table will fail on netboot images --- xCAT-genesis-scripts/bin/doxcat | 6 +++++- xCAT-genesis-scripts/bin/nextdestiny | 25 ++++++++++++++++--------- xCAT-server/lib/xcat/plugins/destiny.pm | 5 +---- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/xCAT-genesis-scripts/bin/doxcat b/xCAT-genesis-scripts/bin/doxcat index 0f39e1e89..a5a9ecb2b 100755 --- a/xCAT-genesis-scripts/bin/doxcat +++ b/xCAT-genesis-scripts/bin/doxcat @@ -422,7 +422,11 @@ while :; do logger -s -t $log_label -p local4.info "Poweroff..." poweroff -f else - logger -s -t $log_label -p local4.err "Unrecognized directive (dest=$dest)" + if [ "$dest" = error ]; then + logger -s -t $log_label -p local4.info "$destparameter" + else + logger -s -t $log_label -p local4.err "Unrecognized directive (dest=$dest)" + fi destiny='' dest='' delay=$((30+$RANDOM%270)) diff --git a/xCAT-genesis-scripts/bin/nextdestiny b/xCAT-genesis-scripts/bin/nextdestiny index 29b6c255f..086951c98 100755 --- a/xCAT-genesis-scripts/bin/nextdestiny +++ b/xCAT-genesis-scripts/bin/nextdestiny @@ -7,23 +7,30 @@ echo " 300 " > /tmp/destreq.xml if [ -f /tmp/destiny.xml ]; then rm /tmp/destiny.xml; fi -while [ ! -f /tmp/destiny.xml ] || grep error /tmp/destiny.xml; do - if [ -f /tmp/destiny.xml ]; then - timer=60 - while [ $timer -gt 0 ]; do - echo -en "Retrying in $timer seconds \r" >&2 - sleep 1 - timer=$(($timer-1)); - done - fi +timer=0 +while [ ! -f /tmp/destiny.xml ]; do + while [ $timer -gt 0 ]; do + echo -en "No destiny command received, retrying in $timer seconds \r" >&2 + sleep 1 + timer=$(($timer-1)); + done echo " " >&2; if [ -f /etc/xcat/cert.pem -a -f /etc/xcat/certkey.pem ]; then #use client cert if available cat /tmp/destreq.xml | openssl s_client -key /etc/xcat/certkey.pem -cert /etc/xcat/cert.pem -connect $XCATDEST -quiet 2> /dev/null > /tmp/destiny.xml else cat /tmp/destreq.xml | openssl s_client -connect $XCATDEST -quiet 2> /dev/null > /tmp/destiny.xml fi + timer=60 done rm /tmp/destreq.xml DESTINY=`grep '' /tmp/destiny.xml | awk -F'>' '{print $2}'|awk -F'<' '{print $1}'` +if [ -z "$DESTINY" ]; then + ERROR=`grep '' /tmp/destiny.xml | awk -F'>' '{print $2}'|awk -F'<' '{print $1}'` + if [ ! -z "$ERROR" ]; then + DESTINY="error=$ERROR" + else + DESTINY="error=No destiny command received" + fi +fi rm /tmp/destiny.xml echo $DESTINY diff --git a/xCAT-server/lib/xcat/plugins/destiny.pm b/xCAT-server/lib/xcat/plugins/destiny.pm index 54a7804c7..76f9d208c 100755 --- a/xCAT-server/lib/xcat/plugins/destiny.pm +++ b/xCAT-server/lib/xcat/plugins/destiny.pm @@ -389,10 +389,7 @@ sub setdestiny { ignorekernelchk => $ignorekernelchk, bootparams => \$bphash}, \&relay_response); if ($errored) { - my @myself = xCAT::NetworkUtils->determinehostname(); - my $myname = $myself[ (scalar @myself) - 1 ]; - # The callback function point to xcatd::build_response, it use dclone to clone data, but it can only accept a reference. The error msg here is a simple string, and will cause dclone failed. Seems to be string array can be used by dclone. - $callback->({ errorcode => [1], error => ["Some nodes failed to set up $state resources on server $myname, aborting"] }); + # The error messeage for mkinstall/mknetboot/mkstatelite had been output within relay_response function above, don't need to output more return; } From fc3af470bf87064ff6f4f3795d8d1b3eeed7a44d Mon Sep 17 00:00:00 2001 From: XuWei Date: Wed, 15 Mar 2017 04:41:41 -0400 Subject: [PATCH 093/187] change command parse to support service for openbmc --- xCAT-server/lib/xcat/plugins/openbmc.pm | 86 +++++++++++++++---------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index d25dbb218..4ba2c2e82 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -196,9 +196,11 @@ sub preprocess_request { #------------------------------------------------------- sub process_request { my $request = shift; - my $noderange = $request->{node}; + my $command = $request->{command}->[0]; + my $noderange = $request->{node}; parse_node_info($noderange); + parse_command_status($command); $cookie_jar = HTTP::Cookies->new({}); $async = HTTP::Async->new( @@ -252,17 +254,56 @@ sub parse_args { return $check; } + if (!defined($extrargs)) { + return ([ 1, "No option specified for rpower" ]); + } + + if (scalar(@ARGV) > 1) { + return ([ 1, "Only one option is supportted at the same time" ]); + } + + my $subcommand = $ARGV[0]; + if ($command eq "rpower") { + if ($subcommand ne "on" and $subcommand ne "off" and $subcommand ne "reset" and $subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat" and $subcommand ne "boot") { + return ([ 1, "$subcommand is not supported for rpower" ]); + } + } + + if ($command eq "rinv") { + if ($subcommand ne "cpu" and $subcommand ne "dimm" and $subcommand ne "bios" and $subcommand ne "all") { + return ([ 1, "Only 'cpu','dimm', 'bios','all' are supportted currently" ]); + } + } + + return; +} + + +sub unsupported { + my $callback = shift; + if ($::OPENBMC_DEVEL ne "YES") { + return ([ 1, "This function is currently not supported" ]); + } else { + xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk\n", $callback); + return; + } +} + +#------------------------------------------------------- + +=head3 parse_command_status + + Parse the command to init status machine + +=cut + +#------------------------------------------------------- +sub parse_command_status { + my $command = shift; + $next_status{LOGIN_REQUEST} = "LOGIN_RESPONSE"; if ($command eq "rpower") { - if (!defined($extrargs)) { - return ([ 1, "No option specified for rpower" ]); - } - - if (scalar(@ARGV) > 1) { - return ([ 1, "Only one option is supportted at the same time" ]); - } - my $subcommand = $ARGV[0]; if ($subcommand eq "on") { @@ -284,45 +325,20 @@ sub parse_args { $next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE"; $next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST"; $next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE"; - } else { - return ([ 1, "$subcommand is not supported for rpower" ]); } - } + } if ($command eq "rinv") { - if (!defined($extrargs)) { - return ([ 1, "No option specified for rpower" ]); - } - - if (scalar(@ARGV) > 1) { - return ([ 1, "Only one option is supportted at the same time" ]); - } - my $subcommand = $ARGV[0]; if ($subcommand eq "cpu" or $subcommand eq "dimm" or $subcommand eq "bios" or $subcommand eq "all") { $next_status{LOGIN_RESPONSE} = "RINV_REQUEST"; $next_status{RINV_REQUEST} = "RINV_RESPONSE"; $status_info{RINV_RESPONSE}{argv} = "$subcommand"; - } else { - return ([ 1, "Only 'cpu','dimm', 'bios','all' are supportted currently" ]); } } print Dumper(\%next_status) . "\n"; - - return; -} - - -sub unsupported { - my $callback = shift; - if ($::OPENBMC_DEVEL ne "YES") { - return ([ 1, "This function is currently not supported" ]); - } else { - xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk\n", $callback); - return; - } } #------------------------------------------------------- From 97f03932cd6a35c18e5935d1fa80f1c1740b1694 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Wed, 15 Mar 2017 07:02:20 -0400 Subject: [PATCH 094/187] modify diskfull testcase --- .../installation/reg_linux_diskfull_installation_flat | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat index e96f78bc3..56d8b37b4 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat @@ -32,7 +32,7 @@ cmd:a=0;while true; do [ $a -eq 100 ] && exit 1;output=$(makedhcp -q $$CN);[ $? check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]];then chdef -t node -o $$CN postscripts=setupntp; fi +cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "sles12.2" ]];then chdef -t node -o $$CN postscripts=setupntp; fi cmd:lsdef -l $$CN check:rc==0 cmd:rinstall $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute @@ -55,10 +55,10 @@ cmd:xdsh $$CN mount check:rc==0 cmd:sleep 120 #comment for further discussion -#cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]];then xdsh $$CN service ntpd status;fi +#cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "sles12.2" ]];then xdsh $$CN service ntpd status;fi #check:rc==0 #check:output=~running -cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]];then chdef -t node -o $$CN postscripts=" "; fi +cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "sles12.2" ]];then chdef -t node -o $$CN postscripts=" "; fi cmd:lsdef -l $$CN check:rc==0 cmd:ping $$CN -c 3 From 705556a368bdfd104af27abbef588cdddb606303 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 15 Mar 2017 10:50:05 -0400 Subject: [PATCH 095/187] Fix spelling mistake on 'dependency' --- xCAT-server/share/xcat/netboot/debian/genimage | 2 +- xCAT-server/share/xcat/netboot/fedora12/genimage | 2 +- xCAT-server/share/xcat/netboot/fedora12/geninitrd | 2 +- xCAT-server/share/xcat/netboot/rh/genimage | 4 ++-- xCAT-server/share/xcat/netboot/rh/genimage.rh4 | 2 +- xCAT-server/share/xcat/netboot/sles/genimage | 2 +- xCAT-server/share/xcat/netboot/ubuntu/genimage | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/xCAT-server/share/xcat/netboot/debian/genimage b/xCAT-server/share/xcat/netboot/debian/genimage index aa9afbe46..537e7d221 100755 --- a/xCAT-server/share/xcat/netboot/debian/genimage +++ b/xCAT-server/share/xcat/netboot/debian/genimage @@ -386,7 +386,7 @@ while (scalar @checkdeps) { unless (grep { $_ eq $dep } @ndrivers) { #only add if not added unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } } } diff --git a/xCAT-server/share/xcat/netboot/fedora12/genimage b/xCAT-server/share/xcat/netboot/fedora12/genimage index d108d0dcc..23f831ec4 100755 --- a/xCAT-server/share/xcat/netboot/fedora12/genimage +++ b/xCAT-server/share/xcat/netboot/fedora12/genimage @@ -384,7 +384,7 @@ while (scalar @checkdeps) { unless (grep { $_ eq $dep } @ndrivers) { #only add if not added unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } } } diff --git a/xCAT-server/share/xcat/netboot/fedora12/geninitrd b/xCAT-server/share/xcat/netboot/fedora12/geninitrd index 6eaa3fa92..95480753b 100755 --- a/xCAT-server/share/xcat/netboot/fedora12/geninitrd +++ b/xCAT-server/share/xcat/netboot/fedora12/geninitrd @@ -393,7 +393,7 @@ while (scalar @checkdeps) { unless (grep { $_ eq $dep } @ndrivers) { #only add if not added unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } } } diff --git a/xCAT-server/share/xcat/netboot/rh/genimage b/xCAT-server/share/xcat/netboot/rh/genimage index 17e06fd19..9a7e5d9e5 100755 --- a/xCAT-server/share/xcat/netboot/rh/genimage +++ b/xCAT-server/share/xcat/netboot/rh/genimage @@ -686,7 +686,7 @@ while (scalar @checkdeps) { foreach $dep (@deps) { $dep =~ s/.*\///; unless (grep { $_ eq $dep } @ndrivers) { #only add if not added - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); @@ -1140,7 +1140,7 @@ sub mkinitrd { unless (grep { $_ eq $dep } @ndrivers) { #only add if not added unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } } } diff --git a/xCAT-server/share/xcat/netboot/rh/genimage.rh4 b/xCAT-server/share/xcat/netboot/rh/genimage.rh4 index 7eb1d05fa..89c130c16 100755 --- a/xCAT-server/share/xcat/netboot/rh/genimage.rh4 +++ b/xCAT-server/share/xcat/netboot/rh/genimage.rh4 @@ -402,7 +402,7 @@ while (scalar @checkdeps) { unless (grep { $_ eq $dep } @ndrivers) { #only add if not added unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } } } diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index 0092945e9..84897d2ed 100755 --- a/xCAT-server/share/xcat/netboot/sles/genimage +++ b/xCAT-server/share/xcat/netboot/sles/genimage @@ -925,7 +925,7 @@ while (scalar @checkdeps) { foreach $dep (@deps) { $dep =~ s/.*\///; unless (grep { $_ eq $dep } @ndrivers) { #only add if not added - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); diff --git a/xCAT-server/share/xcat/netboot/ubuntu/genimage b/xCAT-server/share/xcat/netboot/ubuntu/genimage index 41ed2f46c..c8e6d139d 100755 --- a/xCAT-server/share/xcat/netboot/ubuntu/genimage +++ b/xCAT-server/share/xcat/netboot/ubuntu/genimage @@ -715,7 +715,7 @@ while (scalar @checkdeps) { unless (grep { $_ eq $dep } @ndrivers) { #only add if not added unshift(@checkdeps, $dep); #recursively check dependencies unshift(@ndrivers, $dep); - print "Added $dep as an autodetected depedency\n"; + print "Added $dep as an autodetected dependency\n"; } } } From 5793009eab6a2d51e356aafa0fad67bc596d79cf Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Mon, 20 Feb 2017 20:29:23 -0500 Subject: [PATCH 096/187] Support ssh based console in rcons for openbmc --- xCAT-server/lib/xcat/plugins/openbmc.pm | 65 ++++++++++++++- xCAT-server/share/xcat/cons/openbmc | 100 ++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 2 deletions(-) create mode 100755 xCAT-server/share/xcat/cons/openbmc diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 4ba2c2e82..fc4fb6678 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -1,11 +1,21 @@ #!/usr/bin/perl -## IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +#------------------------------------------------------- +=head1 + xCAT plugin package to handle openbmc + + Supported command: + getopenbmccons + +=cut + +#------------------------------------------------------- package xCAT_plugin::openbmc; BEGIN { - $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; } use lib "$::XCATROOT/lib/perl"; use strict; @@ -24,6 +34,10 @@ use JSON; $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; +my $VERBOSE = 0; +my %allerrornodes = (); +my $callback; + #------------------------------------------------------- =head3 handled_commands @@ -37,6 +51,7 @@ sub handled_commands { return { rpower => 'nodehm:mgt', rinv => 'nodehm:mgt', + getopenbmccons => 'nodehm:cons', }; } @@ -233,6 +248,33 @@ sub process_request { } } + + #Assume the openbmc user/password is defined in the passwd + my $passtab = xCAT::Table->new('passwd'); + if ($passtab) { + ($dba) = $passtab->getAttribs({key=>'openbmc'},qw(username password)); + if ($dba) { + if ($dba->{username}) { $username = $dba->{username}; } + if ($dba->{password}) { $password = $dba->{password}; } + } + } + + + foreach (@$noderange) { + my $node = $_; + my $nodeip = $node; + push @donargs, [ $node,$nodeip,$username, $password]; + my $output = "openbmc, get $username and $password from passwd table for $nodeip"; + xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes); + } + + + if ($request->{command}->[0] eq "getopenbmccons") { + foreach (@donargs) { + getopenbmccons($_, $callback); + } + return; + } return; } @@ -625,4 +667,23 @@ sub rinv_response { } +sub getopenbmccons { + my $argr = shift; + + #$argr is [$node,$nodeuser,$nodepass]; + my $callback = shift; + + my $rsp; + my $node=$argr->[0]; + my $output = "openbmc, getopenbmccoms"; + xCAT::SvrUtils::sendmsg($output, $callback, $argr->[0], %allerrornodes); + + $rsp = { node => [ { name => [ $argr->[0] ] } ] }; + $rsp->{node}->[0]->{nodeip}->[0] = $argr->[1]; + $rsp->{node}->[0]->{username}->[0] = $argr->[2]; + $rsp->{node}->[0]->{passwd}->[0] = $argr->[3]; + $callback->($rsp); + return $rsp; +} + 1; diff --git a/xCAT-server/share/xcat/cons/openbmc b/xCAT-server/share/xcat/cons/openbmc new file mode 100755 index 000000000..a83038a81 --- /dev/null +++ b/xCAT-server/share/xcat/cons/openbmc @@ -0,0 +1,100 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +use Fcntl qw(:DEFAULT :flock); +use Time::HiRes qw(sleep); +use File::Path; +BEGIN { + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; +} +my $sleepint = int(rand(10)); #Stagger start to avoid overwhelming conserver/xCATd +my ($lockfd, $nodeip); +my $username = 'UESRID'; +my $password = 'PASSWD'; +my $node = $ARGV[0]; + +use constant CONSOLE_LOCK_FILE => "/tmp/xcat/consolelock"; +use constant CONSOLE_LOCK_DIR => "/tmp/xcat"; + +sub acquire_lock { + umask 0077; + mkpath(CONSOLE_LOCK_DIR); + print "Acquiring startup lock..."; + unless (sysopen($lockfd, CONSOLE_LOCK_FILE, O_WRONLY | O_CREAT)) { + print "Unable to open file ".CONSOLE_LOCK_FILE."\n"; + sleep(15); + exit 1; + } + unless (flock($lockfd, LOCK_EX)) { + print "Unable to lock file ".CONSOLE_LOCK_FILE."\n"; + close($lockfd); + sleep(15); + exit 1; + } + print "done\n"; + unless (syswrite($lockfd, $$, length($$))) { + print "Unable to write file ".CONSOLE_LOCK_FILE."\n"; + close($lockfd); + sleep(15); + exit 1; + } +} + +sub release_lock { + flock($lockfd, LOCK_UN); + close($lockfd); +} + + +use lib "$::XCATROOT/lib/perl"; +require xCAT::Client; + +sub getans { + my $rsp = shift; + if ($rsp->{node}) { + $nodeip = $rsp->{node}->[0]->{nodeip}->[0]; + $username = $rsp->{node}->[0]->{username}->[0]; + $password = $rsp->{node}->[0]->{passwd}->[0]; + if (exists $rsp->{node}->[0]->{error}) { + my $error = $rsp->{node}->[0]->{error}->[0]; + print "$error\n"; + } + } +} +my $cmdref = { + command => ["getopenbmccons"], + arg => ["text"], + noderange => [ $ARGV[0] ] +}; +acquire_lock(); +# avoid of congestion +sleep(0.1); +release_lock(); +xCAT::Client::submit_request($cmdref, \&getans); + +until (($username or $password) and $nodeip ) { + #Let other clients have a go + $sleepint = 10 + int(rand(20)); + print "Console not ready, retrying in $sleepint seconds (Ctrl-e,c,o to skip delay) \n"; + sleep ($sleepint); + acquire_lock(); + sleep(0.1); + release_lock(); + xCAT::Client::submit_request($cmdref, \&getans); +} + +my $isintel = 0; +my $sleepint; +my $rc; + +my $sshport = 2200; +if ($ENV{SSHCONSOLEPORT}) { + $sshport= $ENV{SSHCONSOLEPORT}; +} + +#sshpass command needs to install before can run that +if (-x '/usr/bin/sshpass') { + exec "/usr/bin/sshpass -p $password ssh -p $sshport -l $username $nodeip"; +} else { + print "Please install sshpass first. \n"; +} + From 8a8c5a943ded374787e1f874d0fce59bc24e6e2a Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Tue, 28 Feb 2017 17:08:05 -0500 Subject: [PATCH 097/187] use mgt=ipmi instead of openbmc --- xCAT-server/lib/xcat/plugins/openbmc.pm | 35 ++++++++++++++++--------- xCAT-server/share/xcat/cons/openbmc | 7 +---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index fc4fb6678..84b32ab3c 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -31,6 +31,16 @@ use xCAT::SvrUtils; use File::Basename; use Data::Dumper; use JSON; +use Getopt::Long; +use File::Path; +use Term::ANSIColor; +use Time::Local; +use strict; +use Class::Struct; +use XML::Simple; +use Storable qw(dclone); +use SNMP; +use xCAT::PasswordUtils; $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; @@ -249,22 +259,23 @@ sub process_request { } - #Assume the openbmc user/password is defined in the passwd - my $passtab = xCAT::Table->new('passwd'); - if ($passtab) { - ($dba) = $passtab->getAttribs({key=>'openbmc'},qw(username password)); - if ($dba) { - if ($dba->{username}) { $username = $dba->{username}; } - if ($dba->{password}) { $password = $dba->{password}; } - } - } - + my $ipmitab = xCAT::Table->new('ipmi'); + my $ipmihash = $ipmitab->getNodesAttribs($noderange, [ 'bmc', 'username', 'password' ]); + my $authdata = xCAT::PasswordUtils::getIPMIAuth(noderange => $noderange, ipmihash => $ipmihash); foreach (@$noderange) { my $node = $_; my $nodeip = $node; - push @donargs, [ $node,$nodeip,$username, $password]; - my $output = "openbmc, get $username and $password from passwd table for $nodeip"; + my $nodeuser = $authdata->{$node}->{username}; + my $nodepass = $authdata->{$node}->{password}; + my $nodeip = $node; + my $ent; + if (defined($ipmitab)) { + $ent = $ipmihash->{$node}->[0]; + if (ref($ent) and defined $ent->{bmc}) { $nodeip = $ent->{bmc}; } + } + push @donargs, [ $node,$nodeip,$nodeuser, $nodepass]; + my $output = "openbmc, get $username and $password from ipmi table for $nodeip"; xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes); } diff --git a/xCAT-server/share/xcat/cons/openbmc b/xCAT-server/share/xcat/cons/openbmc index a83038a81..87a2a7a7b 100755 --- a/xCAT-server/share/xcat/cons/openbmc +++ b/xCAT-server/share/xcat/cons/openbmc @@ -91,10 +91,5 @@ if ($ENV{SSHCONSOLEPORT}) { $sshport= $ENV{SSHCONSOLEPORT}; } -#sshpass command needs to install before can run that -if (-x '/usr/bin/sshpass') { - exec "/usr/bin/sshpass -p $password ssh -p $sshport -l $username $nodeip"; -} else { - print "Please install sshpass first. \n"; -} +exec "ssh -p $sshport -l $username $nodeip"; From 20b71f888bf1fd87003853bd521cb52856a47cda Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Fri, 3 Mar 2017 14:26:42 -0500 Subject: [PATCH 098/187] Add support to config passwordless for openbmc --- xCAT-server/lib/xcat/plugins/openbmc.pm | 103 +++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 84b32ab3c..f99e3808b 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -41,6 +41,7 @@ use XML::Simple; use Storable qw(dclone); use SNMP; use xCAT::PasswordUtils; +use Expect; $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; @@ -282,6 +283,7 @@ sub process_request { if ($request->{command}->[0] eq "getopenbmccons") { foreach (@donargs) { + configssh($_, $callback); getopenbmccons($_, $callback); } return; @@ -688,7 +690,7 @@ sub getopenbmccons { my $node=$argr->[0]; my $output = "openbmc, getopenbmccoms"; xCAT::SvrUtils::sendmsg($output, $callback, $argr->[0], %allerrornodes); - + $rsp = { node => [ { name => [ $argr->[0] ] } ] }; $rsp->{node}->[0]->{nodeip}->[0] = $argr->[1]; $rsp->{node}->[0]->{username}->[0] = $argr->[2]; @@ -697,4 +699,103 @@ sub getopenbmccons { return $rsp; } +#------------------------------------------------------- + +=head3 configssh + + config passwordless for openbmc + +=cut + +#------------------------------------------------------- +sub configssh { + my $argr = shift; + my $callback = shift; + + my $rsp; + my $node=$argr->[0]; + my $bmcip = $argr->[1]; + my $bmcuser = $argr->[2]; + my $bmcpass = $argr->[3]; + my $timeout = 10; + + my $output = "openbmc, configssh "; + xCAT::SvrUtils::sendmsg($output, $callback, $argr->[0], %allerrornodes); + + my $rootkey = `cat /root/.ssh/id_rsa.pub`; + + # remove old host key from /root/.ssh/known_hosts + my $cmd = `ssh-keygen -R $bmcip`; + + my ($exp, $errstr) = openbmc_connect($bmcip, $bmcuser, $bmcpass, $timeout); + if (!defined $exp) { + print ("connect failed $errstr\n"); + next; + } + + my $ret; + my $err; + + ($ret, $err) = openbmc_exec($exp, "mkdir -p /home/root/.ssh"); + ($ret, $err) = openbmc_exec($exp, "chmod 700 /home/root/.ssh"); + ($ret, $err) = openbmc_exec($exp, "echo \"$rootkey\" >/home/root/.ssh/authorized_keys"); + ($ret, $err) = openbmc_exec($exp, "chmod 644 /home/root/.ssh/authorized_keys"); + + $exp->hard_close(); +} + +sub openbmc_connect { + my $server = shift; + my $userid = shift; + my $password = shift; + my $timeout = shift; + + my $ssh = Expect->new; + my $command = 'ssh'; + my @parameters = ($userid . "@" . $server); + + $ssh->debug(0); + $ssh->log_stdout(0); # suppress stdout output.. + $ssh->slave->stty(qw(sane -echo)); + + unless ($ssh->spawn($command, @parameters)) + { + my $err = $!; + $ssh->soft_close(); + my $rsp; + return(undef, "unable to run command $command $err\n"); + } + + $ssh->expect($timeout, + [ "-re", qr/WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED/, sub {die "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"; } ], + [ "-re", qr/\(yes\/no\)\?\s*$/, sub { $ssh->send("yes\n"); exp_continue; } ], + [ "-re", qr/ password:/, sub { $ssh->send("$password\n"); exp_continue; } ], + [ "-re", qr/:~\#/, sub { $ssh->clear_accum(); } ], + [ timeout => sub { die "No login.\n"; } ] + ); + $ssh->clear_accum(); + return ($ssh); +} + +sub openbmc_exec { + my $exp = shift; + my $cmd = shift; + my $timeout = shift; + my $prompt = shift; + + $timeout = 10 unless defined $timeout; + $prompt = qr/:~\#/ unless defined $prompt; + + $exp->clear_accum(); + $exp->send("$cmd\n"); + my ($mpos, $merr, $mstr, $mbmatch, $mamatch) = $exp->expect(6, "-re", $prompt); + + if (defined $merr) { + return(undef,$merr); + } + return($mbmatch); +} + + + 1; From 6112875d5d2ce3b7a5dbb68ccef5177548b7c128 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Tue, 7 Mar 2017 11:31:51 -0500 Subject: [PATCH 099/187] disable configssh routine --- xCAT-server/lib/xcat/plugins/openbmc.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index f99e3808b..72337c133 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -283,7 +283,7 @@ sub process_request { if ($request->{command}->[0] eq "getopenbmccons") { foreach (@donargs) { - configssh($_, $callback); + #configssh($_, $callback); getopenbmccons($_, $callback); } return; From a924cfffe50531680cf5f8af903df1bbf49bb5c5 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Thu, 9 Mar 2017 13:19:52 -0500 Subject: [PATCH 100/187] remove configssh routine --- xCAT-server/lib/xcat/plugins/openbmc.pm | 106 +----------------------- xCAT-server/share/xcat/cons/openbmc | 6 +- 2 files changed, 4 insertions(+), 108 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 72337c133..531bf70ba 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -1,5 +1,5 @@ #!/usr/bin/perl -# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +# IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html #------------------------------------------------------- =head1 @@ -37,11 +37,7 @@ use Term::ANSIColor; use Time::Local; use strict; use Class::Struct; -use XML::Simple; -use Storable qw(dclone); -use SNMP; use xCAT::PasswordUtils; -use Expect; $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; @@ -283,7 +279,6 @@ sub process_request { if ($request->{command}->[0] eq "getopenbmccons") { foreach (@donargs) { - #configssh($_, $callback); getopenbmccons($_, $callback); } return; @@ -699,103 +694,4 @@ sub getopenbmccons { return $rsp; } -#------------------------------------------------------- - -=head3 configssh - - config passwordless for openbmc - -=cut - -#------------------------------------------------------- -sub configssh { - my $argr = shift; - my $callback = shift; - - my $rsp; - my $node=$argr->[0]; - my $bmcip = $argr->[1]; - my $bmcuser = $argr->[2]; - my $bmcpass = $argr->[3]; - my $timeout = 10; - - my $output = "openbmc, configssh "; - xCAT::SvrUtils::sendmsg($output, $callback, $argr->[0], %allerrornodes); - - my $rootkey = `cat /root/.ssh/id_rsa.pub`; - - # remove old host key from /root/.ssh/known_hosts - my $cmd = `ssh-keygen -R $bmcip`; - - my ($exp, $errstr) = openbmc_connect($bmcip, $bmcuser, $bmcpass, $timeout); - if (!defined $exp) { - print ("connect failed $errstr\n"); - next; - } - - my $ret; - my $err; - - ($ret, $err) = openbmc_exec($exp, "mkdir -p /home/root/.ssh"); - ($ret, $err) = openbmc_exec($exp, "chmod 700 /home/root/.ssh"); - ($ret, $err) = openbmc_exec($exp, "echo \"$rootkey\" >/home/root/.ssh/authorized_keys"); - ($ret, $err) = openbmc_exec($exp, "chmod 644 /home/root/.ssh/authorized_keys"); - - $exp->hard_close(); -} - -sub openbmc_connect { - my $server = shift; - my $userid = shift; - my $password = shift; - my $timeout = shift; - - my $ssh = Expect->new; - my $command = 'ssh'; - my @parameters = ($userid . "@" . $server); - - $ssh->debug(0); - $ssh->log_stdout(0); # suppress stdout output.. - $ssh->slave->stty(qw(sane -echo)); - - unless ($ssh->spawn($command, @parameters)) - { - my $err = $!; - $ssh->soft_close(); - my $rsp; - return(undef, "unable to run command $command $err\n"); - } - - $ssh->expect($timeout, - [ "-re", qr/WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED/, sub {die "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"; } ], - [ "-re", qr/\(yes\/no\)\?\s*$/, sub { $ssh->send("yes\n"); exp_continue; } ], - [ "-re", qr/ password:/, sub { $ssh->send("$password\n"); exp_continue; } ], - [ "-re", qr/:~\#/, sub { $ssh->clear_accum(); } ], - [ timeout => sub { die "No login.\n"; } ] - ); - $ssh->clear_accum(); - return ($ssh); -} - -sub openbmc_exec { - my $exp = shift; - my $cmd = shift; - my $timeout = shift; - my $prompt = shift; - - $timeout = 10 unless defined $timeout; - $prompt = qr/:~\#/ unless defined $prompt; - - $exp->clear_accum(); - $exp->send("$cmd\n"); - my ($mpos, $merr, $mstr, $mbmatch, $mamatch) = $exp->expect(6, "-re", $prompt); - - if (defined $merr) { - return(undef,$merr); - } - return($mbmatch); -} - - - 1; diff --git a/xCAT-server/share/xcat/cons/openbmc b/xCAT-server/share/xcat/cons/openbmc index 87a2a7a7b..e309357df 100755 --- a/xCAT-server/share/xcat/cons/openbmc +++ b/xCAT-server/share/xcat/cons/openbmc @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +# IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html use Fcntl qw(:DEFAULT :flock); use Time::HiRes qw(sleep); use File::Path; @@ -8,8 +8,8 @@ BEGIN { } my $sleepint = int(rand(10)); #Stagger start to avoid overwhelming conserver/xCATd my ($lockfd, $nodeip); -my $username = 'UESRID'; -my $password = 'PASSWD'; +my $username = 'root'; +my $password = '0penBmc'; my $node = $ARGV[0]; use constant CONSOLE_LOCK_FILE => "/tmp/xcat/consolelock"; From 4fa11191789fc5c7113191ceecb8be53e015ac93 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Fri, 10 Mar 2017 14:23:46 -0500 Subject: [PATCH 101/187] change nodeip to bmcip --- xCAT-server/lib/xcat/plugins/openbmc.pm | 13 ++++++------- xCAT-server/share/xcat/cons/openbmc | 11 +++++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 531bf70ba..6c19cb4f4 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -262,17 +262,16 @@ sub process_request { foreach (@$noderange) { my $node = $_; - my $nodeip = $node; + my $bmcip; my $nodeuser = $authdata->{$node}->{username}; my $nodepass = $authdata->{$node}->{password}; - my $nodeip = $node; my $ent; if (defined($ipmitab)) { $ent = $ipmihash->{$node}->[0]; - if (ref($ent) and defined $ent->{bmc}) { $nodeip = $ent->{bmc}; } + if (ref($ent) and defined $ent->{bmc}) { $bmcip = $ent->{bmc}; } } - push @donargs, [ $node,$nodeip,$nodeuser, $nodepass]; - my $output = "openbmc, get $username and $password from ipmi table for $nodeip"; + push @donargs, [ $node,$bmcip,$nodeuser, $nodepass]; + my $output = "openbmc, get $username and $password from ipmi table for $bmcip"; xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes); } @@ -678,7 +677,7 @@ sub rinv_response { sub getopenbmccons { my $argr = shift; - #$argr is [$node,$nodeuser,$nodepass]; + #$argr is [$node,$bmcip,$nodeuser,$nodepass]; my $callback = shift; my $rsp; @@ -687,7 +686,7 @@ sub getopenbmccons { xCAT::SvrUtils::sendmsg($output, $callback, $argr->[0], %allerrornodes); $rsp = { node => [ { name => [ $argr->[0] ] } ] }; - $rsp->{node}->[0]->{nodeip}->[0] = $argr->[1]; + $rsp->{node}->[0]->{bmcip}->[0] = $argr->[1]; $rsp->{node}->[0]->{username}->[0] = $argr->[2]; $rsp->{node}->[0]->{passwd}->[0] = $argr->[3]; $callback->($rsp); diff --git a/xCAT-server/share/xcat/cons/openbmc b/xCAT-server/share/xcat/cons/openbmc index e309357df..172bb272e 100755 --- a/xCAT-server/share/xcat/cons/openbmc +++ b/xCAT-server/share/xcat/cons/openbmc @@ -7,7 +7,7 @@ BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; } my $sleepint = int(rand(10)); #Stagger start to avoid overwhelming conserver/xCATd -my ($lockfd, $nodeip); +my ($lockfd, $bmcip); my $username = 'root'; my $password = '0penBmc'; my $node = $ARGV[0]; @@ -51,13 +51,14 @@ require xCAT::Client; sub getans { my $rsp = shift; if ($rsp->{node}) { - $nodeip = $rsp->{node}->[0]->{nodeip}->[0]; + $bmcip = $rsp->{node}->[0]->{bmcip}->[0]; $username = $rsp->{node}->[0]->{username}->[0]; $password = $rsp->{node}->[0]->{passwd}->[0]; if (exists $rsp->{node}->[0]->{error}) { my $error = $rsp->{node}->[0]->{error}->[0]; print "$error\n"; } + print "$bmcip, $username, $password\n"; } } my $cmdref = { @@ -71,7 +72,7 @@ sleep(0.1); release_lock(); xCAT::Client::submit_request($cmdref, \&getans); -until (($username or $password) and $nodeip ) { +until (($username or $password) and $bmcip ) { #Let other clients have a go $sleepint = 10 + int(rand(20)); print "Console not ready, retrying in $sleepint seconds (Ctrl-e,c,o to skip delay) \n"; @@ -91,5 +92,7 @@ if ($ENV{SSHCONSOLEPORT}) { $sshport= $ENV{SSHCONSOLEPORT}; } -exec "ssh -p $sshport -l $username $nodeip"; +print "If the console cannot connect, please verify whether ssh keys has been configured on the bmc for $username user\n"; + +exec "ssh -p $sshport -l $username $bmcip"; From 033fa4fb41433812185964f03b6a5fb520f54312 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Wed, 15 Mar 2017 15:49:42 -0400 Subject: [PATCH 102/187] fix process_request routine after merge --- xCAT-server/lib/xcat/plugins/openbmc.pm | 77 +++++++++---------------- 1 file changed, 26 insertions(+), 51 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 6c19cb4f4..c89e0605a 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -1,21 +1,11 @@ #!/usr/bin/perl -# IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html -#------------------------------------------------------- +## IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html -=head1 - xCAT plugin package to handle openbmc - - Supported command: - getopenbmccons - -=cut - -#------------------------------------------------------- package xCAT_plugin::openbmc; BEGIN { - $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; } use lib "$::XCATROOT/lib/perl"; use strict; @@ -31,20 +21,9 @@ use xCAT::SvrUtils; use File::Basename; use Data::Dumper; use JSON; -use Getopt::Long; -use File::Path; -use Term::ANSIColor; -use Time::Local; -use strict; -use Class::Struct; -use xCAT::PasswordUtils; $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; -my $VERBOSE = 0; -my %allerrornodes = (); -my $callback; - #------------------------------------------------------- =head3 handled_commands @@ -154,6 +133,7 @@ my $async; my $cookie_jar; my $callback; +my %allerrornodes = (); #------------------------------------------------------- @@ -237,6 +217,7 @@ sub process_request { my $handle_id; my $content; $wait_node_num = keys %node_info; + my @donargs = (); foreach my $node (keys %node_info) { $bmcip = $node_info{$node}{bmc}; @@ -246,8 +227,18 @@ sub process_request { $handle_id_node{$handle_id} = $node; $node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }; print "$node: DEBUG POST $login_url -d $content\n"; + push @donargs, [ $node,$bmcip,$node_info{$node}{username}, $node_info{$node}{password}]; } + #process rcons + if ($request->{command}->[0] eq "getopenbmccons") { + foreach (@donargs) { + getopenbmccons($_, $callback); + } + return; + } + + while (1) { last unless ($wait_node_num); while (my ($response, $handle_id) = $async->wait_for_next_response) { @@ -255,33 +246,6 @@ sub process_request { } } - - my $ipmitab = xCAT::Table->new('ipmi'); - my $ipmihash = $ipmitab->getNodesAttribs($noderange, [ 'bmc', 'username', 'password' ]); - my $authdata = xCAT::PasswordUtils::getIPMIAuth(noderange => $noderange, ipmihash => $ipmihash); - - foreach (@$noderange) { - my $node = $_; - my $bmcip; - my $nodeuser = $authdata->{$node}->{username}; - my $nodepass = $authdata->{$node}->{password}; - my $ent; - if (defined($ipmitab)) { - $ent = $ipmihash->{$node}->[0]; - if (ref($ent) and defined $ent->{bmc}) { $bmcip = $ent->{bmc}; } - } - push @donargs, [ $node,$bmcip,$nodeuser, $nodepass]; - my $output = "openbmc, get $username and $password from ipmi table for $bmcip"; - xCAT::SvrUtils::sendmsg($output, $callback, $node, %allerrornodes); - } - - - if ($request->{command}->[0] eq "getopenbmccons") { - foreach (@donargs) { - getopenbmccons($_, $callback); - } - return; - } return; } @@ -330,6 +294,7 @@ sub parse_args { sub unsupported { my $callback = shift; + xCAT::SvrUtils::sendmsg("ENV: OPENBMC_DEVEL=$ENV{OPENBMC_DEVEL},$ENV{'OPENBMC_DEVEL'}\n", $callback); if ($::OPENBMC_DEVEL ne "YES") { return ([ 1, "This function is currently not supported" ]); } else { @@ -673,7 +638,15 @@ sub rinv_response { return; } +#------------------------------------------------------- +=head3 getopenbmccons + + Process getopenbmccons + +=cut + +#------------------------------------------------------- sub getopenbmccons { my $argr = shift; @@ -684,7 +657,7 @@ sub getopenbmccons { my $node=$argr->[0]; my $output = "openbmc, getopenbmccoms"; xCAT::SvrUtils::sendmsg($output, $callback, $argr->[0], %allerrornodes); - + $rsp = { node => [ { name => [ $argr->[0] ] } ] }; $rsp->{node}->[0]->{bmcip}->[0] = $argr->[1]; $rsp->{node}->[0]->{username}->[0] = $argr->[2]; @@ -693,4 +666,6 @@ sub getopenbmccons { return $rsp; } + + 1; From c66aadb0b79db3a12be8585b7eb4587dd4f862a6 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Wed, 15 Mar 2017 15:52:30 -0400 Subject: [PATCH 103/187] remove a debug message --- xCAT-server/lib/xcat/plugins/openbmc.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index c89e0605a..1bea4b1a5 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -294,7 +294,6 @@ sub parse_args { sub unsupported { my $callback = shift; - xCAT::SvrUtils::sendmsg("ENV: OPENBMC_DEVEL=$ENV{OPENBMC_DEVEL},$ENV{'OPENBMC_DEVEL'}\n", $callback); if ($::OPENBMC_DEVEL ne "YES") { return ([ 1, "This function is currently not supported" ]); } else { From 3e09eebec7d94a4f2ccc80e680a68910fe17aca8 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Thu, 16 Mar 2017 03:50:12 -0400 Subject: [PATCH 104/187] modify rhels7.3_ppc64.bundle for 2650 --- xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle index d679521ca..0303d2545 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle @@ -4,9 +4,7 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 -makehosts_h makehosts_help -makehosts_n makehosts_n_noderange updatenode_h updatenode_v @@ -44,10 +42,7 @@ chtab_modify_node chtab_modify_key chtab_h chtab_v -copycds_iso copycds_n -copycds_a -copycds_n_a copycds_a_err copycds_n_err packimage_o_p_a_m @@ -230,12 +225,10 @@ lsxcatd_h lsxcatd_d lsxcatd_a makehosts_h -makehosts_help makehosts_null makehosts_l makehosts_d makehosts_n -makehosts_n_noderange xdcp_src_dst makedns_h makedns_d_node @@ -259,7 +252,6 @@ confignics_disable_set_to_yes confignics_disable_set_to_1 confignics_s copycds_iso -copycds_n copycds_a copycds_n_a xdsh_h @@ -291,9 +283,6 @@ switchdiscover_range_r switchdiscover_range_x switchdiscover_range_z switchdiscover_range_z_V -nodeset_shell -nodeset_cmdline -nodeset_runimg makentp_v makentp_h nodeset_check_warninginfo From 7afa95b0fb4b4876268f8fa20ac0c3ba37a9d738 Mon Sep 17 00:00:00 2001 From: XuWei Date: Thu, 16 Mar 2017 22:51:39 -0400 Subject: [PATCH 105/187] Add warning message when OPENBMC_DEVEL is not YES in openbmc.pm --- xCAT-server/lib/xcat/plugins/openbmc.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 1bea4b1a5..505fe7588 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -272,19 +272,19 @@ sub parse_args { } if (scalar(@ARGV) > 1) { - return ([ 1, "Only one option is supportted at the same time" ]); + return ([ 1, "Only one option is supported at the same time" ]); } my $subcommand = $ARGV[0]; if ($command eq "rpower") { - if ($subcommand ne "on" and $subcommand ne "off" and $subcommand ne "reset" and $subcommand ne "status" and $subcommand ne "state" and $subcommand ne "stat" and $subcommand ne "boot") { + unless ($subcommand =~ /^on$|^off$|^reset$|^boot$|^status$|^stat$|^state$/) { return ([ 1, "$subcommand is not supported for rpower" ]); } } if ($command eq "rinv") { - if ($subcommand ne "cpu" and $subcommand ne "dimm" and $subcommand ne "bios" and $subcommand ne "all") { - return ([ 1, "Only 'cpu','dimm', 'bios','all' are supportted currently" ]); + unless ($subcommand =~ /^cpu$|^dimm$|^bios$|^all$/) { + return ([ 1, "Only 'cpu','dimm', 'bios','all' are supported currently" ]); } } @@ -295,7 +295,7 @@ sub parse_args { sub unsupported { my $callback = shift; if ($::OPENBMC_DEVEL ne "YES") { - return ([ 1, "This function is currently not supported" ]); + return ([ 1, "This function is currently not supported\nTo enable development code, run the following commands:\n\nexport OPENBMC_DEVEL=YES\nrestartxcatd" ]); } else { xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk\n", $callback); return; From b67145f860ba6e6f9855c45d0f589e7541006e3d Mon Sep 17 00:00:00 2001 From: XuWei Date: Thu, 16 Mar 2017 01:31:19 -0400 Subject: [PATCH 106/187] Add man page related with openbmc --- .../guides/admin-guides/references/man1/rpower.1.rst | 7 +++++++ perl-xCAT/xCAT/Usage.pm | 2 ++ xCAT-client/pods/man1/rpower.1.pod | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/docs/source/guides/admin-guides/references/man1/rpower.1.rst b/docs/source/guides/admin-guides/references/man1/rpower.1.rst index 9eda41449..26353ba44 100644 --- a/docs/source/guides/admin-guides/references/man1/rpower.1.rst +++ b/docs/source/guides/admin-guides/references/man1/rpower.1.rst @@ -111,6 +111,13 @@ pdu specific: \ **rpower**\ \ *noderange*\ [\ **stat | off | on**\ ] +OpenBMC (using Redfish) specific: +================================= + + +\ **rpower**\ \ *noderange*\ [\ **off | on | reset | boot | stat | state | status**\ ] + + *********** DESCRIPTION diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index 1b8e1d5c3..1b8a53f43 100755 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -53,6 +53,8 @@ my %usage = ( pdu specific: rpower noderange [off|on|stat] rpower noderange [pduoff|pduon|pdustat] + OpenBMC (using Redfish) specific: + rpower noderange [on|off|reset|boot|stat|state|status] ", "rbeacon" => "Usage: rbeacon [on|off|stat] [-V|--verbose] diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index d9ca23bf4..31ed50d28 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -60,6 +60,10 @@ B I [B|B|B|B|B|B B I [B|B|B] +=head2 OpenBMC (using Redfish) specific: + +B I [B|B|B|B|B|B|B] + =head1 DESCRIPTION B controls the power for a single or range of nodes, via the out-of-band path. From cd6c6c90d3efaca1c75fb6c100528fe3a57fe9c4 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Fri, 17 Mar 2017 04:43:10 -0400 Subject: [PATCH 107/187] modify diskeless hierarchy testcase for issue #2624 --- .../installation/reg_linux_diskless_installation_hierarchy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy index 0bb2aa173..187640357 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_hierarchy @@ -36,7 +36,8 @@ cmd:if cat /etc/*release |grep SUSE >/dev/null;then if [ ! -e /install/custom/ne check:rc==0 cmd:if cat /etc/*release |grep SUSE >/dev/null;then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/sles/compute.synclist; elif cat /etc/*release |grep "Red Hat" >/dev/null;then chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/rh/compute.synclist;fi check:rc==0 - +cmd:updatenode $$CN -f +check:rc==0 cmd:genimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute check:rc==0 cmd:packimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute From 76dc257538dd740a1a119bb784cce40b1cd20df9 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Fri, 17 Mar 2017 06:18:58 -0400 Subject: [PATCH 108/187] modify ppc64le bundle for rhels7.3 --- xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 9 --------- 1 file changed, 9 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index 4a8e312bb..7ad3e6fb1 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -149,13 +149,6 @@ nodestat_err_node rinv_noderange_err rmdef_null rmdef_t_err -rpower_off -rpower_stat -rpower_boot -rpower_on -rpower_reset -rpower_noderange -rpower_noderange_nodeps rpower_err_noderange rscan_noderange rscan_x @@ -164,7 +157,6 @@ rscan_w rscan_x_w rscan_z_w rvitals_lcds -rvitals_all rvitals_noderange_err tabdump_table tabdump_d @@ -290,7 +282,6 @@ nodeset_cmdline nodeset_runimg makentp_v makentp_h -nodeset_check_warninginfo runcmdinstaller_h runcmdinstaller_command get_xcat_postscripts_loginfo From 54fb8edcdbf708c535c84b95ec5e2c7be455f0c2 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Sun, 19 Mar 2017 21:00:45 -0400 Subject: [PATCH 109/187] remove duplicate copycds cases --- xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle | 1 - xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 5 ----- 2 files changed, 6 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle index 9b299d8e5..f44f53daf 100644 --- a/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle @@ -28,7 +28,6 @@ updatenode_diskful_syncfiles_P_script1 updatenode_script3 updatenode_P_script1_script2 updatenode_without_flag - chdef_null chdef_t_node chdef_t_network diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index 4a8e312bb..f44f53daf 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -56,7 +56,6 @@ packimage_o_p_a_m packimage_imagename packimage_h packimage_v - pping_h pping_v pping_node @@ -252,10 +251,6 @@ confignics_config_multiple_port_withnicaliases_multiple_value confignics_disable_set_to_yes confignics_disable_set_to_1 confignics_s -copycds_iso -copycds_n -copycds_a -copycds_n_a xdsh_h xdsh_V xdsh_regular_command From 891f4ee1050ee498573553af33c807844454280c Mon Sep 17 00:00:00 2001 From: bybai Date: Sun, 19 Mar 2017 23:22:27 -0400 Subject: [PATCH 110/187] fix issue 2657 --- xCAT-server/lib/xcat/plugins/hosts.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/hosts.pm b/xCAT-server/lib/xcat/plugins/hosts.pm index 6cfb16694..87daa39b2 100755 --- a/xCAT-server/lib/xcat/plugins/hosts.pm +++ b/xCAT-server/lib/xcat/plugins/hosts.pm @@ -74,7 +74,7 @@ sub addnode { if ($hosts[$idx] =~ /^${ip}\s/ - or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.r]/) + or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.\r]/) { if ($foundone) { From 98ef5adea24ac460b1c988ccdb4b01cf7afdeeda Mon Sep 17 00:00:00 2001 From: XuWei Date: Sun, 19 Mar 2017 21:37:33 -0400 Subject: [PATCH 111/187] modified depending on comments --- .../admin-guides/references/man1/rpower.1.rst | 14 +++++++------- perl-xCAT/xCAT/Usage.pm | 4 ++-- xCAT-client/pods/man1/rpower.1.pod | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man1/rpower.1.rst b/docs/source/guides/admin-guides/references/man1/rpower.1.rst index 26353ba44..ca436bd30 100644 --- a/docs/source/guides/admin-guides/references/man1/rpower.1.rst +++ b/docs/source/guides/admin-guides/references/man1/rpower.1.rst @@ -32,6 +32,13 @@ BMC (using IPMI) specific: \ **rpower**\ \ *noderange*\ [\ **pduon | pduoff | pdustat**\ ] +OpenBMC specific: +================= + + +\ **rpower**\ \ *noderange*\ [\ **off | on | reset | boot | stat | state | status**\ ] + + PPC (with IVM or HMC) specific: =============================== @@ -111,13 +118,6 @@ pdu specific: \ **rpower**\ \ *noderange*\ [\ **stat | off | on**\ ] -OpenBMC (using Redfish) specific: -================================= - - -\ **rpower**\ \ *noderange*\ [\ **off | on | reset | boot | stat | state | status**\ ] - - *********** DESCRIPTION diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index 1b8a53f43..c7f7bb3ef 100755 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -26,6 +26,8 @@ my %usage = ( "rpower" => "Usage: rpower [--nodeps] [on|onstandby|off|suspend|reset|stat|state|boot] [-V|--verbose] [-m table.colum==expectedstatus][-m table.colum==expectedstatus...] [-r ] [-t ] rpower [-h|--help|-v|--version] + OpenBMC specific: + rpower noderange [on|off|reset|boot|stat|state|status] KVM Virtualization specific: rpower [boot] [ -c ] PPC (with IVM or HMC) specific: @@ -53,8 +55,6 @@ my %usage = ( pdu specific: rpower noderange [off|on|stat] rpower noderange [pduoff|pduon|pdustat] - OpenBMC (using Redfish) specific: - rpower noderange [on|off|reset|boot|stat|state|status] ", "rbeacon" => "Usage: rbeacon [on|off|stat] [-V|--verbose] diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index 31ed50d28..bc8a0e062 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -14,6 +14,10 @@ B I [B|B|B|B|B|B|B I [B|B|B] +=head2 OpenBMC specific: + +B I [B|B|B|B|B|B|B] + =head2 PPC (with IVM or HMC) specific: B I [B<--nodeps>] {B} @@ -60,10 +64,6 @@ B I [B|B|B|B|B|B B I [B|B|B] -=head2 OpenBMC (using Redfish) specific: - -B I [B|B|B|B|B|B|B] - =head1 DESCRIPTION B controls the power for a single or range of nodes, via the out-of-band path. From 23d3a046ccaefe99e98454c09f3bba3558974f6c Mon Sep 17 00:00:00 2001 From: immarvin Date: Mon, 20 Mar 2017 13:32:30 +0800 Subject: [PATCH 112/187] fix issue [DEV] Install xcat on ubuntu14.4.4+ppc64le by go-xcat show "Restarting xcatd ERROR:". That is why Diskless_installation_flat_p8_le always fail and stay on powering_on`` --- xCAT-server/lib/xcat/plugins/AAsn.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/AAsn.pm b/xCAT-server/lib/xcat/plugins/AAsn.pm index 2bf735b03..40b90d15a 100755 --- a/xCAT-server/lib/xcat/plugins/AAsn.pm +++ b/xCAT-server/lib/xcat/plugins/AAsn.pm @@ -1279,7 +1279,7 @@ sub setup_HTTP #----------------------------------------------------------------------------- sub stop_TFTP { - my $distro; + my $distro=xCAT::Utils->osver(); # Check whether the tftp-hpa has been installed, the ubuntu tftpd-hpa configure file is under /etc/default unless (-x "/usr/sbin/in.tftpd" and (-e "/etc/xinetd.d/tftp" or -e "/etc/default/tftpd-hpa")) { xCAT::MsgUtils->message("S", "ERROR: The tftpd was not installed, enable the tftp failed."); From 936c35814b2823995d49295b761527bd79edacf1 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Mon, 20 Mar 2017 14:31:12 +0800 Subject: [PATCH 113/187] Update the test case for "updatenode -S", and check if package gcc is really installed on the compute node --- xCAT-test/autotest/testcase/updatenode/cases2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xCAT-test/autotest/testcase/updatenode/cases2 b/xCAT-test/autotest/testcase/updatenode/cases2 index 06201a066..f413ff7b7 100644 --- a/xCAT-test/autotest/testcase/updatenode/cases2 +++ b/xCAT-test/autotest/testcase/updatenode/cases2 @@ -15,4 +15,6 @@ check:rc==0 cmd:grep 'Running of Software Maintenance has completed' /tmp/updatenode.S.out check:rc==0 cmd:mv `cat /tmp/pkglist.filename`.save `cat /tmp/pkglist.filename` +cmd:xdsh $$CN '(rpm -qa || dpkg -l) | grep gcc' | grep gcc +check:rc==0 end From fd0e6aa3e3630d78f37e5548ad3b476ac65064e5 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Mon, 20 Mar 2017 14:59:23 +0800 Subject: [PATCH 114/187] More reasonable error message when open() file failed. --- xCAT-test/autotest/testcase/installation/pre_deploy_sn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/pre_deploy_sn b/xCAT-test/autotest/testcase/installation/pre_deploy_sn index d46f49564..a4c30001a 100755 --- a/xCAT-test/autotest/testcase/installation/pre_deploy_sn +++ b/xCAT-test/autotest/testcase/installation/pre_deploy_sn @@ -20,7 +20,7 @@ if ($ENV{XCAT_DATABASE} eq "PostgreSQL") { $cmd = "XCATPGPW=12345 /opt/xcat/bin/pgsqlsetup -i -V"; runcmd("$cmd"); - open(my $fh, '>>', '/var/lib/pgsql/data/pg_hba.conf') or die; + open(my $fh, '>>', '/var/lib/pgsql/data/pg_hba.conf') or die("failed open file /var/lib/pgsql/data/pg_bha.conf"); print $fh "host all all 0.0.0.0/0 md5\n"; print $fh "host all all ::0/0 md5\n"; close $fh; From da8222ad777b5a0b45a00001bd96fc9684d93842 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 20 Mar 2017 03:12:37 -0400 Subject: [PATCH 115/187] modify diskfull testcase for intergration --- .../installation/reg_linux_diskfull_installation_flat | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat index 56d8b37b4..7b9fd6e71 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat @@ -32,7 +32,8 @@ cmd:a=0;while true; do [ $a -eq 100 ] && exit 1;output=$(makedhcp -q $$CN);[ $? check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "sles12.2" ]];then chdef -t node -o $$CN postscripts=setupntp; fi +cmd:if ! ([[ "__GETNODEATTR($$CN,os)__" = "sles12.1" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "ubuntu" && "__GETNODEATTR($$CN,arch)__" = "x86_64" ]]) ; then chdef -t node -o $$CN postscripts=setupntp; fi +check:rc==0 cmd:lsdef -l $$CN check:rc==0 cmd:rinstall $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute @@ -55,10 +56,10 @@ cmd:xdsh $$CN mount check:rc==0 cmd:sleep 120 #comment for further discussion -#cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "sles12.2" ]];then xdsh $$CN service ntpd status;fi +#cmd:if ! ([[ "__GETNODEATTR($$CN,os)__" = "sles12.1" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "ubuntu" && "__GETNODEATTR($$CN,arch)__" = "x86_64" ]]) ;then xdsh $$CN service ntpd status;fi #check:rc==0 #check:output=~running -cmd:if [[ "__GETNODEATTR($$CN,os)__" =~ "sles11" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "rhels" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "sles12.2" ]];then chdef -t node -o $$CN postscripts=" "; fi +cmd:if ! ([[ "__GETNODEATTR($$CN,os)__" = "sles12.1" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "ubuntu" && "__GETNODEATTR($$CN,arch)__" = "x86_64" ]]) ;then chdef -t node -o $$CN -m postscripts="setupntp"; fi cmd:lsdef -l $$CN check:rc==0 cmd:ping $$CN -c 3 From ef53d65b5e8c4b7c0161b69c3ad5ea5b7b981529 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 20 Mar 2017 03:48:37 -0400 Subject: [PATCH 116/187] modify testcase for intergration --- .../testcase/installation/reg_linux_diskless_installation_flat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat index 99c2e6773..320f90f10 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskless_installation_flat @@ -24,7 +24,7 @@ check:rc==0 cmd:copycds $$ISO check:rc==0 -cmd:rootimgdir=`lsdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute|grep rootimgdir|awk -F'=' '{print $2}'`; if [ -d $rootimgdir ]; then `mv $rootimgdir $rootimgdir.regbak -f`;fi +cmd:rootimgdir=`lsdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute|grep rootimgdir|awk -F'=' '{print $2}'`; if [ -d $rootimgdir ]; then mv $rootimgdir $rootimgdir.regbak -f;fi check:rc==0 cmd:if cat /etc/*release |grep SUSE >/dev/null;then if [ ! -d /install/custom/netboot/sles ]; then mkdir -p /install/custom/netboot/sles; fi; elif cat /etc/*release |grep "Red Hat" >/dev/null;then if [ ! -d /install/custom/netboot/rh ]; then mkdir -p /install/custom/netboot/rh; fi; elif cat /etc/*release |grep "Ubuntu" >/dev/null;then if [ ! -d /install/custom/netboot/ubuntu ]; then mkdir -p /install/custom/netboot/ubuntu; fi; fi From f45f19fa187ab0c9959d239e0a6c418a07d04e5a Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 20 Mar 2017 07:14:12 -0400 Subject: [PATCH 117/187] modify testcase for intergration --- .../testcase/installation/reg_linux_diskfull_installation_flat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat index 7b9fd6e71..c79c7387c 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_flat @@ -60,8 +60,8 @@ cmd:sleep 120 #check:rc==0 #check:output=~running cmd:if ! ([[ "__GETNODEATTR($$CN,os)__" = "sles12.1" ]] || [[ "__GETNODEATTR($$CN,os)__" =~ "ubuntu" && "__GETNODEATTR($$CN,arch)__" = "x86_64" ]]) ;then chdef -t node -o $$CN -m postscripts="setupntp"; fi -cmd:lsdef -l $$CN check:rc==0 +cmd:lsdef -l $$CN cmd:ping $$CN -c 3 check:rc==0 check:output=~64 bytes from $$CN From cc8129ec0f420f1c58e5e42a7e55ce29c0afc33e Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 20 Mar 2017 07:53:05 -0400 Subject: [PATCH 118/187] modidfy rhels7.3 ppc64le --- xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index 7ad3e6fb1..e88e7a2e0 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -149,6 +149,13 @@ nodestat_err_node rinv_noderange_err rmdef_null rmdef_t_err +rpower_off +rpower_stat +rpower_boot +rpower_on +rpower_reset +rpower_noderange +rpower_noderange_nodeps rpower_err_noderange rscan_noderange rscan_x @@ -282,6 +289,7 @@ nodeset_cmdline nodeset_runimg makentp_v makentp_h +nodeset_check_warninginfo runcmdinstaller_h runcmdinstaller_command get_xcat_postscripts_loginfo From 848b50c8acd7df034e74e24318d77d3ae7364df8 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Mon, 20 Mar 2017 17:09:12 +0800 Subject: [PATCH 119/187] Do cleanup --- xCAT-test/autotest/testcase/updatenode/cases2 | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-test/autotest/testcase/updatenode/cases2 b/xCAT-test/autotest/testcase/updatenode/cases2 index f413ff7b7..9ba8c73e5 100644 --- a/xCAT-test/autotest/testcase/updatenode/cases2 +++ b/xCAT-test/autotest/testcase/updatenode/cases2 @@ -15,6 +15,7 @@ check:rc==0 cmd:grep 'Running of Software Maintenance has completed' /tmp/updatenode.S.out check:rc==0 cmd:mv `cat /tmp/pkglist.filename`.save `cat /tmp/pkglist.filename` +cmd:rm -f /tmp/pkglist.filename cmd:xdsh $$CN '(rpm -qa || dpkg -l) | grep gcc' | grep gcc check:rc==0 end From 56f38f5f0cb38bfacb9403922c6d079937163e58 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 20 Mar 2017 08:20:44 -0400 Subject: [PATCH 120/187] modify bundle for issue #2670 --- xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle | 4 ---- xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle | 4 ---- xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 4 ---- 3 files changed, 12 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle index fe2dee644..be7019aea 100644 --- a/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle @@ -4,8 +4,6 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 -makehosts_h -makehosts_help makehosts_n makehosts_n_noderange updatenode_h @@ -234,8 +232,6 @@ makehosts_help makehosts_null makehosts_l makehosts_d -makehosts_n -makehosts_n_noderange xdcp_src_dst makedns_h makedns_d_node diff --git a/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle index f44f53daf..179d2109b 100644 --- a/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.2_ppc64le.bundle @@ -6,10 +6,6 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 -makehosts_h -makehosts_help -makehosts_n -makehosts_n_noderange updatenode_h updatenode_v updatenode_diskful_syncfiles diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index f44f53daf..179d2109b 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -6,10 +6,6 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 -makehosts_h -makehosts_help -makehosts_n -makehosts_n_noderange updatenode_h updatenode_v updatenode_diskful_syncfiles From 57e90bbf96e1ca139de9d37cee2c3a14e9d2e406 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Mon, 20 Mar 2017 12:04:21 -0400 Subject: [PATCH 121/187] Move the unsupported function to the top and reword slightly --- xCAT-server/lib/xcat/plugins/openbmc.pm | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 505fe7588..8505125d0 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -24,6 +24,18 @@ use JSON; $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; + +sub unsupported { + my $callback = shift; + if (defined($::OPENBMC_DEVEL) && ($::OPENBMC_DEVEL eq "YES")) { + xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk. Unset OPENBMC_DEVEL and `restartxcatd` to disable.\n", $callback); + return; + } else { + return ([ 1, "This openbmc related function is unsupported and disabled. To bypass, run the following: \n\texport OPENBMC_DEVEL=YES\n\trestartxcatd" ]); + } +} + + #------------------------------------------------------- =head3 handled_commands @@ -291,17 +303,6 @@ sub parse_args { return; } - -sub unsupported { - my $callback = shift; - if ($::OPENBMC_DEVEL ne "YES") { - return ([ 1, "This function is currently not supported\nTo enable development code, run the following commands:\n\nexport OPENBMC_DEVEL=YES\nrestartxcatd" ]); - } else { - xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk\n", $callback); - return; - } -} - #------------------------------------------------------- =head3 parse_command_status From 7b227192f626d2f3a2d4c4819ce8de75fbe8dca9 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Mon, 20 Mar 2017 12:10:03 -0400 Subject: [PATCH 122/187] Move the rpower usage checking under the rpower option --- xCAT-server/lib/xcat/plugins/openbmc.pm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 8505125d0..95e332bd8 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -279,16 +279,15 @@ sub parse_args { return $check; } - if (!defined($extrargs)) { - return ([ 1, "No option specified for rpower" ]); - } - if (scalar(@ARGV) > 1) { return ([ 1, "Only one option is supported at the same time" ]); } my $subcommand = $ARGV[0]; if ($command eq "rpower") { + if (!defined($extrargs)) { + return ([ 1, "No option specified for rpower" ]); + } unless ($subcommand =~ /^on$|^off$|^reset$|^boot$|^status$|^stat$|^state$/) { return ([ 1, "$subcommand is not supported for rpower" ]); } From b045fe79f0813cfd9b208ba91eda6903d3eb6096 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Mon, 20 Mar 2017 12:18:03 -0400 Subject: [PATCH 123/187] Move the unsupported call to each command support to control what is supported and unsupported at a finer level --- xCAT-server/lib/xcat/plugins/openbmc.pm | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 95e332bd8..2f346e45c 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -273,11 +273,7 @@ sub process_request { sub parse_args { my $command = shift; my $extrargs = shift; - - my $check = unsupported($callback); - if (ref($check) eq "ARRAY") { - return $check; - } + my $check = undef; if (scalar(@ARGV) > 1) { return ([ 1, "Only one option is supported at the same time" ]); @@ -285,6 +281,12 @@ sub parse_args { my $subcommand = $ARGV[0]; if ($command eq "rpower") { + # + # disable function until fully tested + # + $check = unsupported($callback); + if (ref($check) eq "ARRAY") { return $check; } + if (!defined($extrargs)) { return ([ 1, "No option specified for rpower" ]); } @@ -294,6 +296,13 @@ sub parse_args { } if ($command eq "rinv") { + # + # disable function until fully tested + # + $check = unsupported($callback); + if (ref($check) eq "ARRAY") { return $check; } + + unless ($subcommand =~ /^cpu$|^dimm$|^bios$|^all$/) { return ([ 1, "Only 'cpu','dimm', 'bios','all' are supported currently" ]); } From b831595b70f02b52946fefeecf12327a0d2a04e7 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Mon, 20 Mar 2017 13:12:16 -0400 Subject: [PATCH 124/187] Add the same handled commands from ipmi.pm and a generic clause that will print Unsupported --- xCAT-server/lib/xcat/plugins/openbmc.pm | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 2f346e45c..4d611aff0 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -50,6 +50,17 @@ sub handled_commands { rpower => 'nodehm:mgt', rinv => 'nodehm:mgt', getopenbmccons => 'nodehm:cons', + rsetboot => 'nodehm:mgt', + rspconfig => 'nodehm:mgt', + rvitals => 'nodehm:mgt', + rflash => 'nodehm:mgt', + reventlog => 'nodehm:mgt', + rspreset => 'nodehm:mgt', + rbeacon => 'nodehm:mgt', + renergy => 'nodehm:mgt', + rscan => 'nodehm:mgt', + ripmi => 'ipmi', + getrvidparms => 'nodehm:mgt', }; } @@ -284,8 +295,7 @@ sub parse_args { # # disable function until fully tested # - $check = unsupported($callback); - if (ref($check) eq "ARRAY") { return $check; } + $check = unsupported($callback); if (ref($check) eq "ARRAY") { return $check; } if (!defined($extrargs)) { return ([ 1, "No option specified for rpower" ]); @@ -293,19 +303,18 @@ sub parse_args { unless ($subcommand =~ /^on$|^off$|^reset$|^boot$|^status$|^stat$|^state$/) { return ([ 1, "$subcommand is not supported for rpower" ]); } - } - - if ($command eq "rinv") { + } elsif ($command eq "rinv") { # # disable function until fully tested # - $check = unsupported($callback); - if (ref($check) eq "ARRAY") { return $check; } + $check = unsupported($callback); if (ref($check) eq "ARRAY") { return $check; } unless ($subcommand =~ /^cpu$|^dimm$|^bios$|^all$/) { return ([ 1, "Only 'cpu','dimm', 'bios','all' are supported currently" ]); } + } else { + return ([ 1, "Command is not supported." ]); } return; From 4e1d4629a9230d60a9468932e9fea65f3fd864b6 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Mon, 20 Mar 2017 13:19:39 -0400 Subject: [PATCH 125/187] Preserve the user ownership of the file for xdcp command --- perl-xCAT/xCAT/DSHCLI.pm | 11 +++++++++++ xCAT-client/bin/xdsh | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index 8121f475d..2fa5c5a14 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -4434,6 +4434,17 @@ sub parse_and_run_dcp return 0; } + unless ($options{'user'}) + { + # user was not specified with -l flag, check it user calling the command + # was saved in DSH_FROM_USERID environment variable + my $current_userid = $ENV{'DSH_FROM_USERID'}; + if (defined($current_userid)) { + # Set userid from value in DSH_FROM_USERID environment variable + $options{'user'} = $current_userid; + } + } + if (defined($options{'rootimg'})) { if (xCAT::Utils->isAIX()) diff --git a/xCAT-client/bin/xdsh b/xCAT-client/bin/xdsh index 0797f4d93..cad1bf394 100644 --- a/xCAT-client/bin/xdsh +++ b/xCAT-client/bin/xdsh @@ -666,6 +666,24 @@ sub parse_args_xdcp $::NODE_RCP = 1; } + # find out who is the current user running xdcp + my $current_userid = getpwuid($>); + + $ENV{DSH_FROM_USERID} = $current_userid; + + my $to_userid; + if ($options{'user'}) # if -l option + { + $to_userid = $options{'user'}; + } + else + { + $to_userid = $current_userid; + } + # Save userid running this command in ENV variable. + # It will be later extraced by DSHCLI.pm + $ENV{DSH_TO_USERID} = $to_userid; + if ($options{'bypass'}) { $ENV{XCATBYPASS} = "yes"; # bypass xcatd From 2bf5b57eb0579d4856bc9335fc38ce02a258fe85 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Mon, 20 Mar 2017 13:29:19 -0400 Subject: [PATCH 126/187] Change the endpoint urls into variables --- xCAT-server/lib/xcat/plugins/openbmc.pm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 4d611aff0..a538b8590 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -28,7 +28,7 @@ $::OPENBMC_DEVEL = $ENV{'OPENBMC_DEVEL'}; sub unsupported { my $callback = shift; if (defined($::OPENBMC_DEVEL) && ($::OPENBMC_DEVEL eq "YES")) { - xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk. Unset OPENBMC_DEVEL and `restartxcatd` to disable.\n", $callback); + xCAT::SvrUtils::sendmsg("Warning: Currently running development code, use at your own risk. Unset OPENBMC_DEVEL and `restartxcatd` to disable.", $callback); return; } else { return ([ 1, "This openbmc related function is unsupported and disabled. To bypass, run the following: \n\texport OPENBMC_DEVEL=YES\n\trestartxcatd" ]); @@ -64,7 +64,8 @@ sub handled_commands { }; } -my $pre_url = "/org/openbmc"; +my $openbmc_url = "/org/openbmc"; +my $openbmc_project_url = "/xyz/openbmc_project"; #------------------------------------------------------- # The hash table to store method and url for request, @@ -82,7 +83,7 @@ my %status_info = ( RPOWER_ON_REQUEST => { method => "PUT", - init_url => "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition", + init_url => "$openbmc_project_url/state/host0/attr/RequestedHostTransition", data => "xyz.openbmc_project.State.Host.Transition.On", }, RPOWER_ON_RESPONSE => { @@ -90,7 +91,7 @@ my %status_info = ( }, RPOWER_OFF_REQUEST => { method => "PUT", - init_url => "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition", + init_url => "$openbmc_project_url/state/host0/attr/RequestedHostTransition", data => "xyz.openbmc_project.State.Host.Transition.Off", }, RPOWER_OFF_RESPONSE => { @@ -98,7 +99,7 @@ my %status_info = ( }, RPOWER_RESET_REQUEST => { method => "PUT", - init_url => "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition", + init_url => "$openbmc_project_url/state/host0/attr/RequestedHostTransition", data => "xyz.openbmc_project.State.Host.Transition.Reboot", }, RPOWER_RESET_RESPONSE => { @@ -106,7 +107,7 @@ my %status_info = ( }, RPOWER_STATUS_REQUEST => { method => "GET", - init_url => "/xyz/openbmc_project/state/host0", + init_url => "$openbmc_project_url/state/host0", }, RPOWER_STATUS_RESPONSE => { process => \&rpower_response, @@ -114,7 +115,7 @@ my %status_info = ( RINV_REQUEST => { method => "GET", - init_url => "$pre_url/inventory/enumerate", + init_url => "$openbmc_url/inventory/enumerate", }, RINV_RESPONSE => { process => \&rinv_response, From f78c9320cce867c0ea5f64576306ebcd6369356c Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Mon, 20 Mar 2017 17:33:55 -0400 Subject: [PATCH 127/187] Fix links and formatting --- docs/source/advanced/security/security.rst | 23 ++++++++++--------- .../manage_clusters/common/parallel_cmd.rst | 16 ++++++------- .../install-guides/apt/prepare_mgmt_node.rst | 2 ++ .../zypper/prepare_mgmt_node.rst | 2 ++ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/source/advanced/security/security.rst b/docs/source/advanced/security/security.rst index 7f2e4ab3b..32d9b9c4e 100644 --- a/docs/source/advanced/security/security.rst +++ b/docs/source/advanced/security/security.rst @@ -14,29 +14,30 @@ Commands Access Control Except SSL channel, xCAT only authorize root on the management node to run **xCAT** commands by default. But xCAT can be configured to allow both **non-root users** and **remote users** to run limited xCAT commands. For remote users, we mean the users who triggers the xCAT commands from other nodes and not have to login to the management node. xCAT uses the **policy** table to control who has authority to run specific xCAT commands. For a full explanation of the **policy** table, refer to :doc:`policy ` man page. +.. _granting_xcat_privileges: Granting Users xCAT Privileges `````````````````````````````` -To give a non-root user all xCAT commands privileges, run ``tabedit policy`` and add a line: :: +To give a non-root user all xCAT command privileges, run ``tabedit policy`` and add a line: :: "6","",,,,,,"allow",, -Where is the name of the user that you are granting privileges to. In the above case, this user can now perform all xCAT commands, including changing the ``policy`` table to grant right to other users, so this should be used with caution. +Where is the name of the user that you are granting privileges to. This user can now perform all xCAT commands, including changing the ``policy`` table to grant rights to other users, so this should be used with caution. -You may only want to grant users limited access. One example is that one user may only be allowed to run ``nodels``. This can be done as follows: :: +To grant a user ability to run ``nodels`` command: :: "6","",,"nodels",,,,"allow",, -If you want to grant all users the ability to run nodels, add this line: :: +To grant all users the ability to run ``nodels``: :: "6.1","*",,"nodels",,,,"allow",, -You also can do this by running: :: +CLI can also be used: :: chdef -t policy -o 6.1 name=* commands=nodels rule=allow -**Note** Make sure the directories that contain the xCAT commands are in the user's ``$PATH``. If not, add them to ``$PATH`` as appropriate way in your system. :: +**Note** Make sure the directories that contain the xCAT commands are in the user's ``$PATH``. If not, add them to ``$PATH`` as appropriate in your system. :: echo $PATH | grep xcat /opt/xcat/bin:/opt/xcat/sbin: ....... @@ -44,18 +45,18 @@ You also can do this by running: :: Extra Setup for Remote Commands ``````````````````````````````` -To give a user the ability to run remote commands (xdsh, xdcp, psh, pcp) in some node, except above steps, also need to run below steps: :: +To give a user the ability to run remote commands (``xdsh``, ``xdcp``, ``psh``, ``pcp``) in some node, in addition to above steps, also need to run below steps: :: su - xdsh -K -This will setup the user and root ssh keys for the user under the ``$HOME/.ssh`` directory of the user on the nodes. The root ssh keys are needed for the user to run the xCAT commands under the xcatd daemon, where the user will be running as root. **Note**: the uid for the user should match the uid on the management node and a password for the user must have been set on the nodes. +This will setup the user and root ssh keys for the user under the ``$HOME/.ssh`` directory of the user on the nodes. The root ssh keys are needed for the user to run the xCAT commands under the xcatd daemon, where the user will be running as root. **Note**: the uid and the password for the user on the management node, should match the uid and password on the managed nodes. Set Up Login Node (Remote Client) ````````````````````````````````` -In some cases, you don't want your **non-root** user login to management node but still can run some xCAT commands. This time, you need setup a login node(i.e. remote client) for these users. +In some cases, you don't want your **non-root** user login to management node but still can run some xCAT commands. This time, you need setup a login node (i.e. remote client) for these users. Below are the steps of how to set up a login node. @@ -65,9 +66,9 @@ Below are the steps of how to set up a login node. * :doc:`Configure xCAT Software Repository in RHEL` - * `Configure the Base OS Repository in SUSE `_ + * :ref:`Configure the Base OS Repository in SUSE ` - * `Configure the Base OS Repository in Ubuntu `_ + * :ref:`Configure the Base OS Repository in Ubuntu ` Then install ``xCAT-client``. diff --git a/docs/source/guides/admin-guides/manage_clusters/common/parallel_cmd.rst b/docs/source/guides/admin-guides/manage_clusters/common/parallel_cmd.rst index 3c9a59790..f1ad71ba3 100644 --- a/docs/source/guides/admin-guides/manage_clusters/common/parallel_cmd.rst +++ b/docs/source/guides/admin-guides/manage_clusters/common/parallel_cmd.rst @@ -25,11 +25,11 @@ Examples for xdsh xdsh node1 -K -- To run the ps -ef command on node targets node1 and node2, enter: :: +- To run the ``ps -ef`` command on node targets node1 and node2, enter: :: xdsh node1,node2 "ps -ef" -- To run the ps command on node targets node1 and run the remote command with the -v and -t flag, enter: :: +- To run the ``ps`` command on node targets node1 and run the remote command with the ``-v`` and ``-t`` flag, enter: :: xdsh node1,node2 -o"-v -t" ps =item * @@ -37,15 +37,15 @@ Examples for xdsh xdsh node1,node2 -f 1 -e myfile -- To run the ps command on node1 and ignore all the dsh environment variable except the DSH_NODE_OPTS, enter: :: +- To run the ``ps`` command on node1 and ignore all the dsh environment variable except the DSH_NODE_OPTS, enter: :: xdsh node1 -X `DSH_NODE_OPTS' ps -- To run on Linux, the xdsh command "dpkg | grep vim" on the node ubuntu diskless image, enter: :: +- To run on Linux, the ``xdsh`` command ``dpkg -l| grep vim`` on the node ubuntu diskless image, enter: :: xdsh -i /install/netboot/ubuntu14.04.2/ppc64el/compute/rootimg "dpkg -l|grep vim" -- To run xdsh with the non-root userid "user1" that has been setup as an xCAT userid and with sudo on node1 and node2 to run as root, do the following, see xCAT doc on Granting_Users_xCAT_privileges: :: +- To run ``xdsh`` with the non-root userid "user1" that has been setup as an xCAT userid and with sudo on node1 and node2 to run as root, do the following, see :ref:`Granting users xCAT privileges `: :: xdsh node1,node2 --sudo -l user1 "cat /etc/passwd" @@ -70,7 +70,7 @@ Examples for xdcp xdcp all /etc/hosts /etc/hosts -- To rsync the /etc/hosts file to your compute nodes: +- To ``rsync`` the /etc/hosts file to your compute nodes: Create a rsync file /tmp/myrsync, with this line: :: @@ -84,7 +84,7 @@ Examples for xdcp xdcp compute -F /tmp/myrsync -- To rsync the /etc/file1 and file2 to your compute nodes and rename to filex and filey: +- To ``rsync`` the /etc/file1 and file2 to your compute nodes and rename to filex and filey: Create a rsync file /tmp/myrsync, with these line: :: @@ -96,7 +96,7 @@ Examples for xdcp xdcp compute -F /tmp/myrsync to update the Compute Nodes -- To rsync files in the Linux image at /install/netboot/ubuntu14.04.2/ppc64el/compute/rootimg on the MN: +- To ``rsync`` files in the Linux image at /install/netboot/ubuntu14.04.2/ppc64el/compute/rootimg on the MN: Create a rsync file /tmp/myrsync, with this line: :: diff --git a/docs/source/guides/install-guides/apt/prepare_mgmt_node.rst b/docs/source/guides/install-guides/apt/prepare_mgmt_node.rst index f67fefc32..20d3f0672 100644 --- a/docs/source/guides/install-guides/apt/prepare_mgmt_node.rst +++ b/docs/source/guides/install-guides/apt/prepare_mgmt_node.rst @@ -10,6 +10,8 @@ Install an OS on the Management Node :start-after: BEGIN_install_os_mgmt_node :end-before: END_install_os_mgmt_node +.. _apt_configure_the_base_os_repository: + Configure the Base OS Repository -------------------------------- diff --git a/docs/source/guides/install-guides/zypper/prepare_mgmt_node.rst b/docs/source/guides/install-guides/zypper/prepare_mgmt_node.rst index fce8dc660..fd52e4387 100644 --- a/docs/source/guides/install-guides/zypper/prepare_mgmt_node.rst +++ b/docs/source/guides/install-guides/zypper/prepare_mgmt_node.rst @@ -10,6 +10,8 @@ Install an OS on the Management Node :start-after: BEGIN_install_os_mgmt_node :end-before: END_install_os_mgmt_node +.. _zypper_configure_the_base_os_repository: + Configure the Base OS Repository -------------------------------- From d7d015d4da0a2846c7c3465f4e58dd84ca7d2ffb Mon Sep 17 00:00:00 2001 From: XuWei Date: Mon, 20 Mar 2017 22:35:25 -0400 Subject: [PATCH 128/187] fix issue 2687, get username and password from passwd table --- xCAT-server/lib/xcat/plugins/openbmc.pm | 31 +++++++++++++++---------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 505fe7588..b7fff6193 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -170,7 +170,7 @@ sub preprocess_request { my $parse_result = parse_args($command, $extrargs); if (ref($parse_result) eq 'ARRAY') { - $callback->({ error => $parse_result->[1], errorcode => $parse_result->[0] }); + $callback->({ errorcode => $parse_result->[0], data => $parse_result->[1] }); $request = {}; return; } @@ -278,13 +278,13 @@ sub parse_args { my $subcommand = $ARGV[0]; if ($command eq "rpower") { unless ($subcommand =~ /^on$|^off$|^reset$|^boot$|^status$|^stat$|^state$/) { - return ([ 1, "$subcommand is not supported for rpower" ]); + return ([ 1, "Unsupported command: $command $subcommand" ]); } } if ($command eq "rinv") { unless ($subcommand =~ /^cpu$|^dimm$|^bios$|^all$/) { - return ([ 1, "Only 'cpu','dimm', 'bios','all' are supported currently" ]); + return ([ 1, "Unsupported command: $command $subcommand" ]); } } @@ -366,28 +366,35 @@ sub parse_command_status { sub parse_node_info { my $noderange = shift; - my $table = xCAT::Table->new('openbmc'); - my $tablehash = $table->getNodesAttribs(\@$noderange, ['bmc', 'username', 'password']); + my $passwd_table = xCAT::Table->new('passwd'); + my $passwd_hash = $passwd_table->getAttribs({ 'key' => 'openbmc' }, qw(username password)); + + my $openbmc_table = xCAT::Table->new('openbmc'); + my $openbmc_hash = $openbmc_table->getNodesAttribs(\@$noderange, ['bmc', 'username', 'password']); foreach my $node (@$noderange) { - if (defined($tablehash->{$node}->[0])) { - if ($tablehash->{$node}->[0]->{'bmc'}) { - $node_info{$node}{bmc} = $tablehash->{$node}->[0]->{'bmc'}; + if (defined($openbmc_hash->{$node}->[0])) { + if ($openbmc_hash->{$node}->[0]->{'bmc'}) { + $node_info{$node}{bmc} = $openbmc_hash->{$node}->[0]->{'bmc'}; } else { xCAT::SvrUtils::sendmsg("Unable to get attribute bmc", $callback, $node); next; } - if ($tablehash->{$node}->[0]->{'username'}) { - $node_info{$node}{username} = $tablehash->{$node}->[0]->{'username'}; + if ($openbmc_hash->{$node}->[0]->{'username'}) { + $node_info{$node}{username} = $openbmc_hash->{$node}->[0]->{'username'}; + } elsif ($passwd_hash and $passwd_hash->{username}) { + $node_info{$node}{username} = $passwd_hash->{username}; } else { xCAT::SvrUtils::sendmsg("Unable to get attribute username", $callback, $node); delete $node_info{$node}; next; } - if ($tablehash->{$node}->[0]->{'password'}) { - $node_info{$node}{password} = $tablehash->{$node}->[0]->{'password'}; + if ($openbmc_hash->{$node}->[0]->{'password'}) { + $node_info{$node}{password} = $openbmc_hash->{$node}->[0]->{'password'}; + } elsif ($passwd_hash and $passwd_hash->{password}) { + $node_info{$node}{password} = $passwd_hash->{password}; } else { xCAT::SvrUtils::sendmsg("Unable to get attribute password", $callback, $node); delete $node_info{$node}; From 65d01288a52615ea5e3e2f4e943c69a932d04b58 Mon Sep 17 00:00:00 2001 From: immarvin Date: Tue, 21 Mar 2017 14:57:41 +0800 Subject: [PATCH 129/187] fix issue When "site" attribute "sharedtftp" is false, the "nodeset" command fails #2492 --- xCAT-server/lib/xcat/plugins/petitboot.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index cea7eeaea..d40e60694 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -5,6 +5,7 @@ use File::Path; use Getopt::Long; use xCAT::Table; use Sys::Syslog; +use xCAT::Scope; my $globaltftpdir = xCAT::TableUtils->getTftpDir(); From 38831c8358ec61893cd81376b64db3e4485797a7 Mon Sep 17 00:00:00 2001 From: ertaozh Date: Tue, 21 Mar 2017 05:27:52 -0400 Subject: [PATCH 130/187] Modify the waiting time clearer for user for ntp-wait --- xCAT-genesis-scripts/bin/doxcat | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xCAT-genesis-scripts/bin/doxcat b/xCAT-genesis-scripts/bin/doxcat index 434252519..18efbc2e8 100755 --- a/xCAT-genesis-scripts/bin/doxcat +++ b/xCAT-genesis-scripts/bin/doxcat @@ -266,9 +266,11 @@ ip addr show dev $bootnic|grep -v 'scope link'|grep -v 'dynamic'|grep -v inet6| logger -s -t $log_label -p local4.info "Starting ntpd..." ntpd -g -x -NTP_WAIT_SECONDS=60 -logger -s -t $log_label -p local4.info "Waiting $NTP_WAIT_SECONDS seconds for ntpd to synchronize..." -ntp-wait -n $NTP_WAIT_SECONDS -s 1 -v +# ntp-wait defaults to 6 seconds between retries, wait for 1 minute +NTP_TRIES=10 +NTP_SLEEP=6 +logger -s -t $log_label -p local4.info "Waiting for $NTP_TRIES x $NTP_SLEEP seconds for ntpd to synchronize..." +ntp-wait -n $NTP_TRIES -s $NTP_SLEEP -v if [ $? -ne 0 ] then logger -s -t $log_label -p local4.info "... ntpd did not synchronize." From a481910874fb533d5bbde8b1467b69b6dfc7cd72 Mon Sep 17 00:00:00 2001 From: Victor Hu Date: Tue, 21 Mar 2017 09:47:57 -0400 Subject: [PATCH 131/187] Remove commands that are not needed, change https to protocol variable --- xCAT-server/lib/xcat/plugins/openbmc.pm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index a538b8590..88441b2cf 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -1,5 +1,5 @@ #!/usr/bin/perl -## IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +## IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::openbmc; @@ -58,12 +58,10 @@ sub handled_commands { rspreset => 'nodehm:mgt', rbeacon => 'nodehm:mgt', renergy => 'nodehm:mgt', - rscan => 'nodehm:mgt', - ripmi => 'ipmi', - getrvidparms => 'nodehm:mgt', }; } +my $http_protocol="https"; my $openbmc_url = "/org/openbmc"; my $openbmc_project_url = "/xyz/openbmc_project"; #------------------------------------------------------- @@ -245,7 +243,7 @@ sub process_request { foreach my $node (keys %node_info) { $bmcip = $node_info{$node}{bmc}; - $login_url = "https://$bmcip/login"; + $login_url = "$http_protocol://$bmcip/login"; $content = '{"data": [ "' . $node_info{$node}{username} .'", "' . $node_info{$node}{password} . '" ] }'; $handle_id = xCAT::OPENBMC->new($async, $login_url, $content); $handle_id_node{$handle_id} = $node; @@ -464,7 +462,7 @@ sub gen_send_request { } else { $request_url = $status_info{ $node_info{$node}{cur_status} }{init_url}; } - $request_url = "https://" . $node_info{$node}{bmc} . $request_url; + $request_url = "$http_protocol://" . $node_info{$node}{bmc} . $request_url; my $handle_id = xCAT::OPENBMC->send_request($async, $method, $request_url, $content); $handle_id_node{$handle_id} = $node; From 1463615f3fc8e9a6aafdd0481e7df73ccbbcb359 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Tue, 21 Mar 2017 11:45:26 -0400 Subject: [PATCH 132/187] Changes suggested by comments --- xCAT-client/bin/xdsh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xCAT-client/bin/xdsh b/xCAT-client/bin/xdsh index cad1bf394..164f4ba77 100644 --- a/xCAT-client/bin/xdsh +++ b/xCAT-client/bin/xdsh @@ -666,11 +666,6 @@ sub parse_args_xdcp $::NODE_RCP = 1; } - # find out who is the current user running xdcp - my $current_userid = getpwuid($>); - - $ENV{DSH_FROM_USERID} = $current_userid; - my $to_userid; if ($options{'user'}) # if -l option { @@ -678,6 +673,11 @@ sub parse_args_xdcp } else { + # find out who is the current user running xdcp + my $current_userid = getpwuid($>); + + $ENV{DSH_FROM_USERID} = $current_userid; + $to_userid = $current_userid; } # Save userid running this command in ENV variable. From 865527400f47fb0fb79aec3c77ec2f29259e3bdb Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Tue, 21 Mar 2017 12:01:42 -0400 Subject: [PATCH 133/187] ADD support for power reset of PDU outlet --- docs/source/advanced/pdu/pdu.rst | 24 +++++- .../admin-guides/references/man1/rpower.1.rst | 4 +- .../admin-guides/references/man5/nodehm.5.rst | 2 +- .../references/man5/openbmc.5.rst | 82 +++++++++++++++++++ .../admin-guides/references/man5/passwd.5.rst | 4 +- .../admin-guides/references/man5/xcatdb.5.rst | 6 ++ .../admin-guides/references/man7/group.7.rst | 20 ++++- .../admin-guides/references/man7/node.7.rst | 20 ++++- perl-xCAT/xCAT/Usage.pm | 4 +- xCAT-client/pods/man1/rpower.1.pod | 4 +- xCAT-server/lib/perl/xCAT/PPC.pm | 2 +- xCAT-server/lib/xcat/plugins/blade.pm | 2 +- xCAT-server/lib/xcat/plugins/esx.pm | 2 +- xCAT-server/lib/xcat/plugins/hpblade.pm | 2 +- xCAT-server/lib/xcat/plugins/hpilo.pm | 2 +- xCAT-server/lib/xcat/plugins/ipmi.pm | 2 +- xCAT-server/lib/xcat/plugins/kvm.pm | 2 +- xCAT-server/lib/xcat/plugins/pdu.pm | 13 ++- xCAT-server/lib/xcat/plugins/rhevm.pm | 2 +- xCAT-server/lib/xcat/plugins/xen.pm | 2 +- xCAT-server/lib/xcat/plugins/zvm.pm | 2 +- 21 files changed, 172 insertions(+), 31 deletions(-) create mode 100644 docs/source/guides/admin-guides/references/man5/openbmc.5.rst diff --git a/docs/source/advanced/pdu/pdu.rst b/docs/source/advanced/pdu/pdu.rst index 781a7dbc9..9ed9b705c 100644 --- a/docs/source/advanced/pdu/pdu.rst +++ b/docs/source/advanced/pdu/pdu.rst @@ -63,6 +63,12 @@ The following commands are supported against a compute node: cn01: f5pdu3 outlet 6 is on cn01: f5pdu3 outlet 7 is on + * Power cycling the PDU outlets on a compute node: :: + + # rpower cn01 pdureset + cn01: f5pdu3 outlet 6 is on + cn01: f5pdu3 outlet 7 is on + The following commands are supported against a PDU: * Check the status of the full PDU: :: @@ -98,7 +104,7 @@ The following commands are supported against a PDU: f5pdu3: outlet 12 is off * Power on the full PDU: :: - + # rpower f5pdu3 on f5pdu3: outlet 1 is on f5pdu3: outlet 2 is on @@ -112,6 +118,22 @@ The following commands are supported against a PDU: f5pdu3: outlet 10 is on f5pdu3: outlet 11 is on f5pdu3: outlet 12 is on + + * Power reset the full PDU: :: + + # rpower f5pdu3 reset + f5pdu3: outlet 1 is on + f5pdu3: outlet 2 is on + f5pdu3: outlet 3 is on + f5pdu3: outlet 4 is on + f5pdu3: outlet 5 is on + f5pdu3: outlet 6 is on + f5pdu3: outlet 7 is on + f5pdu3: outlet 8 is on + f5pdu3: outlet 9 is on + f5pdu3: outlet 10 is on + f5pdu3: outlet 11 is on + f5pdu3: outlet 12 is on **Note:** For BMC based compute nodes, turning the PDU outlet power on does not automatically power on the compute side. Users will need to issue ``rpower on`` to power on the compute node after the BMC boots. diff --git a/docs/source/guides/admin-guides/references/man1/rpower.1.rst b/docs/source/guides/admin-guides/references/man1/rpower.1.rst index ca436bd30..b344f75d6 100644 --- a/docs/source/guides/admin-guides/references/man1/rpower.1.rst +++ b/docs/source/guides/admin-guides/references/man1/rpower.1.rst @@ -29,7 +29,7 @@ BMC (using IPMI) specific: \ **rpower**\ \ *noderange*\ [\ **on | off | softoff | reset | boot | stat | state | status | wake | suspend**\ [\ **-w**\ \ *timeout*\ ] [\ **-o**\ ] [\ **-r**\ ]] -\ **rpower**\ \ *noderange*\ [\ **pduon | pduoff | pdustat**\ ] +\ **rpower**\ \ *noderange*\ [\ **pduon | pduoff | pdustat | pdureset**\ ] OpenBMC specific: @@ -115,7 +115,7 @@ pdu specific: ============= -\ **rpower**\ \ *noderange*\ [\ **stat | off | on**\ ] +\ **rpower**\ \ *noderange*\ [\ **stat | off | on | reset**\ ] diff --git a/docs/source/guides/admin-guides/references/man5/nodehm.5.rst b/docs/source/guides/admin-guides/references/man5/nodehm.5.rst index e3978e25e..ef568e90f 100644 --- a/docs/source/guides/admin-guides/references/man5/nodehm.5.rst +++ b/docs/source/guides/admin-guides/references/man5/nodehm.5.rst @@ -50,7 +50,7 @@ nodehm Attributes: \ **mgt**\ - The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details. + The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: openbmc, ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details. diff --git a/docs/source/guides/admin-guides/references/man5/openbmc.5.rst b/docs/source/guides/admin-guides/references/man5/openbmc.5.rst new file mode 100644 index 000000000..7e006120c --- /dev/null +++ b/docs/source/guides/admin-guides/references/man5/openbmc.5.rst @@ -0,0 +1,82 @@ + +######### +openbmc.5 +######### + +.. highlight:: perl + + +**** +NAME +**** + + +\ **openbmc**\ - a table in the xCAT database. + + +******** +SYNOPSIS +******** + + +\ **openbmc Attributes:**\ \ *node*\ , \ *bmc*\ , \ *username*\ , \ *password*\ , \ *comments*\ , \ *disable*\ + + +*********** +DESCRIPTION +*********** + + +Setting for nodes that are controlled by an on-board OpenBmc. + + +******************* +openbmc Attributes: +******************* + + + +\ **node**\ + + The node name or group name. + + + +\ **bmc**\ + + The hostname of the BMC adapter. + + + +\ **username**\ + + The BMC userid. + + + +\ **password**\ + + The BMC password. + + + +\ **comments**\ + + Any user-written notes. + + + +\ **disable**\ + + Set to 'yes' or '1' to comment out this row. + + + + +******** +SEE ALSO +******** + + +\ **nodels(1)**\ , \ **chtab(8)**\ , \ **tabdump(8)**\ , \ **tabedit(8)**\ + diff --git a/docs/source/guides/admin-guides/references/man5/passwd.5.rst b/docs/source/guides/admin-guides/references/man5/passwd.5.rst index 3438aa4b6..4123a9258 100644 --- a/docs/source/guides/admin-guides/references/man5/passwd.5.rst +++ b/docs/source/guides/admin-guides/references/man5/passwd.5.rst @@ -50,13 +50,13 @@ passwd Attributes: \ **password**\ - The default password for this type of component + The default password for this type of component. On Linux, a crypted form could be provided. Hashes starting with $1$, $5$ and $6$ (md5, sha256 and sha512 respectively) are supported. \ **cryptmethod**\ - Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default. + Indicates the method to use to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default to encrypt plain-text passwords. diff --git a/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst b/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst index 4f8be2d93..4100de4bb 100644 --- a/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst +++ b/docs/source/guides/admin-guides/references/man5/xcatdb.5.rst @@ -565,6 +565,12 @@ notification(5)|notification.5 +openbmc(5)|openbmc.5 + + Setting for nodes that are controlled by an on-board OpenBmc. + + + osdistro(5)|osdistro.5 Information about all the OS distros in the xCAT cluster diff --git a/docs/source/guides/admin-guides/references/man7/group.7.rst b/docs/source/guides/admin-guides/references/man7/group.7.rst index 7e42304f6..8894cc520 100644 --- a/docs/source/guides/admin-guides/references/man7/group.7.rst +++ b/docs/source/guides/admin-guides/references/man7/group.7.rst @@ -57,16 +57,24 @@ group Attributes: -\ **bmc**\ (ipmi.bmc) +\ **bmc**\ (ipmi.bmc, openbmc.bmc) + + The hostname of the BMC adapter. + + or The hostname of the BMC adapter. -\ **bmcpassword**\ (ipmi.password) +\ **bmcpassword**\ (ipmi.password, openbmc.password) The BMC password. If not specified, the key=ipmi row in the passwd table is used as the default. + or + + The BMC password. + \ **bmcport**\ (ipmi.bmcport) @@ -115,10 +123,14 @@ group Attributes: -\ **bmcusername**\ (ipmi.username) +\ **bmcusername**\ (ipmi.username, openbmc.username) The BMC userid. If not specified, the key=ipmi row in the passwd table is used as the default. + or + + The BMC userid. + \ **bmcvlantag**\ (ipmi.taggedvlan) @@ -461,7 +473,7 @@ group Attributes: \ **mgt**\ (nodehm.mgt) - The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details. + The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: openbmc, ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details. diff --git a/docs/source/guides/admin-guides/references/man7/node.7.rst b/docs/source/guides/admin-guides/references/man7/node.7.rst index f1ae11918..f375eaac0 100644 --- a/docs/source/guides/admin-guides/references/man7/node.7.rst +++ b/docs/source/guides/admin-guides/references/man7/node.7.rst @@ -69,16 +69,24 @@ node Attributes: -\ **bmc**\ (ipmi.bmc) +\ **bmc**\ (ipmi.bmc, openbmc.bmc) + + The hostname of the BMC adapter. + + or The hostname of the BMC adapter. -\ **bmcpassword**\ (ipmi.password) +\ **bmcpassword**\ (ipmi.password, openbmc.password) The BMC password. If not specified, the key=ipmi row in the passwd table is used as the default. + or + + The BMC password. + \ **bmcport**\ (ipmi.bmcport) @@ -127,10 +135,14 @@ node Attributes: -\ **bmcusername**\ (ipmi.username) +\ **bmcusername**\ (ipmi.username, openbmc.username) The BMC userid. If not specified, the key=ipmi row in the passwd table is used as the default. + or + + The BMC userid. + \ **bmcvlantag**\ (ipmi.taggedvlan) @@ -461,7 +473,7 @@ node Attributes: \ **mgt**\ (nodehm.mgt) - The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details. + The method to use to do general hardware management of the node. This attribute is used as the default if power or getmac is not set. Valid values: openbmc, ipmi, blade, hmc, ivm, fsp, bpa, kvm, esx, rhevm. See the power attribute for more details. diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index c7f7bb3ef..6d675bbe6 100755 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -53,8 +53,8 @@ my %usage = ( docker specific: rpower noderange [start|stop|restart|pause|unpause|state] pdu specific: - rpower noderange [off|on|stat] - rpower noderange [pduoff|pduon|pdustat] + rpower noderange [off|on|stat|status|reset] + rpower noderange [pduoff|pduon|pdustat|pdustatus|pdureset] ", "rbeacon" => "Usage: rbeacon [on|off|stat] [-V|--verbose] diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index bc8a0e062..3c9b36716 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -12,7 +12,7 @@ B [B<-h>|B<--help>|B<-v>|B<--version>] B I [B|B|B|B|B|B|B|B|B|B [B<-w> I] [B<-o>] [B<-r>]] -B I [B|B|B] +B I [B|B|B|B] =head2 OpenBMC specific: @@ -62,7 +62,7 @@ B I [B|B|B|B|B|B =head2 pdu specific: -B I [B|B|B] +B I [B|B|B|B] =head1 DESCRIPTION diff --git a/xCAT-server/lib/perl/xCAT/PPC.pm b/xCAT-server/lib/perl/xCAT/PPC.pm index cfb58162c..ab2e4f072 100644 --- a/xCAT-server/lib/perl/xCAT/PPC.pm +++ b/xCAT-server/lib/perl/xCAT/PPC.pm @@ -235,7 +235,7 @@ sub process_command { if ($command eq 'rpower') { $subcommand = $request->{op}; } #pdu commands will be handled in the pdu plugin - if(($subcommand eq 'pduoff') || ($subcommand eq 'pduon') || ($subcommand eq 'pdustat')){ + if(($subcommand eq 'pduoff') || ($subcommand eq 'pduon') || ($subcommand eq 'pdustat') || ($subcommand eq 'pdureset')){ return 0; } diff --git a/xCAT-server/lib/xcat/plugins/blade.pm b/xCAT-server/lib/xcat/plugins/blade.pm index 5eaac006c..c202c331b 100644 --- a/xCAT-server/lib/xcat/plugins/blade.pm +++ b/xCAT-server/lib/xcat/plugins/blade.pm @@ -4401,7 +4401,7 @@ sub process_request { else { $moreinfo = build_more_info($noderange, $callback); } #pdu commands will be handled in the pdu plugin - if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) { + if ($command eq "rpower" and grep(/^pduon|pduoff|pdureset|pdustat$/, @exargs)) { return; } diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index d705ca81e..fcdb09b0c 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -407,7 +407,7 @@ sub process_request { } #pdu commands will be handled in the pdu plugin - if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) { + if ($command eq "rpower" and grep(/^pduon|pduoff|pdureset|pdustat$/, @exargs)) { return; } #my $sitetab = xCAT::Table->new('site'); diff --git a/xCAT-server/lib/xcat/plugins/hpblade.pm b/xCAT-server/lib/xcat/plugins/hpblade.pm index 090bb6738..364627ba7 100755 --- a/xCAT-server/lib/xcat/plugins/hpblade.pm +++ b/xCAT-server/lib/xcat/plugins/hpblade.pm @@ -647,7 +647,7 @@ sub process_request { else { $moreinfo = build_more_info($noderange, $callback); } #pdu commands will be handled in the pdu plugin - if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) { + if ($command eq "rpower" and grep(/^pduon|pduoff|pdureset|pdustat$/, @exargs)) { return; } diff --git a/xCAT-server/lib/xcat/plugins/hpilo.pm b/xCAT-server/lib/xcat/plugins/hpilo.pm index 72855e11a..3a88db4e3 100755 --- a/xCAT-server/lib/xcat/plugins/hpilo.pm +++ b/xCAT-server/lib/xcat/plugins/hpilo.pm @@ -362,7 +362,7 @@ sub process_request { } #pdu commands will be handled in the pdu plugin - if (($extrargs->[0] eq 'pdustat') || ($extrargs->[0] eq 'pduon') || ($extrargs->[0] eq 'pduoff')) { + if (($extrargs->[0] eq 'pdustat') || ($extrargs->[0] eq 'pdureset') || ($extrargs->[0] eq 'pduon') || ($extrargs->[0] eq 'pduoff')) { return; } diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index ae76557c1..2d86fe981 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -7682,7 +7682,7 @@ sub preprocess_request { } #pdu commands will be handled in the pdu plugin - if(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){ + if(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat') || ($subcmd eq 'pdureset')){ return 0; } diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index becd4c557..6e2434eea 100755 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -3675,7 +3675,7 @@ sub process_request { } #pdu commands will be handled in the pdu plugin - if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) { + if ($command eq "rpower" and grep(/^pduon|pduoff|pdureset|pdustat$/, @exargs)) { return; } diff --git a/xCAT-server/lib/xcat/plugins/pdu.pm b/xCAT-server/lib/xcat/plugins/pdu.pm index 92d3c3350..9d54d92fc 100644 --- a/xCAT-server/lib/xcat/plugins/pdu.pm +++ b/xCAT-server/lib/xcat/plugins/pdu.pm @@ -140,7 +140,7 @@ sub process_request return powerstat($noderange, $callback); }elsif ($command eq "rpower") { my $subcmd = $exargs[0]; - if (($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){ + if (($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')|| ($subcmd eq 'pdureset') ){ #if one day, pdu node have pdu attribute, handle in this section too return powerpduoutlet($noderange, $subcmd, $callback); } else { @@ -160,7 +160,7 @@ sub process_request } } if(@allpdunodes) { - if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat') || ($subcmd eq 'state')){ + if(($subcmd eq 'on') || ($subcmd eq 'off') || ($subcmd eq 'stat') || ($subcmd eq 'state') || ($subcmd eq 'reset') ){ return powerpdu(\@allpdunodes, $subcmd, $callback); } else { my $pdunode = join (",", @allpdunodes); @@ -232,9 +232,12 @@ sub powerpdu { if ($subcmd eq "off") { $value = 0; $statstr = "off"; - } else { + } elsif ( $subcmd eq "on") { $value = 1; $statstr = "on"; + } else { + $value = 2; + $statstr = "reset"; } for (my $outlet =1; $outlet <= $count; $outlet++) @@ -304,6 +307,10 @@ sub powerpduoutlet { $value = 1; $statstr = "on"; outletpower($session, $outlet, $value); + } elsif ($subcmd eq "pdureset") { + $value = 2; + $statstr = "reset"; + outletpower($session, $outlet, $value); } else { $callback->({ error => "$subcmd is not support"}); } diff --git a/xCAT-server/lib/xcat/plugins/rhevm.pm b/xCAT-server/lib/xcat/plugins/rhevm.pm index 5a45e7870..c2b833958 100644 --- a/xCAT-server/lib/xcat/plugins/rhevm.pm +++ b/xCAT-server/lib/xcat/plugins/rhevm.pm @@ -127,7 +127,7 @@ sub preprocess_request { } #pdu commands will be handled in the pdu plugin - if (($extraargs->[0] eq 'pdustat') || ($extraargs->[0] eq 'pduon') || ($extraargs->[0] eq 'pduoff')) { + if (($extraargs->[0] eq 'pdustat') || ($extraargs->[0] eq 'pdureset') || ($extraargs->[0] eq 'pduon') || ($extraargs->[0] eq 'pduoff')) { return; } diff --git a/xCAT-server/lib/xcat/plugins/xen.pm b/xCAT-server/lib/xcat/plugins/xen.pm index 7a552e7aa..6629f9b9f 100644 --- a/xCAT-server/lib/xcat/plugins/xen.pm +++ b/xCAT-server/lib/xcat/plugins/xen.pm @@ -706,7 +706,7 @@ sub process_request { } #pdu commands will be handled in the pdu plugin - if ($command eq "rpower" and grep(/^pduon|pduoff|pdustat$/, @exargs)) { + if ($command eq "rpower" and grep(/^pduon|pduoff|pdureset|pdustat$/, @exargs)) { return; } diff --git a/xCAT-server/lib/xcat/plugins/zvm.pm b/xCAT-server/lib/xcat/plugins/zvm.pm index 911be973e..d04a98aae 100644 --- a/xCAT-server/lib/xcat/plugins/zvm.pm +++ b/xCAT-server/lib/xcat/plugins/zvm.pm @@ -2319,7 +2319,7 @@ sub powerVM { my $out; ##pdu commands will be handled in the pdu plugin - if ($args->[0] eq 'pduon' || $args->[0] eq 'pduoff' || $args->[0] eq 'pdustat') { + if ($args->[0] eq 'pduon' || $args->[0] eq 'pdureset' || $args->[0] eq 'pduoff' || $args->[0] eq 'pdustat') { return; } From 47b59f91e71a4d4f92556d719a34bf89fe668f9e Mon Sep 17 00:00:00 2001 From: Amanda Duffy Date: Tue, 21 Mar 2017 16:10:34 -0400 Subject: [PATCH 134/187] Add reseat to rpower man page Add reseat to rpower man page, under "Blade specific" sections. Also add definition. --- xCAT-client/pods/man1/rpower.1.pod | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index bc8a0e062..353fddbbe 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -46,11 +46,11 @@ B I [B|B|B|B|B|B|B|B I [B|B|B|B|B|B] +B I [B|B|B|B|B|B|B] =head2 Blade specific: -B I [B|B] +B I [B|B|B] =head2 zVM specific: @@ -173,6 +173,9 @@ This option is recommended over B. Power off, then on. +=item B + + =item B Boot the node to open firmware console mode. From 8c92218b9566c69e4fa195fb105efa5a01e129c5 Mon Sep 17 00:00:00 2001 From: Amanda Duffy Date: Tue, 21 Mar 2017 16:20:43 -0400 Subject: [PATCH 135/187] rpower reseat definition Add definition of reseat which was apparently missed in last commit. --- xCAT-client/pods/man1/rpower.1.pod | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index 353fddbbe..f875cb8bf 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -175,6 +175,7 @@ Power off, then on. =item B +For blades and NeXtScale, simulates unplugging and replugging the node into the chassis. =item B From a08134d9f7c604c53222b1362e8c72d16918a18b Mon Sep 17 00:00:00 2001 From: Kilian Cavalotti Date: Tue, 21 Mar 2017 14:03:53 -0700 Subject: [PATCH 136/187] dodiscovery: add a fallback for getting MTM from DMI In some cases, FRU pages are not available, or don't contain relevant readable or relevant information. In those cases, we could still fall back to DMI to get the MTM information, and log a warning that MTMS-based discovery may not work as expected. --- xCAT-genesis-scripts/bin/dodiscovery | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xCAT-genesis-scripts/bin/dodiscovery b/xCAT-genesis-scripts/bin/dodiscovery index 6d20ba9da..f33ef9c3d 100755 --- a/xCAT-genesis-scripts/bin/dodiscovery +++ b/xCAT-genesis-scripts/bin/dodiscovery @@ -76,6 +76,11 @@ if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86 FRU=`ipmitool fru print 0` if [ $? -eq 0 ]; then MTM=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {m=$2} /Product Name/ {n=$2} END {print m":"n}'` + else + logger -s -t $log_label -p local4.warning "Couldn't find MTM information in FRU, falling back to DMI (MTMS-based discovery may fail)" + m=`cat /sys/devices/virtual/dmi/id/sys_vendor` + n=`cat /sys/devices/virtual/dmi/id/product_name` + MTM="$m:$n" fi fi SERIAL=`cat /sys/devices/virtual/dmi/id/product_serial` From d01499ea72cf437d230fc2bacec6c84caddc0c70 Mon Sep 17 00:00:00 2001 From: Amanda Duffy Date: Tue, 21 Mar 2017 17:10:27 -0400 Subject: [PATCH 137/187] reseat option for high-density servers Add "Lenovo High-Density Server" to rpower man and usage. Add reseat option. --- perl-xCAT/xCAT/Usage.pm | 2 ++ xCAT-client/pods/man1/rpower.1.pod | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index c7f7bb3ef..f2d728189 100755 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -46,6 +46,8 @@ my %usage = ( rpower [on|onstandby|off|cycle|state|sms] Blade(using AMM) specific: rpower [cycle|softoff] [-V|--verbose] + Lenovo high-density server specific: + rpower [on|off|reset|boot|reseat] zVM specific: rpower noderange [on|off|reset|stat|softoff] MIC specific: diff --git a/xCAT-client/pods/man1/rpower.1.pod b/xCAT-client/pods/man1/rpower.1.pod index f875cb8bf..3bbe23d2b 100644 --- a/xCAT-client/pods/man1/rpower.1.pod +++ b/xCAT-client/pods/man1/rpower.1.pod @@ -46,11 +46,15 @@ B I [B|B|B|B|B|B|B|B I [B|B|B|B|B|B|B] +B I [B|B|B|B|B|B] =head2 Blade specific: -B I [B|B|B] +B I [B|B] + +=head2 Lenovo High-Density Server specific: + +B I [B|B|B|B|B] =head2 zVM specific: @@ -175,7 +179,7 @@ Power off, then on. =item B -For blades and NeXtScale, simulates unplugging and replugging the node into the chassis. +For Lenovo high-density servers, simulates unplugging and replugging the node into the chassis. =item B From 2971c1f01a516a5979ffaffdbc5e435e7b576775 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Wed, 22 Mar 2017 01:44:33 -0400 Subject: [PATCH 138/187] modify rhesl7.2.ppc bundle --- xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle index be7019aea..7246a2e12 100644 --- a/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.2_ppc64.bundle @@ -4,8 +4,6 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 -makehosts_n -makehosts_n_noderange updatenode_h updatenode_v updatenode_diskful_syncfiles @@ -232,6 +230,8 @@ makehosts_help makehosts_null makehosts_l makehosts_d +makehosts_n +makehosts_n_noderange xdcp_src_dst makedns_h makedns_d_node From c3a93cc026413ca5a9142fb70e06e7d951630582 Mon Sep 17 00:00:00 2001 From: "litingt@cn.ibm.com" Date: Tue, 21 Mar 2017 23:06:46 -0400 Subject: [PATCH 139/187] add copycds -p cases, fix #2699 --- xCAT-test/autotest/testcase/copycds/cases0 | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/xCAT-test/autotest/testcase/copycds/cases0 b/xCAT-test/autotest/testcase/copycds/cases0 index 77ce810e4..e9d30f81d 100644 --- a/xCAT-test/autotest/testcase/copycds/cases0 +++ b/xCAT-test/autotest/testcase/copycds/cases0 @@ -168,3 +168,29 @@ check:rc==0 check:output=~~Copying media to /install/__GETNODEATTR($$CN,os)__/__GETNODEATTR($$CN,arch)__ end + +start:copycds_p_newdir +os:Linux +cmd:if [ -e /install/newdir ];then mv /install/newdir /install/newdirbak; fi +cmd:copycds $$ISO -p /install/newdir +check:rc==0 +check:output=~Copying media to /install/newdir +check:output=~Media copy operation successful +cmd:ls -l /install/newdir/Packages +check:rc==0 +cmd:rm -rf /install/newdir +cmd:if [ -e /install/newdirbak ];then mv /install/newdirbak /install/newdir; fi +end + +start:copycds_p_noninstalldir +os:Linux +cmd:if [ -e /noninstalldir ];then mv /noninstalldir /noninstaldirbak; fi +cmd:copycds $$ISO -p /noninstalldir +check:rc==0 +check:output=~Warning: copycds: the specified path "/noninstalldir" is not a subdirectory under /install +check:output=~Copying media to /noninstalldir +cmd:ls -l /noninstalldir/Packages +check:rc==0 +cmd:rm -rf /noninstalldir +cmd:if [ -e /noninstalldirbak ];then mv /noninstalldirbak /noninstalldir; fi +end From b4fa5f0486966538f862c038d9dc0108a93018b6 Mon Sep 17 00:00:00 2001 From: bybai Date: Wed, 22 Mar 2017 03:08:33 -0400 Subject: [PATCH 140/187] fix issue 2717 makehosts -d will delete erroneously entries /etc/hosts if one node s01 another is --- xCAT-server/lib/xcat/plugins/hosts.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/hosts.pm b/xCAT-server/lib/xcat/plugins/hosts.pm index 87daa39b2..bf0cd10ec 100755 --- a/xCAT-server/lib/xcat/plugins/hosts.pm +++ b/xCAT-server/lib/xcat/plugins/hosts.pm @@ -44,7 +44,7 @@ sub delnode while ($idx <= $#hosts) { if (($ip and $hosts[$idx] =~ /^${ip}\s/) - or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.r]/) + or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.\r]/) { $hosts[$idx] = ""; } From 0b98b3f57ddc5846443f6d91ce49d6503e73231d Mon Sep 17 00:00:00 2001 From: Yuan Bai Date: Wed, 22 Mar 2017 15:40:09 +0800 Subject: [PATCH 141/187] fix issue 2634 Quotes in tables' comment field break mypostscript (#2716) * fix issue 2634 Quotes in tables' comment field break mypostscript * polish comments * polish comments --- xCAT-server/lib/perl/xCAT/Postage.pm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 257a2625b..9952169d5 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -1582,7 +1582,13 @@ sub dump_all_attribs_in_tabs } else { $values .= "$attrib=$val||"; if ($attrib =~ /^disable$/) { - $values .= "comments=$t"; + # Updated on 2017-03-22 for issue 2634 Quotes in tables' comment field break mypostscript + # The original line is : $values .= "comments=$t"; + # In order to fix issue 2634, change this line to : $values .= "comments="; + # To keep the free-style of comments and avoid the issues caused by special characters in + # the comments, the value of comments will not be appending to network related environment + # variables in mypostscript + $values .= "comments="; } } } From 9d331290f7c1ad1468ed96df18bcb491d6eed8f8 Mon Sep 17 00:00:00 2001 From: hu-weihua Date: Wed, 22 Mar 2017 03:54:07 -0400 Subject: [PATCH 142/187] Modify syntex error --- xCAT-test/autotest/testcase/installation/pre_deploy_sn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/pre_deploy_sn b/xCAT-test/autotest/testcase/installation/pre_deploy_sn index a4c30001a..ea12ed759 100755 --- a/xCAT-test/autotest/testcase/installation/pre_deploy_sn +++ b/xCAT-test/autotest/testcase/installation/pre_deploy_sn @@ -25,7 +25,7 @@ if ($ENV{XCAT_DATABASE} eq "PostgreSQL") { print $fh "host all all ::0/0 md5\n"; close $fh; - $cmd = "service postgresql restart" + $cmd = "service postgresql restart"; runcmd("$cmd"); } else { $cmd = "XCATMYSQLADMIN_PW=12345 XCATMYSQLROOT_PW=12345 /opt/xcat/bin/mysqlsetup -i -V"; From cd96ea74c8d5eeab9d6f2a4fd9633fb36132f7b9 Mon Sep 17 00:00:00 2001 From: immarvin Date: Wed, 22 Mar 2017 16:38:38 +0800 Subject: [PATCH 143/187] fix issue Wrong permissions for ssh host private keys on CentOS 7 #2617 --- xCAT-server/sbin/xcatconfig | 20 ++++++++++++++++++++ xCAT/postscripts/remoteshell | 13 ++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index 04b4e6e2f..4327ff09d 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -969,6 +969,10 @@ sub genSSHNodeHostKey # # generate new hostkeys # + + my ($rlogin,$rpass,$ruid,$rgid) = getpwnam("root"); + my ($sname, $spasswd,$sgid,$smembers)=getgrnam("ssh_keys"); + my @sshkeylist; xCAT::MsgUtils->message('I', "Generating new node hostkeys..."); xCAT::MsgUtils->message('I', "Generating SSH2 RSA Key..."); my $cmd = @@ -978,6 +982,10 @@ sub genSSHNodeHostKey { xCAT::MsgUtils->message('E', "Could not generate SSH2 RSA key."); } + else{ + push @sshkeylist,"/etc/xcat/hostkeys/ssh_host_rsa_key"; + } + xCAT::MsgUtils->message('I', "Generating SSH2 DSA Key..."); $cmd = @@ -987,6 +995,9 @@ sub genSSHNodeHostKey { xCAT::MsgUtils->message('E', "Could not generate SSH2 DSA key."); } + else{ + push @sshkeylist,"/etc/xcat/hostkeys/ssh_host_dsa_key"; + } # see if this system supports the ecdsa xCAT::Utils->runcmd('rm -rf /tmp/ecdsa_key >/dev/null 2>&1 ; /usr/bin/ssh-keygen -t ecdsa -f /tmp/ecdsa_key -P "" &>/dev/null', 0); @@ -999,8 +1010,17 @@ sub genSSHNodeHostKey { xCAT::MsgUtils->message('E', "Could not generate SSH2 ECDSA key."); } + else{ + push @sshkeylist,"/etc/xcat/hostkeys/ssh_host_ecdsa_key"; + } } + if(@sshkeylist){ + if(defined $ruid && defined $sgid){ + chown $ruid,$sgid,@sshkeylist; + } + chmod 0640,@sshkeylist; + } # copy the public keys to install directory $cmd = diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index 690ff2e97..a93722457 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -149,7 +149,8 @@ if [ $? -ne 0 ]; then getcredentials.awk ssh_dsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_dsa_key MYCONT=`cat /etc/ssh/ssh_host_dsa_key` done - chmod 600 /etc/ssh/ssh_host_dsa_key + chown root:ssh_keys /etc/ssh/ssh_host_dsa_key + chmod 640 /etc/ssh/ssh_host_dsa_key if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_dsa_key > /dev/null 2>&1 ; then rm /etc/ssh/ssh_host_dsa_key else @@ -215,13 +216,14 @@ if [ $? -ne 0 ]; then getcredentials.awk ssh_rsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_rsa_key MYCONT=`cat /etc/ssh/ssh_host_rsa_key` done - chmod 600 /etc/ssh/ssh_host_rsa_key + chown root:ssh_keys /etc/ssh/ssh_host_rsa_key + chmod 640 /etc/ssh/ssh_host_rsa_key if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_rsa_key > /dev/null 2>&1 ; then rm /etc/ssh/ssh_host_rsa_key else ssh-keygen -y -f /etc/ssh/ssh_host_rsa_key > /etc/ssh/ssh_host_rsa_key.pub - chmod 644 /etc/ssh/ssh_host_rsa_key.pub - chown root /etc/ssh/ssh_host_rsa_key.pub + chmod 644 /etc/ssh/ssh_host_rsa_key.pub + chown root /etc/ssh/ssh_host_rsa_key.pub fi else #This is an error message @@ -286,7 +288,8 @@ if ssh-keygen -t ecdsa -f /tmp/ecdsa_key -P "" &>/dev/null ; then getcredentials.awk ssh_ecdsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_ecdsa_key MYCONT=`cat /etc/ssh/ssh_host_ecdsa_key` done - chmod 600 /etc/ssh/ssh_host_ecdsa_key + chown root:ssh_keys /etc/ssh/ssh_host_ecdsa_key + chmod 640 /etc/ssh/ssh_host_ecdsa_key if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_ecdsa_key > /dev/null 2>&1 ; then rm /etc/ssh/ssh_host_ecdsa_key else From 37f9e770f4ea8df5cb7facb5bfdaab16d28ea0b1 Mon Sep 17 00:00:00 2001 From: immarvin Date: Wed, 22 Mar 2017 23:20:29 -0400 Subject: [PATCH 144/187] fix issue postscript fails and status=booted. #2665 --- xCAT-server/share/xcat/install/scripts/post.xcat | 15 +++++++++++++++ xCAT/postscripts/xcatinstallpost | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/xCAT-server/share/xcat/install/scripts/post.xcat b/xCAT-server/share/xcat/install/scripts/post.xcat index 2179b2f82..48024de9c 100755 --- a/xCAT-server/share/xcat/install/scripts/post.xcat +++ b/xCAT-server/share/xcat/install/scripts/post.xcat @@ -180,6 +180,7 @@ echo " # global value to store the running status of the postbootscripts,the value is non-zero if one postbootscript failed return_value=0 + # subroutine used to run postscripts # \$1 argument is the script type # rest argument is the script name and arguments @@ -227,6 +228,7 @@ run_ps () { return_value=-1 fi + return 0 } # subroutine end @@ -389,6 +391,19 @@ fi #create the preboot script and run here TMP=`sed "/^#\s*postbootscripts-start-here/,/^#\s*postbootscripts-end-here/ d" /xcatpost/mypostscript` echo "$TMP" > /xcatpost/mypostscript + +echo " +#save bad return code to /opt/xcat/xcatinfo +if [ \"\$return_value\" -ne \"0\" ]; then + grep 'POSTSCRIPTS_RC' /opt/xcat/xcatinfo > /dev/null 2>&1 + if [ \$? -eq 0 ]; then + sed -i \"s/POSTSCRIPTS_RC=.*/POSTSCRIPTS_RC=1/\" /opt/xcat/xcatinfo + else + echo \"POSTSCRIPTS_RC=1\" >> /opt/xcat/xcatinfo + fi +fi +" >> /xcatpost/mypostscript + chmod 755 /xcatpost/mypostscript export ARCH=#TABLE:nodetype:THISNODE:arch# diff --git a/xCAT/postscripts/xcatinstallpost b/xCAT/postscripts/xcatinstallpost index 598cb93d4..de68037f0 100755 --- a/xCAT/postscripts/xcatinstallpost +++ b/xCAT/postscripts/xcatinstallpost @@ -84,6 +84,9 @@ if [ -z "$CNS" ] || [[ "$CNS" =~ ^(1|yes|y)$ ]]; then echo " +[ -f /opt/xcat/xcatinfo ] && grep 'POSTSCRIPTS_RC=1' /opt/xcat/xcatinfo >/dev/null 2>&1 && return_value=1 + + if [ \"\$return_value\" -eq \"0\" ]; then if [ \"\$XCATDEBUGMODE\" = \"1\" ] || [ \"\$XCATDEBUGMODE\" = \"2\" ]; then msgutil_r \"\$MASTER_IP\" \"info\" \"node booted, reporting status...\" \"/var/log/xcat/xcat.log\" @@ -99,6 +102,7 @@ fi " >> /xcatpost/mypostscript.post fi + chmod +x /xcatpost/mypostscript.post if [ -x /xcatpost/mypostscript.post ];then msgutil_r "$MASTER_IP" "info" "running /xcatpost/mypostscript.post" "/var/log/xcat/xcat.log" From 540eca5c4c936bf84561f7258ed5bbce8fffe6f3 Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 23 Mar 2017 04:10:31 -0400 Subject: [PATCH 145/187] fix 2666 Test cases related rpower need to modify --- xCAT-test/autotest/testcase/rpower/cases0 | 60 ++++++++++++----------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/xCAT-test/autotest/testcase/rpower/cases0 b/xCAT-test/autotest/testcase/rpower/cases0 index c522406c2..6322fa241 100644 --- a/xCAT-test/autotest/testcase/rpower/cases0 +++ b/xCAT-test/autotest/testcase/rpower/cases0 @@ -1,75 +1,79 @@ start:rpower_off -cmd:rpower $$CN stat -check:ouptut=~Running +cmd:rpower $$CN on +cmd:a=0;while ! `rpower $$CN stat|grep "Running\|on" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done +check:ouptut=~Running|on cmd:rpower $$CN off check:rc==0 -check:output=~Success -cmd:sleep 60 +cmd:a=0;while ! `rpower $$CN stat|grep "Not Activated\|off" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:output=~Not Activated -cmd:rpower $$CN on -cmd:sleep 60 +check:output=~Not Activated|off end start:rpower_stat +cmd:rpower $$CN on +cmd:a=0;while ! `rpower $$CN stat|grep "Running\|on" >/dev/null`; do sleep 5;((a++));if [ $a -gt 5 ];then break;fi done cmd:rpower $$CN stat check:rc==0 -check:output=~Running +check:output=~Running|on cmd:rpower $$CN state check:rc==0 -check:output=~Running +check:output=~Running|on +cmd:rpower $$CN off +cmd:a=0;while ! `rpower $$CN stat|grep "Not Activated\|off" >/dev/null`; do sleep 5;((a++));if [ $a -gt 5 ];then break;fi done +cmd:rpower $$CN stat +check:rc==0 +check:output=~Not Activated|off +cmd:rpower $$CN state +check:rc==0 +check:output=~Not Activated|off end start:rpower_boot cmd:rpower $$CN off -cmd:sleep 60 +cmd:a=0;while ! `rpower $$CN stat|grep "Not Activated\|off" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:output=~Not Activated +check:output=~Not Activated|off cmd:rpower $$CN boot check:rc==0 -check:output=~Success -cmd:sleep 60 +cmd:a=0;while ! `rpower $$CN stat|grep "Running\|on" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:output=~Running -cmd:sleep 60 +check:output=~Running|on end start:rpower_on cmd:rpower $$CN off -cmd:sleep 60 +cmd:a=0;while ! `rpower $$CN stat|grep "Not Activated\|off" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:output=~Not Activated +check:output=~Not Activated|off cmd:rpower $$CN on check:rc==0 -check:output=~Success -cmd:sleep 60 +cmd:a=0;while ! `rpower $$CN stat|grep "Running\|on" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:output=~Running -cmd:sleep 60 +check:output=~Running|on end start:rpower_reset +cmd:rpower $$CN on +cmd:a=0;while ! `rpower $$CN stat|grep "Running\|on" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:ouptut=~Running +check:ouptut=~Running|on cmd:rpower $$CN reset check:rc==0 -check:output=~Success -cmd:sleep 60 +cmd:a=0;while ! `rpower $$CN stat|grep "Running\|on" >/dev/null`; do sleep 5;((a++));if [ $a -gt 11 ];then break;fi done cmd:rpower $$CN stat -check:output=~Running -cmd:sleep 60 +check:output=~Running|on end start:rpower_noderange cmd:rpower $$CN check:rc!=0 -check:output=~Usage +check:output=~Unsupported end start:rpower_noderange_nodeps cmd:rpower $$CN --nodeps check:rc!=0 -check:output=~Usage +check:output=~Unsupported end start:rpower_err_noderange From ae4ad2474438404ff6e5feb64dbb5b40dff20ce0 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Thu, 23 Mar 2017 07:30:31 -0400 Subject: [PATCH 146/187] modify makehosts testcase according to issue:add test case to makehosts erroneously deletes entries from /etc/hosts #2674 --- xCAT-test/autotest/testcase/makehosts/cases0 | 62 ++++++++++++++++---- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/xCAT-test/autotest/testcase/makehosts/cases0 b/xCAT-test/autotest/testcase/makehosts/cases0 index 9ec2032ac..46965af78 100644 --- a/xCAT-test/autotest/testcase/makehosts/cases0 +++ b/xCAT-test/autotest/testcase/makehosts/cases0 @@ -14,7 +14,7 @@ end start:makehosts_null description:makehosts -cmd:cp -f /etc/hosts /etc/hosts.xcatbak +cmd:cp -f /etc/hosts /etc/hosts.xcatbakautotest cmd:chtab node=compute hosts.ip="|node(\d+)|1.2.3.(\$1+0)|" hosts.hostnames="|(.*)|(\$1).cluster.net|" check:rc==0 cmd:mkdef -t node -o node01,node02 groups="compute" @@ -31,11 +31,11 @@ check:output=~node02 cmd:chtab -d node=compute hosts cmd:rmdef node01 cmd:rmdef node02 -cmd:mv -f /etc/hosts.xcatbak /etc/hosts +cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts end start:makehosts_l -cmd:cp -f /etc/hosts /etc/hosts.xcatbak +cmd:cp -f /etc/hosts /etc/hosts.xcatbakautotest cmd:chtab node=compute hosts.ip="|node(\d+)|1.2.3.(\$1+0)|" hosts.hostnames="|(.*)|(\$1).cluster.net|" check:rc==0 cmd:chdef -t node -o node01,node02 groups="compute" @@ -51,12 +51,12 @@ check:output=~node02.cluster.net cmd:chtab -d node=compute hosts cmd:rmdef node01 cmd:rmdef node02 -cmd:mv -f /etc/hosts.xcatbak /etc/hosts +cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts cmd:rm -rf /tmp/hosts end start:makehosts_d -cmd:cp -f /etc/hosts /etc/hosts.xcatbak +cmd:cp -f /etc/hosts /etc/hosts.xcatbakautotest cmd:chtab node=compute hosts.ip="|node(\d+)|1.2.3.(\$1+0)|" hosts.hostnames="|(.*)|(\$1).cluster.net|" check:rc==0 cmd:chdef -t node -o node01 groups="compute" @@ -73,12 +73,12 @@ cmd:diff /tmp/1 /tmp/2 check:output=~node01.cluster.net cmd:chtab -d node=compute hosts cmd:rmdef node01 -cmd:mv -f /etc/hosts.xcatbak /etc/hosts +cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts cmd:rm -f /tmp/1 /tmp/2 end start:makehosts_n -cmd:cp -f /etc/hosts /etc/hosts.xcatbak +cmd:cp -f /etc/hosts /etc/hosts.xcatbakautotest cmd:chtab node=compute hosts.ip="|node(\d+)|1.2.3.(\$1+0)|" hosts.hostnames="|(.*)|(\$1).cluster.net|" check:rc==0 cmd:chdef -t node -o node01 groups="compute" @@ -97,12 +97,12 @@ check:output=~node01.cluster.net cmd:chtab -d node=compute hosts cmd:rmdef node01 cmd:cp /etc/hosts /hosts -cmd:mv -f /etc/hosts.xcatbak /etc/hosts +cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts cmd:rm -rf /tmp/hosts end start:makehosts_n_noderange -cmd:cp -f /etc/hosts /etc/hosts.xcatbak +cmd:cp -f /etc/hosts /etc/hosts.xcatbakautotest cmd:chtab node=compute hosts.ip="|node(\d+)|1.2.3.(\$1+0)|" hosts.hostnames="|(.*)|(\$1).cluster.net|" check:rc==0 cmd:chdef -t node -o node01 groups="compute" @@ -119,10 +119,52 @@ cmd:cat /tmp/hosts check:output=~node01.cluster.net cmd:chtab -d node=compute hosts cmd:rmdef node01 -cmd:mv -f /etc/hosts.xcatbak /etc/hosts +cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts cmd:cat /etc/hosts| grep -v node01 > /tmp/1 cmd:mv -f /tmp/1 /etc/hosts cmd:rm -rf /tmp/hosts end +start:makehost_n_r +descriptions:modify makehosts testcases according to special node name eg:s01 and s01r* . for issue #2717 and #2683 +cmd:cp -f /etc/hosts /etc/hosts.xcatbakautotest +cmd:lsdef s01;if [ $? -eq 0 ]; then lsdef -l s01 -z >/tmp/s01.standa ;rmdef s01;fi +check:rc==0 +cmd:lsdef s01r1b01;if [ $? -eq 0 ]; then lsdef -l s01r1b01 -z >/tmp/s01r1b01.standa ;rmdef s01r1b01;fi +check:rc==0 +cmd:nodeadd s01 groups=service; chdef s01 ip=70.2.0.254;nodeadd s01r1b01 groups=compute; chdef s01r1b01 ip=80.2.0.254;makehosts +check:rc==0 +cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 =~ "70.2.0.254 s01" ]] && [[ $rc2 =~ "80.2.0.254 s01r1b01" ]];then exit 0;else exit 1;fi +check:rc==0 +cmd:makehosts s01 +check:rc==0 +cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 =~ "70.2.0.254 s01" ]] && [[ $rc2 =~ "80.2.0.254 s01r1b01" ]];then exit 0;else exit 1;fi +check:rc==0 +cmd:makehosts service +check:rc==0 +cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 =~ "70.2.0.254 s01" ]] && [[ $rc2 =~ "80.2.0.254 s01r1b01" ]];then exit 0;else exit 1;fi +check:rc==0 +cmd:makehosts -d s01 +check:rc==0 +cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 = "" ]] && [[ $rc2 =~ "80.2.0.254 s01r1b01" ]];then exit 0;else exit 1;fi +check:rc==0 +cmd:makehosts +check:rc==0 +cmd:makehosts -d service +check:rc==0 +cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 = "" ]] && [[ $rc2 =~ "80.2.0.254 s01r1b01" ]];then exit 0;else exit 1;fi +check:rc==0 +cmd:makehosts +check:rc==0 +cmd:makehosts -d s01r1b01 +check:rc==0 +cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 =~ "70.2.0.254 s01" ]] && [[ $rc2 = "" ]];then exit 0;else exit 1;fi +check:rc==0 +cmd:if [ -e /tmp/s01.standa ]; then rmdef s01; cat /tmp/s01.standa | mkdef -z; rm -rf /tmp/s01.standa; fi +check:rc==0 +cmd:if [ -e /tmp/s01r1b01.standa ]; then rmdef s01r1b01; cat /tmp/s01r1b01.standa | mkdef -z; rm -rf /tmp/s01r1b01.standa; fi +check:rc==0 +cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts +end + From 21436b9577c83c525e09ad254bb5167161e5fc63 Mon Sep 17 00:00:00 2001 From: xuweibj Date: Thu, 23 Mar 2017 17:32:22 +0800 Subject: [PATCH 147/187] fix issue 2727, add Async path to @INC when want to use it (#2730) --- xCAT-server/lib/xcat/plugins/docker.pm | 4 ++++ xCAT-server/lib/xcat/plugins/openbmc.pm | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/docker.pm b/xCAT-server/lib/xcat/plugins/docker.pm index 5b7e16796..3118da70c 100755 --- a/xCAT-server/lib/xcat/plugins/docker.pm +++ b/xCAT-server/lib/xcat/plugins/docker.pm @@ -12,6 +12,10 @@ package xCAT_plugin::docker; BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + my $async_path = "/usr/local/share/perl5/"; + unless (grep { $_ eq $async_path } @INC) { + push @INC, $async_path; + } } use lib "$::XCATROOT/lib/perl"; diff --git a/xCAT-server/lib/xcat/plugins/openbmc.pm b/xCAT-server/lib/xcat/plugins/openbmc.pm index 88441b2cf..6a102cd68 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc.pm @@ -6,6 +6,10 @@ package xCAT_plugin::openbmc; BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + my $async_path = "/usr/local/share/perl5/"; + unless (grep { $_ eq $async_path } @INC) { + push @INC, $async_path; + } } use lib "$::XCATROOT/lib/perl"; use strict; From 60475151226071d7e755f06993974c771813f376 Mon Sep 17 00:00:00 2001 From: ertaozh Date: Thu, 23 Mar 2017 05:48:56 -0400 Subject: [PATCH 148/187] enable ipmi raw data if xcatdebugmodel set --- xCAT-server/lib/perl/xCAT/IPMI.pm | 5 +++++ xCAT-server/lib/xcat/plugins/ipmi.pm | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/xCAT-server/lib/perl/xCAT/IPMI.pm b/xCAT-server/lib/perl/xCAT/IPMI.pm index bb332bb13..05014a585 100644 --- a/xCAT-server/lib/perl/xCAT/IPMI.pm +++ b/xCAT-server/lib/perl/xCAT/IPMI.pm @@ -15,6 +15,7 @@ use lib "$::XCATROOT/lib/perl"; use strict; use warnings "all"; use Time::HiRes qw/time/; +use xCAT::SvrUtils; use IO::Socket::INET qw/!AF_INET6 !PF_INET6/; my $initialtimeout = 0.5; @@ -415,6 +416,10 @@ sub subcmd { my %args = @_; $self->{expectedcmd} = $args{command}; $self->{expectednetfn} = $args{netfn} + 1; + if ($self->{onlogon_args}->{xcatdebugmodel}) { + my $msg = sprintf ("The command running: $self->{onlogon_args}->{command}:$self->{onlogon_args}->{subcommand}(@{$self->{onlogon_args}->{extraargs}}), the raw data: netfn(0x%02x), cmd(0x%02x)", $args{netfn}, $args{command}); + xCAT::SvrUtils::sendmsg([0, $msg], $self->{onlogon_args}->{outfunc}); + } my $seqincrement = 7; while ($tabooseq{ $self->{expectednetfn} }->{ $self->{expectedcmd} }->{ $self->{seqlun} } and $seqincrement) { #avoid using a seqlun formerly marked 'taboo', but don't advance by more than 7, just in case $tabooseq{ $self->{expectednetfn} }->{ $self->{expectedcmd} }->{ $self->{seqlun} }--; #forgive a taboo lun over time... diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index ae76557c1..e505d62eb 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -43,6 +43,7 @@ my %allerrornodes = (); my %newnodestatus = (); my $global_sessdata; my %child_pids; +my $xcatdebugmodel = 0; my $IPMIXCAT = "/opt/xcat/bin/ipmitool-xcat"; my $NON_BLOCK = 1; @@ -8162,6 +8163,7 @@ sub process_request { if ($::XCATSITEVALS{ipmitimeout}) { $ipmitimeout = $::XCATSITEVALS{ipmitimeout} } if ($::XCATSITEVALS{ipmiretries}) { $ipmitrys = $::XCATSITEVALS{ipmitretries} } if ($::XCATSITEVALS{ipmisdrcache}) { $enable_cache = $::XCATSITEVALS{ipmisdrcache} } + if ($::XCATSITEVALS{xcatdebugmodel}) { $xcatdebugmodel = $::XCATSITEVALS{xcatdebugmodel} } #my @threads; my @donargs = (); @@ -8375,6 +8377,8 @@ sub donode { command => $command, extraargs => \@exargs, subcommand => $exargs[0], + xcatdebugmodel => $xcatdebugmodel, + outfunc => $callback, }; if ($sessiondata{$node}->{ipmisession}->{error}) { xCAT::SvrUtils::sendmsg([ 1, $sessiondata{$node}->{ipmisession}->{error} ], $callback, $node, %allerrornodes); From 87c182d25db2f6fc6f26b6d23ca342cd390e130a Mon Sep 17 00:00:00 2001 From: junxiawang Date: Thu, 23 Mar 2017 09:01:44 -0400 Subject: [PATCH 149/187] modify bundle files for makehosts testcase modified --- xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle | 1 + xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle | 1 + xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle | 5 +++-- xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 1 + xCAT-test/autotest/bundle/rhels7.3_x86_64.bundle | 1 + xCAT-test/autotest/bundle/sles11.4_ppc64.bundle | 1 + xCAT-test/autotest/bundle/sles11.4_x86_64.bundle | 1 + xCAT-test/autotest/bundle/sles12.2_ppc64le.bundle | 1 + xCAT-test/autotest/bundle/ubuntu14.04.4_ppc64le.bundle | 1 + xCAT-test/autotest/bundle/ubuntu14.04.4_x86_64.bundle | 1 + xCAT-test/autotest/bundle/ubuntu16.04.1_ppc64le.bundle | 1 + xCAT-test/autotest/bundle/ubuntu16.04.1_x86_64.bundle | 1 + 12 files changed, 14 insertions(+), 2 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle b/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle index 3d02946bd..d0f631fd2 100644 --- a/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle @@ -232,6 +232,7 @@ makehosts_l makehosts_d makehosts_n makehosts_n_noderange +makehost_n_r xdcp_src_dst makedns_h makedns_d_node diff --git a/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle b/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle index bd2907ad7..9e922a688 100644 --- a/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle +++ b/xCAT-test/autotest/bundle/rhels6.9_x86_64.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle index 0303d2545..9577fb385 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle @@ -4,8 +4,6 @@ go_xcat_noinput go_xcat_with_x go_xcat_with_xcat-version-1 go_xcat_online_repo_case6 -makehosts_help -makehosts_n_noderange updatenode_h updatenode_v updatenode_diskful_syncfiles @@ -224,11 +222,14 @@ lsxcatd_null lsxcatd_h lsxcatd_d lsxcatd_a +makehosts_help +makehosts_n_noderange makehosts_h makehosts_null makehosts_l makehosts_d makehosts_n +makehost_n_r xdcp_src_dst makedns_h makedns_d_node diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index e7dc0de66..8d723572b 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -224,6 +224,7 @@ makehosts_l makehosts_d makehosts_n makehosts_n_noderange +makehost_n_r xdcp_src_dst makedns_h makedns_d_node diff --git a/xCAT-test/autotest/bundle/rhels7.3_x86_64.bundle b/xCAT-test/autotest/bundle/rhels7.3_x86_64.bundle index 497756717..53b49e38d 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_x86_64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_x86_64.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle b/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle index 66b390c1d..956d7fa6b 100644 --- a/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle +++ b/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle @@ -214,6 +214,7 @@ makehosts_l makehosts_d makehosts_n makehosts_n_noderange +makehost_n_r xdcp_src_dst makedns_h makedns_d_node diff --git a/xCAT-test/autotest/bundle/sles11.4_x86_64.bundle b/xCAT-test/autotest/bundle/sles11.4_x86_64.bundle index 620a1d9a4..1515dd3a5 100644 --- a/xCAT-test/autotest/bundle/sles11.4_x86_64.bundle +++ b/xCAT-test/autotest/bundle/sles11.4_x86_64.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/sles12.2_ppc64le.bundle b/xCAT-test/autotest/bundle/sles12.2_ppc64le.bundle index 65ff91ea2..13d930b24 100644 --- a/xCAT-test/autotest/bundle/sles12.2_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/sles12.2_ppc64le.bundle @@ -10,6 +10,7 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/ubuntu14.04.4_ppc64le.bundle b/xCAT-test/autotest/bundle/ubuntu14.04.4_ppc64le.bundle index be6932c9d..f258d566c 100644 --- a/xCAT-test/autotest/bundle/ubuntu14.04.4_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/ubuntu14.04.4_ppc64le.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n_noderange makehosts_n +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/ubuntu14.04.4_x86_64.bundle b/xCAT-test/autotest/bundle/ubuntu14.04.4_x86_64.bundle index 72d300f72..b45a72056 100644 --- a/xCAT-test/autotest/bundle/ubuntu14.04.4_x86_64.bundle +++ b/xCAT-test/autotest/bundle/ubuntu14.04.4_x86_64.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n_noderange makehosts_n +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/ubuntu16.04.1_ppc64le.bundle b/xCAT-test/autotest/bundle/ubuntu16.04.1_ppc64le.bundle index 74df70cbe..212853add 100644 --- a/xCAT-test/autotest/bundle/ubuntu16.04.1_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/ubuntu16.04.1_ppc64le.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n_noderange makehosts_n +makehost_n_r chdef_null chdef_z chdef_t_o_error diff --git a/xCAT-test/autotest/bundle/ubuntu16.04.1_x86_64.bundle b/xCAT-test/autotest/bundle/ubuntu16.04.1_x86_64.bundle index 51decc528..9b377bcca 100644 --- a/xCAT-test/autotest/bundle/ubuntu16.04.1_x86_64.bundle +++ b/xCAT-test/autotest/bundle/ubuntu16.04.1_x86_64.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n_noderange makehosts_n +makehost_n_r chdef_null chdef_z chdef_t_o_error From f26aba338b7be2d7f7953fa54dfd0c23f60f0b87 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Thu, 23 Mar 2017 12:07:52 -0400 Subject: [PATCH 150/187] rinv command get error message on Habanero --- xCAT-server/lib/xcat/plugins/ipmi.pm | 45 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index ae76557c1..0134cb4e4 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -2666,16 +2666,18 @@ sub add_textual_frus { my $type = shift; my $sessdata = shift; unless ($type) { $type = 'hw'; } + if ($desc =~ /System Firmware/i and $category =~ /product/i) { $type = 'firmware,bmc'; } - if ($desc =~ /NODE \d+/ and $category =~ /chassis/) { + if ( ($desc =~ /NODE \d+/ or $desc =~ /Backplane/) and $category =~ /chassis/) { add_textual_fru($parsedfru, $desc . " " . $categorydesc . "Part Number", $category, "partnumber", 'model', $sessdata); add_textual_fru($parsedfru, $desc . " " . $categorydesc . "Serial Number", $category, "serialnumber", 'serial', $sessdata); } else { add_textual_fru($parsedfru, $desc . " " . $categorydesc . "Part Number", $category, "partnumber", $type, $sessdata); add_textual_fru($parsedfru, $desc . " " . $categorydesc . "Serial Number", $category, "serialnumber", $type, $sessdata); } + add_textual_fru($parsedfru, $desc . " " . $categorydesc . "Manufacturer", $category, "manufacturer", $type, $sessdata); add_textual_fru($parsedfru, $desc . " " . $categorydesc . "FRU Number", $category, "frunum", $type, $sessdata); add_textual_fru($parsedfru, $desc . " " . $categorydesc . "Version", $category, "version", $type, $sessdata); @@ -3035,6 +3037,7 @@ sub initfru_with_mprom { sub process_currfruid { my $rsp = shift; my $sessdata = shift; + if ($rsp->{code} == 0xcb) { $sessdata->{currfrudata} = "Not Present"; $sessdata->{currfrudone} = 1; @@ -3299,7 +3302,11 @@ sub initfru_zero { if ($sessdata->{skipotherfru} and isopenpower($sessdata)) { # For openpower servers, fru 3 is used to get MTM/Serial information, fru 47 is used to get firmware information - @{$sessdata->{frus_for_openpower}} = qw(3 47); + if (isHabanero($sessdata)) { + @{$sessdata->{frus_for_openpower}} = qw(2 43); + } else { + @{$sessdata->{frus_for_openpower}} = qw(3 47); + } my %fruids_hash = map {$_ => 1} @{$sessdata->{frus_for_openpower}}; foreach my $key (keys %{ $sessdata->{sdr_hash} }) { my $sdr = $sessdata->{sdr_hash}->{$key}; @@ -3692,7 +3699,7 @@ sub readcurrfrudevice { if ($data[0] != $sessdata->{currfruchunk}) { # Fix FRU 43,48 and 49 for GRS server that they can not return as much data as shall return - if ($data[0] gt 0) { + if ($data[0] ge 0) { $sessdata->{currfrudone} = 1; } else { my $text = "Received incorrect data from BMC for FRU ID: " . $sessdata->{currfruid}; @@ -7683,7 +7690,7 @@ sub preprocess_request { #pdu commands will be handled in the pdu plugin if(($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')){ - return 0; + 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')) { @@ -8459,6 +8466,36 @@ sub genhwtree } +########################################################################## +# To check if this is Habanero system +# we identified Hananero via Chassis Part number : 8348-21C +########################################################################## +sub isHabanero +{ + my $sessdata = shift; + + my $bmc_addr = $sessdata->{ipmisession}->{bmc}; + my $bmc_userid = $sessdata->{ipmisession}->{userid}; + my $bmc_password = undef; + if (defined($sessdata->{ipmisession}->{password})) { + $bmc_password = $sessdata->{ipmisession}->{password}; + } + + my $pre_cmd = "$IPMIXCAT -H $bmc_addr -I lanplus -U $bmc_userid"; + if ($bmc_password) { + $pre_cmd = $pre_cmd . " -P $bmc_password"; + } + + my $cmd = $pre_cmd . " fru print 2"; + my $output = xCAT::Utils->runcmd($cmd, -1); + if ($::RUNCMD_RC == 0) { + if ($output =~ /8348-21C/) { + return 1; + } + } + + return 0; +} From 35e704bd14a6dd3e7ec781f93f88290a2a5610b5 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Thu, 23 Mar 2017 15:05:21 -0400 Subject: [PATCH 151/187] modify with Victor's review --- xCAT-server/lib/xcat/plugins/ipmi.pm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index 0134cb4e4..b2b4e8d24 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -3288,7 +3288,7 @@ sub initfru_zero { if ($_->{encoding} == 3) { $fru->value($_->{value}); } else { - next; + #print Dumper($_); #print $_->{encoding}; @@ -3301,9 +3301,10 @@ sub initfru_zero { if ($sessdata->{skipotherfru}) { #skip non-primary fru devices if ($sessdata->{skipotherfru} and isopenpower($sessdata)) { - # For openpower servers, fru 3 is used to get MTM/Serial information, fru 47 is used to get firmware information - if (isHabanero($sessdata)) { + # For openpower Big Data servers, fru 2 has MTM/Serial and fru 43 has firmware information + if (isopenpower_bd($sessdata)) { @{$sessdata->{frus_for_openpower}} = qw(2 43); + # For openpower HPC servers, fru 3 has MTM/Serial and fru 47 has firmware information } else { @{$sessdata->{frus_for_openpower}} = qw(3 47); } @@ -8467,10 +8468,10 @@ sub genhwtree } ########################################################################## -# To check if this is Habanero system -# we identified Hananero via Chassis Part number : 8348-21C +# To check if this is openpower Big Data system +# we identified it via Chassis Part number : 8348-21C ########################################################################## -sub isHabanero +sub isopenpower_bd { my $sessdata = shift; From 4b0ce18b9d2865b8f1668040df371d0eb3c8c4e9 Mon Sep 17 00:00:00 2001 From: Mark Gurevich Date: Thu, 23 Mar 2017 15:40:22 -0400 Subject: [PATCH 152/187] Add DSH_VERIFY environment variable to xdsh command --- .../admin-guides/references/man1/xdsh.1.rst | 34 +++++++++++-------- perl-xCAT/xCAT/DSHCLI.pm | 8 ++++- xCAT-client/bin/xdsh | 5 +++ xCAT-client/pods/man1/xdsh.1.pod | 32 +++++++++-------- xCAT-server/lib/xcat/dsh/Context/DSH.pm | 1 + 5 files changed, 51 insertions(+), 29 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man1/xdsh.1.rst b/docs/source/guides/admin-guides/references/man1/xdsh.1.rst index 51f71f74d..6132f8048 100644 --- a/docs/source/guides/admin-guides/references/man1/xdsh.1.rst +++ b/docs/source/guides/admin-guides/references/man1/xdsh.1.rst @@ -264,7 +264,7 @@ running commands, are terminated (SIGTERM). xdsh will chroot (xcatchroot for AIX) to this path and run the xdsh command against the install image. No other xdsh flags, environment variables apply with this input. A noderange is not accepted. Only runs on the local host, - normally the Management Node. The command you run must not prompt for input, the prompt will not be returned to you, and it will appear that xdsh hangs. + normally the Management Node. The command you run must not prompt for input, the prompt will not be returned to you, and it will appear that \ **xdsh**\ hangs. @@ -381,8 +381,8 @@ running commands, are terminated (SIGTERM). displays an error and terminates execution for the remote targets that failed to respond. If \ *timeout*\ is not specified, \ **xdsh**\ waits indefinitely to continue processing output from - all remote targets. The exception is the -K flag which defaults - to 10 seconds. + all remote targets. The exception is the \ **-K**\ flag which defaults + to 10 seconds. @@ -512,22 +512,28 @@ running commands, are terminated (SIGTERM). If \ **DSH_REMOTE_PASSWORD**\ 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. + you use the \ **-K**\ flag, you will not be prompted for a password. \ **DSH_SYNTAX**\ Specifies the shell syntax to use on remote targets; \ **ksh**\ or - \ **csh**\ . If not specified, the \ **ksh**\ syntax is assumed. This + \ **csh**\ . If not specified, the \ **ksh**\ syntax is assumed. This variable is overridden by the \ **-S**\ flag. \ **DSH_TIMEOUT**\ - Specifies the time, in seconds, to wait for output from - each remote target. This variable is overridden by the \ **-t**\ flag. + Specifies the time, in seconds, to wait for output from + each remote target. This variable is overridden by the \ **-t**\ flag. + + + +\ **DSH_VERIFY**\ + + Verifies each target before executing any remote commands on the target. If a target is not responding, execution of remote commands for the target is canceled. This variable is overridden by the \ **-v**\ flag. @@ -537,10 +543,10 @@ running commands, are terminated (SIGTERM). ********************************** -To provide backward compatibility for scripts written using dsh in +To provide backward compatibility for scripts written using \ **dsh**\ in AIX and CSM, a tool has been provided \ **groupfiles4dsh**\ , which will build node group files from the -xCAT database that can be used by dsh. See \ **man groupfiles4dsh**\ . +xCAT database that can be used by \ **dsh**\ . See \ **man groupfiles4dsh**\ . **************** @@ -566,7 +572,7 @@ userdefined. ******************* -The dsh command exit code is 0 if the command executed without errors and all remote shell commands finished with exit codes of 0. If internal dsh errors occur or the remote shell commands do not complete successfully, the dsh command exit value is greater than 0. The exit value is increased by 1 for each successive instance of an unsuccessful remote command execution. If the remotely issued command is run in the background, the exit code of the remotely issued command is 0. +The \ **xdsh**\ command exit code is 0 if the command executed without errors and all remote shell commands finished with exit codes of 0. If internal dsh errors occur or the remote shell commands do not complete successfully, the dsh command exit value is greater than 0. The exit value is increased by 1 for each successive instance of an unsuccessful remote command execution. If the remotely issued command is run in the background, the exit code of the remotely issued command is 0. **************** @@ -662,7 +668,7 @@ on the service node fedora9 diskless image, enter: To define the QLogic IB switch as a node and to set up the SSH keys for IB switch \ **qswitch**\ with device configuration file - \ **/var/opt/xcat/IBSwitch/Qlogic/config**\ and user name \ **username**\ , Enter + \ **/var/opt/xcat/IBSwitch/Qlogic/config**\ and user name \ **username**\ , enter .. code-block:: perl @@ -674,7 +680,7 @@ on the service node fedora9 diskless image, enter: -10. To define the Management Node in the database so you can use xdsh, Enter +10. To define the Management Node in the database so you can use \ **xdsh**\ , enter .. code-block:: perl @@ -685,7 +691,7 @@ on the service node fedora9 diskless image, enter: 11. To define the Mellanox switch as a node and run a command to show the ssh keys. -\ **mswitch**\ with and user name \ **username**\ , Enter +\ **mswitch**\ with and user name \ **username**\ , enter .. code-block:: perl @@ -723,7 +729,7 @@ on the service node fedora9 diskless image, enter: 13. - To run xdsh with the non-root userid "user1" that has been setup as an xCAT userid and with sudo on node1 and node2 to run as root, do the following, see xCAT doc on Granting_Users_xCAT_privileges: + To run \ **xdsh**\ with the non-root userid "user1" that has been setup as an xCAT userid and with sudo on node1 and node2 to run as root, do the following, see xCAT doc on Granting_Users_xCAT_privileges: .. code-block:: perl diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index 2fa5c5a14..787bb64c7 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -50,7 +50,7 @@ our @dsh_valid_env = ( 'DSH_REMOTE_PASSWORD', 'DSH_TO_USERID', 'DSH_FROM_USERID', 'DEVICETYPE', 'RSYNCSN', 'DSH_RSYNC_FILE', - 'RSYNCSNONLY', + 'RSYNCSNONLY', 'DSH_VERIFY', ); select(STDERR); $| = 1; @@ -2492,6 +2492,12 @@ sub config_dsh $dsh_trace && xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + $$options{'verify'} = $$options{'verify'} || $ENV{'DSH_VERIFY'} || undef; + my $rsp = {}; + $rsp->{data}->[0] = "TRACE: Verify value is $$options{'verify'} "; + $dsh_trace + && xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + # Check if $$options{'pre-command'} has been overwritten # Mellanox uses pre-command = cli if (!$$options{'pre-command'}) diff --git a/xCAT-client/bin/xdsh b/xCAT-client/bin/xdsh index 164f4ba77..89e4ff0a6 100644 --- a/xCAT-client/bin/xdsh +++ b/xCAT-client/bin/xdsh @@ -190,6 +190,11 @@ if ($ENV{'DSH_ENVIRONMENT'}) push(@{ $cmdref->{env} }, "DSH_ENVIRONMENT=$ENV{'DSH_ENVIRONMENT'}"); } +if ($ENV{'DSH_VERIFY'}) +{ + push(@{ $cmdref->{env} }, "DSH_VERIFY=$ENV{'DSH_VERIFY'}"); +} + xCAT::Client::submit_request($cmdref, \&xCAT::Client::handle_response); exit $xCAT::Client::EXITCODE; diff --git a/xCAT-client/pods/man1/xdsh.1.pod b/xCAT-client/pods/man1/xdsh.1.pod index a9d06a6c4..38596e793 100644 --- a/xCAT-client/pods/man1/xdsh.1.pod +++ b/xCAT-client/pods/man1/xdsh.1.pod @@ -231,7 +231,7 @@ for valid names. xdsh will chroot (xcatchroot for AIX) to this path and run the xdsh command against the install image. No other xdsh flags, environment variables apply with this input. A noderange is not accepted. Only runs on the local host, -normally the Management Node. The command you run must not prompt for input, the prompt will not be returned to you, and it will appear that xdsh hangs. +normally the Management Node. The command you run must not prompt for input, the prompt will not be returned to you, and it will appear that B hangs. =item B<-K>|B<--ssh-setup> @@ -324,8 +324,8 @@ available from any target in the specified I, B displays an error and terminates execution for the remote targets that failed to respond. If I is not specified, B waits indefinitely to continue processing output from -all remote targets. The exception is the -K flag which defaults -to 10 seconds. +all remote targets. The exception is the B<-K> flag which defaults +to 10 seconds. =item B<-T>|B<--trace> @@ -430,28 +430,32 @@ remote I is used. 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. +you use the B<-K> flag, you will not be prompted for a password. =item B Specifies the shell syntax to use on remote targets; B or -B. If not specified, the B syntax is assumed. This +B. If not specified, the B syntax is assumed. This variable is overridden by the B<-S> flag. =item B -Specifies the time, in seconds, to wait for output from -each remote target. This variable is overridden by the B<-t> flag. +Specifies the time, in seconds, to wait for output from +each remote target. This variable is overridden by the B<-t> flag. + +=item B + +Verifies each target before executing any remote commands on the target. If a target is not responding, execution of remote commands for the target is canceled. This variable is overridden by the B<-v> flag. =back =head1 B -To provide backward compatibility for scripts written using dsh in +To provide backward compatibility for scripts written using B in AIX and CSM, a tool has been provided B, which will build node group files from the -xCAT database that can be used by dsh. See B. +xCAT database that can be used by B. See B. =head1 B @@ -470,7 +474,7 @@ userdefined. =head1 B -The dsh command exit code is 0 if the command executed without errors and all remote shell commands finished with exit codes of 0. If internal dsh errors occur or the remote shell commands do not complete successfully, the dsh command exit value is greater than 0. The exit value is increased by 1 for each successive instance of an unsuccessful remote command execution. If the remotely issued command is run in the background, the exit code of the remotely issued command is 0. +The B command exit code is 0 if the command executed without errors and all remote shell commands finished with exit codes of 0. If internal dsh errors occur or the remote shell commands do not complete successfully, the dsh command exit value is greater than 0. The exit value is increased by 1 for each successive instance of an unsuccessful remote command execution. If the remotely issued command is run in the background, the exit code of the remotely issued command is 0. =head1 B @@ -524,20 +528,20 @@ To cleanup the servicenode directory that stages the copy of files to the nodes, To define the QLogic IB switch as a node and to set up the SSH keys for IB switch B with device configuration file -B and user name B, Enter +B and user name B, enter chdef -t node -o qswitch groups=all nodetype=switch xdsh qswitch -K -l username --devicetype IBSwitch::Qlogic =item 10. -To define the Management Node in the database so you can use xdsh, Enter +To define the Management Node in the database so you can use B, enter xcatconfig -m =item 11. To define the Mellanox switch as a node and run a command to show the ssh keys. -B with and user name B, Enter +B with and user name B, enter chdef -t node -o mswitch groups=all nodetype=switch @@ -559,7 +563,7 @@ If it is for Telnet, add I in front of the user name: I. =item 13. -To run xdsh with the non-root userid "user1" that has been setup as an xCAT userid and with sudo on node1 and node2 to run as root, do the following, see xCAT doc on Granting_Users_xCAT_privileges: +To run B with the non-root userid "user1" that has been setup as an xCAT userid and with sudo on node1 and node2 to run as root, do the following, see xCAT doc on Granting_Users_xCAT_privileges: xdsh node1,node2 --sudo -l user1 "cat /etc/passwd" diff --git a/xCAT-server/lib/xcat/dsh/Context/DSH.pm b/xCAT-server/lib/xcat/dsh/Context/DSH.pm index 14299915b..2d30f630d 100644 --- a/xCAT-server/lib/xcat/dsh/Context/DSH.pm +++ b/xCAT-server/lib/xcat/dsh/Context/DSH.pm @@ -132,6 +132,7 @@ sub context_properties { || $ENV{'DSH_REPORTS_DIRECTORY'}; $properties{'DSH_SYNTAX'} = $ENV{'DSH_SYNTAX'}; $properties{'DSH_TIMEOUT'} = $ENV{'DSH_TIMEOUT'}; + $properties{'DSH_VERIFY'} = $ENV{'DSH_VERIFY'}; $properties{'RSYNC_RSH'} = $ENV{'RSYNC_RSH'}; if ($ENV{'DSH_ON_HMC'}) { From d022582718c60801084b4c6c99d20047a0480753 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Thu, 23 Mar 2017 17:29:30 -0400 Subject: [PATCH 153/187] add back the line I deleted --- xCAT-server/lib/xcat/plugins/ipmi.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index b2b4e8d24..ee9f2184e 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -3288,7 +3288,7 @@ sub initfru_zero { if ($_->{encoding} == 3) { $fru->value($_->{value}); } else { - + next; #print Dumper($_); #print $_->{encoding}; From fd5e40b8ca535d9584035af1ecb458af5907e656 Mon Sep 17 00:00:00 2001 From: banuchka Date: Fri, 24 Mar 2017 12:01:12 +0000 Subject: [PATCH 154/187] add console.logging=full if global consoleondemand set to no. Use value from consoleondemand per node basis. --- xCAT-server/lib/xcat/plugins/confluent.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/confluent.pm b/xCAT-server/lib/xcat/plugins/confluent.pm index 595d00bf6..0b0602acc 100644 --- a/xCAT-server/lib/xcat/plugins/confluent.pm +++ b/xCAT-server/lib/xcat/plugins/confluent.pm @@ -463,7 +463,7 @@ sub donodeent { } } if (defined($cfgent->{consoleondemand})) { - if ($cfgent->{consoleondemand}) { + if ($cfgent->{consoleondemand} == 'yes') { $parameters{'console.logging'} = 'none'; } else { @@ -472,6 +472,9 @@ sub donodeent { } elsif ($::XCATSITEVALS{'consoleondemand'} and $::XCATSITEVALS{'consoleondemand'} !~ m/^n/) { $parameters{'console.logging'} = 'none'; } + elsif ($::XCATSITEVALS{'consoleondemand'} and $::XCATSITEVALS{'consoleondemand'} == 'no') { + $parameters{'console.logging'} = 'full'; + } # ok, now for nodepos... if (defined $cfgent->{u}) { From 8b8021fa3f9b42827a9d2cb17c2b65dc3b3ae807 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Fri, 24 Mar 2017 14:18:25 -0400 Subject: [PATCH 155/187] remove checking for Habanero server --- xCAT-server/lib/xcat/plugins/ipmi.pm | 41 ++-------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index ee9f2184e..30edfb46e 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -3302,12 +3302,8 @@ sub initfru_zero { if ($sessdata->{skipotherfru} and isopenpower($sessdata)) { # For openpower Big Data servers, fru 2 has MTM/Serial and fru 43 has firmware information - if (isopenpower_bd($sessdata)) { - @{$sessdata->{frus_for_openpower}} = qw(2 43); # For openpower HPC servers, fru 3 has MTM/Serial and fru 47 has firmware information - } else { - @{$sessdata->{frus_for_openpower}} = qw(3 47); - } + @{$sessdata->{frus_for_openpower}} = qw(2 3 43 47); my %fruids_hash = map {$_ => 1} @{$sessdata->{frus_for_openpower}}; foreach my $key (keys %{ $sessdata->{sdr_hash} }) { my $sdr = $sessdata->{sdr_hash}->{$key}; @@ -3594,7 +3590,7 @@ sub add_fruhash { $fru->rec_type("hw"); } $fru->value($sessdata->{currfrudata}); - if (exists($sessdata->{currfrusdr})) { + if ($sessdata->{currfrusdr}) { $fru->desc($sessdata->{currfrusdr}->id_string); } $sessdata->{fru_hash}->{ $sessdata->{frudex} } = $fru; @@ -8467,37 +8463,4 @@ sub genhwtree } -########################################################################## -# To check if this is openpower Big Data system -# we identified it via Chassis Part number : 8348-21C -########################################################################## -sub isopenpower_bd -{ - my $sessdata = shift; - - my $bmc_addr = $sessdata->{ipmisession}->{bmc}; - my $bmc_userid = $sessdata->{ipmisession}->{userid}; - my $bmc_password = undef; - if (defined($sessdata->{ipmisession}->{password})) { - $bmc_password = $sessdata->{ipmisession}->{password}; - } - - my $pre_cmd = "$IPMIXCAT -H $bmc_addr -I lanplus -U $bmc_userid"; - if ($bmc_password) { - $pre_cmd = $pre_cmd . " -P $bmc_password"; - } - - my $cmd = $pre_cmd . " fru print 2"; - my $output = xCAT::Utils->runcmd($cmd, -1); - if ($::RUNCMD_RC == 0) { - if ($output =~ /8348-21C/) { - return 1; - } - } - - return 0; -} - - - 1; From 49257896031fb2d29e6fbdbd5d465e5ad730b494 Mon Sep 17 00:00:00 2001 From: bybai Date: Sun, 26 Mar 2017 23:05:44 -0400 Subject: [PATCH 156/187] polished --- xCAT-test/autotest/testcase/rpower/cases0 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-test/autotest/testcase/rpower/cases0 b/xCAT-test/autotest/testcase/rpower/cases0 index 6322fa241..6f47659f5 100644 --- a/xCAT-test/autotest/testcase/rpower/cases0 +++ b/xCAT-test/autotest/testcase/rpower/cases0 @@ -67,13 +67,13 @@ end start:rpower_noderange cmd:rpower $$CN check:rc!=0 -check:output=~Unsupported +check:output=~Unsupported|Usage end start:rpower_noderange_nodeps cmd:rpower $$CN --nodeps check:rc!=0 -check:output=~Unsupported +check:output=~Unsupported|Usage end start:rpower_err_noderange From d17f54004381e9026016c4946588f3f319c53e9b Mon Sep 17 00:00:00 2001 From: hu-weihua Date: Sun, 26 Mar 2017 23:07:08 -0400 Subject: [PATCH 157/187] Remove invalid cases and remove stop label of xdcp_src_dst --- xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 7 ------- 1 file changed, 7 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index e7dc0de66..6deef43a1 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -152,13 +152,6 @@ rpower_reset rpower_noderange rpower_noderange_nodeps rpower_err_noderange -rscan_noderange -rscan_x -rscan_z -rscan_w -rscan_x_w -rscan_z_w -rvitals_lcds rvitals_noderange_err tabdump_table tabdump_d From 65491e3e409e7a017393e74cff6b6d6dcf5b2f82 Mon Sep 17 00:00:00 2001 From: hu-weihua Date: Sun, 26 Mar 2017 23:08:31 -0400 Subject: [PATCH 158/187] Remove invalid cases and remove stop label of xdcp_src_dst --- xCAT-test/autotest/testcase/xdcp/cases0 | 1 - 1 file changed, 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/xdcp/cases0 b/xCAT-test/autotest/testcase/xdcp/cases0 index efaa943df..b23b1c647 100644 --- a/xCAT-test/autotest/testcase/xdcp/cases0 +++ b/xCAT-test/autotest/testcase/xdcp/cases0 @@ -10,7 +10,6 @@ check:output=~Version end start:xdcp_src_dst -stop:yes cmd:xdsh $$CN rm -f /tmp/hosts cmd:xdcp $$CN /etc/hosts /tmp/hosts check:rc==0 From 59996da1da972038dcc8198f658cf4f5e0289d97 Mon Sep 17 00:00:00 2001 From: hu-weihua Date: Mon, 27 Mar 2017 00:32:21 -0400 Subject: [PATCH 159/187] Fix bug 2667 test case nodeset_check_warninginfo need to refine --- xCAT-test/autotest/testcase/nodeset/cases0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/nodeset/cases0 b/xCAT-test/autotest/testcase/nodeset/cases0 index 49f2ec47d..3f81504ec 100644 --- a/xCAT-test/autotest/testcase/nodeset/cases0 +++ b/xCAT-test/autotest/testcase/nodeset/cases0 @@ -169,7 +169,7 @@ cmd:mkdef -t node -o testnode1 arch=ppc64el cons=ipmi groups=pbmc mgt=ipmi ip=10 check:rc==0 cmd:nodeset testnode1 osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute check:rc==0 -check:output=~Warning: testnode1: petitboot might be invalid +check:output=~Warning: testnode1: petitboot might be invalid|testnode1 could not be resolved cmd:noderm testnode1 end From 4fc47291b9eaf0f0bc14db5e56690989a4c672c4 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 27 Mar 2017 14:24:00 +0800 Subject: [PATCH 160/187] modify hierarchy testcase for syncfile issue:#2624 (#2753) --- .../installation/reg_linux_diskfull_installation_hierarchy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy index abba79cee..09f12aecc 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy +++ b/xCAT-test/autotest/testcase/installation/reg_linux_diskfull_installation_hierarchy @@ -27,6 +27,8 @@ check:rc==0 cmd:copycds $$ISO check:rc==0 +cmd:updatenode $$CN -f +check:rc==0 cmd:rinstall $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute check:rc==0 check:output=~Provision node\(s\)\: $$CN From 0ea17375c3441eaf2fbcba545726b9d8b664a6a1 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Mon, 27 Mar 2017 16:08:33 +0800 Subject: [PATCH 161/187] Add test case to verify github issue #2582 --- xCAT-test/autotest/testcase/mkdef/cases1 | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 xCAT-test/autotest/testcase/mkdef/cases1 diff --git a/xCAT-test/autotest/testcase/mkdef/cases1 b/xCAT-test/autotest/testcase/mkdef/cases1 new file mode 100644 index 000000000..0d77e6e28 --- /dev/null +++ b/xCAT-test/autotest/testcase/mkdef/cases1 @@ -0,0 +1,11 @@ +start:mkdef_github_issue2582 +description:Verify github issue 2582 +cmd:mkdef -t group -o doubletrouble bmc='|\z|-imm|' mgt=ipmi +check:rc==0 +cmd:mkdef mgt02 groups=doubletrouble +check:rc==0 +cmd:lsdef mgt02 -i bmc | grep bmc=mgt02-imm$ +check:rc==0 +cmd:rmdef mgt02 +cmd:rmdef -t group doubletrouble +end From 58d2acfea2b012ed74b713a588ef2097fcebace5 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Mon, 27 Mar 2017 09:21:07 -0400 Subject: [PATCH 162/187] modify confignics testcase for issue:#2683 --- xCAT-test/autotest/testcase/confignics/cases0 | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/xCAT-test/autotest/testcase/confignics/cases0 b/xCAT-test/autotest/testcase/confignics/cases0 index c63a8ad8f..213b6d39f 100644 --- a/xCAT-test/autotest/testcase/confignics/cases0 +++ b/xCAT-test/autotest/testcase/confignics/cases0 @@ -1,6 +1,6 @@ start:confignics_config_one_port_single_value description:confignics -cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 check:rc==0 @@ -8,16 +8,16 @@ cmd:updatenode $$CN -P confignics check:rc==0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~100.1.0.100 -check:output!~dhcp +check:output=~MTU=1501 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi end start:confignics_config_multiple_ports_single_value description:confignics -cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 200_1_0_0-255_255_0_0 net=200.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 200_1_0_0-255_255_0_0 net=200.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1502 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 check:rc==0 @@ -28,9 +28,11 @@ check:rc==0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~100.1.0.100 check:output!~dhcp +check:output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~200.1.0.100 check:output!~dhcp +check:output=~MTU=1502 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:rmdef -t network -o 200_1_0_0-255_255_0_0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi @@ -39,13 +41,13 @@ end start:confignics_config_multiple_ports_multiple_value description:confignics -cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 check:rc==0 -cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 -cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1504 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC="11.1.0.100|12.1.0.100" nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC="11_1_0_0-255_255_0_0|12_1_0_0-255_255_0_0" check:rc==0 @@ -56,15 +58,19 @@ check:rc==0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~11.1.0.100 check:output!~dhcp +check:output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp +check:output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp +check:output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp +check:output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -77,13 +83,13 @@ end start:confignics_config_multiple_port_withnichostnamesuffixes_multiple_value description:confignics -cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 check:rc==0 -cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 -cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1504 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC="11.1.0.100|12.1.0.100" nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC="11_1_0_0-255_255_0_0|12_1_0_0-255_255_0_0" nichostnamesuffixes.$$SECONDNIC="-$$SECONDNIC-1|-$$SECONDNIC-2" check:rc==0 @@ -103,15 +109,19 @@ check:rc==0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~11.1.0.100 check:output!~dhcp +output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp +output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp +output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp +output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -125,13 +135,13 @@ end start:confignics_config_multiple_port_withnicaliases_multiple_value description:confignics -cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 check:rc==0 -cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 -cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC +cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1504 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC="11.1.0.100|12.1.0.100" nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC="11_1_0_0-255_255_0_0|12_1_0_0-255_255_0_0" nicaliases.$$SECONDNIC="aliases1-1|aliases1-2" check:rc==0 @@ -149,15 +159,19 @@ check:rc==0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~11.1.0.100 check:output!~dhcp +output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp +output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp +output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp +output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -173,7 +187,7 @@ description:confignics cmd:xdsh $$CN ifdown $$SECONDNIC cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC check:rc==0 -cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 +cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 mtu=1501 check:rc==0 cmd:chtab node=$$CN nics.disable=yes check:rc==0 @@ -181,6 +195,7 @@ cmd:updatenode $$CN -P confignics check:rc==0 cmd:if [ "$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-$$SECONDNIC; fi check:output!~100.1.0.100 +output=~MTU=1501 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:chtab node=$$CN nics.disable=0 end @@ -188,7 +203,7 @@ end start:confignics_disable_set_to_1 description:confignics cmd:xdsh $$CN ifdown $$SECONDNIC -cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC +cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 check:rc==0 @@ -198,15 +213,19 @@ cmd:updatenode $$CN -P confignics check:rc==0 cmd:if [ "$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-$$SECONDNIC; fi check:output!~100.1.0.100 +output=~MTU=1501 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:chtab node=$$CN nics.disable=0 end start:confignics_s description:confignics_s +cmd:chdef -t network -o $$NETWORKNAME mtu=1501 +check:rc==0 cmd:updatenode $$CN "confignics -s" check:rc==0 check:output!~invalid -cmd:if cat /etc/*release |grep "Red Hat" >/dev/null;then xdsh $$CN "cat /etc/sysconfig/network-scripts/ifcfg-eth0 |grep IPADDR=$$NODEIP";elif cat /etc/*release |grep SUSE >/dev/null; then xdsh $$CN "cat /etc/sysconfig/network/ifcfg-eth0 |grep IPADDR=$$NODEIP";fi -cmd:sleep 5 +cmd:if cat /etc/*release |grep "Red Hat" >/dev/null ;then if [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "MTU=1501" ]] ; then exit 0 ;else exit 1 ; fi ;elif cat /etc/*release |grep SUSE >/dev/null ; then if [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "MTU=1501" ]] ;then exit 0;else exit 1;fi;fi +check:rc==0 +cmd:chdef -t network -o $$NETWORKNAME mtu=" " check:rc==0 end From 71d478e54b5d7b064154e610d2e3506388ffbac5 Mon Sep 17 00:00:00 2001 From: immarvin Date: Mon, 27 Mar 2017 05:35:20 -0400 Subject: [PATCH 163/187] fix issue 2757 --- xCAT/postscripts/remoteshell | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index a93722457..45c15a1a3 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -11,7 +11,6 @@ # id.rsa # # if on the Management Node, exit - if [ -f /etc/os-release ] && cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then #TODO echo "Cumulus OS is not supported yet, nothing to do..." @@ -149,8 +148,7 @@ if [ $? -ne 0 ]; then getcredentials.awk ssh_dsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_dsa_key MYCONT=`cat /etc/ssh/ssh_host_dsa_key` done - chown root:ssh_keys /etc/ssh/ssh_host_dsa_key - chmod 640 /etc/ssh/ssh_host_dsa_key + egrep -i "^ssh_keys:" /etc/group >/dev/null 2>&1 && chown root:ssh_keys /etc/ssh/ssh_host_dsa_key 2>/dev/null && chmod 640 /etc/ssh/ssh_host_dsa_key if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_dsa_key > /dev/null 2>&1 ; then rm /etc/ssh/ssh_host_dsa_key else @@ -216,8 +214,7 @@ if [ $? -ne 0 ]; then getcredentials.awk ssh_rsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_rsa_key MYCONT=`cat /etc/ssh/ssh_host_rsa_key` done - chown root:ssh_keys /etc/ssh/ssh_host_rsa_key - chmod 640 /etc/ssh/ssh_host_rsa_key + egrep -i "^ssh_keys:" /etc/group >/dev/null 2>&1 && chown root:ssh_keys /etc/ssh/ssh_host_rsa_key 2>/dev/null && chmod 640 /etc/ssh/ssh_host_rsa_key if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_rsa_key > /dev/null 2>&1 ; then rm /etc/ssh/ssh_host_rsa_key else @@ -288,8 +285,7 @@ if ssh-keygen -t ecdsa -f /tmp/ecdsa_key -P "" &>/dev/null ; then getcredentials.awk ssh_ecdsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_ecdsa_key MYCONT=`cat /etc/ssh/ssh_host_ecdsa_key` done - chown root:ssh_keys /etc/ssh/ssh_host_ecdsa_key - chmod 640 /etc/ssh/ssh_host_ecdsa_key + egrep -i "^ssh_keys:" /etc/group >/dev/null 2>&1 && chown root:ssh_keys /etc/ssh/ssh_host_ecdsa_key 2>/dev/null && chmod 640 /etc/ssh/ssh_host_ecdsa_key if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_ecdsa_key > /dev/null 2>&1 ; then rm /etc/ssh/ssh_host_ecdsa_key else From 39b1df045fb88a3a42313545056303da516b3f6f Mon Sep 17 00:00:00 2001 From: ertaozh Date: Mon, 27 Mar 2017 09:10:28 -0400 Subject: [PATCH 164/187] use wrong site attribute xcatdebugmodel before, change to xcatdebugmode --- xCAT-server/lib/perl/xCAT/IPMI.pm | 2 +- xCAT-server/lib/xcat/plugins/ipmi.pm | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/IPMI.pm b/xCAT-server/lib/perl/xCAT/IPMI.pm index 05014a585..7df20d63d 100644 --- a/xCAT-server/lib/perl/xCAT/IPMI.pm +++ b/xCAT-server/lib/perl/xCAT/IPMI.pm @@ -416,7 +416,7 @@ sub subcmd { my %args = @_; $self->{expectedcmd} = $args{command}; $self->{expectednetfn} = $args{netfn} + 1; - if ($self->{onlogon_args}->{xcatdebugmodel}) { + if ($self->{onlogon_args}->{xcatdebugmode}) { my $msg = sprintf ("The command running: $self->{onlogon_args}->{command}:$self->{onlogon_args}->{subcommand}(@{$self->{onlogon_args}->{extraargs}}), the raw data: netfn(0x%02x), cmd(0x%02x)", $args{netfn}, $args{command}); xCAT::SvrUtils::sendmsg([0, $msg], $self->{onlogon_args}->{outfunc}); } diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index e505d62eb..300d52e71 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -43,7 +43,7 @@ my %allerrornodes = (); my %newnodestatus = (); my $global_sessdata; my %child_pids; -my $xcatdebugmodel = 0; +my $xcatdebugmode = 0; my $IPMIXCAT = "/opt/xcat/bin/ipmitool-xcat"; my $NON_BLOCK = 1; @@ -8163,7 +8163,7 @@ sub process_request { if ($::XCATSITEVALS{ipmitimeout}) { $ipmitimeout = $::XCATSITEVALS{ipmitimeout} } if ($::XCATSITEVALS{ipmiretries}) { $ipmitrys = $::XCATSITEVALS{ipmitretries} } if ($::XCATSITEVALS{ipmisdrcache}) { $enable_cache = $::XCATSITEVALS{ipmisdrcache} } - if ($::XCATSITEVALS{xcatdebugmodel}) { $xcatdebugmodel = $::XCATSITEVALS{xcatdebugmodel} } + if ($::XCATSITEVALS{xcatdebugmode}) { $xcatdebugmodel = $::XCATSITEVALS{xcatdebugmode} } #my @threads; my @donargs = (); @@ -8377,7 +8377,7 @@ sub donode { command => $command, extraargs => \@exargs, subcommand => $exargs[0], - xcatdebugmodel => $xcatdebugmodel, + xcatdebugmode => $xcatdebugmode, outfunc => $callback, }; if ($sessiondata{$node}->{ipmisession}->{error}) { From 8e879cec0eed9037ce02f84e5afcb7dd1895aa9c Mon Sep 17 00:00:00 2001 From: ertaozh Date: Mon, 27 Mar 2017 11:25:47 -0400 Subject: [PATCH 165/187] fix an issue when list ipmi raw data --- xCAT-server/lib/xcat/plugins/ipmi.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index 300d52e71..d14fe012f 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -8163,7 +8163,7 @@ sub process_request { if ($::XCATSITEVALS{ipmitimeout}) { $ipmitimeout = $::XCATSITEVALS{ipmitimeout} } if ($::XCATSITEVALS{ipmiretries}) { $ipmitrys = $::XCATSITEVALS{ipmitretries} } if ($::XCATSITEVALS{ipmisdrcache}) { $enable_cache = $::XCATSITEVALS{ipmisdrcache} } - if ($::XCATSITEVALS{xcatdebugmode}) { $xcatdebugmodel = $::XCATSITEVALS{xcatdebugmode} } + if ($::XCATSITEVALS{xcatdebugmode}) { $xcatdebugmode = $::XCATSITEVALS{xcatdebugmode} } #my @threads; my @donargs = (); From 4776e2c7f5842c10d399e6b1a708a3933a729fe5 Mon Sep 17 00:00:00 2001 From: Casandra Qiu Date: Mon, 27 Mar 2017 21:59:59 -0400 Subject: [PATCH 166/187] change output string from "on" to "reset" --- docs/source/advanced/pdu/pdu.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/source/advanced/pdu/pdu.rst b/docs/source/advanced/pdu/pdu.rst index 9ed9b705c..a8566b5f8 100644 --- a/docs/source/advanced/pdu/pdu.rst +++ b/docs/source/advanced/pdu/pdu.rst @@ -66,8 +66,8 @@ The following commands are supported against a compute node: * Power cycling the PDU outlets on a compute node: :: # rpower cn01 pdureset - cn01: f5pdu3 outlet 6 is on - cn01: f5pdu3 outlet 7 is on + cn01: f5pdu3 outlet 6 is reset + cn01: f5pdu3 outlet 7 is reset The following commands are supported against a PDU: @@ -122,18 +122,18 @@ The following commands are supported against a PDU: * Power reset the full PDU: :: # rpower f5pdu3 reset - f5pdu3: outlet 1 is on - f5pdu3: outlet 2 is on - f5pdu3: outlet 3 is on - f5pdu3: outlet 4 is on - f5pdu3: outlet 5 is on - f5pdu3: outlet 6 is on - f5pdu3: outlet 7 is on - f5pdu3: outlet 8 is on - f5pdu3: outlet 9 is on - f5pdu3: outlet 10 is on - f5pdu3: outlet 11 is on - f5pdu3: outlet 12 is on + f5pdu3: outlet 1 is reset + f5pdu3: outlet 2 is reset + f5pdu3: outlet 3 is reset + f5pdu3: outlet 4 is reset + f5pdu3: outlet 5 is reset + f5pdu3: outlet 6 is reset + f5pdu3: outlet 7 is reset + f5pdu3: outlet 8 is reset + f5pdu3: outlet 9 is reset + f5pdu3: outlet 10 is reset + f5pdu3: outlet 11 is reset + f5pdu3: outlet 12 is reset **Note:** For BMC based compute nodes, turning the PDU outlet power on does not automatically power on the compute side. Users will need to issue ``rpower on`` to power on the compute node after the BMC boots. From 08443c20e0c714a78b491c50d0cbeb7f7a8442a1 Mon Sep 17 00:00:00 2001 From: XuWei Date: Wed, 22 Mar 2017 03:30:14 -0400 Subject: [PATCH 167/187] fix issue 2348, check error msg when run bmcdiscover --- xCAT-server/lib/xcat/plugins/bmcdiscover.pm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/bmcdiscover.pm b/xCAT-server/lib/xcat/plugins/bmcdiscover.pm index b593236fb..d05a44ef5 100644 --- a/xCAT-server/lib/xcat/plugins/bmcdiscover.pm +++ b/xCAT-server/lib/xcat/plugins/bmcdiscover.pm @@ -896,6 +896,11 @@ sub bmcdiscovery_ipmi { my $output = xCAT::Utils->runcmd("$icmd", -1); if ($output =~ $bmcstr) { + if ($output =~ /RAKP 2 message indicates an error : (.+)\nError: (.+)/) { + xCAT::MsgUtils->message("E", { data => ["$2: $1 for $ip"] }, $::CALLBACK); + return 1; + } + # The output contains System Power indicated the username/password is correct, then try to get MTMS if ($output =~ /System Power\s*:\s*\S*/) { my $mtm = ''; From 353a8302eba58d84c0406ce5e0b461c60c700d57 Mon Sep 17 00:00:00 2001 From: immarvin Date: Tue, 28 Mar 2017 00:45:47 -0400 Subject: [PATCH 168/187] fix issue [DEV] "remoteshell" postscript complains "chown: invalid group: root:ssh_keys" and "Permissions 0640 for /etc/ssh/ssh_host_dsa_key are too open" on sles11.4 --- xCAT/postscripts/remoteshell | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index 45c15a1a3..5e5805b52 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -11,6 +11,7 @@ # id.rsa # # if on the Management Node, exit +umask 0077 if [ -f /etc/os-release ] && cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 ; then #TODO echo "Cumulus OS is not supported yet, nothing to do..." @@ -314,7 +315,7 @@ if [[ $NTYPE = service ]]; then cp /etc/ssh/ssh* /etc/xcat/hostkeys/. fi -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 From e9b395d1aef7bb0eb2e147cafdd244c79ea3cfc8 Mon Sep 17 00:00:00 2001 From: chenglch Date: Tue, 21 Mar 2017 14:07:48 +0800 Subject: [PATCH 169/187] Fix timeout issue if bmc is unreachable for rflash As the original ipmi code do not exit with error code, it is not possible to judge the success or not from return code of child procss. This patch will send message from child processes directly. This patch also change the wait time to check whether the ipmi session is useable and add power on at the end of rflash process. close-issue: #2693 close-issue: #2682 --- xCAT-server/lib/xcat/plugins/ipmi.pm | 119 ++++++++++++++++----------- 1 file changed, 71 insertions(+), 48 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index ae76557c1..8a5f9cef5 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -1731,6 +1731,37 @@ sub do_firmware_update { $ret = get_ipmitool_version(\$ipmitool_ver); exit $ret if $ret < 0; + my $exit_with_error_func = sub { + my ($node, $callback, $message) = @_; + my $status = "failed to update firmware"; + my $nodelist_table = xCAT::Table->new('nodelist'); + if (!$nodelist_table) { + xCAT::MsgUtils->message("S", "Unable to open nodelist table, denying"); + } else { + $nodelist_table->setNodeAttribs($node, { status => $status }); + $nodelist_table->close(); + } + xCAT::MsgUtils->message("S", $node.": ".$message); + $callback->({ error => "$node: $message", errorcode => 1 }); + exit -1; + }; + + my $exit_with_success_func = sub { + my ($node, $callback, $message) = @_; + my $status = "success to update firmware"; + my $nodelist_table = xCAT::Table->new('nodelist'); + if (!$nodelist_table) { + xCAT::MsgUtils->message("S", "Unable to open nodelist table, denying"); + } else { + $nodelist_table->setNodeAttribs($node, { status => $status }); + $nodelist_table->close(); + } + xCAT::MsgUtils->message("S", $node.": ".$message); + $callback->({ data => "$node: $message" }); + exit 0; + }; + + # only 1.8.15 or above support hpm update for firestone machines. if (calc_ipmitool_version($ipmitool_ver) < calc_ipmitool_version("1.8.15")) { $callback->({ error => "IPMITool $ipmitool_ver do not support firmware update for " . @@ -1741,9 +1772,8 @@ sub do_firmware_update { if (($hpm_data_hash{deviceID} ne $sessdata->{device_id}) || ($hpm_data_hash{productID} ne $sessdata->{prod_id}) || ($hpm_data_hash{manufactureID} ne $sessdata->{mfg_id})) { - xCAT::SvrUtils::sendmsg([ 1, "The image file doesn't match this machine" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "The image file doesn't match this machine"); } my $output; @@ -1773,9 +1803,8 @@ sub do_firmware_update { my $cmd = $pre_cmd . " fru print 3"; $output = xCAT::Utils->runcmd($cmd, -1); if ($::RUNCMD_RC != 0) { - xCAT::SvrUtils::sendmsg([ 1, "Running ipmitool command $cmd failed: $output" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); } if ($output =~ /8335-GTB/) { $buffer_size = "15000"; @@ -1786,18 +1815,16 @@ sub do_firmware_update { $cmd = $pre_cmd . " fru print 47"; $output = xCAT::Utils->runcmd($cmd, -1); if ($::RUNCMD_RC != 0) { - xCAT::SvrUtils::sendmsg([ 1, "Running ipmitool command $cmd failed: $output" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); } my $grs_version = $output =~ /OP8_v(\d*\.\d*_\d*\.\d*)/; if ($grs_version =~ /\d\.(\d+)_(\d+\.\d+)/) { my $prim_grs_version = $1; my $sec_grs_version = $2; if ($prim_grs_version <= 7 && $sec_grs_version < 2.55) { - xCAT::SvrUtils::sendmsg([ 1, "Error: Current firmware level OP8v_$grs_version requires one-time manual update to at least version OP8v_1.7_2.55" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "Error: Current firmware level OP8v_$grs_version requires one-time manual update to at least version OP8v_1.7_2.55"); } } } @@ -1806,34 +1833,30 @@ sub do_firmware_update { $cmd = $pre_cmd . " chassis power off"; $output = xCAT::Utils->runcmd($cmd, -1); if ($::RUNCMD_RC != 0) { - xCAT::SvrUtils::sendmsg([ 1, "Running ipmitool command $cmd failed: $output" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); } # step 2 reset cold $cmd = $pre_cmd . " mc reset cold"; $output = xCAT::Utils->runcmd($cmd, -1); if ($::RUNCMD_RC != 0) { - xCAT::SvrUtils::sendmsg([ 1, "Running ipmitool command $cmd failed: $output" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); } # check reset status - unless (check_bmc_status_with_ipmitool($pre_cmd, 5, 24)) { - xCAT::SvrUtils::sendmsg([ 1, "Timeout to check the bmc status" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + unless (check_bmc_status_with_ipmitool($pre_cmd, 5, 60)) { + $exit_with_error_func->($sessdata->{node}, $callback, + "Timeout to check the bmc status"); } # step 3 protect network $cmd = $pre_cmd . " raw 0x32 0xba 0x18 0x00"; $output = xCAT::Utils->runcmd($cmd, -1); if ($::RUNCMD_RC != 0) { - xCAT::SvrUtils::sendmsg([ 1, "Running ipmitool command $cmd failed: $output" ], - $callback, $sessdata->{node}, %allerrornodes); - exit -1; + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); } # step 4 upgrade firmware @@ -1850,7 +1873,28 @@ sub do_firmware_update { xCAT::SvrUtils::sendmsg([ 0, "rflashing ... See the detail progress :\"tail -f $rflash_log_file\"" ], $callback, $sessdata->{node}); - exec($cmd); + + $output = xCAT::Utils->runcmd($cmd, -1); + if ($::RUNCMD_RC != 0) { + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); + } + + # step 5 power on + # check reset status + unless (check_bmc_status_with_ipmitool($pre_cmd, 5, 60)) { + $exit_with_error_func->($sessdata->{node}, $callback, + "Timeout to check the bmc status"); + } + + $cmd = $pre_cmd . " chassis power on"; + $output = xCAT::Utils->runcmd($cmd, -1); + if ($::RUNCMD_RC != 0) { + $exit_with_error_func->($sessdata->{node}, $callback, + "Running ipmitool command $cmd failed: $output"); + } + $exit_with_success_func->($sessdata->{node}, $callback, + "Success to update firmware. FRU information will be populated in a few minutes."); } sub rflash { @@ -1996,29 +2040,8 @@ sub start_rflash_processes { # Wait for all processes to end while (keys %child_pids) { - my ($node_status, $rc, $cpid); + my $cpid; if (($cpid = wait()) > 0) { - $rc = $?; - if (!grep(/^(-c|--check)$/i, @exargs)) { - $node_status->{node} = $child_pids{$cpid}; - if ($rc == 0) { - $node_status->{status} = "success to update firmware"; - } else { - $node_status->{status} = "failed to update firmware"; - } - my $nodelist_table = xCAT::Table->new('nodelist'); - if (!$nodelist_table) { - xCAT::MsgUtils->message("S", "Unable to open nodelist table, denying"); - } else { - $nodelist_table->setNodeAttribs($node_status->{node}, - { status => $node_status->{status} }); - $nodelist_table->close(); - } - xCAT::MsgUtils->message("S", - $node_status->{node}.": ". $node_status->{status}); - xCAT::SvrUtils::sendmsg([ $rc, - $node_status->{status} ], $callback, $node_status->{node}); - } delete $child_pids{$cpid}; } } From d59bd7088b1fb036ff4dba0458ca580dda7431ae Mon Sep 17 00:00:00 2001 From: junxiawang Date: Tue, 28 Mar 2017 02:26:49 -0400 Subject: [PATCH 170/187] modify confignics testcase 2683 --- xCAT-test/autotest/testcase/confignics/cases0 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-test/autotest/testcase/confignics/cases0 b/xCAT-test/autotest/testcase/confignics/cases0 index 213b6d39f..4a1695acf 100644 --- a/xCAT-test/autotest/testcase/confignics/cases0 +++ b/xCAT-test/autotest/testcase/confignics/cases0 @@ -219,13 +219,13 @@ cmd:chtab node=$$CN nics.disable=0 end start:confignics_s description:confignics_s -cmd:chdef -t network -o $$NETWORKNAME mtu=1501 +cmd:MASTERIP=`lsdef -t site -i master -c 2>&1 | awk -F'=' '{print $2}'`;NETWORKNAME=`tabdump networks |grep 10.3.5.9 |awk -F'"' '{print $2}'`;chdef -t network -o $NETWORKNAME mtu=1501 check:rc==0 cmd:updatenode $$CN "confignics -s" check:rc==0 check:output!~invalid cmd:if cat /etc/*release |grep "Red Hat" >/dev/null ;then if [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "MTU=1501" ]] ; then exit 0 ;else exit 1 ; fi ;elif cat /etc/*release |grep SUSE >/dev/null ; then if [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "MTU=1501" ]] ;then exit 0;else exit 1;fi;fi check:rc==0 -cmd:chdef -t network -o $$NETWORKNAME mtu=" " +cmd:MASTERIP=`lsdef -t site -i master -c 2>&1 | awk -F'=' '{print $2}'`;NETWORKNAME=`tabdump networks |grep 10.3.5.9 |awk -F'"' '{print $2}'`;chdef -t network -o $NETWORKNAME mtu=" " check:rc==0 end From b78fc0ae40b1e676e8747555704c8fde62386bb9 Mon Sep 17 00:00:00 2001 From: ertaozh Date: Tue, 28 Mar 2017 03:07:06 -0400 Subject: [PATCH 171/187] modify the output ipmi raw data with readable information --- xCAT-server/lib/perl/xCAT/IPMI.pm | 61 ++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/perl/xCAT/IPMI.pm b/xCAT-server/lib/perl/xCAT/IPMI.pm index 7df20d63d..d7223dc6b 100644 --- a/xCAT-server/lib/perl/xCAT/IPMI.pm +++ b/xCAT-server/lib/perl/xCAT/IPMI.pm @@ -80,6 +80,63 @@ sub hexdump { print "\n"; } +my %command_info = ( + 6 => { + 56 => "Get Channel Authentication Capabilities", + 59 => "Set session privilege level", + 60 => "Close Session", + 58 => "activate session", + 57 => "Get Session Challenge", + 1 => "Get Device ID", + 2 => "Cold Reset", + 55 => "Get System GUID", + 64 => "Set Channel Access", + 76 => "Set User Payload Access", + 10 => "Get Command Support", + }, + 4 => { + 18 => "Set PEF Configuration Parameters", + 19 => "Get PEF Configuration Parameters", + 45 => "Get Sensor Reading", + }, + 0 => { + 8 => "Set System Boot Options", + 9 => "Get System Boot Options", + 4 => "Chassis Identify(beacon)", + 2 => "Chassis Control", + 1 => "Get Chassis Status", + }, + 12 => { + 1 => "Set LAN Configuration Parameters", + 2 => "Get LAN Configuration Parameters", + 33 => "Set SOL Configuration Parameters", + 34 => "Get SOL Configuration Parameters", + }, + 10 => { + 35 => "Get SDR", + 34 => "Reserve SDR Repository", + 71 => "Clear SEL", + 67 => "Get SEL Entry", + 66 => "Reserve SEL", + 72 => "Get SEL Time", + 64 => "Get SEL Info", + 17 => "Read FRU Data", + 16 => "Get FRU Inventory Area Info", + 32 => "Get SDR Repository Info", + }, +); + +my %netfn_types = ( + 0 => "Chassis", + 2 => "Bridge", + 4 => "Sensor/Event", + 6 => "App", + 8 => "Firmware", + 10 => "Storage", + 12 => "Transport", + # do we need to define anymore then these? +); + my %payload_types = ( #help readability in certain areas of code by specifying payload by name rather than number 'ipmi' => 0, 'sol' => 1, @@ -417,7 +474,9 @@ sub subcmd { $self->{expectedcmd} = $args{command}; $self->{expectednetfn} = $args{netfn} + 1; if ($self->{onlogon_args}->{xcatdebugmode}) { - my $msg = sprintf ("The command running: $self->{onlogon_args}->{command}:$self->{onlogon_args}->{subcommand}(@{$self->{onlogon_args}->{extraargs}}), the raw data: netfn(0x%02x), cmd(0x%02x)", $args{netfn}, $args{command}); + my $command_string = $command_info{$args{netfn}}->{$args{command}}; + my $data_values = join ", ", @{$args{data}}; + my $msg = sprintf ("[ipmi_debug] $self->{onlogon_args}->{command}:$self->{onlogon_args}->{subcommand}(@{$self->{onlogon_args}->{extraargs}}), raw_cmd: netfn(0x%02x=>%s), cmd(0x%02x=>%s), data=[%s]", $args{netfn}, $netfn_types{$args{netfn}}, $args{command}, $command_string, $data_values); xCAT::SvrUtils::sendmsg([0, $msg], $self->{onlogon_args}->{outfunc}); } my $seqincrement = 7; From 938b50eaf75ae11508d1a60bc4211b487b8b381b Mon Sep 17 00:00:00 2001 From: junxiawang Date: Tue, 28 Mar 2017 08:14:40 -0400 Subject: [PATCH 172/187] modify makehosts testcase according to issue:add test case to makehosts erroneously deletes entries from /etc/hosts #2674 --- xCAT-test/autotest/bundle/sles12.2_x86_64.bundle | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-test/autotest/bundle/sles12.2_x86_64.bundle b/xCAT-test/autotest/bundle/sles12.2_x86_64.bundle index 4003012a6..78877bdbd 100644 --- a/xCAT-test/autotest/bundle/sles12.2_x86_64.bundle +++ b/xCAT-test/autotest/bundle/sles12.2_x86_64.bundle @@ -9,6 +9,7 @@ makehosts_h makehosts_help makehosts_n makehosts_n_noderange +makehost_n_r chdef_null chdef_z chdef_t_o_error From f297e91bbff2c0503b48799c1db7f035db3f08c8 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Tue, 28 Mar 2017 08:10:26 -0400 Subject: [PATCH 173/187] modify confignics testcase 2683 --- xCAT-test/autotest/testcase/confignics/cases0 | 12 ++-- .../testcase/confignics/mtu_set_clean | 59 +++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) create mode 100755 xCAT-test/autotest/testcase/confignics/mtu_set_clean diff --git a/xCAT-test/autotest/testcase/confignics/cases0 b/xCAT-test/autotest/testcase/confignics/cases0 index 4a1695acf..1238039d8 100644 --- a/xCAT-test/autotest/testcase/confignics/cases0 +++ b/xCAT-test/autotest/testcase/confignics/cases0 @@ -62,7 +62,7 @@ check:output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp -check:output=~MTU=1502 +check:output=~MTU_1=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp @@ -70,7 +70,7 @@ check:output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp -check:output=~MTU=1504 +check:output=~MTU_1=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -187,7 +187,7 @@ description:confignics cmd:xdsh $$CN ifdown $$SECONDNIC cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC check:rc==0 -cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 mtu=1501 +cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 check:rc==0 cmd:chtab node=$$CN nics.disable=yes check:rc==0 @@ -219,13 +219,15 @@ cmd:chtab node=$$CN nics.disable=0 end start:confignics_s description:confignics_s -cmd:MASTERIP=`lsdef -t site -i master -c 2>&1 | awk -F'=' '{print $2}'`;NETWORKNAME=`tabdump networks |grep 10.3.5.9 |awk -F'"' '{print $2}'`;chdef -t network -o $NETWORKNAME mtu=1501 +cmd:/opt/xcat/share/xcat/tools/autotest/testcase/confignics/mtu_set_clean S 1501 +check:rc==0 +cmd:tabdump networks check:rc==0 cmd:updatenode $$CN "confignics -s" check:rc==0 check:output!~invalid cmd:if cat /etc/*release |grep "Red Hat" >/dev/null ;then if [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "MTU=1501" ]] ; then exit 0 ;else exit 1 ; fi ;elif cat /etc/*release |grep SUSE >/dev/null ; then if [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "MTU=1501" ]] ;then exit 0;else exit 1;fi;fi check:rc==0 -cmd:MASTERIP=`lsdef -t site -i master -c 2>&1 | awk -F'=' '{print $2}'`;NETWORKNAME=`tabdump networks |grep 10.3.5.9 |awk -F'"' '{print $2}'`;chdef -t network -o $NETWORKNAME mtu=" " +cmd:/opt/xcat/share/xcat/tools/autotest/testcase/confignics/mtu_set_clean C 1501 check:rc==0 end diff --git a/xCAT-test/autotest/testcase/confignics/mtu_set_clean b/xCAT-test/autotest/testcase/confignics/mtu_set_clean new file mode 100755 index 000000000..adbc8db69 --- /dev/null +++ b/xCAT-test/autotest/testcase/confignics/mtu_set_clean @@ -0,0 +1,59 @@ +#!/bin/bash +function test_ip() +{ + IP=$1 + VALID_CHECK=$(echo $IP|awk -F. '$1<=255&&$2<=255&&$3<=255&&$4<=255{print "yes"}') + if echo $IP|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then + if [ ${VALID_CHECK:-no} == "yes" ]; then + echo $1; + else + return 1; + fi + else + return 1; + fi + +} +function get_master_ip() +{ + test_ip $1; + if [[ $? -eq 1 ]]; then + rc2=`ping $MASTERIP -c 10`; + if [[ $? -eq 0 ]]; then + MASTERIPN=` ping $MASTERIP -c 1 |grep "64 bytes from" |awk -F'(' '{print $2}'|awk -F')' '{print $1}'`; + echo $MASTERIPN; + else + echo "invalid master value"; + exit 1; + fi + fi + +} +MASTERIP="" +NETWORKNAME="" +MASTERIP=`lsdef -t site -i master -c 2>&1 | awk -F'=' '{print $2}'`; +MASTERIP=$(get_master_ip $MASTERIP); +if [[ `tabdump networks |grep $MASTERIP` = "" ]]; then + makenetworks +fi +NETWORKNAME=`tabdump networks |grep $MASTERIP|awk -F'"' '{print $2}'`; +echo $NETWORKNAME,$MASTERIP; +if [[ $NETWORKNAME = "" ]] || [[ $MASTERIP = "" ]];then + exit 2; +else + if [ $1 = "S" ] ;then + chdef -t network -o $NETWORKNAME mtu=$2 + if [[ $? -eq 0 ]];then + exit 0; + else + exit 1; + fi + else [ $1 = "C" ] + chdef -t network -o $NETWORKNAME mtu=" " + if [[ $? -eq 0 ]];then + exit 0; + else + exit 1; + fi + fi +fi From 43fdd43877e06cee3cb382f950e2e3c4f18b3199 Mon Sep 17 00:00:00 2001 From: GONG Jie Date: Mon, 27 Mar 2017 15:25:36 +0800 Subject: [PATCH 174/187] Add test case for the addkcomdline attribute of node definition --- xCAT-test/autotest/testcase/nodeset/cases1 | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 xCAT-test/autotest/testcase/nodeset/cases1 diff --git a/xCAT-test/autotest/testcase/nodeset/cases1 b/xCAT-test/autotest/testcase/nodeset/cases1 new file mode 100644 index 000000000..816f4ee59 --- /dev/null +++ b/xCAT-test/autotest/testcase/nodeset/cases1 @@ -0,0 +1,9 @@ +start:nodeset_addkcmdline +cmd:chdef $$CN addkcmdline=debug +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:find -L /tftpboot -name '*$$CN*' -exec cat {} + | grep debug +check:rc==0 +cmd:chdef $$CN addkcmdline= +end From d0da3108cf07c1993ef59c01067fdd2bdd93f14c Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 28 Mar 2017 09:28:20 -0400 Subject: [PATCH 175/187] Fix if macdata does not exist If macdata undefined, it took out all of inventory. --- xCAT-server/lib/xcat/plugins/ipmi.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index ae76557c1..dda10dba8 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -4104,7 +4104,7 @@ sub parseboard { my $macdata = $boardinf{extra}->[6]->{value}; my $macstring = "1"; my $macprefix; - while ($macstring !~ /00:00:00:00:00:00/ and not ref $global_sessdata->{currmacs}) { + while ($macdata and $macstring !~ /00:00:00:00:00:00/ and not ref $global_sessdata->{currmacs}) { my @currmac = splice @$macdata, 0, 6; unless ((scalar @currmac) == 6) { last; From 0efb6aa83f56a42f1b75a3a2aa6f3e239f1f1263 Mon Sep 17 00:00:00 2001 From: immarvin Date: Wed, 29 Mar 2017 13:00:24 +0800 Subject: [PATCH 176/187] fix issue rinstall is not able to set or detect the arch , does not happen with nodeset #2745 --- xCAT-server/lib/xcat/plugins/rinstall.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/rinstall.pm b/xCAT-server/lib/xcat/plugins/rinstall.pm index 666935592..b68bf8ac3 100644 --- a/xCAT-server/lib/xcat/plugins/rinstall.pm +++ b/xCAT-server/lib/xcat/plugins/rinstall.pm @@ -218,9 +218,9 @@ sub rinstall { } my $nodetypearch = $nodetypeattribs->{'arch'}; if ($nodetypearch ne $osimagearch) { - unless ((($nodetypearch =~ /ppc64le/) or ($nodetypearch =~ /ppc64el/)) and (($osimagearch =~ /ppc64le/) or ($osimagearch =~ /ppc64el/))) { + unless(($nodetypearch =~ /^ppc64(le|el)?$/i) and ($osimagearch =~ /^ppc64(le|el)?$/i)){ my $rsp = {}; - $rsp->{error}->[0] = "$node: The value of 'arch' attribute is not same as the 'osarch' attribute for osimage."; + $rsp->{error}->[0] = "$node: The value of 'arch' attribute of node does not match the 'osarch' attribute of osimage."; $rsp->{errorcode}->[0] = 1; xCAT::MsgUtils->message("E", $rsp, $callback); next; From 172082f14f7eadcd186f977e8b621c6b8e64559b Mon Sep 17 00:00:00 2001 From: junxiawang Date: Wed, 29 Mar 2017 05:32:54 -0400 Subject: [PATCH 177/187] modify makehosts testcase according to issue:add test case to makehosts erroneously deletes entries from /etc/hosts #2674 --- xCAT-test/autotest/testcase/makehosts/cases0 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-test/autotest/testcase/makehosts/cases0 b/xCAT-test/autotest/testcase/makehosts/cases0 index 46965af78..f2671d6bf 100644 --- a/xCAT-test/autotest/testcase/makehosts/cases0 +++ b/xCAT-test/autotest/testcase/makehosts/cases0 @@ -160,9 +160,9 @@ cmd:makehosts -d s01r1b01 check:rc==0 cmd:rc1=`cat /etc/hosts | grep "70.2.0.254" | grep s01`;rc2=`cat /etc/hosts | grep "80.2.0.254" | grep s01r1b01`;if [[ $rc1 =~ "70.2.0.254 s01" ]] && [[ $rc2 = "" ]];then exit 0;else exit 1;fi check:rc==0 -cmd:if [ -e /tmp/s01.standa ]; then rmdef s01; cat /tmp/s01.standa | mkdef -z; rm -rf /tmp/s01.standa; fi +cmd:if [ -e /tmp/s01.standa ]; then rmdef s01; cat /tmp/s01.standa | mkdef -z; rm -rf /tmp/s01.standa; else rmdef s01;fi check:rc==0 -cmd:if [ -e /tmp/s01r1b01.standa ]; then rmdef s01r1b01; cat /tmp/s01r1b01.standa | mkdef -z; rm -rf /tmp/s01r1b01.standa; fi +cmd:if [ -e /tmp/s01r1b01.standa ]; then rmdef s01r1b01; cat /tmp/s01r1b01.standa | mkdef -z; rm -rf /tmp/s01r1b01.standa;else rmdef s01r1b01; fi check:rc==0 cmd:mv -f /etc/hosts.xcatbakautotest /etc/hosts end From a8f727e454d42f816ed5ecfa71aed7148eebab2b Mon Sep 17 00:00:00 2001 From: chenglch Date: Wed, 29 Mar 2017 02:16:23 -0400 Subject: [PATCH 178/187] Use rinstall to replace nodeset to boot into genesis close-issue: #1174 --- .../references/man1/getadapter.1.rst | 9 ++- xCAT-client/pods/man1/getadapter.1.pod | 9 ++- xCAT-server/lib/xcat/plugins/getadapter.pm | 62 ++----------------- 3 files changed, 14 insertions(+), 66 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man1/getadapter.1.rst b/docs/source/guides/admin-guides/references/man1/getadapter.1.rst index d1046d6ca..7bd216c97 100644 --- a/docs/source/guides/admin-guides/references/man1/getadapter.1.rst +++ b/docs/source/guides/admin-guides/references/man1/getadapter.1.rst @@ -33,12 +33,11 @@ Traditionally, network interfaces in Linux are enumerated as eth[0123...], but t \ **getadapter**\ use genesis to collect network adapters information, so that mean it need to restart the target node. -\ **getadapter**\ follows below scheme: +\ **getadapter**\ For each node within the , follows below scheme: -If the target node is scaned for the first time, \ **getadapter**\ will trigger genesis to collect information then save the information at local. -If the target node has ever been scaned, i.e. this node has network device information in local, \ **getadapter**\ use the local information first. -If user doesn't want to use local information, can use \ **-f**\ option to force to trigger new round scan process. -if part nodes of \ *noderange*\ don't have network device information in local and the rest have, \ **getadapter**\ only trigger real scan process for these nodes which don't have local information, the nodes have network device information in local, \ **getadapter**\ still use the local information first. +If the target node is scaned for the first time, \ **getadapter**\ will trigger genesis to collect information then save the information at the \ **nicsadapter**\ column of nics table. +If the target node has ever been scaned, \ **getadapter**\ will use the information from nics table first. +If user hopes to scan the adapter information for the node but these information already exist, \ **-f**\ option can be used to start rescan process. \ **getadapter**\ tries to collect more information for the target network device, but doesn't guarantee collect same much information for every network device. diff --git a/xCAT-client/pods/man1/getadapter.1.pod b/xCAT-client/pods/man1/getadapter.1.pod index 2fca0dac1..0c10af7a1 100644 --- a/xCAT-client/pods/man1/getadapter.1.pod +++ b/xCAT-client/pods/man1/getadapter.1.pod @@ -14,12 +14,11 @@ Traditionally, network interfaces in Linux are enumerated as eth[0123...], but t B use genesis to collect network adapters information, so that mean it need to restart the target node. -B follows below scheme: +B For each node within the , follows below scheme: -If the target node is scaned for the first time, B will trigger genesis to collect information then save the information at local. -If the target node has ever been scaned, i.e. this node has network device information in local, B use the local information first. -If user doesn't want to use local information, can use B<-f> option to force to trigger new round scan process. -if part nodes of I don't have network device information in local and the rest have, B only trigger real scan process for these nodes which don't have local information, the nodes have network device information in local, B still use the local information first. +If the target node is scaned for the first time, B will trigger genesis to collect information then save the information at the B column of nics table. +If the target node has ever been scaned, B will use the information from nics table first. +If user hopes to scan the adapter information for the node but these information already exist, B<-f> option can be used to start rescan process. B tries to collect more information for the target network device, but doesn't guarantee collect same much information for every network device. diff --git a/xCAT-server/lib/xcat/plugins/getadapter.pm b/xCAT-server/lib/xcat/plugins/getadapter.pm index ccacbad75..19edc1817 100644 --- a/xCAT-server/lib/xcat/plugins/getadapter.pm +++ b/xCAT-server/lib/xcat/plugins/getadapter.pm @@ -304,66 +304,16 @@ sub deploy_genesis { my ($node, $node_desc_ptr, $callback, $subreq) = @_; my $outref = xCAT::Utils->runxcmd( { - command => ['nodeset'], + command => ['rinstall'], node => ["$node"], arg => ['runcmd=getadapter'], }, $subreq, 0, 1); if ($::RUNCMD_RC != 0) { - $callback->({ error => "failed to run command: nodeset $node runcmd=getadapter", errorcode => 1 }); - return 1; - } - - # TODO: use rinstall to replace the following code when rinstall is ready. - if ($node_desc_ptr->{mgt} eq "ipmi") { - $outref = xCAT::Utils->runxcmd( - { - command => ["rsetboot"], - node => ["$node"], - arg => ['net'], - }, - $subreq, 0, 1); - if ($::RUNCMD_RC != 0) { - $callback->({ error => "failed to run command: rsetboot $node net", errorcode => 1 }); - return 1; + foreach my $out (@$outref) { + $callback->({data => "$out"}) } - $outref = xCAT::Utils->runxcmd( - { - command => ['rpower'], - node => ["$node"], - arg => ['reset'], - }, - $subreq, 0, 1); - if ($::RUNCMD_RC != 0) { - $callback->({ error => "failed to run command: rpower $node reset", errorcode => 1 }); - return 1; - } - } elsif ($node_desc_ptr->{mgt} eq "kvm") { - $outref = xCAT::Utils->runxcmd( - { - command => ['rpower'], - node => ["$node"], - arg => ['reset'], - }, - $subreq, 0, 1); - if ($::RUNCMD_RC != 0) { - $callback->({ error => "failed to run command: rpower $node reset", errorcode => 1 }); - return 1; - } - } elsif ($node_desc_ptr->{mgt} eq "hmc") { - $outref = xCAT::Utils->runxcmd( - { - command => ["rnetboot"], - node => ["$node"], - }, - $subreq, 0, 1); - if ($::RUNCMD_RC != 0) { - $callback->({ error => "failed to run command: rnetboot $node", errorcode => 1 }); - return 1; - } - } else { - $callback->({ error => "$node: The mgt configuration is not supported by getadapter.", - errorcode => 1 }); + $callback->({ error => "failed to run command: rinstall $node runcmd=getadapter", errorcode => 1 }); return 1; } $callback->({ data => "$node: Booting into genesis, this could take several minutes..." }); @@ -495,8 +445,8 @@ sub update_adapter_result { } $callback->({ data => "$output" }); if (!$has_nic) { - $callback->({ data => "$node: Couldn't find interface name information detected by udevadm," - . " the nics table will not be updated." }); + $callback->({ data => "$node: nics talbe will not be updated as not any ". + "useful information could be found with udevadm command." }); return 0; } my $nics_table = xCAT::Table->new('nics'); From 1f2610cc09004189795aff51efa143a4357ad93e Mon Sep 17 00:00:00 2001 From: junxiawang Date: Wed, 29 Mar 2017 07:48:22 -0400 Subject: [PATCH 179/187] modify confignics testcase 2683 --- xCAT-test/autotest/testcase/confignics/cases0 | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/xCAT-test/autotest/testcase/confignics/cases0 b/xCAT-test/autotest/testcase/confignics/cases0 index 1238039d8..ece7d81e5 100644 --- a/xCAT-test/autotest/testcase/confignics/cases0 +++ b/xCAT-test/autotest/testcase/confignics/cases0 @@ -1,5 +1,7 @@ start:confignics_config_one_port_single_value description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC=100.1.0.100 nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC=100_1_0_0-255_255_0_0 @@ -11,10 +13,14 @@ check:output=~100.1.0.100 check:output=~MTU=1501 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end start:confignics_config_multiple_ports_single_value description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 200_1_0_0-255_255_0_0 net=200.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1502 @@ -37,10 +43,14 @@ cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:rmdef -t network -o 200_1_0_0-255_255_0_0 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$SECONDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end start:confignics_config_multiple_ports_multiple_value description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 @@ -62,7 +72,7 @@ check:output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp -check:output=~MTU_1=1502 +check:output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp @@ -70,7 +80,7 @@ check:output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp -check:output=~MTU_1=1504 +check:output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -79,10 +89,14 @@ cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$ cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$SECONDNIC:1; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1; fi cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC:1; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1; fi +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end start:confignics_config_multiple_port_withnichostnamesuffixes_multiple_value description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 @@ -131,10 +145,14 @@ cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$S cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC:1; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1; fi cmd:cp /etc/hosts.backup /etc/hosts +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end start:confignics_config_multiple_port_withnicaliases_multiple_value description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 @@ -180,10 +198,14 @@ cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$S cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$SECONDNIC:1; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1; fi cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN rm -rf /etc/network/interfaces.d/$$THIRDNIC:1; else xdsh $$CN rm -rf /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1; fi +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end start:confignics_disable_set_to_yes description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:xdsh $$CN ifdown $$SECONDNIC cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC check:rc==0 @@ -198,10 +220,14 @@ check:output!~100.1.0.100 output=~MTU=1501 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:chtab node=$$CN nics.disable=0 +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end start:confignics_disable_set_to_1 description:confignics +cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi +check:rc==0 cmd:xdsh $$CN ifdown $$SECONDNIC cmd:mkdef -t network -o 100_1_0_0-255_255_0_0 net=100.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 @@ -216,7 +242,10 @@ check:output!~100.1.0.100 output=~MTU=1501 cmd:rmdef -t network -o 100_1_0_0-255_255_0_0 cmd:chtab node=$$CN nics.disable=0 +cmd:if [ -e /tmp/CN.standa ]; then rmdef $$CN; cat /tmp/CN.standa | mkdef -z; rm -rf /tmp/CN.standa; fi +check:rc==0 end + start:confignics_s description:confignics_s cmd:/opt/xcat/share/xcat/tools/autotest/testcase/confignics/mtu_set_clean S 1501 @@ -226,7 +255,7 @@ check:rc==0 cmd:updatenode $$CN "confignics -s" check:rc==0 check:output!~invalid -cmd:if cat /etc/*release |grep "Red Hat" >/dev/null ;then if [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-eth0 ` =~ "MTU=1501" ]] ; then exit 0 ;else exit 1 ; fi ;elif cat /etc/*release |grep SUSE >/dev/null ; then if [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-eth0 ` =~ "MTU=1501" ]] ;then exit 0;else exit 1;fi;fi +cmd:if cat /etc/*release |grep "Red Hat" >/dev/null ;then if [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-* ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network-scripts/ifcfg-* ` =~ "MTU=1501" ]] ; then exit 0 ;else exit 1 ; fi ;elif cat /etc/*release |grep SUSE >/dev/null ; then if [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-* ` =~ "IPADDR=$$NODEIP" ]] && [[ `xdsh $$CN cat /etc/sysconfig/network/ifcfg-* ` =~ "MTU=1501" ]] ;then exit 0;else exit 1;fi;fi check:rc==0 cmd:/opt/xcat/share/xcat/tools/autotest/testcase/confignics/mtu_set_clean C 1501 check:rc==0 From 4625fa30395c645566d8c9daad60bcc5112e458c Mon Sep 17 00:00:00 2001 From: Yuan Bai Date: Wed, 29 Mar 2017 16:51:15 +0800 Subject: [PATCH 180/187] fix 2762 setupntp and some genimage failure in sles12.2 statelite (#2771) * fix 2762 postbootscript setupntp failure result in privision failed in sles12.2-ppc64le * update statelite sles testcase litefile --- .../manage_clusters/ppc64le/statelite/config_statelite.rst | 2 ++ xCAT-test/autotest/testcase/installation/litefile_sles.csv | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst b/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst index bdb243214..ce44725f0 100644 --- a/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst +++ b/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst @@ -90,6 +90,8 @@ This is the minimal list of files needed, you can add additional files to the li "ALL","/opt/xcat/","tmpfs",, "ALL","/xcatpost/","tmpfs",, "ALL","/root/.ssh/","tmpfs",, + "ALL","/etc/systemd/system/","tmpfs",, + "ALL","/etc/adjtime","tmpfs",, litetree table -------------- diff --git a/xCAT-test/autotest/testcase/installation/litefile_sles.csv b/xCAT-test/autotest/testcase/installation/litefile_sles.csv index e4a30153b..b3ade0407 100644 --- a/xCAT-test/autotest/testcase/installation/litefile_sles.csv +++ b/xCAT-test/autotest/testcase/installation/litefile_sles.csv @@ -16,3 +16,5 @@ "ALL","/root/.ssh/","tmpfs",, "ALL","/etc/init.d/rc3.d/","tmpfs",, "ALL","/etc/init.d/rc5.d/","tmpfs",, +"ALL","/etc/systemd/system/","tmpfs",, +"ALL","/etc/adjtime","tmpfs",, From a3f233691c148baf1380d9a293130bab7cbed5a7 Mon Sep 17 00:00:00 2001 From: bybai Date: Wed, 29 Mar 2017 05:03:02 -0400 Subject: [PATCH 181/187] fix 2769 Add test case for Quotes in tables' comment field break mypostscript --- xCAT-test/autotest/testcase/confignics/cases0 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/confignics/cases0 b/xCAT-test/autotest/testcase/confignics/cases0 index ece7d81e5..e5cc30e5f 100644 --- a/xCAT-test/autotest/testcase/confignics/cases0 +++ b/xCAT-test/autotest/testcase/confignics/cases0 @@ -250,7 +250,13 @@ start:confignics_s description:confignics_s cmd:/opt/xcat/share/xcat/tools/autotest/testcase/confignics/mtu_set_clean S 1501 check:rc==0 -cmd:tabdump networks +cmd:tabdump networks > /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv +check:rc==0 +cmd:cp -f /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv.bak +check:rc==0 +cmd:echo "99_1_0_0-255_255_0_0,99.1.0.0,255.255.0.0,,,,,,,,,,,,,,,,test quotes ' in comments," >>/opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv +check:rc==0 +cmd:if [ -e /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv ]; then tabrestore /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv; fi check:rc==0 cmd:updatenode $$CN "confignics -s" check:rc==0 @@ -259,4 +265,8 @@ cmd:if cat /etc/*release |grep "Red Hat" >/dev/null ;then if [[ `xdsh $$CN cat check:rc==0 cmd:/opt/xcat/share/xcat/tools/autotest/testcase/confignics/mtu_set_clean C 1501 check:rc==0 +cmd:cp -f /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv.bak /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv +check:rc==0 +cmd:if [ -e /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv ]; then tabrestore /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv; rm -f /opt/xcat/share/xcat/tools/autotest/testcase/confignics/networks.csv*; fi +check:rc==0 end From 7018324e5b3630510a880d9e32b761ed8488e9d9 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Thu, 30 Mar 2017 08:10:56 -0400 Subject: [PATCH 182/187] modify confignics testcase for issue 2777 --- xCAT-test/autotest/testcase/confignics/cases0 | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/xCAT-test/autotest/testcase/confignics/cases0 b/xCAT-test/autotest/testcase/confignics/cases0 index e5cc30e5f..4ff07aeba 100644 --- a/xCAT-test/autotest/testcase/confignics/cases0 +++ b/xCAT-test/autotest/testcase/confignics/cases0 @@ -53,11 +53,11 @@ cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi check:rc==0 cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 +cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 -cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1504 +cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC="11.1.0.100|12.1.0.100" nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC="11_1_0_0-255_255_0_0|12_1_0_0-255_255_0_0" check:rc==0 @@ -72,7 +72,6 @@ check:output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp -check:output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp @@ -80,7 +79,6 @@ check:output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp -check:output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -99,11 +97,11 @@ cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi check:rc==0 cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 +cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 -cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1504 +cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC="11.1.0.100|12.1.0.100" nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC="11_1_0_0-255_255_0_0|12_1_0_0-255_255_0_0" nichostnamesuffixes.$$SECONDNIC="-$$SECONDNIC-1|-$$SECONDNIC-2" check:rc==0 @@ -127,7 +125,6 @@ output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp -output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp @@ -135,7 +132,6 @@ output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp -output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 @@ -155,11 +151,11 @@ cmd:lsdef $$CN;if [ $? -eq 0 ]; then lsdef -l $$CN -z >/tmp/CN.standa ;fi check:rc==0 cmd:mkdef -t network -o 11_1_0_0-255_255_0_0 net=11.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 -cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1502 +cmd:mkdef -t network -o 12_1_0_0-255_255_0_0 net=12.1.0.0 mask=255.255.0.0 mgtifname=$$SECONDNIC mtu=1501 check:rc==0 cmd:mkdef -t network -o 13_1_0_0-255_255_0_0 net=13.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 -cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1504 +cmd:mkdef -t network -o 14_1_0_0-255_255_0_0 net=14.1.0.0 mask=255.255.0.0 mgtifname=$$THIRDNIC mtu=1503 check:rc==0 cmd:chdef $$CN nicips.$$SECONDNIC="11.1.0.100|12.1.0.100" nictypes.$$SECONDNIC=Ethernet nicnetworks.$$SECONDNIC="11_1_0_0-255_255_0_0|12_1_0_0-255_255_0_0" nicaliases.$$SECONDNIC="aliases1-1|aliases1-2" check:rc==0 @@ -181,7 +177,6 @@ output=~MTU=1501 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$SECONDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$SECONDNIC; fi check:output=~12.1.0.100 check:output!~dhcp -output=~MTU=1502 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC; else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~13.1.0.100 check:output!~dhcp @@ -189,7 +184,6 @@ output=~MTU=1503 cmd:if [ "$$OS" = "ubuntu" ];then xdsh $$CN cat /etc/network/interfaces.d/$$THIRDNIC:1 ; elif [ "$$OS" = "rhels" ]; then xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC:1;else xdsh $$CN cat /etc/sysconfig/network*/ifcfg-$$THIRDNIC; fi check:output=~14.1.0.100 check:output!~dhcp -output=~MTU=1504 cmd:rmdef -t network -o 11_1_0_0-255_255_0_0 cmd:rmdef -t network -o 12_1_0_0-255_255_0_0 cmd:rmdef -t network -o 13_1_0_0-255_255_0_0 From df369b9387de6864d9dbb2b05ae2e972a6bd2529 Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 30 Mar 2017 04:48:54 -0400 Subject: [PATCH 183/187] update mtu description in networks table --- perl-xCAT/xCAT/Schema.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index ff764754a..c6b615b4e 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -572,7 +572,7 @@ passed as argument rather than by table value', ddnsdomain => 'A domain to be combined with nodename to construct FQDN for DDNS updates induced by DHCP. This is not passed down to the client as "domain"', vlanid => 'The vlan ID if this network is within a vlan.', domain => 'The DNS domain name (ex. cluster.com).', - mtu => 'The default MTU for the network', + mtu => 'The default MTU for the network, if this network is for aliases, mtu value should be the same with its basic network mtu value.', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, From 7e3c314922775b3c744e3691d0e128da756511af Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 30 Mar 2017 05:01:50 -0400 Subject: [PATCH 184/187] update mtu description in networks table --- perl-xCAT/xCAT/Schema.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index c6b615b4e..2ced68c9e 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -572,7 +572,7 @@ passed as argument rather than by table value', ddnsdomain => 'A domain to be combined with nodename to construct FQDN for DDNS updates induced by DHCP. This is not passed down to the client as "domain"', vlanid => 'The vlan ID if this network is within a vlan.', domain => 'The DNS domain name (ex. cluster.com).', - mtu => 'The default MTU for the network, if this network is for aliases, mtu value should be the same with its basic network mtu value.', + mtu => 'The default MTU for the network, if the nic belong to multiple networks, mtu value should be the same in all networks entry.', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, From a79e1d713f5f4d1c09b19a8e2b041c74c7e854aa Mon Sep 17 00:00:00 2001 From: immarvin Date: Thu, 30 Mar 2017 18:08:14 +0800 Subject: [PATCH 185/187] fix a typo --- .../xcat/netboot/rh/dracut/patch/syslog/parse-syslog-opts.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xCAT-server/share/xcat/netboot/rh/dracut/patch/syslog/parse-syslog-opts.sh b/xCAT-server/share/xcat/netboot/rh/dracut/patch/syslog/parse-syslog-opts.sh index 6c070fbd6..e58c8f5a7 100755 --- a/xCAT-server/share/xcat/netboot/rh/dracut/patch/syslog/parse-syslog-opts.sh +++ b/xCAT-server/share/xcat/netboot/rh/dracut/patch/syslog/parse-syslog-opts.sh @@ -1,6 +1,5 @@ #!/bin/sh -# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offs -et: 4; -*- +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh # Parses the syslog commandline options From d19d8f624783aa7779f568f812b8bc5ed2888c13 Mon Sep 17 00:00:00 2001 From: junxiawang Date: Fri, 31 Mar 2017 01:56:39 -0400 Subject: [PATCH 186/187] delete confignics_s testcase --- xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle | 1 - xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle | 1 - xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle | 1 - xCAT-test/autotest/bundle/sles11.4_ppc64.bundle | 1 - 4 files changed, 4 deletions(-) diff --git a/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle b/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle index d0f631fd2..7b9705878 100644 --- a/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels6.9_ppc64.bundle @@ -254,7 +254,6 @@ confignics_config_multiple_port_withnichostnamesuffixes_multiple_value confignics_config_multiple_port_withnicaliases_multiple_value confignics_disable_set_to_yes confignics_disable_set_to_1 -confignics_s xdsh_h xdsh_V xdsh_regular_command diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle index 9577fb385..94715c5b2 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64.bundle @@ -251,7 +251,6 @@ confignics_config_multiple_port_withnichostnamesuffixes_multiple_value confignics_config_multiple_port_withnicaliases_multiple_value confignics_disable_set_to_yes confignics_disable_set_to_1 -confignics_s copycds_iso copycds_a copycds_n_a diff --git a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle index f17b883c8..76a9799df 100644 --- a/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle +++ b/xCAT-test/autotest/bundle/rhels7.3_ppc64le.bundle @@ -239,7 +239,6 @@ confignics_config_multiple_port_withnichostnamesuffixes_multiple_value confignics_config_multiple_port_withnicaliases_multiple_value confignics_disable_set_to_yes confignics_disable_set_to_1 -confignics_s xdsh_h xdsh_V xdsh_regular_command diff --git a/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle b/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle index 956d7fa6b..a6a025161 100644 --- a/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle +++ b/xCAT-test/autotest/bundle/sles11.4_ppc64.bundle @@ -236,7 +236,6 @@ confignics_config_multiple_port_withnichostnamesuffixes_multiple_value confignics_config_multiple_port_withnicaliases_multiple_value confignics_disable_set_to_yes confignics_disable_set_to_1 -confignics_s xdsh_h xdsh_V xdsh_regular_command From baeb4b717ec2bafda80cef89ac7a108547bb015a Mon Sep 17 00:00:00 2001 From: bybai Date: Thu, 30 Mar 2017 21:58:24 -0400 Subject: [PATCH 187/187] polished --- perl-xCAT/xCAT/Schema.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 2ced68c9e..a7c3f9f54 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -572,7 +572,7 @@ passed as argument rather than by table value', ddnsdomain => 'A domain to be combined with nodename to construct FQDN for DDNS updates induced by DHCP. This is not passed down to the client as "domain"', vlanid => 'The vlan ID if this network is within a vlan.', domain => 'The DNS domain name (ex. cluster.com).', - mtu => 'The default MTU for the network, if the nic belong to multiple networks, mtu value should be the same in all networks entry.', + mtu => 'The default MTU for the network, If multiple networks are applied to the same nic on the SN and/or CN, the MTU shall be the same for those networks.', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", },