General Informations
STORAGE SERVER TECHNICAL OVERVIEW
In the following document is breefly presented some informations about how the Elemento Storage Server works. :::info This little guide is a way to create an initial documentation of how processes works and to introduce, eventually, new developers to the basics informations they may need to work on this topic. :::
General informations
API Call Rundown
:::info Every functionality is requested via Rest API. ::: :::info StorageServer responds to api calls on port 7772 ::: Here are reported functionality (and relative endpoints and purpose) for the storage server.
:::success IMPLEMENTED:
βΆοΈ CREATE
purpose: Create a simple volume
endpoint: http://<server_ip>:7772/api/<version>/create
βΆοΈ LIST ACCESSIBLE VOLUMES
purpose: returns the volumes a user can access
endpoint: http://<server_ip>:7772/api/<version>/accessible
βΆοΈ SINGLE VOLUME INFORMATIONS
purpose: Get the informations about a single volume
endpoint: http://<server_ip>:7772/api/<version>/info
βΆοΈ DESTROY
purpose: Destroy a volume
endpoint: http://<server_ip>:7772/api/<version>/destroy
βΆοΈ RESIZE
purpose: Update the size of a volume
endpoint: http://<server_ip>:7772/api/<version>/update/resize
βΆοΈ Convert
purpose: Convert a volume to another format
endpoint: http://<server_ip>:7772/api/<version>/update/convert
βΆοΈ CLOUDINIT VOLUME
purpose: Create a cloudinit Volume
endpoint: http://<server_ip>:7772/api/<version>/cloudinit/create
purpose: Upload the needed cloudinit metadata files to create an iso volume for cloudinit utility
endpoint: http://<server_ip>:7772/api/<version>/cloudinit/metadata
βΆοΈ CREATE ISO VOLUME
purpose: Create a volume containing a bootable iso, an OS Installer or a iso containing tools (driver and such)
endpoint: http://<server_ip>:7772/api/<version>/iso/create
βΆοΈ UPDATE VOLUME METADATA
purpose: Update the volume metadata
endpoint: http://<server_ip>:7772/api/<version>/update
βΆοΈ CREATE CEPH VOLUME - WIP
purpose: Create a volume on a ceph cluster using storage server as an interface
endpoint: http://<server_ip>:7772/api/<version>/iso/create
βΆοΈ LIVE MIGRATION - PREPARE
purpose: Prepare the storage server export structure to abilitate the live migration process
endpoint: http://<server_ip>:7772/api/<version>/livemigration/prepare
βΆοΈ LIVE MIGRATION - REVERT
purpose: Return to normal esport state if live migration fails
endpoint: http://<server_ip>:7772/api/<version>/livemigration/revert
βΆοΈ LIVE MIGRATION - CONCLUDE
purpose: Consolodate the state of the volumes if the live migration process was successful
endpoint: http://<server_ip>:7772/api/<version>/livemigration/conclude
:::
:::warning TODO or WIP:
βΆοΈ TRANSFER PROPERTY - TODO
purpose: Update the volume owner
endpoint: http://<server_ip>:7772/api/<version>/transfer
βΆοΈ CLONE - TODO
purpose: Create a new volume cloning another one
endpoint: http://<server_ip>:7772/api/<version>/clone
:::
where are my volumes created into?
Inside the elemento's architecture a new volumes will be created folling this rules:
- A new volume will be created inside the
/mntpath or in one of his first layer subdirectory - For a path to be recognised as valid to allocate new volumes a
settings.jsonfile has to be present. - Multiple paths inside
/mntare allowed, the system will chose from the available ones automatically.
This will be considered a valid structure where there are 3 different paths that can be choosen as location to create volumes:
/mnt/
βββ valid_path_1/
β βββ settings.json
β βββ volume_1A/
β βββ volume_1B/
β βββ volume_1C/
βββ valid_path_2/
β βββ settings.json
| βββ volume_2A/
β βββ volume_2B/
βββ invalid_path_3/
β βββ random_file_1
β βββ random_file_2
βββ valid_path_4/
βββ settings.json
βββ volume_4A/
βββ volume_4B/
βββ volume_4C/
:::warning
Note that inside the path /mnt/invalid_path_3 is present a directory containing a settings.json file but the directory is not a valid path because is not at the higher nesting level that contains the settings.json file.
:::
what is a settings.json file?
In this context a settings.json files is elemento's architecture tool to know that a path inside /mnt has to be considered as a place where volumes can be created and managed, and at the same time introducing some rules for the location.
settings.json contains informations following this structure:
{
"max-volumes": 6,
"max-volume-size": "50G",
"max-total-size": "200G",
"file-system": "default"
}
Where:
max-volumesis the number of volumes that can be created in this location and -max-volume-sizeis the maximum virtual size allowed for each volume.max-total-sizeis the maximum virtual total size allowed the volume in this pathfile-systemchosen fromdefaultoruniqueallow the storage server to know what king of filesystem he has to create volumes on
what is a vid.<whatever_uid>.elimg?
Each of this kind of directory represent an elemento storage volume.
The name of the folder that represent a volume always follows this structure:
vid.<volume_uid>.elimg where <volume_uid> represent the unique id of the volume.
Each one of theese directories will contain the effective volume data.<ext> and the relative informations where <ext> represent the image format (for raw format the extension is img).
:::spoiler knowing this the previous directory tree will appear like this
/mnt/
βββ valid_path_1/
β βββ settings.json
β βββ vid.volume1A_uid.elimg/
β β βββ data.<ext>
β β βββ meta.json
β βββ vid.volume2A_uid.elimg/
β β βββ data.<ext>
β β βββ meta.json
β βββ vid.volume3A_uid.elimg/
β βββ data.<ext>
β βββ meta.json
βββ data_volumes/
β βββ valid_path_2/
β β βββ settings.json
β β βββ vol.volume2A_uid.elimg/
β | | βββ data.<ext>
β | | βββ meta.json
β | βββ vid.volume2B_uid.elimg/
β | βββ data.<ext>
β | βββ meta.json
β βββ valid_path_3/
β βββ settings.json
β βββ vid.volume3A_uid.elimg/
β | βββ data.<ext>
β | βββ meta.json
β βββ not_valid_path/
β βββ settings.json
βββ valid_path_4/
βββ settings.json
βββ vid.volume4A_uid.elimg/
β βββ data.<ext>
β βββ meta.json
βββ vid.volume4B_uid.elimg/
βββ data.<ext>
βββ meta.json
:::
Elemento Storage Volume tree
As follows is represented the structure of an Elemento volume (.elimg)
vid.<volume_id>.elimg/
βββ meta.json
βββ isoinfo.json # only present if the volume is contains a non cloudinit iso
βββ iqn.2004-10.cloud.elemento:01:<client_uid ^ volume_uid>.exported # if exported
βββ data.<ext>
βββ cloud-init-metadata/ # this is present only if the vol is cloudinit
βββ elemento.<n>.expected
βββ user-data
βββ network-data
βββ meta-data
βββ script_a.sh
βββ script_b.sh
here it is a more in depth explaination of how what each files or subdirectory does and what is their purpose in the context of the Elemento Volume.
meta.json
This file contains most of the informations about the volume, is a simple json file. When the system rescan in search for new volumes this file allows to retrive most of the informations necessary to perform the actions on the volume following the right steps.
This is an example of a meta.json (is formatted for better readability, but in the actual file is not)
{
"creatorID": "5e96afa52c1a53348adc5c5663978058",
"name": "cloudinit-ubuntu",
"private": false,
"bootable": true,
"readonly": false,
"shareable": false,
"clonable": true,
"alg": "cp",
"format": "qcow2",
"bus": "virtio",
"cloudinit": true,
"ceph": false
}
In the following are present the major informations about the data contained inside the json
| key | datatype | purpose | allowed values | default |
|---|---|---|---|---|
| volumeID | string | uid of the volume | ||
| size | int | virtual size in bytes of the image | ||
| name | str | human readable name of the volume | ||
| format | str | format of the volume image | raw, qcow2, rdb, iso | raw |
| private | bool | if the volume can be seen just by the creator | ||
| bootable | bool | if the volume can be used to boot from | ||
| shareable | bool | if the volume can be exported multiple times | ||
| clonable | bool | if the volume can be cloned | True | |
| alg | str | the choosing of the algorithm used to clone the volume | cp, rclone, rsync | cp |
| bus | str | the choosed driver to connect the volume to a VM | virtio, scsi, sata, ide | virtio |
| cloudinit | bool | if the volume has cloudinit purposes | False | |
| ceph | bool | if the volume belongs to a ceph cluster | False |
data.<ext>
This file contains the actual volume image. The image can be in different formats:
- raw
- qcow2
- rbd (on a ceph cluster)
- iso
:::info Some things to note:
- ext is representing the image format
- if image format is raw ext is img
:::
:::warning
For ceph volumes the
data.rbdfile is actually "fake", the real volumes stays onto the ceph cluster, this file is just a tool to allow the storage server to manage the volume whitout coninuosly ask stuff to the ceph cluster. :::
cloud-init-metadata subdirectory
Cloudinit allows a VM to execute commands and import configurations in order to have the VM preconfigured at first boot. In addition to the cloudimage volume cloudinit also needs a set of metadata files (config files and scripts) that can read and use to apply the desired configuration: all of this informations will be transformed into an iso that can be mounted alongside the boot volume. This directory will contain all of that files.
A file named elemento.<n>.expected will be present in this directory too. This file allow the system to keep track of how many files it has to expect and when all the files are present.
The most commons files for a cloud init setup are 3:
- meta-data
- user-data
- network-data
:::info Some things to note: script files can also be included to be used during installations process. Never the less this number is not fixed and can change. :::
::: warning For now is important to notice that there is no way to update this file via api. the fastest way will be to modify the files directly on the host or recreate the volume from scratch and sending along the updated files. :::
other files
:::spoiler
lock system
The files in the form of elemento.purpose.<operation_uid>.ignore are used to lock the volumes. This lock is implemented in order to avoid overlapping of actions on the same volume. While the volume is locked the system still knows his dimension, but does not return it to the user (still not implemented very well, but it works, this flow can be better managed). For smaller volume or a single user that has accesss to the volume is not a big deal beacuse actions are fast, but if the volume is pretty big or multiple user would execute operations onto the same volume this could've happened. For now this is a simpler method to avoid this kind of scenarios.
export system
If the volume is being exported a file in the form of iqn.<whatever_uid>.exported will be present in the volume as simple way to track this action.
While exported the file is repetedly touched in the same location by a small container.
isoinfo.json
this file is for (non cloudinit) iso volumes. Is a simple json and allows the system to fetch again the informations about the iso: Some examples:
- for tools:
{
"isotype": "tool",
"os_family": "windows",
"scope": "driver",
"version": "x.y"
}
- for OS installer or bootable iso:
{
"isotype": "os_generic",
"os_family": "linux",
"os_flavour": "debian"
"os_version": "12.9"
}
:::
Export
General
This Graph represent if a volume can be exported based on its parameters and its status:
P -- Yes --> O{is owned?}
O -- Yes -->privateS{Condition 4?}
privateS{"is shareable?"}
privateS -- yes --> privateOwnedShareable["True"]
privateS -- no --> privateOwnedNotShareable{"yet exported?<br>(conn is None)"}
privateOwnedNotShareable -- yes --> o1["true"]
privateOwnedNotShareable -- no --> o2["false"]
O -- No --> PrivateNotOwned["False"]
P -- No --> notPrivateS{is shareable}
notPrivateS -- Yes --> notPrivateShaerable["True"]
notPrivateS -- No --> notPrivateNotShaerable{"yet exported?<br>(conn is None)"}
notPrivateNotShaerable -- yes --> o3["true"]
notPrivateNotShaerable -- no --> o4["false"]
:::info if a volume is bootable cannot be shaerable :::
Local export
Samba export
ISCSI export
Cloud-Init
cloudinit addon for storageserver
the cloudinitAddon object is our way to manage all the informations that a cloudinit volume needs to have to be correcly used to setup a VM (expecially its metadata)
Get the cloud image
Upload of the metadata
Create the iso
Api Endpoints
:::info StorageServer responds to api calls on port is 7772 ::: Here are reported functionality (and relative endpoints and purpose) for the storage server.
Create
purpose: Create a simple volume
endpoint: http://<server_ip>:7772/api/<version>/create
headers:"Content-Type": "application/json"
Payload/body:
{
"creatorID": "uuid_of_the_creator",
"name": "name_of_the_volume",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": false,
"alg": "algorithm_of_choice_for_cloning",
"format": "desired_volume_format",
"bus": "mounting_driver_for_the_volume",
"size": size_of_the_volume_in_GB
}
:::spoiler Requests examples π Example payload:
{
"creatorID": "ffffffffffffffffffffffffffffffff"
"name": "test-create",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": false,
"alg": "no",
"format": "qcow2",
"bus": "virtio",
"size": 1
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/create \
-H "Content-Type: application/json" \
-d '{"creatorID": "ffffffffffffffffffffffffffffffff","name": "test-create", "private":false, "readonly": false, "shareable": false, "bootable": false, "clonable": false, "alg": "no", "format": "qcow2", "bus": "virtio", "size": 1}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/create"
headers = {
"Content-Type": "application/json",
}
payload = {
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "test-create",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": false,
"alg": "no",
"format": "qcow2",
"bus": "virtio",
"size": 1
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"alg": "no",
"bootable": false,
"bus": "virtio",
"clonable": false,
"creatorID": "ffffffffffffffffffffffffffffffff",
"img_format": "qcow2",
"name": "test-create",
"private": false,
"readonly": false,
"shareable": false,
"size": 1,
"vid": "ffffffffffffffffffffffffffffffff"
}
note that the uuid of the newly created volume is included along the other parameters
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"creatorID": "ffffffffffffffffffffffffffffffff"
"name": "test-create",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": false,
"alg": "no",
"format": "qcow2",
"bus": "virtio",
"size": 1
}
:::
List Accessible Volumes
purpose: returns the volumes a user can access
endpoint: http://<server_ip>:7772/api/<version>/accessible
headers:"Content-Type": "application/json"
Payload/body:
{
"client_uid": "uuid_of_the_user_that_ask_for_volumes",
}
:::spoiler Requests examples π Example payload:
{
"client_uid": "ffffffffffffffffffffffffffffffff"
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/accessible \
-H "Content-Type: application/json" \
-d '{"client_uid": "ffffffffffffffffffffffffffffffff"}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/accessible"
headers = {
"Content-Type": "application/json",
}
payload = {
"client_uid": "ffffffffffffffffffffffffffffffff"
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
[
{
"volumeID": "155a8574f06542f1ac2fbe8790b35160",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 4000000000,
"name": "test",
"format": "qcow2",
"private": false,
"bootable": false,
"readonly": false,
"shareable": false,
"clonable": false,
"alg": "no",
"bus": "virtio",
"cloudinit": false,
"ceph": false,
"exported": false,
"sizeOnDisk": 196672,
"lastUpdated": "2025-02-05 23:34:07.1850"
},
{
"volumeID": "2bef4e8692674ff5b0adbf88c5882710",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 6203355136,
"name": "ubuntu-destop-iso",
"format": "iso",
"iso_type": "os_generic",
"private": false,
"bootable": true,
"readonly": true,
"shareable": false,
"clonable": true,
"alg": "cp",
"bus": "sata",
"cloudinit": false,
"ceph": false,
"exported": false,
"sizeOnDisk": 6203355136,
"lastUpdated": "2024-08-27 18:25:25.0000"
}
]
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"client_uid": "ffffffffffffffffffffffffffffffff"
}
:::
Single Volume Informations
purpose: Get the informations about a single volume
endpoint: http://<server_ip>:7772/api/<version>/info
headers:"Content-Type": "application/json"
Payload/body:
{
"volume_id": "uuid_of_the_volume_infos_are_asked_about",
}
:::spoiler Requests examples π Example payload:
{
"volume_id": "ffffffffffffffffffffffffffffffff"
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/info \
-H "Content-Type: application/json" \
-d '{"volume_id": "ffffffffffffffffffffffffffffffff"}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/info"
headers = {
"Content-Type": "application/json",
}
payload = {
"volume_id": "ffffffffffffffffffffffffffffffff"
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"volumeID": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 4000000000,
"name": "test",
"format": "qcow2",
"private": false,
"bootable": false,
"readonly": false,
"shareable": false,
"clonable": false,
"alg": "no",
"bus": "virtio",
"cloudinit": false,
"ceph": false,
"exported": false,
"sizeOnDisk": 196672,
"lastUpdated": "2025-02-05 23:34:07.1850"
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"volume_id": "ffffffffffffffffffffffffffffffff"
}
:::
Destroy
purpose: Destroy a volume
endpoint: http://<server_ip>:7772/api/<version>/destroy
headers:"Content-Type": "application/json"
Payload/body:
{
"volume_id": "uuid_of_the_volume_to_destroy",
}
:::spoiler Requests examples π Example payload:
{
"volume_id": "ffffffffffffffffffffffffffffffff"
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/destroy \
-H "Content-Type: application/json" \
-d '{"volume_id": "ffffffffffffffffffffffffffffffff"}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/destroy"
headers = {
"Content-Type": "application/json",
}
payload = {
"volume_id": "ffffffffffffffffffffffffffffffff"
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"vid": "ffffffffffffffffffffffffffffffff"
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"volume_id": "ffffffffffffffffffffffffffffffff"
}
:::
Update Metadata
purpose: Update the volume metadata
endpoint: http://<server_ip>:7772/api/<version>/update
headers:"Content-Type": "application/json"
Payload/body:
{
"vid": "uuid_of_the_volume_to_modify",
"creatorID": "uuid_of_the_client_asking_the_changes_on_the_volume",
"name": "test-update",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": true,
"alg": "cp",
"bus": "sata"
}
:::spoiler Requests examples π Example payload:
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "test-update",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": true,
"alg": "cp",
"bus": "sata"
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/update/resize \
-H "Content-Type: application/json" \
-d '{"vid": "ffffffffffffffffffffffffffffffff", "creatorID": "ffffffffffffffffffffffffffffffff", "name": "test-update", "private": false, "readonly": false, "shareable": false, "bootable": false, "clonable": true, "alg": "cp", "bus": "sata"}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/update"
headers = {
"Content-Type": "application/json",
}
payload = {
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "test-update",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": true,
"alg": "cp",
"bus": "sata"
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "test-update",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": true,
"alg": "cp",
"bus": "sata"
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "test-update",
"private": false,
"readonly": false,
"shareable": false,
"bootable": false,
"clonable": true,
"alg": "cp",
"bus": "sata"
}
:::
Resize
purpose: Update the size of a volume
endpoint: http://<server_ip>:7772/api/<version>/update/resize
headers:"Content-Type": "application/json"
Payload/body:
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 10
}
:::spoiler Requests examples π Example payload:
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 10
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/update/resize \
-H "Content-Type: application/json" \
-d '{"vid": "ffffffffffffffffffffffffffffffff", "creatorID": "ffffffffffffffffffffffffffffffff", "size": 10}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/update/resize"
headers = {
"Content-Type": "application/json",
}
payload = {
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 10
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 10
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"size": 10
}
:::
Convert
purpose: Convert a volume to another format
endpoint: http://<server_ip>:7772/api/<version>/update/convert
headers:"Content-Type": "application/json"
Payload/body:
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"format": "qcow2"
}
:::spoiler Requests examples π Example payload:
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"format": "qcow2"
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/update/convert \
-H "Content-Type: application/json" \
-d '{"vid": "ffffffffffffffffffffffffffffffff", "creatorID": "ffffffffffffffffffffffffffffffff", "format": "qcow2"}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/update/convert"
headers = {
"Content-Type": "application/json",
}
payload = {
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"format": "qcow2"
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"format": "qcow2"
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"vid": "ffffffffffffffffffffffffffffffff",
"creatorID": "ffffffffffffffffffffffffffffffff",
"format": "qcow2"
}
:::
Create Cloudinit Cloudimage volume
purpose: Create a cloudinit Volume
endpoint: http://<server_ip>:7772/api/<version>/cloudinit/create
Cloudinit Metadata Volume
::: info TBH :::
1οΈβ£ First Call
purpose: Upload the needed cloudinit metadata files to create an iso volume for cloudinit utility
endpoint: http://<server_ip>:7772/api/<version>/cloudinit/metadata
β© Following calls
purpose: Upload the needed cloudinit metadata files to create an iso volume for cloudinit utility
endpoint: http://<server_ip>:7772/api/<version>/cloudinit/metadata
Create ISO volume
::: info this next two calls have different type of payload, but goes to the same endpoint :::
π¨iso volume with tool purpose
purpose: Create a volume containing a bootable iso(live) or an OS Installer.
endpoint: http://<server_ip>:7772/api/<version>/iso/create
headers:"Content-Type": "application/json"
Payload/body:
{
"creatorID": "uuid_of_the_client",
"name": "virtio-win-driver",
"private": false,
"clonable": true,
"alg": "cp",
"isotype": "tool",
"os_family": "windows",
"scope": "drivers",
"version": "2021",
"size": 15
}
:::spoiler Requests examples π Example payload:
{
"alg": "cp",
"clonable": true,
"creatorID": "ffffffffffffffffffffffffffffffff",
"isotype": "tool",
"name": "virtio-win-driver",
"os_family": "windows",
"os_flavour": null,
"os_version": null,
"private": false,
"tool_scope": "drivers",
"tool_version": "2021"
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/update/convert \
-H "Content-Type: application/json" \
-d '{"alg": "cp", "clonable": true, "creatorID": "ffffffffffffffffffffffffffffffff", "isotype": "tool", "name": "virtio-win-driver", "os_family": "windows", "os_flavour": null, "os_version": null, "private": false, "tool_scope": "drivers", "tool_version": "2021"}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/iso/create"
headers = {
"Content-Type": "application/json",
}
payload = {
"alg": "cp",
"clonable": true,
"creatorID": "ffffffffffffffffffffffffffffffff",
"isotype": "tool",
"name": "virtio-win-driver",
"os_family": "windows",
"os_flavour": null,
"os_version": null,
"private": false,
"tool_scope": "drivers",
"tool_version": "2021"
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"alg": "cp",
"clonable": true,
"creatorID": "ffffffffffffffffffffffffffffffff",
"isotype": "tool",
"name": "virtio-win-driver",
"os_family": "windows",
"os_flavour": null,
"os_version": null,
"private": false,
"tool_scope": "drivers",
"tool_version": "2021",
"vid": "ffffffffffffffffffffffffffffffff"
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"alg": "cp",
"clonable": true,
"creatorID": "ffffffffffffffffffffffffffffffff",
"isotype": "tool",
"name": "virtio-win-driver",
"os_family": "windows",
"private": false,
"tool_scope": "drivers",
"tool_version": "2021"
}
:::
π» iso volume for operative system installer or live
purpose: Create a volume containing tools (driver and such) iso.
endpoint: http://<server_ip>:7772/api/<version>/iso/create
headers:"Content-Type": "application/json"
Payload/body:
{
"creatorID": "uuid_of_the_client",
"name": "dabian-iso",
"private": false,
"clonable": true,
"alg": "cp",
"isotype": "os_generic",
"os_family": "linux",
"os_flavour": "debian",
"os_version": "12.10",
"size": 15
}
:::spoiler Requests examples π Example payload:
{
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "dabian-iso",
"private": false,
"clonable": true,
"alg": "cp",
"isotype": "os_generic",
"os_family": "linux",
"os_flavour": "debian",
"os_version": "12.10",
"size": 15
}
π» Bash:
curl -X POST "http://<server_ip>:7772/api/<version>/update/convert \
-H "Content-Type: application/json" \
-d '{"creatorID": "ffffffffffffffffffffffffffffffff", "name": "dabian-iso", "private": false, "clonable": true, "alg": "cp", "isotype": "os_generic", "os_family": "linux", "os_flavour": "debian", "os_version": "12.10", "size": 15}'
π Python:
import requests
url = "http://<server_ip>:7772/api/<version>/iso/create"
headers = {
"Content-Type": "application/json",
}
payload = {
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "dabian-iso",
"private": false,
"clonable": true,
"alg": "cp",
"isotype": "os_generic",
"os_family": "linux",
"os_flavour": "debian",
"os_version": "12.10",
"size": 15
}
response = requests.post(url, json=payload, headers=headers)
# Then manage the response
::: :::spoiler Response examples
β 200 - OK
{
"alg": "cp",
"clonable": true,
"creatorID": "ffffffffffffffffffffffffffffffff",
"isotype": "os_generic",
"name": "dabian-iso",
"os_family": "linux",
"os_flavour": "debian",
"os_version": "12.10",
"private": false,
"tool_scope": null,
"tool_version": null,
"vid": "ffffffffffffffffffffffffffffffff"
}
β οΈ 400 - bad request
{
"error": "request was badly formatted. 'the_required_key_that_is_missing'"
}
β οΈ 404 - unreachable
β 500 - internal server error
{
"creatorID": "ffffffffffffffffffffffffffffffff",
"name": "dabian-iso",
"private": false,
"clonable": true,
"alg": "cp",
"isotype": "os_generic",
"os_family": "linux",
"os_flavour": "debian",
"os_version": "12.10",
"size": 15
}
:::
WIP or TODO API calls
βΆοΈ TRANSFER PROPERTY - TODO
purpose: Update the volume owner
endpoint: http://<server_ip>:7772/api/<version>/transfer
βΆοΈ CLONE - TODO
purpose: Create a new volume cloning another one
endpoint: http://<server_ip>:7772/api/<version>/clone
βΆοΈ LIVE MIGRATION - PREPARE - WIP
purpose: Prepare the storage server export structure to abilitate the live migration process
endpoint: http://<server_ip>:7772/api/<version>/livemigration/prepare
βΆοΈ LIVE MIGRATION - REVERT - WIP
purpose: Return to normal esport state if live migration fails
endpoint: http://<server_ip>:7772/api/<version>/livemigration/revert
βΆοΈ LIVE MIGRATION - CONCLUDE - WIP
purpose: Consolodate the state of the volumes if the live migration process was successful
endpoint: http://<server_ip>:7772/api/<version>/livemigration/conclude
No comments to display
No comments to display