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        hostPowerOn: function() {
536          var deferred = $q.defer();
537          $http({
538            method: 'PUT',
539            url: DataService.getHost() +
540                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
541            headers: {
542              'Accept': 'application/json',
543              'Content-Type': 'application/json'
544            },
545            withCredentials: true,
546            data: JSON.stringify(
547                {'data': 'xyz.openbmc_project.State.Host.Transition.On'})
548          })
549              .then(
550                  function(response) {
551                    var json = JSON.stringify(response.data);
552                    var content = JSON.parse(json);
553                    deferred.resolve(content.status);
554                  },
555                  function(error) {
556                    console.log(error);
557                    deferred.reject(error);
558                  });
559          return deferred.promise;
560        },
561        hostPowerOff: function() {
562          var deferred = $q.defer();
563          $http({
564            method: 'PUT',
565            url: DataService.getHost() +
566                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
567            headers: {
568              'Accept': 'application/json',
569              'Content-Type': 'application/json'
570            },
571            withCredentials: true,
572            data: JSON.stringify(
573                {'data': 'xyz.openbmc_project.State.Host.Transition.Off'})
574          })
575              .then(
576                  function(response) {
577                    var json = JSON.stringify(response.data);
578                    var content = JSON.parse(json);
579                    deferred.resolve(content.status);
580                  },
581                  function(error) {
582                    console.log(error);
583                    deferred.reject(error);
584                  });
585          return deferred.promise;
586        },
587        hostReboot: function() {
588          var deferred = $q.defer();
589          $http({
590            method: 'PUT',
591            url: DataService.getHost() +
592                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
593            headers: {
594              'Accept': 'application/json',
595              'Content-Type': 'application/json'
596            },
597            withCredentials: true,
598            data: JSON.stringify(
599                {'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'})
600          })
601              .then(
602                  function(response) {
603                    var json = JSON.stringify(response.data);
604                    var content = JSON.parse(json);
605                    deferred.resolve(content.status);
606                  },
607                  function(error) {
608                    console.log(error);
609                    deferred.reject(error);
610                  });
611
612          return deferred.promise;
613        },
614        hostShutdown: function(callback) {
615          $http({
616            method: 'POST',
617            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
618            headers: {
619              'Accept': 'application/json',
620              'Content-Type': 'application/json'
621            },
622            withCredentials: true,
623            data: JSON.stringify({'data': []})
624          })
625              .then(
626                  function(response) {
627                    var json = JSON.stringify(response.data);
628                    var content = JSON.parse(json);
629                    if (callback) {
630                      return callback(content);
631                    }
632                  },
633                  function(error) {
634                    if (callback) {
635                      callback(error);
636                    } else {
637                      console.log(error);
638                    }
639                  });
640        },
641        getLogs: function() {
642          var deferred = $q.defer();
643          $http({
644            method: 'GET',
645            url: DataService.getHost() +
646                '/xyz/openbmc_project/logging/enumerate',
647            headers: {
648              'Accept': 'application/json',
649              'Content-Type': 'application/json'
650            },
651            withCredentials: true
652          })
653              .then(
654                  function(response) {
655                    var json = JSON.stringify(response.data);
656                    var content = JSON.parse(json);
657                    var dataClone = JSON.parse(JSON.stringify(content.data));
658                    var data = [];
659                    var severityCode = '';
660                    var priority = '';
661                    var health = '';
662                    var relatedItems = [];
663                    var eventID = 'None';
664                    var description = 'None';
665
666                    for (var key in content.data) {
667                      if (content.data.hasOwnProperty(key) &&
668                          content.data[key].hasOwnProperty('Id')) {
669                        var severityFlags = {
670                          low: false,
671                          medium: false,
672                          high: false
673                        };
674                        var healthFlags = {
675                          critical: false,
676                          warning: false,
677                          good: false
678                        };
679                        severityCode =
680                            content.data[key].Severity.split('.').pop();
681                        priority =
682                            Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
683                        severityFlags[priority.toLowerCase()] = true;
684                        health = Constants.SEVERITY_TO_HEALTH_MAP[severityCode];
685                        healthFlags[health.toLowerCase()] = true;
686                        relatedItems = [];
687                        content.data[key].associations.forEach(function(item) {
688                          relatedItems.push(item[2]);
689                        });
690
691                        if (content.data[key].hasOwnProperty(['EventID'])) {
692                          eventID = content.data[key].EventID;
693                        }
694
695                        if (content.data[key].hasOwnProperty(['Description'])) {
696                          description = content.data[key].Description;
697                        }
698
699                        data.push(Object.assign(
700                            {
701                              path: key,
702                              copied: false,
703                              priority: priority,
704                              severity_code: severityCode,
705                              severity_flags: severityFlags,
706                              health_flags: healthFlags,
707                              additional_data:
708                                  content.data[key].AdditionalData.join('\n'),
709                              type: content.data[key].Message,
710                              selected: false,
711                              search_text:
712                                  ('#' + content.data[key].Id + ' ' +
713                                   severityCode + ' ' +
714                                   content.data[key].Message + ' ' +
715                                   content.data[key].Severity + ' ' +
716                                   content.data[key].AdditionalData.join(' '))
717                                      .toLowerCase(),
718                              meta: false,
719                              confirm: false,
720                              related_items: relatedItems,
721                              eventID: eventID,
722                              description: description,
723                              data: {key: key, value: content.data[key]}
724                            },
725                            content.data[key]));
726                      }
727                    }
728                    deferred.resolve({data: data, original: dataClone});
729                  },
730                  function(error) {
731                    console.log(error);
732                    deferred.reject(error);
733                  });
734
735          return deferred.promise;
736        },
737        getAllSensorStatus: function(callback) {
738          $http({
739            method: 'GET',
740            url: DataService.getHost() +
741                '/xyz/openbmc_project/sensors/enumerate',
742            headers: {
743              'Accept': 'application/json',
744              'Content-Type': 'application/json'
745            },
746            withCredentials: true
747          })
748              .then(
749                  function(response) {
750                    var json = JSON.stringify(response.data);
751                    var content = JSON.parse(json);
752                    var dataClone = JSON.parse(JSON.stringify(content.data));
753                    var sensorData = [];
754                    var severity = {};
755                    var title = '';
756                    var tempKeyParts = [];
757                    var order = 0;
758                    var customOrder = 0;
759
760                    function getSensorStatus(reading) {
761                      var severityFlags = {
762                        critical: false,
763                        warning: false,
764                        normal: false
765                      },
766                          severityText = '', order = 0;
767
768                      if (reading.hasOwnProperty('CriticalLow') &&
769                          reading.Value < reading.CriticalLow) {
770                        severityFlags.critical = true;
771                        severityText = 'critical';
772                        order = 2;
773                      } else if (
774                          reading.hasOwnProperty('CriticalHigh') &&
775                          reading.Value > reading.CriticalHigh) {
776                        severityFlags.critical = true;
777                        severityText = 'critical';
778                        order = 2;
779                      } else if (
780                          reading.hasOwnProperty('CriticalLow') &&
781                          reading.hasOwnProperty('WarningLow') &&
782                          reading.Value >= reading.CriticalLow &&
783                          reading.Value <= reading.WarningLow) {
784                        severityFlags.warning = true;
785                        severityText = 'warning';
786                        order = 1;
787                      } else if (
788                          reading.hasOwnProperty('WarningHigh') &&
789                          reading.hasOwnProperty('CriticalHigh') &&
790                          reading.Value >= reading.WarningHigh &&
791                          reading.Value <= reading.CriticalHigh) {
792                        severityFlags.warning = true;
793                        severityText = 'warning';
794                        order = 1;
795                      } else {
796                        severityFlags.normal = true;
797                        severityText = 'normal';
798                      }
799                      return {
800                        flags: severityFlags,
801                        severityText: severityText,
802                        order: order
803                      };
804                    }
805
806                    for (var key in content.data) {
807                      if (content.data.hasOwnProperty(key) &&
808                          content.data[key].hasOwnProperty('Unit')) {
809                        severity = getSensorStatus(content.data[key]);
810
811                        if (!content.data[key].hasOwnProperty('CriticalLow')) {
812                          content.data[key].CriticalLow = '--';
813                          content.data[key].CriticalHigh = '--';
814                        }
815
816                        if (!content.data[key].hasOwnProperty('WarningLow')) {
817                          content.data[key].WarningLow = '--';
818                          content.data[key].WarningHigh = '--';
819                        }
820
821                        tempKeyParts = key.split('/');
822                        title = tempKeyParts.pop();
823                        title = tempKeyParts.pop() + '_' + title;
824                        title = title.split('_')
825                                    .map(function(item) {
826                                      return item.toLowerCase()
827                                                 .charAt(0)
828                                                 .toUpperCase() +
829                                          item.slice(1);
830                                    })
831                                    .reduce(function(prev, el) {
832                                      return prev + ' ' + el;
833                                    });
834
835                        content.data[key].Value = getScaledValue(
836                            content.data[key].Value, content.data[key].Scale);
837                        content.data[key].CriticalLow = getScaledValue(
838                            content.data[key].CriticalLow,
839                            content.data[key].Scale);
840                        content.data[key].CriticalHigh = getScaledValue(
841                            content.data[key].CriticalHigh,
842                            content.data[key].Scale);
843                        content.data[key].WarningLow = getScaledValue(
844                            content.data[key].WarningLow,
845                            content.data[key].Scale);
846                        content.data[key].WarningHigh = getScaledValue(
847                            content.data[key].WarningHigh,
848                            content.data[key].Scale);
849                        if (Constants.SENSOR_SORT_ORDER.indexOf(
850                                content.data[key].Unit) > -1) {
851                          customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
852                              content.data[key].Unit);
853                        } else {
854                          customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
855                        }
856
857                        sensorData.push(Object.assign(
858                            {
859                              path: key,
860                              selected: false,
861                              confirm: false,
862                              copied: false,
863                              title: title,
864                              unit:
865                                  Constants
866                                      .SENSOR_UNIT_MAP[content.data[key].Unit],
867                              severity_flags: severity.flags,
868                              status: severity.severityText,
869                              order: severity.order,
870                              custom_order: customOrder,
871                              search_text:
872                                  (title + ' ' + content.data[key].Value + ' ' +
873                                   Constants.SENSOR_UNIT_MAP[content.data[key]
874                                                                 .Unit] +
875                                   ' ' + severity.severityText + ' ' +
876                                   content.data[key].CriticalLow + ' ' +
877                                   content.data[key].CriticalHigh + ' ' +
878                                   content.data[key].WarningLow + ' ' +
879                                   content.data[key].WarningHigh + ' ')
880                                      .toLowerCase(),
881                              original_data:
882                                  {key: key, value: content.data[key]}
883                            },
884                            content.data[key]));
885                      }
886                    }
887
888                    callback(sensorData, dataClone);
889                  },
890                  function(error) {
891                    console.log(error);
892                  });
893        },
894        getActivation: function(imageId) {
895          return $http({
896                   method: 'GET',
897                   url: DataService.getHost() +
898                       '/xyz/openbmc_project/software/' + imageId +
899                       '/attr/Activation',
900                   headers: {
901                     'Accept': 'application/json',
902                     'Content-Type': 'application/json'
903                   },
904                   withCredentials: true
905                 })
906              .then(function(response) {
907                return response.data;
908              });
909        },
910        getFirmwares: function() {
911          var deferred = $q.defer();
912          $http({
913            method: 'GET',
914            url: DataService.getHost() +
915                '/xyz/openbmc_project/software/enumerate',
916            headers: {
917              'Accept': 'application/json',
918              'Content-Type': 'application/json'
919            },
920            withCredentials: true
921          })
922              .then(
923                  function(response) {
924                    var json = JSON.stringify(response.data);
925                    var content = JSON.parse(json);
926                    var data = [];
927                    var activationStatus = '';
928                    var isExtended = false;
929                    var bmcActiveVersion = '';
930                    var hostActiveVersion = '';
931                    var imageType = '';
932                    var extendedVersions = [];
933                    var functionalImages = [];
934
935                    function getFormatedExtendedVersions(extendedVersion) {
936                      var versions = [];
937                      extendedVersion = extendedVersion.split(',');
938
939                      extendedVersion.forEach(function(item) {
940                        var parts = item.split('-');
941                        var numberIndex = 0;
942                        for (var i = 0; i < parts.length; i++) {
943                          if (/[0-9]/.test(parts[i])) {
944                            numberIndex = i;
945                            break;
946                          }
947                        }
948                        var titlePart = parts.splice(0, numberIndex);
949                        titlePart = titlePart.join('');
950                        titlePart = titlePart[0].toUpperCase() +
951                            titlePart.substr(1, titlePart.length);
952                        var versionPart = parts.join('-');
953                        versions.push({title: titlePart, version: versionPart});
954                      });
955
956                      return versions;
957                    }
958
959                    // Get the list of functional images so we can compare
960                    // later if an image is functional
961                    if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
962                      functionalImages =
963                          content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
964                              .endpoints;
965                    }
966                    for (var key in content.data) {
967                      if (content.data.hasOwnProperty(key) &&
968                          content.data[key].hasOwnProperty('Version')) {
969                        // If the image is "Functional" use that for the
970                        // activation status, else use the value of "Activation"
971                        // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
972                        activationStatus =
973                            content.data[key].Activation.split('.').pop();
974                        if (functionalImages.includes(key)) {
975                          activationStatus = 'Functional';
976                        }
977
978                        imageType = content.data[key].Purpose.split('.').pop();
979                        isExtended = content.data[key].hasOwnProperty(
980                                         'ExtendedVersion') &&
981                            content.data[key].ExtendedVersion != '';
982                        if (isExtended) {
983                          extendedVersions = getFormatedExtendedVersions(
984                              content.data[key].ExtendedVersion);
985                        }
986                        data.push(Object.assign(
987                            {
988                              path: key,
989                              activationStatus: activationStatus,
990                              imageId: key.split('/').pop(),
991                              imageType: imageType,
992                              isExtended: isExtended,
993                              extended:
994                                  {show: false, versions: extendedVersions},
995                              data: {key: key, value: content.data[key]}
996                            },
997                            content.data[key]));
998
999                        if (activationStatus == 'Functional' &&
1000                            imageType == 'BMC') {
1001                          bmcActiveVersion = content.data[key].Version;
1002                        }
1003
1004                        if (activationStatus == 'Functional' &&
1005                            imageType == 'Host') {
1006                          hostActiveVersion = content.data[key].Version;
1007                        }
1008                      }
1009                    }
1010
1011                    deferred.resolve({
1012                      data: data,
1013                      bmcActiveVersion: bmcActiveVersion,
1014                      hostActiveVersion: hostActiveVersion
1015                    });
1016                  },
1017                  function(error) {
1018                    console.log(error);
1019                    deferred.reject(error);
1020                  });
1021
1022          return deferred.promise;
1023        },
1024        changePriority: function(imageId, priority) {
1025          var deferred = $q.defer();
1026          $http({
1027            method: 'PUT',
1028            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1029                imageId + '/attr/Priority',
1030            headers: {
1031              'Accept': 'application/json',
1032              'Content-Type': 'application/json'
1033            },
1034            withCredentials: true,
1035            data: JSON.stringify({'data': priority})
1036          })
1037              .then(
1038                  function(response) {
1039                    var json = JSON.stringify(response.data);
1040                    var content = JSON.parse(json);
1041                    deferred.resolve(content);
1042                  },
1043                  function(error) {
1044                    console.log(error);
1045                    deferred.reject(error);
1046                  });
1047
1048          return deferred.promise;
1049        },
1050        deleteImage: function(imageId) {
1051          var deferred = $q.defer();
1052          $http({
1053            method: 'POST',
1054            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1055                imageId + '/action/Delete',
1056            headers: {
1057              'Accept': 'application/json',
1058              'Content-Type': 'application/json'
1059            },
1060            withCredentials: true,
1061            data: JSON.stringify({'data': []})
1062          })
1063              .then(
1064                  function(response) {
1065                    var json = JSON.stringify(response.data);
1066                    var content = JSON.parse(json);
1067                    deferred.resolve(content);
1068                  },
1069                  function(error) {
1070                    console.log(error);
1071                    deferred.reject(error);
1072                  });
1073
1074          return deferred.promise;
1075        },
1076        activateImage: function(imageId) {
1077          var deferred = $q.defer();
1078          $http({
1079            method: 'PUT',
1080            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1081                imageId + '/attr/RequestedActivation',
1082            headers: {
1083              'Accept': 'application/json',
1084              'Content-Type': 'application/json'
1085            },
1086            withCredentials: true,
1087            data:
1088                JSON.stringify({'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
1089          })
1090              .then(
1091                  function(response) {
1092                    var json = JSON.stringify(response.data);
1093                    var content = JSON.parse(json);
1094                    deferred.resolve(content);
1095                  },
1096                  function(error) {
1097                    console.log(error);
1098                    deferred.reject(error);
1099                  });
1100
1101          return deferred.promise;
1102        },
1103        uploadImage: function(file) {
1104          return $http({
1105                   method: 'POST',
1106                   timeout: 5 * 60 * 1000,
1107                   url: DataService.getHost() + '/upload/image',
1108                   headers: {'Content-Type': 'application/octet-stream'},
1109                   withCredentials: true,
1110                   data: file
1111                 })
1112              .then(function(response) {
1113                return response.data;
1114              });
1115        },
1116        downloadImage: function(host, filename) {
1117          return $http({
1118                   method: 'POST',
1119                   url: DataService.getHost() +
1120                       '/xyz/openbmc_project/software/action/DownloadViaTFTP',
1121                   headers: {
1122                     'Accept': 'application/json',
1123                     'Content-Type': 'application/json'
1124                   },
1125                   withCredentials: true,
1126                   data: JSON.stringify({'data': [filename, host]}),
1127                   responseType: 'arraybuffer'
1128                 })
1129              .then(function(response) {
1130                return response.data;
1131              });
1132        },
1133        getBMCEthernetInfo: function() {
1134          var deferred = $q.defer();
1135          $http({
1136            method: 'GET',
1137            url: DataService.getHost() +
1138                '/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet',
1139            headers: {
1140              'Accept': 'application/json',
1141              'Content-Type': 'application/json'
1142            },
1143            withCredentials: true
1144          })
1145              .then(
1146                  function(response) {
1147                    var json = JSON.stringify(response.data);
1148                    var content = JSON.parse(json);
1149                    deferred.resolve(content.data);
1150                  },
1151                  function(error) {
1152                    console.log(error);
1153                    deferred.reject(error);
1154                  });
1155
1156          return deferred.promise;
1157        },
1158        getBMCInfo: function(callback) {
1159          var deferred = $q.defer();
1160          $http({
1161            method: 'GET',
1162            url: DataService.getHost() +
1163                '/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc',
1164            headers: {
1165              'Accept': 'application/json',
1166              'Content-Type': 'application/json'
1167            },
1168            withCredentials: true
1169          })
1170              .then(
1171                  function(response) {
1172                    var json = JSON.stringify(response.data);
1173                    var content = JSON.parse(json);
1174                    deferred.resolve(content.data);
1175                  },
1176                  function(error) {
1177                    console.log(error);
1178                    deferred.reject(error);
1179                  });
1180          return deferred.promise;
1181        },
1182        getServerInfo: function() {
1183          // TODO: openbmc/openbmc#3117 Need a way via REST to get
1184          // interfaces so we can get the system object(s) by the looking
1185          // for the system interface.
1186          return $http({
1187                   method: 'GET',
1188                   url: DataService.getHost() +
1189                       '/xyz/openbmc_project/inventory/system',
1190                   headers: {
1191                     'Accept': 'application/json',
1192                     'Content-Type': 'application/json'
1193                   },
1194                   withCredentials: true
1195                 })
1196              .then(function(response) {
1197                return response.data;
1198              });
1199        },
1200        getBMCTime: function() {
1201          return $http({
1202                   method: 'GET',
1203                   url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
1204                   headers: {
1205                     'Accept': 'application/json',
1206                     'Content-Type': 'application/json'
1207                   },
1208                   withCredentials: true
1209                 })
1210              .then(function(response) {
1211                return response.data;
1212              });
1213        },
1214        getHardwares: function(callback) {
1215          $http({
1216            method: 'GET',
1217            url: DataService.getHost() +
1218                '/xyz/openbmc_project/inventory/enumerate',
1219            headers: {
1220              'Accept': 'application/json',
1221              'Content-Type': 'application/json'
1222            },
1223            withCredentials: true
1224          }).then(function(response) {
1225            var json = JSON.stringify(response.data);
1226            var content = JSON.parse(json);
1227            var hardwareData = [];
1228            var keyIndexMap = {};
1229            var title = '';
1230            var data = [];
1231            var searchText = '';
1232            var componentIndex = -1;
1233            var tempParts = [];
1234
1235            function isSubComponent(key) {
1236              for (var i = 0; i < Constants.HARDWARE.parent_components.length;
1237                   i++) {
1238                if (key.split(Constants.HARDWARE.parent_components[i]).length ==
1239                    2)
1240                  return true;
1241              }
1242
1243              return false;
1244            }
1245
1246            function titlelize(title) {
1247              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1248              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
1249                   i++) {
1250                if (title.toLowerCase().indexOf(
1251                        (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
1252                  return title.toUpperCase();
1253                }
1254              }
1255
1256              return title;
1257            }
1258
1259            function camelcaseToLabel(obj) {
1260              var transformed = [], label = '', value = '';
1261              for (var key in obj) {
1262                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1263                if (obj[key] !== '') {
1264                  value = obj[key];
1265                  if (value == 1 || value == 0) {
1266                    value = (value == 1) ? 'Yes' : 'No';
1267                  }
1268                  transformed.push({key: label, value: value});
1269                }
1270              }
1271
1272              return transformed;
1273            }
1274
1275            function getSearchText(data) {
1276              var searchText = '';
1277              for (var i = 0; i < data.length; i++) {
1278                searchText += ' ' + data[i].key + ' ' + data[i].value;
1279              }
1280
1281              return searchText;
1282            }
1283
1284            for (var key in content.data) {
1285              if (content.data.hasOwnProperty(key) &&
1286                  key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
1287                data = camelcaseToLabel(content.data[key]);
1288                searchText = getSearchText(data);
1289                title = key.split('/').pop();
1290
1291                title = titlelize(title);
1292
1293                if (!isSubComponent(key)) {
1294                  hardwareData.push(Object.assign(
1295                      {
1296                        path: key,
1297                        title: title,
1298                        selected: false,
1299                        expanded: false,
1300                        search_text: title.toLowerCase() + ' ' +
1301                            searchText.toLowerCase(),
1302                        sub_components: [],
1303                        original_data: {key: key, value: content.data[key]}
1304                      },
1305                      {items: data}));
1306
1307                  keyIndexMap[key] = hardwareData.length - 1;
1308                } else {
1309                  var tempParts = key.split('/');
1310                  tempParts.pop();
1311                  tempParts = tempParts.join('/');
1312                  componentIndex = keyIndexMap[tempParts];
1313                  data = content.data[key];
1314                  data.title = title;
1315                  hardwareData[componentIndex].sub_components.push(data);
1316                  hardwareData[componentIndex].search_text +=
1317                      ' ' + title.toLowerCase();
1318
1319                  // Sort the subcomponents alphanumeric so they are displayed
1320                  // on the inventory page in order (e.g. core 0, core 1, core
1321                  // 2, ... core 12, core 13)
1322                  hardwareData[componentIndex].sub_components.sort(function(
1323                      a, b) {
1324                    return a.title.localeCompare(
1325                        b.title, 'en', {numeric: true});
1326                  });
1327                }
1328              }
1329            }
1330
1331            if (callback) {
1332              callback(hardwareData, content.data);
1333            } else {
1334              return {data: hardwareData, original_data: content.data};
1335            }
1336          });
1337        },
1338        deleteLogs: function(logs) {
1339          var defer = $q.defer();
1340          var promises = [];
1341
1342          function finished() {
1343            defer.resolve();
1344          }
1345
1346          logs.forEach(function(item) {
1347            promises.push($http({
1348              method: 'POST',
1349              url: DataService.getHost() +
1350                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1351                  '/action/Delete',
1352              headers: {
1353                'Accept': 'application/json',
1354                'Content-Type': 'application/json'
1355              },
1356              withCredentials: true,
1357              data: JSON.stringify({'data': []})
1358            }));
1359          });
1360
1361          $q.all(promises).then(finished);
1362
1363          return defer.promise;
1364        },
1365        resolveLogs: function(logs) {
1366          var defer = $q.defer();
1367          var promises = [];
1368
1369          function finished() {
1370            defer.resolve();
1371          }
1372
1373          logs.forEach(function(item) {
1374            promises.push($http({
1375              method: 'PUT',
1376              url: DataService.getHost() +
1377                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1378                  '/attr/Resolved',
1379              headers: {
1380                'Accept': 'application/json',
1381                'Content-Type': 'application/json'
1382              },
1383              withCredentials: true,
1384              data: JSON.stringify({'data': '1'})
1385            }));
1386          });
1387
1388          $q.all(promises).then(finished);
1389
1390          return defer.promise;
1391        },
1392        getPowerConsumption: function() {
1393          return $http({
1394                   method: 'GET',
1395                   url: DataService.getHost() +
1396                       '/xyz/openbmc_project/sensors/power/total_power',
1397                   headers: {
1398                     'Accept': 'application/json',
1399                     'Content-Type': 'application/json'
1400                   },
1401                   withCredentials: true
1402                 })
1403              .then(
1404                  function(response) {
1405                    var json = JSON.stringify(response.data);
1406                    var content = JSON.parse(json);
1407
1408                    return getScaledValue(
1409                               content.data.Value, content.data.Scale) +
1410                        ' ' +
1411                        Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
1412                  },
1413                  function(error) {
1414                    if ('Not Found' == error.statusText) {
1415                      return Constants.POWER_CONSUMPTION_TEXT.notavailable;
1416                    } else {
1417                      throw error;
1418                    }
1419                  });
1420        },
1421        getPowerCap: function() {
1422          return $http({
1423                   method: 'GET',
1424                   url: DataService.getHost() +
1425                       '/xyz/openbmc_project/control/host0/power_cap',
1426                   headers: {
1427                     'Accept': 'application/json',
1428                     'Content-Type': 'application/json'
1429                   },
1430                   withCredentials: true
1431                 })
1432              .then(function(response) {
1433                var json = JSON.stringify(response.data);
1434                var content = JSON.parse(json);
1435
1436                return (false == content.data.PowerCapEnable) ?
1437                    Constants.POWER_CAP_TEXT.disabled :
1438                    content.data.PowerCap + ' ' + Constants.POWER_CAP_TEXT.unit;
1439              });
1440        },
1441        setHostname: function(hostname) {
1442          return $http({
1443                   method: 'PUT',
1444                   url: DataService.getHost() +
1445                       '/xyz/openbmc_project/network/config/attr/HostName',
1446                   headers: {
1447                     'Accept': 'application/json',
1448                     'Content-Type': 'application/json'
1449                   },
1450                   withCredentials: true,
1451                   data: JSON.stringify({'data': hostname})
1452                 })
1453              .then(function(response) {
1454                return response.data;
1455              });
1456        },
1457      };
1458      return SERVICE;
1459    }
1460  ]);
1461
1462})(window.angular);
1463