浏览代码

HUE-1176 [jb] Protect YARN fields against missing values

Romain Rigaux 8 年之前
父节点
当前提交
93e8ab471e

+ 34 - 31
apps/jobbrowser/src/jobbrowser/apis/job_api.py

@@ -20,15 +20,14 @@ import logging
 
 from django.utils.translation import ugettext as _
 
-from jobbrowser.apis.base_api import Api, MockDjangoRequest, _extract_query_params
-from jobbrowser.views import job_attempt_logs_json, kill_job
-
 
 LOG = logging.getLogger(__name__)
 
 
 try:
   from jobbrowser.api import YarnApi as NativeYarnApi
+  from jobbrowser.apis.base_api import Api, MockDjangoRequest, _extract_query_params
+  from jobbrowser.views import job_attempt_logs_json, kill_job, massage_job_for_json
 except Exception, e:
   LOG.exception('Some application are not enabled: %s' % e)
 
@@ -94,48 +93,52 @@ class YarnApi(Api):
 
     jobs = NativeYarnApi(self.user).get_jobs(**filter_params)
 
+    apps = [massage_job_for_json(job, user=self.user) for job in jobs]
+
     return {
       'apps': [{
-        'id': app.jobId,
-        'name': app.name,
-        'type': app.applicationType,
-        'status': app.status,
-        'apiStatus': self._api_status(app.status),
-        'user': self.user.username,
-        'progress': app.progress,
-        'duration': 10 * 3600,
-        'submitted': app.startTimeMs
-      } for app in jobs],
+        'id': app['id'],
+        'name': app['name'],
+        'type': app['applicationType'],
+        'status': app['status'],
+        'apiStatus': self._api_status(app['status']),
+        'user': app['user'],
+        'progress': app['progress'],
+        'duration': app['durationMs'],
+        'submitted': app['startTimeMs']
+      } for app in apps],
       'total': None
     }
 
+
   def app(self, appid):
     app = NativeYarnApi(self.user).get_job(jobid=appid)
 
+    app = massage_job_for_json(app, user=self.user)
+
     common = {
-        'id': app.jobId,
-        'name': app.name,
-        'type': app.applicationType,
-        'status': app.status,
-        'apiStatus': self._api_status(app.status),
-        'user': self.user.username,
-        'progress': app.progress,
-        'duration': 10 * 3600,
-        'submitted': 10 * 3600
+        'id': app['id'],
+        'name': app['name'],
+        'type': app['applicationType'],
+        'status': app['status'],
+        'apiStatus': self._api_status(app['status']),
+        'user': app['user'],
+        'progress': app['progress'],
+        'duration': app['durationMs'],
+        'submitted': app['startTimeMs']
     }
 
-    if app.applicationType == 'MR2':
+    if app['applicationType'] == 'MR2':
       common['type'] = 'MAPREDUCE'
-      common['duration'] = app.duration
-      common['durationFormatted'] = app.durationFormatted
+      common['durationFormatted'] = app['durationFormatted']
 
       common['properties'] = {
-          'maps_percent_complete': app.maps_percent_complete,
-          'reduces_percent_complete': app.reduces_percent_complete,
-          'finishedMaps': app.finishedMaps,
-          'finishedReduces': app.finishedReduces,
-          'desiredMaps': app.desiredMaps,
-          'desiredReduces': app.desiredReduces,
+          'maps_percent_complete': app['mapsPercentComplete'],
+          'reduces_percent_complete': app['reducesPercentComplete'],
+          'finishedMaps': app['finishedMaps'],
+          'finishedReduces': app['finishedReduces'],
+          'desiredMaps': app['desiredMaps'],
+          'desiredReduces': app['desiredReduces'],
 
           'tasks': [],
           'metadata': [],

+ 4 - 3
apps/jobbrowser/src/jobbrowser/templates/job_browser.mako

@@ -166,7 +166,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
                   <tr data-bind="click: fetchJob">
                     <td><div class="hueCheckbox fa" data-bind="click: function() {}, clickBubble: false, multiCheck: '#runningJobsTable', value: $data, hueChecked: $parent.jobs.selectedJobs"></div></td>
                     <td data-bind="text: duration"></td>
-                    <td data-bind="text: submitted></td>
+                    <td data-bind="text: submitted"></td>
                     <td data-bind="text: type"></td>
                     <td data-bind="text: status"></td>
                     <td data-bind="text: progress"></td>
@@ -1025,7 +1025,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
       self.mainType = ko.observable(vm.interface());
 
       self.hasKill = ko.computed(function() {
-        return ['workflow'].indexOf(self.type()) != -1;
+        return ['MAPREDUCE', 'SPARK', 'workflow'].indexOf(self.type()) != -1;
       });
       self.killEnabled = ko.computed(function() {
         return self.hasKill() && self.apiStatus() == 'RUNNING';
@@ -1253,6 +1253,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
             }
           });
         }
+      };
     };
 
     var Jobs = function (vm) {
@@ -1270,7 +1271,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
       self.selectedJobs = ko.observableArray();
 
       self.hasKill = ko.computed(function() {
-        return ['workflows'].indexOf(vm.interface()) != -1;
+        return ['jobs', 'workflows'].indexOf(vm.interface()) != -1;
       });
       self.killEnabled = ko.computed(function() {
         return self.hasKill() && self.selectedJobs().length > 0 && $.grep(self.selectedJobs(), function(job) {

+ 3 - 2
apps/jobbrowser/src/jobbrowser/views.py

@@ -165,7 +165,7 @@ def jobs(request):
   })
 
 
-def massage_job_for_json(job, request):
+def massage_job_for_json(job, request=None, user=None):
   job = {
     'id': job.jobId,
     'shortId': job.jobId_short,
@@ -178,6 +178,7 @@ def massage_job_for_json(job, request):
     'user': job.user,
     'isRetired': job.is_retired,
     'isMR2': job.is_mr2,
+    'progress': hasattr(job, 'progress') and job.progress or '',
     'mapProgress': hasattr(job, 'mapProgress') and job.mapProgress or '',
     'reduceProgress': hasattr(job, 'reduceProgress') and job.reduceProgress or '',
     'setupProgress': hasattr(job, 'setupProgress') and job.setupProgress or '',
@@ -198,7 +199,7 @@ def massage_job_for_json(job, request):
     'finishTimeFormatted': hasattr(job, 'finishTimeFormatted') and job.finishTimeFormatted or '',
     'durationFormatted': hasattr(job, 'durationFormatted') and job.durationFormatted or '',
     'durationMs': hasattr(job, 'durationInMillis') and job.durationInMillis or 0,
-    'canKill': can_kill_job(job, request.user),
+    'canKill': can_kill_job(job, request.user if request else user),
     'killUrl': job.jobId and reverse('jobbrowser.views.kill_job', kwargs={'job': job.jobId}) or '',
   }
   return job