diff options
author | zdc <zdc@users.noreply.github.com> | 2020-07-30 23:13:25 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-30 23:13:25 +0300 |
commit | 6dc8bb5cda13f1bf1ed73fba653fdc39f58c8a58 (patch) | |
tree | a8b7af14a7ba4d0d4deacdf5b593913b37c1de56 /cloudinit/config/cc_vyos.py | |
parent | b259f14598a5468df65a31bbe24640ae560bb614 (diff) | |
parent | ab385feb8db847960dc83adbe8fb267b4471a0b9 (diff) | |
download | vyos-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
Diffstat (limited to 'cloudinit/config/cc_vyos.py')
-rw-r--r-- | cloudinit/config/cc_vyos.py | 120 |
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']) |