summaryrefslogtreecommitdiff
path: root/cloudinit/sources
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2017-09-07 09:59:47 -0400
committerScott Moser <smoser@brickies.net>2017-09-07 16:37:44 -0400
commit922c3c5c1a86f2d58e95a328e72b49a3bb234ca8 (patch)
treefc4c6377b9b60e33d3c0c7d7cadaedbd467eedd1 /cloudinit/sources
parent409918f9ba83e45e9bc5cc0b6c589e2fc8ae9b60 (diff)
downloadvyos-cloud-init-922c3c5c1a86f2d58e95a328e72b49a3bb234ca8.tar.gz
vyos-cloud-init-922c3c5c1a86f2d58e95a328e72b49a3bb234ca8.zip
Ec2: only attempt to operate at local mode on known platforms.
This change makes the DataSourceEc2Local do nothing unless it is on actual AWS platform. The motivation is twofold: a.) It is generally safer to only make this function available to Ec2 clones that explicitly identify themselves to the guest. (It also gives them a reason to supply identification code to cloud-init.) b.) On non-intel OpenStack platforms ds-identify would enable both the Ec2 and OpenStack sources. That is because there is not good data (such as dmi) to positively identify the platform. Previously that would be fine as OpenStack would run first and be successful. The change to add Ec2Local meant that an Ec2 now runs first. The best case for 'b' would be a slow down as attempts at the Ec2 metadata service time out. The discovered case was worse. Additionally we add a simple check for datatype of 'network' in the metadata before attempting to read it. LP: #1715128
Diffstat (limited to 'cloudinit/sources')
-rw-r--r--cloudinit/sources/DataSourceEc2.py43
1 files changed, 35 insertions, 8 deletions
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index 07c12bb4..41367a8b 100644
--- a/cloudinit/sources/DataSourceEc2.py
+++ b/cloudinit/sources/DataSourceEc2.py
@@ -27,6 +27,8 @@ SKIP_METADATA_URL_CODES = frozenset([uhelp.NOT_FOUND])
STRICT_ID_PATH = ("datasource", "Ec2", "strict_id")
STRICT_ID_DEFAULT = "warn"
+_unset = "_unset"
+
class Platforms(object):
ALIYUN = "AliYun"
@@ -57,7 +59,7 @@ class DataSourceEc2(sources.DataSource):
_cloud_platform = None
- _network_config = None # Used for caching calculated network config v1
+ _network_config = _unset # Used for caching calculated network config v1
# Whether we want to get network configuration from the metadata service.
get_network_metadata = False
@@ -284,10 +286,24 @@ class DataSourceEc2(sources.DataSource):
@property
def network_config(self):
"""Return a network config dict for rendering ENI or netplan files."""
- if self._network_config is None:
- if self.metadata is not None:
- self._network_config = convert_ec2_metadata_network_config(
- self.metadata)
+ if self._network_config != _unset:
+ return self._network_config
+
+ if self.metadata is None:
+ # this would happen if get_data hadn't been called. leave as _unset
+ LOG.warning(
+ "Unexpected call to network_config when metadata is None.")
+ return None
+
+ result = None
+ net_md = self.metadata.get('network')
+ if isinstance(net_md, dict):
+ result = convert_ec2_metadata_network_config(net_md)
+ else:
+ LOG.warning("unexpected metadata 'network' key not valid: %s",
+ net_md)
+ self._network_config = result
+
return self._network_config
def _crawl_metadata(self):
@@ -321,6 +337,14 @@ class DataSourceEc2Local(DataSourceEc2):
"""
get_network_metadata = True # Get metadata network config if present
+ def get_data(self):
+ supported_platforms = (Platforms.AWS,)
+ if self.cloud_platform not in supported_platforms:
+ LOG.debug("Local Ec2 mode only supported on %s, not %s",
+ supported_platforms, self.cloud_platform)
+ return False
+ return super(DataSourceEc2Local, self).get_data()
+
def read_strict_mode(cfgval, default):
try:
@@ -434,10 +458,13 @@ def _collect_platform_data():
return data
-def convert_ec2_metadata_network_config(metadata=None, macs_to_nics=None):
+def convert_ec2_metadata_network_config(network_md, macs_to_nics=None):
"""Convert ec2 metadata to network config version 1 data dict.
- @param: metadata: Dictionary of metadata crawled from EC2 metadata url.
+ @param: network_md: 'network' portion of EC2 metadata.
+ generally formed as {"interfaces": {"macs": {}} where
+ 'macs' is a dictionary with mac address as key and contents like:
+ {"device-number": "0", "interface-id": "...", "local-ipv4s": ...}
@param: macs_to_name: Optional dict mac addresses and the nic name. If
not provided, get_interfaces_by_mac is called to get it from the OS.
@@ -446,7 +473,7 @@ def convert_ec2_metadata_network_config(metadata=None, macs_to_nics=None):
netcfg = {'version': 1, 'config': []}
if not macs_to_nics:
macs_to_nics = net.get_interfaces_by_mac()
- macs_metadata = metadata['network']['interfaces']['macs']
+ macs_metadata = network_md['interfaces']['macs']
for mac, nic_name in macs_to_nics.items():
nic_metadata = macs_metadata.get(mac)
if not nic_metadata: