diff options
author | Scott Moser <smoser@brickies.net> | 2017-09-07 09:59:47 -0400 |
---|---|---|
committer | Scott Moser <smoser@brickies.net> | 2017-09-07 16:37:44 -0400 |
commit | 922c3c5c1a86f2d58e95a328e72b49a3bb234ca8 (patch) | |
tree | fc4c6377b9b60e33d3c0c7d7cadaedbd467eedd1 /cloudinit/sources/DataSourceEc2.py | |
parent | 409918f9ba83e45e9bc5cc0b6c589e2fc8ae9b60 (diff) | |
download | vyos-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/DataSourceEc2.py')
-rw-r--r-- | cloudinit/sources/DataSourceEc2.py | 43 |
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: |