1/**
2 * Controller for power-operations
3 *
4 * @module app/serverControl
5 * @exports powerOperationsController
6 * @name powerOperationsController
7 */
8
9window.angular && (function(angular) {
10  'use strict';
11
12  angular.module('app.serverControl').controller('powerOperationsController', [
13    '$scope', 'APIUtils', 'dataService', 'Constants', '$timeout', '$interval',
14    '$q', 'toastService',
15    function(
16        $scope, APIUtils, dataService, Constants, $timeout, $interval, $q,
17        toastService) {
18      $scope.dataService = dataService;
19      // Is a || of the other 4 "confirm" variables to ensure only
20      // one confirm is shown at a time.
21      $scope.confirm = false;
22      $scope.confirmWarmReboot = false;
23      $scope.confirmColdReboot = false;
24      $scope.confirmOrderlyShutdown = false;
25      $scope.confirmImmediateShutdown = false;
26      $scope.loading = true;
27
28      var pollChassisStatusTimer = undefined;
29      var pollStartTime = null;
30
31      /**
32       * Checks the host status provided by the dataService using an
33       * interval timer
34       * @param {string} statusType : host status type to check for
35       * @param {number} timeout : timeout limit
36       * @param {string} error : error message
37       * @returns {Promise} : returns a deferred promise that will be fulfilled
38       * if the status is met or be rejected if the timeout is reached
39       */
40      var checkHostStatus = (statusType, timeout, error = 'Time out.') => {
41        const deferred = $q.defer();
42        const start = new Date();
43        const checkHostStatusInverval = $interval(() => {
44          let now = new Date();
45          let timePassed = now.getTime() - start.getTime();
46          if (timePassed > timeout) {
47            deferred.reject(error);
48            $interval.cancel(checkHostStatusInverval);
49          }
50          if (dataService.server_state === statusType) {
51            deferred.resolve();
52            $interval.cancel(checkHostStatusInverval);
53          }
54        }, Constants.POLL_INTERVALS.POWER_OP);
55        return deferred.promise;
56      };
57
58      APIUtils.getLastPowerTime()
59          .then(
60              function(data) {
61                if (data.data == 0) {
62                  $scope.powerTime = 'not available';
63                } else {
64                  $scope.powerTime = data.data;
65                }
66              },
67              function(error) {
68                console.log(JSON.stringify(error));
69              })
70          .finally(function() {
71            $scope.loading = false;
72          });
73
74      $scope.toggleState = function() {
75        dataService.server_state =
76            (dataService.server_state == 'Running') ? 'Off' : 'Running';
77      };
78
79      $scope.powerOn = function() {
80        $scope.loading = true;
81        dataService.setUnreachableState();
82        APIUtils.hostPowerOn()
83            .then(function(response) {
84              return response;
85            })
86            .then(function(lastStatus) {
87              return APIUtils.pollHostStatusTillOn();
88            })
89            .then(function(hostState) {
90              $scope.loading = false;
91            })
92            .catch(function(error) {
93              toastService.error(Constants.MESSAGES.POWER_OP.POWER_ON_FAILED);
94              $scope.loading = false;
95            });
96      };
97
98      function pollChassisStatusTillOff() {
99        var deferred = $q.defer();
100        pollChassisStatusTimer = $interval(function() {
101          var now = new Date();
102          if ((now.getTime() - pollStartTime.getTime()) >=
103              Constants.TIMEOUT.CHASSIS_OFF) {
104            $interval.cancel(pollChassisStatusTimer);
105            pollChassisStatusTimer = undefined;
106            deferred.reject(
107                new Error(Constants.MESSAGES.POLL.CHASSIS_OFF_TIMEOUT));
108          }
109          APIUtils.getChassisState()
110              .then(function(state) {
111                if (state === Constants.CHASSIS_POWER_STATE.off_code) {
112                  $interval.cancel(pollChassisStatusTimer);
113                  pollChassisStatusTimer = undefined;
114                  deferred.resolve(state);
115                }
116              })
117              .catch(function(error) {
118                $interval.cancel(pollChassisStatusTimer);
119                pollChassisStatusTimer = undefined;
120                deferred.reject(error);
121              });
122        }, Constants.POLL_INTERVALS.POWER_OP);
123
124        return deferred.promise;
125      }
126      $scope.warmReboot = function() {
127        $scope.loading = true;
128        dataService.setUnreachableState();
129        APIUtils.hostReboot()
130            .then(function(response) {
131              return response;
132            })
133            .then(function(lastStatus) {
134              return APIUtils.pollHostStatusTilReboot();
135            })
136            .then(function(hostState) {
137              $scope.loading = false;
138            })
139            .catch(function(error) {
140              toastService.error(
141                  Constants.MESSAGES.POWER_OP.WARM_REBOOT_FAILED);
142              $scope.loading = false;
143            });
144      };
145
146      $scope.warmRebootConfirm = function() {
147        if ($scope.confirm) {
148          // If another "confirm" is already shown return
149          return;
150        }
151        $scope.confirm = true;
152        $scope.confirmWarmReboot = true;
153      };
154
155      $scope.coldReboot = function() {
156        $scope.loading = true;
157        dataService.setUnreachableState();
158        APIUtils.chassisPowerOff()
159            .then(function() {
160              return checkHostStatus(
161                  Constants.HOST_STATE_TEXT.off,
162                  Constants.TIMEOUT.HOST_OFF_IMMEDIATE,
163                  Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT);
164            })
165            .then(function() {
166              return APIUtils.hostPowerOn();
167            })
168            .then(function() {
169              return checkHostStatus(
170                  Constants.HOST_STATE_TEXT.on, Constants.TIMEOUT.HOST_ON,
171                  Constants.MESSAGES.POLL.HOST_ON_TIMEOUT);
172            })
173            .catch(function(error) {
174              console.log(error);
175              toastService.error(
176                  Constants.MESSAGES.POWER_OP.COLD_REBOOT_FAILED);
177            })
178            .finally(function() {
179              $scope.loading = false;
180            })
181      };
182      $scope.coldRebootConfirm = function() {
183        if ($scope.confirm) {
184          return;
185        }
186        $scope.confirm = true;
187        $scope.confirmColdReboot = true;
188      };
189
190      $scope.orderlyShutdown = function() {
191        $scope.loading = true;
192        dataService.setUnreachableState();
193        APIUtils.hostPowerOff()
194            .then(function(response) {
195              return response;
196            })
197            .then(function(lastStatus) {
198              return APIUtils.pollHostStatusTillOff();
199            })
200            .then(function(hostState) {
201              pollStartTime = new Date();
202              return pollChassisStatusTillOff();
203            })
204            .then(function(chassisState) {
205              $scope.loading = false;
206            })
207            .catch(function(error) {
208              toastService.error(
209                  Constants.MESSAGES.POWER_OP.ORDERLY_SHUTDOWN_FAILED);
210              $scope.loading = false;
211            });
212      };
213      $scope.orderlyShutdownConfirm = function() {
214        if ($scope.confirm) {
215          return;
216        }
217        $scope.confirm = true;
218        $scope.confirmOrderlyShutdown = true;
219      };
220
221      $scope.immediateShutdown = function() {
222        $scope.loading = true;
223        dataService.setUnreachableState();
224        APIUtils.chassisPowerOff()
225            .then(function(response) {
226              return response;
227            })
228            .then(function(lastStatus) {
229              pollStartTime = new Date();
230              return pollChassisStatusTillOff();
231            })
232            .then(function(chassisState) {
233              dataService.setPowerOffState();
234              $scope.loading = false;
235            })
236            .catch(function(error) {
237              toastService.error(
238                  Constants.MESSAGES.POWER_OP.IMMEDIATE_SHUTDOWN_FAILED);
239              $scope.loading = false;
240            });
241      };
242      $scope.immediateShutdownConfirm = function() {
243        if ($scope.confirm) {
244          return;
245        }
246        $scope.confirm = true;
247        $scope.confirmImmediateShutdown = true;
248      };
249    }
250  ]);
251})(angular);
252