LearnBMC & Server ManagementOpenBMC on Real Firmware

The Real Service Root

Point curl at real OpenBMC firmware and read what a BMC actually exposes. Identify the service root schema and protocol version, follow the OData links to the ComputerSystem and Chassis objects, and pull the boot targets this BMC can force, all off bmcweb running on an emulated AST2500 service processor.

The machine nobody can name

Bay 3 holds a server that did not come from Dell or HPE. There is no iDRAC on it and no iLO. The rack label says the service processor answers on the management network, and that is the whole of the documentation you were handed.

You have an address, a user name, and a password. One request is about to tell you what that firmware is, which version of which standard it speaks, and every part of the machine it is willing to let you touch.

Everything in this module runs against real OpenBMC firmware: the image the OpenBMC project publishes, booted on an emulated AST2500 service processor. The tools are the same tools. The answers come out of the firmware, not out of a script we wrote.

What is answering you

OpenBMC is open source firmware for baseboard management controllers. Meta, Google, Microsoft and IBM ship it on production fleets. Instead of a vendor shell that only that vendor understands, it serves a standard API.

That API is Redfish: a management interface built on ordinary HTTPS and JSON. You ask for a URL, you get back a JSON object. No special client, no vendor SDK.

The program serving it on this BMC is called bmcweb. It is a real web server running on the service processor, and it answers on port 443 like any other HTTPS service.

The one URL you always start from

Every Redfish implementation on earth answers at the same first address: /redfish/v1/. That object is the service root, and it is the index of the whole tree.

Redfish is built on OData, a convention for linking resources. Two field names carry it. @odata.id is a resource address, and @odata.type says what kind of thing you are looking at, including its schema version.

Your endpoint is already exported in your shell as $BMC_URL. The certificate is self-signed, so curl needs -k to accept it, and -s keeps the progress meter out of your output.

Ask the service root what it is.

prompt: ops@dc-east-fw01:~$ answer: curl -sk -u root:0penBmc "$BMC_URL/redfish/v1/" | jq -r '."@odata.type"' ||| curl -sk -u root:0penBmc $BMC_URL/redfish/v1/ | jq -r '."@odata.type"' output: #ServiceRoot.v1_15_0.ServiceRoot hint: curl -sk -u root:0penBmc then "$BMC_URL/redfish/v1/", a padded pipe, then jq -r on the "@odata.type" field

Read that answer slowly. #ServiceRoot is the schema. v1_15_0 is the version of that schema this firmware implements. You did not have to know the vendor to ask, and you did not have to know the vendor to understand the reply.

jq is the JSON field scalpel. jq -r prints the raw value without JSON quotes, which is what you want when you are pulling one field out to read or to save.

The whole index, in one object

Now read the entire root instead of one field. Here is what came back from this firmware when the endpoint was first opened.

{
  "@odata.id": "/redfish/v1",
  "@odata.type": "#ServiceRoot.v1_15_0.ServiceRoot",
  "AccountService": { "@odata.id": "/redfish/v1/AccountService" },
  "Cables": { "@odata.id": "/redfish/v1/Cables" },
  "CertificateService": { "@odata.id": "/redfish/v1/CertificateService" },
  "Chassis": { "@odata.id": "/redfish/v1/Chassis" },
  "EventService": { "@odata.id": "/redfish/v1/EventService" },
  "Fabrics": { "@odata.id": "/redfish/v1/Fabrics" },
  "Id": "RootService",
  "JsonSchemas": { "@odata.id": "/redfish/v1/JsonSchemas" },
  "Links": {
    "ManagerProvidingService": { "@odata.id": "/redfish/v1/Managers/bmc" },
    "Sessions": { "@odata.id": "/redfish/v1/SessionService/Sessions" }
  },
  "Managers": { "@odata.id": "/redfish/v1/Managers" },
  "Name": "Root Service",
  "RedfishVersion": "1.17.0",
  "Registries": { "@odata.id": "/redfish/v1/Registries" },
  "SessionService": { "@odata.id": "/redfish/v1/SessionService" },
  "Systems": { "@odata.id": "/redfish/v1/Systems" },
  "Tasks": { "@odata.id": "/redfish/v1/TaskService" },
  "TelemetryService": { "@odata.id": "/redfish/v1/TelemetryService" },
  "UUID": "a3d459ac-6324-4179-a58d-96125d1b7991",
  "UpdateService": { "@odata.id": "/redfish/v1/UpdateService" }
}

Four of those entries are the ones you will live in.

That capture leaves out one block, ProtocolFeaturesSupported, purely for length. Your own pull will include it. When you save the root to a file in the lab, expect a little more than what is printed above.

Which link hands out tokens?

How current is this firmware?

Two versions matter and they are different things. @odata.type gave you the schema version of one object. RedfishVersion gives you the version of the whole standard this service implements.

That number tells you which features you are allowed to expect. Pull it.

prompt: ops@dc-east-fw01:~$ answer: curl -sk -u root:0penBmc "$BMC_URL/redfish/v1/" | jq -r '.RedfishVersion' ||| curl -sk -u root:0penBmc $BMC_URL/redfish/v1/ | jq -r '.RedfishVersion' output: 1.17.0 hint: Same request as before, but ask jq for the RedfishVersion field

This is not a museum piece. A current protocol version, a live TelemetryService, and a real TaskService for long-running jobs. The open firmware is not the cut-down option.

Follow a link to the machine itself

The service root said Systems lives at /redfish/v1/Systems. That is a collection, a list of resources. On this machine the collection holds exactly one member: /redfish/v1/Systems/system.

That object is the host computer as Redfish sees it. Ask it what it is.

prompt: ops@dc-east-fw01:~$ answer: curl -sk -u root:0penBmc "$BMC_URL/redfish/v1/Systems/system" | jq -r '."@odata.type"' ||| curl -sk -u root:0penBmc $BMC_URL/redfish/v1/Systems/system | jq -r '."@odata.type"' output: #ComputerSystem.v1_22_0.ComputerSystem hint: Same shape as the service root request, but the URL ends in /redfish/v1/Systems/system

Here is part of what that object carried before anything was touched.

  "PowerState": "Off",
  "Status": { "Health": "OK", "State": "Disabled" },
  "SerialConsole": {
    "IPMI": { "ServiceEnabled": true },
    "MaxConcurrentSessions": 15,
    "SSH": {
      "HotKeySequenceDisplay": "Press ~. to exit console",
      "Port": 2200,
      "ServiceEnabled": true
    }
  }

PowerState is Off, so the host is not running. Status.Health is OK, which is the BMC telling you the machine is fine, it is simply not powered. Those two fields answer different questions and beginners mix them up constantly.

The lid the BMC is holding shut

The same object also publishes the boot override list: the devices the BMC can force the host to boot from on its next start. That list is why a BMC can rescue a machine with a dead disk from another continent.

Read it. Each value comes out on its own line.

prompt: ops@dc-east-fw01:~$ answer: curl -sk -u root:0penBmc "$BMC_URL/redfish/v1/Systems/system" | jq -r '.Boot."[email protected]"[]' ||| curl -sk -u root:0penBmc $BMC_URL/redfish/v1/Systems/system | jq -r '.Boot."[email protected]"[]' output: None Pxe Hdd Cd Diags BiosSetup Usb hint: The list lives under .Boot in the ComputerSystem object, in the field named [email protected]. Add [] after the field to print one value per line

Pxe means you can force a network install on a machine you cannot see. BiosSetup means you can drop it into firmware setup and then watch on the console. This is real remote hands, published as data.

What the standard bought you

Look back at what just happened. You did not know the vendor. You did not install a management agent. You asked one URL for its type, and the machine told you its schema, its protocol version, its power state and its boot options.

That is the entire promise of Redfish, and you just collected on it against firmware that has never heard of you.

Your cheat sheet

Everything this lesson taught, in four moves.

Work Order FW-01, five objectives. Your endpoint is in $BMC_URL, credentials root / 0penBmc, and that is a zero, not a letter O.

1. Save the service root. Put the whole object in ~/service-root.json. 2. Record the protocol version. Write it to ~/redfish-version.txt. 3. Save the ComputerSystem object to ~/system.json. 4. Save the Chassis object to ~/chassis.json. 5. The challenge. List every boot target into ~/boot-targets.txt.

Stuck is normal. Hit Request a signal on any objective for a nudge, or ask Daemon. It knows which task you are on and will nudge, not spoil.

Ready to practice

Your workstation dc-east-fw01 is booting in the bay below, and the OpenBMC instance comes up beside it on the lab network. Real firmware takes about two minutes to answer, so if your first request times out, run bmc-wait and let it finish. Then open Work Order FW-01.

Practice The Real Service Root in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.

More lessons in OpenBMC on Real Firmware