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