summaryrefslogtreecommitdiffstats
path: root/rest-api.md
blob: fc88310a1745f76d3c4e3708a7e44793b4d9ab75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# OpenBMC REST API

The primary management interface for OpenBMC is REST. This document provides
some basic structure and usage examples for the REST interface.

The schema for the rest interface is directly defined by the OpenBMC D-Bus
structure. Therefore, the objects, attributes and methods closely map to those
in the D-Bus schema.

For a quick explanation of HTTP verbs and how they relate to a RESTful API, see
<http://www.restapitutorial.com/lessons/httpmethods.html>.

## Authentication

See the details on authentication at
https://github.com/openbmc/docs/blob/master/REST-cheatsheet.md

This tutorial uses the basic authentication URL encoding, so just pass in the
user name and password as part of the URL and no separate login/logout commands
are required:

```
export bmc=<username>:<password>@<hostname>
```

## HTTP GET operations & URL structure

There are a few conventions on the URL structure of the OpenBMC rest interface.
They are:

 - To query the attributes of an object, perform a GET request on the object
   name, with no trailing slash. For example:

        $ curl -k https://${bmc}/xyz/openbmc_project/inventory/system
        {
          "data": {
            "AssetTag": "",
            "BuildDate": "",
            "Cached": 0,
            "FieldReplaceable": 0,
            "Manufacturer": "",
            "Model": "0000000000000000",
            "PartNumber": "",
            "Present": 1,
            "PrettyName": "",
            "SerialNumber": "0000000000000000"
          },
          "message": "200 OK",
          "status": "ok"
        }

 - To query a single attribute, use the `attr/<name>` path. Using the
   `system` object from above, we can query just the `Name` value:

        $ curl -k https://${bmc}/xyz/openbmc_project/inventory/system/attr/Model
        {
          "data": "0000000000000000",
          "message": "200 OK",
          "status": "ok"
        }

 - When a path has a trailing-slash, the response will list the sub objects of
   the URL. For example, using the same object path as above, but adding a
   slash:

        $ curl -k https://${bmc}/xyz/openbmc_project/
        {
          "data": [
            "/xyz/openbmc_project/dump",
            "/xyz/openbmc_project/software",
            "/xyz/openbmc_project/control",
            "/xyz/openbmc_project/network",
            "/xyz/openbmc_project/logging",
            "/xyz/openbmc_project/sensors",
            "/xyz/openbmc_project/inventory",
            "/xyz/openbmc_project/user",
            "/xyz/openbmc_project/time",
            "/xyz/openbmc_project/led",
            "/xyz/openbmc_project/state"

          ],
          "message": "200 OK",
          "status": "ok"
        }

   This shows that there are 11 children of the `openbmc_project/` object:
   `dump`, `software`, `control`, `network`, `logging`, `sensors`, `inventory`,
   `user`, `time`, `led`, and `state`. This can be used with the base REST URL
   (ie., `http://${bmc}/`), to discover all objects in the hierarchy.

 - Performing the same query with `/list` will list the child objects
   *recursively*.

        $ curl -k https://${bmc}/xyz/openbmc_project/network/list
        {
          "data": [
            "/xyz/openbmc_project/network/config",
            "/xyz/openbmc_project/network/eth0",
            "/xyz/openbmc_project/network/eth0/ipv4/3cf9573",
            "/xyz/openbmc_project/network/eth0/ipv6/c354c06",
            "/xyz/openbmc_project/network/host0/intf",
            "/xyz/openbmc_project/network/host0/intf/addr",
            "/xyz/openbmc_project/network/config/dhcp"
          ],
          "message": "200 OK",
          "status": "ok"
        }

 - Adding `/enumerate` instead of `/list` will also include the attributes of
   the listed objects.

        $ curl -k https://${bmc}/xyz/openbmc_project/time/enumerate
        {
          "data": {
            "/xyz/openbmc_project/time/bmc": {
              "Elapsed": 1511205212119165
            },
            "/xyz/openbmc_project/time/host": {
              "Elapsed": 1511205212134372
            },
            "/xyz/openbmc_project/time/owner": {
              "TimeOwner": "xyz.openbmc_project.Time.Owner.Owners.BMC"
            },
            "/xyz/openbmc_project/time/sync_method": {
              "TimeSyncMethod": "xyz.openbmc_project.Time.Synchronization.Method.NTP"
            }
          },
          "message": "200 OK",
          "status": "ok"
        }

## HTTP PUT operations

PUT operations are for updating an existing resource (an object or property), or
for creating a new resource when the client already knows where to put it.
These require a json formatted payload. To get an example of what that looks
like:

    curl -k https://${bmc}/xyz/openbmc_project/state/host0 > host.json

    $ cat host.json
    {
      "data": {
        "AttemptsLeft": 0,
        "BootProgress": "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified",
        "CurrentHostState": "xyz.openbmc_project.State.Host.HostState.Off",
        "OperatingSystemState": "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive",
        "RequestedHostTransition": "xyz.openbmc_project.State.Host.Transition.Off"
      },
      "message": "200 OK",
      "status": "ok"
    }

or

    curl -k \
        https://${bmc}/xyz/openbmc_project/state/host0/attr/RequestedHostTransition > requested_host.json

    $ cat requested_host.json
    {
      "data": "xyz.openbmc_project.State.Host.Transition.Off",
      "message": "200 OK",
      "status": "ok"
    }

When turning around and sending these as requests, delete the message and status
properties.

To make curl use the correct content type header use the -H option to specify
that we're sending JSON data:

    curl -k -X PUT -d <json> <url>

A PUT operation on an object requires a complete object. For partial updates
there is PATCH but that is not implemented yet. As a workaround individual
attributes are PUTable.

For example, make changes to the requested_host.json file and do a PUT (upload):

    $ cat requested_host.json
    {"data": "xyz.openbmc_project.State.Host.Transition.On"}

    curl -k -X PUT -T requested_host.json \
        https://${bmc}/xyz/openbmc_project/state/host0/attr/RequestedHostTransition

Alternatively specify the json inline with -d:

    curl -k -X PUT \
        -d '{"data": "xyz.openbmc_project.State.Host.Transition.On"}' \
        https://${bmc}/xyz/openbmc_project/state/host0/attr/RequestedHostTransition

When using '-d' just remember that json requires quoting.

## HTTP POST operations
POST operations are for calling methods, but also for creating new resources
when the client doesn't know where to put it. OpenBMC does not support creating
new resources via REST so any attempt to create a new resource will result in a
HTTP 403 (Forbidden).

These also require a json formatted payload.

To invoke a method with parameters (Downloading a Tar image via TFTP):

    curl -k -X POST -d '{"data": ["<Image Tarball>", "<TFTP Server>"]}' \
       https://${bmc}/xyz/openbmc_project/software/action/DownloadViaTFTP

To invoke a method without parameters (Factory Reset of BMC and Host):

    curl -k -X POST -d '{"data":[]}' \
        https://${bmc}/xyz/openbmc_project/software/action/Reset

## HTTP DELETE operations
DELETE operations are for removing instances. Only D-Bus objects (instances) can
be removed. If the underlying D-Bus object implements the
`xyz.openbmc_project.Object.Delete` interface the REST server will call it. If
`xyz.openbmc_project.Object.Delete` is not implemented, the REST server will
return a HTTP 403 (Forbidden) error.

For example, to delete the event record with ID 1:

   curl -k -X DELETE https://${bmc}/xyz/openbmc_project/logging/entry/1


## Uploading images
It is possible to upload software upgrade images (for example to upgrade the BMC
or host software) via REST. The content-type should be set to
"application/octet-stream".

For example, to upload an image:

    curl -k -H "Content-Type: application/octet-stream" \
        -X POST -T <file_to_upload> https://${bmc}/upload/image

In above example, the filename on the BMC will be chosen by the REST server.

It is possible for the user to choose the uploaded file's remote name:

    curl -k -H "Content-Type: application/octet-stream" \
        -X PUT -T foo https://${bmc}/upload/image/bar

In above example, the file foo will be saved with the name bar on the BMC.

The operation will either return the version id (hash) of the uploaded file
on success:

    {
        "data": "ffdaab9b",
        "message": "200 OK",
        "status": "ok"
    }

or an error message:

    {
        "data": {
            "description": "Version already exists or failed to be extracted"
        },
        "message": "400 Bad Request",
        "status": "error"
    }

## Event subscription protocol
It is possible to subscribe to events, of interest, occurring on the BMC. The
implementation on the BMC uses WebSockets for this purpose, so that clients
don't have do employ polling. Instead, the rest server on the BMC can push
data to clients over a websocket. The BMC can push out information
pertaining to D-Bus InterfacesAdded and PropertiesChanged signals.

Following is a description of the event subscription protocol, with example
JS code snippets denoting client-side code.

a) The client needs to have logged on to the BMC.
b) The client needs to open a secure websocket with the URL <BMC IP>/subscribe.

```
   var ws = new WebSocket("wss://<BMC IP>/subscribe")
```

c) The client needs to send, over the websocket, a JSON dictionary, comprising
   of key-value pairs. This dictionary serves as the "events filter". All the
   keys are optional, so the dictionary can be empty if no filtering is desired.
   The filters represented by each of the key-value pairs are ORed.

   One of the supported keys is "paths". The corresponding value is an array of
   D-Bus paths. The InterfacesAdded and PropertiesChanged D-Bus signals
   emanating from any of these path(s) alone, and not from any other paths, will
   be included in the event message going out of the BMC.

   The other supported key is "interfaces". The corresponding value is an
   array of D-Bus interfaces. The InterfacesAdded and PropertiesChanged D-Bus
   signal messages comprising of any of these interfaces will be included in
   the event message going out of the BMC.

   All of the following are valid:

   ```
   var data = JSON.stringify(
   {
       "paths": ["/xyz/openbmc_project/logging", "/xyz/openbmc_project/sensors"],
       "interfaces": ["xyz.openbmc_project.Logging.Entry", "xyz.openbmc_project.Sensor.Value"]
   });
   ws.onopen = function() {
       ws.send(data);
   };
   ```

   ```
   var data = JSON.stringify(
   {
       "paths": ["/xyz/openbmc_project/logging", "/xyz/openbmc_project/sensors"],
   });
   ws.onopen = function() {
       ws.send(data);
   };
   ```

   ```
   var data = JSON.stringify(
   {
       "interfaces": ["xyz.openbmc_project.Logging.Entry", "xyz.openbmc_project.Sensor.Value"]
   });
   ws.onopen = function() {
       ws.send(data);
   };
   ```

   ```
   var data = JSON.stringify(
   {
   });
   ws.onopen = function() {
       ws.send(data);
   };
   ```

d) The rest server on the BMC will respond over the websocket when a D-Bus event
   occurs, considering the client supplied filters. The rest servers notifies
   about InterfacesAdded and PropertiesChanged events. The response is a JSON
   dictionary as follows :

   InterfacesAdded
   ```
   "event": InterfacesAdded
   "path": <string : new D-Bus path that was created>
   "interfaces": <dict : a dictionary of interfaces> (similar to org.freedesktop.DBus.ObjectManager.InterfacesAdded )
   ```

   PropertiesChanged
   ```
   "event": PropertiesChanged
   "path": <string : D-Bus path whose property changed>
   "interface": <string : D-Bus interface to which the changed property belongs>
   "properties": <dict : a dictionary of properties> (similar to org.freedesktop.DBus.Properties.PropertiesChanged)
   ```
OpenPOWER on IntegriCloud