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