Learn › BMC & Server Management › Modern Management
Redfish turns hardware inventory into structured JSON. Walk the Systems, Chassis, and Managers tree with curl, extract exactly the fields the NOC asked for with jq, and file a machine-readable intake record for the Bay 14 PowerEdge.
It is 09:40 at the DC-EAST facility in Ashburn, Virginia. The asset team just bounced your teammate's intake record for the Dell PowerEdge R750xs in Bay 14, Row 7. He sent them a terminal screenshot of raw hardware output. They sent it back with one line: "We need fields, not pictures."
Their list is exact: model, serial number, BIOS version, power state, PSU capacity, and the BMC's own firmware. Work Order DC-EAST-WO-1012 is now yours: pull the inventory over Redfish, the BMC's web API, and hand back exactly those fields.
This is a Practice Zone. The diagrams below react to you: click the boxes, flip the switches. The real machine comes at the end, under Ready to practice.
You already know one road. IPMI can dump FRU (Field Replaceable Unit) data: ipmitool -I lanplus -C 3 -H $BMC_IP -U ADMIN -P ADMIN fru print. Run that against real hardware and you get a wall of human-readable text: inconsistent labels, vendor quirks, hex padding. A person can read it. A script cannot, not without fragile text surgery that breaks on the next vendor.
Redfish is the modern answer: the BMC serves the same facts as a web API. You ask over HTTP, it answers in JSON (JavaScript Object Notation), structured data with named fields like "SerialNumber": "SVC1234567". A program asks for a field by name and gets the value. No parsing, no prayer.
Trace both roads to the same destination, then flip the collection method.
{ "height": 380, "caption": "Same destination, two very different roads. Flip the method.", "nodes": [ { "id": "you", "label": "You", "kind": "admin", "x": 0, "y": 170, "detail": "You at dc-east-ws01, holding the NOC field list for Bay 14, Row 7." }, { "id": "ipmi", "label": "ipmitool fru", "kind": "nic", "x": 230, "y": 40, "detail": "IPMI FRU: raw fields, vendor quirks, hex padding. No structure a script can trust." }, { "id": "wall", "label": "Wall of text", "kind": "sensor", "x": 470, "y": 40, "detail": "Human-readable, machine-hostile. Parsing this means fragile grep and prayer." }, { "id": "rf", "label": "GET Systems/1", "kind": "bmc", "x": 230, "y": 300, "detail": "One HTTP call returns the same facts as named JSON fields." }, { "id": "json", "label": "Structured JSON", "kind": "net", "x": 470, "y": 300, "detail": "Model, SerialNumber, BiosVersion: keys a program can address directly." }, { "id": "jqn", "label": "jq", "kind": "nic", "x": 690, "y": 300, "detail": "Field extraction in one flag: -r for raw text, @csv for the database." }, { "id": "db", "label": "Asset database", "kind": "net", "x": 920, "y": 170, "detail": "The NOC intake record for Bay 14. It imports fields, not screenshots." } ], "edges": [ { "from": "you", "to": "ipmi", "kind": "oob" }, { "from": "ipmi", "to": "wall", "kind": "plain" }, { "from": "wall", "to": "db", "label": "hand copying, typos", "kind": "plain" }, { "from": "you", "to": "rf", "kind": "mgmt" }, { "from": "rf", "to": "json", "kind": "plain" }, { "from": "json", "to": "jqn", "kind": "plain" }, { "from": "jqn", "to": "db", "label": "clean import", "kind": "mgmt" } ], "toggle": { "label": "Collection method:", "on": "Redfish + jq", "off": "IPMI FRU", "dimOn": ["ipmi", "wall", "e:you-ipmi", "e:ipmi-wall", "e:wall-db"], "dimOff": ["rf", "json", "jqn", "e:you-rf", "e:rf-json", "e:json-jqn", "e:jqn-db"] } }
>>> JSON has named fields a program addresses directly: ask for .SerialNumber, get the serial. FRU text needs hand-built parsing that breaks per vendor, per firmware, per field. That difference is the whole reason this work order says Redfish.
Every Redfish BMC serves a service root at /redfish/v1/: a table of contents that names every drawer in the filing cabinet. Three drawers matter today:
Every answer contains @odata.id links naming where to go next. You never guess a URL; the API hands you the map as you walk it. Click through the tree, then flip the toggle to see which drawers answer which question.
{ "height": 420, "caption": "The Redfish resource tree. Click a drawer, then flip who the question is about.", "nodes": [ { "id": "you", "label": "You", "kind": "admin", "x": 0, "y": 190, "detail": "You at dc-east-ws01, holding the NOC field list." }, { "id": "api", "label": "Redfish API :5000", "kind": "bmc", "x": 210, "y": 190, "detail": "The BMC answering HTTP on the management network." }, { "id": "root", "label": "/redfish/v1/", "kind": "net", "x": 430, "y": 190, "detail": "The service root: a table of contents that names every drawer." }, { "id": "sys", "label": "Systems/1", "kind": "host", "x": 670, "y": 40, "detail": "The computer: model, serial, BIOS version, power state, CPU and memory summaries." }, { "id": "cha", "label": "Chassis/1", "kind": "net", "x": 670, "y": 190, "detail": "The physical box: rack-mount sheet metal, part number, links to thermal and power." }, { "id": "mgr", "label": "Managers/1", "kind": "bmc", "x": 670, "y": 340, "detail": "The BMC describing itself: ManagerType BMC, its own firmware 6.10.30.00." }, { "id": "pwr", "label": "Chassis/1/Power", "kind": "psu", "x": 920, "y": 120, "detail": "PSU inventory: two Dell DPS-1100FB, 1100 W each, with their own firmware." }, { "id": "thm", "label": "Chassis/1/Thermal", "kind": "sensor", "x": 920, "y": 260, "detail": "Temperatures and fans. That is the next lab." } ], "edges": [ { "from": "you", "to": "api", "label": "GET + Basic auth", "kind": "mgmt" }, { "from": "api", "to": "root", "kind": "mgmt" }, { "from": "root", "to": "sys", "label": "@odata.id", "kind": "plain" }, { "from": "root", "to": "cha", "label": "@odata.id", "kind": "plain" }, { "from": "root", "to": "mgr", "label": "@odata.id", "kind": "plain" }, { "from": "cha", "to": "pwr", "kind": "power" }, { "from": "cha", "to": "thm", "kind": "plain" } ], "toggle": { "label": "The NOC asks about:", "on": "The server (host)", "off": "The BMC itself", "dimOn": ["mgr", "e:root-mgr"], "dimOff": ["sys", "cha", "pwr", "thm", "e:root-sys", "e:root-cha", "e:cha-pwr", "e:cha-thm"] } }
>>> BiosVersion is the host's firmware, the code the big server boots with. The BMC is a separate computer, and it describes itself under Managers: its FirmwareVersion is the BMC's own. Two computers in one box, two firmware versions. Auditors ask about both, separately.
One Redfish call has five moving parts: a client, credentials, a resource URL, a JSON answer, and whatever you do with that answer. Flip the credentials off and watch what survives.
{ "height": 300, "caption": "Five moving parts in one call. Flip the credentials and see what survives.", "nodes": [ { "id": "you", "label": "You", "kind": "admin", "x": 0, "y": 170 }, { "id": "curl", "label": "curl -s -u", "kind": "nic", "x": 200, "y": 170, "detail": "The HTTP client, presenting ADMIN:ADMIN as Basic auth on every request." }, { "id": "door", "label": "Auth check", "kind": "bmc", "x": 410, "y": 170, "detail": "The emulated iDRAC verifies credentials on every request. Without them it answers 401 AccessDenied and nothing else." }, { "id": "res", "label": "Systems/1 JSON", "kind": "host", "x": 630, "y": 170, "detail": "The full ComputerSystem resource: 30+ fields of structured JSON." }, { "id": "jq", "label": "jq filter", "kind": "nic", "x": 850, "y": 170, "detail": "The field scalpel: {Model, SerialNumber} keeps only the fields you name." }, { "id": "file", "label": "~/system-summary.csv", "kind": "net", "x": 1060, "y": 170, "detail": "Evidence on file, ready for the asset database." } ], "edges": [ { "from": "you", "to": "curl", "kind": "plain" }, { "from": "curl", "to": "door", "label": "GET /redfish/v1/Systems/1", "kind": "mgmt" }, { "from": "door", "to": "res", "label": "200 OK", "kind": "oob" }, { "from": "res", "to": "jq", "label": "pipe", "kind": "plain" }, { "from": "jq", "to": "file", "label": "> redirect", "kind": "plain" } ], "toggle": { "label": "Credentials:", "on": "-u ADMIN:ADMIN", "off": "none", "dimOff": ["res", "jq", "file", "e:door-res", "e:res-jq", "e:jq-file"] } }
Without -u ADMIN:ADMIN the BMC answers 401 AccessDenied and nothing else. Every request under /redfish/v1/ is checked; there is no anonymous read.
Now make your first call for real. $BMC_IP is preset in the lab, and this BMC serves Redfish on port 5000. Ask the Systems drawer what it holds. Type: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems
prompt: ops@dc-east-ws01:~$ answer: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems output: {"@odata.id":"/redfish/v1/Systems","@odata.type":"#ComputerSystemCollection.ComputerSystemCollection","Members":[{"@odata.id":"/redfish/v1/Systems/1"}],"[email protected]":1,"Name":"Computer System Collection"} hint: Type it exactly: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems
Read the command left to right: curl is the HTTP client, -s silences the progress meter, -u ADMIN:ADMIN sends the credentials as Basic auth, and the URL names the resource. Now read the reply: [email protected] says this BMC fronts exactly one computer system, and Members hands you its address, /redfish/v1/Systems/1. That is the hypermedia walk from the diagram: every answer names the next URL.
But notice the format. The whole answer arrived as one solid line of machine JSON. Real, correct, and nearly unreadable. Fixing that is the next step.
The BMC in this lab is a standards-faithful Redfish emulator: real JSON, real Basic auth enforcement, so every curl and jq keystroke here transfers to a physical iDRAC or iLO unchanged. Two honest differences: a production iDRAC serves HTTPS on port 443 (not HTTP on 5000) and also offers session-token logins, and it exposes deeper per-DIMM and per-drive detail where this emulator keeps component data at the summary level.
jq is the tool that turns a wall of JSON into exactly what was asked. First, put the full system record where jq can reach it: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems/1 -o system.json. The -o flag writes the reply body to a file and prints nothing; the file is the result.
Five jq moves cover this work order:
jq . system.json pretty-prints everything, your first look at any resource.jq '.Model' system.json pulls one field by name. Nested paths chain with dots: .MemorySummary.TotalSystemMemoryGiB.jq '{Model, SerialNumber}' system.json builds a smaller object holding just the named fields.jq -r outputs raw text instead of JSON: no quotes, ready for files and scripts.@csv turns a list of fields into one database-ready CSV line.Four of the NOC's six fields live in the record you just saved. Aim the scalpel at it. Type: jq '{Model, SerialNumber, BiosVersion, PowerState}' system.json
prompt: ops@dc-east-ws01:~$ answer: jq '{Model, SerialNumber, BiosVersion, PowerState}' system.json output: { "Model": "PowerEdge R750xs", "SerialNumber": "SVC1234567", "BiosVersion": "1.9.1", "PowerState": "On" } hint: jq, then a filter in single quotes: curly braces listing the four field names separated by commas, then the filename system.json.
Thirty-plus fields in, four fields out, and every one the asset team asked for by name. On the real floor you will usually skip the intermediate file and chain the calls with a shell pipe, which hands curl's output straight to jq. This one-liner produces the database import line:
curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/Systems/1 | jq -r '[.Model, .SerialNumber, .BiosVersion, .PowerState] | @csv'
"PowerEdge R750xs","SVC1234567","1.9.1","On"
Inside jq, the square brackets collect the four values into a list and @csv formats that list as one comma-separated line. The -r flag matters more than it looks: @csv produces a JSON string, and without -r, jq prints it AS JSON.
One more scalpel move for later: inside a quoted jq string, \(.Field) splices a value into your own text:
jq -r '"\(.Model) serial \(.SerialNumber)"' system.json
PowerEdge R750xs serial SVC1234567
>>> Without -r the line prints as a JSON string: outer quotes around everything and a backslash before every inner quote. The database import would choke on it. -r means raw: hand me the text itself. For output headed to files and other systems, -r is almost always what you want.
The NOC list has two items left, and neither lives in Systems.
PSU capacity lives in the Chassis drawer, at Chassis/1/Power. Its .PowerSupplies field is an array, a JSON list holding one entry per physical supply. Name the field to see the whole list, or add [] to iterate: .PowerSupplies[] streams each PSU one at a time so you can project fields from each. This box runs two Dell DPS-1100FB units, 1100 W apiece, and each reports its own FirmwareVersion and live output wattage.
BMC firmware lives in the Managers drawer. Managers/1 is the controller describing itself: ManagerType says BMC, Model names the iDRAC, and FirmwareVersion is the BMC's own code level, 6.10.30.00 on this machine.
Three different firmware versions live in this one box: the PSU firmware in Chassis/1/Power, the host BIOS in Systems/1, and the BMC firmware in Managers/1. Auditors ask about each separately, and mixing them up is the classic intake mistake. The drawer you found the field in tells you whose firmware you are reading.
Time to do it for real. On the machine you are about to open, close out Work Order DC-EAST-WO-1012 by filing the intake record for Bay 14, Row 7. The BMC address is preset in $BMC_IP, credentials ADMIN / ADMIN, Redfish on port 5000.
Six objectives close this work order:
1. Walk the collection. Ask the Systems drawer for its member list and see how many computer systems this BMC fronts. 2. Pull the full record. Capture the entire system resource into ~/system.json. 3. Extract the system fields. The four that live in the system record (model, serial, BIOS version, power state) as one line in ~/system-summary.csv. 4. Inventory the power supplies. Both units, with capacities, into ~/psu-inventory.json. 5. Identify the manager. The BMC's own type, model, and firmware into ~/bmc-manager.json. 6. The challenge. The capacity planner wants one line in ~/noc-report.txt stating total memory plus the CPU count and model. No structure given.
Here is the deal: the workspace shows no commands. It hands you one objective at a time, and you recall the move. That recall is the whole point; it is how last hour's reading becomes your skill.
Stuck is normal. Hit Request a signal on any objective for a nudge, or ask Daemon. It knows exactly which task you are on and will nudge, not spoil.
Your workstation dc-east-ws01 is booting in the bay below, with the Dell BMC beside it on the management bridge. $BMC_IP is preset, credentials ADMIN / ADMIN, Redfish on port 5000. Launch it and file the record.
Practice Redfish Inventory in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.