浏览代码

AMBARI-4567. Ambari should check that there is enough disk space during installation. (xiwang via yusaku)

Yusaku Sako 11 年之前
父节点
当前提交
bd48dca60b

+ 2 - 0
ambari-web/app/config.js

@@ -38,6 +38,8 @@ App.maxRunsForAppBrowser = 500;
 App.pageReloadTime=3600000;
 App.singleNodeInstall = false;
 App.singleNodeAlias = document.location.hostname;
+App.minDiskSpace = 2.0; // minimum disk space required for '/' for each host before install, unit GB
+App.minDiskSpaceUsrLib = 1.0; // minimum disk space for '/usr/lib' for each host before install, unit GB
 
 // experimental features are automatically enabled if running on brunch server
 App.enableExperimental = false;

+ 134 - 40
ambari-web/app/controllers/wizard/step3_controller.js

@@ -18,6 +18,7 @@
 
 var App = require('app');
 var lazyloading = require('utils/lazy_loading');
+var numberUtils = require('utils/number_utils');
 
 App.WizardStep3Controller = Em.Controller.extend({
   name: 'wizardStep3Controller',
@@ -539,6 +540,10 @@ App.WizardStep3Controller = Em.Controller.extend({
     this.parseWarnings(jsonData);
     var repoWarnings = [];
     var hostsContext = [];
+    var diskWarnings = [];
+    var hostsDiskContext = [];
+    var hostsDiskNames = [];
+    var hostsRepoNames = [];
     hosts.forEach(function (_host) {
       var host = (App.testMode) ? jsonData.items[0] : jsonData.items.findProperty('Hosts.host_name', _host.name);
       if (App.skipBootstrap) {
@@ -556,19 +561,39 @@ App.WizardStep3Controller = Em.Controller.extend({
         var context = self.checkHostOSType(host.Hosts.os_type, host.Hosts.host_name);
         if(context) {
           hostsContext.push(context);
+          hostsRepoNames.push(host.Hosts.host_name);
         }
+        var diskContext = self.checkHostDiskSpace(host.Hosts.host_name, host.Hosts.disk_info);
+        if (diskContext) {
+          hostsDiskContext.push(diskContext);
+          hostsDiskNames.push(host.Hosts.host_name);
+        }
+
       }
     });
     if (hostsContext.length > 0) { // warning exist
       var repoWarning = {
         name: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.name'),
         hosts: hostsContext,
+        hostsNames: hostsRepoNames,
         category: 'repositories',
         onSingleHost: false
       };
       repoWarnings.push(repoWarning);
     }
+    if (hostsDiskContext.length > 0) { // disk space warning exist
+      var diskWarning = {
+        name: Em.I18n.t('installer.step3.hostWarningsPopup.disk.name'),
+        hosts: hostsDiskContext,
+        hostsNames: hostsDiskNames,
+        category: 'disk',
+        onSingleHost: false
+      };
+      diskWarnings.push(diskWarning);
+    }
+
     this.set('repoCategoryWarnings', repoWarnings);
+    this.set('diskCategoryWarnings', diskWarnings);
     this.set('bootHosts', hosts);
     this.stopRegistration();
   },
@@ -612,6 +637,35 @@ App.WizardStep3Controller = Em.Controller.extend({
     }
   },
 
+  /**
+   * Check if current host has enough free disk usage.
+   */
+  checkHostDiskSpace: function (hostName, diskInfo) {
+    var minFreeRootSpace = App.minDiskSpace * 1024 * 1024; //in kilobyte
+    var minFreeUsrLibSpace = App.minDiskSpaceUsrLib * 1024 * 1024; //in kilobyte
+    var warningString = '';
+
+    diskInfo.forEach( function(info) {
+      switch (info.mountpoint) {
+        case '/':
+          warningString = info.available < minFreeRootSpace ? Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpace + 'GB', info.mountpoint) + ' ' + warningString : warningString;
+          break;
+        case '/usr':
+        case '/usr/lib':
+          warningString = info.available < minFreeUsrLibSpace ? Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpaceUsrLib + 'GB', info.mountpoint) + ' ' + warningString : warningString;
+          break;
+        default:
+          break;
+      }
+    });
+    if (warningString) {
+      console.log('WARNING: Getting host free disk space. ' + 'Host Name: '+ hostName);
+      return Em.I18n.t('installer.step3.hostWarningsPopup.disk.context1').format(hostName) + ' ' + warningString;
+    } else {
+      return null;
+    }
+  },
+
   selectCategory: function(event, context){
     this.set('category', event.context);
   },
@@ -967,6 +1021,7 @@ App.WizardStep3Controller = Em.Controller.extend({
   hostWarningsPopup: function(event){
     var self = this;
     var repoCategoryWarnings = this.get('repoCategoryWarnings');
+    var diskCategoryWarnings = this.get('diskCategoryWarnings');
     App.ModalPopup.show({
 
       header: Em.I18n.t('installer.step3.warnings.popup.header'),
@@ -1046,37 +1101,47 @@ App.WizardStep3Controller = Em.Controller.extend({
         content: function () {
           var categoryWarnings = this.get('categoryWarnings');
           return [
-             Ember.Object.create({
-                warnings: repoCategoryWarnings,
-                title: Em.I18n.t('installer.step3.hostWarningsPopup.repositories'),
-                message: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.message'),
-                type: Em.I18n.t('common.issues'),
-                emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.repositories'),
-                action: Em.I18n.t('installer.step3.hostWarningsPopup.action.invalid'),
-                category: 'repositories',
-                isCollapsed: true
-             }),
-             Ember.Object.create({
-               warnings: categoryWarnings.filterProperty('category', 'firewall'),
-               title: Em.I18n.t('installer.step3.hostWarningsPopup.firewall'),
-               message: Em.I18n.t('installer.step3.hostWarningsPopup.firewall.message'),
-               type: Em.I18n.t('common.issues'),
-               emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.firewall'),
-               action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
-               category: 'firewall',
-               isCollapsed: true
-             }),
-             Ember.Object.create({
-               warnings: categoryWarnings.filterProperty('category', 'processes'),
-               title: Em.I18n.t('installer.step3.hostWarningsPopup.process'),
-               message: Em.I18n.t('installer.step3.hostWarningsPopup.processes.message'),
-               type: Em.I18n.t('common.process'),
-               emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.processes'),
-               action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
-               category: 'process',
-               isCollapsed: true
-             }),
-             Ember.Object.create({
+            Ember.Object.create({
+              warnings: diskCategoryWarnings,
+              title: Em.I18n.t('installer.step3.hostWarningsPopup.disk'),
+              message: Em.I18n.t('installer.step3.hostWarningsPopup.disk.message'),
+              type: Em.I18n.t('common.issues'),
+              emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.disk'),
+              action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
+              category: 'disk',
+              isCollapsed: true
+            }),
+            Ember.Object.create({
+              warnings: repoCategoryWarnings,
+              title: Em.I18n.t('installer.step3.hostWarningsPopup.repositories'),
+              message: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.message'),
+              type: Em.I18n.t('common.issues'),
+              emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.repositories'),
+              action: Em.I18n.t('installer.step3.hostWarningsPopup.action.invalid'),
+              category: 'repositories',
+              isCollapsed: true
+            }),
+            Ember.Object.create({
+             warnings: categoryWarnings.filterProperty('category', 'firewall'),
+             title: Em.I18n.t('installer.step3.hostWarningsPopup.firewall'),
+             message: Em.I18n.t('installer.step3.hostWarningsPopup.firewall.message'),
+             type: Em.I18n.t('common.issues'),
+             emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.firewall'),
+             action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
+             category: 'firewall',
+             isCollapsed: true
+            }),
+            Ember.Object.create({
+             warnings: categoryWarnings.filterProperty('category', 'processes'),
+             title: Em.I18n.t('installer.step3.hostWarningsPopup.process'),
+             message: Em.I18n.t('installer.step3.hostWarningsPopup.processes.message'),
+             type: Em.I18n.t('common.process'),
+             emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.processes'),
+             action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
+             category: 'process',
+             isCollapsed: true
+            }),
+            Ember.Object.create({
               warnings: categoryWarnings.filterProperty('category', 'packages'),
               title: Em.I18n.t('installer.step3.hostWarningsPopup.package'),
               message: Em.I18n.t('installer.step3.hostWarningsPopup.packages.message'),
@@ -1086,7 +1151,7 @@ App.WizardStep3Controller = Em.Controller.extend({
               category: 'package',
               isCollapsed: true
             }),
-             Ember.Object.create({
+            Ember.Object.create({
               warnings: categoryWarnings.filterProperty('category', 'fileFolders'),
               title: Em.I18n.t('installer.step3.hostWarningsPopup.fileAndFolder'),
               message: Em.I18n.t('installer.step3.hostWarningsPopup.fileFolders.message'),
@@ -1096,7 +1161,7 @@ App.WizardStep3Controller = Em.Controller.extend({
               category: 'fileFolders',
               isCollapsed: true
             }),
-             Ember.Object.create({
+            Ember.Object.create({
               warnings: categoryWarnings.filterProperty('category', 'services'),
               title: Em.I18n.t('installer.step3.hostWarningsPopup.service'),
               message: Em.I18n.t('installer.step3.hostWarningsPopup.services.message'),
@@ -1106,7 +1171,7 @@ App.WizardStep3Controller = Em.Controller.extend({
               category: 'service',
               isCollapsed: true
             }),
-             Ember.Object.create({
+            Ember.Object.create({
               warnings: categoryWarnings.filterProperty('category', 'users'),
               title: Em.I18n.t('installer.step3.hostWarningsPopup.user'),
               message: Em.I18n.t('installer.step3.hostWarningsPopup.users.message'),
@@ -1145,15 +1210,44 @@ App.WizardStep3Controller = Em.Controller.extend({
           this.$('#' + category.context.category).toggle('blind', 500);
           category.context.set("isCollapsed", !category.context.get("isCollapsed"));
         },
-        warningsNotice: function () {
-          var warnings = this.get('warnings');
+        /**
+         * generate number of hosts which had warnings, avoid duplicated host names in different warnings.
+         */
+        warningHostsNamesCount: function () {
+          var hostNameMap = Ember.Object.create();
           var warningsByHost = self.get('warningsByHost').slice();
           warningsByHost.shift();
-          var issuesNumber = warnings.length + repoCategoryWarnings.length;
+          warningsByHost.forEach( function( _host) {
+            if (_host.warnings.length) {
+              hostNameMap[_host.name] = true;
+            }
+          })
+          if (repoCategoryWarnings.length) {
+            repoCategoryWarnings[0].hostsNames.forEach(function (_hostName) {
+              if (!hostNameMap[_hostName]) {
+                hostNameMap[_hostName] = true;
+              }
+            })
+          }
+          if (diskCategoryWarnings.length) {
+            diskCategoryWarnings[0].hostsNames.forEach(function (_hostName) {
+              if (!hostNameMap[_hostName]) {
+                hostNameMap[_hostName] = true;
+              }
+            })
+          }
+          var size = 0;
+          for (var key in hostNameMap) {
+            if (hostNameMap.hasOwnProperty(key)) size++;
+          }
+          return size;
+        },
+        warningsNotice: function () {
+          var warnings = this.get('warnings');
+          var issuesNumber = warnings.length + repoCategoryWarnings.length + diskCategoryWarnings.length;
           var issues = issuesNumber + ' ' + (issuesNumber.length === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.issue') : Em.I18n.t('installer.step3.hostWarningsPopup.issues'));
-          var repoHostsNumber = (repoCategoryWarnings.length > 0 ? repoCategoryWarnings[0].hosts.length : 0);
-          var hostsNumber = repoHostsNumber + warningsByHost.length - warningsByHost.filterProperty('warnings.length', 0).length;
-          var hosts = hostsNumber + ' ' + (hostsNumber === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.host') : Em.I18n.t('installer.step3.hostWarningsPopup.hosts'));
+          var hostsCnt = this.warningHostsNamesCount();
+          var hosts = hostsCnt + ' ' + (hostsCnt === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.host') : Em.I18n.t('installer.step3.hostWarningsPopup.hosts'));
           return Em.I18n.t('installer.step3.hostWarningsPopup.summary').format(issues, hosts);
         }.property('warnings', 'warningsByHost'),
         /**

+ 8 - 2
ambari-web/app/messages.js

@@ -411,11 +411,16 @@ Em.I18n.translations = {
     '<br><div class="code-snippet">python /usr/lib/python2.6/site-packages/ambari_agent/HostCleanup.py --silent --skip=users</div>' +
     '<div class="alert alert-warn"><b>Note</b>: To clean up in interactive mode, remove <b>--silent</b> option. To clean up all resources, including <i>users</i>, remove <b>--skip=users</b> option. Use <b>--help</b> for a list of available options.</div>',
   'installer.step3.hostWarningsPopup.summary':'{0} on {1}',
-  'installer.step3.hostWarningsPopup.firewall':'Firewall Issues',
   'installer.step3.hostWarningsPopup.repositories':'Repository Issues',
   'installer.step3.hostWarningsPopup.repositories.name':'Repository for OS not available',
   'installer.step3.hostWarningsPopup.repositories.context':'Host ({0}) has a {1} OS type, But the repositories chosen in "Select Stack" step was {2}.',
-  'installer.step3.hostWarningsPopup.repositories.message':'The following registered hosts have different Operating System types from the available Repositories chosen in "Select Stack" step. You can go back to "Select Stack" step to select another OS repository <b>or</b> remove the host.',
+  'installer.step3.hostWarningsPopup.repositories.message': 'The following registered hosts have different Operating System types from the available Repositories chosen in "Select Stack" step. You can go back to "Select Stack" step to select another OS repository <b>or</b> remove the host.',
+  'installer.step3.hostWarningsPopup.disk':'Disk Issues',
+  'installer.step3.hostWarningsPopup.disk.name':'Not enough disk space ',
+  'installer.step3.hostWarningsPopup.disk.context1':'Not enough disk space on host ({0}).',
+  'installer.step3.hostWarningsPopup.disk.context2':'A minimum of {0} is required for "{1}" mount.',
+  'installer.step3.hostWarningsPopup.disk.message':'The following registered hosts have issues related to disk space',
+  'installer.step3.hostWarningsPopup.firewall':'Firewall Issues',
   'installer.step3.hostWarningsPopup.firewall.message':'Firewall is running on the following hosts. Please configure the firewall to allow communications on the ports documented in the <i>Configuring Ports</i> section of  the <a target=\"_blank\" href=\"http://ambari.apache.org/current/installing-hadoop-using-ambari/content/\">Ambari documentation</a>',
   'installer.step3.hostWarningsPopup.firewall.name':'<i>iptables</i> Running',
   'installer.step3.hostWarningsPopup.process':'Process Issues',
@@ -442,6 +447,7 @@ Em.I18n.translations = {
   'installer.step3.hostWarningsPopup.empty.misc':'issues',
   'installer.step3.hostWarningsPopup.empty.firewall':'firewalls running',
   'installer.step3.hostWarningsPopup.empty.repositories':'repositories OS type mis-match with registered hosts',
+  'installer.step3.hostWarningsPopup.empty.disk':'disk space issues',
   'installer.step3.hostWarningsPopup.action.exists':'Exists on',
   'installer.step3.hostWarningsPopup.action.notRunning':'Not running on',
   'installer.step3.hostWarningsPopup.action.installed':'Installed on',

+ 2 - 2
ambari-web/app/views/wizard/step3_view.js

@@ -50,7 +50,7 @@ App.WizardStep3View = Em.View.extend({
       this.set('status', 'alert-warn');
       this.set('linkText', '');
       this.set('message', Em.I18n.t('installer.step3.warnings.missingHosts'));
-    } else if (this.get('controller.isHostHaveWarnings') || this.get('controller.repoCategoryWarnings.length')) {
+    } else if (this.get('controller.isHostHaveWarnings') || this.get('controller.repoCategoryWarnings.length') || this.get('controller.diskCategoryWarnings.length')) {
       this.set('status', 'alert-warn');
       this.set('linkText', Em.I18n.t('installer.step3.warnings.linkText'));
       this.set('message', Em.I18n.t('installer.step3.warnings.fails').format(hosts.length - failedHosts));
@@ -70,7 +70,7 @@ App.WizardStep3View = Em.View.extend({
         this.set('message', Em.I18n.t('installer.step3.warnings.someWarnings').format((hosts.length-failedHosts), failedHosts));
       }
     }
-  }.observes('controller.isHostHaveWarnings', 'controller.bootHosts.@each.bootStatus', 'controller.repoCategoryWarnings')
+  }.observes('controller.isHostHaveWarnings', 'controller.bootHosts.@each.bootStatus', 'controller.repoCategoryWarnings', 'controller.diskCategoryWarnings')
 });
 
 //todo: move it inside WizardStep3View