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