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