Skip to content

PVTX Rest API

PVTX is a tool to manage pantavisor devices using only tar files exported from PVR CLI. Allowing to manage without using any cloud service or docker container sources.

This rest api exposes the same actions availables on the pvtx CLI.

Endpoints

The api is available by default on __ORIGIN__/cgi-bin/pvtx the access is public it doesn't need password or credentials.

logs

The api has an endpoint to give you the logs by source, if source is not defined the returned logs are going to be the logs from the pantavisor.

curl __ORIGIN__/cgi-bin/logs

The available query string parameters are:

  • rev: the revision number
  • source: the source will be the platform name
  • tail: (true/false) activate the tail of logs
  • follow: (true/false) the follow parameters sents the logs as stream, only works if the tails arguments is true
  • tailn: same as tail -n parameter, only applies if the follow and tail parameters are set

show

The show endpoint show the current transaction running on pvtx. If doesn't exist any transaction will return and error.

curl __ORIGIN__/cgi-bin/pvtx/show

If doesn't have any transaction started will return HTTP/1.1 400 Bad Request with this body

{
  "error": "No active transaction.",
  "transaction": null
}

If there is a transaction will return the full state json of that transaction like this one.

Example response:

{
  "#spec": "pantavisor-service-system@1",
  "_config/pvr-sdk/etc/pvr-sdk/config.json": {
    "httpd": {
      "listen": "0.0.0.0",
      "port": "12368"
    }
  },
  "_hostconfig/pvr/docker.json": {
    "platforms": [
      "linux/arm64",
      "linux/arm"
    ]
  },
  "bsp/addon-plymouth.cpio.xz4": "beae6a7bb235916cac52bcfece64c30615cded8c4c640e6941e7ecabe53b4920",
  "bsp/build.json": {
    "altrepogroups": "",
    "branch": "master",
    "commit": "7d5ba78761e4d880c3403d642187bfdc93e49683",
    "gitdescribe": "014-rc9-12-g7d5ba78",
    "pipeline": "355967648",
    "platform": "rpi64",
    "project": "pantacor/pv-manifest",
    "pvrversion": "pvr version 022-15-g26ebb342",
    "target": "arm-rpi64",
    "time": "2021-08-19 15:08:44 +0000"
  },
  "bsp/firmware.squashfs": "c968a674d12258f00f4d9251637065a04abf7f95285308bfca7e4f6ccf9de7c5",
  "bsp/kernel.img": "b59438e4cb0db11689601e7e26e8dc6dad0b5007072edbf10e886a8dd51d2397",
  "bsp/modules.squashfs": "385f04fca555912f8655018f97cd09a2502fdd79afc14cd5fd57682d0a2cf4e0",
  "bsp/pantavisor": "405f907a1d1d086d89808c6fc691bf7d169e6e38b24c0110c7b950c4dda2742d",
  "bsp/run.json": {
    "addons": [
      "addon-plymouth.cpio.xz4"
    ],
    "firmware": "firmware.squashfs",
    "initrd": "pantavisor",
    "initrd_config": "",
    "linux": "kernel.img",
    "modules": "modules.squashfs"
  },
  "bsp/src.json": {
    "#spec": "bsp-manifest-src@1",
    "pvr": "https://pvr.pantahub.com/pantahub-ci/arm_rpi64_bsp_latest#bsp"
  },
  "network-mapping.json": {},
  "pvr-sdk/lxc.container.conf": "a69205914de2e8b95270f94591d5c015796590da5273db35ef6b2ed40631fcca",
  "pvr-sdk/root.squashfs": "896d66166794aa11f14ffe3c8fddc80a0563d85bae086d25dce69836d8eb0468",
  "pvr-sdk/root.squashfs.docker-digest": "35e1d5180e95445a7effdd44e8ef09405e2051d6c50c6b71965469fabc768368",
  "pvr-sdk/run.json": {
    "#spec": "service-manifest-run@1",
    "config": "lxc.container.conf",
    "name": "pvr-sdk",
    "root-volume": "root.squashfs",
    "storage": {
      "docker--etc-dropbear": {
        "persistence": "permanent"
      },
      "docker--etc-volume": {
        "persistence": "permanent"
      },
      "docker--home-pantavisor-.ssh": {
        "persistence": "permanent"
      },
      "docker--var-pvr-sdk": {
        "persistence": "permanent"
      },
      "lxc-overlay": {
        "persistence": "boot"
      }
    },
    "type": "lxc",
    "volumes": []
  },
  "pvr-sdk/src.json": {
    "#spec": "service-manifest-src@1",
    "args": {
      "PV_LXC_EXTRA_CONF": "lxc.mount.entry = /volumes/_pv/addons/plymouth/text-io var/run/plymouth-io-sockets none bind,rw,optional,create=dir 0 0",
      "PV_SECURITY_WITH_STORAGE": "yes"
    },
    "config": {},
    "docker_digest": "registry.gitlab.com/pantacor/pv-platforms/pvr-sdk@sha256:95b5d63a216773af9c8b2b82e25e2e9d40a049bae9c62cd2308eff5feb9b32dd",
    "docker_name": "registry.gitlab.com/pantacor/pv-platforms/pvr-sdk",
    "docker_source": "remote,local",
    "docker_tag": "arm32v6",
    "persistence": {},
    "template": "builtin-lxc-docker"
  },
  "storage-mapping.json": {},
}

begin

The begin endpoint start a new transaction only if there is not a trasaction started. If a transaction is already started this is going to fail.

curl -X POST __ORIGIN__/cgi-bin/pvtx/begin

If there is not error will return 200 with the full state response (the same seem on show)

Response:

{
  # ...FULL TRANSACTION
}

If there is an error will get this response

{
  "error": "No active transaction.",
  "transaction": { ...FULL TRANSACTION }
}

abort

This will abort the current transation running. If there is not transaction running is going to fail.

curl -X POST __ORIGIN__/cgi-bin/pvtx/abort

If everything is ok you will get a 200 OK response. If not an error similar to this.

{
  "error": "No active transaction. Start a transaction first.",
  "transaction": null
}

add

This add and update parts using the tar file result of a pvr export command.

curl -X PUT __ORIGIN__/cgi-bin/pvtx/add --data-binary @exported.tgz

This will fail if there is not transaction started or fails to add that exported file.

remove?part=PART_NAME

Remove any part of the current transaction. Using the example here on the show command we can see it has several parts, we could delete one by name, example: pvr-sdk.

curl -X PUT __ORIGIN__/cgi-bin/pvtx/remove?part=pvr-sdk

That will return the now state without the pvr-sdk part.

Could give you an error in case it fails.

{ "error": "ERROR_MESSAGE_STRING" }

commit

The commit endpoint allows to commit all the changes in the transaction and returns a revision ID that could be now run.

curl -X POST __ORIGIN__/cgi-bin/pvtx/commit

Response:

{
  "revision": "locals/pvtx-1636485481-42c76d97"
}

If there is not transaction to commit you will get an error.

{
  "error": "No active transaction. Start a transaction first.",
  "transaction": null
}

run?rev=REVISION_ID

Runs allow you to run any revision on the device.

curl -X POST __ORIGIN__/cgi-bin/pvtx/run?rev=locals/pvtx-1636485481-42c76d97

This will return the progress of that revision when success

{
  "status": "TESTING",
  "status-msg": "Awaiting to see if update is stable",
  "progress": 95
}

status?rev=REVISION_ID

Return the progress of a revision. The rev parameter will default to current.

curl __ORIGIN__/cgi-bin/pvtx/status

Response

{
  "rev": "REVISION_ID", 
  "progress": {
    "status": "UPDATED",
    "status-msg": "Update finished, revision not set as rollback point",
    "progress": 100
  }
}

or

curl __ORIGIN__/cgi-bin/pvtx/status?rev=locals/pvtx-1636485481-42c76d97

Response:

{
  "rev": "locals/pvtx-1636485481-42c76d97", 
  "progress": {
    "status": "UPDATED",
    "status-msg": "Update finished, revision not set as rollback point",
    "progress": 100
  }
}

get-config

Get all device configuration, device-meta and user-meta

curl __ORIGIN__/cgi-bin/pvtx/get-config

Response:

{
  "device": {
    "time": {
      "timeval": {
        "tv_sec": 33,
        "tv_usec": 72601
      },
      "timezone": {
        "tz_minuteswest": 0,
        "tz_dsttime": 0
      }
    },
    "sysinfo": {
      "uptime": 34,
      "loads.0": 34688,
      "loads.1": 8448,
      "loads.2": 2816,
      "totalram": 3990536192,
      "freeram": 3530027008,
      "sharedram": 0,
      "bufferram": 17485824,
      "totalswap": 0,
      "freeswap": 0,
      "procs": 86,
      "totalhigh": 0,
      "freehigh": 0,
      "mem_unit": 1
    },
    "storage": {
      "total": 31354646528,
      "free": 26463305728,
      "reserved": 1567732326,
      "real_free": 24895573402
    },
    "pantavisor.version": "018-11-g2ff4a37-221130-1076ae1",
    "pantavisor.uname": {
      "kernel.name": "Linux",
      "kernel.release": "4.19.127-v8+",
      "kernel.version": "#1 SMP PREEMPT Wed Nov 30 08:35:45 UTC 2022",
      "node.name": "(none)",
      "machine": "aarch64"
    },
    "pantavisor.revision": "155",
    "pantavisor.mode": "remote",
    "pantavisor.dtmodel": "Raspberry Pi 4 Model B Rev 1.2",
    "pantavisor.arch": "aarch64/64/EL",
    "pantahub.state": "idle",
    "pantahub.online": "1",
    "pantahub.claimed": "1",
    "pantahub.address": "51.158.191.153:443",
    "interfaces": {
      "lo.ipv4": [
        "127.0.0.1"
      ],
      "eth0.ipv4": [
        "192.168.68.109"
      ],
      "wlan0.ipv4": [
        "10.50.0.1"
      ],
      "lxcbr0.ipv4": [
        "10.0.3.1"
      ],
      "tailscale0.ipv4": [
        "100.109.175.19"
      ],
      "lo.ipv6": [
        "::1"
      ],
      "eth0.ipv6": [
        "fe80::1b19:27ae:2cb7:5ecc%eth0"
      ],
      "wlan0.ipv6": [
        "fe80::d3cc:6b18:8bce:b287%wlan0"
      ],
      "lxcbr0.ipv6": [
        "fe80::216:3eff:fe00:0%lxcbr0"
      ],
      "tailscale0.ipv6": [
        "fd7a:115c:a1e0:ab12:4843:cd96:626d:af13",
        "fe80::3706:f735:423:de8a%tailscale0"
      ],
      "vethN884XO.ipv6": [
        "fe80::fcbd:4ff:fe87:45b1%vethN884XO"
      ]
    }
  },
  "user": {
    "wireguard-vpn.enabled": "false",
    "tailscale.enabled": "true",
    "pvr-sdk.authorized_keys": "...........",
    "openvpn.enabled": "false",
    "fleet.channel": "arm_rpi64_bsp_latest",
    "cloudflared.upstream": "false"
  }
}

usermeta/save?key=KEY

Set an user meta value, this will add or update the key with the new value.

curl \
  -X POST \
  '__ORIGIN__/cgi-bin/pvtx/usermeta/save?key=newkey' \
  -H 'Content-Type: text/plain' \
  --data-raw "value of the usermeta"

Response:

{
  "newkey": "value of the usermeta",
  "wireguard-vpn.enabled": "false",
  "tailscale.enabled": "true",
  "openvpn.enabled": "false",
  "fleet.channel": "arm_rpi64_bsp_latest",
  "cloudflared.upstream": "false"
}

usermeta/delete?key=KEY

Remove a key from the user-meta

curl \
  -X PUT \
  '__ORIGIN__/cgi-bin/pvtx/usermeta/delete?key=newkey' \
  -H 'Content-Type: application/json'

Response:

{
  "wireguard-vpn.enabled": "false",
  "tailscale.enabled": "true",
  "openvpn.enabled": "false",
  "fleet.channel": "arm_rpi64_bsp_latest",
  "cloudflared.upstream": "false"
}