Explorar o código

AMBARI-8630 Hosts / Host Details: Stack Version Management: Integrate with final API. (atkach)

Andrii Tkach %!s(int64=10) %!d(string=hai) anos
pai
achega
dacca7b5fa

+ 88 - 38
ambari-web/app/assets/data/hosts/HDP2/hosts.json

@@ -15,44 +15,94 @@
       },
       "stack_versions": [
         {
-          "HostStackVersions": {
-            "id": 1,
-            "stack": "HDP-2.2",
-            "version": "2.2.0.1-885",
-            "state": "INIT"
-          }
-        },
-        {
-          "HostStackVersions":  {
-            "id": 2,
-            "stack": "HDP-2.2",
-            "version": "2.2.1.1-885",
-            "state": "INSTALLED"
-          }
-        },
-        {
-          "HostStackVersions": {
-            "id": 3,
-            "stack": "HDP-2.2",
-            "version": "2.2.2.1-885",
-            "state": "INSTALL_FAILED"
-          }
-        },
-        {
-          "HostStackVersions":  {
-            "id": 4,
-            "stack": "HDP-2.3",
-            "version": "2.3.0.1-885",
-            "state": "INSTALLING"
-          }
-        },
-        {
-          "HostStackVersions": {
-            "id": 5,
-            "stack": "HDP-2.3",
-            "version": "2.3.1.1-885",
-            "state": "CURRENT"
-          }
+          "HostStackVersions" : {
+            "cluster_name" : "c1",
+            "host_name" : "dev01.hortonworks.com",
+            "id" : 1,
+            "stack" : "HDP",
+            "state" : "CURRENT",
+            "version" : "2.2"
+          },
+          "repository_versions" : [
+            {
+              "RepositoryVersions" : {
+                "id" : 1,
+                "repository_version" : "2.2.0.1-885"
+              }
+            }
+          ]
+        },
+        {
+          "HostStackVersions" : {
+            "cluster_name" : "c1",
+            "host_name" : "dev01.hortonworks.com",
+            "id" : 2,
+            "stack" : "HDP",
+            "state" : "INSTALLED",
+            "version" : "2.2"
+          },
+          "repository_versions" : [
+            {
+              "RepositoryVersions" : {
+                "id" : 2,
+                "repository_version" : "2.2.1.1-885"
+              }
+            }
+          ]
+        },
+        {
+          "HostStackVersions" : {
+            "cluster_name" : "c1",
+            "host_name" : "dev01.hortonworks.com",
+            "id" : 3,
+            "stack" : "HDP",
+            "state" : "INIT",
+            "version" : "2.2"
+          },
+          "repository_versions" : [
+            {
+              "RepositoryVersions" : {
+                "id" : 3,
+                "repository_version" : "2.2.2.1-885"
+              }
+            }
+          ]
+        },
+        {
+          "HostStackVersions" : {
+            "cluster_name" : "c1",
+            "host_name" : "dev01.hortonworks.com",
+            "id" : 4,
+            "stack" : "HDP",
+            "state" : "INSTALL_FAILED",
+            "version" : "2.2"
+          },
+          "repository_versions" : [
+            {
+              "RepositoryVersions" : {
+                "id" : 4,
+                "repository_version" : "2.2.3.1-885"
+              }
+            }
+          ]
+        },
+        {
+          "HostStackVersions" : {
+            "cluster_name" : "c1",
+            "host_name" : "dev01.hortonworks.com",
+            "id" : 5,
+            "stack" : "HDP",
+            "state" : "INSTALLING",
+            "version" : "2.3"
+          },
+          "repository_versions" : [
+            {
+              "RepositoryVersions" : {
+                "id" : 6,
+                "repository_version" : "2.2.4.1-885"
+              }
+            }
+          ]
         }
       ],
       "host_components" : [

+ 1 - 0
ambari-web/app/assets/test/tests.js

@@ -188,6 +188,7 @@ var files = ['test/init_model_test',
   'test/views/main/dashboard/widgets/namenode_cpu_test',
   'test/views/main/host/details_test',
   'test/views/main/host/summary_test',
+  'test/views/main/host/stack_versions_view_test',
   'test/views/main/host/details/host_component_view_test',
   'test/views/main/host/details/host_component_views/decommissionable_test',
   'test/views/main/host/details/host_component_views/datanode_view_test',

+ 2 - 1
ambari-web/app/controllers/global/update_controller.js

@@ -159,7 +159,8 @@ App.UpdateController = Em.Controller.extend({
       'host_components/HostRoles/stale_configs,host_components/HostRoles/service_name,host_components/HostRoles/desired_admin_state,' +
         'metrics/disk,metrics/load/load_one,Hosts/total_mem<hostAuxiliaryInfo><stackVersions>&minimal_response=true';
     var hostAuxiliaryInfo = ',Hosts/os_arch,Hosts/os_type,metrics/cpu/cpu_system,metrics/cpu/cpu_user,metrics/memory/mem_total,metrics/memory/mem_free';
-    realUrl = realUrl.replace("<stackVersions>", (App.get('supports.stackUpgrade') ? ",stack_versions/HostStackVersions" : ""));
+    var stackVersionInfo = ',stack_versions/HostStackVersions,stack_versions/repository_versions/RepositoryVersions/repository_version,stack_versions/repository_versions/RepositoryVersions/id';
+    realUrl = realUrl.replace("<stackVersions>", (App.get('supports.stackUpgrade') ? stackVersionInfo : ""));
 
     if (App.router.get('currentState.name') == 'index' && App.router.get('currentState.parentState.name') == 'hosts') {
       App.updater.updateInterval('updateHost', App.get('contentUpdateInterval'));

+ 27 - 0
ambari-web/app/controllers/main/host/details.js

@@ -1783,5 +1783,32 @@ App.MainHostDetailsController = Em.Controller.extend({
     }
     App.showAlertPopup(Em.I18n.t('services.service.actions.run.executeCustomCommand.error'), error);
     console.warn('Error during executing custom command');
+  },
+
+  /**
+   * install HostStackVersion on host
+   * @param {object} event
+   */
+  installVersion: function (event) {
+    App.ajax.send({
+      name: 'host.stack_versions.install',
+      sender: this,
+      data: {
+        hostName: this.get('content.hostName'),
+        version: event.context
+      },
+      success: 'installVersionSuccessCallback'
+    });
+  },
+
+  /**
+   * success callback of <code>installVersion</code>
+   * on success set version status to INSTALLING
+   * @param {object} data
+   * @param {object} opt
+   * @param {object} params
+   */
+  installVersionSuccessCallback: function (data, opt, params) {
+    App.HostStackVersion.find(params.version.get('id')).set('status', 'INSTALLING');
   }
 });

+ 5 - 6
ambari-web/app/mappers/hosts_mapper.js

@@ -66,9 +66,10 @@ App.hostsMapper = App.QuickDataMapper.create({
     admin_state: 'HostRoles.desired_admin_state'
   },
   stackVersionConfig: {
-    id: 'id',
-    stack_id: 'stack_id',
-    stack_name: 'HostStackVersions.stack',
+    id: 'HostStackVersions.id',
+    stack: 'HostStackVersions.stack',
+    repo_id: 'repository_versions[0].RepositoryVersions.id',
+    repo_version: 'repository_versions[0].RepositoryVersions.repository_version',
     version: 'HostStackVersions.version',
     status: 'HostStackVersions.state',
     host_name: 'host_name',
@@ -107,9 +108,7 @@ App.hostsMapper = App.QuickDataMapper.create({
 
         if (App.get('supports.stackUpgrade')) {
           item.stack_versions.forEach(function (stackVersion) {
-            stackVersion.id = stackVersion.HostStackVersions.stack + "_" + stackVersion.HostStackVersions.version + "_" + item.Hosts.host_name;
             stackVersion.host_name = item.Hosts.host_name;
-            stackVersion.stack_id = stackVersion.HostStackVersions.stack + stackVersion.HostStackVersions.version;
             stackVersions.push(this.parseIt(stackVersion, this.stackVersionConfig));
           }, this);
         }
@@ -124,7 +123,7 @@ App.hostsMapper = App.QuickDataMapper.create({
             stack_versions_key: 'stack_versions',
             stack_versions_type: 'array',
             stack_versions: {
-              item: 'id'
+              item: 'HostStackVersions.id'
             }
           })
         }

+ 1 - 1
ambari-web/app/models/host.js

@@ -60,7 +60,7 @@ App.Host = DS.Model.extend({
   isRequested: DS.attr('boolean'),
 
   currentVersion: function () {
-    return this.get('stackVersions').findProperty('isCurrent').get('version');
+    return this.get('stackVersions').findProperty('isCurrent').get('repoVersion');
   }.property('stackVersions.@each.isCurrent'),
 
   /**

+ 4 - 2
ambari-web/app/models/host_stack_version.js

@@ -19,9 +19,11 @@
 var App = require('app');
 
 App.HostStackVersion = DS.Model.extend({
-  stackName: DS.attr('string'),
-  stack: DS.belongsTo('App.StackVersion'),
+  stack: DS.attr('string'),
   version: DS.attr('string'),
+  repo: DS.belongsTo('App.Repository'),
+  repoVersion: DS.attr('string'),
+
   /**
    * possible property value defined at App.HostStackVersion.statusDefinition
    */

+ 7 - 7
ambari-web/app/templates/main/host/stack_versions.hbs

@@ -18,14 +18,14 @@
 <table class="table advanced-header-table table-bordered table-striped">
   <thead>
   {{#view view.sortView classNames="label-row" contentBinding="view.filteredContent"}}
-    {{view view.parentView.stackNameSort classNames="first"}}
-    {{view view.parentView.versionSort}}
+    {{view view.parentView.stackSort classNames="first"}}
+    {{view view.parentView.repoVersionSort}}
     {{view view.parentView.statusSort}}
     <th></th>
   {{/view}}
   <tr class="filter-row">
-    <th class="first stack-name-filter">{{view view.stackNameFilterView}}</th>
-    <th class="repo-version-filter">{{view view.versionFilterView}}</th>
+    <th class="first stack-name-filter">{{view view.stackFilterView}}</th>
+    <th class="repo-version-filter">{{view view.repoVersionFilterView}}</th>
     <th class="status-filter">{{view view.statusFilterView}}</th>
     <th> </th>
   </tr>
@@ -34,8 +34,8 @@
   {{#if view.pageContent}}
     {{#each view.pageContent}}
       <tr>
-        <td class="first stack-name">{{this.stackName}}</td>
-        <td class="repo-version">{{this.version}}</td>
+        <td class="first stack-name">{{this.stack}}</td>
+        <td class="repo-version">{{this.repoVersion}}</td>
         <td class="host-stack-version-status">
           {{this.displayStatus}}
           {{#if this.isCurrent}}
@@ -44,7 +44,7 @@
         </td>
         <td class="install-repo-version">
           {{#isAccessible ADMIN}}
-            <button class="btn" {{bindAttr disabled="this.installDisabled"}}><i class="icon-off"></i>&nbsp;{{t common.install}}</button>
+            <button class="btn" {{action installVersion this target="controller"}} {{bindAttr disabled="this.installDisabled"}}><i class="icon-off"></i>&nbsp;{{t common.install}}</button>
           {{/isAccessible}}
         </td>
       </tr>

+ 16 - 0
ambari-web/app/utils/ajax/ajax.js

@@ -2030,6 +2030,22 @@ var urls = {
     'real': '/clusters/{clusterName}?fields=Clusters/health_report,Clusters/total_hosts,alerts_summary&minimal_response=true',
     'mock': '/data/hosts/HDP2/host_status_counters.json'
   },
+  'host.stack_versions.install': {
+    'real': '/clusters/{clusterName}/hosts/{hostName}/stack_versions',
+    'mock': '',
+    'type': 'POST',
+    'format': function (data) {
+      return {
+        data: JSON.stringify({
+          "HostStackVersions": {
+            "stack": data.version.get('stack'),
+            "version": data.version.get('version'),
+            "repository_version": data.version.get('repoVersion')
+          }
+        })
+      }
+    }
+  },
   'components.filter_by_status': {
     'real': '/clusters/{clusterName}/components?fields=host_components/HostRoles/host_name,ServiceComponentInfo/component_name,ServiceComponentInfo/started_count{urlParams}&minimal_response=true',
     'mock': ''

+ 1 - 6
ambari-web/app/views/main/host.js

@@ -64,11 +64,6 @@ App.MainHostView = App.TableView.extend(App.TableServerViewMixin, {
     return [];
   }.property('controller.content'),
 
-  stackVersions: function () {
-    //TODO obtain versions from model App.StackVersion
-    return App.HostStackVersion.find().mapProperty('version').uniq();
-  }.property(),
-
   onRequestErrorHandler: function() {
     this.set('requestError', null);
     this.get('controller').get('dataSource').setEach('isRequested', false);
@@ -1014,7 +1009,7 @@ App.MainHostView = App.TableView.extend(App.TableServerViewMixin, {
               value: '',
               label: Em.I18n.t('common.all')
             }
-          ].concat(this.get('parentView.parentView.parentView.stackVersions').map(function (version) {
+          ].concat(App.HostStackVersion.find().mapProperty('version').uniq().map(function (version) {
             return {
               value: version,
               label: version

+ 40 - 13
ambari-web/app/views/main/host/stack_versions_view.js

@@ -24,35 +24,56 @@ App.MainHostStackVersionsView = App.TableView.extend({
   templateName: require('templates/main/host/stack_versions'),
   classNames: ['host-tab-content'],
 
+  /**
+   * @type {Ember.Object}
+   */
   host: function () {
     return App.router.get('mainHostDetailsController.content');
   }.property('App.router.mainHostDetailsController.content'),
 
+  /**
+   * @type {Ember.Array}
+   */
   content: function () {
     return App.HostStackVersion.find();
   }.property(),
 
   /**
    * return filtered number of all content number information displayed on the page footer bar
-   * @returns {String}
+   * @returns {string}
    */
   filteredContentInfo: function () {
     return this.t('hosts.host.stackVersions.table.filteredInfo').format(this.get('filteredCount'), this.get('totalCount'));
   }.property('filteredCount', 'totalCount'),
 
+  /**
+   * @type {Ember.View}
+   */
   sortView: sort.wrapperView,
-  stackNameSort: sort.fieldView.extend({
+
+  /**
+   * @type {Ember.View}
+   */
+  stackSort: sort.fieldView.extend({
     column: 1,
-    name: 'stackName',
+    name: 'stack',
     displayName: Em.I18n.t('common.stack'),
     type: 'version'
   }),
-  versionSort: sort.fieldView.extend({
+
+  /**
+   * @type {Ember.View}
+   */
+  repoVersionSort: sort.fieldView.extend({
     column: 2,
-    name: 'version',
+    name: 'repoVersion',
     displayName: Em.I18n.t('common.version'),
     type: 'version'
   }),
+
+  /**
+   * @type {Ember.View}
+   */
   statusSort: sort.fieldView.extend({
     column: 3,
     name: 'status',
@@ -62,8 +83,9 @@ App.MainHostStackVersionsView = App.TableView.extend({
   /**
    * Filter view for stackName column
    * Based on <code>filters</code> library
+   * @type {Ember.View}
    */
-  stackNameFilterView: filters.createSelectView({
+  stackFilterView: filters.createSelectView({
     column: 1,
     fieldType: 'filter-input-width',
     content: function () {
@@ -72,7 +94,7 @@ App.MainHostStackVersionsView = App.TableView.extend({
           value: '',
           label: Em.I18n.t('common.all')
         }
-      ].concat(this.get('parentView.content').mapProperty('stackName').uniq().map(function (item) {
+      ].concat(this.get('parentView.content').mapProperty('stack').uniq().map(function (item) {
         return {
           value: item,
           label: item
@@ -87,8 +109,9 @@ App.MainHostStackVersionsView = App.TableView.extend({
   /**
    * Filter view for version column
    * Based on <code>filters</code> library
+   * @type {Ember.View}
    */
-  versionFilterView: filters.createSelectView({
+  repoVersionFilterView: filters.createSelectView({
     column: 2,
     fieldType: 'filter-input-width',
     content: function () {
@@ -97,10 +120,10 @@ App.MainHostStackVersionsView = App.TableView.extend({
           value: '',
           label: Em.I18n.t('common.all')
         }
-      ].concat(this.get('parentView.content').map(function (item) {
+      ].concat(this.get('parentView.content').mapProperty('repoVersion').uniq().map(function (version) {
         return {
-          value: item.get('version'),
-          label: item.get('version')
+          value: version,
+          label: version
         }
       }));
     }.property('App.router.clusterController.isLoaded'),
@@ -112,6 +135,7 @@ App.MainHostStackVersionsView = App.TableView.extend({
   /**
    * Filter view for status column
    * Based on <code>filters</code> library
+   * @type {Ember.View}
    */
   statusFilterView: filters.createSelectView({
     column: 3,
@@ -134,10 +158,13 @@ App.MainHostStackVersionsView = App.TableView.extend({
     }
   }),
 
+  /**
+   * @type {Array}
+   */
   colPropAssoc: function () {
     var associations = [];
-    associations[1] = 'stackName';
-    associations[2] = 'version';
+    associations[1] = 'stack';
+    associations[2] = 'repoVersion';
     associations[3] = 'status';
     return associations;
   }.property()

+ 35 - 0
ambari-web/test/controllers/main/host/details_test.js

@@ -21,6 +21,7 @@ var App = require('app');
 require('controllers/main/host/details');
 require('models/service');
 require('models/host_component');
+require('models/host_stack_version');
 var batchUtils = require('utils/batch_scheduled_requests');
 var componentsUtils = require('utils/components');
 var controller;
@@ -2317,4 +2318,38 @@ describe('App.MainHostDetailsController', function () {
       controller.loadConfigs.restore();
     });
   });
+
+  describe("#installVersion()", function() {
+    it("call App.ajax.send", function() {
+      controller.set('content.hostName', 'host1');
+      controller.installVersion({context: {}});
+      expect(App.ajax.send.getCall(0).args[0]).to.eql({
+        name: 'host.stack_versions.install',
+        sender: controller,
+        data: {
+          hostName: 'host1',
+          version: {}
+        },
+        success: 'installVersionSuccessCallback'
+      });
+    });
+  });
+
+  describe("#installVersionSuccessCallback()", function () {
+    before(function () {
+      this.mock = sinon.stub(App.HostStackVersion, 'find');
+    });
+    after(function () {
+      this.mock.restore();
+    });
+    it("", function () {
+      var version = Em.Object.create({
+        id: 1,
+        status: 'INIT'
+      });
+      this.mock.returns(version);
+      controller.installVersionSuccessCallback({}, {}, {version: version});
+      expect(version.get('status')).to.equal('INSTALLING');
+    });
+  });
 });

+ 20 - 0
ambari-web/test/models/host_stack_version_test.js

@@ -95,4 +95,24 @@ describe('App.HostStackVersion', function () {
       });
     }, this);
   });
+
+  describe("#isCurrent", function () {
+    afterEach(function () {
+      App.HostStackVersion.find().clear();
+    });
+    it("status is CURRENT", function () {
+      App.store.load(App.HostStackVersion, {
+        id: 1,
+        status: 'CURRENT'
+      });
+      expect(App.HostStackVersion.find(1).get('isCurrent')).to.be.true;
+    });
+    it("status is not CURRENT", function () {
+      App.store.load(App.HostStackVersion, {
+        id: 1,
+        status: 'INSTALLED'
+      });
+      expect(App.HostStackVersion.find(1).get('isCurrent')).to.be.false;
+    });
+  });
 });

+ 69 - 0
ambari-web/test/views/main/host/stack_versions_view_test.js

@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+describe('App.MainHostStackVersionsView', function() {
+  var view = App.MainHostStackVersionsView.create({
+    filteredCount: 0,
+    totalCount: 0
+  });
+
+  describe("#host", function () {
+    before(function () {
+      sinon.stub(App.router, 'get').returns(Em.Object.create({
+        id: 1
+      }));
+    });
+    after(function () {
+      App.router.get.restore();
+    });
+    it("", function () {
+      view.propertyDidChange('host');
+      expect(view.get('host')).to.eql(Em.Object.create({
+        id: 1
+      }));
+    });
+  });
+
+  describe("#content", function () {
+    before(function () {
+      sinon.stub(App.HostStackVersion, 'find').returns([Em.Object.create({
+        id: 1
+      })]);
+    });
+    after(function () {
+      App.HostStackVersion.find.restore();
+    });
+    it("", function () {
+      view.propertyDidChange('content');
+      expect(view.get('content')).to.eql([Em.Object.create({
+        id: 1
+      })]);
+    });
+  });
+
+  describe("#filteredContentInfo", function () {
+    it("", function () {
+      view.set('filteredCount', 1);
+      view.set('totalCount', 2);
+      view.propertyDidChange('filteredContentInfo');
+      expect(view.get('filteredContentInfo')).to.eql(Em.I18n.t('hosts.host.stackVersions.table.filteredInfo').format(1, 2));
+    });
+  });
+});