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 other disk formats support for building bootable bootc image. #458

Merged
merged 2 commits into from
Oct 16, 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
6 changes: 4 additions & 2 deletions os_tests/libs/utils_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,15 @@ def init_args():
parser.add_argument('--quay_io_data', dest='quay_io_data', default=None, action='store',
help='specify the login data for quay.io, e.g., username,password,quay.io', required=False)
parser.add_argument('--bootc_io_data', dest='bootc_io_data', default=None, action='store',
help='specify the login data for bootc repo, e.g., e.g., username,password,bootc io name', required=False)
help='specify the login data for bootc repo, e.g., username,password,bootc io name', required=False)
parser.add_argument('--bootc_base_image_digest', dest='bootc_base_image_digest', default=None, action='store',
help='specify the previous bootc_base_image_digest', required=False)
parser.add_argument('--config_toml_file', dest='config_toml_file', default=None, action='store',
help='specify the config_toml for login info of the custom container disk image', required=False)
parser.add_argument('--config_toml_info', dest='config_toml_info', default=None, action='store',
help='specify login info of the custom container disk image', required=False)
parser.add_argument('--aws_info', dest='aws_info', default=None, action='store',
help='specify the aws configure information, e.g., AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,aws-region,aws-bucket', required=False)
args = parser.parse_args()
return args

Expand Down Expand Up @@ -397,7 +399,7 @@ def init_case(test_instance):
test_instance.log.info("Case Doc: {}".format(eval(test_instance.id()).__doc__))
test_instance.log.info("Case Params:")
for key in test_instance.params.keys():
if key in ['password', 'subscription_username', 'subscription_password', 'quay_io_data', 'bootc_io_data', 'config_toml_info'] or 'password' in key:
if key in ['password', 'subscription_username', 'subscription_password', 'quay_io_data', 'bootc_io_data', 'config_toml_info', 'aws_info'] or 'password' in key:
test_instance.log.info("key:{}, val:*******".format(key))
else:
test_instance.log.info("key:{}, val:{}".format(key, test_instance.params[key]))
Expand Down
211 changes: 138 additions & 73 deletions os_tests/tests/test_image_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def _prepare_containerfile(self,containerfile,bootc_base_image_url,pkgs):
From $bootc_base_image_url
ADD ./rhel.repo /etc/yum.repos.d/rhel.repo
RUN echo $pkgs
RUN dnf install -y $pkgs && dnf clean all && rm -f /etc/yum.repos.d/rhel.repo
RUN dnf install -y $pkgs && dnf clean all
''')
fh, tmp_containerfile_file = tempfile.mkstemp(suffix='_containerfile', dir='/tmp', text=False)
with open(tmp_containerfile_file, 'a') as fh:
Expand Down Expand Up @@ -107,31 +107,30 @@ def test_build_rhel_bootc_image(self):
if self.params.get('subscription_username') and self.params.get('subscription_password'):
utils_lib.rhsm_register(self, cancel_case=True)
utils_lib.is_pkg_installed(self, pkg_name='container-tools', is_install=True, cancel_case=True)

#prepare containerfile
disk_image_format = self.params.get('disk_image_format')
containerfile = self.params.get('containerfile')
pkgs = self.params.get('pkgs')
pkgs = pkgs.replace(",", " ")
if pkgs:
pkgs = pkgs.replace(",", " ")
bootc_base_image_url = self.params.get('bootc_base_image_url')

#prepare containerfile
arch = utils_lib.run_cmd(self, 'uname -m', expect_ret=0, msg="Check the architechure")
if not containerfile:
if not bootc_base_image_url:
self.skipTest("Please sepcify the base rhel bootc container image url.")
if disk_image_format == 'ami':
default_pkgs = "cloud-init"
default_pkgs = "cloud-init"
if disk_image_format == 'iso':
default_pkgs = "cloud-init,hyperv-daemons"
#default_bootc_image_configure = ""
if disk_image_format == 'qcow2':
default_pkgs = "cloud-init"
if disk_image_format == 'vmdk':
default_pkgs = "cloud-init,open-vm-tools"
if disk_image_format == 'vhdx':
default_pkgs = "hyperv-daemons"
if disk_image_format == 'vhd':
default_pkgs = "cloud-init,hyperv-daemons"
pkgs = default_pkgs.replace(',',' ') + " " + pkgs
if pkgs:
pkgs = default_pkgs.replace(',',' ') + " " + pkgs
else:
pkgs = default_pkgs.replace(',',' ')
self.log.info("print %s" % pkgs)
self._prepare_containerfile(containerfile, bootc_base_image_url, pkgs)
dnf_repo_url = self.params.get('dnf_repo_url')
Expand All @@ -155,8 +154,8 @@ def test_build_rhel_bootc_image(self):
bootc_base_image = utils_lib.run_cmd(self, cmd, expect_ret=0, msg='Fetch bootc base image repo')
cmd = "sudo podman rmi {} -f".format(bootc_base_image)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="remove old bootc base image")
cmd = "sudo podman pull {}".format(bootc_base_image)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="pull bootc base image")
cmd = "sudo podman pull {} --arch {}".format(bootc_base_image, arch)
utils_lib.run_cmd(self, cmd, expect_ret=0, timeout = 1200, msg="pull bootc base image")
cmd = "sudo podman images"
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="Check all container images")
cmd = "sudo podman inspect {} --format '{{{{.ID}}}}' | tr -d '\n'".format(bootc_base_image)
Expand All @@ -171,6 +170,8 @@ def test_build_rhel_bootc_image(self):
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="check bootc base image info")
cmd = "sudo podman inspect {} --format '{{{{.Architecture}}}}' | tr -d '\n'".format(bootc_base_image)
bootc_image_arch = utils_lib.run_cmd(self, cmd, expect_ret=0, msg="check bootc base image Architecture")
if bootc_image_arch == 'amd64':
bootc_image_arch = 'x86_64'
cmd = "sudo jq -r .[].Config.Labels.\\\"redhat.compose-id\\\" {} | tr -d '\n'".format(inspect_json_name)
bootc_base_image_compose_id = utils_lib.run_cmd(self, cmd, expect_ret=0, msg="check bootc base image compose-id")
bootc_custom_image_name = '{}_{}_{}_{}'.format(bootc_base_image_name,
Expand All @@ -181,30 +182,76 @@ def test_build_rhel_bootc_image(self):
if bootc_base_image_digest == self.params.get('bootc_base_image_digest'):
self.skipTest("Custom bootc image based bootc image {} Digest:{} was already built. Skip this case."
.format(bootc_base_image_name, bootc_base_image_digest))
bootc_custom_image_tag = bootc_base_image_digest
bootc_custom_image = "quay.io/{}/{}:{}".format(quay_io_data.split(',')[0], bootc_custom_image_name, bootc_custom_image_tag)
cmd = "sudo podman build -t {} .".format(bootc_custom_image)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="Build bootc custom image")
if quay_io_data:
bootc_custom_image = "quay.io/{}/{}:{}".format(quay_io_data.split(',')[0], bootc_custom_image_name, bootc_custom_image_tag)
else:
bootc_custom_image = "localhost/{}:{}".format(bootc_custom_image_name, bootc_custom_image_tag)
cmd = "sudo podman build -t {} . --arch {}".format(bootc_custom_image, arch)
utils_lib.run_cmd(self, cmd, expect_ret=0, timeout = 1200, msg="Build bootc custom image")

#Create directory for converted disk images
output_dir = 'output_{}_{}'.format(bootc_custom_image_name, bootc_custom_image_tag)
cmd = "sudo rm {} -rf && sudo mkdir {}".format(output_dir, output_dir)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="Create output directory")
#Create bootable disks with custom bootc images
bootc_image_builder = self.params.get('bootc_image_builder') or bootc_base_image.replace('rhel-bootc','bootc-image-builder')

#Build custom bootc images
bootc_image_builder = bootc_base_image.replace('rhel-bootc','bootc-image-builder')
config_toml_file = self.params.get('config_toml_file')
config_toml_info = self.params.get('config_toml_info')
if config_toml_file:
tmp_config_toml = '/tmp/config_toml'
self.SSH.put_file(local_file=config_toml_file, rmt_file=tmp_config_toml)
cmd = "sudo cp {} ./config.toml".format(tmp_config_toml)
utils_lib.run_cmd(self, cmd, msg='copy {}'.format(config_toml_file))
if os.path.exists(tmp_config_toml):
os.unlink(tmp_config_toml)
self.log.info("delete temp config.toml file")
elif config_toml_info:
utils_lib.run_cmd(self, """
if disk_image_format == 'ami':
utils_lib.is_pkg_installed(self, pkg_name='awscli2', is_install=True, cancel_case=True)
ami_name = '{}_{}_{}'.format(bootc_custom_image_name, bootc_custom_image_tag, bootc_base_image_compose_id)
aws_info = self.params.get('aws_info')
if aws_info and aws_info.split(',')[3]:
aws_bucket = aws_info.split(',')[3]
else:
aws_bucket = 'rh-image-files'
if aws_info and aws_info.split(',')[0] and aws_info.split(',')[1]:
cmd = "sudo podman run --rm -it --privileged --pull=newer --tls-verify=false \
--security-opt label=type:unconfined_t -v /var/lib/containers/storage:/var/lib/containers/storage \
--env AWS_ACCESS_KEY_ID={} --env AWS_SECRET_ACCESS_KEY={} {} --type ami --target-arch {} --local --aws-ami-name {} \
--aws-region {} --aws-bucket {} {}".format(
aws_info.split(',')[0],
aws_info.split(',')[1],
bootc_image_builder,
bootc_image_arch,
ami_name,
aws-bucket,
aws_info.split(',')[2],
bootc_custom_image)
utils_lib.run_cmd(self, cmd, timeout=3600, is_log_cmd=False, msg='Create ami for image mode testing based on {}'.format(bootc_base_image_compose_id))

else:
cmd = "sudo grep region .aws/config | awk '{print $(3)}'| tr -d '\n'"
aws_region = utils_lib.run_cmd(self, cmd, msg='Check aws region')
if not aws_region:
self.FailTest('Please configure awscli')
else:
cmd = "sudo podman run --rm -it --privileged --pull=newer -v /root/.aws:/root/.aws:ro \
--env AWS_PROFILE=default -v /var/lib/containers/storage:/var/lib/containers/storage {} --local --type ami \
--target-arch {} --aws-ami-name {} --aws-region {} --aws-bucket {} {}".format(
bootc_image_builder,
bootc_image_arch,
ami_name,
aws_region,
aws_bucket,
bootc_custom_image)
utils_lib.run_cmd(self, cmd, timeout=3600, msg='Create ami for image mode testing based on {}'.format(bootc_base_image_compose_id))
cmd = "aws ec2 describe-images --filters 'Name=name,Values={}' --query 'Images[*].ImageId' --output text | tr -d '\n'".format(ami_name)
ami_id = utils_lib.run_cmd(self, cmd, msg='check ami id')
if ami_id:
self.log.info("AMI name:{} ID:{} based on bootc image {} compose-id:{} Digest:{} is uploaded \
to AWS {}".format(ami_name, ami_id, bootc_base_image, bootc_base_image_compose_id, bootc_base_image_digest, aws_region))
else:
self.FailTest('Failed to upload AMI')
else:
config_toml_file = self.params.get('config_toml_file')
config_toml_info = self.params.get('config_toml_info')
if config_toml_file:
tmp_config_toml = '/tmp/config_toml'
self.SSH.put_file(local_file=config_toml_file, rmt_file=tmp_config_toml)
cmd = "sudo cp {} ./config.toml".format(tmp_config_toml)
utils_lib.run_cmd(self, cmd, msg='copy {}'.format(config_toml_file))
if os.path.exists(tmp_config_toml):
os.unlink(tmp_config_toml)
self.log.info("delete temp config.toml file")
elif config_toml_info:
#Note the key will display in the disk convert log if you specify it.
utils_lib.run_cmd(self, """
sudo cat << EOF | sudo tee ./config.toml
[[customizations.user]]
name = "{}"
Expand All @@ -213,47 +260,65 @@ def test_build_rhel_bootc_image(self):
groups = ["wheel"]
EOF
""".format(config_toml_info.split(',')[0], config_toml_info.split(',')[1], config_toml_info.split(',')[2]),
is_log_cmd=False,
msg='create config_toml file')

#Convert custom bootc container image to disk image
disk_image_type = disk_image_format
if disk_image_format in ['vhdx', 'vhd']:
disk_image_type = 'qcow2'
cmd = "sudo podman run --rm -it --privileged --pull=newer --security-opt \
label=type:unconfined_t -v ./config.toml:/config.toml -v ./{}:/output -v \
/var/lib/containers/storage:/var/lib/containers/storage {} --type {} \
--config /config.toml --local {}".format(output_dir, bootc_image_builder, disk_image_type, bootc_custom_image)
utils_lib.run_cmd(self,
cmd,
expect_ret=0,
timeout = 1200,
msg="Create container disk image {} for image mode testing based on {}".format(bootc_custom_image, bootc_base_image_compose_id))

manifest_file = 'manifest{}'.format(output_dir.replace('output',''))
cmd = "sudo mv {}/manifest-{}.json {}".format(output_dir, disk_image_type, manifest_file)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='move manifest-{}.json to {}'.format(disk_image_type, manifest_file))
disk_file = 'disk{}'.format(output_dir.replace('output',''), disk_image_type)
cmd = "sudo mv {}/{}/disk.{} {}".format(output_dir, disk_image_type, disk_image_type, disk_file)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='copy disk.{} to {}'.format(disk_image_type, disk_file))

#uploade the output to attachment
workdir = utils_lib.run_cmd(self, "sudo pwd | tr -d '\n'", expect_ret=0)
utils_lib.save_file(self, file_dir=workdir, file_name=manifest_file)
utils_lib.save_file(self, file_dir=workdir, file_name=disk_file)
is_log_cmd=False,
msg='create config_toml file')

#Create directory for converted disk images
output_dir = 'output_{}_{}'.format(bootc_custom_image_name, bootc_custom_image_tag)
cmd = "sudo rm {} -rf && sudo mkdir {}".format(output_dir, output_dir)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg="Create output directory")

self.log.info("Disk image {} based on bootc image {} \
compose-id:{} Digest:{} is saved to attachments.".format(disk_file,
bootc_base_image,
bootc_base_image_compose_id,
bootc_base_image_digest))
for image in ['bootc_base_image', 'bootc_custom_image']:
cmd = "sudo podman rmi {} -f".format(image)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='remove container image')
#Convert custom bootc container image to disk image
disk_image_type = disk_image_format
if disk_image_format in ['vhdx', 'vhd']:
disk_image_type = 'qcow2'
cmd = "sudo podman run --rm -it --privileged --pull=newer --security-opt \
label=type:unconfined_t -v ./config.toml:/config.toml -v ./{}:/output -v \
/var/lib/containers/storage:/var/lib/containers/storage {} --type {} --target-arch {} \
--config /config.toml --local {}".format(output_dir, bootc_image_builder, disk_image_type, bootc_image_arch, bootc_custom_image)
utils_lib.run_cmd(self,
cmd,
expect_ret=0,
timeout = 3600,
msg="Create container disk image {} for image mode testing based on {}".format(bootc_custom_image, bootc_base_image_compose_id))

cmd = "sudo podman rmi {} -f".format(bootc_custom_image)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='remove bootc_custom_image')
manifest_file = 'manifest{}'.format(output_dir.replace('output',''))
cmd = "sudo mv {}/manifest-{}.json {}".format(output_dir, disk_image_type, manifest_file)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='move manifest-{}.json to {}'.format(disk_image_type, manifest_file))
utils_lib.is_cmd_exist(self,"qemu-img")
if disk_image_format == 'vhdx':
cmd = "sudo qemu-img convert -O vhdx {}/qcow2/disk.qcow2 {}/qcow2/disk.vhdx".format(output_dir, output_dir)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='convert qcow2 disk to vhdx disk')
if disk_image_format == 'vhd':
cmd = "sudo qemu-img convert -f qcow2 -o subformat=fixed,force_size -O vpc {}/qcow2/disk.qcow2 {}/qcow2/disk.vhd".format(output_dir, output_dir)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='convert qcow2 disk to vhd disk')
disk_dir = disk_image_type
disk_file = 'disk.{}'.format(disk_image_format)
if disk_image_type == 'iso':
disk_file = 'install.iso'
disk_dir = 'bootiso'
cmd = "sudo mv {}/{}/{} {}.{}".format(output_dir, disk_dir, disk_file, output_dir.replace('output_',''), disk_file.split('.')[1])
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='move {} to workdir'.format(disk_file))
#uploade the output to attachment
workdir = utils_lib.run_cmd(self, "sudo pwd | tr -d '\n'", expect_ret=0)
utils_lib.save_file(self, file_dir=workdir, file_name=inspect_json_name)
utils_lib.save_file(self, file_dir=workdir, file_name=manifest_file)
#Copy the disk file to your test environment by manual,
#Or comment out below line to save it to attachments in log.
utils_lib.save_file(self, file_dir=workdir, file_name='{}.{}'.format(output_dir.replace('output_',''), disk_image_format))

self.log.info("Please copy Disk image ./{}.{} based on bootc image {} \
compose-id:{} Digest:{} to your test environment.".format(
output_dir.replace('output_',''),
disk_image_format,
bootc_base_image,
bootc_base_image_compose_id,
bootc_base_image_digest))
#delete container images
for image in [bootc_base_image, bootc_custom_image, bootc_image_builder]:
cmd = "sudo podman rmi {} -f".format(image)
utils_lib.run_cmd(self, cmd, expect_ret=0, msg='remove container image {}'.format(image))

def tearDown(self):
utils_lib.finish_case(self)
pass
Expand Down
Loading