diff --git a/xCAT-test/autotest/testcase/xcat-inventory/validatehelper b/xCAT-test/autotest/testcase/xcat-inventory/validatehelper index 3910d5ec1..ab21b0cfa 100755 --- a/xCAT-test/autotest/testcase/xcat-inventory/validatehelper +++ b/xCAT-test/autotest/testcase/xcat-inventory/validatehelper @@ -1,191 +1,251 @@ -#!/usr/bin/bash +#!/usr/bin/python +from __future__ import print_function -objtype=$1 -objname=$2 -attribute=$3 -attrvalue=$4 -tmpdir=$5 +import yaml +import json +import os +import re +import sys +import shutil +import subprocess -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" +#remove the dict entries whose value is null or '' +def Util_rmnullindict(mydict): + for key in mydict.keys(): + if isinstance(mydict[key],dict): + Util_rmnullindict(mydict[key]) + if not mydict[key].keys(): + del mydict[key] + else: + if not mydict[key]: + del mydict[key] -function usage { - echo "Usage:" - echo "${BASH_SOURCE[0]} [ OBJTYPE OBJNAME ATTRIBUTE ATTRVALUE TMPDIR]" -} +# get the dict value mydict[a][b][c] with key path a.b.c +def Util_getdictval(mydict,keystr): + if not isinstance(mydict,dict): + return None + dictkeyregex=re.compile("([^\.]+)\.?(\S+)*") + result=re.findall(dictkeyregex,keystr) + if result: + (key,remdkey)=result[0] + if key not in mydict.keys(): + return None + if remdkey: + return Util_getdictval(mydict[key],remdkey) + else: + return mydict[key] -echo objtype=\"${objtype}\" -echo objname=\"${objname}\" -echo attribute=\"${attribute}\" -echo attrvalue=\"${attrvalue}\" -echo tmpdir=\"${tmpdir}\" +# get the dict value mydict[a][b][c] with key path a.b.c +def Util_setdictval(mydict,keystr,value): + dictkeyregex=re.compile("([^\.]+)\.?(\S+)*") + result=re.findall(dictkeyregex,keystr) + if result: + (key,remdkey)=result[0] + if remdkey: + if key not in mydict.keys(): + mydict[key]={} + Util_setdictval(mydict[key],remdkey,value) + else: + mydict[key]=value + +def GetAttrInFile(fpath,objtype,objname,attrpath): + f=open(fpath,'r') + try: + objdict=json.loads(f) + except TypeError,ValueError: + try: + objdict=yaml.load(f) + except Exception,e: + raise Exception("Error: cannot open file "+fpath+"! "+str(e)) + + f.close() + myattrpath=objtype+"."+objname+"."+attrpath + myvalue=Util_getdictval(objdict,myattrpath) + if isinstance(myvalue,list): + myvalue=myvalue[0] + return myvalue + +def runCommand(cmd, env=None): + """ Run one command only, when you don't want to bother setting up + the Popen stuff. + """ + print('Running command: %s' %cmd) + try: + p = subprocess.Popen(cmd, + env=env, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + out, err = p.communicate() + except OSError,e: + print('RunCommand failed due to OSError %s' % e) + if p.returncode: + print('Command %s failed with return code %d : %s' % (cmd , p.returncode, err)) + print(out) + print(err) + return p.returncode + + +def UpdateAttrInFile(fpath,fformat,objtype,objname,attrpath,value): + f=open(fpath,'r') + try: + objdict=json.loads(f) + except TypeError,ValueError: + try: + objdict=yaml.load(f) + except Exception,e: + raise Exception("Error: cannot open file "+fpath+"! "+str(e)) + + f.close() + myattrpath=objtype+"."+objname+"."+attrpath + if value == "": + Util_setdictval(objdict,myattrpath,"") + Util_rmnullindict(objdict) + else: + origobjdict=Util_getdictval(objdict,myattrpath) + if isinstance(origobjdict,list) and not isinstance(value,list): + newvalue=[value] + else: + newvalue=value + Util_setdictval(objdict,myattrpath,newvalue) + f=open(fpath,'w') + if fformat == "yaml": + print(yaml.dump(objdict,default_flow_style=False),file=f) + elif fformat == "json": + print(json.dumps(objdict, sort_keys=True, indent=4, separators=(',', ': ')),file=f) + f.close() + +def removeobj(objtype,objname): + print("removing existing \""+objtype+"\" type object \""+objname+"\" from xCAT\n") + if str(objtype) in ('node','osimage','network','site','route','zone','policy'): + runCommand("rmdef -t "+objtype+" -o "+objname) + elif str(objtype) in ('passwd'): + runCommand("tabch -d key="+objname+" passwd") + +def Usage(): + print("Usage:\n") + print(sys.argv[0]+" [OBJTYPE OBJNAME ATTRIBUTE ATTRVALUE TMPDIR]") + +if len(sys.argv) < 6: + Usage() + exit(1) + + +objtype=str(sys.argv[1]) +objname=str(sys.argv[2]) +attribute=str(sys.argv[3]) +attrvalue=str(sys.argv[4]) +tmpdir=str(sys.argv[5]) +print("objtype=%s\nobjname=%s\nattribute=%s\nattrvalue=%s\ntmpdir=%s\n"%(objtype,objname,attribute,attrvalue,tmpdir)) + +if os.path.exists(tmpdir): + runCommand("rm -rf "+tmpdir) + +os.mkdir(tmpdir) + +print("Temporary directory to hold intermediate files: "+tmpdir+"\n") + +curdir=os.path.split(os.path.realpath(sys.argv[0]))[0] +yamldeftmpl=curdir+"/templates/"+objtype+'.yaml' +jsondeftmpl=curdir+"/templates/"+objtype+'.json' +yamldef=tmpdir+"/"+objtype+'.yaml' +jsondef=tmpdir+"/"+objtype+'.json' +yamldefout=tmpdir+"/"+objtype+'.out.yaml' +jsondefout=tmpdir+"/"+objtype+'.out.json' + +shutil.copyfile(yamldeftmpl,yamldef) +shutil.copyfile(jsondeftmpl,jsondef) + +rcfinal=0 +rcyaml=0 +rcjson=0 +rc=0 + +UpdateAttrInFile(yamldef,'yaml',objtype,objname,attribute,attrvalue) +print("=================the inventory file to import: "+yamldef+"=====================\n") +runCommand("cat "+yamldef) +print("===============================================================================\n") -if [ -z "$objtype" ] || [ -z "$objname" ] || [ -z "$attribute" ] || [ -z "$tmpdir" ]; then - usage - exit 1 -fi +print("import the inventory file "+yamldef+"\n") +rc=runCommand("xcat-inventory import -t "+objtype+" -o "+objname+" -f "+yamldef) +if rc !=0: + print("failed to import the inventory file "+yamldef) + rcyaml=1 +else: + print("the inventory file "+yamldef+" imported successfully\n") + print("export the \""+objtype+"\" type object \""+objname+"\" just imported\n") + rc=runCommand("xcat-inventory export -t "+objtype+" -o "+objname+" --format=yaml 1>"+yamldefout) + if rc!=0: + print("failed to export the \""+objtype+"\" type object \""+objname+"\"\n") + rcyaml=1 + else: + print("==============the exported inventory file "+yamldefout+"======================\n") + runCommand("cat "+yamldefout) + print("===========================================================================\n") + myattrvalue=GetAttrInFile(yamldefout,objtype,objname,attribute) + if attrvalue == '': + if myattrvalue is not None: + rcyaml=1 + else: + if myattrvalue != attrvalue: + rcyaml=1 -RETCODE_YAML=0 -RETCODE_JSON=0 +if rcyaml == 0: + print("yaml validation passed\n") +else: + print("yaml validation failed\n") -[ -e "$tmpdir" ] || rm -rf $tmpdir -mkdir -p $tmpdir -echo "Temporary directory to hold intermediate files: $tmpdir" +removeobj(objtype,objname) -cp ${DIR}/templates/${objtype}.json ${tmpdir}/ -cp ${DIR}/templates/${objtype}.yaml ${tmpdir}/ - -#the intermediate inventory files to import -yamldef="${tmpdir}/${objtype}.yaml" -jsondef="${tmpdir}/${objtype}.json" - -#the intermediate inventory files exported -yamldefout="${tmpdir}/${objtype}.out.yaml" -jsondefout="${tmpdir}/${objtype}.out.json" - -echo "removing existing \"$objtype\" type object \"$objname\" from xCAT" -echo "osimage node network site route zone policy "|grep -q -w "$objtype" -if [ $? -eq 0 ];then - rmdef -t $objtype -o $objname -fi -if [ "$objtype" = "passwd" ];then - tabch -d key=$objname passwd -fi - -#substitute the attribute value in inventory files -if [ ${#attrvalue} -ne 0 ];then - sed -i -E -e "s/^(\s*["'"'"']?$attribute["'"'"']?:\s*["'"'"']?)[^'"'"'"]*(["'"'"']?[,]?\s*)$/\1$attrvalue\2/g" $yamldef -else - sed -i -e "/^\s*["'"'"']*$attribute["'"'"']*:/d" $yamldef -fi - -echo "=================the inventory file to import: ${yamldef}=====================" -cat $yamldef -echo "==============================================================================" +UpdateAttrInFile(jsondef,'json',objtype,objname,attribute,attrvalue) +print("=================the inventory file to import: "+jsondef+"=====================\n") +runCommand("cat "+jsondef) +print("===============================================================================\n") -echo "import the inventory file $yamldef " -xcat-inventory import -t $objtype -o $objname -f $yamldef -if [ $? -ne 0 ];then - echo "failed to import the inventory file $yamldef" - RETCODE_YAML=1 -else - echo "the inventory file $yamldef imported successfully" - echo "export the \"$objtype\" type object \"$objname\" just imported" - xcat-inventory export -t $objtype -o $objname --format=yaml 1>$yamldefout - if [ $? -ne 0 ];then - echo "failed to export the \"$objtype\" type object \"$objname\"" - RETCODE_YAML=1 - else - echo "the inventory data of the \"$objtype\" type object \"$objname\" exported to $yamldefout" - echo "==============the exported inventory file $yamldefout======================" - cat $yamldefout - echo "===========================================================================" - echo "make sure the attribute $attribute is imported and exported successfully" - if [ -n "$attrvalue" ]; then - cat $yamldefout|grep -w "$attribute"|grep -q -w "$attrvalue" - if [ $? -ne 0 ];then - RETCODE_YAML=1 - fi - else - cat $yamldefout|grep -q -w "$attribute" - if [ $? -eq 0 ];then - RETCODE_YAML=1 - fi - fi +print("import the inventory file "+jsondef+"\n") +rc=runCommand("xcat-inventory import -t "+objtype+" -o "+objname+" -f "+jsondef) +print("rc="+str(rc)) +if rc !=0: + print("failed to import the inventory file "+jsondef) + rcjson=1 +else: + print("the inventory file "+jsondef+" imported successfully\n") + print("export the \""+objtype+"\" type object \""+objname+"\" just imported\n") + rc=runCommand("xcat-inventory export -t "+objtype+" -o "+objname+" --format=json 1>"+jsondefout) + if rc!=0: + print("failed to export the \""+objtype+"\" type object \""+objname+"\"\n") + rcjson=1 + else: + print("==============the exported inventory file "+jsondefout+"======================\n") + runCommand("cat "+jsondefout) + print("===========================================================================\n") + myattrvalue=GetAttrInFile(jsondefout,objtype,objname,attribute) + if attrvalue == '': + if myattrvalue is not None: + rcjson=1 + else: + if myattrvalue != attrvalue: + rcjson=1 + +if rcjson ==0: + print("json validation passed\n") +else: + print("json validation failed\n") + +removeobj(objtype,objname) + +if rcjson !=0 or rcyaml!=0: + rcfinal=1 + +print("remove intermediate directory "+tmpdir) +if os.path.exists(tmpdir): + runCommand("rm -rf "+tmpdir) + +exit(rcfinal) - fi -fi - -if [ $RETCODE_YAML -eq 0 ]; then - echo "yaml validation passed" -else - echo "yaml validation failed" -fi - -echo "removing existing \"$objtype\" type object \"$objname\" from xCAT" -echo "osimage node network site route zone policy "|grep -q -w "$objtype" -if [ $? -eq 0 ];then - rmdef -t $objtype -o $objname -fi - -if [ "$objtype" = "passwd" ];then - tabch -d key=$objname passwd -fi - - -if [ ${#attrvalue} -ne 0 ];then - sed -i -E -e "s/^(\s*["'"'"']?$attribute["'"'"']?:\s*["'"'"']?)[^'"'"'"]*(["'"'"']?[,]?\s*)$/\1$attrvalue\2/g" $jsondef -else - sed -i -e "/^\s*["'"'"']*$attribute["'"'"']*:/d" $jsondef -fi - -echo "=================the inventory file to import: ${jsondef}=====================" -cat $jsondef -echo "==============================================================================" - -echo "import the inventory file $jsondef " -xcat-inventory import -t $objtype -o $objname -f $jsondef -if [ $? -ne 0 ];then - echo "failed to import the inventory file $jsondef" - RETCODE_JSON=1 -else - xcat-inventory export -t $objtype -o $objname 1>$jsondefout - if [ $? -ne 0 ];then - echo "the inventory file $jsondef imported successfully" - echo "export the \"$objtype\" type object \"$objname\" just imported" - RETCODE_JSON=1 - else - echo "the inventory data of the \"$objtype\" type object \"$objname\" exported to $jsondefout" - echo "==============the exported inventory file $jsondefout======================" - cat $jsondefout - echo "===========================================================================" - echo "make sure the attribute $attribute is imported and exported successfully" - if [ -n "$attrvalue" ]; then - cat $jsondefout|grep -w "$attribute"|grep -q -w "$attrvalue" - if [ $? -ne 0 ];then - RETCODE_JSON=1 - fi - else - cat $jsondefout|grep -q -w "$attribute" - if [ $? -eq 0 ];then - RETCODE_JSON=1 - fi - fi - - fi -fi - -if [ $RETCODE_JSON -eq 0 ]; then - echo "json validation passed" -else - echo "json validation failed" -fi - - -echo "osimage node network site route zone policy "|grep -q -w "$objtype" -if [ $? -eq 0 ];then - rmdef -t $objtype -o $objname -fi - -if [ "$objtype" = "passwd" ];then - tabch -d key=$objname passwd -fi - -echo "remove intermediate directory $tmpdir" -[ -e "$tmpdir" ] || rm -rf $tmpdir - -if [ $RETCODE_YAML -ne 0 ] || [ $RETCODE_JSON -ne 0 ]; then - exit 1 -fi - -exit 0