Skip to content

Commit 79dad3c

Browse files
hiroshi-ikutaYusuke Hirota
authored andcommitted
Fixes #38498 - Fix incorrect Cycle power operation in Redfish provider
Bug #38498 mentions 3 power operation bugs in Redfish provider. This PR fixes wrong implementation of Cycle power operatoin: When user pushes Cycle button, Redfish provider does ForceRestart instead of PowerCycle. This PR makes powercycle method does 'PowerCycle'. Co-Authored-By: Vanou Ishii <[email protected]>, Yusuke Hirota <[email protected]>
1 parent 3d74a04 commit 79dad3c

File tree

6 files changed

+140
-3
lines changed

6 files changed

+140
-3
lines changed

modules/bmc/bmc_plugin.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Plugin < Proxy::Plugin
1111
capability 'shell'
1212
capability 'ssh'
1313
capability -> { Proxy::BMC::IPMI.providers_installed }
14+
capability 'poweraction_fix_3_16'
1415

1516
# Load IPMI to ensure the capabilities can be determined
1617
load_classes do

modules/bmc/redfish.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def poweroff(soft = false)
7171
end
7272

7373
def powercycle
74-
poweraction('ForceRestart')
74+
poweraction('PowerCycle')
7575
end
7676

7777
def poweron

test/bmc/bmc_api_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
require 'json'
33
require 'bmc/bmc_plugin'
44
require 'bmc/bmc_api'
5+
require 'bmc/redfish'
6+
require 'test/bmc/redfish_test_helper'
57

68
ENV['RACK_ENV'] = 'test'
79

@@ -13,6 +15,7 @@
1315

1416
class BmcApiTest < Test::Unit::TestCase
1517
include Rack::Test::Methods
18+
include RedfishTestHelper
1619

1720
def app
1821
Proxy::BMC::Api.new
@@ -25,6 +28,7 @@ def setup
2528
provider ||= ENV["ipmiprovider"] || "ipmitool"
2629
@args = { 'bmc_provider' => provider, 'blah' => 'test' }
2730
authorize user, pass
31+
mask_redfish_acceess
2832
end
2933

3034
def test_api_throws_401_error_when_auth_is_not_provided
@@ -572,6 +576,13 @@ def test_api_throws_400_error_when_get_sensors_action_list_execption
572576
assert_equal 400, last_response.status
573577
end
574578

579+
def test_api_calls_redfish_provider_cycle
580+
expect = Proxy::BMC::Redfish.any_instance.stubs(:powercycle)
581+
test_args = { 'bmc_provider' => 'redfish' }
582+
put "/#{@host}/chassis/power/cycle", test_args
583+
assert expect.once
584+
end
585+
575586
def test_api_can_pass_options_in_body
576587
Rubyipmi.stubs(:is_provider_installed?).returns(true)
577588
args = { 'bmc_provider' => 'freeipmi', :options => {:driver => 'lan20', :privilege => 'USER'} }.to_json

test/bmc/bmc_redfish_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require 'test_helper'
2+
require 'bmc/bmc_plugin'
3+
require 'bmc/redfish'
4+
require 'test/bmc/redfish_test_helper'
5+
require 'json'
6+
7+
class BmcRedfishTest < Test::Unit::TestCase
8+
include RedfishTestHelper
9+
10+
def setup
11+
@host = "host"
12+
@protocol = "https"
13+
mask_redfish_acceess(protocol: @protocol, host: @host)
14+
@args = { :username => "user", :password => "pass", :host => @host }
15+
@bmc = Proxy::BMC::Redfish.new(@args)
16+
end
17+
18+
def test_redfish_provider_cycle
19+
stub_request(:post, "#{@protocol}://#{@host}#{SYSTEM_DATA['Actions']['#ComputerSystem.Reset']['target']}").
20+
with(body: JSON.generate({"ResetType" => "PowerCycle"})).
21+
to_return(status: 200, body: JSON.generate({}))
22+
assert @bmc.powercycle
23+
end
24+
end

test/bmc/integration_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_features
1616
mod = response['bmc']
1717
refute_nil(mod)
1818
assert_equal('running', mod['state'], Proxy::LogBuffer::Buffer.instance.info[:failed_modules][:bmc])
19-
assert_equal(['redfish', 'shell', 'ssh'], mod['capabilities'])
19+
assert_equal(['poweraction_fix_3_16', 'redfish', 'shell', 'ssh'], mod['capabilities'])
2020

2121
assert_equal({}, mod['settings'])
2222
end
@@ -32,7 +32,7 @@ def test_features_with_freeipmi_installed
3232
mod = response['bmc']
3333
refute_nil(mod)
3434
assert_equal('running', mod['state'], Proxy::LogBuffer::Buffer.instance.info[:failed_modules][:bmc])
35-
assert_equal(['freeipmi', 'redfish', 'shell', 'ssh'], mod['capabilities'])
35+
assert_equal(['freeipmi', 'poweraction_fix_3_16', 'redfish', 'shell', 'ssh'], mod['capabilities'])
3636

3737
assert_equal({}, mod['settings'])
3838
end

test/bmc/redfish_test_helper.rb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
require 'json'
2+
3+
module RedfishTestHelper
4+
ROOT_DATA = {
5+
"Name" => "Redfish Server Test Mock",
6+
"Systems" => {
7+
"@odata.id" => "/redfish/v1/Systems",
8+
},
9+
"Managers" => {
10+
"@odata.id" => "/redfish/v1/Managers",
11+
},
12+
"@odata.id" => "/redfish/v1",
13+
}.freeze
14+
15+
SYSTEMS_DATA = {
16+
"@odata.id" => "/redfish/v1/Systems",
17+
"Members" => [
18+
{ "@odata.id" => "/redfish/v1/Systems/TESTSYSTEM" },
19+
],
20+
}.freeze
21+
22+
SYSTEM_DATA = {
23+
"@odata.id" => "/redfish/v1/Systems/TESTSYSTEM",
24+
"Manufacture" => "Server Vendor",
25+
"IndicatorLED" => "Off",
26+
"PowerState" => "On",
27+
"Boot" => {
28+
"BootSourceOverrideTarget" => "Pxe",
29+
},
30+
"Model" => "TestServer A",
31+
"SerialNumber" => "AA645",
32+
"AssetTag" => "ax",
33+
"Actions" => {
34+
"#ComputerSystem.Reset" => {
35+
"target" => "/redfish/v1/Systems/TESTSYSTEM/Actions/ComputerSystem.Reset",
36+
},
37+
},
38+
}.freeze
39+
40+
MANAGERS_DATA = {
41+
"@odata.id" => "/redfish/v1/Managers",
42+
"Members" => [
43+
{ "@odata.id" => "/redfish/v1/Managers/TESTBMC" },
44+
],
45+
}.freeze
46+
47+
MANAGER_DATA = {
48+
"@odata.id" => "/redfish/v1/Managers/TESTBMC",
49+
"FirmwareVersion" => "v1.0.0",
50+
"UUID" => "dff64837-f76b-40c2-b1a2-4717a78d828d",
51+
"EthernetInterfaces" => {
52+
"@odata.id" => "/redfish/v1/Managers/TESTBMC/EthernetInterfaces",
53+
},
54+
}.freeze
55+
56+
ETHERNET_INTERFACES_DATA = {
57+
"@odata.id" => "/redfish/v1/Managers/TESTBMC/EthernetInterfaces",
58+
"Members" => [
59+
{ "@odata.id" => "/redfish/v1/Managers/TESTBMC/EthernetInterfaces/BMC" },
60+
],
61+
}.freeze
62+
63+
BMC_NIC_DATA = {
64+
"@odata.id" => "/redfish/v1/Managers/TESTBMC/EthernetInterfaces/BMC",
65+
"MACAddress" => "52:54:00:01:23:45",
66+
"IPv4Addresses" => [
67+
{ "Address" => "192.168.124.123",
68+
"Gateway" => "192.168.124.1",
69+
"SubnetMask" => "255.255.255.0",
70+
"AddressOrigin" => "DHCP" },
71+
],
72+
"VLAN" => {
73+
"VLANEnable" => true,
74+
"VLANId" => 10,
75+
},
76+
}.freeze
77+
78+
def mask_redfish_acceess(protocol: "https", host: "host")
79+
# root
80+
stub_request(:get, "#{protocol}://#{host}#{ROOT_DATA['@odata.id']}").
81+
to_return(status: 200, body: JSON.generate(ROOT_DATA))
82+
# root.systems
83+
stub_request(:get, "#{protocol}://#{host}#{SYSTEMS_DATA['@odata.id']}").
84+
to_return(status: 200, body: JSON.generate(SYSTEMS_DATA))
85+
# root.system
86+
stub_request(:get, "#{protocol}://#{host}#{SYSTEM_DATA['@odata.id']}").
87+
to_return(status: 200, body: JSON.generate(SYSTEM_DATA))
88+
# root.managers
89+
stub_request(:get, "#{protocol}://#{host}#{MANAGERS_DATA['@odata.id']}").
90+
to_return(status: 200, body: JSON.generate(MANAGERS_DATA))
91+
# root.manager
92+
stub_request(:get, "#{protocol}://#{host}#{MANAGER_DATA['@odata.id']}").
93+
to_return(status: 200, body: JSON.generate(MANAGER_DATA))
94+
# root.manager.ethernetinterfaces
95+
stub_request(:get, "#{protocol}://#{host}#{ETHERNET_INTERFACES_DATA['@odata.id']}").
96+
to_return(status: 200, body: JSON.generate(ETHERNET_INTERFACES_DATA))
97+
# bmcnic
98+
stub_request(:get, "#{protocol}://#{host}#{BMC_NIC_DATA['@odata.id']}").
99+
to_return(status: 200, body: JSON.generate(BMC_NIC_DATA))
100+
end
101+
end

0 commit comments

Comments
 (0)