diff --git a/qemu/qemu.go b/qemu/qemu.go index d2f27f51dc..c883de53a3 100644 --- a/qemu/qemu.go +++ b/qemu/qemu.go @@ -85,6 +85,9 @@ const ( // VHostVSockPCI is the vhost vsock pci driver. VHostVSockPCI DeviceDriver = "vhost-vsock-pci" + + // VirtioRng is the paravirtualized RNG device driver. + VirtioRng DeviceDriver = "virtio-rng" ) // ObjectType is a string representing a qemu object type. @@ -1017,6 +1020,63 @@ func (vsock VSOCKDevice) QemuParams(config *Config) []string { return qemuParams } +// RngDevice represents a random number generator device. +type RngDevice struct { + // ID is the device ID + ID string + // Filename is entropy source on the host + Filename string + // MaxBytes is the bytes allowed to guest to get from the host’s entropy per period + MaxBytes uint + // Period is duration of a read period in seconds + Period uint +} + +// Valid returns true if the RngDevice structure is valid and complete. +func (v RngDevice) Valid() bool { + if v.ID == "" { + return false + } + + return true +} + +// QemuParams returns the qemu parameters built out of the RngDevice. +func (v RngDevice) QemuParams(_ *Config) []string { + var qemuParams []string + + //-object rng-random,filename=/dev/hwrng,id=rng0 + var objectParams []string + //-device virtio-rng-pci,rng=rng0,max-bytes=1024,period=1000 + var deviceParams []string + + objectParams = append(objectParams, "rng-random") + objectParams = append(objectParams, "id="+v.ID) + + deviceParams = append(deviceParams, string(VirtioRng)) + deviceParams = append(deviceParams, "rng="+v.ID) + + if v.Filename != "" { + objectParams = append(objectParams, "filename="+v.Filename) + } + + if v.MaxBytes > 0 { + deviceParams = append(deviceParams, fmt.Sprintf("max-bytes=%d", v.MaxBytes)) + } + + if v.Period > 0 { + deviceParams = append(deviceParams, fmt.Sprintf("period=%d", v.Period)) + } + + qemuParams = append(qemuParams, "-object") + qemuParams = append(qemuParams, strings.Join(objectParams, ",")) + + qemuParams = append(qemuParams, "-device") + qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) + + return qemuParams +} + // RTCBaseType is the qemu RTC base time type. type RTCBaseType string diff --git a/qemu/qemu_test.go b/qemu/qemu_test.go index 7fdaa9bffb..f8bdf34eb0 100644 --- a/qemu/qemu_test.go +++ b/qemu/qemu_test.go @@ -17,6 +17,7 @@ package qemu import ( + "fmt" "io/ioutil" "os" "strings" @@ -361,6 +362,48 @@ func TestVSOCKValid(t *testing.T) { } } +func TestAppendVirtioRng(t *testing.T) { + var objectString = "-object rng-random,id=rng0" + var deviceString = "-device " + string(VirtioRng) + ",rng=rng0" + rngDevice := RngDevice{ + ID: "rng0", + } + + testAppend(rngDevice, objectString+" "+deviceString, t) + + rngDevice.Filename = "/dev/urandom" + objectString += ",filename=" + rngDevice.Filename + + testAppend(rngDevice, objectString+" "+deviceString, t) + + rngDevice.MaxBytes = 20 + + deviceString += fmt.Sprintf(",max-bytes=%d", rngDevice.MaxBytes) + testAppend(rngDevice, objectString+" "+deviceString, t) + + rngDevice.Period = 500 + + deviceString += fmt.Sprintf(",period=%d", rngDevice.Period) + testAppend(rngDevice, objectString+" "+deviceString, t) + +} + +func TestVirtioRngValid(t *testing.T) { + rng := RngDevice{ + ID: "", + } + + if rng.Valid() { + t.Fatalf("rng should be not valid when ID is empty") + } + + rng.ID = "rng0" + if !rng.Valid() { + t.Fatalf("rng should be valid") + } + +} + var deviceSCSIControllerStr = "-device virtio-scsi-pci,id=foo" var deviceSCSIControllerBusAddrStr = "-device virtio-scsi-pci,id=foo,bus=pci.0,addr=00:04.0,disable-modern=true,iothread=iothread1"