Files
kata-containers/src/runtime/pkg/device/drivers/block.go
Vijay Dhanraj 435c8f181a acrn: Enable ACRN hypervisor support for Kata 2.x release
Currently ACRN hypervisor support in Kata2.x releases is broken.
This commit re-enables ACRN hypervisor support and also refactors
the code so as to remove dependency on Sandbox.

Fixes #3027

Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com>
2022-10-07 07:40:32 -07:00

186 lines
5.0 KiB
Go

// Copyright (c) 2017-2018 Intel Corporation
// Copyright (c) 2018-2019 Huawei Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package drivers
import (
"context"
"path/filepath"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/api"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
)
const maxDevIDSize = 31
// BlockDevice refers to a block storage device implementation.
type BlockDevice struct {
*GenericDevice
BlockDrive *config.BlockDrive
}
// NewBlockDevice creates a new block device based on DeviceInfo
func NewBlockDevice(devInfo *config.DeviceInfo) *BlockDevice {
return &BlockDevice{
GenericDevice: &GenericDevice{
ID: devInfo.ID,
DeviceInfo: devInfo,
},
}
}
// Attach is standard interface of api.Device, it's used to add device to some
// DeviceReceiver
func (device *BlockDevice) Attach(ctx context.Context, devReceiver api.DeviceReceiver) (err error) {
skip, err := device.bumpAttachCount(true)
if err != nil {
return err
}
if skip {
return nil
}
// Increment the block index for the sandbox. This is used to determine the name
// for the block device in the case where the block device is used as container
// rootfs and the predicted block device name needs to be provided to the agent.
index, err := devReceiver.GetAndSetSandboxBlockIndex()
defer func() {
if err != nil {
devReceiver.UnsetSandboxBlockIndex(index)
device.bumpAttachCount(false)
}
}()
if err != nil {
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",
ID: utils.MakeNameID("drive", device.DeviceInfo.ID, maxDevIDSize),
Index: index,
Pmem: device.DeviceInfo.Pmem,
ReadOnly: device.DeviceInfo.ReadOnly,
}
if fs, ok := device.DeviceInfo.DriverOptions[config.FsTypeOpt]; ok {
drive.Format = fs
}
customOptions := device.DeviceInfo.DriverOptions
if customOptions == nil ||
customOptions[config.BlockDriverOpt] == config.VirtioSCSI {
// User has not chosen a specific block device type
// Default to SCSI
scsiAddr, err := utils.GetSCSIAddress(index)
if err != nil {
return err
}
drive.SCSIAddr = scsiAddr
} else if customOptions[config.BlockDriverOpt] != config.Nvdimm {
var globalIdx int
switch customOptions[config.BlockDriverOpt] {
case config.VirtioBlock:
globalIdx = index
case config.VirtioBlockCCW:
globalIdx = index
case config.VirtioMmio:
//With firecracker the rootfs for the VM itself
//sits at /dev/vda and consumes the first index.
//Longer term block based VM rootfs should be added
//as a regular block device which eliminates the
//offset.
//https://github.com/kata-containers/runtime/issues/1061
globalIdx = index + 1
}
driveName, err := utils.GetVirtDriveName(globalIdx)
if err != nil {
return err
}
drive.VirtPath = filepath.Join("/dev", driveName)
}
deviceLogger().WithField("device", device.DeviceInfo.HostPath).WithField("VirtPath", drive.VirtPath).Infof("Attaching %s device", customOptions[config.BlockDriverOpt])
device.BlockDrive = drive
if err = devReceiver.HotplugAddDevice(ctx, device, config.DeviceBlock); err != nil {
return err
}
return nil
}
// Detach is standard interface of api.Device, it's used to remove device from some
// DeviceReceiver
func (device *BlockDevice) Detach(ctx context.Context, devReceiver api.DeviceReceiver) error {
skip, err := device.bumpAttachCount(false)
if err != nil {
return err
}
if skip {
return nil
}
defer func() {
if err != nil {
device.bumpAttachCount(true)
} else {
devReceiver.UnsetSandboxBlockIndex(device.BlockDrive.Index)
}
}()
deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Unplugging block device")
if err = devReceiver.HotplugRemoveDevice(ctx, device, config.DeviceBlock); err != nil {
deviceLogger().WithError(err).Error("Failed to unplug block device")
return err
}
return nil
}
// DeviceType is standard interface of api.Device, it returns device type
func (device *BlockDevice) DeviceType() config.DeviceType {
return config.DeviceBlock
}
// GetDeviceInfo returns device information used for creating
func (device *BlockDevice) GetDeviceInfo() interface{} {
return device.BlockDrive
}
// Save converts Device to DeviceState
func (device *BlockDevice) Save() config.DeviceState {
ds := device.GenericDevice.Save()
ds.Type = string(device.DeviceType())
ds.BlockDrive = device.BlockDrive
return ds
}
// Load loads DeviceState and converts it to specific device
func (device *BlockDevice) Load(ds config.DeviceState) {
device.GenericDevice = &GenericDevice{}
device.GenericDevice.Load(ds)
device.BlockDrive = ds.BlockDrive
}
// It should implement GetAttachCount() and DeviceID() as api.Device implementation
// here it shares function from *GenericDevice so we don't need duplicate codes