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