Optimize QEMU launch and add V-sock support

Refactored QEMU argument construction and launching logic by removing the dependency on 'agent.Computation'. This simplification makes the VM creation process more streamlined. Additionally, introduced V-sock capabilities in the QEMU configuration to facilitate improved guest-host communication. Updated the README to include kernel module setup instructions for the new V-sock feature.

The V-sock implementation enables VMs to use a consistent communication channel that is not affected by network configuration changes, enhancing reliability and potential interoperability with host services. It's important to ensure that the necessary kernel modules are loaded as part of the setup process, as documented.

Signed-off-by: SammyOina <sammyoina@gmail.com>
This commit is contained in:
SammyOina
2024-01-16 17:45:54 +03:00
parent c25cfec84c
commit 44557c39d9
6 changed files with 33 additions and 18 deletions
+1 -2
View File
@@ -12,7 +12,6 @@ import (
mglog "github.com/absmach/magistrala/logger"
"github.com/absmach/magistrala/pkg/uuid"
"github.com/ultravioletrs/cocos/agent"
"github.com/ultravioletrs/cocos/internal"
"github.com/ultravioletrs/cocos/internal/env"
"github.com/ultravioletrs/cocos/internal/events"
@@ -86,7 +85,7 @@ func main() {
if err := env.Parse(&qemuCfg, env.Options{Prefix: envPrefixQemu}); err != nil {
logger.Fatal(fmt.Sprintf("failed to load QEMU configuration: %s", err))
}
exe, args, err := qemu.ExecutableAndArgs(qemuCfg, agent.Computation{})
exe, args, err := qemu.ExecutableAndArgs(qemuCfg)
if err != nil {
logger.Fatal(fmt.Sprintf("failed to parse QEMU configuration: %s", err))
}
+13 -1
View File
@@ -47,6 +47,17 @@ sudo apt install qemu-kvm
Create `img` directory in `cmd/manager`. Create `tmp` directory in `cmd/manager`.
#### Add V-sock
The necessary kernel modules must be loaded on the hypervisor.
```shell
sudo modprobe vhost_vsock
ls -l /dev/vhost-vsock
# crw-rw-rw- 1 root kvm 10, 241 Jan 16 12:05 /dev/vhost-vsock
ls -l /dev/vsock
# crw-rw-rw- 1 root root 10, 121 Jan 16 12:05 /dev/vsock
```
### Prepare Cocos HAL
Cocos HAL for Linux is framework for building custom in-enclave Linux distribution. Use the instructions in [Readme](https://github.com/ultravioletrs/cocos/blob/main/hal/linux/README.md).
@@ -78,8 +89,9 @@ qemu-system-x86_64 \
-drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \
-netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 \
-device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \
-device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 \
-kernel $KERNEL \
-append "earlyprintk=serial console=ttyS0 computation={\"id\":\"c0d15c5e-e37d-4426-b3b7-b432c966fb09\",\"name\":\"Sample_Computation\",\"description\":\"A_sample_computation\",\"datasets\":[{\"provider\":\"Provider1\",\"id\":\"Dataset1\"},{\"provider\":\"Provider2\",\"id\":\"Dataset2\"}],\"algorithms\":[{\"provider\":\"AlgorithmProvider1\",\"id\":\"Algorithm1\"}],\"result_consumers\":[\"Consumer1\"], \"timeout\":\"10m\"}" \
-append "earlyprintk=serial console=ttyS0" \
-initrd $INITRD \
-nographic \
-monitor pty \
+13 -2
View File
@@ -56,6 +56,12 @@ type SevConfig struct {
ReducedPhysBits int `env:"SEV_REDUCED_PHYS_BITS" envDefault:"1"`
}
type VSockConfig struct {
ID string `env:"VSOCK_ID" envDefault:"vhost-vsock-pci0"`
GuestCID int `env:"VSOCK_GUEST_CID" envDefault:"3"`
vnc int `env:"VSOCK_VNC" envDefault:"0"`
}
type Config struct {
TmpFileLoc string `env:"TMP_FILE_LOC" envDefault:"tmp"`
UseSudo bool `env:"USE_SUDO" envDefault:"false"`
@@ -78,6 +84,9 @@ type Config struct {
NetDevConfig
VirtioNetPciConfig
// Vsock
VSockConfig
// disk
VirtioScsiPciConfig
DiskImgConfig
@@ -90,7 +99,7 @@ type Config struct {
Monitor string `env:"MONITOR" envDefault:"pty"`
}
func constructQemuArgs(config Config, computation string) []string {
func constructQemuArgs(config Config) []string {
args := []string{}
// virtualization
@@ -137,9 +146,11 @@ func constructQemuArgs(config Config, computation string) []string {
config.VirtioScsiPciConfig.DisableLegacy,
config.VirtioScsiPciConfig.IOMMUPlatform))
args = append(args, "-device", fmt.Sprintf("vhost-vsock-pci,id=%s,guest-cid=%d -vnc :%d", config.VSockConfig.ID, config.VSockConfig.GuestCID, config.VSockConfig.vnc))
args = append(args, "-kernel", config.DiskImgConfig.KernelFile)
args = append(args, "-append", fmt.Sprintf("earlyprintk=serial console=ttyS0 computation=%s", computation))
args = append(args, "-append", "earlyprintk=serial console=ttyS0")
args = append(args, "-initrd", config.DiskImgConfig.RootFsFile)
+4 -12
View File
@@ -4,13 +4,10 @@ package qemu
import (
"context"
"encoding/json"
"fmt"
"os/exec"
"strconv"
"github.com/gofrs/uuid"
"github.com/ultravioletrs/cocos/agent"
"github.com/ultravioletrs/cocos/internal"
)
@@ -21,7 +18,7 @@ const (
rootfsFile = "rootfs.cpio"
)
func CreateVM(ctx context.Context, cfg Config, ac agent.Computation) (*exec.Cmd, error) {
func CreateVM(ctx context.Context, cfg Config) (*exec.Cmd, error) {
// Create unique emu device identifiers.
id, err := uuid.NewV4()
if err != nil {
@@ -58,7 +55,7 @@ func CreateVM(ctx context.Context, cfg Config, ac agent.Computation) (*exec.Cmd,
}
qemuCfg.DiskImgConfig.RootFsFile = dstFile
exe, args, err := ExecutableAndArgs(qemuCfg, ac)
exe, args, err := ExecutableAndArgs(qemuCfg)
if err != nil {
return &exec.Cmd{}, err
}
@@ -70,18 +67,13 @@ func CreateVM(ctx context.Context, cfg Config, ac agent.Computation) (*exec.Cmd,
return cmd, nil
}
func ExecutableAndArgs(cfg Config, ac agent.Computation) (string, []string, error) {
func ExecutableAndArgs(cfg Config) (string, []string, error) {
exe, err := exec.LookPath(qemuRelPath)
if err != nil {
return "", nil, err
}
cmpBytes, err := json.Marshal(ac)
if err != nil {
return "", nil, err
}
args := constructQemuArgs(cfg, strconv.Quote(string(cmpBytes)))
args := constructQemuArgs(cfg)
if cfg.UseSudo {
args = append([]string{exe}, args...)
+1 -1
View File
@@ -80,7 +80,7 @@ func (ms *managerService) Run(ctx context.Context, c *Computation) (string, erro
ms.qemuCfg.HostFwdAgent = agentPort
ms.publishEvent("vm-provision", c.Id, "in-progress", json.RawMessage{})
if _, err = qemu.CreateVM(ctx, ms.qemuCfg, ac); err != nil {
if _, err = qemu.CreateVM(ctx, ms.qemuCfg); err != nil {
ms.publishEvent("vm-provision", c.Id, "failed", json.RawMessage{})
return "", err
}
+1
View File
@@ -0,0 +1 @@
package manager