2022-03-25 18:46:06 +01:00
|
|
|
--- cloudinit/distros/__init__.py.orig
|
|
|
|
+++ cloudinit/distros/__init__.py
|
|
|
|
@@ -220,6 +220,15 @@ class Distro(persistence.CloudInitPickle
|
|
|
|
network_state = parse_net_config_data(netconfig)
|
|
|
|
try:
|
|
|
|
self._write_network_state(network_state)
|
|
|
|
+ # The sysconfig renderer has no route writing implementation
|
|
|
|
+ # for SUSE yet use the old code for now that depends on the
|
|
|
|
+ # raw config.
|
|
|
|
+ try:
|
|
|
|
+ # Only exists for SUSE distro via this patch all other
|
|
|
|
+ # implementations throw which breaks testing
|
|
|
|
+ self._write_routes(netconfig)
|
|
|
|
+ except AttributeError:
|
|
|
|
+ pass
|
|
|
|
except NotImplementedError:
|
|
|
|
# backwards compat until all distros have apply_network_config
|
|
|
|
return self._apply_network_from_network_config(
|
2019-01-18 10:50:54 +01:00
|
|
|
--- cloudinit/distros/opensuse.py.orig
|
|
|
|
+++ cloudinit/distros/opensuse.py
|
2021-08-19 14:25:42 +02:00
|
|
|
@@ -8,9 +8,12 @@
|
|
|
|
#
|
|
|
|
# This file is part of cloud-init. See LICENSE file for license information.
|
|
|
|
|
|
|
|
+import logging
|
|
|
|
+
|
2019-11-08 16:05:12 +01:00
|
|
|
from cloudinit import distros
|
|
|
|
|
|
|
|
from cloudinit.distros.parsers.hostname import HostnameConf
|
|
|
|
+from cloudinit.net.network_state import mask_to_net_prefix
|
|
|
|
|
|
|
|
from cloudinit import helpers
|
2021-08-19 14:25:42 +02:00
|
|
|
from cloudinit import subp
|
|
|
|
@@ -19,6 +22,7 @@ from cloudinit import util
|
|
|
|
from cloudinit.distros import rhel_util as rhutil
|
|
|
|
from cloudinit.settings import PER_INSTANCE
|
|
|
|
|
|
|
|
+LOG = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
class Distro(distros.Distro):
|
|
|
|
clock_conf_fn = '/etc/sysconfig/clock'
|
2022-03-25 18:46:06 +01:00
|
|
|
@@ -168,6 +172,143 @@ class Distro(distros.Distro):
|
|
|
|
conf.set_hostname(hostname)
|
|
|
|
util.write_file(filename, str(conf), 0o644)
|
2019-01-18 10:50:54 +01:00
|
|
|
|
2020-05-19 21:06:35 +02:00
|
|
|
+ def _write_routes_v1(self, netconfig):
|
2019-01-18 10:50:54 +01:00
|
|
|
+ """Write route files, not part of the standard distro interface"""
|
|
|
|
+ # Due to the implementation of the sysconfig renderer default routes
|
|
|
|
+ # are setup in ifcfg-* files. But this does not work on SLES or
|
|
|
|
+ # openSUSE https://bugs.launchpad.net/cloud-init/+bug/1812117
|
|
|
|
+ # this is a very hacky way to get around the problem until a real
|
|
|
|
+ # solution is found in the sysconfig renderer
|
|
|
|
+ device_configs = netconfig.get('config', [])
|
|
|
|
+ default_nets = ('::', '0.0.0.0')
|
|
|
|
+ for config in device_configs:
|
|
|
|
+ if_name = config.get('name')
|
|
|
|
+ subnets = config.get('subnets', [])
|
2019-04-30 22:39:13 +02:00
|
|
|
+ config_routes = ''
|
2020-03-27 13:40:41 +01:00
|
|
|
+ has_default_route = False
|
2020-11-10 12:41:01 +01:00
|
|
|
+ seen_default_gateway = None
|
2019-01-18 10:50:54 +01:00
|
|
|
+ for subnet in subnets:
|
2020-03-25 20:41:57 +01:00
|
|
|
+ # Render the default gateway if it is present
|
|
|
|
+ gateway = subnet.get('gateway')
|
|
|
|
+ if gateway:
|
|
|
|
+ config_routes += ' '.join(
|
|
|
|
+ ['default', gateway, '-', '-\n']
|
|
|
|
+ )
|
2020-03-27 13:40:41 +01:00
|
|
|
+ has_default_route = True
|
2020-11-10 12:41:01 +01:00
|
|
|
+ if not seen_default_gateway:
|
|
|
|
+ seen_default_gateway = gateway
|
2020-03-25 20:41:57 +01:00
|
|
|
+ # Render subnet routes
|
2019-01-18 10:50:54 +01:00
|
|
|
+ routes = subnet.get('routes', [])
|
|
|
|
+ for route in routes:
|
2020-03-26 18:22:08 +01:00
|
|
|
+ dest = route.get('destination') or route.get('network')
|
2020-03-27 13:40:41 +01:00
|
|
|
+ if not dest or dest in default_nets:
|
2019-01-18 10:50:54 +01:00
|
|
|
+ dest = 'default'
|
2021-01-04 23:34:44 +01:00
|
|
|
+ if not has_default_route:
|
|
|
|
+ has_default_route = True
|
2019-01-18 10:50:54 +01:00
|
|
|
+ if dest != 'default':
|
2020-03-25 20:41:57 +01:00
|
|
|
+ netmask = route.get('netmask')
|
2020-02-12 20:33:31 +01:00
|
|
|
+ if netmask:
|
|
|
|
+ prefix = mask_to_net_prefix(netmask)
|
|
|
|
+ dest += '/' + str(prefix)
|
|
|
|
+ if '/' not in dest:
|
|
|
|
+ LOG.warning(
|
2020-03-27 13:40:41 +01:00
|
|
|
+ 'Skipping route; has no prefix "%s"', dest
|
2020-02-12 20:33:31 +01:00
|
|
|
+ )
|
2020-03-27 13:40:41 +01:00
|
|
|
+ continue
|
2021-01-04 23:34:44 +01:00
|
|
|
+ gateway = route.get('gateway')
|
|
|
|
+ if not gateway:
|
|
|
|
+ LOG.warning(
|
|
|
|
+ 'Missing gateway for "%s", skipping', dest
|
|
|
|
+ )
|
|
|
|
+ continue
|
2020-11-10 12:41:01 +01:00
|
|
|
+ if (
|
|
|
|
+ dest == 'default' and
|
|
|
|
+ has_default_route and
|
|
|
|
+ gateway == seen_default_gateway
|
|
|
|
+ ):
|
2020-10-17 12:31:14 +02:00
|
|
|
+ dest_info = dest
|
|
|
|
+ if gateway:
|
|
|
|
+ dest_info = ' '.join([dest, gateway, '-', '-'])
|
2020-03-27 13:40:41 +01:00
|
|
|
+ LOG.warning(
|
|
|
|
+ '%s already has default route, skipping "%s"',
|
2020-10-17 12:31:14 +02:00
|
|
|
+ if_name, dest_info
|
2020-03-27 13:40:41 +01:00
|
|
|
+ )
|
|
|
|
+ continue
|
2019-11-08 16:05:12 +01:00
|
|
|
+ config_routes += ' '.join(
|
|
|
|
+ [dest, gateway, '-', '-\n']
|
|
|
|
+ )
|
2019-01-18 10:50:54 +01:00
|
|
|
+ if config_routes:
|
|
|
|
+ route_file = '/etc/sysconfig/network/ifroute-%s' % if_name
|
|
|
|
+ util.write_file(route_file, config_routes)
|
2020-05-19 21:06:35 +02:00
|
|
|
+
|
|
|
|
+ def _render_route_string(self, netconfig_route):
|
|
|
|
+ route_to = netconfig_route.get('to', None)
|
|
|
|
+ route_via = netconfig_route.get('via', None)
|
|
|
|
+ route_metric = netconfig_route.get('metric', None)
|
|
|
|
+ route_string = ''
|
|
|
|
+
|
|
|
|
+ if route_to and route_via:
|
|
|
|
+ route_string = ' '.join([route_to, route_via, '-', '-'])
|
|
|
|
+ if route_metric:
|
|
|
|
+ route_string += ' metric {}\n'.format(route_metric)
|
|
|
|
+ else:
|
|
|
|
+ route_string += '\n'
|
|
|
|
+ else:
|
|
|
|
+ LOG.warning('invalid route definition, skipping route')
|
|
|
|
+
|
|
|
|
+ return route_string
|
|
|
|
+
|
|
|
|
+ def _write_routes_v2(self, netconfig):
|
|
|
|
+ for device_type in netconfig:
|
|
|
|
+ if device_type == 'version':
|
|
|
|
+ continue
|
|
|
|
+
|
|
|
|
+ if device_type == 'routes':
|
|
|
|
+ # global static routes
|
|
|
|
+ config_routes = ''
|
|
|
|
+ for route in netconfig['routes']:
|
|
|
|
+ config_routes += self._render_route_string(route)
|
|
|
|
+ if config_routes:
|
|
|
|
+ route_file = '/etc/sysconfig/network/routes'
|
|
|
|
+ util.write_file(route_file, config_routes)
|
|
|
|
+ else:
|
|
|
|
+ devices = netconfig[device_type]
|
|
|
|
+ for device_name in devices:
|
|
|
|
+ config_routes = ''
|
|
|
|
+ device_config = devices[device_name]
|
|
|
|
+ try:
|
|
|
|
+ gateways = [
|
|
|
|
+ v for k, v in device_config.items()
|
|
|
|
+ if 'gateway' in k
|
|
|
|
+ ]
|
|
|
|
+ for gateway in gateways:
|
|
|
|
+ config_routes += ' '.join(
|
|
|
|
+ ['default', gateway, '-', '-\n']
|
|
|
|
+ )
|
|
|
|
+ for route in device_config.get('routes', []):
|
|
|
|
+ config_routes += self._render_route_string(route)
|
|
|
|
+ if config_routes:
|
|
|
|
+ route_file = '/etc/sysconfig/network/ifroute-{}'.format(
|
|
|
|
+ device_name
|
|
|
|
+ )
|
|
|
|
+ util.write_file(route_file, config_routes)
|
|
|
|
+ except Exception:
|
|
|
|
+ # the parser above epxects another level of nesting
|
|
|
|
+ # which should be there in case it's properly
|
|
|
|
+ # formatted; if not we may get an exception on items()
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+ def _write_routes(self, netconfig):
|
|
|
|
+ netconfig_ver = netconfig.get('version')
|
|
|
|
+ if netconfig_ver == 1:
|
|
|
|
+ self._write_routes_v1(netconfig)
|
|
|
|
+ elif netconfig_ver == 2:
|
|
|
|
+ self._write_routes_v2(netconfig)
|
|
|
|
+ else:
|
|
|
|
+ LOG.warning(
|
|
|
|
+ 'unsupported or missing netconfig version, not writing routes'
|
|
|
|
+ )
|
2022-03-25 18:46:06 +01:00
|
|
|
+
|
2019-01-18 10:50:54 +01:00
|
|
|
@property
|
|
|
|
def preferred_ntp_clients(self):
|
2022-03-25 18:46:06 +01:00
|
|
|
"""The preferred ntp client is dependent on the version."""
|