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