File cloud-init-trigger-udev.patch of Package cloud-init

--- cloudinit/distros/opensuse.py.orig
+++ cloudinit/distros/opensuse.py
@@ -38,6 +38,8 @@ class Distro(distros.Distro):
         'sysconfig': {
             'control': 'etc/sysconfig/network/config',
             'iface_templates': '%(base)s/network/ifcfg-%(name)s',
+            'netrules_path': (
+                'etc/udev/rules.d/85-persistent-net-cloud-init.rules'),
             'route_templates': {
                 'ipv4': '%(base)s/network/ifroute-%(name)s',
                 'ipv6': '%(base)s/network/ifroute-%(name)s',
--- cloudinit/net/sysconfig.py.orig
+++ cloudinit/net/sysconfig.py
@@ -8,6 +8,7 @@ import six
 from cloudinit.distros.parsers import networkmanager_conf
 from cloudinit.distros.parsers import resolv_conf
 from cloudinit import log as logging
+from cloudinit import net
 from cloudinit import util
 
 from configobj import ConfigObj
@@ -699,6 +700,14 @@ class Renderer(renderer.Renderer):
             if nm_conf_content:
                 util.write_file(nm_conf_path, nm_conf_content, file_mode)
         if self.netrules_path:
+            # When many interfaces are present it can happen that we get here
+            # before they are all setup. Settle if that is the case.
+            for iface in network_state.iter_interfaces(
+                    renderer.filter_by_physical):
+                path = net.sys_dev_path(iface.name)
+                if not os.path.exists(path):
+                    util.udevadm_settle(path, 5)
+                    break
             netrules_content = self._render_persistent_net(network_state)
             netrules_path = util.target_path(target, self.netrules_path)
             util.write_file(netrules_path, netrules_content, file_mode)