1/**
2 * API utilities service
3 *
4 * @module app/common/services/api-utils
5 * @exports APIUtils
6 * @name APIUtils
7 * @version 0.0.1
8 */
9
10window.angular && (function (angular) {
11    'use strict';
12    angular
13        .module('app.common.services')
14        .factory('APIUtils', ['$http', 'Constants', '$q', 'dataService',function($http, Constants, $q, DataService){
15          var SERVICE = {
16              API_CREDENTIALS: Constants.API_CREDENTIALS,
17              API_RESPONSE: Constants.API_RESPONSE,
18              CHASSIS_POWER_STATE: Constants.CHASSIS_POWER_STATE,
19              HOST_STATE_TEXT: Constants.HOST_STATE,
20              HOST_STATE: Constants.HOST_STATE,
21              LED_STATE: Constants.LED_STATE,
22              LED_STATE_TEXT: Constants.LED_STATE_TEXT,
23              HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
24              getChassisState: function(callback){
25                $http({
26                  method: 'GET',
27                  url: DataService.getHost() + "/xyz/openbmc_project/state/chassis0",
28                  headers: {
29                      'Accept': 'application/json',
30                      'Content-Type': 'application/json'
31                  },
32                  withCredentials: true
33                }).then(function(response){
34                      var json = JSON.stringify(response.data);
35                      var content = JSON.parse(json);
36                      callback(content.data.CurrentPowerState);
37                }, function(error){
38                  console.log(error);
39                });
40              },
41              getHostState: function(callback){
42                $http({
43                  method: 'GET',
44                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
45                  headers: {
46                      'Accept': 'application/json',
47                      'Content-Type': 'application/json'
48                  },
49                  withCredentials: true
50                }).then(function(response){
51                      var json = JSON.stringify(response.data);
52                      var content = JSON.parse(json);
53                      callback(content.data.CurrentHostState);
54                }, function(error){
55                  console.log(error);
56                });
57              },
58              getNetworkInfo: function(){
59                var deferred = $q.defer();
60                $http({
61                  method: 'GET',
62                  url: DataService.getHost() + "/xyz/openbmc_project/network/enumerate",
63                  headers: {
64                      'Accept': 'application/json',
65                      'Content-Type': 'application/json'
66                  },
67                  withCredentials: true
68                }).then(function(response){
69                    var json = JSON.stringify(response.data);
70                    var content = JSON.parse(json);
71                    var hostname = "";
72                    var macAddress = "";
73
74                    function parseNetworkData(content){
75                      var data = {
76                        interface_ids: [],
77                        interfaces: {
78                        }
79                      };
80                      var interfaceId = '', keyParts = [], interfaceHash = '', interfaceType = '';
81                      for(var key in content.data){
82                        if(key.match(/network\/eth\d+$/ig)){
83                          interfaceId = key.split("/").pop();
84                          if(data.interface_ids.indexOf(interfaceId) == -1){
85                            data.interface_ids.push(interfaceId);
86                            data.interfaces[interfaceId] = {
87                              interfaceIname: '',
88                              domainName:'',
89                              MACAddress:'',
90                              Nameservers: [],
91                              DHCPEnabled: 0,
92                              ipv4:
93                                {
94                                 ids: [],
95                                 values: []
96                                },
97                              ipv6:
98                                {
99                                 ids: [],
100                                 values: []
101                                }
102                            };
103                            data.interfaces[interfaceId].MACAddress = content.data[key].MACAddress;
104                            data.interfaces[interfaceId].DomainName = content.data[key].DomainName.join(" ");
105                            data.interfaces[interfaceId].Nameservers = content.data[key].Nameservers;
106                            data.interfaces[interfaceId].DHCPEnabled = content.data[key].DHCPEnabled;
107                          }
108                        }else if(key.match(/network\/eth\d+\/ipv[4|6]\/[a-z0-9]+$/ig)){
109                          keyParts = key.split("/");
110                          interfaceHash = keyParts.pop();
111                          interfaceType = keyParts.pop();
112                          interfaceId = keyParts.pop();
113
114                          if(data.interfaces[interfaceId][interfaceType].ids.indexOf(interfaceHash) == -1){
115                            data.interfaces[interfaceId][interfaceType].ids.push(interfaceHash);
116                            data.interfaces[interfaceId][interfaceType].values.push(content.data[key]);
117                          }
118                        }
119                      }
120                      return data;
121                    }
122
123                    if(content.data.hasOwnProperty('/xyz/openbmc_project/network/config') &&
124                      content.data['/xyz/openbmc_project/network/config'].hasOwnProperty('HostName')
125                      ){
126                      hostname = content.data['/xyz/openbmc_project/network/config'].HostName;
127                    }
128
129                    if(content.data.hasOwnProperty('/xyz/openbmc_project/network/eth0') &&
130                      content.data['/xyz/openbmc_project/network/eth0'].hasOwnProperty('MACAddress')
131                      ){
132                      macAddress = content.data['/xyz/openbmc_project/network/eth0'].MACAddress;
133                    }
134
135                    deferred.resolve({
136                      data: content.data,
137                      hostname: hostname,
138                      mac_address: macAddress,
139                      formatted_data: parseNetworkData(content)
140                    });
141                }, function(error){
142                  console.log(error);
143                  deferred.reject(error);
144                });
145                return deferred.promise;
146              },
147              getLEDState: function(){
148                var deferred = $q.defer();
149                $http({
150                  method: 'GET',
151                  url: DataService.getHost() + "/xyz/openbmc_project/led/groups/enclosure_identify",
152                  headers: {
153                      'Accept': 'application/json',
154                      'Content-Type': 'application/json'
155                  },
156                  withCredentials: true
157                }).then(function(response){
158                    var json = JSON.stringify(response.data);
159                    var content = JSON.parse(json);
160                    deferred.resolve(content.data.Asserted);
161                }, function(error){
162                  console.log(error);
163                  deferred.reject(error);
164                });
165                return deferred.promise;
166              },
167              login: function(username, password, callback){
168                $http({
169                  method: 'POST',
170                  url: DataService.getHost() + "/login",
171                  headers: {
172                      'Accept': 'application/json',
173                      'Content-Type': 'application/json'
174                  },
175                  withCredentials: true,
176                  data: JSON.stringify({"data": [username, password]})
177                }).then(function(response){
178                  if(callback){
179                      callback(response.data);
180                  }
181                }, function(error){
182                  if(callback){
183                      if(error && error.status && error.status == 'error'){
184                        callback(error);
185                      }else{
186                        callback(error, true);
187                      }
188                  }
189                  console.log(error);
190                });
191              },
192              testPassword: function(username, password){
193                // Calls /login without the current session to verify the given password is correct
194                // ignore the interceptor logout on a bad password
195                DataService.ignoreHttpError = true;
196                var deferred = $q.defer();
197                $http({
198                  method: 'POST',
199                  url: DataService.getHost() + "/login",
200                  headers: {
201                    'Accept': 'application/json',
202                    'Content-Type': 'application/json'
203                  },
204                  withCredentials: false,
205                  data: JSON.stringify({"data": [username, password]})
206                }).then(function(response){
207                  var json = JSON.stringify(response.data);
208                  var content = JSON.parse(json);
209                  DataService.ignoreHttpError = false;
210                  deferred.resolve(content.data);
211                }, function(error){
212                  DataService.ignoreHttpError = false;
213                  deferred.reject(error);
214                });
215                return deferred.promise;
216              },
217              logout: function(callback){
218                $http({
219                  method: 'POST',
220                  url: DataService.getHost() + "/logout",
221                  headers: {
222                      'Accept': 'application/json',
223                      'Content-Type': 'application/json'
224                  },
225                  withCredentials: true,
226                  data: JSON.stringify({"data": []})
227                }).then(function(response){
228                  if(callback){
229                      callback(response.data);
230                  }
231                }, function(error){
232                  if(callback){
233                      callback(null, error);
234                  }
235                  console.log(error);
236                });
237              },
238              changePassword: function(user, newPassword){
239                var deferred = $q.defer();
240                $http({
241                  method: 'POST',
242                  url: DataService.getHost() + "/xyz/openbmc_project/user/" + user + "/action/SetPassword",
243                  headers: {
244                    'Accept': 'application/json',
245                    'Content-Type': 'application/json'
246                  },
247                  withCredentials: true,
248                  data: JSON.stringify({"data": [newPassword]}),
249                  responseType: 'arraybuffer'
250                }).then(function(response, status, headers){
251                  deferred.resolve({
252                    data: response,
253                    status: status,
254                    headers: headers
255                  });
256                }, function(error){
257                  console.log(error);
258                  deferred.reject(error);
259                });
260                return deferred.promise;
261              },
262              chassisPowerOn: function(callback){
263                $http({
264                  method: 'POST',
265                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
266                  headers: {
267                      'Accept': 'application/json',
268                      'Content-Type': 'application/json'
269                  },
270                  withCredentials: true,
271                  data: JSON.stringify({"data": []})
272                }).then(function(response){
273                      var json = JSON.stringify(response.data);
274                      var content = JSON.parse(json);
275                      if(callback){
276                          return callback(content.data.CurrentPowerState);
277                      }
278                }, function(error){
279                  if(callback){
280                      callback(error);
281                  }else{
282                      console.log(error);
283                  }
284                });
285              },
286              chassisPowerOff: function(callback){
287                $http({
288                  method: 'PUT',
289                  url: DataService.getHost() + "/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition",
290                  headers: {
291                      'Accept': 'application/json',
292                      'Content-Type': 'application/json'
293                  },
294                  withCredentials: true,
295                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Chassis.Transition.Off"})
296                }).then(function(response){
297                      var json = JSON.stringify(response.data);
298                      var content = JSON.parse(json);
299                      if(callback){
300                          return callback(content.status);
301                      }
302                }, function(error){
303                  if(callback){
304                      callback(error);
305                  }else{
306                      console.log(error);
307                  }
308                });
309              },
310              setLEDState: function(state, callback){
311                $http({
312                  method: 'PUT',
313                  url: DataService.getHost() + "/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted",
314                  headers: {
315                      'Accept': 'application/json',
316                      'Content-Type': 'application/json'
317                  },
318                  withCredentials: true,
319                  data: JSON.stringify({"data": state})
320                }).then(function(response){
321                      var json = JSON.stringify(response.data);
322                      var content = JSON.parse(json);
323                      if(callback){
324                          return callback(content.status);
325                      }
326                }, function(error){
327                  if(callback){
328                      callback(error);
329                  }else{
330                      console.log(error);
331                  }
332                });
333              },
334              bmcReboot: function(callback){
335                $http({
336                  method: 'PUT',
337                  url: DataService.getHost() + "/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition",
338                  headers: {
339                      'Accept': 'application/json',
340                      'Content-Type': 'application/json'
341                  },
342                  withCredentials: true,
343                  data: JSON.stringify({"data": "xyz.openbmc_project.State.BMC.Transition.Reboot"})
344                }).then(function(response){
345                      var json = JSON.stringify(response.data);
346                      var content = JSON.parse(json);
347                      if(callback){
348                          return callback(content.status);
349                      }
350                }, function(error){
351                  if(callback){
352                      callback(error);
353                  }else{
354                      console.log(error);
355                  }
356                });
357              },
358              hostPowerOn: function(callback){
359                $http({
360                  method: 'PUT',
361                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
362                  headers: {
363                      'Accept': 'application/json',
364                      'Content-Type': 'application/json'
365                  },
366                  withCredentials: true,
367                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Host.Transition.On"})
368                }).then(function(response){
369                      var json = JSON.stringify(response.data);
370                      var content = JSON.parse(json);
371                      if(callback){
372                          return callback(content.status);
373                      }
374                }, function(error){
375                  if(callback){
376                      callback(error);
377                  }else{
378                      console.log(error);
379                  }
380                });
381              },
382              hostPowerOff: function(callback){
383                $http({
384                  method: 'PUT',
385                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
386                  headers: {
387                      'Accept': 'application/json',
388                      'Content-Type': 'application/json'
389                  },
390                  withCredentials: true,
391                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Host.Transition.Off"})
392                }).then(function(response){
393                      var json = JSON.stringify(response.data);
394                      var content = JSON.parse(json);
395                      if(callback){
396                          return callback(content.status);
397                      }
398                }, function(error){
399                  if(callback){
400                      callback(error);
401                  }else{
402                      console.log(error);
403                  }
404                });
405              },
406              hostReboot: function(callback){
407                $http({
408                  method: 'PUT',
409                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0/attr/RequestedHostTransition",
410                  headers: {
411                      'Accept': 'application/json',
412                      'Content-Type': 'application/json'
413                  },
414                  withCredentials: true,
415                  data: JSON.stringify({"data": "xyz.openbmc_project.State.Host.Transition.Reboot"})
416                }).then(function(response){
417                      var json = JSON.stringify(response.data);
418                      var content = JSON.parse(json);
419                      if(callback){
420                          return callback(content.status);
421                      }
422                }, function(error){
423                  if(callback){
424                      callback(error);
425                  }else{
426                      console.log(error);
427                  }
428                });
429              },
430              hostShutdown: function(callback){
431                $http({
432                  method: 'POST',
433                  url: DataService.getHost() + "/xyz/openbmc_project/state/host0",
434                  headers: {
435                      'Accept': 'application/json',
436                      'Content-Type': 'application/json'
437                  },
438                  withCredentials: true,
439                  data: JSON.stringify({"data": []})
440                }).then(function(response){
441                      var json = JSON.stringify(response.data);
442                      var content = JSON.parse(json);
443                      if(callback){
444                          return callback(content);
445                      }
446                }, function(error){
447                  if(callback){
448                      callback(error);
449                  }else{
450                      console.log(error);
451                  }
452                });
453              },
454              getLogs: function(){
455                var deferred = $q.defer();
456                $http({
457                  method: 'GET',
458                  url: DataService.getHost() + "/xyz/openbmc_project/logging/enumerate",
459                  headers: {
460                      'Accept': 'application/json',
461                      'Content-Type': 'application/json'
462                  },
463                  withCredentials: true
464                }).then(function(response){
465                      var json = JSON.stringify(response.data);
466                      var content = JSON.parse(json);
467                      var dataClone = JSON.parse(JSON.stringify(content.data));
468                      var data = [];
469                      var severityCode = '';
470                      var priority = '';
471                      var health = '';
472                      var relatedItems = [];
473
474                      for(var key in content.data){
475                        if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Id')){
476                          var severityFlags = {low: false, medium: false, high: false};
477                          var healthFlags = {critical: false, warning: false, good: false};
478                          severityCode = content.data[key].Severity.split(".").pop();
479                          priority = Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
480                          severityFlags[priority.toLowerCase()] = true;
481                          health = Constants.SEVERITY_TO_HEALTH_MAP[severityCode];
482                          healthFlags[health.toLowerCase()] = true;
483                          relatedItems = [];
484                          content.data[key].associations.forEach(function(item){
485                            relatedItems.push(item[2]);
486                          });
487
488                          data.push(Object.assign({
489                            path: key,
490                            copied: false,
491                            priority: priority,
492                            severity_code: severityCode,
493                            severity_flags: severityFlags,
494                            health_flags: healthFlags,
495                            additional_data: content.data[key].AdditionalData.join("\n"),
496                            type: content.data[key].Message,
497                            selected: false,
498                            search_text: ("#" + content.data[key].Id + " " + severityCode + " " + content.data[key].Severity + " " + content.data[key].AdditionalData.join(" ")).toLowerCase(),
499                            meta: false,
500                            confirm: false,
501                            related_items: relatedItems,
502                            data: {key: key, value: content.data[key]}
503                          }, content.data[key]));
504                        }
505                      }
506                      deferred.resolve({data: data, original: dataClone});
507                }, function(error){
508                  console.log(error);
509                  deferred.reject(error);
510                });
511
512                return deferred.promise;
513              },
514              getAllSensorStatus: function(callback){
515                $http({
516                  method: 'GET',
517                  url: DataService.getHost() + "/xyz/openbmc_project/sensors/enumerate",
518                  headers: {
519                      'Accept': 'application/json',
520                      'Content-Type': 'application/json'
521                  },
522                  withCredentials: true
523                }).then(function(response){
524                      var json = JSON.stringify(response.data);
525                      var content = JSON.parse(json);
526                      var dataClone = JSON.parse(JSON.stringify(content.data));
527                      var sensorData = [];
528                      var severity = {};
529                      var title = "";
530                      var tempKeyParts = [];
531                      var order = 0;
532                      var customOrder = 0;
533
534                      function getScaledValue(value, scale){
535                        scale = scale + "";
536                        scale = parseInt(scale, 10);
537                        var power = Math.abs(parseInt(scale,10));
538
539                        if(scale > 0){
540                          value = value * Math.pow(10, power);
541                        }else if(scale < 0){
542                          value = value / Math.pow(10, power);
543                        }
544                        return value;
545                      }
546
547                      function getSensorStatus(reading){
548                        var severityFlags = {critical: false, warning: false, normal: false}, severityText = '', order = 0;
549
550                        if(reading.hasOwnProperty('CriticalLow') &&
551                          reading.Value < reading.CriticalLow
552                          ){
553                          severityFlags.critical = true;
554                          severityText = 'critical';
555                          order = 2;
556                        }else if(reading.hasOwnProperty('CriticalHigh') &&
557                          reading.Value > reading.CriticalHigh
558                          ){
559                          severityFlags.critical = true;
560                          severityText = 'critical';
561                          order = 2;
562                        }else if(reading.hasOwnProperty('CriticalLow') &&
563                          reading.hasOwnProperty('WarningLow') &&
564                          reading.Value >= reading.CriticalLow && reading.Value <= reading.WarningLow){
565                          severityFlags.warning = true;
566                          severityText = 'warning';
567                          order = 1;
568                        }else if(reading.hasOwnProperty('WarningHigh') &&
569                          reading.hasOwnProperty('CriticalHigh') &&
570                          reading.Value >= reading.WarningHigh && reading.Value <= reading.CriticalHigh){
571                          severityFlags.warning = true;
572                          severityText = 'warning';
573                          order = 1;
574                        }else{
575                          severityFlags.normal = true;
576                          severityText = 'normal';
577                        }
578                        return { flags: severityFlags, severityText: severityText, order: order};
579                      }
580
581                      for(var key in content.data){
582                        if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Unit')){
583
584                          severity = getSensorStatus(content.data[key]);
585
586                          if(!content.data[key].hasOwnProperty('CriticalLow')){
587                            content.data[key].CriticalLow = "--";
588                            content.data[key].CriticalHigh = "--";
589                          }
590
591                          if(!content.data[key].hasOwnProperty('WarningLow')){
592                            content.data[key].WarningLow = "--";
593                            content.data[key].WarningHigh = "--";
594                          }
595
596                          tempKeyParts = key.split("/");
597                          title = tempKeyParts.pop();
598                          title = tempKeyParts.pop() + '_' + title;
599                          title = title.split("_").map(function(item){
600                             return item.toLowerCase().charAt(0).toUpperCase() + item.slice(1);
601                          }).reduce(function(prev, el){
602                            return prev + " " + el;
603                          });
604
605                          content.data[key].Value = getScaledValue(content.data[key].Value, content.data[key].Scale);
606                          content.data[key].CriticalLow = getScaledValue(content.data[key].CriticalLow, content.data[key].Scale);
607                          content.data[key].CriticalHigh = getScaledValue(content.data[key].CriticalHigh, content.data[key].Scale);
608                          content.data[key].WarningLow = getScaledValue(content.data[key].WarningLow, content.data[key].Scale);
609                          content.data[key].WarningHigh = getScaledValue(content.data[key].WarningHigh, content.data[key].Scale);
610                          if(Constants.SENSOR_SORT_ORDER.indexOf(content.data[key].Unit) > -1){
611                            customOrder = Constants.SENSOR_SORT_ORDER.indexOf(content.data[key].Unit);
612                          }else{
613                            customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
614                          }
615
616                          sensorData.push(Object.assign({
617                            path: key,
618                            selected: false,
619                            confirm: false,
620                            copied: false,
621                            title: title,
622                            unit: Constants.SENSOR_UNIT_MAP[content.data[key].Unit],
623                            severity_flags: severity.flags,
624                            status: severity.severityText,
625                            order: severity.order,
626                            custom_order: customOrder,
627                            search_text: (title + " " + content.data[key].Value + " " +
628                               Constants.SENSOR_UNIT_MAP[content.data[key].Unit] + " " +
629                               severity.severityText + " " +
630                               content.data[key].CriticalLow + " " +
631                               content.data[key].CriticalHigh + " " +
632                               content.data[key].WarningLow + " " +
633                               content.data[key].WarningHigh + " "
634                               ).toLowerCase(),
635                            original_data: {key: key, value: content.data[key]}
636                          }, content.data[key]));
637                        }
638                      }
639
640                      callback(sensorData, dataClone);
641                }, function(error){
642                  console.log(error);
643                });
644              },
645              getFirmwares: function(){
646                var deferred = $q.defer();
647                $http({
648                  method: 'GET',
649                  url: DataService.getHost() + "/xyz/openbmc_project/software/enumerate",
650                  headers: {
651                      'Accept': 'application/json',
652                      'Content-Type': 'application/json'
653                  },
654                  withCredentials: true
655                }).then(function(response){
656                      var json = JSON.stringify(response.data);
657                      var content = JSON.parse(json);
658                      var data = [];
659                      var activationStatus = "";
660                      var isExtended = false;
661                      var bmcActiveVersion = "";
662                      var hostActiveVersion = "";
663                      var imageType = "";
664                      var extendedVersions = [];
665                      var functionalImages = [];
666
667                      function getFormatedExtendedVersions(extendedVersion){
668                        var versions = [];
669                        extendedVersion = extendedVersion.split(",");
670
671                        extendedVersion.forEach(function(item){
672                          var parts = item.split("-");
673                          var numberIndex = 0;
674                          for(var i = 0; i < parts.length; i++){
675                            if(/[0-9]/.test(parts[i])){
676                              numberIndex = i;
677                              break;
678                            }
679                          }
680                          var titlePart = parts.splice(0, numberIndex);
681                          titlePart = titlePart.join("");
682                          titlePart = titlePart[0].toUpperCase() + titlePart.substr(1, titlePart.length);
683                          var versionPart = parts.join("-");
684                          versions.push({
685                            title: titlePart,
686                            version: versionPart
687                          });
688                        });
689
690                        return versions;
691                      }
692
693                      // Get the list of functional images so we can compare
694                      // later if an image is functional
695                      if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH])
696                      {
697                        functionalImages = content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH].endpoints;
698                      }
699                      for(var key in content.data){
700                        if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Version')){
701                          // If the image is "Functional" use that for the
702                          // activation status, else use the value of "Activation"
703                          // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
704                          activationStatus = content.data[key].Activation.split(".").pop();
705                          if (functionalImages.includes(key))
706                          {
707                            activationStatus = "Functional";
708                          }
709
710                          imageType = content.data[key].Purpose.split(".").pop();
711                          isExtended = content.data[key].hasOwnProperty('ExtendedVersion') && content.data[key].ExtendedVersion != "";
712                          if(isExtended){
713                            extendedVersions = getFormatedExtendedVersions(content.data[key].ExtendedVersion);
714                          }
715                          data.push(Object.assign({
716                            path: key,
717                            activationStatus: activationStatus,
718                            imageId: key.split("/").pop(),
719                            imageType: imageType,
720                            isExtended: isExtended,
721                            extended: {
722                              show: false,
723                              versions: extendedVersions
724                            },
725                            data: {key: key, value: content.data[key]}
726                          }, content.data[key]));
727
728                          if(activationStatus == 'Functional' && imageType == 'BMC'){
729                            bmcActiveVersion = content.data[key].Version;
730                          }
731
732                          if(activationStatus == 'Functional' && imageType == 'Host'){
733                            hostActiveVersion = content.data[key].Version;
734                          }
735                        }
736                      }
737
738                      deferred.resolve({
739                          data: data,
740                          bmcActiveVersion: bmcActiveVersion,
741                          hostActiveVersion: hostActiveVersion
742                      });
743                }, function(error){
744                  console.log(error);
745                  deferred.reject(error);
746                });
747
748                return deferred.promise;
749              },
750              changePriority: function(imageId, priority){
751                var deferred = $q.defer();
752                $http({
753                  method: 'PUT',
754                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/Priority",
755                  headers: {
756                      'Accept': 'application/json',
757                      'Content-Type': 'application/json'
758                  },
759                  withCredentials: true,
760                  data: JSON.stringify({"data": priority})
761                }).then(function(response){
762                      var json = JSON.stringify(response.data);
763                      var content = JSON.parse(json);
764                      deferred.resolve(content);
765                }, function(error){
766                  console.log(error);
767                  deferred.reject(error);
768                });
769
770                return deferred.promise;
771              },
772              deleteImage: function(imageId){
773                var deferred = $q.defer();
774                $http({
775                  method: 'POST',
776                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/action/Delete",
777                  headers: {
778                      'Accept': 'application/json',
779                      'Content-Type': 'application/json'
780                  },
781                  withCredentials: true,
782                  data: JSON.stringify({"data": []})
783                }).then(function(response){
784                      var json = JSON.stringify(response.data);
785                      var content = JSON.parse(json);
786                      deferred.resolve(content);
787                }, function(error){
788                  console.log(error);
789                  deferred.reject(error);
790                });
791
792                return deferred.promise;
793              },
794              activateImage: function(imageId){
795                var deferred = $q.defer();
796                $http({
797                  method: 'PUT',
798                  url: DataService.getHost() + "/xyz/openbmc_project/software/" + imageId + "/attr/RequestedActivation",
799                  headers: {
800                      'Accept': 'application/json',
801                      'Content-Type': 'application/json'
802                  },
803                  withCredentials: true,
804                  data: JSON.stringify({"data": Constants.FIRMWARE.ACTIVATE_FIRMWARE})
805                }).then(function(response){
806                      var json = JSON.stringify(response.data);
807                      var content = JSON.parse(json);
808                      deferred.resolve(content);
809                }, function(error){
810                  console.log(error);
811                  deferred.reject(error);
812                });
813
814                return deferred.promise;
815              },
816              uploadImage: function(file){
817                var deferred = $q.defer();
818                $http({
819                  method: 'POST',
820                  timeout: 5 * 60 * 1000,
821                  url: DataService.getHost() + "/upload/image",
822                  headers: {
823                    'Content-Type': 'application/octet-stream'
824                  },
825                  withCredentials: true,
826                  data: file
827                }).then(function(response){
828                      var json = JSON.stringify(response.data);
829                      var content = JSON.parse(json);
830                      deferred.resolve(content);
831                }, function(error){
832                  console.log(error);
833                  deferred.reject(error);
834                });
835
836                return deferred.promise;
837              },
838              downloadImage: function(host, filename){
839                var deferred = $q.defer();
840                $http({
841                  method: 'POST',
842                  url: DataService.getHost() + "/xyz/openbmc_project/software/action/DownloadViaTFTP",
843                  headers: {
844                      'Accept': 'application/json',
845                      'Content-Type': 'application/json'
846                  },
847                  withCredentials: true,
848                  data: JSON.stringify({"data": [filename, host]}),
849                  responseType: 'arraybuffer'
850                }).then(function(response, status, headers){
851                  deferred.resolve({
852                    data: response,
853                    status: status,
854                    headers: headers
855                  });
856                }, function(error){
857                  console.log(error);
858                  deferred.reject(error);
859                });
860
861                return deferred.promise;
862              },
863              getBMCEthernetInfo: function(){
864                var deferred = $q.defer();
865                $http({
866                  method: 'GET',
867                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc/ethernet",
868                  headers: {
869                      'Accept': 'application/json',
870                      'Content-Type': 'application/json'
871                  },
872                  withCredentials: true
873                }).then(function(response){
874                    var json = JSON.stringify(response.data);
875                    var content = JSON.parse(json);
876                    deferred.resolve(content.data);
877                }, function(error){
878                  console.log(error);
879                  deferred.reject(error);
880                });
881
882                return deferred.promise;
883              },
884              getBMCInfo: function(callback){
885                var deferred = $q.defer();
886                $http({
887                  method: 'GET',
888                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/system/chassis/motherboard/boxelder/bmc",
889                  headers: {
890                      'Accept': 'application/json',
891                      'Content-Type': 'application/json'
892                  },
893                  withCredentials: true
894                }).then(function(response){
895                    var json = JSON.stringify(response.data);
896                    var content = JSON.parse(json);
897                    deferred.resolve(content.data);
898                }, function(error){
899                  console.log(error);
900                  deferred.reject(error);
901                });
902                return deferred.promise;
903              },
904              getHardwares: function(callback){
905                $http({
906                  method: 'GET',
907                  url: DataService.getHost() + "/xyz/openbmc_project/inventory/enumerate",
908                  headers: {
909                      'Accept': 'application/json',
910                      'Content-Type': 'application/json'
911                  },
912                  withCredentials: true
913                }).then(function(response){
914                      var json = JSON.stringify(response.data);
915                      var content = JSON.parse(json);
916                      var hardwareData = [];
917                      var keyIndexMap = {};
918                      var title = "";
919                      var data = [];
920                      var searchText = "";
921                      var componentIndex = -1;
922                      var tempParts = [];
923
924
925                      function isSubComponent(key){
926
927                        for(var i = 0; i < Constants.HARDWARE.parent_components.length; i++){
928                          if(key.split(Constants.HARDWARE.parent_components[i]).length == 2) return true;
929                        }
930
931                        return false;
932                      }
933
934                      function titlelize(title){
935                        title = title.replace(/([A-Z0-9]+)/g, " $1").replace(/^\s+/, "");
936                        for(var i = 0; i < Constants.HARDWARE.uppercase_titles.length; i++){
937                          if(title.toLowerCase().indexOf((Constants.HARDWARE.uppercase_titles[i] + " ")) > -1){
938                            return title.toUpperCase();
939                          }
940                        }
941
942                        return title;
943                      }
944
945                      function camelcaseToLabel(obj){
946                        var transformed = [], label = "", value = "";
947                        for(var key in obj){
948                          label = key.replace(/([A-Z0-9]+)/g, " $1").replace(/^\s+/, "");
949                          if(obj[key] !== ""){
950                            value = obj[key];
951                            if(value == 1 || value == 0){
952                              value = (value == 1) ? 'Yes' : 'No';
953                            }
954                            transformed.push({key:label, value: value});
955                          }
956                        }
957
958                        return transformed;
959                      }
960
961                      function getSearchText(data){
962                        var searchText = "";
963                        for(var i = 0; i < data.length; i++){
964                          searchText += " " + data[i].key + " " + data[i].value;
965                        }
966
967                        return searchText;
968                      }
969
970                      for(var key in content.data){
971                        if(content.data.hasOwnProperty(key) &&
972                           key.indexOf(Constants.HARDWARE.component_key_filter) == 0){
973
974                          data = camelcaseToLabel(content.data[key]);
975                          searchText = getSearchText(data);
976                          title = key.split("/").pop();
977
978                          title = titlelize(title);
979
980                          if(!isSubComponent(key)){
981                              hardwareData.push(Object.assign({
982                                path: key,
983                                title: title,
984                                selected: false,
985                                expanded: false,
986                                search_text: title.toLowerCase() + " " + searchText.toLowerCase(),
987                                sub_components: [],
988                                original_data: {key: key, value: content.data[key]}
989                              }, {items: data}));
990
991                              keyIndexMap[key] = hardwareData.length - 1;
992                          }else{
993                            var tempParts = key.split("/");
994                            tempParts.pop();
995                            tempParts = tempParts.join("/");
996                            componentIndex = keyIndexMap[tempParts];
997                            data = content.data[key];
998                            data.title = title;
999                            hardwareData[componentIndex].sub_components.push(data);
1000                            hardwareData[componentIndex].search_text += " " + title.toLowerCase();
1001
1002                            // Sort the subcomponents alphanumeric so they are displayed on the
1003                            // inventory page in order (e.g. core 0, core 1, core 2, ... core 12, core 13)
1004                            hardwareData[componentIndex].sub_components.sort(function (a, b) {
1005                                return a.title.localeCompare(b.title, 'en', { numeric: true });
1006                            });
1007                          }
1008                      }
1009                    }
1010
1011                    if(callback){
1012                       callback(hardwareData, content.data);
1013                    }else{
1014                       return { data: hardwareData, original_data: content.data};
1015                    }
1016                });
1017              },
1018              deleteLogs: function(logs) {
1019                  var defer = $q.defer();
1020                  var promises = [];
1021
1022                  function finished(){
1023                      defer.resolve();
1024                  }
1025
1026                  logs.forEach(function(item){
1027                    promises.push($http({
1028                                      method: 'POST',
1029                                      url: DataService.getHost() + "/xyz/openbmc_project/logging/entry/"+item.Id+"/action/Delete",
1030                                      headers: {
1031                                          'Accept': 'application/json',
1032                                          'Content-Type': 'application/json'
1033                                      },
1034                                      withCredentials: true,
1035                                      data: JSON.stringify({"data": []})
1036                                 }));
1037                  });
1038
1039                  $q.all(promises).then(finished);
1040
1041                  return defer.promise;
1042              },
1043              resolveLogs: function(logs) {
1044                  var defer = $q.defer();
1045                  var promises = [];
1046
1047                  function finished(){
1048                      defer.resolve();
1049                  }
1050
1051                  logs.forEach(function(item){
1052                    promises.push($http({
1053                                      method: 'PUT',
1054                                      url: DataService.getHost() + "/xyz/openbmc_project/logging/entry/"+item.Id+"/attr/Resolved",
1055                                      headers: {
1056                                          'Accept': 'application/json',
1057                                          'Content-Type': 'application/json'
1058                                      },
1059                                      withCredentials: true,
1060                                      data: JSON.stringify({"data": "1"})
1061                                 }));
1062                  });
1063
1064                  $q.all(promises).then(finished);
1065
1066                  return defer.promise;
1067              },
1068          };
1069          return SERVICE;
1070        }]);
1071
1072        })(window.angular);
1073