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