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