Repository: ambari
Updated Branches:
  refs/heads/trunk b95615065 -> 16e04b2ba


AMBARI-15309 UI: ability to perform bulk delete host components (zhewang)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/16e04b2b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/16e04b2b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/16e04b2b

Branch: refs/heads/trunk
Commit: 16e04b2ba3eaeedf6d6633b43c6e001593de9198
Parents: b956150
Author: Zhe (Joe) Wang <[email protected]>
Authored: Fri Aug 26 14:58:07 2016 -0700
Committer: Zhe (Joe) Wang <[email protected]>
Committed: Fri Aug 26 14:58:24 2016 -0700

----------------------------------------------------------------------
 .../main/host/bulk_operations_controller.js     | 194 +++++++++++++++++++
 ambari-web/app/messages.js                      |   6 +
 ambari-web/app/utils/ajax/ajax.js               |  10 +
 .../views/main/host/hosts_table_menu_view.js    |  11 ++
 4 files changed, 221 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/16e04b2b/ambari-web/app/controllers/main/host/bulk_operations_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/bulk_operations_controller.js 
b/ambari-web/app/controllers/main/host/bulk_operations_controller.js
index 0e73c0c..aca50bf 100644
--- a/ambari-web/app/controllers/main/host/bulk_operations_controller.js
+++ b/ambari-web/app/controllers/main/host/bulk_operations_controller.js
@@ -41,6 +41,9 @@ App.BulkOperationsController = Em.Controller.extend({
       else if (operationData.action === 'ADD') {
         this.bulkOperationForHostComponentsAdd(operationData, hosts);
       }
+      else if (operationData.action === 'DELETE') {
+        this.bulkOperationForHostComponentsDelete(operationData, hosts);
+      }
       else {
         if (operationData.action.indexOf('DECOMMISSION') == -1) {
           this.bulkOperationForHostComponents(operationData, hosts);
@@ -644,6 +647,197 @@ App.BulkOperationsController = Em.Controller.extend({
   },
 
   /**
+   * Confirm bulk delete for selected hostComponent
+   * @param {Object} operationData - data about bulk operation (action, 
hostComponent etc)
+   * @param {Array} hosts - list of affected hosts
+   */
+  bulkOperationForHostComponentsDelete: function (operationData, hosts) {
+    var self = this;
+    return batchUtils.getComponentsFromServer({
+      components: [operationData.componentName],
+      hosts: hosts.mapProperty('hostName'),
+      displayParams: ['host_components/HostRoles/state']
+    }, function (data) {
+      return 
self._getComponentsFromServerForHostComponentsDeleteCallback(operationData, 
data);
+    });
+  },
+
+  _getComponentsFromServerForHostComponentsDeleteCallback: function 
(operationData, data) {
+    var self = this;
+    var minToInstall = 
App.StackServiceComponent.find(operationData.componentName).get('minToInstall');
+    var installedCount = 
App.HostComponent.getCount(operationData.componentName, 'totalCount');
+    var installedHosts = data.items.mapProperty('Hosts.host_name');
+    var hostsToDelete = data.items.filter(function (host) {
+      var state = host.host_components[0].HostRoles.state;
+      return [App.HostComponentStatus.stopped, 
App.HostComponentStatus.unknown, App.HostComponentStatus.install_failed, 
App.HostComponentStatus.upgrade_failed, 
App.HostComponentStatus.init].contains(state);
+    }).mapProperty('Hosts.host_name');
+
+    if (!hostsToDelete.length) {
+      return App.ModalPopup.show({
+        header: Em.I18n.t('rolling.nothingToDo.header'),
+        body: 
Em.I18n.t('hosts.bulkOperation.confirmation.delete.component.nothingToDo.body').format(operationData.componentNameFormatted),
+        secondary: false
+      });
+    }
+    if (installedCount - hostsToDelete.length < minToInstall) {
+      return App.ModalPopup.show({
+        header: Em.I18n.t('rolling.nothingToDo.header'),
+        body: 
Em.I18n.t('hosts.bulkOperation.confirmation.delete.component.minimum.body').format(minToInstall,
 operationData.componentNameFormatted),
+        secondary: false
+      });
+    }
+
+    var hostsToSkip = installedHosts.filter(function (host) {
+      return !hostsToDelete.contains(host);
+    });
+
+    var minShown = 3;
+
+    return App.ModalPopup.show({
+      header: Em.I18n.t('hosts.bulkOperation.confirmation.header'),
+      hostNames: hostsToDelete.join("\n"),
+      visibleHosts: self._showHostNames(hostsToDelete, "\n", minShown),
+      hostNamesSkippedVisible: self._showHostNames(hostsToSkip, "\n", 
minShown),
+      expanded: false,
+
+      hostNamesSkipped: function() {
+        return hostsToSkip.length ? hostsToSkip.join("\n") : false;
+      }.property(),
+
+      didInsertElement: function() {
+        this.set('expanded', hostsToDelete.length <= minShown);
+      },
+
+      onPrimary: function() {
+        self.bulkDeleteHostComponents(operationData, hostsToDelete);
+        this._super();
+      },
+      bodyClass: Em.View.extend({
+        templateName: 
require('templates/main/host/bulk_operation_confirm_popup'),
+        message: 
Em.I18n.t('hosts.bulkOperation.confirmation.add.component').format(operationData.message,
 operationData.componentNameFormatted, hostsToDelete.length),
+        warningInfo: 
Em.I18n.t('hosts.bulkOperation.confirmation.delete.component.skip').format(operationData.componentNameFormatted),
+        textareaVisible: false,
+        textTrigger: function() {
+          this.toggleProperty('textareaVisible');
+        },
+
+        showAll: function() {
+          this.set('parentView.visibleHosts', 
this.get('parentView.hostNames'));
+          this.set('parentView.hostNamesSkippedVisible', 
this.get('parentView.hostNamesSkipped'));
+          this.set('parentView.expanded', true);
+        },
+        putHostNamesToTextarea: function() {
+          var hostNames = this.get('parentView.hostNames');
+          if (this.get('textareaVisible')) {
+            var wrapper = $(".task-detail-log-maintext");
+            
$('.task-detail-log-clipboard').html(hostNames).width(wrapper.width()).height(250);
+            Em.run.next(function() {
+              $('.task-detail-log-clipboard').select();
+            });
+          }
+        }.observes('textareaVisible')
+      })
+    });
+  },
+
+  /**
+   * Bulk delete for selected hostComponent
+   * @param {Object} operationData - data about bulk operation (action, 
hostComponent etc)
+   * @param {Array} hostNames - list of affected hosts' names
+   */
+  bulkDeleteHostComponents: function (operationData, hostNames) {
+    var self= this;
+    App.get('router.mainAdminKerberosController').getKDCSessionState(function 
() {
+      App.ajax.send({
+        name: 'host.host_component.delete_components',
+        sender: self,
+        data: {
+          data: JSON.stringify({
+            RequestInfo: {
+              query: 'HostRoles/host_name.in(' + hostNames.join(',') + 
')&HostRoles/component_name.in(' + operationData.componentName + ')'
+            }
+          })
+        },
+        success: 'bulkOperationForHostComponentsDeleteCallback'
+      });
+    });
+  },
+
+  /**
+   * Show popup after bulk delete host_components
+   * @method bulkOperationForHostComponentsDeleteCallback
+   */
+  bulkOperationForHostComponentsDeleteCallback: function (arg0, arg1, arg2, 
arg3, arg4) {
+    var deletedHosts = [];
+    var undeletableHosts = [];
+    if (arg1 == "error") {
+      var request = arg0;
+      var params = arg4;
+      var response = JSON.parse(request.responseText);
+      var host = Ember.Object.create({
+        error: {
+          key: params.hosts[0],
+          code: response.status,
+          message: response.message
+        },
+        isCollapsed: true,
+        isBodyVisible: Em.computed.ifThenElse('isCollapsed', 'display: none;', 
'display: block;')
+      });
+      undeletableHosts.push(host);
+    } else {
+      var data = arg0;
+      var params = arg2;
+      if (data) {
+        data.deleteResult.forEach(function (host) {
+          if (host.deleted) {
+            deletedHosts.push(host);
+          } else {
+            var _host = Ember.Object.create({
+              error: host.error,
+              isCollapsed: true,
+              isBodyVisible: Em.computed.ifThenElse('isCollapsed', 'display: 
none;', 'display: block;')
+            });
+            undeletableHosts.push(_host);
+          }
+        });
+      } else {
+        var host = {
+          deleted: {
+            key: params.hosts[0]
+          }
+        };
+        deletedHosts.push(host);
+      }
+    }
+
+    return App.ModalPopup.show({
+      header: Em.I18n.t('hosts.bulkOperation.delete.component.result.header'),
+
+      secondary: null,
+
+      bodyClass: Em.View.extend({
+        templateName: require('templates/main/host/delete_hosts_result_popup'),
+        message: 
Em.I18n.t('hosts.bulkOperation.delete.component.dryRun.message').format(undeletableHosts.length),
+        undeletableHosts: undeletableHosts,
+        deletedHosts: deletedHosts,
+        onToggleHost: function (host) {
+          host.contexts[0].toggleProperty('isCollapsed');
+        }
+      }),
+
+      onPrimary: function () {
+        location.reload();
+        this._super();
+      },
+
+      onClose: function () {
+        location.reload();
+        this._super();
+      }
+    });
+  },
+
+  /**
    * Bulk operation for selected hostComponents
    * @param {Object} operationData - data about bulk operation (action, 
hostComponents etc)
    * @param {Array} hosts - list of affected hosts

http://git-wip-us.apache.org/repos/asf/ambari/blob/16e04b2b/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 4cf3564..b216918 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2446,6 +2446,12 @@ Em.I18n.translations = {
   'hosts.bulkOperation.deleteHosts.confirmation.body.msg4': 'If the hosts were 
hosting a Zookeeper Server, the Zookeeper Service should be restarted. Go to 
the <i>Services</i> page.',
   'hosts.bulkOperation.deleteHosts.result.header':'Delete Hosts',
   'hosts.bulkOperation.deleteHosts.result.body': 'The following hosts were 
deleted successfully:',
+  'hosts.bulkOperation.confirmation.delete.component.minimum.body': 'At least 
{0} {1} should be installed in the cluster.',
+  'hosts.bulkOperation.confirmation.delete.component.nothingToDo.body': '{0} 
are neither installed on selected hosts nor in the states that can be deleted.',
+  'hosts.bulkOperation.confirmation.delete.component.skip':'The following 
hosts are skipped as {0} on them are not in the states that can be deleted.',
+  'hosts.bulkOperation.delete.component.result.header':'Delete Hosts',
+  'hosts.bulkOperation.delete.component.result.body': 'The following hosts 
were deleted successfully:',
+  'hosts.bulkOperation.delete.component.dryRun.message':'There are <strong>{0} 
host(s)</strong> that cannot be deleted (expand for reason):',
 
   'hosts.selectHostsDialog.title': 'Select Configuration Group Hosts',
   'hosts.selectHostsDialog.message': 'Select hosts that should belong to this 
{0} Configuration Group. All hosts belonging to this group will have the same 
set of configurations.',

http://git-wip-us.apache.org/repos/asf/ambari/blob/16e04b2b/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js 
b/ambari-web/app/utils/ajax/ajax.js
index 5538e6d..dd15f9f 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -924,6 +924,16 @@ var urls = {
     }
   },
 
+  'host.host_component.delete_components': {
+    'real': '/clusters/{clusterName}/host_components',
+    'format': function (data) {
+      return {
+        type: 'DELETE',
+        data: data.data
+      }
+    }
+  },
+
   'host.host_component.slave_desired_admin_state': {
     'real': 
'/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}/?fields=HostRoles/desired_admin_state',
     'mock': '/data/hosts/HDP2/decommission_state.json'

http://git-wip-us.apache.org/repos/asf/ambari/blob/16e04b2b/ambari-web/app/views/main/host/hosts_table_menu_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/hosts_table_menu_view.js 
b/ambari-web/app/views/main/host/hosts_table_menu_view.js
index dccffaa..8849244 100644
--- a/ambari-web/app/views/main/host/hosts_table_menu_view.js
+++ b/ambari-web/app/views/main/host/hosts_table_menu_view.js
@@ -136,6 +136,17 @@ App.HostTableMenuView = Em.View.extend({
               serviceName: content.serviceName,
               componentNameFormatted: content.componentNameFormatted
             })
+          }),
+          O.create({
+            label: Em.I18n.t('common.delete'),
+            delete: true,
+            operationData: O.create({
+              action: 'DELETE',
+              message: Em.I18n.t('common.delete'),
+              componentName: content.componentName,
+              serviceName: content.serviceName,
+              componentNameFormatted: content.componentNameFormatted
+            })
           })
         ])
       }

Reply via email to