nocloud: fix network config regression

With commit
f0fe66b30b,
the network config in case of NoCloudConfigDrive was supported only if
it was in the format:

```yaml
network:
  config: ...
  version: 1|2
```

Before the commit, the following format was also supported:

```yaml
config: ...
version: 1
```

Added support for both formats and made sure that the `network` key is
not required.

Change-Id: I7478a8654443db83f0f3995839811910c468a06c
Signed-off-by: Adrian Vladu <avladu@cloudbasesolutions.com>
This commit is contained in:
Adrian Vladu
2024-06-21 14:30:14 +03:00
parent bf61aecd60
commit 1a98b6742a
2 changed files with 143 additions and 117 deletions

View File

@@ -237,10 +237,11 @@ class NoCloudNetworkConfigV1Parser(object):
networks = [] networks = []
services = [] services = []
network_config = network_config.get('network') \ if network_config and network_config.get('network'):
if network_config else {} network_config = network_config.get('network')
network_config = network_config.get('config') \ if network_config:
if network_config else None network_config = network_config.get('config')
if not network_config: if not network_config:
LOG.warning("Network configuration is empty") LOG.warning("Network configuration is empty")
return return
@@ -479,8 +480,9 @@ class NoCloudNetworkConfigV2Parser(object):
networks = [] networks = []
services = [] services = []
network_config = network_config.get('network') \ if network_config and network_config.get('network'):
if network_config else {} network_config = network_config.get('network')
if not network_config: if not network_config:
LOG.warning("Network configuration is empty") LOG.warning("Network configuration is empty")
return return
@@ -529,12 +531,21 @@ class NoCloudNetworkConfigParser(object):
@staticmethod @staticmethod
def parse(network_data): def parse(network_data):
network_data_version = network_data.get("network", {}).get("version") # we can have a network key in some cases
if network_data.get("network"):
network_data = network_data.get("network")
network_data_version = network_data.get("version")
if network_data_version == 1: if network_data_version == 1:
network_config_parser = NoCloudNetworkConfigV1Parser() network_config_parser = NoCloudNetworkConfigV1Parser()
return network_config_parser.parse(network_data) elif network_data_version == 2:
network_config_parser = NoCloudNetworkConfigV2Parser()
else:
raise exception.CloudbaseInitException(
"Unsupported network_data_version: '%s'"
% network_data_version)
return NoCloudNetworkConfigV2Parser().parse(network_data) return network_config_parser.parse(network_data)
class NoCloudConfigDriveService(baseconfigdrive.BaseConfigDriveService): class NoCloudConfigDriveService(baseconfigdrive.BaseConfigDriveService):

View File

@@ -15,6 +15,7 @@
import ddt import ddt
import importlib import importlib
import os import os
import textwrap
import unittest import unittest
import unittest.mock as mock import unittest.mock as mock
@@ -48,55 +49,57 @@ network:
config: config:
- type: router - type: router
""" """
NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1 = """ NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1_LEGACY = """
network: version: 1
version: 1 config:
config: - type: physical
- type: physical name: interface0
name: interface0 mac_address: "52:54:00:12:34:00"
mac_address: "52:54:00:12:34:00" mtu: 1450
mtu: 1450 subnets:
subnets: - type: static
- type: static address: 192.168.1.10
address: 192.168.1.10 netmask: 255.255.255.0
netmask: 255.255.255.0 gateway: 192.168.1.1
gateway: 192.168.1.1 dns_nameservers:
dns_nameservers: - 192.168.1.11
- 192.168.1.11 - type: bond
- type: bond name: bond0
name: bond0 bond_interfaces:
bond_interfaces: - gbe0
- gbe0 - gbe1
- gbe1 mac_address: "52:54:00:12:34:00"
mac_address: "52:54:00:12:34:00" params:
params: bond-mode: active-backup
bond-mode: active-backup bond-lacp-rate: false
bond-lacp-rate: false mtu: 1450
mtu: 1450 subnets:
subnets: - type: static
- type: static address: 192.168.1.10
address: 192.168.1.10 netmask: 255.255.255.0
netmask: 255.255.255.0 dns_nameservers:
dns_nameservers: - 192.168.1.11
- 192.168.1.11 - type: vlan
- type: vlan name: vlan0
name: vlan0 vlan_link: eth1
vlan_link: eth1 vlan_id: 150
vlan_id: 150 mac_address: "52:54:00:12:34:00"
mac_address: "52:54:00:12:34:00" mtu: 1450
mtu: 1450 subnets:
subnets: - type: static
- type: static address: 192.168.1.10
address: 192.168.1.10 netmask: 255.255.255.0
netmask: 255.255.255.0 dns_nameservers:
dns_nameservers: - 192.168.1.11
- 192.168.1.11 - type: nameserver
- type: nameserver address:
address: - 192.168.23.2
- 192.168.23.2 - 8.8.8.8
- 8.8.8.8 search: acme.local
search: acme.local
""" """
NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1 = """
network:%s
""" % (textwrap.indent(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1_LEGACY, " "))
NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_EMPTY_CONFIG = """ NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_EMPTY_CONFIG = """
""" """
NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_CONFIG_IS_NOT_DICT = """ NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_CONFIG_IS_NOT_DICT = """
@@ -116,67 +119,69 @@ network:
eth0: eth0:
- test - test
""" """
NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2 = """ NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_LEGACY = """
network: version: 2
version: 2 ethernets:
ethernets: interface0:
interface0: match:
match: macaddress: "52:54:00:12:34:00"
macaddress: "52:54:00:12:34:00" set-name: "eth0"
set-name: "eth0" addresses:
- 192.168.1.10/24
gateway4: 192.168.1.1
nameservers:
addresses: addresses:
- 192.168.1.10/24 - 192.168.1.11
gateway4: 192.168.1.1 - 192.168.1.12
nameservers: search:
addresses: - acme.local
- 192.168.1.11 mtu: 1450
- 192.168.1.12 interface1:
search: set-name: "interface1"
- acme.local addresses:
mtu: 1450 - 192.168.1.100/24
interface1: gateway4: 192.168.1.1
set-name: "interface1" nameservers:
addresses: addresses:
- 192.168.1.100/24 - 192.168.1.11
gateway4: 192.168.1.1 - 192.168.1.12
nameservers: search:
addresses: - acme.local
- 192.168.1.11 bonds:
- 192.168.1.12 bond0:
search: interfaces: ["gbe0", "gbe1"]
- acme.local match:
bonds: macaddress: "52:54:00:12:34:00"
bond0: parameters:
interfaces: ["gbe0", "gbe1"] mode: active-backup
match: lacp-rate: false
macaddress: "52:54:00:12:34:00" addresses:
parameters: - 192.168.1.10/24
mode: active-backup nameservers:
lacp-rate: false
addresses: addresses:
- 192.168.1.10/24 - 192.168.1.11
nameservers: mtu: 1450
addresses: vlans:
- 192.168.1.11 vlan0:
mtu: 1450 id: 150
vlans: link: eth1
vlan0: dhcp4: yes
id: 150 match:
link: eth1 macaddress: "52:54:00:12:34:00"
dhcp4: yes addresses:
match: - 192.168.1.10/24
macaddress: "52:54:00:12:34:00" nameservers:
addresses: addresses:
- 192.168.1.10/24 - 192.168.1.11
nameservers: mtu: 1450
addresses: bridges:
- 192.168.1.11 br0:
mtu: 1450 interfaces: ['eth0']
bridges: dhcp4: true
br0:
interfaces: ['eth0']
dhcp4: true
""" """
NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2 = """
network:%s
""" % (textwrap.indent(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_LEGACY, " "))
@ddt.ddt @ddt.ddt
@@ -207,7 +212,12 @@ class TestNoCloudNetworkConfigV1Parser(unittest.TestCase):
self.assertEqual(True, expected_result[0] in self.snatcher.output[0]) self.assertEqual(True, expected_result[0] in self.snatcher.output[0])
self.assertEqual(result, expected_result[1]) self.assertEqual(result, expected_result[1])
def test_network_details_v2(self): @ddt.data(
(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1, True),
(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1_LEGACY, True)
)
@ddt.unpack
def test_network_details_v2(self, test_data, expected_result):
expected_bond = nm.Bond( expected_bond = nm.Bond(
members=["gbe0", "gbe1"], members=["gbe0", "gbe1"],
type=nm.BOND_TYPE_ACTIVE_BACKUP, type=nm.BOND_TYPE_ACTIVE_BACKUP,
@@ -275,7 +285,7 @@ class TestNoCloudNetworkConfigV1Parser(unittest.TestCase):
search='acme.local') search='acme.local')
result = self._parser.parse( result = self._parser.parse(
serialization.parse_json_yaml(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V1)) serialization.parse_json_yaml(test_data))
self.assertEqual(result.links[0], expected_link) self.assertEqual(result.links[0], expected_link)
self.assertEqual(result.networks[0], expected_network) self.assertEqual(result.networks[0], expected_network)
@@ -318,7 +328,12 @@ class TestNoCloudNetworkConfigV2Parser(unittest.TestCase):
self.assertEqual(True, expected_result[0] in self.snatcher.output[0]) self.assertEqual(True, expected_result[0] in self.snatcher.output[0])
self.assertEqual(result, expected_result[1]) self.assertEqual(result, expected_result[1])
def test_network_details_v2(self): @ddt.data(
(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2, True),
(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2_LEGACY, True)
)
@ddt.unpack
def test_network_details_v2(self, test_data, expected_result):
expected_bond = nm.Bond( expected_bond = nm.Bond(
members=["gbe0", "gbe1"], members=["gbe0", "gbe1"],
type=nm.BOND_TYPE_ACTIVE_BACKUP, type=nm.BOND_TYPE_ACTIVE_BACKUP,
@@ -406,7 +421,7 @@ class TestNoCloudNetworkConfigV2Parser(unittest.TestCase):
search='acme.local') search='acme.local')
result = self._parser.parse( result = self._parser.parse(
serialization.parse_json_yaml(NOCLOUD_NETWORK_CONFIG_TEST_DATA_V2)) serialization.parse_json_yaml(test_data))
self.assertEqual(result.links[0], expected_link) self.assertEqual(result.links[0], expected_link)
self.assertEqual(result.links[1], expected_link_if1) self.assertEqual(result.links[1], expected_link_if1)