diff --git a/aegea/launch.py b/aegea/launch.py index 7e3f3cea..917f9b17 100644 --- a/aegea/launch.py +++ b/aegea/launch.py @@ -135,7 +135,7 @@ def launch(args): KeyName=ssh_key_name, SecurityGroupIds=[sg.id for sg in security_groups], InstanceType=args.instance_type, - BlockDeviceMappings=get_bdm(ebs_storage=args.storage), + BlockDeviceMappings=get_bdm(ami=args.ami, ebs_storage=args.storage), UserData=get_user_data(**user_data_args)) tag_spec = dict(ResourceType="instance", Tags=encode_tags(instance_tags)) logger.info("Launch spec user data is %i bytes long", len(launch_spec["UserData"])) @@ -220,6 +220,11 @@ def instance_types(self, **kwargs): parser = register_parser(launch) parser.add_argument("hostname") +parser.add_argument("--storage", nargs="+", metavar="MOUNTPOINT=SIZE_GB", + type=lambda x: x.rstrip("GBgb").split("=", 1), + help="At launch time, attach EBS volume(s) of this size, format and mount them.") +parser.add_argument("--efs-home", action="store_true", + help="Create and manage an EFS filesystem that the instance will use for user home directories") parser.add_argument("--commands", nargs="+", metavar="COMMAND", help="Commands to run on host upon startup") parser.add_argument("--packages", nargs="+", metavar="PACKAGE", help="APT packages to install on host upon startup") parser.add_argument("--ssh-key-name") @@ -248,11 +253,6 @@ def instance_types(self, **kwargs): help="Tags to apply to launched instances.") parser.add_argument("--wait-for-ssh", action="store_true", help="Wait for launched instance to begin accepting SSH connections. Security groups and NACLs must permit SSH from launching host.") # noqa -parser.add_argument("--efs-home", action="store_true", - help="Create and manage an EFS filesystem that the instance will use for user home directories") -parser.add_argument("--storage", nargs="+", metavar="MOUNTPOINT=SIZE_GB", - type=lambda x: x.rstrip("GBgb").split("=", 1), - help="At launch time, attach EBS volume(s) of this size, format and mount them.") parser.add_argument("--iam-role", default=__name__, help="Pass this IAM role to the launched instance through an instance profile. Role credentials will become available in the instance metadata.") # noqa parser.add_argument("--iam-policies", nargs="+", metavar="IAM_POLICY_NAME", diff --git a/aegea/rootfs.skel/etc/cloud/cloud.cfg.d/99_aegea.cfg b/aegea/rootfs.skel/etc/cloud/cloud.cfg.d/99_aegea.cfg index e20de43f..06c9868e 100644 --- a/aegea/rootfs.skel/etc/cloud/cloud.cfg.d/99_aegea.cfg +++ b/aegea/rootfs.skel/etc/cloud/cloud.cfg.d/99_aegea.cfg @@ -3,6 +3,8 @@ datasource_list: [Ec2] cloud_init_modules: - bootcmd - write-files + - growpart + - resizefs - disk_setup - mounts - set_hostname diff --git a/aegea/util/aws/__init__.py b/aegea/util/aws/__init__.py index 75dae046..da94631b 100644 --- a/aegea/util/aws/__init__.py +++ b/aegea/util/aws/__init__.py @@ -268,13 +268,21 @@ def resolve_instance_id(name): except IndexError: raise AegeaException('Could not resolve "{}" to a known instance'.format(name)) -def get_bdm(max_devices=12, ebs_storage=frozenset()): +def get_bdm(ami=None, max_devices=12, ebs_storage=frozenset()): # Note: d2.8xl and hs1.8xl have 24 devices bdm = [dict(VirtualName="ephemeral" + str(i), DeviceName="xvd" + chr(ord("b") + i)) for i in range(max_devices)] ebs_bdm = [] # type: List[Dict] for i, (mountpoint, size_gb) in enumerate(ebs_storage): - ebs_spec = dict(Encrypted=True, DeleteOnTermination=True, VolumeType="st1", VolumeSize=int(size_gb)) - ebs_bdm.insert(0, dict(DeviceName="xvd" + chr(ord("z") - i), Ebs=ebs_spec)) + if mountpoint == "/": + rootfs_bdm = resources.ec2.Image(ami).block_device_mappings[0] + if "Ebs" not in rootfs_bdm or "SnapshotId" not in rootfs_bdm.get("Ebs", []): + raise AegeaException("Unable to locate block device mapping for root volume of {}".format(ami)) + rootfs_bdm["Ebs"]["VolumeSize"] = int(size_gb) + bdm.insert(0, rootfs_bdm) + else: + volume_type = "st1" if int(size_gb) > 125 else "gp3" + ebs_spec = dict(Encrypted=True, DeleteOnTermination=True, VolumeType=volume_type, VolumeSize=int(size_gb)) + ebs_bdm.insert(0, dict(DeviceName="xvd" + chr(ord("z") - i), Ebs=ebs_spec)) bdm.extend(ebs_bdm) return bdm