1# OpenBMC REST API 2 3The primary management interface for OpenBMC is REST. This document provides 4some basic structure and usage examples for the REST interface. 5 6The schema for the rest interface is directly defined by the OpenBMC D-Bus 7structure. Therefore, the objects, attributes and methods closely map to those 8in the D-Bus schema. 9 10For a quick explanation of HTTP verbs and how they relate to a RESTful API, see 11<http://www.restapitutorial.com/lessons/httpmethods.html>. 12 13## Authentication 14 15See the details on authentication at 16[REST-cheatsheet](https://github.com/openbmc/docs/blob/master/REST-cheatsheet.md#establish-rest-connection-session). 17 18This tutorial uses token based authentication method: 19 20``` 21$ export bmc=xx.xx.xx.xx 22$ export token=`curl -k -H "Content-Type: application/json" -X POST https://${bmc}/login -d '{"username" : "root", "password" : "0penBmc"}' | grep token | awk '{print $2;}' | tr -d '"'` 23$ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/... 24``` 25 26## HTTP GET operations & URL structure 27 28There are a few conventions on the URL structure of the OpenBMC rest interface. 29They are: 30 31- To query the attributes of an object, perform a GET request on the object 32 name, with no trailing slash. For example: 33 34 ``` 35 $ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/inventory/system 36 { 37 "data": { 38 "AssetTag": "", 39 "BuildDate": "", 40 "Cached": true, 41 "FieldReplaceable": true, 42 "Manufacturer": "", 43 "Model": "", 44 "PartNumber": "", 45 "Present": true, 46 "PrettyName": "", 47 "SerialNumber": "" 48 }, 49 "message": "200 OK", 50 "status": "ok" 51 } 52 ``` 53 54- To query a single attribute, use the `attr/<name>` path. Using the `system` 55 object from above, we can query just the `Name` value: 56 57 ``` 58 $ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/inventory/system/attr/Cached 59 { 60 "data": true, 61 "message": "200 OK", 62 "status": "ok" 63 } 64 ``` 65 66- When a path has a trailing-slash, the response will list the sub objects of 67 the URL. For example, using the same object path as above, but adding a slash: 68 69 ``` 70 $ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/ 71 { 72 "data": [ 73 "/xyz/openbmc_project/Chassis", 74 "/xyz/openbmc_project/Hiomapd", 75 "/xyz/openbmc_project/Ipmi", 76 "/xyz/openbmc_project/certs", 77 "/xyz/openbmc_project/console", 78 "/xyz/openbmc_project/control", 79 "/xyz/openbmc_project/dump", 80 "/xyz/openbmc_project/events", 81 "/xyz/openbmc_project/inventory", 82 "/xyz/openbmc_project/ipmi", 83 "/xyz/openbmc_project/led", 84 "/xyz/openbmc_project/logging", 85 "/xyz/openbmc_project/network", 86 "/xyz/openbmc_project/object_mapper", 87 "/xyz/openbmc_project/sensors", 88 "/xyz/openbmc_project/software", 89 "/xyz/openbmc_project/state", 90 "/xyz/openbmc_project/time", 91 "/xyz/openbmc_project/user" 92 ], 93 "message": "200 OK", 94 "status": "ok" 95 } 96 ``` 97 98 This shows that there are 19 children of the `openbmc_project/` object: 99 `dump`, `software`, `control`, `network`, `logging`,etc. This can be used with 100 the base REST URL (ie., `http://${bmc}/`), to discover all objects in the 101 hierarchy. 102 103- Performing the same query with `/list` will list the child objects 104 _recursively_. 105 106 ``` 107 $ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/network/list 108 { 109 "data": [ 110 "/xyz/openbmc_project/network/config", 111 "/xyz/openbmc_project/network/config/dhcp", 112 "/xyz/openbmc_project/network/eth0", 113 "/xyz/openbmc_project/network/eth0/ipv4", 114 "/xyz/openbmc_project/network/eth0/ipv4/3b9faa36", 115 "/xyz/openbmc_project/network/eth0/ipv6", 116 "/xyz/openbmc_project/network/eth0/ipv6/ff81b6d6", 117 "/xyz/openbmc_project/network/eth1", 118 "/xyz/openbmc_project/network/eth1/ipv4", 119 "/xyz/openbmc_project/network/eth1/ipv4/3b9faa36", 120 "/xyz/openbmc_project/network/eth1/ipv4/66e63348", 121 "/xyz/openbmc_project/network/eth1/ipv6", 122 "/xyz/openbmc_project/network/eth1/ipv6/ff81b6d6", 123 "/xyz/openbmc_project/network/host0", 124 "/xyz/openbmc_project/network/host0/intf", 125 "/xyz/openbmc_project/network/host0/intf/addr", 126 "/xyz/openbmc_project/network/sit0", 127 "/xyz/openbmc_project/network/snmp", 128 "/xyz/openbmc_project/network/snmp/manager" 129 ], 130 "message": "200 OK", 131 "status": "ok" 132 } 133 ``` 134 135- Adding `/enumerate` instead of `/list` will also include the attributes of the 136 listed objects. 137 138 ``` 139 $ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/time/enumerate 140 { 141 "data": { 142 "/xyz/openbmc_project/time/bmc": { 143 "Elapsed": 1563209492098739 144 }, 145 "/xyz/openbmc_project/time/host": { 146 "Elapsed": 1563209492101678 147 }, 148 "/xyz/openbmc_project/time/owner": { 149 "TimeOwner": "xyz.openbmc_project.Time.Owner.Owners.BMC" 150 }, 151 "/xyz/openbmc_project/time/sync_method": { 152 "TimeSyncMethod": "xyz.openbmc_project.Time.Synchronization.Method.NTP" 153 } 154 }, 155 "message": "200 OK", 156 "status": "ok" 157 } 158 ``` 159 160## HTTP PUT operations 161 162PUT operations are for updating an existing resource (an object or property), or 163for creating a new resource when the client already knows where to put it. These 164require a json formatted payload. To get an example of what that looks like: 165 166``` 167$ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/state/host0 > host.json 168$ cat host.json 169{ 170 "data": { 171 "AttemptsLeft": 3, 172 "BootProgress": "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified", 173 "CurrentHostState": "xyz.openbmc_project.State.Host.HostState.Off", 174 "OperatingSystemState": "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive", 175 "RequestedHostTransition": "xyz.openbmc_project.State.Host.Transition.Off" 176 }, 177 "message": "200 OK", 178 "status": "ok" 179} 180``` 181 182or 183 184``` 185$ curl -k -H "X-Auth-Token: $token" https://${bmc}/xyz/openbmc_project/state/host0/attr/RequestedHostTransition > requested_host.json 186$ cat requested_host.json 187{ 188 "data": "xyz.openbmc_project.State.Host.Transition.Off", 189 "message": "200 OK", 190 "status": "ok" 191} 192``` 193 194When turning around and sending these as requests, delete the message and status 195properties. 196 197To make curl use the correct content type header use the -H option to specify 198that we're sending JSON data: 199 200``` 201$ curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X PUT -d <json> <url> 202``` 203 204A PUT operation on an object requires a complete object. For partial updates 205there is PATCH but that is not implemented yet. As a workaround individual 206attributes are PUTable. 207 208For example, make changes to the requested_host.json file and do a PUT (upload): 209 210``` 211$ cat requested_host.json 212{"data": "xyz.openbmc_project.State.Host.Transition.Off"} 213$ curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X PUT -T requested_host.json https://${bmc}/xyz/openbmc_project/state/host0/attr/RequestedHostTransition 214``` 215 216Alternatively specify the json inline with -d: 217 218``` 219$ curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X PUT -d '{"data": "xyz.openbmc_project.State.Host.Transition.On"}' https://${bmc}/xyz/openbmc_project/state/host0/attr/RequestedHostTransition 220``` 221 222When using '-d' just remember that json requires quoting. 223 224## HTTP POST operations 225 226POST operations are for calling methods, but also for creating new resources 227when the client doesn't know where to put it. OpenBMC does not support creating 228new resources via REST so any attempt to create a new resource will result in a 229HTTP 403 (Forbidden). These also require a json formatted payload. To delete 230logging entries: 231 232``` 233$ curl -k -H "X-Auth-Token: $token" -H 'Content-Type: application/json' -X POST -d '{"data":[]}' https://${bmc}/xyz/openbmc_project/logging/action/DeleteAll 234``` 235 236To invoke a method without parameters (Factory Reset of BMC and Host): 237 238``` 239$ curl -k -H "X-Auth-Token: $token" -H 'Content-Type: application/json' -X POST -d '{"data":[]}' https://${bmc}/xyz/openbmc_project/software/action/Reset 240``` 241 242## HTTP DELETE operations 243 244DELETE operations are for removing instances. Only D-Bus objects (instances) can 245be removed. If the underlying D-Bus object implements the 246`xyz.openbmc_project.Object.Delete` interface the REST server will call it. If 247`xyz.openbmc_project.Object.Delete` is not implemented, the REST server will 248return a HTTP 403 (Forbidden) error. 249 250For example, to delete a event record: 251 252Display logging entries: 253 254``` 255$ curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X GET https://${bmc}/xyz/openbmc_project/logging/entry/enumerate 256``` 257 258Then delete the event record with ID 1: 259 260``` 261$ curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X DELETE https://${bmc}/xyz/openbmc_project/logging/entry/1 262``` 263 264## Uploading images 265 266It is possible to upload software upgrade images (for example to upgrade the BMC 267or host software) via REST. The content-type should be set to 268"application/octet-stream". 269 270For example, to upload an image:(the `<file_to_upload>` must be a tar ball) 271 272``` 273$ curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/octet-stream" -X POST -T <file_to_upload> https://${bmc}/upload/image 274``` 275 276In above example, the filename on the BMC will be chosen by the REST server. 277 278It is possible for the user to choose the uploaded file's remote name: 279 280``` 281curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/octet-stream" -X PUT -T foo https://${bmc}/upload/image/bar 282``` 283 284In above example, the file foo will be saved with the name bar on the BMC. 285 286The operation will either return the version id (hash) of the uploaded file on 287success: 288 289``` 290{ 291 "data": "afb92384", 292 "message": "200 OK", 293 "status": "ok" 294} 295``` 296 297or an error message 298 299``` 300{ 301 "data": { 302 "description": "Version already exists or failed to be extracted" 303 }, 304 "message": "400 Bad Request", 305 "status": "error" 306} 307``` 308 309For more details on uploading and updating software, see: 310https://github.com/openbmc/docs/tree/master/architecture/code-update 311 312## Event subscription protocol 313 314It is possible to subscribe to events, of interest, occurring on the BMC. The 315implementation on the BMC uses WebSockets for this purpose, so that clients 316don't have do employ polling. Instead, the rest server on the BMC can push data 317to clients over a websocket. The BMC can push out information pertaining to 318D-Bus InterfacesAdded and PropertiesChanged signals. 319 320Following is a description of the event subscription protocol, with example JS 321code snippets denoting client-side code. 322 323a) The client needs to have logged on to the BMC. b) The client needs to open a 324secure websocket with the URL <BMC IP>/subscribe. 325 326``` 327 var ws = new WebSocket("wss://<BMC IP>/subscribe") 328``` 329 330c) The client needs to send, over the websocket, a JSON dictionary, comprising 331of key-value pairs. This dictionary serves as the "events filter". All the keys 332are optional, so the dictionary can be empty if no filtering is desired. The 333filters represented by each of the key-value pairs are ORed. 334 335One of the supported keys is "paths". The corresponding value is an array of 336D-Bus paths. The InterfacesAdded and PropertiesChanged D-Bus signals emanating 337from any of these path(s) alone, and not from any other paths, will be included 338in the event message going out of the BMC. 339 340The other supported key is "interfaces". The corresponding value is an array of 341D-Bus interfaces. The InterfacesAdded and PropertiesChanged D-Bus signal 342messages comprising of any of these interfaces will be included in the event 343message going out of the BMC. 344 345All of the following are valid: 346 347``` 348var data = JSON.stringify( 349{ 350 "paths": ["/xyz/openbmc_project/logging", "/xyz/openbmc_project/sensors"], 351 "interfaces": ["xyz.openbmc_project.Logging.Entry", "xyz.openbmc_project.Sensor.Value"] 352}); 353ws.onopen = function() { 354 ws.send(data); 355}; 356``` 357 358``` 359var data = JSON.stringify( 360{ 361 "paths": ["/xyz/openbmc_project/logging", "/xyz/openbmc_project/sensors"], 362}); 363ws.onopen = function() { 364 ws.send(data); 365}; 366``` 367 368``` 369var data = JSON.stringify( 370{ 371 "interfaces": ["xyz.openbmc_project.Logging.Entry", "xyz.openbmc_project.Sensor.Value"] 372}); 373ws.onopen = function() { 374 ws.send(data); 375}; 376``` 377 378``` 379var data = JSON.stringify( 380{ 381}); 382ws.onopen = function() { 383 ws.send(data); 384}; 385``` 386 387d) The rest server on the BMC will respond over the websocket when a D-Bus event 388occurs, considering the client supplied filters. The rest servers notifies about 389InterfacesAdded and PropertiesChanged events. The response is a JSON dictionary 390as follows : 391 392InterfacesAdded 393 394``` 395"event": InterfacesAdded 396"path": <string : new D-Bus path that was created> 397"interfaces": <dict : a dictionary of interfaces> (similar to org.freedesktop.DBus.ObjectManager.InterfacesAdded ) 398``` 399 400PropertiesChanged 401 402``` 403"event": PropertiesChanged 404"path": <string : D-Bus path whose property changed> 405"interface": <string : D-Bus interface to which the changed property belongs> 406"properties": <dict : a dictionary of properties> (similar to org.freedesktop.DBus.Properties.PropertiesChanged) 407``` 408