How to discover disk uids for freeNAS HTTP API v2.0?

bever1337

Cadet
Joined
Aug 20, 2020
Messages
1
Howdy,

I'm a full-stack developer trying to understand and implement against the FreeNAS HTTP API surface. I chose 2.0 because it's new and my machine running FreeNAS-11.3-U3.1 supports it. Excited to nerd out and pull random data from my machine, the first thing I did was bust open the swagger UI on my machine to discover the swagger configuration is maybe lacking for some endpoints.

Moving on, my first goal was just to grab a list of disks, and then query a specific disk.

Here is what I tried:
Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/
*   Trying 192.168.1.17:80...
* TCP_NODELAY set
* Connected to 192.168.1.17 (192.168.1.17) port 80 (#0)
* Server auth using Basic with user 'root'
> GET /api/v2.0/disk/ HTTP/1.1
> Host: 192.168.1.17
> Authorization: Basic myBase64EncodedUsernameAndPassword
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 20 Aug 2020 16:32:01 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 5795
< Connection: keep-alive
< Strict-Transport-Security: max-age=0
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1
<
[
 ... // other disks in JSON response omitted for the sake of brevity
 {
  "identifier": "{serial_lunid}Z1Z4R6NV0000C4512DB4_5000c50058f4fa23",
  "name": "da0",
  "subsystem": "da",
  "number": 0,
  "serial": "Z1Z4R6NV0000C4512DB4",
  "size": 4000787030016,
  "type": "HDD",
  "rotationrate": 7200,
  "model": "IBM-B040 ST4000NM0023",
  "multipath_name": "",
  "multipath_member": "",
  "description": "",
  "transfermode": "Auto",
  "hddstandby": "ALWAYS ON",
  "advpowermgmt": "DISABLED",
  "acousticlevel": "DISABLED",
  "togglesmart": true,
  "smartoptions": "",
  "expiretime": null,
  "passwd": "",
  "difference": null,
  "informational": null,
  "critical": null,
  "devname": "da0",
  "enclosure": null
 },
 ... // other disks in JSON response omitted for the sake of brevity
* Connection #0 to host 192.168.1.17 left intact
]%  


Nice, so that works great! Now I want to grab info for a specific disk, so I will try and use the endpoint `api/v2.0/disk/id/{id}`. There's no `id` key/value in the JSON blob response from `/disk/` so I tried using `name`, `identifier`, `serial`, as well as the array index of the item:

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/da0

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/{serial_lunid}Z1Z4R6NV0000C4512DB4_5000c50058f4fa23

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/Z1Z4R6NV0000C4512DB4

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/2

All requests result in a 404. I know that curly brackets are characters that must be escaped, so then I try this one:
Code:
curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/%7Bserial_lunid%7DZ1Z4R6NV0000C4512DB4_5000c50058f4fa23

Also a 404!

I want to try and use the swagger ui to debug this but the swagger config is expecting an array of ids for this path. I'm not aware of any official spec on sending arrays in HTTP query parameters, but I did make several attempts to convince the swagger UI to execute my request. No dice!

Does anyone know how to discover disk uids for freeNAS HTTP API v2.0 or how to correctly format this request?

Thanks!
 

Patrick M. Hausen

Hall of Famer
Joined
Nov 25, 2013
Messages
7,776
You have all the data in the result of your first query, so my guess is you are expected to just parse the json output into a suitable data structure. What am I missing? I doubt there is any more information TrueNAS maintains and makes available via the API.
 

sretalla

Powered by Neutrality
Moderator
Joined
Jan 1, 2016
Messages
9,703
What about trying this for the ID?
"number": 0,
 

Dustin Olson

Cadet
Joined
May 27, 2016
Messages
1
Howdy,

I'm a full-stack developer trying to understand and implement against the FreeNAS HTTP API surface. I chose 2.0 because it's new and my machine running FreeNAS-11.3-U3.1 supports it. Excited to nerd out and pull random data from my machine, the first thing I did was bust open the swagger UI on my machine to discover the swagger configuration is maybe lacking for some endpoints.

Moving on, my first goal was just to grab a list of disks, and then query a specific disk.

Here is what I tried:
Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/
*   Trying 192.168.1.17:80...
* TCP_NODELAY set
* Connected to 192.168.1.17 (192.168.1.17) port 80 (#0)
* Server auth using Basic with user 'root'
> GET /api/v2.0/disk/ HTTP/1.1
> Host: 192.168.1.17
> Authorization: Basic myBase64EncodedUsernameAndPassword
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 20 Aug 2020 16:32:01 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 5795
< Connection: keep-alive
< Strict-Transport-Security: max-age=0
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1
<
[
... // other disks in JSON response omitted for the sake of brevity
{
  "identifier": "{serial_lunid}Z1Z4R6NV0000C4512DB4_5000c50058f4fa23",
  "name": "da0",
  "subsystem": "da",
  "number": 0,
  "serial": "Z1Z4R6NV0000C4512DB4",
  "size": 4000787030016,
  "type": "HDD",
  "rotationrate": 7200,
  "model": "IBM-B040 ST4000NM0023",
  "multipath_name": "",
  "multipath_member": "",
  "description": "",
  "transfermode": "Auto",
  "hddstandby": "ALWAYS ON",
  "advpowermgmt": "DISABLED",
  "acousticlevel": "DISABLED",
  "togglesmart": true,
  "smartoptions": "",
  "expiretime": null,
  "passwd": "",
  "difference": null,
  "informational": null,
  "critical": null,
  "devname": "da0",
  "enclosure": null
},
... // other disks in JSON response omitted for the sake of brevity
* Connection #0 to host 192.168.1.17 left intact
]%  


Nice, so that works great! Now I want to grab info for a specific disk, so I will try and use the endpoint `api/v2.0/disk/id/{id}`. There's no `id` key/value in the JSON blob response from `/disk/` so I tried using `name`, `identifier`, `serial`, as well as the array index of the item:

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/da0

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/{serial_lunid}Z1Z4R6NV0000C4512DB4_5000c50058f4fa23

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/Z1Z4R6NV0000C4512DB4

Code:
➜  ~ curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/2

All requests result in a 404. I know that curly brackets are characters that must be escaped, so then I try this one:
Code:
curl --verbose --user $rootUser:$rootPass http://192.168.1.17/api/v2.0/disk/id/%7Bserial_lunid%7DZ1Z4R6NV0000C4512DB4_5000c50058f4fa23

Also a 404!

I want to try and use the swagger ui to debug this but the swagger config is expecting an array of ids for this path. I'm not aware of any official spec on sending arrays in HTTP query parameters, but I did make several attempts to convince the swagger UI to execute my request. No dice!

Does anyone know how to discover disk uids for freeNAS HTTP API v2.0 or how to correctly format this request?

Thanks!

Did you ever figure this out? I have been creating my own application that retrieves data as well, and I cant seem to figure out what the server is looking for in regards to "id"?
 

einhirn

Cadet
Joined
Feb 28, 2023
Messages
2
I guess this is a bug in the api. "/disk/id/{id}" requires an integer argument, but the Identifier of a disk actually is the long string starting with "{serial_lunid}...". The Issue is that RESTful api is automatically constructed according to the definition of the websocket api assuming integer IDs for "item_method"s, but this one takes a string as an id for "disk.update" like this:

Code:
midclt call disk.update '{serial_lunid}P4HEY9UC            _5000cca249d46e61' '{"smartoptions":"-d sat"}'

(This is on TrueNAS 13-U4)

Anyway I digged around a little in the middlewared's code, but ended at "whatever, I can do what I need by using midclt". I don't actually know how to report a bug in TrueNAS' API - anyone?

You can see part of the definition of the disk.update call here:
Code:
  "disk.update": {
    "description": "Update disk of `id`.\n[...]",
    "examples": {},
    "accepts": [
      {
        "title": "id",
        "_required_": false,
        "type": "string"
      },
      {
        "type": "object",
        "properties": {
      }
   ]

The method accepts two positional parameters, first a plain string as ID, second a JSON dict with parameters to be updated... And this doesn't translate to the RESTful wrappers "id/<integer>" thing - perhaps there isn't even a numeric ID stored for Disks in middlewared's database...
 

Samuel Tai

Never underestimate your own stupidity
Moderator
Joined
Apr 24, 2020
Messages
5,399
Yes, this is a bug in the RESTful 2.0 API. The API call works correctly using midclt call disk.update '{serial_lunid}P4HEY9UC_5000cca249d46e61' '{"smartoptions":"-d sat"}'. The basic issue is the dictionary for the storage_disk table in the configuration database doesn't have a field corresponding to id.
 
Top