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