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