diff --git a/cmd/coreos-assembler.go b/cmd/coreos-assembler.go index 88475c1187751c73e20e33b51b2878014eedf427..d7f14a79769ba8ed16d881ae5ae62e8571b68e0e 100644 --- a/cmd/coreos-assembler.go +++ b/cmd/coreos-assembler.go @@ -14,7 +14,8 @@ import ( // commands we'd expect to use in the local dev path var buildCommands = []string{"init", "fetch", "build", "run", "prune", "clean", "list"} var advancedBuildCommands = []string{"buildfetch", "buildupload", "oc-adm-release", "push-container", "upload-oscontainer", "buildextend-extensions"} -var buildextendCommands = []string{"aliyun", "aws", "azure", "digitalocean", "exoscale", "extensions-container", "gcp", "hashlist-experimental", "ibmcloud", "kubevirt", "legacy-oscontainer", "live", "metal", "metal4k", "nutanix", "openstack", "qemu", "secex", "virtualbox", "vmware", "vultr"} +var buildextendCommands = []string{"aliyun", "applehv", "aws", "azure", "digitalocean", "exoscale", "extensions", "extensions-container", "gcp", "hashlist-experimental", "hyperv", "ibmcloud", "kubevirt", "legacy-oscontainer", "live", "metal", "metal4k", "nutanix", "openstack", "qemu", "secex", "virtualbox", "vmware", "vultr"} + var utilityCommands = []string{"aws-replicate", "compress", "copy-container", "koji-upload", "kola", "push-container-manifest", "remote-build-container", "remote-prune", "remote-session", "sign", "tag", "update-variant"} var otherCommands = []string{"shell", "meta"} diff --git a/src/cmd-buildextend-applehv b/src/cmd-buildextend-applehv new file mode 120000 index 0000000000000000000000000000000000000000..c0388001b22f32e90f0895b14d87c0db11ce5c1b --- /dev/null +++ b/src/cmd-buildextend-applehv @@ -0,0 +1 @@ +cmd-artifact-disk \ No newline at end of file diff --git a/src/cmd-buildextend-hyperv b/src/cmd-buildextend-hyperv new file mode 120000 index 0000000000000000000000000000000000000000..c0388001b22f32e90f0895b14d87c0db11ce5c1b --- /dev/null +++ b/src/cmd-buildextend-hyperv @@ -0,0 +1 @@ +cmd-artifact-disk \ No newline at end of file diff --git a/src/cmd-buildextend-kubevirt b/src/cmd-buildextend-kubevirt new file mode 120000 index 0000000000000000000000000000000000000000..4f0d225c7850abd6438877ccb9a7c93e50983c61 --- /dev/null +++ b/src/cmd-buildextend-kubevirt @@ -0,0 +1 @@ +cmd-ore-wrapper \ No newline at end of file diff --git a/src/cmd-generate-release-meta b/src/cmd-generate-release-meta index 17a2c4350702661ca28cbb5f418f53268dc6955f..3a3a5ec06284bd081cd5f2d9a8a1a64b462d2f80 100755 --- a/src/cmd-generate-release-meta +++ b/src/cmd-generate-release-meta @@ -124,7 +124,7 @@ def append_build(out, input_): # build the architectures dict arch_dict = {"media": {}} ensure_dup(input_, arch_dict, "ostree-commit", "commit") - platforms = ["aliyun", "aws", "azure", "azurestack", "digitalocean", "exoscale", "gcp", "ibmcloud", "metal", "nutanix", "openstack", "powervs", "qemu", "vmware", "vultr"] + platforms = ["aliyun", "applehv", "aws", "azure", "azurestack", "digitalocean", "exoscale", "gcp", "hyperv", "ibmcloud", "metal", "nutanix", "openstack", "powervs", "qemu", "vmware", "vultr"] for platform in platforms: if input_.get("images", {}).get(platform, None) is not None: print(f" - {platform}") diff --git a/src/cmd-ore-wrapper b/src/cmd-ore-wrapper index 2ad6d68c22fbb3c3f5d5cb4b2e998fd48367afba..ba2ad840594a1a2dee1af14434dcf4cf0f8aaebc 100755 --- a/src/cmd-ore-wrapper +++ b/src/cmd-ore-wrapper @@ -16,6 +16,7 @@ from cosalib.cli import ( ) from cosalib.qemuvariants import get_qemu_variant from cosalib.ibmcloud import get_ibmcloud_variant +from cosalib.kubevirt import get_kubevirt_variant if __name__ == '__main__': log.basicConfig( @@ -102,6 +103,8 @@ Each target has its own sub options. To access them us: # Now _extend the parser with the cloud targets_ if target in ['ibmcloud', 'powervs']: build = get_ibmcloud_variant(target, args) + elif target == "kubevirt": + build = get_kubevirt_variant(target, args) else: build = get_qemu_variant(target, args) log.info(f"operating on {build.image_name}") diff --git a/src/cosalib/buildah.py b/src/cosalib/buildah.py new file mode 100644 index 0000000000000000000000000000000000000000..2746e581624479ed2b2a9db2866c894cccff2809 --- /dev/null +++ b/src/cosalib/buildah.py @@ -0,0 +1,16 @@ +import os + +# https://access.redhat.com/documentation/en-us/openshift_container_platform/4.1/html/builds/custom-builds-buildah +NESTED_BUILD_ARGS = ['--storage-driver', 'vfs'] + + +def buildah_base_args(containers_storage=None): + buildah_base_argv = ['buildah'] + if containers_storage is not None: + buildah_base_argv.append(f"--root={containers_storage}") + if os.environ.get('container') is not None: + print("Using nested container mode due to container environment variable") + buildah_base_argv.extend(NESTED_BUILD_ARGS) + else: + print("Skipping nested container mode") + return buildah_base_argv diff --git a/src/cosalib/cli.py b/src/cosalib/cli.py index 68ec5cb7dce81da1ceee5e3058d0577ee260ff1e..707d4056ae6b1f66036b64406483d29b096c0930 100644 --- a/src/cosalib/cli.py +++ b/src/cosalib/cli.py @@ -13,7 +13,8 @@ from cosalib import ( gcp, vultr, exoscale, - ibmcloud + ibmcloud, + kubevirt ) CLOUD_CLI_TARGET = { @@ -44,6 +45,9 @@ CLOUD_CLI_TARGET = { "powervs": (ibmcloud.ibmcloud_cli, ibmcloud.ibmcloud_run_ore, ibmcloud.ibmcloud_run_ore_replicate), + "kubevirt": (kubevirt.kubevirt_cli, + kubevirt.kubevirt_run_ore, + kubevirt.kubevirt_run_ore_replicate), } diff --git a/src/cosalib/kubevirt.py b/src/cosalib/kubevirt.py new file mode 100644 index 0000000000000000000000000000000000000000..b4499e6c988a539290d97ba4c2ed8ba6f80fa930 --- /dev/null +++ b/src/cosalib/kubevirt.py @@ -0,0 +1,77 @@ +import os +import logging as log + +from cosalib.cmdlib import runcmd +from cosalib.qemuvariants import QemuVariantImage + + +class KubeVirtImage(QemuVariantImage): + """ + KubeVirtImage uses QemuVariantImage to create a normal qcow2 image. + This image is then wrapped into an ociarchive as final build artifact which + can be pushed to container registries and used as ContainerDisk in kubevirt. + """ + + def __init__(self, **kwargs): + QemuVariantImage.__init__(self, **kwargs) + # Set the QemuVariant mutate_callback so that OVA is called. + self.mutate_callback = self.write_oci + self.mutate_callback_creates_final_image = True + + def write_oci(self, _): + """ + Take the qcow2 base image and convert it to an oci-archive. + """ + ctxdir = self._tmpdir + final_img = os.path.join(os.path.abspath(self.build_dir), self.image_name) + # Create the Containerfile to use for the build + with open(os.path.join(ctxdir, "Containerfile"), "w") as f: + f.write(f"FROM scratch\nADD {self.image_name_base}.{self.image_format} /disk/\n") + # Run the build inside a supermin VM because in OpenShift things are extremely + # locked down. Here we are doing two things that are interesting. We are using + # a virtio-serial device to write the output file to because we've seen 9p + # issues in our pipeline. We're also using an undocumented feature of podman-build, + # which is to write directly to an oci-archive via --tag=oci-archive:file.ociarchive + # https://github.com/containers/buildah/issues/4740. + runcmd(['/usr/lib/coreos-assembler/runvm.sh', + '-chardev', f'file,id=ociarchiveout,path={final_img}', + '-device', 'virtserialport,chardev=ociarchiveout,name=ociarchiveout', + '--', 'podman', 'build', '--disable-compression=false', + '--label', f'version={self.build_id}', + '--tag=oci-archive:/dev/virtio-ports/ociarchiveout', ctxdir]) + + +def kubevirt_run_ore(build, args): + """ + This function is not necessary for Kubevirt. We'll push the ociarchive + files using cosa push-container-manifest in the release job. + """ + raise Exception("not implemented") + + +def kubevirt_run_ore_replicate(*args, **kwargs): + """ + This function is not necessary for Kubevirt. We'll push the ociarchive + files using cosa push-container-manifest in the release job. + """ + raise Exception("not implemented") + + +def kubevirt_cli(parser): + return parser + + +def get_kubevirt_variant(variant, parser, kwargs={}): + """ + Helper function to get the KubeVirtCloudImage Build Obj + """ + log.debug(f"returning KubeVirtCloudImage for {variant}") + return KubeVirtImage( + buildroot=parser.buildroot, + build=parser.build, + schema=parser.schema, + variant=variant, + force=parser.force, + arch=parser.arch, + compress=parser.compress, + **kwargs) diff --git a/src/cosalib/qemuvariants.py b/src/cosalib/qemuvariants.py index a8092eacec098964981dd8670bb62ac734b7c0d5..e0692e180fd452244b0d3f9f238b9e1e43f38103 100644 --- a/src/cosalib/qemuvariants.py +++ b/src/cosalib/qemuvariants.py @@ -52,6 +52,12 @@ VARIANTS = { "image_format": "qcow2", "platform": "aliyun", }, + "applehv": { + "image_format": "raw", + "image_suffix": "raw.gz", + "platform": "applehv", + "compression": "gzip" + }, "azure": { "image_format": "vpc", "image_suffix": "vhd", @@ -91,6 +97,18 @@ VARIANTS = { "--format=oldgnu" ] }, + "hyperv": { + "image_format": "vhdx", + "image_suffix": "vhdx.zip", + "platform": "hyperv", + "compression": "zip" + }, + "kubevirt": { + "image_format": "qcow2", + "platform": "kubevirt", + "image_suffix": "ociarchive", + "compression": "skip", + }, "openstack": { "image_format": "qcow2", "platform": "openstack", @@ -170,6 +188,7 @@ class QemuVariantImage(_Build): self.tar_flags = kwargs.pop("tar_flags", [DEFAULT_TAR_FLAGS]) self.gzip = kwargs.pop("gzip", False) self.virtual_size = kwargs.pop("virtual_size", None) + self.mutate_callback_creates_final_image = False # this is used in case the image has a different disk # name than the platform @@ -282,8 +301,7 @@ class QemuVariantImage(_Build): tar_cmd.extend(['-f', final_img]) tar_cmd.extend(tarlist) run_verbose(tar_cmd) - - else: + elif not self.mutate_callback_creates_final_image: log.info(f"Moving {work_img} to {final_img}") shutil.move(work_img, final_img) diff --git a/src/oscontainer.py b/src/oscontainer.py index 733352bb71f5ce62fb15a7634cfc2d1fc0fac43f..136648c87cb8f76b2924db3434468ced6c670dfa 100755 --- a/src/oscontainer.py +++ b/src/oscontainer.py @@ -20,12 +20,12 @@ import os import shutil import subprocess from cosalib import cmdlib +from cosalib.buildah import ( + buildah_base_args +) OSCONTAINER_COMMIT_LABEL = 'com.coreos.ostree-commit' -# https://access.redhat.com/documentation/en-us/openshift_container_platform/4.1/html/builds/custom-builds-buildah -NESTED_BUILD_ARGS = ['--storage-driver', 'vfs'] - def run_get_json(args): return json.loads(subprocess.check_output(args)) @@ -113,14 +113,7 @@ def oscontainer_build(containers_storage, tmpdir, src, ref, image_name_and_tag, else: ostree_version = None - buildah_base_argv = ['buildah'] - if containers_storage is not None: - buildah_base_argv.append(f"--root={containers_storage}") - if os.environ.get('container') is not None: - print("Using nested container mode due to container environment variable") - buildah_base_argv.extend(NESTED_BUILD_ARGS) - else: - print("Skipping nested container mode") + buildah_base_argv = buildah_base_args(containers_storage) # In general, we just stick with the default tmpdir set up. But if a # workdir is provided, then we want to be sure that all the heavy I/O work