Quellcode durchsuchen

HUE-1176 [jb] Adding Batches and Schedules based on Oozie

Romain Rigaux vor 9 Jahren
Ursprung
Commit
7e2d25f1df

+ 3 - 6
apps/jobbrowser/src/jobbrowser/api2.py

@@ -22,15 +22,12 @@ from django.utils.translation import ugettext as _
 from desktop.lib.i18n import smart_unicode
 from desktop.lib.i18n import smart_unicode
 from desktop.lib.django_util import JsonResponse
 from desktop.lib.django_util import JsonResponse
 
 
-from jobbrowser.job_api import YarnApi
+from jobbrowser.job_api import get_api
 
 
 
 
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 
 
-def get_api(user):
-  pass
-
 
 
 def api_error_handler(func):
 def api_error_handler(func):
   def decorator(*args, **kwargs):
   def decorator(*args, **kwargs):
@@ -53,9 +50,9 @@ def api_error_handler(func):
 def jobs(request):
 def jobs(request):
   response = {'status': -1}
   response = {'status': -1}
 
 
-  search = json.loads(request.POST.get('search', '{}'))
+  interface = json.loads(request.POST.get('interface'))
 
 
-  response['apps'] = YarnApi(request.user).apps()
+  response['apps'] = get_api(request.user, interface).apps()
   response['status'] = 0
   response['status'] = 0
 
 
   return JsonResponse(response)
   return JsonResponse(response)

+ 30 - 5
apps/jobbrowser/src/jobbrowser/job_api.py

@@ -18,16 +18,28 @@
 import logging
 import logging
 
 
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
+
+# TODO Protect in case modules are not there
 from jobbrowser.api import YarnApi as NativeYarnApi
 from jobbrowser.api import YarnApi as NativeYarnApi
+from liboozie.oozie_api import get_oozie
+from oozie.conf import OOZIE_JOBS_COUNT
 
 
+from desktop.lib.exceptions_renderable import PopupException
 
 
-LOG = logging.getLogger(__name__)
 
 
+LOG = logging.getLogger(__name__)
 
 
 
 
-def get_api(user):
-  pass
 
 
+def get_api(user, interface):
+  if interface == 'batches':
+    return BatchApi(user)
+  elif interface == 'schedules':
+    return ScheduleApi(user)
+  elif interface == 'jobs':
+    return YarnApi(user)
+  else:
+    raise PopupException(_('Interface %s is unknown') % interface)
 
 
 
 
 class Api():
 class Api():
@@ -80,12 +92,25 @@ class ImpalaApi(Api):
 # Batch
 # Batch
 
 
 class BatchApi(Api):
 class BatchApi(Api):
-  pass
+
+  def apps(self):
+    oozie_api = get_oozie(self.user)
+    kwargs = {'cnt': OOZIE_JOBS_COUNT.get(), 'filters': []}
+    wf_list = oozie_api.get_workflows(**kwargs)
+
+    return [{'id': app.id, 'status': app.status} for app in wf_list.jobs]
+
 
 
 # Schedule
 # Schedule
 
 
 class ScheduleApi(Api):
 class ScheduleApi(Api):
-  pass
+
+  def apps(self):
+    oozie_api = get_oozie(self.user)
+    kwargs = {'cnt': OOZIE_JOBS_COUNT.get(), 'filters': []}
+    wf_list = oozie_api.get_coordinators(**kwargs)
+
+    return [{'id': app.id, 'status': app.status} for app in wf_list.jobs]
 
 
 
 
 # History
 # History

+ 41 - 14
apps/jobbrowser/src/jobbrowser/templates/apps.mako

@@ -51,10 +51,18 @@ ${ require.config() }
   ${_('Username')} <input id="userFilter" type="text" class="input-medium search-query" placeholder="${_('Search for username')}" value="${ user_filter or '' }">
   ${_('Username')} <input id="userFilter" type="text" class="input-medium search-query" placeholder="${_('Search for username')}" value="${ user_filter or '' }">
   &nbsp;&nbsp;${_('Text')} <input id="textFilter" type="text" class="input-xlarge search-query" placeholder="${_('Search for id, name, status...')}" value="${ text_filter or '' }">
   &nbsp;&nbsp;${_('Text')} <input id="textFilter" type="text" class="input-xlarge search-query" placeholder="${_('Search for id, name, status...')}" value="${ text_filter or '' }">
 
 
+  <span>
+    <span><input class="btn btn-status" type="radio" name="interface" value="jobs" data-bind="checked: jobs.interface" />${ _('Jobs') }</span>
+    <span><input class="btn btn-status" type="radio" name="interface" value="batches" data-bind="checked: jobs.interface" />${ _('Batches') }</span>
+    <span><input class="btn btn-status" type="radio" name="interface" value="schedules" data-bind="checked: jobs.interface" />${ _('Schedules') }</span>
+  </span>
+
   <span class="btn-group">
   <span class="btn-group">
-    <a class="btn btn-status" data-value="completed">${ _('Jobs') }</a>
-    <a class="btn btn-status" data-value="running">${ _('Batches') }</a>
-    <a class="btn btn-status" data-value="killed">${ _('Schedules') }</a>
+    <span class="btn-group">
+      <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>
+    </span>
   </span>
   </span>
 
 
   <div class="card card-small">
   <div class="card card-small">
@@ -74,7 +82,7 @@ ${ require.config() }
       <th>${_('Submitted')}</th>
       <th>${_('Submitted')}</th>
     </tr>
     </tr>
     </thead>
     </thead>
-    <tbody data-bind="foreach: apps">
+    <tbody data-bind="foreach: jobs.apps">
       <tr>
       <tr>
         <td></td>
         <td></td>
         <td data-bind="text: id"></td>
         <td data-bind="text: id"></td>
@@ -119,27 +127,46 @@ ${ require.config() }
       self.submitted = ko.observable(typeof job.submitted != "undefined" && job.submitted != null ? job.submitted : null);
       self.submitted = ko.observable(typeof job.submitted != "undefined" && job.submitted != null ? job.submitted : null);
     };
     };
 
 
-    var JobBrowserViewModel = function (options) {
+    var Jobs = function (vm, options) {
       var self = this;
       var self = this;
 
 
       self.apps = ko.observableArray();
       self.apps = ko.observableArray();
       self.loadingApps = ko.observable(false);
       self.loadingApps = ko.observable(false);
 
 
-      self.fetchJobs = function (callback) {
+      self.username = ko.observable('${ user.username }');
+
+      self.interface = ko.observable('jobs');
+      self.interface.subscribe(function(val) {
+        self.fetchJobs();
+      });
+
+      self.fetchJobs = function () {
         self.loadingApps(true);
         self.loadingApps(true);
-        $.get("/jobbrowser/api/jobs", {
+        $.post("/jobbrowser/api/jobs", {
+          username: ko.mapping.toJSON(self.username),
+          interface: ko.mapping.toJSON(self.interface)
         }, function(data) {
         }, function(data) {
-          var apps = [];
-          if (data && data.apps){
-            data.apps.forEach(function(job){
-              apps.push(new Job(self, job));
-            });
+          if (data.status == 0) {
+            var apps = [];
+            if (data && data.apps) {
+              data.apps.forEach(function(job){
+                apps.push(new Job(self, job));
+              });
+            }
+            self.apps(apps);
+          } else {
+            $(document).trigger("error", data.message);
           }
           }
-          self.apps(apps);
         }).always(function(){
         }).always(function(){
           self.loadingApps(false);
           self.loadingApps(false);
         });
         });
       };
       };
+    }
+
+    var JobBrowserViewModel = function (options) {
+      var self = this;
+
+      self.jobs = new Jobs(self, options);
     };
     };
 
 
     var viewModel;
     var viewModel;
@@ -154,7 +181,7 @@ ${ require.config() }
       viewModel = new JobBrowserViewModel(options);
       viewModel = new JobBrowserViewModel(options);
       ko.applyBindings(viewModel);
       ko.applyBindings(viewModel);
 
 
-      viewModel.fetchJobs();
+      viewModel.jobs.fetchJobs();
     });
     });
   });
   });
 </script>
 </script>