1/**
2 * API utilities service
3 *
4 * @module app/common/services/api-utils
5 * @exports APIUtils
6 * @name APIUtils
7 */
8
9window.angular && (function(angular) {
10  'use strict';
11  angular.module('app.common.services').factory('APIUtils', [
12    '$http', 'Constants', '$q', 'dataService', '$interval',
13    function($http, Constants, $q, DataService, $interval) {
14      var getScaledValue = function(value, scale) {
15        scale = scale + '';
16        scale = parseInt(scale, 10);
17        var power = Math.abs(parseInt(scale, 10));
18
19        if (scale > 0) {
20          value = value * Math.pow(10, power);
21        } else if (scale < 0) {
22          value = value / Math.pow(10, power);
23        }
24        return value;
25      };
26      var SERVICE = {
27        API_CREDENTIALS: Constants.API_CREDENTIALS,
28        API_RESPONSE: Constants.API_RESPONSE,
29        CHASSIS_POWER_STATE: Constants.CHASSIS_POWER_STATE,
30        HOST_STATE_TEXT: Constants.HOST_STATE,
31        HOST_STATE: Constants.HOST_STATE,
32        LED_STATE: Constants.LED_STATE,
33        LED_STATE_TEXT: Constants.LED_STATE_TEXT,
34        HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
35        getChassisState: function() {
36          var deferred = $q.defer();
37          $http({
38            method: 'GET',
39            url: DataService.getHost() +
40                '/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState',
41            withCredentials: true
42          })
43              .then(
44                  function(response) {
45                    var json = JSON.stringify(response.data);
46                    var content = JSON.parse(json);
47                    deferred.resolve(content.data);
48                  },
49                  function(error) {
50                    console.log(error);
51                    deferred.reject(error);
52                  });
53          return deferred.promise;
54        },
55        validIPV4IP: function(ip) {
56          // Checks for [0-255].[0-255].[0-255].[0-255]
57          return ip.match(
58              /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/);
59        },
60        getHostState: function() {
61          var deferred = $q.defer();
62          $http({
63            method: 'GET',
64            url: DataService.getHost() +
65                '/xyz/openbmc_project/state/host0/attr/CurrentHostState',
66            withCredentials: true
67          })
68              .then(
69                  function(response) {
70                    var json = JSON.stringify(response.data);
71                    var content = JSON.parse(json);
72                    deferred.resolve(content.data);
73                  },
74                  function(error) {
75                    console.log(error);
76                    deferred.reject(error);
77                  });
78          return deferred.promise;
79        },
80        getSNMPManagers: function() {
81          return $http({
82                   method: 'GET',
83                   url: DataService.getHost() +
84                       '/xyz/openbmc_project/network/snmp/manager/enumerate',
85                   withCredentials: true
86                 })
87              .then(function(response) {
88                return response.data;
89              });
90        },
91        pollHostStatusTillOn: function() {
92          var deferred = $q.defer();
93          var hostOnTimeout = setTimeout(function() {
94            ws.close();
95            deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_ON_TIMEOUT));
96          }, Constants.TIMEOUT.HOST_ON);
97
98          var ws =
99              new WebSocket('wss://' + DataService.server_id + '/subscribe');
100          var data = JSON.stringify({
101            'paths': ['/xyz/openbmc_project/state/host0'],
102            'interfaces': ['xyz.openbmc_project.State.Host']
103          });
104          ws.onopen = function() {
105            ws.send(data);
106          };
107          ws.onmessage = function(evt) {
108            var content = JSON.parse(evt.data);
109            var hostState = content.properties.CurrentHostState;
110            if (hostState === Constants.HOST_STATE_TEXT.on_code) {
111              clearTimeout(hostOnTimeout);
112              ws.close();
113              deferred.resolve();
114            } else if (hostState === Constants.HOST_STATE_TEXT.error_code) {
115              clearTimeout(hostOnTimeout);
116              ws.close();
117              deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_QUIESCED));
118            }
119          };
120        },
121
122        pollHostStatusTilReboot: function() {
123          var deferred = $q.defer();
124          var onState = Constants.HOST_STATE_TEXT.on_code;
125          var offState = Constants.HOST_STATE_TEXT.on_code;
126          var hostTimeout;
127          var setHostTimeout = function(message, timeout) {
128            hostTimeout = setTimeout(function() {
129              ws.close();
130              deferred.reject(new Error(message));
131            }, timeout);
132          };
133          var ws =
134              new WebSocket('wss://' + DataService.server_id + '/subscribe');
135          var data = JSON.stringify({
136            'paths': ['/xyz/openbmc_project/state/host0'],
137            'interfaces': ['xyz.openbmc_project.State.Host']
138          });
139          ws.onopen = function() {
140            ws.send(data);
141          };
142          setHostTimeout(
143              Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT,
144              Constants.TIMEOUT.HOST_OFF);
145          var pollState = offState;
146          ws.onmessage = function(evt) {
147            var content = JSON.parse(evt.data);
148            var hostState = content.properties.CurrentHostState;
149            if (hostState === pollState) {
150              if (pollState === offState) {
151                clearTimeout(hostTimeout);
152                pollState = onState;
153                setHostTimeout(
154                    Constants.MESSAGES.POLL.HOST_ON_TIMEOUT,
155                    Constants.TIMEOUT.HOST_ON);
156              }
157              if (pollState === onState) {
158                clearTimeout(hostTimeout);
159                ws.close();
160                deferred.resolve();
161              }
162            } else if (hostState === Constants.HOST_STATE_TEXT.error_code) {
163              clearTimeout(hostTimeout);
164              ws.close();
165              deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_QUIESCED));
166            }
167          };
168        },
169
170        pollHostStatusTillOff: function() {
171          var deferred = $q.defer();
172          var hostOffTimeout = setTimeout(function() {
173            ws.close();
174            deferred.reject(
175                new Error(Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT));
176          }, Constants.TIMEOUT.HOST_OFF);
177
178          var ws =
179              new WebSocket('wss://' + DataService.server_id + '/subscribe');
180          var data = JSON.stringify({
181            'paths': ['/xyz/openbmc_project/state/host0'],
182            'interfaces': ['xyz.openbmc_project.State.Host']
183          });
184          ws.onopen = function() {
185            ws.send(data);
186          };
187          ws.onmessage = function(evt) {
188            var content = JSON.parse(evt.data);
189            var hostState = content.properties.CurrentHostState;
190            if (hostState === Constants.HOST_STATE_TEXT.off_code) {
191              clearTimeout(hostOffTimeout);
192              ws.close();
193              deferred.resolve();
194            }
195          };
196        },
197        getNetworkInfo: function() {
198          var deferred = $q.defer();
199          $http({
200            method: 'GET',
201            url: DataService.getHost() +
202                '/xyz/openbmc_project/network/enumerate',
203            withCredentials: true
204          })
205              .then(
206                  function(response) {
207                    var json = JSON.stringify(response.data);
208                    var content = JSON.parse(json);
209                    var hostname = '';
210                    var defaultgateway = '';
211                    var macAddress = '';
212
213                    function parseNetworkData(content) {
214                      var data = {
215                        interface_ids: [],
216                        interfaces: {},
217                        ip_addresses: {ipv4: [], ipv6: []},
218                      };
219                      var interfaceId = '', keyParts = [], interfaceHash = '',
220                          interfaceType = '';
221                      for (var key in content.data) {
222                        if (key.match(/network\/eth\d+(_\d+)?$/ig)) {
223                          interfaceId = key.split('/').pop();
224                          if (data.interface_ids.indexOf(interfaceId) == -1) {
225                            data.interface_ids.push(interfaceId);
226                            data.interfaces[interfaceId] = {
227                              interfaceIname: '',
228                              DomainName: '',
229                              MACAddress: '',
230                              Nameservers: [],
231                              DHCPEnabled: 0,
232                              ipv4: {ids: [], values: []},
233                              ipv6: {ids: [], values: []}
234                            };
235                            data.interfaces[interfaceId].MACAddress =
236                                content.data[key].MACAddress;
237                            data.interfaces[interfaceId].DomainName =
238                                content.data[key].DomainName.join(' ');
239                            data.interfaces[interfaceId].Nameservers =
240                                content.data[key].Nameservers;
241                            data.interfaces[interfaceId].DHCPEnabled =
242                                content.data[key].DHCPEnabled;
243                          }
244                        } else if (
245                            key.match(
246                                /network\/eth\d+(_\d+)?\/ipv[4|6]\/[a-z0-9]+$/ig)) {
247                          keyParts = key.split('/');
248                          interfaceHash = keyParts.pop();
249                          interfaceType = keyParts.pop();
250                          interfaceId = keyParts.pop();
251
252                          if (data.interfaces[interfaceId][interfaceType]
253                                  .ids.indexOf(interfaceHash) == -1) {
254                            data.interfaces[interfaceId][interfaceType]
255                                .ids.push(interfaceHash);
256                            data.interfaces[interfaceId][interfaceType]
257                                .values.push(content.data[key]);
258                            data.ip_addresses[interfaceType].push(
259                                content.data[key]['Address']);
260                          }
261                        }
262                      }
263                      return data;
264                    }
265
266                    if (content.data.hasOwnProperty(
267                            '/xyz/openbmc_project/network/config')) {
268                      if (content.data['/xyz/openbmc_project/network/config']
269                              .hasOwnProperty('HostName')) {
270                        hostname =
271                            content.data['/xyz/openbmc_project/network/config']
272                                .HostName;
273                      }
274                      if (content.data['/xyz/openbmc_project/network/config']
275                              .hasOwnProperty('DefaultGateway')) {
276                        defaultgateway =
277                            content.data['/xyz/openbmc_project/network/config']
278                                .DefaultGateway;
279                      }
280                    }
281
282                    if (content.data.hasOwnProperty(
283                            '/xyz/openbmc_project/network/eth0') &&
284                        content.data['/xyz/openbmc_project/network/eth0']
285                            .hasOwnProperty('MACAddress')) {
286                      macAddress =
287                          content.data['/xyz/openbmc_project/network/eth0']
288                              .MACAddress;
289                    }
290
291                    deferred.resolve({
292                      data: content.data,
293                      hostname: hostname,
294                      defaultgateway: defaultgateway,
295                      mac_address: macAddress,
296                      formatted_data: parseNetworkData(content)
297                    });
298                  },
299                  function(error) {
300                    console.log(error);
301                    deferred.reject(error);
302                  });
303          return deferred.promise;
304        },
305        setMACAddress: function(interface_name, mac_address) {
306          return $http({
307                   method: 'PUT',
308                   url: DataService.getHost() +
309                       '/xyz/openbmc_project/network/' + interface_name +
310                       '/attr/MACAddress',
311                   withCredentials: true,
312                   data: JSON.stringify({'data': mac_address})
313                 })
314              .then(function(response) {
315                return response.data;
316              });
317        },
318        setDefaultGateway: function(defaultGateway) {
319          return $http({
320                   method: 'PUT',
321                   url: DataService.getHost() +
322                       '/xyz/openbmc_project/network/config/attr/DefaultGateway',
323                   withCredentials: true,
324                   data: JSON.stringify({'data': defaultGateway})
325                 })
326              .then(function(response) {
327                return response.data;
328              });
329        },
330        setDHCPEnabled: function(interfaceName, dhcpEnabled) {
331          return $http({
332                   method: 'PUT',
333                   url: DataService.getHost() +
334                       '/xyz/openbmc_project/network/' + interfaceName +
335                       '/attr/DHCPEnabled',
336                   withCredentials: true,
337                   data: JSON.stringify({'data': dhcpEnabled})
338                 })
339              .then(function(response) {
340                return response.data;
341              });
342        },
343        setNameservers: function(interfaceName, dnsServers) {
344          return $http({
345                   method: 'PUT',
346                   url: DataService.getHost() +
347                       '/xyz/openbmc_project/network/' + interfaceName +
348                       '/attr/Nameservers',
349                   withCredentials: true,
350                   data: JSON.stringify({'data': dnsServers})
351                 })
352              .then(function(response) {
353                return response.data;
354              });
355        },
356        deleteIPV4: function(interfaceName, networkID) {
357          return $http({
358                   method: 'POST',
359                   url: DataService.getHost() +
360                       '/xyz/openbmc_project/network/' + interfaceName +
361                       '/ipv4/' + networkID + '/action/Delete',
362                   withCredentials: true,
363                   data: JSON.stringify({'data': []})
364                 })
365              .then(function(response) {
366                return response.data;
367              });
368        },
369        addIPV4: function(
370            interfaceName, ipAddress, netmaskPrefixLength, gateway) {
371          return $http({
372                   method: 'POST',
373                   url: DataService.getHost() +
374                       '/xyz/openbmc_project/network/' + interfaceName +
375                       '/action/IP',
376                   withCredentials: true,
377                   data: JSON.stringify({
378                     'data': [
379                       'xyz.openbmc_project.Network.IP.Protocol.IPv4',
380                       ipAddress, +netmaskPrefixLength, gateway
381                     ]
382                   })
383                 })
384              .then(function(response) {
385                return response.data;
386              });
387        },
388        getLEDState: function() {
389          var deferred = $q.defer();
390          $http({
391            method: 'GET',
392            url: DataService.getHost() +
393                '/xyz/openbmc_project/led/groups/enclosure_identify',
394            withCredentials: true
395          })
396              .then(
397                  function(response) {
398                    var json = JSON.stringify(response.data);
399                    var content = JSON.parse(json);
400                    deferred.resolve(content.data.Asserted);
401                  },
402                  function(error) {
403                    console.log(error);
404                    deferred.reject(error);
405                  });
406          return deferred.promise;
407        },
408        login: function(username, password, callback) {
409          $http({
410            method: 'POST',
411            url: DataService.getHost() + '/login',
412            withCredentials: true,
413            data: JSON.stringify({'data': [username, password]})
414          })
415              .then(
416                  function(response) {
417                    if (callback) {
418                      callback(response.data);
419                    }
420                  },
421                  function(error) {
422                    if (callback) {
423                      if (error && error.status && error.status == 'error') {
424                        callback(error);
425                      } else {
426                        callback(error, true);
427                      }
428                    }
429                    console.log(error);
430                  });
431        },
432        testPassword: function(username, password) {
433          // Calls /login without the current session to verify the given
434          // password is correct ignore the interceptor logout on a bad password
435          return $http({
436                   method: 'POST',
437                   url: DataService.getHost() + '/login',
438                   withCredentials: false,
439                   data: JSON.stringify({'data': [username, password]})
440                 })
441              .then(function(response) {
442                return response.data;
443              });
444        },
445        logout: function(callback) {
446          $http({
447            method: 'POST',
448            url: DataService.getHost() + '/logout',
449            withCredentials: true,
450            data: JSON.stringify({'data': []})
451          })
452              .then(
453                  function(response) {
454                    if (callback) {
455                      callback(response.data);
456                    }
457                  },
458                  function(error) {
459                    if (callback) {
460                      callback(null, error);
461                    }
462                    console.log(error);
463                  });
464        },
465        changePassword: function(user, newPassword) {
466          var deferred = $q.defer();
467          $http({
468            method: 'POST',
469            url: DataService.getHost() + '/xyz/openbmc_project/user/' + user +
470                '/action/SetPassword',
471            withCredentials: true,
472            data: JSON.stringify({'data': [newPassword]}),
473            responseType: 'arraybuffer'
474          })
475              .then(
476                  function(response, status, headers) {
477                    deferred.resolve(
478                        {data: response, status: status, headers: headers});
479                  },
480                  function(error) {
481                    console.log(error);
482                    deferred.reject(error);
483                  });
484          return deferred.promise;
485        },
486        chassisPowerOff: function() {
487          var deferred = $q.defer();
488          $http({
489            method: 'PUT',
490            url: DataService.getHost() +
491                '/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition',
492            withCredentials: true,
493            data: JSON.stringify(
494                {'data': 'xyz.openbmc_project.State.Chassis.Transition.Off'})
495          })
496              .then(
497                  function(response) {
498                    var json = JSON.stringify(response.data);
499                    var content = JSON.parse(json);
500                    deferred.resolve(content.status);
501                  },
502                  function(error) {
503                    console.log(error);
504                    deferred.reject(error);
505                  });
506          return deferred.promise;
507        },
508        setLEDState: function(state, callback) {
509          $http({
510            method: 'PUT',
511            url: DataService.getHost() +
512                '/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted',
513            withCredentials: true,
514            data: JSON.stringify({'data': state})
515          })
516              .then(
517                  function(response) {
518                    var json = JSON.stringify(response.data);
519                    var content = JSON.parse(json);
520                    if (callback) {
521                      return callback(content.status);
522                    }
523                  },
524                  function(error) {
525                    if (callback) {
526                      callback(error);
527                    } else {
528                      console.log(error);
529                    }
530                  });
531        },
532        bmcReboot: function(callback) {
533          $http({
534            method: 'PUT',
535            url: DataService.getHost() +
536                '/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition',
537            withCredentials: true,
538            data: JSON.stringify(
539                {'data': 'xyz.openbmc_project.State.BMC.Transition.Reboot'})
540          })
541              .then(
542                  function(response) {
543                    var json = JSON.stringify(response.data);
544                    var content = JSON.parse(json);
545                    if (callback) {
546                      return callback(content.status);
547                    }
548                  },
549                  function(error) {
550                    if (callback) {
551                      callback(error);
552                    } else {
553                      console.log(error);
554                    }
555                  });
556        },
557        getLastRebootTime: function() {
558          return $http({
559                   method: 'GET',
560                   url: DataService.getHost() +
561                       '/xyz/openbmc_project/state/bmc0/attr/LastRebootTime',
562                   withCredentials: true
563                 })
564              .then(function(response) {
565                return response.data;
566              });
567        },
568        hostPowerOn: function() {
569          var deferred = $q.defer();
570          $http({
571            method: 'PUT',
572            url: DataService.getHost() +
573                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
574            withCredentials: true,
575            data: JSON.stringify(
576                {'data': 'xyz.openbmc_project.State.Host.Transition.On'})
577          })
578              .then(
579                  function(response) {
580                    var json = JSON.stringify(response.data);
581                    var content = JSON.parse(json);
582                    deferred.resolve(content.status);
583                  },
584                  function(error) {
585                    console.log(error);
586                    deferred.reject(error);
587                  });
588          return deferred.promise;
589        },
590        hostPowerOff: function() {
591          var deferred = $q.defer();
592          $http({
593            method: 'PUT',
594            url: DataService.getHost() +
595                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
596            withCredentials: true,
597            data: JSON.stringify(
598                {'data': 'xyz.openbmc_project.State.Host.Transition.Off'})
599          })
600              .then(
601                  function(response) {
602                    var json = JSON.stringify(response.data);
603                    var content = JSON.parse(json);
604                    deferred.resolve(content.status);
605                  },
606                  function(error) {
607                    console.log(error);
608                    deferred.reject(error);
609                  });
610          return deferred.promise;
611        },
612        hostReboot: function() {
613          var deferred = $q.defer();
614          $http({
615            method: 'PUT',
616            url: DataService.getHost() +
617                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
618            withCredentials: true,
619            data: JSON.stringify(
620                {'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'})
621          })
622              .then(
623                  function(response) {
624                    var json = JSON.stringify(response.data);
625                    var content = JSON.parse(json);
626                    deferred.resolve(content.status);
627                  },
628                  function(error) {
629                    console.log(error);
630                    deferred.reject(error);
631                  });
632
633          return deferred.promise;
634        },
635        hostShutdown: function(callback) {
636          $http({
637            method: 'POST',
638            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
639            withCredentials: true,
640            data: JSON.stringify({'data': []})
641          })
642              .then(
643                  function(response) {
644                    var json = JSON.stringify(response.data);
645                    var content = JSON.parse(json);
646                    if (callback) {
647                      return callback(content);
648                    }
649                  },
650                  function(error) {
651                    if (callback) {
652                      callback(error);
653                    } else {
654                      console.log(error);
655                    }
656                  });
657        },
658        getLastPowerTime: function() {
659          return $http({
660                   method: 'GET',
661                   url: DataService.getHost() +
662                       '/xyz/openbmc_project/state/chassis0/attr/LastStateChangeTime',
663                   withCredentials: true
664                 })
665              .then(function(response) {
666                return response.data;
667              });
668        },
669        getLogs: function() {
670          var deferred = $q.defer();
671          $http({
672            method: 'GET',
673            url: DataService.getHost() +
674                '/xyz/openbmc_project/logging/enumerate',
675            withCredentials: true
676          })
677              .then(
678                  function(response) {
679                    var json = JSON.stringify(response.data);
680                    var content = JSON.parse(json);
681                    var dataClone = JSON.parse(JSON.stringify(content.data));
682                    var data = [];
683                    var severityCode = '';
684                    var priority = '';
685                    var health = '';
686                    var relatedItems = [];
687                    var eventID = 'None';
688                    var description = 'None';
689
690                    for (var key in content.data) {
691                      if (content.data.hasOwnProperty(key) &&
692                          content.data[key].hasOwnProperty('Id')) {
693                        var severityFlags = {
694                          low: false,
695                          medium: false,
696                          high: false
697                        };
698                        severityCode =
699                            content.data[key].Severity.split('.').pop();
700                        priority =
701                            Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
702                        severityFlags[priority.toLowerCase()] = true;
703                        relatedItems = [];
704                        content.data[key].associations.forEach(function(item) {
705                          relatedItems.push(item[2]);
706                        });
707
708                        if (content.data[key].hasOwnProperty(['EventID'])) {
709                          eventID = content.data[key].EventID;
710                        }
711
712                        if (content.data[key].hasOwnProperty(['Description'])) {
713                          description = content.data[key].Description;
714                        }
715
716                        data.push(Object.assign(
717                            {
718                              path: key,
719                              copied: false,
720                              priority: priority,
721                              severity_code: severityCode,
722                              severity_flags: severityFlags,
723                              additional_data:
724                                  content.data[key].AdditionalData.join('\n'),
725                              type: content.data[key].Message,
726                              selected: false,
727                              search_text:
728                                  ('#' + content.data[key].Id + ' ' +
729                                   severityCode + ' ' +
730                                   content.data[key].Message + ' ' +
731                                   content.data[key].Severity + ' ' +
732                                   content.data[key].AdditionalData.join(' '))
733                                      .toLowerCase(),
734                              meta: false,
735                              confirm: false,
736                              related_items: relatedItems,
737                              eventID: eventID,
738                              description: description,
739                              data: {key: key, value: content.data[key]}
740                            },
741                            content.data[key]));
742                      }
743                    }
744                    deferred.resolve({data: data, original: dataClone});
745                  },
746                  function(error) {
747                    console.log(error);
748                    deferred.reject(error);
749                  });
750
751          return deferred.promise;
752        },
753        getAllSensorStatus: function(callback) {
754          $http({
755            method: 'GET',
756            url: DataService.getHost() +
757                '/xyz/openbmc_project/sensors/enumerate',
758            withCredentials: true
759          })
760              .then(
761                  function(response) {
762                    var json = JSON.stringify(response.data);
763                    var content = JSON.parse(json);
764                    var dataClone = JSON.parse(JSON.stringify(content.data));
765                    var sensorData = [];
766                    var severity = {};
767                    var title = '';
768                    var tempKeyParts = [];
769                    var order = 0;
770                    var customOrder = 0;
771
772                    function getSensorStatus(reading) {
773                      var severityFlags = {
774                        critical: false,
775                        warning: false,
776                        normal: false
777                      },
778                          severityText = '', order = 0;
779
780                      if (reading.hasOwnProperty('CriticalLow') &&
781                          reading.Value < reading.CriticalLow) {
782                        severityFlags.critical = true;
783                        severityText = 'critical';
784                        order = 2;
785                      } else if (
786                          reading.hasOwnProperty('CriticalHigh') &&
787                          reading.Value > reading.CriticalHigh) {
788                        severityFlags.critical = true;
789                        severityText = 'critical';
790                        order = 2;
791                      } else if (
792                          reading.hasOwnProperty('CriticalLow') &&
793                          reading.hasOwnProperty('WarningLow') &&
794                          reading.Value >= reading.CriticalLow &&
795                          reading.Value <= reading.WarningLow) {
796                        severityFlags.warning = true;
797                        severityText = 'warning';
798                        order = 1;
799                      } else if (
800                          reading.hasOwnProperty('WarningHigh') &&
801                          reading.hasOwnProperty('CriticalHigh') &&
802                          reading.Value >= reading.WarningHigh &&
803                          reading.Value <= reading.CriticalHigh) {
804                        severityFlags.warning = true;
805                        severityText = 'warning';
806                        order = 1;
807                      } else {
808                        severityFlags.normal = true;
809                        severityText = 'normal';
810                      }
811                      return {
812                        flags: severityFlags,
813                        severityText: severityText,
814                        order: order
815                      };
816                    }
817
818                    for (var key in content.data) {
819                      if (content.data.hasOwnProperty(key) &&
820                          content.data[key].hasOwnProperty('Unit')) {
821                        severity = getSensorStatus(content.data[key]);
822
823                        if (!content.data[key].hasOwnProperty('CriticalLow')) {
824                          content.data[key].CriticalLow = '--';
825                          content.data[key].CriticalHigh = '--';
826                        }
827
828                        if (!content.data[key].hasOwnProperty('WarningLow')) {
829                          content.data[key].WarningLow = '--';
830                          content.data[key].WarningHigh = '--';
831                        }
832
833                        tempKeyParts = key.split('/');
834                        title = tempKeyParts.pop();
835                        title = tempKeyParts.pop() + '_' + title;
836                        title = title.split('_')
837                                    .map(function(item) {
838                                      return item.toLowerCase()
839                                                 .charAt(0)
840                                                 .toUpperCase() +
841                                          item.slice(1);
842                                    })
843                                    .reduce(function(prev, el) {
844                                      return prev + ' ' + el;
845                                    });
846
847                        content.data[key].Value = getScaledValue(
848                            content.data[key].Value, content.data[key].Scale);
849                        content.data[key].CriticalLow = getScaledValue(
850                            content.data[key].CriticalLow,
851                            content.data[key].Scale);
852                        content.data[key].CriticalHigh = getScaledValue(
853                            content.data[key].CriticalHigh,
854                            content.data[key].Scale);
855                        content.data[key].WarningLow = getScaledValue(
856                            content.data[key].WarningLow,
857                            content.data[key].Scale);
858                        content.data[key].WarningHigh = getScaledValue(
859                            content.data[key].WarningHigh,
860                            content.data[key].Scale);
861                        if (Constants.SENSOR_SORT_ORDER.indexOf(
862                                content.data[key].Unit) > -1) {
863                          customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
864                              content.data[key].Unit);
865                        } else {
866                          customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
867                        }
868
869                        sensorData.push(Object.assign(
870                            {
871                              path: key,
872                              selected: false,
873                              confirm: false,
874                              copied: false,
875                              title: title,
876                              unit:
877                                  Constants
878                                      .SENSOR_UNIT_MAP[content.data[key].Unit],
879                              severity_flags: severity.flags,
880                              status: severity.severityText,
881                              order: severity.order,
882                              custom_order: customOrder,
883                              search_text:
884                                  (title + ' ' + content.data[key].Value + ' ' +
885                                   Constants.SENSOR_UNIT_MAP[content.data[key]
886                                                                 .Unit] +
887                                   ' ' + severity.severityText + ' ' +
888                                   content.data[key].CriticalLow + ' ' +
889                                   content.data[key].CriticalHigh + ' ' +
890                                   content.data[key].WarningLow + ' ' +
891                                   content.data[key].WarningHigh + ' ')
892                                      .toLowerCase(),
893                              original_data:
894                                  {key: key, value: content.data[key]}
895                            },
896                            content.data[key]));
897                      }
898                    }
899
900                    callback(sensorData, dataClone);
901                  },
902                  function(error) {
903                    console.log(error);
904                  });
905        },
906        getActivation: function(imageId) {
907          return $http({
908                   method: 'GET',
909                   url: DataService.getHost() +
910                       '/xyz/openbmc_project/software/' + imageId +
911                       '/attr/Activation',
912                   withCredentials: true
913                 })
914              .then(function(response) {
915                return response.data;
916              });
917        },
918        getFirmwares: function() {
919          var deferred = $q.defer();
920          $http({
921            method: 'GET',
922            url: DataService.getHost() +
923                '/xyz/openbmc_project/software/enumerate',
924            withCredentials: true
925          })
926              .then(
927                  function(response) {
928                    var json = JSON.stringify(response.data);
929                    var content = JSON.parse(json);
930                    var data = [];
931                    var isExtended = false;
932                    var bmcActiveVersion = '';
933                    var hostActiveVersion = '';
934                    var imageType = '';
935                    var extendedVersions = [];
936                    var functionalImages = [];
937
938                    function getFormatedExtendedVersions(extendedVersion) {
939                      var versions = [];
940                      extendedVersion = extendedVersion.split(',');
941
942                      extendedVersion.forEach(function(item) {
943                        var parts = item.split('-');
944                        var numberIndex = 0;
945                        for (var i = 0; i < parts.length; i++) {
946                          if (/[0-9]/.test(parts[i])) {
947                            numberIndex = i;
948                            break;
949                          }
950                        }
951                        var titlePart = parts.splice(0, numberIndex);
952                        titlePart = titlePart.join('');
953                        titlePart = titlePart[0].toUpperCase() +
954                            titlePart.substr(1, titlePart.length);
955                        var versionPart = parts.join('-');
956                        versions.push({title: titlePart, version: versionPart});
957                      });
958
959                      return versions;
960                    }
961
962                    // Get the list of functional images so we can compare
963                    // later if an image is functional
964                    if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
965                      functionalImages =
966                          content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
967                              .endpoints;
968                    }
969                    for (var key in content.data) {
970                      if (content.data.hasOwnProperty(key) &&
971                          content.data[key].hasOwnProperty('Version')) {
972                        var activationStatus = '';
973
974                        // If the image is "Functional" use that for the
975                        // activation status, else use the value of "Activation"
976                        // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
977                        if (content.data[key].Activation) {
978                          activationStatus =
979                              content.data[key].Activation.split('.').pop();
980                        }
981
982                        if (functionalImages.includes(key)) {
983                          activationStatus = 'Functional';
984                        }
985
986                        imageType = content.data[key].Purpose.split('.').pop();
987                        isExtended = content.data[key].hasOwnProperty(
988                                         'ExtendedVersion') &&
989                            content.data[key].ExtendedVersion != '';
990                        if (isExtended) {
991                          extendedVersions = getFormatedExtendedVersions(
992                              content.data[key].ExtendedVersion);
993                        }
994                        data.push(Object.assign(
995                            {
996                              path: key,
997                              activationStatus: activationStatus,
998                              imageId: key.split('/').pop(),
999                              imageType: imageType,
1000                              isExtended: isExtended,
1001                              extended:
1002                                  {show: false, versions: extendedVersions},
1003                              data: {key: key, value: content.data[key]}
1004                            },
1005                            content.data[key]));
1006
1007                        if (activationStatus == 'Functional' &&
1008                            imageType == 'BMC') {
1009                          bmcActiveVersion = content.data[key].Version;
1010                        }
1011
1012                        if (activationStatus == 'Functional' &&
1013                            imageType == 'Host') {
1014                          hostActiveVersion = content.data[key].Version;
1015                        }
1016                      }
1017                    }
1018
1019                    deferred.resolve({
1020                      data: data,
1021                      bmcActiveVersion: bmcActiveVersion,
1022                      hostActiveVersion: hostActiveVersion
1023                    });
1024                  },
1025                  function(error) {
1026                    console.log(error);
1027                    deferred.reject(error);
1028                  });
1029
1030          return deferred.promise;
1031        },
1032        changePriority: function(imageId, priority) {
1033          var deferred = $q.defer();
1034          $http({
1035            method: 'PUT',
1036            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1037                imageId + '/attr/Priority',
1038            withCredentials: true,
1039            data: JSON.stringify({'data': priority})
1040          })
1041              .then(
1042                  function(response) {
1043                    var json = JSON.stringify(response.data);
1044                    var content = JSON.parse(json);
1045                    deferred.resolve(content);
1046                  },
1047                  function(error) {
1048                    console.log(error);
1049                    deferred.reject(error);
1050                  });
1051
1052          return deferred.promise;
1053        },
1054        deleteImage: function(imageId) {
1055          var deferred = $q.defer();
1056          $http({
1057            method: 'POST',
1058            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1059                imageId + '/action/Delete',
1060            withCredentials: true,
1061            data: JSON.stringify({'data': []})
1062          })
1063              .then(
1064                  function(response) {
1065                    var json = JSON.stringify(response.data);
1066                    var content = JSON.parse(json);
1067                    deferred.resolve(content);
1068                  },
1069                  function(error) {
1070                    console.log(error);
1071                    deferred.reject(error);
1072                  });
1073
1074          return deferred.promise;
1075        },
1076        activateImage: function(imageId) {
1077          var deferred = $q.defer();
1078          $http({
1079            method: 'PUT',
1080            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1081                imageId + '/attr/RequestedActivation',
1082            withCredentials: true,
1083            data:
1084                JSON.stringify({'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
1085          })
1086              .then(
1087                  function(response) {
1088                    var json = JSON.stringify(response.data);
1089                    var content = JSON.parse(json);
1090                    deferred.resolve(content);
1091                  },
1092                  function(error) {
1093                    console.log(error);
1094                    deferred.reject(error);
1095                  });
1096
1097          return deferred.promise;
1098        },
1099        uploadImage: function(file) {
1100          return $http({
1101                   method: 'POST',
1102                   timeout: 5 * 60 * 1000,
1103                   url: DataService.getHost() + '/upload/image',
1104                   // Overwrite the default 'application/json' Content-Type
1105                   headers: {'Content-Type': 'application/octet-stream'},
1106                   withCredentials: true,
1107                   data: file
1108                 })
1109              .then(function(response) {
1110                return response.data;
1111              });
1112        },
1113        downloadImage: function(host, filename) {
1114          return $http({
1115                   method: 'POST',
1116                   url: DataService.getHost() +
1117                       '/xyz/openbmc_project/software/action/DownloadViaTFTP',
1118                   withCredentials: true,
1119                   data: JSON.stringify({'data': [filename, host]}),
1120                   responseType: 'arraybuffer'
1121                 })
1122              .then(function(response) {
1123                return response.data;
1124              });
1125        },
1126        getServerInfo: function() {
1127          // TODO: openbmc/openbmc#3117 Need a way via REST to get
1128          // interfaces so we can get the system object(s) by the looking
1129          // for the system interface.
1130          return $http({
1131                   method: 'GET',
1132                   url: DataService.getHost() +
1133                       '/xyz/openbmc_project/inventory/system',
1134                   withCredentials: true
1135                 })
1136              .then(function(response) {
1137                return response.data;
1138              });
1139        },
1140        getBMCTime: function() {
1141          return $http({
1142                   method: 'GET',
1143                   url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
1144                   withCredentials: true
1145                 })
1146              .then(function(response) {
1147                return response.data;
1148              });
1149        },
1150        getTime: function() {
1151          return $http({
1152                   method: 'GET',
1153                   url: DataService.getHost() +
1154                       '/xyz/openbmc_project/time/enumerate',
1155                   withCredentials: true
1156                 })
1157              .then(function(response) {
1158                return response.data;
1159              });
1160        },
1161        // Even though NTPServers is a network interface specific path
1162        // (e.g. /xyz/openbmc_project/network/eth0/attr/NTPServers) it acts
1163        // like a global setting. Just use eth0 for setting and getting the
1164        // NTP Servers until it is moved to a non-network interface specific
1165        // path like it is in Redfish. TODO: openbmc/phosphor-time-manager#4
1166        getNTPServers: function() {
1167          return $http({
1168                   method: 'GET',
1169                   url: DataService.getHost() +
1170                       '/xyz/openbmc_project/network/eth0/attr/NTPServers',
1171                   headers: {
1172                     'Accept': 'application/json',
1173                     'Content-Type': 'application/json'
1174                   },
1175                   withCredentials: true
1176                 })
1177              .then(function(response) {
1178                return response.data;
1179              });
1180        },
1181        setNTPServers: function(ntpServers) {
1182          return $http({
1183                   method: 'PUT',
1184                   url: DataService.getHost() +
1185                       '/xyz/openbmc_project/network/eth0/attr/NTPServers',
1186                   headers: {
1187                     'Accept': 'application/json',
1188                     'Content-Type': 'application/json'
1189                   },
1190                   withCredentials: true,
1191                   data: JSON.stringify({'data': ntpServers})
1192                 })
1193              .then(function(response) {
1194                return response.data;
1195              });
1196        },
1197        setTimeMode: function(timeMode) {
1198          return $http({
1199                   method: 'PUT',
1200                   url: DataService.getHost() +
1201                       '/xyz/openbmc_project/time/sync_method/attr/TimeSyncMethod',
1202                   headers: {
1203                     'Accept': 'application/json',
1204                     'Content-Type': 'application/json'
1205                   },
1206                   withCredentials: true,
1207                   data: JSON.stringify({'data': timeMode})
1208                 })
1209              .then(function(response) {
1210                return response.data;
1211              });
1212        },
1213        setTimeOwner: function(timeOwner) {
1214          return $http({
1215                   method: 'PUT',
1216                   url: DataService.getHost() +
1217                       '/xyz/openbmc_project/time/owner/attr/TimeOwner',
1218                   headers: {
1219                     'Accept': 'application/json',
1220                     'Content-Type': 'application/json'
1221                   },
1222                   withCredentials: true,
1223                   data: JSON.stringify({'data': timeOwner})
1224                 })
1225              .then(function(response) {
1226                return response.data;
1227              });
1228        },
1229        setBMCTime: function(time) {
1230          return $http({
1231                   method: 'PUT',
1232                   url: DataService.getHost() +
1233                       '/xyz/openbmc_project/time/bmc/attr/Elapsed',
1234                   headers: {
1235                     'Accept': 'application/json',
1236                     'Content-Type': 'application/json'
1237                   },
1238                   withCredentials: true,
1239                   data: JSON.stringify({'data': time})
1240                 })
1241              .then(function(response) {
1242                return response.data;
1243              });
1244        },
1245        setHostTime: function(time) {
1246          return $http({
1247                   method: 'PUT',
1248                   url: DataService.getHost() +
1249                       '/xyz/openbmc_project/time/host/attr/Elapsed',
1250                   headers: {
1251                     'Accept': 'application/json',
1252                     'Content-Type': 'application/json'
1253                   },
1254                   withCredentials: true,
1255                   data: JSON.stringify({'data': time})
1256                 })
1257              .then(function(response) {
1258                return response.data;
1259              });
1260        },
1261        getHardwares: function(callback) {
1262          $http({
1263            method: 'GET',
1264            url: DataService.getHost() +
1265                '/xyz/openbmc_project/inventory/enumerate',
1266            withCredentials: true
1267          }).then(function(response) {
1268            var json = JSON.stringify(response.data);
1269            var content = JSON.parse(json);
1270            var hardwareData = [];
1271            var keyIndexMap = {};
1272            var title = '';
1273            var data = [];
1274            var searchText = '';
1275            var componentIndex = -1;
1276            var tempParts = [];
1277
1278            function isSubComponent(key) {
1279              for (var i = 0; i < Constants.HARDWARE.parent_components.length;
1280                   i++) {
1281                if (key.split(Constants.HARDWARE.parent_components[i]).length ==
1282                    2)
1283                  return true;
1284              }
1285
1286              return false;
1287            }
1288
1289            function titlelize(title) {
1290              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1291              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
1292                   i++) {
1293                if (title.toLowerCase().indexOf(
1294                        (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
1295                  return title.toUpperCase();
1296                }
1297              }
1298
1299              return title;
1300            }
1301
1302            function camelcaseToLabel(obj) {
1303              var transformed = [], label = '', value = '';
1304              for (var key in obj) {
1305                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1306                if (obj[key] !== '') {
1307                  value = obj[key];
1308                  if (value == 1 || value == 0) {
1309                    value = (value == 1) ? 'Yes' : 'No';
1310                  }
1311                  transformed.push({key: label, value: value});
1312                }
1313              }
1314
1315              return transformed;
1316            }
1317
1318            function getSearchText(data) {
1319              var searchText = '';
1320              for (var i = 0; i < data.length; i++) {
1321                searchText += ' ' + data[i].key + ' ' + data[i].value;
1322              }
1323
1324              return searchText;
1325            }
1326
1327            for (var key in content.data) {
1328              if (content.data.hasOwnProperty(key) &&
1329                  key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
1330                data = camelcaseToLabel(content.data[key]);
1331                searchText = getSearchText(data);
1332                title = key.split('/').pop();
1333
1334                title = titlelize(title);
1335
1336                if (!isSubComponent(key)) {
1337                  hardwareData.push(Object.assign(
1338                      {
1339                        path: key,
1340                        title: title,
1341                        selected: false,
1342                        expanded: false,
1343                        search_text: title.toLowerCase() + ' ' +
1344                            searchText.toLowerCase(),
1345                        sub_components: [],
1346                        original_data: {key: key, value: content.data[key]}
1347                      },
1348                      {items: data}));
1349
1350                  keyIndexMap[key] = hardwareData.length - 1;
1351                } else {
1352                  var tempParts = key.split('/');
1353                  tempParts.pop();
1354                  tempParts = tempParts.join('/');
1355                  componentIndex = keyIndexMap[tempParts];
1356                  data = content.data[key];
1357                  data.title = title;
1358                  hardwareData[componentIndex].sub_components.push(data);
1359                  hardwareData[componentIndex].search_text +=
1360                      ' ' + title.toLowerCase();
1361
1362                  // Sort the subcomponents alphanumeric so they are displayed
1363                  // on the inventory page in order (e.g. core 0, core 1, core
1364                  // 2, ... core 12, core 13)
1365                  hardwareData[componentIndex].sub_components.sort(function(
1366                      a, b) {
1367                    return a.title.localeCompare(
1368                        b.title, 'en', {numeric: true});
1369                  });
1370                }
1371              }
1372            }
1373
1374            if (callback) {
1375              callback(hardwareData, content.data);
1376            } else {
1377              return {data: hardwareData, original_data: content.data};
1378            }
1379          });
1380        },
1381        deleteLogs: function(logs) {
1382          var defer = $q.defer();
1383          var promises = [];
1384
1385          function finished() {
1386            defer.resolve();
1387          }
1388
1389          logs.forEach(function(item) {
1390            promises.push($http({
1391              method: 'POST',
1392              url: DataService.getHost() +
1393                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1394                  '/action/Delete',
1395              withCredentials: true,
1396              data: JSON.stringify({'data': []})
1397            }));
1398          });
1399
1400          $q.all(promises).then(finished);
1401
1402          return defer.promise;
1403        },
1404        resolveLogs: function(logs) {
1405          var defer = $q.defer();
1406          var promises = [];
1407
1408          function finished() {
1409            defer.resolve();
1410          }
1411
1412          logs.forEach(function(item) {
1413            promises.push($http({
1414              method: 'PUT',
1415              url: DataService.getHost() +
1416                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1417                  '/attr/Resolved',
1418              withCredentials: true,
1419              data: JSON.stringify({'data': '1'})
1420            }));
1421          });
1422
1423          $q.all(promises).then(finished);
1424
1425          return defer.promise;
1426        },
1427        getPowerConsumption: function() {
1428          return $http({
1429                   method: 'GET',
1430                   url: DataService.getHost() +
1431                       '/xyz/openbmc_project/sensors/power/total_power',
1432                   withCredentials: true
1433                 })
1434              .then(
1435                  function(response) {
1436                    var json = JSON.stringify(response.data);
1437                    var content = JSON.parse(json);
1438
1439                    return getScaledValue(
1440                               content.data.Value, content.data.Scale) +
1441                        ' ' +
1442                        Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
1443                  },
1444                  function(error) {
1445                    if ('Not Found' == error.statusText) {
1446                      return Constants.POWER_CONSUMPTION_TEXT.notavailable;
1447                    } else {
1448                      throw error;
1449                    }
1450                  });
1451        },
1452        getPowerCap: function() {
1453          return $http({
1454                   method: 'GET',
1455                   url: DataService.getHost() +
1456                       '/xyz/openbmc_project/control/host0/power_cap',
1457                   withCredentials: true
1458                 })
1459              .then(function(response) {
1460                return response.data;
1461              });
1462        },
1463        setPowerCapEnable: function(powerCapEnable) {
1464          return $http({
1465                   method: 'PUT',
1466                   url: DataService.getHost() +
1467                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCapEnable',
1468                   withCredentials: true,
1469                   data: JSON.stringify({'data': powerCapEnable})
1470                 })
1471              .then(function(response) {
1472                return response.data;
1473              });
1474        },
1475        setPowerCap: function(powerCap) {
1476          return $http({
1477                   method: 'PUT',
1478                   url: DataService.getHost() +
1479                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCap',
1480                   withCredentials: true,
1481                   data: JSON.stringify({'data': powerCap})
1482                 })
1483              .then(function(response) {
1484                return response.data;
1485              });
1486        },
1487        setHostname: function(hostname) {
1488          return $http({
1489                   method: 'PUT',
1490                   url: DataService.getHost() +
1491                       '/xyz/openbmc_project/network/config/attr/HostName',
1492                   withCredentials: true,
1493                   data: JSON.stringify({'data': hostname})
1494                 })
1495              .then(function(response) {
1496                return response.data;
1497              });
1498        },
1499      };
1500      return SERVICE;
1501    }
1502  ]);
1503})(window.angular);
1504