Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package cloud-init for openSUSE:Factory checked in at 2026-07-06 12:27:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cloud-init (Old) and /work/SRC/openSUSE:Factory/.cloud-init.new.1982 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cloud-init" Mon Jul 6 12:27:18 2026 rev:111 rq:1362985 version:25.1.3 Changes: -------- --- /work/SRC/openSUSE:Factory/cloud-init/cloud-init.changes 2025-11-20 14:46:19.712105608 +0100 +++ /work/SRC/openSUSE:Factory/.cloud-init.new.1982/cloud-init.changes 2026-07-06 12:27:36.481555072 +0200 @@ -1,0 +2,5 @@ +Wed Jun 24 12:45:55 UTC 2026 - Robert Schweikert <[email protected]> + +- Re-add cloud-init-write-routes.patch (bsc#1267422) incorrectly dropped + +------------------------------------------------------------------- New: ---- cloud-init-write-routes.patch ----------(New B)---------- New: - Re-add cloud-init-write-routes.patch (bsc#1267422) incorrectly dropped ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cloud-init.spec ++++++ --- /var/tmp/diff_new_pack.reqnSb/_old 2026-07-06 12:27:37.217580599 +0200 +++ /var/tmp/diff_new_pack.reqnSb/_new 2026-07-06 12:27:37.221580738 +0200 @@ -59,6 +59,7 @@ Patch11: cloud-init-no-single-process.patch # FIXME https://github.com/canonical/cloud-init/pull/6214 Patch12: cloud-init-needs-action.patch +Patch13: cloud-init-write-routes.patch BuildRequires: fdupes BuildRequires: filesystem @@ -110,7 +111,7 @@ Requires: %{pythons}-passlib Requires: %{pythons}-PyYAML Requires: %{pythons}-requests -Requires: %{pythons}-serial +Requires: %{pythons}-pyserial Requires: %{pythons}-setuptools Requires: %{pythons}-xml Requires: sudo @@ -172,6 +173,7 @@ %patch -P 9 %patch -P 11 %patch -P 12 +%patch -P 13 # patch in the full version to version.py version_pys=$(find . -name version.py -type f) ++++++ cloud-init-write-routes.patch ++++++ --- cloudinit/distros/__init__.py.orig +++ cloudinit/distros/__init__.py @@ -455,6 +455,15 @@ class Distro(persistence.CloudInitPickle renderer = self.network_renderer network_state = parse_net_config_data(netconfig, renderer=renderer) self._write_network_state(network_state, renderer) + # 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 # Now try to bring them up if bring_up: --- cloudinit/distros/opensuse.py.orig +++ cloudinit/distros/opensuse.py @@ -11,7 +11,7 @@ import logging import os -from cloudinit import distros, helpers, subp, util +from cloudinit import distros, helpers, subp, util, net from cloudinit.distros import PackageList from cloudinit.distros import rhel_util as rhutil from cloudinit.distros.parsers.hostname import HostnameConf @@ -256,6 +256,147 @@ class Distro(distros.Distro): conf.set_hostname(hostname) util.write_file(filename, str(conf), 0o644) + def _write_routes_v1(self, netconfig): + """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', []) + config_routes = '' + has_default_route = False + seen_default_gateway = None + for subnet in subnets: + # Render the default gateway if it is present + gateway = subnet.get('gateway') + if gateway: + config_routes += ' '.join( + ['default', gateway, '-', '-\n'] + ) + has_default_route = True + if not seen_default_gateway: + seen_default_gateway = gateway + # Render subnet routes + routes = subnet.get('routes', []) + for route in routes: + dest = route.get('destination') or route.get('network') + if not dest or dest in default_nets: + dest = 'default' + if not has_default_route: + has_default_route = True + if dest != 'default': + netmask = route.get('netmask') + if netmask: + if net.is_ipv4_network(netmask): + prefix = net.ipv4_mask_to_net_prefix(netmask) + if net.is_ipv6_network(netmask): + prefix = net.ipv6_mask_to_net_prefix(netmask) + dest += '/' + str(prefix) + if '/' not in dest: + LOG.warning( + 'Skipping route; has no prefix "%s"', dest + ) + continue + gateway = route.get('gateway') + if not gateway: + LOG.warning( + 'Missing gateway for "%s", skipping', dest + ) + continue + if ( + dest == 'default' + and has_default_route + and gateway == seen_default_gateway + ): + dest_info = dest + if gateway: + dest_info = ' '.join([dest, gateway, '-', '-']) + LOG.warning( + '%s already has default route, skipping "%s"', + if_name, dest_info + ) + continue + config_routes += ' '.join( + [dest, gateway, '-', '-\n'] + ) + if config_routes: + route_file = '/etc/sysconfig/network/ifroute-%s' % if_name + util.write_file(route_file, config_routes) + + 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' + ) + @property def preferred_ntp_clients(self): """The preferred ntp client is dependent on the version."""
