فهرست منبع

AMBARI-3622 [perf] Background operations dialog should not get all details of requests. (atkach)

atkach 11 سال پیش
والد
کامیت
c275b7312b

+ 27 - 331
ambari-web/app/assets/data/background_operations/list_on_start.json

@@ -1,341 +1,37 @@
 {
-  "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/?fields=tasks/*",
+  "href" : "http://192.168.56.101:8080/api/v1/clusters/perf/requests?to=end&page_size=10&fields=Requests",
   "items" : [
     {
-      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3",
+      "href" : "http://192.168.56.101:8080/api/v1/clusters/perf/requests/12",
       "Requests" : {
-        "id" : 3,
-        "cluster_name" : "mycluster",
-        "request_context" : "Stop Services"
-      },
-      "tasks" : [
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3/tasks/16",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "QUEUED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 16,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 3,
-            "command" : "STOP",
-            "role" : "NAMENODE",
-            "start_time" : 1352125378300,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3/tasks/15",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 15,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 3,
-            "command" : "STOP",
-            "role" : "DATANODE",
-            "start_time" : 1352125378280,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/3/tasks/17",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 17,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 3,
-            "command" : "STOP",
-            "role" : "SECONDARY_NAMENODE",
-            "start_time" : 1352125378315,
-            "stage_id" : 1
-          }
-        }
-      ]
+        "aborted_task_count" : 0,
+        "cluster_name" : "perf",
+        "completed_task_count" : 4,
+        "failed_task_count" : 0,
+        "id" : 12,
+        "progress_percent" : 100.0,
+        "queued_task_count" : 0,
+        "request_context" : "Start YARN",
+        "request_status" : "COMPLETED",
+        "task_count" : 4,
+        "timed_out_task_count" : 0
+      }
     },
     {
-      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2",
+      "href" : "http://192.168.56.101:8080/api/v1/clusters/perf/requests/13",
       "Requests" : {
-        "id" : 2,
-        "cluster_name" : "mycluster",
-        "request_context" : "Start HDFS Service"
-      },
-      "tasks" : [
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/11",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 11,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "START",
-            "role" : "JOBTRACKER",
-            "start_time" : 1352119106491,
-            "stage_id" : 2
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/14",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 14,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "EXECUTE",
-            "role" : "MAPREDUCE_SERVICE_CHECK",
-            "start_time" : 1352119157294,
-            "stage_id" : 3
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/13",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 13,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "START",
-            "role" : "TASKTRACKER",
-            "start_time" : 1352119106518,
-            "stage_id" : 2
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/12",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 12,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "START",
-            "role" : "SECONDARY_NAMENODE",
-            "start_time" : 1352119106506,
-            "stage_id" : 2
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/9",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 9,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "START",
-            "role" : "NAMENODE",
-            "start_time" : 1352119024782,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/8",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 8,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "START",
-            "role" : "DATANODE",
-            "start_time" : 1352119024765,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/2/tasks/10",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 10,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 1,
-            "request_id" : 2,
-            "command" : "EXECUTE",
-            "role" : "HDFS_SERVICE_CHECK",
-            "start_time" : 1352119106480,
-            "stage_id" : 2
-          }
-        }
-      ]
-    },
-    {
-      "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1",
-      "Requests" : {
-        "id" : 1,
-        "cluster_name" : "mycluster",
-        "request_context" : "Install Service"
-      },
-      "tasks" : [
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/1",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 1,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "DATANODE",
-            "start_time" : 1352118607290,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/4",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 4,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "MAPREDUCE_CLIENT",
-            "start_time" : 1352118607672,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/5",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 5,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "NAMENODE",
-            "start_time" : 1352118607808,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/3",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 3,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "JOBTRACKER",
-            "start_time" : 1352118607566,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/7",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 7,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "TASKTRACKER",
-            "start_time" : 1352118608124,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/2",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 2,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "HDFS_CLIENT",
-            "start_time" : 1352118607469,
-            "stage_id" : 1
-          }
-        },
-        {
-          "href" : "http://dev.hortonworks.com:8080/api/clusters/mycluster/requests/1/tasks/6",
-          "Tasks" : {
-            "exit_code" : 0,
-            "stdout" : "Output",
-            "status" : "COMPLETED",
-            "stderr" : "none",
-            "host_name" : "dev.hortonworks.com",
-            "id" : 6,
-            "cluster_name" : "mycluster",
-            "attempt_cnt" : 2,
-            "request_id" : 1,
-            "command" : "INSTALL",
-            "role" : "SECONDARY_NAMENODE",
-            "start_time" : 1352118607958,
-            "stage_id" : 1
-          }
-        }
-      ]
+        "aborted_task_count" : 0,
+        "cluster_name" : "perf",
+        "completed_task_count" : 0,
+        "failed_task_count" : 0,
+        "id" : 13,
+        "progress_percent" : 9.0,
+        "queued_task_count" : 2,
+        "request_context" : "Stop YARN",
+        "request_status" : "PENDING",
+        "task_count" : 2,
+        "timed_out_task_count" : 0
+      }
     }
   ]
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 67 - 0
ambari-web/app/assets/data/background_operations/task_by_request12.json


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 31 - 0
ambari-web/app/assets/data/background_operations/task_by_request13.json


+ 123 - 40
ambari-web/app/controllers/global/background_operations_controller.js

@@ -33,6 +33,19 @@ App.BackgroundOperationsController = Em.Controller.extend({
    */
   services:[],
   serviceTimestamp: null,
+  /**
+   * Possible levels:
+   * REQUESTS_LIST
+   * HOSTS_LIST
+   * TASKS_LIST
+   * TASK_DETAILS
+   */
+  levelInfo: Em.Object.create({
+    name: 'REQUESTS_LIST',
+    requestId: null,
+    taskId: null,
+    sync: false
+  }),
 
   /**
    * Start polling, when <code>isWorking</code> become true
@@ -45,59 +58,129 @@ App.BackgroundOperationsController = Em.Controller.extend({
   }.observes('isWorking'),
 
   /**
-   * Get all requests from server
+   * Get requests data from server
    * @param callback
    */
-  requestMostRecent: function(callback){
+  requestMostRecent: function (callback) {
+    var queryParams = this.getQueryParams();
     App.ajax.send({
-      name: 'background_operations.get_most_recent',
+      'name': queryParams.name,
       'sender': this,
-      'success': 'callBackForMostRecent',
-      'callback': callback
+      'success': queryParams.successCallback,
+      'callback': callback,
+      'data': queryParams.data
     });
   },
+  /**
+   * construct params of ajax query regarding displayed level
+   */
+  getQueryParams: function () {
+    var levelInfo = this.get('levelInfo');
+    var result = {
+      name: 'background_operations.get_most_recent',
+      successCallback: 'callBackForMostRecent',
+      data: {}
+    };
+    if (levelInfo.get('name') === 'TASK_DETAILS' && !App.testMode) {
+      result.name = 'background_operations.get_by_task';
+      result.successCallback = 'callBackFilteredByTask';
+      result.data = {
+        'taskId': levelInfo.get('taskId'),
+        'requestId': levelInfo.get('requestId'),
+        'sync': levelInfo.get('sync')
+      };
+    } else if (levelInfo.get('name') === 'TASKS_LIST' || levelInfo.get('name') === 'HOSTS_LIST') {
+      result.name = 'background_operations.get_by_request';
+      result.successCallback = 'callBackFilteredByRequest';
+      result.data = {
+        'requestId': levelInfo.get('requestId'),
+        'sync': levelInfo.get('sync')
+      };
+    }
+    levelInfo.set('sync', false);
+    return result;
+  },
+
+  /**
+   * Push hosts and their tasks to request
+   * @param data
+   * @param ajaxQuery
+   * @param params
+   */
+  callBackFilteredByRequest: function (data, ajaxQuery, params) {
+    var hostsMap = {};
+    var request = this.get('services').findProperty('id', data.Requests.id);
+    data.tasks.forEach(function (task) {
+      if (hostsMap[task.Tasks.host_name]) {
+        hostsMap[task.Tasks.host_name].logTasks.push(task);
+      } else {
+        hostsMap[task.Tasks.host_name] = {
+          name: task.Tasks.host_name,
+          publicName: task.Tasks.host_name,
+          logTasks: [task]
+        };
+      }
+    }, this);
+    request.set('hostsMap', hostsMap);
+    this.set('serviceTimestamp', new Date().getTime());
+  },
+  /**
+   * Update task, with uploading two additional properties: stdout and stderr
+   * @param data
+   * @param ajaxQuery
+   * @param params
+   */
+  callBackFilteredByTask: function (data, ajaxQuery, params) {
+    var request = this.get('services').findProperty('id', data.Tasks.request_id);
+    var host = request.get('hostsMap')[data.Tasks.host_name];
+    var task = host.logTasks.findProperty('Tasks.id', data.Tasks.id);
+    task.Tasks.status = data.Tasks.status;
+    task.Tasks.stdout = data.Tasks.stdout;
+    task.Tasks.stderr = data.Tasks.stderr;
+    this.set('serviceTimestamp', new Date().getTime());
+  },
 
   /**
-   * Prepare recived from server requests for host component popup
+   * Prepare, received from server, requests for host component popup
    * @param data
    */
-  callBackForMostRecent: function(data){
-    this.get("services").clear();
+  callBackForMostRecent: function (data) {
     var runningServices = 0;
     var self = this;
-    data.items = data.items.sort(function(a,b){return b.Requests.id - a.Requests.id});
-    data.items.forEach(function(request){
-      var hostsMap = {};
-      var isRunningTasks = false;
-      request.tasks.forEach(function (task) {
-        if (!isRunningTasks && (['QUEUED', 'IN_PROGRESS', 'PENDING'].contains(task.Tasks.status))) {
-          isRunningTasks = true;
-        }
-        if (hostsMap[task.Tasks.host_name]) {
-          hostsMap[task.Tasks.host_name].logTasks.push(task);
-        } else {
-          hostsMap[task.Tasks.host_name] = {
-            name: task.Tasks.host_name,
-            publicName: task.Tasks.host_name,
-            logTasks: [task]
-          };
-        }
-      }, this);
+    var currentRequestIds = [];
 
-      var rq = Em.Object.create({
-        id: request.Requests.id,
-        name: request.Requests.request_context || 'Request name not specified',
-        displayName: request.Requests.request_context || 'Request name not specified',
-        progress: 10,
-        status: "",
-        isRunning: isRunningTasks,
-        hostsMap: hostsMap,
-        tasks: request.tasks
-      });
-      runningServices += ~~isRunningTasks;
-      self.get("services").push(rq);
+    data.items.forEach(function (request) {
+      var rq = self.get("services").findProperty('id', request.Requests.id);
+      var isRunning = (request.Requests.task_count -
+        (request.Requests.aborted_task_count + request.Requests.completed_task_count + request.Requests.failed_task_count
+         + request.Requests.timed_out_task_count - request.Requests.queued_task_count)) > 0;
+      currentRequestIds.push(request.Requests.id);
+      if (rq) {
+        rq.set('progress', Math.round(request.Requests.progress_percent));
+        rq.set('status', request.Requests.request_status);
+        rq.set('isRunning', isRunning);
+      } else {
+        rq = Em.Object.create({
+          id: request.Requests.id,
+          name: request.Requests.request_context || 'Request name not specified',
+          displayName: request.Requests.request_context || 'Request name not specified',
+          progress: Math.round(request.Requests.progress_percent),
+          status: request.Requests.request_status,
+          isRunning: isRunning,
+          hostsMap: {},
+          tasks: []
+        });
+        self.get("services").unshift(rq);
+      }
+      runningServices += ~~isRunning;
+    });
+    //remove old request if it's absent in API response
+    self.get('services').forEach(function(service, index, services){
+      if(!currentRequestIds.contains(service.id)) {
+        services.splice(index, 1);
+      }
     });
-    self.set("allOperationsCount",runningServices);
+    self.set("allOperationsCount", runningServices);
     self.set('serviceTimestamp', new Date().getTime());
   },
 
@@ -109,7 +192,7 @@ App.BackgroundOperationsController = Em.Controller.extend({
    */
   showPopup: function(){
     App.updater.immediateRun('requestMostRecent');
-    if(this.get('popupView') && App.HostPopup.get('showServices')){
+    if(this.get('popupView') && App.HostPopup.get('isBackgroundOperations')){
       this.set('popupView.isOpen', true);
       $(this.get('popupView.element')).appendTo('#wrapper');
     } else {

+ 1 - 1
ambari-web/app/templates/common/host_progress_popup.hbs

@@ -65,7 +65,7 @@
 
   <div {{bindAttr class="view.isHostListHidden:hidden :task-list-main-warp"}}>
     <div class="task-top-wrap">
-      {{#if controller.showServices}}
+      {{#if controller.isBackgroundOperations}}
         <a class="task-detail-back-to-hosts" href="javascript:void(null)" {{action backToServiceList}} >
           <i class="icon-arrow-left"></i>&nbsp;{{t common.operations}}
         </a>

+ 19 - 9
ambari-web/app/utils/ajax.js

@@ -30,20 +30,30 @@ var App = require('app');
  * @type {Object}
  */
 var urls = {
-  'background_operations': {
-    'real': '/clusters/{clusterName}/requests/?fields=tasks/*',
+  'background_operations.get_most_recent': {
+    'real': '/clusters/{clusterName}/requests?to=end&page_size=10&fields=Requests',
     'mock': '/data/background_operations/list_on_start.json',
     'testInProduction': true
   },
-  'background_operations.update_task': {
-    'real': '/clusters/{clusterName}/requests/{requestId}/tasks/{taskId}',
-    'mock': '/data/background_operations/one_task.json',
-    'testInProduction': true
+  'background_operations.get_by_request': {
+    'real': '/clusters/{clusterName}/requests/{requestId}?fields=*,tasks/Tasks/command,tasks/Tasks/exit_code,tasks/Tasks/host_name,tasks/Tasks/id,tasks/Tasks/role,tasks/Tasks/status',
+    'mock': '/data/background_operations/task_by_request{requestId}.json',
+    'testInProduction': true,
+    'format': function (data) {
+      return {
+        async: !data.sync
+      };
+    }
   },
-  'background_operations.get_most_recent': {
-    'real': '/clusters/{clusterName}/requests?to=end&page_size=10&fields=*,tasks/Tasks/*',
+  'background_operations.get_by_task': {
+    'real': '/clusters/{clusterName}/requests/{requestId}/tasks/{taskId}',
     'mock': '/data/background_operations/list_on_start.json',
-    'testInProduction': true
+    'testInProduction': true,
+    'format': function (data) {
+      return {
+        async: !data.sync
+      };
+    }
   },
   'service.item.start_stop': {
     'real': '/clusters/{clusterName}/services/{serviceName}?params/run_smoke_test=true',

+ 92 - 71
ambari-web/app/utils/host_progress_popup.js

@@ -30,8 +30,8 @@ App.HostPopup = Em.Object.create({
   currentServiceId: null,
   previousServiceId: null,
   popupHeaderName: "",
-  serviceController: null,
-  showServices: false,
+  dataSourceController: null,
+  isBackgroundOperations: false,
   currentHostName: null,
   isPopup: null,
 
@@ -51,18 +51,18 @@ App.HostPopup = Em.Object.create({
    * Entering point of this component
    * @param serviceName
    * @param controller
-   * @param showServices
+   * @param isBackgroundOperations
    */
-  initPopup: function (serviceName, controller, showServices) {
-    if (!showServices) {
+  initPopup: function (serviceName, controller, isBackgroundOperations) {
+    if (!isBackgroundOperations) {
       this.clearHostPopup();
       this.set("popupHeaderName", serviceName);
     }
     this.set("serviceName", serviceName);
-    this.set("serviceController", controller);
-    this.set("showServices", showServices);
-    this.set("inputData", this.get("serviceController.services"));
-    if(this.get('showServices')){
+    this.set("dataSourceController", controller);
+    this.set("isBackgroundOperations", isBackgroundOperations);
+    this.set("inputData", this.get("dataSourceController.services"));
+    if(isBackgroundOperations){
       this.onServiceUpdate();
     } else {
       this.onHostUpdate();
@@ -78,10 +78,9 @@ App.HostPopup = Em.Object.create({
     this.set('currentServiceId', null);
     this.set('previousServiceId', null);
     this.set('popupHeaderName', "");
-    this.set('serviceController', null);
-    this.set('showServices', false);
+    this.set('dataSourceController', null);
     this.set('currentHostName', null);
-    this.get('isPopup')?this.get('isPopup').remove():null;
+    this.get('isPopup') ? this.get('isPopup').remove() : null;
   },
 
   /**
@@ -206,13 +205,12 @@ App.HostPopup = Em.Object.create({
 
   /**
    * For Background operation popup calculate number of running Operations, and set popup header
+   * @param isServiceListHidden
    */
-  setBackgroundOperationHeader: function () {
-    if (this.get("showServices")) {
+  setBackgroundOperationHeader: function (isServiceListHidden) {
+    if (this.get('isBackgroundOperations') && !isServiceListHidden) {
       var numRunning =  App.router.get('backgroundOperationsController.allOperationsCount');
       this.set("popupHeaderName", numRunning + Em.I18n.t('hostPopup.header.postFix'));
-    } else {
-      this.set("popupHeaderName", this.get("serviceName"));
     }
   },
 
@@ -220,41 +218,38 @@ App.HostPopup = Em.Object.create({
    * Create services obj data structure for popup
    * Set data for services
    */
-  onServiceUpdate: function () {
-    if (this.get('showServices') && this.get("inputData")) {
+  onServiceUpdate: function (isServiceListHidden) {
+    if (this.get('isBackgroundOperations') && this.get("inputData")) {
       var self = this;
       var allNewServices = [];
+      var statuses = {
+        'FAILED': ['FAILED', 'icon-exclamation-sign', 'progress-danger', false],
+        'ABORTED': ['CANCELLED', 'icon-minus', 'progress-warning', false],
+        'TIMEDOUT': ['TIMEDOUT', 'icon-time', 'progress-warning', false],
+        'IN_PROGRESS': ['IN_PROGRESS', 'icon-cogs', 'progress-info', true],
+        'COMPLETED': ['SUCCESS', 'icon-ok', 'progress-success', false]
+      };
+      var pendingStatus = ['PENDING', 'icon-cog', 'progress-info', true];
       this.set("servicesInfo", null);
       this.get("inputData").forEach(function (service) {
+        var status = statuses[service.status] || pendingStatus;
         var newService = Ember.Object.create({
           id: service.id,
           displayName: service.displayName,
-          detailMessage: service.detailMessage,
-          message: service.message,
-          progress: 0,
-          status: App.format.taskStatus("PENDING"),
+          progress: service.progress,
+          status: App.format.taskStatus(status[0]),
+          isRunning: service.isRunning,
           name: service.name,
           isVisible: true,
-          icon: 'icon-cog',
-          barColor: 'progress-info',
-          barWidth: 'width:0%;'
+          icon: status[1],
+          barColor: status[2],
+          isInProgress: status[3],
+          barWidth: "width:" + service.progress + "%;"
         });
-        var allTasks = service.tasks;
-
-        if (allTasks.length > 0) {
-          var status = self.getStatus(allTasks);
-          var progress = self.getProgress(allTasks);
-          newService.set('status', App.format.taskStatus(status[0]));
-          newService.set('icon', status[1]);
-          newService.set('barColor', status[2]);
-          newService.set('isInProgress', status[3]);
-          newService.set('progress', progress);
-          newService.set('barWidth', "width:" + progress + "%;");
-        }
         allNewServices.push(newService);
       });
       self.set('servicesInfo', allNewServices);
-      if (this.get("serviceName") == "") this.setBackgroundOperationHeader();
+      this.setBackgroundOperationHeader(isServiceListHidden);
     }
   },
 
@@ -283,31 +278,33 @@ App.HostPopup = Em.Object.create({
    */
   onHostUpdate: function () {
     var self = this;
-    if (this.get("inputData")) {
+    var inputData = this.get("inputData");
+    if (inputData) {
       var hostsArr = [];
-      var hostsData = this.get("inputData");
+      var hostsData;
       var hostsMap = {};
-      if (!this.get("showServices") || this.get("serviceName")) {
-        if (this.get("currentServiceId") != null) {
-          hostsData = hostsData.findProperty("id", this.get("currentServiceId"));
-        } else {
-          hostsData = hostsData.findProperty("name", this.get("serviceName"));
-        }
 
-        if (hostsData) {
-          if (hostsData.hostsMap) {
-            hostsMap = hostsData.hostsMap;
-          } else if (hostsData.hosts) {
-            //hosts data come from wizard as array
-            hostsData.hosts.forEach(function (_host) {
-              hostsMap[_host.name] = _host;
-            });
-          }
+      if(this.get('isBackgroundOperations') && this.get("currentServiceId")){
+        //hosts popup for Background Operations
+        hostsData = inputData.findProperty("id", this.get("currentServiceId"));
+      } else if (this.get("serviceName")) {
+        //hosts popup for Wizards
+        hostsData = inputData.findProperty("name", this.get("serviceName"));
+      }
+      if (hostsData) {
+        if (hostsData.hostsMap) {
+          //hosts data come from Background Operations as object map
+          hostsMap = hostsData.hostsMap;
+        } else if (hostsData.hosts) {
+          //hosts data come from Wizard as array
+          hostsData.hosts.forEach(function (_host) {
+            hostsMap[_host.name] = _host;
+          });
         }
       }
       var existedHosts = self.get('hosts');
 
-      if (existedHosts && this.get('currentServiceId') === this.get('previousServiceId')) {
+      if (existedHosts && (existedHosts.length > 0) && this.get('currentServiceId') === this.get('previousServiceId')) {
         existedHosts.forEach(function (host) {
           var newHostInfo = hostsMap[host.get('name')];
           if (newHostInfo) {
@@ -461,7 +458,7 @@ App.HostPopup = Em.Object.create({
     var self = this;
     var hostsInfo = this.get("hosts");
     var servicesInfo = this.get("servicesInfo");
-    var showServices = this.get('showServices');
+    var isBackgroundOperations = this.get('isBackgroundOperations');
     var categoryObject = Em.Object.extend({
       value: '',
       count: 0,
@@ -472,7 +469,7 @@ App.HostPopup = Em.Object.create({
     });
     self.set('isPopup', App.ModalPopup.show({
       //no need to track is it loaded when popup contain only list of hosts
-      isLoaded: !showServices,
+      isLoaded: !isBackgroundOperations,
       isOpen: false,
       didInsertElement: function(){
         this.set('isOpen', true);
@@ -485,8 +482,9 @@ App.HostPopup = Em.Object.create({
       autoHeight: false,
       closeModelPopup: function () {
         this.set('isOpen', false);
-        if(showServices){
+        if(isBackgroundOperations){
           $(this.get('element')).detach();
+          App.router.get('backgroundOperationsController').set('levelInfo.name', 'REQUESTS_LIST');
         } else {
           this.hide();
           self.set('isPopup', null);
@@ -515,8 +513,7 @@ App.HostPopup = Em.Object.create({
         services: self.get('servicesInfo'),
 
         tasks: function () {
-          if (!this.get('controller.currentHostName')) return [];
-          if (this.get('hosts') && this.get('hosts').length) {
+          if (this.get('hosts') && this.get('hosts').length && this.get('controller.currentHostName')) {
             var currentHost = this.get('hosts').findProperty('name', this.get('controller.currentHostName'));
             if (currentHost) {
               return currentHost.get('tasks');
@@ -525,15 +522,11 @@ App.HostPopup = Em.Object.create({
           return [];
         }.property('hosts.@each.tasks', 'hosts.@each.tasks.@each.status'),
 
-        didInsertElement: function () {
-          this.setOnStart();
-        },
-
         /**
          * Preset values on init
          */
         setOnStart: function () {
-          if (this.get("controller.showServices")) {
+          if (this.get("controller.isBackgroundOperations")) {
             this.get('controller').setSelectCount(this.get("services"), this.get('categories'));
             this.updateHostInfo();
           } else {
@@ -551,7 +544,7 @@ App.HostPopup = Em.Object.create({
             this.set('isTaskListHidden', true);
             this.set('isHostListHidden', true);
             this.set('isServiceListHidden', false);
-            this.get("controller").setBackgroundOperationHeader();
+            this.get("controller").setBackgroundOperationHeader(false);
             this.setOnStart();
           }
         }.observes('parentView.isOpen'),
@@ -562,8 +555,8 @@ App.HostPopup = Em.Object.create({
         updateHostInfo: function () {
           if(!this.get('parentView.isOpen')) return;
           this.set('parentView.isLoaded', false);
-          this.get("controller").set("inputData", this.get("controller.serviceController.services"));
-          this.get("controller").onServiceUpdate();
+          this.get("controller").set("inputData", this.get("controller.dataSourceController.services"));
+          this.get("controller").onServiceUpdate(this.get('isServiceListHidden'));
           this.get("controller").onHostUpdate();
           this.set('parentView.isLoaded', true);
           //push hosts into view when none or all hosts are loaded
@@ -571,7 +564,7 @@ App.HostPopup = Em.Object.create({
             this.set("hosts", this.get("controller.hosts"));
           }
           this.set("services", this.get("controller.servicesInfo"));
-        }.observes("controller.serviceController.serviceTimestamp"),
+        }.observes("controller.dataSourceController.serviceTimestamp"),
 
         /**
          * Depending on service filter, set which services should be shown
@@ -677,6 +670,29 @@ App.HostPopup = Em.Object.create({
           }
         }.observes('tasks.@each.status', 'hosts.@each.status', 'isTaskListHidden', 'isHostListHidden', 'services.length', 'services.@each.status'),
 
+        /**
+         * control data uploading, depending on which display level is showed
+         * @param levelName
+         */
+        switchLevel: function (levelName) {
+          if (this.get("controller.isBackgroundOperations")) {
+            var BGController = App.router.get('backgroundOperationsController');
+            var levelInfo = BGController.get('levelInfo');
+            levelInfo.set('taskId', this.get('openedTaskId'));
+            levelInfo.set('requestId', this.get('controller.currentServiceId'));
+            levelInfo.set('name', levelName);
+            if (levelName === 'HOSTS_LIST') {
+              levelInfo.set('sync', (this.get('controller.hosts').length === 0));
+              BGController.requestMostRecent();
+            } else if (levelName === 'TASK_DETAILS') {
+              levelInfo.set('sync', true);
+              BGController.requestMostRecent();
+            } else if (levelName === 'REQUESTS_LIST') {
+              this.get('controller.hosts').clear();
+              BGController.requestMostRecent();
+            }
+          }
+        },
         /**
          * Onclick handler for button <-Tasks
          * @param event
@@ -699,6 +715,7 @@ App.HostPopup = Em.Object.create({
           this.set("isTaskListHidden", true);
           this.set("tasks", null);
           this.get("controller").set("popupHeaderName", this.get("controller.serviceName"));
+          this.switchLevel("HOSTS_LIST");
         },
 
         /**
@@ -713,7 +730,8 @@ App.HostPopup = Em.Object.create({
           this.set("isTaskListHidden", true);
           this.set("tasks", null);
           this.set("hosts", null);
-          this.get("controller").setBackgroundOperationHeader();
+          this.get("controller").setBackgroundOperationHeader(false);
+          this.switchLevel("REQUESTS_LIST");
         },
 
         /**
@@ -725,6 +743,7 @@ App.HostPopup = Em.Object.create({
           this.get("controller").set("serviceName", event.context.get("name"));
           this.get("controller").set("currentServiceId", event.context.get("id"));
           this.get("controller").onHostUpdate();
+          this.switchLevel("HOSTS_LIST");
           var servicesInfo = this.get("controller.hosts");
           if (servicesInfo.length) {
             this.get("controller").set("popupHeaderName", event.context.get("name"));
@@ -757,6 +776,7 @@ App.HostPopup = Em.Object.create({
             this.get("controller").set("popupHeaderName", taskInfo.objectAt(0).hostName);
             this.get("controller").set("currentHostName", taskInfo.objectAt(0).hostName);
           }
+          this.switchLevel("TASKS_LIST");
           this.set('tasks', taskInfo);
           this.set("isHostListHidden", true);
           this.set("isTaskListHidden", false);
@@ -803,6 +823,7 @@ App.HostPopup = Em.Object.create({
           this.set("isHostListHidden", true);
           this.set("isTaskListHidden", true);
           this.set('openedTaskId', taskInfo.id);
+          this.switchLevel("TASK_DETAILS");
           $(".modal").scrollTop(0);
           $(".modal-body").scrollTop(0);
         },

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است