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