소스 검색

HUE-1176 [jb] Adding SLAs page

Romain Rigaux 8 년 전
부모
커밋
4f8476844d

+ 3 - 1
apps/jobbrowser/src/jobbrowser/apis/base_api.py

@@ -31,7 +31,7 @@ def get_api(user, interface):
   from jobbrowser.apis.schedule_api import ScheduleApi
   from jobbrowser.apis.workflow_api import WorkflowApi
 
-  if interface == 'apps':
+  if interface == 'jobs':
     return JobApi(user)
   elif interface == 'workflows':
     return WorkflowApi(user)
@@ -39,6 +39,8 @@ def get_api(user, interface):
     return ScheduleApi(user)
   elif interface == 'bundles':
     return BundleApi(user)
+  elif interface == 'slas':
+    return BundleApi(user)  
   else:
     raise PopupException(_('Interface %s is unknown') % interface)
 

+ 90 - 0
apps/jobbrowser/src/jobbrowser/apis/slas_api.py

@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import re
+
+from django.utils.translation import ugettext as _
+
+from liboozie.oozie_api import get_oozie
+
+from jobbrowser.apis.base_api import Api
+
+
+LOG = logging.getLogger(__name__)
+
+
+try:
+  from oozie.views.dashboard import massaged_sla_for_json
+except Exception, e:
+  LOG.exception('Some application are not enabled: %s' % e)
+
+
+class SlaApi(Api):
+
+  def apps(self, filters):
+    oozie_api = get_oozie(self.user,  api_version="v2")
+
+    params = {}
+
+    job_name = filters.POST.get('job_name')
+ 
+    if re.match('.*-oozie-oozi-[WCB]', job_name):
+      params['id'] = job_name
+      params['parent_id'] = job_name
+    else:
+      params['app_name'] = job_name
+ 
+#     if 'useDates' in request.POST:
+#       if request.POST.get('start'):
+#         params['nominal_start'] = request.POST.get('start')
+#       if request.POST.get('end'):
+#         params['nominal_end'] = request.POST.get('end')
+
+    oozie_slas = oozie_api.get_oozie_slas(**params)
+
+
+
+    massaged_slas = []
+    for sla in oozie_slas:
+      massaged_slas.append(massaged_sla_for_json(sla, request))
+
+    return massaged_slas
+
+#   configuration = oozie_api.get_configuration()
+#   show_slas_hint = 'org.apache.oozie.sla.service.SLAService' not in configuration.get('oozie.services.ext', '')
+
+    return [{
+        'id': app.id,
+        'name': app.appName,
+        'status': app.status,
+        'type': 'bundle',
+        'user': app.user,
+        'progress': 100,
+        'duration': 10 * 3600,
+        'submitted': 10 * 3600
+    } for app in wf_list.jobs]
+
+  def app(self, appid):
+    oozie_api = get_oozie(self.user)
+    bundle = oozie_api.get_bundle(jobid=appid)
+
+    return {
+        'id': bundle.bundleJobId,
+        'name': bundle.bundleJobName,
+        'status': bundle.status,
+    }

+ 120 - 5
apps/jobbrowser/src/jobbrowser/templates/job_browser.mako

@@ -81,11 +81,11 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
                 ${ _('Job Browser') }
               </a>
             </li>
-            <li data-bind="css: {'active': interface() === 'apps'}"><a class="pointer" data-bind="click: function(){ interface('apps'); resetBreadcrumbs(); }">${ _('Jobs') }</a></li>
+            <li data-bind="css: {'active': interface() === 'jobs'}"><a class="pointer" data-bind="click: function(){ interface('jobs'); resetBreadcrumbs(); }">${ _('Jobs') }</a></li>
             <li data-bind="css: {'active': interface() === 'workflows'}"><a class="pointer" data-bind="click: function(){ interface('workflows'); resetBreadcrumbs(); }">${ _('Workflows') }</a></li>
             <li data-bind="css: {'active': interface() === 'schedules'}"><a class="pointer" data-bind="click: function(){ interface('schedules'); resetBreadcrumbs(); }">${ _('Schedules') }</a></li>
             <li data-bind="css: {'active': interface() === 'bundles'}"><a class="pointer" data-bind="click: function(){ interface('bundles'); resetBreadcrumbs(); }">${ _('Bundles') }</a></li>
-            <li data-bind="css: {'active': interface() === 'slas'}"><a class="pointer" data-bind="click: function(){ interface('apps'); resetBreadcrumbs(); }">${ _('SLAs') }</a></li>
+            <li data-bind="css: {'active': interface() === 'slas'}"><a class="pointer" data-bind="click: function(){ interface('slas'); resetBreadcrumbs(); }">${ _('SLAs') }</a></li>
             </ul>
           % if not hiveserver2_impersonation_enabled:
             <div class="pull-right alert alert-warning" style="margin-top: 4px">${ _("Hive jobs are running as the 'hive' user") }</div>
@@ -180,7 +180,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
 
           <!-- ko if: $root.job() -->
           <!-- ko with: $root.job() -->
-            <!-- ko if: mainType() == 'apps' -->
+            <!-- ko if: mainType() == 'jobs' -->
               <div data-bind="template: { name: 'job-page' }"></div>
             <!-- /ko -->
 
@@ -201,6 +201,10 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
             <!-- ko if: mainType() == 'bundles' -->
               <div data-bind="template: { name: 'bundle-page' }"></div>
             <!-- /ko -->
+            
+            <!-- ko if: mainType() == 'sla' -->
+              <div data-bind="template: { name: 'sla-page' }"></div>
+            <!-- /ko -->
           <!-- /ko -->
           <!-- /ko -->
 
@@ -799,6 +803,117 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
 </script>
 
 
+<script type="text/html" id="slas-page">
+<div class="container-fluid">
+  <div class="card card-small">
+
+      <div class="card-body">
+        <p>
+          <div class="search-something center empty-wrapper">
+            <a href="http://gethue.com/hadoop-tutorial-monitor-and-get-alerts-for-your-workflows-with-the-oozie-slas/" target="_blank" title="${ _('Click to learn more') }">
+              <i class="fa fa-exclamation"></i>
+            </a>
+            <h1>${_('Oozie is not setup to create SLAs')}</h1>
+            <br/>
+          </div>
+        </p>
+      </div>
+
+      <h1 class="card-heading simple">
+      <div class="pull-left" style="margin-right: 20px;margin-top: 2px">${_('Search')}</div>
+      <form class="form-inline" id="searchForm" method="GET" action="." style="margin-bottom: 4px">
+        <label>
+          ${_('Name or Id')}
+          <input type="text" name="job_name" class="searchFilter input-xlarge search-query" placeholder="${_('Job Name or Id (required)')}">
+        </label>
+        <span style="padding-left:25px">
+          <label class="label-with-margin">
+            ${ _('Start') }
+            <input type="text" name="start_0" class="input-small date" value="" placeholder="${_('Date in GMT')}"  data-bind="enable: useDates">
+            <input type="text" name="start_1" class="input-small time" value="" data-bind="enable: useDates">
+          </label>
+          <label>
+            ${ _('End') }
+            <input type="text" name="end_0" class="input-small date" value="" placeholder="${_('Date in GMT')}" data-bind="enable: useDates">
+            <input type="text" name="end_1" class="input-small time" value="" data-bind="enable: useDates">
+          </label>
+        </span>
+        <label class="checkbox label-with-margin">
+          <input type="checkbox" name="useDates" class="searchFilter" data-bind="checked: useDates, click: performSearch()">
+          ${ _('Date filter') }
+        </label>
+      </form>
+      </h1>
+      <div class="card-body">
+        <p>
+          <div class="loader hide" style="text-align: center;margin-top: 20px">
+            <!--[if lte IE 9]>
+              <img src="${ static('desktop/art/spinner-big.gif') }" />
+            <![endif]-->
+            <!--[if !IE]> -->
+              <i class="fa fa-spinner fa-spin" style="font-size: 60px; color: #DDD"></i>
+            <!-- <![endif]-->
+          </div>
+
+          <div class="search-something center empty-wrapper">
+            <i class="fa fa-search"></i>
+            <h1>${_('Use the form above to search for SLAs.')}</h1>
+            <br/>
+          </div>
+
+          <div class="no-results center empty-wrapper hide">
+            <h1>${_('The server returned no results.')}</h1>
+            <br/>
+          </div>
+
+         <div class="results hide">
+           <ul class="nav nav-tabs">
+             <li class="active"><a href="#slaListTab" data-toggle="tab">${ _('List') }</a></li>
+             <li><a href="#chartTab" data-toggle="tab">${ _('Chart') }</a></li>
+           </ul>
+
+           <div class="tab-content" style="padding-bottom:200px">
+             <div class="tab-pane active" id="slaListTab">
+               <div class="tabbable">
+                 <div class="tab-content">
+                   <table id="slaTable" class="table table-striped table-condensed">
+                     <thead>
+                       <th>${_('Status')}</th>
+                       <th>${_('Name')}</th>
+                       <th>${_('Type')}</th>
+                       <th>${_('ID')}</th>
+                       <th>${_('Nominal Time')}</th>
+                       <th>${_('Expected Start')}</th>
+                       <th>${_('Actual Start')}</th>
+                       <th>${_('Expected End')}</th>
+                       <th>${_('Actual End')}</th>
+                       <th>${_('Expected Duration')}</th>
+                       <th>${_('Actual Duration')}</th>
+                       <th>${_('Job Status')}</th>
+                       <th>${_('User')}</th>
+                       <th>${_('Last Modified')}</th>
+                     </thead>
+                     <tbody>
+                     </tbody>
+                   </table>
+                 </div>
+               </div>
+             </div>
+
+             <div class="tab-pane" id="chartTab" style="padding-left: 20px">
+               <div id="yAxisLabel" class="hide">${_('Time since Nominal Time in min')}</div>
+               <div id="slaChart"></div>
+             </div>
+            </div>
+          </div>
+        </p>
+      </div>
+
+  </div>
+</div>
+</script>
+
+
 <script type="text/javascript">
 
   (function () {
@@ -994,7 +1109,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
       self.username = ko.observable('${ user.username }');
       self.textFilter = ko.observable('${ user.username }').extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 500 } });
 
-      self.filters = [ {'text': self.textFilter} ];
+      self.filters = [{'text': self.textFilter}];
 
       self.textFilter.subscribe(function(value) {
         self.fetchJobs();
@@ -1055,7 +1170,7 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
       self.jobs = new Jobs(self, options);
       self.job = ko.observable();
 
-      self.interface = ko.observable('apps');
+      self.interface = ko.observable('jobs');
       self.interface.subscribe(function (val) {
         hueUtils.changeURL('#!' + val);
         self.jobs.fetchJobs();