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