mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-08 08:27:24 +00:00
repo: Merge osbuilder/1.11.0-rc0 into kata-containers/2.0-dev
Merge osbuilder into kata-containers for 2.0 development cycle. Signed-off-by: Salvador Fuentes <salvador.fuentes@intel.com>
This commit is contained in:
commit
21c830c7da
tools/osbuilder
.gitignoreCODE_OF_CONDUCT.mdCONTRIBUTING.mdLICENSEMakefileREADME.mdVERSION
dracut
image-builder
initrd-builder
rootfs-builder
scripts
tests
2
tools/osbuilder/.gitignore
vendored
Normal file
2
tools/osbuilder/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
image-builder/nsdax
|
||||
dracut/Dockerfile
|
3
tools/osbuilder/CODE_OF_CONDUCT.md
Normal file
3
tools/osbuilder/CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,3 @@
|
||||
## Kata Containers osbuilder Code of Conduct
|
||||
|
||||
Kata Containers follows the [OpenStack Foundation Code of Conduct](https://www.openstack.org/legal/community-code-of-conduct/).
|
5
tools/osbuilder/CONTRIBUTING.md
Normal file
5
tools/osbuilder/CONTRIBUTING.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Contributing
|
||||
|
||||
## This repo is part of [Kata Containers](https://katacontainers.io)
|
||||
|
||||
For details on how to contribute to the Kata Containers project, please see the main [contributing document](https://github.com/kata-containers/community/blob/master/CONTRIBUTING.md).
|
201
tools/osbuilder/LICENSE
Normal file
201
tools/osbuilder/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
211
tools/osbuilder/Makefile
Normal file
211
tools/osbuilder/Makefile
Normal file
@ -0,0 +1,211 @@
|
||||
#
|
||||
# Copyright (c) 2017 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
MK_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
TEST_RUNNER := $(MK_DIR)/tests/test_images.sh
|
||||
ROOTFS_BUILDER := $(MK_DIR)/rootfs-builder/rootfs.sh
|
||||
INITRD_BUILDER := $(MK_DIR)/initrd-builder/initrd_builder.sh
|
||||
IMAGE_BUILDER := $(MK_DIR)/image-builder/image_builder.sh
|
||||
|
||||
DISTRO := centos
|
||||
BUILD_METHOD := distro
|
||||
BUILD_METHOD_LIST := distro dracut
|
||||
AGENT_INIT ?= no
|
||||
ROOTFS_BUILD_DEST := $(shell pwd)
|
||||
IMAGES_BUILD_DEST := $(shell pwd)
|
||||
ROOTFS_MARKER_SUFFIX := _rootfs.done
|
||||
TARGET_ROOTFS := $(ROOTFS_BUILD_DEST)/$(DISTRO)_rootfs
|
||||
TARGET_ROOTFS_MARKER := $(ROOTFS_BUILD_DEST)/.$(DISTRO)$(ROOTFS_MARKER_SUFFIX)
|
||||
TARGET_IMAGE := $(IMAGES_BUILD_DEST)/kata-containers.img
|
||||
TARGET_INITRD := $(IMAGES_BUILD_DEST)/kata-containers-initrd.img
|
||||
|
||||
VERSION_FILE := ./VERSION
|
||||
VERSION := $(shell grep -v ^\# $(VERSION_FILE))
|
||||
COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
|
||||
COMMIT := $(if $(shell git status --porcelain --untracked-files=no),${COMMIT_NO}-dirty,${COMMIT_NO})
|
||||
VERSION_COMMIT := $(if $(COMMIT),$(VERSION)-$(COMMIT),$(VERSION))
|
||||
|
||||
ifeq ($(filter $(BUILD_METHOD),$(BUILD_METHOD_LIST)),)
|
||||
$(error Invalid BUILD_METHOD value '$(BUILD_METHOD)'. Supported values: $(BUILD_METHOD_LIST))
|
||||
endif
|
||||
|
||||
ifeq (dracut,$(BUILD_METHOD))
|
||||
DISTRO :=
|
||||
TARGET_ROOTFS := dracut_rootfs
|
||||
TARGET_ROOTFS_MARKER := $(ROOTFS_BUILD_DEST)/.dracut$(ROOTFS_MARKER_SUFFIX)
|
||||
# dracut specific variables
|
||||
DRACUT_KVERSION :=
|
||||
DRACUT_OVERLAY_DIR := $(MK_DIR)/dracut_overlay
|
||||
DRACUT_DIR := $(MK_DIR)/dracut
|
||||
DRACUT_CONF_DIR := $(DRACUT_DIR)/dracut.conf.d
|
||||
DRACUT_OPTIONS := --no-compress --conf /dev/null --confdir $(DRACUT_CONF_DIR)
|
||||
|
||||
ifneq (,$(DRACUT_KVERSION))
|
||||
# Explicitly use bash, which is what dracut uses to process conf files
|
||||
DRACUT_KMODULES := $(shell bash -c 'source $(DRACUT_CONF_DIR)/10-drivers.conf; echo "$$drivers"')
|
||||
else
|
||||
# If a kernel version is not specified, do not make systemd load modules
|
||||
# at startup
|
||||
DRACUT_OPTIONS += --no-kernel
|
||||
endif
|
||||
|
||||
ifeq (,$(DRACUT_OVERLAY_DIR))
|
||||
$(error DRACUT_OVERLAY_DIR cannot be empty)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Set the variable to silent logs using chronic
|
||||
OSBUILDER_USE_CHRONIC :=
|
||||
|
||||
# silent_run allows running make recipes using the chronic wrapper, so logs are
|
||||
# muted if the recipe command succeeds.
|
||||
# Arguments:
|
||||
# - Message
|
||||
# - Command to run
|
||||
ifeq (,$(OSBUILDER_USE_CHRONIC))
|
||||
define silent_run
|
||||
@echo $(1)
|
||||
$(2)
|
||||
endef
|
||||
else
|
||||
define silent_run
|
||||
@echo $(1) with command: $(2)
|
||||
@chronic $(2)
|
||||
endef
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
rootfs-%: $(ROOTFS_BUILD_DEST)/.%$(ROOTFS_MARKER_SUFFIX)
|
||||
@ # DONT remove. This is not cancellation rule.
|
||||
|
||||
.PRECIOUS: $(ROOTFS_BUILD_DEST)/.%$(ROOTFS_MARKER_SUFFIX)
|
||||
$(ROOTFS_BUILD_DEST)/.%$(ROOTFS_MARKER_SUFFIX):: rootfs-builder/%
|
||||
$(call silent_run,Creating rootfs for "$*",$(ROOTFS_BUILDER) -o $(VERSION_COMMIT) -r $(ROOTFS_BUILD_DEST)/$*_rootfs $*)
|
||||
@touch $@
|
||||
|
||||
# To generate a dracut rootfs, we first generate a dracut initrd and then
|
||||
# extract it in a local folder.
|
||||
# Notes:
|
||||
# - assuming a not compressed initrd.
|
||||
.PRECIOUS: $(ROOTFS_BUILD_DEST)/.dracut$(ROOTFS_MARKER_SUFFIX)
|
||||
$(ROOTFS_BUILD_DEST)/.dracut$(ROOTFS_MARKER_SUFFIX): $(TARGET_INITRD)
|
||||
mkdir -p $(TARGET_ROOTFS)
|
||||
(cd $(TARGET_ROOTFS); cat $< | cpio --extract --preserve-modification-time --make-directories)
|
||||
@touch $@
|
||||
|
||||
image-%: $(IMAGES_BUILD_DEST)/kata-containers-image-%.img
|
||||
@ # DONT remove. This is not cancellation rule.
|
||||
|
||||
.PRECIOUS: $(IMAGES_BUILD_DEST)/kata-containers-image-%.img
|
||||
$(IMAGES_BUILD_DEST)/kata-containers-image-%.img: rootfs-%
|
||||
$(call silent_run,Creating image based on $^,$(IMAGE_BUILDER) -o $@ $(ROOTFS_BUILD_DEST)/$*_rootfs)
|
||||
|
||||
initrd-%: $(IMAGES_BUILD_DEST)/kata-containers-initrd-%.img
|
||||
@ # DONT remove. This is not cancellation rule.
|
||||
|
||||
.PRECIOUS: $(IMAGES_BUILD_DEST)/kata-containers-initrd-%.img
|
||||
$(IMAGES_BUILD_DEST)/kata-containers-initrd-%.img: rootfs-%
|
||||
$(call silent_run,Creating initrd image for $*,$(INITRD_BUILDER) -o $@ $(ROOTFS_BUILD_DEST)/$*_rootfs)
|
||||
|
||||
.PHONY: all
|
||||
all: image initrd
|
||||
|
||||
.PHONY: rootfs
|
||||
rootfs: $(TARGET_ROOTFS_MARKER)
|
||||
|
||||
.PHONY: image
|
||||
image: $(TARGET_IMAGE)
|
||||
|
||||
$(TARGET_IMAGE): $(TARGET_ROOTFS_MARKER)
|
||||
$(call silent_run,Creating image based on "$(TARGET_ROOTFS)",$(IMAGE_BUILDER) -o $@ "$(TARGET_ROOTFS)")
|
||||
|
||||
|
||||
.PHONY: initrd
|
||||
initrd: $(TARGET_INITRD)
|
||||
|
||||
ifeq (distro,$(BUILD_METHOD))
|
||||
$(TARGET_INITRD): $(TARGET_ROOTFS_MARKER)
|
||||
$(call silent_run,Creating initrd image based on "$(TARGET_ROOTFS)",$(INITRD_BUILDER) "$(TARGET_ROOTFS)")
|
||||
else
|
||||
$(TARGET_INITRD): $(DRACUT_OVERLAY_DIR)
|
||||
@echo Creating initrd image based on the host OS using dracut
|
||||
dracut $(DRACUT_OPTIONS) --include $< / $@ $(DRACUT_KVERSION)
|
||||
endif
|
||||
|
||||
# Notes on overlay dir:
|
||||
# - If user specified any kernel module in the dracut conf file,
|
||||
# we need to make sure these are pre-loaded at startup using
|
||||
# systemd modules-load.d
|
||||
$(DRACUT_OVERLAY_DIR):
|
||||
mkdir -p $@
|
||||
# Modules preload
|
||||
$(ROOTFS_BUILDER) -o $(VERSION_COMMIT) -r $@
|
||||
mkdir -p $@/etc/modules-load.d
|
||||
echo $(DRACUT_KMODULES) | tr " " "\n" > $@/etc/modules-load.d/kata-modules.conf
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(TEST_RUNNER) "$(DISTRO)"
|
||||
|
||||
.PHONY: test-image-only
|
||||
test-image-only:
|
||||
$(TEST_RUNNER) --test-images-only "$(DISTRO)"
|
||||
|
||||
.PHONY: test-initrd-only
|
||||
test-initrd-only:
|
||||
$(TEST_RUNNER) --test-initrds-only "$(DISTRO)"
|
||||
|
||||
.PHONY: list-distros
|
||||
list-distros:
|
||||
@ $(ROOTFS_BUILDER) -l
|
||||
|
||||
DESTDIR := /
|
||||
KATADIR := /usr/libexec/kata-containers
|
||||
OSBUILDER_DIR := $(KATADIR)/osbuilder
|
||||
INSTALL_DIR :=$(DESTDIR)/$(OSBUILDER_DIR)
|
||||
DIST_CONFIGS:= $(wildcard rootfs-builder/*/config.sh)
|
||||
|
||||
SCRIPTS :=
|
||||
SCRIPTS += rootfs-builder/rootfs.sh
|
||||
SCRIPTS += image-builder/image_builder.sh
|
||||
SCRIPTS += initrd-builder/initrd_builder.sh
|
||||
|
||||
HELPER_FILES :=
|
||||
HELPER_FILES += rootfs-builder/versions.txt
|
||||
HELPER_FILES += scripts/lib.sh
|
||||
HELPER_FILES += image-builder/nsdax.gpl.c
|
||||
|
||||
define INSTALL_FILE
|
||||
echo "Installing $(abspath $2/$1)";
|
||||
install -m 644 -D $1 $2/$1;
|
||||
endef
|
||||
|
||||
define INSTALL_SCRIPT
|
||||
echo "Installing $(abspath $2/$1)";
|
||||
install -m 755 -D $1 $(abspath $2/$1);
|
||||
endef
|
||||
|
||||
.PHONY: install-scripts
|
||||
install-scripts:
|
||||
@echo "Installing scripts"
|
||||
@$(foreach f,$(SCRIPTS),$(call INSTALL_SCRIPT,$f,$(INSTALL_DIR)))
|
||||
@echo "Installing helper files"
|
||||
@$(foreach f,$(HELPER_FILES),$(call INSTALL_FILE,$f,$(INSTALL_DIR)))
|
||||
@echo "Installing installing config files"
|
||||
@$(foreach f,$(DIST_CONFIGS),$(call INSTALL_FILE,$f,$(INSTALL_DIR)))
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(TARGET_ROOTFS_MARKER) $(TARGET_ROOTFS) $(TARGET_IMAGE) $(TARGET_INITRD) $(DRACUT_OVERLAY_DIR)
|
||||
|
||||
# Prints the name of the variable passed as suffix to the print- target,
|
||||
# E.g., if Makefile contains:
|
||||
# MY_MAKE_VAR := foobar
|
||||
# Then:
|
||||
# $ make printf-MY_MAKE_VAR
|
||||
# Will print "foobar"
|
||||
print-%:
|
||||
@echo $($*)
|
212
tools/osbuilder/README.md
Normal file
212
tools/osbuilder/README.md
Normal file
@ -0,0 +1,212 @@
|
||||
[](https://travis-ci.org/kata-containers/osbuilder)
|
||||
|
||||
# osbuilder
|
||||
|
||||
* [osbuilder](#osbuilder)
|
||||
* [Introduction](#introduction)
|
||||
* [Terms](#terms)
|
||||
* [Building](#building)
|
||||
* [Rootfs creation](#rootfs-creation)
|
||||
* [Rootfs with systemd as init](#rootfs-with-systemd-as-init)
|
||||
* [Rootfs with the agent as init](#rootfs-with-the-agent-as-init)
|
||||
* [dracut based rootfs](#dracut-based-rootfs)
|
||||
* [Image creation](#image-creation)
|
||||
* [Image with systemd as init](#image-with-systemd-as-init)
|
||||
* [Image with the agent as init](#image-with-the-agent-as-init)
|
||||
* [dracut based image](#dracut-based-image)
|
||||
* [Initrd creation](#initrd-creation)
|
||||
* [Rootfs based initrd](#rootfs-based-initrd)
|
||||
* [dracut based initrd](#dracut-based-initrd)
|
||||
* [dracut options](#dracut-options)
|
||||
* [Add kernel modules](#add-kernel-modules)
|
||||
* [Testing](#testing)
|
||||
* [Platform-Distro Compatibility Matrix](#platform-distro-compatibility-matrix)
|
||||
|
||||
## Introduction
|
||||
|
||||
The Kata Containers runtime creates a virtual machine (VM) to isolate a set of
|
||||
container workloads. The VM requires a guest kernel and a guest operating system
|
||||
("guest OS") to boot and create containers inside the guest
|
||||
environment.
|
||||
|
||||
This repository contains tools to create a guest OS disk image.
|
||||
|
||||
## Terms
|
||||
|
||||
This section describes the terms used for all documentation in this repository.
|
||||
|
||||
- rootfs
|
||||
|
||||
The root filesystem or "rootfs" is a slight misnomer as it is not a true filesystem. It is a tree of files contained in a particular directory, which represents the root disk layout. A rootfs can be turned into either an image or an initrd.
|
||||
|
||||
See the [rootfs creation](#rootfs-creation) section.
|
||||
|
||||
- "Guest OS" (or "Guest Image")
|
||||
|
||||
A "virtual disk" or "disk image" built from a rootfs. It contains a
|
||||
filesystem that is used by the VM, in conjunction with a guest kernel, to
|
||||
create an environment to host the container. Neither the guest OS nor the
|
||||
guest kernel need to be the same as the host operating system.
|
||||
|
||||
See the [image creation](#image-creation) section.
|
||||
|
||||
- initrd (or "initramfs")
|
||||
|
||||
A compressed `cpio(1)` archive, created from a rootfs which is loaded into memory and used as part of the Linux startup process. During startup, the kernel unpacks it into a special instance of a `tmpfs` that becomes the initial root filesystem.
|
||||
|
||||
See the [initrd creation](#initrd-creation) section.
|
||||
|
||||
- "Base OS"
|
||||
|
||||
A particular version of a Linux distribution used to create a rootfs from.
|
||||
|
||||
- dracut
|
||||
|
||||
A guest OS build method where the building host is used as the Base OS.
|
||||
For more information refer to the [dracut homepage](https://dracut.wiki.kernel.org/index.php/Main_Page).
|
||||
|
||||
## Building
|
||||
|
||||
The top-level `Makefile` contains an example of how to use the available components.
|
||||
Set `DEBUG=true` to execute build scripts in debug mode.
|
||||
|
||||
Two build methods are available, `distro` and `dracut`.
|
||||
By default, the `distro` build method is used, and this creates a rootfs using
|
||||
distro specific commands (e.g.: `debootstrap` for Debian or `yum` for CentOS).
|
||||
The `dracut` build method uses the distro-agnostic tool `dracut` to obtain the same goal.
|
||||
|
||||
By default components are run on the host system. However, some components
|
||||
offer the ability to run from within a container (for ease of setup) by setting the
|
||||
`USE_DOCKER=true` or `USE_PODMAN=true` variable. If both are set, `USE_DOCKER=true`
|
||||
takes precedence over `USE_PODMAN=true`.
|
||||
|
||||
For more detailed information, consult the documentation for a particular component.
|
||||
|
||||
When invoking the appropriate make target as showed below, a single command is used
|
||||
to generate an initrd or an image. This is what happens in details:
|
||||
1. A rootfs is generated based on the specified target distribution.
|
||||
2. The rootfs is provisioned with Kata-specific components and configuration files.
|
||||
3. The rootfs is used as a base to generate an initrd or an image.
|
||||
|
||||
When using the dracut build method however, the build sequence is different:
|
||||
1. An overlay directory is populated with Kata-specific components.
|
||||
2. dracut is instructed to merge the overlay directory with the required host-side
|
||||
filesystem components to generate an initrd.
|
||||
3. When generating an image, the initrd is extracted to obtain the base rootfs for
|
||||
the image.
|
||||
|
||||
### Rootfs creation
|
||||
|
||||
This section shows how to build a basic rootfs using the default distribution.
|
||||
For further details, see
|
||||
[the rootfs builder documentation](rootfs-builder/README.md).
|
||||
|
||||
#### Rootfs with systemd as init
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make USE_DOCKER=true rootfs
|
||||
```
|
||||
|
||||
#### Rootfs with the agent as init
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make USE_DOCKER=true AGENT_INIT=yes rootfs
|
||||
```
|
||||
|
||||
#### dracut based rootfs
|
||||
|
||||
> **Note**: the dracut build method does not need a rootfs as a base for an image or initrd.
|
||||
However, a rootfs can be generated by extracting the generated initrd.
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make BUILD_METHOD=dracut rootfs
|
||||
```
|
||||
|
||||
### Image creation
|
||||
|
||||
This section shows how to create an image from the already-created rootfs. For
|
||||
further details, see
|
||||
[the image builder documentation](image-builder/README.md).
|
||||
|
||||
#### Image with systemd as init
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make USE_DOCKER=true image
|
||||
```
|
||||
|
||||
#### Image with the agent as init
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make USE_DOCKER=true AGENT_INIT=yes image
|
||||
```
|
||||
|
||||
#### dracut based image
|
||||
|
||||
> Note: the dracut build method generates an image by first building an initrd,
|
||||
and then using the rootfs extracted from it.
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make BUILD_METHOD=dracut image
|
||||
```
|
||||
|
||||
### Initrd creation
|
||||
|
||||
#### Rootfs based initrd
|
||||
|
||||
Create an initrd from the already-created rootfs and with the agent acting as the init daemon
|
||||
using:
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make AGENT_INIT=yes initrd
|
||||
```
|
||||
|
||||
#### dracut based initrd
|
||||
|
||||
Create an initrd using the dracut build method with:
|
||||
|
||||
```
|
||||
$ sudo -E PATH=$PATH make BUILD_METHOD=dracut AGENT_INIT=yes initrd
|
||||
```
|
||||
|
||||
For further details,
|
||||
see [the initrd builder documentation](initrd-builder/README.md).
|
||||
|
||||
### dracut options
|
||||
|
||||
#### Add kernel modules
|
||||
|
||||
If the initrd or image needs to contain kernel modules, this can be done by:
|
||||
|
||||
1. Specify the name of the modules (as reported by `modinfo MODULE-NAME`) in
|
||||
`dracut/dracut.conf.d/10-drivers.conf`. For example this file can contain:
|
||||
```
|
||||
drivers="9p 9pnet 9pnet_virtio"
|
||||
```
|
||||
2. Set the `DRACUT_KVERSION` make variable to the release name of the kernel that
|
||||
is paired with the built image or initrd, using the `uname -r` format. For example:
|
||||
```
|
||||
$ make BUILD_METHOD=dracut DRACUT_KVERSION=5.2.1-23-kata AGENT_INIT=yes initrd
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```
|
||||
$ make test
|
||||
```
|
||||
|
||||
For further details, see [the tests documentation](tests/README.md).
|
||||
|
||||
## Platform-Distro Compatibility Matrix
|
||||
|
||||
The following table illustrates what target architecture is supported for each
|
||||
of the the osbuilder distributions.
|
||||
|
||||
> Note: this table is not relevant for the dracut build method, since it supports
|
||||
any Linux distribution and architecture where dracut is available.
|
||||
|
||||
| |Alpine |CentOS |Clear Linux |Debian/Ubuntu |EulerOS |Fedora |openSUSE |
|
||||
|-- |-- |-- |-- |-- |-- |-- |-- |
|
||||
|**ARM64** |:heavy_check_mark:|:heavy_check_mark:| | |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|
|
||||
|**PPC64le**|:heavy_check_mark:|:heavy_check_mark:| |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|
|
||||
|**s390x** |:heavy_check_mark:| | |:heavy_check_mark:| |:heavy_check_mark:| |
|
||||
|**x86_64** |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|
|
1
tools/osbuilder/VERSION
Normal file
1
tools/osbuilder/VERSION
Normal file
@ -0,0 +1 @@
|
||||
1.11.0-rc0
|
38
tools/osbuilder/dracut/Dockerfile.in
Normal file
38
tools/osbuilder/dracut/Dockerfile.in
Normal file
@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (c) 2019 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from opensuse/tumbleweed
|
||||
|
||||
RUN zypper --non-interactive refresh; \
|
||||
zypper --non-interactive install --no-recommends --force-resolution \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
cmake \
|
||||
coreutils \
|
||||
cpio \
|
||||
curl \
|
||||
dracut \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git-core \
|
||||
glibc-devel \
|
||||
glibc-devel-static \
|
||||
glibc-utils \
|
||||
libstdc++-devel \
|
||||
linux-glibc-devel \
|
||||
m4 \
|
||||
make \
|
||||
sed \
|
||||
tar \
|
||||
vim \
|
||||
which; \
|
||||
zypper --non-interactive clean --all;
|
||||
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_MUSL@
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
17
tools/osbuilder/dracut/dracut.conf.d/05-base.conf
Normal file
17
tools/osbuilder/dracut/dracut.conf.d/05-base.conf
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2019 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Main dracut config for Kata Containers
|
||||
|
||||
# do NOT combine early microcode with ramdisk
|
||||
early_microcode="no"
|
||||
# do NOT install only what's needed to boot the local host
|
||||
hostonly="no"
|
||||
# do NOT store the kernel command line arguments in the initramfs
|
||||
hostonly_cmdline="no"
|
||||
# create reproducible images
|
||||
reproducible="yes"
|
||||
# dracut modules to include (NOTE: these are NOT kernel modules)
|
||||
dracutmodules="kernel-modules udev-rules syslog systemd"
|
9
tools/osbuilder/dracut/dracut.conf.d/10-drivers.conf
Normal file
9
tools/osbuilder/dracut/dracut.conf.d/10-drivers.conf
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Copyright (c) 2019 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Specify a space-separated set of kernel modules to copy from the host to
|
||||
# the initramfs image. For example:
|
||||
# drivers="9p 9pnet 9pnet_virtio"
|
||||
drivers=""
|
10
tools/osbuilder/image-builder/Dockerfile
Normal file
10
tools/osbuilder/image-builder/Dockerfile
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
From docker.io/fedora:latest
|
||||
|
||||
RUN [ -n "$http_proxy" ] && sed -i '$ a proxy='$http_proxy /etc/dnf/dnf.conf ; true
|
||||
|
||||
RUN dnf install -y qemu-img parted gdisk e2fsprogs gcc xfsprogs findutils
|
29
tools/osbuilder/image-builder/README.md
Normal file
29
tools/osbuilder/image-builder/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
* [Creating a guest OS image](#creating-a-guest-os-image)
|
||||
* [Further information](#further-information)
|
||||
|
||||
# Kata Containers image generation
|
||||
|
||||
A Kata Containers disk image is generated using the `image_builder.sh` script.
|
||||
This uses a rootfs directory created by the `rootfs-builder/rootfs.sh` script.
|
||||
|
||||
## Creating a guest OS image
|
||||
|
||||
To create a guest OS image run:
|
||||
|
||||
```
|
||||
$ sudo ./image_builder.sh path/to/rootfs
|
||||
```
|
||||
|
||||
Where `path/to/rootfs` is the directory populated by `rootfs.sh`.
|
||||
|
||||
> **Note**: If you are building an image from an Alpine rootfs, see
|
||||
> the important note [here](/rootfs-builder/README.md#rootfs-requirements).
|
||||
|
||||
## Further information
|
||||
|
||||
For more information about usage (including how to adjust the size of the
|
||||
image), run:
|
||||
|
||||
```
|
||||
$ ./image_builder.sh -h
|
||||
```
|
513
tools/osbuilder/image-builder/image_builder.sh
Executable file
513
tools/osbuilder/image-builder/image_builder.sh
Executable file
@ -0,0 +1,513 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2017-2019 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -e
|
||||
|
||||
[ -n "${DEBUG}" ] && set -x
|
||||
|
||||
DOCKER_RUNTIME=${DOCKER_RUNTIME:-runc}
|
||||
|
||||
readonly script_name="${0##*/}"
|
||||
readonly script_dir=$(dirname "$(readlink -f "$0")")
|
||||
readonly lib_file="${script_dir}/../scripts/lib.sh"
|
||||
|
||||
readonly ext4_format="ext4"
|
||||
readonly xfs_format="xfs"
|
||||
|
||||
# ext4: percentage of the filesystem which may only be allocated by privileged processes.
|
||||
readonly reserved_blocks_percentage=3
|
||||
|
||||
# Where the rootfs starts in MB
|
||||
readonly rootfs_start=1
|
||||
|
||||
# Where the rootfs ends in MB
|
||||
readonly rootfs_end=-1
|
||||
|
||||
# DAX header size
|
||||
# * NVDIMM driver reads the device namespace information from nvdimm namespace (4K offset).
|
||||
# The MBR #1 + DAX metadata are saved in the first 2MB of the image.
|
||||
readonly dax_header_sz=2
|
||||
|
||||
# DAX aligment
|
||||
# * DAX huge pages [2]: 2MB alignment
|
||||
# [2] - https://nvdimm.wiki.kernel.org/2mib_fs_dax
|
||||
readonly dax_alignment=2
|
||||
|
||||
# The list of systemd units and files that are not needed in Kata Containers
|
||||
readonly -a systemd_units=(
|
||||
"systemd-coredump@"
|
||||
"systemd-journald"
|
||||
"systemd-journald-dev-log"
|
||||
"systemd-journal-flush"
|
||||
"systemd-random-seed"
|
||||
"systemd-timesyncd"
|
||||
"systemd-tmpfiles-setup"
|
||||
"systemd-udevd"
|
||||
"systemd-udevd-control"
|
||||
"systemd-udevd-kernel"
|
||||
"systemd-udev-trigger"
|
||||
"systemd-update-utmp"
|
||||
)
|
||||
|
||||
readonly -a systemd_files=(
|
||||
"systemd-bless-boot-generator"
|
||||
"systemd-fstab-generator"
|
||||
"systemd-getty-generator"
|
||||
"systemd-gpt-auto-generator"
|
||||
"systemd-tmpfiles-cleanup.timer"
|
||||
)
|
||||
|
||||
# Set a default value
|
||||
AGENT_INIT=${AGENT_INIT:-no}
|
||||
|
||||
# Align image to (size in MB) according to different architecture.
|
||||
case "$(uname -m)" in
|
||||
aarch64) readonly mem_boundary_mb=16 ;;
|
||||
*) readonly mem_boundary_mb=128 ;;
|
||||
esac
|
||||
|
||||
# shellcheck source=../scripts/lib.sh
|
||||
source "${lib_file}"
|
||||
|
||||
usage() {
|
||||
cat <<EOT
|
||||
Usage: ${script_name} [options] <rootfs-dir>
|
||||
This script will create a Kata Containers image file of
|
||||
an adequate size based on the <rootfs-dir> directory.
|
||||
|
||||
Options:
|
||||
-h Show this help
|
||||
-o path to generate image file ENV: IMAGE
|
||||
-r Free space of the root partition in MB ENV: ROOT_FREE_SPACE
|
||||
|
||||
Extra environment variables:
|
||||
AGENT_BIN: Use it to change the expected agent binary name
|
||||
AGENT_INIT: Use kata agent as init process
|
||||
NSDAX_BIN: Use to specify path to pre-compiled 'nsdax' tool.
|
||||
FS_TYPE: Filesystem type to use. Only xfs and ext4 are supported.
|
||||
USE_DOCKER: If set will build image in a Docker Container (requries docker)
|
||||
DEFAULT: not set
|
||||
USE_PODMAN: If set and USE_DOCKER not set, will build image in a Podman Container (requries podman)
|
||||
DEFAULT: not set
|
||||
|
||||
|
||||
Following diagram shows how the resulting image will look like
|
||||
|
||||
.-----------.----------.---------------.-----------.
|
||||
| 0 - 512 B | 4 - 8 Kb | 2M - 2M+512B | 3M |
|
||||
|-----------+----------+---------------+-----------+
|
||||
| MBR #1 | DAX | MBR #2 | Rootfs |
|
||||
'-----------'----------'---------------'-----------+
|
||||
| | ^ | ^
|
||||
| '-data-' '--------'
|
||||
| |
|
||||
'--------rootfs-partition---------'
|
||||
|
||||
|
||||
MBR: Master boot record.
|
||||
DAX: Metadata required by the NVDIMM driver to enable DAX in the guest [1][2] (struct nd_pfn_sb).
|
||||
Rootfs: partition that contains the root filesystem (/usr, /bin, ect).
|
||||
|
||||
Kernels and hypervisors that support DAX/NVDIMM read the MBR #2, otherwise MBR #1 is read.
|
||||
|
||||
[1] - https://github.com/kata-containers/osbuilder/blob/master/image-builder/nsdax.gpl.c
|
||||
[2] - https://github.com/torvalds/linux/blob/master/drivers/nvdimm/pfn.h
|
||||
|
||||
EOT
|
||||
}
|
||||
|
||||
|
||||
# build the image using container engine
|
||||
build_with_container() {
|
||||
local rootfs="$1"
|
||||
local image="$2"
|
||||
local fs_type="$3"
|
||||
local block_size="$4"
|
||||
local root_free_space="$5"
|
||||
local agent_bin="$6"
|
||||
local agent_init="$7"
|
||||
local container_engine="$8"
|
||||
local nsdax_bin="$9"
|
||||
local container_image_name="image-builder-osbuilder"
|
||||
local shared_files=""
|
||||
|
||||
image_dir=$(readlink -f "$(dirname "${image}")")
|
||||
image_name=$(basename "${image}")
|
||||
|
||||
"${container_engine}" build \
|
||||
--build-arg http_proxy="${http_proxy}" \
|
||||
--build-arg https_proxy="${https_proxy}" \
|
||||
-t "${container_image_name}" "${script_dir}"
|
||||
|
||||
readonly mke2fs_conf="/etc/mke2fs.conf"
|
||||
if [ -f "${mke2fs_conf}" ]; then
|
||||
shared_files+="-v ${mke2fs_conf}:${mke2fs_conf}:ro "
|
||||
fi
|
||||
|
||||
#Make sure we use a compatible runtime to build rootfs
|
||||
# In case Clear Containers Runtime is installed we dont want to hit issue:
|
||||
#https://github.com/clearcontainers/runtime/issues/828
|
||||
"${container_engine}" run \
|
||||
--rm \
|
||||
--runtime "${DOCKER_RUNTIME}" \
|
||||
--privileged \
|
||||
--env AGENT_BIN="${agent_bin}" \
|
||||
--env AGENT_INIT="${agent_init}" \
|
||||
--env FS_TYPE="${fs_type}" \
|
||||
--env BLOCK_SIZE="${block_size}" \
|
||||
--env ROOT_FREE_SPACE="${root_free_space}" \
|
||||
--env NSDAX_BIN="${nsdax_bin}" \
|
||||
--env DEBUG="${DEBUG}" \
|
||||
-v /dev:/dev \
|
||||
-v "${script_dir}":"/osbuilder" \
|
||||
-v "${script_dir}/../scripts":"/scripts" \
|
||||
-v "${rootfs}":"/rootfs" \
|
||||
-v "${image_dir}":"/image" \
|
||||
${shared_files} \
|
||||
${container_image_name} \
|
||||
bash "/osbuilder/${script_name}" -o "/image/${image_name}" /rootfs
|
||||
}
|
||||
|
||||
check_rootfs() {
|
||||
local rootfs="${1}"
|
||||
|
||||
[ -d "${rootfs}" ] || die "${rootfs} is not a directory"
|
||||
|
||||
# The kata rootfs image expect init and kata-agent to be installed
|
||||
init_path="/sbin/init"
|
||||
init="${rootfs}${init_path}"
|
||||
if [ ! -x "${init}" ] && [ ! -L "${init}" ]; then
|
||||
error "${init_path} is not installed in ${rootfs}"
|
||||
return 1
|
||||
fi
|
||||
OK "init is installed"
|
||||
|
||||
|
||||
systemd_path="/lib/systemd/systemd"
|
||||
systemd="${rootfs}${systemd_path}"
|
||||
|
||||
# check agent or systemd
|
||||
case "${AGENT_INIT}" in
|
||||
"no")
|
||||
if [ ! -x "${systemd}" ] && [ ! -L "${systemd}" ]; then
|
||||
error "${systemd_path} is not installed in ${rootfs}"
|
||||
return 1
|
||||
fi
|
||||
OK "init is systemd"
|
||||
;;
|
||||
|
||||
"yes")
|
||||
agent_path="/sbin/init"
|
||||
agent="${rootfs}${agent_path}"
|
||||
if [ ! -x "${agent}" ]; then
|
||||
error "${agent_path} is not installed in ${rootfs}. Use AGENT_BIN env variable to change the expected agent binary name"
|
||||
return 1
|
||||
fi
|
||||
# checksum must be different to system
|
||||
if [ -f "${systemd}" ] && cmp -s "${systemd}" "${agent}"; then
|
||||
error "The agent is not the init process. ${agent_path} is systemd"
|
||||
return 1
|
||||
fi
|
||||
|
||||
OK "Agent installed"
|
||||
;;
|
||||
|
||||
*)
|
||||
error "Invalid value for AGENT_INIT: '${AGENT_INIT}'. Use to 'yes' or 'no'"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
calculate_required_disk_size() {
|
||||
local rootfs="$1"
|
||||
local fs_type="$2"
|
||||
local block_size="$3"
|
||||
|
||||
readonly rootfs_size_mb=$(du -B 1MB -s "${rootfs}" | awk '{print $1}')
|
||||
readonly image="$(mktemp)"
|
||||
readonly mount_dir="$(mktemp -d)"
|
||||
readonly max_tries=20
|
||||
readonly increment=10
|
||||
|
||||
for i in $(seq 1 $max_tries); do
|
||||
local img_size="$((rootfs_size_mb + (i * increment)))"
|
||||
create_disk "${image}" "${img_size}" "${fs_type}" "${rootfs_start}" > /dev/null 2>&1
|
||||
if ! device="$(setup_loop_device "${image}")"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! format_loop "${device}" "${block_size}" "${fs_type}" > /dev/null 2>&1 ; then
|
||||
die "Could not format loop device: ${device}"
|
||||
fi
|
||||
mount "${device}p1" "${mount_dir}"
|
||||
avail="$(df -BM --output=avail "${mount_dir}" | tail -n1 | sed 's/[M ]//g')"
|
||||
umount "${mount_dir}"
|
||||
losetup -d "${device}"
|
||||
|
||||
if [ "${avail}" -gt "${rootfs_size_mb}" ]; then
|
||||
rmdir "${mount_dir}"
|
||||
rm -f "${image}"
|
||||
echo "${img_size}"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
rmdir "${mount_dir}"
|
||||
rm -f "${image}"
|
||||
error "Could not calculate the required disk size"
|
||||
}
|
||||
|
||||
# Calculate image size based on the rootfs and free space
|
||||
calculate_img_size() {
|
||||
local rootfs="$1"
|
||||
local root_free_space_mb="$2"
|
||||
local fs_type="$3"
|
||||
local block_size="$4"
|
||||
|
||||
# rootfs start + DAX header size + rootfs end
|
||||
local reserved_size_mb=$((rootfs_start + dax_header_sz + rootfs_end))
|
||||
|
||||
disk_size="$(calculate_required_disk_size "${rootfs}" "${fs_type}" "${block_size}")"
|
||||
|
||||
img_size="$((disk_size + reserved_size_mb))"
|
||||
if [ -n "${root_free_space_mb}" ]; then
|
||||
img_size="$((img_size + root_free_space_mb))"
|
||||
fi
|
||||
|
||||
remaining="$((img_size % mem_boundary_mb))"
|
||||
if [ "${remaining}" != "0" ]; then
|
||||
img_size=$((img_size + mem_boundary_mb - remaining))
|
||||
fi
|
||||
|
||||
echo "${img_size}"
|
||||
}
|
||||
|
||||
setup_loop_device() {
|
||||
local image="$1"
|
||||
|
||||
# Get the loop device bound to the image file (requires /dev mounted in the
|
||||
# image build system and root privileges)
|
||||
device=$(losetup -P -f --show "${image}")
|
||||
|
||||
#Refresh partition table
|
||||
partprobe -s "${device}" > /dev/null
|
||||
# Poll for the block device p1
|
||||
for _ in $(seq 1 5); do
|
||||
if [ -b "${device}p1" ]; then
|
||||
echo "${device}"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
error "File ${device}p1 is not a block device"
|
||||
return 1
|
||||
}
|
||||
|
||||
format_loop() {
|
||||
local device="$1"
|
||||
local block_size="$2"
|
||||
local fs_type="$3"
|
||||
|
||||
case "${fs_type}" in
|
||||
"${ext4_format}")
|
||||
mkfs.ext4 -q -F -b "${block_size}" "${device}p1"
|
||||
info "Set filesystem reserved blocks percentage to ${reserved_blocks_percentage}%"
|
||||
tune2fs -m "${reserved_blocks_percentage}" "${device}p1"
|
||||
;;
|
||||
|
||||
"${xfs_format}")
|
||||
mkfs.xfs -q -f -b size="${block_size}" "${device}p1"
|
||||
;;
|
||||
|
||||
*)
|
||||
error "Unsupported fs type: ${fs_type}"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
create_disk() {
|
||||
local image="$1"
|
||||
local img_size="$2"
|
||||
local fs_type="$3"
|
||||
local part_start="$4"
|
||||
|
||||
info "Creating raw disk with size ${img_size}M"
|
||||
qemu-img create -q -f raw "${image}" "${img_size}M"
|
||||
OK "Image file created"
|
||||
|
||||
# Kata runtime expect an image with just one partition
|
||||
# The partition is the rootfs content
|
||||
info "Creating partitions"
|
||||
parted -s -a optimal "${image}" -- \
|
||||
mklabel msdos \
|
||||
mkpart primary "${fs_type}" "${part_start}"M "${rootfs_end}"M
|
||||
|
||||
OK "Partitions created"
|
||||
}
|
||||
|
||||
create_rootfs_image() {
|
||||
local rootfs="$1"
|
||||
local image="$2"
|
||||
local img_size="$3"
|
||||
local fs_type="$4"
|
||||
local block_size="$5"
|
||||
|
||||
create_disk "${image}" "${img_size}" "${fs_type}" "${rootfs_start}"
|
||||
|
||||
if ! device="$(setup_loop_device "${image}")"; then
|
||||
die "Could not setup loop device"
|
||||
fi
|
||||
|
||||
if ! format_loop "${device}" "${block_size}" "${fs_type}"; then
|
||||
die "Could not format loop device: ${device}"
|
||||
fi
|
||||
|
||||
info "Mounting root partition"
|
||||
readonly mount_dir=$(mktemp -p ${TMPDIR:-/tmp} -d osbuilder-mount-dir.XXXX)
|
||||
mount "${device}p1" "${mount_dir}"
|
||||
OK "root partition mounted"
|
||||
|
||||
info "Copying content from rootfs to root partition"
|
||||
cp -a "${rootfs}"/* "${mount_dir}"
|
||||
sync
|
||||
OK "rootfs copied"
|
||||
|
||||
info "Removing unneeded systemd services and sockets"
|
||||
for u in "${systemd_units[@]}"; do
|
||||
find "${mount_dir}" -type f \( \
|
||||
-name "${u}.service" -o \
|
||||
-name "${u}.socket" \) \
|
||||
-exec rm -f {} \;
|
||||
done
|
||||
|
||||
info "Removing unneeded systemd files"
|
||||
for u in "${systemd_files[@]}"; do
|
||||
find "${mount_dir}" -type f -name "${u}" -exec rm -f {} \;
|
||||
done
|
||||
|
||||
info "Creating empty machine-id to allow systemd to bind-mount it"
|
||||
touch "${mount_dir}/etc/machine-id"
|
||||
|
||||
info "Unmounting root partition"
|
||||
umount "${mount_dir}"
|
||||
OK "Root partition unmounted"
|
||||
|
||||
if [ "${fs_type}" = "${ext4_format}" ]; then
|
||||
fsck.ext4 -D -y "${device}p1"
|
||||
fi
|
||||
|
||||
losetup -d "${device}"
|
||||
rmdir "${mount_dir}"
|
||||
}
|
||||
|
||||
set_dax_header() {
|
||||
local image="$1"
|
||||
local img_size="$2"
|
||||
local fs_type="$3"
|
||||
local nsdax_bin="$4"
|
||||
|
||||
# rootfs start + DAX header size
|
||||
local rootfs_offset=$((rootfs_start + dax_header_sz))
|
||||
local header_image="${image}.header"
|
||||
local dax_image="${image}.dax"
|
||||
rm -f "${dax_image}" "${header_image}"
|
||||
|
||||
create_disk "${header_image}" "${img_size}" "${fs_type}" "${rootfs_offset}"
|
||||
|
||||
dax_header_bytes=$((dax_header_sz * 1024 * 1024))
|
||||
dax_alignment_bytes=$((dax_alignment * 1024 * 1024))
|
||||
info "Set DAX metadata"
|
||||
# Set metadata header
|
||||
# Issue: https://github.com/kata-containers/osbuilder/issues/240
|
||||
if [ -z "${nsdax_bin}" ] ; then
|
||||
nsdax_bin="${script_dir}/nsdax"
|
||||
gcc -O2 "${script_dir}/nsdax.gpl.c" -o "${nsdax_bin}"
|
||||
trap "rm ${nsdax_bin}" EXIT
|
||||
fi
|
||||
"${nsdax_bin}" "${header_image}" "${dax_header_bytes}" "${dax_alignment_bytes}"
|
||||
sync
|
||||
|
||||
touch "${dax_image}"
|
||||
# Copy MBR #1 + DAX metadata
|
||||
dd if="${header_image}" of="${dax_image}" bs="${dax_header_sz}M" count=1
|
||||
# Copy MBR #2 + Rootfs
|
||||
dd if="${image}" of="${dax_image}" oflag=append conv=notrunc
|
||||
# final image
|
||||
mv "${dax_image}" "${image}"
|
||||
sync
|
||||
|
||||
rm -f "${dax_image}" "${header_image}"
|
||||
}
|
||||
|
||||
main() {
|
||||
[ "$(id -u)" -eq 0 ] || die "$0: must be run as root"
|
||||
|
||||
# variables that can be overwritten by environment variables
|
||||
local agent_bin="${AGENT_BIN:-kata-agent}"
|
||||
local agent_init="${AGENT_INIT:-no}"
|
||||
local fs_type="${FS_TYPE:-${ext4_format}}"
|
||||
local image="${IMAGE:-kata-containers.img}"
|
||||
local block_size="${BLOCK_SIZE:-4096}"
|
||||
local root_free_space="${ROOT_FREE_SPACE:-}"
|
||||
local nsdax_bin="${NSDAX_BIN:-}"
|
||||
|
||||
while getopts "ho:r:f:" opt
|
||||
do
|
||||
case "$opt" in
|
||||
h) usage; return 0;;
|
||||
o) image="${OPTARG}" ;;
|
||||
r) root_free_space="${OPTARG}" ;;
|
||||
f) fs_type="${OPTARG}" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( OPTIND - 1 ))
|
||||
rootfs="$(readlink -f "$1")"
|
||||
if [ -z "${rootfs}" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
local container_engine
|
||||
if [ -n "${USE_DOCKER}" ]; then
|
||||
container_engine="docker"
|
||||
elif [ -n "${USE_PODMAN}" ]; then
|
||||
container_engine="podman"
|
||||
fi
|
||||
|
||||
if [ -n "$container_engine" ]; then
|
||||
build_with_container "${rootfs}" \
|
||||
"${image}" "${fs_type}" "${block_size}" \
|
||||
"${root_free_space}" "${agent_bin}" \
|
||||
"${agent_init}" "${container_engine}" \
|
||||
"${nsdax_bin}"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if ! check_rootfs "${rootfs}" ; then
|
||||
die "Invalid rootfs"
|
||||
fi
|
||||
|
||||
img_size=$(calculate_img_size "${rootfs}" "${root_free_space}" "${fs_type}" "${block_size}")
|
||||
|
||||
# the first 2M are for the first MBR + NVDIMM metadata and were already
|
||||
# consider in calculate_img_size
|
||||
rootfs_img_size=$((img_size - dax_header_sz))
|
||||
create_rootfs_image "${rootfs}" "${image}" "${rootfs_img_size}" \
|
||||
"${fs_type}" "${block_size}"
|
||||
|
||||
# insert at the beginning of the image the MBR + DAX header
|
||||
set_dax_header "${image}" "${img_size}" "${fs_type}" "${nsdax_bin}"
|
||||
}
|
||||
|
||||
main "$@"
|
171
tools/osbuilder/image-builder/nsdax.gpl.c
Normal file
171
tools/osbuilder/image-builder/nsdax.gpl.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright(c) 2013-2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define __KERNEL__
|
||||
#include <linux/types.h>
|
||||
#include <linux/byteorder/little_endian.h>
|
||||
|
||||
/*
|
||||
Next types, definitions and functions were copied from kernel 4.19.24 source
|
||||
code, specifically from nvdimm driver
|
||||
*/
|
||||
|
||||
#define PFN_SIG_LEN 16
|
||||
#define PFN_SIG "NVDIMM_PFN_INFO"
|
||||
#define SZ_4K 0x00001000
|
||||
|
||||
typedef __u16 u16;
|
||||
typedef __u8 u8;
|
||||
typedef __u64 u64;
|
||||
typedef __u32 u32;
|
||||
|
||||
enum nd_pfn_mode {
|
||||
PFN_MODE_NONE,
|
||||
PFN_MODE_RAM,
|
||||
PFN_MODE_PMEM,
|
||||
};
|
||||
|
||||
struct nd_pfn_sb {
|
||||
u8 signature[PFN_SIG_LEN];
|
||||
u8 uuid[16];
|
||||
u8 parent_uuid[16];
|
||||
__le32 flags;
|
||||
__le16 version_major;
|
||||
__le16 version_minor;
|
||||
__le64 dataoff; /* relative to namespace_base + start_pad */
|
||||
__le64 npfns;
|
||||
__le32 mode;
|
||||
/* minor-version-1 additions for section alignment */
|
||||
__le32 start_pad;
|
||||
__le32 end_trunc;
|
||||
/* minor-version-2 record the base alignment of the mapping */
|
||||
__le32 align;
|
||||
u8 padding[4000];
|
||||
__le64 checksum;
|
||||
};
|
||||
|
||||
struct nd_gen_sb {
|
||||
char reserved[SZ_4K - 8];
|
||||
__le64 checksum;
|
||||
};
|
||||
|
||||
|
||||
u64 nd_fletcher64(void *addr, size_t len, bool le)
|
||||
{
|
||||
u32 *buf = addr;
|
||||
u32 lo32 = 0;
|
||||
u64 hi32 = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len / sizeof(u32); i++) {
|
||||
lo32 += le ? __le32_to_cpu((__le32) buf[i]) : buf[i];
|
||||
hi32 += lo32;
|
||||
}
|
||||
|
||||
return hi32 << 32 | lo32;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* nd_sb_checksum: compute checksum for a generic info block
|
||||
*
|
||||
* Returns a fletcher64 checksum of everything in the given info block
|
||||
* except the last field (since that's where the checksum lives).
|
||||
*/
|
||||
u64 nd_sb_checksum(struct nd_gen_sb *nd_gen_sb)
|
||||
{
|
||||
u64 sum;
|
||||
__le64 sum_save;
|
||||
|
||||
sum_save = nd_gen_sb->checksum;
|
||||
nd_gen_sb->checksum = 0;
|
||||
sum = nd_fletcher64(nd_gen_sb, sizeof(*nd_gen_sb), 1);
|
||||
nd_gen_sb->checksum = sum_save;
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
void show_usage(const char* name) {
|
||||
printf("Usage: %s IMAGE_FILE DATA_OFFSET ALIGNMENT\n", name);
|
||||
printf("DATA_OFFSET and ALIGNMENT must be in bytes\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 4) {
|
||||
show_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* img_path = argv[1];
|
||||
|
||||
char *ptr = NULL;
|
||||
const long int data_offset = strtol(argv[2], &ptr, 10);
|
||||
if (ptr == argv[2]) {
|
||||
fprintf(stderr, "Couldn't convert string '%s' to int\n", argv[2]);
|
||||
show_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = NULL;
|
||||
const long int alignment = strtol(argv[3], &ptr, 10);
|
||||
if (ptr == argv[3]) {
|
||||
fprintf(stderr, "Couldn't convert string '%s' to int\n", argv[3]);
|
||||
show_usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Opening file '%s'\n", img_path);
|
||||
int fd = open(img_path, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
perror("open:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct nd_pfn_sb sb = { 0 };
|
||||
|
||||
snprintf((char*)sb.signature, PFN_SIG_LEN, PFN_SIG);
|
||||
sb.mode = PFN_MODE_RAM;
|
||||
sb.align = alignment;
|
||||
sb.dataoff = data_offset;
|
||||
sb.version_minor = 2;
|
||||
|
||||
// checksum must be calculated at the end
|
||||
sb.checksum = nd_sb_checksum((struct nd_gen_sb*) &sb);
|
||||
|
||||
// NVDIMM driver: SZ_4K is the namespace-relative starting offset
|
||||
int ret = lseek(fd, SZ_4K, SEEK_SET);
|
||||
if (ret == -1) {
|
||||
perror("lseek: ");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Writing metadata\n");
|
||||
ret = write(fd, &sb, sizeof(sb));
|
||||
if (ret == -1) {
|
||||
perror("write: ");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
printf("OK!\n");
|
||||
|
||||
return 0;
|
||||
}
|
25
tools/osbuilder/initrd-builder/README.md
Normal file
25
tools/osbuilder/initrd-builder/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
* [Creating a guest OS initrd image](#creating-a-guest-os-initrd-image)
|
||||
* [Further information](#further-information)
|
||||
|
||||
# Kata Containers initrd image generation
|
||||
|
||||
A Kata Containers initrd image is generated using the `initrd_builder.sh` script.
|
||||
This script uses a rootfs directory created by the `rootfs-builder/rootfs.sh` script.
|
||||
|
||||
## Creating a guest OS initrd image
|
||||
|
||||
To create a guest OS initrd image run:
|
||||
|
||||
```
|
||||
$ sudo ./initrd_builder.sh path/to/rootfs
|
||||
```
|
||||
|
||||
The `rootfs.sh` script populates the `path/to/rootfs` directory.
|
||||
|
||||
## Further information
|
||||
|
||||
For more information on how to use the `initrd_builder.sh` script, run:
|
||||
|
||||
```
|
||||
$ ./initrd_builder.sh -h
|
||||
```
|
77
tools/osbuilder/initrd-builder/initrd_builder.sh
Executable file
77
tools/osbuilder/initrd-builder/initrd_builder.sh
Executable file
@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2018 HyperHQ Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -e
|
||||
|
||||
[ -n "$DEBUG" ] && set -x
|
||||
|
||||
script_name="${0##*/}"
|
||||
script_dir="$(dirname $(readlink -f $0))"
|
||||
|
||||
lib_file="${script_dir}/../scripts/lib.sh"
|
||||
source "$lib_file"
|
||||
|
||||
INITRD_IMAGE="${INITRD_IMAGE:-kata-containers-initrd.img}"
|
||||
AGENT_BIN=${AGENT_BIN:-kata-agent}
|
||||
AGENT_INIT=${AGENT_INIT:-no}
|
||||
|
||||
usage()
|
||||
{
|
||||
error="${1:-0}"
|
||||
cat <<EOT
|
||||
Usage: ${script_name} [options] <rootfs-dir>
|
||||
This script creates a Kata Containers initrd image file based on the
|
||||
<rootfs-dir> directory.
|
||||
|
||||
Options:
|
||||
-h Show help
|
||||
-o Set the path where the generated image file is stored.
|
||||
DEFAULT: the path stored in the environment variable INITRD_IMAGE
|
||||
|
||||
Extra environment variables:
|
||||
AGENT_BIN: use it to change the expected agent binary name
|
||||
DEFAULT: kata-agent
|
||||
AGENT_INIT: use kata agent as init process
|
||||
DEFAULT: no
|
||||
EOT
|
||||
exit "${error}"
|
||||
}
|
||||
|
||||
while getopts "ho:" opt
|
||||
do
|
||||
case "$opt" in
|
||||
h) usage ;;
|
||||
o) INITRD_IMAGE="${OPTARG}" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
ROOTFS="$1"
|
||||
|
||||
|
||||
[ -n "${ROOTFS}" ] || usage
|
||||
[ -d "${ROOTFS}" ] || die "${ROOTFS} is not a directory"
|
||||
|
||||
ROOTFS=$(readlink -f ${ROOTFS})
|
||||
IMAGE_DIR=$(dirname ${INITRD_IMAGE})
|
||||
IMAGE_DIR=$(readlink -f ${IMAGE_DIR})
|
||||
IMAGE_NAME=$(basename ${INITRD_IMAGE})
|
||||
|
||||
# The kata rootfs image expects init to be installed
|
||||
init="${ROOTFS}/sbin/init"
|
||||
[ -x "${init}" ] || [ -L ${init} ] || die "/sbin/init is not installed in ${ROOTFS}"
|
||||
OK "init is installed"
|
||||
[ "${AGENT_INIT}" == "yes" ] || [ -x "${ROOTFS}/usr/bin/${AGENT_BIN}" ] || \
|
||||
die "/usr/bin/${AGENT_BIN} is not installed in ${ROOTFS}
|
||||
use AGENT_BIN env variable to change the expected agent binary name"
|
||||
OK "Agent is installed"
|
||||
|
||||
# initramfs expects /init
|
||||
ln -sf /sbin/init "${ROOTFS}/init"
|
||||
|
||||
info "Creating ${IMAGE_DIR}/${IMAGE_NAME} based on rootfs at ${ROOTFS}"
|
||||
( cd "${ROOTFS}" && find . | cpio -H newc -o | gzip -9 ) > "${IMAGE_DIR}"/"${IMAGE_NAME}"
|
1
tools/osbuilder/rootfs-builder/.gitignore
vendored
Normal file
1
tools/osbuilder/rootfs-builder/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
Dockerfile
|
212
tools/osbuilder/rootfs-builder/README.md
Normal file
212
tools/osbuilder/rootfs-builder/README.md
Normal file
@ -0,0 +1,212 @@
|
||||
* [Building a Guest OS rootfs for Kata Containers](#building-a-guest-os-rootfs-for-kata-containers)
|
||||
* [Supported base OSs](#supported-base-oss)
|
||||
* [Extra features](#extra-features)
|
||||
* [Supported distributions list](#supported-distributions-list)
|
||||
* [Generate Kata specific files](#generate-kata-specific-files)
|
||||
* [Rootfs requirements](#rootfs-requirements)
|
||||
* [Creating a rootfs](#creating-a-rootfs)
|
||||
* [Creating a rootfs with kernel modules](#creating-a-rootfs-with-kernel-modules)
|
||||
* [Build a rootfs using Docker](#build-a-rootfs-using-docker)
|
||||
* [Adding support for a new guest OS](#adding-support-for-a-new-guest-os)
|
||||
* [Create template files](#create-template-files)
|
||||
* [Modify template files](#modify-template-files)
|
||||
* [Expected rootfs directory content](#expected-rootfs-directory-content)
|
||||
* [Optional - Customize the rootfs](#optional---customize-the-rootfs)
|
||||
* [Adding extra packages](#adding-extra-packages)
|
||||
* [Arbitrary rootfs changes](#arbitrary-rootfs-changes)
|
||||
|
||||
# Building a Guest OS rootfs for Kata Containers
|
||||
|
||||
The Kata Containers rootfs is created using the `rootfs.sh` script.
|
||||
|
||||
## Supported base OSs
|
||||
|
||||
The `rootfs.sh` script builds a rootfs based on a particular Linux\*
|
||||
distribution. The script supports multiple distributions and can be extended
|
||||
to add further ones.
|
||||
|
||||
### Extra features
|
||||
|
||||
#### Supported distributions list
|
||||
|
||||
List the supported distributions by running the following:
|
||||
```
|
||||
$ ./rootfs.sh -l
|
||||
```
|
||||
|
||||
#### Generate Kata specific files
|
||||
The `rootfs.sh` script can be used to populate a directory with only Kata specific files and
|
||||
components, without creating a full usable rootfs.
|
||||
This feature is used to create a rootfs based on a distribution not officially
|
||||
supported by osbuilder, and when building an image using the dracut build method.
|
||||
|
||||
To achieve this, simply invoke `rootfs.sh` without specifying a target rootfs, e.g.:
|
||||
```
|
||||
$ mkdir kata-overlay
|
||||
$ ./rootfs.sh -r "$PWD/kata-overlay"
|
||||
```
|
||||
|
||||
## Rootfs requirements
|
||||
|
||||
The rootfs must provide at least the following components:
|
||||
|
||||
- [Kata agent](https://github.com/kata-containers/agent)
|
||||
|
||||
Path: `/bin/kata-agent` - Kata Containers guest.
|
||||
|
||||
- An `init` system (e.g. `systemd`) to start the Kata agent
|
||||
when the guest OS boots.
|
||||
|
||||
Path: `/sbin/init` - init binary called by the kernel.
|
||||
|
||||
When the `AGENT_INIT` environment variable is set to `yes`, use Kata agent as `/sbin/init`.
|
||||
|
||||
> **Note**: `AGENT_INIT=yes` **must** be used for the Alpine distribution
|
||||
> since it does not use `systemd` as its init daemon.
|
||||
|
||||
## Creating a rootfs
|
||||
|
||||
To build a rootfs for your chosen distribution, run:
|
||||
|
||||
```
|
||||
$ sudo ./rootfs.sh <distro>
|
||||
```
|
||||
|
||||
## Creating a rootfs with kernel modules
|
||||
|
||||
To build a rootfs with additional kernel modules, run:
|
||||
```
|
||||
$ sudo KERNEL_MODULES_DIR=${kernel_mod_dir} ./rootfs.sh <distro>
|
||||
```
|
||||
Where `kernel_mod_dir` points to the kernel modules directory to be put under the
|
||||
`/lib/modules/` directory of the created rootfs.
|
||||
|
||||
## Build a rootfs using Docker
|
||||
|
||||
Depending on the base OS to build the rootfs guest OS, it is required some
|
||||
specific programs that probably are not available or installed in the system
|
||||
that will build the guest image. For this case `rootfs.sh` can use
|
||||
a Docker\* container to build the rootfs. The following requirements
|
||||
must be met:
|
||||
|
||||
1. Docker 1.12+ installed.
|
||||
|
||||
2. `runc` is configured as the default runtime.
|
||||
|
||||
To check if `runc` is the default runtime:
|
||||
|
||||
```
|
||||
$ docker info | grep 'Default Runtime: runc'
|
||||
```
|
||||
|
||||
Note:
|
||||
|
||||
This requirement is specific to the Clear Containers runtime.
|
||||
See [issue](https://github.com/clearcontainers/runtime/issues/828) for
|
||||
more information.
|
||||
|
||||
3. Export `USE_DOCKER` variable.
|
||||
|
||||
```
|
||||
$ export USE_DOCKER=true
|
||||
```
|
||||
|
||||
4. Use `rootfs.sh`:
|
||||
|
||||
Example:
|
||||
```
|
||||
$ export USE_DOCKER=true
|
||||
$ # build guest O/S rootfs based on fedora
|
||||
$ ./rootfs-builder/rootfs.sh -r "${PWD}/fedora_rootfs" fedora
|
||||
$ # build image based rootfs created above
|
||||
$ ./image-builder/image_builder.sh "${PWD}/fedora_rootfs"
|
||||
```
|
||||
|
||||
## Adding support for a new guest OS
|
||||
|
||||
The `rootfs.sh` script will check for immediate sub-directories
|
||||
containing the following expected files:
|
||||
|
||||
- A `bash(1)` script called `config.sh`
|
||||
|
||||
This represents the specific configuration for `<distro>`. It must
|
||||
provide configuration specific variables for the user to modify as needed.
|
||||
The `config.sh` file will be loaded before executing `build_rootfs()` to
|
||||
provide all the needed configuration to the function.
|
||||
|
||||
Path: `rootfs-builder/<distro>/config.sh`.
|
||||
|
||||
- (OPTIONAL) A `bash(1)` script called `rootfs_lib.sh`
|
||||
|
||||
This file must contain a function called `build_rootfs()`, which must
|
||||
receive the path to where the rootfs is created, as its first argument.
|
||||
Normally, this file is needed if a new distro with a special requirement
|
||||
is needed. This function will override the `build_rootfs()` function in
|
||||
`scripts/lib.sh`.
|
||||
|
||||
Path: `rootfs-builder/<distro>/rootfs_lib.sh`.
|
||||
|
||||
### Create template files
|
||||
|
||||
To create a directory with the expected file structure run:
|
||||
|
||||
```
|
||||
$ make -f template/Makefile ROOTFS_BASE_NAME=my_new_awesome_rootfs
|
||||
```
|
||||
|
||||
After running the previous command, a new directory is created in
|
||||
`rootfs-builder/my_new_awesome_rootfs/`.
|
||||
|
||||
|
||||
To verify the directory can be used to build a rootfs, run `./rootfs.sh -h`.
|
||||
Running this script shows `my_new_awesome_rootfs` as one of the options for
|
||||
use. To use the new guest OS, follow the instructions in [Creating a rootfs](#creating-a-rootfs).
|
||||
|
||||
### Modify template files
|
||||
|
||||
After the new directory structure is created:
|
||||
|
||||
- If needed, add configuration variables to
|
||||
`rootfs-builder/my_new_awesome_rootfs/config.sh`.
|
||||
|
||||
- Implement the stub `build_rootfs()` function from
|
||||
`rootfs-builder/my_new_awesome_rootfs/rootfs_lib.sh`.
|
||||
|
||||
### Expected rootfs directory content
|
||||
|
||||
After the function `build_rootfs` is called, the script expects the
|
||||
rootfs directory to contain `/sbin/init` and `/sbin/kata-agent` binaries.
|
||||
|
||||
### Optional - Customize the rootfs
|
||||
|
||||
For particular use cases developers might want to modify the guest OS.
|
||||
|
||||
#### Adding extra packages
|
||||
|
||||
To add additional packages, use one of the following methods:
|
||||
|
||||
- Use the environment variable `EXTRA_PKGS` to provide a list of space-separated
|
||||
packages to install.
|
||||
|
||||
Note:
|
||||
|
||||
The package names might vary among Linux distributions, the extra
|
||||
package names must exist in the base OS flavor you use to build the
|
||||
rootfs from.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
$ EXTRA_PKGS="vim emacs" ./rootfs-builder/rootfs.sh -r ${PWD}/myrootfs fedora
|
||||
```
|
||||
|
||||
- Modify the variable `PACKAGES` in `rootfs-builder/<distro>/config.sh`.
|
||||
|
||||
This variable specifies the minimal set of packages needed. The
|
||||
configuration file must use the package names from the distro for which they
|
||||
were created.
|
||||
|
||||
#### Arbitrary rootfs changes
|
||||
|
||||
Once the rootfs directory is created, you can add and remove files as
|
||||
needed. Changes affect the files included in the final guest image.
|
41
tools/osbuilder/rootfs-builder/alpine/Dockerfile.in
Normal file
41
tools/osbuilder/rootfs-builder/alpine/Dockerfile.in
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (c) 2018 HyperHQ Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
From docker.io/golang:@GO_VERSION@-alpine
|
||||
|
||||
RUN apk update && apk add \
|
||||
apk-tools-static \
|
||||
autoconf \
|
||||
automake \
|
||||
bash \
|
||||
binutils \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
libc-dev \
|
||||
libseccomp \
|
||||
libseccomp-dev \
|
||||
linux-headers \
|
||||
m4 \
|
||||
make \
|
||||
musl \
|
||||
musl-dev \
|
||||
tar \
|
||||
vim
|
||||
# alpine doesn't support x86_64-unknown-linux-gnu
|
||||
# It only support x86_64-unknown-linux-musl. Even worse,
|
||||
# it doesn't support proc-macro, which is needed for serde_derive
|
||||
#
|
||||
# See issue: https://github.com/kata-containers/osbuilder/issues/386
|
||||
# -- FIXME
|
||||
#
|
||||
# Thus, we cannot build rust agent on alpine
|
||||
# The way to use alpine is to generate rootfs or build
|
||||
# go agent to get rootfs and then cp rust agent to rootfs.
|
||||
# pity..
|
||||
# RUN ln -svf /usr/bin/gcc /bin/musl-gcc; ln -svf /usr/bin/g++ /bin/musl-g++
|
26
tools/osbuilder/rootfs-builder/alpine/config.sh
Normal file
26
tools/osbuilder/rootfs-builder/alpine/config.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
OS_NAME="Alpine"
|
||||
|
||||
OS_VERSION=${OS_VERSION:-latest-stable}
|
||||
|
||||
BASE_PACKAGES="alpine-base"
|
||||
|
||||
# Alpine mirror to use
|
||||
# See a list of mirrors at http://nl.alpinelinux.org/alpine/MIRRORS.txt
|
||||
MIRROR=http://dl-5.alpinelinux.org/alpine
|
||||
|
||||
# Mandatory Packages that must be installed
|
||||
# - iptables: Need by Kata agent
|
||||
PACKAGES="iptables"
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=kata-agent
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=()
|
||||
|
||||
[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp" || true
|
44
tools/osbuilder/rootfs-builder/alpine/rootfs_lib.sh
Normal file
44
tools/osbuilder/rootfs-builder/alpine/rootfs_lib.sh
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2018 HyperHQ Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# - Arguments
|
||||
# rootfs_dir=$1
|
||||
#
|
||||
# - Optional environment variables
|
||||
#
|
||||
# EXTRA_PKGS: Variable to add extra PKGS provided by the user
|
||||
#
|
||||
# BIN_AGENT: Name of the Kata-Agent binary
|
||||
#
|
||||
# Any other configuration variable for a specific distro must be added
|
||||
# and documented on its own config.sh
|
||||
#
|
||||
# - Expected result
|
||||
#
|
||||
# rootfs_dir populated with rootfs pkgs
|
||||
# It must provide a binary in /sbin/init
|
||||
build_rootfs() {
|
||||
# Mandatory
|
||||
local ROOTFS_DIR=$1
|
||||
|
||||
# In case of support EXTRA packages, use it to allow
|
||||
# users add more packages to the base rootfs
|
||||
local EXTRA_PKGS=${EXTRA_PKGS:-}
|
||||
|
||||
# Populate ROOTFS_DIR
|
||||
check_root
|
||||
mkdir -p "${ROOTFS_DIR}"
|
||||
|
||||
/sbin/apk.static \
|
||||
-X ${MIRROR}/${OS_VERSION}/main \
|
||||
-U \
|
||||
--allow-untrusted \
|
||||
--root ${ROOTFS_DIR}\
|
||||
--initdb add ${BASE_PACKAGES} ${EXTRA_PKGS} ${PACKAGES}
|
||||
|
||||
mkdir -p ${ROOTFS_DIR}{/root,/etc/apk,/proc}
|
||||
echo "${MIRROR}/${OS_VERSION}/main" > ${ROOTFS_DIR}/etc/apk/repositories
|
||||
}
|
41
tools/osbuilder/rootfs-builder/centos/Dockerfile.in
Normal file
41
tools/osbuilder/rootfs-builder/centos/Dockerfile.in
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
From docker.io/centos:@OS_VERSION@
|
||||
|
||||
@SET_PROXY@
|
||||
|
||||
RUN yum -y update && yum install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
chrony \
|
||||
coreutils \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git \
|
||||
glibc-common \
|
||||
glibc-devel \
|
||||
glibc-headers \
|
||||
glibc-static \
|
||||
glibc-utils \
|
||||
libseccomp \
|
||||
libseccomp-devel \
|
||||
libstdc++-devel \
|
||||
libstdc++-static \
|
||||
m4 \
|
||||
make \
|
||||
sed \
|
||||
tar \
|
||||
vim \
|
||||
which
|
||||
|
||||
# install cmake because centos7's cmake is too old
|
||||
@INSTALL_CMAKE@
|
||||
@INSTALL_MUSL@
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
38
tools/osbuilder/rootfs-builder/centos/config.sh
Normal file
38
tools/osbuilder/rootfs-builder/centos/config.sh
Normal file
@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
OS_NAME="Centos"
|
||||
|
||||
OS_VERSION=${OS_VERSION:-7}
|
||||
|
||||
LOG_FILE="/var/log/yum-centos.log"
|
||||
|
||||
MIRROR_LIST="http://mirrorlist.centos.org/?release=${OS_VERSION}&arch=${ARCH}&repo=os&container=container"
|
||||
|
||||
# Aditional Repos
|
||||
CENTOS_UPDATES_MIRROR_LIST="http://mirrorlist.centos.org/?release=${OS_VERSION}&arch=${ARCH}&repo=updates&container=container"
|
||||
|
||||
CENTOS_EXTRAS_MIRROR_LIST="http://mirrorlist.centos.org/?release=${OS_VERSION}&arch=${ARCH}&repo=extras&container=container"
|
||||
|
||||
CENTOS_PLUS_MIRROR_LIST="http://mirrorlist.centos.org/?release=${OS_VERSION}&arch=${ARCH}&repo=centosplus&container=container"
|
||||
|
||||
GPG_KEY_URL="https://www.centos.org/keys/RPM-GPG-KEY-CentOS-7"
|
||||
|
||||
GPG_KEY_FILE="RPM-GPG-KEY-CentOS-7"
|
||||
|
||||
PACKAGES="iptables chrony"
|
||||
|
||||
#Optional packages:
|
||||
# systemd: An init system that will start kata-agent if kata-agent
|
||||
# itself is not configured as init process.
|
||||
[ "$AGENT_INIT" == "no" ] && PACKAGES+=" systemd" || true
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=()
|
||||
|
||||
[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp" || true
|
18
tools/osbuilder/rootfs-builder/centos/config_aarch64.sh
Normal file
18
tools/osbuilder/rootfs-builder/centos/config_aarch64.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright (c) 2018 ARM Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Base Repos
|
||||
BASE_URL="http://mirror.centos.org/altarch/${OS_VERSION}/os/${ARCH}/"
|
||||
|
||||
# Additional Repos
|
||||
CENTOS_UPDATES_URL="http://mirror.centos.org/altarch/${OS_VERSION}/updates/${ARCH}/"
|
||||
|
||||
CENTOS_EXTRAS_URL="http://mirror.centos.org/altarch/${OS_VERSION}/extras/${ARCH}/"
|
||||
|
||||
CENTOS_PLUS_URL="http://mirror.centos.org/altarch/${OS_VERSION}/centosplus/${ARCH}/"
|
||||
|
||||
GPG_KEY_ARCH_URL="http://mirror.centos.org/altarch/7/os/aarch64/RPM-GPG-KEY-CentOS-7-aarch64"
|
||||
|
||||
GPG_KEY_ARCH_FILE="RPM-GPG-KEY-CentOS-7-aarch64"
|
18
tools/osbuilder/rootfs-builder/centos/config_ppc64le.sh
Normal file
18
tools/osbuilder/rootfs-builder/centos/config_ppc64le.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright (c) 2018 IBM
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Base Repos
|
||||
BASE_URL="http://mirror.centos.org/altarch/${OS_VERSION}/os/${ARCH}/"
|
||||
|
||||
# Additional Repos
|
||||
CENTOS_UPDATES_URL="http://mirror.centos.org/altarch/${OS_VERSION}/updates/${ARCH}/"
|
||||
|
||||
CENTOS_EXTRAS_URL="http://mirror.centos.org/altarch/${OS_VERSION}/extras/${ARCH}/"
|
||||
|
||||
CENTOS_PLUS_URL="http://mirror.centos.org/altarch/${OS_VERSION}/centosplus/${ARCH}/"
|
||||
|
||||
GPG_KEY_ARCH_URL="http://mirror.centos.org/altarch/7/os/ppc64le/RPM-GPG-KEY-CentOS-SIG-AltArch-7-ppc64le"
|
||||
|
||||
GPG_KEY_ARCH_FILE="RPM-GPG-KEY-CentOS-SIG-AltArch-7-ppc64le"
|
43
tools/osbuilder/rootfs-builder/clearlinux/Dockerfile.in
Normal file
43
tools/osbuilder/rootfs-builder/clearlinux/Dockerfile.in
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
From docker.io/fedora:30
|
||||
|
||||
@SET_PROXY@
|
||||
|
||||
RUN dnf -y update && dnf install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
chrony \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git \
|
||||
glibc-common \
|
||||
glibc-devel \
|
||||
glibc-headers \
|
||||
glibc-static \
|
||||
glibc-utils \
|
||||
libseccomp \
|
||||
libseccomp-devel \
|
||||
libstdc++-devel \
|
||||
libstdc++-static \
|
||||
m4 \
|
||||
make \
|
||||
pkgconfig \
|
||||
sed \
|
||||
systemd \
|
||||
tar \
|
||||
vim \
|
||||
which
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_MUSL@
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
31
tools/osbuilder/rootfs-builder/clearlinux/config.sh
Normal file
31
tools/osbuilder/rootfs-builder/clearlinux/config.sh
Normal file
@ -0,0 +1,31 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
OS_NAME="Clear"
|
||||
REPO_NAME="clear"
|
||||
|
||||
OS_VERSION=${OS_VERSION:-latest}
|
||||
|
||||
clr_url="https://download.clearlinux.org"
|
||||
|
||||
# resolve version
|
||||
[ "${OS_VERSION}" = "latest" ] && OS_VERSION=$(curl -sL "${clr_url}/latest")
|
||||
|
||||
BASE_URL="${clr_url}/releases/${OS_VERSION}/${REPO_NAME}/${ARCH}/os/"
|
||||
|
||||
PACKAGES="libudev0-shim kmod-bin"
|
||||
|
||||
#Optional packages:
|
||||
# systemd: An init system that will start kata-agent if kata-agent
|
||||
# itself is not configured as init process.
|
||||
[ "$AGENT_INIT" == "no" ] && PACKAGES+=" systemd chrony iptables-bin util-linux-bin" || true
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=( aarch64 ppc64le s390x )
|
||||
|
||||
[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp" || true
|
35
tools/osbuilder/rootfs-builder/debian/Dockerfile-aarch64.in
Normal file
35
tools/osbuilder/rootfs-builder/debian/Dockerfile-aarch64.in
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (c) 2020 ARM Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# NOTE: OS_VERSION is set according to config.sh
|
||||
from docker.io/debian:@OS_VERSION@
|
||||
|
||||
# RUN commands
|
||||
RUN apt-get update && apt-get install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
build-essential \
|
||||
chrony \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
debianutils \
|
||||
debootstrap \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
libc-dev \
|
||||
libstdc++-6-dev \
|
||||
m4 \
|
||||
make \
|
||||
sed \
|
||||
systemd \
|
||||
tar \
|
||||
vim
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
||||
@INSTALL_MUSL@
|
||||
@INSTALL_RUST@
|
41
tools/osbuilder/rootfs-builder/debian/Dockerfile.in
Normal file
41
tools/osbuilder/rootfs-builder/debian/Dockerfile.in
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# NOTE: OS_VERSION is set according to config.sh
|
||||
from docker.io/debian:@OS_VERSION@
|
||||
|
||||
# RUN commands
|
||||
RUN apt-get update && apt-get --no-install-recommends install -y \
|
||||
apt-utils \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
chrony \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
debianutils \
|
||||
debootstrap \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
libc-dev \
|
||||
libstdc++-6-dev \
|
||||
m4 \
|
||||
make \
|
||||
musl \
|
||||
musl-dev \
|
||||
musl-tools \
|
||||
sed \
|
||||
systemd \
|
||||
tar \
|
||||
vim \
|
||||
wget
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
20
tools/osbuilder/rootfs-builder/debian/config.sh
Normal file
20
tools/osbuilder/rootfs-builder/debian/config.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
OS_VERSION=${OS_VERSION:-9.5}
|
||||
|
||||
# Set OS_NAME to the desired debian "codename"
|
||||
OS_NAME=${OS_NAME:-"stretch"}
|
||||
|
||||
PACKAGES="systemd iptables init chrony kmod"
|
||||
|
||||
# NOTE: Re-using ubuntu rootfs configuration, see 'ubuntu' folder for full content.
|
||||
source $script_dir/ubuntu/$CONFIG_SH
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=()
|
7
tools/osbuilder/rootfs-builder/debian/rootfs_lib.sh
Normal file
7
tools/osbuilder/rootfs-builder/debian/rootfs_lib.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# NOTE: Re-using ubuntu rootfs lib, see 'ubuntu' folder for details.
|
||||
source ${script_dir}/ubuntu/$LIB_SH
|
46
tools/osbuilder/rootfs-builder/euleros/Dockerfile.in
Normal file
46
tools/osbuilder/rootfs-builder/euleros/Dockerfile.in
Normal file
@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (C) 2018 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM docker.io/euleros:@OS_VERSION@
|
||||
|
||||
@SET_PROXY@
|
||||
|
||||
RUN yum -y update && yum install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
chrony \
|
||||
coreutils \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git \
|
||||
glibc-common \
|
||||
glibc-devel \
|
||||
glibc-headers \
|
||||
glibc-static \
|
||||
glibc-utils \
|
||||
libstdc++-devel \
|
||||
libstdc++-static \
|
||||
m4 \
|
||||
make \
|
||||
sed \
|
||||
tar \
|
||||
vim \
|
||||
which \
|
||||
yum
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
||||
|
||||
# several problems prevent us from building rust agent on euleros
|
||||
# 1. There is no libstdc++.a. copy one from somewhere get through
|
||||
# compilation
|
||||
# 2. The kernel (3.10.x) is too old, kernel-headers pacakge
|
||||
# has no vm_socket.h because kernel has no vsock support or
|
||||
# vsock header files
|
||||
|
||||
# We will disable rust agent build in rootfs.sh for euleros
|
||||
# and alpine(musl cannot support proc-macro)
|
52
tools/osbuilder/rootfs-builder/euleros/RPM-GPG-KEY-EulerOS
Normal file
52
tools/osbuilder/rootfs-builder/euleros/RPM-GPG-KEY-EulerOS
Normal file
@ -0,0 +1,52 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v2
|
||||
|
||||
mQINBFhFFc8BEADu77vsD7rA1zCTreI9Ex9dIbWWR0Ntu4e7OL+VSIxXserWron2
|
||||
kTHagPIrDGtFqWTQgbt4tpjJ8vOAMzCADYq2eNRbEbUL/TOGfYk5Lgfo0P7F5Slr
|
||||
dXNow2HrZhxehTwRSvseQg9Yrx2LVXDgr8wAMLldnkCSa0iyAE90ehDLOUaf2Lal
|
||||
c99p+4tw8GhWP7C41pX4ywLrJ1FXodFTpg+I7p9EW5zt5mZhwX7NkhdoISnNAA6L
|
||||
R5NA+6G8rCC1fdTGfqYPfNGrO9DBSZNfunWZsN+kYo4ac3GbZkdnh3LA2YCW4yiA
|
||||
u5AoPv1UIkFMLh0KoJDxOORMkxI++3qFAIzShtMRAQencsM85bzdXNmk3VE+nY9V
|
||||
J0BHCLMELtr/o6b+e5ak3qcG1sMFBEMn367/k6suIpTF5sEszQScWeqbhdeFmXt6
|
||||
mur2z6zDwwa5Y4n0x9Lsz50PxgkDrHXxeoLO5ByE8iTJqxhYSl0hb/bhSmBaYXnW
|
||||
JiqtoLbYW/isgZ8OW414P2ZUwgByA9O4Tso37oEU69ycrxFVI63M5xUGkchI+HBo
|
||||
VB9XZ7QzjU8SGoelj5YtjV7og974dcXC4NwUTnhJW3pd3MfiA3C96voCN/ozjzpg
|
||||
uJGg0vzuTUcHAIMhujWPWCb0YN6fr5z+7Et8yqPv4qt3fgaxdVO5qQds1wARAQAB
|
||||
tC5FdWxlck9TIChFdWxlck9TIDIuMCBTUDIpIDxFdWxlck9TQGh1YXdlaS5jb20+
|
||||
iQI/BBMBAgApBQJYRRXPAhsDBQkJZgGABwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC
|
||||
F4AACgkQYAMXvDgdesNPCxAAh7huw08/oFHpCSN9dYd/YlFfCs/+wb2KUqZZ2yIK
|
||||
SSpmRmQiQdJRUiJly69WZL4H2NYCw3MQiV8Q433err3iQXMjumfl5hq2KplMgsAQ
|
||||
sraOreJPeN1687rzEV9eDjuKV7btd2VaSyiMIaAFaWjoxl6E77x8ifNbXcnTHk+5
|
||||
39BCRn3WsSXbQKWolFEvwNr/SYzGIIdtmrlZSog/vAKPqzTsJDj/Qsf/0Uec1iCX
|
||||
6pnZwMrQTlc+nnnAp9bMVla39uWGwyhhicTsokElm/4wD+OaLF2xz3gWk3l3fHjh
|
||||
V8PtzhQxpHlyqR7pOvG5eun9VsBeWwH6TcHU1B+cPi4SmQcflvJCV/XCTTcK6Z1i
|
||||
/35cmZdwCoDnM+Aadfywfoaliy5rnsvvMSljI+hw8gX3NACIDd2RBPmER3wknZw6
|
||||
bIpm0vtlaG1fcCio0kFo9CplLYbYHtx9Y7Icln3O3keODlR+rc8HI5X0YPkLa9Fs
|
||||
mqP0fN2PGcEPm7CjoEdFdfOJn+1TvR7T1cnBiso5hLcMPtX8b6vzvIrFy5OKq90N
|
||||
LYjgdn8LMmE6Gi/LA6yEBB958vGS5kAQI3HvCmw9vBeGdVZ+QXjmeVN6Vp9bEnBS
|
||||
3oZbUXzo3CpeGxvj7+8s8j6MMvDLPLIdxXWi1ZTJkZFa+ElvZMG34SI/kSHHdSSO
|
||||
gRG5Ag0EWEUVzwEQANBn+RzOAOl8OVPBtmDRIC/G7yssy7Q3ZGWUDIxs2NNk2oBH
|
||||
9RsCm+vYeQkScloed+Cv6dkQvCPiFk+VtlLeSl0ugmvjNjZknuMhbgiC1ObR2SmV
|
||||
uNpT3qMaNQQBJg0tJGU/1hLHDqjj2TGvj+WJDfzRoVie1dHq6bnogOErEXvKGmNZ
|
||||
/cDuvmeURmFqx/+cwim2QFc95hcylBXRhnTnGblgxjzYXnXbIMvtCNz3Nnd1yT3P
|
||||
9Z+h7Mwk746UEK2R1EgpVzZa9YF/mg2NRwBFuuJ4yP0MxmzP1AMgqQSp7XrMP6KG
|
||||
6RbmDymrTHFTkP/lI3qZ1bgNB64bq/Eq1J3qgukEDN8JZKMiG+/vAg3lkPQwn3Uy
|
||||
8IfBCqVrF0/dg+kJesgEMs6T+CsINWQ/SEPYHT/6LGytr+4MgDVqI1wxII8gBZzk
|
||||
FHohleNRWvKKGLphECO7NwgrDFwWlIsT46d1Hga0uHNDSg1mczU2swYHD7/j1HQE
|
||||
McByTVuzUjT/eAxmbN+DZ4cGBccqMP8RkZfBpalhB5lyjnIN2tMJ3y3yZrpmJkU1
|
||||
LaetdFqwycMmV7Mmi2dEdqumnmKhSZqyJ1ShuSm9pEBxahwJGdhtC6Id7iwzZ3uJ
|
||||
53nhO7hvGC0gt3w0frX0TcvT7aFa4ZsgaJxUJy0MKDPZmv/3hYKpH/QkLiu7ABEB
|
||||
AAGJAiUEGAECAA8FAlhFFc8CGwwFCQlmAYAACgkQYAMXvDgdesO+fw//bQImNhW0
|
||||
ZwG5FG7oP+KPgmma2+N/JnzemqEUzjRTIiEN4LCj8qvJ/aKYZJkfUcKvP4kpVW66
|
||||
+tlJ11Ie9Bnkqm3GdT1nkWDghzTK7/x6ktRwyuowmEYh01fW3bybB0RcQOJzGnMK
|
||||
umnNzd4VUdMGwdbg/sQnKc6lMU9+hz/tCOU9Ok6Ps384gRXjmRQ+J9EFHq14kXtP
|
||||
Xy584MD1+OBsPwlMViAAjV9L3pxtS1JoFplNPYogbBOKHdImS3dNOMLwV3dHAf1d
|
||||
l0MqgMEabLBQusx2q7CUw4xBi5EJJtnos9bJvGSCplDyjlshDiY7wxcFLLb90VWs
|
||||
TnJVbDswCjsdVi5x8eyPplygGxgt9Qg2XNYN5EgN9MLbmbC7Mi7oRf1E7QMLuuQ+
|
||||
+lkTb1rAe4YewwwAZHao4zGJelNXmSPN8u8s/zUrnFKG78qjLDZW9kGvkFpElOPj
|
||||
KkgsSaTn8kbxWoyR9wKW56onTos6eMfhItLCFy5/oAD3sIp5aCsATuJZPSAtDKxw
|
||||
1jzQRx4KOOYYrsS1qMd7gG151/QM15E56gdi+6gaeLcz8YQ2zcvxg5eabUDKp+bP
|
||||
I47NsT6rLAhV5mTB0NneC//Yng7JJ0q0jkiJu49BQ1if6Pz8txDxBs4U3mvCw2rA
|
||||
qSxRE/XMoebNx2CFQwFp7izDHwuG6uRRUQQ=
|
||||
=3beT
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
29
tools/osbuilder/rootfs-builder/euleros/config.sh
Normal file
29
tools/osbuilder/rootfs-builder/euleros/config.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (C) 2018 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
OS_NAME="EulerOS"
|
||||
|
||||
OS_VERSION=${OS_VERSION:-2.2}
|
||||
|
||||
BASE_URL="http://developer.huawei.com/ict/site-euleros/euleros/repo/yum/${OS_VERSION}/os/${ARCH}/"
|
||||
|
||||
GPG_KEY_FILE="RPM-GPG-KEY-EulerOS"
|
||||
|
||||
PACKAGES="iptables chrony"
|
||||
|
||||
#Optional packages:
|
||||
# systemd: An init system that will start kata-agent if kata-agent
|
||||
# itself is not configured as init process.
|
||||
[ "$AGENT_INIT" == "no" ] && PACKAGES+=" systemd" || true
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=( aarch64 ppc64le s390x )
|
||||
# Allow the build to fail without generating an error.
|
||||
# For more info see: https://github.com/kata-containers/osbuilder/issues/190
|
||||
BUILD_CAN_FAIL=1
|
||||
|
||||
[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp" || true
|
43
tools/osbuilder/rootfs-builder/fedora/Dockerfile.in
Normal file
43
tools/osbuilder/rootfs-builder/fedora/Dockerfile.in
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
From docker.io/fedora:@OS_VERSION@
|
||||
|
||||
@SET_PROXY@
|
||||
|
||||
RUN dnf -y update && dnf install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
chrony \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git \
|
||||
glibc-common \
|
||||
glibc-devel \
|
||||
glibc-headers \
|
||||
glibc-static \
|
||||
glibc-utils \
|
||||
libseccomp \
|
||||
libseccomp-devel \
|
||||
libstdc++-devel \
|
||||
libstdc++-static \
|
||||
m4 \
|
||||
make \
|
||||
pkgconfig \
|
||||
redhat-release \
|
||||
sed \
|
||||
systemd \
|
||||
tar \
|
||||
vim \
|
||||
which
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_MUSL@
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
23
tools/osbuilder/rootfs-builder/fedora/config.sh
Normal file
23
tools/osbuilder/rootfs-builder/fedora/config.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
OS_NAME="Fedora"
|
||||
|
||||
OS_VERSION=${OS_VERSION:-30}
|
||||
|
||||
MIRROR_LIST="https://mirrors.fedoraproject.org/metalink?repo=fedora-${OS_VERSION}&arch=\$basearch"
|
||||
|
||||
PACKAGES="iptables chrony"
|
||||
|
||||
#Optional packages:
|
||||
# systemd: An init system that will start kata-agent if kata-agent
|
||||
# itself is not configured as init process.
|
||||
[ "$AGENT_INIT" == "no" ] && PACKAGES+=" systemd" || true
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
ARCH_EXCLUDE_LIST=()
|
||||
|
||||
[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp" || true
|
10
tools/osbuilder/rootfs-builder/fedora/config_aarch64.sh
Normal file
10
tools/osbuilder/rootfs-builder/fedora/config_aarch64.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) 2019 ARM Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# image busybox will fail on fedora 30 rootfs image
|
||||
# see https://github.com/kata-containers/osbuilder/issues/334 for detailed info
|
||||
OS_VERSION="29"
|
||||
|
||||
MIRROR_LIST="https://mirrors.fedoraproject.org/metalink?repo=fedora-${OS_VERSION}&arch=\$basearch"
|
686
tools/osbuilder/rootfs-builder/rootfs.sh
Executable file
686
tools/osbuilder/rootfs-builder/rootfs.sh
Executable file
@ -0,0 +1,686 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o errtrace
|
||||
|
||||
[ -n "$DEBUG" ] && set -x
|
||||
|
||||
script_name="${0##*/}"
|
||||
script_dir="$(dirname $(readlink -f $0))"
|
||||
AGENT_VERSION=${AGENT_VERSION:-}
|
||||
GO_AGENT_PKG=${GO_AGENT_PKG:-github.com/kata-containers/agent}
|
||||
RUST_AGENT_PKG=${RUST_AGENT_PKG:-github.com/kata-containers/kata-containers}
|
||||
RUST_AGENT=${RUST_AGENT:-no}
|
||||
RUST_VERSION="null"
|
||||
CMAKE_VERSION=${CMAKE_VERSION:-"null"}
|
||||
MUSL_VERSION=${MUSL_VERSION:-"null"}
|
||||
AGENT_BIN=${AGENT_BIN:-kata-agent}
|
||||
AGENT_INIT=${AGENT_INIT:-no}
|
||||
KERNEL_MODULES_DIR=${KERNEL_MODULES_DIR:-""}
|
||||
OSBUILDER_VERSION="unknown"
|
||||
DOCKER_RUNTIME=${DOCKER_RUNTIME:-runc}
|
||||
GO_VERSION="null"
|
||||
export GOPATH=${GOPATH:-${HOME}/go}
|
||||
|
||||
lib_file="${script_dir}/../scripts/lib.sh"
|
||||
source "$lib_file"
|
||||
|
||||
handle_error() {
|
||||
local exit_code="${?}"
|
||||
local line_number="${1:-}"
|
||||
echo "Failed at $line_number: ${BASH_COMMAND}"
|
||||
exit "${exit_code}"
|
||||
|
||||
}
|
||||
trap 'handle_error $LINENO' ERR
|
||||
|
||||
# Default architecture
|
||||
ARCH=$(uname -m)
|
||||
|
||||
# distro-specific config file
|
||||
typeset -r CONFIG_SH="config.sh"
|
||||
|
||||
# optional arch-specific config file
|
||||
typeset -r CONFIG_ARCH_SH="config_${ARCH}.sh"
|
||||
|
||||
# Name of an optional distro-specific file which, if it exists, must implement the
|
||||
# build_rootfs() function.
|
||||
typeset -r LIB_SH="rootfs_lib.sh"
|
||||
|
||||
# rootfs distro name specified by the user
|
||||
typeset distro=
|
||||
|
||||
# Absolute path to the rootfs root folder
|
||||
typeset ROOTFS_DIR
|
||||
|
||||
# Absolute path in the rootfs to the "init" executable / symlink.
|
||||
# Typically something like "${ROOTFS_DIR}/init
|
||||
typeset init=
|
||||
|
||||
#$1: Error code if want to exit different to 0
|
||||
usage()
|
||||
{
|
||||
error="${1:-0}"
|
||||
cat <<EOT
|
||||
|
||||
Usage: ${script_name} [options] [DISTRO]
|
||||
|
||||
Build and setup a rootfs directory based on DISTRO OS, used to create
|
||||
Kata Containers images or initramfs.
|
||||
|
||||
When no DISTRO is provided, an existing base rootfs at ROOTFS_DIR is provisioned
|
||||
with the Kata specific components and configuration.
|
||||
|
||||
Supported DISTRO values:
|
||||
$(get_distros | tr "\n" " ")
|
||||
|
||||
Options:
|
||||
-a <version> Specify the agent version. Overrides the AGENT_VERSION
|
||||
environment variable.
|
||||
-h Show this help message.
|
||||
-l List the supported Linux distributions and exit immediately.
|
||||
-o <version> Specify the version of osbuilder to embed in the rootfs
|
||||
yaml description.
|
||||
-r <directory> Specify the rootfs base directory. Overrides the ROOTFS_DIR
|
||||
environment variable.
|
||||
-t DISTRO Print the test configuration for DISTRO and exit
|
||||
immediately.
|
||||
|
||||
Environment Variables:
|
||||
AGENT_BIN Name of the agent binary (used when running sanity checks on
|
||||
the rootfs).
|
||||
Default value: ${AGENT_BIN}
|
||||
|
||||
AGENT_INIT When set to "yes", use ${AGENT_BIN} as init process in place
|
||||
of systemd.
|
||||
Default value: no
|
||||
|
||||
RUST_AGENT When set to "yes", build kata-agent from kata-rust-agent instead of go agent
|
||||
Default value: "no"
|
||||
|
||||
RUST_AGENT_PKG URL of the Git repository hosting the agent package.
|
||||
Default value: ${RUST_AGENT_PKG}
|
||||
|
||||
AGENT_VERSION Version of the agent to include in the rootfs.
|
||||
Default value: ${AGENT_VERSION:-<not set>}
|
||||
|
||||
AGENT_SOURCE_BIN Path to the directory of agent binary.
|
||||
If set, use the binary as agent but not build agent package.
|
||||
Default value: <not set>
|
||||
|
||||
DISTRO_REPO Use host repositories to install guest packages.
|
||||
Default value: <not set>
|
||||
|
||||
GO_AGENT_PKG URL of the Git repository hosting the agent package.
|
||||
Default value: ${GO_AGENT_PKG}
|
||||
|
||||
GRACEFUL_EXIT If set, and if the DISTRO configuration specifies a
|
||||
non-empty BUILD_CAN_FAIL variable, do not return with an
|
||||
error code in case any of the build step fails.
|
||||
This is used when running CI jobs, to tolerate failures for
|
||||
specific distributions.
|
||||
Default value: <not set>
|
||||
|
||||
KERNEL_MODULES_DIR Path to a directory containing kernel modules to include in
|
||||
the rootfs.
|
||||
Default value: <empty>
|
||||
|
||||
ROOTFS_DIR Path to the directory that is populated with the rootfs.
|
||||
Default value: <${script_name} path>/rootfs-<DISTRO-name>
|
||||
|
||||
USE_DOCKER If set, build the rootfs inside a container (requires
|
||||
Docker).
|
||||
Default value: <not set>
|
||||
|
||||
USE_PODMAN If set and USE_DOCKER not set, then build the rootfs inside
|
||||
a podman container (requires podman).
|
||||
Default value: <not set>
|
||||
|
||||
DOCKER_RUNTIME Docker runtime to use when USE_DOCKER is set.
|
||||
Default value: runc
|
||||
|
||||
Refer to the Platform-OS Compatibility Matrix for more details on the supported
|
||||
architectures:
|
||||
https://github.com/kata-containers/osbuilder#platform-distro-compatibility-matrix
|
||||
|
||||
EOT
|
||||
exit "${error}"
|
||||
}
|
||||
|
||||
get_distros() {
|
||||
cdirs=$(find "${script_dir}" -maxdepth 1 -type d)
|
||||
find ${cdirs} -maxdepth 1 -name "${CONFIG_SH}" -printf '%H\n' | while read dir; do
|
||||
basename "${dir}"
|
||||
done
|
||||
}
|
||||
|
||||
get_test_config() {
|
||||
local -r distro="$1"
|
||||
[ -z "$distro" ] && die "No distro name specified"
|
||||
|
||||
local config="${script_dir}/${distro}/config.sh"
|
||||
source ${config}
|
||||
|
||||
echo -e "INIT_PROCESS:\t\t$INIT_PROCESS"
|
||||
echo -e "ARCH_EXCLUDE_LIST:\t\t${ARCH_EXCLUDE_LIST[@]}"
|
||||
}
|
||||
|
||||
check_function_exist()
|
||||
{
|
||||
function_name="$1"
|
||||
[ "$(type -t ${function_name})" == "function" ] || die "${function_name} function was not defined"
|
||||
}
|
||||
|
||||
docker_extra_args()
|
||||
{
|
||||
local args=""
|
||||
|
||||
case "$1" in
|
||||
ubuntu | debian)
|
||||
# Requred to chroot
|
||||
args+=" --cap-add SYS_CHROOT"
|
||||
# debootstrap needs to create device nodes to properly function
|
||||
args+=" --cap-add MKNOD"
|
||||
;&
|
||||
suse)
|
||||
# Required to mount inside a container
|
||||
args+=" --cap-add SYS_ADMIN"
|
||||
# When AppArmor is enabled, mounting inside a container is blocked with docker-default profile.
|
||||
# See https://github.com/moby/moby/issues/16429
|
||||
args+=" --security-opt apparmor=unconfined"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$args"
|
||||
}
|
||||
|
||||
setup_agent_init()
|
||||
{
|
||||
agent_bin="$1"
|
||||
init_bin="$2"
|
||||
|
||||
[ -z "$agent_bin" ] && die "need agent binary path"
|
||||
[ -z "$init_bin" ] && die "need init bin path"
|
||||
|
||||
info "Install $agent_bin as init process"
|
||||
mv -f "${agent_bin}" ${init_bin}
|
||||
OK "Agent is installed as init process"
|
||||
}
|
||||
|
||||
copy_kernel_modules()
|
||||
{
|
||||
local module_dir="$1"
|
||||
local rootfs_dir="$2"
|
||||
|
||||
[ -z "$module_dir" ] && die "need module directory"
|
||||
[ -z "$rootfs_dir" ] && die "need rootfs directory"
|
||||
|
||||
local dest_dir="${rootfs_dir}/lib/modules"
|
||||
|
||||
info "Copy kernel modules from ${KERNEL_MODULES_DIR}"
|
||||
mkdir -p "${dest_dir}"
|
||||
cp -a "${KERNEL_MODULES_DIR}" "${dest_dir}/"
|
||||
OK "Kernel modules copied"
|
||||
}
|
||||
|
||||
error_handler()
|
||||
{
|
||||
[ "$?" -eq 0 ] && return
|
||||
|
||||
if [ -n "$GRACEFUL_EXIT" ] && [ -n "$BUILD_CAN_FAIL" ]; then
|
||||
info "Detected a build error, but $distro is allowed to fail (BUILD_CAN_FAIL specified), so exiting sucessfully"
|
||||
touch "$(dirname ${ROOTFS_DIR})/${distro}_fail"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Compares two SEMVER-style versions passed as arguments, up to the MINOR version
|
||||
# number.
|
||||
# Returns a zero exit code if the version specified by the first argument is
|
||||
# older OR equal than / to the version in the second argument, non-zero exit
|
||||
# code otherwise.
|
||||
compare_versions()
|
||||
{
|
||||
typeset -i -a v1=($(echo "$1" | awk 'BEGIN {FS = "."} {print $1" "$2}'))
|
||||
typeset -i -a v2=($(echo "$2" | awk 'BEGIN {FS = "."} {print $1" "$2}'))
|
||||
|
||||
# Sanity check: first version can't be all zero
|
||||
[ "${v1[0]}" -eq "0" ] && \
|
||||
[ "${v1[1]}" -eq "0" ] && \
|
||||
die "Failed to parse version number"
|
||||
|
||||
# Major
|
||||
[ "${v1[0]}" -gt "${v2[0]}" ] && { false; return; }
|
||||
|
||||
# Minor
|
||||
[ "${v1[0]}" -eq "${v2[0]}" ] && \
|
||||
[ "${v1[1]}" -gt "${v2[1]}" ] && { false; return; }
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
check_env_variables()
|
||||
{
|
||||
# Fetch the first element from GOPATH as working directory
|
||||
# as go get only works against the first item in the GOPATH
|
||||
[ -z "$GOPATH" ] && die "GOPATH not set"
|
||||
GOPATH_LOCAL="${GOPATH%%:*}"
|
||||
|
||||
[ "$AGENT_INIT" == "yes" -o "$AGENT_INIT" == "no" ] || die "AGENT_INIT($AGENT_INIT) is invalid (must be yes or no)"
|
||||
|
||||
if [ -z "${AGENT_SOURCE_BIN}" ]; then
|
||||
[ "$RUST_AGENT" == "yes" -o "$RUST_AGENT" == "no" ] || die "RUST_AGENT($RUST_AGENT) is invalid (must be yes or no)"
|
||||
fi
|
||||
|
||||
[ -n "${KERNEL_MODULES_DIR}" ] && [ ! -d "${KERNEL_MODULES_DIR}" ] && die "KERNEL_MODULES_DIR defined but is not an existing directory"
|
||||
|
||||
[ -n "${OSBUILDER_VERSION}" ] || die "need osbuilder version"
|
||||
}
|
||||
|
||||
# Builds a rootfs based on the distro name provided as argument
|
||||
build_rootfs_distro()
|
||||
{
|
||||
[ -n "${distro}" ] || usage 1
|
||||
distro_config_dir="${script_dir}/${distro}"
|
||||
|
||||
# Source config.sh from distro
|
||||
rootfs_config="${distro_config_dir}/${CONFIG_SH}"
|
||||
source "${rootfs_config}"
|
||||
|
||||
# Source arch-specific config file
|
||||
rootfs_arch_config="${distro_config_dir}/${CONFIG_ARCH_SH}"
|
||||
if [ -f "${rootfs_arch_config}" ]; then
|
||||
source "${rootfs_arch_config}"
|
||||
fi
|
||||
|
||||
[ -d "${distro_config_dir}" ] || die "Not found configuration directory ${distro_config_dir}"
|
||||
|
||||
if [ -z "$ROOTFS_DIR" ]; then
|
||||
ROOTFS_DIR="${script_dir}/rootfs-${OS_NAME}"
|
||||
fi
|
||||
|
||||
if [ -e "${distro_config_dir}/${LIB_SH}" ];then
|
||||
rootfs_lib="${distro_config_dir}/${LIB_SH}"
|
||||
info "rootfs_lib.sh file found. Loading content"
|
||||
source "${rootfs_lib}"
|
||||
fi
|
||||
|
||||
CONFIG_DIR=${distro_config_dir}
|
||||
check_function_exist "build_rootfs"
|
||||
|
||||
if [ -z "$INSIDE_CONTAINER" ] ; then
|
||||
# Capture errors, but only outside of the docker container
|
||||
trap error_handler ERR
|
||||
fi
|
||||
|
||||
mkdir -p ${ROOTFS_DIR}
|
||||
|
||||
detect_go_version ||
|
||||
die "Could not detect the required Go version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
|
||||
echo "Required Go version: $GO_VERSION"
|
||||
|
||||
# need to detect rustc's version too?
|
||||
detect_rust_version ||
|
||||
die "Could not detect the required rust version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
|
||||
echo "Required rust version: $RUST_VERSION"
|
||||
|
||||
detect_cmake_version ||
|
||||
die "Could not detect the required cmake version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
|
||||
echo "Required cmake version: $CMAKE_VERSION"
|
||||
|
||||
detect_musl_version ||
|
||||
die "Could not detect the required musl version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
|
||||
echo "Required musl version: $MUSL_VERSION"
|
||||
|
||||
if [ -z "${USE_DOCKER}" ] && [ -z "${USE_PODMAN}" ]; then
|
||||
#Generate an error if the local Go version is too old
|
||||
foundVersion=$(go version | sed -E "s/^.+([0-9]+\.[0-9]+\.[0-9]+).*$/\1/g")
|
||||
|
||||
compare_versions "${GO_VERSION}" "${foundVersion}" || \
|
||||
die "Your Go version ${foundVersion} is older than the minimum expected Go version ${GO_VERSION}"
|
||||
|
||||
if [ "${RUST_AGENT}" == "yes" ]; then
|
||||
source "${HOME}/.cargo/env"
|
||||
foundVersion=$(rustc --version | sed -E "s/^.+([0-9]+\.[0-9]+\.[0-9]+).*$/\1/g")
|
||||
|
||||
compare_versions "${RUST_VERSION}" "${foundVersion}" || \
|
||||
die "Your rust version ${foundVersion} is older than the minimum expected rust version ${RUST_VERSION}"
|
||||
|
||||
foundVersion=$(cmake --version | grep "[0-9]\+.[0-9]\+.[0-9]\+" | sed -E "s/^.+([0-9]+\.[0-9]+\.[0-9]+).*$/\1/g")
|
||||
|
||||
fi
|
||||
else
|
||||
if [ -n "${USE_DOCKER}" ]; then
|
||||
container_engine="docker"
|
||||
elif [ -n "${USE_PODMAN}" ]; then
|
||||
container_engine="podman"
|
||||
fi
|
||||
|
||||
image_name="${distro}-rootfs-osbuilder"
|
||||
|
||||
# setup to install go or rust here
|
||||
generate_dockerfile "${distro_config_dir}"
|
||||
"$container_engine" build \
|
||||
--build-arg http_proxy="${http_proxy}" \
|
||||
--build-arg https_proxy="${https_proxy}" \
|
||||
-t "${image_name}" "${distro_config_dir}"
|
||||
|
||||
# fake mapping if KERNEL_MODULES_DIR is unset
|
||||
kernel_mod_dir=${KERNEL_MODULES_DIR:-${ROOTFS_DIR}}
|
||||
|
||||
docker_run_args=""
|
||||
docker_run_args+=" --rm"
|
||||
docker_run_args+=" --runtime ${DOCKER_RUNTIME}"
|
||||
|
||||
if [ -z "${AGENT_SOURCE_BIN}" ] ; then
|
||||
if [ "$RUST_AGENT" == "no" ]; then
|
||||
docker_run_args+=" --env GO_AGENT_PKG=${GO_AGENT_PKG}"
|
||||
else
|
||||
docker_run_args+=" --env RUST_AGENT_PKG=${RUST_AGENT_PKG}"
|
||||
fi
|
||||
docker_run_args+=" --env RUST_AGENT=${RUST_AGENT} -v ${GOPATH_LOCAL}:${GOPATH_LOCAL} --env GOPATH=${GOPATH_LOCAL}"
|
||||
else
|
||||
docker_run_args+=" --env AGENT_SOURCE_BIN=${AGENT_SOURCE_BIN}"
|
||||
docker_run_args+=" -v ${AGENT_SOURCE_BIN}:${AGENT_SOURCE_BIN}"
|
||||
fi
|
||||
|
||||
docker_run_args+=" $(docker_extra_args $distro)"
|
||||
|
||||
# Relabel volumes so SELinux allows access (see docker-run(1))
|
||||
if command -v selinuxenabled > /dev/null && selinuxenabled ; then
|
||||
SRC_VOL=("${GOPATH_LOCAL}")
|
||||
|
||||
for volume_dir in "${script_dir}" \
|
||||
"${ROOTFS_DIR}" \
|
||||
"${script_dir}/../scripts" \
|
||||
"${kernel_mod_dir}" \
|
||||
"${SRC_VOL[@]}"; do
|
||||
chcon -Rt svirt_sandbox_file_t "$volume_dir"
|
||||
done
|
||||
fi
|
||||
|
||||
#Make sure we use a compatible runtime to build rootfs
|
||||
# In case Clear Containers Runtime is installed we dont want to hit issue:
|
||||
#https://github.com/clearcontainers/runtime/issues/828
|
||||
"$container_engine" run \
|
||||
--env https_proxy="${https_proxy}" \
|
||||
--env http_proxy="${http_proxy}" \
|
||||
--env AGENT_VERSION="${AGENT_VERSION}" \
|
||||
--env ROOTFS_DIR="/rootfs" \
|
||||
--env AGENT_BIN="${AGENT_BIN}" \
|
||||
--env AGENT_INIT="${AGENT_INIT}" \
|
||||
--env KERNEL_MODULES_DIR="${KERNEL_MODULES_DIR}" \
|
||||
--env EXTRA_PKGS="${EXTRA_PKGS}" \
|
||||
--env OSBUILDER_VERSION="${OSBUILDER_VERSION}" \
|
||||
--env INSIDE_CONTAINER=1 \
|
||||
--env SECCOMP="${SECCOMP}" \
|
||||
--env DEBUG="${DEBUG}" \
|
||||
--env HOME="/root" \
|
||||
-v "${script_dir}":"/osbuilder" \
|
||||
-v "${ROOTFS_DIR}":"/rootfs" \
|
||||
-v "${script_dir}/../scripts":"/scripts" \
|
||||
-v "${kernel_mod_dir}":"${kernel_mod_dir}" \
|
||||
$docker_run_args \
|
||||
${image_name} \
|
||||
bash /osbuilder/rootfs.sh "${distro}"
|
||||
|
||||
exit $?
|
||||
fi
|
||||
|
||||
build_rootfs ${ROOTFS_DIR}
|
||||
}
|
||||
|
||||
# Used to create a minimal directory tree where the agent can be instaleld.
|
||||
# This is used when a distro is not specified.
|
||||
prepare_overlay()
|
||||
{
|
||||
pushd "${ROOTFS_DIR}" > /dev/null
|
||||
mkdir -p ./etc ./lib/systemd ./sbin ./var
|
||||
|
||||
# This symlink hacking is mostly to make later rootfs
|
||||
# validation work correctly for the dracut case.
|
||||
# We skip this if /sbin/init exists in the rootfs, meaning
|
||||
# we were passed a pre-populated rootfs directory
|
||||
if [ ! -e ./sbin/init ]; then
|
||||
ln -sf ./usr/lib/systemd/systemd ./init
|
||||
ln -sf ../../init ./lib/systemd/systemd
|
||||
ln -sf ../init ./sbin/init
|
||||
fi
|
||||
|
||||
# Kata systemd unit file
|
||||
mkdir -p ./etc/systemd/system/basic.target.wants/
|
||||
ln -sf /usr/lib/systemd/system/kata-containers.target ./etc/systemd/system/basic.target.wants/kata-containers.target
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
# Setup an existing rootfs directory, based on the OPTIONAL distro name
|
||||
# provided as argument
|
||||
setup_rootfs()
|
||||
{
|
||||
info "Create symlink to /tmp in /var to create private temporal directories with systemd"
|
||||
pushd "${ROOTFS_DIR}" >> /dev/null
|
||||
if [ "$PWD" != "/" ] ; then
|
||||
rm -rf ./var/cache/ ./var/lib ./var/log ./var/tmp
|
||||
fi
|
||||
|
||||
ln -s ../tmp ./var/
|
||||
|
||||
# For some distros tmp.mount may not be installed by default in systemd paths
|
||||
if ! [ -f "./etc/systemd/system/tmp.mount" ] && \
|
||||
! [ -f "./usr/lib/systemd/system/tmp.mount" ] &&
|
||||
[ "$AGENT_INIT" != "yes" ]; then
|
||||
local unitFile="./etc/systemd/system/tmp.mount"
|
||||
info "Install tmp.mount in ./etc/systemd/system"
|
||||
mkdir -p `dirname "$unitFile"`
|
||||
cp ./usr/share/systemd/tmp.mount "$unitFile" || cat > "$unitFile" << EOT
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Temporary Directory (/tmp)
|
||||
Documentation=man:hier(7)
|
||||
Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
|
||||
ConditionPathIsSymbolicLink=!/tmp
|
||||
DefaultDependencies=no
|
||||
Conflicts=umount.target
|
||||
Before=local-fs.target umount.target
|
||||
After=swap.target
|
||||
|
||||
[Mount]
|
||||
What=tmpfs
|
||||
Where=/tmp
|
||||
Type=tmpfs
|
||||
Options=mode=1777,strictatime,nosuid,nodev
|
||||
EOT
|
||||
fi
|
||||
|
||||
popd >> /dev/null
|
||||
|
||||
[ -n "${KERNEL_MODULES_DIR}" ] && copy_kernel_modules ${KERNEL_MODULES_DIR} ${ROOTFS_DIR}
|
||||
|
||||
info "Create ${ROOTFS_DIR}/etc"
|
||||
mkdir -p "${ROOTFS_DIR}/etc"
|
||||
|
||||
case "${distro}" in
|
||||
"ubuntu" | "debian")
|
||||
echo "I am ubuntu or debian"
|
||||
chrony_conf_file="${ROOTFS_DIR}/etc/chrony/chrony.conf"
|
||||
chrony_systemd_service="${ROOTFS_DIR}/lib/systemd/system/chrony.service"
|
||||
;;
|
||||
*)
|
||||
chrony_conf_file="${ROOTFS_DIR}/etc/chrony.conf"
|
||||
chrony_systemd_service="${ROOTFS_DIR}/usr/lib/systemd/system/chronyd.service"
|
||||
;;
|
||||
esac
|
||||
|
||||
info "Configure chrony file ${chrony_conf_file}"
|
||||
cat >> "${chrony_conf_file}" <<EOT
|
||||
refclock PHC /dev/ptp0 poll 3 dpoll -2 offset 0
|
||||
# Step the system clock instead of slewing it if the adjustment is larger than
|
||||
# one second, at any time
|
||||
makestep 1 -1
|
||||
EOT
|
||||
|
||||
# Comment out ntp sources for chrony to be extra careful
|
||||
# Reference: https://chrony.tuxfamily.org/doc/3.4/chrony.conf.html
|
||||
sed -i 's/^\(server \|pool \|peer \)/# &/g' ${chrony_conf_file}
|
||||
|
||||
if [ -f "$chrony_systemd_service" ]; then
|
||||
sed -i '/^\[Unit\]/a ConditionPathExists=\/dev\/ptp0' ${chrony_systemd_service}
|
||||
fi
|
||||
|
||||
# The CC on s390x for fedora needs to be manually set to gcc when the golang is downloaded from the main page.
|
||||
# See issue: https://github.com/kata-containers/osbuilder/issues/217
|
||||
[ "$distro" == "fedora" ] && [ "$ARCH" == "s390x" ] && export CC=gcc
|
||||
|
||||
AGENT_DIR="${ROOTFS_DIR}/usr/bin"
|
||||
AGENT_DEST="${AGENT_DIR}/${AGENT_BIN}"
|
||||
|
||||
if [ -z "${AGENT_SOURCE_BIN}" ] ; then
|
||||
if [ "$RUST_AGENT" != "yes" ]; then
|
||||
agent_pkg="${GO_AGENT_PKG}"
|
||||
agent_dir="${GOPATH_LOCAL}/src/${GO_AGENT_PKG}"
|
||||
else
|
||||
# The PATH /.cargo/bin is apparently wrong
|
||||
# looks like $HOME is resolved to empty when
|
||||
# container is started
|
||||
source "${HOME}/.cargo/env"
|
||||
agent_pkg="${RUST_AGENT_PKG}"
|
||||
agent_dir="${GOPATH_LOCAL}/src/${RUST_AGENT_PKG}/src/agent"
|
||||
# For now, rust-agent doesn't support seccomp yet.
|
||||
SECCOMP="no"
|
||||
fi
|
||||
|
||||
info "Pull Agent source code"
|
||||
go get -d "${agent_pkg}" || true
|
||||
OK "Pull Agent source code"
|
||||
|
||||
info "Build agent"
|
||||
pushd "${agent_dir}"
|
||||
[ -n "${AGENT_VERSION}" ] && git checkout "${AGENT_VERSION}" && OK "git checkout successful" || info "checkout failed!"
|
||||
make clean
|
||||
make INIT=${AGENT_INIT}
|
||||
make install DESTDIR="${ROOTFS_DIR}" INIT=${AGENT_INIT} SECCOMP=${SECCOMP}
|
||||
popd
|
||||
else
|
||||
cp ${AGENT_SOURCE_BIN} ${AGENT_DEST}
|
||||
OK "cp ${AGENT_SOURCE_BIN} ${AGENT_DEST}"
|
||||
fi
|
||||
|
||||
[ -x "${AGENT_DEST}" ] || die "${AGENT_DEST} is not installed in ${ROOTFS_DIR}"
|
||||
OK "Agent installed"
|
||||
|
||||
[ "${AGENT_INIT}" == "yes" ] && setup_agent_init "${AGENT_DEST}" "${init}"
|
||||
|
||||
info "Check init is installed"
|
||||
[ -x "${init}" ] || [ -L "${init}" ] || die "/sbin/init is not installed in ${ROOTFS_DIR}"
|
||||
OK "init is installed"
|
||||
|
||||
# Create an empty /etc/resolv.conf, to allow agent to bind mount container resolv.conf to Kata VM
|
||||
dns_file="${ROOTFS_DIR}/etc/resolv.conf"
|
||||
if [ -L "$dns_file" ]; then
|
||||
# if /etc/resolv.conf is a link, it cannot be used for bind mount
|
||||
rm -f "$dns_file"
|
||||
fi
|
||||
info "Create /etc/resolv.conf file in rootfs if not exist"
|
||||
touch "$dns_file"
|
||||
|
||||
info "Creating summary file"
|
||||
create_summary_file "${ROOTFS_DIR}"
|
||||
}
|
||||
|
||||
parse_arguments()
|
||||
{
|
||||
while getopts a:hlo:r:t: opt
|
||||
do
|
||||
case $opt in
|
||||
a) AGENT_VERSION="${OPTARG}" ;;
|
||||
h) usage ;;
|
||||
l) get_distros | sort && exit 0;;
|
||||
o) OSBUILDER_VERSION="${OPTARG}" ;;
|
||||
r) ROOTFS_DIR="${OPTARG}" ;;
|
||||
t) get_test_config "${OPTARG}" && exit 0;;
|
||||
*) die "Found an invalid option";;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND - 1))
|
||||
distro="$1"
|
||||
arch=$(uname -m)
|
||||
|
||||
if [ "${distro}" == "alpine" -o "${distro}" == "euleros" ]; then
|
||||
if [ "${RUST_AGENT}" == "yes" ]; then
|
||||
die "rust agent cannot be built on ${distro}.
|
||||
alpine: only has stable/nightly-x86_64-unknown-linux-musl toolchain. It does not support proc-macro compilation.
|
||||
See issue: https://github.com/kata-containers/osbuilder/issues/386
|
||||
euleros: 1. Missing libstdc++.a
|
||||
2. kernel is 3.10.x, there is no vsock support
|
||||
You can build rust agent on your host and then copy it into
|
||||
image's rootfs(eg. rootfs-builder/rootfs/usr/bin), and then
|
||||
use image_builder.sh to build image with the rootfs. Please
|
||||
refer to documentation for how to use customer agent.
|
||||
See issue: https://github.com/kata-containers/osbuilder/issues/387"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${RUST_AGENT}" == "yes" ] && [ "${arch}" == "s390x" -o "${arch}" == "ppc64le" ]; then
|
||||
die "Cannot build rust agent on ppc64le.
|
||||
musl cannot be built on ppc64le because of long double
|
||||
reprentation is broken. And rust has no musl target on ppc64le.
|
||||
See issue: https://github.com/kata-containers/osbuilder/issues/388"
|
||||
fi
|
||||
}
|
||||
|
||||
detect_host_distro()
|
||||
{
|
||||
source /etc/os-release
|
||||
|
||||
case "$ID" in
|
||||
"*suse*")
|
||||
distro="suse"
|
||||
;;
|
||||
"clear-linux-os")
|
||||
distro="clearlinux"
|
||||
;;
|
||||
*)
|
||||
distro="$ID"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
parse_arguments $*
|
||||
check_env_variables
|
||||
init="${ROOTFS_DIR}/sbin/init"
|
||||
|
||||
if [ -n "$distro" ]; then
|
||||
build_rootfs_distro
|
||||
else
|
||||
#Make sure ROOTFS_DIR is set correctly
|
||||
[ -d "${ROOTFS_DIR}" ] || die "Invalid rootfs directory: '$ROOTFS_DIR'"
|
||||
|
||||
# Set the distro for dracut build method
|
||||
detect_host_distro
|
||||
prepare_overlay
|
||||
fi
|
||||
|
||||
setup_rootfs
|
||||
}
|
||||
|
||||
main $*
|
20
tools/osbuilder/rootfs-builder/suse/Dockerfile.in
Normal file
20
tools/osbuilder/rootfs-builder/suse/Dockerfile.in
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#suse: docker image to be used to create a rootfs
|
||||
#@OS_VERSION@: Docker image version to build this dockerfile
|
||||
from docker.io/opensuse/leap
|
||||
|
||||
# This dockerfile needs to provide all the componets need to build a rootfs
|
||||
# Install any package need to create a rootfs (package manager, extra tools)
|
||||
|
||||
COPY install-packages.sh config.sh /
|
||||
# RUN commands
|
||||
RUN chmod +x /install-packages.sh; /install-packages.sh
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_MUSL@
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
58
tools/osbuilder/rootfs-builder/suse/config.sh
Normal file
58
tools/osbuilder/rootfs-builder/suse/config.sh
Normal file
@ -0,0 +1,58 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# May also be "Tumbleweed"
|
||||
OS_DISTRO="Leap"
|
||||
|
||||
# Leave this empty for distro "Tumbleweed"
|
||||
OS_VERSION=${OS_VERSION:-15.0}
|
||||
|
||||
OS_IDENTIFIER="$OS_DISTRO${OS_VERSION:+:$OS_VERSION}"
|
||||
|
||||
# Extra packages to install in the rootfs
|
||||
PACKAGES="systemd iptables libudev1"
|
||||
|
||||
# http or https
|
||||
REPO_TRANSPORT="https"
|
||||
|
||||
# Can specify an alternative domain
|
||||
REPO_DOMAIN="download.opensuse.org"
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=()
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# NOTE: you probably dont need to edit things below this
|
||||
#
|
||||
|
||||
SUSE_URL_BASE="${REPO_TRANSPORT}://${REPO_DOMAIN}"
|
||||
SUSE_PATH_OSS="/distribution/${OS_DISTRO,,}/$OS_VERSION/repo/oss"
|
||||
SUSE_PATH_UPDATE="/update/${OS_DISTRO,,}/$OS_VERSION/oss"
|
||||
|
||||
arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
REPO_URL_PORT=""
|
||||
;;
|
||||
ppc|ppc64le)
|
||||
REPO_URL_PORT="/ports/ppc"
|
||||
;;
|
||||
aarch64)
|
||||
REPO_URL_PORT="/ports/aarch64"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported architecture: $arch"
|
||||
;;
|
||||
esac
|
||||
SUSE_FULLURL_OSS="${SUSE_URL_BASE}${REPO_URL_PORT}${SUSE_PATH_OSS}"
|
||||
SUSE_FULLURL_UPDATE="${SUSE_URL_BASE}${SUSE_PATH_UPDATE}"
|
||||
|
||||
if [ -z "${REPO_URL:-}" ]; then
|
||||
REPO_URL="$SUSE_FULLURL_OSS"
|
||||
fi
|
40
tools/osbuilder/rootfs-builder/suse/config.xml
Normal file
40
tools/osbuilder/rootfs-builder/suse/config.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2018 SUSE LLC
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<image schemaversion="6.8" name="openSUSE-rootfs-for-Kata-vm">
|
||||
<description type="system">
|
||||
<author>SUSE</author>
|
||||
<contact>mvedovati@suse.com</contact>
|
||||
<specification>openSUSE rootfs for Kata Containers guest vm</specification>
|
||||
</description>
|
||||
<preferences>
|
||||
<version>1.0.0</version>
|
||||
<packagemanager>zypper</packagemanager>
|
||||
<locale>en_US</locale>
|
||||
<keytable>us</keytable>
|
||||
<rpm-excludedocs>true</rpm-excludedocs>
|
||||
<type image="vmx" filesystem="ext4" />
|
||||
</preferences>
|
||||
<repository type="rpm-md">
|
||||
<!-- NOTE: the following is a placeholder, specify the actual path with kiwi option set-repo=... -->
|
||||
<source path="obs://"/>
|
||||
</repository>
|
||||
<packages type="image">
|
||||
<package name=""/>
|
||||
</packages>
|
||||
<packages type="delete">
|
||||
<package name="zypper"/>
|
||||
<package name="rpm"/>
|
||||
</packages>
|
||||
<packages type="bootstrap" patternType="onlyRequired">
|
||||
<package name="udev"/>
|
||||
<package name="filesystem"/>
|
||||
<package name="ca-certificates"/>
|
||||
<package name="ca-certificates-mozilla"/>
|
||||
<package name="openSUSE-release"/>
|
||||
</packages>
|
||||
|
||||
</image>
|
50
tools/osbuilder/rootfs-builder/suse/install-packages.sh
Normal file
50
tools/osbuilder/rootfs-builder/suse/install-packages.sh
Normal file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source config.sh
|
||||
|
||||
removeRepos=(repo-non-oss repo-update-non-oss repo-oss repo-update)
|
||||
|
||||
for r in ${removeRepos[@]}; do
|
||||
zypper --non-interactive removerepo $r
|
||||
done
|
||||
|
||||
zypper --non-interactive addrepo ${SUSE_FULLURL_OSS} osbuilder-oss
|
||||
zypper --non-interactive addrepo ${SUSE_FULLURL_UPDATE} osbuilder-update
|
||||
|
||||
|
||||
# Workaround for zypper slowdowns observed when running inside
|
||||
# a container: see https://github.com/openSUSE/zypper/pull/209
|
||||
# The fix is upstream but it will take a while before landing
|
||||
# in Leap
|
||||
ulimit -n 1024
|
||||
zypper --non-interactive refresh
|
||||
zypper --non-interactive install --no-recommends --force-resolution \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git \
|
||||
glibc-devel \
|
||||
glibc-devel-static \
|
||||
glibc-utils \
|
||||
libstdc++-devel \
|
||||
linux-glibc-devel \
|
||||
m4 \
|
||||
make \
|
||||
python3-kiwi \
|
||||
sed \
|
||||
tar \
|
||||
vim \
|
||||
which
|
||||
zypper --non-interactive clean --all
|
||||
|
76
tools/osbuilder/rootfs-builder/suse/rootfs_lib.sh
Normal file
76
tools/osbuilder/rootfs-builder/suse/rootfs_lib.sh
Normal file
@ -0,0 +1,76 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# - Arguments
|
||||
# rootfs_dir=$1
|
||||
#
|
||||
# - Optional environment variables
|
||||
#
|
||||
# EXTRA_PKGS: Variable to add extra PKGS provided by the user
|
||||
#
|
||||
# BIN_AGENT: Name of the Kata-Agent binary
|
||||
#
|
||||
# REPO_URL: URL to distribution repository ( should be configured in
|
||||
# config.sh file)
|
||||
#
|
||||
# Any other configuration variable for a specific distro must be added
|
||||
# and documented on its own config.sh
|
||||
#
|
||||
# - Expected result
|
||||
#
|
||||
# rootfs_dir populated with rootfs pkgs
|
||||
# It must provide a binary in /sbin/init
|
||||
#
|
||||
# Note: For some distros, the build_rootfs() function provided in scripts/lib.sh
|
||||
# will suffice. If a new distro is introduced with a special requirement,
|
||||
# then, a rootfs_builder/<distro>/rootfs_lib.sh file should be created
|
||||
# using this template.
|
||||
|
||||
build_rootfs() {
|
||||
# Mandatory
|
||||
local ROOTFS_DIR=$1
|
||||
|
||||
#Name of the Kata-Agent binary
|
||||
local BIN_AGENT=${BIN_AGENT}
|
||||
|
||||
# In case of support EXTRA packages, use it to allow
|
||||
# users add more packages to the base rootfs
|
||||
local EXTRA_PKGS=${EXTRA_PKGS:-}
|
||||
|
||||
#PATH where files this script is placed
|
||||
#Use it to refer to files in the same directory
|
||||
#Exmaple: ${CONFIG_DIR}/foo
|
||||
local CONFIG_DIR=${CONFIG_DIR}
|
||||
|
||||
# Populate ROOTFS_DIR
|
||||
# Must provide /sbin/init and /bin/${BIN_AGENT}
|
||||
if [ -e "$ROOTFS_DIR" ] && ! [ -z "$(ls -A $ROOTFS_DIR)" ]; then
|
||||
echo "ERROR: $ROOTFS_DIR is not empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local addPackages=""
|
||||
for p in $PACKAGES $EXTRA_PKGS; do
|
||||
addPackages+=" --add-package=$p"
|
||||
done
|
||||
|
||||
# set-repo format: <source,type,alias,priority,imageinclude,package_gpgcheck>
|
||||
# man kiwi::system::build for details
|
||||
local setRepo=" --set-repo $REPO_URL,rpm-md,$OS_IDENTIFIER,99,false,false"
|
||||
|
||||
# Workaround for zypper slowdowns observed when running inside
|
||||
# a container: see https://github.com/openSUSE/zypper/pull/209
|
||||
# The fix is upstream but it will take a while before landing
|
||||
# in Leap
|
||||
ulimit -n 1024
|
||||
kiwi system prepare \
|
||||
--description $CONFIG_DIR \
|
||||
--allow-existing-root \
|
||||
--root $ROOTFS_DIR \
|
||||
$addPackages \
|
||||
$setRepo
|
||||
install -d $ROOTFS_DIR/lib/systemd
|
||||
ln -s /usr/lib/systemd/systemd $ROOTFS_DIR/lib/systemd/systemd
|
||||
}
|
16
tools/osbuilder/rootfs-builder/template/Dockerfile.template
Normal file
16
tools/osbuilder/rootfs-builder/template/Dockerfile.template
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@distro@: docker image to be used to create a rootfs
|
||||
#@OS_VERSION@: Docker image version to build this dockerfile
|
||||
from @distro@:@OS_VERSION@
|
||||
|
||||
# This dockerfile needs to provide all the componets need to build a rootfs
|
||||
# Install any package need to create a rootfs (package manager, extra tools)
|
||||
|
||||
# RUN commands
|
||||
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
20
tools/osbuilder/rootfs-builder/template/Makefile
Normal file
20
tools/osbuilder/rootfs-builder/template/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2017 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#
|
||||
MK_DIR :=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
## Default destdir is one level up where is rootfs.sh script
|
||||
DESTDIR ?= "$(realpath $(MK_DIR)/../)/$(ROOTFS_BASE_NAME)"
|
||||
all:
|
||||
ifndef ROOTFS_BASE_NAME
|
||||
$(error ROOTFS_BASE_NAME is not set, use $ make ROOTFS_BASE_NAME=new_supported_os)
|
||||
endif
|
||||
mkdir -p $(DESTDIR)
|
||||
cp "$(MK_DIR)/rootfs_lib_template.sh" "$(DESTDIR)/rootfs_lib.sh"
|
||||
cp "$(MK_DIR)/config_template.sh" "$(DESTDIR)/config.sh"
|
||||
sed \
|
||||
-e "s|@distro@|$(ROOTFS_BASE_NAME)|g" \
|
||||
"$(MK_DIR)/Dockerfile.template" > $(DESTDIR)/Dockerfile.in
|
||||
|
||||
|
22
tools/osbuilder/rootfs-builder/template/config_template.sh
Normal file
22
tools/osbuilder/rootfs-builder/template/config_template.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This is a configuration file add extra variables to
|
||||
# be used by build_rootfs() from rootfs_lib.sh the variables will be
|
||||
# loaded just before call the function. For more information see the
|
||||
# rootfs-builder/README.md file.
|
||||
|
||||
OS_VERSION=${OS_VERSION:-DEFAULT_VERSION}
|
||||
|
||||
PACKAGES="systemd iptables udevlib.so"
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=()
|
||||
# [When uncommented,] Allow the build to fail without generating an error
|
||||
# For more info see: https://github.com/kata-containers/osbuilder/issues/190
|
||||
#BUILD_CAN_FAIL=1
|
@ -0,0 +1,49 @@
|
||||
# - Arguments
|
||||
# rootfs_dir=$1
|
||||
#
|
||||
# - Optional environment variables
|
||||
#
|
||||
# EXTRA_PKGS: Variable to add extra PKGS provided by the user
|
||||
#
|
||||
# BIN_AGENT: Name of the Kata-Agent binary
|
||||
#
|
||||
# REPO_URL: URL to distribution repository ( should be configured in
|
||||
# config.sh file)
|
||||
#
|
||||
# Any other configuration variable for a specific distro must be added
|
||||
# and documented on its own config.sh
|
||||
#
|
||||
# - Expected result
|
||||
#
|
||||
# rootfs_dir populated with rootfs pkgs
|
||||
# It must provide a binary in /sbin/init
|
||||
#
|
||||
# Note: For some distros, the build_rootfs() function provided in scripts/lib.sh
|
||||
# will suffice. If a new distro is introduced with a special requirement,
|
||||
# then, a rootfs_builder/<distro>/rootfs_lib.sh file should be created
|
||||
# using this template.
|
||||
|
||||
build_rootfs() {
|
||||
# Mandatory
|
||||
local ROOTFS_DIR=$1
|
||||
|
||||
#Name of the Kata-Agent binary
|
||||
local BIN_AGENT=${BIN_AGENT}
|
||||
|
||||
# In case of support EXTRA packages, use it to allow
|
||||
# users add more packages to the base rootfs
|
||||
local EXTRA_PKGS=${EXTRA_PKGS:-}
|
||||
|
||||
#In case rootfs is created usign repositories allow user to modify
|
||||
# the default URL
|
||||
local REPO_URL=${REPO_URL:-YOUR_REPO}
|
||||
|
||||
#PATH where files this script is placed
|
||||
#Use it to refer to files in the same directory
|
||||
#Exmaple: ${CONFIG_DIR}/foo
|
||||
local CONFIG_DIR=${CONFIG_DIR}
|
||||
|
||||
|
||||
# Populate ROOTFS_DIR
|
||||
# Must provide /sbin/init and /bin/${BIN_AGENT}
|
||||
}
|
39
tools/osbuilder/rootfs-builder/ubuntu/Dockerfile-aarch64.in
Normal file
39
tools/osbuilder/rootfs-builder/ubuntu/Dockerfile-aarch64.in
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (c) 2020 ARM Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#ubuntu: docker image to be used to create a rootfs
|
||||
#@OS_VERSION@: Docker image version to build this dockerfile
|
||||
from docker.io/ubuntu:@OS_VERSION@
|
||||
|
||||
# This dockerfile needs to provide all the componets need to build a rootfs
|
||||
# Install any package need to create a rootfs (package manager, extra tools)
|
||||
|
||||
# RUN commands
|
||||
RUN apt-get update && apt-get install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
build-essential \
|
||||
chrony \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
debianutils \
|
||||
debootstrap \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
libc6-dev \
|
||||
libstdc++-8-dev \
|
||||
m4 \
|
||||
make \
|
||||
sed \
|
||||
systemd \
|
||||
tar \
|
||||
vim
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
||||
@INSTALL_MUSL@
|
||||
@INSTALL_RUST@
|
44
tools/osbuilder/rootfs-builder/ubuntu/Dockerfile.in
Normal file
44
tools/osbuilder/rootfs-builder/ubuntu/Dockerfile.in
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (c) 2018 Yash Jain
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#ubuntu: docker image to be used to create a rootfs
|
||||
#@OS_VERSION@: Docker image version to build this dockerfile
|
||||
from docker.io/ubuntu:@OS_VERSION@
|
||||
|
||||
# This dockerfile needs to provide all the componets need to build a rootfs
|
||||
# Install any package need to create a rootfs (package manager, extra tools)
|
||||
|
||||
# RUN commands
|
||||
RUN apt-get update && apt-get --no-install-recommends install -y \
|
||||
apt-utils \
|
||||
autoconf \
|
||||
automake \
|
||||
binutils \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
chrony \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
debianutils \
|
||||
debootstrap \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
libc6-dev \
|
||||
libstdc++-8-dev \
|
||||
m4 \
|
||||
make \
|
||||
musl \
|
||||
musl-dev \
|
||||
musl-tools \
|
||||
sed \
|
||||
systemd \
|
||||
tar \
|
||||
vim \
|
||||
wget
|
||||
# This will install the proper golang to build Kata components
|
||||
@INSTALL_GO@
|
||||
@INSTALL_RUST@
|
33
tools/osbuilder/rootfs-builder/ubuntu/config.sh
Normal file
33
tools/osbuilder/rootfs-builder/ubuntu/config.sh
Normal file
@ -0,0 +1,33 @@
|
||||
# This is a configuration file add extra variables to
|
||||
#
|
||||
# Copyright (c) 2018 Yash Jain
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# be used by build_rootfs() from rootfs_lib.sh the variables will be
|
||||
# loaded just before call the function. For more information see the
|
||||
# rootfs-builder/README.md file.
|
||||
|
||||
OS_VERSION=${OS_VERSION:-18.04}
|
||||
# this should be ubuntu's codename eg bionic for 18.04
|
||||
OS_NAME=${OS_NAME:-"bionic"}
|
||||
|
||||
# packages to be installed by default
|
||||
PACKAGES="systemd iptables init chrony kmod"
|
||||
|
||||
DEBOOTSTRAP=${PACKAGE_MANAGER:-"debootstrap"}
|
||||
|
||||
case $(uname -m) in
|
||||
x86_64) ARCHITECTURE="amd64";;
|
||||
ppc64le) ARCHITECTURE="ppc64el";;
|
||||
aarch64) ARCHITECTURE="arm64";;
|
||||
s390x) ARCHITECTURE="s390x";;
|
||||
(*) die "$(uname -m) not supported "
|
||||
esac
|
||||
|
||||
# Init process must be one of {systemd,kata-agent}
|
||||
INIT_PROCESS=systemd
|
||||
# List of zero or more architectures to exclude from build,
|
||||
# as reported by `uname -m`
|
||||
ARCH_EXCLUDE_LIST=()
|
||||
|
||||
[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp2" || true
|
84
tools/osbuilder/rootfs-builder/ubuntu/rootfs_lib.sh
Normal file
84
tools/osbuilder/rootfs-builder/ubuntu/rootfs_lib.sh
Normal file
@ -0,0 +1,84 @@
|
||||
# - Arguments
|
||||
#
|
||||
# Copyright (c) 2018 Yash Jain
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#
|
||||
# rootfs_dir=$1
|
||||
#
|
||||
# - Optional environment variables
|
||||
#
|
||||
# EXTRA_PKGS: Variable to add extra PKGS provided by the user
|
||||
#
|
||||
# BIN_AGENT: Name of the Kata-Agent binary
|
||||
#
|
||||
# REPO_URL: URL to distribution repository ( should be configured in
|
||||
# config.sh file)
|
||||
#
|
||||
# Any other configuration variable for a specific distro must be added
|
||||
# and documented on its own config.sh
|
||||
#
|
||||
# - Expected result
|
||||
#
|
||||
# rootfs_dir populated with rootfs pkgs
|
||||
# It must provide a binary in /sbin/init
|
||||
#
|
||||
build_rootfs() {
|
||||
# Mandatory
|
||||
local ROOTFS_DIR=$1
|
||||
|
||||
# Name of the Kata-Agent binary
|
||||
local BIN_AGENT=${BIN_AGENT}
|
||||
|
||||
# In case of support EXTRA packages, use it to allow
|
||||
# users to add more packages to the base rootfs
|
||||
local EXTRA_PKGS=${EXTRA_PKGS:-}
|
||||
|
||||
# In case rootfs is created using repositories allow user to modify
|
||||
# the default URL
|
||||
local REPO_URL=${REPO_URL:-YOUR_REPO}
|
||||
|
||||
# PATH where files this script is placed
|
||||
# Use it to refer to files in the same directory
|
||||
# Example: ${CONFIG_DIR}/foo
|
||||
local CONFIG_DIR=${CONFIG_DIR}
|
||||
|
||||
|
||||
# Populate ROOTFS_DIR
|
||||
# Must provide /sbin/init and /bin/${BIN_AGENT}
|
||||
DEBOOTSTRAP="debootstrap"
|
||||
check_root
|
||||
mkdir -p "${ROOTFS_DIR}"
|
||||
if [ -n "${PKG_MANAGER}" ]; then
|
||||
info "debootstrap path provided by user: ${PKG_MANAGER}"
|
||||
elif check_program $DEBOOTSTRAP ; then
|
||||
PKG_MANAGER=$DEBOOTSTRAP
|
||||
else
|
||||
die "$DEBOOTSTRAP is not installed"
|
||||
fi
|
||||
# trim whitespace
|
||||
PACKAGES=$(echo $PACKAGES |xargs )
|
||||
EXTRA_PKGS=$(echo $EXTRA_PKGS |xargs)
|
||||
# add comma as debootstrap needs , separated package names.
|
||||
# Don't change $PACKAGES in config.sh to include ','
|
||||
# This is done to maintain consistency
|
||||
PACKAGES=$(echo $PACKAGES | sed -e 's/ /,/g' )
|
||||
EXTRA_PKGS=$(echo $EXTRA_PKGS | sed -e 's/ /,/g' )
|
||||
|
||||
# extra packages are added to packages and finally passed to debootstrap
|
||||
if [ "${EXTRA_PKGS}" = "" ]; then
|
||||
echo "no extra packages"
|
||||
else
|
||||
PACKAGES="${PACKAGES},${EXTRA_PKGS}"
|
||||
fi
|
||||
|
||||
${PKG_MANAGER} --variant=minbase \
|
||||
--arch=${ARCHITECTURE}\
|
||||
--include="$PACKAGES" \
|
||||
${OS_NAME} \
|
||||
${ROOTFS_DIR}
|
||||
|
||||
chroot $ROOTFS_DIR ln -s /lib/systemd/systemd /usr/lib/systemd/systemd
|
||||
}
|
||||
|
72
tools/osbuilder/scripts/install-yq.sh
Normal file
72
tools/osbuilder/scripts/install-yq.sh
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2019 IBM
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# If we fail for any reason a message will be displayed
|
||||
die() {
|
||||
msg="$*"
|
||||
echo "ERROR: $msg" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Install the yq yaml query package from the mikefarah github repo
|
||||
# Install via binary download, as we may not have golang installed at this point
|
||||
function install_yq() {
|
||||
GOPATH=${GOPATH:-${HOME}/go}
|
||||
local yq_path="${GOPATH}/bin/yq"
|
||||
local yq_pkg="github.com/mikefarah/yq"
|
||||
[ -x "${GOPATH}/bin/yq" ] && return
|
||||
|
||||
read -r -a sysInfo <<< "$(uname -sm)"
|
||||
|
||||
case "${sysInfo[0]}" in
|
||||
"Linux" | "Darwin")
|
||||
goos="${sysInfo[0],}"
|
||||
;;
|
||||
"*")
|
||||
die "OS ${sysInfo[0]} not supported"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${sysInfo[1]}" in
|
||||
"aarch64")
|
||||
goarch=arm64
|
||||
;;
|
||||
"ppc64le")
|
||||
goarch=ppc64le
|
||||
;;
|
||||
"x86_64")
|
||||
goarch=amd64
|
||||
;;
|
||||
"s390x")
|
||||
goarch=s390x
|
||||
;;
|
||||
"*")
|
||||
die "Arch ${sysInfo[1]} not supported"
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p "${GOPATH}/bin"
|
||||
|
||||
# Check curl
|
||||
if ! command -v "curl" >/dev/null; then
|
||||
die "Please install curl"
|
||||
fi
|
||||
|
||||
local yq_version=2.3.0
|
||||
|
||||
local yq_url="https://${yq_pkg}/releases/download/${yq_version}/yq_${goos}_${goarch}"
|
||||
curl -o "${yq_path}" -LSsf ${yq_url}
|
||||
[ $? -ne 0 ] && die "Download ${yq_url} failed"
|
||||
chmod +x ${yq_path}
|
||||
|
||||
if ! command -v "${yq_path}" >/dev/null; then
|
||||
die "Cannot not get ${yq_path} executable"
|
||||
fi
|
||||
}
|
||||
|
||||
install_yq
|
||||
|
566
tools/osbuilder/scripts/lib.sh
Normal file
566
tools/osbuilder/scripts/lib.sh
Normal file
@ -0,0 +1,566 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -e
|
||||
|
||||
GO_AGENT_PKG=${GO_AGENT_PKG:-github.com/kata-containers/agent}
|
||||
GO_RUNTIME_PKG=${GO_RUNTIME_PKG:-github.com/kata-containers/runtime}
|
||||
RUST_AGENT_PKG=${RUST_AGENT_PKG:-github.com/kata-containers/kata-rust-agent}
|
||||
CMAKE_VERSION=${CMAKE_VERSION:-"null"}
|
||||
MUSL_VERSION=${MUSL_VERSION:-"null"}
|
||||
#https://github.com/kata-containers/tests/blob/master/.ci/jenkins_job_build.sh
|
||||
# Give preference to variable set by CI
|
||||
KATA_BRANCH=${branch:-}
|
||||
KATA_BRANCH=${KATA_BRANCH:-master}
|
||||
yq_file="${script_dir}/../scripts/install-yq.sh"
|
||||
|
||||
error()
|
||||
{
|
||||
local msg="$*"
|
||||
echo "ERROR: ${msg}" >&2
|
||||
}
|
||||
|
||||
die()
|
||||
{
|
||||
error "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
OK()
|
||||
{
|
||||
local msg="$*"
|
||||
echo "[OK] ${msg}" >&2
|
||||
}
|
||||
|
||||
info()
|
||||
{
|
||||
local msg="$*"
|
||||
echo "INFO: ${msg}"
|
||||
}
|
||||
|
||||
warning()
|
||||
{
|
||||
local msg="$*"
|
||||
echo "WARNING: ${msg}"
|
||||
}
|
||||
|
||||
check_program()
|
||||
{
|
||||
type "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_root()
|
||||
{
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "Root is needed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
generate_dnf_config()
|
||||
{
|
||||
REPO_NAME=${REPO_NAME:-"base"}
|
||||
CACHE_DIR=${CACHE_DIR:-"/var/cache/dnf"}
|
||||
cat > "${DNF_CONF}" << EOF
|
||||
[main]
|
||||
cachedir=${CACHE_DIR}
|
||||
logfile=${LOG_FILE}
|
||||
keepcache=0
|
||||
debuglevel=2
|
||||
exactarch=1
|
||||
obsoletes=1
|
||||
plugins=0
|
||||
installonly_limit=3
|
||||
reposdir=/root/mash
|
||||
retries=5
|
||||
EOF
|
||||
if [ "$BASE_URL" != "" ]; then
|
||||
cat >> "${DNF_CONF}" << EOF
|
||||
|
||||
[base]
|
||||
name=${OS_NAME}-${OS_VERSION} ${REPO_NAME}
|
||||
failovermethod=priority
|
||||
baseurl=${BASE_URL}
|
||||
enabled=1
|
||||
EOF
|
||||
elif [ "$MIRROR_LIST" != "" ]; then
|
||||
cat >> "${DNF_CONF}" << EOF
|
||||
|
||||
[base]
|
||||
name=${OS_NAME}-${OS_VERSION} ${REPO_NAME}
|
||||
mirrorlist=${MIRROR_LIST}
|
||||
enabled=1
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -n "$GPG_KEY_URL" ]; then
|
||||
if [ ! -f "${CONFIG_DIR}/${GPG_KEY_FILE}" ]; then
|
||||
curl -L ${GPG_KEY_URL} -o ${CONFIG_DIR}/${GPG_KEY_FILE}
|
||||
fi
|
||||
cat >> "${DNF_CONF}" << EOF
|
||||
gpgcheck=1
|
||||
gpgkey=file://${CONFIG_DIR}/${GPG_KEY_FILE}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -n "$GPG_KEY_ARCH_URL" ]; then
|
||||
if [ ! -f "${CONFIG_DIR}/${GPG_KEY_ARCH_FILE}" ]; then
|
||||
curl -L ${GPG_KEY_ARCH_URL} -o ${CONFIG_DIR}/${GPG_KEY_ARCH_FILE}
|
||||
fi
|
||||
cat >> "${DNF_CONF}" << EOF
|
||||
file://${CONFIG_DIR}/${GPG_KEY_ARCH_FILE}
|
||||
EOF
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
build_rootfs()
|
||||
{
|
||||
# Mandatory
|
||||
local ROOTFS_DIR="$1"
|
||||
|
||||
[ -z "$ROOTFS_DIR" ] && die "need rootfs"
|
||||
|
||||
# In case of support EXTRA packages, use it to allow
|
||||
# users add more packages to the base rootfs
|
||||
local EXTRA_PKGS=${EXTRA_PKGS:-""}
|
||||
|
||||
#PATH where files this script is placed
|
||||
#Use it to refer to files in the same directory
|
||||
#Exmaple: ${CONFIG_DIR}/foo
|
||||
#local CONFIG_DIR=${CONFIG_DIR}
|
||||
|
||||
check_root
|
||||
if [ ! -f "${DNF_CONF}" ] && [ -z "${DISTRO_REPO}" ] ; then
|
||||
DNF_CONF="./kata-${OS_NAME}-dnf.conf"
|
||||
generate_dnf_config
|
||||
fi
|
||||
mkdir -p "${ROOTFS_DIR}"
|
||||
if [ -n "${PKG_MANAGER}" ]; then
|
||||
info "DNF path provided by user: ${PKG_MANAGER}"
|
||||
elif check_program "dnf"; then
|
||||
PKG_MANAGER="dnf"
|
||||
elif check_program "yum" ; then
|
||||
PKG_MANAGER="yum"
|
||||
else
|
||||
die "neither yum nor dnf is installed"
|
||||
fi
|
||||
|
||||
DNF="${PKG_MANAGER} -y --installroot=${ROOTFS_DIR} --noplugins"
|
||||
if [ -n "${DNF_CONF}" ] ; then
|
||||
DNF="${DNF} --config=${DNF_CONF}"
|
||||
else
|
||||
DNF="${DNF} --releasever=${OS_VERSION}"
|
||||
fi
|
||||
$DNF install ${EXTRA_PKGS} ${PACKAGES}
|
||||
}
|
||||
|
||||
# Create a YAML metadata file inside the rootfs.
|
||||
#
|
||||
# This provides useful information about the rootfs than can be interrogated
|
||||
# once the rootfs has been converted into a image/initrd.
|
||||
create_summary_file()
|
||||
{
|
||||
local -r rootfs_dir="$1"
|
||||
|
||||
[ -z "$rootfs_dir" ] && die "need rootfs"
|
||||
|
||||
local -r file_dir="/var/lib/osbuilder"
|
||||
local -r dir="${rootfs_dir}${file_dir}"
|
||||
|
||||
local -r filename="osbuilder.yaml"
|
||||
local file="${dir}/${filename}"
|
||||
|
||||
local -r now=$(date -u -d@${SOURCE_DATE_EPOCH:-$(date +%s.%N)} '+%Y-%m-%dT%T.%N%zZ')
|
||||
|
||||
# sanitise package lists
|
||||
PACKAGES=$(echo "$PACKAGES"|tr ' ' '\n'|sort -u|tr '\n' ' ')
|
||||
EXTRA_PKGS=$(echo "$EXTRA_PKGS"|tr ' ' '\n'|sort -u|tr '\n' ' ')
|
||||
|
||||
local -r packages=$(for pkg in ${PACKAGES}; do echo " - \"${pkg}\""; done)
|
||||
local -r extra=$(for pkg in ${EXTRA_PKGS}; do echo " - \"${pkg}\""; done)
|
||||
|
||||
mkdir -p "$dir"
|
||||
|
||||
# Semantic version of the summary file format.
|
||||
#
|
||||
# XXX: Increment every time the format of the summary file changes!
|
||||
local -r format_version="0.0.2"
|
||||
|
||||
local -r osbuilder_url="https://github.com/kata-containers/osbuilder"
|
||||
|
||||
local agent="${AGENT_DEST}"
|
||||
[ "$AGENT_INIT" = yes ] && agent="${init}"
|
||||
|
||||
local agent_version
|
||||
if [ "${RUST_AGENT}" == "no" ]; then
|
||||
agent_version=$("$agent" --version|awk '{print $NF}')
|
||||
else
|
||||
local -r agentdir="${GOPATH}/src/${RUST_AGENT_PKG}/src/agent"
|
||||
agent_version=$(cat ${agentdir}/VERSION)
|
||||
fi
|
||||
|
||||
local REAL_AGENT_PKG
|
||||
|
||||
if [ "$RUST_AGENT" == "no" ]; then
|
||||
REAL_AGENT_PKG=${GO_AGENT_PKG}
|
||||
else
|
||||
REAL_AGENT_PKG=${RUST_AGENT_PKG}
|
||||
fi
|
||||
|
||||
cat >"$file"<<-EOT
|
||||
---
|
||||
osbuilder:
|
||||
url: "${osbuilder_url}"
|
||||
version: "${OSBUILDER_VERSION}"
|
||||
rootfs-creation-time: "${now}"
|
||||
description: "osbuilder rootfs"
|
||||
file-format-version: "${format_version}"
|
||||
architecture: "${ARCH}"
|
||||
base-distro:
|
||||
name: "${OS_NAME}"
|
||||
version: "${OS_VERSION}"
|
||||
packages:
|
||||
default:
|
||||
${packages}
|
||||
extra:
|
||||
${extra}
|
||||
agent:
|
||||
url: "https://${REAL_AGENT_PKG}"
|
||||
name: "${AGENT_BIN}"
|
||||
version: "${agent_version}"
|
||||
agent-is-init-daemon: "${AGENT_INIT}"
|
||||
EOT
|
||||
|
||||
local rootfs_file="${file_dir}/$(basename "${file}")"
|
||||
info "Created summary file '${rootfs_file}' inside rootfs"
|
||||
}
|
||||
|
||||
# generate_dockerfile takes as only argument a path. It expects a Dockerfile.in
|
||||
# Dockerfile template to be present in that path, and will generate a usable
|
||||
# Dockerfile replacing the '@PLACEHOLDER@' in that Dockerfile
|
||||
generate_dockerfile()
|
||||
{
|
||||
dir="$1"
|
||||
[ -d "${dir}" ] || die "${dir}: not a directory"
|
||||
|
||||
local architecture=$(uname -m)
|
||||
local rustarch=${architecture}
|
||||
local muslarch=${architecture}
|
||||
case "$(uname -m)" in
|
||||
"ppc64le")
|
||||
goarch=ppc64le
|
||||
rustarch=powerpc64le
|
||||
muslarch=powerpc64
|
||||
;;
|
||||
|
||||
"aarch64")
|
||||
goarch=arm64
|
||||
;;
|
||||
"s390x")
|
||||
goarch=s390x
|
||||
;;
|
||||
|
||||
*)
|
||||
goarch=amd64
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -n "${http_proxy:-}" ] && readonly set_proxy="RUN sed -i '$ a proxy="${http_proxy:-}"' /etc/dnf/dnf.conf /etc/yum.conf; true"
|
||||
|
||||
curlOptions=("-OL")
|
||||
[ -n "${http_proxy:-}" ] && curlOptions+=("-x ${http_proxy:-}")
|
||||
|
||||
readonly install_go="
|
||||
RUN cd /tmp ; curl ${curlOptions[@]} https://storage.googleapis.com/golang/go${GO_VERSION}.linux-${goarch}.tar.gz
|
||||
RUN tar -C /usr/ -xzf /tmp/go${GO_VERSION}.linux-${goarch}.tar.gz
|
||||
ENV GOROOT=/usr/go
|
||||
ENV PATH=\$PATH:\$GOROOT/bin:\$GOPATH/bin
|
||||
"
|
||||
|
||||
# Rust agent
|
||||
# rust installer should set path apropiately, just in case
|
||||
local cmake_file="cmake-${CMAKE_VERSION}.tar.gz"
|
||||
local cmake_dir="cmake-${CMAKE_VERSION}"
|
||||
readonly install_cmake="
|
||||
RUN pushd /root; \
|
||||
curl -sLO https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${cmake_file}; \
|
||||
tar -zxf ${cmake_file}; \
|
||||
cd ${cmake_dir}; \
|
||||
./bootstrap > /dev/null 2>\&1; \
|
||||
make > /dev/null 2>\&1; \
|
||||
make install > /dev/null 2>\&1; \
|
||||
popd
|
||||
"
|
||||
# install musl for compiling rust-agent
|
||||
install_musl=
|
||||
if [ "${muslarch}" == "aarch64" ]; then
|
||||
local musl_tar="${muslarch}-linux-musl-native.tgz"
|
||||
local musl_dir="${muslarch}-linux-musl-native"
|
||||
install_musl="
|
||||
RUN cd /tmp; \
|
||||
curl -sLO https://musl.cc/${musl_tar}; tar -zxf ${musl_tar}; \
|
||||
mkdir -p /usr/local/musl/; \
|
||||
cp -r ${musl_dir}/* /usr/local/musl/
|
||||
ENV PATH=\$PATH:/usr/local/musl/bin
|
||||
RUN ln -sf /usr/local/musl/bin/g++ /usr/bin/g++
|
||||
"
|
||||
else
|
||||
local musl_tar="musl-${MUSL_VERSION}.tar.gz"
|
||||
local musl_dir="musl-${MUSL_VERSION}"
|
||||
install_musl="
|
||||
RUN pushd /root; \
|
||||
curl -sLO https://www.musl-libc.org/releases/${musl_tar}; tar -zxf ${musl_tar}; \
|
||||
cd ${musl_dir}; \
|
||||
sed -i \"s/^ARCH = .*/ARCH = ${muslarch}/g\" dist/config.mak; \
|
||||
./configure > /dev/null 2>\&1; \
|
||||
make > /dev/null 2>\&1; \
|
||||
make install > /dev/null 2>\&1; \
|
||||
echo \"/usr/local/musl/lib\" > /etc/ld-musl-${muslarch}.path; \
|
||||
popd
|
||||
ENV PATH=\$PATH:/usr/local/musl/bin
|
||||
"
|
||||
fi
|
||||
|
||||
readonly install_rust="
|
||||
RUN curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSLf --output /tmp/rust-init; \
|
||||
chmod a+x /tmp/rust-init; \
|
||||
export http_proxy=${http_proxy:-}; \
|
||||
export https_proxy=${http_proxy:-}; \
|
||||
/tmp/rust-init -y
|
||||
RUN . /root/.cargo/env; \
|
||||
export http_proxy=${http_proxy:-}; \
|
||||
export https_proxy=${http_proxy:-}; \
|
||||
cargo install cargo-when; \
|
||||
rustup toolchain install ${RUST_VERSION}; \
|
||||
rustup default ${RUST_VERSION}; \
|
||||
rustup target install ${rustarch}-unknown-linux-musl
|
||||
RUN ln -sf /usr/bin/g++ /bin/musl-g++
|
||||
"
|
||||
# rust agent still need go to build
|
||||
# because grpc-sys need go to build
|
||||
pushd ${dir}
|
||||
dockerfile_template="Dockerfile.in"
|
||||
dockerfile_arch_template="Dockerfile-${architecture}.in"
|
||||
# if arch-specific docker file exists, swap the univesal one with it.
|
||||
if [ -f "${dockerfile_arch_template}" ]; then
|
||||
dockerfile_template="${dockerfile_arch_template}"
|
||||
else
|
||||
[ -f "${dockerfile_template}" ] || die "${dockerfile_template}: file not found"
|
||||
fi
|
||||
|
||||
# powerpc have no musl target, don't setup rust enviroment
|
||||
# since we cannot static link agent. Besides, there is
|
||||
# also long double representation problem when building musl-libc
|
||||
if [ "${architecture}" == "ppc64le" ] || [ "${architecture}" == "s390x" ]; then
|
||||
sed \
|
||||
-e "s|@GO_VERSION@|${GO_VERSION}|g" \
|
||||
-e "s|@OS_VERSION@|${OS_VERSION:-}|g" \
|
||||
-e "s|@INSTALL_CMAKE@||g" \
|
||||
-e "s|@INSTALL_MUSL@||g" \
|
||||
-e "s|@INSTALL_GO@|${install_go//$'\n'/\\n}|g" \
|
||||
-e "s|@INSTALL_RUST@||g" \
|
||||
-e "s|@SET_PROXY@|${set_proxy:-}|g" \
|
||||
${dockerfile_template} > Dockerfile
|
||||
else
|
||||
sed \
|
||||
-e "s|@GO_VERSION@|${GO_VERSION}|g" \
|
||||
-e "s|@OS_VERSION@|${OS_VERSION:-}|g" \
|
||||
-e "s|@INSTALL_CMAKE@|${install_cmake//$'\n'/\\n}|g" \
|
||||
-e "s|@INSTALL_MUSL@|${install_musl//$'\n'/\\n}|g" \
|
||||
-e "s|@INSTALL_GO@|${install_go//$'\n'/\\n}|g" \
|
||||
-e "s|@INSTALL_RUST@|${install_rust//$'\n'/\\n}|g" \
|
||||
-e "s|@SET_PROXY@|${set_proxy:-}|g" \
|
||||
${dockerfile_template} > Dockerfile
|
||||
fi
|
||||
popd
|
||||
}
|
||||
|
||||
detect_go_version()
|
||||
{
|
||||
info "Detecting agent go version"
|
||||
typeset yq=$(command -v yq || command -v ${GOPATH}/bin/yq || echo "${GOPATH}/bin/yq")
|
||||
if [ ! -f "$yq" ]; then
|
||||
source "$yq_file"
|
||||
fi
|
||||
|
||||
local runtimeRevision=""
|
||||
|
||||
# Detect runtime revision by fetching the agent's VERSION file
|
||||
local runtime_version_url="https://raw.githubusercontent.com/kata-containers/agent/${AGENT_VERSION:-master}/VERSION"
|
||||
info "Detecting runtime version using ${runtime_version_url}"
|
||||
|
||||
if runtimeRevision="$(curl -fsSL ${runtime_version_url})"; then
|
||||
[ -n "${runtimeRevision}" ] || die "failed to get agent version"
|
||||
typeset -r runtimeVersionsURL="https://raw.githubusercontent.com/kata-containers/runtime/${runtimeRevision}/versions.yaml"
|
||||
info "Getting golang version from ${runtimeVersionsURL}"
|
||||
# This may fail if we are a kata bump.
|
||||
if GO_VERSION="$(curl -fsSL "$runtimeVersionsURL" | $yq r - "languages.golang.version")"; then
|
||||
[ "$GO_VERSION" != "null" ]
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Agent version has not match with a runtime version, assumming it is a PR"
|
||||
local kata_runtime_pkg_dir="${GOPATH}/src/${GO_RUNTIME_PKG}"
|
||||
if [ ! -d "${kata_runtime_pkg_dir}" ];then
|
||||
info "There is not runtime repository in filesystem (${kata_runtime_pkg_dir})"
|
||||
local runtime_versions_url="https://raw.githubusercontent.com/kata-containers/runtime/${KATA_BRANCH}/versions.yaml"
|
||||
info "Get versions file from ${runtime_versions_url}"
|
||||
GO_VERSION="$(curl -fsSL "${runtime_versions_url}" | $yq r - "languages.golang.version")"
|
||||
if [ "$?" == "0" ] && [ "$GO_VERSION" != "null" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
local kata_versions_file="${kata_runtime_pkg_dir}/versions.yaml"
|
||||
info "Get Go version from ${kata_versions_file}"
|
||||
GO_VERSION="$(cat "${kata_versions_file}" | $yq r - "languages.golang.version")"
|
||||
|
||||
[ "$?" == "0" ] && [ "$GO_VERSION" != "null" ]
|
||||
}
|
||||
|
||||
detect_rust_version()
|
||||
{
|
||||
info "Detecting agent rust version"
|
||||
typeset -r yq=$(command -v yq || command -v ${GOPATH}/bin/yq || echo "${GOPATH}/bin/yq")
|
||||
if [ ! -f "$yq" ]; then
|
||||
source "$yq_file"
|
||||
fi
|
||||
|
||||
local runtimeRevision=""
|
||||
|
||||
# Detect runtime revision by fetching the agent's VERSION file
|
||||
local runtime_version_url="https://raw.githubusercontent.com/kata-containers/agent/${AGENT_VERSION:-master}/VERSION"
|
||||
info "Detecting runtime version using ${runtime_version_url}"
|
||||
|
||||
if runtimeRevision="$(curl -fsSL ${runtime_version_url})"; then
|
||||
[ -n "${runtimeRevision}" ] || die "failed to get agent version"
|
||||
typeset -r runtimeVersionsURL="https://raw.githubusercontent.com/kata-containers/runtime/${runtimeRevision}/versions.yaml"
|
||||
info "Getting rust version from ${runtimeVersionsURL}"
|
||||
# This may fail if we are a kata bump.
|
||||
if RUST_VERSION="$(curl -fsSL "$runtimeVersionsURL" | $yq r - "languages.rust.version")"; then
|
||||
[ "$RUST_VERSION" != "null" ]
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Agent version has not match with a runtime version, assumming it is a PR"
|
||||
local kata_runtime_pkg_dir="${GOPATH}/src/${GO_RUNTIME_PKG}"
|
||||
if [ ! -d "${kata_runtime_pkg_dir}" ];then
|
||||
info "There is not runtime repository in filesystem (${kata_runtime_pkg_dir})"
|
||||
local runtime_versions_url="https://raw.githubusercontent.com/kata-containers/runtime/${KATA_BRANCH}/versions.yaml"
|
||||
info "Get versions file from ${runtime_versions_url}"
|
||||
RUST_VERSION="$(curl -fsSL "${runtime_versions_url}" | $yq r - "languages.rust.version")"
|
||||
if [ "$?" == "0" ] && [ "$RUST_VERSION" != "null" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
local kata_versions_file="${kata_runtime_pkg_dir}/versions.yaml"
|
||||
info "Get rust version from ${kata_versions_file}"
|
||||
RUST_VERSION="$(cat "${kata_versions_file}" | $yq r - "languages.rust.version")"
|
||||
|
||||
[ "$?" == "0" ] && [ "$RUST_VERSION" != "null" ]
|
||||
}
|
||||
|
||||
detect_cmake_version()
|
||||
{
|
||||
info "Detecting cmake version"
|
||||
|
||||
typeset -r yq=$(command -v yq || command -v ${GOPATH}/bin/yq || echo "${GOPATH}/bin/yq")
|
||||
if [ ! -f "$yq" ]; then
|
||||
source "$yq_file"
|
||||
fi
|
||||
|
||||
local runtimeRevision=""
|
||||
|
||||
# Detect runtime revision by fetching the agent's VERSION file
|
||||
local runtime_version_url="https://raw.githubusercontent.com/kata-containers/agent/${AGENT_VERSION:-master}/VERSION"
|
||||
info "Detecting runtime version using ${runtime_version_url}"
|
||||
|
||||
if runtimeRevision="$(curl -fsSL ${runtime_version_url})"; then
|
||||
[ -n "${runtimeRevision}" ] || die "failed to get agent version"
|
||||
typeset -r runtimeVersionsURL="https://raw.githubusercontent.com/kata-containers/runtime/${runtimeRevision}/versions.yaml"
|
||||
info "Getting cmake version from ${runtimeVersionsURL}"
|
||||
# This may fail if we are a kata bump.
|
||||
if CMAKE_VERSION="$(curl -fsSL "$runtimeVersionsURL" | $yq r - "externals.cmake.version")"; then
|
||||
[ "$CMAKE_VERSION" != "null" ]
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Agent version has not match with a runtime version, assumming it is a PR"
|
||||
local kata_runtime_pkg_dir="${GOPATH}/src/${GO_RUNTIME_PKG}"
|
||||
if [ ! -d "${kata_runtime_pkg_dir}" ];then
|
||||
info "There is not runtime repository in filesystem (${kata_runtime_pkg_dir})"
|
||||
local runtime_versions_url="https://raw.githubusercontent.com/kata-containers/runtime/${KATA_BRANCH}/versions.yaml"
|
||||
info "Get versions file from ${runtime_versions_url}"
|
||||
CMAKE_VERSION="$(curl -fsSL "${runtime_versions_url}" | $yq r - "externals.cmake.version")"
|
||||
if [ "$?" == "0" ] && [ "$CMAKE_VERSION" != "null" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
local kata_versions_file="${kata_runtime_pkg_dir}/versions.yaml"
|
||||
info "Get cmake version from ${kata_versions_file}"
|
||||
CMAKE_VERSION="$(cat "${kata_versions_file}" | $yq r - "externals.cmake.version")"
|
||||
|
||||
[ "$?" == "0" ] && [ "$CMAKE_VERSION" != "null" ]
|
||||
}
|
||||
|
||||
detect_musl_version()
|
||||
{
|
||||
info "Detecting musl version"
|
||||
|
||||
typeset -r yq=$(command -v yq || command -v ${GOPATH}/bin/yq || echo "${GOPATH}/bin/yq")
|
||||
if [ ! -f "$yq" ]; then
|
||||
source "$yq_file"
|
||||
fi
|
||||
|
||||
local runtimeRevision=""
|
||||
|
||||
# Detect runtime revision by fetching the agent's VERSION file
|
||||
local runtime_version_url="https://raw.githubusercontent.com/kata-containers/agent/${AGENT_VERSION:-master}/VERSION"
|
||||
info "Detecting runtime version using ${runtime_version_url}"
|
||||
|
||||
if runtimeRevision="$(curl -fsSL ${runtime_version_url})"; then
|
||||
[ -n "${runtimeRevision}" ] || die "failed to get agent version"
|
||||
typeset -r runtimeVersionsURL="https://raw.githubusercontent.com/kata-containers/runtime/${runtimeRevision}/versions.yaml"
|
||||
info "Getting musl version from ${runtimeVersionsURL}"
|
||||
# This may fail if we are a kata bump.
|
||||
if MUSL_VERSION="$(curl -fsSL "$runtimeVersionsURL" | $yq r - "externals.musl.version")"; then
|
||||
[ "$MUSL_VERSION" != "null" ]
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Agent version has not match with a runtime version, assumming it is a PR"
|
||||
local kata_runtime_pkg_dir="${GOPATH}/src/${GO_RUNTIME_PKG}"
|
||||
if [ ! -d "${kata_runtime_pkg_dir}" ];then
|
||||
info "There is not runtime repository in filesystem (${kata_runtime_pkg_dir})"
|
||||
local runtime_versions_url="https://raw.githubusercontent.com/kata-containers/runtime/${KATA_BRANCH}/versions.yaml"
|
||||
info "Get versions file from ${runtime_versions_url}"
|
||||
MUSL_VERSION="$(curl -fsSL "${runtime_versions_url}" | $yq r - "externals.musl.version")"
|
||||
if [ "$?" == "0" ] && [ "$MUSL_VERSION" != "null" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
local kata_versions_file="${kata_runtime_pkg_dir}/versions.yaml"
|
||||
info "Get musl version from ${kata_versions_file}"
|
||||
MUSL_VERSION="$(cat "${kata_versions_file}" | $yq r - "externals.musl.version")"
|
||||
|
||||
[ "$?" == "0" ] && [ "$MUSL_VERSION" != "null" ]
|
||||
}
|
32
tools/osbuilder/tests/README.md
Normal file
32
tools/osbuilder/tests/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
* [Run the osbuilder tests](#run-the-osbuilder-tests)
|
||||
* [Further information](#further-information)
|
||||
|
||||
## Run the osbuilder tests
|
||||
|
||||
osbuilder provides a test script that creates all rootfs disk images and
|
||||
initrd images for all supported distributions and then tests them to ensure a
|
||||
Kata Container can be created with each.
|
||||
|
||||
Before the build phase, the test script installs the Docker container manager
|
||||
and all the Kata components required to run test containers. Individual tests
|
||||
will also alter host `kata-runtime` and `docker` service configuration as needed.
|
||||
|
||||
All host config editing can be skipped by setting the environment variable
|
||||
`KATA_DEV_MODE` to a non-empty value. In this mode, image/initrd targets
|
||||
will be built but not runtime tested; If your host is configured to have
|
||||
`kata-runtime` set as the default docker runtime, you will need to switch
|
||||
to a runtime like `runc`/`crun` so the `docker build` test commands work
|
||||
correctly.
|
||||
|
||||
```
|
||||
$ ./test_images.sh
|
||||
```
|
||||
|
||||
## Further information
|
||||
|
||||
The test script provides various options to modify the way it runs. For full
|
||||
details:
|
||||
|
||||
```
|
||||
$ ./test_images.sh -h
|
||||
```
|
68
tools/osbuilder/tests/test_config.sh
Normal file
68
tools/osbuilder/tests/test_config.sh
Normal file
@ -0,0 +1,68 @@
|
||||
#
|
||||
# Copyright (c) 2018 SUSE LLC
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# List of distros not to test, when running all tests with test_images.sh
|
||||
typeset -a skipWhenTestingAll
|
||||
typeset -a distros
|
||||
arch="$(uname -m)"
|
||||
sdir="${BASH_SOURCE[0]%/*}"
|
||||
for distro in $(${sdir}/../rootfs-builder/rootfs.sh -l); do
|
||||
distros+=("${distro}")
|
||||
done
|
||||
test_distros=()
|
||||
test_distros+=("clearlinux")
|
||||
test_distros+=("ubuntu")
|
||||
|
||||
skipForRustDistros=()
|
||||
skipForRustDistros+=("alpine")
|
||||
skipForRustDistros+=("euleros")
|
||||
|
||||
skipForRustArch=()
|
||||
skipForRustArch+=("ppc64le")
|
||||
skipForRustArch+=("s390x")
|
||||
|
||||
distro_in_set() {
|
||||
local d=$1
|
||||
shift
|
||||
local dt
|
||||
for dt in "$@"; do
|
||||
if [ "${dt}" == "${d}" ]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -n "${CI:-}" ]; then
|
||||
# CI tests may timeout with euleros, see:
|
||||
# https://github.com/kata-containers/osbuilder/issues/46"
|
||||
# Since too many distros timeout for now, we only test clearlinux and ubuntu. We can enable other distros when we fix timeout problem.
|
||||
for distro in "${distros[@]}"; do
|
||||
if distro_in_set "${distro}" "${test_distros[@]}"; then
|
||||
continue
|
||||
fi
|
||||
skipWhenTestingAll+=("${distro}")
|
||||
done
|
||||
|
||||
if [ "${RUST_AGENT:-}" == "yes" ]; then
|
||||
# add skipForRustDistros to skipWhenTestingAll if it is not
|
||||
for td in "${skipForRustDistros[@]}"; do
|
||||
if distro_in_set "${td}" "${skipWhenTestingAll[@]}"; then
|
||||
continue
|
||||
fi
|
||||
# not found in skipWhenTestingAll, add to it
|
||||
skipWhenTestingAll+=("${td}")
|
||||
done
|
||||
|
||||
if distro_in_set "${arch}" "${skipForRustArch[@]}"; then
|
||||
for distro in "${test_distros[@]}"; do
|
||||
if distro_in_set "${distro}" "${skipWhenTestingAll[@]}"; then
|
||||
continue
|
||||
fi
|
||||
skipWhenTestingAll+=("${distro}")
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
750
tools/osbuilder/tests/test_images.sh
Executable file
750
tools/osbuilder/tests/test_images.sh
Executable file
@ -0,0 +1,750 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
[ -n "${DEBUG:-}" ] && set -o xtrace
|
||||
|
||||
readonly script_dir="$(dirname $(readlink -f $0))"
|
||||
readonly script_name=${0##*/}
|
||||
readonly project_dir="$(dirname ${script_dir})"
|
||||
readonly tmp_dir=$(mktemp -t -d osbuilder-test.XXXXXXX)
|
||||
readonly tmp_rootfs="${tmp_dir}/rootfs-osbuilder"
|
||||
readonly images_dir="${tmp_dir}/images"
|
||||
readonly osbuilder_file="/var/lib/osbuilder/osbuilder.yaml"
|
||||
readonly docker_image="busybox"
|
||||
readonly systemd_docker_config_file="/etc/systemd/system/docker.service.d/kata-containers.conf"
|
||||
readonly sysconfig_docker_config_file="/etc/sysconfig/docker"
|
||||
readonly tests_repo="github.com/kata-containers/tests"
|
||||
readonly tests_repo_dir="${project_dir}/../tests"
|
||||
readonly mgr="${tests_repo_dir}/cmd/kata-manager/kata-manager.sh"
|
||||
readonly test_config=${script_dir}/test_config.sh
|
||||
readonly rootfs_builder=${project_dir}/rootfs-builder/rootfs.sh
|
||||
readonly DOCKER_RUNTIME=${DOCKER_RUNTIME:-runc}
|
||||
readonly RUNTIME=${RUNTIME:-kata-runtime}
|
||||
readonly MACHINE_TYPE=`uname -m`
|
||||
readonly CI=${CI:-}
|
||||
readonly KATA_HYPERVISOR="${KATA_HYPERVISOR:-}"
|
||||
readonly KATA_DEV_MODE="${KATA_DEV_MODE:-}"
|
||||
readonly ci_results_dir="/var/osbuilder/tests"
|
||||
readonly dracut_dir=${project_dir}/dracut
|
||||
|
||||
build_images=1
|
||||
build_initrds=1
|
||||
typeset -a distrosSystemd distrosAgent
|
||||
distrosSystemd=()
|
||||
distrosAgent=()
|
||||
# Hashes used to keep track of image sizes.
|
||||
# - Key: name of distro.
|
||||
# - Value: colon-separated roots and image sizes ("${rootfs_size}:${image_size}").
|
||||
typeset -A built_images
|
||||
typeset -A built_initrds
|
||||
|
||||
# If set, show the reason why a container using the built images/initrds could
|
||||
# not be started. Needed only after all images/initrd built successfully
|
||||
typeset -A showKataRunFailure=
|
||||
|
||||
source ${test_config}
|
||||
source "${project_dir}/scripts/lib.sh"
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOT
|
||||
Usage: $script_name [options] [command | <distro>]
|
||||
|
||||
Options:
|
||||
-h | --help # Show usage.
|
||||
--list # List all distros that can be tested.
|
||||
--test-images-only # Only run images tests for the list of distros under test.
|
||||
--test-initrds-only # Only run initrds tests for the list of distros under test.
|
||||
|
||||
Commands:
|
||||
help : Show usage.
|
||||
|
||||
|
||||
When <distro> is specified, tests are run only for the specified <distro>.
|
||||
Otherwise, tests are run on all distros.
|
||||
|
||||
$(basename ${test_config}) includes a list of distros to exclude from testing,
|
||||
depending on the detected test environment. However, when a <distro> is specified,
|
||||
distro exclusion based on $(basename ${test_config}) is not enforced.
|
||||
EOT
|
||||
}
|
||||
|
||||
# Add an entry to the specified stats file
|
||||
add_to_stats_file()
|
||||
{
|
||||
local statsfile="$1"
|
||||
local name="$2"
|
||||
local entry="$3"
|
||||
local entry_type="$4"
|
||||
|
||||
local rootfs_size_bytes
|
||||
local rootfs_size_mb
|
||||
|
||||
local image_size_bytes
|
||||
local image_size_mb
|
||||
|
||||
rootfs_size_bytes=$(echo "$entry"|cut -d: -f1)
|
||||
image_size_bytes=$(echo "$entry"|cut -d: -f2)
|
||||
|
||||
rootfs_size_mb=$(bc <<< "scale=2; ${rootfs_size_bytes} / 2^20")
|
||||
image_size_mb=$(bc <<< "scale=2; ${image_size_bytes} / 2^20")
|
||||
|
||||
printf '%12.12s\t%10.10s\t%12.12s\t%10.10s\t%-8.8s\t%-20.20s\n' \
|
||||
"${image_size_bytes}" \
|
||||
"${image_size_mb}" \
|
||||
"${rootfs_size_bytes}" \
|
||||
"${rootfs_size_mb}" \
|
||||
"${entry_type}" \
|
||||
"${name}" >> "$statsfile"
|
||||
}
|
||||
|
||||
# Show the sizes of all the generated initrds and images
|
||||
show_stats()
|
||||
{
|
||||
local name
|
||||
local sizes
|
||||
|
||||
local tmpfile=$(mktemp)
|
||||
|
||||
# images
|
||||
for name in "${!built_images[@]}"
|
||||
do
|
||||
sizes=${built_images[$name]}
|
||||
add_to_stats_file "$tmpfile" "$name" "$sizes" 'image'
|
||||
done
|
||||
|
||||
# initrds
|
||||
if [ "$KATA_HYPERVISOR" != "firecracker" ]; then
|
||||
for name in "${!built_initrds[@]}"
|
||||
do
|
||||
sizes=${built_initrds[$name]}
|
||||
add_to_stats_file "$tmpfile" "$name" "$sizes" 'initrd'
|
||||
done
|
||||
fi
|
||||
|
||||
info "Image and rootfs sizes (in bytes and MB), smallest image first:"
|
||||
echo
|
||||
|
||||
printf '%12.12s\t%10.10s\t%12.12s\t%10.10s\t%-8.8s\t%-20.20s\n' \
|
||||
"image-bytes" \
|
||||
"image-MB" \
|
||||
"rootfs-bytes" \
|
||||
"rootfs-MB" \
|
||||
"Type" \
|
||||
"Name"
|
||||
|
||||
sort -k1,1n -k3,3n "$tmpfile"
|
||||
|
||||
rm -f "${tmpfile}"
|
||||
}
|
||||
|
||||
|
||||
# Run a kata-manager.sh command
|
||||
run_mgr()
|
||||
{
|
||||
[ -n "${KATA_DEV_MODE:-}" ] && return
|
||||
silent_run $mgr $*
|
||||
}
|
||||
|
||||
|
||||
exit_handler()
|
||||
{
|
||||
if [ "$?" -eq 0 ]
|
||||
then
|
||||
info "tests passed successfully - cleaning up"
|
||||
|
||||
# Rootfs and images are owned by root
|
||||
sudo -E rm -rf "${tmp_rootfs}"
|
||||
sudo -E rm -rf "${images_dir}"
|
||||
|
||||
rm -rf "${tmp_dir}"
|
||||
|
||||
# Restore the default image in config file
|
||||
[ -n "${TRAVIS:-}" ] || run_mgr configure-image
|
||||
|
||||
return
|
||||
fi
|
||||
|
||||
info "ERROR: test failed"
|
||||
|
||||
# The test failed so dump what we can
|
||||
if [ -d "${tmp_rootfs}" ]; then
|
||||
info "rootfs:"
|
||||
sudo -E ls -l "${tmp_rootfs}" >&2
|
||||
sudo -E rm -rf "${tmp_rootfs}"
|
||||
else
|
||||
info "no rootfs created"
|
||||
# If no rootfs are created, no need to dump other info
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -d "${images_dir}" ]; then
|
||||
info "images:"
|
||||
sudo -E ls -l "${images_dir}" >&2
|
||||
sudo -E rm -rf "${images_dir}"
|
||||
else
|
||||
info "no images created"
|
||||
# If no images are created, no need to dump other info
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "${showKataRunFailure}" ]; then
|
||||
# Restore the default image in config file
|
||||
run_mgr configure-image
|
||||
return
|
||||
fi
|
||||
|
||||
info "local runtime config:"
|
||||
cat /etc/kata-containers/configuration.toml >&2
|
||||
|
||||
info "main runtime config:"
|
||||
cat /usr/share/defaults/kata-containers/configuration.toml >&2
|
||||
|
||||
info "collect script output:"
|
||||
sudo -E kata-collect-data.sh >&2
|
||||
|
||||
info "processes:"
|
||||
sudo -E ps -efwww | egrep "docker|kata" >&2
|
||||
|
||||
# Restore the default image in config file
|
||||
run_mgr configure-image
|
||||
}
|
||||
|
||||
die()
|
||||
{
|
||||
msg="$*"
|
||||
echo "ERROR: $msg" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
info()
|
||||
{
|
||||
s="$*"
|
||||
echo -en "INFO: $s\n" >&2
|
||||
}
|
||||
|
||||
debug()
|
||||
{
|
||||
[ -z "${TEST_DEBUG:-}" ] && return
|
||||
s="$*"
|
||||
echo -e "DBG: $s" >&2
|
||||
}
|
||||
|
||||
# Run a command in silent mode using chronic.
|
||||
# The command output is printed only if the command fails
|
||||
silent_run()
|
||||
{
|
||||
typeset -a commandLine=("$@")
|
||||
info "running: ${commandLine[@]}"
|
||||
if [ -z "${DEBUG:-}" ]; then
|
||||
chronic "${commandLine[@]}"
|
||||
else
|
||||
"${commandLine[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
set_runtime()
|
||||
{
|
||||
local name="$1"
|
||||
|
||||
[ -z "$name" ] && die "need name"
|
||||
|
||||
[ -n "${KATA_DEV_MODE}" ] && return
|
||||
|
||||
# Travis doesn't support VT-x
|
||||
[ -n "${TRAVIS:-}" ] && return
|
||||
|
||||
if [ "$KATA_HYPERVISOR" != "firecracker" ]; then
|
||||
if [ -f "$sysconfig_docker_config_file" ]; then
|
||||
docker_config_file="$sysconfig_docker_config_file"
|
||||
sed_script="s|^( *DOCKER_OPTS=.+--default-runtime[= ] *)[^ \"]+(.*\"$)|\1${name}\2|g"
|
||||
else
|
||||
docker_config_file="$systemd_docker_config_file"
|
||||
sed_script="s/--default-runtime[= ][^ ]*/--default-runtime=${name}/g"
|
||||
fi
|
||||
|
||||
sudo -E sed -i -E "$sed_script" "$docker_config_file"
|
||||
sudo -E systemctl daemon-reload
|
||||
sudo -E systemctl restart docker
|
||||
fi
|
||||
}
|
||||
|
||||
setup()
|
||||
{
|
||||
mkdir -p "${images_dir}"
|
||||
|
||||
if [ -n "$CI" ]; then
|
||||
sudo -E rm -rf ${ci_results_dir}
|
||||
sudo -E mkdir -p ${ci_results_dir}
|
||||
fi
|
||||
|
||||
# Travis doesn't support VT-x
|
||||
[ -n "${TRAVIS:-}" ] && return
|
||||
|
||||
[ ! -d "${tests_repo_dir}" ] && git clone "https://${tests_repo}" "${tests_repo_dir}"
|
||||
|
||||
if [ -z "${KATA_DEV_MODE}" ]; then
|
||||
mkdir -p /etc/kata-containers/
|
||||
sudo cp -a /usr/share/defaults/kata-containers/configuration.toml /etc/kata-containers/configuration.toml
|
||||
else
|
||||
info "Running with KATA_DEV_MODE set, skipping installation of docker and kata packages"
|
||||
fi
|
||||
run_mgr enable-debug
|
||||
|
||||
# "docker build" does not work with a VM-based runtime, and
|
||||
# also does not accept a --runtime option, so our only
|
||||
# option is to overwrite the system docker default runtime
|
||||
set_runtime "${DOCKER_RUNTIME}"
|
||||
}
|
||||
|
||||
# Fetches the distros test configuration from the distro-specific config.sh file.
|
||||
# $1 : only fetch configuration for the distro with name $1. When not specified,
|
||||
# fetch configuration for all distros.
|
||||
get_distros_config()
|
||||
{
|
||||
local distro="$1"
|
||||
local distrosList
|
||||
local -A distroCfg=(\
|
||||
[INIT_PROCESS]=\
|
||||
[ARCH_EXCLUDE_LIST]=\
|
||||
)
|
||||
|
||||
if [ -n "$distro" ]; then
|
||||
distrosList=("$distro")
|
||||
# When specifying a single distro name, skip does not apply
|
||||
skipWhenTestingAll=()
|
||||
else
|
||||
distrosList=($(make list-distros))
|
||||
fi
|
||||
|
||||
for d in ${distrosList[@]:-}; do
|
||||
debug "Getting config for distro $d"
|
||||
distroPattern="\<${d}\>"
|
||||
if [[ "${skipWhenTestingAll[@]:-}" =~ $distroPattern ]]; then
|
||||
info "Skipping distro $d as specified by $(basename ${test_config})"
|
||||
continue
|
||||
fi
|
||||
|
||||
tmpfile=$(mktemp /tmp/osbuilder-$d-config.XXX)
|
||||
${rootfs_builder} -t $d > $tmpfile
|
||||
# Get value of all keys in distroCfg
|
||||
for k in ${!distroCfg[@]}; do
|
||||
distroCfg[$k]="$(awk -v cfgKey=$k 'BEGIN{FS=":\t+"}{if ($1 == cfgKey) print $2}' $tmpfile)"
|
||||
debug "distroCfg[$k]=${distroCfg[$k]}"
|
||||
done
|
||||
rm -f $tmpfile
|
||||
|
||||
machinePattern="\<${MACHINE_TYPE}\>"
|
||||
if [[ "${distroCfg[ARCH_EXCLUDE_LIST]}" =~ $machinePattern ]]; then
|
||||
info "Skipping distro $d on architecture $MACHINE_TYPE"
|
||||
continue
|
||||
fi
|
||||
|
||||
case "${distroCfg[INIT_PROCESS]}" in
|
||||
systemd) distrosSystemd+=($d) ;;
|
||||
kata-agent) distrosAgent+=($d) ;;
|
||||
*) die "Invalid init process specified for distro $d: \"${distroCfg[INIT_PROCESS]}\"" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
create_container()
|
||||
{
|
||||
# If KATA_DEV_MODE is set, we don't have any way to point kata-runtime
|
||||
# at the image/initrd to boot, so there's nothing to do
|
||||
[ -n "${KATA_DEV_MODE}" ] && return
|
||||
|
||||
out=$(mktemp)
|
||||
|
||||
local file="/proc/version"
|
||||
|
||||
# Create a container using the runtime under test which displays a
|
||||
# file that is expected to exist.
|
||||
docker run --rm -i --runtime "${RUNTIME}" "$docker_image" cat "${file}" > "$out"
|
||||
|
||||
info "contents of docker image ${docker_image} container file '${file}':"
|
||||
cat "${out}" >&2
|
||||
|
||||
[ -s "$out" ]
|
||||
rm -f "$out"
|
||||
}
|
||||
|
||||
install_image_create_container()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
[ -z "$file" ] && die "need file"
|
||||
[ ! -e "$file" ] && die "file does not exist: $file"
|
||||
|
||||
# Travis doesn't support VT-x
|
||||
[ -n "${TRAVIS:-}" ] && return
|
||||
|
||||
showKataRunFailure=1
|
||||
run_mgr reset-config
|
||||
if [ "${RUST_AGENT:-}" = "yes" ]; then
|
||||
run_mgr enable-vsock
|
||||
fi
|
||||
run_mgr configure-image "$file"
|
||||
create_container
|
||||
showKataRunFailure=
|
||||
}
|
||||
|
||||
install_initrd_create_container()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
[ -z "$file" ] && die "need file"
|
||||
[ ! -e "$file" ] && die "file does not exist: $file"
|
||||
|
||||
# Travis doesn't support VT-x
|
||||
[ -n "${TRAVIS:-}" ] && return
|
||||
|
||||
showKataRunFailure=1
|
||||
run_mgr reset-config
|
||||
if [ "${RUST_AGENT:-}" = "yes" ]; then
|
||||
run_mgr enable-vsock
|
||||
fi
|
||||
run_mgr configure-initrd "$file"
|
||||
create_container
|
||||
showKataRunFailure=
|
||||
}
|
||||
|
||||
# Displays a list of distros which can be tested
|
||||
list_distros()
|
||||
{
|
||||
tr " " "\n" <<< "${distrosSystemd[@]:-} ${distrosAgent[@]:-}" | sort
|
||||
}
|
||||
|
||||
#
|
||||
# Calls the `GNU make` utility with the set of passed arguments.
|
||||
# Arguments can either be make targets or make variables assignments (in the form of VARIABLE=<value>)
|
||||
#
|
||||
call_make() {
|
||||
targetType=$1
|
||||
shift
|
||||
makeVars=()
|
||||
makeTargets=()
|
||||
# Split args between make variable and targets
|
||||
for t in $@; do
|
||||
# RE to match a make variable assignment
|
||||
pattern="^\w+\="
|
||||
if [[ "$t" =~ $pattern ]]; then
|
||||
makeVars+=("$t")
|
||||
else
|
||||
makeTargets+=($targetType-$t)
|
||||
fi
|
||||
done
|
||||
|
||||
# Set a default make target
|
||||
[ "${#makeTargets[@]}" = "0" ] && makeTargets+=($targetType)
|
||||
|
||||
makeJobs=
|
||||
if [ -z "$CI" ]; then
|
||||
((makeJobs=$(nproc) / 2))
|
||||
fi
|
||||
|
||||
# When calling make, do not use the silent_run wrapper, pass the
|
||||
# OSBUILDER_USE_CHRONIC instead.
|
||||
# In this way running make in parallel mode will, in case of failure, just
|
||||
# show the print out of the single target failing.
|
||||
makeVars+=(OSBUILDER_USE_CHRONIC=1)
|
||||
|
||||
info "Starting make with \n\
|
||||
# of // jobs: ${makeJobs:-[unlimited]} \n\
|
||||
targets: ${makeTargets[@]} \n\
|
||||
variables: ${makeVars[@]}"
|
||||
|
||||
sudo -E make -j $makeJobs ${makeTargets[@]} ${makeVars[@]}
|
||||
}
|
||||
|
||||
make_rootfs() {
|
||||
call_make rootfs $@
|
||||
}
|
||||
|
||||
make_image() {
|
||||
call_make image $@
|
||||
}
|
||||
|
||||
make_initrd() {
|
||||
call_make initrd $@
|
||||
}
|
||||
|
||||
get_rootfs_size() {
|
||||
[ $# -ne 1 ] && die "get_rootfs_size: wrong number of arguments"
|
||||
|
||||
local rootfs_dir=$1
|
||||
! [ -d "$rootfs_dir" ] && die "$rootfs_dir is not a valid rootfs path"
|
||||
|
||||
sudo -E du -sb "${rootfs_dir}" | awk '{print $1}'
|
||||
}
|
||||
|
||||
|
||||
show_rootfs_metadata() {
|
||||
[ $# -ne 1 ] && die "show_rootfs_metadata: wrong number of arguments"
|
||||
local rootfs_path=$1
|
||||
local osbuilder_file_fullpath="${rootfs_path}/${osbuilder_file}"
|
||||
yamllint "${osbuilder_file_fullpath}"
|
||||
|
||||
info "osbuilder metadata file for $d:"
|
||||
cat "${osbuilder_file_fullpath}" >&2
|
||||
}
|
||||
|
||||
# Create an image and/or initrd for the available distributions,
|
||||
# then test each by configuring the runtime and creating a container.
|
||||
#
|
||||
# When passing the name of a distribution, tests are run against that
|
||||
# distribution only.
|
||||
#
|
||||
# Parameters:
|
||||
#
|
||||
# 1: distro name.
|
||||
#
|
||||
test_distros()
|
||||
{
|
||||
local distro="$1"
|
||||
get_distros_config "$distro"
|
||||
local commonMakeVars=( \
|
||||
USE_DOCKER=true \
|
||||
DOCKER_RUNTIME="${DOCKER_RUNTIME}" \
|
||||
ROOTFS_BUILD_DEST="$tmp_rootfs" \
|
||||
IMAGES_BUILD_DEST="$images_dir" \
|
||||
DEBUG=1 )
|
||||
|
||||
# If a distro was specified, filter out the distro list to only include that distro
|
||||
if [ -n "$distro" ]; then
|
||||
pattern="\<$distro\>"
|
||||
if [[ "${distrosAgent[@]:-}" =~ $pattern ]]; then
|
||||
distrosAgent=($distro)
|
||||
distrosSystemd=()
|
||||
elif [[ "${distrosSystemd[@]:-}" =~ $pattern ]]; then
|
||||
distrosSystemd=($distro)
|
||||
distrosAgent=()
|
||||
build_initrds=
|
||||
else
|
||||
die "Not a valid distro: $distro"
|
||||
fi
|
||||
|
||||
info "Running tests for distro: $distro"
|
||||
|
||||
else
|
||||
info "Running tests for all distros"
|
||||
# Graceful exit allowed for selected distros, but only when testing all distros
|
||||
commonMakeVars+=(GRACEFUL_EXIT=1)
|
||||
fi
|
||||
|
||||
# distro with systemd as init -> normal rootfs image
|
||||
# distro with kata-agent as init -> normal rootfs image AND initrd image
|
||||
|
||||
# If user does not need rootfs images, then do not build systemd rootfses
|
||||
[ -z "$build_images" ] && distrosSystemd=()
|
||||
|
||||
# Build systemd and agent rootfs with 2 separate jobs
|
||||
bgJobs=()
|
||||
|
||||
if [ ${#distrosSystemd[@]} -gt 0 ]; then
|
||||
info "building rootfses with systemd as init: ${distrosSystemd[@]}"
|
||||
make_rootfs ${commonMakeVars[@]} "${distrosSystemd[@]}" &
|
||||
bgJobs+=($!)
|
||||
fi
|
||||
|
||||
if [ "$KATA_HYPERVISOR" != "firecracker" ]; then
|
||||
if [ ${#distrosAgent[@]} -gt 0 ]; then
|
||||
info "building all rootfses with kata-agent as init"
|
||||
make_rootfs ${commonMakeVars[@]} AGENT_INIT=yes "${distrosAgent[@]}" &
|
||||
bgJobs+=($!)
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for build failures (`wait` remembers up to CHILD_MAX bg processes exit status)
|
||||
for j in ${bgJobs[@]}; do
|
||||
if ! wait $j; then
|
||||
info "Background rootfs build job failed:"
|
||||
#find completed an uncompleted jobs checking for the rootfs marker
|
||||
local marker=$(make print-ROOTFS_MARKER_SUFFIX)
|
||||
[ -z "$marker" ] && die "Invalid rootfs marker"
|
||||
typeset -a completed=($(find ${tmp_rootfs} -name ".*${marker}" -exec basename {} \; | sed -E "s/\.(.+)${marker}/\1/"))
|
||||
for d in "${distrosSystemd[@]:-}" "${distrosAgent[@]:-}"; do
|
||||
if [[ "${completed[@]}" =~ $d ]]; then
|
||||
info "- $d : completed"
|
||||
else
|
||||
info "- $d : failed"
|
||||
fi
|
||||
done
|
||||
die "rootfs build failed"
|
||||
fi
|
||||
done
|
||||
|
||||
# TODO: once support for rootfs images with kata-agent as init is in place,
|
||||
# uncomment the following line
|
||||
# for d in ${distrosSystemd[@]} ${distrosAgent[@]}; do
|
||||
for d in ${distrosSystemd[@]:-}; do
|
||||
local rootfs_path="${tmp_rootfs}/${d}_rootfs"
|
||||
local image_path="${images_dir}/kata-containers-image-$d.img"
|
||||
local rootfs_size=$(get_rootfs_size "$rootfs_path")
|
||||
|
||||
# Skip failed distros
|
||||
if [ -e "${tmp_rootfs}/${d}_fail" ]; then
|
||||
info "Building rootfs for ${d} failed, not creating an image"
|
||||
[ -n "$CI" ] && sudo -E touch "${ci_results_dir}/${d}_fail"
|
||||
continue
|
||||
fi
|
||||
|
||||
show_rootfs_metadata "$rootfs_path"
|
||||
info "Making rootfs image for ${d}"
|
||||
make_image ${commonMakeVars[@]} $d
|
||||
local image_size=$(stat -c "%s" "${image_path}")
|
||||
|
||||
built_images["${d}"]="${rootfs_size}:${image_size}"
|
||||
info "Creating container for ${d}"
|
||||
install_image_create_container $image_path
|
||||
done
|
||||
|
||||
for d in ${distrosAgent[@]:-}; do
|
||||
local rootfs_path="${tmp_rootfs}/${d}_rootfs"
|
||||
local initrd_path="${images_dir}/kata-containers-initrd-$d.img"
|
||||
local rootfs_size=$(get_rootfs_size "$rootfs_path")
|
||||
|
||||
# Skip failed distros
|
||||
if [ -e "${tmp_rootfs}/${d}_fail" ]; then
|
||||
info "Building rootfs for ${d} failed, not creating an initrd"
|
||||
[ -n "$CI" ] && touch "${ci_results_dir}/${d}_fail"
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
if [ "$KATA_HYPERVISOR" != "firecracker" ]; then
|
||||
info "Making initrd image for ${d}"
|
||||
make_initrd ${commonMakeVars[@]} AGENT_INIT=yes $d
|
||||
local initrd_size=$(stat -c "%s" "${initrd_path}")
|
||||
|
||||
built_initrds["${d}"]="${rootfs_size}:${initrd_size}"
|
||||
info "Creating container for ${d}"
|
||||
install_initrd_create_container $initrd_path
|
||||
fi
|
||||
done
|
||||
|
||||
show_stats
|
||||
}
|
||||
|
||||
test_dracut()
|
||||
{
|
||||
local initrd_path="${images_dir}/kata-containers-initrd-dracut.img"
|
||||
local image_path="${images_dir}/kata-containers-image-dracut.img"
|
||||
local rootfs_path="${tmp_rootfs}/dracut_rootfs"
|
||||
local overlay_path="${tmp_rootfs}/dracut_overlay"
|
||||
|
||||
detect_go_version ||
|
||||
die "Could not detect the required Go version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
detect_rust_version ||
|
||||
die "Could not detect the required rust version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
detect_cmake_version ||
|
||||
die "Could not detect the required cmake version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
detect_musl_version ||
|
||||
die "Could not detect the required musl version for AGENT_VERSION='${AGENT_VERSION:-master}'."
|
||||
|
||||
generate_dockerfile ${dracut_dir}
|
||||
info "Creating container for dracut"
|
||||
silent_run docker build -t dracut-test-osbuilder ${dracut_dir}
|
||||
|
||||
typeset -a dockerRunArgs=(\
|
||||
--rm \
|
||||
--runtime="${DOCKER_RUNTIME}" \
|
||||
-v "${project_dir}":"${project_dir}" \
|
||||
-v "${tmp_dir}":"${tmp_dir}" \
|
||||
-v /etc/localtime:/etc/localtime:ro \
|
||||
dracut-test-osbuilder \
|
||||
)
|
||||
|
||||
typeset -a makeVars=(\
|
||||
BUILD_METHOD=dracut \
|
||||
TARGET_INITRD="${initrd_path}" \
|
||||
TARGET_IMAGE=${image_path} \
|
||||
TARGET_ROOTFS=${rootfs_path} \
|
||||
DRACUT_OVERLAY_DIR="${overlay_path}" \
|
||||
USE_DOCKER=1 \
|
||||
DOCKER_RUNTIME="${DOCKER_RUNTIME}" \
|
||||
)
|
||||
|
||||
info "Making image for dracut inside a container"
|
||||
silent_run docker run ${dockerRunArgs[@]} make -C ${project_dir} ${makeVars[@]} rootfs
|
||||
make_image ${makeVars[@]}
|
||||
local image_size=$(stat -c "%s" "${image_path}")
|
||||
local rootfs_size=$(get_rootfs_size "$rootfs_path")
|
||||
built_images["dracut"]="${rootfs_size}:${image_size}"
|
||||
info "Creating container for dracut"
|
||||
install_image_create_container $image_path
|
||||
|
||||
if [ "$KATA_HYPERVISOR" != "firecracker" ]; then
|
||||
info "Making initrd for dracut inside a container"
|
||||
silent_run docker run ${dockerRunArgs[@]} make -C ${project_dir} ${makeVars[@]} AGENT_INIT=yes clean initrd
|
||||
local initrd_size=$(stat -c "%s" "${initrd_path}")
|
||||
built_initrds["dracut"]="${rootfs_size}:${initrd_size}"
|
||||
install_initrd_create_container $initrd_path
|
||||
fi
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
local args=$(getopt \
|
||||
-n "$script_name" \
|
||||
-a \
|
||||
--options="h" \
|
||||
--longoptions="help distro: list test-images-only test-initrds-only" \
|
||||
-- "$@")
|
||||
|
||||
eval set -- "$args"
|
||||
[ $? -ne 0 ] && { usage >&2; exit 1; }
|
||||
|
||||
local distro=
|
||||
|
||||
while [ $# -gt 1 ]
|
||||
do
|
||||
case "$1" in
|
||||
-h|--help) usage; exit 0 ;;
|
||||
|
||||
--list) list_distros; exit 0;;
|
||||
|
||||
--test-images-only)
|
||||
build_initrds=
|
||||
;;
|
||||
|
||||
--test-initrds-only)
|
||||
build_images=
|
||||
;;
|
||||
|
||||
--) shift; break ;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# Consume getopt cruft
|
||||
[ "$1" = "--" ] && shift
|
||||
|
||||
case "${1:-}" in
|
||||
help) usage; exit 0;;
|
||||
|
||||
*) distro="${1:-}";;
|
||||
esac
|
||||
|
||||
trap exit_handler EXIT ERR
|
||||
setup
|
||||
|
||||
# Run only if distro is not dracut
|
||||
[ "${distro:-}" != "dracut" ] && test_distros "$distro"
|
||||
# Run if distro is empty or it is dracut
|
||||
[ -z "$distro" ] || [ "$distro" = "dracut" ] && test_dracut
|
||||
|
||||
# We shouldn't really need a message like this but the CI can fail in
|
||||
# mysterious ways so make it clear!
|
||||
info "all tests finished successfully"
|
||||
}
|
||||
|
||||
main "$@"
|
Loading…
Reference in New Issue
Block a user