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