Refactor power operations

Refactored power operations to use checkHostStatus function
that checks host_status property provided by dataService,
instead of polling for host/chassis status.
Added property to check when a power operation is in progress.
This property will show/hide the in progress message and make
other operations unavailable until the operation completes.
We were previously checking whether the server_state property
was set to 'Unreachable', which enables the Power on button in
the middle of a reboot, since the server_state changes to 'Off'
during reboot.

- Removed unused $timeout service

Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: I234749a9a875c7370b52bd23ed74d6e9617cf5e2
diff --git a/app/server-control/controllers/power-operations-controller.js b/app/server-control/controllers/power-operations-controller.js
index 9713d21..986ac3b 100644
--- a/app/server-control/controllers/power-operations-controller.js
+++ b/app/server-control/controllers/power-operations-controller.js
@@ -10,11 +10,10 @@
   'use strict';
 
   angular.module('app.serverControl').controller('powerOperationsController', [
-    '$scope', 'APIUtils', 'dataService', 'Constants', '$timeout', '$interval',
-    '$q', 'toastService',
+    '$scope', 'APIUtils', 'dataService', 'Constants', '$interval', '$q',
+    'toastService',
     function(
-        $scope, APIUtils, dataService, Constants, $timeout, $interval, $q,
-        toastService) {
+        $scope, APIUtils, dataService, Constants, $interval, $q, toastService) {
       $scope.dataService = dataService;
       // Is a || of the other 4 "confirm" variables to ensure only
       // one confirm is shown at a time.
@@ -25,35 +24,39 @@
       $scope.confirmImmediateShutdown = false;
       $scope.loading = true;
 
-      var pollChassisStatusTimer = undefined;
-      var pollStartTime = null;
+      // When a power operation is in progress, set to true,
+      // when a power operation completes (success/fail) set to false.
+      // This property is used to show/hide the 'in progress' message
+      // in markup.
+      $scope.operationPending = false;
 
       /**
        * Checks the host status provided by the dataService using an
        * interval timer
        * @param {string} statusType : host status type to check for
-       * @param {number} timeout : timeout limit
-       * @param {string} error : error message
+       * @param {number} timeout : timeout limit, defaults to 5 minutes
+       * @param {string} error : error message, defaults to 'Time out'
        * @returns {Promise} : returns a deferred promise that will be fulfilled
        * if the status is met or be rejected if the timeout is reached
        */
-      var checkHostStatus = (statusType, timeout, error = 'Time out.') => {
-        const deferred = $q.defer();
-        const start = new Date();
-        const checkHostStatusInverval = $interval(() => {
-          let now = new Date();
-          let timePassed = now.getTime() - start.getTime();
-          if (timePassed > timeout) {
-            deferred.reject(error);
-            $interval.cancel(checkHostStatusInverval);
-          }
-          if (dataService.server_state === statusType) {
-            deferred.resolve();
-            $interval.cancel(checkHostStatusInverval);
-          }
-        }, Constants.POLL_INTERVALS.POWER_OP);
-        return deferred.promise;
-      };
+      var checkHostStatus =
+          (statusType, timeout = 300000, error = 'Time out.') => {
+            const deferred = $q.defer();
+            const start = new Date();
+            const checkHostStatusInverval = $interval(() => {
+              let now = new Date();
+              let timePassed = now.getTime() - start.getTime();
+              if (timePassed > timeout) {
+                deferred.reject(error);
+                $interval.cancel(checkHostStatusInverval);
+              }
+              if (dataService.server_state === statusType) {
+                deferred.resolve();
+                $interval.cancel(checkHostStatusInverval);
+              }
+            }, Constants.POLL_INTERVALS.POWER_OP);
+            return deferred.promise;
+          };
 
       APIUtils.getLastPowerTime()
           .then(
@@ -76,71 +79,56 @@
             (dataService.server_state == 'Running') ? 'Off' : 'Running';
       };
 
-      $scope.powerOn = function() {
-        $scope.loading = true;
+      /**
+       * Initiate Power on
+       */
+      $scope.powerOn = () => {
+        $scope.operationPending = true;
         dataService.setUnreachableState();
         APIUtils.hostPowerOn()
-            .then(function(response) {
-              return response;
+            .then(() => {
+              // Check for on state
+              return checkHostStatus(
+                  Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON,
+                  Constants.MESSAGES.POLL.HOST_ON_TIMEOUT);
             })
-            .then(function(lastStatus) {
-              return APIUtils.pollHostStatusTillOn();
-            })
-            .then(function(hostState) {
-              $scope.loading = false;
-            })
-            .catch(function(error) {
+            .catch((error) => {
+              console.log(error);
               toastService.error(Constants.MESSAGES.POWER_OP.POWER_ON_FAILED);
-              $scope.loading = false;
-            });
+            })
+            .finally(() => {
+              $scope.operationPending = false;
+            })
       };
 
-      function pollChassisStatusTillOff() {
-        var deferred = $q.defer();
-        pollChassisStatusTimer = $interval(function() {
-          var now = new Date();
-          if ((now.getTime() - pollStartTime.getTime()) >=
-              Constants.TIMEOUT.CHASSIS_OFF) {
-            $interval.cancel(pollChassisStatusTimer);
-            pollChassisStatusTimer = undefined;
-            deferred.reject(
-                new Error(Constants.MESSAGES.POLL.CHASSIS_OFF_TIMEOUT));
-          }
-          APIUtils.getChassisState()
-              .then(function(state) {
-                if (state === Constants.CHASSIS_POWER_STATE.off_code) {
-                  $interval.cancel(pollChassisStatusTimer);
-                  pollChassisStatusTimer = undefined;
-                  deferred.resolve(state);
-                }
-              })
-              .catch(function(error) {
-                $interval.cancel(pollChassisStatusTimer);
-                pollChassisStatusTimer = undefined;
-                deferred.reject(error);
-              });
-        }, Constants.POLL_INTERVALS.POWER_OP);
-
-        return deferred.promise;
-      }
-      $scope.warmReboot = function() {
-        $scope.loading = true;
+      /**
+       * Initiate Orderly reboot
+       * Attempts to stop all software
+       */
+      $scope.warmReboot = () => {
+        $scope.operationPending = true;
         dataService.setUnreachableState();
         APIUtils.hostReboot()
-            .then(function(response) {
-              return response;
+            .then(() => {
+              // Check for off state
+              return checkHostStatus(
+                  Constants.HOST_STATE_TEXT.off, Constants.TIMEOUT.HOST_OFF,
+                  Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT);
             })
-            .then(function(lastStatus) {
-              return APIUtils.pollHostStatusTilReboot();
+            .then(() => {
+              // Check for on state
+              return checkHostStatus(
+                  Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON,
+                  Constants.MESSAGES.POLL.HOST_ON_TIMEOUT);
             })
-            .then(function(hostState) {
-              $scope.loading = false;
-            })
-            .catch(function(error) {
+            .catch((error) => {
+              console.log(error);
               toastService.error(
                   Constants.MESSAGES.POWER_OP.WARM_REBOOT_FAILED);
-              $scope.loading = false;
-            });
+            })
+            .finally(() => {
+              $scope.operationPending = false;
+            })
       };
 
       $scope.warmRebootConfirm = function() {
@@ -152,33 +140,40 @@
         $scope.confirmWarmReboot = true;
       };
 
-      $scope.coldReboot = function() {
-        $scope.loading = true;
+      /**
+       * Initiate Immediate reboot
+       * Does not attempt to stop all software
+       */
+      $scope.coldReboot = () => {
+        $scope.operationPending = true;
         dataService.setUnreachableState();
         APIUtils.chassisPowerOff()
-            .then(function() {
+            .then(() => {
+              // Check for off state
               return checkHostStatus(
                   Constants.HOST_STATE_TEXT.off,
                   Constants.TIMEOUT.HOST_OFF_IMMEDIATE,
                   Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT);
             })
-            .then(function() {
+            .then(() => {
               return APIUtils.hostPowerOn();
             })
-            .then(function() {
+            .then(() => {
+              // Check for on state
               return checkHostStatus(
                   Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON,
                   Constants.MESSAGES.POLL.HOST_ON_TIMEOUT);
             })
-            .catch(function(error) {
+            .catch((error) => {
               console.log(error);
               toastService.error(
                   Constants.MESSAGES.POWER_OP.COLD_REBOOT_FAILED);
             })
-            .finally(function() {
-              $scope.loading = false;
+            .finally(() => {
+              $scope.operationPending = false;
             })
       };
+
       $scope.coldRebootConfirm = function() {
         if ($scope.confirm) {
           return;
@@ -187,29 +182,30 @@
         $scope.confirmColdReboot = true;
       };
 
-      $scope.orderlyShutdown = function() {
-        $scope.loading = true;
+      /**
+       * Initiate Orderly shutdown
+       * Attempts to stop all software
+       */
+      $scope.orderlyShutdown = () => {
+        $scope.operationPending = true;
         dataService.setUnreachableState();
         APIUtils.hostPowerOff()
-            .then(function(response) {
-              return response;
+            .then(() => {
+              // Check for off state
+              return checkHostStatus(
+                  Constants.HOST_STATE_TEXT.off, Constants.TIMEOUT.HOST_OFF,
+                  Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT);
             })
-            .then(function(lastStatus) {
-              return APIUtils.pollHostStatusTillOff();
-            })
-            .then(function(hostState) {
-              pollStartTime = new Date();
-              return pollChassisStatusTillOff();
-            })
-            .then(function(chassisState) {
-              $scope.loading = false;
-            })
-            .catch(function(error) {
+            .catch((error) => {
+              console.log(error);
               toastService.error(
                   Constants.MESSAGES.POWER_OP.ORDERLY_SHUTDOWN_FAILED);
-              $scope.loading = false;
-            });
+            })
+            .finally(() => {
+              $scope.operationPending = false;
+            })
       };
+
       $scope.orderlyShutdownConfirm = function() {
         if ($scope.confirm) {
           return;
@@ -218,27 +214,34 @@
         $scope.confirmOrderlyShutdown = true;
       };
 
-      $scope.immediateShutdown = function() {
-        $scope.loading = true;
+      /**
+       * Initiate Immediate shutdown
+       * Does not attempt to stop all software
+       */
+      $scope.immediateShutdown = () => {
+        $scope.operationPending = true;
         dataService.setUnreachableState();
         APIUtils.chassisPowerOff()
-            .then(function(response) {
-              return response;
+            .then(() => {
+              // Check for off state
+              return checkHostStatus(
+                  Constants.HOST_STATE_TEXT.off,
+                  Constants.TIMEOUT.HOST_OFF_IMMEDIATE,
+                  Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT);
             })
-            .then(function(lastStatus) {
-              pollStartTime = new Date();
-              return pollChassisStatusTillOff();
-            })
-            .then(function(chassisState) {
+            .then(() => {
               dataService.setPowerOffState();
-              $scope.loading = false;
             })
-            .catch(function(error) {
+            .catch((error) => {
+              console.log(error);
               toastService.error(
                   Constants.MESSAGES.POWER_OP.IMMEDIATE_SHUTDOWN_FAILED);
-              $scope.loading = false;
-            });
+            })
+            .finally(() => {
+              $scope.operationPending = false;
+            })
       };
+
       $scope.immediateShutdownConfirm = function() {
         if ($scope.confirm) {
           return;