Bläddra i källkod

HUE-2805 [oozie] Ignore a terminated Coordinator action

krish 10 år sedan
förälder
incheckning
74f7646532

+ 39 - 15
apps/oozie/src/oozie/templates/dashboard/list_oozie_coordinator.mako

@@ -99,7 +99,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                   <div id="rerun-coord-modal" class="modal hide"></div>
                   <div id="rerun-coord-modal" class="modal hide"></div>
                   <button title="${ _('Suspend the coordinator after finishing the current running actions') }" id="suspend-btn"
                   <button title="${ _('Suspend the coordinator after finishing the current running actions') }" id="suspend-btn"
                      data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='suspend') }"
                      data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='suspend') }"
-                     data-confirmation-message="${ _('Are you sure you\'d like to suspend this job?') }"
+                     data-confirmation-header="${ _('Are you sure you\'d like to suspend this job?') }"
                      class="btn btn-small confirmationModal
                      class="btn btn-small confirmationModal
                      % if not oozie_coordinator.is_running():
                      % if not oozie_coordinator.is_running():
                        hide
                        hide
@@ -109,7 +109,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                   </button>
                   </button>
                   <button title="${ _('Resume the coordinator') }" id="resume-btn"
                   <button title="${ _('Resume the coordinator') }" id="resume-btn"
                      data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='resume') }"
                      data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='resume') }"
-                     data-confirmation-message="${ _('Are you sure you\'d like to resume this job?') }"
+                     data-confirmation-header="${ _('Are you sure you\'d like to resume this job?') }"
                      class="btn btn-small confirmationModal
                      class="btn btn-small confirmationModal
                      % if oozie_coordinator.is_running():
                      % if oozie_coordinator.is_running():
                        hide
                        hide
@@ -119,7 +119,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                   </button>
                   </button>
                   <button title="${ _('Edit End Time') }" id="edit-endtime-btn"
                   <button title="${ _('Edit End Time') }" id="edit-endtime-btn"
                      data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='change') }"
                      data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='change') }"
-                     data-confirmation-message="${ _('Update End Time') }"
+                     data-confirmation-header="${ _('Update End Time') }"
                      class="btn btn-small confirmationModal
                      class="btn btn-small confirmationModal
                      % if not oozie_coordinator.is_running():
                      % if not oozie_coordinator.is_running():
                        hide
                        hide
@@ -139,7 +139,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                     href="javascript:void(0)"
                     href="javascript:void(0)"
                     data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='kill') }"
                     data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='kill') }"
                     data-message="${ _('The coordinator was killed!') }"
                     data-message="${ _('The coordinator was killed!') }"
-                    data-confirmation-message="${ _('Are you sure you\'d like to kill this job?') }" style="margin-bottom: 5px">
+                    data-confirmation-header="${ _('Are you sure you\'d like to kill this job?') }" style="margin-bottom: 5px">
                       ${_('Kill')}
                       ${_('Kill')}
                   </button>
                   </button>
                 </li>
                 </li>
@@ -173,13 +173,24 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
                 <div class="pull-left">
                 <div class="pull-left">
                   <input type="text" data-bind="textInput: searchFilter, value: searchFilter,  valueUpdate: 'input'" class="input-xlarge search-query" placeholder="${_('Filter results')}">
                   <input type="text" data-bind="textInput: searchFilter, value: searchFilter,  valueUpdate: 'input'" class="input-xlarge search-query" placeholder="${_('Filter results')}">
                   % if has_job_edition_permission(oozie_coordinator, user):
                   % if has_job_edition_permission(oozie_coordinator, user):
-                      <button data-bind="enable: selectedActions().length > 0" class="btn btn-primary rerun-btn action-button"
-                         % if oozie_coordinator.is_running() or oozie_coordinator.status in ('KILLED', 'FAILED'):
-                           disabled="disabled"
-                         % endif
-                        data-rerun-url="${ url('oozie:rerun_oozie_coord', job_id=oozie_coordinator.id, app_path=oozie_coordinator.coordJobPath) }">
-                        <i class="fa fa-refresh"></i> ${ _('Rerun') }
-                      </button>
+                      <div id="coord-actions" data-bind="enable: selectedActions().length > 0" class="btn-group" style="vertical-align: middle">
+                        <button data-bind="enable: selectedActions().length > 0" class="btn btn-primary rerun-btn"
+                           % if oozie_coordinator.is_running() or oozie_coordinator.status in ('KILLED', 'FAILED'):
+                             disabled="disabled"
+                           % endif
+                          data-rerun-url="${ url('oozie:rerun_oozie_coord', job_id=oozie_coordinator.id, app_path=oozie_coordinator.coordJobPath) }">
+                          <i class="fa fa-refresh"></i> ${ _('Rerun') }
+                        </button>
+                        <button id="trash-btn-caret" class="btn toolbarBtn dropdown-toggle" data-toggle="dropdown"
+                          data-bind="enable: selectedActions().length > 0">
+                          <span class="caret"></span>
+                        </button>
+                        <ul class="dropdown-menu"> <li data-bind="enable: selectedActions().length > 0">
+                            <a href='#' class="ignore-btn confirmationModal" data-url="${ url('oozie:manage_oozie_jobs', job_id=oozie_coordinator.id, action='ignore') }"
+                                data-confirmation-body="${ _('Are you sure you want to ignore the action(s)?')}"
+                                data-confirmation-header="${ _('Note: You can only ignore a FAILED, KILLED or TIMEDOUT action' )}" > ${ _('Ignore') } </a></li>
+                        </ul>
+                      </div>
                   % endif
                   % endif
                 </div>
                 </div>
                 <span class="btn-group pull-right" style="margin-right: 20px">
                 <span class="btn-group pull-right" style="margin-right: 20px">
@@ -387,11 +398,14 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
 <div id="confirmation" class="modal hide">
 <div id="confirmation" class="modal hide">
   <div class="modal-header">
   <div class="modal-header">
     <a href="#" class="close" data-dismiss="modal">&times;</a>
     <a href="#" class="close" data-dismiss="modal">&times;</a>
-    <h3 class="message"></h3>
+    <h3 class="confirmation_header"></h3>
   </div>
   </div>
   <div id="update-endtime" class="span10">
   <div id="update-endtime" class="span10">
     ${ utils.render_field_no_popover(update_endtime_form['end'], show_label=False) }
     ${ utils.render_field_no_popover(update_endtime_form['end'], show_label=False) }
   </div>
   </div>
+  <div class="modal-body">
+      <p class="confirmation_body"></p>
+  </div>
   <div class="modal-footer">
   <div class="modal-footer">
     <a href="#" class="btn" data-dismiss="modal">${_('No')}</a>
     <a href="#" class="btn" data-dismiss="modal">${_('No')}</a>
     <a class="btn btn-danger disable-feedback" href="javascript:void(0);">${_('Yes')}</a>
     <a class="btn btn-danger disable-feedback" href="javascript:void(0);">${_('Yes')}</a>
@@ -576,7 +590,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
     ACTUAL_END: "${_('Actual End')}",
     ACTUAL_END: "${_('Actual End')}",
     TOOLTIP_ADDON: "${_('click for the SLA dashboard')}"
     TOOLTIP_ADDON: "${_('click for the SLA dashboard')}"
   }
   }
-  var slaTable;
+  var slaTable, refreshViewTimer;
   var PAGE_SIZE = 50;
   var PAGE_SIZE = 50;
   var actionTableOffset = 1;
   var actionTableOffset = 1;
 
 
@@ -659,7 +673,10 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
 
 
     $(".confirmationModal").click(function(){
     $(".confirmationModal").click(function(){
       var _this = $(this);
       var _this = $(this);
-      $("#confirmation .message").text(_this.attr("data-confirmation-message"));
+      $("#confirmation .confirmation_header").text(_this.attr("data-confirmation-header"));
+      if (_this.hasClass("ignore-btn")) {
+        $("#confirmation .confirmation_body").text(_this.attr("data-confirmation-body"));
+      }
       $("#confirmation").modal("show");
       $("#confirmation").modal("show");
 
 
       if (_this.attr("id") == "edit-endtime-btn") {
       if (_this.attr("id") == "edit-endtime-btn") {
@@ -668,6 +685,7 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
         $("#update-endtime").hide();
         $("#update-endtime").hide();
       }
       }
 
 
+      $("#confirmation a.btn-danger").unbind();
       $("#confirmation a.btn-danger").click(function() {
       $("#confirmation a.btn-danger").click(function() {
         _this.trigger('confirmation');
         _this.trigger('confirmation');
         $(this).attr("data-loading-text", $(this).text() + " ...");
         $(this).attr("data-loading-text", $(this).text() + " ...");
@@ -685,12 +703,16 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
         params['end_time'] = moment($("input[name='end_0']").val() + " " + $("input[name='end_1']").val(),
         params['end_time'] = moment($("input[name='end_0']").val() + " " + $("input[name='end_1']").val(),
                                         IN_DATETIME_FORMAT).format(OUT_DATETIME_FORMAT);
                                         IN_DATETIME_FORMAT).format(OUT_DATETIME_FORMAT);
       }
       }
+      else if ($(this).hasClass("ignore-btn")) {
+        params['actions'] = viewModel.selectedActions().join(' ');
+      }
 
 
       $.post($(this).attr("data-url"), params,
       $.post($(this).attr("data-url"), params,
         function(response) {
         function(response) {
           if (response['status'] != 0) {
           if (response['status'] != 0) {
             $(document).trigger("error", "${ _('Problem: ') }" + response['data']);
             $(document).trigger("error", "${ _('Problem: ') }" + response['data']);
             $("#confirmation a.btn-danger").button("reset");
             $("#confirmation a.btn-danger").button("reset");
+            $("#confirmation").modal("hide");
           } else {
           } else {
             window.location.reload();
             window.location.reload();
           }
           }
@@ -849,7 +871,9 @@ ${ layout.menubar(section='coordinators', dashboard=True) }
         if (data.status != "RUNNING" && data.status != "PREP"){
         if (data.status != "RUNNING" && data.status != "PREP"){
           return;
           return;
         }
         }
-        window.setTimeout(refreshView, 5000);
+
+        window.clearTimeout(refreshViewTimer);
+        refreshViewTimer = window.setTimeout(refreshView, 5000);
       });
       });
     }
     }
 
 

+ 19 - 1
apps/oozie/src/oozie/tests.py

@@ -160,7 +160,7 @@ class MockOozieApi:
   def get_action(self, action_id):
   def get_action(self, action_id):
     return WorkflowAction(MockOozieApi.WORKFLOW_ACTION)
     return WorkflowAction(MockOozieApi.WORKFLOW_ACTION)
 
 
-  def job_control(self, job_id, action):
+  def job_control(self, job_id, action, parameters=None):
     return 'Done'
     return 'Done'
 
 
   def get_job_definition(self, jobid):
   def get_job_definition(self, jobid):
@@ -3387,6 +3387,24 @@ class TestDashboard(OozieMockBase):
     data = json.loads(response.content)
     data = json.loads(response.content)
     assert_equal(0, data['status'])
     assert_equal(0, data['status'])
 
 
+    response = self.c.post(reverse('oozie:manage_oozie_jobs', args=[MockOozieApi.COORDINATOR_IDS[0], 'suspend']))
+    data = json.loads(response.content)
+    assert_equal(0, data['status'])
+
+    response = self.c.post(reverse('oozie:manage_oozie_jobs', args=[MockOozieApi.COORDINATOR_IDS[0], 'resume']))
+    data = json.loads(response.content)
+    assert_equal(0, data['status'])
+
+    params = {'end_time': u'12:00 AM'}
+    response = self.c.post(reverse('oozie:manage_oozie_jobs', args=[MockOozieApi.COORDINATOR_IDS[0], 'change']), params)
+    data = json.loads(response.content)
+    assert_equal(0, data['status'])
+
+    params = {'actions': '1 2 3'}
+    response = self.c.post(reverse('oozie:manage_oozie_jobs', args=[MockOozieApi.COORDINATOR_IDS[0], 'ignore']), params)
+    data = json.loads(response.content)
+    assert_equal(0, data['status'])
+
 
 
   def test_workflows_permissions(self):
   def test_workflows_permissions(self):
     response = self.c.get(reverse('oozie:list_oozie_workflows') + '?format=json&status=SUCCEEDED')
     response = self.c.get(reverse('oozie:list_oozie_workflows') + '?format=json&status=SUCCEEDED')

+ 1 - 1
apps/oozie/src/oozie/urls.py

@@ -133,7 +133,7 @@ urlpatterns += patterns(
   url(r'^rerun_oozie_job/(?P<job_id>[-\w]+)/(?P<app_path>.+?)$', 'rerun_oozie_job', name='rerun_oozie_job'),
   url(r'^rerun_oozie_job/(?P<job_id>[-\w]+)/(?P<app_path>.+?)$', 'rerun_oozie_job', name='rerun_oozie_job'),
   url(r'^rerun_oozie_coord/(?P<job_id>[-\w]+)/(?P<app_path>.+?)$', 'rerun_oozie_coordinator', name='rerun_oozie_coord'),
   url(r'^rerun_oozie_coord/(?P<job_id>[-\w]+)/(?P<app_path>.+?)$', 'rerun_oozie_coordinator', name='rerun_oozie_coord'),
   url(r'^rerun_oozie_bundle/(?P<job_id>[-\w]+)/(?P<app_path>.+?)$', 'rerun_oozie_bundle', name='rerun_oozie_bundle'),
   url(r'^rerun_oozie_bundle/(?P<job_id>[-\w]+)/(?P<app_path>.+?)$', 'rerun_oozie_bundle', name='rerun_oozie_bundle'),
-  url(r'^manage_oozie_jobs/(?P<job_id>[-\w]+)/(?P<action>(start|suspend|resume|kill|rerun|change))$', 'manage_oozie_jobs', name='manage_oozie_jobs'),
+  url(r'^manage_oozie_jobs/(?P<job_id>[-\w]+)/(?P<action>(start|suspend|resume|kill|rerun|change|ignore))$', 'manage_oozie_jobs', name='manage_oozie_jobs'),
   url(r'^bulk_manage_oozie_jobs/$', 'bulk_manage_oozie_jobs', name='bulk_manage_oozie_jobs'),
   url(r'^bulk_manage_oozie_jobs/$', 'bulk_manage_oozie_jobs', name='bulk_manage_oozie_jobs'),
 
 
   url(r'^submit_external_job/(?P<application_path>.+?)$', 'submit_external_job', name='submit_external_job'),
   url(r'^submit_external_job/(?P<application_path>.+?)$', 'submit_external_job', name='submit_external_job'),

+ 15 - 5
apps/oozie/src/oozie/views/dashboard.py

@@ -100,17 +100,27 @@ def manage_oozie_jobs(request, job_id, action):
 
 
   try:
   try:
     oozie_api = get_oozie(request.user)
     oozie_api = get_oozie(request.user)
+    params = None
+
     if action == 'change':
     if action == 'change':
-      end_time = 'endtime=%s' % (request.POST.get('end_time'))
-      response['data'] = oozie_api.job_control(job_id, action, parameters={'value': end_time})
-    else:
-      response['data'] = oozie_api.job_control(job_id, action)
+      params = {'value': 'endtime=%s' % (request.POST.get('end_time'))}
+    elif action == 'ignore':
+      oozie_api = get_oozie(request.user, api_version="v2")
+      params = {
+        'type': 'action',
+        'scope': ','.join(job.aggreate(request.POST.get('actions').split())),
+      }
+
+    response['data'] = oozie_api.job_control(job_id, action, parameters=params)
 
 
     response['status'] = 0
     response['status'] = 0
     if 'notification' in request.POST:
     if 'notification' in request.POST:
       request.info(_(request.POST.get('notification')))
       request.info(_(request.POST.get('notification')))
   except RestException, ex:
   except RestException, ex:
-    msg = _("Error performing %s on Oozie job %s: %s.") % (action, job_id, ex.message)
+    ex_message = ex.message
+    if ex._headers.get('oozie-error-message'):
+      ex_message = ex._headers.get('oozie-error-message')
+    msg = _("Error performing %s on Oozie job %s: %s.") % (action, job_id, ex_message)
     LOG.exception(msg)
     LOG.exception(msg)
 
 
     response['data'] = msg
     response['data'] = msg

+ 1 - 1
desktop/libs/liboozie/src/liboozie/oozie_api.py

@@ -201,7 +201,7 @@ class OozieApi(object):
     job_control(jobid, action) -> None
     job_control(jobid, action) -> None
     Raise RestException on error.
     Raise RestException on error.
     """
     """
-    if action not in ('start', 'suspend', 'resume', 'kill', 'rerun', 'coord-rerun', 'bundle-rerun', 'change'):
+    if action not in ('start', 'suspend', 'resume', 'kill', 'rerun', 'coord-rerun', 'bundle-rerun', 'change', 'ignore'):
       msg = 'Invalid oozie job action: %s' % (action,)
       msg = 'Invalid oozie job action: %s' % (action,)
       LOG.error(msg)
       LOG.error(msg)
       raise ValueError(msg)
       raise ValueError(msg)