summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzdc <zdc@users.noreply.github.com>2020-07-30 23:13:25 +0300
committerGitHub <noreply@github.com>2020-07-30 23:13:25 +0300
commit6dc8bb5cda13f1bf1ed73fba653fdc39f58c8a58 (patch)
treea8b7af14a7ba4d0d4deacdf5b593913b37c1de56
parentb259f14598a5468df65a31bbe24640ae560bb614 (diff)
parentab385feb8db847960dc83adbe8fb267b4471a0b9 (diff)
downloadvyos-cloud-init-6dc8bb5cda13f1bf1ed73fba653fdc39f58c8a58.tar.gz
vyos-cloud-init-6dc8bb5cda13f1bf1ed73fba653fdc39f58c8a58.zip
Merge pull request #15 from zdc/T2403-equuleus
cc_vyos: T2403: Resolved IP addresses configuration conflicts
-rw-r--r--cloudinit/config/cc_vyos.py120
1 files changed, 96 insertions, 24 deletions
diff --git a/cloudinit/config/cc_vyos.py b/cloudinit/config/cc_vyos.py
index f1b8781f..37f45cf8 100644
--- a/cloudinit/config/cc_vyos.py
+++ b/cloudinit/config/cc_vyos.py
@@ -133,13 +133,13 @@ def set_config_ovf(config, metadata):
cidr = str(ipaddress.IPv4Network('0.0.0.0/' + mask_0).prefixlen)
ipcidr = ip_0 + '/' + cidr
- config.set(['interfaces', 'ethernet', 'eth0', 'address'], value=ipcidr, replace=True)
+ set_ipaddress(config, 'eth0', ipcidr)
config.set_tag(['interfaces', 'ethernet'])
config.set(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop'], value=gateway, replace=True)
config.set_tag(['protocols', 'static', 'route'])
config.set_tag(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop'])
else:
- config.set(['interfaces', 'ethernet', 'eth0', 'address'], value='dhcp', replace=True)
+ set_ipaddress(config, 'eth0', 'dhcp')
config.set_tag(['interfaces', 'ethernet'])
DNS = [server for server in DNS if server and server != 'null']
@@ -165,8 +165,58 @@ def set_config_ovf(config, metadata):
config.set_tag(['service', 'https', 'listen-address'])
+# get an IP address type
+def get_ip_type(address):
+ addr_type = None
+ if address in ['dhcp', 'dhcpv6']:
+ addr_type = address
+ else:
+ try:
+ ip_version = ipaddress.ip_interface(address).version
+ if ip_version == 4:
+ addr_type = 'ipv4'
+ if ip_version == 6:
+ addr_type = 'ipv6'
+ except Exception as err:
+ logger.error("Unable to detect IP address type: {}".format(err))
+ logger.debug("IP address {} have type: {}".format(address, addr_type))
+ return addr_type
+
+
+# configure IP address for interface
+def set_ipaddress(config, iface, address):
+ # detect an IP address type
+ addr_type = get_ip_type(address)
+ if not addr_type:
+ logger.error("Unable to configure the IP address: {}".format(address))
+ return
+
+ # check a current configuration of an interface
+ if config.exists(['interfaces', 'ethernet', iface, 'address']):
+ current_addresses = config.return_values(['interfaces', 'ethernet', iface, 'address'])
+ logger.debug("IP address for interface {} already configured: {}".format(iface, current_addresses))
+ # check if currently configured addresses can be used with new one
+ incompatible_addresses = []
+ for current_address in current_addresses:
+ # dhcp cannot be used with static IP address at the same time
+ if ((addr_type == 'dhcp' and get_ip_type(current_address) == 'ipv4') or
+ (addr_type == 'ipv4' and get_ip_type(current_address) == 'dhcp') or
+ (addr_type == 'dhcpv6' and get_ip_type(current_address) == 'ipv6') or
+ (addr_type == 'ipv6' and get_ip_type(current_address) == 'dhcpv6')):
+ incompatible_addresses.append(current_address)
+ # inform about error and skip configuration
+ if incompatible_addresses:
+ logger.error("IP address {} cannot be configured, because it conflicts with already exists: {}".format(address, incompatible_addresses))
+ return
+
+ # configure address
+ logger.debug("Configuring IP address {} on interface {}".format(address, iface))
+ config.set(['interfaces', 'ethernet', iface, 'address'], value=address, replace=False)
+
+
# configure interface from networking config version 1
def set_config_interfaces_v1(config, iface_config):
+ logger.debug("Configuring network using Cloud-init networking config version 1")
# configure physical interfaces
if iface_config['type'] == 'physical':
iface_name = iface_config['name']
@@ -178,20 +228,13 @@ def set_config_interfaces_v1(config, iface_config):
# configure subnets
if 'subnets' in iface_config:
- # if DHCP is already configured, we should ignore all other addresses, as in VyOS it is impossible to use both on the same interface
- dhcp4_configured = False
- dhcp6_configured = False
for subnet in iface_config['subnets']:
# configure DHCP client
if subnet['type'] in ['dhcp', 'dhcp4', 'dhcp6']:
if subnet['type'] == 'dhcp6':
- logger.debug("Configuring DHCPv6 for {}".format(iface_name))
- config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp6', replace=True)
- dhcp6_configured = True
+ set_ipaddress(config, iface_name, 'dhcpv6')
else:
- logger.debug("Configuring DHCPv4 for {}".format(iface_name))
- config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp', replace=True)
- dhcp4_configured = True
+ set_ipaddress(config, iface_name, 'dhcp')
config.set_tag(['interfaces', 'ethernet'])
continue
@@ -205,18 +248,17 @@ def set_config_interfaces_v1(config, iface_config):
ip_address = ip_interface.ip.compressed
ip_static_addr = ''
# format IPv4
- if ip_version == 4 and ip_address != '0.0.0.0' and dhcp4_configured is not True:
+ if ip_version == 4 and ip_address != '0.0.0.0':
if '/' in subnet['address']:
ip_static_addr = ip_interface.compressed
else:
ip_static_addr = ipaddress.IPv4Interface('{}/{}'.format(ip_address, subnet['netmask'])).compressed
# format IPv6
- if ip_version == 6 and dhcp6_configured is not True:
+ if ip_version == 6:
ip_static_addr = ip_interface.compressed
# apply to the configuration
if ip_static_addr:
- logger.debug("Configuring static IP address for {}: {}".format(iface_name, ip_static_addr))
- config.set(['interfaces', 'ethernet', iface_name, 'address'], value=ip_static_addr, replace=True)
+ set_ipaddress(config, iface_name, ip_static_addr)
config.set_tag(['interfaces', 'ethernet'])
except Exception as err:
logger.error("Impossible to configure static IP address: {}".format(err))
@@ -237,12 +279,12 @@ def set_config_interfaces_v1(config, iface_config):
logger.debug("Configuring IPv4 route on {}: {} via {}".format(iface_name, ip_network.compressed, item['gateway']))
config.set(['protocols', 'static', 'route', ip_network.compressed, 'next-hop'], value=item['gateway'], replace=True)
config.set_tag(['protocols', 'static', 'route'])
- config.set_tag(['protocols', 'static', 'route', item['to'], 'next-hop'])
+ config.set_tag(['protocols', 'static', 'route', ip_network.compressed, 'next-hop'])
if ip_network.version == 6:
logger.debug("Configuring IPv6 route on {}: {} via {}".format(iface_name, ip_network.compressed, item['gateway']))
config.set(['protocols', 'static', 'route6', ip_network.compressed, 'next-hop'], value=item['gateway'], replace=True)
config.set_tag(['protocols', 'static', 'route6'])
- config.set_tag(['protocols', 'static', 'route6', item['to'], 'next-hop'])
+ config.set_tag(['protocols', 'static', 'route6', ip_network.compressed, 'next-hop'])
except Exception as err:
logger.error("Impossible to detect IP protocol version: {}".format(err))
@@ -257,26 +299,56 @@ def set_config_interfaces_v1(config, iface_config):
logger.debug("Configuring DNS search domain for {}: {}".format(iface_name, item))
config.set(['system', 'domain-search'], value=item, replace=False)
+ # configure nameservers
+ if iface_config['type'] == 'nameserver':
+ for item in iface_config['address']:
+ logger.debug("Configuring DNS nameserver: {}".format(item))
+ config.set(['system', 'name-server'], value=item, replace=False)
+
+ if 'search' in iface_config:
+ for item in iface_config['search']:
+ logger.debug("Configuring DNS search domain: {}".format(item))
+ config.set(['system', 'domain-search'], value=item, replace=False)
+
+ # configure routes
+ if iface_config['type'] == 'route':
+ try:
+ ip_network = ipaddress.ip_network(iface_config['destination'])
+ if ip_network.version == 4:
+ logger.debug("Configuring IPv4 route: {} via {}".format(ip_network.compressed, iface_config['gateway']))
+ config.set(['protocols', 'static', 'route', ip_network.compressed, 'next-hop'], value=iface_config['gateway'], replace=True)
+ config.set_tag(['protocols', 'static', 'route'])
+ config.set_tag(['protocols', 'static', 'route', ip_network.compressed, 'next-hop'])
+ if 'metric' in iface_config:
+ config.set(['protocols', 'static', 'route', ip_network.compressed, 'next-hop', iface_config['gateway'], distance], value=iface_config['metric'], replace=True)
+ if ip_network.version == 6:
+ logger.debug("Configuring IPv6 route: {} via {}".format(ip_network.compressed, iface_config['gateway']))
+ config.set(['protocols', 'static', 'route6', ip_network.compressed, 'next-hop'], value=iface_config['gateway'], replace=True)
+ config.set_tag(['protocols', 'static', 'route6'])
+ config.set_tag(['protocols', 'static', 'route6', ip_network.compressed, 'next-hop'])
+ if 'metric' in iface_config:
+ config.set(['protocols', 'static', 'route6', ip_network.compressed, 'next-hop', iface_config['gateway'], distance], value=iface_config['metric'], replace=True)
+ except Exception as err:
+ logger.error("Impossible to detect IP protocol version: {}".format(err))
+
# configure interface from networking config version 2
def set_config_interfaces_v2(config, iface_name, iface_config):
+ logger.debug("Configuring network using Cloud-init networking config version 2")
# configure DHCP client
if 'dhcp4' in iface_config:
if iface_config['dhcp4'] is True:
- logger.debug("Configuring DHCPv4 for {}".format(iface_name))
- config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp', replace=True)
+ set_ipaddress(config, iface_name, 'dhcp')
config.set_tag(['interfaces', 'ethernet'])
if 'dhcp6' in iface_config:
if iface_config['dhcp6'] is True:
- logger.debug("Configuring DHCPv6 for {}".format(iface_name))
- config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp6', replace=True)
+ set_ipaddress(config, iface_name, 'dhcpv6')
config.set_tag(['interfaces', 'ethernet'])
# configure static addresses
if 'addresses' in iface_config:
for item in iface_config['addresses']:
- logger.debug("Configuring static IP address for {}: {}".format(iface_name, item))
- config.set(['interfaces', 'ethernet', iface_name, 'address'], value=item, replace=True)
+ set_ipaddress(config, iface_name, item)
config.set_tag(['interfaces', 'ethernet'])
# configure gateways
@@ -329,7 +401,7 @@ def set_config_interfaces_v2(config, iface_name, iface_config):
# configure DHCP client for eth0 interface (fallback)
def set_config_dhcp(config):
logger.debug("Configuring DHCPv4 on eth0 interface (fallback)")
- config.set(['interfaces', 'ethernet', 'eth0', 'address'], value='dhcp', replace=True)
+ set_ipaddress(config, 'eth0', 'dhcp')
config.set_tag(['interfaces', 'ethernet'])