xref: /openbmc/docs/rest-api.md (revision d045c8aa)
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