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