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