Opentest-AddingTEEs

back to Opentest's home

In order to service a request the dispatcher will eventually need to use the services provided by one or more Test Execution Engines (TEE) present in the framework. To successfully add a TEE to the framework it is necessary that the TEE registers with the appropriate services in the Test Master Controller (TMC) layer and that it is able to comply with the interface defined for TEEs in the system. This section describes the steps necessary to successfully add a TEE to the framework.

TEE Adapter
The TMC layer of the framework has been designed as a couple of STAF services, Dispatcher and Resource Manager, therefore any interaction between the TEE and the TMC layer is done through STAF calls. For this reason it is essential that when a new TEE is added to the framework it is done so as a STAF service that is required to:


 * 1) Register at start-up with the Resource Manager.
 * 2) Unregister at shutdown with the Resource Manager.
 * 3) Implement the interface defined in [[Media:TEE-Interface.ppt|Test Execution Engines (TEE) Interface]]

TEE Registration
At startup a TEE must inform the TMC layer of its presence in the system, to do so the TEE Adapter must:
 * 1) Register with the Resource Manager by submitting a successful "ADD TYPE  NAME  CAPABILITIES " to the Resource Manager service in the TMC Machine.
 * 2) *The TMC machine is the machine name or IP address of the machine where the Dispatcher is Running. This information must be known by the user and can be saved in the STAF configuration file by setting a shared variable that is read at start-up.
 * 3) *The Resource Manager service is the name given to the resource manager service when it was registered in the TMC machine. This information is saved in the TMC machine in a shared variable called STAF/TMC/ResMgr, when the service is registering with STAF is should obtain the value of this variable by submitting a "GET SHARED VAR STAF/TMC/ResMgr" request to the VAR service in the TMC machine.
 * 4) * is the name given to the TEE service when registering with STAF.
 * 5) * is the name or IP address where the TEE resides this information can be obtain during service initialization by performing STAFUtil.resolveInitVar("{STAF/TMC/Machine}",) call.
 * 6) *  specifies the hardware assets associated with this TEE. This information can be saved in the STAF configuration file by setting a shared variable that is read at start-up.

The steps shown before can be implemented in a java staf service as follows: In the STAF.cfg file enter add the following line set shared var staf/tmc/machine= service add service library jstaf execute parms For example, for the TEE Adapter: set shared var staf/tmc/machine=158.218.103.6 service add service vatf@1 library jstaf execute C:\myJar\TeeAdapter.jar params "txtype=xslt requesttxpath=C:/mydir/afile.xsl requesttxpath=C:/mydir/afile.xsl resultpath=C:\vatf_results.xml hwassets=[dm355,nand2k]"

In the Initialization function defined by staf for the TEE service add: //Obtaining the TEE service name this.teeServiceName = info.name; //Creating a STAFHandle for the Service teeServiceHandle = new STAFHandle("STAF/Service/" + info.name); //Obtaining the TEE's machine name STAFResult res = STAFUtil.resolveInitVar("{STAF/Config/Machine}", teeServiceHandle); if (res.rc != STAFResult.Ok) return res; teeMachine = res.result; //Obtaining the root and temp data directories String endOfPath = "/"; if(info.writeLocation.endsWith("\\") || info.writeLocation.endsWith("/"))endOfPath=""; rootDataDir = info.writeLocation.replaceAll("\\\\","/") + endOfPath; tempDataDir = rootDataDir + "tmp"; File tmpDir = new File(tempDataDir); if(!tmpDir.exists && !tmpDir.mkdirs)throw new Exception("Unable to create data directory " + tempDataDir); //Obtaining the TMC machine name or IP address res = STAFUtil.resolveInitVar("{STAF/TMC/Machine}", teeServiceHandle); if (res.rc != STAFResult.Ok) return res; this.tmcMachine = res.result; //Obtaining the TEE test scripts root directory res = STAFUtil.resolveInitVar("{"+ this.teeServiceName +"/STAF/TEE/test_scripts_root}", teeServiceHandle); if (res.rc == STAFResult.Ok){ this.testRootDir = res.result; } else {  this.testRootDir = null; } //Obtaining the System's line separator res = STAFUtil.resolveInitVar("{STAF/Config/Sep/Line}", teeServiceHandle); if (res.rc != STAFResult.Ok) return res; this.lineSeparator = res.result; // Obtaining the name of the Resource Manager service from the TMC Machine res = this.teeServiceHandle.submit2(this.tmcMachine,"VAR","GET SHARED VAR STAF/TMC/ResMgr"); if (res.rc != STAFResult.Ok) return res; this.tmcResMgr = res.result; //Parsing the parameters passed during service registration Hashtable  regParams = getParms(info.parms); //Obtaining TEE service configuration info if(!regParams.containsKey("txtype") || !regParams.containsKey("requesttxfile") || !regParams.containsKey("resulttxfile") || !regParams.containsKey("hwassets"))throw new Exception("Missing required txType, requesttxfile, resulttxfile or hwassets registration parameter.Check parms option"); this.hwAssets = regParams.get("hwassets"); String description = ""; if(regParams.containsKey("description"))description = " DESCRIPTION " + "\""+ regParams.get("description") + "\""; // Registering with the resource manager STAFResult resMgrRegRes = teeServiceHandle.submit2(this.tmcMachine,this.tmcResMgr,"ADD TYPE \""+this.teeServiceName+"\" NAME \""+this.teeMachine+"\" CAPABILITIES \""+this.hwAssets+"\"" + description); if (resMgrRegRes.rc != STAFResult.Ok) return resMgrRegRes; // Loading the tx type and transformation files this.txType = regParams.get("txtype").trim; res = STAFUtil.resolveInitVar(regParams.get("requesttxfile"), teeServiceHandle); if(res.rc != STAFResult.Ok)return res; File reqTxFile = getTxFile(new File(res.result)); if(reqTxFile!=null){ this.teeRequestTxFile = reqTxFile; this.reqTxPath = res.result; } else throw new Exception("Unable to access requesttxfile "+regParams.get("requesttxfile")); res = STAFUtil.resolveInitVar(regParams.get("resulttxfile"), teeServiceHandle); if(res.rc != STAFResult.Ok)return res; File resTxFile = getTxFile(new File(res.result)); if(resTxFile!=null) {  this.teeResultTxFile = resTxFile; this.resTxPath = res.result; } else throw new Exception("Unable to access resulttxfile "+regParams.get("resulttxfile")); //Obtaining the location of the xml results file generated by the TEE, if any if(regParams.containsKey("resultpath")) {  res = STAFUtil.resolveInitVar(regParams.get("resultpath"), teeServiceHandle); if(res.rc != STAFResult.Ok)return res; this.xmlResultsPath=res.result.replaceAll("\\\\", "/"); } //Obtaining the name of the monitor service res = this.teeServiceHandle.submit2(this.tmcMachine,"VAR","GET SHARED VAR STAF/TMC/Monitor"); if (res.rc == STAFResult.Ok) {  this.tmcMonitor = res.result; STAFResult monitorServiceCheck = this.teeServiceHandle.submit2("LOCAL","SERVICE","QUERY SERVICE "+this.tmcMonitor); if(monitorServiceCheck.rc != 0) {    STAFResult varResult = this.teeServiceHandle.submit2("LOCAL","VAR","SET SHARED VAR \"auto/Tee/Monitor="+this.tmcMonitor+"\""); if(varResult.rc != STAFResult.Ok)return varResult; STAFResult monRegRes = this.teeServiceHandle.submit2("LOCAL","SERVICE","ADD SERVICE " + this.tmcMonitor + " LIBRARY STAFMon"); if(monRegRes.rc != STAFResult.Ok)return monRegRes; } }

TEE Un-registration
At shutdown a TEE must inform the TMC layer that it will no longer be present in the system, to do so the TEE Adapter must:
 * 1) Unregister with the Resource Manager by submitting a successful "DELETE TYPE  NAME  CONFIRM"
 * 2) * is the name given to the TEE service when registering with STAF.
 * 3) * is the name or IP address where the TEE resides.

The steps shown before can be implemented in a java staf service as follows: In the termination function defined by staf for the TEE service add: this.teeServiceHandle.submit2(this.tmcMachine,this.tmcResMgr,"DELETE TYPE "+this.teeServiceName+" NAME "+this.teeMachine+" CONFIRM");

TEE Adapter Implementation
A TEE service can be implemented in any language supported by STAF (C/C++, Java, etc) for more information about STAF service development refer to Staf Service Developer's Guide. The TEE adapter must implement the interface defined in [[Media:TEE-Interface.ppt|Test Execution Engines (TEE) Interface]], this interface requires the TEE service to support a "Run [FORCECOPY]" command which is used by the dispatcher to send a test request to the TEE service. The sequence of events between the dispatcher and the TEE during a request is as follows:
 * 1) For each software asset needed for the tests the Dispatcher sets a STAF variable  /auto/sw_assets/  in the TEE that points to the location of the asset in the Dispatcher's cache.
 * 2) The dispatcher sets the  /auto/TEE/test_scripts_root in the TEE to value specified in the build Information of the test. If supported by the TEE this value is used to specify the version of the test scripts that will be used for the tests.
 * 3) The Dispatcher sends a "Run [FORCECOPY]" (defined at [[Media:TEE-Interface.ppt|Test Execution Engines (TEE) Interface]]) command to the TEE service.
 * 4) The TEE service copies the assets specified in 1 locally. Although it is not required, ideally the TEE service should keep a local cache with the assets it has copied in previous iterations and copy only the assets not present in its cache unless the FORCECOPY flag is specified.
 * 5) The TEE service gets the and runs the tests.
 * 6) The TEE service returns a STAF result with a Map class than contains a resultsfile entry pointing to the xml results file generated by the TEE service.

An example template of a "Run [FORCECOPY]" implementation in java could be: //Checking that the requesting service has the required trust level STAFResult trustResult = STAFUtil.validateTrust(3, this.teeServiceName, "Run", this.teeMachine, info); if (trustResult.rc != STAFResult.Ok) return trustResult; //Checking that the run request has the correct structure STAFCommandParseResult parsedRequest = getParser("run").parse(info.request); if(parsedRequest.rc != STAFResult.Ok) return new STAFResult(STAFResult.InvalidRequestString, parsedRequest.errorBuffer); //Copying the xml test data String teeReqFile = STAFUtil.resolveRequestVar(parsedRequest.optionValue("run"),this.teeServiceHandle,info.requestNumber).result; String localTestRequest = this.tempDataDir+"/tee_req_" + String.valueOf(new Date.getTime)+ ".xml"; STAFResult copyReqResult = submit2(this.tmcMachine,"FS", "COPY FILE "+teeReqFile +" TOFILE "+localTestRequest); if(copyReqResult.rc != STAFResult.Ok) return copyReqResult; //Obtaining the location of the software assets specified for this test session, and copying to the cache if necessary STAFResult varResult = this.teeServiceHandle.submit2("local","var","list shared"); if(varResult.rc == STAFResult.Ok) {  Map varMap = (Map) varResult.resultObj; Set mapKeys = varMap.keySet; for(Iterator resIter = mapKeys.iterator; resIter.hasNext;) {    String currentKey = (String) resIter.next; if(currentKey.trim.toLowerCase.startsWith("auto/sw_assets/")) {      String currentAssetLocation = (String)varMap.get(currentKey); if(currentAssetLocation.startsWith("/"))currentAssetLocation=currentAssetLocation.replaceFirst("/",""); int baseDirindex = currentAssetLocation.toLowerCase.indexOf("sw_assets"); String localAsset = this.cacheRootDir; if(baseDirindex > -1) {      String assetLocSubString = currentAssetLocation.substring(baseDirindex+9); if(assetLocSubString.startsWith("/"))assetLocSubString=assetLocSubString.replaceFirst("/",""); localAsset+=assetLocSubString; }      else localAsset+=currentAssetLocation; File localFile = new File(localAsset); if(!(localFile.exists) || parsedRequest.optionTimes("FORCECOPY") != 0) {        localFile.getParentFile.mkdirs; STAFResult copySoftwareRes = this.teeServiceHandle.submit2(this.tmcMachine,"FS","COPY FILE \""+currentAssetLocation+"\" TOFILE \""+localAsset+"\""); if(copySoftwareRes.rc != STAFResult.Ok) return copySoftwareRes; }      STAFResult varSetRes = this.teeServiceHandle.submit2("LOCAL","VAR","SET SHARED VAR \""+currentKey+"="+localAsset+"\""); if(varSetRes.rc != STAFResult.Ok) return varSetRes; }  } } else return varResult; //Setting the test scripts that will be used to the appropriate version. STAFResult testScriptVarRes = this.teeServiceHandle.submit2("LOCAL","VAR","GET SHARED VAR auto/TEE /test_scripts_root"); if(testScriptVarRes.rc == STAFResult.Ok) {  String[] testScriptRootInfo = testScriptVarRes.result.trim.split("://"); String testScriptRootType = testScriptRootInfo[0].trim.toLowerCase; String testScriptRootSetupInfo = testScriptRootInfo[1].trim; TestScriptHelper testScriptHelp; if(testScriptRootType.equals("clearcase"))testScriptHelp = new ClearCaseHelper(this.teeServiceHandle, "automation_teeadapter", this.tempDataDir, this.adLogger); else testScriptHelp = null; String teeScriptDrive = null; if(testScriptHelp != null) {    try {      teeScriptDrive = testScriptHelp.setTestDir(testScriptRootSetupInfo); } catch (Exception e)    { String eTrace = e.toString+"\n"; StackTraceElement[] eStack = e.getStackTrace; for(int i =0; i < eStack.length; i++)eTrace+=eStack[i].toString+"\n"; }  }   if(teeScriptDrive != null) {    STAFResult teeScriptsRes = submit2("LOCAL","VAR","SET SHARED VAR \"auto/TEE/test_scripts_root="+teeScriptDrive+"\""); } }  String resultFile = ""; //TEE Specific execution code goes here .        .         .         .  //Sending the result message to the Dispatcher STAFMarshallingContext runMC = new STAFMarshallingContext; runMC.setMapClassDefinition(runMapClass); Map resultMap = runMapClass.createInstance; resultMap.put("resultsfile", resultFile.replaceAll("\\\\","/")); runMC.setRootObject(resultMap); return new STAFResult(STAFResult.Ok,runMC.marshall);

TEE Adapter Implementation Example
An example implementation of a TEE Adapter can be found at TEEAdapter source. This TEE adapter was developed to integrate VATF into the framework.