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