Преглед изворни кода

HUE-2292 [oozie] Paginate coordinator actions

krish пре 10 година
родитељ
комит
3a6bfa0

+ 59 - 14
apps/oozie/src/oozie/templates/dashboard/list_oozie_coordinator.mako

@@ -200,15 +200,6 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                 <tbody data-bind="template: { name: 'calendarTemplate', foreach: filteredActions}" >
                 </tbody>
                 <tfoot>
-                  <tr>
-                    <td data-bind="visible: !isLoading() && paginate()" colspan="10">
-                      <br/>
-                      <div class="alert">
-                        ${ _('There are older actions to be shown:') }
-                        <a class="btn" href="${ oozie_coordinator.get_absolute_url() }?show_all_actions=true">${ _('Expand') }</a>
-                      </div>
-                    </td>
-                  </tr>
                   <tr data-bind="visible: isLoading()">
                     <td colspan="2" class="left">
                       <img src="${ static('desktop/art/spinner.gif') }" />
@@ -223,6 +214,13 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                   </tr>
                 </tfoot>
               </table>
+
+              <div class="pagination dataTables_paginate">
+                <ul>
+                  <li class="prev"><a href="javascript:void(0)" class="btn-actions-pagination" data-value="prev" data-table="calendar"><i class="fa fa-long-arrow-left"></i> ${ _('Previous') }</a></li>
+                  <li class="next"><a href="javascript:void(0)" class="btn-actions-pagination" data-value="next" data-table="calendar">${ _('Next') } <i class="fa fa-long-arrow-right"></i></a></li>
+                </ul>
+              </div>
             </div>
 
             <script id="calendarTemplate" type="text/html">
@@ -278,6 +276,13 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                 </tr>
                 </tfoot>
               </table>
+
+              <div class="pagination dataTables_paginate">
+                <ul>
+                  <li class="prev"><a href="javascript:void(0)" class="btn-actions-pagination" data-value="prev" data-table="actions"><i class="fa fa-long-arrow-left"></i> ${ _('Previous') }</a></li>
+                  <li class="next"><a href="javascript:void(0)" class="btn-actions-pagination" data-value="next" data-table="actions">${ _('Next') } <i class="fa fa-long-arrow-right"></i></a></li>
+                </ul>
+              </div>
             </div>
 
             <script id="actionTemplate" type="text/html">
@@ -445,10 +450,6 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
       return new Action(action);
     });
 
-    this.paginate = ko.computed(function(){
-      return self.actions().length >= ${ MAX_COORD_ACTIONS } && ${ "false" if show_all_actions else 'true' | n,unicode };
-    });
-
     this.allSelected = ko.observable(false);
 
     this.filter = ko.observableArray([]);
@@ -592,6 +593,9 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
     TOOLTIP_ADDON: "${_('click for the SLA dashboard')}"
   }
   var slaTable;
+  var PAGE_SIZE = 50;
+  var actionTableOffset = 1;
+
 
   $(document).ready(function(){
     $("a[data-row-selector='true']").jHueRowSelector();
@@ -645,6 +649,19 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
       % endif
     });
 
+    $("a.btn-actions-pagination").on("click", function () {
+      if (!$(this).parent().hasClass("disabled")) {
+        var _additionalOffset = 0;
+        if ($(this).data("value") == "prev") {
+          actionTableOffset -= PAGE_SIZE;
+        }
+        else {
+          actionTableOffset += PAGE_SIZE;
+        }
+        refreshView();
+      }
+    });
+
     $(".confirmationModal").click(function(){
       var _this = $(this);
       $("#confirmation .message").text(_this.attr("data-confirmation-message"));
@@ -732,8 +749,32 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
       });
     }
 
+    function refreshActionPaginationButtons(totalJobs) {
+      var prevBtnActions = $("a.btn-actions-pagination[data-table='actions'][data-value='prev']");
+      var nextBtnActions = $("a.btn-actions-pagination[data-table='actions'][data-value='next']");
+      var prevBtnCalendar = $("a.btn-actions-pagination[data-table='calendar'][data-value='prev']");
+      var nextBtnCalendar = $("a.btn-actions-pagination[data-table='calendar'][data-value='next']");
+
+      if (actionTableOffset == 1 || !totalJobs) {
+        prevBtnActions.parent().addClass("disabled");
+        prevBtnCalendar.parent().addClass("disabled");
+      }
+      else {
+        prevBtnActions.parent().removeClass("disabled");
+        prevBtnCalendar.parent().removeClass("disabled");
+      }
+      if (totalJobs < (actionTableOffset + PAGE_SIZE) || !totalJobs) {
+        nextBtnActions.parent().addClass("disabled");
+        nextBtnCalendar.parent().addClass("disabled");
+      }
+      else if (totalJobs >= actionTableOffset + PAGE_SIZE) {
+        nextBtnActions.parent().removeClass("disabled");
+        nextBtnCalendar.parent().removeClass("disabled");
+      }
+    }
+
     function refreshView() {
-      $.getJSON("${ oozie_coordinator.get_absolute_url(oozie_bundle=oozie_bundle, format='json') }" + "${ "&show_all_actions=true" if show_all_actions else '' | n,unicode }", function (data) {
+      $.getJSON("${ oozie_coordinator.get_absolute_url(oozie_bundle=oozie_bundle, format='json') }" + "&offset=" + actionTableOffset, function (data) {
         viewModel.isLoading(false);
         if (data != null && data.actions){
           viewModel.actions(ko.utils.arrayMap(data.actions, function (action) {
@@ -741,6 +782,10 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
           }));
         }
 
+        // Refresh actions pagination
+        totalActions = data.total_actions;
+        refreshActionPaginationButtons(totalActions);
+
         $("#status span").attr("class", "label").addClass(getStatusClass(data.status)).text(data.status);
 
         $.jHueTitleUpdater.set(data.progress + "%");

+ 17 - 2
apps/oozie/src/oozie/tests.py

@@ -67,11 +67,19 @@ class MockOozieApi:
   WORKFLOW_IDS = [wf['id'] for wf in JSON_WORKFLOW_LIST]
   WORKFLOW_DICT = dict([(wf['id'], wf) for wf in JSON_WORKFLOW_LIST])
 
+  JSON_ACTION_COORDINATOR_LIST = [
+      {u'status': u'SUCCEEDED', u'toString': u'WorkflowAction name[00000013-120706144403213-oozie-oozi-C@1] status[SUCCEEDED]', u'runConf': None, u'errorMessage': None, u'missingDependencies': u'', u'coordJobId': u'00000013-120706144403213-oozie-oozi-C', u'errorCode': None, u'actionNumber': 1, u'consoleUrl': None, u'nominalTime': u'Mon, 31 Dec 2012 16:00:00 PST', u'externalStatus': u'', u'createdConf': None, u'createdTime': u'Fri, 25 Jan 2013 10:53:39 PST', u'externalId': u'0000035-130124125317829-oozie-oozi-W', u'lastModifiedTime': u'Fri, 25 Jan 2013 10:53:51 PST', u'type': None, u'id': u'00000013-120706144403213-oozie-oozi-C@1', u'trackerUri': None},
+      {u'status': u'SUCCEEDED', u'toString': u'WorkflowAction name[00000013-120706144403213-oozie-oozi-C@2] status[SUCCEEDED]', u'runConf': None, u'errorMessage': None, u'missingDependencies': u'', u'coordJobId': u'00000013-120706144403213-oozie-oozi-C', u'errorCode': None, u'actionNumber': 2, u'consoleUrl': None, u'nominalTime': u'Tue, 01 Jan 2013 16:00:00 PST', u'externalStatus': u'', u'createdConf': None, u'createdTime': u'Fri, 25 Jan 2013 10:56:27 PST', u'externalId': u'0000038-130124125317829-oozie-oozi-W', u'lastModifiedTime': u'Fri, 25 Jan 2013 10:56:41 PST', u'type': None, u'id': u'00000013-120706144403213-oozie-oozi-C@2', u'trackerUri': None},
+      {u'status': u'SUCCEEDED', u'toString': u'WorkflowAction name[00000013-120706144403213-oozie-oozi-C@3] status[SUCCEEDED]', u'runConf': None, u'errorMessage': None, u'missingDependencies': u'', u'coordJobId': u'00000013-120706144403213-oozie-oozi-C', u'errorCode': None, u'actionNumber': 3, u'consoleUrl': None, u'nominalTime': u'Wed, 02 Jan 2013 16:00:00 PST', u'externalStatus': u'', u'createdConf': None, u'createdTime': u'Fri, 25 Jan 2013 08:59:38 PST', u'externalId': u'0000026-130124125317829-oozie-oozi-W', u'lastModifiedTime': u'Fri, 25 Jan 2013 09:00:05 PST', u'type': None, u'id': u'00000013-120706144403213-oozie-oozi-C@3', u'trackerUri': None},
+      {u'status': u'SUCCEEDED', u'toString': u'WorkflowAction name[00000013-120706144403213-oozie-oozi-C@4] status[SUCCEEDED]', u'runConf': None, u'errorMessage': None, u'missingDependencies': u'', u'coordJobId': u'00000013-120706144403213-oozie-oozi-C', u'errorCode': None, u'actionNumber': 4, u'consoleUrl': None, u'nominalTime': u'Thu, 03 Jan 2013 16:00:00 PST', u'externalStatus': u'', u'createdConf': None, u'createdTime': u'Fri, 25 Jan 2013 10:53:39 PST', u'externalId': u'0000037-130124125317829-oozie-oozi-W', u'lastModifiedTime': u'Fri, 25 Jan 2013 10:54:17 PST', u'type': None, u'id': u'00000013-120706144403213-oozie-oozi-C@4', u'trackerUri': None}
+  ]
+
   JSON_COORDINATOR_LIST = [{u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': [], u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[0000041-120717205528122-oozie-oozi-C] status[RUNNING]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'RUNNING', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/test/demo2', u'timeUnit': u'DAY', u'coordJobId': u'0000041-120717205528122-oozie-oozi-C', u'coordJobName': u'DailyWordCount1', u'nextMaterializedTime': u'Wed, 04 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Wed, 04 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 00:00:00 GMT'},
                            {u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': [], u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[0000011-120706144403213-oozie-oozi-C] status[DONEWITHERROR]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'DONEWITHERROR', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/hue/jobsub/_romain_-design-2', u'timeUnit': u'DAY', u'coordJobId': u'0000011-120706144403213-oozie-oozi-C', u'coordJobName': u'DailyWordCount2', u'nextMaterializedTime': u'Thu, 05 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Thu, 05 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 18:54:00 GMT'},
                            {u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': [], u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[0000010-120706144403213-oozie-oozi-C] status[DONEWITHERROR]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'DONEWITHERROR', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/hue/jobsub/_romain_-design-2', u'timeUnit': u'DAY', u'coordJobId': u'0000010-120706144403213-oozie-oozi-C', u'coordJobName': u'DailyWordCount3', u'nextMaterializedTime': u'Thu, 05 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Thu, 05 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 18:54:00 GMT'},
                            {u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': [], u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[0000009-120706144403213-oozie-oozi-C] status[DONEWITHERROR]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'DONEWITHERROR', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/hue/jobsub/_romain_-design-2', u'timeUnit': u'DAY', u'coordJobId': u'0000009-120706144403213-oozie-oozi-C', u'coordJobName': u'DailyWordCount4', u'nextMaterializedTime': u'Thu, 05 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Thu, 05 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 18:54:00 GMT'},
-                           {u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': [], u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[00000012-120706144403213-oozie-oozi-C] status[DONEWITHERROR]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'DONEWITHERROR', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/hue/jobsub/_romain_-design-2', u'timeUnit': u'DAY', u'coordJobId': u'0000009-120706144403213-oozie-oozi-C', u'coordJobName': u'DåilyWordCount5', u'nextMaterializedTime': u'Thu, 05 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Thu, 05 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 18:54:00 GMT'}]
+                           {u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': [], u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[00000012-120706144403213-oozie-oozi-C] status[DONEWITHERROR]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'DONEWITHERROR', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/hue/jobsub/_romain_-design-2', u'timeUnit': u'DAY', u'coordJobId': u'0000009-120706144403213-oozie-oozi-C', u'coordJobName': u'DåilyWordCount5', u'nextMaterializedTime': u'Thu, 05 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Thu, 05 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 18:54:00 GMT'},
+                           {u'startTime': u'Sun, 01 Jul 2012 00:00:00 GMT', u'actions': JSON_ACTION_COORDINATOR_LIST, u'frequency': 1, u'concurrency': 1, u'pauseTime': None, u'group': None, u'toString': u'Coornidator application id[00000013-120706144403213-oozie-oozi-C] status[DONEWITHERROR]', u'consoleUrl': None, u'mat_throttling': 0, u'status': u'DONEWITHERROR', u'conf': None, u'user': u'test', u'timeOut': 120, u'coordJobPath': u'hdfs://localhost:8020/user/hue/jobsub/_romain_-design-2', u'timeUnit': u'DAY', u'coordJobId': u'00000013-120706144403213-oozie-oozi-C', u'coordJobName': u'DåilyWordCount6', u'nextMaterializedTime': u'Thu, 05 Jul 2012 00:00:00 GMT', u'coordExternalId': None, u'acl': None, u'lastAction': u'Thu, 05 Jul 2012 00:00:00 GMT', u'executionPolicy': u'FIFO', u'timeZone': u'America/Los_Angeles', u'endTime': u'Wed, 04 Jul 2012 18:54:00 GMT'}]
   COORDINATOR_IDS = [coord['coordJobId'] for coord in JSON_COORDINATOR_LIST]
   COORDINATOR_DICT = dict([(coord['coordJobId'], coord) for coord in JSON_COORDINATOR_LIST])
 
@@ -140,7 +148,7 @@ class MockOozieApi:
     else:
       return OozieWorkflow(self, {'id': job_id, 'actions': []})
 
-  def get_coordinator(self, job_id):
+  def get_coordinator(self, job_id, action_offset=1):
     if job_id in MockOozieApi.COORDINATOR_DICT:
       return OozieCoordinator(self, MockOozieApi.COORDINATOR_DICT[job_id])
     else:
@@ -3350,6 +3358,13 @@ class TestDashboard(OozieMockBase):
     assert_true(u'Coordinator DåilyWordCount5' in response.content.decode('utf-8', 'replace'), response.content.decode('utf-8', 'replace'))
     assert_true('Workflow' in response.content, response.content)
 
+    # Test action list
+    response = self.c.get(reverse('oozie:list_oozie_coordinator', args=[MockOozieApi.COORDINATOR_IDS[5]]) + "?format=json&offset=1")
+    assert_true('00000013-120706144403213-oozie-oozi-C@1' in response.content, response.content)
+    assert_true('00000013-120706144403213-oozie-oozi-C@2' in response.content, response.content)
+    assert_true('00000013-120706144403213-oozie-oozi-C@3' in response.content, response.content)
+    assert_true('00000013-120706144403213-oozie-oozi-C@4' in response.content, response.content)
+
 
   def test_list_bundle(self):
     response = self.c.get(reverse('oozie:list_oozie_bundle', args=[MockOozieApi.BUNDLE_IDS[0]]))

+ 8 - 11
apps/oozie/src/oozie/views/dashboard.py

@@ -65,7 +65,6 @@ def get_workflow():
 
 
 LOG = logging.getLogger(__name__)
-MAX_COORD_ACTIONS = 250
 
 
 """
@@ -384,7 +383,8 @@ def list_oozie_workflow(request, job_id):
 
 @show_oozie_error
 def list_oozie_coordinator(request, job_id):
-  oozie_coordinator = check_job_access_permission(request, job_id)
+  actions_offset = request.GET.get('offset', 1)
+  oozie_coordinator = check_job_access_permission(request, job_id, actions_offset)
 
   # Cross reference the submission history (if any)
   coordinator = get_history().get_coordinator_from_config(oozie_coordinator.conf_dict)
@@ -400,12 +400,8 @@ def list_oozie_coordinator(request, job_id):
     except:
       LOG.exception("Ignoring error getting oozie bundle for job_id=%s", job_id)
 
-  show_all_actions = request.GET.get('show_all_actions') == 'true'
-
   if request.GET.get('format') == 'json':
     actions = massaged_coordinator_actions_for_json(oozie_coordinator, oozie_bundle)
-    if not show_all_actions:
-      actions = actions[:MAX_COORD_ACTIONS]
 
     return_obj = {
       'id': oozie_coordinator.id,
@@ -414,7 +410,7 @@ def list_oozie_coordinator(request, job_id):
       'nextTime': format_time(oozie_coordinator.nextMaterializedTime),
       'endTime': format_time(oozie_coordinator.endTime),
       'actions': actions,
-      'show_all_actions': show_all_actions
+      'total_actions': oozie_coordinator.total
     }
     return JsonResponse(return_obj, encoder=JSONEncoderForHTML)
 
@@ -436,8 +432,6 @@ def list_oozie_coordinator(request, job_id):
     'coordinator': coordinator,
     'oozie_bundle': oozie_bundle,
     'has_job_edition_permission': has_job_edition_permission,
-    'show_all_actions': show_all_actions,
-    'MAX_COORD_ACTIONS': MAX_COORD_ACTIONS,
     'enable_cron_scheduling': enable_cron_scheduling,
     'update_endtime_form': update_endtime_form,
   })
@@ -984,7 +978,7 @@ def massaged_oozie_jobs_for_json(oozie_jobs, user, just_sla=False):
   return { 'jobs': jobs }
 
 
-def check_job_access_permission(request, job_id):
+def check_job_access_permission(request, job_id, actions_offset=1):
   """
   Decorator ensuring that the user has access to the job submitted to Oozie.
 
@@ -1003,7 +997,10 @@ def check_job_access_permission(request, job_id):
       get_job = oozie_api.get_bundle
 
     try:
-      oozie_job = get_job(job_id)
+      if job_id.endswith('C'):
+        oozie_job = get_job(job_id, actions_offset)
+      else:
+        oozie_job = get_job(job_id)
     except RestException, ex:
       msg = _("Error accessing Oozie job %s.") % (job_id,)
       LOG.exception(msg)

+ 4 - 2
desktop/libs/liboozie/src/liboozie/oozie_api.py

@@ -34,6 +34,7 @@ DEFAULT_USER = DEFAULT_USER.get()
 API_VERSION = 'v1' # Overridden to v2 for SLA
 
 _XML_CONTENT_TYPE = 'application/xml;charset=UTF-8'
+ACTIONS_PER_PAGE = 50
 
 
 def get_oozie(user, api_version=API_VERSION):
@@ -142,9 +143,10 @@ class OozieApi(object):
     wf = Workflow(self, resp)
     return wf
 
-  def get_coordinator(self, jobid):
+  def get_coordinator(self, jobid, actions_offset=1):
     params = self._get_params()
-    params.update({'len': -1})
+    params.update({'offset': actions_offset})
+    params.update({'len': ACTIONS_PER_PAGE})
     params.update({'order': 'desc'})
     resp = self._root.get('job/%s' % (jobid,), params)
     return Coordinator(self, resp)

+ 2 - 1
desktop/libs/liboozie/src/liboozie/types.py

@@ -486,7 +486,8 @@ class Coordinator(Job):
     'timeUnit',
     'timeZone',
     'user',
-    'bundleId'
+    'bundleId',
+    'total'
   ]
   ACTION = CoordinatorAction
   RUNNING_STATUSES = set(['PREP', 'RUNNING', 'RUNNINGWITHERROR', 'PREPSUSPENDED', 'SUSPENDED', 'SUSPENDEDWITHERROR', 'PREPPAUSED', 'PAUSED', 'PAUSEDWITHERROR'])