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                        if (numberIndex > 0) {
1099                          var titlePart = parts.splice(0, numberIndex);
1100                          titlePart = titlePart.join('');
1101                          titlePart = titlePart[0].toUpperCase() +
1102                              titlePart.substr(1, titlePart.length);
1103                          var versionPart = parts.join('-');
1104                          versions.push(
1105                              {title: titlePart, version: versionPart});
1106                        }
1107                      });
1108
1109                      return versions;
1110                    }
1111
1112                    // Get the list of functional images so we can compare
1113                    // later if an image is functional
1114                    if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
1115                      functionalImages =
1116                          content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
1117                              .endpoints;
1118                    }
1119                    for (var key in content.data) {
1120                      if (content.data.hasOwnProperty(key) &&
1121                          content.data[key].hasOwnProperty('Version')) {
1122                        var activationStatus = '';
1123
1124                        // If the image is "Functional" use that for the
1125                        // activation status, else use the value of
1126                        // "Activation"
1127                        // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
1128                        if (content.data[key].Activation) {
1129                          activationStatus =
1130                              content.data[key].Activation.split('.').pop();
1131                        }
1132
1133                        if (functionalImages.includes(key)) {
1134                          activationStatus = 'Functional';
1135                        }
1136
1137                        imageType = content.data[key].Purpose.split('.').pop();
1138                        isExtended = content.data[key].hasOwnProperty(
1139                                         'ExtendedVersion') &&
1140                            content.data[key].ExtendedVersion != '';
1141                        if (isExtended) {
1142                          extendedVersions = getFormatedExtendedVersions(
1143                              content.data[key].ExtendedVersion);
1144                        }
1145                        data.push(Object.assign(
1146                            {
1147                              path: key,
1148                              activationStatus: activationStatus,
1149                              imageId: key.split('/').pop(),
1150                              imageType: imageType,
1151                              isExtended: isExtended,
1152                              extended:
1153                                  {show: false, versions: extendedVersions},
1154                              data: {key: key, value: content.data[key]}
1155                            },
1156                            content.data[key]));
1157
1158                        if (activationStatus == 'Functional' &&
1159                            imageType == 'BMC') {
1160                          bmcActiveVersion = content.data[key].Version;
1161                        }
1162
1163                        if (activationStatus == 'Functional' &&
1164                            imageType == 'Host') {
1165                          hostActiveVersion = content.data[key].Version;
1166                        }
1167                      }
1168                    }
1169
1170                    deferred.resolve({
1171                      data: data,
1172                      bmcActiveVersion: bmcActiveVersion,
1173                      hostActiveVersion: hostActiveVersion
1174                    });
1175                  },
1176                  function(error) {
1177                    console.log(error);
1178                    deferred.reject(error);
1179                  });
1180
1181          return deferred.promise;
1182        },
1183        changePriority: function(imageId, priority) {
1184          return $http({
1185                   method: 'PUT',
1186                   url: DataService.getHost() +
1187                       '/xyz/openbmc_project/software/' + imageId +
1188                       '/attr/Priority',
1189                   withCredentials: true,
1190                   data: JSON.stringify({'data': priority})
1191                 })
1192              .then(function(response) {
1193                return response.data;
1194              });
1195        },
1196        deleteImage: function(imageId) {
1197          return $http({
1198                   method: 'POST',
1199                   url: DataService.getHost() +
1200                       '/xyz/openbmc_project/software/' + imageId +
1201                       '/action/Delete',
1202                   withCredentials: true,
1203                   data: JSON.stringify({'data': []})
1204                 })
1205              .then(function(response) {
1206                return response.data;
1207              });
1208        },
1209        activateImage: function(imageId) {
1210          return $http({
1211                   method: 'PUT',
1212                   url: DataService.getHost() +
1213                       '/xyz/openbmc_project/software/' + imageId +
1214                       '/attr/RequestedActivation',
1215                   withCredentials: true,
1216                   data: JSON.stringify(
1217                       {'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
1218                 })
1219              .then(function(response) {
1220                return response.data;
1221              });
1222        },
1223        uploadImage: function(file) {
1224          return $http({
1225                   method: 'POST',
1226                   timeout: 5 * 60 * 1000,
1227                   url: DataService.getHost() + '/upload/image',
1228                   // Overwrite the default 'application/json' Content-Type
1229                   headers: {'Content-Type': 'application/octet-stream'},
1230                   withCredentials: true,
1231                   data: file
1232                 })
1233              .then(function(response) {
1234                return response.data;
1235              });
1236        },
1237        downloadImage: function(host, filename) {
1238          return $http({
1239                   method: 'POST',
1240                   url: DataService.getHost() +
1241                       '/xyz/openbmc_project/software/action/DownloadViaTFTP',
1242                   withCredentials: true,
1243                   data: JSON.stringify({'data': [filename, host]}),
1244                   responseType: 'arraybuffer'
1245                 })
1246              .then(function(response) {
1247                return response.data;
1248              });
1249        },
1250        getServerInfo: function() {
1251          // TODO: openbmc/openbmc#3117 Need a way via REST to get
1252          // interfaces so we can get the system object(s) by the looking
1253          // for the system interface.
1254          return $http({
1255                   method: 'GET',
1256                   url: DataService.getHost() +
1257                       '/xyz/openbmc_project/inventory/system',
1258                   withCredentials: true
1259                 })
1260              .then(function(response) {
1261                return response.data;
1262              });
1263        },
1264        getBMCTime: function() {
1265          return $http({
1266                   method: 'GET',
1267                   url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
1268                   withCredentials: true
1269                 })
1270              .then(function(response) {
1271                return response.data;
1272              });
1273        },
1274        getTime: function() {
1275          return $http({
1276                   method: 'GET',
1277                   url: DataService.getHost() +
1278                       '/xyz/openbmc_project/time/enumerate',
1279                   withCredentials: true
1280                 })
1281              .then(function(response) {
1282                return response.data;
1283              });
1284        },
1285        // Even though NTPServers is a network interface specific path
1286        // (e.g. /xyz/openbmc_project/network/eth0/attr/NTPServers) it acts
1287        // like a global setting. Just use eth0 for setting and getting the
1288        // NTP Servers until it is moved to a non-network interface specific
1289        // path like it is in Redfish. TODO: openbmc/phosphor-time-manager#4
1290        getNTPServers: function() {
1291          return $http({
1292                   method: 'GET',
1293                   url: DataService.getHost() +
1294                       '/xyz/openbmc_project/network/eth0/attr/NTPServers',
1295                   withCredentials: true
1296                 })
1297              .then(function(response) {
1298                return response.data;
1299              });
1300        },
1301        setNTPServers: function(ntpServers) {
1302          return $http({
1303                   method: 'PUT',
1304                   url: DataService.getHost() +
1305                       '/xyz/openbmc_project/network/eth0/attr/NTPServers',
1306                   withCredentials: true,
1307                   data: JSON.stringify({'data': ntpServers})
1308                 })
1309              .then(function(response) {
1310                return response.data;
1311              });
1312        },
1313        setTimeMode: function(timeMode) {
1314          return $http({
1315                   method: 'PUT',
1316                   url: DataService.getHost() +
1317                       '/xyz/openbmc_project/time/sync_method/attr/TimeSyncMethod',
1318                   withCredentials: true,
1319                   data: JSON.stringify({'data': timeMode})
1320                 })
1321              .then(function(response) {
1322                return response.data;
1323              });
1324        },
1325        setTimeOwner: function(timeOwner) {
1326          return $http({
1327                   method: 'PUT',
1328                   url: DataService.getHost() +
1329                       '/xyz/openbmc_project/time/owner/attr/TimeOwner',
1330                   withCredentials: true,
1331                   data: JSON.stringify({'data': timeOwner})
1332                 })
1333              .then(function(response) {
1334                return response.data;
1335              });
1336        },
1337        setBMCTime: function(time) {
1338          return $http({
1339                   method: 'PUT',
1340                   url: DataService.getHost() +
1341                       '/xyz/openbmc_project/time/bmc/attr/Elapsed',
1342                   withCredentials: true,
1343                   data: JSON.stringify({'data': time})
1344                 })
1345              .then(function(response) {
1346                return response.data;
1347              });
1348        },
1349        setHostTime: function(time) {
1350          return $http({
1351                   method: 'PUT',
1352                   url: DataService.getHost() +
1353                       '/xyz/openbmc_project/time/host/attr/Elapsed',
1354                   withCredentials: true,
1355                   data: JSON.stringify({'data': time})
1356                 })
1357              .then(function(response) {
1358                return response.data;
1359              });
1360        },
1361        getCertificateLocations: function() {
1362          return $http({
1363                   method: 'GET',
1364                   url: DataService.getHost() +
1365                       '/redfish/v1/CertificateService/CertificateLocations',
1366                   withCredentials: true
1367                 })
1368              .then(function(response) {
1369                return response.data;
1370              });
1371        },
1372        getCertificate: function(location) {
1373          return $http({
1374                   method: 'GET',
1375                   url: DataService.getHost() + location,
1376                   withCredentials: true
1377                 })
1378              .then(function(response) {
1379                return response.data;
1380              });
1381        },
1382        addNewCertificate: function(file, type) {
1383          return $http({
1384                   method: 'POST',
1385                   url: DataService.getHost() + type.location,
1386                   headers: {'Content-Type': 'application/x-pem-file'},
1387                   withCredentials: true,
1388                   data: file
1389                 })
1390              .then(function(response) {
1391                return response.data;
1392              });
1393        },
1394        replaceCertificate: function(data) {
1395          return $http({
1396                   method: 'POST',
1397                   url: DataService.getHost() +
1398                       '/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate',
1399                   withCredentials: true,
1400                   data: data
1401                 })
1402              .then(function(response) {
1403                return response.data;
1404              });
1405        },
1406        getHardwares: function(callback) {
1407          $http({
1408            method: 'GET',
1409            url: DataService.getHost() +
1410                '/xyz/openbmc_project/inventory/enumerate',
1411            withCredentials: true
1412          }).then(function(response) {
1413            var json = JSON.stringify(response.data);
1414            var content = JSON.parse(json);
1415            var hardwareData = [];
1416            var keyIndexMap = {};
1417            var title = '';
1418            var depth = '';
1419            var data = [];
1420            var searchText = '';
1421            var componentIndex = -1;
1422            var parent = '';
1423
1424            function isSubComponent(key) {
1425              for (var i = 0; i < Constants.HARDWARE.parent_components.length;
1426                   i++) {
1427                if (key.split(Constants.HARDWARE.parent_components[i]).length ==
1428                    2)
1429                  return true;
1430              }
1431
1432              return false;
1433            }
1434
1435            function titlelize(title) {
1436              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1437              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
1438                   i++) {
1439                if (title.toLowerCase().indexOf(
1440                        (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
1441                  return title.toUpperCase();
1442                }
1443              }
1444
1445              return title;
1446            }
1447
1448            function camelcaseToLabel(obj) {
1449              var transformed = [], label = '', value = '';
1450              for (var key in obj) {
1451                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1452                if (obj[key] !== '') {
1453                  value = obj[key];
1454                  if (value == 1 || value == 0) {
1455                    value = (value == 1) ? 'Yes' : 'No';
1456                  }
1457                  transformed.push({key: label, value: value});
1458                }
1459              }
1460
1461              return transformed;
1462            }
1463
1464            function determineParent(key) {
1465              var levels = key.split('/');
1466              levels.pop();
1467              return levels.join('/');
1468            }
1469
1470            function getSearchText(data) {
1471              var searchText = '';
1472              for (var i = 0; i < data.length; i++) {
1473                searchText += ' ' + data[i].key + ' ' + data[i].value;
1474              }
1475
1476              return searchText;
1477            }
1478
1479            for (var key in content.data) {
1480              if (content.data.hasOwnProperty(key) &&
1481                  key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
1482                data = camelcaseToLabel(content.data[key]);
1483                searchText = getSearchText(data);
1484                title = key.split('/').pop();
1485                // All and only associations have the property "endpoints".
1486                // We don't want to show associations on the hardware page.
1487                // Example: An association from the BMC inventory item to the
1488                // BMC firmware images.
1489                if (content.data[key].hasOwnProperty('endpoints')) {
1490                  continue;
1491                }
1492
1493                title = titlelize(title);
1494                // e.g. /xyz/openbmc_project/inventory/system and
1495                // /xyz/openbmc_project/inventory/system/chassis are depths of 5
1496                // and 6.
1497                depth = key.split('/').length;
1498                parent = determineParent(key);
1499
1500                if (!isSubComponent(key)) {
1501                  hardwareData.push(Object.assign(
1502                      {
1503                        path: key,
1504                        title: title,
1505                        depth: depth,
1506                        parent: parent,
1507                        selected: false,
1508                        expanded: false,
1509                        search_text: title.toLowerCase() + ' ' +
1510                            searchText.toLowerCase(),
1511                        sub_components: [],
1512                        original_data: {key: key, value: content.data[key]}
1513                      },
1514                      {items: data}));
1515
1516                  keyIndexMap[key] = hardwareData.length - 1;
1517                } else {
1518                  parent = determineParent(key)
1519                  componentIndex = keyIndexMap[parent];
1520                  data = content.data[key];
1521                  data.title = title;
1522                  hardwareData[componentIndex].sub_components.push(data);
1523                  hardwareData[componentIndex].search_text +=
1524                      ' ' + title.toLowerCase();
1525
1526                  // Sort the subcomponents alphanumeric so they are displayed
1527                  // on the inventory page in order (e.g. core 0, core 1, core
1528                  // 2, ... core 12, core 13)
1529                  hardwareData[componentIndex].sub_components.sort(function(
1530                      a, b) {
1531                    return a.title.localeCompare(
1532                        b.title, 'en', {numeric: true});
1533                  });
1534                }
1535              }
1536            }
1537            // First, order the components by depth and then place the child
1538            // components beneath their parent component alphanumerically. Can
1539            // be removed with completion of
1540            // https://github.com/openbmc/openbmc/issues/3401
1541            // TODO: Remove this once implemented in back end
1542            hardwareData.sort(function(a, b) {
1543              if (a.depth < b.depth) return -1;
1544              if (a.depth > b.depth) return 1;
1545              return b.title.localeCompare(a.title, 'en', {numeric: true});
1546            });
1547
1548            var orderedComponents = [];
1549
1550            for (var i = 0; i < hardwareData.length; i++) {
1551              if (!keyIndexMap[hardwareData[i].parent]) {
1552                orderedComponents.push(hardwareData[i]);
1553              } else {
1554                for (var j = 0; j < orderedComponents.length; j++) {
1555                  if (orderedComponents[j].path === hardwareData[i].parent) {
1556                    var child = hardwareData[i];
1557                    orderedComponents.splice(j + 1, 0, child);
1558                  }
1559                }
1560              }
1561            }
1562
1563            if (callback) {
1564              callback(orderedComponents, content.data);
1565            } else {
1566              return {data: orderedComponents, original_data: content.data};
1567            }
1568          });
1569        },
1570        deleteLogs: function(logs) {
1571          var defer = $q.defer();
1572          var promises = [];
1573
1574          function finished() {
1575            defer.resolve();
1576          }
1577
1578          logs.forEach(function(item) {
1579            promises.push($http({
1580              method: 'POST',
1581              url: DataService.getHost() +
1582                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1583                  '/action/Delete',
1584              withCredentials: true,
1585              data: JSON.stringify({'data': []})
1586            }));
1587          });
1588
1589          $q.all(promises).then(finished);
1590
1591          return defer.promise;
1592        },
1593        resolveLogs: function(logs) {
1594          var promises = [];
1595
1596          logs.forEach(function(item) {
1597            promises.push($http({
1598              method: 'PUT',
1599              url: DataService.getHost() +
1600                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1601                  '/attr/Resolved',
1602              withCredentials: true,
1603              data: JSON.stringify({'data': true})
1604            }));
1605          });
1606          return $q.all(promises);
1607        },
1608        setRemoteLoggingServer: (data) => {
1609          const ip = data.hostname;
1610          const port = data.port;
1611          const setIPRequest = $http({
1612            method: 'PUT',
1613            url: DataService.getHost() +
1614                '/xyz/openbmc_project/logging/config/remote/attr/Address',
1615            withCredentials: true,
1616            data: {'data': ip}
1617          });
1618          const setPortRequest = $http({
1619            method: 'PUT',
1620            url: DataService.getHost() +
1621                '/xyz/openbmc_project/logging/config/remote/attr/Port',
1622            withCredentials: true,
1623            data: {'data': port}
1624          });
1625          const promises = [setIPRequest, setPortRequest];
1626          return $q.all(promises);
1627        },
1628        getRemoteLoggingServer: () => {
1629          return $http({
1630                   method: 'GET',
1631                   url: DataService.getHost() +
1632                       '/xyz/openbmc_project/logging/config/remote',
1633                   withCredentials: true
1634                 })
1635              .then((response) => {
1636                const remoteServer = response.data.data;
1637                if (remoteServer === undefined) {
1638                  return undefined;
1639                }
1640                const hostname = remoteServer.Address;
1641                const port = remoteServer.Port;
1642                if (hostname === '') {
1643                  return undefined;
1644                } else {
1645                  return {
1646                    hostname, port
1647                  }
1648                }
1649              });
1650        },
1651        disableRemoteLoggingServer: () => {
1652          return SERVICE.setRemoteLoggingServer({hostname: '', port: 0});
1653        },
1654        updateRemoteLoggingServer: (data) => {
1655          // Recommended to disable existing configuration
1656          // before updating config to new server
1657          // https://github.com/openbmc/phosphor-logging#changing-the-rsyslog-server
1658          return SERVICE.disableRemoteLoggingServer()
1659              .then(() => {
1660                return SERVICE.setRemoteLoggingServer(data);
1661              })
1662              .catch(() => {
1663                // try updating server even if initial disable attempt fails
1664                return SERVICE.setRemoteLoggingServer(data);
1665              });
1666        },
1667        getPowerConsumption: function() {
1668          return $http({
1669                   method: 'GET',
1670                   url: DataService.getHost() +
1671                       '/xyz/openbmc_project/sensors/power/total_power',
1672                   withCredentials: true
1673                 })
1674              .then(
1675                  function(response) {
1676                    var json = JSON.stringify(response.data);
1677                    var content = JSON.parse(json);
1678
1679                    return getScaledValue(
1680                               content.data.Value, content.data.Scale) +
1681                        ' ' +
1682                        Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
1683                  },
1684                  function(error) {
1685                    if ('Not Found' == error.statusText) {
1686                      return Constants.POWER_CONSUMPTION_TEXT.notavailable;
1687                    } else {
1688                      throw error;
1689                    }
1690                  });
1691        },
1692        getPowerCap: function() {
1693          return $http({
1694                   method: 'GET',
1695                   url: DataService.getHost() +
1696                       '/xyz/openbmc_project/control/host0/power_cap',
1697                   withCredentials: true
1698                 })
1699              .then(function(response) {
1700                return response.data;
1701              });
1702        },
1703        setPowerCapEnable: function(powerCapEnable) {
1704          return $http({
1705                   method: 'PUT',
1706                   url: DataService.getHost() +
1707                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCapEnable',
1708                   withCredentials: true,
1709                   data: JSON.stringify({'data': powerCapEnable})
1710                 })
1711              .then(function(response) {
1712                return response.data;
1713              });
1714        },
1715        setPowerCap: function(powerCap) {
1716          return $http({
1717                   method: 'PUT',
1718                   url: DataService.getHost() +
1719                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCap',
1720                   withCredentials: true,
1721                   data: JSON.stringify({'data': powerCap})
1722                 })
1723              .then(function(response) {
1724                return response.data;
1725              });
1726        },
1727        setHostname: function(hostname) {
1728          return $http({
1729                   method: 'PUT',
1730                   url: DataService.getHost() +
1731                       '/xyz/openbmc_project/network/config/attr/HostName',
1732                   withCredentials: true,
1733                   data: JSON.stringify({'data': hostname})
1734                 })
1735              .then(function(response) {
1736                return response.data;
1737              });
1738        },
1739      };
1740      return SERVICE;
1741    }
1742  ]);
1743})(window.angular);
1744