Custom block volumes defined in profiles?

Currently I am manually creating and attaching storage volumes. I am using them to experiment with ceph block io.

How can I do the equivalent to this bash script but in a profile?
Can I set the volume to auto delete when the instance deletes via the profile as well?


#!/bin/bash
VMS="v1 v2 v3"
DISKS="data1 data2 data3"
readonly DATA_DISK="100GiB"

for VM in $VMS
do
    for DISK in $DISKS
    do
        lxc storage volume create default "${VM}-${DISK}" --type block size=${DATA_DISK}
        lxc config device add ${VM} "${VM}-${DISK}" disk pool=default source="${VM}-${DISK}"
    done
done

Would be something like like;

DISKS="data1 data2 data3"
PROJECT=arg[0]

#Note my addition of the project here, better to build support now than later.
lxc project switch ${PROJECT}

PROFILE_NAME="${VM}-${PROJECT}-volumes"

lxc profile create "${PROFILE_NAME}"

foreach($DISKS){
    DISK_NAME="${PROJECT}-${VM}-${DISK}"
    lxc storage volume create "${DISK_NAME}" ...
    lxc profile device add  ...
}

lxc launch ubuntu: c1 -p default -p "${PROFILE_NAME}"

Though with your follow up request (below) im not sure its any better than using instance config.

The follow up question (if i’ve understood it correctly) implies you want to delete the volume when the instance is deleted. Attaching a disk device to a profile would imply you want more than one instance to attach the volumes (but if more than one instance is using the profile with the volumes you wont be able to delete the profile & volumes without deleting the other instances first).

I dont think LXD has an ephemeral key on storage (it might, i’m not a dev, there may be hacky workaround here) so I dont think you can implement this without writing code;

# pseudo code
client = new LXDClient()

volumeNames = [
     "data1", 
     "data2", 
     "data3"
]

client.events.listen(function(event){
    //TODO Make sure the operation has finished with success before trying this.
    if(event.metadata.action === "instance-delete"){
            //TODO The below will fail if > 1 instance uses the profile
            client.profile.delete(`${event.VM}-${event.PROJECT}-volumes`)
             foreach(volumeNames as volume){
                 client.volumes.delete(`${event.VM}-${event.PROJECT}-${volume}`)
            }
    }
});

There may be naming inconsistencies between the suggested first script & follow script, this is on you to address as this was supposed to serve as a “jumping off” point.

I assume you mean something like this:

lxc profile cp default test
lxc profile device add test data disk path=/mnt pool=default disktype=block

Unfortunately this is not, yet, possible as far as I know

  1. currently source key is marked required and does not have a default value, meaning it must be defined as an absolute path on the host
  2. key disktype is not yet defined/implemented

Unfortunately this too is not yet possible/implemented (again, as far as I know)


NOTE
In the meantime I suggest you use GNU parallel as opposed a for loop, this allows you to perform all operations simultaneously thus saving you a lot of time.

Block volumes can only be used by a single instance at a time.
Profiles do not support templating so you cannot add a disk device to a profile with a dynamic part that selects the instance’s associated volume dynamically.

So the approach you are using now is the best way currently to do it.

I don’t believe this is supported at this time.

it would be great to add a feature request to dynamically create volumes based on tags on the host when created or in the profile.

eg
vol:
pool: default
source: %h-data
type: disk
autodelete: true
autocreate: true
reuse: true

where %h is the hostname or instance name

essentially I would like to eliminate as many of the for loops and/or secondary steps after initializing the container.

i would like to be able to do
lxc init images:foo c1 -p addl_disk -p default

it would also be great to be able to re-use unattached disks etc

1 Like