Merge pull request #10239 from fidencio/topic/remove-acrn

acrn: Drop support
This commit is contained in:
Fabiano Fidêncio 2024-09-19 23:10:29 +02:00 committed by GitHub
commit 77c844da12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 16 additions and 2906 deletions

View File

@ -50,7 +50,7 @@ We provide `Dragonball` Sandbox to enable built-in VMM by integrating VMM's func
#### How To Support Async
The kata-runtime is controlled by TOKIO_RUNTIME_WORKER_THREADS to run the OS thread, which is 2 threads by default. For TTRPC and container-related threads run in the `tokio` thread in a unified manner, and related dependencies need to be switched to Async, such as Timer, File, Netlink, etc. With the help of Async, we can easily support no-block I/O and timer. Currently, we only utilize Async for kata-runtime. The built-in VMM keeps the OS thread because it can ensure that the threads are controllable.
**For N tokio worker threads and M containers**
**For N `tokio` worker threads and M containers**
- Sync runtime(both OS thread and `tokio` task are OS thread but without `tokio` worker thread) OS thread number: 4 + 12*M
- Async runtime(only OS thread is OS thread) OS thread number: 2 + N
@ -103,7 +103,6 @@ In our case, there will be a variety of resources, and every resource has severa
| `Cgroup V2` | | Stage 2 | 🚧 |
| Hypervisor | `Dragonball` | Stage 1 | 🚧 |
| | QEMU | Stage 2 | 🚫 |
| | ACRN | Stage 3 | 🚫 |
| | Cloud Hypervisor | Stage 3 | 🚫 |
| | Firecracker | Stage 3 | 🚫 |

View File

@ -20,12 +20,6 @@
for the VM rootfs. Refer to the following guide for additional configuration
steps:
- [Setup Kata containers with `firecracker`](how-to-use-kata-containers-with-firecracker.md)
- `ACRN`
While `qemu` , `cloud-hypervisor` and `firecracker` work out of the box with installation of Kata,
some additional configuration is needed in case of `ACRN`.
Refer to the following guides for additional configuration steps:
- [Kata Containers with ACRN Hypervisor](how-to-use-kata-containers-with-acrn.md)
## Confidential Containers Policy

View File

@ -46,7 +46,6 @@ There are several kinds of Kata configurations and they are listed below.
| `io.katacontainers.config.hypervisor.block_device_cache_set` | `boolean` | cache-related options will be set to block devices or not |
| `io.katacontainers.config.hypervisor.block_device_driver` | string | the driver to be used for block device, valid values are `virtio-blk`, `virtio-scsi`, `nvdimm`|
| `io.katacontainers.config.hypervisor.cpu_features` | `string` | Comma-separated list of CPU features to pass to the CPU (QEMU) |
| `io.katacontainers.config.hypervisor.ctlpath` (R) | `string` | Path to the `acrnctl` binary for the ACRN hypervisor |
| `io.katacontainers.config.hypervisor.default_max_vcpus` | uint32| the maximum number of vCPUs allocated for the VM by the hypervisor |
| `io.katacontainers.config.hypervisor.default_memory` | uint32| the memory assigned for a VM by the hypervisor in `MiB` |
| `io.katacontainers.config.hypervisor.default_vcpus` | float32| the default vCPUs assigned for a VM by the hypervisor |
@ -209,7 +208,6 @@ the configuration entry:
| Key | Config file entry | Comments |
|-------| ----- | ----- |
| `ctlpath` | `valid_ctlpaths` | Valid paths for `acrnctl` binary |
| `entropy_source` | `valid_entropy_sources` | Valid entropy sources, e.g. `/dev/random` |
| `file_mem_backend` | `valid_file_mem_backends` | Valid locations for the file-based memory backend root directory |
| `jailer_path` | `valid_jailer_paths`| Valid paths for the jailer constraining the container VM (Firecracker) |

View File

@ -1,125 +0,0 @@
# Kata Containers with ACRN
This document provides an overview on how to run Kata containers with ACRN hypervisor and device model.
## Introduction
ACRN is a flexible, lightweight Type-1 reference hypervisor built with real-time and safety-criticality in mind. ACRN uses an open source platform making it optimized to streamline embedded development.
Some of the key features being:
- Small footprint - Approx. 25K lines of code (LOC).
- Real Time - Low latency, faster boot time, improves overall responsiveness with hardware.
- Adaptability - Multi-OS support for guest operating systems like Linux, Android, RTOSes.
- Rich I/O mediators - Allows sharing of various I/O devices across VMs.
- Optimized for a variety of IoT (Internet of Things) and embedded device solutions.
Please refer to ACRN [documentation](https://projectacrn.github.io/latest/index.html) for more details on ACRN hypervisor and device model.
## Pre-requisites
This document requires the presence of the ACRN hypervisor and Kata Containers on your system. Install using the instructions available through the following links:
- ACRN supported [Hardware](https://projectacrn.github.io/latest/hardware.html#supported-hardware).
> **Note:** Please make sure to have a minimum of 4 logical processors (HT) or cores.
- ACRN [software](https://projectacrn.github.io/latest/tutorials/run_kata_containers.html) setup.
- For networking, ACRN supports either MACVTAP or TAP. If MACVTAP is not enabled in the Service OS, please follow the below steps to update the kernel:
```sh
$ git clone https://github.com/projectacrn/acrn-kernel.git
$ cd acrn-kernel
$ cp kernel_config_sos .config
$ sed -i "s/# CONFIG_MACVLAN is not set/CONFIG_MACVLAN=y/" .config
$ sed -i '$ i CONFIG_MACVTAP=y' .config
$ make clean && make olddefconfig && make && sudo make modules_install INSTALL_MOD_PATH=out/
```
Login into Service OS and update the kernel with MACVTAP support:
```sh
$ sudo mount /dev/sda1 /mnt
$ sudo scp -r <user name>@<host address>:<your workspace>/acrn-kernel/arch/x86/boot/bzImage /mnt/EFI/org.clearlinux/
$ sudo scp -r <user name>@<host address>:<your workspace>/acrn-kernel/out/lib/modules/* /lib/modules/
$ conf_file=$(sed -n '$ s/default //p' /mnt/loader/loader.conf).conf
$ kernel_img=$(sed -n 2p /mnt/loader/entries/$conf_file | cut -d'/' -f4)
$ sudo sed -i "s/$kernel_img/bzImage/g" /mnt/loader/entries/$conf_file
$ sync && sudo umount /mnt && sudo reboot
```
- Kata Containers installation: Automated installation does not seem to be supported for Clear Linux, so please use [manual installation](../Developer-Guide.md) steps.
> **Note:** Create rootfs image and not initrd image.
In order to run Kata with ACRN, your container stack must provide block-based storage, such as device-mapper.
> **Note:** Currently, by design you can only launch one VM from Kata Containers using ACRN hypervisor (SDC scenario). Based on feedback from community we can increase number of VMs.
## Configure Docker
To configure Docker for device-mapper and Kata,
1. Stop Docker daemon if it is already running.
```bash
$ sudo systemctl stop docker
```
2. Set `/etc/docker/daemon.json` with the following contents.
```
{
"storage-driver": "devicemapper"
}
```
3. Restart docker.
```bash
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```
4. Configure [Docker](../Developer-Guide.md#update-the-docker-systemd-unit-file) to use `kata-runtime`.
## Configure Kata Containers with ACRN
To configure Kata Containers with ACRN, copy the generated `configuration-acrn.toml` file when building the `kata-runtime` to either `/etc/kata-containers/configuration.toml` or `/usr/share/defaults/kata-containers/configuration.toml`.
The following command shows full paths to the `configuration.toml` files that the runtime loads. It will use the first path that exists. (Please make sure the kernel and image paths are set correctly in the `configuration.toml` file)
```bash
$ sudo kata-runtime --show-default-config-paths
```
>**Warning:** Please offline CPUs using [this](offline_cpu.sh) script, else VM launches will fail.
```bash
$ sudo ./offline_cpu.sh
```
Start an ACRN based Kata Container,
```bash
$ sudo docker run -ti --runtime=kata-runtime busybox sh
```
You will see ACRN(`acrn-dm`) is now running on your system, as well as a `kata-shim`. You should obtain an interactive shell prompt. Verify that all the Kata processes terminate once you exit the container.
```bash
$ ps -ef | grep -E "kata|acrn"
```
Validate ACRN hypervisor by using `kata-runtime kata-env`,
```sh
$ kata-runtime kata-env | awk -v RS= '/\[Hypervisor\]/'
[Hypervisor]
MachineType = ""
Version = "DM version is: 1.2-unstable-254577a6-dirty (daily tag:acrn-2019w27.4-140000p)
Path = "/usr/bin/acrn-dm"
BlockDeviceDriver = "virtio-blk"
EntropySource = "/dev/urandom"
Msize9p = 0
MemorySlots = 10
Debug = false
UseVSock = false
SharedFS = ""
```

View File

@ -18,7 +18,6 @@ for i in $(ls -d /sys/devices/system/cpu/cpu[1-9]*); do
echo 0 > $i/online
online=`cat $i/online`
done
echo $idx > /sys/class/vhm/acrn_vhm/offline_cpu
fi
done

View File

@ -18,7 +18,6 @@ which hypervisors you may wish to investigate further.
| Hypervisor | Written in | Architectures | Type |
|-|-|-|-|
|[ACRN] | C | `x86_64` | Type 1 (bare metal) |
|[Cloud Hypervisor] | rust | `aarch64`, `x86_64` | Type 2 ([KVM]) |
|[Firecracker] | rust | `aarch64`, `x86_64` | Type 2 ([KVM]) |
|[QEMU] | C | all | Type 2 ([KVM]) | `configuration-qemu.toml` |
@ -38,7 +37,6 @@ the hypervisors:
| Hypervisor | Summary | Features | Limitations | Container Creation speed | Memory density | Use cases | Comment |
|-|-|-|-|-|-|-|-|
|[ACRN] | Safety critical and real-time workloads | | | excellent | excellent | Embedded and IOT systems | For advanced users |
|[Cloud Hypervisor] | Low latency, small memory footprint, small attack surface | Minimal | | excellent | excellent | High performance modern cloud workloads | |
|[Firecracker] | Very slimline | Extremely minimal | Doesn't support all device types | excellent | excellent | Serverless / FaaS | |
|[QEMU] | Lots of features | Lots | | good | good | Good option for most users | |
@ -57,7 +55,6 @@ are available, their default values and how each setting can be used.
| Hypervisor | Golang runtime config file | golang runtime short name | golang runtime default | rust runtime config file | rust runtime short name | rust runtime default |
|-|-|-|-|-|-|-|
| [ACRN] | [`configuration-acrn.toml`](../src/runtime/config/configuration-acrn.toml.in) | `acrn` | | | | |
| [Cloud Hypervisor] | [`configuration-clh.toml`](../src/runtime/config/configuration-clh.toml.in) | `clh` | | [`configuration-cloud-hypervisor.toml`](../src/runtime-rs/config/configuration-cloud-hypervisor.toml.in) | `cloud-hypervisor` | |
| [Firecracker] | [`configuration-fc.toml`](../src/runtime/config/configuration-fc.toml.in) | `fc` | | | | |
| [QEMU] | [`configuration-qemu.toml`](../src/runtime/config/configuration-qemu.toml.in) | `qemu` | yes | [`configuration-qemu.toml`](../src/runtime-rs/config/configuration-qemu-runtime-rs.toml.in) | `qemu` | |
@ -93,10 +90,9 @@ are available, their default values and how each setting can be used.
To switch the configured hypervisor, you only need to run a single command.
See [the `kata-manager` documentation](../utils/README.md#choose-a-hypervisor) for further details.
[ACRN]: https://projectacrn.org
[Cloud Hypervisor]: https://github.com/cloud-hypervisor/cloud-hypervisor
[Firecracker]: https://github.com/firecracker-microvm/firecracker
[KVM]: https://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine
[QEMU]: http://www.qemu-project.org
[QEMU]: http://www.qemu.org
[`Dragonball`]: https://github.com/kata-containers/kata-containers/blob/main/src/dragonball
[StratoVirt]: https://gitee.com/openeuler/stratovirt

View File

@ -88,12 +88,6 @@ pub const KATA_ANNO_CFG_HYPERVISOR_PREFIX: &str = "io.katacontainers.config.hype
pub const KATA_ANNO_CFG_HYPERVISOR_PATH: &str = "io.katacontainers.config.hypervisor.path";
/// A sandbox annotation for passing a container hypervisor binary SHA-512 hash value.
pub const KATA_ANNO_CFG_HYPERVISOR_HASH: &str = "io.katacontainers.config.hypervisor.path_hash";
/// A sandbox annotation for passing a per container path pointing at the hypervisor control binary
/// that will run the container VM.
pub const KATA_ANNO_CFG_HYPERVISOR_CTLPATH: &str = "io.katacontainers.config.hypervisor.ctlpath";
/// A sandbox annotation for passing a container hypervisor control binary SHA-512 hash value.
pub const KATA_ANNO_CFG_HYPERVISOR_CTLHASH: &str =
"io.katacontainers.config.hypervisor.hypervisorctl_hash";
/// A sandbox annotation for passing a per container path pointing at the jailer that will constrain
/// the container VM.
pub const KATA_ANNO_CFG_HYPERVISOR_JAILER_PATH: &str =
@ -506,10 +500,6 @@ impl Annotation {
hv.validate_hypervisor_path(value)?;
hv.path = value.to_string();
}
KATA_ANNO_CFG_HYPERVISOR_CTLPATH => {
hv.validate_hypervisor_ctlpath(value)?;
hv.ctlpath = value.to_string();
}
KATA_ANNO_CFG_HYPERVISOR_JAILER_PATH => {
hv.validate_jailer_path(value)?;

View File

@ -83,7 +83,6 @@ LOCALSTATEDIR := /var
CONFIG_FILE = configuration.toml
RUNTIMENAME := virt_container
HYPERVISOR_DB = dragonball
HYPERVISOR_ACRN = acrn
HYPERVISOR_FC = firecracker
HYPERVISOR_QEMU = qemu
HYPERVISOR_CLH = cloud-hypervisor
@ -92,7 +91,7 @@ HYPERVISOR_CLH = cloud-hypervisor
DEFAULT_HYPERVISOR ?= $(HYPERVISOR_DB)
##VAR HYPERVISOR=<hypervisor_name> List of hypervisors this build system can generate configuration for.
HYPERVISORS := $(HYPERVISOR_DB) $(HYPERVISOR_ACRN) $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH)
HYPERVISORS := $(HYPERVISOR_DB) $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH)
CLHPATH := $(CLHBINDIR)/$(CLHCMD)
CLHVALIDHYPERVISORPATHS := [\"$(CLHPATH)\"]
@ -399,7 +398,6 @@ USER_VARS += SYSCONFDIR
USER_VARS += DEFVCPUS
USER_VARS += DEFVCPUS_QEMU
USER_VARS += DEFMAXVCPUS
USER_VARS += DEFMAXVCPUS_ACRN
USER_VARS += DEFMAXVCPUS_DB
USER_VARS += DEFMAXVCPUS_QEMU
USER_VARS += DEFMEMSZ
@ -647,9 +645,6 @@ ifneq (,$(findstring $(HYPERVISOR_CLH),$(KNOWN_HYPERVISORS)))
endif
ifneq (,$(findstring $(HYPERVISOR_FC),$(KNOWN_HYPERVISORS)))
@printf "\t$(HYPERVISOR_FC) hypervisor path (FCPATH) : %s\n" $(abspath $(FCPATH))
endif
ifneq (,$(findstring $(HYPERVISOR_ACRN),$(KNOWN_HYPERVISORS)))
@printf "\t$(HYPERVISOR_ACRN) hypervisor path (ACRNPATH) : %s\n" $(abspath $(ACRNPATH))
endif
@printf "\tassets path (PKGDATADIR) : %s\n" $(abspath $(PKGDATADIR))
@printf "\tshim path (PKGLIBEXECDIR) : %s\n" $(abspath $(PKGLIBEXECDIR))

View File

@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashSet;
#[derive(Serialize, Deserialize, Default, Clone, Debug)]
pub struct HypervisorState {
// Type of hypervisor, E.g. dragonball/qemu/firecracker/acrn.
// Type of hypervisor, E.g. dragonball/qemu/firecracker.
pub hypervisor_type: String,
pub pid: Option<i32>,
pub uuid: String,

View File

@ -82,7 +82,6 @@ BINDIR := $(EXEC_PREFIX)/bin
QEMUBINDIR := $(PREFIXDEPS)/bin
CLHBINDIR := $(PREFIXDEPS)/bin
FCBINDIR := $(PREFIXDEPS)/bin
ACRNBINDIR := $(PREFIXDEPS)/bin
STRATOVIRTBINDIR := $(PREFIXDEPS)/bin
SYSCONFDIR := /etc
LOCALSTATEDIR := /var
@ -99,7 +98,6 @@ RUNTIME_NAME = $(TARGET)
GENERATED_FILES += $(COLLECT_SCRIPT)
GENERATED_VARS = \
VERSION \
CONFIG_ACRN_IN \
CONFIG_QEMU_IN \
CONFIG_QEMU_COCO_DEV_IN \
CONFIG_QEMU_NVIDIA_GPU_IN \
@ -159,7 +157,6 @@ KERNELTDXPARAMS += $(ROOTMEASURECONFIG)
# Name of default configuration file the runtime will use.
CONFIG_FILE = configuration.toml
HYPERVISOR_ACRN = acrn
HYPERVISOR_FC = firecracker
HYPERVISOR_QEMU = qemu
HYPERVISOR_CLH = cloud-hypervisor
@ -170,7 +167,7 @@ HYPERVISOR_REMOTE = remote
DEFAULT_HYPERVISOR ?= $(HYPERVISOR_QEMU)
# List of hypervisors this build system can generate configuration for.
HYPERVISORS := $(HYPERVISOR_ACRN) $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH) $(HYPERVISOR_STRATOVIRT) $(HYPERVISOR_REMOTE)
HYPERVISORS := $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH) $(HYPERVISOR_STRATOVIRT) $(HYPERVISOR_REMOTE)
QEMUPATH := $(QEMUBINDIR)/$(QEMUCMD)
QEMUVALIDHYPERVISORPATHS := [\"$(QEMUPATH)\"]
@ -193,11 +190,6 @@ FCVALIDHYPERVISORPATHS := [\"$(FCPATH)\"]
FCJAILERPATH = $(FCBINDIR)/$(FCJAILERCMD)
FCVALIDJAILERPATHS = [\"$(FCJAILERPATH)\"]
ACRNPATH := $(ACRNBINDIR)/$(ACRNCMD)
ACRNVALIDHYPERVISORPATHS := [\"$(ACRNPATH)\"]
ACRNCTLPATH := $(ACRNBINDIR)/$(ACRNCTLCMD)
ACRNVALIDCTLPATHS := [\"$(ACRNCTLPATH)\"]
STRATOVIRTPATH = $(STRATOVIRTBINDIR)/$(STRATOVIRTCMD)
STRATOVIRTVALIDHYPERVISORPATHS := [\"$(STRATOVIRTPATH)\"]
@ -538,30 +530,6 @@ ifneq (,$(FCCMD))
KERNELPATH_FC = $(KERNELDIR)/$(KERNEL_NAME_FC)
endif
ifneq (,$(ACRNCMD))
KNOWN_HYPERVISORS += $(HYPERVISOR_ACRN)
CONFIG_FILE_ACRN = configuration-acrn.toml
CONFIG_ACRN = config/$(CONFIG_FILE_ACRN)
CONFIG_ACRN_IN = $(CONFIG_ACRN).in
CONFIG_PATH_ACRN = $(abspath $(CONFDIR)/$(CONFIG_FILE_ACRN))
CONFIG_PATHS += $(CONFIG_PATH_ACRN)
SYSCONFIG_ACRN = $(abspath $(SYSCONFDIR)/$(CONFIG_FILE_ACRN))
SYSCONFIG_PATHS += $(SYSCONFIG_ACRN)
CONFIGS += $(CONFIG_ACRN)
# acrn-specific options (all should be suffixed by "_ACRN")
DEFMAXVCPUS_ACRN := 1
DEFBLOCKSTORAGEDRIVER_ACRN := virtio-blk
DEFNETWORKMODEL_ACRN := macvtap
KERNELTYPE_ACRN = compressed
KERNEL_NAME_ACRN = $(call MAKE_KERNEL_NAME,$(KERNELTYPE_ACRN))
KERNELPATH_ACRN = $(KERNELDIR)/$(KERNEL_NAME_ACRN)
endif
ifeq (,$(KNOWN_HYPERVISORS))
$(error "ERROR: No hypervisors known for architecture $(ARCH) (looked for: $(HYPERVISORS))")
endif
@ -586,10 +554,6 @@ ifeq ($(DEFAULT_HYPERVISOR),$(HYPERVISOR_FC))
DEFAULT_HYPERVISOR_CONFIG = $(CONFIG_FILE_FC)
endif
ifeq ($(DEFAULT_HYPERVISOR),$(HYPERVISOR_ACRN))
DEFAULT_HYPERVISOR_CONFIG = $(CONFIG_FILE_ACRN)
endif
ifeq ($(DEFAULT_HYPERVISOR),$(HYPERVISOR_CLH))
DEFAULT_HYPERVISOR_CONFIG = $(CONFIG_FILE_CLH)
endif
@ -609,7 +573,6 @@ SHAREDIR := $(SHAREDIR)
# list of variables the user may wish to override
USER_VARS += ARCH
USER_VARS += BINDIR
USER_VARS += CONFIG_ACRN_IN
USER_VARS += CONFIG_CLH_IN
USER_VARS += CONFIG_FC_IN
USER_VARS += CONFIG_STRATOVIRT_IN
@ -618,12 +581,6 @@ USER_VARS += CONFIG_QEMU_IN
USER_VARS += CONFIG_REMOTE_IN
USER_VARS += DESTDIR
USER_VARS += DEFAULT_HYPERVISOR
USER_VARS += ACRNCMD
USER_VARS += ACRNCTLCMD
USER_VARS += ACRNPATH
USER_VARS += ACRNVALIDHYPERVISORPATHS
USER_VARS += ACRNCTLPATH
USER_VARS += ACRNVALIDCTLPATHS
USER_VARS += CLHPATH
USER_VARS += CLHVALIDHYPERVISORPATHS
USER_VARS += FIRMWAREPATH_CLH
@ -667,9 +624,7 @@ USER_VARS += MACHINETYPE
USER_VARS += KERNELDIR
USER_VARS += KERNELTYPE
USER_VARS += KERNELTYPE_FC
USER_VARS += KERNELTYPE_ACRN
USER_VARS += KERNELTYPE_CLH
USER_VARS += KERNELPATH_ACRN
USER_VARS += KERNELPATH
USER_VARS += KERNELCONFIDENTIALPATH
USER_VARS += KERNELSEPATH
@ -722,12 +677,10 @@ USER_VARS += SHAREDIR
USER_VARS += SYSCONFDIR
USER_VARS += DEFVCPUS
USER_VARS += DEFMAXVCPUS
USER_VARS += DEFMAXVCPUS_ACRN
USER_VARS += DEFMEMSZ
USER_VARS += DEFMEMSLOTS
USER_VARS += DEFMAXMEMSZ
USER_VARS += DEFBRIDGES
USER_VARS += DEFNETWORKMODEL_ACRN
USER_VARS += DEFNETWORKMODEL_CLH
USER_VARS += DEFNETWORKMODEL_FC
USER_VARS += DEFNETWORKMODEL_QEMU
@ -739,7 +692,6 @@ USER_VARS += DEFDISABLEGUESTSELINUX
USER_VARS += DEFGUESTSELINUXLABEL
USER_VARS += DEFAULTEXPFEATURES
USER_VARS += DEFDISABLEBLOCK
USER_VARS += DEFBLOCKSTORAGEDRIVER_ACRN
USER_VARS += DEFBLOCKSTORAGEDRIVER_FC
USER_VARS += DEFBLOCKSTORAGEDRIVER_QEMU
USER_VARS += DEFBLOCKSTORAGEDRIVER_STRATOVIRT
@ -1106,9 +1058,6 @@ endif
ifneq (,$(findstring $(HYPERVISOR_FC),$(KNOWN_HYPERVISORS)))
@printf "\t$(HYPERVISOR_FC) hypervisor path (FCPATH) : %s\n" $(abspath $(FCPATH))
endif
ifneq (,$(findstring $(HYPERVISOR_ACRN),$(KNOWN_HYPERVISORS)))
@printf "\t$(HYPERVISOR_ACRN) hypervisor path (ACRNPATH) : %s\n" $(abspath $(ACRNPATH))
endif
ifneq (,$(findstring $(HYPERVISOR_STRATOVIRT),$(KNOWN_HYPERVISORS)))
@printf "\t$(HYPERVISOR_STRATOVIRT) hypervisor path (STRATOVIRTPATH) : %s\n" $(abspath $(STRATOVIRTPATH))
endif

View File

@ -20,10 +20,6 @@ FCCMD := firecracker
# Firecracker's jailer binary name
FCJAILERCMD := jailer
#ACRN binary name
ACRNCMD := acrn-dm
ACRNCTLCMD := acrnctl
# cloud-hypervisor binary name
CLHCMD := cloud-hypervisor

View File

@ -9,8 +9,6 @@ import (
"fmt"
"os"
"strings"
"syscall"
"unsafe"
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
"github.com/sirupsen/logrus"
@ -45,41 +43,6 @@ const (
cpuTypeUnknown = -1
)
const acrnDevice = "/dev/acrn_hsm"
// ioctl_ACRN_CREATE_VM is the IOCTL to create VM in ACRN.
// Current Linux mainstream kernel doesn't have support for ACRN.
// Due to this several macros are not defined in Linux headers.
// Until the support is available, directly use the value instead
// of macros.
// https://github.com/kata-containers/runtime/issues/1784
const ioctl_ACRN_CREATE_VM = 0xC030A210 //nolint
const ioctl_ACRN_PAUSE_VM = 0xA213 //nolint
const ioctl_ACRN_DESTROY_VM = 0xA211 //nolint
type acrn_vm_creation struct { //nolint
vmid uint16 //nolint
reserved0 uint16 //nolint
vcpu_num uint16 //nolint
reserved1 uint16 //nolint
name [16]uint8
vm_flag uint64 //nolint
ioreq_buf uint64 //nolint
cpu_affinity uint64 //nolint
}
var io_request_page [4096]byte
type acrn_io_request struct { // nolint
io_type uint32 // nolint
completion_polling uint32 // nolint
reserved0 [14]uint32 // nolint
data [8]uint64 // nolint
reserved1 uint32 // nolint
kernel_handled uint32 // nolint
processed uint32 // nolint
}
// cpuType save the CPU type
var cpuType int
@ -155,28 +118,6 @@ func setCPUtype(hypervisorType vc.HypervisorType) error {
required: false,
},
}
case vc.AcrnHypervisor:
archRequiredCPUFlags = map[string]string{
cpuFlagLM: "64Bit CPU",
cpuFlagSSE4_1: "SSE4.1",
}
archRequiredCPUAttribs = map[string]string{
archGenuineIntel: "Intel Architecture CPU",
}
archRequiredKernelModules = map[string]kernelModule{
kernelModvhost: {
desc: msgKernelVirtio,
required: false,
},
kernelModvhostnet: {
desc: msgKernelVirtioNet,
required: false,
},
kernelModvhostvsock: {
desc: msgKernelVirtioVhostVsock,
required: false,
},
}
case vc.MockHypervisor:
archRequiredCPUFlags = map[string]string{
cpuFlagVMX: "Virtualization support",
@ -249,68 +190,6 @@ func kvmIsUsable() error {
return genericKvmIsUsable()
}
// acrnIsUsable determines if it will be possible to create a full virtual machine
// by creating a minimal VM and then deleting it.
func acrnIsUsable() error {
flags := syscall.O_RDWR | syscall.O_CLOEXEC
f, err := syscall.Open(acrnDevice, flags, 0)
if err != nil {
return err
}
defer syscall.Close(f)
kataLog.WithField("device", acrnDevice).Info("device available")
var createVM acrn_vm_creation
copy(createVM.name[:], "KataACRNVM")
ioreq_buf := (*acrn_io_request)(unsafe.Pointer(&io_request_page))
createVM.ioreq_buf = uint64(uintptr(unsafe.Pointer(ioreq_buf)))
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
uintptr(f),
uintptr(ioctl_ACRN_CREATE_VM),
uintptr(unsafe.Pointer(&createVM)))
if ret != 0 || errno != 0 {
if errno == syscall.EBUSY {
kataLog.WithField("reason", "another hypervisor running").Error("cannot create VM")
}
kataLog.WithFields(logrus.Fields{
"ret": ret,
"errno": errno,
"VM_name": createVM.name,
}).Info("Create VM Error")
return errno
}
ret, _, errno = syscall.Syscall(syscall.SYS_IOCTL,
uintptr(f),
uintptr(ioctl_ACRN_PAUSE_VM),
0)
if ret != 0 || errno != 0 {
kataLog.WithFields(logrus.Fields{
"ret": ret,
"errno": errno,
}).Info("PAUSE VM Error")
return errno
}
ret, _, errno = syscall.Syscall(syscall.SYS_IOCTL,
uintptr(f),
uintptr(ioctl_ACRN_DESTROY_VM),
0)
if ret != 0 || errno != 0 {
kataLog.WithFields(logrus.Fields{
"ret": ret,
"errno": errno,
}).Info("Destroy VM Error")
return errno
}
kataLog.WithField("feature", "create-vm").Info("feature available")
return nil
}
func archHostCanCreateVMContainer(hypervisorType vc.HypervisorType) error {
switch hypervisorType {
case vc.QemuHypervisor:
@ -321,8 +200,6 @@ func archHostCanCreateVMContainer(hypervisorType vc.HypervisorType) error {
fallthrough
case vc.FirecrackerHypervisor:
return kvmIsUsable()
case vc.AcrnHypervisor:
return acrnIsUsable()
case vc.RemoteHypervisor:
return nil
case vc.MockHypervisor:

View File

@ -916,7 +916,6 @@ func TestGetHypervisorInfoSocket(t *testing.T) {
}
hypervisors := []TestHypervisorDetails{
{vc.AcrnHypervisor, false},
{vc.ClhHypervisor, true},
{vc.FirecrackerHypervisor, true},
{vc.MockHypervisor, false},

View File

@ -1,263 +0,0 @@
# Copyright (c) 2017-2019 Intel Corporation
# Copyright (c) 2021 Adobe Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# XXX: WARNING: this file is auto-generated.
# XXX:
# XXX: Source file: "@CONFIG_ACRN_IN@"
# XXX: Project:
# XXX: Name: @PROJECT_NAME@
# XXX: Type: @PROJECT_TYPE@
[hypervisor.acrn]
path = "@ACRNPATH@"
ctlpath = "@ACRNCTLPATH@"
kernel = "@KERNELPATH_ACRN@"
image = "@IMAGEPATH@"
# rootfs filesystem type:
# - ext4 (default)
# - xfs
# - erofs
rootfs_type=@DEFROOTFSTYPE@
# List of valid annotation names for the hypervisor
# Each member of the list is a regular expression, which is the base name
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
enable_annotations = @DEFENABLEANNOTATIONS@
# List of valid annotations values for the hypervisor
# Each member of the list is a path pattern as described by glob(3).
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @ACRNVALIDHYPERVISORPATHS@
valid_hypervisor_paths = @ACRNVALIDHYPERVISORPATHS@
# List of valid annotations values for ctlpath
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @ACRNVALIDCTLPATHS@
valid_ctlpaths = @ACRNVALIDCTLPATHS@
# Optional space-separated list of options to pass to the guest kernel.
# For example, use `kernel_params = "vsyscall=emulate"` if you are having
# trouble running pre-2.15 glibc.
#
# WARNING: - any parameter specified here will take priority over the default
# parameter value of the same name used to start the virtual machine.
# Do not set values here unless you understand the impact of doing so as you
# may stop the virtual machine from booting.
# To see the list of default parameters, enable hypervisor debug, create a
# container and look for 'default-kernel-parameters' log entries.
kernel_params = "@KERNELPARAMS@"
# Path to the firmware.
# If you want that acrn uses the default firmware leave this option empty
firmware = "@FIRMWAREPATH@"
# Default maximum number of vCPUs per SB/VM:
# unspecified or == 0 --> will be set to the actual number of physical cores or to the maximum number
# of vCPUs supported by KVM if that number is exceeded
# > 0 <= number of physical cores --> will be set to the specified number
# > number of physical cores --> will be set to the actual number of physical cores or to the maximum number
# of vCPUs supported by KVM if that number is exceeded
# WARNING: Depending of the architecture, the maximum number of vCPUs supported by KVM is used when
# the actual number of physical cores is greater than it.
# WARNING: Be aware that this value impacts the virtual machine's memory footprint and CPU
# the hotplug functionality. For example, `default_maxvcpus = 240` specifies that until 240 vCPUs
# can be added to a SB/VM, but the memory footprint will be big. Another example, with
# `default_maxvcpus = 8` the memory footprint will be small, but 8 will be the maximum number of
# vCPUs supported by the SB/VM. In general, we recommend that you do not edit this variable,
# unless you know what are you doing.
default_maxvcpus = @DEFMAXVCPUS_ACRN@
# Bridges can be used to hot plug devices.
# Limitations:
# * Currently only pci bridges are supported
# * Until 30 devices per bridge can be hot plugged.
# * Until 5 PCI bridges can be cold plugged per VM.
# This limitation could be a bug in the kernel
# Default number of bridges per SB/VM:
# unspecified or 0 --> will be set to @DEFBRIDGES@
# > 1 <= 5 --> will be set to the specified number
# > 5 --> will be set to 5
default_bridges = @DEFBRIDGES@
# Default memory size in MiB for SB/VM.
# If unspecified then it will be set @DEFMEMSZ@ MiB.
default_memory = @DEFMEMSZ@
# Block storage driver to be used for the hypervisor in case the container
# rootfs is backed by a block device. ACRN only supports virtio-blk.
block_device_driver = "@DEFBLOCKSTORAGEDRIVER_ACRN@"
# This option changes the default hypervisor and kernel parameters
# to enable debug output where available.
#
# Default false
#enable_debug = true
# Disable the customizations done in the runtime when it detects
# that it is running on top a VMM. This will result in the runtime
# behaving as it would when running on bare metal.
#
#disable_nesting_checks = true
# If host doesn't support vhost_net, set to true. Thus we won't create vhost fds for nics.
# Default false
#disable_vhost_net = true
# Path to OCI hook binaries in the *guest rootfs*.
# This does not affect host-side hooks which must instead be added to
# the OCI spec passed to the runtime.
#
# You can create a rootfs with hooks by customizing the osbuilder scripts:
# https://github.com/kata-containers/kata-containers/tree/main/tools/osbuilder
#
# Hooks must be stored in a subdirectory of guest_hook_path according to their
# hook type, i.e. "guest_hook_path/{prestart,poststart,poststop}".
# The agent will scan these directories for executable files and add them, in
# lexicographical order, to the lifecycle of the guest container.
# Hooks are executed in the runtime namespace of the guest. See the official documentation:
# https://github.com/opencontainers/runtime-spec/blob/v1.0.1/config.md#posix-platform-hooks
# Warnings will be logged if any error is encountered while scanning for hooks,
# but it will not abort container execution.
#guest_hook_path = "/usr/share/oci/hooks"
# disable applying SELinux on the VMM process (default false)
disable_selinux=@DEFDISABLESELINUX@
[agent.@PROJECT_TYPE@]
# If enabled, make the agent display debug-level messages.
# (default: disabled)
#enable_debug = true
# Enable agent tracing.
#
# If enabled, the agent will generate OpenTelemetry trace spans.
#
# Notes:
#
# - If the runtime also has tracing enabled, the agent spans will be
# associated with the appropriate runtime parent span.
# - If enabled, the runtime will wait for the container to shutdown,
# increasing the container shutdown time slightly.
#
# (default: disabled)
#enable_tracing = true
# Enable debug console.
# If enabled, user can connect guest OS running inside hypervisor
# through "kata-runtime exec <sandbox-id>" command
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 45)
dial_timeout = 45
# Confidential Data Hub API timeout value in seconds
# (default: 50)
#cdh_api_timeout = 50
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
# (default: disabled)
#enable_debug = true
#
# Internetworking model
# Determines how the VM should be connected to the
# the container network interface
# Options:
#
# - bridged (Deprecated)
# Uses a linux bridge to interconnect the container interface to
# the VM. Works for most cases except macvlan and ipvlan.
# ***NOTE: This feature has been deprecated with plans to remove this
# feature in the future. Please use other network models listed below.
#
#
# - macvtap
# Used when the Container network interface can be bridged using
# macvtap.
#
# - none
# Used when customize network. Only creates a tap device. No veth pair.
#
# - tcfilter
# Uses tc filter rules to redirect traffic from the network interface
# provided by plugin to a tap interface connected to the VM.
#
internetworking_model="@DEFNETWORKMODEL_ACRN@"
# disable guest seccomp
# Determines whether container seccomp profiles are passed to the virtual
# machine and applied by the kata agent. If set to true, seccomp is not applied
# within the guest
# (default: true)
disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# If enabled, the runtime will create opentracing.io traces and spans.
# (See https://www.jaegertracing.io/docs/getting-started).
# (default: disabled)
#enable_tracing = true
# Set the full url to the Jaeger HTTP Thrift collector.
# The default if not set will be "http://localhost:14268/api/traces"
#jaeger_endpoint = ""
# Sets the username to be used if basic auth is required for Jaeger.
#jaeger_user = ""
# Sets the password to be used if basic auth is required for Jaeger.
#jaeger_password = ""
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
# `disable_new_netns` conflicts with `internetworking_model=bridged` and `internetworking_model=macvtap`. It works only
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
# (like OVS) directly.
# (default: false)
#disable_new_netns = true
# if enabled, the runtime will add all the kata processes inside one dedicated cgroup.
# The container cgroups in the host are not created, just one single cgroup per sandbox.
# The runtime caller is free to restrict or collect cgroup stats of the overall Kata sandbox.
# The sandbox cgroup path is the parent cgroup of a container with the PodSandbox annotation.
# The sandbox cgroup is constrained if there is no container type annotation.
# See: https://pkg.go.dev/github.com/kata-containers/kata-containers/src/runtime/virtcontainers#ContainerType
sandbox_cgroup_only=@DEFSANDBOXCGROUPONLY@
# If enabled, the runtime will not create Kubernetes emptyDir mounts on the guest filesystem. Instead, emptyDir mounts will
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir=@DEFDISABLEGUESTEMPTYDIR@
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
# Supported experimental features:
# (default: [])
experimental=@DEFAULTEXPFEATURES@
# If enabled, user can run pprof tools with shim v2 process through kata-monitor.
# (default: false)
# enable_pprof = true
# Indicates the CreateContainer request timeout needed for the workload(s)
# It using guest_pull this includes the time to pull the image inside the guest
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
# Note: The effective timeout is determined by the lesser of two values: runtime-request-timeout from kubelet config
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout) and create_container_timeout.
# In essence, the timeout used for guest pull=runtime-request-timeout<create_container_timeout?runtime-request-timeout:create_container_timeout.
create_container_timeout = @DEFCREATECONTAINERTIMEOUT@
# Base directory of directly attachable network config.
# Network devices for VM-based containers are allowed to be placed in the
# host netns to eliminate as many hops as possible, which is what we
# called a "Directly Attachable Network". The config, set by special CNI
# plugins, is used to tell the Kata containers what devices are attached
# to the hypervisor.
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"

View File

@ -60,12 +60,6 @@ func (device *BlockDevice) Attach(ctx context.Context, devReceiver api.DeviceRec
return err
}
hypervisorType := devReceiver.GetHypervisorType()
if hypervisorType == "acrn" {
deviceLogger().Debug("Special casing for ACRN to increment BlockIndex")
index = index + 1
}
drive := &config.BlockDrive{
File: device.DeviceInfo.HostPath,
Format: "raw",

View File

@ -30,7 +30,7 @@ type CPUDevice struct {
type HypervisorState struct {
BlockIndexMap map[int]struct{}
// Type of hypervisor, E.g. qemu/firecracker/acrn.
// Type of hypervisor, E.g. qemu/firecracker
Type string
UUID string
// clh sepcific: refer to 'virtcontainers/clh.go:CloudHypervisorState'

View File

@ -44,7 +44,6 @@ var DEFAULTRUNTIMECONFIGURATION = "@CONFIG_PATH@"
// defaultRuntimeConfiguration.
var DEFAULTSYSCONFRUNTIMECONFIGURATION = "@SYSCONFIG@"
var defaultHypervisorPath = "/usr/bin/qemu-system-x86_64"
var defaultHypervisorCtlPath = "/usr/bin/acrnctl"
var defaultJailerPath = "/usr/bin/jailer"
var defaultImagePath = "/usr/share/kata-containers/kata-containers.img"
var defaultKernelPath = "/usr/share/kata-containers/vmlinuz.container"

View File

@ -50,7 +50,6 @@ const (
firecrackerHypervisorTableType = "firecracker"
clhHypervisorTableType = "clh"
qemuHypervisorTableType = "qemu"
acrnHypervisorTableType = "acrn"
dragonballHypervisorTableType = "dragonball"
stratovirtHypervisorTableType = "stratovirt"
remoteHypervisorTableType = "remote"
@ -83,7 +82,6 @@ type hypervisor struct {
Path string `toml:"path"`
JailerPath string `toml:"jailer_path"`
Kernel string `toml:"kernel"`
CtlPath string `toml:"ctlpath"`
Initrd string `toml:"initrd"`
Image string `toml:"image"`
RootfsType string `toml:"rootfs_type"`
@ -109,7 +107,6 @@ type hypervisor struct {
SnpCertsPath string `toml:"snp_certs_path"`
HypervisorPathList []string `toml:"valid_hypervisor_paths"`
JailerPathList []string `toml:"valid_jailer_paths"`
CtlPathList []string `toml:"valid_ctlpaths"`
VirtioFSDaemonList []string `toml:"valid_virtio_fs_daemon_paths"`
VirtioFSExtraArgs []string `toml:"virtio_fs_extra_args"`
PFlashList []string `toml:"pflashes"`
@ -225,16 +222,6 @@ func (h hypervisor) path() (string, error) {
return ResolvePath(p)
}
func (h hypervisor) ctlpath() (string, error) {
p := h.CtlPath
if h.CtlPath == "" {
p = defaultHypervisorCtlPath
}
return ResolvePath(p)
}
func (h hypervisor) jailerPath() (string, error) {
p := h.JailerPath
@ -1022,79 +1009,6 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
}, nil
}
func newAcrnHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
hypervisor, err := h.path()
if err != nil {
return vc.HypervisorConfig{}, err
}
hypervisorctl, err := h.ctlpath()
if err != nil {
return vc.HypervisorConfig{}, err
}
kernel, err := h.kernel()
if err != nil {
return vc.HypervisorConfig{}, err
}
image, err := h.image()
if err != nil {
return vc.HypervisorConfig{}, err
}
if image == "" {
return vc.HypervisorConfig{},
errors.New("image must be defined in the configuration file")
}
rootfsType, err := h.rootfsType()
if err != nil {
return vc.HypervisorConfig{}, err
}
firmware, err := h.firmware()
if err != nil {
return vc.HypervisorConfig{}, err
}
kernelParams := h.kernelParams()
blockDriver, err := h.blockDeviceDriver()
if err != nil {
return vc.HypervisorConfig{}, err
}
return vc.HypervisorConfig{
HypervisorPath: hypervisor,
HypervisorPathList: h.HypervisorPathList,
KernelPath: kernel,
ImagePath: image,
RootfsType: rootfsType,
HypervisorCtlPath: hypervisorctl,
HypervisorCtlPathList: h.CtlPathList,
FirmwarePath: firmware,
KernelParams: vc.DeserializeParams(vc.KernelParamFields(kernelParams)),
NumVCPUsF: h.defaultVCPUs(),
DefaultMaxVCPUs: h.defaultMaxVCPUs(),
MemorySize: h.defaultMemSz(),
MemSlots: h.defaultMemSlots(),
DefaultMaxMemorySize: h.defaultMaxMemSz(),
EntropySource: h.GetEntropySource(),
EntropySourceList: h.EntropySourceList,
DefaultBridges: h.defaultBridges(),
HugePages: h.HugePages,
Debug: h.Debug,
DisableNestingChecks: h.DisableNestingChecks,
BlockDeviceDriver: blockDriver,
DisableVhostNet: h.DisableVhostNet,
GuestHookPath: h.guestHookPath(),
DisableSeLinux: h.DisableSeLinux,
EnableAnnotations: h.EnableAnnotations,
DisableGuestSeLinux: true, // Guest SELinux is not supported in ACRN
}, nil
}
func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
hypervisor, err := h.path()
if err != nil {
@ -1393,9 +1307,6 @@ func updateRuntimeConfigHypervisor(configPath string, tomlConf tomlConfig, confi
case qemuHypervisorTableType:
config.HypervisorType = vc.QemuHypervisor
hConfig, err = newQemuHypervisorConfig(hypervisor)
case acrnHypervisorTableType:
config.HypervisorType = vc.AcrnHypervisor
hConfig, err = newAcrnHypervisorConfig(hypervisor)
case clhHypervisorTableType:
config.HypervisorType = vc.ClhHypervisor
hConfig, err = newClhHypervisorConfig(hypervisor)

View File

@ -1770,9 +1770,6 @@ func TestUpdateRuntimeConfigHypervisor(t *testing.T) {
configFile := "/some/where/configuration.toml"
// Note: We cannot test acrnHypervisorTableType since
// newAcrnHypervisorConfig() expects ACRN binaries to be
// installed.
var entries = []tableTypeEntry{
{clhHypervisorTableType, true},
{dragonballHypervisorTableType, true},

View File

@ -578,13 +578,6 @@ func addHypervisorPathOverrides(ocispec specs.Spec, config *vc.SandboxConfig, ru
config.HypervisorConfig.JailerPath = value
}
if value, ok := ocispec.Annotations[vcAnnotations.CtlPath]; ok {
if !checkPathIsInGlobs(runtime.HypervisorConfig.HypervisorCtlPathList, value) {
return fmt.Errorf("hypervisor control %v required from annotation is not valid", value)
}
config.HypervisorConfig.HypervisorCtlPath = value
}
if value, ok := ocispec.Annotations[vcAnnotations.KernelParams]; ok {
if value != "" {
params := vc.DeserializeParams(strings.Fields(value))

View File

@ -483,9 +483,6 @@ func TestAddAssetAnnotations(t *testing.T) {
vcAnnotations.HypervisorPath: fakeAssetFile,
vcAnnotations.HypervisorHash: "bbbbb",
vcAnnotations.HypervisorCtlPath: fakeAssetFile,
vcAnnotations.HypervisorCtlHash: "cc",
vcAnnotations.ImagePath: fakeAssetFile,
vcAnnotations.ImageHash: "52ss2550983",
@ -533,7 +530,6 @@ func TestAddAssetAnnotations(t *testing.T) {
// Check that it works if all path lists are enabled
runtimeConfig.HypervisorConfig.HypervisorPathList = []string{tmpdirGlob}
runtimeConfig.HypervisorConfig.JailerPathList = []string{tmpdirGlob}
runtimeConfig.HypervisorConfig.HypervisorCtlPathList = []string{tmpdirGlob}
err = addAnnotations(ocispec, &config, runtimeConfig)
assert.NoError(err)

View File

@ -1,684 +0,0 @@
//go:build linux
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
"github.com/pkg/errors"
"github.com/prometheus/procfs"
"github.com/sirupsen/logrus"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
hv "github.com/kata-containers/kata-containers/src/runtime/pkg/hypervisors"
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils/katatrace"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
)
// acrnTracingTags defines tags for the trace span
var acrnTracingTags = map[string]string{
"source": "runtime",
"package": "virtcontainers",
"subsystem": "hypervisor",
"type": "acrn",
}
// AcrnState keeps track of VM UUID, PID.
type AcrnState struct {
PID int
}
// Acrn is an Hypervisor interface implementation for the Linux acrn hypervisor.
type Acrn struct {
sandbox *Sandbox
ctx context.Context
arch acrnArch
store persistapi.PersistDriver
id string
acrnConfig Config
config HypervisorConfig
state AcrnState
}
const (
acrnConsoleSocket = "console.sock"
acrnStopSandboxTimeoutSecs = 15
)
// agnostic list of kernel parameters
var acrnDefaultKernelParameters = []Param{
{"panic", "1"},
}
func (a *Acrn) kernelParameters() string {
// get a list of arch kernel parameters
params := a.arch.kernelParameters(a.config.Debug)
// use default parameters
params = append(params, acrnDefaultKernelParameters...)
// set the maximum number of vCPUs
params = append(params, Param{"maxcpus", fmt.Sprintf("%d", a.config.DefaultMaxVCPUs)})
// add the params specified by the provided config. As the kernel
// honours the last parameter value set and since the config-provided
// params are added here, they will take priority over the defaults.
params = append(params, a.config.KernelParams...)
paramsStr := SerializeParams(params, "=")
return strings.Join(paramsStr, " ")
}
// Adds all capabilities supported by Acrn implementation of hypervisor interface
func (a *Acrn) Capabilities(ctx context.Context) types.Capabilities {
span, _ := katatrace.Trace(ctx, a.Logger(), "Capabilities", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
return a.arch.capabilities(a.config)
}
func (a *Acrn) HypervisorConfig() HypervisorConfig {
return a.config
}
// Get cpu apicid to identify vCPU that will be assigned for a VM by reading `proc/cpuinfo`
func (a *Acrn) getNextApicid() (string, error) {
fs, err := procfs.NewFS("/proc")
if err != nil {
return "", err
}
cpuinfo, err := fs.CPUInfo()
if err != nil {
return "", err
}
prevIdx := -1
fileName := filepath.Join(a.config.VMStorePath, "cpu_affinity_idx")
_, err = os.Stat(fileName)
if err == nil {
data, err := os.ReadFile(fileName)
if err != nil {
a.Logger().Error("Loading cpu affinity index from file failed!")
return "", err
}
prevIdx, err = strconv.Atoi(string(data))
if err != nil {
a.Logger().Error("CreateVM: Convert from []byte to integer failed!")
return "", err
}
if prevIdx >= (len(cpuinfo) - 1) {
prevIdx = -1
}
}
currentIdx := prevIdx + 1
err = os.WriteFile(fileName, []byte(strconv.Itoa(currentIdx)), defaultFilePerms)
if err != nil {
a.Logger().Error("Storing cpu affinity index from file failed!")
return "", err
}
return cpuinfo[currentIdx].APICID, nil
}
// get the acrn binary path
func (a *Acrn) acrnPath() (string, error) {
p, err := a.config.HypervisorAssetPath()
if err != nil {
return "", err
}
if p == "" {
p, err = a.arch.acrnPath()
if err != nil {
return "", err
}
}
if _, err = os.Stat(p); os.IsNotExist(err) {
return "", fmt.Errorf("acrn path (%s) does not exist", p)
}
return p, nil
}
// get the ACRNCTL binary path
func (a *Acrn) acrnctlPath() (string, error) {
ctlpath, err := a.config.HypervisorCtlAssetPath()
if err != nil {
return "", err
}
if ctlpath == "" {
ctlpath, err = a.arch.acrnctlPath()
if err != nil {
return "", err
}
}
if _, err = os.Stat(ctlpath); os.IsNotExist(err) {
return "", fmt.Errorf("acrnctl path (%s) does not exist", ctlpath)
}
return ctlpath, nil
}
// Logger returns a logrus logger appropriate for logging acrn messages
func (a *Acrn) Logger() *logrus.Entry {
return virtLog.WithField("subsystem", "acrn")
}
func (a *Acrn) memoryTopology() (Memory, error) {
memMb := uint64(a.config.MemorySize)
return a.arch.memoryTopology(memMb), nil
}
func (a *Acrn) appendImage(devices []Device, imagePath string) ([]Device, error) {
if imagePath == "" {
return nil, fmt.Errorf("Image path is empty: %s", imagePath)
}
var err error
devices, err = a.arch.appendImage(devices, imagePath)
if err != nil {
return nil, err
}
return devices, nil
}
func (a *Acrn) buildDevices(ctx context.Context, imagePath string) ([]Device, error) {
var devices []Device
if imagePath == "" {
return nil, fmt.Errorf("Image Path should not be empty: %s", imagePath)
}
_, console, err := a.GetVMConsole(ctx, a.id)
if err != nil {
return nil, err
}
// Add bridges before any other devices. This way we make sure that
// bridge gets the first available PCI address.
devices = a.arch.appendBridges(devices)
//Add LPC device to the list of other devices.
devices = a.arch.appendLPC(devices)
devices = a.arch.appendConsole(devices, console)
devices, err = a.appendImage(devices, imagePath)
if err != nil {
return nil, err
}
// Create virtio blk devices with dummy backend as a place
// holder for container rootfs (as acrn doesn't support hot-plug).
// Once the container rootfs is known, replace the dummy backend
// with actual path (using block rescan feature in acrn)
devices, err = a.createDummyVirtioBlkDev(ctx, devices)
if err != nil {
return nil, err
}
return devices, nil
}
// setup sets the Acrn structure up.
func (a *Acrn) setup(ctx context.Context, id string, hypervisorConfig *HypervisorConfig) error {
span, _ := katatrace.Trace(ctx, a.Logger(), "setup", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
if err := a.setConfig(hypervisorConfig); err != nil {
return err
}
a.id = id
var err error
a.arch, err = newAcrnArch(a.config)
if err != nil {
return err
}
return nil
}
func (a *Acrn) createDummyVirtioBlkDev(ctx context.Context, devices []Device) ([]Device, error) {
span, _ := katatrace.Trace(ctx, a.Logger(), "createDummyVirtioBlkDev", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
// Since acrn doesn't support hot-plug, dummy virtio-blk
// devices are added and later replaced with container-rootfs.
// Starting from driveIndex 1, as 0 is allocated for VM rootfs.
for driveIndex := 1; driveIndex <= AcrnBlkDevPoolSz; driveIndex++ {
drive := config.BlockDrive{
File: "nodisk",
Index: driveIndex,
}
devices = a.arch.appendBlockDevice(devices, drive)
}
return devices, nil
}
func (a *Acrn) setConfig(config *HypervisorConfig) error {
a.config = *config
return nil
}
// CreateVM is the VM creation
func (a *Acrn) CreateVM(ctx context.Context, id string, network Network, hypervisorConfig *HypervisorConfig) error {
// Save the tracing context
a.ctx = ctx
span, ctx := katatrace.Trace(ctx, a.Logger(), "CreateVM", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
if err := a.setup(ctx, id, hypervisorConfig); err != nil {
return err
}
memory, err := a.memoryTopology()
if err != nil {
return err
}
kernelPath, err := a.config.KernelAssetPath()
if err != nil {
return err
}
imagePath, err := a.config.ImageAssetPath()
if err != nil {
return err
}
kernel := Kernel{
Path: kernelPath,
ImagePath: imagePath,
Params: a.kernelParameters(),
}
devices, err := a.buildDevices(ctx, imagePath)
if err != nil {
return err
}
acrnPath, err := a.acrnPath()
if err != nil {
return err
}
acrnctlPath, err := a.acrnctlPath()
if err != nil {
return err
}
vmName := fmt.Sprintf("sbx-%s", a.id)
if len(vmName) > 15 {
return fmt.Errorf("VM Name len is %d but ACRN supports max VM name len of 15.", len(vmName))
}
apicID, err := a.getNextApicid()
if err != nil {
return err
}
acrnConfig := Config{
ACPIVirt: true,
Path: acrnPath,
CtlPath: acrnctlPath,
Memory: memory,
Devices: devices,
Kernel: kernel,
Name: vmName,
ApicID: apicID,
}
a.acrnConfig = acrnConfig
return nil
}
// StartVM will start the Sandbox's VM.
func (a *Acrn) StartVM(ctx context.Context, timeoutSecs int) error {
span, ctx := katatrace.Trace(ctx, a.Logger(), "StartVM", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
if a.config.Debug {
params := a.arch.kernelParameters(a.config.Debug)
strParams := SerializeParams(params, "=")
formatted := strings.Join(strParams, " ")
// The name of this field matches a similar one generated by
// the runtime and allows users to identify which parameters
// are set here, which come from the runtime and which are set
// by the user.
a.Logger().WithField("default-kernel-parameters", formatted).Debug()
}
vmPath := filepath.Join(a.config.VMStorePath, a.id)
err := os.MkdirAll(vmPath, DirMode)
if err != nil {
return err
}
defer func() {
if err != nil {
if err := os.RemoveAll(vmPath); err != nil {
a.Logger().WithError(err).Error("Failed to clean up vm directory")
}
}
}()
var strErr string
var PID int
a.Logger().Error("StartVM: LaunchAcrn() function called")
PID, strErr, err = LaunchAcrn(a.acrnConfig, virtLog.WithField("subsystem", "acrn-dm"))
if err != nil {
return fmt.Errorf("%s", strErr)
}
a.state.PID = PID
if err = a.waitVM(ctx, timeoutSecs); err != nil {
a.Logger().WithField("acrn wait failed:", err).Debug()
return err
}
return nil
}
// waitVM will wait for the Sandbox's VM to be up and running.
func (a *Acrn) waitVM(ctx context.Context, timeoutSecs int) error {
span, _ := katatrace.Trace(ctx, a.Logger(), "waitVM", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
if timeoutSecs < 0 {
return fmt.Errorf("Invalid timeout %ds", timeoutSecs)
}
time.Sleep(time.Duration(timeoutSecs) * time.Second)
return nil
}
// StopVM will stop the Sandbox's VM.
func (a *Acrn) StopVM(ctx context.Context, waitOnly bool) (err error) {
span, _ := katatrace.Trace(ctx, a.Logger(), "StopVM", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
a.Logger().Info("Stopping acrn VM")
defer func() {
if err != nil {
a.Logger().Info("StopVM failed")
} else {
a.Logger().Info("acrn VM stopped")
}
}()
fileName := filepath.Join(a.config.VMStorePath, "cpu_affinity_idx")
data, err := os.ReadFile(fileName)
if err != nil {
a.Logger().Error("Loading cpu affinity index from file failed!")
return err
}
currentIdx, err := strconv.Atoi(string(data))
if err != nil {
a.Logger().Error("Converting from []byte to integer failed!")
return err
}
currentIdx = currentIdx - 1
err = os.WriteFile(fileName, []byte(strconv.Itoa(currentIdx)), defaultFilePerms)
if err != nil {
a.Logger().Error("Storing cpu affinity index from file failed!")
return err
}
pid := a.state.PID
shutdownSignal := syscall.SIGINT
if waitOnly {
// NOP
shutdownSignal = syscall.Signal(0)
}
return utils.WaitLocalProcess(pid, acrnStopSandboxTimeoutSecs, shutdownSignal, a.Logger())
}
func (a *Acrn) updateBlockDevice(drive *config.BlockDrive) error {
if drive.Swap {
return fmt.Errorf("Acrn doesn't support swap")
}
var err error
if drive.File == "" || drive.Index >= AcrnBlkDevPoolSz {
return fmt.Errorf("Empty filepath or invalid drive index, Dive ID:%s, Drive Index:%d",
drive.ID, drive.Index)
}
slot := AcrnBlkdDevSlot[drive.Index]
//Explicitly set PCIPath to NULL, so that VirtPath can be used
drive.PCIPath = types.PciPath{}
args := []string{"blkrescan", a.acrnConfig.Name, fmt.Sprintf("%d,%s", slot, drive.File)}
a.Logger().WithFields(logrus.Fields{
"drive": drive,
"path": a.config.HypervisorCtlPath,
}).Info("updateBlockDevice with acrnctl path")
cmd := exec.Command(a.config.HypervisorCtlPath, args...)
if err := cmd.Run(); err != nil {
a.Logger().WithError(err).Error("updating Block device with newFile path")
}
return err
}
func (a *Acrn) HotplugAddDevice(ctx context.Context, devInfo interface{}, devType DeviceType) (interface{}, error) {
span, _ := katatrace.Trace(ctx, a.Logger(), "HotplugAddDevice", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
switch devType {
case BlockDev:
//The drive placeholder has to exist prior to Update
return nil, a.updateBlockDevice(devInfo.(*config.BlockDrive))
default:
return nil, fmt.Errorf("HotplugAddDevice: unsupported device: devInfo:%v, deviceType%v",
devInfo, devType)
}
}
func (a *Acrn) HotplugRemoveDevice(ctx context.Context, devInfo interface{}, devType DeviceType) (interface{}, error) {
span, _ := katatrace.Trace(ctx, a.Logger(), "HotplugRemoveDevice", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
// Not supported. return success
return nil, nil
}
func (a *Acrn) PauseVM(ctx context.Context) error {
span, _ := katatrace.Trace(ctx, a.Logger(), "PauseVM", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
// Not supported. return success
return nil
}
func (a *Acrn) ResumeVM(ctx context.Context) error {
span, _ := katatrace.Trace(ctx, a.Logger(), "ResumeVM", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
// Not supported. return success
return nil
}
// AddDevice will add extra devices to acrn command line.
func (a *Acrn) AddDevice(ctx context.Context, devInfo interface{}, devType DeviceType) error {
var err error
span, _ := katatrace.Trace(ctx, a.Logger(), "AddDevice", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
switch v := devInfo.(type) {
case types.Volume:
// Not supported. return success
err = nil
case types.Socket:
a.acrnConfig.Devices = a.arch.appendSocket(a.acrnConfig.Devices, v)
case types.VSock:
a.acrnConfig.Devices = a.arch.appendVSock(a.acrnConfig.Devices, v)
case Endpoint:
a.acrnConfig.Devices = a.arch.appendNetwork(a.acrnConfig.Devices, v)
case config.BlockDrive:
a.acrnConfig.Devices = a.arch.appendBlockDevice(a.acrnConfig.Devices, v)
case config.VhostUserDeviceAttrs:
// Not supported. return success
err = nil
case config.VFIODev:
// Not supported. return success
err = nil
default:
err = nil
a.Logger().WithField("unknown-device-type", devInfo).Error("Adding device")
}
return err
}
// GetVMConsole builds the path of the console where we can read logs coming
// from the sandbox.
func (a *Acrn) GetVMConsole(ctx context.Context, id string) (string, string, error) {
span, _ := katatrace.Trace(ctx, a.Logger(), "GetVMConsole", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
consoleURL, err := utils.BuildSocketPath(a.config.VMStorePath, id, acrnConsoleSocket)
if err != nil {
a.Logger().Error("GetVMConsole returned error")
return consoleProtoUnix, "", err
}
return consoleProtoUnix, consoleURL, nil
}
func (a *Acrn) SaveVM() error {
a.Logger().Info("Save sandbox")
// Not supported. return success
return nil
}
func (a *Acrn) Disconnect(ctx context.Context) {
span, _ := katatrace.Trace(ctx, a.Logger(), "Disconnect", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
// Not supported.
}
func (a *Acrn) GetThreadIDs(ctx context.Context) (VcpuThreadIDs, error) {
span, _ := katatrace.Trace(ctx, a.Logger(), "GetThreadIDs", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
// Not supported. return success
//Just allocating an empty map
return VcpuThreadIDs{}, nil
}
func (a *Acrn) GetTotalMemoryMB(ctx context.Context) uint32 {
return a.config.MemorySize
}
func (a *Acrn) ResizeMemory(ctx context.Context, reqMemMB uint32, memoryBlockSizeMB uint32, probe bool) (uint32, MemoryDevice, error) {
return 0, MemoryDevice{}, nil
}
func (a *Acrn) ResizeVCPUs(ctx context.Context, reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
return 0, 0, nil
}
func (a *Acrn) Cleanup(ctx context.Context) error {
span, _ := katatrace.Trace(ctx, a.Logger(), "Cleanup", acrnTracingTags, map[string]string{"sandbox_id": a.id})
defer span.End()
return nil
}
func (a *Acrn) GetPids() []int {
return []int{a.state.PID}
}
func (a *Acrn) GetVirtioFsPid() *int {
return nil
}
func (a *Acrn) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, j []byte) error {
return errors.New("acrn is not supported by VM cache")
}
func (a *Acrn) toGrpc(ctx context.Context) ([]byte, error) {
return nil, errors.New("acrn is not supported by VM cache")
}
func (a *Acrn) Save() (s hv.HypervisorState) {
s.Pid = a.state.PID
s.Type = string(AcrnHypervisor)
return
}
func (a *Acrn) Load(s hv.HypervisorState) {
a.state.PID = s.Pid
}
func (a *Acrn) Check() error {
if err := syscall.Kill(a.state.PID, syscall.Signal(0)); err != nil {
return errors.Wrapf(err, "failed to ping acrn process")
}
return nil
}
func (a *Acrn) GenerateSocket(id string) (interface{}, error) {
socket, err := generateVMSocket(id, a.config.VMStorePath)
if err != nil {
return "", err
}
vsock, _ := socket.(types.VSock)
vsock.VhostFd.Close()
return socket, err
}
func (a *Acrn) IsRateLimiterBuiltin() bool {
return false
}

View File

@ -1,802 +0,0 @@
//go:build linux
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"strings"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/sirupsen/logrus"
)
type acrnArch interface {
// acrnPath returns the path to the acrn binary
acrnPath() (string, error)
// acrnctlPath returns the path to the acrnctl binary
acrnctlPath() (string, error)
// kernelParameters returns the kernel parameters
// if debug is true then kernel debug parameters are included
kernelParameters(debug bool) []Param
//capabilities returns the capabilities supported by acrn
capabilities(config HypervisorConfig) types.Capabilities
// memoryTopology returns the memory topology using the given amount of memoryMb and hostMemoryMb
memoryTopology(memMb uint64) Memory
// appendConsole appends a console to devices
appendConsole(devices []Device, path string) []Device
// appendImage appends an image to devices
appendImage(devices []Device, path string) ([]Device, error)
// appendBridges appends bridges to devices
appendBridges(devices []Device) []Device
// appendLPC appends LPC to devices
// UART device emulated by the acrn-dm is connected to the system by the LPC bus
appendLPC(devices []Device) []Device
// appendSocket appends a socket to devices
appendSocket(devices []Device, socket types.Socket) []Device
// appendVSock appends a vsock PCI to devices
appendVSock(devices []Device, vsock types.VSock) []Device
// appendNetwork appends a endpoint device to devices
appendNetwork(devices []Device, endpoint Endpoint) []Device
// appendBlockDevice appends a block drive to devices
appendBlockDevice(devices []Device, drive config.BlockDrive) []Device
// handleImagePath handles the Hypervisor Config image path
handleImagePath(config HypervisorConfig) error
}
type acrnArchBase struct {
path string
ctlpath string
kernelParamsNonDebug []Param
kernelParamsDebug []Param
kernelParams []Param
}
const acrnPath = "/usr/bin/acrn-dm"
const acrnctlPath = "/usr/bin/acrnctl"
// acrn GVT-g slot is harded code to 2 as there is
// no simple way to pass arguments of PCI slots from
// device model (acrn-dm) to ACRNGT module.
const acrnGVTgReservedSlot = 2
const acrnLPCDev = "lpc"
const acrnHostBridge = "hostbridge"
var baselogger *logrus.Entry
// AcrnBlkDevPoolSz defines the number of dummy virtio-blk
// device that will be created for hot-plugging container
// rootfs. Since acrn doesn't support hot-plug, dummy virtio-blk
// devices are added and later replaced with container-rootfs.
var AcrnBlkDevPoolSz = 8
// AcrnBlkdDevSlot array provides translation between
// the vitio-blk device index and slot it is currently
// attached.
// Allocating extra 1 to accommodate for VM rootfs
// which is at driveIndex 0
var AcrnBlkdDevSlot = make([]int, AcrnBlkDevPoolSz+1)
// acrnKernelParamsNonDebug is a list of the default kernel
// parameters that will be used in standard (non-debug) mode.
var acrnKernelParamsNonDebug = []Param{
{"quiet", ""},
}
// acrnKernelParamsSystemdNonDebug is a list of the default systemd related
// kernel parameters that will be used in standard (non-debug) mode.
var acrnKernelParamsSystemdNonDebug = []Param{
{"systemd.show_status", "false"},
}
// acrnKernelParamsDebug is a list of the default kernel
// parameters that will be used in debug mode (as much boot output as
// possible).
var acrnKernelParamsDebug = []Param{
{"debug", ""},
}
// acrnKernelParamsSystemdDebug is a list of the default systemd related kernel
// parameters that will be used in debug mode (as much boot output as
// possible).
var acrnKernelParamsSystemdDebug = []Param{
{"systemd.show_status", "true"},
{"systemd.log_level", "debug"},
{"systemd.log_target", "kmsg"},
{"printk.devkmsg", "on"},
}
var acrnKernelRootParams = []Param{
{"root", "/dev/vda1 rw rootwait"},
}
var acrnKernelParams = []Param{
{"tsc", "reliable"},
{"no_timer_check", ""},
{"nohpet", ""},
{"console", "tty0"},
{"console", "ttyS0"},
{"console", "hvc0"},
{"log_buf_len", "16M"},
{"consoleblank", "0"},
}
// Device is the acrn device interface.
type Device interface {
Valid() bool
AcrnParams(slot int, config *Config) []string
}
// ConsoleDeviceBackend is the character device backend for acrn
type ConsoleDeviceBackend string
const (
// Socket creates a 2 way stream socket (TCP or Unix).
Socket ConsoleDeviceBackend = "socket"
// Stdio sends traffic from the guest to acrn's standard output.
Stdio ConsoleDeviceBackend = "console"
// File backend only supports console output to a file (no input).
File ConsoleDeviceBackend = "file"
// TTY is an alias for Serial.
TTY ConsoleDeviceBackend = "tty"
// PTY creates a new pseudo-terminal on the host and connect to it.
PTY ConsoleDeviceBackend = "pty"
)
// BEPortType marks the port as console port or virtio-serial port
type BEPortType int
const (
// SerialBE marks the port as serial port
SerialBE BEPortType = iota
//ConsoleBE marks the port as console port (append @)
ConsoleBE
)
// ConsoleDevice represents a acrn console device.
type ConsoleDevice struct {
// Name of the socket
Name string
//Path to virtio-console backend (can be omitted for pty, tty, stdio)
Path string
//Backend device used for virtio-console
Backend ConsoleDeviceBackend
// PortType marks the port as serial or console port (@)
PortType BEPortType
}
// VSOCKDevice represents a AF_VSOCK socket.
type VSOCKDevice struct {
//Guest CID assigned by Host.
ContextID uint64
}
// NetDeviceType is a acrn networking device type.
type NetDeviceType string
const (
// TAP is a TAP networking device type.
TAP NetDeviceType = "tap"
// MACVTAP is a macvtap networking device type.
MACVTAP NetDeviceType = "macvtap"
)
// NetDevice represents a guest networking device
type NetDevice struct {
// Type is the netdev type (e.g. tap).
Type NetDeviceType
// IfName is the interface name
IFName string
//MACAddress is the networking device interface MAC address
MACAddress string
}
// BlockDevice represents a acrn block device.
type BlockDevice struct {
// mem path to block device
FilePath string
//BlkIndex - Blk index corresponding to slot
Index int
}
// BridgeDevice represents a acrn bridge device like pci-bridge, pxb, etc.
type BridgeDevice struct {
// Emul is a string describing the type of PCI device e.g. virtio-net
Emul string
// Config is an optional string, depending on the device, that can be
// used for configuration
Config string
// Function is PCI function. Func can be from 0 to 7
Function int
}
// LPCDevice represents a acrn LPC device
type LPCDevice struct {
// Emul is a string describing the type of PCI device e.g. virtio-net
Emul string
// Function is PCI function. Func can be from 0 to 7
Function int
}
// Memory is the guest memory configuration structure.
type Memory struct {
// Size is the amount of memory made available to the guest.
// It should be suffixed with M or G for sizes in megabytes or
// gigabytes respectively.
Size string
}
// Kernel is the guest kernel configuration structure.
type Kernel struct {
// Path is the guest kernel path on the host filesystem.
Path string
// InitrdPath is the guest initrd path on the host filesystem.
ImagePath string
// Params is the kernel parameters string.
Params string
}
// Config is the acrn configuration structure.
// It allows for passing custom settings and parameters to the acrn-dm API.
type Config struct {
// Devices is a list of devices for acrn to create and drive.
Devices []Device
// Path is the acrn binary path.
Path string
// Path is the acrn binary path.
CtlPath string
// Name is the acrn guest name
Name string
// APICID to identify vCPU that will be assigned for this VM.
ApicID string
// Kernel is the guest kernel configuration.
Kernel Kernel
// Memory is the guest memory configuration.
Memory Memory
acrnParams []string
// ACPI virtualization support
ACPIVirt bool
}
// MaxAcrnVCPUs returns the maximum number of vCPUs supported
func MaxAcrnVCPUs() uint32 {
return uint32(8)
}
func newAcrnArch(config HypervisorConfig) (acrnArch, error) {
a := &acrnArchBase{
path: acrnPath,
ctlpath: acrnctlPath,
kernelParamsNonDebug: acrnKernelParamsNonDebug,
kernelParamsDebug: acrnKernelParamsDebug,
kernelParams: acrnKernelParams,
}
if err := a.handleImagePath(config); err != nil {
return nil, err
}
return a, nil
}
func (a *acrnArchBase) acrnPath() (string, error) {
p := a.path
return p, nil
}
func (a *acrnArchBase) acrnctlPath() (string, error) {
ctlpath := a.ctlpath
return ctlpath, nil
}
func (a *acrnArchBase) kernelParameters(debug bool) []Param {
params := a.kernelParams
if debug {
params = append(params, a.kernelParamsDebug...)
} else {
params = append(params, a.kernelParamsNonDebug...)
}
return params
}
func (a *acrnArchBase) memoryTopology(memoryMb uint64) Memory {
mem := fmt.Sprintf("%dM", memoryMb)
memory := Memory{
Size: mem,
}
return memory
}
func (a *acrnArchBase) capabilities(config HypervisorConfig) types.Capabilities {
var caps types.Capabilities
caps.SetBlockDeviceSupport()
caps.SetBlockDeviceHotplugSupport()
caps.SetNetworkDeviceHotplugSupported()
return caps
}
// Valid returns true if the CharDevice structure is valid and complete.
func (cdev ConsoleDevice) Valid() bool {
if cdev.Backend != "tty" && cdev.Backend != "pty" &&
cdev.Backend != "console" && cdev.Backend != "socket" &&
cdev.Backend != "file" {
return false
} else if cdev.PortType != ConsoleBE && cdev.PortType != SerialBE {
return false
} else if cdev.Path == "" {
return false
} else {
return true
}
}
// AcrnParams returns the acrn parameters built out of this console device.
func (cdev ConsoleDevice) AcrnParams(slot int, config *Config) []string {
var acrnParams []string
var deviceParams []string
acrnParams = append(acrnParams, "-s")
deviceParams = append(deviceParams, fmt.Sprintf("%d,virtio-console,", slot))
if cdev.PortType == ConsoleBE {
deviceParams = append(deviceParams, "@")
}
switch cdev.Backend {
case "pty":
deviceParams = append(deviceParams, "pty:pty_port")
case "tty":
deviceParams = append(deviceParams, fmt.Sprintf("tty:tty_port=%s", cdev.Path))
case "socket":
deviceParams = append(deviceParams, fmt.Sprintf("socket:%s=%s", cdev.Name, cdev.Path))
case "file":
deviceParams = append(deviceParams, fmt.Sprintf("file:file_port=%s", cdev.Path))
case "stdio":
deviceParams = append(deviceParams, "stdio:stdio_port")
default:
// do nothing. Error should be already caught
}
acrnParams = append(acrnParams, strings.Join(deviceParams, ""))
return acrnParams
}
// AcrnNetdevParam converts to the acrn type to string
func (netdev NetDevice) AcrnNetdevParam() []string {
var deviceParams []string
switch netdev.Type {
case TAP:
deviceParams = append(deviceParams, netdev.IFName)
deviceParams = append(deviceParams, fmt.Sprintf(",mac=%s", netdev.MACAddress))
case MACVTAP:
deviceParams = append(deviceParams, netdev.IFName)
deviceParams = append(deviceParams, fmt.Sprintf(",mac=%s", netdev.MACAddress))
default:
deviceParams = append(deviceParams, netdev.IFName)
}
return deviceParams
}
const (
// MinimalGuestCID is the smallest valid context ID for a guest.
MinimalGuestCID uint64 = 3
// MaxGuestCID is the largest valid context ID for a guest.
MaxGuestCID uint64 = 1<<32 - 1
)
// Valid returns true if the VSOCKDevice structure is valid and complete.
func (vsock VSOCKDevice) Valid() bool {
if vsock.ContextID < MinimalGuestCID || vsock.ContextID > MaxGuestCID {
return false
}
return true
}
// AcrnParams returns the acrn parameters built out of this vsock device.
func (vsock VSOCKDevice) AcrnParams(slot int, config *Config) []string {
var acrnParams []string
acrnParams = append(acrnParams, "-s")
acrnParams = append(acrnParams, fmt.Sprintf("%d,vhost-vsock,cid=%d", slot, uint32(vsock.ContextID)))
return acrnParams
}
// Valid returns true if the NetDevice structure is valid and complete.
func (netdev NetDevice) Valid() bool {
if netdev.IFName == "" {
return false
} else if netdev.MACAddress == "" {
return false
} else if netdev.Type != TAP && netdev.Type != MACVTAP {
return false
} else {
return true
}
}
// AcrnParams returns the acrn parameters built out of this network device.
func (netdev NetDevice) AcrnParams(slot int, config *Config) []string {
var acrnParams []string
acrnParams = append(acrnParams, "-s")
acrnParams = append(acrnParams, fmt.Sprintf("%d,virtio-net,%s", slot, strings.Join(netdev.AcrnNetdevParam(), "")))
return acrnParams
}
// Valid returns true if the BlockDevice structure is valid and complete.
func (blkdev BlockDevice) Valid() bool {
return blkdev.FilePath != ""
}
// AcrnParams returns the acrn parameters built out of this block device.
func (blkdev BlockDevice) AcrnParams(slot int, config *Config) []string {
var acrnParams []string
device := "virtio-blk"
acrnParams = append(acrnParams, "-s")
acrnParams = append(acrnParams, fmt.Sprintf("%d,%s,%s",
slot, device, blkdev.FilePath))
// Update the global array (BlkIndex<->slot)
// Used to identify slots for the hot-plugged virtio-blk devices
if blkdev.Index <= AcrnBlkDevPoolSz {
AcrnBlkdDevSlot[blkdev.Index] = slot
} else {
baselogger.WithFields(logrus.Fields{
"device": device,
"index": blkdev.Index,
}).Info("Invalid index device")
}
return acrnParams
}
// Valid returns true if the BridgeDevice structure is valid and complete.
func (bridgeDev BridgeDevice) Valid() bool {
if bridgeDev.Function != 0 || bridgeDev.Emul != acrnHostBridge {
return false
}
return true
}
// AcrnParams returns the acrn parameters built out of this bridge device.
func (bridgeDev BridgeDevice) AcrnParams(slot int, config *Config) []string {
var acrnParams []string
acrnParams = append(acrnParams, "-s")
acrnParams = append(acrnParams, fmt.Sprintf("%d:%d,%s", slot,
bridgeDev.Function, bridgeDev.Emul))
return acrnParams
}
// Valid returns true if the BridgeDevice structure is valid and complete.
func (lpcDev LPCDevice) Valid() bool {
return lpcDev.Emul == acrnLPCDev
}
// AcrnParams returns the acrn parameters built out of this bridge device.
func (lpcDev LPCDevice) AcrnParams(slot int, config *Config) []string {
var acrnParams []string
var deviceParams []string
acrnParams = append(acrnParams, "-s")
acrnParams = append(acrnParams, fmt.Sprintf("%d:%d,%s", slot,
lpcDev.Function, lpcDev.Emul))
//define UART port
deviceParams = append(deviceParams, "-l")
deviceParams = append(deviceParams, "com1,stdio")
acrnParams = append(acrnParams, strings.Join(deviceParams, ""))
return acrnParams
}
func (config *Config) appendName() {
if config.Name != "" {
config.acrnParams = append(config.acrnParams, config.Name)
}
}
func (config *Config) appendDevices() {
slot := 0
for _, d := range config.Devices {
if !d.Valid() {
continue
}
if slot == acrnGVTgReservedSlot {
slot++ /*Slot 2 is assigned for GVT-g in acrn, so skip 2 */
baselogger.Info("Slot 2 is assigned for GVT-g in acrn, so skipping this slot")
}
config.acrnParams = append(config.acrnParams, d.AcrnParams(slot, config)...)
slot++
}
}
func (config *Config) appendACPI() {
if config.ACPIVirt {
config.acrnParams = append(config.acrnParams, "-A")
}
}
func (config *Config) appendMemory() {
if config.Memory.Size != "" {
config.acrnParams = append(config.acrnParams, "-m")
config.acrnParams = append(config.acrnParams, config.Memory.Size)
}
}
func (config *Config) appendCPUAffinity() {
if config.ApicID == "" {
return
}
config.acrnParams = append(config.acrnParams, "--cpu_affinity")
config.acrnParams = append(config.acrnParams, config.ApicID)
}
func (config *Config) appendKernel() {
if config.Kernel.Path == "" {
return
}
config.acrnParams = append(config.acrnParams, "-k")
config.acrnParams = append(config.acrnParams, config.Kernel.Path)
if config.Kernel.Params == "" {
return
}
config.acrnParams = append(config.acrnParams, "-B")
config.acrnParams = append(config.acrnParams, config.Kernel.Params)
}
// LaunchAcrn can be used to launch a new acrn instance.
//
// The Config parameter contains a set of acrn parameters and settings.
//
// This function writes its log output via logger parameter.
func LaunchAcrn(config Config, logger *logrus.Entry) (int, string, error) {
baselogger = logger
config.appendACPI()
config.appendMemory()
config.appendDevices()
config.appendCPUAffinity()
config.appendKernel()
config.appendName()
return LaunchCustomAcrn(context.Background(), config.Path, config.acrnParams, logger)
}
// LaunchCustomAcrn can be used to launch a new acrn instance.
//
// The path parameter is used to pass the acrn executable path.
//
// params is a slice of options to pass to acrn-dm
//
// This function writes its log output via logger parameter.
func LaunchCustomAcrn(ctx context.Context, path string, params []string,
logger *logrus.Entry) (int, string, error) {
errStr := ""
if path == "" {
path = "acrn-dm"
}
/* #nosec */
cmd := exec.CommandContext(ctx, path, params...)
var stderr bytes.Buffer
cmd.Stderr = &stderr
logger.WithFields(logrus.Fields{
"Path": path,
"Params": params,
}).Info("launching acrn with:")
err := cmd.Start()
if err != nil {
logger.Errorf("Unable to launch %s: %v", path, err)
errStr = stderr.String()
logger.Errorf("%s", errStr)
}
return cmd.Process.Pid, errStr, err
}
func (a *acrnArchBase) appendImage(devices []Device, path string) ([]Device, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil, err
}
ImgBlkdevice := BlockDevice{
FilePath: path,
Index: 0,
}
devices = append(devices, ImgBlkdevice)
return devices, nil
}
// appendBridges appends to devices the given bridges
func (a *acrnArchBase) appendBridges(devices []Device) []Device {
devices = append(devices,
BridgeDevice{
Function: 0,
Emul: acrnHostBridge,
Config: "",
},
)
return devices
}
// appendBridges appends to devices the given bridges
func (a *acrnArchBase) appendLPC(devices []Device) []Device {
devices = append(devices,
LPCDevice{
Function: 0,
Emul: acrnLPCDev,
},
)
return devices
}
func (a *acrnArchBase) appendConsole(devices []Device, path string) []Device {
console := ConsoleDevice{
Name: "console0",
Backend: Socket,
PortType: ConsoleBE,
Path: path,
}
devices = append(devices, console)
return devices
}
func (a *acrnArchBase) appendSocket(devices []Device, socket types.Socket) []Device {
serailsocket := ConsoleDevice{
Name: socket.Name,
Backend: Socket,
PortType: SerialBE,
Path: socket.HostPath,
}
devices = append(devices, serailsocket)
return devices
}
func (a *acrnArchBase) appendVSock(devices []Device, vsock types.VSock) []Device {
vmsock := VSOCKDevice{
ContextID: vsock.ContextID,
}
devices = append(devices, vmsock)
return devices
}
func networkModelToAcrnType(model NetInterworkingModel) NetDeviceType {
switch model {
case NetXConnectMacVtapModel:
return MACVTAP
default:
//TAP should work for most other cases
return TAP
}
}
func (a *acrnArchBase) appendNetwork(devices []Device, endpoint Endpoint) []Device {
switch ep := endpoint.(type) {
case *VethEndpoint:
netPair := ep.NetworkPair()
devices = append(devices,
NetDevice{
Type: networkModelToAcrnType(netPair.NetInterworkingModel),
IFName: netPair.TAPIface.Name,
MACAddress: netPair.TAPIface.HardAddr,
},
)
case *MacvtapEndpoint:
devices = append(devices,
NetDevice{
Type: MACVTAP,
IFName: ep.Name(),
MACAddress: ep.HardwareAddr(),
},
)
default:
// Return devices as is for unsupported endpoint.
baselogger.WithField("Endpoint", endpoint).Error("Unsupported N/W Endpoint")
}
return devices
}
func (a *acrnArchBase) appendBlockDevice(devices []Device, drive config.BlockDrive) []Device {
if drive.File == "" {
return devices
}
devices = append(devices,
BlockDevice{
FilePath: drive.File,
Index: drive.Index,
},
)
return devices
}
func (a *acrnArchBase) handleImagePath(config HypervisorConfig) error {
if config.ImagePath != "" {
a.kernelParams = append(a.kernelParams, acrnKernelRootParams...)
a.kernelParamsNonDebug = append(a.kernelParamsNonDebug, acrnKernelParamsSystemdNonDebug...)
a.kernelParamsDebug = append(a.kernelParamsDebug, acrnKernelParamsSystemdDebug...)
}
return nil
}

View File

@ -1,305 +0,0 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
//go:build linux
// +build linux
package virtcontainers
import (
"fmt"
"net"
"os"
"path/filepath"
"testing"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/fs"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/stretchr/testify/assert"
)
const (
acrnArchBaseAcrnPath = "/usr/bin/acrn"
acrnArchBaseAcrnCtlPath = "/usr/bin/acrnctl"
)
var acrnArchBaseKernelParamsNonDebug = []Param{
{"quiet", ""},
}
var acrnArchBaseKernelParamsDebug = []Param{
{"debug", ""},
}
var acrnArchBaseKernelParams = []Param{
{"root", "/dev/vda"},
}
func newAcrnArchBase() *acrnArchBase {
return &acrnArchBase{
path: acrnArchBaseAcrnPath,
ctlpath: acrnArchBaseAcrnCtlPath,
kernelParamsNonDebug: acrnArchBaseKernelParamsNonDebug,
kernelParamsDebug: acrnArchBaseKernelParamsDebug,
kernelParams: acrnArchBaseKernelParams,
}
}
func TestAcrnArchBaseAcrnPaths(t *testing.T) {
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
p, err := acrnArchBase.acrnPath()
assert.NoError(err)
assert.Equal(p, acrnArchBaseAcrnPath)
ctlp, err := acrnArchBase.acrnctlPath()
assert.NoError(err)
assert.Equal(ctlp, acrnArchBaseAcrnCtlPath)
}
func TestAcrnArchBaseKernelParameters(t *testing.T) {
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
// with debug params
expectedParams := acrnArchBaseKernelParams
debugParams := acrnArchBaseKernelParamsDebug
expectedParams = append(expectedParams, debugParams...)
p := acrnArchBase.kernelParameters(true)
assert.Equal(expectedParams, p)
// with non-debug params
expectedParams = acrnArchBaseKernelParams
nonDebugParams := acrnArchBaseKernelParamsNonDebug
expectedParams = append(expectedParams, nonDebugParams...)
p = acrnArchBase.kernelParameters(false)
assert.Equal(expectedParams, p)
}
func TestAcrnArchBaseCapabilities(t *testing.T) {
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
config := HypervisorConfig{}
c := acrnArchBase.capabilities(config)
assert.True(c.IsBlockDeviceSupported())
assert.True(c.IsBlockDeviceHotplugSupported())
assert.False(c.IsFsSharingSupported())
assert.True(c.IsNetworkDeviceHotplugSupported())
}
func TestAcrnArchBaseMemoryTopology(t *testing.T) {
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
mem := uint64(8192)
expectedMemory := Memory{
Size: fmt.Sprintf("%dM", mem),
}
m := acrnArchBase.memoryTopology(mem)
assert.Equal(expectedMemory, m)
}
func TestAcrnArchBaseAppendConsoles(t *testing.T) {
var devices []Device
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
path := filepath.Join(filepath.Join(fs.MockRunStoragePath(), "test"), consoleSocket)
expectedOut := []Device{
ConsoleDevice{
Name: "console0",
Backend: Socket,
PortType: ConsoleBE,
Path: path,
},
}
devices = acrnArchBase.appendConsole(devices, path)
assert.Equal(expectedOut, devices)
}
func TestAcrnArchBaseAppendImage(t *testing.T) {
var devices []Device
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
image, err := os.CreateTemp("", "img")
assert.NoError(err)
defer os.Remove(image.Name())
err = image.Close()
assert.NoError(err)
devices, err = acrnArchBase.appendImage(devices, image.Name())
assert.NoError(err)
assert.Len(devices, 1)
expectedOut := []Device{
BlockDevice{
FilePath: image.Name(),
Index: 0,
},
}
assert.Equal(expectedOut, devices)
}
func TestAcrnArchBaseAppendBridges(t *testing.T) {
function := 0
emul := acrnHostBridge
config := ""
var devices []Device
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
devices = acrnArchBase.appendBridges(devices)
assert.Len(devices, 1)
expectedOut := []Device{
BridgeDevice{
Function: function,
Emul: emul,
Config: config,
},
}
assert.Equal(expectedOut, devices)
}
func TestAcrnArchBaseAppendLpcDevice(t *testing.T) {
function := 0
emul := acrnLPCDev
var devices []Device
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
devices = acrnArchBase.appendLPC(devices)
assert.Len(devices, 1)
expectedOut := []Device{
LPCDevice{
Function: function,
Emul: emul,
},
}
assert.Equal(expectedOut, devices)
}
func testAcrnArchBaseAppend(t *testing.T, structure interface{}, expected []Device) {
var devices []Device
var err error
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
switch s := structure.(type) {
case types.Socket:
devices = acrnArchBase.appendSocket(devices, s)
case config.BlockDrive:
devices = acrnArchBase.appendBlockDevice(devices, s)
}
assert.NoError(err)
assert.Equal(devices, expected)
}
func TestAcrnArchBaseAppendSocket(t *testing.T) {
name := "archserial.test"
hostPath := "/tmp/archserial.sock"
expectedOut := []Device{
ConsoleDevice{
Name: name,
Backend: Socket,
PortType: SerialBE,
Path: hostPath,
},
}
socket := types.Socket{
HostPath: hostPath,
Name: name,
}
testAcrnArchBaseAppend(t, socket, expectedOut)
}
func TestAcrnArchBaseAppendBlockDevice(t *testing.T) {
path := "/tmp/archtest.img"
index := 5
expectedOut := []Device{
BlockDevice{
FilePath: path,
Index: index,
},
}
drive := config.BlockDrive{
File: path,
Index: index,
}
testAcrnArchBaseAppend(t, drive, expectedOut)
}
func TestAcrnArchBaseAppendNetwork(t *testing.T) {
var devices []Device
assert := assert.New(t)
acrnArchBase := newAcrnArchBase()
macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x04}
vethEp := &VethEndpoint{
NetPair: NetworkInterfacePair{
TapInterface: TapInterface{
ID: "uniqueTestID0",
Name: "br0_kata",
TAPIface: NetworkInterface{
Name: "tap0_kata",
},
},
VirtIface: NetworkInterface{
Name: "eth0",
HardAddr: macAddr.String(),
},
NetInterworkingModel: DefaultNetInterworkingModel,
},
EndpointType: VethEndpointType,
}
macvtapEp := &MacvtapEndpoint{
EndpointType: MacvtapEndpointType,
EndpointProperties: NetworkInfo{
Iface: NetlinkIface{
Type: "macvtap",
},
},
}
expectedOut := []Device{
NetDevice{
Type: TAP,
IFName: vethEp.NetPair.TAPIface.Name,
MACAddress: vethEp.NetPair.TAPIface.HardAddr,
},
NetDevice{
Type: MACVTAP,
IFName: macvtapEp.Name(),
MACAddress: macvtapEp.HardwareAddr(),
},
}
devices = acrnArchBase.appendNetwork(devices, vethEp)
devices = acrnArchBase.appendNetwork(devices, macvtapEp)
assert.Equal(expectedOut, devices)
}

View File

@ -1,287 +0,0 @@
//go:build linux
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"context"
"fmt"
"path/filepath"
"testing"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/stretchr/testify/assert"
)
func newAcrnConfig() HypervisorConfig {
return HypervisorConfig{
KernelPath: testAcrnKernelPath,
ImagePath: testAcrnImagePath,
HypervisorPath: testAcrnPath,
HypervisorCtlPath: testAcrnCtlPath,
NumVCPUsF: defaultVCPUs,
MemorySize: defaultMemSzMiB,
BlockDeviceDriver: config.VirtioBlock,
DefaultBridges: defaultBridges,
DefaultMaxVCPUs: MaxAcrnVCPUs(),
// Adding this here, as hypervisorconfig.valid()
// forcefully adds it even when 9pfs is not supported
Msize9p: defaultMsize9p,
}
}
func testAcrnKernelParameters(t *testing.T, kernelParams []Param, debug bool) {
assert := assert.New(t)
acrnConfig := newAcrnConfig()
acrnConfig.KernelParams = kernelParams
if debug == true {
acrnConfig.Debug = true
}
a := &Acrn{
config: acrnConfig,
arch: &acrnArchBase{},
}
expected := fmt.Sprintf("panic=1 maxcpus=%d foo=foo bar=bar", a.config.DefaultMaxVCPUs)
params := a.kernelParameters()
assert.Equal(params, expected)
}
func TestAcrnKernelParameters(t *testing.T) {
params := []Param{
{
Key: "foo",
Value: "foo",
},
{
Key: "bar",
Value: "bar",
},
}
testAcrnKernelParameters(t, params, true)
testAcrnKernelParameters(t, params, false)
}
func TestAcrnCapabilities(t *testing.T) {
assert := assert.New(t)
a := &Acrn{
ctx: context.Background(),
arch: &acrnArchBase{},
}
caps := a.Capabilities(a.ctx)
assert.True(caps.IsBlockDeviceSupported())
assert.True(caps.IsBlockDeviceHotplugSupported())
assert.True(caps.IsNetworkDeviceHotplugSupported())
}
func testAcrnAddDevice(t *testing.T, devInfo interface{}, devType DeviceType, expected []Device) {
assert := assert.New(t)
a := &Acrn{
ctx: context.Background(),
arch: &acrnArchBase{},
}
err := a.AddDevice(context.Background(), devInfo, devType)
assert.NoError(err)
assert.Exactly(a.acrnConfig.Devices, expected)
}
func TestAcrnAddDeviceSerialPortDev(t *testing.T) {
name := "serial.test"
hostPath := "/tmp/serial.sock"
expectedOut := []Device{
ConsoleDevice{
Name: name,
Backend: Socket,
PortType: SerialBE,
Path: hostPath,
},
}
socket := types.Socket{
HostPath: hostPath,
Name: name,
}
testAcrnAddDevice(t, socket, SerialPortDev, expectedOut)
}
func TestAcrnAddDeviceBlockDev(t *testing.T) {
path := "/tmp/test.img"
index := 1
expectedOut := []Device{
BlockDevice{
FilePath: path,
Index: index,
},
}
drive := config.BlockDrive{
File: path,
Index: index,
}
testAcrnAddDevice(t, drive, BlockDev, expectedOut)
}
func TestAcrnHotplugUnsupportedDeviceType(t *testing.T) {
assert := assert.New(t)
acrnConfig := newAcrnConfig()
a := &Acrn{
ctx: context.Background(),
id: "acrnTest",
config: acrnConfig,
}
_, err := a.HotplugAddDevice(a.ctx, &MemoryDevice{0, 128, uint64(0), false}, FsDev)
assert.Error(err)
}
func TestAcrnUpdateBlockDeviceInvalidPath(t *testing.T) {
assert := assert.New(t)
path := ""
index := 1
acrnConfig := newAcrnConfig()
a := &Acrn{
ctx: context.Background(),
id: "acrnBlkTest",
config: acrnConfig,
}
drive := &config.BlockDrive{
File: path,
Index: index,
}
err := a.updateBlockDevice(drive)
assert.Error(err)
}
func TestAcrnUpdateBlockDeviceInvalidIdx(t *testing.T) {
assert := assert.New(t)
path := "/tmp/test.img"
index := AcrnBlkDevPoolSz + 1
acrnConfig := newAcrnConfig()
a := &Acrn{
ctx: context.Background(),
id: "acrnBlkTest",
config: acrnConfig,
}
drive := &config.BlockDrive{
File: path,
Index: index,
}
err := a.updateBlockDevice(drive)
assert.Error(err)
}
func TestAcrnGetSandboxConsole(t *testing.T) {
assert := assert.New(t)
store, err := persist.GetDriver()
assert.NoError(err)
a := &Acrn{
ctx: context.Background(),
config: HypervisorConfig{
VMStorePath: store.RunVMStoragePath(),
RunStorePath: store.RunStoragePath(),
},
store: store,
}
sandboxID := "testSandboxID"
expected := filepath.Join(store.RunVMStoragePath(), sandboxID, consoleSocket)
proto, result, err := a.GetVMConsole(a.ctx, sandboxID)
assert.NoError(err)
assert.Equal(result, expected)
assert.Equal(proto, consoleProtoUnix)
}
func TestAcrnCreateVM(t *testing.T) {
assert := assert.New(t)
acrnConfig := newAcrnConfig()
store, err := persist.GetDriver()
assert.NoError(err)
a := &Acrn{
store: store,
config: HypervisorConfig{
VMStorePath: store.RunVMStoragePath(),
RunStorePath: store.RunStoragePath(),
},
}
sandbox := &Sandbox{
ctx: context.Background(),
id: "testSandbox",
config: &SandboxConfig{
HypervisorConfig: acrnConfig,
},
state: types.SandboxState{BlockIndexMap: make(map[int]struct{})},
}
a.sandbox = sandbox
a.state.PID = 1
network, err := NewNetwork()
assert.NoError(err)
err = a.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)
assert.NoError(err)
assert.Exactly(acrnConfig, a.config)
}
func TestAcrnMemoryTopology(t *testing.T) {
mem := uint32(1000)
assert := assert.New(t)
a := &Acrn{
arch: &acrnArchBase{},
config: HypervisorConfig{
MemorySize: mem,
},
}
expectedOut := Memory{
Size: fmt.Sprintf("%dM", mem),
}
memory, err := a.memoryTopology()
assert.NoError(err)
assert.Exactly(memory, expectedOut)
}
func TestAcrnSetConfig(t *testing.T) {
assert := assert.New(t)
config := newAcrnConfig()
a := &Acrn{}
assert.Equal(a.config, HypervisorConfig{})
err := a.setConfig(&config)
assert.NoError(err)
assert.Equal(a.config, config)
}

View File

@ -102,9 +102,6 @@ const (
// QemuHypervisor is the QEMU hypervisor.
QemuHypervisor HypervisorType = "qemu"
// AcrnHypervisor is the ACRN hypervisor.
AcrnHypervisor HypervisorType = "acrn"
// ClhHypervisor is the ICH hypervisor.
ClhHypervisor HypervisorType = "clh"
@ -173,12 +170,6 @@ type HypervisorConfig struct {
// HypervisorPathList is the list of hypervisor paths names allowed in annotations
HypervisorPathList []string
// HypervisorCtlPathList is the list of hypervisor control paths names allowed in annotations
HypervisorCtlPathList []string
// HypervisorCtlPath is the hypervisor ctl executable host path.
HypervisorCtlPath string
// JailerPath is the jailer executable host path.
JailerPath string

View File

@ -589,11 +589,7 @@ func (f *FilesystemShare) ShareRootFilesystem(ctx context.Context, c *Container)
rootfsStorage.Source = blockDrive.DevNo
case f.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock:
rootfsStorage.Driver = kataBlkDevType
if f.sandbox.config.HypervisorType == AcrnHypervisor {
rootfsStorage.Source = blockDrive.VirtPath
} else {
rootfsStorage.Source = blockDrive.PCIPath.String()
}
case f.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI:
rootfsStorage.Driver = kataSCSIDevType
rootfsStorage.Source = blockDrive.SCSIAddr

View File

@ -42,9 +42,6 @@ const (
// QemuHypervisor is the QEMU hypervisor.
QemuHypervisor HypervisorType = "qemu"
// AcrnHypervisor is the ACRN hypervisor.
AcrnHypervisor HypervisorType = "acrn"
// ClhHypervisor is the ICH hypervisor.
ClhHypervisor HypervisorType = "clh"
@ -231,9 +228,6 @@ func (hType *HypervisorType) Set(value string) error {
case "firecracker":
*hType = FirecrackerHypervisor
return nil
case "acrn":
*hType = AcrnHypervisor
return nil
case "clh":
*hType = ClhHypervisor
return nil
@ -261,8 +255,6 @@ func (hType *HypervisorType) String() string {
return string(QemuHypervisor)
case FirecrackerHypervisor:
return string(FirecrackerHypervisor)
case AcrnHypervisor:
return string(AcrnHypervisor)
case ClhHypervisor:
return string(ClhHypervisor)
case StratovirtHypervisor:
@ -357,9 +349,6 @@ type HypervisorConfig struct {
// HypervisorPath is the hypervisor executable host path.
HypervisorPath string
// HypervisorCtlPath is the hypervisor ctl executable host path.
HypervisorCtlPath string
// JailerPath is the jailer executable host path.
JailerPath string
@ -430,9 +419,6 @@ type HypervisorConfig struct {
// HypervisorPathList is the list of hypervisor paths names allowed in annotations
HypervisorPathList []string
// HypervisorCtlPathList is the list of hypervisor control paths names allowed in annotations
HypervisorCtlPathList []string
// JailerPathList is the list of jailer paths names allowed in annotations
JailerPathList []string
@ -809,8 +795,6 @@ func (conf *HypervisorConfig) assetPath(t types.AssetType) (string, error) {
return conf.InitrdPath, nil
case types.HypervisorAsset:
return conf.HypervisorPath, nil
case types.HypervisorCtlAsset:
return conf.HypervisorCtlPath, nil
case types.JailerAsset:
return conf.JailerPath, nil
case types.FirmwareAsset:
@ -866,11 +850,6 @@ func (conf *HypervisorConfig) IfPVPanicEnabled() bool {
return conf.GuestMemoryDumpPath != ""
}
// HypervisorCtlAssetPath returns the VM hypervisor ctl path
func (conf *HypervisorConfig) HypervisorCtlAssetPath() (string, error) {
return conf.assetPath(types.HypervisorCtlAsset)
}
// CustomHypervisorAsset returns true if the hypervisor asset is a custom one, false otherwise.
func (conf *HypervisorConfig) CustomHypervisorAsset() bool {
return conf.isCustomAsset(types.HypervisorAsset)

View File

@ -32,8 +32,6 @@ func NewHypervisor(hType HypervisorType) (Hypervisor, error) {
return &qemu{}, nil
case FirecrackerHypervisor:
return &firecracker{}, nil
case AcrnHypervisor:
return &Acrn{}, nil
case ClhHypervisor:
return &cloudHypervisor{}, nil
case StratovirtHypervisor:

View File

@ -477,7 +477,6 @@ func TestAssetPath(t *testing.T) {
// annotation name.
cfg := HypervisorConfig{
HypervisorPath: "/" + "io.katacontainers.config.hypervisor.path",
HypervisorCtlPath: "/" + "io.katacontainers.config.hypervisor.ctlpath",
KernelPath: "/" + "io.katacontainers.config.hypervisor.kernel",

View File

@ -217,8 +217,6 @@ func (s *Sandbox) dumpConfig(ss *persistapi.SandboxState) {
CPUFeatures: sconfig.HypervisorConfig.CPUFeatures,
HypervisorPath: sconfig.HypervisorConfig.HypervisorPath,
HypervisorPathList: sconfig.HypervisorConfig.HypervisorPathList,
HypervisorCtlPath: sconfig.HypervisorConfig.HypervisorCtlPath,
HypervisorCtlPathList: sconfig.HypervisorConfig.HypervisorCtlPathList,
JailerPath: sconfig.HypervisorConfig.JailerPath,
JailerPathList: sconfig.HypervisorConfig.JailerPathList,
BlockDeviceDriver: sconfig.HypervisorConfig.BlockDeviceDriver,
@ -457,8 +455,6 @@ func loadSandboxConfig(id string) (*SandboxConfig, error) {
CPUFeatures: hconf.CPUFeatures,
HypervisorPath: hconf.HypervisorPath,
HypervisorPathList: hconf.HypervisorPathList,
HypervisorCtlPath: hconf.HypervisorCtlPath,
HypervisorCtlPathList: hconf.HypervisorCtlPathList,
JailerPath: hconf.JailerPath,
JailerPathList: hconf.JailerPathList,
BlockDeviceDriver: hconf.BlockDeviceDriver,

View File

@ -36,10 +36,6 @@ type HypervisorConfig struct {
// HypervisorPath is the hypervisor executable host path.
HypervisorPath string
// HypervisorCtlPath is the hypervisor ctl executable host path.
HypervisorCtlPath string
// HypervisorCtlPath is the hypervisor ctl executable host path.
// JailerPath is the jailer executable host path.
JailerPath string
@ -94,9 +90,6 @@ type HypervisorConfig struct {
// HypervisorPathList is the list of hypervisor paths names allowed in annotations
HypervisorPathList []string
// HypervisorCtlPathList is the list of hypervisor control paths names allowed in annotations
HypervisorCtlPathList []string
// JailerPathList is the list of jailer paths names allowed in annotations
JailerPathList []string

View File

@ -18,14 +18,6 @@ type PersistDriver interface {
// It returns Unlock Function and errors
Lock(sid string, exclusive bool) (func() error, error)
// GlobalWrite writes "data" to "StorageRootPath"/"relativePath";
// GlobalRead reads "data" from "StorageRootPath"/"relativePath";
// these functions are used for writing/reading some global data,
// they are specially designed for ACRN so far.
// Don't use them too much unless you have no other choice! @weizhang555
GlobalWrite(relativePath string, data []byte) error
GlobalRead(relativePath string) ([]byte, error)
// RunStoragePath is the sandbox runtime directory.
// It will contain one state.json and one lock file for each created sandbox.
RunStoragePath() string

View File

@ -43,15 +43,9 @@ const (
// HypervisorPath is a sandbox annotation for passing a per container path pointing at the hypervisor that will run the container VM.
HypervisorPath = kataAnnotHypervisorPrefix + "path"
// HypervisorCtlPath is a sandbox annotation for passing a per container path pointing at the hypervisor control binary that will run the container VM.
HypervisorCtlPath = kataAnnotHypervisorPrefix + "ctlpath"
// JailerPath is a sandbox annotation for passing a per container path pointing at the jailer that will constrain the container VM.
JailerPath = kataAnnotHypervisorPrefix + "jailer_path"
// CtlPath is a sandbox annotation for passing a per container path pointing at the acrn ctl binary
CtlPath = kataAnnotHypervisorPrefix + "ctlpath"
// FirmwarePath is a sandbox annotation for passing a per container path pointing at the guest firmware that will run the container VM.
FirmwarePath = kataAnnotHypervisorPrefix + "firmware"
@ -71,9 +65,6 @@ const (
// HypervisorHash is an sandbox annotation for passing a container hypervisor binary SHA-512 hash value.
HypervisorHash = kataAnnotHypervisorPrefix + "hypervisor_hash"
// HypervisorCtlHash is a sandbox annotation for passing a container hypervisor control binary SHA-512 hash value.
HypervisorCtlHash = kataAnnotHypervisorPrefix + "hypervisorctl_hash"
// JailerHash is an sandbox annotation for passing a jailer binary SHA-512 hash value.
JailerHash = kataAnnotHypervisorPrefix + "jailer_hash"

View File

@ -673,7 +673,6 @@ func TestSandboxCreateAssets(t *testing.T) {
originalInitrdPath := filepath.Join(testDir, testInitrd)
originalFirmwarePath := filepath.Join(testDir, testFirmware)
originalHypervisorPath := filepath.Join(testDir, testHypervisor)
originalHypervisorCtlPath := filepath.Join(testDir, testHypervisorCtl)
originalJailerPath := filepath.Join(testDir, testJailer)
hc := HypervisorConfig{
@ -682,7 +681,6 @@ func TestSandboxCreateAssets(t *testing.T) {
InitrdPath: originalInitrdPath,
FirmwarePath: originalFirmwarePath,
HypervisorPath: originalHypervisorPath,
HypervisorCtlPath: originalHypervisorCtlPath,
JailerPath: originalJailerPath,
}
@ -701,13 +699,6 @@ func TestSandboxCreateAssets(t *testing.T) {
annotations.HypervisorHash: assetContentHash,
},
},
{
types.HypervisorCtlAsset,
map[string]string{
annotations.HypervisorCtlPath: filename,
annotations.HypervisorCtlHash: assetContentHash,
},
},
{
types.ImageAsset,
map[string]string{

View File

@ -35,9 +35,6 @@ const (
// HypervisorAsset is an hypervisor asset.
HypervisorAsset AssetType = "hypervisor"
// HypervisorCtlAsset is a hypervisor control asset.
HypervisorCtlAsset AssetType = "hypervisorctl"
// JailerAsset is a jailer asset.
JailerAsset AssetType = "jailer"
@ -57,7 +54,6 @@ func AssetTypes() []AssetType {
FirmwareAsset,
FirmwareVolumeAsset,
HypervisorAsset,
HypervisorCtlAsset,
ImageAsset,
InitrdAsset,
JailerAsset,
@ -92,8 +88,6 @@ func (t AssetType) Annotations() (string, string, error) {
return annotations.InitrdPath, annotations.InitrdHash, nil
case HypervisorAsset:
return annotations.HypervisorPath, annotations.HypervisorHash, nil
case HypervisorCtlAsset:
return annotations.HypervisorCtlPath, annotations.HypervisorCtlHash, nil
case JailerAsset:
return annotations.JailerPath, annotations.JailerHash, nil
case FirmwareAsset:

View File

@ -115,7 +115,6 @@ func TestAssetNew(t *testing.T) {
{annotations.ImagePath, annotations.ImageHash, ImageAsset, assetContentHash, false, false},
{annotations.InitrdPath, annotations.InitrdHash, InitrdAsset, assetContentHash, false, false},
{annotations.HypervisorPath, annotations.HypervisorHash, HypervisorAsset, assetContentHash, false, false},
{annotations.HypervisorCtlPath, annotations.HypervisorCtlHash, HypervisorCtlAsset, assetContentHash, false, false},
{annotations.JailerPath, annotations.JailerHash, JailerAsset, assetContentHash, false, false},
{annotations.FirmwarePath, annotations.FirmwareHash, FirmwareAsset, assetContentHash, false, false},
{annotations.FirmwareVolumePath, annotations.FirmwareVolumeHash, FirmwareVolumeAsset, assetContentHash, false, false},
@ -125,7 +124,6 @@ func TestAssetNew(t *testing.T) {
{annotations.ImagePath, annotations.ImageHash, ImageAsset, assetContentWrongHash, true, false},
{annotations.InitrdPath, annotations.InitrdHash, InitrdAsset, assetContentWrongHash, true, false},
{annotations.HypervisorPath, annotations.HypervisorHash, HypervisorAsset, assetContentWrongHash, true, false},
{annotations.HypervisorCtlPath, annotations.HypervisorCtlHash, HypervisorCtlAsset, assetContentWrongHash, true, false},
{annotations.JailerPath, annotations.JailerHash, JailerAsset, assetContentWrongHash, true, false},
{annotations.FirmwarePath, annotations.FirmwareHash, FirmwareAsset, assetContentWrongHash, true, false},
{annotations.FirmwareVolumePath, annotations.FirmwareVolumeHash, FirmwareVolumeAsset, assetContentWrongHash, true, false},

View File

@ -28,7 +28,6 @@ const testHypervisor = "hypervisor"
const testJailer = "jailer"
const testFirmware = "firmware"
const testVirtiofsd = "virtiofsd"
const testHypervisorCtl = "hypervisorctl"
const testBundle = "bundle"
const testDisabledAsNonRoot = "Test disabled as requires root privileges"
@ -44,10 +43,6 @@ var testClhKernelPath = ""
var testClhImagePath = ""
var testClhInitrdPath = ""
var testClhPath = ""
var testAcrnKernelPath = ""
var testAcrnImagePath = ""
var testAcrnPath = ""
var testAcrnCtlPath = ""
var testStratovirtKernelPath = ""
var testStratovirtImagePath = ""
var testStratovirtInitrdPath = ""
@ -69,18 +64,6 @@ func setup() {
}
}
func setupAcrn() {
os.Mkdir(filepath.Join(testDir, testBundle), DirMode)
for _, filename := range []string{testAcrnKernelPath, testAcrnImagePath, testAcrnPath, testAcrnCtlPath} {
_, err := os.Create(filename)
if err != nil {
fmt.Printf("Could not recreate %s:%v", filename, err)
os.Exit(1)
}
}
}
func setupClh() {
os.Mkdir(filepath.Join(testDir, testBundle), DirMode)
@ -150,13 +133,6 @@ func TestMain(m *testing.M) {
setup()
testAcrnKernelPath = filepath.Join(testDir, testKernel)
testAcrnImagePath = filepath.Join(testDir, testImage)
testAcrnPath = filepath.Join(testDir, testHypervisor)
testAcrnCtlPath = filepath.Join(testDir, testHypervisorCtl)
setupAcrn()
testVirtiofsdPath = filepath.Join(testDir, testBundle, testVirtiofsd)
testClhKernelPath = filepath.Join(testDir, testBundle, testKernel)
testClhImagePath = filepath.Join(testDir, testBundle, testImage)