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        chassisPowerOff: function() {
426          var deferred = $q.defer();
427          $http({
428            method: 'PUT',
429            url: DataService.getHost() +
430                '/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition',
431            headers: {
432              'Accept': 'application/json',
433              'Content-Type': 'application/json'
434            },
435            withCredentials: true,
436            data: JSON.stringify(
437                {'data': 'xyz.openbmc_project.State.Chassis.Transition.Off'})
438          })
439              .then(
440                  function(response) {
441                    var json = JSON.stringify(response.data);
442                    var content = JSON.parse(json);
443                    deferred.resolve(content.status);
444                  },
445                  function(error) {
446                    console.log(error);
447                    deferred.reject(error);
448                  });
449          return deferred.promise;
450        },
451        setLEDState: function(state, callback) {
452          $http({
453            method: 'PUT',
454            url: DataService.getHost() +
455                '/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted',
456            headers: {
457              'Accept': 'application/json',
458              'Content-Type': 'application/json'
459            },
460            withCredentials: true,
461            data: JSON.stringify({'data': state})
462          })
463              .then(
464                  function(response) {
465                    var json = JSON.stringify(response.data);
466                    var content = JSON.parse(json);
467                    if (callback) {
468                      return callback(content.status);
469                    }
470                  },
471                  function(error) {
472                    if (callback) {
473                      callback(error);
474                    } else {
475                      console.log(error);
476                    }
477                  });
478        },
479        bmcReboot: function(callback) {
480          $http({
481            method: 'PUT',
482            url: DataService.getHost() +
483                '/xyz/openbmc_project/state/bmc0/attr/RequestedBmcTransition',
484            headers: {
485              'Accept': 'application/json',
486              'Content-Type': 'application/json'
487            },
488            withCredentials: true,
489            data: JSON.stringify(
490                {'data': 'xyz.openbmc_project.State.BMC.Transition.Reboot'})
491          })
492              .then(
493                  function(response) {
494                    var json = JSON.stringify(response.data);
495                    var content = JSON.parse(json);
496                    if (callback) {
497                      return callback(content.status);
498                    }
499                  },
500                  function(error) {
501                    if (callback) {
502                      callback(error);
503                    } else {
504                      console.log(error);
505                    }
506                  });
507        },
508        getLastRebootTime: function() {
509          return $http({
510                   method: 'GET',
511                   url: DataService.getHost() +
512                       '/xyz/openbmc_project/state/bmc0/attr/LastRebootTime',
513                   headers: {
514                     'Accept': 'application/json',
515                     'Content-Type': 'application/json'
516                   },
517                   withCredentials: true
518                 })
519              .then(function(response) {
520                return response.data;
521              });
522        },
523        hostPowerOn: function() {
524          var deferred = $q.defer();
525          $http({
526            method: 'PUT',
527            url: DataService.getHost() +
528                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
529            headers: {
530              'Accept': 'application/json',
531              'Content-Type': 'application/json'
532            },
533            withCredentials: true,
534            data: JSON.stringify(
535                {'data': 'xyz.openbmc_project.State.Host.Transition.On'})
536          })
537              .then(
538                  function(response) {
539                    var json = JSON.stringify(response.data);
540                    var content = JSON.parse(json);
541                    deferred.resolve(content.status);
542                  },
543                  function(error) {
544                    console.log(error);
545                    deferred.reject(error);
546                  });
547          return deferred.promise;
548        },
549        hostPowerOff: function() {
550          var deferred = $q.defer();
551          $http({
552            method: 'PUT',
553            url: DataService.getHost() +
554                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
555            headers: {
556              'Accept': 'application/json',
557              'Content-Type': 'application/json'
558            },
559            withCredentials: true,
560            data: JSON.stringify(
561                {'data': 'xyz.openbmc_project.State.Host.Transition.Off'})
562          })
563              .then(
564                  function(response) {
565                    var json = JSON.stringify(response.data);
566                    var content = JSON.parse(json);
567                    deferred.resolve(content.status);
568                  },
569                  function(error) {
570                    console.log(error);
571                    deferred.reject(error);
572                  });
573          return deferred.promise;
574        },
575        hostReboot: function() {
576          var deferred = $q.defer();
577          $http({
578            method: 'PUT',
579            url: DataService.getHost() +
580                '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
581            headers: {
582              'Accept': 'application/json',
583              'Content-Type': 'application/json'
584            },
585            withCredentials: true,
586            data: JSON.stringify(
587                {'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'})
588          })
589              .then(
590                  function(response) {
591                    var json = JSON.stringify(response.data);
592                    var content = JSON.parse(json);
593                    deferred.resolve(content.status);
594                  },
595                  function(error) {
596                    console.log(error);
597                    deferred.reject(error);
598                  });
599
600          return deferred.promise;
601        },
602        hostShutdown: function(callback) {
603          $http({
604            method: 'POST',
605            url: DataService.getHost() + '/xyz/openbmc_project/state/host0',
606            headers: {
607              'Accept': 'application/json',
608              'Content-Type': 'application/json'
609            },
610            withCredentials: true,
611            data: JSON.stringify({'data': []})
612          })
613              .then(
614                  function(response) {
615                    var json = JSON.stringify(response.data);
616                    var content = JSON.parse(json);
617                    if (callback) {
618                      return callback(content);
619                    }
620                  },
621                  function(error) {
622                    if (callback) {
623                      callback(error);
624                    } else {
625                      console.log(error);
626                    }
627                  });
628        },
629        getLastPowerTime: function() {
630          return $http({
631                   method: 'GET',
632                   url: DataService.getHost() +
633                       '/xyz/openbmc_project/state/chassis0/attr/LastStateChangeTime',
634                   headers: {
635                     'Accept': 'application/json',
636                     'Content-Type': 'application/json'
637                   },
638                   withCredentials: true
639                 })
640              .then(function(response) {
641                return response.data;
642              });
643        },
644        getLogs: function() {
645          var deferred = $q.defer();
646          $http({
647            method: 'GET',
648            url: DataService.getHost() +
649                '/xyz/openbmc_project/logging/enumerate',
650            headers: {
651              'Accept': 'application/json',
652              'Content-Type': 'application/json'
653            },
654            withCredentials: true
655          })
656              .then(
657                  function(response) {
658                    var json = JSON.stringify(response.data);
659                    var content = JSON.parse(json);
660                    var dataClone = JSON.parse(JSON.stringify(content.data));
661                    var data = [];
662                    var severityCode = '';
663                    var priority = '';
664                    var health = '';
665                    var relatedItems = [];
666                    var eventID = 'None';
667                    var description = 'None';
668
669                    for (var key in content.data) {
670                      if (content.data.hasOwnProperty(key) &&
671                          content.data[key].hasOwnProperty('Id')) {
672                        var severityFlags = {
673                          low: false,
674                          medium: false,
675                          high: false
676                        };
677                        var healthFlags = {
678                          critical: false,
679                          warning: false,
680                          good: false
681                        };
682                        severityCode =
683                            content.data[key].Severity.split('.').pop();
684                        priority =
685                            Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
686                        severityFlags[priority.toLowerCase()] = true;
687                        health = Constants.SEVERITY_TO_HEALTH_MAP[severityCode];
688                        healthFlags[health.toLowerCase()] = true;
689                        relatedItems = [];
690                        content.data[key].associations.forEach(function(item) {
691                          relatedItems.push(item[2]);
692                        });
693
694                        if (content.data[key].hasOwnProperty(['EventID'])) {
695                          eventID = content.data[key].EventID;
696                        }
697
698                        if (content.data[key].hasOwnProperty(['Description'])) {
699                          description = content.data[key].Description;
700                        }
701
702                        data.push(Object.assign(
703                            {
704                              path: key,
705                              copied: false,
706                              priority: priority,
707                              severity_code: severityCode,
708                              severity_flags: severityFlags,
709                              health_flags: healthFlags,
710                              additional_data:
711                                  content.data[key].AdditionalData.join('\n'),
712                              type: content.data[key].Message,
713                              selected: false,
714                              search_text:
715                                  ('#' + content.data[key].Id + ' ' +
716                                   severityCode + ' ' +
717                                   content.data[key].Message + ' ' +
718                                   content.data[key].Severity + ' ' +
719                                   content.data[key].AdditionalData.join(' '))
720                                      .toLowerCase(),
721                              meta: false,
722                              confirm: false,
723                              related_items: relatedItems,
724                              eventID: eventID,
725                              description: description,
726                              data: {key: key, value: content.data[key]}
727                            },
728                            content.data[key]));
729                      }
730                    }
731                    deferred.resolve({data: data, original: dataClone});
732                  },
733                  function(error) {
734                    console.log(error);
735                    deferred.reject(error);
736                  });
737
738          return deferred.promise;
739        },
740        getAllSensorStatus: function(callback) {
741          $http({
742            method: 'GET',
743            url: DataService.getHost() +
744                '/xyz/openbmc_project/sensors/enumerate',
745            headers: {
746              'Accept': 'application/json',
747              'Content-Type': 'application/json'
748            },
749            withCredentials: true
750          })
751              .then(
752                  function(response) {
753                    var json = JSON.stringify(response.data);
754                    var content = JSON.parse(json);
755                    var dataClone = JSON.parse(JSON.stringify(content.data));
756                    var sensorData = [];
757                    var severity = {};
758                    var title = '';
759                    var tempKeyParts = [];
760                    var order = 0;
761                    var customOrder = 0;
762
763                    function getSensorStatus(reading) {
764                      var severityFlags = {
765                        critical: false,
766                        warning: false,
767                        normal: false
768                      },
769                          severityText = '', order = 0;
770
771                      if (reading.hasOwnProperty('CriticalLow') &&
772                          reading.Value < reading.CriticalLow) {
773                        severityFlags.critical = true;
774                        severityText = 'critical';
775                        order = 2;
776                      } else if (
777                          reading.hasOwnProperty('CriticalHigh') &&
778                          reading.Value > reading.CriticalHigh) {
779                        severityFlags.critical = true;
780                        severityText = 'critical';
781                        order = 2;
782                      } else if (
783                          reading.hasOwnProperty('CriticalLow') &&
784                          reading.hasOwnProperty('WarningLow') &&
785                          reading.Value >= reading.CriticalLow &&
786                          reading.Value <= reading.WarningLow) {
787                        severityFlags.warning = true;
788                        severityText = 'warning';
789                        order = 1;
790                      } else if (
791                          reading.hasOwnProperty('WarningHigh') &&
792                          reading.hasOwnProperty('CriticalHigh') &&
793                          reading.Value >= reading.WarningHigh &&
794                          reading.Value <= reading.CriticalHigh) {
795                        severityFlags.warning = true;
796                        severityText = 'warning';
797                        order = 1;
798                      } else {
799                        severityFlags.normal = true;
800                        severityText = 'normal';
801                      }
802                      return {
803                        flags: severityFlags,
804                        severityText: severityText,
805                        order: order
806                      };
807                    }
808
809                    for (var key in content.data) {
810                      if (content.data.hasOwnProperty(key) &&
811                          content.data[key].hasOwnProperty('Unit')) {
812                        severity = getSensorStatus(content.data[key]);
813
814                        if (!content.data[key].hasOwnProperty('CriticalLow')) {
815                          content.data[key].CriticalLow = '--';
816                          content.data[key].CriticalHigh = '--';
817                        }
818
819                        if (!content.data[key].hasOwnProperty('WarningLow')) {
820                          content.data[key].WarningLow = '--';
821                          content.data[key].WarningHigh = '--';
822                        }
823
824                        tempKeyParts = key.split('/');
825                        title = tempKeyParts.pop();
826                        title = tempKeyParts.pop() + '_' + title;
827                        title = title.split('_')
828                                    .map(function(item) {
829                                      return item.toLowerCase()
830                                                 .charAt(0)
831                                                 .toUpperCase() +
832                                          item.slice(1);
833                                    })
834                                    .reduce(function(prev, el) {
835                                      return prev + ' ' + el;
836                                    });
837
838                        content.data[key].Value = getScaledValue(
839                            content.data[key].Value, content.data[key].Scale);
840                        content.data[key].CriticalLow = getScaledValue(
841                            content.data[key].CriticalLow,
842                            content.data[key].Scale);
843                        content.data[key].CriticalHigh = getScaledValue(
844                            content.data[key].CriticalHigh,
845                            content.data[key].Scale);
846                        content.data[key].WarningLow = getScaledValue(
847                            content.data[key].WarningLow,
848                            content.data[key].Scale);
849                        content.data[key].WarningHigh = getScaledValue(
850                            content.data[key].WarningHigh,
851                            content.data[key].Scale);
852                        if (Constants.SENSOR_SORT_ORDER.indexOf(
853                                content.data[key].Unit) > -1) {
854                          customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
855                              content.data[key].Unit);
856                        } else {
857                          customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
858                        }
859
860                        sensorData.push(Object.assign(
861                            {
862                              path: key,
863                              selected: false,
864                              confirm: false,
865                              copied: false,
866                              title: title,
867                              unit:
868                                  Constants
869                                      .SENSOR_UNIT_MAP[content.data[key].Unit],
870                              severity_flags: severity.flags,
871                              status: severity.severityText,
872                              order: severity.order,
873                              custom_order: customOrder,
874                              search_text:
875                                  (title + ' ' + content.data[key].Value + ' ' +
876                                   Constants.SENSOR_UNIT_MAP[content.data[key]
877                                                                 .Unit] +
878                                   ' ' + severity.severityText + ' ' +
879                                   content.data[key].CriticalLow + ' ' +
880                                   content.data[key].CriticalHigh + ' ' +
881                                   content.data[key].WarningLow + ' ' +
882                                   content.data[key].WarningHigh + ' ')
883                                      .toLowerCase(),
884                              original_data:
885                                  {key: key, value: content.data[key]}
886                            },
887                            content.data[key]));
888                      }
889                    }
890
891                    callback(sensorData, dataClone);
892                  },
893                  function(error) {
894                    console.log(error);
895                  });
896        },
897        getActivation: function(imageId) {
898          return $http({
899                   method: 'GET',
900                   url: DataService.getHost() +
901                       '/xyz/openbmc_project/software/' + imageId +
902                       '/attr/Activation',
903                   headers: {
904                     'Accept': 'application/json',
905                     'Content-Type': 'application/json'
906                   },
907                   withCredentials: true
908                 })
909              .then(function(response) {
910                return response.data;
911              });
912        },
913        getFirmwares: function() {
914          var deferred = $q.defer();
915          $http({
916            method: 'GET',
917            url: DataService.getHost() +
918                '/xyz/openbmc_project/software/enumerate',
919            headers: {
920              'Accept': 'application/json',
921              'Content-Type': 'application/json'
922            },
923            withCredentials: true
924          })
925              .then(
926                  function(response) {
927                    var json = JSON.stringify(response.data);
928                    var content = JSON.parse(json);
929                    var data = [];
930                    var isExtended = false;
931                    var bmcActiveVersion = '';
932                    var hostActiveVersion = '';
933                    var imageType = '';
934                    var extendedVersions = [];
935                    var functionalImages = [];
936
937                    function getFormatedExtendedVersions(extendedVersion) {
938                      var versions = [];
939                      extendedVersion = extendedVersion.split(',');
940
941                      extendedVersion.forEach(function(item) {
942                        var parts = item.split('-');
943                        var numberIndex = 0;
944                        for (var i = 0; i < parts.length; i++) {
945                          if (/[0-9]/.test(parts[i])) {
946                            numberIndex = i;
947                            break;
948                          }
949                        }
950                        var titlePart = parts.splice(0, numberIndex);
951                        titlePart = titlePart.join('');
952                        titlePart = titlePart[0].toUpperCase() +
953                            titlePart.substr(1, titlePart.length);
954                        var versionPart = parts.join('-');
955                        versions.push({title: titlePart, version: versionPart});
956                      });
957
958                      return versions;
959                    }
960
961                    // Get the list of functional images so we can compare
962                    // later if an image is functional
963                    if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
964                      functionalImages =
965                          content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
966                              .endpoints;
967                    }
968                    for (var key in content.data) {
969                      if (content.data.hasOwnProperty(key) &&
970                          content.data[key].hasOwnProperty('Version')) {
971                        var activationStatus = '';
972
973                        // If the image is "Functional" use that for the
974                        // activation status, else use the value of "Activation"
975                        // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
976                        if (content.data[key].Activation) {
977                          activationStatus =
978                              content.data[key].Activation.split('.').pop();
979                        }
980
981                        if (functionalImages.includes(key)) {
982                          activationStatus = 'Functional';
983                        }
984
985                        imageType = content.data[key].Purpose.split('.').pop();
986                        isExtended = content.data[key].hasOwnProperty(
987                                         'ExtendedVersion') &&
988                            content.data[key].ExtendedVersion != '';
989                        if (isExtended) {
990                          extendedVersions = getFormatedExtendedVersions(
991                              content.data[key].ExtendedVersion);
992                        }
993                        data.push(Object.assign(
994                            {
995                              path: key,
996                              activationStatus: activationStatus,
997                              imageId: key.split('/').pop(),
998                              imageType: imageType,
999                              isExtended: isExtended,
1000                              extended:
1001                                  {show: false, versions: extendedVersions},
1002                              data: {key: key, value: content.data[key]}
1003                            },
1004                            content.data[key]));
1005
1006                        if (activationStatus == 'Functional' &&
1007                            imageType == 'BMC') {
1008                          bmcActiveVersion = content.data[key].Version;
1009                        }
1010
1011                        if (activationStatus == 'Functional' &&
1012                            imageType == 'Host') {
1013                          hostActiveVersion = content.data[key].Version;
1014                        }
1015                      }
1016                    }
1017
1018                    deferred.resolve({
1019                      data: data,
1020                      bmcActiveVersion: bmcActiveVersion,
1021                      hostActiveVersion: hostActiveVersion
1022                    });
1023                  },
1024                  function(error) {
1025                    console.log(error);
1026                    deferred.reject(error);
1027                  });
1028
1029          return deferred.promise;
1030        },
1031        changePriority: function(imageId, priority) {
1032          var deferred = $q.defer();
1033          $http({
1034            method: 'PUT',
1035            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1036                imageId + '/attr/Priority',
1037            headers: {
1038              'Accept': 'application/json',
1039              'Content-Type': 'application/json'
1040            },
1041            withCredentials: true,
1042            data: JSON.stringify({'data': priority})
1043          })
1044              .then(
1045                  function(response) {
1046                    var json = JSON.stringify(response.data);
1047                    var content = JSON.parse(json);
1048                    deferred.resolve(content);
1049                  },
1050                  function(error) {
1051                    console.log(error);
1052                    deferred.reject(error);
1053                  });
1054
1055          return deferred.promise;
1056        },
1057        deleteImage: function(imageId) {
1058          var deferred = $q.defer();
1059          $http({
1060            method: 'POST',
1061            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1062                imageId + '/action/Delete',
1063            headers: {
1064              'Accept': 'application/json',
1065              'Content-Type': 'application/json'
1066            },
1067            withCredentials: true,
1068            data: JSON.stringify({'data': []})
1069          })
1070              .then(
1071                  function(response) {
1072                    var json = JSON.stringify(response.data);
1073                    var content = JSON.parse(json);
1074                    deferred.resolve(content);
1075                  },
1076                  function(error) {
1077                    console.log(error);
1078                    deferred.reject(error);
1079                  });
1080
1081          return deferred.promise;
1082        },
1083        activateImage: function(imageId) {
1084          var deferred = $q.defer();
1085          $http({
1086            method: 'PUT',
1087            url: DataService.getHost() + '/xyz/openbmc_project/software/' +
1088                imageId + '/attr/RequestedActivation',
1089            headers: {
1090              'Accept': 'application/json',
1091              'Content-Type': 'application/json'
1092            },
1093            withCredentials: true,
1094            data:
1095                JSON.stringify({'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
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        uploadImage: function(file) {
1111          return $http({
1112                   method: 'POST',
1113                   timeout: 5 * 60 * 1000,
1114                   url: DataService.getHost() + '/upload/image',
1115                   headers: {'Content-Type': 'application/octet-stream'},
1116                   withCredentials: true,
1117                   data: file
1118                 })
1119              .then(function(response) {
1120                return response.data;
1121              });
1122        },
1123        downloadImage: function(host, filename) {
1124          return $http({
1125                   method: 'POST',
1126                   url: DataService.getHost() +
1127                       '/xyz/openbmc_project/software/action/DownloadViaTFTP',
1128                   headers: {
1129                     'Accept': 'application/json',
1130                     'Content-Type': 'application/json'
1131                   },
1132                   withCredentials: true,
1133                   data: JSON.stringify({'data': [filename, host]}),
1134                   responseType: 'arraybuffer'
1135                 })
1136              .then(function(response) {
1137                return response.data;
1138              });
1139        },
1140        getServerInfo: function() {
1141          // TODO: openbmc/openbmc#3117 Need a way via REST to get
1142          // interfaces so we can get the system object(s) by the looking
1143          // for the system interface.
1144          return $http({
1145                   method: 'GET',
1146                   url: DataService.getHost() +
1147                       '/xyz/openbmc_project/inventory/system',
1148                   headers: {
1149                     'Accept': 'application/json',
1150                     'Content-Type': 'application/json'
1151                   },
1152                   withCredentials: true
1153                 })
1154              .then(function(response) {
1155                return response.data;
1156              });
1157        },
1158        getBMCTime: function() {
1159          return $http({
1160                   method: 'GET',
1161                   url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
1162                   headers: {
1163                     'Accept': 'application/json',
1164                     'Content-Type': 'application/json'
1165                   },
1166                   withCredentials: true
1167                 })
1168              .then(function(response) {
1169                return response.data;
1170              });
1171        },
1172        getHardwares: function(callback) {
1173          $http({
1174            method: 'GET',
1175            url: DataService.getHost() +
1176                '/xyz/openbmc_project/inventory/enumerate',
1177            headers: {
1178              'Accept': 'application/json',
1179              'Content-Type': 'application/json'
1180            },
1181            withCredentials: true
1182          }).then(function(response) {
1183            var json = JSON.stringify(response.data);
1184            var content = JSON.parse(json);
1185            var hardwareData = [];
1186            var keyIndexMap = {};
1187            var title = '';
1188            var data = [];
1189            var searchText = '';
1190            var componentIndex = -1;
1191            var tempParts = [];
1192
1193            function isSubComponent(key) {
1194              for (var i = 0; i < Constants.HARDWARE.parent_components.length;
1195                   i++) {
1196                if (key.split(Constants.HARDWARE.parent_components[i]).length ==
1197                    2)
1198                  return true;
1199              }
1200
1201              return false;
1202            }
1203
1204            function titlelize(title) {
1205              title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1206              for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
1207                   i++) {
1208                if (title.toLowerCase().indexOf(
1209                        (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
1210                  return title.toUpperCase();
1211                }
1212              }
1213
1214              return title;
1215            }
1216
1217            function camelcaseToLabel(obj) {
1218              var transformed = [], label = '', value = '';
1219              for (var key in obj) {
1220                label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
1221                if (obj[key] !== '') {
1222                  value = obj[key];
1223                  if (value == 1 || value == 0) {
1224                    value = (value == 1) ? 'Yes' : 'No';
1225                  }
1226                  transformed.push({key: label, value: value});
1227                }
1228              }
1229
1230              return transformed;
1231            }
1232
1233            function getSearchText(data) {
1234              var searchText = '';
1235              for (var i = 0; i < data.length; i++) {
1236                searchText += ' ' + data[i].key + ' ' + data[i].value;
1237              }
1238
1239              return searchText;
1240            }
1241
1242            for (var key in content.data) {
1243              if (content.data.hasOwnProperty(key) &&
1244                  key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
1245                data = camelcaseToLabel(content.data[key]);
1246                searchText = getSearchText(data);
1247                title = key.split('/').pop();
1248
1249                title = titlelize(title);
1250
1251                if (!isSubComponent(key)) {
1252                  hardwareData.push(Object.assign(
1253                      {
1254                        path: key,
1255                        title: title,
1256                        selected: false,
1257                        expanded: false,
1258                        search_text: title.toLowerCase() + ' ' +
1259                            searchText.toLowerCase(),
1260                        sub_components: [],
1261                        original_data: {key: key, value: content.data[key]}
1262                      },
1263                      {items: data}));
1264
1265                  keyIndexMap[key] = hardwareData.length - 1;
1266                } else {
1267                  var tempParts = key.split('/');
1268                  tempParts.pop();
1269                  tempParts = tempParts.join('/');
1270                  componentIndex = keyIndexMap[tempParts];
1271                  data = content.data[key];
1272                  data.title = title;
1273                  hardwareData[componentIndex].sub_components.push(data);
1274                  hardwareData[componentIndex].search_text +=
1275                      ' ' + title.toLowerCase();
1276
1277                  // Sort the subcomponents alphanumeric so they are displayed
1278                  // on the inventory page in order (e.g. core 0, core 1, core
1279                  // 2, ... core 12, core 13)
1280                  hardwareData[componentIndex].sub_components.sort(function(
1281                      a, b) {
1282                    return a.title.localeCompare(
1283                        b.title, 'en', {numeric: true});
1284                  });
1285                }
1286              }
1287            }
1288
1289            if (callback) {
1290              callback(hardwareData, content.data);
1291            } else {
1292              return {data: hardwareData, original_data: content.data};
1293            }
1294          });
1295        },
1296        deleteLogs: function(logs) {
1297          var defer = $q.defer();
1298          var promises = [];
1299
1300          function finished() {
1301            defer.resolve();
1302          }
1303
1304          logs.forEach(function(item) {
1305            promises.push($http({
1306              method: 'POST',
1307              url: DataService.getHost() +
1308                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1309                  '/action/Delete',
1310              headers: {
1311                'Accept': 'application/json',
1312                'Content-Type': 'application/json'
1313              },
1314              withCredentials: true,
1315              data: JSON.stringify({'data': []})
1316            }));
1317          });
1318
1319          $q.all(promises).then(finished);
1320
1321          return defer.promise;
1322        },
1323        resolveLogs: function(logs) {
1324          var defer = $q.defer();
1325          var promises = [];
1326
1327          function finished() {
1328            defer.resolve();
1329          }
1330
1331          logs.forEach(function(item) {
1332            promises.push($http({
1333              method: 'PUT',
1334              url: DataService.getHost() +
1335                  '/xyz/openbmc_project/logging/entry/' + item.Id +
1336                  '/attr/Resolved',
1337              headers: {
1338                'Accept': 'application/json',
1339                'Content-Type': 'application/json'
1340              },
1341              withCredentials: true,
1342              data: JSON.stringify({'data': '1'})
1343            }));
1344          });
1345
1346          $q.all(promises).then(finished);
1347
1348          return defer.promise;
1349        },
1350        getPowerConsumption: function() {
1351          return $http({
1352                   method: 'GET',
1353                   url: DataService.getHost() +
1354                       '/xyz/openbmc_project/sensors/power/total_power',
1355                   headers: {
1356                     'Accept': 'application/json',
1357                     'Content-Type': 'application/json'
1358                   },
1359                   withCredentials: true
1360                 })
1361              .then(
1362                  function(response) {
1363                    var json = JSON.stringify(response.data);
1364                    var content = JSON.parse(json);
1365
1366                    return getScaledValue(
1367                               content.data.Value, content.data.Scale) +
1368                        ' ' +
1369                        Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
1370                  },
1371                  function(error) {
1372                    if ('Not Found' == error.statusText) {
1373                      return Constants.POWER_CONSUMPTION_TEXT.notavailable;
1374                    } else {
1375                      throw error;
1376                    }
1377                  });
1378        },
1379        getPowerCap: function() {
1380          return $http({
1381                   method: 'GET',
1382                   url: DataService.getHost() +
1383                       '/xyz/openbmc_project/control/host0/power_cap',
1384                   headers: {
1385                     'Accept': 'application/json',
1386                     'Content-Type': 'application/json'
1387                   },
1388                   withCredentials: true
1389                 })
1390              .then(function(response) {
1391                return response.data;
1392              });
1393        },
1394        setPowerCapEnable: function(powerCapEnable) {
1395          return $http({
1396                   method: 'PUT',
1397                   url: DataService.getHost() +
1398                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCapEnable',
1399                   headers: {
1400                     'Accept': 'application/json',
1401                     'Content-Type': 'application/json'
1402                   },
1403                   withCredentials: true,
1404                   data: JSON.stringify({'data': powerCapEnable})
1405                 })
1406              .then(function(response) {
1407                return response.data;
1408              });
1409        },
1410        setPowerCap: function(powerCap) {
1411          return $http({
1412                   method: 'PUT',
1413                   url: DataService.getHost() +
1414                       '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCap',
1415                   headers: {
1416                     'Accept': 'application/json',
1417                     'Content-Type': 'application/json'
1418                   },
1419                   withCredentials: true,
1420                   data: JSON.stringify({'data': powerCap})
1421                 })
1422              .then(function(response) {
1423                return response.data;
1424              });
1425        },
1426        setHostname: function(hostname) {
1427          return $http({
1428                   method: 'PUT',
1429                   url: DataService.getHost() +
1430                       '/xyz/openbmc_project/network/config/attr/HostName',
1431                   headers: {
1432                     'Accept': 'application/json',
1433                     'Content-Type': 'application/json'
1434                   },
1435                   withCredentials: true,
1436                   data: JSON.stringify({'data': hostname})
1437                 })
1438              .then(function(response) {
1439                return response.data;
1440              });
1441        },
1442      };
1443      return SERVICE;
1444    }
1445  ]);
1446})(window.angular);
1447