vME APIs
Overview
vME's API allows you to programatically manage the vME instances and Docker engine.
Base URL
The API is served over HTTPS and reverse-proxied under the /api path on the appliance. Every endpoint documented here is relative to that base:
https://<your-vme-host>/api
For example, the Show all pools route documented as /pool/show is called at https://<your-vme-host>/api/pool/show.
To keep the examples below concise, they assume a base_url (Python) / BASE_URL (curl) variable that you set once to your appliance's API base:
- Python
- Curl
# Set this once; every example below reuses it.
base_url = "https://<your-vme-host>/api"
# Set this once; every example below reuses it.
export BASE_URL="https://<your-vme-host>/api"
Authentication
All endpoints are authenticated according to the following headers schema:
{
"username" : "xxxxxx", # your username
"api-key" : "xxxxxx" # your api-key
}
The examples assume these are defined once as headers (Python) or passed as -H flags (curl). Some routes additionally require an administrator account; those are marked Admin only in this reference.
The admin API for managing agents, dispatching jobs, and orchestrating onboarding workflows is documented below under Agent API and Workflow API.
Disk Partition Details
This API call retrieves all disk details like name, partitions, model and size.
GET /zfs/disks
-
AUTHENTICATIONS:
headers -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/zfs/disks", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/zfs/disks"
Pool Routes
Show all pools
This API Call is used to show all the current pools that are existing.
GET /pool/show
-
AUTHENTICATIONS:
headers -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/pool/show", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/pool/show"
Create a pool
Here, we are creating a pool from this API call and the respective body schema
POST /pool/create
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool",
"device" : ["test1","test2"]
}Name Type Description name requiredString Name of pool to be created.device requiredList List of device names. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "vme-pool",
"device" : ["nvme0n2", "nvme0n3"]
}
response = requests.post(f"{base_url}/pool/create", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'vme-pool', 'device': ['nvme0n2', 'nvme0n3']}" \
"$BASE_URL/pool/create"
Destroy a pool
This API call is responsible for destroying a pool that already exists
DELETE /pool/destroy
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool"
}Name Type Description name requiredString Name of pool to be destroyed. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "vme-pool"
}
response = requests.delete(f"{base_url}/pool/destroy", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'vme-pool'}" \
"$BASE_URL/pool/destroy"
Show current status of a pool
This API call will let us know what the current status is for a specific pool, which could be active,creating or destroyed.
GET /pool/status
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool"
}Name Type Description name requiredString The name of the pool to show status on. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
"name" : "vme-pool"
}
response = requests.get(f"{base_url}/pool/status", params=params, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/pool/status?name=vme-pool"
Show history of a pool
Here, we can check all the operations that have been performed on that pool, from when it was created, till it has been destroyed.
GET /pool/history
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool"
}Name Type Description name requiredString The name of the pool to run the history command on. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
"name" : "vme-pool"
}
response = requests.get(f"{base_url}/pool/history", params=params, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/pool/history?name=vme-pool"
Register a pool
Here we can register the pool for creation of sources and other operations like cloning and snapshotting.
POST /pool/register
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool"
}Name Type Description name requiredString The name of the pool to be registered. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {"name" : "vme-pool"}
response = requests.post(f"{base_url}/pool/register", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'vme-pool'}" \
"$BASE_URL/pool/register"
Source Routes
Show all sources
This API call will return all sources present under the specified pool
GET /source/show
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool"
}Name Type Description pool_name optionalString Name of pool, default is vme-pool. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
"pool_name" : "vme-pool"
}
response = requests.get(f"{base_url}/source/show", params=params, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/source/show?pool_name=vme-pool"
Create a source
We can create a source under a particular pool name along with other properties like size/quote,compression type, database method and so on.
POST /source/create
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
- database method:
container{
"pool_name" : "vme-pool",
"name" : "foo",
"quota" : "1G",
"compression" : "lzjb"
} - database method
network, NFS{
"pool_name" : "vme-pool",
"name" : "foo",
"compression" : "lzjb",
"database_method" : "network",
"network_info" : {
"type" : "nfs"
}
} - database method
network, iSCSI{
"pool_name" : "vme-pool",
"name" : "foo",
"compression" : "lzjb",
"database_method" : "network",
"network_info" : {
"type" : "iscsi",
"auto_grow" : true,
"auto_grow_max_gb" : 16384
}
}
Name Type Description name requiredString Name of source to be created. pool_name requiredString Name of pool that contains a source. dbtype optionalString Database type, such as mysql, mariadb, mssql, mongodb etc., used to label a source, default is unknown.quota optionalString A limit on the amount of disk space a dataset can consume, for example, 10Gfor ten GB.compression optionalString Name of process where data is stored using less disk space, the name can be one of on,off,lzjb,gzip,gzip-1,gzip-2,gzip-3,gzip-4,gzip-5,gzip-6,gzip-7,gzip-8,gzip-9,zle,lz4,False, default isFalse.database_method optionalString container(default) ornetwork. Usenetworkto expose the source over NFS or iSCSI so an external host can mount it.network_info optionalDictionary Required when database_methodisnetwork. Holds the network settings below (at minimumtype).network_info.type requiredString nfsoriscsi. Required insidenetwork_info.network_info.auto_grow optionalBoolean iSCSI only. When true, the volume is thin-provisioned and grows on demand up toauto_grow_max_gb. Defaultfalse.network_info.auto_grow_max_gb optionalInteger iSCSI only. Maximum size (GB) the volume can grow to when auto_growis enabled. Default16384.network_info.vsize optionalInteger iSCSI only. Fixed volume size (GB). Used when auto_growisfalse; if omitted or0, the volume auto-grows.noteFor iSCSI, creating a source with
database_method: networkprovisions the iSCSI target and LUN automatically as part of source creation - no separate call is needed to expose it. For NFS, use/db/network/createafter creating the source to publish the share and set the client allow-list (client_address). - database method:
-
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"name" : "foo"
}
response = requests.post(f"{base_url}/source/create", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"pool_name": "vme-pool", "name": "foo"}' \
"$BASE_URL/source/create"
Modify a source
This API call is used to understand and modify the source properties as per use case.
POST /source/modify
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo",
"property" : {
"database_method" :"network",
"quota":"5G",
"dbtype":"mysql",
"compression":"gzip"
}
}Name Type Description name requiredString Name of source to be modified. pool_name requiredString Name of pool that contains a source. property requiredDictionary The properties of the source to be modified. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"name" : "foo",
"property" : {
"database_method" : "network",
"quota" : "5G",
"dbtype" : "mysql",
"compression" : "gzip",
"client_address" : "9.87.65.43"
}
}
response = requests.post(f"{base_url}/source/modify", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"pool_name": "vme-pool", "name": "foo", "property" : {"database_method" : "network", "quota" : "5G", "dbtype" : "mysql", "compression" : "gzip", "client_address" : "9.87.65.43"}}' \
"$BASE_URL/source/modify"
Rename a source
PUT /source/rename
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"currentname" : "foo",
"newname" : "foofoo"
}Name Type Description pool_name requiredString Name of pool that contains a source. currentname requiredString Name of source to be renamed. newname requiredString New source name. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"currentname" : "foo",
"newname" : "foofoo"
}
response = requests.put(f"{base_url}/source/rename", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X PUT \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'currentname': 'foo', 'newname': 'foofoo'}" \
"$BASE_URL/source/rename"
Destroy a source
This is used to remove a source listed under that specific pool.
DELETE /source/destroy
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo"
}Name Type Description pool_name requiredString Name of pool that contains a source. source_name requiredString Name of source to be destroyed. recursive optionalBoolean The recursive option, default is False. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"source_name" : "foo"
}
response = requests.delete(f"{base_url}/source/destroy", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'source_name': 'foo'}" \
"$BASE_URL/source/destroy"
Snapshot Routes
Show all snapshots
GET /snapshot/show
This API call is used to list all snapshots taken under the particular source.
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "vme-pool",
"source_name" : "foo"
}Name Type Description pool_name optionalString Name of pool. source_name optionalString Name of source/clone. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
"pool_name" : "vme-pool"
}
response = requests.get(f"{base_url}/snapshot/show", params=params, headers=headers)
if response.status_code < 200:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/snapshot/show?pool_name=vme-pool"
Create a snapshot
POST /snapshot/create
This is used to create a snapshot under the particular source name which can be used for cloning.
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo",
"name" : "snap"
}Name Type Description pool_name requiredString Name of pool. source_name requiredString Name of source/clone. name requiredString Name of snapshot/bookmark to be created. recursive optionalBoolean Recursive option, default is False. -
RESPONSE: On success the response now includes a
stopped_containersarray listing any containers that were stopped to take a crash-consistent snapshot (empty if none).{
"status": 1,
"message": "snapshot created successfully",
"stopped_containers": ["container-a", "container-b"]
}Crash-consistent snapshotsIf the source has a container mount, vME finds any running containers bind-mounted on that source and stops them before taking the snapshot, so the captured data is consistent. The containers that were stopped are returned in
stopped_containers. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"source_name" : "foo",
"name" : "snap"
}
response = requests.post(f"{base_url}/snapshot/create", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'source_name': 'foo', 'name': 'snap'}" \
"$BASE_URL/snapshot/create"
Rollback a snapshot
POST /snapshot/rollback
This functionality is used to go back to the last saved instance of the snapshot previously captured
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap",
"force" : true
}Name Type Description pool_name requiredString Name of pool. source_name requiredString Name of source/clone. snapshot_name requiredString Name of snapshot/bookmark to be created. force optionalBoolean Force option to rollback, default is False. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap",
"force" : True
}
response = requests.post(f"{base_url}/snapshot/rollback", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'source_name': 'foo', 'snapshot_name': 'snap', 'force': true}" \
"$BASE_URL/snapshot/rollback"
Rename a snapshot
PUT /snapshot/rename
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo",
"currentname" : "snap",
"newname" : "snap-new"
}Name Type Description pool_name requiredString Name of pool. source_name requiredString Name of source/clone. currentname requiredString Name of snapshot/bookmark to be renamed. newname requiredString New name of snapshot/bookmark. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"source_name" : "foo",
"currentname" : "snap",
"newname" : "snap-new"
}
response = requests.put(f"{base_url}/snapshot/rename", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X PUT \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'source_name': 'foo', 'currentname': 'snap', 'newname': 'snap-new'}" \
"$BASE_URL/snapshot/rename"
Destroy a snapshot
DELETE /snapshot/destroy
Helps remove a previously existing snapshot in the source list.
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap"
}Name Type Description pool_name requiredString Name of pool. source_name requiredString Name of source/clone. snapshot_name requiredString Name of snapshot/bookmark to be destroyed. recursive optionalBoolean The recursive option, default is False. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap"
}
response = requests.delete(f"{base_url}/snapshot/destroy", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'source_name': 'foo', 'snapshot_name': 'snap'}" \
"$BASE_URL/snapshot/destroy"
Clone Routes
Show all clones
GET /clone/show
Lists down all available clones listed under that specific source
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap"
}Name Type Description pool_name optionalString Name of pool. source_name optionalString Name of source. snapshot_name optionalString Name of snapshot. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
'pool_name' : 'vme-pool'
}
response = requests.get(f"{base_url}/clone/show", params=params, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H 'api-key: xxxx' \
"$BASE_URL/clone/show?pool_name=vme-pool"
Create a clone
POST /clone/create
This API call assistsis responsible in creating a copy from the snapshot that has been captured.
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
- database method
container(default){
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap",
"name" : "foo-clone"
} - database method
network, iSCSI{
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap",
"name" : "foo-clone",
"database_method" : "network",
"network_info" : {
"type" : "iscsi"
}
}
Name Type Description pool_name requiredString Name of pool. source_name requiredString Name of source. snapshot_name requiredString Name of snapshot. name requiredString Name of clone to be created. dbtype optionalString Database type, such as mysql, mariadb, mssql, mongodb etc., used to label a source, default is unknown.size optionalInteger Number of clones (clonefarm) to be created, default is 1.database_method optionalString container(default) ornetwork. Usenetworkto expose the clone over NFS or iSCSI so an external host can mount it.network_info optionalDictionary Required when database_methodisnetwork. Must containtype(nfsoriscsi). A clone inherits its size from the snapshot, so novsizeis needed.network_info.type requiredString nfsoriscsi. Required insidenetwork_info.noteFor an iSCSI clone, the iSCSI target and LUN are created automatically as part of clone creation - no separate call is needed to expose it. For NFS, use
/db/network/createafter the clone is created to publish the share and set the client allow-list. - database method
-
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"source_name" : "foo",
"snapshot_name" : "snap",
"name" : "foo-clone"
}
response = requests.post(f"{base_url}/clone/create", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'source_name': 'foo', 'snapshot_name': 'snap', 'name': 'foo-clone'}" \
"$BASE_URL/clone/create"
Modify a clone
POST /clone/modify
Here we can modify the properties of the clone based on the compression type, db type, quota and so on.
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"name" : "foo-clone",
"property" : {
"database_method" : "network",
"quota" : "5G",
"dbtype" : "mysql",
"compression" : "gzip"
}
}Name Type Description name requiredString Name of clone to be modified. pool_name requiredString Name of pool that contains a source. property requiredDictionary The properties of the source to be modified. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"name" : "foo-clone",
"property" : {
"database_method" : "network",
"quota" : "5G",
"dbtype" : "mysql",
"compression" : "gzip",
"client_address" : "9.87.65.43"
}
}
response = requests.post(f"{base_url}/clone/modify", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"pool_name": "vme-pool", "name": "foo-clone", "property" : {"database_method" : "network", "quota" : "5G", "dbtype" : "mysql", "compression" : "gzip", "client_address" : "9.87.65.43"}}' \
"$BASE_URL/clone/modify"
Rename a clone
PUT /clone/rename
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"currentname" : "foo-clone",
"newname" : "foofoo-clone"
}Name Type Description pool_name requiredString Name of pool. currentname requiredString Name of clone to be renamed. newname requiredString New name of clone. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"currentname" : "foo-clone",
"newname" : "foofoo-clone"
}
response = requests.put(f"{base_url}/clone/rename", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X PUT \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'currentname': 'foo-clone', 'newname': 'foofoo-clone'}" \
"$BASE_URL/clone/rename"
Destroy a clone
DELETE /clone/destroy
Removes an existing clone under the specified pool
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"clone_name" : "foo-clone"
}Name Type Description pool_name requiredString Name of pool. clone_name requiredString Name of clone to be destroyed. recursive optionalBoolean The recursive option, default is False. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"clone_name" : "foo-clone"
}
response = requests.delete(f"{base_url}/clone/destroy", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'clone_name': 'foo-clone'}" \
"$BASE_URL/clone/destroy"
Docker Image Routes
Pull an image
Similar to the docker pull command.
POST /docker/image/pull
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"repository" : "mysql",
"tag" : "8.4.0",
"credential" : {"username":"","password":""}
}Name Type Description repository requiredString Name of image repository to be pulled. tag optionalString Name of tag, default is latest.dbtype optionalString Database type, such as mysql, mariadb, mssql, mongodb etc., used to label a source, default is same as repository name. credential optionalDictionary Information used to verify repository accession, default is None. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"repository" : "mysql",
}
response = requests.post(f"{base_url}/docker/image/pull", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'repository': 'mysql'}" \
"$BASE_URL/docker/image/pull"
Register an image
POST /docker/image/register
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "mysql:latest",
"dbtype" : "mysql"
}Name Type Description name requiredString Name of image name:tagto be registered.dbtype optionalString Database type, such as mysql, mariadb, mssql, mongodb etc., used to label a source, default is same as repository name. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "mysql:latest",
"dbtype" : "mysql"
}
response = requests.post(f"{base_url}/docker/image/register", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'mysql:latest', 'dbtype': 'mysql'}" \
"$BASE_URL/docker/image/register"
List all images
Similar to the docker images command.
GET /docker/image/list
-
AUTHENTICATIONS:
headers -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/docker/image/list", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/docker/image/list"
Save an image as .tar
POST /docker/image/save
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"image" : "mysql:latest",
"filename" : "myimage.tar"
}Name Type Description image requiredString Name of image name:tagto be saved.filename requiredString Filename of saved image, the tar file will be saved at /home/vme/uploads. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"image" : "mysql:latest",
"filename" : "myimage.tar"
}
response = requests.post(f"{base_url}/docker/image/save", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'image': 'mysql:latest', 'filename': 'myimage.tar'}" \
"$BASE_URL/docker/image/save"
Load an image from .tar
POST /docker/image/load
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"filename" : "myimage.tar"
}Name Type Description filename requiredString Filename of image to be loaded. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"filename" : "myimage.tar"
}
response = requests.post(f"{base_url}/docker/image/load", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'filename': 'myimage.tar'}" \
"$BASE_URL/docker/image/load"
Remove an image
DELETE /docker/image/remove
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"image" : "mysql:latest"
}Name Type Description image requiredString Name of image name:tagto be removed. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"image" : "mysql:latest"
}
response = requests.delete(f"{base_url}/docker/image/remove", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'image': 'mysql:latest'}" \
"$BASE_URL/docker/image/remove"
Docker Container Routes
Create a container
Similar to the docker run command.
POST /docker/container/create
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"image" : "mysql:latest",
"name" : "foo-mysql",
"volumes" : ["/vme-pool/sources/foo:/var/lib/mysql"],
"ports" : "8888:3306",
"environment" : ["MYSQL_ROOT_PASSWORD=secret_password"]
}Name Type Description image requiredString Name of image. name requiredString Name of container to be created. detach optionalBoolean Boolean for running container in the background, default is True.command optionalString Command to run in the container, default is None.environment optionalList or Dictionary Environment variables to set inside the container, as a dictionary or a list of strings in the format ["SOMEVARIABLE=xxx"], default isNone.volumes optionalList or Dictionary Configure volumes mounted inside the container, default is [].ports optionalString Ports to bind inside the container in the format "a:b,c:d,...", for example8080:80means map port8080on the host to TCP port80in the container, default isNone. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"image" : "mysql:latest",
"name" : "foo-mysql",
"volumes" : ["/vme-pool/sources/foo:/var/lib/mysql"],
"ports" : "8888:3306",
"environment" : ["MYSQL_ROOT_PASSWORD=secret_password"]
}
response = requests.post(f"{base_url}/docker/container/create", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'image': 'mysql:latest', 'name': 'foo-mysql', 'volumes': ['/vme-pool/sources/foo:/var/lib/mysql'], 'ports': '8888:3306', 'environment': ['MYSQL_ROOT_PASSWORD=secret_password']}" \
"$BASE_URL/docker/container/create"
List all containers
Similar to the docker ps -a command. This endpoint is also used to retrieve container connection information, including each container's environment variables (for example database credentials such as POSTGRES_PASSWORD, POSTGRES_USER, and POSTGRES_DB), port mappings, mount paths, and database type.
GET /docker/container/list
-
AUTHENTICATIONS:
headers -
RESPONSE SCHEMA: On success (
statusis1), theresultfield is a list of container objects. Each object includes anenvarray of strings inKEY=valueformat (the same values shown in the vME UI under Connection Information for a container).Name Type Description name String Container name. id String Full Docker container ID. short_id String Short Docker container ID. image String Image reference (for example postgres:17).status String Container state from Docker Engine (for example running,paused).port Object Docker port bindings ( NetworkSettings.Ports).mounted List Bind mounts as host_path:container_pathstrings.dbtype String Database type from the registered image (for example postgres).created String Human-readable time since the container was created. env List Environment variables as KEY=valuestrings.Example excerpt from
resultfor a single container:{
"name": "posttest",
"id": "205ce1989e609ecf7ffbaa616df26a9bf14cf34600e79d94cd0592b7a2bd2d91",
"short_id": "205ce1989e60",
"image": "postgres:17",
"status": "running",
"dbtype": "postgres",
"created": "12 minutes ago",
"port": {},
"mounted": ["/testing/sources/postgressource:/var/lib/postgresql/data"],
"env": [
"POSTGRES_PASSWORD=Password123",
"POSTGRES_USER=VME",
"POSTGRES_DB=VME",
"PATH=/usr/local/sbin:/usr/local/bin:...",
"GOSU_VERSION=1.19",
"LANG=en_US.utf8",
"PG_MAJOR=17",
"PG_VERSION=17.10-1.pgdg13+1",
"PGDATA=/var/lib/postgresql/data"
]
} -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/docker/container/list", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/docker/container/list"
Start a container
Similar to the docker start command.
POST /docker/container/start
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "foo-mysql"
}Name Type Description name requiredString Name of container to be started. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "foo-mysql"
}
response = requests.post(f"{base_url}/docker/container/start", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'foo-mysql'}" \
"$BASE_URL/docker/container/start"
Stop a container
Similar to the docker stop command.
POST /docker/container/stop
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "foo-mysql"
}Name Type Description name requiredString Name of container to be stoped. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "foo-mysql"
}
response = requests.post(f"{base_url}/docker/container/stop", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'foo-mysql'}" \
"$BASE_URL/docker/container/stop"
Execute command inside a container
Similar to the docker exec command.
POST /docker/container/exec
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "foo-mysql",
"command" : "mysql --user=root --password=\"secret_password\" -e \"show databases;\""
}Name Type Description name requiredString Name of container to be executed. command requiredString or List Commands to be executed. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "foo-mysql",
"command" : "mysql --user=root --password=\"secret_password\" -e \"show databases;\""
}
response = requests.post(f"{base_url}/docker/container/exec", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'foo-mysql', 'command': 'mysql --user=root --password=\"secret_password\" -e \"show databases;\"'}" \
"$BASE_URL/docker/container/exec"
Remove a container
Delete /docker/container/remove
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "foo-mysql"
}Name Type Description name requiredString Name of container to be removed. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"name" : "foo-mysql"
}
response = requests.delete(f"{base_url}/docker/container/remove", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'name': 'foo-mysql'}" \
"$BASE_URL/docker/container/remove"
Get a container log
GET /docker/container/log
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "foo-mysql"
}Name Type Description name requiredString Name of container to get the log. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
"name" : "foo-con"
}
response = requests.get(f"{base_url}/docker/container/log", params=params, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/docker/container/log?name=foo-con"
Get a container detail
GET /docker/container/detail
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"name" : "foo-mysql"
}Name Type Description name requiredString Name of container to get the detail. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
params = {
"name" : "foo-con"
}
response = requests.get(f"{base_url}/docker/container/detail", params=params, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/docker/container/detail?name=foo-con"
Database Routes
Connect to database
POST /db/connect
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"dbtype" : "mysql",
"host" : "localhost",
"user" : "root",
"password" : "secret_password",
"port" : 8888
}The body is the required credential information, the general formatting is
{"dbtype": "<database_type>", "host": "<host>", "user": "<user>", "password": "<password>", "port": "<port>"}. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
credential = {
"dbtype" : "mysql",
"host" : "localhost",
"user" : "root",
"password" : "secret_password",
"port" : 8888
}
response = requests.post(f"{base_url}/db/connect", json=credential, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'dbtype': 'mysql', 'host': 'localhost', 'user': 'root', 'password': 'secret_password', 'port': 8888}" \
"$BASE_URL/db/connect"
Receive database
Receive backup and restore dataset.
POST /db/receive
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"pool_name" : "vme-pool",
"dataset_name" : "restored-sender-from-backup",
"dbtype" : "mysql",
"src" : "demo-pool-sources-sender@now-20230829183552.vmebk"
}Name Type Description pool_name requiredString Name of pool. dataset_name requiredString Name of dataset to be restored. dbtype optionalString Database type, such as mysql, mariadb, mssql, mongodb etc., used to label a source, default is unknown.src requiredString Path name of received backup file in .vmebkformat, the default absolute path is/enov8/vme/data/<filename>when only the filename is provided. -
RESPONSE: Returns HTTP 202 with a
task_id. The restore runs as a background task; poll its progress with/tasks/<task_id>using the returnedtask_id.{
"task_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "queued"
} -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"pool_name" : "vme-pool",
"dataset_name" : "restored-sender-from-backup",
"src" : "demo-pool-sources-sender@now-20230829183552.vmebk"
}
response = requests.post(f"{base_url}/db/receive", json=body, headers=headers)
if response.status_code < 500:
result = response.json()
print(result)
# Use the task_id to track the restore
task_id = result.get('task_id')curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'pool_name': 'vme-pool', 'dataset_name': 'restored-sender-from-backup', 'src': 'demo-pool-sources-sender@now-20230829183552.vmebk'}" \
"$BASE_URL/db/receive"
Send database
POST /db/send
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
- pool2pool
{
"type" : "pool2pool",
"dataset" : "demo-pool/sources/sender@now",
"receiver" : {
"pool_name" : "vme-pool",
"dataset_name" : "receiver-snap"
}
} - sys2sys
{
"type" : "sys2sys",
"dataset" : "demo-pool/sources/sender@now",
"receiver" : {
"address" : "https://9.87.654.321",
"username" : "admin",
"api-key" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"pool_name" : "vme-pool",
"dataset_name" : "receiver-sys2sys-snap"
}
}sys2sys authenticationFor a
sys2systransfer, provide the receiver'saddress,username, and adminapi-key. The sending appliance uses theapi-keyto establish SSH trust with the receiver automatically, registering its own managed public key on the target.
Name Type Description type requiredString Sending type, pool2poolorsys2sys.dataset requiredString Name of dataset to be send. receiver requiredDictionary Information of receiver. For pool2poolcontainspool_nameanddataset_name. Forsys2sysalso containsaddress,username, andapi-key(the receiver's admin API key, used to automatically establish SSH trust).receiver.ssh_address optionalString sys2sysonly. Override the host used for the SSH/ZFS transfer when it differs from the receiver's APIaddress(e.g. a separate data network). Defaults to the host inaddress.overwrite optionalBoolean If true, destroy an existing destination dataset on the receiver before sending. Default isfalse(a name clash fails the transfer).keep_snapshot optionalBoolean If true, keep the temporary snapshot created for the send operation. Default isfalse(snapshot is deleted after send completes). - pool2pool
-
RESPONSE: Returns HTTP 202 with a
task_idthat can be used to track the transfer status.{
"task_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "queued"
} -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"type" : "pool2pool",
"dataset" : "demo-pool/sources/sender@now",
"receiver" : {
"pool_name" : "vme-pool",
"dataset_name" : "receiver-snap"
}
}
response = requests.post(f"{base_url}/db/send", json=body, headers=headers)
if response.status_code < 500:
result = response.json()
print(result)
# Use the task_id to check status later
task_id = result.get('task_id')curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'type': 'pool2pool', 'dataset': 'demo-pool/sources/sender@now', 'receiver': {'pool_name': 'vme-pool', 'dataset_name': 'receiver-snap'}}" \
"$BASE_URL/db/send"
Get send status
Check the status of a database send operation by task ID or get all transfer history for a specific dataset.
GET /db/send/status
-
AUTHENTICATIONS:
headers -
QUERY PARAMETERS: (mutually exclusive - provide either
task_idordataset, not both)Name Type Description task_id optionalString The task ID returned from the /db/sendendpoint. Returns status for a specific transfer.dataset optionalString Dataset name (e.g., vme-pool/sources/foo). Returns all transfer history for this dataset. -
RESPONSE SCHEMA:
- Query by task_id: Returns information about a single transfer
{
"task_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "completed",
"progress_percentage": 100,
"message": "Transfer completed successfully",
"error": null,
"dataset": "demo-pool/sources/sender@now",
"dataset_type": "snapshot",
"send_type": "pool2pool",
"destination": {
"pool_name": "vme-pool",
"dataset_name": "receiver-snap",
"address": null
},
"started_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:35:00Z",
"initiated_by": "admin"
} - Query by dataset: Returns all transfers for the dataset
{
"dataset": "vme-pool/sources/foo",
"total_transfers": 2,
"transfers": [
{
"task_id": "...",
"status": "completed",
"progress_percentage": 100,
...
},
{
"task_id": "...",
"status": "in_progress",
"progress_percentage": 45,
...
}
]
}
Status values:
queued- Transfer is waiting to startin_progress- Transfer is currently runningcompleted- Transfer completed successfullyfailed- Transfer failed (seeerrorfield for details)
- Query by task_id: Returns information about a single transfer
-
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
# Check status by task_id
params = {
"task_id" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
response = requests.get(f"{base_url}/db/send/status", params=params, headers=headers)
if response.status_code < 500:
print(response.json())
# Or check all transfers for a dataset
params = {
"dataset" : "vme-pool/sources/foo"
}
response = requests.get(f"{base_url}/db/send/status", params=params, headers=headers)
if response.status_code < 500:
print(response.json())# Check status by task_id
curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/db/send/status?task_id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Or check all transfers for a dataset
curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/db/send/status?dataset=vme-pool/sources/foo"
Cancel a send
Cancel an in-flight database send (or receive) by its task ID. The running transfer task is signalled to stop and its transfer-history record is marked cancelled.
POST /db/send/cancel
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"task_id" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}Name Type Description task_id requiredString The task_idreturned by/db/sendor/db/receive. May also be supplied as a query parameter (?task_id=). -
RESPONSE:
200on success. A transfer that has already finished (completed,failed, or alreadycancelled) is returned as-is with200. An unknowntask_idreturns404. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = { "task_id" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
response = requests.post(f"{base_url}/db/send/cancel", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'task_id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'}" \
"$BASE_URL/db/send/cancel"
Backup database
Get all backup filenames.
GET /db/backup
-
AUTHENTICATIONS:
headers -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/db/backup", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/db/backup"
Create backup file.
POST /db/backup
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"dataset" : "vme-pool/sources/foo"
}Name Type Description dataset requiredString Name of dataset to be backup. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"dataset" : "vme-pool/sources/foo"
}
response = requests.post(f"{base_url}/db/backup", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d "{'dataset' : 'vme-pool/sources/foo'}" \
"$BASE_URL/db/backup"
Create a network share
Expose a source or clone dataset over the network (NFS or iSCSI, depending on how the dataset's network type is configured) so a database client can mount it. Use this to serve a restored/cloned database to an external host.
POST /db/network/create
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"full_name" : "vme-pool/sources/foo",
"client_address" : ["10.0.0.21", "10.0.0.22"]
}Name Type Description full_name requiredString Fully-qualified dataset, in the form <pool>/sources/<source>or<pool>/clones/<clone>. The dataset must already have a supported network type configured.client_address requiredString or List One IPv4 address, or a list of IPv4 addresses, permitted to access the share. client_username optionalString Client username for the share. Default admin.client_password optionalString Client password for the share. Default admin.anonuid optionalNumber Anonymous UID for NFS mapping. Default 117.anongid optionalNumber Anonymous GID for NFS mapping. Default 122. -
RESPONSE:
{ "status": 1, "message": "Network create success : <full_name>" } -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"full_name" : "vme-pool/sources/foo",
"client_address" : ["10.0.0.21", "10.0.0.22"]
}
response = requests.post(f"{base_url}/db/network/create", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"full_name": "vme-pool/sources/foo", "client_address": ["10.0.0.21", "10.0.0.22"]}' \
"$BASE_URL/db/network/create"
Delete a network share
Tear down an existing network share for a dataset.
DELETE /db/network/delete
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"full_name" : "vme-pool/sources/foo"
}Name Type Description full_name requiredString Fully-qualified dataset ( <pool>/sources/<source>or<pool>/clones/<clone>) whose share should be removed. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = { "full_name" : "vme-pool/sources/foo" }
response = requests.delete(f"{base_url}/db/network/delete", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"full_name": "vme-pool/sources/foo"}' \
"$BASE_URL/db/network/delete"
Poll a background task
Several operations run asynchronously and return a task_id (for example /db/receive and /db/send). Use this endpoint to poll a task's state by its ID.
GET /tasks/<task_id>
-
AUTHENTICATIONS:
headers -
PATH PARAMETERS:
Name Type Description task_id requiredString The task ID returned by an asynchronous endpoint. -
RESPONSE: A
stateofPENDING,STARTED,SUCCESS, orFAILURE. OnSUCCESSthe payload is returned inresult; otherwise a human-readablestatusdescribes the current state or error.{ "state": "SUCCESS", "result": { "status": 1, "message": "done" } }tipThis is the generic Celery task poll used after
dbandpooloperations. It is not the same as the setup wizard's/setup/task/<id>poll. For database send transfers you can alternatively use/db/send/status, which returns richer transfer history. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
task_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
response = requests.get(f"{base_url}/tasks/" + task_id, headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/tasks/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
User Management Routes
Add User
This API call adds a new user. Requires an administrator account.
POST /user/add
-
AUTHENTICATIONS:
headers- Admin only -
REQUEST BODY SCHEMA:
{
"username": "jane",
"name": "Jane Doe",
"mail": "jane@company.com",
"group_id": 1,
"auth_type": "ldap"
}Name Type Description username requiredString Login name for the new user. name requiredString Full/display name of the user. mail requiredString Email address for the user. group_id optionalNumber ID of the group to assign the user to. If omitted, a new group is created and the user is assigned to it (used for first-time setup). auth_type requiredString Authentication type (e.g. ldaporlocal).password optionalString Required when auth_typeislocal(or omitted). Initial password for the new local user. Not used forldap. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"username": "jane",
"name": "Jane Doe",
"mail": "jane@company.com",
"group_id": 1,
"auth_type": "ldap"
}
response = requests.post(f"{base_url}/user/add", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"username": "jane", "name": "Jane Doe", "mail": "jane@company.com", "group_id": 1, "auth_type": "ldap"}' \
"$BASE_URL/user/add"
Modify User
This API call modifies an existing user. You can update email, full name, auth type, and (for local users) password.
POST /user/modify
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"username": "jane",
"current_password": "OldPass123!",
"password": {
"current": "OldPass123!",
"new": "NewPass456!",
"confirm": "NewPass456!"
}
}Name Type Description username requiredString Login name of the user to modify (must be your own account; cannot be changed). current_password requiredString Your current password, required to authorise any modification. password optionalObject To change the password, pass an object with current,new, andconfirmkeys (all three required). Omit to leave the password unchanged.name optionalString Updated full/display name. mail optionalString Updated email address. auth_type optionalString Authentication type (e.g. localorldap).rotate_api_key optionalBoolean If true, issue a new API key for the user; the new key is returned inupdated.api_key.note/user/modifyrequirescurrent_password, and a password change must be sent as a structured object (password: {current, new, confirm}). A user can only modify their own account. -
RESPONSE:
200with anupdatedobject listing the fields that changed (a changed password shows as***updated***; a rotated key appears asapi_key).{ "status": 1, "message": "user modify success", "updated": { "password": "***updated***" } } -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"username": "jane",
"current_password": "OldPass123!",
"password": {
"current": "OldPass123!",
"new": "NewPass456!",
"confirm": "NewPass456!"
}
}
response = requests.post(f"{base_url}/user/modify", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"username": "jane", "current_password": "OldPass123!", "password": {"current": "OldPass123!", "new": "NewPass456!", "confirm": "NewPass456!"}}' \
"$BASE_URL/user/modify"
Delete User
This API call deletes a user.
DELETE /user/delete
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"username": "ubuntu123",
"password": "MyPassword123!",
"confirm_text": "DELETE ubuntu123"
}Name Type Description username requiredString Login name of the user to delete. password requiredString Your password, required to authorise the deletion. confirm_text requiredString Confirmation phrase; must be the literal string DELETE <username>(e.g.DELETE ubuntu123).method optionalString Sign-in method used to verify the password. Default is password.note/user/deleterequires yourpasswordand aconfirm_textvalue of exactlyDELETE <username>in addition tousername. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"username": "ubuntu123",
"password": "MyPassword123!",
"confirm_text": "DELETE ubuntu123"
}
response = requests.delete(f"{base_url}/user/delete", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"username": "ubuntu123", "password": "MyPassword123!", "confirm_text": "DELETE ubuntu123"}' \
"$BASE_URL/user/delete"
Change Password
Change your own password using your current password. Authenticated users can only change their own password.
POST /user/changepass
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"username": "jane",
"password": "OldPass123!",
"new_password": "NewPass456!"
}Name Type Description username requiredString Your login name. Must match the authenticated user; changing another user's password returns 403.password requiredString Your current password. new_password requiredString The new password to set. -
RESPONSE:
{ "status": 1, "message": "password changed successfully" } -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"username": "jane",
"password": "OldPass123!",
"new_password": "NewPass456!"
}
response = requests.post(f"{base_url}/user/changepass", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"username": "jane", "password": "OldPass123!", "new_password": "NewPass456!"}' \
"$BASE_URL/user/changepass"
Get All Users
This API call returns all users. Requires an administrator account.
GET /admin/user/list
-
AUTHENTICATIONS:
headers- Admin only -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/admin/user/list", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/admin/user/list"
LDAP Configuration Routes
All LDAP configuration endpoints (GET/POST/PUT/DELETE on /user/ldap) require an administrator account. A separate POST /user/ldap/test endpoint (also admin-only) validates a connection without saving it.
Get LDAP Configuration
This API call retrieves the current LDAP configuration.
GET /user/ldap
-
AUTHENTICATIONS:
headers -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.get(f"{base_url}/user/ldap", headers=headers)
if response.status_code < 500:
print(response.json())curl -X GET \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/user/ldap"
Delete LDAP Configuration
This API call removes the LDAP configuration.
DELETE /user/ldap
-
AUTHENTICATIONS:
headers -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
response = requests.delete(f"{base_url}/user/ldap", headers=headers)
if response.status_code < 500:
print(response.json())curl -X DELETE \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
"$BASE_URL/user/ldap"
Create LDAP Configuration
This API call creates the LDAP server.
POST /user/ldap
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"server": "sample.com",
"port": 389,
"bind_dn": "cn=readonly,dc=company,dc=com",
"bind_password": "admin",
"user_search_base": "ou=users,dc=company,dc=com",
"user_filter": "(uid={adminuser})",
"vme_attrs": {"username": "uid", "name": "cn", "mail": "mail"}
}Name Type Description server requiredString Hostname or IP address of the LDAP server. port requiredNumber Port on which the LDAP server listens (e.g. 389 for LDAP, 636 for LDAPS). bind_dn requiredString Distinguished Name (DN) used to bind to the LDAP server. bind_password requiredString Password for the bind_dn account. user_search_base requiredString Base DN under which user entries are searched. user_filter requiredString LDAP search filter for users; placeholder (e.g. {adminuser}) is replaced by the login name.vme_attrs requiredObject Mapping of VME user fields ( username,name,mail) to LDAP attribute names. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"server": "sample.com",
"port": 389,
"bind_dn": "cn=readonly,dc=company,dc=com",
"bind_password": "admin",
"user_search_base": "ou=users,dc=company,dc=com",
"user_filter": "(uid={adminuser})",
"vme_attrs": {"username": "uid", "name": "cn", "mail": "mail"}
}
response = requests.post(f"{base_url}/user/ldap", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"server": "sample.com", "port": 389, "bind_dn": "cn=readonly,dc=company,dc=com", "bind_password": "admin", "user_search_base": "ou=users,dc=company,dc=com", "user_filter": "(uid={adminuser})", "vme_attrs": {"username": "uid", "name": "cn", "mail": "mail"}}' \
"$BASE_URL/user/ldap"
Update LDAP Configuration
This API call updates the existing LDAP configuration.
PUT /user/ldap
-
AUTHENTICATIONS:
headers -
REQUEST BODY SCHEMA:
{
"server": "sample.com",
"port": 389,
"bind_dn": "cn=readonly,dc=company,dc=com",
"bind_password": "admin",
"user_search_base": "ou=users,dc=company,dc=com",
"user_filter": "(uid={adminuser})",
"vme_attrs": {"username": "uid", "name": "cn", "mail": "mail"}
}Name Type Description server requiredString Hostname or IP address of the LDAP server. port requiredNumber Port on which the LDAP server listens (e.g. 389 for LDAP, 636 for LDAPS). bind_dn requiredString Distinguished Name (DN) used to bind to the LDAP server. bind_password requiredString Password for the bind_dn account. user_search_base requiredString Base DN under which user entries are searched. user_filter requiredString LDAP search filter for users; placeholder (e.g. {adminuser}) is replaced by the login name.vme_attrs requiredObject Mapping of VME user fields ( username,name,mail) to LDAP attribute names. -
EXAMPLE:
- Python
- Curl
# Download the requests library from https://docs.python-requests.org/en/latest/
import requests
body = {
"server": "sample.com",
"port": 389,
"bind_dn": "cn=readonly,dc=company,dc=com",
"bind_password": "admin",
"user_search_base": "ou=users,dc=company,dc=com",
"user_filter": "(uid={adminuser})",
"vme_attrs": {"username": "uid", "name": "cn", "mail": "mail"}
}
response = requests.put(f"{base_url}/user/ldap", json=body, headers=headers)
if response.status_code < 500:
print(response.json())curl -X PUT \
-H "Content-Type: application/json" \
-H "username: xxxxx" \
-H "api-key: xxxxx" \
-d '{"server": "sample.com", "port": 389, "bind_dn": "cn=readonly,dc=company,dc=com", "bind_password": "admin", "user_search_base": "ou=users,dc=company,dc=com", "user_filter": "(uid={adminuser})", "vme_attrs": {"username": "uid", "name": "cn", "mail": "mail"}}' \
"$BASE_URL/user/ldap"
Agent API
vME can drive database onboarding and clone workflows on remote hosts through enrolled agents (for example, the Windows iSCSI Agent). The endpoints in this section, together with the Workflow API, are the admin-facing surface for that automation.
Every endpoint in the Agent API and Workflow API sections requires an administrator account.
How it works:
- An administrator mints a one-time enrollment token (
POST /agent-token) and gives it to whoever installs the agent. - The agent enrols itself with that token, receives a long-lived agent key, and runs as a background service on the host.
- The agent polls vME for assigned jobs, runs each one locally, and reports progress and results back.
- An administrator dispatches jobs (
POST /agent-job) and monitors them, or drives a higher-level onboarding workflow that sequences jobs across two appliances.
Enrollment, polling, and progress reporting are performed by the agent itself using its own credentials (x-agent-id / x-agent-key). Those routes are part of the agent's protocol and are not called by hand.
Create an enrollment token
An enrollment token is a single-use, time-limited secret that lets a host register one agent.
POST /agent-token
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{
"label" : "prod-sql-01",
"environment" : "prod",
"ttl_minutes" : 60
}Name Type Description label optionalString Friendly name for the agent that will enrol with this token. environment optionalString Environment the host belongs to (e.g. prod,dev,test).ttl_minutes optionalNumber How long the token stays valid. Defaults to a short-lived window suitable for one install. - RESPONSE: The raw
tokenis returned once - store it immediately, it cannot be retrieved again.{ "result": { "token_id": "...", "token": "...", "environment": "prod", "expires_at": "..." } } - EXAMPLE:
curl -X POST \
-H "Content-Type: application/json" \
-H "username: xxxxx" -H "api-key: xxxxx" \
-d '{"label": "prod-sql-01", "environment": "prod", "ttl_minutes": 60}' \
"$BASE_URL/agent-token"
List enrollment tokens
GET /agent-token
- AUTHENTICATIONS:
headers- Admin only - QUERY PARAMETERS:
active_only(optional) - whentrue, return only tokens that are still valid and unused. - RESPONSE:
{ "result": [ ... ] }(raw token values are never returned again).
Revoke an enrollment token
DELETE /agent-token
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{ "token_id": "..." }
List agents
GET /agent
- AUTHENTICATIONS:
headers- Admin only - QUERY PARAMETERS (all optional filters):
environment,status,enabled,version. - RESPONSE:
{ "result": [ ... ] }- each agent includes its ID, label, environment, version, enabled flag, and an effective status (online / inactive / disabled). - EXAMPLE:
curl -X GET -H "username: xxxxx" -H "api-key: xxxxx" \
"$BASE_URL/agent?environment=prod&status=online"
Manage an agent
Perform a lifecycle action on an enrolled agent.
PATCH /agent
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{ "agent_id": "...", "action": "disable" }Name Type Description agent_id requiredString The agent to act on. action requiredString One of enable,disable,rotate, ortouch.rotateissues a new agent key (returned once in the response);touchrefreshes the agent's last-seen timestamp.
Delete an agent
DELETE /agent
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{ "agent_id": "..." }
POST /agent (enrolment) and PATCH /agent sent with x-agent-* headers (heartbeat) are used by the agent itself during install and while running. They are not part of the admin workflow and are not documented here.
Create an agent job
A job is a single unit of work assigned to an agent - one workflow phase run against a target host.
POST /agent-job
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{
"agent_id" : "...",
"phase" : "SourcePrep",
"config" : { "portal": "10.0.0.10", "manualIQN": "data,log" },
"secrets" : { "chapPassword": "..." }
}Name Type Description agent_id requiredString The agent that should run the job. The agent must be online. phase requiredString The workflow phase to run: DiscoverHost,ConnectTargets,SourcePrep,SourcePrepOnly,SourceMigrateOnly,CloneMount, orCloneUnmount.config optionalObject Non-secret configuration for the phase (the same fields used by the connector's config.json).secrets optionalObject Secret values for the phase (e.g. CHAP credentials). Stored encrypted and never returned in job listings. workflow_id optionalString Associate the job with an onboarding workflow. - RESPONSE:
{ "result": { ... } }- the created job (without secret values).
List agent jobs
GET /agent-job
- AUTHENTICATIONS:
headers- Admin only - QUERY PARAMETERS:
job_idfor a single job, or filters such asagent_id,state,workflow_id,job_type,role, andlimit. Addinclude_events=1to include the job's progress events.
Cancel an agent job
PATCH /agent-job
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{ "job_id": "...", "action": "cancel" }
Agents claim and update their own jobs via GET /agent-job?next=1 and PATCH /agent-job using their agent credentials. As with the agent lifecycle routes, those calls are part of the agent protocol and are not made by an administrator.
Workflow API
An onboarding workflow is a higher-level orchestrator that sequences agent jobs and ZFS operations across two appliances to clone a production database onto another vME (the "Onboard Application" wizard). The endpoints below let you list, inspect, and tear down workflows, and validate a target appliance. All require an administrator account.
The Onboarding (API) folder in the vME Postman collection walks the entire Onboard Application sequence - create workflow, provision the iSCSI sources, discover, prep, snapshot, send to the target, clone, and mount - as ordered, chained requests. Run it top to bottom, or use Postman's Code button to copy each call into your own scripts.
List workflows
GET /workflow
- AUTHENTICATIONS:
headers- Admin only - QUERY PARAMETERS (optional filters):
state,created_by,workflow_type,source_mode,target_mode,transport_mode. - RESPONSE:
{ "result": [ ... ] }.
Show a workflow
GET /workflow/<workflow_id>
- AUTHENTICATIONS:
headers- Admin only - RESPONSE: The workflow with its steps and the agent jobs linked to each step.
Create a workflow
POST /workflow
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{ "name": "...", "workflow_type": "...", "template_id": "...", "config": { ... } }. A new workflow starts in thedraftstate. The web wizard drives most workflow creation; call this directly only when scripting your own automation.
Update a workflow
PATCH /workflow/<workflow_id>
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA: any of
name,state,current_step,config, orsecrets. Useconfig_mode: "merge"(default) or"replace"to control howconfigis applied. State and step values are validated against the allowed workflow states.
List cleanup candidates
GET /workflow/<workflow_id>/cleanup-candidates
- AUTHENTICATIONS:
headers- Admin only - RESPONSE: The objects a cleanup delete would destroy, across both appliances - each with a
key, theside(local/remote), itskind(source / snapshot / clone), and a displaylabel. Use this to preview, or to build a subset for a selective delete.
Cancel or delete a workflow
DELETE /workflow/<workflow_id>
- AUTHENTICATIONS:
headers- Admin only - QUERY PARAMETERS:
Name Description (none) Soft-cancel: the workflow is marked cancelled; its record and the ZFS objects it created are kept.purge=1 Hard-delete the workflow record. Required before cleanuporforcebelow have any effect.purge=1&cleanup=1 Also destroy the source / snapshot / clone objects the workflow created on both appliances. purge=1&force=1 Delete the record even if some cleanup steps failed. - REQUEST BODY SCHEMA (optional):
{ "objects": ["key1", "key2"] }- restrict acleanupdelete to a subset of the cleanup candidates. - RESPONSE:
{ "message": "...", "cleanup": { ... } }. If a cleanup step fails andforceis not set, the call returns 409 Conflict with a report of what could not be removed. - EXAMPLE - hard-delete and clean up everything on both sides:
curl -X DELETE -H "username: xxxxx" -H "api-key: xxxxx" \
"$BASE_URL/workflow/WORKFLOW_ID?purge=1&cleanup=1"
Validate a target appliance (remote preview)
Confirm that a target appliance is reachable, list its pools, and establish SSH trust with it (so the clone transfer can run).
POST /workflow/<workflow_id>/remote-preview
- AUTHENTICATIONS:
headers- Admin only - REQUEST BODY SCHEMA:
{
"address" : "https://10.0.0.20",
"admin_username" : "admin",
"admin_api_key" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
} - RESPONSE:
{ "result": { "host": "...", "pools": [ ... ], "peer_trust": { "added": true, "fingerprint": "..." } } }.
List workflow templates
GET /workflow-templates
- AUTHENTICATIONS:
headers- Admin only - QUERY PARAMETERS:
enabled_only(optional) - return only enabled templates. - RESPONSE:
{ "result": [ ... ], "default_template_id": "..." }.
API Examples (Postman Collection)
Click here to download the Postman collection with example requests for various vME API requests.
If you're unsure how to import the collection into Postman, please refer to the Postman documentation for a step-by-step guide on importing collection.