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