diff --git a/os_tests/libs/utils_lib.py b/os_tests/libs/utils_lib.py index 08f6111c..f100fe23 100644 --- a/os_tests/libs/utils_lib.py +++ b/os_tests/libs/utils_lib.py @@ -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 @@ -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])) diff --git a/os_tests/tests/test_image_mode.py b/os_tests/tests/test_image_mode.py index 1ca21737..e0d2da33 100644 --- a/os_tests/tests/test_image_mode.py +++ b/os_tests/tests/test_image_mode.py @@ -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: @@ -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') @@ -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) @@ -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, @@ -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 = "{}" @@ -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