← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~smoser/cloud-init:bug/1732917-fix-fallback-interface into cloud-init:master

 

Scott Moser has proposed merging ~smoser/cloud-init:bug/1732917-fix-fallback-interface into cloud-init:master.

Commit message:
EC2: Fix bug using fallback nic restoring from old pickled object.

If user upgraded to new cloud-init and rebooted, the restored
object never was pickled with a value in fallback_nic.  That caused
an attempt to configure networking with a None device.

We support reading the old .fallback_nic attribute if it ever
got set, but new versions will call net.find_fallback_nic() if
there has not been one found.

LP: #1732917

Requested reviews:
  cloud-init commiters (cloud-init-dev)
Related bugs:
  Bug #1732917 in cloud-init (Ubuntu): "17.1 update breaks EC2 nodes"
  https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1732917

For more details, see:
https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/333923
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~smoser/cloud-init:bug/1732917-fix-fallback-interface into cloud-init:master.
diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py
index 0cba703..1a561be 100644
--- a/cloudinit/net/dhcp.py
+++ b/cloudinit/net/dhcp.py
@@ -41,8 +41,7 @@ def maybe_perform_dhcp_discovery(nic=None):
     if nic is None:
         nic = find_fallback_nic()
         if nic is None:
-            LOG.debug(
-                'Skip dhcp_discovery: Unable to find fallback nic.')
+            LOG.debug('Skip dhcp_discovery: Unable to find fallback nic.')
             return {}
     elif nic not in get_devicelist():
         LOG.debug(
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index 0ef2217..ccf41cd 100644
--- a/cloudinit/sources/DataSourceEc2.py
+++ b/cloudinit/sources/DataSourceEc2.py
@@ -65,7 +65,7 @@ class DataSourceEc2(sources.DataSource):
     get_network_metadata = False
 
     # Track the discovered fallback nic for use in configuration generation.
-    fallback_nic = None
+    _fallback_interface = None
 
     def __init__(self, sys_cfg, distro, paths):
         sources.DataSource.__init__(self, sys_cfg, distro, paths)
@@ -92,18 +92,17 @@ class DataSourceEc2(sources.DataSource):
         elif self.cloud_platform == Platforms.NO_EC2_METADATA:
             return False
 
-        self.fallback_nic = net.find_fallback_nic()
         if self.get_network_metadata:  # Setup networking in init-local stage.
             if util.is_FreeBSD():
                 LOG.debug("FreeBSD doesn't support running dhclient with -sf")
                 return False
-            dhcp_leases = dhcp.maybe_perform_dhcp_discovery(self.fallback_nic)
+            dhcp_leases = dhcp.maybe_perform_dhcp_discovery(
+                self.fallback_interface)
             if not dhcp_leases:
                 # DataSourceEc2Local failed in init-local stage. DataSourceEc2
                 # will still run in init-network stage.
                 return False
             dhcp_opts = dhcp_leases[-1]
-            self.fallback_nic = dhcp_opts.get('interface')
             net_params = {'interface': dhcp_opts.get('interface'),
                           'ip': dhcp_opts.get('fixed-address'),
                           'prefix_or_mask': dhcp_opts.get('subnet-mask'),
@@ -303,12 +302,11 @@ class DataSourceEc2(sources.DataSource):
         result = None
         net_md = self.metadata.get('network')
         # Limit network configuration to only the primary/fallback nic
-        macs_to_nics = {
-            net.get_interface_mac(self.fallback_nic): self.fallback_nic}
+        iface = self.fallback_interface
+        macs_to_nics = {net.get_interface_mac(iface): iface}
         if isinstance(net_md, dict):
             result = convert_ec2_metadata_network_config(
-                net_md, macs_to_nics=macs_to_nics,
-                fallback_nic=self.fallback_nic)
+                net_md, macs_to_nics=macs_to_nics, fallback_nic=iface)
         else:
             LOG.warning("unexpected metadata 'network' key not valid: %s",
                         net_md)
@@ -316,6 +314,21 @@ class DataSourceEc2(sources.DataSource):
 
         return self._network_config
 
+    @property
+    def fallback_interface(self):
+        if self._fallback_interface is None:
+            # fallback_nic was used at one point, so restored objects may
+            # have an attribute there. respect that if found.
+            _legacy_fbnic = getattr(self, 'fallback_nic', None)
+            if _legacy_fbnic:
+                self._fallback_interface = _legacy_fbnic
+                self.fallback_nic = None
+            else:
+                self._fallback_interface = net.find_fallback_nic()
+                if self._fallback_interface is None:
+                    LOG.warning("Did not find a fallback interface on EC2.")
+        return self._fallback_interface
+
     def _crawl_metadata(self):
         """Crawl metadata service when available.
 

References