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