瀏覽代碼

HUE-1176 [jb] Add bundle page and its actions

Romain Rigaux 8 年之前
父節點
當前提交
c4e25f4832

+ 51 - 7
apps/jobbrowser/src/jobbrowser/apis/bundle_api.py

@@ -16,14 +16,15 @@
 # limitations under the License.
 
 import logging
+import json
 
 from django.utils.translation import ugettext as _
 
 from liboozie.oozie_api import get_oozie
-from notebook.connectors.oozie_batch import OozieApi
 
-from jobbrowser.apis.base_api import Api
-from oozie.views.dashboard import get_oozie_job_log
+from jobbrowser.apis.base_api import Api, MockDjangoRequest
+from liboozie.utils import format_time
+from oozie.views.dashboard import get_oozie_job_log, massaged_bundle_actions_for_json
 
 
 LOG = logging.getLogger(__name__)
@@ -31,7 +32,6 @@ LOG = logging.getLogger(__name__)
 
 try:
   from oozie.conf import OOZIE_JOBS_COUNT
-  from oozie.views.dashboard import massaged_coordinator_actions_for_json
 except Exception, e:
   LOG.exception('Some application are not enabled: %s' % e)
 
@@ -44,25 +44,69 @@ class BundleApi(Api):
     jobs = oozie_api.get_bundles(**kwargs)
 
     return {
-      'apps': [{
+      'apps':[{
         'id': app.id,
         'name': app.appName,
         'status': app.status,
+        'apiStatus': self._api_status(app.status),
         'type': 'bundle',
         'user': app.user,
-        'progress': 100,
+        'progress': app.get_progress(),
         'duration': 10 * 3600,
         'submitted': 10 * 3600
       } for app in jobs.jobs],
       'total': jobs.total
     }
 
+
   def app(self, appid):
     oozie_api = get_oozie(self.user)
     bundle = oozie_api.get_bundle(jobid=appid)
 
-    return {
+    common = {
         'id': bundle.bundleJobId,
         'name': bundle.bundleJobName,
         'status': bundle.status,
+        'apiStatus': self._api_status(bundle.status),
+        'progress': bundle.get_progress(),
+        'type': 'bundle',
+        'startTime': format_time(bundle.startTime),
+        'properties': {}
     }
+    common['properties']['actions'] = massaged_bundle_actions_for_json(bundle)
+    common['properties']['xml'] = ''
+    common['properties']['properties'] = ''
+
+    return common
+
+  def logs(self, appid, app_type, log_name=None):
+    request = MockDjangoRequest(self.user)
+    data = get_oozie_job_log(request, job_id=appid)
+
+    return {'logs': json.loads(data.content)['log']}
+
+
+  def profile(self, appid, app_type, app_property):
+    if app_property == 'xml':
+      oozie_api = get_oozie(self.user)
+      workflow = oozie_api.get_bundle(jobid=appid)
+      return {
+        'xml': workflow.definition,
+      }
+    elif app_property == 'properties':
+      oozie_api = get_oozie(self.user)
+      workflow = oozie_api.get_bundle(jobid=appid)
+      return {
+        'properties': workflow.conf_dict,
+      }
+
+  def _api_status(self, status):
+    if status in ['PREP', 'RUNNING', 'RUNNINGWITHERROR']:
+      return 'RUNNING'
+    elif status in ['PREPSUSPENDED', 'SUSPENDED', 'SUSPENDEDWITHERROR', 'PREPPAUSED', 'PAUSED', 'PAUSEDWITHERROR']:
+      return 'PAUSED'
+    elif status == 'SUCCEEDED':
+      return 'SUCCEEDED'
+    else:
+      return 'FINISHED' # DONEWITHERROR, KILLED, FAILED
+

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

@@ -641,7 +641,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
   ${ _('Progress') } <span data-bind="text: progress"></span>
   ${ _('Duration') } <span data-bind="text: duration"></span>
   ${ _('Submitted') } <span data-bind="text: submitted"></span>
-  
+
   <div data-bind="template: { name: 'job-actions' }"></div>
 </script>
 
@@ -822,7 +822,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
 
     <div class="tab-pane" id="schedule-page-tasks">
       <div data-bind="template: { name: 'job-actions' }"></div>
-      
+
       ${_('Filter')} <input type="text" class="input-xlarge search-query"  placeholder="${_('Filter by id, name, user...')}" />
       <div class="btn-group">
         <select size="3" multiple="true"></select>
@@ -830,7 +830,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
         <a class="btn btn-status btn-warning" data-value="running">${ _('Running') }</a>
         <a class="btn btn-status btn-danger disable-feedback" data-value="failed">${ _('Failed') }</a>
       </div>
-    
+
       <table id="jobsTable" class="datatables table table-condensed">
         <thead>
         <tr>
@@ -885,6 +885,88 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
   ${ _('Progress') } <span data-bind="text: progress"></span>
   ${ _('Duration') } <span data-bind="text: duration"></span>
   ${ _('Submitted') } <span data-bind="text: submitted"></span>
+
+
+  <br><br>
+  Variables, Workspace<br>
+  Duration 8s<br>
+  nextTime<span data-bind="text: properties['nextTime']"></span><br>
+  total_actions<span data-bind="text: properties['total_actions']"></span><br>
+  endTime<span data-bind="text: properties['endTime']"></span><br>
+  <br><br>
+
+  <div class="progress-job progress active pull-left" style="background-color: #FFF; width: 100%" data-bind="css: {'progress-warning': progress() < 100, 'progress-success': progress() === 100}">
+    <div class="bar" data-bind="style: {'width': progress() + '%'}"></div>
+  </div>
+
+  <div data-bind="template: { name: 'job-actions' }"></div>
+
+  <br>
+
+  <ul class="nav nav-tabs">
+    <li class="active"><a href="#bundle-page-coordinators" data-toggle="tab">${ _('Tasks') }</a></li>
+    <li><a href="#schedule-page-logs" data-toggle="tab">${ _('Logs') }</a></li>
+    <li><a href="#schedule-page-metadata"  data-bind="click: function(){ fetchProfile('properties'); $('a[href=\'#schedule-page-metadata\']').tab('show'); }">${ _('Properties') }</a></li>
+    <li><a href="#schedule-page-xml" data-bind="click: function(){ fetchProfile('xml'); $('a[href=\'#schedule-page-xml\']').tab('show'); }">${ _('XML') }</a></li>
+  </ul>
+
+  <div class="tab-content">
+    <div class="tab-pane active" id="bundle-page-coordinators">
+      <div data-bind="template: { name: 'job-actions' }"></div>
+
+      ${_('Filter')} <input type="text" class="input-xlarge search-query"  placeholder="${_('Filter by id, name, user...')}" />
+      <div class="btn-group">
+        <select size="3" multiple="true"></select>
+        <a class="btn btn-status btn-success" data-value="completed">${ _('Succeeded') }</a>
+        <a class="btn btn-status btn-warning" data-value="running">${ _('Running') }</a>
+        <a class="btn btn-status btn-danger disable-feedback" data-value="failed">${ _('Failed') }</a>
+      </div>
+
+      <table id="jobsTable" class="datatables table table-condensed">
+        <thead>
+        <tr>
+          <th width="1%"><div class="select-all hueCheckbox fa"></div></th>
+          <th>${_('Status')}</th>
+          <th>${_('Title')}</th>
+          <th>${_('type')}</th>
+          <th>${_('errorMessage')}</th>
+          <th>${_('missingDependencies')}</th>
+          <th>${_('number')}</th>
+          <th>${_('errorCode')}</th>
+          <th>${_('externalId')}</th>
+          <th>${_('id')}</th>
+          <th>${_('lastModifiedTime')}</th>
+        </tr>
+        </thead>
+        <tbody data-bind="foreach: properties['actions']">
+          <tr data-bind="click: function() {  if (externalId()) { $root.job().id(externalId()); $root.job().fetchJob();} }">
+            <td><div class="hueCheckbox fa"></div></td>
+            <td data-bind="text: status"></td>
+            <td data-bind="text: title"></td>
+            <td data-bind="text: type"></td>
+            <td data-bind="text: errorMessage"></td>
+            <td data-bind="text: missingDependencies"></td>
+            <td data-bind="text: number"></td>
+            <td data-bind="text: errorCode"></td>
+            <td data-bind="text: externalId"></td>
+            <td data-bind="text: id"></td>
+            <td data-bind="text: lastModifiedTime"></td>
+          </tr>
+        </tbody>
+      </table>    </div>
+
+    <div class="tab-pane" id="schedule-page-logs">
+      <pre data-bind="html: logs"></pre>
+    </div>
+
+    <div class="tab-pane" id="schedule-page-metadata">
+      <pre data-bind="text: ko.toJSON(properties['properties'], null, 2)"></pre>
+    </div>
+
+    <div class="tab-pane" id="schedule-page-xml">
+      <div data-bind="readonlyXML: properties['xml'], path: 'xml'"></div>
+    </div>
+  </div>
 </script>