Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bootc image builder case #5540

Merged
merged 1 commit into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions provider/bootc_image_builder/aws_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright Red Hat
#
# SPDX-License-Identifier: GPL-2.0
#
# Author: [email protected]
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"""Helper functions for aws management"""

import logging
import os
import shutil
import textwrap
import pathlib

from avocado.utils import process
from avocado.core import exceptions

LOG = logging.getLogger('avocado.' + __name__)


def install_aws_cli_tool(params):
"""
Download AWS command line tool and install it

:param params: wrap up all parameters
"""
vm_arch_name = params.get("vm_arch_name", "x86_64")
aws_install_cmd = f"curl https://awscli.amazonaws.com/awscli-exe-linux-{vm_arch_name}.zip -o awscliv2.zip " \
f" && unzip awscliv2.zip -d ./ && ./aws/install "
if not os.path.exists("/usr/local/bin/aws"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank for bringing up this idea.Current solution is AWS official site to introduce how we install tools on linux, see https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

if os.path.exists("/usr/local/aws-cli"):
shutil.rmtree("/usr/local/aws-cli")
if os.path.exists("/usr/local/bin/aws_completer"):
shutil.rmtree("/usr/local/bin/aws_completer")
if os.path.exists("aws"):
shutil.rmtree("aws")
if os.path.exists("awscliv2.zip"):
os.remove("awscliv2.zip")
process.run(aws_install_cmd, shell=True, ignore_status=False)


def create_aws_credentials_file(aws_access_key_id, aws_access_key):
"""
Create AWS credentials file

:param aws_access_key_id: AWS access key id
:param aws_access_key: AWS access key
"""
folder = os.path.expanduser("~/.aws")
if not os.path.exists(folder):
os.mkdir(folder)
secret_path = pathlib.Path(folder) / "credentials"
secret_path.write_text(textwrap.dedent(f"""
[default]
AWS_ACCESS_KEY_ID={aws_access_key_id}
AWS_SECRET_ACCESS_KEY={aws_access_key}
"""), encoding="utf8")

return os.path.join(folder, "credentials")


def create_aws_config_file(aws_region):
"""
Create AWS configuration file

:param aws_region: AWS region
"""
folder = os.path.expanduser("~/.aws")
if not os.path.exists(folder):
os.mkdir(folder)
secret_path = pathlib.Path(folder) / "config"
secret_path.write_text(textwrap.dedent(f"""
[default]
region={aws_region}
"""), encoding="utf8")

return os.path.join(folder, "config")


def delete_aws_ami_id(params):
"""
delete AWS AMI id

@param params: one dictionary wrapping various parameter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and elsewhere please change to ":param params:"

"""
ami_id = params.get("aws_ami_id")
if ami_id:
delete_cmd = "aws ec2 deregister-image --image-id %s" % ami_id
process.run(delete_cmd, shell=True, verbose=True, ignore_status=True)


def delete_aws_ami_snapshot_id(params):
"""
delete AWS AMI snapshot id

@param params: one dictionary wrapping various parameter
"""
aws_ami_snapshot_id = params.get("aws_ami_snapshot_id")
if aws_ami_snapshot_id:
delete_cmd = "aws ec2 delete-snapshot --snapshot-id %s" % aws_ami_snapshot_id
process.run(delete_cmd, shell=True, verbose=True, ignore_status=True)


def delete_aws_key_pair(params):
"""
delete AWS key pair

@param params: one dictionary wrapping various parameter
"""
aws_key_name = params.get("aws_key_name")
delete_key_pair_cmd = f"aws ec2 delete-key-pair --key-name {aws_key_name}"
process.run(delete_key_pair_cmd, shell=True, ignore_status=True).exit_status


def import_aws_key_pair(params):
"""
Import key into AWS key pair

@param params: one dictionary wrapping various parameter
"""
aws_key_name = params.get("aws_key_name")
check_key_pair_cmd = f"aws ec2 describe-key-pairs --key-name {aws_key_name}"
status = process.run(check_key_pair_cmd, shell=True, ignore_status=True).exit_status
if status != 0:
public_key_path = os.path.join(os.path.expanduser("~/.ssh/"), "id_rsa.pub")
import_cmd = "aws ec2 import-key-pair --key-name {aws_key_name}--public-key-material fileb://{public_key_path}"
process.run(import_cmd, shell=True, verbose=True, ignore_status=True)


def create_aws_instance(params):
"""
create AWS instance

@param params: one dictionary wrapping various parameter
"""
import_aws_key_pair(params)
vm_name = params.get("vm_name_bootc")
aws_key_name = params.get("aws_key_name")
aws_ami_id = params.get("aws_ami_id")
aws_subnet_id = params.get("aws_subnet_id")
aws_security_group = params.get("aws_security_group")
aws_instance_type = params.get("aws_instance_type")
create_aws_instance_cmd = "aws ec2 run-instances --image-id %s --count 1" \
" --security-group-ids %s" \
" --instance-type %s --key-name %s --subnet-id %s" \
" --associate-public-ip-address --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=%s}]'" \
" --block-device-mappings '[{\"DeviceName\":\"/dev/xvda\",\"Ebs\":{\"VolumeSize\":20,\"VolumeType\":\"gp2\"}}]'" \
" --query 'Instances[0].InstanceId' --output text" % (aws_ami_id, aws_security_group, aws_instance_type, aws_key_name, aws_subnet_id, vm_name)
instance_id = process.run(create_aws_instance_cmd, shell=True, ignore_status=True).stdout_text.strip()
params.update({"aws_instance_id": "%s" % instance_id})
return instance_id


def wait_aws_instance_running(params):
"""
wait for AWS instance running

@param params: one dictionary wrapping various parameter
"""
aws_instance_id = params.get("aws_instance_id")
if aws_instance_id:
wait_aws_instance_cmd = f"timeout 30 aws ec2 wait instance-running --instance-ids {aws_instance_id}"
process.run(wait_aws_instance_cmd, shell=True, ignore_status=True)


def get_aws_instance_privateip(params):
"""
Get AWS instance private ip

@param params: one dictionary wrapping various parameter
"""
wait_aws_instance_running(params)
aws_instance_id = params.get("aws_instance_id")
if aws_instance_id:
get_aws_instance_privateip_cmd = f"aws ec2 describe-instances --instance-ids {aws_instance_id}" \
f" --query 'Reservations[*].Instances[*].PrivateIpAddress' --output text"
private_ip = process.run(get_aws_instance_privateip_cmd, shell=True, ignore_status=True).stdout_text.strip()
return private_ip
else:
raise exceptions.TestFail(f"AWS instance not existed yet")


def terminate_aws_instance(params):
"""
terminate AWS instance

@param params: one dictionary wrapping various parameter
"""
aws_instance_id = params.get("aws_instance_id")
if aws_instance_id:
terminate_aws_instance_cmd = f"aws ec2 terminate-instances --instance-ids {aws_instance_id}"
process.run(terminate_aws_instance_cmd, shell=True, ignore_status=True)
wait_instance_terminated = f"timeout 20 aws ec2 wait instance-terminated --instance-ids {aws_instance_id}"
process.run(wait_instance_terminated, shell=True, ignore_status=True)
Loading
Loading