qemu driver: Add option to configure drive_interface (#11864)

This commit is contained in:
Daniel Rossbach 2022-06-10 16:03:51 +02:00 committed by GitHub
parent 0443a3b8c1
commit 8c52c03c8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 4 deletions

3
.changelog/11864.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
qemu: Added option to configure `drive_interface`
```

View File

@ -95,6 +95,7 @@ var (
// a taskConfig within a job. It is returned in the TaskConfigSchema RPC // a taskConfig within a job. It is returned in the TaskConfigSchema RPC
taskConfigSpec = hclspec.NewObject(map[string]*hclspec.Spec{ taskConfigSpec = hclspec.NewObject(map[string]*hclspec.Spec{
"image_path": hclspec.NewAttr("image_path", "string", true), "image_path": hclspec.NewAttr("image_path", "string", true),
"drive_interface": hclspec.NewAttr("drive_interface", "string", false),
"accelerator": hclspec.NewAttr("accelerator", "string", false), "accelerator": hclspec.NewAttr("accelerator", "string", false),
"graceful_shutdown": hclspec.NewAttr("graceful_shutdown", "bool", false), "graceful_shutdown": hclspec.NewAttr("graceful_shutdown", "bool", false),
"guest_agent": hclspec.NewAttr("guest_agent", "bool", false), "guest_agent": hclspec.NewAttr("guest_agent", "bool", false),
@ -125,6 +126,7 @@ type TaskConfig struct {
Args []string `codec:"args"` // extra arguments to qemu executable Args []string `codec:"args"` // extra arguments to qemu executable
PortMap hclutils.MapStrInt `codec:"port_map"` // A map of host port and the port name defined in the image manifest file PortMap hclutils.MapStrInt `codec:"port_map"` // A map of host port and the port name defined in the image manifest file
GracefulShutdown bool `codec:"graceful_shutdown"` GracefulShutdown bool `codec:"graceful_shutdown"`
DriveInterface string `codec:"drive_interface"` // Use interface for image
GuestAgent bool `codec:"guest_agent"` GuestAgent bool `codec:"guest_agent"`
} }
@ -344,6 +346,19 @@ func isAllowedImagePath(allowedPaths []string, allocDir, imagePath string) bool
return false return false
} }
// hardcoded list of drive interfaces, Qemu currently supports
var allowedDriveInterfaces = []string{"ide", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"}
func isAllowedDriveInterface(driveInterface string) bool {
for _, ai := range allowedDriveInterfaces {
if driveInterface == ai {
return true
}
}
return false
}
// validateArgs ensures that all QEMU command line params are in the // validateArgs ensures that all QEMU command line params are in the
// allowlist. This function must be called after all interpolation has // allowlist. This function must be called after all interpolation has
// taken place. // taken place.
@ -414,12 +429,20 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
return nil, nil, err return nil, nil, err
} }
driveInterface := "ide"
if driverConfig.DriveInterface != "" {
driveInterface = driverConfig.DriveInterface
}
if !isAllowedDriveInterface(driveInterface) {
return nil, nil, fmt.Errorf("Unsupported drive_interface")
}
args := []string{ args := []string{
absPath, absPath,
"-machine", "type=pc,accel=" + accelerator, "-machine", "type=pc,accel=" + accelerator,
"-name", vmID, "-name", vmID,
"-m", mem, "-m", mem,
"-drive", "file=" + vmPath, "-drive", "file=" + vmPath + ",if=" + driveInterface,
"-nographic", "-nographic",
} }

View File

@ -390,6 +390,7 @@ func TestConfig_ParseAllHCL(t *testing.T) {
cfgStr := ` cfgStr := `
config { config {
image_path = "/tmp/image_path" image_path = "/tmp/image_path"
drive_interface = "virtio"
accelerator = "kvm" accelerator = "kvm"
args = ["arg1", "arg2"] args = ["arg1", "arg2"]
port_map { port_map {
@ -400,9 +401,10 @@ config {
}` }`
expected := &TaskConfig{ expected := &TaskConfig{
ImagePath: "/tmp/image_path", ImagePath: "/tmp/image_path",
Accelerator: "kvm", DriveInterface: "virtio",
Args: []string{"arg1", "arg2"}, Accelerator: "kvm",
Args: []string{"arg1", "arg2"},
PortMap: map[string]int{ PortMap: map[string]int{
"http": 80, "http": 80,
"https": 443, "https": 443,
@ -416,6 +418,19 @@ config {
require.EqualValues(t, expected, tc) require.EqualValues(t, expected, tc)
} }
func TestIsAllowedDriveInterface(t *testing.T) {
validInterfaces := []string{"ide", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"}
invalidInterfaces := []string{"foo", "virtio-foo"}
for _, i := range validInterfaces {
require.Truef(t, isAllowedDriveInterface(i), "drive_interface should be allowed: %v", i)
}
for _, i := range invalidInterfaces {
require.Falsef(t, isAllowedDriveInterface(i), "drive_interface should be not allowed: %v", i)
}
}
func TestIsAllowedImagePath(t *testing.T) { func TestIsAllowedImagePath(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)

View File

@ -42,6 +42,10 @@ The `qemu` driver supports the following configuration in the job spec:
contains the image in a subfolder, the path will need to be the relative path contains the image in a subfolder, the path will need to be the relative path
(`subdir/from_archive/my.img`). (`subdir/from_archive/my.img`).
- `drive_interface` - (Optional) This option defines on which type of interface
the drive is connected. Available types are: `ide`, `scsi`, `sd`, `mtd`,
`floppy`, `pflash`, `virtio` and `none`. Default is `ide`.
- `accelerator` - (Optional) The type of accelerator to use in the invocation. - `accelerator` - (Optional) The type of accelerator to use in the invocation.
If the host machine has `qemu` installed with KVM support, users can specify If the host machine has `qemu` installed with KVM support, users can specify
`kvm` for the `accelerator`. Default is `tcg`. `kvm` for the `accelerator`. Default is `tcg`.