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