You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2018/01/29 21:07:15 UTC
[airavata-django-portal] 03/03: AIRAVATA-2615 List job details in
experiment summary
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit 550884b5e2a4096d90a245614a83eeccc3b00fe5
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Mon Jan 29 16:07:04 2018 -0500
AIRAVATA-2615 List job details in experiment summary
---
django_airavata/apps/api/serializers.py | 10 +++++++-
.../js/models/FullExperiment.js | 10 ++++++--
.../static/django_airavata_api/js/models/Job.js | 30 ++++++++++++++++++++++
.../django_airavata_api/js/models/JobState.js | 14 ++++++++++
.../django_airavata_api/js/models/JobStatus.js | 20 +++++++++++++++
django_airavata/apps/api/views.py | 13 +++++++++-
.../js/components/experiment/ExperimentSummary.vue | 22 ++++++++++++++++
7 files changed, 115 insertions(+), 4 deletions(-)
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index d9d32cc..3a0fd09 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -5,6 +5,7 @@ from airavata.model.appcatalog.computeresource.ttypes import BatchQueue
from airavata.model.application.io.ttypes import InputDataObjectType, OutputDataObjectType
from airavata.model.data.replica.ttypes import DataProductModel, DataReplicaLocationModel
from airavata.model.experiment.ttypes import ExperimentModel
+from airavata.model.job.ttypes import JobModel
from airavata.model.status.ttypes import ExperimentStatus
from airavata.model.workspace.ttypes import Project
@@ -245,6 +246,7 @@ class ExperimentSerializer(
url = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:experiment-detail', lookup_field='experimentId', lookup_url_kwarg='experiment_id')
full_experiment = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:full-experiment-detail', lookup_field='experimentId', lookup_url_kwarg='experiment_id')
project = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:project-detail', lookup_field='projectId', lookup_url_kwarg='project_id')
+ jobs = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:experiment-jobs', lookup_field='experimentId', lookup_url_kwarg='experiment_id')
userName = GatewayUsernameDefaultField()
gatewayId = GatewayIdDefaultField()
creationTime = UTCPosixTimestampDateTimeField(allow_null=True)
@@ -270,7 +272,7 @@ class FullExperiment:
def __init__(self, experimentModel, project=None, outputDataProducts=None,
inputDataProducts=None, applicationModule=None,
- computeResource=None):
+ computeResource=None, jobDetails=None):
self.experiment = experimentModel
self.experimentId = experimentModel.experimentId
self.project = project
@@ -278,6 +280,11 @@ class FullExperiment:
self.inputDataProducts = inputDataProducts
self.applicationModule = applicationModule
self.computeResource = computeResource
+ self.jobDetails = jobDetails
+
+
+class JobSerializer(thrift_utils.create_serializer_class(JobModel)):
+ creationTime = UTCPosixTimestampDateTimeField()
class FullExperimentSerializer(serializers.Serializer):
@@ -291,6 +298,7 @@ class FullExperimentSerializer(serializers.Serializer):
applicationModule = ApplicationModuleSerializer(read_only=True)
computeResource = ComputeResourceDescriptionSerializer(read_only=True)
project = ProjectSerializer(read_only=True)
+ jobDetails = JobSerializer(many=True, read_only=True)
def create(self, validated_data):
raise Exception("Not implemented")
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/FullExperiment.js b/django_airavata/apps/api/static/django_airavata_api/js/models/FullExperiment.js
index 6059b2a..b7bac6a 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/FullExperiment.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/FullExperiment.js
@@ -2,8 +2,9 @@
import ApplicationModule from './ApplicationModule'
import BaseModel from './BaseModel'
import ComputeResourceDescription from './ComputeResourceDescription'
-import DataProduct from './DataProduct.js'
+import DataProduct from './DataProduct'
import Experiment from './Experiment'
+import Job from './Job'
import Project from './Project'
const FIELDS = [
@@ -33,7 +34,12 @@ const FIELDS = [
name: 'inputDataProducts',
type: DataProduct,
list: true
- }
+ },
+ {
+ name: 'jobDetails',
+ type: Job,
+ list: true,
+ },
];
export default class FullExperiment extends BaseModel {
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/Job.js b/django_airavata/apps/api/static/django_airavata_api/js/models/Job.js
new file mode 100644
index 0000000..866088a
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/Job.js
@@ -0,0 +1,30 @@
+import BaseModel from './BaseModel';
+import JobStatus from './JobStatus';
+
+const FIELDS = [
+ 'jobId',
+ 'taskId',
+ 'processId',
+ 'jobDescription',
+ {
+ name: 'creationTime',
+ type: 'date',
+ },
+ {
+ name: 'jobStatuses',
+ type: JobStatus,
+ list: true,
+ },
+ 'computeResourceConsumed',
+ 'jobName',
+ 'workingDir',
+ 'stdOut',
+ 'stdErr',
+ 'exitCode',
+];
+
+export default class Job extends BaseModel {
+ constructor(data = {}) {
+ super(FIELDS, data);
+ }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/JobState.js b/django_airavata/apps/api/static/django_airavata_api/js/models/JobState.js
new file mode 100644
index 0000000..88d616d
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/JobState.js
@@ -0,0 +1,14 @@
+import BaseEnum from './BaseEnum'
+
+export default class JobState extends BaseEnum {
+}
+JobState.init([
+ 'SUBMITTED',
+ 'QUEUED',
+ 'ACTIVE',
+ 'COMPLETE',
+ 'CANCELED',
+ 'FAILED',
+ 'SUSPENDED',
+ 'UNKNOWN',
+]);
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/JobStatus.js b/django_airavata/apps/api/static/django_airavata_api/js/models/JobStatus.js
new file mode 100644
index 0000000..3aaac57
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/JobStatus.js
@@ -0,0 +1,20 @@
+import BaseModel from './BaseModel';
+import JobState from './JobState';
+
+const FIELDS = [
+ {
+ name: 'jobState',
+ type: JobState,
+ },
+ {
+ name: 'timeOfStateChange',
+ type: 'date',
+ },
+ 'reason',
+];
+
+export default class JobStatus extends BaseModel {
+ constructor(data = {}) {
+ super(FIELDS, data);
+ }
+}
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 99fce0d..c9b2f57 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -259,6 +259,14 @@ class ExperimentViewSet(APIBackedViewSet):
except Exception as e:
return Response({'success': False, 'errorMessage': e.message})
+ @detail_route(methods=['get'])
+ def jobs(self, request, experiment_id=None):
+ jobs = request.airavata_client.getJobDetails(
+ self.authz_token, experiment_id)
+ serializer = serializers.JobSerializer(
+ jobs, many=True, context={'request': request})
+ return Response(serializer.data)
+
class FullExperimentViewSet(mixins.RetrieveModelMixin,
GenericAPIBackedViewSet):
@@ -303,13 +311,16 @@ class FullExperimentViewSet(mixins.RetrieveModelMixin,
if compute_resource_id else None
project = self.request.airavata_client.getProject(
self.authz_token, experimentModel.projectId)
+ job_details = self.request.airavata_client.getJobDetails(
+ self.authz_token, lookup_value)
full_experiment = serializers.FullExperiment(
experimentModel,
project=project,
outputDataProducts=outputDataProducts,
inputDataProducts=inputDataProducts,
applicationModule=applicationModule,
- computeResource=compute_resource)
+ computeResource=compute_resource,
+ jobDetails=job_details)
return full_experiment
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentSummary.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentSummary.vue
index 17d2634..7a327f7 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentSummary.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentSummary.vue
@@ -60,6 +60,25 @@
{{ localFullExperiment.experimentStatusName }}
</td>
</tr>
+ <tr v-if="localFullExperiment.jobDetails && localFullExperiment.jobDetails.length > 0">
+ <th scope="row">Job</th>
+ <td>
+ <table class="table">
+ <thead>
+ <th>Name</th>
+ <th>ID</th>
+ <th>Status</th>
+ <th>Creation Time</th>
+ </thead>
+ <tr v-for="(jobDetail, index) in localFullExperiment.jobDetails">
+ <td>{{ jobDetail.jobName }}</td>
+ <td>{{ jobDetail.jobId }}</td>
+ <td>{{ jobDetail.jobStatuses[0].jobState.name }}</td>
+ <td><span :title="jobDetail.creationTime.toString()">{{ jobCreationTimes[index] }}</span></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
<!-- TODO: leave this out for now -->
<!-- <tr>
<th scope="row">Notification List</th>
@@ -148,6 +167,9 @@ export default {
},
experiment: function() {
return this.localFullExperiment.experiment;
+ },
+ jobCreationTimes: function() {
+ return this.localFullExperiment.jobDetails.map(jobDetail => moment(jobDetail.creationTime).fromNow());
}
},
methods: {
--
To stop receiving notification emails like this one, please contact
machristie@apache.org.