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