|
|
bfa931 |
From 75ee377f902082f23de0feea190444e19a942420 Mon Sep 17 00:00:00 2001
|
|
|
bfa931 |
From: Scott Moser <smoser@brickies.net>
|
|
|
bfa931 |
Date: Thu, 23 Feb 2017 17:15:27 -0500
|
|
|
bfa931 |
Subject: [PATCH 2/5] DatasourceEc2: add warning message when not on AWS.
|
|
|
bfa931 |
|
|
|
bfa931 |
Based on the setting Datasource/Ec2/strict_id, the datasource
|
|
|
bfa931 |
will now warn once per instance.
|
|
|
bfa931 |
|
|
|
bfa931 |
(cherry picked from commit 9bb55c6c45bcc5e310cf7e4d42cad53759dcca15)
|
|
|
bfa931 |
|
|
|
bfa931 |
Resolves: rhbz#1496113
|
|
|
bfa931 |
|
|
|
bfa931 |
Signed-off-by: Ryan McCabe <rmccabe@redhat.com>
|
|
|
bfa931 |
---
|
|
|
bfa931 |
cloudinit/sources/DataSourceAliYun.py | 4 +
|
|
|
bfa931 |
cloudinit/sources/DataSourceEc2.py | 178 +++++++++++++++++++++++++++++++++-
|
|
|
bfa931 |
2 files changed, 180 insertions(+), 2 deletions(-)
|
|
|
bfa931 |
|
|
|
bfa931 |
diff --git a/cloudinit/sources/DataSourceAliYun.py b/cloudinit/sources/DataSourceAliYun.py
|
|
|
bfa931 |
index 2d00255c..9debe947 100644
|
|
|
bfa931 |
--- a/cloudinit/sources/DataSourceAliYun.py
|
|
|
bfa931 |
+++ b/cloudinit/sources/DataSourceAliYun.py
|
|
|
bfa931 |
@@ -22,6 +22,10 @@ class DataSourceAliYun(EC2.DataSourceEc2):
|
|
|
bfa931 |
def get_public_ssh_keys(self):
|
|
|
bfa931 |
return parse_public_keys(self.metadata.get('public-keys', {}))
|
|
|
bfa931 |
|
|
|
bfa931 |
+ @property
|
|
|
bfa931 |
+ def cloud_platform(self):
|
|
|
bfa931 |
+ return EC2.Platforms.ALIYUN
|
|
|
bfa931 |
+
|
|
|
bfa931 |
|
|
|
bfa931 |
def parse_public_keys(public_keys):
|
|
|
bfa931 |
keys = []
|
|
|
bfa931 |
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
|
|
|
bfa931 |
index c657fd09..26da263a 100644
|
|
|
bfa931 |
--- a/cloudinit/sources/DataSourceEc2.py
|
|
|
bfa931 |
+++ b/cloudinit/sources/DataSourceEc2.py
|
|
|
bfa931 |
@@ -9,6 +9,7 @@
|
|
|
bfa931 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
|
bfa931 |
|
|
|
bfa931 |
import os
|
|
|
bfa931 |
+import textwrap
|
|
|
bfa931 |
import time
|
|
|
bfa931 |
|
|
|
bfa931 |
from cloudinit import ec2_utils as ec2
|
|
|
bfa931 |
@@ -22,12 +23,23 @@ LOG = logging.getLogger(__name__)
|
|
|
bfa931 |
# Which version we are requesting of the ec2 metadata apis
|
|
|
bfa931 |
DEF_MD_VERSION = '2009-04-04'
|
|
|
bfa931 |
|
|
|
bfa931 |
+STRICT_ID_PATH = ("datasource", "Ec2", "strict_id")
|
|
|
bfa931 |
+STRICT_ID_DEFAULT = "warn"
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+class Platforms(object):
|
|
|
bfa931 |
+ ALIYUN = "AliYun"
|
|
|
bfa931 |
+ AWS = "AWS"
|
|
|
bfa931 |
+ SEEDED = "Seeded"
|
|
|
bfa931 |
+ UNKNOWN = "Unknown"
|
|
|
bfa931 |
+
|
|
|
bfa931 |
|
|
|
bfa931 |
class DataSourceEc2(sources.DataSource):
|
|
|
bfa931 |
# Default metadata urls that will be used if none are provided
|
|
|
bfa931 |
# They will be checked for 'resolveability' and some of the
|
|
|
bfa931 |
# following may be discarded if they do not resolve
|
|
|
bfa931 |
metadata_urls = ["http://169.254.169.254", "http://instance-data.:8773"]
|
|
|
bfa931 |
+ _cloud_platform = None
|
|
|
bfa931 |
|
|
|
bfa931 |
def __init__(self, sys_cfg, distro, paths):
|
|
|
bfa931 |
sources.DataSource.__init__(self, sys_cfg, distro, paths)
|
|
|
bfa931 |
@@ -41,8 +53,18 @@ class DataSourceEc2(sources.DataSource):
|
|
|
bfa931 |
self.userdata_raw = seed_ret['user-data']
|
|
|
bfa931 |
self.metadata = seed_ret['meta-data']
|
|
|
bfa931 |
LOG.debug("Using seeded ec2 data from %s", self.seed_dir)
|
|
|
bfa931 |
+ self._cloud_platform = Platforms.SEEDED
|
|
|
bfa931 |
return True
|
|
|
bfa931 |
|
|
|
bfa931 |
+ strict_mode, _sleep = read_strict_mode(
|
|
|
bfa931 |
+ util.get_cfg_by_path(self.sys_cfg, STRICT_ID_PATH,
|
|
|
bfa931 |
+ STRICT_ID_DEFAULT), ("warn", None))
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ LOG.debug("strict_mode: %s, cloud_platform=%s",
|
|
|
bfa931 |
+ strict_mode, self.cloud_platform)
|
|
|
bfa931 |
+ if strict_mode == "true" and self.cloud_platform == Platforms.UNKNOWN:
|
|
|
bfa931 |
+ return False
|
|
|
bfa931 |
+
|
|
|
bfa931 |
try:
|
|
|
bfa931 |
if not self.wait_for_metadata_service():
|
|
|
bfa931 |
return False
|
|
|
bfa931 |
@@ -51,8 +73,8 @@ class DataSourceEc2(sources.DataSource):
|
|
|
bfa931 |
ec2.get_instance_userdata(self.api_ver, self.metadata_address)
|
|
|
bfa931 |
self.metadata = ec2.get_instance_metadata(self.api_ver,
|
|
|
bfa931 |
self.metadata_address)
|
|
|
bfa931 |
- LOG.debug("Crawl of metadata service took %s seconds",
|
|
|
bfa931 |
- int(time.time() - start_time))
|
|
|
bfa931 |
+ LOG.debug("Crawl of metadata service took %.3f seconds",
|
|
|
bfa931 |
+ time.time() - start_time)
|
|
|
bfa931 |
return True
|
|
|
bfa931 |
except Exception:
|
|
|
bfa931 |
util.logexc(LOG, "Failed reading from metadata address %s",
|
|
|
bfa931 |
@@ -190,6 +212,158 @@ class DataSourceEc2(sources.DataSource):
|
|
|
bfa931 |
return az[:-1]
|
|
|
bfa931 |
return None
|
|
|
bfa931 |
|
|
|
bfa931 |
+ @property
|
|
|
bfa931 |
+ def cloud_platform(self):
|
|
|
bfa931 |
+ if self._cloud_platform is None:
|
|
|
bfa931 |
+ self._cloud_platform = identify_platform()
|
|
|
bfa931 |
+ return self._cloud_platform
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ def activate(self, cfg, is_new_instance):
|
|
|
bfa931 |
+ if not is_new_instance:
|
|
|
bfa931 |
+ return
|
|
|
bfa931 |
+ if self.cloud_platform == Platforms.UNKNOWN:
|
|
|
bfa931 |
+ warn_if_necessary(
|
|
|
bfa931 |
+ util.get_cfg_by_path(cfg, STRICT_ID_PATH, STRICT_ID_DEFAULT))
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def read_strict_mode(cfgval, default):
|
|
|
bfa931 |
+ try:
|
|
|
bfa931 |
+ return parse_strict_mode(cfgval)
|
|
|
bfa931 |
+ except ValueError as e:
|
|
|
bfa931 |
+ LOG.warn(e)
|
|
|
bfa931 |
+ return default
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def parse_strict_mode(cfgval):
|
|
|
bfa931 |
+ # given a mode like:
|
|
|
bfa931 |
+ # true, false, warn,[sleep]
|
|
|
bfa931 |
+ # return tuple with string mode (true|false|warn) and sleep.
|
|
|
bfa931 |
+ if cfgval is True:
|
|
|
bfa931 |
+ return 'true', None
|
|
|
bfa931 |
+ if cfgval is False:
|
|
|
bfa931 |
+ return 'false', None
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ if not cfgval:
|
|
|
bfa931 |
+ return 'warn', 0
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ mode, _, sleep = cfgval.partition(",")
|
|
|
bfa931 |
+ if mode not in ('true', 'false', 'warn'):
|
|
|
bfa931 |
+ raise ValueError(
|
|
|
bfa931 |
+ "Invalid mode '%s' in strict_id setting '%s': "
|
|
|
bfa931 |
+ "Expected one of 'true', 'false', 'warn'." % (mode, cfgval))
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ if sleep:
|
|
|
bfa931 |
+ try:
|
|
|
bfa931 |
+ sleep = int(sleep)
|
|
|
bfa931 |
+ except ValueError:
|
|
|
bfa931 |
+ raise ValueError("Invalid sleep '%s' in strict_id setting '%s': "
|
|
|
bfa931 |
+ "not an integer" % (sleep, cfgval))
|
|
|
bfa931 |
+ else:
|
|
|
bfa931 |
+ sleep = None
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ return mode, sleep
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def warn_if_necessary(cfgval):
|
|
|
bfa931 |
+ try:
|
|
|
bfa931 |
+ mode, sleep = parse_strict_mode(cfgval)
|
|
|
bfa931 |
+ except ValueError as e:
|
|
|
bfa931 |
+ LOG.warn(e)
|
|
|
bfa931 |
+ return
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ if mode == "false":
|
|
|
bfa931 |
+ return
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ show_warning(sleep)
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def show_warning(sleep):
|
|
|
bfa931 |
+ message = textwrap.dedent("""
|
|
|
bfa931 |
+ ****************************************************************
|
|
|
bfa931 |
+ # This system is using the EC2 Metadata Service, but does not #
|
|
|
bfa931 |
+ # appear to be running on Amazon EC2 or one of cloud-init's #
|
|
|
bfa931 |
+ # known platforms that provide a EC2 Metadata service. In the #
|
|
|
bfa931 |
+ # future, cloud-init may stop reading metadata from the EC2 #
|
|
|
bfa931 |
+ # Metadata Service unless the platform can be identified #
|
|
|
bfa931 |
+ # #
|
|
|
bfa931 |
+ # If you are seeing this message, please file a bug against #
|
|
|
bfa931 |
+ # cloud-init at https://bugs.launchpad.net/cloud-init/+filebug #
|
|
|
bfa931 |
+ # Make sure to include the cloud provider your instance is #
|
|
|
bfa931 |
+ # running on. #
|
|
|
bfa931 |
+ # #
|
|
|
bfa931 |
+ # For more information see #
|
|
|
bfa931 |
+ # https://bugs.launchpad.net/cloud-init/+bug/1660385 #
|
|
|
bfa931 |
+ # #
|
|
|
bfa931 |
+ # After you have filed a bug, you can disable this warning by #
|
|
|
bfa931 |
+ # launching your instance with the cloud-config below, or #
|
|
|
bfa931 |
+ # putting that content into #
|
|
|
bfa931 |
+ # /etc/cloud/cloud.cfg.d/99-ec2-datasource.cfg #
|
|
|
bfa931 |
+ # #
|
|
|
bfa931 |
+ # #cloud-config #
|
|
|
bfa931 |
+ # datasource: #
|
|
|
bfa931 |
+ # Ec2: #
|
|
|
bfa931 |
+ # strict_id: false #
|
|
|
bfa931 |
+ # #
|
|
|
bfa931 |
+ """)
|
|
|
bfa931 |
+ closemsg = ""
|
|
|
bfa931 |
+ if sleep:
|
|
|
bfa931 |
+ closemsg = " [sleeping for %d seconds] " % sleep
|
|
|
bfa931 |
+ message += closemsg.center(64, "*")
|
|
|
bfa931 |
+ print(message)
|
|
|
bfa931 |
+ LOG.warn(message)
|
|
|
bfa931 |
+ if sleep:
|
|
|
bfa931 |
+ time.sleep(sleep)
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def identify_aws(data):
|
|
|
bfa931 |
+ # data is a dictionary returned by _collect_platform_data.
|
|
|
bfa931 |
+ if (data['uuid'].startswith('ec2') and
|
|
|
bfa931 |
+ (data['uuid_source'] == 'hypervisor' or
|
|
|
bfa931 |
+ data['uuid'] == data['serial'])):
|
|
|
bfa931 |
+ return Platforms.AWS
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ return None
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def identify_platform():
|
|
|
bfa931 |
+ # identify the platform and return an entry in Platforms.
|
|
|
bfa931 |
+ data = _collect_platform_data()
|
|
|
bfa931 |
+ checks = (identify_aws, lambda x: Platforms.UNKNOWN)
|
|
|
bfa931 |
+ for checker in checks:
|
|
|
bfa931 |
+ try:
|
|
|
bfa931 |
+ result = checker(data)
|
|
|
bfa931 |
+ if result:
|
|
|
bfa931 |
+ return result
|
|
|
bfa931 |
+ except Exception as e:
|
|
|
bfa931 |
+ LOG.warn("calling %s with %s raised exception: %s",
|
|
|
bfa931 |
+ checker, data, e)
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+def _collect_platform_data():
|
|
|
bfa931 |
+ # returns a dictionary with all lower case values:
|
|
|
bfa931 |
+ # uuid: system-uuid from dmi or /sys/hypervisor
|
|
|
bfa931 |
+ # uuid_source: 'hypervisor' (/sys/hypervisor/uuid) or 'dmi'
|
|
|
bfa931 |
+ # serial: dmi 'system-serial-number' (/sys/.../product_serial)
|
|
|
bfa931 |
+ data = {}
|
|
|
bfa931 |
+ try:
|
|
|
bfa931 |
+ uuid = util.load_file("/sys/hypervisor/uuid").strip()
|
|
|
bfa931 |
+ data['uuid_source'] = 'hypervisor'
|
|
|
bfa931 |
+ except Exception:
|
|
|
bfa931 |
+ uuid = util.read_dmi_data('system-uuid')
|
|
|
bfa931 |
+ data['uuid_source'] = 'dmi'
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ if uuid is None:
|
|
|
bfa931 |
+ uuid = ''
|
|
|
bfa931 |
+ data['uuid'] = uuid.lower()
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ serial = util.read_dmi_data('system-serial-number')
|
|
|
bfa931 |
+ if serial is None:
|
|
|
bfa931 |
+ serial = ''
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ data['serial'] = serial.lower()
|
|
|
bfa931 |
+
|
|
|
bfa931 |
+ return data
|
|
|
bfa931 |
+
|
|
|
bfa931 |
|
|
|
bfa931 |
# Used to match classes to dependencies
|
|
|
bfa931 |
datasources = [
|
|
|
bfa931 |
--
|
|
|
bfa931 |
2.13.5
|
|
|
bfa931 |
|