Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(rest): improve inspect api #73

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/vfkit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func runVFKit(vmConfig *config.VirtualMachine, opts *cmdline.Options) error {

// Do not enable the rests server if user sets scheme to None
if opts.RestfulURI != cmdline.DefaultRestfulURI {
restVM := restvf.NewVzVirtualMachine(vm, vzVMConfig)
restVM := restvf.NewVzVirtualMachine(vm, vzVMConfig, vmConfig)
srv, err := rest.NewServer(restVM, restVM, opts.RestfulURI)
if err != nil {
return err
Expand Down
10 changes: 5 additions & 5 deletions pkg/config/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ var jsonTests = map[string]jsonTest{
require.NoError(t, err)
return vm
},
expectedJSON: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"virtioblk","DevName":"virtio-blk","ImagePath":"/virtioblk1","ReadOnly":false,"DeviceIdentifier":""},{"kind":"virtioblk","DevName":"virtio-blk","ImagePath":"/virtioblk2","ReadOnly":false,"DeviceIdentifier":"virtio-blk2"}]}`,
expectedJSON: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"virtioblk","devName":"virtio-blk","imagePath":"/virtioblk1","readOnly":false,"deviceIdentifier":""},{"kind":"virtioblk","devName":"virtio-blk","imagePath":"/virtioblk2","readOnly":false,"deviceIdentifier":"virtio-blk2"}]}`,
},
"TestAllVirtioDevices": {
newVM: func(t *testing.T) *VirtualMachine {
Expand Down Expand Up @@ -110,7 +110,7 @@ var jsonTests = map[string]jsonTest{

return vm
},
expectedJSON: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"virtioserial","LogFile":"/virtioserial","UsesStdio":false},{"kind":"virtioinput","inputType":"keyboard"},{"kind":"virtiogpu","usesGUI":false,"width":800,"height":600},{"kind":"virtionet","Nat":true,"MacAddress":"ABEiM0RV","Socket":null,"UnixSocketPath":""},{"kind":"virtiorng"},{"kind":"virtioblk","DevName":"virtio-blk","ImagePath":"/virtioblk","ReadOnly":false,"DeviceIdentifier":""},{"kind":"virtiosock","Port":1234,"SocketURL":"/virtiovsock","Listen":false},{"kind":"virtiofs","MountTag":"tag","SharedDir":"/virtiofs"},{"kind":"usbmassstorage","DevName":"usb-mass-storage","ImagePath":"/usbmassstorage","ReadOnly":false},{"kind":"rosetta","MountTag":"vz-rosetta","InstallRosetta":false}]}`,
expectedJSON: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"virtioserial","logFile":"/virtioserial","usesStdio":false},{"kind":"virtioinput","inputType":"keyboard"},{"kind":"virtiogpu","usesGUI":false,"width":800,"height":600},{"kind":"virtionet","nat":true,"macAddress":"ABEiM0RV","socket":null,"unixSocketPath":""},{"kind":"virtiorng"},{"kind":"virtioblk","devName":"virtio-blk","imagePath":"/virtioblk","readOnly":false,"deviceIdentifier":""},{"kind":"virtiosock","port":1234,"socketURL":"/virtiovsock","listen":false},{"kind":"virtiofs","mountTag":"tag","sharedDir":"/virtiofs"},{"kind":"usbmassstorage","devName":"usb-mass-storage","imagePath":"/usbmassstorage","readOnly":false},{"kind":"rosetta","mountTag":"vz-rosetta","installRosetta":false}]}`,
},
}

Expand All @@ -129,13 +129,13 @@ var invalidJSONTests = map[string]invalidJSONTest{
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"}}`,
},
"TestEmptyDeviceKind": {
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"","DevName":"virtio-blk","ImagePath":"/virtioblk1","ReadOnly":false,"DeviceIdentifier":""}]}`,
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"","devName":"virtio-blk","imagePath":"/virtioblk1","readOnly":false,"deviceIdentifier":""}]}`,
},
"TestInvalidDeviceKind": {
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"invalid","DevName":"virtio-blk","ImagePath":"/virtioblk1","ReadOnly":false,"DeviceIdentifier":""}]}`,
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"kind":"invalid","devName":"virtio-blk","imagePath":"/virtioblk1","readOnly":false,"deviceIdentifier":""}]}`,
},
"TestMissingDeviceKind": {
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"DevName":"virtio-blk","ImagePath":"/virtioblk1","ReadOnly":false,"DeviceIdentifier":""}]}`,
json: `{"vcpus":3,"memoryBytes":4000000000,"bootloader":{"kind":"linuxBootloader","VmlinuzPath":"/vmlinuz","KernelCmdLine":"/initrd","InitrdPath":"console=hvc0"},"devices":[{"devName":"virtio-blk","imagePath":"/virtioblk1","readOnly":false,"deviceIdentifier":""}]}`,
},
}

Expand Down
32 changes: 16 additions & 16 deletions pkg/config/virtio.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,34 @@ type VirtioGPU struct {
type VirtioVsock struct {
// Port is the virtio-vsock port used for this device, see `man vsock` for more
// details.
Port uint
Port uint `json:"port"`
// SocketURL is the path to a unix socket on the host to use for the virtio-vsock communication with the guest.
SocketURL string
SocketURL string `json:"socketURL"`
// If true, vsock connections will have to be done from guest to host. If false, vsock connections will only be possible
// from host to guest
Listen bool
Listen bool `json:"listen"`
}

// VirtioBlk configures a disk device.
type VirtioBlk struct {
StorageConfig
DeviceIdentifier string
DeviceIdentifier string `json:"deviceIdentifier"`
}

type DirectorySharingConfig struct {
MountTag string
MountTag string `json:"mountTag"`
}

// VirtioFs configures directory sharing between the guest and the host.
type VirtioFs struct {
DirectorySharingConfig
SharedDir string
SharedDir string `json:"sharedDir"`
}

// RosettaShare configures rosetta support in the guest to run Intel binaries on Apple CPUs
type RosettaShare struct {
DirectorySharingConfig
InstallRosetta bool
InstallRosetta bool `json:"installRosetta"`
}

// NVMExpressController configures a NVMe controller in the guest
Expand All @@ -91,19 +91,19 @@ type VirtioRng struct {

// VirtioNet configures the virtual machine networking.
type VirtioNet struct {
Nat bool
MacAddress net.HardwareAddr
Nat bool `json:"nat"`
MacAddress net.HardwareAddr `json:"macAddress"`
// file parameter is holding a connected datagram socket.
// see https://github.com/Code-Hex/vz/blob/7f648b6fb9205d6f11792263d79876e3042c33ec/network.go#L113-L155
Socket *os.File
Socket *os.File `json:"socket"`

UnixSocketPath string
UnixSocketPath string `json:"unixSocketPath"`
}

// VirtioSerial configures the virtual machine serial ports.
type VirtioSerial struct {
LogFile string
UsesStdio bool
LogFile string `json:"logFile"`
UsesStdio bool `json:"usesStdio"`
}

// TODO: Add VirtioBalloon
Expand Down Expand Up @@ -676,9 +676,9 @@ func USBMassStorageNew(imagePath string) (VMComponent, error) {

// StorageConfig configures a disk device.
type StorageConfig struct {
DevName string
ImagePath string
ReadOnly bool
DevName string `json:"devName"`
ImagePath string `json:"imagePath"`
ReadOnly bool `json:"readOnly"`
}

func (config *StorageConfig) ToCmdLine() ([]string, error) {
Expand Down
31 changes: 28 additions & 3 deletions pkg/rest/define/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
package define

import (
"github.com/crc-org/vfkit/pkg/config"
)

type VirtioNetResponse struct {
Nat bool `json:"nat"`
MacAddress string `json:"macAddress"`
UnixSocketPath string `json:"unixSocketPath"`
Fd int `json:"fd"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw, I'm not sure fd is going to be useful to expose to an external process?

}

type DevicesResponse struct {
Input []config.VirtioInput `json:"input"`
GPU []config.VirtioGPU `json:"gpu"`
Vsock []config.VirtioVsock `json:"vsock"`
Blk []config.VirtioBlk `json:"blk"`
FS []config.VirtioFs `json:"fs"`
Rosetta config.RosettaShare `json:"rosetta"`
NVMe []config.NVMExpressController `json:"nvme"`
Net []VirtioNetResponse `json:"net"`
Rng bool `json:"rng"`
Serial config.VirtioSerial `json:"serial"`
USBMassStorage []config.USBMassStorage `json:"usbMassStorage"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we reuse the same format as the preexisting json serialization code?

"devices":[{"devName":"virtio-blk","imagePath":"/virtioblk1","readOnly":false,"deviceIdentifier":""}]}

serialization/deserialization to this format should already be working, a new type should not be needed.
Or do you have strong reasons for having such a struct?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#99 reuses the existing json format

}

// InspectResponse is used when responding to a request for
// information about the virtual machine
type InspectResponse struct {
CPUs uint `json:"cpus"`
Memory uint64 `json:"memory"`
// Devices []config.VirtioDevice `json:"devices"`
CPUs uint `json:"cpus"`
Memory uint64 `json:"memory"`
Devices DevicesResponse `json:"devices"`
}

// VMState can be used to describe the current state of a VM
Expand Down
66 changes: 58 additions & 8 deletions pkg/rest/vf/vm_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,80 @@ package rest

import (
"net/http"
"sync"

"github.com/Code-Hex/vz/v3"
"github.com/crc-org/vfkit/pkg/config"
"github.com/crc-org/vfkit/pkg/rest/define"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
)

type VzVirtualMachine struct {
VzVM *vz.VirtualMachine
config *vz.VirtualMachineConfiguration
VzVM *vz.VirtualMachine
config *vz.VirtualMachineConfiguration
vmConfig *config.VirtualMachine
}

func NewVzVirtualMachine(vm *vz.VirtualMachine, config *vz.VirtualMachineConfiguration) *VzVirtualMachine {
return &VzVirtualMachine{config: config, VzVM: vm}
func NewVzVirtualMachine(vm *vz.VirtualMachine, config *vz.VirtualMachineConfiguration, vmConfig *config.VirtualMachine) *VzVirtualMachine {
return &VzVirtualMachine{config: config, VzVM: vm, vmConfig: vmConfig}
}

var (
once sync.Once
devicesResponse define.DevicesResponse
)

func devicesToResp(devices []config.VirtioDevice) define.DevicesResponse {
once.Do(func() {
for _, dev := range devices {
switch d := dev.(type) {
case *config.USBMassStorage:
devicesResponse.USBMassStorage = append(devicesResponse.USBMassStorage, *d)
case *config.VirtioBlk:
devicesResponse.Blk = append(devicesResponse.Blk, *d)
case *config.RosettaShare:
devicesResponse.Rosetta = *d
case *config.NVMExpressController:
devicesResponse.NVMe = append(devicesResponse.NVMe, *d)
case *config.VirtioFs:
devicesResponse.FS = append(devicesResponse.FS, *d)
case *config.VirtioNet:
n := define.VirtioNetResponse{
Nat: d.Nat,
MacAddress: d.MacAddress.String(),
UnixSocketPath: d.UnixSocketPath,
}

if d.Socket != nil {
n.Fd = int(d.Socket.Fd())
}

devicesResponse.Net = append(devicesResponse.Net, n)
case *config.VirtioRng:
devicesResponse.Rng = true
case *config.VirtioSerial:
devicesResponse.Serial = *d
case *config.VirtioVsock:
devicesResponse.Vsock = append(devicesResponse.Vsock, *d)
case *config.VirtioInput:
devicesResponse.Input = append(devicesResponse.Input, *d)
case *config.VirtioGPU:
devicesResponse.GPU = append(devicesResponse.GPU, *d)
}
}
})

return devicesResponse
}

// Inspect returns information about the virtual machine like hw resources
// and devices
func (vm *VzVirtualMachine) Inspect(c *gin.Context) {
ii := define.InspectResponse{
// TODO complete me
CPUs: 1,
Memory: 2048,
//Devices: vm.Devices,
CPUs: vm.vmConfig.Vcpus,
Memory: vm.vmConfig.MemoryBytes,
Devices: devicesToResp(vm.vmConfig.Devices),
}
c.JSON(http.StatusOK, ii)
}
Expand Down
Loading