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, callback) {
842          $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              .then(
850                  function(response) {
851                    var json = JSON.stringify(response.data);
852                    var content = JSON.parse(json);
853                    if (callback) {
854                      return callback(content.status);
855                    }
856                  },
857                  function(error) {
858                    if (callback) {
859                      callback(error);
860                    } else {
861                      console.log(error);
862                    }
863                  });
864        },
865        bmcReboot: function(callback) {
866          $http({
867            method: 'PUT',
868            url: DataService.getHost() +
869                '/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition',
870            withCredentials: true,
871            data: JSON.stringify(
872                {'data': 'xyz.openbmc_project.State.BMC.Transition.Reboot'})
873          })
874              .then(
875                  function(response) {
876                    var json = JSON.stringify(response.data);
877                    var content = JSON.parse(json);
878                    if (callback) {
879                      return callback(content.status);
880                    }
881                  },
882                  function(error) {
883                    if (callback) {
884                      callback(error);
885                    } else {
886                      console.log(error);
887                    }
888                  });
889        },
890        getLastRebootTime: function() {
891          return $http({
892                   method: 'GET',
893                   url: DataService.getHost() +
894                       '/xyz/openbmc_project/state/bmc0/attr/LastRebootTime',
895                   withCredentials: true
896                 })
897              .then(function(response) {
898                return response.data;
899              });
900        },
901        hostPowerOn: function() {
902          var deferred = $q.defer();
903          $http({
904            method: 'PUT',
905            url: DataService.getHost() +
906                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
907            withCredentials: true,
908            data: JSON.stringify(
909                {'data': 'xyz.openbmc_project.State.Host.Transition.On'})
910          })
911              .then(
912                  function(response) {
913                    var json = JSON.stringify(response.data);
914                    var content = JSON.parse(json);
915                    deferred.resolve(content.status);
916                  },
917                  function(error) {
918                    console.log(error);
919                    deferred.reject(error);
920                  });
921          return deferred.promise;
922        },
923        hostPowerOff: function() {
924          var deferred = $q.defer();
925          $http({
926            method: 'PUT',
927            url: DataService.getHost() +
928                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
929            withCredentials: true,
930            data: JSON.stringify(
931                {'data': 'xyz.openbmc_project.State.Host.Transition.Off'})
932          })
933              .then(
934                  function(response) {
935                    var json = JSON.stringify(response.data);
936                    var content = JSON.parse(json);
937                    deferred.resolve(content.status);
938                  },
939                  function(error) {
940                    console.log(error);
941                    deferred.reject(error);
942                  });
943          return deferred.promise;
944        },
945        hostReboot: function() {
946          var deferred = $q.defer();
947          $http({
948            method: 'PUT',
949            url: DataService.getHost() +
950                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
951            withCredentials: true,
952            data: JSON.stringify(
953                {'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'})
954          })
955              .then(
956                  function(response) {
957                    var json = JSON.stringify(response.data);
958                    var content = JSON.parse(json);
959                    deferred.resolve(content.status);
960                  },
961                  function(error) {
962                    console.log(error);
963                    deferred.reject(error);
964                  });
965
966          return deferred.promise;
967        },
968        hostShutdown: function(callback) {
969          $http({
970            method: 'POST',
971            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
972            withCredentials: true,
973            data: JSON.stringify({'data': []})
974          })
975              .then(
976                  function(response) {
977                    var json = JSON.stringify(response.data);
978                    var content = JSON.parse(json);
979                    if (callback) {
980                      return callback(content);
981                    }
982                  },
983                  function(error) {
984                    if (callback) {
985                      callback(error);
986                    } else {
987                      console.log(error);
988                    }
989                  });
990        },
991        getLastPowerTime: function() {
992          return $http({
993                   method: 'GET',
994                   url: DataService.getHost() +
995                       '/xyz/openbmc_project/state/chassis0/attr/LastStateChangeTime',
996                   withCredentials: true
997                 })
998              .then(function(response) {
999                return response.data;
1000              });
1001        },
1002        getLogs: function() {
1003          var deferred = $q.defer();
1004          $http({
1005            method: 'GET',
1006            url: DataService.getHost() +
1007                '/xyz/openbmc_project/logging/enumerate',
1008            withCredentials: true
1009          })
1010              .then(
1011                  function(response) {
1012                    var json = JSON.stringify(response.data);
1013                    var content = JSON.parse(json);
1014                    var dataClone = JSON.parse(JSON.stringify(content.data));
1015                    var data = [];
1016                    var severityCode = '';
1017                    var priority = '';
1018                    var health = '';
1019                    var relatedItems = [];
1020                    var eventID = 'None';
1021                    var description = 'None';
1022
1023                    for (var key in content.data) {
1024                      if (content.data.hasOwnProperty(key) &&
1025                          content.data[key].hasOwnProperty('Id')) {
1026                        var severityFlags = {
1027                          low: false,
1028                          medium: false,
1029                          high: false
1030                        };
1031                        severityCode =
1032                            content.data[key].Severity.split('.').pop();
1033                        priority =
1034                            Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
1035                        severityFlags[priority.toLowerCase()] = true;
1036                        relatedItems = [];
1037                        content.data[key].associations.forEach(function(item) {
1038                          relatedItems.push(item[2]);
1039                        });
1040
1041                        if (content.data[key].hasOwnProperty(['EventID'])) {
1042                          eventID = content.data[key].EventID;
1043                        }
1044
1045                        if (content.data[key].hasOwnProperty(['Description'])) {
1046                          description = content.data[key].Description;
1047                        }
1048
1049                        data.push(Object.assign(
1050                            {
1051                              path: key,
1052                              copied: false,
1053                              priority: priority,
1054                              severity_code: severityCode,
1055                              severity_flags: severityFlags,
1056                              additional_data:
1057                                  content.data[key].AdditionalData.join('\n'),
1058                              type: content.data[key].Message,
1059                              selected: false,
1060                              search_text:
1061                                  ('#' + content.data[key].Id + ' ' +
1062                                   severityCode + ' ' +
1063                                   content.data[key].Message + ' ' +
1064                                   content.data[key].Severity + ' ' +
1065                                   content.data[key].AdditionalData.join(' '))
1066                                      .toLowerCase(),
1067                              meta: false,
1068                              confirm: false,
1069                              related_items: relatedItems,
1070                              eventID: eventID,
1071                              description: description,
1072                              data: {key: key, value: content.data[key]}
1073                            },
1074                            content.data[key]));
1075                      }
1076                    }
1077                    deferred.resolve({data: data, original: dataClone});
1078                  },
1079                  function(error) {
1080                    console.log(error);
1081                    deferred.reject(error);
1082                  });
1083
1084          return deferred.promise;
1085        },
1086        getAllSensorStatus: function(callback) {
1087          $http({
1088            method: 'GET',
1089            url: DataService.getHost() +
1090                '/xyz/openbmc_project/sensors/enumerate',
1091            withCredentials: true
1092          })
1093              .then(
1094                  function(response) {
1095                    var json = JSON.stringify(response.data);
1096                    var content = JSON.parse(json);
1097                    var dataClone = JSON.parse(JSON.stringify(content.data));
1098                    var sensorData = [];
1099                    var severity = {};
1100                    var title = '';
1101                    var tempKeyParts = [];
1102                    var order = 0;
1103                    var customOrder = 0;
1104
1105                    function getSensorStatus(reading) {
1106                      var severityFlags = {
1107                        critical: false,
1108                        warning: false,
1109                        normal: false
1110                      },
1111                          severityText = '', order = 0;
1112
1113                      if (reading.hasOwnProperty('CriticalLow') &&
1114                          reading.Value < reading.CriticalLow) {
1115                        severityFlags.critical = true;
1116                        severityText = 'critical';
1117                        order = 2;
1118                      } else if (
1119                          reading.hasOwnProperty('CriticalHigh') &&
1120                          reading.Value > reading.CriticalHigh) {
1121                        severityFlags.critical = true;
1122                        severityText = 'critical';
1123                        order = 2;
1124                      } else if (
1125                          reading.hasOwnProperty('CriticalLow') &&
1126                          reading.hasOwnProperty('WarningLow') &&
1127                          reading.Value >= reading.CriticalLow &&
1128                          reading.Value <= reading.WarningLow) {
1129                        severityFlags.warning = true;
1130                        severityText = 'warning';
1131                        order = 1;
1132                      } else if (
1133                          reading.hasOwnProperty('WarningHigh') &&
1134                          reading.hasOwnProperty('CriticalHigh') &&
1135                          reading.Value >= reading.WarningHigh &&
1136                          reading.Value <= reading.CriticalHigh) {
1137                        severityFlags.warning = true;
1138                        severityText = 'warning';
1139                        order = 1;
1140                      } else {
1141                        severityFlags.normal = true;
1142                        severityText = 'normal';
1143                      }
1144                      return {
1145                        flags: severityFlags,
1146                        severityText: severityText,
1147                        order: order
1148                      };
1149                    }
1150
1151                    for (var key in content.data) {
1152                      if (content.data.hasOwnProperty(key) &&
1153                          content.data[key].hasOwnProperty('Unit')) {
1154                        severity = getSensorStatus(content.data[key]);
1155
1156                        if (!content.data[key].hasOwnProperty('CriticalLow')) {
1157                          content.data[key].CriticalLow = '--';
1158                          content.data[key].CriticalHigh = '--';
1159                        }
1160
1161                        if (!content.data[key].hasOwnProperty('WarningLow')) {
1162                          content.data[key].WarningLow = '--';
1163                          content.data[key].WarningHigh = '--';
1164                        }
1165
1166                        tempKeyParts = key.split('/');
1167                        title = tempKeyParts.pop();
1168                        title = tempKeyParts.pop() + '_' + title;
1169                        title = title.split('_')
1170                                    .map(function(item) {
1171                                      return item.toLowerCase()
1172                                                 .charAt(0)
1173                                                 .toUpperCase() +
1174                                          item.slice(1);
1175                                    })
1176                                    .reduce(function(prev, el) {
1177                                      return prev + ' ' + el;
1178                                    });
1179
1180                        content.data[key].Value = getScaledValue(
1181                            content.data[key].Value, content.data[key].Scale);
1182                        content.data[key].CriticalLow = getScaledValue(
1183                            content.data[key].CriticalLow,
1184                            content.data[key].Scale);
1185                        content.data[key].CriticalHigh = getScaledValue(
1186                            content.data[key].CriticalHigh,
1187                            content.data[key].Scale);
1188                        content.data[key].WarningLow = getScaledValue(
1189                            content.data[key].WarningLow,
1190                            content.data[key].Scale);
1191                        content.data[key].WarningHigh = getScaledValue(
1192                            content.data[key].WarningHigh,
1193                            content.data[key].Scale);
1194                        if (Constants.SENSOR_SORT_ORDER.indexOf(
1195                                content.data[key].Unit) > -1) {
1196                          customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
1197                              content.data[key].Unit);
1198                        } else {
1199                          customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
1200                        }
1201
1202                        sensorData.push(Object.assign(
1203                            {
1204                              path: key,
1205                              selected: false,
1206                              confirm: false,
1207                              copied: false,
1208                              title: title,
1209                              unit:
1210                                  Constants
1211                                      .SENSOR_UNIT_MAP[content.data[key].Unit],
1212                              severity_flags: severity.flags,
1213                              status: severity.severityText,
1214                              order: severity.order,
1215                              custom_order: customOrder,
1216                              search_text:
1217                                  (title + ' ' + content.data[key].Value + ' ' +
1218                                   Constants.SENSOR_UNIT_MAP[content.data[key]
1219                                                                 .Unit] +
1220                                   ' ' + severity.severityText + ' ' +
1221                                   content.data[key].CriticalLow + ' ' +
1222                                   content.data[key].CriticalHigh + ' ' +
1223                                   content.data[key].WarningLow + ' ' +
1224                                   content.data[key].WarningHigh + ' ')
1225                                      .toLowerCase(),
1226                              original_data:
1227                                  {key: key, value: content.data[key]}
1228                            },
1229                            content.data[key]));
1230                      }
1231                    }
1232
1233                    callback(sensorData, dataClone);
1234                  },
1235                  function(error) {
1236                    console.log(error);
1237                  });
1238        },
1239        getActivation: function(imageId) {
1240          return $http({
1241                   method: 'GET',
1242                   url: DataService.getHost() +
1243                       '/xyz/openbmc_project/software/' + imageId +
1244                       '/attr/Activation',
1245                   withCredentials: true
1246                 })
1247              .then(function(response) {
1248                return response.data;
1249              });
1250        },
1251        getFirmwares: function() {
1252          var deferred = $q.defer();
1253          $http({
1254            method: 'GET',
1255            url: DataService.getHost() +
1256                '/xyz/openbmc_project/software/enumerate',
1257            withCredentials: true
1258          })
1259              .then(
1260                  function(response) {
1261                    var json = JSON.stringify(response.data);
1262                    var content = JSON.parse(json);
1263                    var data = [];
1264                    var isExtended = false;
1265                    var bmcActiveVersion = '';
1266                    var hostActiveVersion = '';
1267                    var imageType = '';
1268                    var extendedVersions = [];
1269                    var functionalImages = [];
1270
1271                    function getFormatedExtendedVersions(extendedVersion) {
1272                      var versions = [];
1273                      extendedVersion = extendedVersion.split(',');
1274
1275                      extendedVersion.forEach(function(item) {
1276                        var parts = item.split('-');
1277                        var numberIndex = 0;
1278                        for (var i = 0; i < parts.length; i++) {
1279                          if (/[0-9]/.test(parts[i])) {
1280                            numberIndex = i;
1281                            break;
1282                          }
1283                        }
1284                        var titlePart = parts.splice(0, numberIndex);
1285                        titlePart = titlePart.join('');
1286                        titlePart = titlePart[0].toUpperCase() +
1287                            titlePart.substr(1, titlePart.length);
1288                        var versionPart = parts.join('-');
1289                        versions.push({title: titlePart, version: versionPart});
1290                      });
1291
1292                      return versions;
1293                    }
1294
1295                    // Get the list of functional images so we can compare
1296                    // later if an image is functional
1297                    if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
1298                      functionalImages =
1299                          content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
1300                              .endpoints;
1301                    }
1302                    for (var key in content.data) {
1303                      if (content.data.hasOwnProperty(key) &&
1304                          content.data[key].hasOwnProperty('Version')) {
1305                        var activationStatus = '';
1306
1307                        // If the image is "Functional" use that for the
1308                        // activation status, else use the value of
1309                        // "Activation"
1310                        // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
1311                        if (content.data[key].Activation) {
1312                          activationStatus =
1313                              content.data[key].Activation.split('.').pop();
1314                        }
1315
1316                        if (functionalImages.includes(key)) {
1317                          activationStatus = 'Functional';
1318                        }
1319
1320                        imageType = content.data[key].Purpose.split('.').pop();
1321                        isExtended = content.data[key].hasOwnProperty(
1322                                         'ExtendedVersion') &&
1323                            content.data[key].ExtendedVersion != '';
1324                        if (isExtended) {
1325                          extendedVersions = getFormatedExtendedVersions(
1326                              content.data[key].ExtendedVersion);
1327                        }
1328                        data.push(Object.assign(
1329                            {
1330                              path: key,
1331                              activationStatus: activationStatus,
1332                              imageId: key.split('/').pop(),
1333                              imageType: imageType,
1334                              isExtended: isExtended,
1335                              extended:
1336                                  {show: false, versions: extendedVersions},
1337                              data: {key: key, value: content.data[key]}
1338                            },
1339                            content.data[key]));
1340
1341                        if (activationStatus == 'Functional' &&
1342                            imageType == 'BMC') {
1343                          bmcActiveVersion = content.data[key].Version;
1344                        }
1345
1346                        if (activationStatus == 'Functional' &&
1347                            imageType == 'Host') {
1348                          hostActiveVersion = content.data[key].Version;
1349                        }
1350                      }
1351                    }
1352
1353                    deferred.resolve({
1354                      data: data,
1355                      bmcActiveVersion: bmcActiveVersion,
1356                      hostActiveVersion: hostActiveVersion
1357                    });
1358                  },
1359                  function(error) {
1360                    console.log(error);
1361                    deferred.reject(error);
1362                  });
1363
1364          return deferred.promise;
1365        },
1366        changePriority: function(imageId, priority) {
1367          var deferred = $q.defer();
1368          $http({
1369            method: 'PUT',
1370            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1371                imageId + '/attr/Priority',
1372            withCredentials: true,
1373            data: JSON.stringify({'data': priority})
1374          })
1375              .then(
1376                  function(response) {
1377                    var json = JSON.stringify(response.data);
1378                    var content = JSON.parse(json);
1379                    deferred.resolve(content);
1380                  },
1381                  function(error) {
1382                    console.log(error);
1383                    deferred.reject(error);
1384                  });
1385
1386          return deferred.promise;
1387        },
1388        deleteImage: function(imageId) {
1389          var deferred = $q.defer();
1390          $http({
1391            method: 'POST',
1392            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1393                imageId + '/action/Delete',
1394            withCredentials: true,
1395            data: JSON.stringify({'data': []})
1396          })
1397              .then(
1398                  function(response) {
1399                    var json = JSON.stringify(response.data);
1400                    var content = JSON.parse(json);
1401                    deferred.resolve(content);
1402                  },
1403                  function(error) {
1404                    console.log(error);
1405                    deferred.reject(error);
1406                  });
1407
1408          return deferred.promise;
1409        },
1410        activateImage: function(imageId) {
1411          var deferred = $q.defer();
1412          $http({
1413            method: 'PUT',
1414            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1415                imageId + '/attr/RequestedActivation',
1416            withCredentials: true,
1417            data:
1418                JSON.stringify({'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
1419          })
1420              .then(
1421                  function(response) {
1422                    var json = JSON.stringify(response.data);
1423                    var content = JSON.parse(json);
1424                    deferred.resolve(content);
1425                  },
1426                  function(error) {
1427                    console.log(error);
1428                    deferred.reject(error);
1429                  });
1430
1431          return deferred.promise;
1432        },
1433        uploadImage: function(file) {
1434          return $http({
1435                   method: 'POST',
1436                   timeout: 5 * 60 * 1000,
1437                   url: DataService.getHost() + '/upload/image',
1438                   // Overwrite the default 'application/json' Content-Type
1439                   headers: {'Content-Type': 'application/octet-stream'},
1440                   withCredentials: true,
1441                   data: file
1442                 })
1443              .then(function(response) {
1444                return response.data;
1445              });
1446        },
1447        downloadImage: function(host, filename) {
1448          return $http({
1449                   method: 'POST',
1450                   url: DataService.getHost() +
1451                       '/xyz/openbmc_project/software/action/DownloadViaTFTP',
1452                   withCredentials: true,
1453                   data: JSON.stringify({'data': [filename, host]}),
1454                   responseType: 'arraybuffer'
1455                 })
1456              .then(function(response) {
1457                return response.data;
1458              });
1459        },
1460        getServerInfo: function() {
1461          // TODO: openbmc/openbmc#3117 Need a way via REST to get
1462          // interfaces so we can get the system object(s) by the looking
1463          // for the system interface.
1464          return $http({
1465                   method: 'GET',
1466                   url: DataService.getHost() +
1467                       '/xyz/openbmc_project/inventory/system',
1468                   withCredentials: true
1469                 })
1470              .then(function(response) {
1471                return response.data;
1472              });
1473        },
1474        getBMCTime: function() {
1475          return $http({
1476                   method: 'GET',
1477                   url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
1478                   withCredentials: true
1479                 })
1480              .then(function(response) {
1481                return response.data;
1482              });
1483        },
1484        getTime: function() {
1485          return $http({
1486                   method: 'GET',
1487                   url: DataService.getHost() +
1488                       '/xyz/openbmc_project/time/enumerate',
1489                   withCredentials: true
1490                 })
1491              .then(function(response) {
1492                return response.data;
1493              });
1494        },
1495        // Even though NTPServers is a network interface specific path
1496        // (e.g. /xyz/openbmc_project/network/eth0/attr/NTPServers) it acts
1497        // like a global setting. Just use eth0 for setting and getting the
1498        // NTP Servers until it is moved to a non-network interface specific
1499        // path like it is in Redfish. TODO: openbmc/phosphor-time-manager#4
1500        getNTPServers: function() {
1501          return $http({
1502                   method: 'GET',
1503                   url: DataService.getHost() +
1504                       '/xyz/openbmc_project/network/eth0/attr/NTPServers',
1505                   withCredentials: true
1506                 })
1507              .then(function(response) {
1508                return response.data;
1509              });
1510        },
1511        setNTPServers: function(ntpServers) {
1512          return $http({
1513                   method: 'PUT',
1514                   url: DataService.getHost() +
1515                       '/xyz/openbmc_project/network/eth0/attr/NTPServers',
1516                   withCredentials: true,
1517                   data: JSON.stringify({'data': ntpServers})
1518                 })
1519              .then(function(response) {
1520                return response.data;
1521              });
1522        },
1523        setTimeMode: function(timeMode) {
1524          return $http({
1525                   method: 'PUT',
1526                   url: DataService.getHost() +
1527                       '/xyz/openbmc_project/time/sync_method/attr/TimeSyncMethod',
1528                   withCredentials: true,
1529                   data: JSON.stringify({'data': timeMode})
1530                 })
1531              .then(function(response) {
1532                return response.data;
1533              });
1534        },
1535        setTimeOwner: function(timeOwner) {
1536          return $http({
1537                   method: 'PUT',
1538                   url: DataService.getHost() +
1539                       '/xyz/openbmc_project/time/owner/attr/TimeOwner',
1540                   withCredentials: true,
1541                   data: JSON.stringify({'data': timeOwner})
1542                 })
1543              .then(function(response) {
1544                return response.data;
1545              });
1546        },
1547        setBMCTime: function(time) {
1548          return $http({
1549                   method: 'PUT',
1550                   url: DataService.getHost() +
1551                       '/xyz/openbmc_project/time/bmc/attr/Elapsed',
1552                   withCredentials: true,
1553                   data: JSON.stringify({'data': time})
1554                 })
1555              .then(function(response) {
1556                return response.data;
1557              });
1558        },
1559        setHostTime: function(time) {
1560          return $http({
1561                   method: 'PUT',
1562                   url: DataService.getHost() +
1563                       '/xyz/openbmc_project/time/host/attr/Elapsed',
1564                   withCredentials: true,
1565                   data: JSON.stringify({'data': time})
1566                 })
1567              .then(function(response) {
1568                return response.data;
1569              });
1570        },
1571        getHardwares: function(callback) {
1572          $http({
1573            method: 'GET',
1574            url: DataService.getHost() +
1575                '/xyz/openbmc_project/inventory/enumerate',
1576            withCredentials: true
1577          }).then(function(response) {
1578            var json = JSON.stringify(response.data);
1579            var content = JSON.parse(json);
1580            var hardwareData = [];
1581            var keyIndexMap = {};
1582            var title = '';
1583            var depth = '';
1584            var data = [];
1585            var searchText = '';
1586            var componentIndex = -1;
1587            var parent = '';
1588
1589            function isSubComponent(key) {
1590              for (var i = 0; i < Constants.HARDWARE.parent_components.length;
1591                   i++) {
1592                if (key.split(Constants.HARDWARE.parent_components[i]).length ==
1593                    2)
1594                  return true;
1595              }
1596
1597              return false;
1598            }
1599
1600            function titlelize(title) {
1601              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1602              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
1603                   i++) {
1604                if (title.toLowerCase().indexOf(
1605                        (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
1606                  return title.toUpperCase();
1607                }
1608              }
1609
1610              return title;
1611            }
1612
1613            function camelcaseToLabel(obj) {
1614              var transformed = [], label = '', value = '';
1615              for (var key in obj) {
1616                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1617                if (obj[key] !== '') {
1618                  value = obj[key];
1619                  if (value == 1 || value == 0) {
1620                    value = (value == 1) ? 'Yes' : 'No';
1621                  }
1622                  transformed.push({key: label, value: value});
1623                }
1624              }
1625
1626              return transformed;
1627            }
1628
1629            function determineParent(key) {
1630              var levels = key.split('/');
1631              levels.pop();
1632              return levels.join('/');
1633            }
1634
1635            function getSearchText(data) {
1636              var searchText = '';
1637              for (var i = 0; i < data.length; i++) {
1638                searchText += ' ' + data[i].key + ' ' + data[i].value;
1639              }
1640
1641              return searchText;
1642            }
1643
1644            for (var key in content.data) {
1645              if (content.data.hasOwnProperty(key) &&
1646                  key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
1647                data = camelcaseToLabel(content.data[key]);
1648                searchText = getSearchText(data);
1649                title = key.split('/').pop();
1650
1651                title = titlelize(title);
1652                // e.g. /xyz/openbmc_project/inventory/system and
1653                // /xyz/openbmc_project/inventory/system/chassis are depths of 5
1654                // and 6.
1655                depth = key.split('/').length;
1656                parent = determineParent(key);
1657
1658                if (!isSubComponent(key)) {
1659                  hardwareData.push(Object.assign(
1660                      {
1661                        path: key,
1662                        title: title,
1663                        depth: depth,
1664                        parent: parent,
1665                        selected: false,
1666                        expanded: false,
1667                        search_text: title.toLowerCase() + ' ' +
1668                            searchText.toLowerCase(),
1669                        sub_components: [],
1670                        original_data: {key: key, value: content.data[key]}
1671                      },
1672                      {items: data}));
1673
1674                  keyIndexMap[key] = hardwareData.length - 1;
1675                } else {
1676                  parent = determineParent(key)
1677                  componentIndex = keyIndexMap[parent];
1678                  data = content.data[key];
1679                  data.title = title;
1680                  hardwareData[componentIndex].sub_components.push(data);
1681                  hardwareData[componentIndex].search_text +=
1682                      ' ' + title.toLowerCase();
1683
1684                  // Sort the subcomponents alphanumeric so they are displayed
1685                  // on the inventory page in order (e.g. core 0, core 1, core
1686                  // 2, ... core 12, core 13)
1687                  hardwareData[componentIndex].sub_components.sort(function(
1688                      a, b) {
1689                    return a.title.localeCompare(
1690                        b.title, 'en', {numeric: true});
1691                  });
1692                }
1693              }
1694            }
1695            // First, order the components by depth and then place the child
1696            // components beneath their parent component alphanumerically. Can
1697            // be removed with completion of
1698            // https://github.com/openbmc/openbmc/issues/3401
1699            // TODO: Remove this once implemented in back end
1700            hardwareData.sort(function(a, b) {
1701              if (a.depth < b.depth) return -1;
1702              if (a.depth > b.depth) return 1;
1703              return b.title.localeCompare(a.title, 'en', {numeric: true});
1704            });
1705
1706            var orderedComponents = [];
1707
1708            for (var i = 0; i < hardwareData.length; i++) {
1709              if (!keyIndexMap[hardwareData[i].parent]) {
1710                orderedComponents.push(hardwareData[i]);
1711              } else {
1712                for (var j = 0; j < orderedComponents.length; j++) {
1713                  if (orderedComponents[j].path === hardwareData[i].parent) {
1714                    var child = hardwareData[i];
1715                    orderedComponents.splice(j + 1, 0, child);
1716                  }
1717                }
1718              }
1719            }
1720
1721            if (callback) {
1722              callback(orderedComponents, content.data);
1723            } else {
1724              return {data: orderedComponents, original_data: content.data};
1725            }
1726          });
1727        },
1728        deleteLogs: function(logs) {
1729          var defer = $q.defer();
1730          var promises = [];
1731
1732          function finished() {
1733            defer.resolve();
1734          }
1735
1736          logs.forEach(function(item) {
1737            promises.push($http({
1738              method: 'POST',
1739              url: DataService.getHost() +
1740                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1741                  '/action/Delete',
1742              withCredentials: true,
1743              data: JSON.stringify({'data': []})
1744            }));
1745          });
1746
1747          $q.all(promises).then(finished);
1748
1749          return defer.promise;
1750        },
1751        resolveLogs: function(logs) {
1752          var defer = $q.defer();
1753          var promises = [];
1754
1755          function finished() {
1756            defer.resolve();
1757          }
1758
1759          logs.forEach(function(item) {
1760            promises.push($http({
1761              method: 'PUT',
1762              url: DataService.getHost() +
1763                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1764                  '/attr/Resolved',
1765              withCredentials: true,
1766              data: JSON.stringify({'data': '1'})
1767            }));
1768          });
1769
1770          $q.all(promises).then(finished);
1771
1772          return defer.promise;
1773        },
1774        getPowerConsumption: function() {
1775          return $http({
1776                   method: 'GET',
1777                   url: DataService.getHost() +
1778                       '/xyz/openbmc_project/sensors/power/total_power',
1779                   withCredentials: true
1780                 })
1781              .then(
1782                  function(response) {
1783                    var json = JSON.stringify(response.data);
1784                    var content = JSON.parse(json);
1785
1786                    return getScaledValue(
1787                               content.data.Value, content.data.Scale) +
1788                        ' ' +
1789                        Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
1790                  },
1791                  function(error) {
1792                    if ('Not Found' == error.statusText) {
1793                      return Constants.POWER_CONSUMPTION_TEXT.notavailable;
1794                    } else {
1795                      throw error;
1796                    }
1797                  });
1798        },
1799        getPowerCap: function() {
1800          return $http({
1801                   method: 'GET',
1802                   url: DataService.getHost() +
1803                       '/xyz/openbmc_project/control/host0/power_cap',
1804                   withCredentials: true
1805                 })
1806              .then(function(response) {
1807                return response.data;
1808              });
1809        },
1810        setPowerCapEnable: function(powerCapEnable) {
1811          return $http({
1812                   method: 'PUT',
1813                   url: DataService.getHost() +
1814                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCapEnable',
1815                   withCredentials: true,
1816                   data: JSON.stringify({'data': powerCapEnable})
1817                 })
1818              .then(function(response) {
1819                return response.data;
1820              });
1821        },
1822        setPowerCap: function(powerCap) {
1823          return $http({
1824                   method: 'PUT',
1825                   url: DataService.getHost() +
1826                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCap',
1827                   withCredentials: true,
1828                   data: JSON.stringify({'data': powerCap})
1829                 })
1830              .then(function(response) {
1831                return response.data;
1832              });
1833        },
1834        setHostname: function(hostname) {
1835          return $http({
1836                   method: 'PUT',
1837                   url: DataService.getHost() +
1838                       '/xyz/openbmc_project/network/config/attr/HostName',
1839                   withCredentials: true,
1840                   data: JSON.stringify({'data': hostname})
1841                 })
1842              .then(function(response) {
1843                return response.data;
1844              });
1845        },
1846      };
1847      return SERVICE;
1848    }
1849  ]);
1850})(window.angular);
1851