[Merge] ~mitchdz/ubuntu/+source/ec2-hibinit-agent:add-IMDSv2-mantic into ubuntu/+source/ec2-hibinit-agent:ubuntu/devel

Mitchell Dzurick mp+443022 at code.launchpad.net
Wed May 17 23:12:15 UTC 2023



Diff comments:

> diff --git a/debian/patches/lp1941785-Add-support-for-IMDSv2.patch b/debian/patches/lp1941785-Add-support-for-IMDSv2.patch
> new file mode 100644
> index 0000000..e64c555
> --- /dev/null
> +++ b/debian/patches/lp1941785-Add-support-for-IMDSv2.patch
> @@ -0,0 +1,161 @@
> +Description: Add support for IMDSv2
> +Author: fred-lefebvre
> +Origin: backport, https://github.com/aws/amazon-ec2-hibinit-agent/commit/9d9bca5c61fa9256289e68c88bd3747af2f62e28
> +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ec2-hibinit-agent/+bug/1941785
> +Last-Update: 2023-05-16
> +---
> +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
> +--- a/agent/hibinit-agent
> ++++ b/agent/hibinit-agent
> +@@ -18,6 +18,7 @@
> + import sys
> + import syslog
> + import math
> ++import requests
> + from subprocess import check_call, check_output, STDOUT
> + from threading import Thread
> + from math import ceil
> +@@ -25,11 +26,6 @@
> + 
> + 
> + try:
> +-    from urllib.request import urlopen, Request
> +-except ImportError:
> +-    from urllib2 import urlopen, Request, HTTPError
> +-
> +-try:
> +     from ConfigParser import ConfigParser, NoSectionError, NoOptionError
> + except:
> +     from configparser import ConfigParser, NoSectionError, NoOptionError
> +@@ -41,7 +37,12 @@
> + log_to_syslog = True
> + log_to_stderr = True
> + SWAP_FILE = '/swap-hibinit'
> +-URL = "http://169.254.169.254/latest/meta-data/hibernation/configured"
> ++
> ++DEFAULT_STATE_DIR = '/var/lib/hibinit-agent'
> ++HIB_ENABLED_FILE = "hibernation-enabled"
> ++IMDS_BASEURL = 'http://169.254.169.254'
> ++IMDS_API_TOKEN_PATH = 'latest/api/token'
> ++IMDS_SPOT_ACTION_PATH = 'latest/meta-data/hibernation/configured'
> + 
> + def log(message):
> +     if log_to_syslog:
> +@@ -314,6 +315,9 @@
> +             get_int('swap', 'percentage-of-ram'), args.swap_ram_percentage, 100)
> +         self.swap_mb = self.merge(
> +             get_int('swap', 'target-size-mb'), args.swap_target_size_mb, 4000)
> ++        self.state_dir = get('core', 'state-dir')
> ++        if self.state_dir is None:
> ++            self.state_dir = DEFAULT_STATE_DIR
> + 
> + 
> +     def merge(self, cf_value, arg_value, def_val):
> +@@ -337,31 +341,55 @@
> +     def __str__(self):
> +         return str(self.__dict__)
> + 
> +-def hibernationEnabled():
> +-     """Returns a boolean indicating whether hibernation is enabled or not."""
> +-     response = None
> +-     try:
> +-         response = urlopen(URL)
> +-         data = response.read()
> +-         if data.lower() in ('false', b'false'):
> +-             return False
> +-     except:
> +-         return False
> +-     finally:
> +-         if response:
> +-             response.close()
> +-     return True
> ++def get_imds_token(seconds=21600):
> ++    """ Get a token to access instance metadata. """
> ++    log("Requesting new IMDSv2 token.")
> ++    request_header = {'X-aws-ec2-metadata-token-ttl-seconds': str(seconds)}

Good catch! This is the only addition to the upstream patch that I needed to make. It is worth noting that one of our personal out-of-tree patches change the default interpreter to python3. See d/p/py3-default. I suppose this conversion works in Python2.7 but I receive an error in Python3.8 which requires this conversion.

requests.exceptions.InvalidHeader: Value for header {X-aws-ec2-metadata-token-ttl-seconds: 21600} must be of type str or bytes, not <class 'int'>

> ++    token_url = '{}/{}'.format(IMDS_BASEURL, IMDS_API_TOKEN_PATH)
> ++    response = requests.put(token_url, headers=request_header)
> ++    response.close()
> ++    if response.status_code != 200:
> ++        return None
> ++
> ++    return response.text
> ++
> ++def create_state_dir(state_dir):
> ++    """ Create agent run dir if it doesn't exists."""
> ++    if not os.path.isdir(state_dir):
> ++        os.makedirs(state_dir)
> ++
> ++def hibernation_enabled(state_dir):
> ++    """Returns a boolean indicating whether hibernation is enabled or not.
> ++    Hibernation can't be enabled/disabled the instance launch. If we find
> ++    hibernation to be enabled, we create a semephore file so that we don't
> ++    have to probe IMDS again. That is useful when a instance is rebooted
> ++    after/if the IMDS http endpoint has been disabled.
> ++    """
> ++    hib_sem_file = os.path.join(state_dir, HIB_ENABLED_FILE)
> ++    if os.path.isfile(hib_sem_file):
> ++        log("Found {!r}, configuring hibernation".format(hib_sem_file))
> ++        return True
> ++
> ++    imds_token = get_imds_token()
> ++    if imds_token is None:
> ++        # IMDS http endpoint is disabled
> ++        return False
> ++
> ++    request_header = {'X-aws-ec2-metadata-token': imds_token}
> ++    response = requests.get("{}/{}".format(IMDS_BASEURL, IMDS_SPOT_ACTION_PATH),
> ++                 headers=request_header)
> ++    response.close()
> ++    if response.status_code != 200 or response.text.lower() == "false":
> ++        return False
> ++
> ++    log("Hibernation Configured Flag found")
> ++    os.mknod(hib_sem_file)
> ++
> ++    return True
> ++
> + 
> + def main():
> +     
> +-    if not hibernationEnabled():
> +-        log("Instance Launch has not enabled Hibernation Configured Flag. hibinit-agent exiting!!")
> +-        exit(0)
> +-    # Validate if disk space>total RAM 
> +-    ram_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
> +-    if get_rootfs_size()<=(math.ceil(float(ram_bytes)/(1024*1024*1024))):
> +-        log("Insufficient disk space. Cannot create setup for hibernation. Please allocate a larger root device")
> +-        exit(1)
> +     # Parse arguments
> +     parser = argparse.ArgumentParser(description="An EC2 background process that creates a setup for instance hibernation "
> +                                                  "at instance launch and also registers ACPI sleep event/actions")
> +@@ -388,6 +416,17 @@
> +     log_to_syslog = config.log_to_syslog
> + 
> +     log("Effective config: %s" % config)
> ++    create_state_dir(config.state_dir)
> ++
> ++    # Let's first check if we even need to run
> ++    if not hibernation_enabled(config.state_dir):
> ++        log("Instance Launch has not enabled Hibernation Configured Flag. hibinit-agent exiting!!")
> ++        exit(0)
> ++    # Validate if disk space>total RAM
> ++    ram_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
> ++    if get_rootfs_size()<=(math.ceil(float(ram_bytes)/(1024*1024*1024))):
> ++	    log("Insufficient disk space. Cannot create setup for hibernation. Please allocate a larger root device")
> ++	    exit(1)
> + 
> +     target_swap_size = config.swap_mb * 1024 * 1024
> +     swap_percentage_size = ram_bytes * config.swap_percentage // 100
> +--- a/etc/hibinit-config.cfg
> ++++ b/etc/hibinit-config.cfg
> +@@ -11,6 +11,9 @@
> + # filesystems.
> + touch-swap = False
> + 
> ++# Location where to create any state files
> ++state-dir = "/var/lib/hibinit-agent"
> ++
> + [swap]
> + # If there's no swap then we create it to be equal to the specified
> + # percentage of RAM or to the target size, whichever is greater


-- 
https://code.launchpad.net/~mitchdz/ubuntu/+source/ec2-hibinit-agent/+git/ec2-hibinit-agent/+merge/443022
Your team Ubuntu Sponsors Team is requested to review the proposed merge of ~mitchdz/ubuntu/+source/ec2-hibinit-agent:add-IMDSv2-mantic into ubuntu/+source/ec2-hibinit-agent:ubuntu/devel.




More information about the Ubuntu-sponsors mailing list