Cloud-init not working (python bug with yaml formatting?)

Following @simos splendid guide, I have set the following profile I’d like to use:
lxc profile show kcloudinit

config:
  user.network-config: |
    network:
      version: 2
      ethernets:
        eth0:
          dhcp4: no
          addresses: [192.168.1.XXX/24]
          gateway4: 192.168.1.YYY
          nameservers:
            addresses: [192.168.1.YYY]
  user.user-data: |
    #cloud-config
    package_upgrade: true
    packages:
      - python
    users:
      - name: root
        ssh_authorized_keys:
         - ssh-rsa key1
         - ssh-rsa key2
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: kcloudinit
used_by: []

However, when I launch lxc launch -p kcloudinit ubuntu:18.04 test-01-kcloudinit it doesn’t work: /etc/netplan/ directory inside the container is empty, ssh-keys are not set and python package is not installed. Here I provide log files:

If I split my configuration like this:

cat net.yml

version: 2
ethernets:
  eth0:
    dhcp4: no
    addresses: [192.168.1.131/24]
    gateway4: 192.168.1.201
    nameservers:
      addresses: [192.168.1.201]

cat userdata.yml

#cloud-config
package_upgrade: true
packages:
  - python
users:
  - name: root
    ssh_authorized_keys:
     - ssh-rsa key1
     - ssh-rsa key2

and then launch:

lxc launch -p default -p br0 ubuntu:18.04 test-01-kcloudinit --config=user.network-config="$(cat net.yml)" --config=user.user-data="$(cat userdata.yml)"

everything works as expected: the static IP is set via netplan, python package is installed and ssh authorized_keys are set.

From what I understand after some digging it migth be the problem with some problem that python3 has with formatting yaml file as seen in provided log files:

2018-11-20 11:17:21,677 - util.py[DEBUG]: failed stage init-local
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 658, in status_wrapper
    ret = functor(name, args)
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 362, in main_init
    init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
  File "/usr/lib/python3/dist-packages/cloudinit/stages.py", line 671, in apply_network_config
    return self.distro.apply_network_config(netcfg, bring_up=bring_up)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/__init__.py", line 178, in apply_network_config
    dev_names = self._write_network_config(netconfig)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/debian.py", line 114, in _write_network_config
    return self._supported_write_network_config(netconfig)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/__init__.py", line 93, in _supported_write_network_config
    renderer.render_network_config(network_config)
  File "/usr/lib/python3/dist-packages/cloudinit/net/renderer.py", line 56, in render_network_config
    templates=templates, target=target)
  File "/usr/lib/python3/dist-packages/cloudinit/net/netplan.py", line 202, in render_network_state
    content = self._render_content(network_state)
  File "/usr/lib/python3/dist-packages/cloudinit/net/netplan.py", line 236, in _render_content
    if network_state.version == 2:
AttributeError: 'NoneType' object has no attribute 'version'

Is it really a bug or have I made a mistake in profile settings?

PS. Same behavior is seen both in snap version (3.7) or standard apt version (3.0). System is Ubuntu 18.04.

Hi!

When I was writing the guide and was testing with the network settings, I noticed that the network config should be written in version: 1 instead of version: 2. Strangely, in the container it would get converted to version: 2. Could you give that a try and report back?

I did that with no luck :frowning: and I’ve just done that one more time just to be sure. Below some details:

If I run my (kcloudinit) proflie modified with version: 1 with lxc launch -p kcloudinit ubuntu:18.04 test-01-kcloudinit:

  1. Network doesn’t work: /etc/netplan is empty, but cat /var/lib/cloud/seed/nocloud-net/network-config shows my config (with version 1 unchanged)
  2. My ssh keys are setup correctly
  3. apt-uptdate and apt install python did NOT run, however cat /var/lib/cloud/seed/nocloud-net/user-data shows the configuration set in lxd profile

This bugreport might shed some light on my problem.

Thanks for reminding this. At the end of the bug report there is a link to a LXD issue that discusses this.
If you put all configuration (including the networking) under user.user-data: | does that solve the issue for you? Can you recheck whether both version 1 and version 2 work in there?

Done. Still no dice.
Because the profile config presented by @simos in bug #1686338 was slightly different than mine, I tried 4 configurations: mine with version 1 and 2, and the other with network version 1 or 2. Then I looked at the output of /var/log/cloud-init.log inside the container. The 4 logs do not differ between each other (apart from timestamps) but they do differ from the previous logs I posted, so I post the output here:

https://paste.ubuntu.com/p/Y4rrHfDPMb/

CONFIG #1

config:
  user.user-data: |
    network:
      version: (1 or 2)
      ethernets:
        eth0:
          dhcp4: no
          addresses: [192.168.1.131/24]
          gateway4: 192.168.1.201
          nameservers:
            addresses: [192.168.1.201]
description: my test profile
devices:
  eth0:
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: kcloudinit
used_by:
- /1.0/containers/test-01-kcloudinit

CONFIG #2

config:
  user.user-data: |
    network:
      version: (1 or 2)
      config:
      - type: physical
        name: eth0
        subnets:
          dhcp4: no
          addresses: [192.168.1.131/24]
          gateway4: 192.168.1.201
          nameservers:
            addresses: [192.168.1.201]
description: my test profile
devices:
  eth0:
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: kcloudinit
used_by:
- /1.0/containers/test-01-kcloudinit

In all versions the output of /etc/netplan/50-cloud-init.yaml was unaltered:

root@test-01-kcloudinit:~#  cat /etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by
# the datasource.  Changes to it will not persist across an instance.
# To disable cloud-init's network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    version: 2
    ethernets:
        eth0:
            dhcp4: true

Version 1 of the network configuration of cloud-init is more arcane.
Have a look at https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v1.html on how to adapt the configuration to be compatible to version 1.

It should look like the following (of course, change it to specify the IP addresses instead of using DHCP)

$ cat mycloudinit.profile
config:
  user.network-config: |
    network:
        version: 1
        config:
        - type: physical
          name: eth0
          subnets:
            - type: dhcp

Ok, so with this profile:

config:
  user.user-data: |
    #cloud-config
    network:
      version: 1
      config:
        - type: physical
          name: eth0
          subnets:
            - type: static
              address: 192.168.1.131/24
              gateway: 192.168.1.201
              dns_nameservers:
                - 192.168.1.201
                - 1.1.1.1
    package_upgrade: true
    packages:
      - python
    users:
      - name: root
        ssh_authorized_keys:
         - key 1
         - key 2
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: kcloudinit
used_by:
- /1.0/containers/test-01-kcloudinit

The static IP is not set and I get this cloud-init.log:

https://paste.ubuntu.com/p/wcX3j2BzZK/

in which it is read (below only a fragment of the log):

2018-11-21 22:49:04,754 - util.py[DEBUG]: Read 121 bytes from /var/lib/cloud/seed/nocloud-net/network-config
...
2018-11-21 22:49:05,073 - stages.py[INFO]: Applying network configuration from ds bringup=False: {'version': 1, 'config': [{'type': 'physical', 'name': 'eth0', 'subnets': [{'type': 'dhcp', 'control': 'auto'}]}]}
...
2018-11-21 22:49:07,596 - stages.py[DEBUG]: No network config applied. Neither a new instance nor datasource network update on 'System boot' event

And with this profile:

config:
  user.network-config: |
    #cloud-config
    network:
      version: 1
      config:
        - type: physical
          name: eth0
          subnets:
            - type: static
              address: 192.168.1.131/24
              gateway: 192.168.1.201
              dns_nameservers:
                - 192.168.1.201
                - 1.1.1.1
  user.user-data: |
    #cloud-config
    package_upgrade: true
    packages:
      - python
    users:
      - name: root
        ssh_authorized_keys:
         - key 1
         - key 2
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: kcloudinit
used_by:
- /1.0/containers/test-01-kcloudinit

Neither I have a static IP BUT I get the following log:

https://paste.ubuntu.com/p/ZW3Fs9hVt6/

Where one can find (below only a fragment of the log):

2018-11-21 22:54:15,936 - util.py[DEBUG]: Read 268 bytes from /var/lib/cloud/seed/nocloud-net/network-config
...
2018-11-21 22:54:16,245 - stages.py[DEBUG]: applying net config names for {'network': {'version': 1, 'config': [{'type': 'physical', 'name': 'eth0', 'subnets': [{'type': 'static', 'address': '192.168.1.131/24', 'gateway': '192.168.1.201', 'dns_nameservers': ['192.168.1.201', '1.1.1.1']}]}]}}
2018-11-21 22:54:16,246 - stages.py[WARNING]: Failed to rename devices: Failed to apply network config names. Found bad network config version: None
2018-11-21 22:54:16,256 - stages.py[INFO]: Applying network configuration from ds bringup=False: {'network': {'version': 1, 'config': [{'type': 'physical', 'name': 'eth0', 'subnets': [{'type': 'static', 'address': '192.168.1.131/24', 'gateway': '192.168.1.201', 'dns_nameservers': ['192.168.1.201', '1.1.1.1']}]}]}}
2018-11-21 22:54:16,257 - __init__.py[DEBUG]: Selected renderer 'netplan' from priority list: None
2018-11-21 22:54:16,258 - util.py[WARNING]: failed stage init-local
2018-11-21 22:54:16,262 - util.py[DEBUG]: failed stage init-local
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 658, in status_wrapper
    ret = functor(name, args)
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 362, in main_init
    init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
  File "/usr/lib/python3/dist-packages/cloudinit/stages.py", line 671, in apply_network_config
    return self.distro.apply_network_config(netcfg, bring_up=bring_up)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/__init__.py", line 178, in apply_network_config
    dev_names = self._write_network_config(netconfig)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/debian.py", line 114, in _write_network_config
    return self._supported_write_network_config(netconfig)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/__init__.py", line 93, in _supported_write_network_config
    renderer.render_network_config(network_config)
  File "/usr/lib/python3/dist-packages/cloudinit/net/renderer.py", line 56, in render_network_config
    templates=templates, target=target)
  File "/usr/lib/python3/dist-packages/cloudinit/net/netplan.py", line 202, in render_network_state
    content = self._render_content(network_state)
  File "/usr/lib/python3/dist-packages/cloudinit/net/netplan.py", line 236, in _render_content
    if network_state.version == 2:
AttributeError: 'NoneType' object has no attribute 'version'
...
2018-11-21 22:54:18,058 - stages.py[DEBUG]: No network config applied. Neither a new instance nor datasource network update on 'System boot' event

So with second configuration (with user.network-config: | and version: 1) it seems the config is parsed but some error stops it from being applied. I believe it has something to do with the message starting with the line:

File “/usr/lib/python3/dist-packages/cloudinit/cmd/main.py”, line 658, in status_wrapper

since the same error was presented when I tried to do it for the first time, with user.network-config: | and version: 2

Had the same problem tonight. However it started working after removing the “network:” line in your user.network-config. So here is my working profile:

   user.network-config: |
     #cloud-config
     version: 1
     config:
       - type: physical
         name: eth0
         subnets:
           - type: static
             address: 10.100.100.2/24
             gateway: 10.100.100.1
             dns_nameservers:
               - 127.0.0.1
2 Likes