You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2014/12/12 00:06:12 UTC
ambari git commit: AMBARI-8659. Rolling upgrade process: implement
nested views of upgrade process. (atkach via yusaku)
Repository: ambari
Updated Branches:
refs/heads/trunk 8ead0a50b -> 2f8de0be4
AMBARI-8659. Rolling upgrade process: implement nested views of upgrade process. (atkach via yusaku)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2f8de0be
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2f8de0be
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2f8de0be
Branch: refs/heads/trunk
Commit: 2f8de0be4b46221afc9b66cdc76ed18231fe3b00
Parents: 8ead0a5
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Thu Dec 11 15:04:26 2014 -0800
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Thu Dec 11 15:04:26 2014 -0800
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 2 +-
.../main/admin/stack_and_upgrade_controller.js | 125 +++++++++++++++-
ambari-web/app/messages.js | 7 +-
ambari-web/app/routes/stack_upgrade_routes.js | 4 +
ambari-web/app/styles/application.less | 18 ++-
.../app/templates/common/error_log_body.hbs | 4 +-
.../templates/common/host_progress_popup.hbs | 4 +-
.../stack_upgrade/stack_upgrade_dialog.hbs | 8 +-
.../main/admin/stack_upgrade/upgrade_group.hbs | 148 +++++++++++++++++++
.../main/admin/stack_upgrade/upgrade_task.hbs | 67 ---------
ambari-web/app/utils/ember_reopen.js | 6 +-
ambari-web/app/utils/helper.js | 36 +++++
ambari-web/app/views.js | 2 +-
.../admin/stack_upgrade/upgrade_group_view.js | 115 ++++++++++++++
.../admin/stack_upgrade/upgrade_task_view.js | 115 --------------
.../admin/stack_upgrade/upgrade_wizard_view.js | 33 ++++-
.../admin/stack_and_upgrade_controller_test.js | 22 ++-
.../stack_upgrade/upgrade_group_view_test.js | 40 +++++
.../stack_upgrade/upgrade_task_view_test.js | 61 --------
19 files changed, 539 insertions(+), 278 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 2aab326..dd816dc 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -168,7 +168,7 @@ var files = ['test/init_model_test',
'test/views/main/alerts/manage_alert_notifications_view_test',
'test/views/main/admin/stack_version/stack_version_details_test',
'test/views/main/admin/stack_upgrade/upgrade_version_box_view_test',
- 'test/views/main/admin/stack_upgrade/upgrade_task_view_test',
+ 'test/views/main/admin/stack_upgrade/upgrade_group_view_test',
'test/views/main/dashboard/config_history_view_test',
'test/views/main/dashboard/widget_test',
'test/views/main/dashboard/widgets_test',
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
index f8c687e..2d73ab3 100644
--- a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
+++ b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
@@ -164,11 +164,81 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
loadUpgradeDataSuccessCallback: function (data) {
App.set('upgradeState', data.Upgrade.request_status);
if (data.upgrade_groups) {
- this.set("upgradeData", data);
+ this.updateUpgradeData(data);
}
},
/**
+ * update data of Upgrade
+ * @param {object} newData
+ */
+ updateUpgradeData: function (newData) {
+ var oldData = this.get('upgradeData'),
+ groupsMap = {},
+ itemsMap = {},
+ tasksMap = {};
+
+ if (Em.isNone(oldData)) {
+ this.initUpgradeData(newData);
+ } else {
+ //create entities maps
+ newData.upgrade_groups.forEach(function (newGroup) {
+ groupsMap[newGroup.UpgradeGroup.group_id] = newGroup.UpgradeGroup;
+ newGroup.upgrade_items.forEach(function (item) {
+ itemsMap[item.UpgradeItem.stage_id] = item.UpgradeItem;
+ item.tasks.forEach(function (task) {
+ tasksMap[task.Tasks.id] = task.Tasks;
+ });
+ })
+ });
+
+ //update existed entities with new data
+ oldData.upgradeGroups.forEach(function (oldGroup) {
+ oldGroup.set('status', groupsMap[oldGroup.get('group_id')].status);
+ oldGroup.set('progress_percent', groupsMap[oldGroup.get('group_id')].progress_percent);
+ oldGroup.upgradeItems.forEach(function (item) {
+ item.set('status', itemsMap[item.get('stage_id')].status);
+ item.set('progress_percent', itemsMap[item.get('stage_id')].progress_percent);
+ item.tasks.forEach(function (task) {
+ task.set('status', tasksMap[task.get('id')].status);
+ });
+ })
+ });
+ }
+ },
+
+ /**
+ * change structure of Upgrade
+ * In order to maintain nested views in template object should have direct link to its properties, for example
+ * item.UpgradeItem.<properties> -> item.<properties>
+ * @param {object} newData
+ */
+ initUpgradeData: function (newData) {
+ var upgradeGroups = [];
+
+ //wrap all entities into App.upgradeEntity
+ newData.upgrade_groups.forEach(function (newGroup) {
+ var oldGroup = App.upgradeEntity.create(newGroup.UpgradeGroup);
+ var upgradeItems = [];
+ newGroup.upgrade_items.forEach(function (item) {
+ var oldItem = App.upgradeEntity.create(item.UpgradeItem);
+ var tasks = [];
+ item.tasks.forEach(function (task) {
+ tasks.pushObject(App.upgradeEntity.create(task.Tasks));
+ });
+ oldItem.set('tasks', tasks);
+ upgradeItems.pushObject(oldItem);
+ });
+ oldGroup.set('upgradeItems', upgradeItems);
+ upgradeGroups.pushObject(oldGroup);
+ });
+ this.set('upgradeData', Em.Object.create({
+ upgradeGroups: upgradeGroups,
+ Upgrade: newData.Upgrade
+ }));
+ },
+
+ /**
* make call to start downgrade process
*/
downgrade: function () {
@@ -292,3 +362,56 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
App.router.transitionTo('admin.stackUpgrade');
}
});
+
+
+/**
+ * @type {Ember.Object}
+ * @class
+ */
+App.upgradeEntity = Em.Object.extend({
+
+ /**
+ * @type {boolean}
+ */
+ errorLogOpened: false,
+
+ /**
+ * @type {boolean}
+ */
+ outputLogOpened: false,
+
+ /**
+ * @type {boolean}
+ */
+ isExpanded: false,
+
+ /**
+ * @type {boolean}
+ */
+ isRunning: function () {
+ return ['IN_PROGRESS'].contains(this.get('status'));
+ }.property('status'),
+
+ /**
+ * width style of progress bar
+ * @type {string}
+ */
+ progressWidth: function () {
+ return "width:" + Math.floor(this.get('progress')) + '%;';
+ }.property('progress'),
+
+ /**
+ * @type {number}
+ */
+ progress: function () {
+ return Math.floor(this.get('progress_percent'));
+ }.property('progress_percent'),
+
+ /**
+ * indicate whether entity has active link
+ * @type {boolean}
+ */
+ isActive: function () {
+ return this.get('status') !== 'PENDING';
+ }.property('status')
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 4dbeb91..0705e88 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -243,6 +243,8 @@ Em.I18n.translations = {
'common.finalize': "Finalize",
'common.severity': "Severity",
'common.dismiss': "Dismiss",
+ 'common.stdout': "stdout",
+ 'common.stderr': "stderr",
'models.alert_instance.tiggered.verbose': "Occured on {0} <br> Checked on {1}",
'models.alert_definition.triggered.verbose': "Occured on {0}",
@@ -1295,10 +1297,11 @@ Em.I18n.translations = {
'admin.stackUpgrade.state.available': "Upgrade Available",
'admin.stackUpgrade.state.notAvailable': "No Upgrade Available",
'admin.stackUpgrade.state.resume': "Resume Upgrade",
- 'admin.stackUpgrade.state.inProgress': "Upgrade in progress",
- 'admin.stackUpgrade.state.paused': "Upgrade is paused",
+ 'admin.stackUpgrade.state.inProgress': "Upgrade in Progress",
+ 'admin.stackUpgrade.state.paused': "Upgrade Paused",
'admin.stackUpgrade.state.stopped': "Upgrade Stopped",
'admin.stackUpgrade.state.completed': "Upgrade Finished",
+ 'admin.stackUpgrade.state.failed': "Upgrade Failed",
'admin.stackUpgrade.state.upgrading': "Upgrading...",
'admin.stackUpgrade.hosts': "hosts",
'admin.stackUpgrade.host': "host",
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/routes/stack_upgrade_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/stack_upgrade_routes.js b/ambari-web/app/routes/stack_upgrade_routes.js
index aca2c62..154a95b 100644
--- a/ambari-web/app/routes/stack_upgrade_routes.js
+++ b/ambari-web/app/routes/stack_upgrade_routes.js
@@ -27,12 +27,16 @@ module.exports = App.WizardRoute.extend({
App.router.get('updateController').set('isWorking', false);
return App.ModalPopup.show({
+ classNames: ['full-width-modal'],
header: function () {
return Em.I18n.t('admin.stackUpgrade.dialog.header').format(App.router.get('mainAdminStackAndUpgradeController').get('upgradeVersion'));
}.property('App.router.mainAdminStackAndUpgradeController.upgradeVersion'),
bodyClass: App.upgradeWizardView,
primary: null,
secondary: null,
+ didInsertElement: function () {
+ this.fitHeight();
+ },
onClose: function() {
var self = this;
var header = Em.I18n.t('admin.stackUpgrade.state.paused');
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index aa5e8b7..1fa74fc 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -6551,8 +6551,8 @@ i.icon-asterisks {
#stack-upgrade-dialog {
.task-list {
- overflow: auto;
- .task-details {
+ overflow-x: hidden;
+ .details-box {
padding: 2px 4px;
margin-left: 15px;
.button-row {
@@ -6569,12 +6569,20 @@ i.icon-asterisks {
.progress {
margin-bottom: 0;
}
- }
- .task-list>div {
- padding: 5px;
+ padding-left: 20px;
i {
margin-right: 5px;
}
+ .task-details {
+ .manage-controls a {
+ cursor: pointer;
+ margin-right: 12px;
+ }
+ textarea {
+ width: 100%;
+ min-height: 100px;
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/templates/common/error_log_body.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/error_log_body.hbs b/ambari-web/app/templates/common/error_log_body.hbs
index 62f1b65..b532901 100644
--- a/ambari-web/app/templates/common/error_log_body.hbs
+++ b/ambari-web/app/templates/common/error_log_body.hbs
@@ -20,9 +20,9 @@
<div class="content-area">
<div class="task-detail-log-clipboard-wrap"></div>
<div class="task-detail-log-maintext">
- <h5>stderr: <span class="muted">{{view.openedTask.errorLog}} </span></h5>
+ <h5>{{t common.stderr}}: <span class="muted">{{view.openedTask.errorLog}} </span></h5>
<pre class="stderr">{{view.openedTask.stderr}}</pre>
- <h5>stdout: <span class="muted"> {{view.openedTask.outputLog}} </span></h5>
+ <h5>{{t common.stdout}}: <span class="muted"> {{view.openedTask.outputLog}} </span></h5>
<pre class="stdout">{{view.openedTask.stdout}}</pre>
{{#if view.openedTask.structuredOut}}
<h5>structured_out: </h5>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/templates/common/host_progress_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/host_progress_popup.hbs b/ambari-web/app/templates/common/host_progress_popup.hbs
index 01008f3..e5469ec 100644
--- a/ambari-web/app/templates/common/host_progress_popup.hbs
+++ b/ambari-web/app/templates/common/host_progress_popup.hbs
@@ -226,9 +226,9 @@
</div>
<hr>
{{/if}}
- <h5>stderr: <span class="muted">{{view.openedTask.errorLog}} </span></h5>
+ <h5>{{t common.stderr}}: <span class="muted">{{view.openedTask.errorLog}} </span></h5>
<pre class="stderr">{{view.openedTask.stderr}}</pre>
- <h5>stdout: <span class="muted"> {{view.openedTask.outputLog}} </span></h5>
+ <h5>{{t common.stdout}}: <span class="muted"> {{view.openedTask.outputLog}} </span></h5>
<pre class="stdout">{{view.openedTask.stdout}}</pre>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_dialog.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_dialog.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_dialog.hbs
index 492e4e9..8509801 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_dialog.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_dialog.hbs
@@ -19,7 +19,7 @@
<div id="stack-upgrade-dialog">
{{#if view.isLoaded}}
<div class="row-fluid">
- <div class="span2">{{t common.progress}}</div>
+ <div class="span2">{{statusIcon controller.upgradeData.Upgrade.request_status}} {{view.upgradeStatusLabel}}</div>
<div class="span9">
<div class="progress progress-striped active">
<div class="bar" {{bindAttr style="view.progressWidth"}}></div>
@@ -30,9 +30,9 @@
</div>
</div>
- <div class="task-list">
- {{#each group in view.groups}}
- {{view App.upgradeTaskView contentBinding="group"}}
+ <div class="task-list limited-height-2">
+ {{#each group in controller.upgradeData.upgradeGroups}}
+ {{view App.upgradeGroupView contentBinding="group"}}
{{/each}}
</div>
{{else}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_group.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_group.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_group.hbs
new file mode 100644
index 0000000..f9dcdfc
--- /dev/null
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_group.hbs
@@ -0,0 +1,148 @@
+{{!
+* 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.
+}}
+
+
+<div class="row-fluid">
+ <div {{bindAttr class="view.content.isActive::not-active-link :span8"}}>
+ {{statusIcon view.content.status}}
+ <a href="#" {{action toggleExpanded view.content controller.upgradeData.upgradeGroups target="view"}}>{{view.content.title}}</a>
+ </div>
+ {{#if view.content.isRunning}}
+ <div class="span3">
+ <div class="progress progress-striped active">
+ <div class="bar" {{bindAttr style="view.content.progressWidth"}}></div>
+ </div>
+ </div>
+ <div class="span1">
+ <div>{{view.content.progress}}%</div>
+ </div>
+ {{/if}}
+</div>
+
+<div {{bindAttr class="view.content.isExpanded::hidden :task-list"}}>
+
+ {{! List of UpgradeItem}}
+ {{#each item in view.content.upgradeItems}}
+ <div class="row-fluid">
+ <div {{bindAttr class="item.isActive::not-active-link :span8"}}>
+ {{statusIcon item.status}}
+ <a href="#" {{action toggleExpanded item view.content.upgradeItems target="view"}}>{{item.context}}</a>
+ </div>
+ {{#if item.isRunning}}
+ <div class="span3">
+ <div class="progress progress-striped active">
+ <div class="bar" {{bindAttr style="item.progressWidth"}}></div>
+ </div>
+ </div>
+ <div class="span1">
+ <div>{{item.progress}}%</div>
+ </div>
+ {{/if}}
+ </div>
+ {{#if item.isExpanded}}
+
+ {{! List of Tasks}}
+ <div class="task-list">
+ {{#each task in item.tasks}}
+ <div {{bindAttr class="task.isActive::not-active-link"}}>{{statusIcon task.status}}<a href="#" {{action toggleExpanded task item.tasks target="view"}}>{{task.command_detail}}</a></div>
+ {{#if task.isExpanded}}
+ <div class="task-details task-detail-info">
+ <ul class="nav nav-tabs">
+ <li class="active"><a href="#tab1" data-toggle="tab">{{t common.stdout}}</a></li>
+ <li><a href="#tab2" data-toggle="tab">{{t common.stderr}}</a></li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" id="tab1">
+ <p>{{task.host_name}}</p>
+ <div class="row-fluid">
+ <p class="pull-left">{{task.output_log}}</p>
+ <div class="manage-controls pull-right">
+ <a title="Click to Copy" {{action copyOutLog task target="view"}} class="task-detail-copy">
+ <i class="icon-copy"></i> {{t common.copy}}
+ </a>
+ <a title="Open in New Window" {{action openLogWindow task.stdout target="view"}} class="task-detail-open-dialog">
+ <i class="icon-external-link"></i> {{t common.open}}
+ </a>
+ </div>
+ </div>
+ <pre {{bindAttr class="task.outputLogOpened:hidden :stdout"}}>{{task.stdout}}</pre>
+ {{view Ember.TextArea valueBinding="task.stdout" classBinding="task.outputLogOpened::hidden" readonly="readonly"}}
+ </div>
+ <div class="tab-pane" id="tab2">
+ <p>{{task.host_name}}</p>
+ <div class="row-fluid">
+ <p class="pull-left">{{task.error_log}}</p>
+ <div class="manage-controls pull-right">
+ <a title="Click to Copy" {{action copyErrLog task target="view"}} class="task-detail-copy">
+ <i class="icon-copy"></i> {{t common.copy}}
+ </a>
+ <a title="Open in New Window" {{action openLogWindow task.stderr target="view"}} class="task-detail-open-dialog">
+ <i class="icon-external-link"></i> {{t common.open}}
+ </a>
+ </div>
+ </div>
+ <pre {{bindAttr class="task.errorLogOpened:hidden :stderr"}}>{{task.stderr}}</pre>
+ {{view Ember.TextArea valueBinding="task.stderr" classBinding="task.errorLogOpened::hidden" readonly="readonly"}}
+ </div>
+ </div>
+ </div>
+ {{/if}}
+ {{/each}}
+ </div>
+ {{/if}}
+ {{/each}}
+</div>
+
+{{#unless view.content.isExpanded}}
+ {{#if view.showProgressInfo}}
+ <div class="box details-box">
+ <div>
+ {{t admin.stackUpgrade.dialog.inProgress}}
+ <a href>{{view.runningItem.context}}</a>
+ </div>
+ </div>
+ {{/if}}
+ {{#if view.isFailed}}
+ <div class="box details-box">
+ <div>
+ {{t admin.stackUpgrade.dialog.failed}}
+ <a href>{{view.failedItem.name}}</a>
+ </div>
+ <div class="button-row">
+ <button class="btn btn-danger">{{t admin.stackUpgrade.dialog.stop}}</button>
+ <button class="btn btn-warning">{{t admin.stackUpgrade.dialog.continue}}</button>
+ <button class="btn">{{t common.retry}}</button>
+ </div>
+ </div>
+ {{/if}}
+ {{#if view.isManualOpened}}
+ <div class="box details-box">
+ <p><strong>{{t admin.stackUpgrade.dialog.manual}}</strong></p>
+
+ <div class="message">
+ {{view Em.Checkbox checkedBinding="view.isManualDone"}}
+ {{t admin.stackUpgrade.dialog.manualDone}}
+ </div>
+ <div class="button-row">
+ <button class="btn btn-danger">{{t admin.stackUpgrade.dialog.stop}}</button>
+ <button
+ class="btn btn-success" {{bindAttr disabled="view.isManualProceedDisabled"}}>{{t common.proceed}}</button>
+ </div>
+ </div>
+ {{/if}}
+{{/unless}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_task.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_task.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_task.hbs
deleted file mode 100644
index 511d04a..0000000
--- a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_task.hbs
+++ /dev/null
@@ -1,67 +0,0 @@
-{{!
-* 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.
-}}
-
-
-<div class="row-fluid">
- <div class="span8"><i {{bindAttr class="view.iconClass"}}></i><a>{{view.content.UpgradeGroup.title}}</a></div>
-
- {{#if view.showProgressBar}}
- <div class="span3">
- <div class="progress progress-striped active">
- <div class="bar" {{bindAttr style="view.progressWidth"}}></div>
- </div>
- </div>
- <div class="span1">
- <div>{{view.progress}}%</div>
- </div>
- {{/if}}
-</div>
-{{#if view.isInProgress}}
- <div class="box task-details">
- <div>
- {{t admin.stackUpgrade.dialog.inProgress}}
- <a href>{{view.runningItem.UpgradeItem.context}}</a>
- </div>
- </div>
-{{/if}}
-{{#if view.isFailed}}
- <div class="box task-details">
- <div>
- {{t admin.stackUpgrade.dialog.failed}}
- <a href>{{view.failedItem.UpgradeItem.name}}</a>
- </div>
- <div class="button-row">
- <button class="btn btn-danger">{{t admin.stackUpgrade.dialog.stop}}</button>
- <button class="btn btn-warning">{{t admin.stackUpgrade.dialog.continue}}</button>
- <button class="btn">{{t common.retry}}</button>
- </div>
- </div>
-{{/if}}
-{{#if view.isManualOpened}}
- <div class="box task-details">
- <p><strong>{{t admin.stackUpgrade.dialog.manual}}</strong></p>
- <div class="message">
- {{view Em.Checkbox checkedBinding="view.isManualDone"}}
- {{t admin.stackUpgrade.dialog.manualDone}}
- </div>
- <div class="button-row">
- <button class="btn btn-danger">{{t admin.stackUpgrade.dialog.stop}}</button>
- <button class="btn btn-success" {{bindAttr disabled="view.isManualProceedDisabled"}}>{{t common.proceed}}</button>
- </div>
- </div>
-{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/utils/ember_reopen.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ember_reopen.js b/ambari-web/app/utils/ember_reopen.js
index 7ac69db..a879cde 100644
--- a/ambari-web/app/utils/ember_reopen.js
+++ b/ambari-web/app/utils/ember_reopen.js
@@ -173,4 +173,8 @@ Em.View.reopen({
console.debug('Calling set on destroyed view');
}
}
-});
\ No newline at end of file
+});
+
+Ember.TextArea.reopen({
+ attributeBindings: ['readonly']
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/utils/helper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/helper.js b/ambari-web/app/utils/helper.js
index a58b732..8d7dc2a 100644
--- a/ambari-web/app/utils/helper.js
+++ b/ambari-web/app/utils/helper.js
@@ -723,6 +723,42 @@ App.registerBoundHelper('formatWordBreak', Em.View.extend({
}));
/**
+ * Return <i></i> with class that correspond to status
+ *
+ * @param {string} content - status
+ *
+ * Examples:
+ *
+ * {{statusIcon view.status}}
+ * returns 'icon-cog'
+ *
+ */
+App.registerBoundHelper('statusIcon', Em.View.extend({
+ tagName: 'i',
+
+ /**
+ * relation map between status and icon class
+ * @type {object}
+ */
+ statusIconMap: {
+ 'COMPLETED': 'icon-ok',
+ 'WARNING': 'icon-warning-sign',
+ 'FAILED': 'icon-warning-sign',
+ 'PENDING': 'icon-cog',
+ 'IN_PROGRESS': 'icon-cogs',
+ 'HOLDING': 'icon-pause'
+ },
+
+ classNameBindings: ['iconClass'],
+ /**
+ * @type {string}
+ */
+ iconClass: function () {
+ return this.get('statusIconMap')[this.get('content')] || 'icon-question-sign';
+ }.property('content')
+}));
+
+/**
* Ambari overrides the default date transformer.
* This is done because of the non-standard data
* sent. For example Nagios sends date as "12345678".
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index c19139a..ab4acb8 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -105,7 +105,7 @@ require('views/main/admin/serviceAccounts_view');
require('views/main/admin/stack_upgrade');
require('views/main/admin/stack_upgrade/upgrade_wizard_view');
require('views/main/admin/stack_upgrade/upgrade_version_box_view');
-require('views/main/admin/stack_upgrade/upgrade_task_view');
+require('views/main/admin/stack_upgrade/upgrade_group_view');
require('views/main/admin/stack_and_upgrade_view');
require('views/main/admin/stack_versions/menu');
require('views/main/admin/stack_versions/repo_version_view');
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/views/main/admin/stack_upgrade/upgrade_group_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_group_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_group_view.js
new file mode 100644
index 0000000..23968d1
--- /dev/null
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_group_view.js
@@ -0,0 +1,115 @@
+/**
+ * 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');
+
+App.upgradeGroupView = Em.View.extend({
+ templateName: require('templates/main/admin/stack_upgrade/upgrade_group'),
+
+ /**
+ * @type {boolean}
+ */
+ isManualDone: false,
+
+ /**
+ * progress info is a box that show running UpgradeItem
+ * @type {boolean}
+ */
+ showProgressInfo: function () {
+ return this.get('content.isRunning') && this.get('runningItem');
+ }.property('content.isRunning', 'runningItem'),
+
+ /**
+ * @type {boolean}
+ */
+ isManualProceedDisabled: function () {
+ return !this.get('isManualDone');
+ }.property('isManualDone'),
+
+ /**
+ * @type {boolean}
+ */
+ isFailed: function () {
+ return this.get('content.status') === 'FAILED';
+ }.property('content.status'),
+
+ /**
+ * if upgrade group is in progress it should have currently running item
+ * @type {object|undefined}
+ */
+ runningItem: function () {
+ return this.get('content.upgradeItems').findProperty('status', 'IN_PROGRESS');
+ }.property('content.upgradeItems.@each.status'),
+
+ /**
+ * if upgrade group is failed it should have failed item
+ * @type {object|undefined}
+ */
+ failedItem: function () {
+ return this.get('content.upgradeItems').findProperty('status', 'FAILED');
+ }.property('content.upgradeItems.@each.status'),
+
+ /**
+ * @type {boolean}
+ */
+ isManualOpened: function () {
+ return this.get('content.status') === 'HOLDING';
+ }.property('content.status'),
+
+ /**
+ * Only one UpgradeGroup or UpgradeItem could be expanded at a time
+ * @param {object} event
+ */
+ toggleExpanded: function (event) {
+ event.contexts[1].forEach(function (item) {
+ if (item == event.context) {
+ item.set('isExpanded', !event.context.get('isExpanded'));
+ } else {
+ item.set('isExpanded', false);
+ }
+ });
+ },
+
+ /**
+ *
+ * @param {object} event
+ */
+ copyErrLog: function(event) {
+ event.context.toggleProperty('errorLogOpened');
+ },
+
+ /**
+ *
+ * @param {object} event
+ */
+ openLogWindow: function(event) {
+ var newWindow = window.open();
+ var newDocument = newWindow.document;
+ newDocument.write(event.context);
+ newDocument.close();
+ },
+
+ /**
+ *
+ * @param {object} event
+ */
+ copyOutLog: function(event) {
+ event.context.toggleProperty('outputLogOpened');
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/views/main/admin/stack_upgrade/upgrade_task_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_task_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_task_view.js
deleted file mode 100644
index bf57734..0000000
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_task_view.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * 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');
-
-App.upgradeTaskView = Em.View.extend({
- templateName: require('templates/main/admin/stack_upgrade/upgrade_task'),
-
- /**
- * relation map between status and icon class
- * @type {Object}
- */
- statusIconMap: {
- 'COMPLETED': 'icon-ok',
- 'WARNING': 'icon-warning-sign',
- 'FAILED': 'icon-warning-sign',
- 'PENDING': 'icon-cog',
- 'IN_PROGRESS': 'icon-cogs'
- },
-
- /**
- * @type {Boolean}
- */
- isManualDone: false,
-
- /**
- * @type {Boolean}
- */
- isManualProceedDisabled: function () {
- return !this.get('isManualDone');
- }.property('isManualDone'),
-
- /**
- * @type {string}
- */
- iconClass: function () {
- return this.get('statusIconMap')[this.get('content.UpgradeGroup.status')] || 'icon-question-sign';
- }.property('content.UpgradeGroup.status'),
-
- /**
- * @type {Boolean}
- */
- isFailed: function () {
- return this.get('content.UpgradeGroup.status') === 'FAILED';
- }.property('content.UpgradeGroup.status'),
-
- /**
- * @type {Boolean}
- */
- showProgressBar: function () {
- return ['IN_PROGRESS', 'FAILED'].contains(this.get('content.UpgradeGroup.status')) && this.get('content.UpgradeGroup.type') !== 'manual';
- }.property('content.UpgradeGroup.status'),
-
- /**
- * @type {Boolean}
- */
- isInProgress: function () {
- return this.get('content.UpgradeGroup.status') === 'IN_PROGRESS' && this.get('content.UpgradeGroup.type') !== 'manual';
- }.property('content.UpgradeGroup.status'),
-
- /**
- * width style of progress bar
- * @type {String}
- */
- progressWidth: function () {
- return "width:" + Math.floor(this.get('progress')) + '%;';
- }.property('content.UpgradeGroup.progress_percent'),
-
- /**
- * @type {number}
- */
- progress: function () {
- return Math.floor(this.get('content.UpgradeGroup.progress_percent'))
- }.property('content.UpgradeGroup.progress_percent'),
-
- /**
- * if upgrade group is in progress it should have currently running item
- * @type {Object|null}
- */
- runningItem: function () {
- return this.get('content.upgrade_items').findProperty('UpgradeItem.status', 'IN_PROGRESS');
- }.property('content.upgrade_items.@each.UpgradeItem.status'),
-
- /**
- * if upgrade group is failed it should have failed item
- * @type {Object|null}
- */
- failedItem: function () {
- return this.get('content.upgrade_items').findProperty('UpgradeItem.status', 'FAILED');
- }.property('content.upgrade_items.@each.UpgradeItem.status'),
-
- /**
- * @type {Boolean}
- */
- isManualOpened: function () {
- //TODO modify logic according to actual API
- return this.get('content.UpgradeGroup.status') === 'IN_PROGRESS' && this.get('content.UpgradeGroup.type') === 'manual'
- }.property('content.UpgradeGroup.status', 'content.UpgradeGroup.type')
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
index b3eaab7..d617437 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
@@ -52,6 +52,30 @@ App.upgradeWizardView = Em.View.extend({
}.property('controller.upgradeData.Upgrade.progress_percent'),
/**
+ * label of Upgrade status
+ * @type {string}
+ */
+ upgradeStatusLabel: function() {
+ switch (this.get('controller.upgradeData.Upgrade.request_status')) {
+ case 'PENDING':
+ case 'IN_PROGRESS':
+ return Em.I18n.t('admin.stackUpgrade.state.inProgress');
+ break;
+ case 'COMPLETED':
+ return Em.I18n.t('admin.stackUpgrade.state.completed');
+ break;
+ case 'HOLDING':
+ return Em.I18n.t('admin.stackUpgrade.state.paused');
+ break;
+ case 'FAILED':
+ return Em.I18n.t('admin.stackUpgrade.state.paused');
+ break;
+ default:
+ return ""
+ }
+ }.property('controller.upgradeData.Upgrade.request_status'),
+
+ /**
* start polling upgrade data
*/
startPolling: function () {
@@ -88,12 +112,5 @@ App.upgradeWizardView = Em.View.extend({
self.get('controller').loadUpgradeData();
self.doPolling();
}, App.bgOperationsUpdateInterval));
- },
-
- /**
- * @type {Array}
- */
- groups: function () {
- return this.get('controller.upgradeData.upgrade_groups');
- }.property('controller.upgradeData.upgrade_groups')
+ }
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js b/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
index 104dfca..f20d9a4 100644
--- a/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
+++ b/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
@@ -186,22 +186,28 @@ describe('App.MainAdminStackAndUpgradeController', function() {
});
describe("#loadUpgradeDataSuccessCallback()", function() {
+ beforeEach(function () {
+ sinon.stub(controller, 'updateUpgradeData', Em.K);
+ });
+ afterEach(function () {
+ controller.updateUpgradeData.restore();
+ });
it("", function() {
var data = {
"Upgrade": {
"request_status": "COMPLETED"
},
"upgrade_groups": [
- {
- "UpgradeGroup": {
- "id": 1
- },
- "upgrade_items": []
- }
- ]};
+ {
+ "UpgradeGroup": {
+ "id": 1
+ },
+ "upgrade_items": []
+ }
+ ]};
controller.loadUpgradeDataSuccessCallback(data);
- expect(controller.get('upgradeData')).to.eql(data);
expect(App.get('upgradeState')).to.equal('COMPLETED');
+ expect(controller.updateUpgradeData.called).to.be.true;
});
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/test/views/main/admin/stack_upgrade/upgrade_group_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_group_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_group_view_test.js
new file mode 100644
index 0000000..f9002e8
--- /dev/null
+++ b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_group_view_test.js
@@ -0,0 +1,40 @@
+/**
+ * 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');
+require('views/main/admin/stack_upgrade/upgrade_group_view');
+
+describe('App.upgradeGroupView', function () {
+ var view = App.upgradeGroupView.create({
+ content: Em.Object.create({})
+ });
+
+ describe("#isFailed", function () {
+ it("task is not failed", function () {
+ view.set('content.status', 'COMPLETED');
+ view.propertyDidChange('isFailed');
+ expect(view.get('isFailed')).to.be.false;
+ });
+ it("task is not failed", function () {
+ view.set('content.status', 'FAILED');
+ view.propertyDidChange('isFailed');
+ expect(view.get('isFailed')).to.be.true;
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2f8de0be/ambari-web/test/views/main/admin/stack_upgrade/upgrade_task_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_task_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_task_view_test.js
deleted file mode 100644
index b40ea28..0000000
--- a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_task_view_test.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * 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');
-require('views/main/admin/stack_upgrade/upgrade_task_view');
-
-describe('App.upgradeTaskView', function () {
- var view = App.upgradeTaskView.create({
- content: Em.Object.create({
- UpgradeGroup: {}
- })
- });
-
- describe("#iconClass", function () {
- it("status has icon", function () {
- view.set('statusIconMap', {
- 'S1': 'icon1'
- });
- view.set('content.UpgradeGroup.status', 'S1');
- view.propertyDidChange('iconClass');
- expect(view.get('iconClass')).to.equal('icon1');
- });
- it("status undefined", function () {
- view.set('statusIconMap', {
- 'S1': 'icon1'
- });
- view.set('content.UpgradeGroup.status', 'S2');
- view.propertyDidChange('iconClass');
- expect(view.get('iconClass')).to.equal('icon-question-sign');
- });
- });
-
- describe("#isFailed", function () {
- it("task is not failed", function () {
- view.set('content.UpgradeGroup.status', 'COMPLETED');
- view.propertyDidChange('isFailed');
- expect(view.get('isFailed')).to.be.false;
- });
- it("task is not failed", function () {
- view.set('content.UpgradeGroup.status', 'FAILED');
- view.propertyDidChange('isFailed');
- expect(view.get('isFailed')).to.be.true;
- });
- });
-});