clh: Enable disk block device hotplug support

[ port from runtime commit c5f97b24d7a1eaac216f144b2c5429feb3451553 ]

With this patch, the container image can be shared from host with guest
as a block device when the 'devicemapper' is used as the storage driver
for docker. Note: The 'block_device_driver="virtio-blk"' entry is
required in the hypervisor config file to work properly.

Signed-off-by: Bo Chen <chen.bo@intel.com>
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
Bo Chen 2020-06-29 19:58:00 -07:00 committed by Peng Tao
parent c20179ee0e
commit 8b5eed70f7
2 changed files with 60 additions and 0 deletions

View File

@ -88,6 +88,8 @@ type clhClient interface {
VmResizePut(ctx context.Context, vmResize chclient.VmResize) (*http.Response, error)
// Add VFIO PCI device to the VM
VmAddDevicePut(ctx context.Context, vmAddDevice chclient.VmAddDevice) (*http.Response, error)
// Add a new disk device to the VM
VmAddDiskPut(ctx context.Context, diskConfig chclient.DiskConfig) (*http.Response, error)
}
type CloudHypervisorVersion struct {
@ -410,6 +412,33 @@ func (clh *cloudHypervisor) getThreadIDs() (vcpuThreadIDs, error) {
return vcpuInfo, nil
}
func (clh *cloudHypervisor) hotplugBlockDevice(drive *config.BlockDrive) error {
cl := clh.client()
ctx, cancel := context.WithTimeout(context.Background(), clhHotPlugAPITimeout*time.Second)
defer cancel()
_, _, err := cl.VmmPingGet(ctx)
if err != nil {
return openAPIClientError(err)
}
if drive.Pmem {
err = fmt.Errorf("pmem device hotplug not supported")
} else {
blkDevice := chclient.DiskConfig{
Path: drive.File,
Readonly: drive.ReadOnly,
VhostUser: false,
}
_, err = cl.VmAddDiskPut(ctx, blkDevice)
}
if err != nil {
err = fmt.Errorf("failed to hotplug block device %+v %s", drive, openAPIClientError(err))
}
return err
}
func (clh *cloudHypervisor) hotPlugVFIODevice(device config.VFIODev) error {
cl := clh.client()
ctx, cancel := context.WithTimeout(context.Background(), clhHotPlugAPITimeout*time.Second)
@ -432,6 +461,9 @@ func (clh *cloudHypervisor) hotplugAddDevice(devInfo interface{}, devType device
defer span.Finish()
switch devType {
case blockDev:
drive := devInfo.(*config.BlockDrive)
return nil, clh.hotplugBlockDevice(drive)
case vfioDev:
device := devInfo.(*config.VFIODev)
return nil, clh.hotPlugVFIODevice(*device)
@ -663,6 +695,7 @@ func (clh *cloudHypervisor) capabilities() types.Capabilities {
clh.Logger().WithField("function", "capabilities").Info("get Capabilities")
var caps types.Capabilities
caps.SetFsSharingSupport()
caps.SetBlockDeviceHotplugSupport()
return caps
}

View File

@ -99,6 +99,11 @@ func (c *clhClientMock) VmAddDevicePut(ctx context.Context, vmAddDevice chclient
return nil, nil
}
//nolint:golint
func (c *clhClientMock) VmAddDiskPut(ctx context.Context, diskConfig chclient.DiskConfig) (*http.Response, error) {
return nil, nil
}
func TestCloudHypervisorAddVSock(t *testing.T) {
assert := assert.New(t)
clh := cloudHypervisor{}
@ -357,3 +362,25 @@ func TestCheckVersion(t *testing.T) {
}
}
}
func TestCloudHypervisorHotplugBlockDevice(t *testing.T) {
assert := assert.New(t)
clhConfig, err := newClhConfig()
assert.NoError(err)
clh := &cloudHypervisor{}
clh.config = clhConfig
clh.APIClient = &clhClientMock{}
clh.config.BlockDeviceDriver = config.VirtioBlock
err = clh.hotplugBlockDevice(&config.BlockDrive{Pmem: false})
assert.NoError(err, "Hotplug disk block device expected no error")
err = clh.hotplugBlockDevice(&config.BlockDrive{Pmem: true})
assert.Error(err, "Hotplug pmem block device expected error")
clh.config.BlockDeviceDriver = config.VirtioSCSI
err = clh.hotplugBlockDevice(&config.BlockDrive{Pmem: false})
assert.Error(err, "Hotplug block device not using 'virtio-blk' expected error")
}