Monday, October 19, 2009

Submitting a Grid Job with OGCE JavaScript API

In the previous post, we showed how to get a MyProxy credential with the OGCE's Cyberaide JavaScript API. We'll now look at how to submit a simple job. We'll build up a very simple HTML page to do this, but you should note that we have much more appealing clients than this if you want to use something out of the box.

Let's start by building upon our earlier MyProxyGaget.html example. This file is called JobSubGadget.html and is in the client subdirectory of the source code. We will combine the MyProxy form with a Job Submission form to simplify security issues; that is, the user will be presented with a form to get a proxy credential (shown last time) and a form to launch a job. The job launching form only appears after the user successfully authenticates.

To do this, we will start with a little jQuery trick. We'll wrap the two tables in <div> classes called proxyFormClass and jobSubClass and define the following CSS entries:

.proxyFormClass {
}

.jobSubClass{
display: none;
}

Then in the authentication callback function (see previous post), we put the code snippet below:

$('div.jobSubClass').show();
$('div.proxyFormClass').hide();

This will turn off the proxy form fields and turn on the job submission fields.

Now we're ready for the job submission form itself. Here's a very bare bones one:
<div class="jobSubClass" id="jobSub">
Fill in the form below to launch a job.
<table>
<tr>
<td>Command</td>
<td><input name="cmd" type="text" id="cmd" size="50" value="/bin/ls"/></td>
</tr>

<tr>
<td>Arguments</td>
<td><input name="arg" type="text" id="arg" size="50" value="-l"/></td>
</tr>
<tr>
<td>GRAM Host</td>
<td><input name="rHost" type="text" id="rHost" size="50" value="grid-co.ncsa.teragrid.org"/>
</td>
</tr>

<tr>
<td>GridFTP Host</td>
<td><input name="ftpHost" type="text" id="ftpHost" size="50" value="gridftp-co.ncsa.teragrid.org"/>
</td>
</tr>

<tr>
<td>Standard Output</td>
<td><input name="stdout" type="text" id="stdout" size="50" value="junk-ls.out"/>
</td>
</tr>

<tr>
<td>Provider</td>
<td><input name="provider" type="radio" id="gt2" checked>GT2
<input name="provider" type="radio" id="gt4">GT4</td>
</tr>
<tr>
<div name="submitStatus" id="submitStatus"/>
</tr>

</table>
<input name="button1" type="button" class="runButton" id="button1" onclick="submitJob();return false" value="Submit job"/>
</div>

This should look familiar. One important thing to note (besides the little div wrapper) is that we need to provide the hostname for both the GRAM and GridFTP hosts. We need this to both run the job and pull back the output. Not all grid installations (notably the TeraGrid) run both the GRAM and GridFTP server on the same machine (network file systems), so we have to allow for this.

Now let's look at some minimal JavaScript code to invoke the service. The main thing we need to do is collect the submission form's parameters and invoke the service.

function submitJob() {
/* extract job specification */
var cmd = document.getElementById("cmd").value;
var arg = document.getElementById("arg").value;
var rHost = document.getElementById("rHost").value;
var ftpHost=document.getElementById("ftpHost").value;
var stdout = document.getElementById("stdout").value;
var provider = document.getElementsByName("provider");
var prov = null;
if(provider[0].checked){
prov = "GT2";
}
else {
prov = "GT4";
}

/* construct karajan workflow */
var strProj = jscog.constructRemoteJob(cmd, arg, rHost, stdout, ftpHost, stdout, prov);
document.getElementById("submitStatus").innerHTML = "Job Submitting";
loc="";
jscog.submitWf(strProj,submitResponse,loc);

}

Job submission is actually a two step process in the API: first we construct the job's workflow (we use the CoG's Karajan on the backend), and then we submit the constructed workflow script (jscog.submitWf()). We also need to write a callback handler (submitResponse in the submitWf() command) to see if the job was submitted successfully. Here is a really simple one:

/*
* Callback to handle the submission response.
*/
function submitResponse(ret) {
document.getElementById("submitStatus").innerHTML="Your job has been submitted with workflow ticket "+ret;

}

The callback function gets an integer ret back from the server. If submission was successful, then this integer will be the job ticket, which you can use to query status and get back results or error messages.

No comments: