Okay, I think this is actually a combination of invalid usage and non-optimal error handling. I can reproduce the error locally on Impish:
# busctl call io.netplan.Netplan /io/netplan/Netplan io.netplan.Netplan Config
o "/io/netplan/Netplan/config/DS7XA1"
# busctl call io.netplan.Netplan /io/netplan/Netplan/config/DS7XA1 io.netplan.Netplan.Config Set ss "network.ethernets=null" "90-snapd-conf"
Call failed: netplan set failed: Child process exited with code 1
stdout: ''
stderr: 'Traceback (most recent call last):
File "/usr/sbin/netplan", line 23, in <module>
netplan.main()
File "/usr/share/netplan/netplan/cli/core.py", line 50, in main
self.run_command()
File "/usr/share/netplan/netplan/cli/utils.py", line 310, in run_command
self.func()
File "/usr/share/netplan/netplan/cli/commands/set.py", line 53, in run
self.run_command()
File "/usr/share/netplan/netplan/cli/utils.py", line 310, in run_command
self.func()
File "/usr/share/netplan/netplan/cli/commands/set.py", line 106, in command_set
self.write_file(subtree, hint + '.yaml', self.root_dir)
File "/usr/share/netplan/netplan/cli/commands/set.py", line 176, in write_file
raise Exception('Invalid input: {}'.format(set_tree))
Exception: Invalid input: {'network': {'ethernets': None}}
BUT: That only seems to happen if the file hint (here: 90-snapd-conf.yaml) does not exist. If 90-snapd-conf.yaml is filled with some config before, it works as expected:
# busctl call io.netplan.Netplan /io/netplan/Netplan/config/DS7XA1 io.netplan.Netplan.Config Set ss "network.ethernets.eth99.dhcp4=true" "90-snapd-conf"
b true
# busctl call io.netplan.Netplan /io/netplan/Netplan/config/DS7XA1 io.netplan.Netplan.Config Set ss "network.ethernets=null" "90-snapd-conf"
b true
Also, if you want to clear any ethernet definition (not just the ones from 90-snapd-conf.yaml) you could pass an empty origin hint, to make it work:
# busctl call io.netplan.Netplan /io/netplan/Netplan/config/DS7XA1 io.netplan.Netplan.Config Set ss "network.ethernets=null" ""
b true
BTW: the same issue happens with the CLI, if you pass a non existing origin-hint and we should probably improve the error handling and error message in cli/commands/set.py -> write_file():
# netplan set network.ethernets=null --origin-hint NON_EXISTING_FILE
Traceback (most recent call last):
File "/usr/sbin/netplan", line 23, in <module>
netplan.main()
File "/usr/share/netplan/netplan/cli/core.py", line 50, in main
self.run_command()
File "/usr/share/netplan/netplan/cli/utils.py", line 310, in run_command
self.func()
File "/usr/share/netplan/netplan/cli/commands/set.py", line 53, in run
self.run_command()
File "/usr/share/netplan/netplan/cli/utils.py", line 310, in run_command
self.func()
File "/usr/share/netplan/netplan/cli/commands/set.py", line 106, in command_set
self.write_file(subtree, hint + '.yaml', self.root_dir)
File "/usr/share/netplan/netplan/cli/commands/set.py", line 176, in write_file
raise Exception('Invalid input: {}'.format(set_tree))
Exception: Invalid input: {'network': {'ethernets': None}}
Okay, I think this is actually a combination of invalid usage and non-optimal error handling. I can reproduce the error locally on Impish:
# busctl call io.netplan.Netplan /io/netplan/Netplan io.netplan.Netplan Config Netplan/ config/ DS7XA1" Netplan/ config/ DS7XA1 io.netplan. Netplan. Config Set ss "network. ethernets= null" "90-snapd-conf" netplan" , line 23, in <module> netplan/ netplan/ cli/core. py", line 50, in main run_command( ) netplan/ netplan/ cli/utils. py", line 310, in run_command netplan/ netplan/ cli/commands/ set.py" , line 53, in run run_command( ) netplan/ netplan/ cli/utils. py", line 310, in run_command netplan/ netplan/ cli/commands/ set.py" , line 106, in command_set write_file( subtree, hint + '.yaml', self.root_dir) netplan/ netplan/ cli/commands/ set.py" , line 176, in write_file set_tree) )
o "/io/netplan/
# busctl call io.netplan.Netplan /io/netplan/
Call failed: netplan set failed: Child process exited with code 1
stdout: ''
stderr: 'Traceback (most recent call last):
File "/usr/sbin/
netplan.main()
File "/usr/share/
self.
File "/usr/share/
self.func()
File "/usr/share/
self.
File "/usr/share/
self.func()
File "/usr/share/
self.
File "/usr/share/
raise Exception('Invalid input: {}'.format(
Exception: Invalid input: {'network': {'ethernets': None}}
BUT: That only seems to happen if the file hint (here: 90-snapd-conf.yaml) does not exist. If 90-snapd-conf.yaml is filled with some config before, it works as expected:
# busctl call io.netplan.Netplan /io/netplan/ Netplan/ config/ DS7XA1 io.netplan. Netplan. Config Set ss "network. ethernets. eth99.dhcp4= true" "90-snapd-conf" Netplan/ config/ DS7XA1 io.netplan. Netplan. Config Set ss "network. ethernets= null" "90-snapd-conf"
b true
# busctl call io.netplan.Netplan /io/netplan/
b true
Also, if you want to clear any ethernet definition (not just the ones from 90-snapd-conf.yaml) you could pass an empty origin hint, to make it work:
# busctl call io.netplan.Netplan /io/netplan/ Netplan/ config/ DS7XA1 io.netplan. Netplan. Config Set ss "network. ethernets= null" ""
b true
BTW: the same issue happens with the CLI, if you pass a non existing origin-hint and we should probably improve the error handling and error message in cli/commands/set.py -> write_file():
# netplan set network. ethernets= null --origin-hint NON_EXISTING_FILE netplan" , line 23, in <module> netplan/ netplan/ cli/core. py", line 50, in main run_command( ) netplan/ netplan/ cli/utils. py", line 310, in run_command netplan/ netplan/ cli/commands/ set.py" , line 53, in run run_command( ) netplan/ netplan/ cli/utils. py", line 310, in run_command netplan/ netplan/ cli/commands/ set.py" , line 106, in command_set write_file( subtree, hint + '.yaml', self.root_dir) netplan/ netplan/ cli/commands/ set.py" , line 176, in write_file set_tree) )
Traceback (most recent call last):
File "/usr/sbin/
netplan.main()
File "/usr/share/
self.
File "/usr/share/
self.func()
File "/usr/share/
self.
File "/usr/share/
self.func()
File "/usr/share/
self.
File "/usr/share/
raise Exception('Invalid input: {}'.format(
Exception: Invalid input: {'network': {'ethernets': None}}