Learn › BMC & Server Management › Modern Management
Stop reading, start doing: discover the Redfish Reset action, POST a graceful shutdown, watch PowerState flip over the API, bring the server back, and cross-check it inside the Dell shell.
It is 21:55 at the DC-EAST facility in Ashburn, Virginia. Maintenance window MW-2026-0703 opens at 22:00: a firmware update for the Dell PowerEdge R750xs in Bay 14, Row 7. The update needs the host taken all the way down, cleanly, and brought back up when it is done, with proof at every stage.
You will not leave your chair. Every move happens from your workstation dc-east-ws01, over the management network, against the machine's BMC.
Here is what makes tonight different. All module long you have been reading this machine over Redfish: inventory, sensors, health. Reading never changed anything. Tonight you send the request that changes the machine.
This is a Practice Zone. The diagrams and practice terminals below react to you: click the boxes, flip the switches, type the commands. The real machine comes at the end, under Ready to practice.
Every Redfish request you have sent so far used the HTTP verb GET. GET has a contract: it asks, it never changes. That contract is why a monitoring system can poll thousands of servers every minute without fear.
Actions live behind a different verb. POST tells the server: do something. Same API, same URLs, same credentials. The verb, not the address, is what separates looking from touching.
{ "height": 340, "caption": "The verb decides. Flip it and watch which path lights up.", "nodes": [ { "id": "you", "label": "You (ops)", "kind": "admin", "x": 0, "y": 170, "detail": "dc-east-ws01. Every request rides HTTP with basic auth to the BMC's Redfish service." }, { "id": "api", "label": "Redfish service :5000", "kind": "bmc", "x": 300, "y": 170, "detail": "The BMC's REST API. Every resource is a URL. What happens to it depends entirely on the verb you send." }, { "id": "pstate", "label": "PowerState record", "kind": "sensor", "x": 620, "y": 40, "detail": "The state GET reports. Reading it changes nothing, no matter how often you ask." }, { "id": "rails", "label": "Power rails", "kind": "psu", "x": 620, "y": 300, "detail": "What a Reset action actually touches. Only a POST reaches this far." } ], "edges": [ { "from": "you", "to": "api", "label": "HTTP + Basic auth", "kind": "mgmt" }, { "from": "api", "to": "pstate", "label": "GET: read only", "kind": "plain" }, { "from": "api", "to": "rails", "label": "POST Reset: acts", "kind": "power" } ], "toggle": { "label": "Request verb:", "on": "GET (safe read)", "off": "POST (performs the action)", "dimOn": ["rails", "e:api-rails"], "dimOff": ["pstate", "e:api-pstate"] } }
>>> Nothing. GET is read-only by contract, which is exactly why monitoring can hammer it around the clock. Change lives behind POST, and that separation is the whole safety model of a REST API.
Prove the reading half one more time. $BMC_IP is preset in the lab, credentials ADMIN / ADMIN. This is the system resource for the R750xs, the machine you will act on at 22:00.
prompt: ops@dc-east-ws01:~$ answer: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems/1 output: {"@odata.id":"/redfish/v1/Systems/1","@odata.type":"#ComputerSystem.v1_16_0.ComputerSystem","Actions":{"#ComputerSystem.Reset":{"[email protected]":["On","ForceOff","ForceRestart","GracefulShutdown","PushPowerButton"],"target":"/redfish/v1/Systems/1/Actions/ComputerSystem.Reset"}},"Bios":{"@odata.id":"/redfish/v1/Systems/1/Bios"},"BiosVersion":"1.9.1","Boot":{"BootSourceOverrideEnabled":"Disabled","BootSourceOverrideMode":"UEFI","BootSourceOverrideTarget":"None"},"Description":"Main Server","HostName":"bay14-r750xs","Id":"1","Links":{"Chassis":[{"@odata.id":"/redfish/v1/Chassis/1"}],"ManagedBy":[{"@odata.id":"/redfish/v1/Managers/1"}]},"Manufacturer":"Dell Inc.","Memory":{"@odata.id":"/redfish/v1/Systems/1/Memory"},"MemorySummary":{"Status":{"Health":"OK","State":"Enabled"},"TotalSystemMemoryGiB":128},"Model":"PowerEdge R750xs","Name":"System","PowerState":"On","ProcessorSummary":{"CoreCount":32,"Count":2,"Model":"Intel Xeon Gold 5416S","Status":{"Health":"OK","State":"Enabled"}},"Processors":{"@odata.id":"/redfish/v1/Systems/1/Processors"},"SKU":"SVC1234567","SerialNumber":"SVC1234567","Status":{"Health":"OK","State":"Enabled"},"Storage":{"@odata.id":"/redfish/v1/Systems/1/Storage"}} hint: curl, the silent flag, -u with the ADMIN:ADMIN credentials, then the Systems/1 URL on port 5000.
That is the whole resource in one breath: machine-format JSON, keys sorted, not a line break in sight. PowerState is in there, and so is the block that matters tonight. Finding either by eye is misery, which is exactly why the next tool exists.
Every Redfish resource that can DO something advertises it in an Actions object. Two parts matter:
Cut the Actions block out of the resource with jq, the JSON field tool. Reading the command: -o system.json writes the reply to a file instead of the screen, && runs the next command only if the first succeeded, and jq '.Actions' system.json pulls just that block out of your copy.
prompt: ops@dc-east-ws01:~$ answer: curl -s -u ADMIN:ADMIN -o system.json http://$BMC_IP:5000/redfish/v1/Systems/1 && jq '.Actions' system.json ||| curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems/1 -o system.json && jq '.Actions' system.json ||| curl -s -u ADMIN:ADMIN -o system.json http://$BMC_IP:5000/redfish/v1/Systems/1 && jq .Actions system.json output: { "#ComputerSystem.Reset": { "[email protected]": [ "On", "ForceOff", "ForceRestart", "GracefulShutdown", "PushPowerButton" ], "target": "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset" } } hint: The same curl as before, plus -o system.json to save the reply, then && jq '.Actions' system.json to read the block from the copy.
On the floor you will usually chain the two with a pipe instead: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems/1 | jq '.Actions'. Same readout, no file. Keep the file habit tonight anyway; evidence is half this job.
Now read the list like an operator. One action, #ComputerSystem.Reset. One target URI. Five allowable values. And notice what is NOT there: GracefulRestart, a verb plenty of real iDRACs do offer. Never memorize reset verbs. Read AllowableValues on the controller in front of you, every time.
>>> A 400 Bad Request, and the error body names the values this controller does accept. GracefulRestart is real Redfish and plenty of iDRACs offer it, but it is not in THIS controller's list. The API polices its own contract, which is why professionals read AllowableValues instead of memorizing verbs.
Here is the action POST, read left to right:
-X POST picks the verb. This is the part that acts.-H 'Content-Type: application/json' declares the body format. The API refuses to parse the body without it.-d '{"ResetType": "GracefulShutdown"}' is the parameter, spelled exactly as AllowableValues lists it.-w '%{http_code}\n' makes curl print the HTTP status code after the reply. You are about to see why that matters.prompt: ops@dc-east-ws01:~$ answer: curl -s -w '%{http_code}\n' -u ADMIN:ADMIN -X POST -H 'Content-Type: application/json' -d '{"ResetType": "GracefulShutdown"}' http://$BMC_IP:5000/redfish/v1/Systems/1/Actions/ComputerSystem.Reset ||| curl -s -w '%{http_code}\n' -u ADMIN:ADMIN -X POST -H 'Content-Type: application/json' -d '{"ResetType":"GracefulShutdown"}' http://$BMC_IP:5000/redfish/v1/Systems/1/Actions/ComputerSystem.Reset output: 204 hint: Type it exactly as shown above: -X POST, the Content-Type header, the ResetType body in single quotes, then the target URI.
204 No Content means success with nothing to say: the action was accepted and the reply has no body. Without -w, this command prints nothing at all, and silence is a terrible receipt. The status code is your receipt. The state you read back is your proof.
prompt: ops@dc-east-ws01:~$ answer: curl -s -u ADMIN:ADMIN -o system.json http://$BMC_IP:5000/redfish/v1/Systems/1 && jq -r '.PowerState' system.json ||| curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems/1 -o system.json && jq -r '.PowerState' system.json ||| curl -s -u ADMIN:ADMIN -o system.json http://$BMC_IP:5000/redfish/v1/Systems/1 && jq -r .PowerState system.json output: Off hint: Fetch a fresh copy with -o system.json, then && jq -r '.PowerState' system.json. The -r flag prints the bare value without quotes.
Off. The machine went down because you asked it to, over HTTP, and the API will tell that truth to anyone who asks.
One honest note about this emulator. It applies the transition instantly: a physical R750xs drains a graceful shutdown for 30 to 60 seconds while the OS halts, and you poll PowerState until it settles. It speaks HTTP on port 5000 with basic auth so every moving part stays visible; production iDRACs serve Redfish over HTTPS on port 443, with session tokens as the norm. And its IPMI daemon keeps a separate power state: an ipmitool chassis readout will not track Redfish resets here, so use the Dell shell when you cross-check this change. On production iDRAC firmware, every interface reads the same state.
Five allowable values, two families:
Flip the host OS below and watch which family survives.
{ "height": 340, "caption": "Graceful verbs need the OS. Force verbs do not.", "nodes": [ { "id": "you", "label": "You (ops)", "kind": "admin", "x": 0, "y": 170 }, { "id": "bmc", "label": "BMC", "kind": "bmc", "x": 300, "y": 170, "detail": "Receives the POST and decides which mechanism the ResetType uses: a polite request to the OS, or the rails." }, { "id": "os", "label": "Host OS", "kind": "host", "x": 620, "y": 40, "detail": "Graceful verbs need it awake and cooperative. It flushes disks, stops services, then halts." }, { "id": "rails", "label": "Power rails", "kind": "psu", "x": 620, "y": 300, "detail": "Force verbs act here. No OS involvement, no cleanup, no waiting." } ], "edges": [ { "from": "you", "to": "bmc", "label": "POST ComputerSystem.Reset", "kind": "oob" }, { "from": "bmc", "to": "os", "label": "GracefulShutdown: asks the OS", "kind": "inband" }, { "from": "os", "to": "rails", "label": "clean halt, then power drops", "kind": "plain" }, { "from": "bmc", "to": "rails", "label": "ForceOff / On / ForceRestart", "kind": "power" } ], "toggle": { "label": "Host OS:", "on": "Responsive", "off": "Hung", "dimOff": ["os", "e:bmc-os", "e:os-rails"] } }
>>> ForceOff. GracefulShutdown is a request to the OS, and a hung OS answers nothing. Force verbs act at the hardware level through the BMC, no OS required. That is the escalation ladder: ask nicely first, pull the rails when the OS cannot answer.
That pairing is the operational habit. Try graceful first. Escalate to force when the OS cannot cooperate. A force verb on a healthy machine throws away clean filesystem state for no reason.
Tonight the operating system cooperated. One POST, one 204, PowerState: Off. Now plan for the night it goes differently.
Picture the same window next quarter. You send GracefulShutdown, you get your 204, and five minutes later the read-back still says On. Nothing is broken. The 204 said the controller accepted your request. It never said the OS obeyed, and a wedged kernel answers nothing.
That is why the ladder has four rungs: ask, wait, verify, force. You have climbed the first three all night. Here is the fourth.
ForceOff is the same request with one word changed. Send it right now, against the machine you already took down, and read the code.
prompt: ops@dc-east-ws01:~$ answer: curl -s -w '%{http_code}\n' -u ADMIN:ADMIN -X POST -H 'Content-Type: application/json' -d '{"ResetType": "ForceOff"}' http://$BMC_IP:5000/redfish/v1/Systems/1/Actions/ComputerSystem.Reset ||| curl -s -w '%{http_code}\n' -u ADMIN:ADMIN -X POST -H 'Content-Type: application/json' -d '{"ResetType":"ForceOff"}' http://$BMC_IP:5000/redfish/v1/Systems/1/Actions/ComputerSystem.Reset output: 204 hint: The same POST shape as the graceful shutdown, with ForceOff as the ResetType in the body.
204, and nothing moved. The box was already off and it is still off. That non-event is the most useful thing this command could have shown you.
ForceOff names a destination, not a change. It drives the machine to off and leaves it there. Run it once, run it five times, run it against a box that is already down, and the machine ends in the same place every time. That property has a name: idempotent. It is what makes a verb safe to put in code that might retry.
On, ForceRestart and GracefulShutdown all name destinations too. Then there is the fifth value, and it is the odd one out.
PushPowerButton does not name a destination. It presses the front-panel button, and a button toggles. Off becomes on. On becomes a shutdown request. Send it twice and the machine is back exactly where it started. Send it once against a state you guessed wrong and it does the opposite of what you meant.
Now read that as an operator. Say your script retries a request that timed out, and the first attempt actually landed before the network ate the reply. ForceOff would shrug: the machine is already off, it stays off. PushPowerButton has just powered a server back on in the middle of a firmware flash.
So the rule is short. Read PowerState, then act. Never put PushPowerButton in a retry loop.
| ResetType | Needs the OS | Ends at | Reach for it when |
|---|---|---|---|
GracefulShutdown | Yes | Off | The OS is healthy and you want a clean stop |
On | No | On | The box is down and you want it back |
ForceOff | No | Off | The OS is hung or gone and the box must be down now |
ForceRestart | No | On | The OS is hung and you need the box back, not down |
PushPowerButton | Sometimes | The opposite of now | You are emulating a physical finger, state already read |
ForceRestart is the row people skip, and it is the row that saves somebody a drive to Ashburn. A hung hypervisor at 03:00 does not need to be off, it needs to be back. ForceOff leaves you with a dark box and a second request still to send, at 03:00, hoping the power-on lands. ForceRestart cuts and reapplies the rails in one stroke, and the machine cold-starts through its full self-test.
Everything in this step is real and it really moves power. On the live machine ahead, your work order needs the R750xs finishing on. If you experiment with a force verb out of order, read PowerState back, bring the box up with the On action, and recapture your evidence before you close DC-EAST-WO-1014.
Your POST changed one thing: the controller's record of the machine's power state. The Redfish API is one door into that record. The Dell shell you met in your first work order is another. A good operator confirms a change through a second channel before closing the order.
{ "height": 340, "caption": "One controller state. Your POST moved it; both doors report it.", "nodes": [ { "id": "you", "label": "You (ops)", "kind": "admin", "x": 0, "y": 170 }, { "id": "rf", "label": "Redfish API (HTTP :5000)", "kind": "net", "x": 300, "y": 40, "detail": "The door you used tonight. GET reads the record, POST Reset rewrites it." }, { "id": "shell", "label": "Dell shell (SSH)", "kind": "net", "x": 300, "y": 300, "detail": "The door from your first work order. getsysinfo reads the very same controller state." }, { "id": "bmcstate", "label": "BMC controller state", "kind": "bmc", "x": 620, "y": 170, "detail": "One source of truth for power state. Every management interface is a view of it." }, { "id": "host", "label": "Host server", "kind": "host", "x": 920, "y": 170, "detail": "The R750xs the state describes. It dims when off; the BMC never sleeps." } ], "edges": [ { "from": "you", "to": "rf", "label": "GET / POST", "kind": "oob" }, { "from": "you", "to": "shell", "label": "ssh admin@$BMC_IP", "kind": "oob" }, { "from": "rf", "to": "bmcstate", "label": "reads + writes", "kind": "plain" }, { "from": "shell", "to": "bmcstate", "label": "reads", "kind": "plain" }, { "from": "bmcstate", "to": "host", "label": "controls power", "kind": "power" } ], "toggle": { "label": "Server power:", "on": "Powered ON", "off": "Powered OFF", "dimOff": ["host"] } }
First, finish the round trip: the same POST you just learned, with {"ResetType": "On"} as the body, brings the box back, and the same read-back shows PowerState flip to On. You will do exactly that on the real machine.
Then check through the second door. SSH into the BMC the way you did in first contact, sshpass -p ADMIN ssh -o StrictHostKeyChecking=no admin@$BMC_IP, and land at the /admin1-> prompt. The readout command must be typed at that prompt, live inside the session.
prompt: /admin1-> answer: getsysinfo output:
System Information ============================================================ System Model: PowerEdge R750xs Manufacturer: Dell Inc. Service Tag: SVC1234567 Hostname: bay14-r750xs Power State: ON
Processor Information ------------------------------------------------------------ CPU Count: 2 CPU Model: Intel Xeon Gold 5416S
Memory Information ------------------------------------------------------------ Total Memory: 128 GB DIMM Slots Used: 4
Firmware Information ------------------------------------------------------------ BIOS Version: 1.9.1 BMC Version: 6.10.30.00
Network Information ------------------------------------------------------------ BMC IP Address: 10.100.7.2 BMC MAC Address: D4:AE:52:B1:23:45 hint: One word, the Dell readout command from your first work order.
Power State: ON, from inside the controller, matching what the API reports. Same record, different door. Cross-checked changes are closed changes.
The window is open. Work Order DC-EAST-WO-1014, six objectives, on the real machine. $BMC_IP is preset
Practice Redfish Actions in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.