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