LXC 4.23 Invalid devices: Name must not start with a number

Hi there,

since lxc version 4.23 I couldn’t start my container because the device name is an IP address instead a name. So I always get the error …

Error: Invalid devices: Device validation failed for "xxx.xxx.xxx.xxx:443": Name must not start with a number

So how can I change the name? I’ve tried the follow commands but the error comes again every time.

In the yaml file I changed the name from xxx.xxx.xxx.xxx:80 to port80.

$ lxc config device remove webserver xxx.xxx.xxx.xxx:80
Error: Invalid devices: Device...

$ lxc config edit webserver < webserver.yaml
Error: Invalid devices: Device...

webserver.yaml

# old yaml
devices:
  xxx.xxx.xxx.xxx:80:
    connect: tcp:10.50.137.55:80
    listen: tcp:xxx.xxx.xxx.xxx:80
    type: proxy
  xxx.xxx.xxx.xxx:443:
    connect: tcp:10.50.137.55:443
    listen: tcp:xxx.xxx.xxx.xxx:443
    type: proxy

# new yaml
devices:
  port80:
    connect: tcp:10.50.137.55:80
    listen: tcp:xxx.xxx.xxx.xxx:80
    type: proxy
  port443:
    connect: tcp:10.50.137.55:443
    listen: tcp:xxx.xxx.xxx.xxx:443
    type: proxy

Thanks in advance,

Stonie

This will be due to this change:

This was to allow the device names to be used as filesystem entities (similar to how instance names were already restricted for that reason).

Your change to the device names in new.yaml will make them compatible with LXD 4.23.

1 Like

Running lxc config edit webserver < webserver.yaml will replace ALL of your instance’s config, not just devices (i.e in your example above it will remove everything except the devices).

Instead you should do lxc config show <instance> > config.yaml, then modify config.yaml and then feed it back lxc config edit <instance> < config.yaml.

E.g

lxc launch images:ubuntu/focal c1
lxc config show c1 > ~/test.yaml
cat ~/test.yaml
architecture: x86_64
config:
  image.architecture: amd64
  image.description: Ubuntu focal amd64 (20220223_07:42)
  image.os: Ubuntu
  image.release: focal
  image.serial: "20220223_07:42"
  image.type: squashfs
  image.variant: default
  volatile.base_image: 1efe07d0cf58930b1f276f5c1ad7ed3174a67285bc294bee3c2a7420fbc00cf0
  volatile.eth0.host_name: veth4f46d576
  volatile.eth0.hwaddr: 00:16:3e:b9:e8:8b
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange>
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1>
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 6e9b9f19-9dba-4c27-ba9e-8a5622d6385e
devices:
  127.0.0.1:
    connect: tcp:10.50.137.55:80
    listen: tcp:0.0.0.0:80
    type: proxy
ephemeral: false
profiles:
- default
stateful: false
description: ""

Try and apply invalid devices:

lxc config edit c1 < ~/test.yaml
Error: Invalid devices: Device validation failed for "127.0.0.1": Name must not start with a number

Edit the test.yaml file with the valid device name:

cat ~/test.yaml
architecture: x86_64
config:
  image.architecture: amd64
  image.description: Ubuntu focal amd64 (20220223_07:42)
  image.os: Ubuntu
  image.release: focal
  image.serial: "20220223_07:42"
  image.type: squashfs
  image.variant: default
  volatile.base_image: 1efe07d0cf58930b1f276f5c1ad7ed3174a67285bc294bee3c2a7420fbc00cf0
  volatile.eth0.host_name: veth4f46d576
  volatile.eth0.hwaddr: 00:16:3e:b9:e8:8b
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange>
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1>
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 6e9b9f19-9dba-4c27-ba9e-8a5622d6385e
devices:
  port80:
    connect: tcp:10.50.137.55:80
    listen: tcp:0.0.0.0:80
    type: proxy
ephemeral: false
profiles:
- default
stateful: false
description: ""

Now apply valid device config:

lxc config edit c1 < ~/test.yaml

@markylaing @stgraber shall we allow fullstops in device names as long as they are singular and the device name doesn’t start with them?

We can also probably relax the can’t start with a number bit?

What do you think?

Hi tomp,

thanks for your help. :slight_smile:

Sorry but what’s the different between my command and your example? My instance is called webserver.

lxc config edit webserver < webserver.yaml
lxc config edit <instance> < config.yaml

My procedure is …

  1. lxc config show webserver > config.yaml
  2. edit config.yaml
  3. lxc config edit webserver < config.yaml
  4. Error Error: Failed to remove device "127.0.0.1:80": Device remove validation failed for "127.0.0.1:80": Name must not start with a number

org. config.yaml

architecture: x86_64
config:
  image.architecture: amd64
  image.description: ubuntu 20.04 LTS amd64 (release) (20201117)
  image.label: release
  image.os: ubuntu
  image.release: focal
  image.serial: "20201117"
  image.type: squashfs
  image.version: "20.04"
  volatile.base_image: c141ba91f766aab428b64f0e2f64b11e583093c2f4e52b4f6c8baa32021d413d
  volatile.eth0.hwaddr: 00:16:3e:09:ee:e2
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 12b6fd29-7155-4bd6-aaeb-0b24dd96ceae
devices:
  127.0.0.1:80:
    connect: tcp:10.50.137.55:80
    listen: tcp:127.0.0.1:80
    type: proxy
  127.0.0.1:443:
    connect: tcp:10.50.137.55:443
    listen: tcp:127.0.0.1:443
    type: proxy
ephemeral: false
profiles:
- default
stateful: false
description: ""
type or paste code here

my new config.yaml

architecture: x86_64
config:
  image.architecture: amd64
  image.description: ubuntu 20.04 LTS amd64 (release) (20201117)
  image.label: release
  image.os: ubuntu
  image.release: focal
  image.serial: "20201117"
  image.type: squashfs
  image.version: "20.04"
  volatile.base_image: c141ba91f766aab428b64f0e2f64b11e583093c2f4e52b4f6c8baa32021d413d
  volatile.eth0.hwaddr: 00:16:3e:09:ee:e2
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 12b6fd29-7155-4bd6-aaeb-0b24dd96ceae
devices:
  webserverport80:
    connect: tcp:10.50.137.55:80
    listen: tcp:127.0.0.1:80
    type: proxy
  webserverport443:
    connect: tcp:10.50.137.55:443
    listen: tcp:127.0.0.1:443
    type: proxy
ephemeral: false
profiles:
- default
stateful: false
description: ""

Is there any workaround until the version update? Maybe a sql query?

Ah, you didn’t show the full error last time, this bit is clearer whats happening now:

Device remove validation failed for...

Its failing to remove the device. Hrm, this will certainly need a bug fix patch to avoid this situation for other users.

In the meantime, yes I think a SQL query is in order.

If you do:

lxd sql global 'select * from instances_devices where instance_id = (select id from instances where name = "<instance_name>")'

This should get you a table that looks something like this:

+------+-------------+--------+------+
|  id  | instance_id |  name  | type |
+------+-------------+--------+------+
| 1180 | 307         | port80 | 8    |
+------+-------------+--------+------+

You can then issue a command to rename it:

lxd sql global 'update instances_devices set name = "valid-name" where id = <device_id> limit 1'

Then restart your instance.

1 Like

Now it works. Thank you so much! :slight_smile:

1 Like

@tomp This is a tricky one. I think it depends on whether we need to parse the file names we write to retrieve project/instance/device information.

For example, currently for dnsmasq host files we have <project>_<instance>.<device>. Before https://github.com/lxc/lxd/pull/9790 we would have been able to extract the project and instance from the file name using this function. However, now this will fail if the device name contains an underscore.

Similarly, if we allow fullstops in device names we wouldn’t be able to parse these dnsmasq file names because a) the project name may contain some, and b) we couldn’t look for the final fullstop and grab everything after it.

So I think either a) relax the validation and be certain we won’t need to parse any filenames like this, or b) restrict device names further to disallow underscores.

Either way I think we can relax starting with a number.

I’m working on a PR for this.

I’m not sure we need to reverse the file names back into their constituent parts, but you never know so would be worthwhile having that property if we can.

If we use _ as the delimiter between instance and device, i.e <project>_<instance>_<device> then because project and instance cannot have _ in them, we can extract the project and the instance (splitting on the first underscore), and then splitting on the next underscore gets us the device name (even if underscores in it).

Where it becomes a problem is if we don’t always write the project name out. So we if always write the project name out (even if its default) for these files then it should be fine to use _ as a delimiter for all parts, and still allow underscores in device names.

What do you think?

Ah I didn’t see that project names couldn’t contain underscores.

Yeah that sounds good :+1:

This PR restores the ability to use ., :, / in device names.
It also allows device names to start with a number.
But still prevents device names starting with ..

It also allows for the removal of a device that is no longer valid, allowing for correcting any invalid names from old config.

We’ve cherry-picked this fix and will begin rollout in the next couple of hours.

1 Like

I also stumbled upon this. Here are a few observations:

  • When changing the validation, it would make sense to migrate existing device names. As it stands currently, the containers just no longer start after a reboot or service restart after lxd updated.
  • To allow fixing no-longer-valid device names, it would make sense to not validate names of devices to remove
  • For those looking for a quick workaround on snap, just run sudo snap revert lxd

The fix has been pushed to stable now and will reach everyone within 24h.

In general for such changes, we don’t like doing live changes but we do normally make sure that fixing the now invalid name is possible without resorting to DB trickery.

The change we merged today both allows more characters and allows invalid configurations to be fixed through the normal API/CLI.

1 Like