small bug in proxmox api docs

uriel

Member
Apr 12, 2020
36
9
13
44
Hi,

Since I check the current existing Proxmox API client in javascript, I realize that all current javascript APi are... ugly. (all of them relay on curl binary).
I'm now digging to build my own api client.

Can you please change some invalid type in the API JSON?
by replacing:


Code:
minimum" : "0",

by:

Code:
"minimum" : 0,

there are 23 similar error.


example:

Code:
bwlimit" : {
    default" : "migrate limit from datacenter or storage config",
    description" : "Override I/O bandwidth limit (in KiB/s).",
    minimum" : "0",
    optional" : 1,
    type" : "number",
    typetext" : "<number> (0 - N)"
},



can you also replace :

Code:
optional" : "1",
by:
Code:
optional" : 1,
there are 4 similar error.


and a question:
what is the difference between integer and number types ?

"type" : "number" is used 154 times
"type" : "integer" is used 845 times.
 
Last edited:
for optional it's actually correct, as that is a boolean, which in our API is a string that accepts '0|1|on|off|yes|no|true|false' ;) but passing in integer/number 1/0 also works, since that gets converted to a string anyway in our backend.

the difference between number and integer is simple, integer is for integers (0, 1, -1, 2, -2, 3, -3, 4, ..), the other is for arbitrary numbers including floating point (the exact RE is /^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/, that module will probably explain some other stuff related to the Schema as well ;))

that being said, encoding booleans, minimum, maximum, length, etc. properly in the API dump makes a lot of sense - so please do file an issue as dietmar suggested, or if you are up for it, even send patches ;) the schema dump used for the API viewer is generated in the pve-docs repository, the core schema code is in pve-common.
 
  • Like
Reactions: Moayad
Thanks for your lighting, after spending some hours, on the pve API, building an API might be more difficult than expected, but is still possible.

the most complex part is to support requires parameters constraint at build time.

I had expect to build an API like this one:
https://www.npmjs.com/package/@ovh-api/api

Using a syntax like that:
Code:
    const archive = await dbaas.logs.$(serviceName).output.graylog.stream.$(streamId).archive.$(archiveId).$get();
    // call API      GET /dbaas/logs/{serviceName}/output/graylog/stream/{streamId}/archive/{archiveId}

in Proxmox case it will be something like that:

Code:
//  POST /api2/json/nodes/{node}/qemu/{vmid}/clone
await api.nodes.$(node).qemu.$(vmid).clone.$post({newid: 200, node, id: 100});
// in modern JavaScript {newid: 200, node, id: 100} is read as {"newid": 200, "node": node, "id": 100}
// so that the real code.

await api.nodes.$(node).qemu.$(vmid).clone.$post({newid: 200, node});
// will throws an error at compilation time because id is mandatory

await api.nodes.$(node).qemu.$(vmid).clone.$post({newid: 200, node, id: 100, foo: 'bar'});
// will throws an error at compilation time because foo is unexpected.
 
I have start the implementation, and it's already working:

github

Using the API the code looks like that:

JavaScript:
import { proxyProxmox } from "./contructor";
import ProxmoxEngine from "./ProxmoxEngine";

async function test() {
    // authorize self signed cert
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
    // load sample authentification info
    const auth = await import('../../../auth');
    const { host, password }  = auth.default;
    // connect to proxmox
    const promox = proxyProxmox(new ProxmoxEngine({host, password}));
    // liste nodes
    const nodes = await promox.nodes.$get();
    // iterate cluster nodes
    for (const node of nodes) {
        const theNode = promox.nodes.$(node.node);
        // list Qemu VMS
        const qemus = await theNode.qemu.$get({full:true});
        // iterate Qemu VMS
        for (const qemu of qemus) {
            // do some suff.
            const config = await theNode.qemu.$(qemu.vmid).config.$get();
            console.log(`vm: ${config.name}, memory: ${config.memory}`);
            // const vnc = await theNode.qemu.$(qemu.vmid).vncproxy.$post();
            // console.log('vnc:', vnc);
            const spice = await theNode.qemu.$(qemu.vmid).spiceproxy.$post();
            console.log('spice:', spice);
        }
    }    
}
test().catch(console.error);

And the IDE intelligent works on every part of the code, no need to check any external docs.

I need some more test before any public release.
 
the one representing your system's copy is shipped as part of pve-docs, but both return and parameter schemas might have 'additionalproperties' set to true, in which case they allow extra keys/values..
 
hi,

I had just implement 'additionalProperties' as accept any other parameters, but I do not help, and I had to change the original model to mate it works, by adding an additionalProperties: 1.

JSON:
{
   "info" : {
      "GET" : {
         "allowtoken" : 1,
         "description" : "Get virtual machine status.",
         "method" : "GET",
         "name" : "vm_status",
         "parameters" : {
            "additionalProperties" : 0, // if set to one can accepte extra param ?
            "properties" : {
               "node" : {
                  "description" : "The cluster node name.",
                  "format" : "pve-node",
                  "type" : "string",
                  "typetext" : "<string>"
               },
               "vmid" : {
                  "description" : "The (unique) ID of the VM.",
                  "format" : "pve-vmid",
                  "minimum" : 1,
                  "type" : "integer",
                  "typetext" : "<integer> (1 - N)"
               }
            }
         },
         "permissions" : {
            "check" : [
               "perm",
               "/vms/{vmid}",
               [
                  "VM.Audit"
               ]
            ]
         },
         "protected" : 1,
         "proxyto" : "node",
         "returns" : {
           "additionalProperties" : 1, // is not present in the originakl json
            "properties" : {
               "agent" : {
                  "description" : "Qemu GuestAgent enabled in config.",
                  "optional" : 1,
                  "type" : "boolean"
               },
            // droped json
               "vmid" : {
                  "description" : "The (unique) ID of the VM.",
                  "format" : "pve-vmid",
                  "minimum" : 1,
                  "type" : "integer"
               }
            },
            "type" : "object"
         }
      }
   },
   "leaf" : 1,
   "path" : "/nodes/{node}/qemu/{vmid}/status/current",
   "text" : "current"
}

there is only 7 "additionalProperties" : 1 in the swagger.
the method I trying to call do not have one of them.
 
yes, the default is 1 so it's often omitted. we could maybe add it to the apidump in all cases where it is not set explicitly..
 
Now that my new Api is working, I would like to submit some improvement to the main swagger.

which git should I clone for changes proposal ?
you have a lot of them: https://git.proxmox.com/


I can make some change in my own copy, but that not the best way to process.

------
I started to clone all the repository to find the right git, it will just take some times.
 
Last edited:
that would be great!

check out

https://pve.proxmox.com/wiki/Developer_Documentation (general guidelines and workflow)
https://git.proxmox.com/?p=pve-common.git;a=blob;f=src/PVE/JSONSchema.pm; (contains most of the basic machinery for our API schema)
https://git.proxmox.com/?p=pve-common.git;a=blob;f=src/PVE/RESTHandler.pm; (contains the code that actually generates the API dump)
https://git.proxmox.com/?p=pve-docs.git;a=blob;f=extractapi.pl; (the repo + code where the dump gets converted to the JS file that the API viewer uses)
 
by the way,
the first time I called : `GET /nodes/{node}/qemu`
with the code: `qemus = await theNode.qemu.$get({full:true});`

I get an error saying that 'true' wasn't a correct boolean, and I had to convert all my boolean to 0 or 1.

bot a big deal, but strange.
a 'fabian' proxmox user told me that:

for optional it's actually correct, as that is a boolean, which in our API is a string that accepts '0|1|on|off|yes|no|true|false' ;) but passing in integer/number 1/0 also works, since that gets converted to a string anyway in our backend.
 
you are correct - the type checking in the API is stricter than the parser later on. in config files, all those values are accepted, but in the API, only 1/0 get through the type checker.
 
I Used most of the data swagger,

for now:
- permissions is not used, it's that not very important for an API, this more a sys-op info.
- I do not know what the field protected is for.
- I do not know what the field leaf is for.

for now pattern regex can not be enforce by typescript;
the min/max length can only be enforced using extra heavy typescript syntax, I prefer not to use it.
I have no way to distinguish integer from number.

the requires field can be enforced, but may create a lots of new conditional typing, So not for now.
some complex format fields can be converted to be more human readable.

That its.

the current version is now 0.0.4 a 0.0.5 is on the way.
 
- I do not know what the field protected is for.
- I do not know what the field leaf is for.

protected means that this API endpoint is proxied to pvedaemon running as root (e.g., because it needs to do storage operations that pveproxy/www-data can't do).

leaf simply means that when looking at the API as tree, that endpoint has no children.
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!