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',
13    function($http, Constants, $q, DataService) {
14      var getScaledValue = function(value, scale) {
15        scale = scale + '';
16        scale = parseInt(scale, 10);
17        var power = Math.abs(parseInt(scale, 10));
18
19        if (scale > 0) {
20          value = value * Math.pow(10, power);
21        } else if (scale < 0) {
22          value = value / Math.pow(10, power);
23        }
24        return value;
25      };
26      var SERVICE = {
27        API_CREDENTIALS: Constants.API_CREDENTIALS,
28        API_RESPONSE: Constants.API_RESPONSE,
29        CHASSIS_POWER_STATE: Constants.CHASSIS_POWER_STATE,
30        HOST_STATE_TEXT: Constants.HOST_STATE,
31        HOST_STATE: Constants.HOST_STATE,
32        LED_STATE: Constants.LED_STATE,
33        LED_STATE_TEXT: Constants.LED_STATE_TEXT,
34        HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
35        getChassisState: function() {
36          var deferred = $q.defer();
37          $http({
38            method: 'GET',
39            url: DataService.getHost() +
40                '/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState',
41            headers: {
42              'Accept': 'application/json',
43              'Content-Type': 'application/json'
44            },
45            withCredentials: true
46          })
47              .then(
48                  function(response) {
49                    var json = JSON.stringify(response.data);
50                    var content = JSON.parse(json);
51                    deferred.resolve(content.data);
52                  },
53                  function(error) {
54                    console.log(error);
55                    deferred.reject(error);
56                  });
57          return deferred.promise;
58        },
59        validIPV4IP: function(ip) {
60          // Checks for [0-255].[0-255].[0-255].[0-255]
61          return ip.match(
62              /\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/);
63        },
64        getHostState: function() {
65          var deferred = $q.defer();
66          $http({
67            method: 'GET',
68            url: DataService.getHost() +
69                '/xyz/openbmc_project/state/host0/attr/CurrentHostState',
70            headers: {
71              'Accept': 'application/json',
72              'Content-Type': 'application/json'
73            },
74            withCredentials: true
75          })
76              .then(
77                  function(response) {
78                    var json = JSON.stringify(response.data);
79                    var content = JSON.parse(json);
80                    deferred.resolve(content.data);
81                  },
82                  function(error) {
83                    console.log(error);
84                    deferred.reject(error);
85                  });
86          return deferred.promise;
87        },
88        getNetworkInfo: function() {
89          var deferred = $q.defer();
90          $http({
91            method: 'GET',
92            url: DataService.getHost() +
93                '/xyz/openbmc_project/network/enumerate',
94            headers: {
95              'Accept': 'application/json',
96              'Content-Type': 'application/json'
97            },
98            withCredentials: true
99          })
100              .then(
101                  function(response) {
102                    var json = JSON.stringify(response.data);
103                    var content = JSON.parse(json);
104                    var hostname = '';
105                    var defaultgateway = '';
106                    var macAddress = '';
107
108                    function parseNetworkData(content) {
109                      var data = {
110                        interface_ids: [],
111                        interfaces: {},
112                        ip_addresses: {ipv4: [], ipv6: []},
113                      };
114                      var interfaceId = '', keyParts = [], interfaceHash = '',
115                          interfaceType = '';
116                      for (var key in content.data) {
117                        if (key.match(/network\/eth\d+(_\d+)?$/ig)) {
118                          interfaceId = key.split('/').pop();
119                          if (data.interface_ids.indexOf(interfaceId) == -1) {
120                            data.interface_ids.push(interfaceId);
121                            data.interfaces[interfaceId] = {
122                              interfaceIname: '',
123                              DomainName: '',
124                              MACAddress: '',
125                              Nameservers: [],
126                              DHCPEnabled: 0,
127                              ipv4: {ids: [], values: []},
128                              ipv6: {ids: [], values: []}
129                            };
130                            data.interfaces[interfaceId].MACAddress =
131                                content.data[key].MACAddress;
132                            data.interfaces[interfaceId].DomainName =
133                                content.data[key].DomainName.join(' ');
134                            data.interfaces[interfaceId].Nameservers =
135                                content.data[key].Nameservers;
136                            data.interfaces[interfaceId].DHCPEnabled =
137                                content.data[key].DHCPEnabled;
138                          }
139                        } else if (
140                            key.match(
141                                /network\/eth\d+(_\d+)?\/ipv[4|6]\/[a-z0-9]+$/ig)) {
142                          keyParts = key.split('/');
143                          interfaceHash = keyParts.pop();
144                          interfaceType = keyParts.pop();
145                          interfaceId = keyParts.pop();
146
147                          if (data.interfaces[interfaceId][interfaceType]
148                                  .ids.indexOf(interfaceHash) == -1) {
149                            data.interfaces[interfaceId][interfaceType]
150                                .ids.push(interfaceHash);
151                            data.interfaces[interfaceId][interfaceType]
152                                .values.push(content.data[key]);
153                            data.ip_addresses[interfaceType].push(
154                                content.data[key]['Address']);
155                          }
156                        }
157                      }
158                      return data;
159                    }
160
161                    if (content.data.hasOwnProperty(
162                            '/xyz/openbmc_project/network/config')) {
163                      if (content.data['/xyz/openbmc_project/network/config']
164                              .hasOwnProperty('HostName')) {
165                        hostname =
166                            content.data['/xyz/openbmc_project/network/config']
167                                .HostName;
168                      }
169                      if (content.data['/xyz/openbmc_project/network/config']
170                              .hasOwnProperty('DefaultGateway')) {
171                        defaultgateway =
172                            content.data['/xyz/openbmc_project/network/config']
173                                .DefaultGateway;
174                      }
175                    }
176
177                    if (content.data.hasOwnProperty(
178                            '/xyz/openbmc_project/network/eth0') &&
179                        content.data['/xyz/openbmc_project/network/eth0']
180                            .hasOwnProperty('MACAddress')) {
181                      macAddress =
182                          content.data['/xyz/openbmc_project/network/eth0']
183                              .MACAddress;
184                    }
185
186                    deferred.resolve({
187                      data: content.data,
188                      hostname: hostname,
189                      defaultgateway: defaultgateway,
190                      mac_address: macAddress,
191                      formatted_data: parseNetworkData(content)
192                    });
193                  },
194                  function(error) {
195                    console.log(error);
196                    deferred.reject(error);
197                  });
198          return deferred.promise;
199        },
200        setMACAddress: function(interface_name, mac_address) {
201          return $http({
202                   method: 'PUT',
203                   url: DataService.getHost() +
204                       '/xyz/openbmc_project/network/' + interface_name +
205                       '/attr/MACAddress',
206                   headers: {
207                     'Accept': 'application/json',
208                     'Content-Type': 'application/json'
209                   },
210                   withCredentials: true,
211                   data: JSON.stringify({'data': mac_address})
212                 })
213              .then(function(response) {
214                return response.data;
215              });
216        },
217        setDefaultGateway: function(defaultGateway) {
218          return $http({
219                   method: 'PUT',
220                   url: DataService.getHost() +
221                       '/xyz/openbmc_project/network/config/attr/DefaultGateway',
222                   headers: {
223                     'Accept': 'application/json',
224                     'Content-Type': 'application/json'
225                   },
226                   withCredentials: true,
227                   data: JSON.stringify({'data': defaultGateway})
228                 })
229              .then(function(response) {
230                return response.data;
231              });
232        },
233        setDHCPEnabled: function(interfaceName, dhcpEnabled) {
234          return $http({
235                   method: 'PUT',
236                   url: DataService.getHost() +
237                       '/xyz/openbmc_project/network/' + interfaceName +
238                       '/attr/DHCPEnabled',
239                   headers: {
240                     'Accept': 'application/json',
241                     'Content-Type': 'application/json'
242                   },
243                   withCredentials: true,
244                   data: JSON.stringify({'data': dhcpEnabled})
245                 })
246              .then(function(response) {
247                return response.data;
248              });
249        },
250        setNameservers: function(interfaceName, dnsServers) {
251          return $http({
252                   method: 'PUT',
253                   url: DataService.getHost() +
254                       '/xyz/openbmc_project/network/' + interfaceName +
255                       '/attr/Nameservers',
256                   headers: {
257                     'Accept': 'application/json',
258                     'Content-Type': 'application/json'
259                   },
260                   withCredentials: true,
261                   data: JSON.stringify({'data': dnsServers})
262                 })
263              .then(function(response) {
264                return response.data;
265              });
266        },
267        deleteIPV4: function(interfaceName, networkID) {
268          return $http({
269                   method: 'POST',
270                   url: DataService.getHost() +
271                       '/xyz/openbmc_project/network/' + interfaceName +
272                       '/ipv4/' + networkID + '/action/Delete',
273                   headers: {
274                     'Accept': 'application/json',
275                     'Content-Type': 'application/json'
276                   },
277                   withCredentials: true,
278                   data: JSON.stringify({'data': []})
279                 })
280              .then(function(response) {
281                return response.data;
282              });
283        },
284        addIPV4: function(
285            interfaceName, ipAddress, netmaskPrefixLength, gateway) {
286          return $http({
287                   method: 'POST',
288                   url: DataService.getHost() +
289                       '/xyz/openbmc_project/network/' + interfaceName +
290                       '/action/IP',
291                   headers: {
292                     'Accept': 'application/json',
293                     'Content-Type': 'application/json'
294                   },
295                   withCredentials: true,
296                   data: JSON.stringify({
297                     'data': [
298                       'xyz.openbmc_project.Network.IP.Protocol.IPv4',
299                       ipAddress, +netmaskPrefixLength, gateway
300                     ]
301                   })
302                 })
303              .then(function(response) {
304                return response.data;
305              });
306        },
307        getLEDState: function() {
308          var deferred = $q.defer();
309          $http({
310            method: 'GET',
311            url: DataService.getHost() +
312                '/xyz/openbmc_project/led/groups/enclosure_identify',
313            headers: {
314              'Accept': 'application/json',
315              'Content-Type': 'application/json'
316            },
317            withCredentials: true
318          })
319              .then(
320                  function(response) {
321                    var json = JSON.stringify(response.data);
322                    var content = JSON.parse(json);
323                    deferred.resolve(content.data.Asserted);
324                  },
325                  function(error) {
326                    console.log(error);
327                    deferred.reject(error);
328                  });
329          return deferred.promise;
330        },
331        login: function(username, password, callback) {
332          $http({
333            method: 'POST',
334            url: DataService.getHost() + '/login',
335            headers: {
336              'Accept': 'application/json',
337              'Content-Type': 'application/json'
338            },
339            withCredentials: true,
340            data: JSON.stringify({'data': [username, password]})
341          })
342              .then(
343                  function(response) {
344                    if (callback) {
345                      callback(response.data);
346                    }
347                  },
348                  function(error) {
349                    if (callback) {
350                      if (error && error.status && error.status == 'error') {
351                        callback(error);
352                      } else {
353                        callback(error, true);
354                      }
355                    }
356                    console.log(error);
357                  });
358        },
359        testPassword: function(username, password) {
360          // Calls /login without the current session to verify the given
361          // password is correct ignore the interceptor logout on a bad password
362          return $http({
363                   method: 'POST',
364                   url: DataService.getHost() + '/login',
365                   headers: {
366                     'Accept': 'application/json',
367                     'Content-Type': 'application/json'
368                   },
369                   withCredentials: false,
370                   data: JSON.stringify({'data': [username, password]})
371                 })
372              .then(function(response) {
373                return response.data;
374              });
375        },
376        logout: function(callback) {
377          $http({
378            method: 'POST',
379            url: DataService.getHost() + '/logout',
380            headers: {
381              'Accept': 'application/json',
382              'Content-Type': 'application/json'
383            },
384            withCredentials: true,
385            data: JSON.stringify({'data': []})
386          })
387              .then(
388                  function(response) {
389                    if (callback) {
390                      callback(response.data);
391                    }
392                  },
393                  function(error) {
394                    if (callback) {
395                      callback(null, error);
396                    }
397                    console.log(error);
398                  });
399        },
400        changePassword: function(user, newPassword) {
401          var deferred = $q.defer();
402          $http({
403            method: 'POST',
404            url: DataService.getHost() + '/xyz/openbmc_project/user/' + user +
405                '/action/SetPassword',
406            headers: {
407              'Accept': 'application/json',
408              'Content-Type': 'application/json'
409            },
410            withCredentials: true,
411            data: JSON.stringify({'data': [newPassword]}),
412            responseType: 'arraybuffer'
413          })
414              .then(
415                  function(response, status, headers) {
416                    deferred.resolve(
417                        {data: response, status: status, headers: headers});
418                  },
419                  function(error) {
420                    console.log(error);
421                    deferred.reject(error);
422                  });
423          return deferred.promise;
424        },
425        chassisPowerOn: function(callback) {
426          $http({
427            method: 'POST',
428            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
429            headers: {
430              'Accept': 'application/json',
431              'Content-Type': 'application/json'
432            },
433            withCredentials: true,
434            data: JSON.stringify({'data': []})
435          })
436              .then(
437                  function(response) {
438                    var json = JSON.stringify(response.data);
439                    var content = JSON.parse(json);
440                    if (callback) {
441                      return callback(content.data.CurrentPowerState);
442                    }
443                  },
444                  function(error) {
445                    if (callback) {
446                      callback(error);
447                    } else {
448                      console.log(error);
449                    }
450                  });
451        },
452        chassisPowerOff: function() {
453          var deferred = $q.defer();
454          $http({
455            method: 'PUT',
456            url: DataService.getHost() +
457                '/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition',
458            headers: {
459              'Accept': 'application/json',
460              'Content-Type': 'application/json'
461            },
462            withCredentials: true,
463            data: JSON.stringify(
464                {'data': 'xyz.openbmc_project.State.Chassis.Transition.Off'})
465          })
466              .then(
467                  function(response) {
468                    var json = JSON.stringify(response.data);
469                    var content = JSON.parse(json);
470                    deferred.resolve(content.status);
471                  },
472                  function(error) {
473                    console.log(error);
474                    deferred.reject(error);
475                  });
476          return deferred.promise;
477        },
478        setLEDState: function(state, callback) {
479          $http({
480            method: 'PUT',
481            url: DataService.getHost() +
482                '/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted',
483            headers: {
484              'Accept': 'application/json',
485              'Content-Type': 'application/json'
486            },
487            withCredentials: true,
488            data: JSON.stringify({'data': state})
489          })
490              .then(
491                  function(response) {
492                    var json = JSON.stringify(response.data);
493                    var content = JSON.parse(json);
494                    if (callback) {
495                      return callback(content.status);
496                    }
497                  },
498                  function(error) {
499                    if (callback) {
500                      callback(error);
501                    } else {
502                      console.log(error);
503                    }
504                  });
505        },
506        bmcReboot: function(callback) {
507          $http({
508            method: 'PUT',
509            url: DataService.getHost() +
510                '/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition',
511            headers: {
512              'Accept': 'application/json',
513              'Content-Type': 'application/json'
514            },
515            withCredentials: true,
516            data: JSON.stringify(
517                {'data': 'xyz.openbmc_project.State.BMC.Transition.Reboot'})
518          })
519              .then(
520                  function(response) {
521                    var json = JSON.stringify(response.data);
522                    var content = JSON.parse(json);
523                    if (callback) {
524                      return callback(content.status);
525                    }
526                  },
527                  function(error) {
528                    if (callback) {
529                      callback(error);
530                    } else {
531                      console.log(error);
532                    }
533                  });
534        },
535        getLastRebootTime: function() {
536          return $http({
537                   method: 'GET',
538                   url: DataService.getHost() +
539                       '/xyz/openbmc_project/state/bmc0/attr/LastRebootTime',
540                   headers: {
541                     'Accept': 'application/json',
542                     'Content-Type': 'application/json'
543                   },
544                   withCredentials: true
545                 })
546              .then(function(response) {
547                return response.data;
548              });
549        },
550        hostPowerOn: function() {
551          var deferred = $q.defer();
552          $http({
553            method: 'PUT',
554            url: DataService.getHost() +
555                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
556            headers: {
557              'Accept': 'application/json',
558              'Content-Type': 'application/json'
559            },
560            withCredentials: true,
561            data: JSON.stringify(
562                {'data': 'xyz.openbmc_project.State.Host.Transition.On'})
563          })
564              .then(
565                  function(response) {
566                    var json = JSON.stringify(response.data);
567                    var content = JSON.parse(json);
568                    deferred.resolve(content.status);
569                  },
570                  function(error) {
571                    console.log(error);
572                    deferred.reject(error);
573                  });
574          return deferred.promise;
575        },
576        hostPowerOff: function() {
577          var deferred = $q.defer();
578          $http({
579            method: 'PUT',
580            url: DataService.getHost() +
581                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
582            headers: {
583              'Accept': 'application/json',
584              'Content-Type': 'application/json'
585            },
586            withCredentials: true,
587            data: JSON.stringify(
588                {'data': 'xyz.openbmc_project.State.Host.Transition.Off'})
589          })
590              .then(
591                  function(response) {
592                    var json = JSON.stringify(response.data);
593                    var content = JSON.parse(json);
594                    deferred.resolve(content.status);
595                  },
596                  function(error) {
597                    console.log(error);
598                    deferred.reject(error);
599                  });
600          return deferred.promise;
601        },
602        hostReboot: function() {
603          var deferred = $q.defer();
604          $http({
605            method: 'PUT',
606            url: DataService.getHost() +
607                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
608            headers: {
609              'Accept': 'application/json',
610              'Content-Type': 'application/json'
611            },
612            withCredentials: true,
613            data: JSON.stringify(
614                {'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'})
615          })
616              .then(
617                  function(response) {
618                    var json = JSON.stringify(response.data);
619                    var content = JSON.parse(json);
620                    deferred.resolve(content.status);
621                  },
622                  function(error) {
623                    console.log(error);
624                    deferred.reject(error);
625                  });
626
627          return deferred.promise;
628        },
629        hostShutdown: function(callback) {
630          $http({
631            method: 'POST',
632            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
633            headers: {
634              'Accept': 'application/json',
635              'Content-Type': 'application/json'
636            },
637            withCredentials: true,
638            data: JSON.stringify({'data': []})
639          })
640              .then(
641                  function(response) {
642                    var json = JSON.stringify(response.data);
643                    var content = JSON.parse(json);
644                    if (callback) {
645                      return callback(content);
646                    }
647                  },
648                  function(error) {
649                    if (callback) {
650                      callback(error);
651                    } else {
652                      console.log(error);
653                    }
654                  });
655        },
656        getLogs: function() {
657          var deferred = $q.defer();
658          $http({
659            method: 'GET',
660            url: DataService.getHost() +
661                '/xyz/openbmc_project/logging/enumerate',
662            headers: {
663              'Accept': 'application/json',
664              'Content-Type': 'application/json'
665            },
666            withCredentials: true
667          })
668              .then(
669                  function(response) {
670                    var json = JSON.stringify(response.data);
671                    var content = JSON.parse(json);
672                    var dataClone = JSON.parse(JSON.stringify(content.data));
673                    var data = [];
674                    var severityCode = '';
675                    var priority = '';
676                    var health = '';
677                    var relatedItems = [];
678                    var eventID = 'None';
679                    var description = 'None';
680
681                    for (var key in content.data) {
682                      if (content.data.hasOwnProperty(key) &&
683                          content.data[key].hasOwnProperty('Id')) {
684                        var severityFlags = {
685                          low: false,
686                          medium: false,
687                          high: false
688                        };
689                        var healthFlags = {
690                          critical: false,
691                          warning: false,
692                          good: false
693                        };
694                        severityCode =
695                            content.data[key].Severity.split('.').pop();
696                        priority =
697                            Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
698                        severityFlags[priority.toLowerCase()] = true;
699                        health = Constants.SEVERITY_TO_HEALTH_MAP[severityCode];
700                        healthFlags[health.toLowerCase()] = true;
701                        relatedItems = [];
702                        content.data[key].associations.forEach(function(item) {
703                          relatedItems.push(item[2]);
704                        });
705
706                        if (content.data[key].hasOwnProperty(['EventID'])) {
707                          eventID = content.data[key].EventID;
708                        }
709
710                        if (content.data[key].hasOwnProperty(['Description'])) {
711                          description = content.data[key].Description;
712                        }
713
714                        data.push(Object.assign(
715                            {
716                              path: key,
717                              copied: false,
718                              priority: priority,
719                              severity_code: severityCode,
720                              severity_flags: severityFlags,
721                              health_flags: healthFlags,
722                              additional_data:
723                                  content.data[key].AdditionalData.join('\n'),
724                              type: content.data[key].Message,
725                              selected: false,
726                              search_text:
727                                  ('#' + content.data[key].Id + ' ' +
728                                   severityCode + ' ' +
729                                   content.data[key].Message + ' ' +
730                                   content.data[key].Severity + ' ' +
731                                   content.data[key].AdditionalData.join(' '))
732                                      .toLowerCase(),
733                              meta: false,
734                              confirm: false,
735                              related_items: relatedItems,
736                              eventID: eventID,
737                              description: description,
738                              data: {key: key, value: content.data[key]}
739                            },
740                            content.data[key]));
741                      }
742                    }
743                    deferred.resolve({data: data, original: dataClone});
744                  },
745                  function(error) {
746                    console.log(error);
747                    deferred.reject(error);
748                  });
749
750          return deferred.promise;
751        },
752        getAllSensorStatus: function(callback) {
753          $http({
754            method: 'GET',
755            url: DataService.getHost() +
756                '/xyz/openbmc_project/sensors/enumerate',
757            headers: {
758              'Accept': 'application/json',
759              'Content-Type': 'application/json'
760            },
761            withCredentials: true
762          })
763              .then(
764                  function(response) {
765                    var json = JSON.stringify(response.data);
766                    var content = JSON.parse(json);
767                    var dataClone = JSON.parse(JSON.stringify(content.data));
768                    var sensorData = [];
769                    var severity = {};
770                    var title = '';
771                    var tempKeyParts = [];
772                    var order = 0;
773                    var customOrder = 0;
774
775                    function getSensorStatus(reading) {
776                      var severityFlags = {
777                        critical: false,
778                        warning: false,
779                        normal: false
780                      },
781                          severityText = '', order = 0;
782
783                      if (reading.hasOwnProperty('CriticalLow') &&
784                          reading.Value < reading.CriticalLow) {
785                        severityFlags.critical = true;
786                        severityText = 'critical';
787                        order = 2;
788                      } else if (
789                          reading.hasOwnProperty('CriticalHigh') &&
790                          reading.Value > reading.CriticalHigh) {
791                        severityFlags.critical = true;
792                        severityText = 'critical';
793                        order = 2;
794                      } else if (
795                          reading.hasOwnProperty('CriticalLow') &&
796                          reading.hasOwnProperty('WarningLow') &&
797                          reading.Value >= reading.CriticalLow &&
798                          reading.Value <= reading.WarningLow) {
799                        severityFlags.warning = true;
800                        severityText = 'warning';
801                        order = 1;
802                      } else if (
803                          reading.hasOwnProperty('WarningHigh') &&
804                          reading.hasOwnProperty('CriticalHigh') &&
805                          reading.Value >= reading.WarningHigh &&
806                          reading.Value <= reading.CriticalHigh) {
807                        severityFlags.warning = true;
808                        severityText = 'warning';
809                        order = 1;
810                      } else {
811                        severityFlags.normal = true;
812                        severityText = 'normal';
813                      }
814                      return {
815                        flags: severityFlags,
816                        severityText: severityText,
817                        order: order
818                      };
819                    }
820
821                    for (var key in content.data) {
822                      if (content.data.hasOwnProperty(key) &&
823                          content.data[key].hasOwnProperty('Unit')) {
824                        severity = getSensorStatus(content.data[key]);
825
826                        if (!content.data[key].hasOwnProperty('CriticalLow')) {
827                          content.data[key].CriticalLow = '--';
828                          content.data[key].CriticalHigh = '--';
829                        }
830
831                        if (!content.data[key].hasOwnProperty('WarningLow')) {
832                          content.data[key].WarningLow = '--';
833                          content.data[key].WarningHigh = '--';
834                        }
835
836                        tempKeyParts = key.split('/');
837                        title = tempKeyParts.pop();
838                        title = tempKeyParts.pop() + '_' + title;
839                        title = title.split('_')
840                                    .map(function(item) {
841                                      return item.toLowerCase()
842                                                 .charAt(0)
843                                                 .toUpperCase() +
844                                          item.slice(1);
845                                    })
846                                    .reduce(function(prev, el) {
847                                      return prev + ' ' + el;
848                                    });
849
850                        content.data[key].Value = getScaledValue(
851                            content.data[key].Value, content.data[key].Scale);
852                        content.data[key].CriticalLow = getScaledValue(
853                            content.data[key].CriticalLow,
854                            content.data[key].Scale);
855                        content.data[key].CriticalHigh = getScaledValue(
856                            content.data[key].CriticalHigh,
857                            content.data[key].Scale);
858                        content.data[key].WarningLow = getScaledValue(
859                            content.data[key].WarningLow,
860                            content.data[key].Scale);
861                        content.data[key].WarningHigh = getScaledValue(
862                            content.data[key].WarningHigh,
863                            content.data[key].Scale);
864                        if (Constants.SENSOR_SORT_ORDER.indexOf(
865                                content.data[key].Unit) > -1) {
866                          customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
867                              content.data[key].Unit);
868                        } else {
869                          customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
870                        }
871
872                        sensorData.push(Object.assign(
873                            {
874                              path: key,
875                              selected: false,
876                              confirm: false,
877                              copied: false,
878                              title: title,
879                              unit:
880                                  Constants
881                                      .SENSOR_UNIT_MAP[content.data[key].Unit],
882                              severity_flags: severity.flags,
883                              status: severity.severityText,
884                              order: severity.order,
885                              custom_order: customOrder,
886                              search_text:
887                                  (title + ' ' + content.data[key].Value + ' ' +
888                                   Constants.SENSOR_UNIT_MAP[content.data[key]
889                                                                 .Unit] +
890                                   ' ' + severity.severityText + ' ' +
891                                   content.data[key].CriticalLow + ' ' +
892                                   content.data[key].CriticalHigh + ' ' +
893                                   content.data[key].WarningLow + ' ' +
894                                   content.data[key].WarningHigh + ' ')
895                                      .toLowerCase(),
896                              original_data:
897                                  {key: key, value: content.data[key]}
898                            },
899                            content.data[key]));
900                      }
901                    }
902
903                    callback(sensorData, dataClone);
904                  },
905                  function(error) {
906                    console.log(error);
907                  });
908        },
909        getActivation: function(imageId) {
910          return $http({
911                   method: 'GET',
912                   url: DataService.getHost() +
913                       '/xyz/openbmc_project/software/' + imageId +
914                       '/attr/Activation',
915                   headers: {
916                     'Accept': 'application/json',
917                     'Content-Type': 'application/json'
918                   },
919                   withCredentials: true
920                 })
921              .then(function(response) {
922                return response.data;
923              });
924        },
925        getFirmwares: function() {
926          var deferred = $q.defer();
927          $http({
928            method: 'GET',
929            url: DataService.getHost() +
930                '/xyz/openbmc_project/software/enumerate',
931            headers: {
932              'Accept': 'application/json',
933              'Content-Type': 'application/json'
934            },
935            withCredentials: true
936          })
937              .then(
938                  function(response) {
939                    var json = JSON.stringify(response.data);
940                    var content = JSON.parse(json);
941                    var data = [];
942                    var isExtended = false;
943                    var bmcActiveVersion = '';
944                    var hostActiveVersion = '';
945                    var imageType = '';
946                    var extendedVersions = [];
947                    var functionalImages = [];
948
949                    function getFormatedExtendedVersions(extendedVersion) {
950                      var versions = [];
951                      extendedVersion = extendedVersion.split(',');
952
953                      extendedVersion.forEach(function(item) {
954                        var parts = item.split('-');
955                        var numberIndex = 0;
956                        for (var i = 0; i < parts.length; i++) {
957                          if (/[0-9]/.test(parts[i])) {
958                            numberIndex = i;
959                            break;
960                          }
961                        }
962                        var titlePart = parts.splice(0, numberIndex);
963                        titlePart = titlePart.join('');
964                        titlePart = titlePart[0].toUpperCase() +
965                            titlePart.substr(1, titlePart.length);
966                        var versionPart = parts.join('-');
967                        versions.push({title: titlePart, version: versionPart});
968                      });
969
970                      return versions;
971                    }
972
973                    // Get the list of functional images so we can compare
974                    // later if an image is functional
975                    if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
976                      functionalImages =
977                          content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
978                              .endpoints;
979                    }
980                    for (var key in content.data) {
981                      if (content.data.hasOwnProperty(key) &&
982                          content.data[key].hasOwnProperty('Version')) {
983                        var activationStatus = '';
984
985                        // If the image is "Functional" use that for the
986                        // activation status, else use the value of "Activation"
987                        // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
988                        if (content.data[key].Activation) {
989                          activationStatus =
990                              content.data[key].Activation.split('.').pop();
991                        }
992
993                        if (functionalImages.includes(key)) {
994                          activationStatus = 'Functional';
995                        }
996
997                        imageType = content.data[key].Purpose.split('.').pop();
998                        isExtended = content.data[key].hasOwnProperty(
999                                         'ExtendedVersion') &&
1000                            content.data[key].ExtendedVersion != '';
1001                        if (isExtended) {
1002                          extendedVersions = getFormatedExtendedVersions(
1003                              content.data[key].ExtendedVersion);
1004                        }
1005                        data.push(Object.assign(
1006                            {
1007                              path: key,
1008                              activationStatus: activationStatus,
1009                              imageId: key.split('/').pop(),
1010                              imageType: imageType,
1011                              isExtended: isExtended,
1012                              extended:
1013                                  {show: false, versions: extendedVersions},
1014                              data: {key: key, value: content.data[key]}
1015                            },
1016                            content.data[key]));
1017
1018                        if (activationStatus == 'Functional' &&
1019                            imageType == 'BMC') {
1020                          bmcActiveVersion = content.data[key].Version;
1021                        }
1022
1023                        if (activationStatus == 'Functional' &&
1024                            imageType == 'Host') {
1025                          hostActiveVersion = content.data[key].Version;
1026                        }
1027                      }
1028                    }
1029
1030                    deferred.resolve({
1031                      data: data,
1032                      bmcActiveVersion: bmcActiveVersion,
1033                      hostActiveVersion: hostActiveVersion
1034                    });
1035                  },
1036                  function(error) {
1037                    console.log(error);
1038                    deferred.reject(error);
1039                  });
1040
1041          return deferred.promise;
1042        },
1043        changePriority: function(imageId, priority) {
1044          var deferred = $q.defer();
1045          $http({
1046            method: 'PUT',
1047            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1048                imageId + '/attr/Priority',
1049            headers: {
1050              'Accept': 'application/json',
1051              'Content-Type': 'application/json'
1052            },
1053            withCredentials: true,
1054            data: JSON.stringify({'data': priority})
1055          })
1056              .then(
1057                  function(response) {
1058                    var json = JSON.stringify(response.data);
1059                    var content = JSON.parse(json);
1060                    deferred.resolve(content);
1061                  },
1062                  function(error) {
1063                    console.log(error);
1064                    deferred.reject(error);
1065                  });
1066
1067          return deferred.promise;
1068        },
1069        deleteImage: function(imageId) {
1070          var deferred = $q.defer();
1071          $http({
1072            method: 'POST',
1073            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1074                imageId + '/action/Delete',
1075            headers: {
1076              'Accept': 'application/json',
1077              'Content-Type': 'application/json'
1078            },
1079            withCredentials: true,
1080            data: JSON.stringify({'data': []})
1081          })
1082              .then(
1083                  function(response) {
1084                    var json = JSON.stringify(response.data);
1085                    var content = JSON.parse(json);
1086                    deferred.resolve(content);
1087                  },
1088                  function(error) {
1089                    console.log(error);
1090                    deferred.reject(error);
1091                  });
1092
1093          return deferred.promise;
1094        },
1095        activateImage: function(imageId) {
1096          var deferred = $q.defer();
1097          $http({
1098            method: 'PUT',
1099            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1100                imageId + '/attr/RequestedActivation',
1101            headers: {
1102              'Accept': 'application/json',
1103              'Content-Type': 'application/json'
1104            },
1105            withCredentials: true,
1106            data:
1107                JSON.stringify({'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
1108          })
1109              .then(
1110                  function(response) {
1111                    var json = JSON.stringify(response.data);
1112                    var content = JSON.parse(json);
1113                    deferred.resolve(content);
1114                  },
1115                  function(error) {
1116                    console.log(error);
1117                    deferred.reject(error);
1118                  });
1119
1120          return deferred.promise;
1121        },
1122        uploadImage: function(file) {
1123          return $http({
1124                   method: 'POST',
1125                   timeout: 5 * 60 * 1000,
1126                   url: DataService.getHost() + '/upload/image',
1127                   headers: {'Content-Type': 'application/octet-stream'},
1128                   withCredentials: true,
1129                   data: file
1130                 })
1131              .then(function(response) {
1132                return response.data;
1133              });
1134        },
1135        downloadImage: function(host, filename) {
1136          return $http({
1137                   method: 'POST',
1138                   url: DataService.getHost() +
1139                       '/xyz/openbmc_project/software/action/DownloadViaTFTP',
1140                   headers: {
1141                     'Accept': 'application/json',
1142                     'Content-Type': 'application/json'
1143                   },
1144                   withCredentials: true,
1145                   data: JSON.stringify({'data': [filename, host]}),
1146                   responseType: 'arraybuffer'
1147                 })
1148              .then(function(response) {
1149                return response.data;
1150              });
1151        },
1152        getBMCEthernetInfo: function() {
1153          var deferred = $q.defer();
1154          $http({
1155            method: 'GET',
1156            url: DataService.getHost() +
1157                '/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet',
1158            headers: {
1159              'Accept': 'application/json',
1160              'Content-Type': 'application/json'
1161            },
1162            withCredentials: true
1163          })
1164              .then(
1165                  function(response) {
1166                    var json = JSON.stringify(response.data);
1167                    var content = JSON.parse(json);
1168                    deferred.resolve(content.data);
1169                  },
1170                  function(error) {
1171                    console.log(error);
1172                    deferred.reject(error);
1173                  });
1174
1175          return deferred.promise;
1176        },
1177        getBMCInfo: function(callback) {
1178          var deferred = $q.defer();
1179          $http({
1180            method: 'GET',
1181            url: DataService.getHost() +
1182                '/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc',
1183            headers: {
1184              'Accept': 'application/json',
1185              'Content-Type': 'application/json'
1186            },
1187            withCredentials: true
1188          })
1189              .then(
1190                  function(response) {
1191                    var json = JSON.stringify(response.data);
1192                    var content = JSON.parse(json);
1193                    deferred.resolve(content.data);
1194                  },
1195                  function(error) {
1196                    console.log(error);
1197                    deferred.reject(error);
1198                  });
1199          return deferred.promise;
1200        },
1201        getServerInfo: function() {
1202          // TODO: openbmc/openbmc#3117 Need a way via REST to get
1203          // interfaces so we can get the system object(s) by the looking
1204          // for the system interface.
1205          return $http({
1206                   method: 'GET',
1207                   url: DataService.getHost() +
1208                       '/xyz/openbmc_project/inventory/system',
1209                   headers: {
1210                     'Accept': 'application/json',
1211                     'Content-Type': 'application/json'
1212                   },
1213                   withCredentials: true
1214                 })
1215              .then(function(response) {
1216                return response.data;
1217              });
1218        },
1219        getBMCTime: function() {
1220          return $http({
1221                   method: 'GET',
1222                   url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
1223                   headers: {
1224                     'Accept': 'application/json',
1225                     'Content-Type': 'application/json'
1226                   },
1227                   withCredentials: true
1228                 })
1229              .then(function(response) {
1230                return response.data;
1231              });
1232        },
1233        getHardwares: function(callback) {
1234          $http({
1235            method: 'GET',
1236            url: DataService.getHost() +
1237                '/xyz/openbmc_project/inventory/enumerate',
1238            headers: {
1239              'Accept': 'application/json',
1240              'Content-Type': 'application/json'
1241            },
1242            withCredentials: true
1243          }).then(function(response) {
1244            var json = JSON.stringify(response.data);
1245            var content = JSON.parse(json);
1246            var hardwareData = [];
1247            var keyIndexMap = {};
1248            var title = '';
1249            var data = [];
1250            var searchText = '';
1251            var componentIndex = -1;
1252            var tempParts = [];
1253
1254            function isSubComponent(key) {
1255              for (var i = 0; i < Constants.HARDWARE.parent_components.length;
1256                   i++) {
1257                if (key.split(Constants.HARDWARE.parent_components[i]).length ==
1258                    2)
1259                  return true;
1260              }
1261
1262              return false;
1263            }
1264
1265            function titlelize(title) {
1266              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1267              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
1268                   i++) {
1269                if (title.toLowerCase().indexOf(
1270                        (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
1271                  return title.toUpperCase();
1272                }
1273              }
1274
1275              return title;
1276            }
1277
1278            function camelcaseToLabel(obj) {
1279              var transformed = [], label = '', value = '';
1280              for (var key in obj) {
1281                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1282                if (obj[key] !== '') {
1283                  value = obj[key];
1284                  if (value == 1 || value == 0) {
1285                    value = (value == 1) ? 'Yes' : 'No';
1286                  }
1287                  transformed.push({key: label, value: value});
1288                }
1289              }
1290
1291              return transformed;
1292            }
1293
1294            function getSearchText(data) {
1295              var searchText = '';
1296              for (var i = 0; i < data.length; i++) {
1297                searchText += ' ' + data[i].key + ' ' + data[i].value;
1298              }
1299
1300              return searchText;
1301            }
1302
1303            for (var key in content.data) {
1304              if (content.data.hasOwnProperty(key) &&
1305                  key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
1306                data = camelcaseToLabel(content.data[key]);
1307                searchText = getSearchText(data);
1308                title = key.split('/').pop();
1309
1310                title = titlelize(title);
1311
1312                if (!isSubComponent(key)) {
1313                  hardwareData.push(Object.assign(
1314                      {
1315                        path: key,
1316                        title: title,
1317                        selected: false,
1318                        expanded: false,
1319                        search_text: title.toLowerCase() + ' ' +
1320                            searchText.toLowerCase(),
1321                        sub_components: [],
1322                        original_data: {key: key, value: content.data[key]}
1323                      },
1324                      {items: data}));
1325
1326                  keyIndexMap[key] = hardwareData.length - 1;
1327                } else {
1328                  var tempParts = key.split('/');
1329                  tempParts.pop();
1330                  tempParts = tempParts.join('/');
1331                  componentIndex = keyIndexMap[tempParts];
1332                  data = content.data[key];
1333                  data.title = title;
1334                  hardwareData[componentIndex].sub_components.push(data);
1335                  hardwareData[componentIndex].search_text +=
1336                      ' ' + title.toLowerCase();
1337
1338                  // Sort the subcomponents alphanumeric so they are displayed
1339                  // on the inventory page in order (e.g. core 0, core 1, core
1340                  // 2, ... core 12, core 13)
1341                  hardwareData[componentIndex].sub_components.sort(function(
1342                      a, b) {
1343                    return a.title.localeCompare(
1344                        b.title, 'en', {numeric: true});
1345                  });
1346                }
1347              }
1348            }
1349
1350            if (callback) {
1351              callback(hardwareData, content.data);
1352            } else {
1353              return {data: hardwareData, original_data: content.data};
1354            }
1355          });
1356        },
1357        deleteLogs: function(logs) {
1358          var defer = $q.defer();
1359          var promises = [];
1360
1361          function finished() {
1362            defer.resolve();
1363          }
1364
1365          logs.forEach(function(item) {
1366            promises.push($http({
1367              method: 'POST',
1368              url: DataService.getHost() +
1369                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1370                  '/action/Delete',
1371              headers: {
1372                'Accept': 'application/json',
1373                'Content-Type': 'application/json'
1374              },
1375              withCredentials: true,
1376              data: JSON.stringify({'data': []})
1377            }));
1378          });
1379
1380          $q.all(promises).then(finished);
1381
1382          return defer.promise;
1383        },
1384        resolveLogs: function(logs) {
1385          var defer = $q.defer();
1386          var promises = [];
1387
1388          function finished() {
1389            defer.resolve();
1390          }
1391
1392          logs.forEach(function(item) {
1393            promises.push($http({
1394              method: 'PUT',
1395              url: DataService.getHost() +
1396                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1397                  '/attr/Resolved',
1398              headers: {
1399                'Accept': 'application/json',
1400                'Content-Type': 'application/json'
1401              },
1402              withCredentials: true,
1403              data: JSON.stringify({'data': '1'})
1404            }));
1405          });
1406
1407          $q.all(promises).then(finished);
1408
1409          return defer.promise;
1410        },
1411        getPowerConsumption: function() {
1412          return $http({
1413                   method: 'GET',
1414                   url: DataService.getHost() +
1415                       '/xyz/openbmc_project/sensors/power/total_power',
1416                   headers: {
1417                     'Accept': 'application/json',
1418                     'Content-Type': 'application/json'
1419                   },
1420                   withCredentials: true
1421                 })
1422              .then(
1423                  function(response) {
1424                    var json = JSON.stringify(response.data);
1425                    var content = JSON.parse(json);
1426
1427                    return getScaledValue(
1428                               content.data.Value, content.data.Scale) +
1429                        ' ' +
1430                        Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
1431                  },
1432                  function(error) {
1433                    if ('Not Found' == error.statusText) {
1434                      return Constants.POWER_CONSUMPTION_TEXT.notavailable;
1435                    } else {
1436                      throw error;
1437                    }
1438                  });
1439        },
1440        getPowerCap: function() {
1441          return $http({
1442                   method: 'GET',
1443                   url: DataService.getHost() +
1444                       '/xyz/openbmc_project/control/host0/power_cap',
1445                   headers: {
1446                     'Accept': 'application/json',
1447                     'Content-Type': 'application/json'
1448                   },
1449                   withCredentials: true
1450                 })
1451              .then(function(response) {
1452                var json = JSON.stringify(response.data);
1453                var content = JSON.parse(json);
1454
1455                return (false == content.data.PowerCapEnable) ?
1456                    Constants.POWER_CAP_TEXT.disabled :
1457                    content.data.PowerCap + ' ' + Constants.POWER_CAP_TEXT.unit;
1458              });
1459        },
1460        setHostname: function(hostname) {
1461          return $http({
1462                   method: 'PUT',
1463                   url: DataService.getHost() +
1464                       '/xyz/openbmc_project/network/config/attr/HostName',
1465                   headers: {
1466                     'Accept': 'application/json',
1467                     'Content-Type': 'application/json'
1468                   },
1469                   withCredentials: true,
1470                   data: JSON.stringify({'data': hostname})
1471                 })
1472              .then(function(response) {
1473                return response.data;
1474              });
1475        },
1476      };
1477      return SERVICE;
1478    }
1479  ]);
1480})(window.angular);
1481