From ec6655af87158c4bea38302246b806e5ff7a7533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Wed, 19 Jan 2022 09:48:56 +0100 Subject: [PATCH 1/5] govmm: Use govmm from our own pkg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's stop using govmm from kata-containers/govmm and let's start using it from our own repo. Fixes: #3495 Signed-off-by: Fabiano Fidêncio --- src/runtime/go.mod | 1 - src/runtime/go.sum | 2 - src/runtime/pkg/govmm/qemu/examples_test.go | 2 +- src/runtime/pkg/katautils/config.go | 2 +- .../github.com/kata-containers/govmm/COPYING | 202 -- .../kata-containers/govmm/qemu/image.go | 77 - .../kata-containers/govmm/qemu/qemu.go | 3039 ----------------- .../kata-containers/govmm/qemu/qmp.go | 1664 --------- src/runtime/vendor/modules.txt | 3 - src/runtime/virtcontainers/qemu.go | 2 +- src/runtime/virtcontainers/qemu_amd64.go | 2 +- src/runtime/virtcontainers/qemu_amd64_test.go | 2 +- src/runtime/virtcontainers/qemu_arch_base.go | 2 +- .../virtcontainers/qemu_arch_base_test.go | 2 +- src/runtime/virtcontainers/qemu_arm64.go | 2 +- src/runtime/virtcontainers/qemu_arm64_test.go | 2 +- src/runtime/virtcontainers/qemu_ppc64le.go | 2 +- .../virtcontainers/qemu_ppc64le_test.go | 2 +- src/runtime/virtcontainers/qemu_s390x.go | 2 +- src/runtime/virtcontainers/qemu_s390x_test.go | 2 +- src/runtime/virtcontainers/qemu_test.go | 2 +- 21 files changed, 14 insertions(+), 5002 deletions(-) delete mode 100644 src/runtime/vendor/github.com/kata-containers/govmm/COPYING delete mode 100644 src/runtime/vendor/github.com/kata-containers/govmm/qemu/image.go delete mode 100644 src/runtime/vendor/github.com/kata-containers/govmm/qemu/qemu.go delete mode 100644 src/runtime/vendor/github.com/kata-containers/govmm/qemu/qmp.go diff --git a/src/runtime/go.mod b/src/runtime/go.mod index 020700c37..ab3fdcbc1 100644 --- a/src/runtime/go.mod +++ b/src/runtime/go.mod @@ -28,7 +28,6 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/hashicorp/go-multierror v1.0.0 github.com/intel-go/cpuid v0.0.0-20210602155658-5747e5cec0d9 - github.com/kata-containers/govmm v0.0.0-20220117131932-0781a21804ee github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f github.com/opencontainers/runc v1.0.3 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 diff --git a/src/runtime/go.sum b/src/runtime/go.sum index 88f3e0a8a..da4fcc3fe 100644 --- a/src/runtime/go.sum +++ b/src/runtime/go.sum @@ -576,8 +576,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kata-containers/govmm v0.0.0-20220117131932-0781a21804ee h1:XofauxL6B1JEeDS+Ta/M1tM9Kutj/n72JSAvx10ubFA= -github.com/kata-containers/govmm v0.0.0-20220117131932-0781a21804ee/go.mod h1:A6QaNB6N6PRQ9mTRpFtUxiF5T5CJpzLALjxBrUQPlFI= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= diff --git a/src/runtime/pkg/govmm/qemu/examples_test.go b/src/runtime/pkg/govmm/qemu/examples_test.go index 1946aeef8..22cc0eff3 100644 --- a/src/runtime/pkg/govmm/qemu/examples_test.go +++ b/src/runtime/pkg/govmm/qemu/examples_test.go @@ -21,7 +21,7 @@ import ( "context" - "github.com/kata-containers/govmm/qemu" + "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" ) func Example() { diff --git a/src/runtime/pkg/katautils/config.go b/src/runtime/pkg/katautils/config.go index 7035860b3..20ed1b695 100644 --- a/src/runtime/pkg/katautils/config.go +++ b/src/runtime/pkg/katautils/config.go @@ -15,7 +15,7 @@ import ( "strings" "github.com/BurntSushi/toml" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/pkg/katautils/katatrace" "github.com/kata-containers/kata-containers/src/runtime/pkg/oci" vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers" diff --git a/src/runtime/vendor/github.com/kata-containers/govmm/COPYING b/src/runtime/vendor/github.com/kata-containers/govmm/COPYING deleted file mode 100644 index d64569567..000000000 --- a/src/runtime/vendor/github.com/kata-containers/govmm/COPYING +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/runtime/vendor/github.com/kata-containers/govmm/qemu/image.go b/src/runtime/vendor/github.com/kata-containers/govmm/qemu/image.go deleted file mode 100644 index ddee0670e..000000000 --- a/src/runtime/vendor/github.com/kata-containers/govmm/qemu/image.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -// Copyright contributors to the Virtual Machine Manager for Go project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ - -package qemu - -import ( - "context" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path" - "syscall" -) - -// CreateCloudInitISO creates a cloud-init ConfigDrive ISO image. This is -// useful for configuring newly booted VMs. Before it can create the ISO -// image it needs to create a file tree with the various files that will -// make up the image. This directory is created under scratchDir and is -// deleted when when the function returns, successfully or otherwise. ctx is -// a context that can be used to timeout or cancel the image creation. -// isoPath contains the desired path of the ISO image to be created. The -// userdata and metadata parameters are byte slices that contain the -// ConfigDrive userdata and metadata that will be stored with the ISO image. -// The attrs parameter can be used to control aspects of the newly created -// qemu process, such as the user and group under which it runs. It may be nil. -func CreateCloudInitISO(ctx context.Context, scratchDir, isoPath string, - userData, metaData []byte, attr *syscall.SysProcAttr) error { - configDrivePath := path.Join(scratchDir, "clr-cloud-init") - dataDirPath := path.Join(configDrivePath, "openstack", "latest") - metaDataPath := path.Join(dataDirPath, "meta_data.json") - userDataPath := path.Join(dataDirPath, "user_data") - - defer func() { - /* #nosec */ - _ = os.RemoveAll(configDrivePath) - }() - - err := os.MkdirAll(dataDirPath, 0750) - if err != nil { - return fmt.Errorf("unable to create config drive directory %s : %v", - dataDirPath, err) - } - - err = ioutil.WriteFile(metaDataPath, metaData, 0644) - if err != nil { - return fmt.Errorf("unable to create %s : %v", metaDataPath, err) - } - - err = ioutil.WriteFile(userDataPath, userData, 0644) - if err != nil { - return fmt.Errorf("unable to create %s : %v", userDataPath, err) - } - - cmd := exec.CommandContext(ctx, "xorriso", "-as", "mkisofs", "-R", "-V", "config-2", - "-o", isoPath, configDrivePath) - cmd.SysProcAttr = attr - err = cmd.Run() - if err != nil { - return fmt.Errorf("unable to create cloudinit iso image %v", err) - } - - return nil -} diff --git a/src/runtime/vendor/github.com/kata-containers/govmm/qemu/qemu.go b/src/runtime/vendor/github.com/kata-containers/govmm/qemu/qemu.go deleted file mode 100644 index c43ff5795..000000000 --- a/src/runtime/vendor/github.com/kata-containers/govmm/qemu/qemu.go +++ /dev/null @@ -1,3039 +0,0 @@ -/* -// Copyright contributors to the Virtual Machine Manager for Go project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ - -// Package qemu provides methods and types for launching and managing QEMU -// instances. Instances can be launched with the LaunchQemu function and -// managed thereafter via QMPStart and the QMP object that this function -// returns. To manage a qemu instance after it has been launched you need -// to pass the -qmp option during launch requesting the qemu instance to create -// a QMP unix domain manageent socket, e.g., -// -qmp unix:/tmp/qmp-socket,server,nowait. For more information see the -// example below. -package qemu - -import ( - "bytes" - "fmt" - "log" - "os" - "os/exec" - "runtime" - "strconv" - "strings" - "syscall" - - "context" -) - -// Machine describes the machine type qemu will emulate. -type Machine struct { - // Type is the machine type to be used by qemu. - Type string - - // Acceleration are the machine acceleration options to be used by qemu. - Acceleration string - - // Options are options for the machine type - // For example gic-version=host and usb=off - Options string -} - -const ( - // MachineTypeMicrovm is the QEMU microvm machine type for amd64 - MachineTypeMicrovm string = "microvm" -) - -// Device is the qemu device interface. -type Device interface { - Valid() bool - QemuParams(config *Config) []string -} - -// DeviceDriver is the device driver string. -type DeviceDriver string - -const ( - // LegacySerial is the legacy serial device driver - LegacySerial DeviceDriver = "serial" - - // NVDIMM is the Non Volatile DIMM device driver. - NVDIMM DeviceDriver = "nvdimm" - - // VirtioNet is the virtio networking device driver. - VirtioNet DeviceDriver = "virtio-net" - - // VirtioNetPCI is the virt-io pci networking device driver. - VirtioNetPCI DeviceDriver = "virtio-net-pci" - - // VirtioNetCCW is the virt-io ccw networking device driver. - VirtioNetCCW DeviceDriver = "virtio-net-ccw" - - // VirtioBlock is the block device driver. - VirtioBlock DeviceDriver = "virtio-blk" - - // Console is the console device driver. - Console DeviceDriver = "virtconsole" - - // Virtio9P is the 9pfs device driver. - Virtio9P DeviceDriver = "virtio-9p" - - // VirtioSerial is the serial device driver. - VirtioSerial DeviceDriver = "virtio-serial" - - // VirtioSerialPort is the serial port device driver. - VirtioSerialPort DeviceDriver = "virtserialport" - - // VirtioRng is the paravirtualized RNG device driver. - VirtioRng DeviceDriver = "virtio-rng" - - // VirtioBalloon is the memory balloon device driver. - VirtioBalloon DeviceDriver = "virtio-balloon" - - //VhostUserSCSI represents a SCSI vhostuser device type. - VhostUserSCSI DeviceDriver = "vhost-user-scsi" - - //VhostUserNet represents a net vhostuser device type. - VhostUserNet DeviceDriver = "virtio-net" - - //VhostUserBlk represents a block vhostuser device type. - VhostUserBlk DeviceDriver = "vhost-user-blk" - - //VhostUserFS represents a virtio-fs vhostuser device type - VhostUserFS DeviceDriver = "vhost-user-fs" - - // PCIBridgeDriver represents a PCI bridge device type. - PCIBridgeDriver DeviceDriver = "pci-bridge" - - // PCIePCIBridgeDriver represents a PCIe to PCI bridge device type. - PCIePCIBridgeDriver DeviceDriver = "pcie-pci-bridge" - - // VfioPCI is the vfio driver with PCI transport. - VfioPCI DeviceDriver = "vfio-pci" - - // VfioCCW is the vfio driver with CCW transport. - VfioCCW DeviceDriver = "vfio-ccw" - - // VfioAP is the vfio driver with AP transport. - VfioAP DeviceDriver = "vfio-ap" - - // VHostVSockPCI is a generic Vsock vhost device with PCI transport. - VHostVSockPCI DeviceDriver = "vhost-vsock-pci" - - // PCIeRootPort is a PCIe Root Port, the PCIe device should be hotplugged to this port. - PCIeRootPort DeviceDriver = "pcie-root-port" - - // Loader is the Loader device driver. - Loader DeviceDriver = "loader" - - // SpaprTPMProxy is used for enabling guest to run in secure mode on ppc64le. - SpaprTPMProxy DeviceDriver = "spapr-tpm-proxy" -) - -func isDimmSupported(config *Config) bool { - switch runtime.GOARCH { - case "amd64", "386", "ppc64le", "arm64": - if config != nil && config.Machine.Type == MachineTypeMicrovm { - // microvm does not support NUMA - return false - } - return true - default: - return false - } -} - -// VirtioTransport is the transport in use for a virtio device. -type VirtioTransport string - -const ( - // TransportPCI is the PCI transport for virtio device. - TransportPCI VirtioTransport = "pci" - - // TransportCCW is the CCW transport for virtio devices. - TransportCCW VirtioTransport = "ccw" - - // TransportMMIO is the MMIO transport for virtio devices. - TransportMMIO VirtioTransport = "mmio" -) - -// defaultTransport returns the default transport for the current combination -// of host's architecture and QEMU machine type. -func (transport VirtioTransport) defaultTransport(config *Config) VirtioTransport { - switch runtime.GOARCH { - case "amd64", "386": - if config != nil && config.Machine.Type == MachineTypeMicrovm { - return TransportMMIO - } - return TransportPCI - case "s390x": - return TransportCCW - default: - return TransportPCI - } -} - -// isVirtioPCI returns true if the transport is PCI. -func (transport VirtioTransport) isVirtioPCI(config *Config) bool { - if transport == "" { - transport = transport.defaultTransport(config) - } - - return transport == TransportPCI -} - -// isVirtioCCW returns true if the transport is CCW. -func (transport VirtioTransport) isVirtioCCW(config *Config) bool { - if transport == "" { - transport = transport.defaultTransport(config) - } - - return transport == TransportCCW -} - -// getName returns the name of the current transport. -func (transport VirtioTransport) getName(config *Config) string { - if transport == "" { - transport = transport.defaultTransport(config) - } - - return string(transport) -} - -// disableModern returns the parameters with the disable-modern option. -// In case the device driver is not a PCI device and it doesn't have the option -// an empty string is returned. -func (transport VirtioTransport) disableModern(config *Config, disable bool) string { - if !transport.isVirtioPCI(config) { - return "" - } - - if disable { - return "disable-modern=true" - } - - return "disable-modern=false" -} - -// ObjectType is a string representing a qemu object type. -type ObjectType string - -const ( - // MemoryBackendFile represents a guest memory mapped file. - MemoryBackendFile ObjectType = "memory-backend-file" - - // MemoryBackendEPC represents a guest memory backend EPC for SGX. - MemoryBackendEPC ObjectType = "memory-backend-epc" - - // TDXGuest represents a TDX object - TDXGuest ObjectType = "tdx-guest" - - // SEVGuest represents an SEV guest object - SEVGuest ObjectType = "sev-guest" - - // SecExecGuest represents an s390x Secure Execution (Protected Virtualization in QEMU) object - SecExecGuest ObjectType = "s390-pv-guest" - // PEFGuest represent ppc64le PEF(Protected Execution Facility) object. - PEFGuest ObjectType = "pef-guest" -) - -// Object is a qemu object representation. -type Object struct { - // Driver is the qemu device driver - Driver DeviceDriver - - // Type is the qemu object type. - Type ObjectType - - // ID is the user defined object ID. - ID string - - // DeviceID is the user defined device ID. - DeviceID string - - // MemPath is the object's memory path. - // This is only relevant for memory objects - MemPath string - - // Size is the object size in bytes - Size uint64 - - // Debug this is a debug object - Debug bool - - // File is the device file - File string - - // CBitPos is the location of the C-bit in a guest page table entry - // This is only relevant for sev-guest objects - CBitPos uint32 - - // ReducedPhysBits is the reduction in the guest physical address space - // This is only relevant for sev-guest objects - ReducedPhysBits uint32 - - // ReadOnly specifies whether `MemPath` is opened read-only or read/write (default) - ReadOnly bool - - // Prealloc enables memory preallocation - Prealloc bool -} - -// Valid returns true if the Object structure is valid and complete. -func (object Object) Valid() bool { - switch object.Type { - case MemoryBackendFile: - return object.ID != "" && object.MemPath != "" && object.Size != 0 - case MemoryBackendEPC: - return object.ID != "" && object.Size != 0 - case TDXGuest: - return object.ID != "" && object.File != "" && object.DeviceID != "" - case SEVGuest: - return object.ID != "" && object.File != "" && object.CBitPos != 0 && object.ReducedPhysBits != 0 - case SecExecGuest: - return object.ID != "" - case PEFGuest: - return object.ID != "" && object.File != "" - - default: - return false - } -} - -// QemuParams returns the qemu parameters built out of this Object device. -func (object Object) QemuParams(config *Config) []string { - var objectParams []string - var deviceParams []string - var driveParams []string - var qemuParams []string - - switch object.Type { - case MemoryBackendFile: - objectParams = append(objectParams, string(object.Type)) - objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID)) - objectParams = append(objectParams, fmt.Sprintf("mem-path=%s", object.MemPath)) - objectParams = append(objectParams, fmt.Sprintf("size=%d", object.Size)) - - deviceParams = append(deviceParams, string(object.Driver)) - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", object.DeviceID)) - deviceParams = append(deviceParams, fmt.Sprintf("memdev=%s", object.ID)) - - if object.ReadOnly { - objectParams = append(objectParams, "readonly=on") - deviceParams = append(deviceParams, "unarmed=on") - } - case MemoryBackendEPC: - objectParams = append(objectParams, string(object.Type)) - objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID)) - objectParams = append(objectParams, fmt.Sprintf("size=%d", object.Size)) - if object.Prealloc { - objectParams = append(objectParams, "prealloc=on") - } - - case TDXGuest: - objectParams = append(objectParams, string(object.Type)) - objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID)) - if object.Debug { - objectParams = append(objectParams, "debug=on") - } - deviceParams = append(deviceParams, string(object.Driver)) - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", object.DeviceID)) - deviceParams = append(deviceParams, fmt.Sprintf("file=%s", object.File)) - case SEVGuest: - objectParams = append(objectParams, string(object.Type)) - objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID)) - objectParams = append(objectParams, fmt.Sprintf("cbitpos=%d", object.CBitPos)) - objectParams = append(objectParams, fmt.Sprintf("reduced-phys-bits=%d", object.ReducedPhysBits)) - - driveParams = append(driveParams, "if=pflash,format=raw,readonly=on") - driveParams = append(driveParams, fmt.Sprintf("file=%s", object.File)) - case SecExecGuest: - objectParams = append(objectParams, string(object.Type)) - objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID)) - case PEFGuest: - objectParams = append(objectParams, string(object.Type)) - objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID)) - - deviceParams = append(deviceParams, string(object.Driver)) - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", object.DeviceID)) - deviceParams = append(deviceParams, fmt.Sprintf("host-path=%s", object.File)) - - } - - if len(deviceParams) > 0 { - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - } - - if len(objectParams) > 0 { - qemuParams = append(qemuParams, "-object") - qemuParams = append(qemuParams, strings.Join(objectParams, ",")) - } - - if len(driveParams) > 0 { - qemuParams = append(qemuParams, "-drive") - qemuParams = append(qemuParams, strings.Join(driveParams, ",")) - } - - return qemuParams -} - -// Virtio9PMultidev filesystem behaviour to deal -// with multiple devices being shared with a 9p export. -type Virtio9PMultidev string - -const ( - // Remap shares multiple devices with only one export. - Remap Virtio9PMultidev = "remap" - - // Warn assumes that only one device is shared by the same export. - // Only a warning message is logged (once) by qemu on host side. - // This is the default behaviour. - Warn Virtio9PMultidev = "warn" - - // Forbid like "warn" but also deny access to additional devices on guest. - Forbid Virtio9PMultidev = "forbid" -) - -// FSDriver represents a qemu filesystem driver. -type FSDriver string - -// SecurityModelType is a qemu filesystem security model type. -type SecurityModelType string - -const ( - // Local is the local qemu filesystem driver. - Local FSDriver = "local" - - // Handle is the handle qemu filesystem driver. - Handle FSDriver = "handle" - - // Proxy is the proxy qemu filesystem driver. - Proxy FSDriver = "proxy" -) - -const ( - // None is like passthrough without failure reports. - None SecurityModelType = "none" - - // PassThrough uses the same credentials on both the host and guest. - PassThrough SecurityModelType = "passthrough" - - // MappedXattr stores some files attributes as extended attributes. - MappedXattr SecurityModelType = "mapped-xattr" - - // MappedFile stores some files attributes in the .virtfs directory. - MappedFile SecurityModelType = "mapped-file" -) - -// FSDevice represents a qemu filesystem configuration. -type FSDevice struct { - // Driver is the qemu device driver - Driver DeviceDriver - - // FSDriver is the filesystem driver backend. - FSDriver FSDriver - - // ID is the filesystem identifier. - ID string - - // Path is the host root path for this filesystem. - Path string - - // MountTag is the device filesystem mount point tag. - MountTag string - - // SecurityModel is the security model for this filesystem device. - SecurityModel SecurityModelType - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport - - // Multidev is the filesystem behaviour to deal - // with multiple devices being shared with a 9p export - Multidev Virtio9PMultidev -} - -// Virtio9PTransport is a map of the virtio-9p device name that corresponds -// to each transport. -var Virtio9PTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-9p-pci", - TransportCCW: "virtio-9p-ccw", - TransportMMIO: "virtio-9p-device", -} - -// Valid returns true if the FSDevice structure is valid and complete. -func (fsdev FSDevice) Valid() bool { - if fsdev.ID == "" || fsdev.Path == "" || fsdev.MountTag == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of this filesystem device. -func (fsdev FSDevice) QemuParams(config *Config) []string { - var fsParams []string - var deviceParams []string - var qemuParams []string - - deviceParams = append(deviceParams, fsdev.deviceName(config)) - if s := fsdev.Transport.disableModern(config, fsdev.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - deviceParams = append(deviceParams, fmt.Sprintf("fsdev=%s", fsdev.ID)) - deviceParams = append(deviceParams, fmt.Sprintf("mount_tag=%s", fsdev.MountTag)) - if fsdev.Transport.isVirtioPCI(config) && fsdev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", fsdev.ROMFile)) - } - if fsdev.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, ",iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", fsdev.DevNo)) - } - - fsParams = append(fsParams, string(fsdev.FSDriver)) - fsParams = append(fsParams, fmt.Sprintf("id=%s", fsdev.ID)) - fsParams = append(fsParams, fmt.Sprintf("path=%s", fsdev.Path)) - fsParams = append(fsParams, fmt.Sprintf("security_model=%s", fsdev.SecurityModel)) - - if fsdev.Multidev != "" { - fsParams = append(fsParams, fmt.Sprintf("multidevs=%s", fsdev.Multidev)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - qemuParams = append(qemuParams, "-fsdev") - qemuParams = append(qemuParams, strings.Join(fsParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU shared filesystem device name for the current -// combination of driver and transport. -func (fsdev FSDevice) deviceName(config *Config) string { - if fsdev.Transport == "" { - fsdev.Transport = fsdev.Transport.defaultTransport(config) - } - - switch fsdev.Driver { - case Virtio9P: - return Virtio9PTransport[fsdev.Transport] - } - - return string(fsdev.Driver) -} - -// CharDeviceBackend is the character device backend for qemu -type CharDeviceBackend string - -const ( - // Pipe creates a 2 way connection to the guest. - Pipe CharDeviceBackend = "pipe" - - // Socket creates a 2 way stream socket (TCP or Unix). - Socket CharDeviceBackend = "socket" - - // CharConsole sends traffic from the guest to QEMU's standard output. - CharConsole CharDeviceBackend = "console" - - // Serial sends traffic from the guest to a serial device on the host. - Serial CharDeviceBackend = "serial" - - // TTY is an alias for Serial. - TTY CharDeviceBackend = "tty" - - // PTY creates a new pseudo-terminal on the host and connect to it. - PTY CharDeviceBackend = "pty" - - // File sends traffic from the guest to a file on the host. - File CharDeviceBackend = "file" -) - -// CharDevice represents a qemu character device. -type CharDevice struct { - Backend CharDeviceBackend - - // Driver is the qemu device driver - Driver DeviceDriver - - // Bus is the serial bus associated to this device. - Bus string - - // DeviceID is the user defined device ID. - DeviceID string - - ID string - Path string - Name string - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// VirtioSerialTransport is a map of the virtio-serial device name that -// corresponds to each transport. -var VirtioSerialTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-serial-pci", - TransportCCW: "virtio-serial-ccw", - TransportMMIO: "virtio-serial-device", -} - -// Valid returns true if the CharDevice structure is valid and complete. -func (cdev CharDevice) Valid() bool { - if cdev.ID == "" || cdev.Path == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of this character device. -func (cdev CharDevice) QemuParams(config *Config) []string { - var cdevParams []string - var deviceParams []string - var qemuParams []string - - deviceParams = append(deviceParams, cdev.deviceName(config)) - if cdev.Driver == VirtioSerial { - if s := cdev.Transport.disableModern(config, cdev.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - } - if cdev.Bus != "" { - deviceParams = append(deviceParams, fmt.Sprintf("bus=%s", cdev.Bus)) - } - deviceParams = append(deviceParams, fmt.Sprintf("chardev=%s", cdev.ID)) - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", cdev.DeviceID)) - if cdev.Name != "" { - deviceParams = append(deviceParams, fmt.Sprintf("name=%s", cdev.Name)) - } - if cdev.Driver == VirtioSerial && cdev.Transport.isVirtioPCI(config) && cdev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", cdev.ROMFile)) - } - - if cdev.Driver == VirtioSerial && cdev.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", cdev.DevNo)) - } - - cdevParams = append(cdevParams, string(cdev.Backend)) - cdevParams = append(cdevParams, fmt.Sprintf("id=%s", cdev.ID)) - if cdev.Backend == Socket { - cdevParams = append(cdevParams, fmt.Sprintf("path=%s,server=on,wait=off", cdev.Path)) - } else { - cdevParams = append(cdevParams, fmt.Sprintf("path=%s", cdev.Path)) - } - - // Legacy serial is special. It does not follow the device + driver model - if cdev.Driver != LegacySerial { - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - } - - qemuParams = append(qemuParams, "-chardev") - qemuParams = append(qemuParams, strings.Join(cdevParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (cdev CharDevice) deviceName(config *Config) string { - if cdev.Transport == "" { - cdev.Transport = cdev.Transport.defaultTransport(config) - } - - switch cdev.Driver { - case VirtioSerial: - return VirtioSerialTransport[cdev.Transport] - } - - return string(cdev.Driver) -} - -// NetDeviceType is a qemu networking device type. -type NetDeviceType string - -const ( - // TAP is a TAP networking device type. - TAP NetDeviceType = "tap" - - // MACVTAP is a macvtap networking device type. - MACVTAP NetDeviceType = "macvtap" - - // IPVTAP is a ipvtap virtual networking device type. - IPVTAP NetDeviceType = "ipvtap" - - // VETHTAP is a veth-tap virtual networking device type. - VETHTAP NetDeviceType = "vethtap" - - // VFIO is a direct assigned PCI device or PCI VF - VFIO NetDeviceType = "VFIO" - - // VHOSTUSER is a vhost-user port (socket) - VHOSTUSER NetDeviceType = "vhostuser" -) - -// QemuNetdevParam converts to the QEMU -netdev parameter notation -func (n NetDeviceType) QemuNetdevParam(netdev *NetDevice, config *Config) string { - if netdev.Transport == "" { - netdev.Transport = netdev.Transport.defaultTransport(config) - } - - switch n { - case TAP: - return "tap" - case MACVTAP: - return "tap" - case IPVTAP: - return "tap" - case VETHTAP: - return "tap" // -netdev type=tap -device virtio-net-pci - case VFIO: - if netdev.Transport == TransportMMIO { - log.Fatal("vfio devices are not support with the MMIO transport") - } - return "" // -device vfio-pci (no netdev) - case VHOSTUSER: - if netdev.Transport == TransportCCW { - log.Fatal("vhost-user devices are not supported on IBM Z") - } - return "vhost-user" // -netdev type=vhost-user (no device) - default: - return "" - - } -} - -// QemuDeviceParam converts to the QEMU -device parameter notation -func (n NetDeviceType) QemuDeviceParam(netdev *NetDevice, config *Config) DeviceDriver { - if netdev.Transport == "" { - netdev.Transport = netdev.Transport.defaultTransport(config) - } - - var device string - - switch n { - case TAP: - device = "virtio-net" - case MACVTAP: - device = "virtio-net" - case IPVTAP: - device = "virtio-net" - case VETHTAP: - device = "virtio-net" // -netdev type=tap -device virtio-net-pci - case VFIO: - if netdev.Transport == TransportMMIO { - log.Fatal("vfio devices are not support with the MMIO transport") - } - device = "vfio" // -device vfio-pci (no netdev) - case VHOSTUSER: - if netdev.Transport == TransportCCW { - log.Fatal("vhost-user devices are not supported on IBM Z") - } - return "" // -netdev type=vhost-user (no device) - default: - return "" - } - - switch netdev.Transport { - case TransportPCI: - return DeviceDriver(device + "-pci") - case TransportCCW: - return DeviceDriver(device + "-ccw") - case TransportMMIO: - return DeviceDriver(device + "-device") - default: - return "" - } -} - -// NetDevice represents a guest networking device -type NetDevice struct { - // Type is the netdev type (e.g. tap). - Type NetDeviceType - - // Driver is the qemu device driver - Driver DeviceDriver - - // ID is the netdevice identifier. - ID string - - // IfName is the interface name, - IFName string - - // Bus is the bus path name of a PCI device. - Bus string - - // Addr is the address offset of a PCI device. - Addr string - - // DownScript is the tap interface deconfiguration script. - DownScript string - - // Script is the tap interface configuration script. - Script string - - // FDs represents the list of already existing file descriptors to be used. - // This is mostly useful for mq support. - FDs []*os.File - VhostFDs []*os.File - - // VHost enables virtio device emulation from the host kernel instead of from qemu. - VHost bool - - // MACAddress is the networking device interface MAC address. - MACAddress string - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// VirtioNetTransport is a map of the virtio-net device name that corresponds -// to each transport. -var VirtioNetTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-net-pci", - TransportCCW: "virtio-net-ccw", - TransportMMIO: "virtio-net-device", -} - -// Valid returns true if the NetDevice structure is valid and complete. -func (netdev NetDevice) Valid() bool { - if netdev.ID == "" || netdev.IFName == "" { - return false - } - - switch netdev.Type { - case TAP: - return true - case MACVTAP: - return true - default: - return false - } -} - -// mqParameter returns the parameters for multi-queue driver. If the driver is a PCI device then the -// vector flag is required. If the driver is a CCW type than the vector flag is not implemented and only -// multi-queue option mq needs to be activated. See comment in libvirt code at -// https://github.com/libvirt/libvirt/blob/6e7e965dcd3d885739129b1454ce19e819b54c25/src/qemu/qemu_command.c#L3633 -func (netdev NetDevice) mqParameter(config *Config) string { - p := []string{"mq=on"} - - if netdev.Transport.isVirtioPCI(config) { - // https://www.linux-kvm.org/page/Multiqueue - // -netdev tap,vhost=on,queues=N - // enable mq and specify msix vectors in qemu cmdline - // (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq) - // -device virtio-net-pci,mq=on,vectors=2N+2... - // enable mq in guest by 'ethtool -L eth0 combined $queue_num' - // Clearlinux automatically sets up the queues properly - // The agent implementation should do this to ensure that it is - // always set - vectors := len(netdev.FDs)*2 + 2 - p = append(p, fmt.Sprintf("vectors=%d", vectors)) - } - - return strings.Join(p, ",") -} - -// QemuDeviceParams returns the -device parameters for this network device -func (netdev NetDevice) QemuDeviceParams(config *Config) []string { - var deviceParams []string - - driver := netdev.Type.QemuDeviceParam(&netdev, config) - if driver == "" { - return nil - } - - deviceParams = append(deviceParams, fmt.Sprintf("driver=%s", driver)) - deviceParams = append(deviceParams, fmt.Sprintf("netdev=%s", netdev.ID)) - deviceParams = append(deviceParams, fmt.Sprintf("mac=%s", netdev.MACAddress)) - - if netdev.Bus != "" { - deviceParams = append(deviceParams, fmt.Sprintf("bus=%s", netdev.Bus)) - } - - if netdev.Addr != "" { - addr, err := strconv.Atoi(netdev.Addr) - if err == nil && addr >= 0 { - deviceParams = append(deviceParams, fmt.Sprintf("addr=%x", addr)) - } - } - if s := netdev.Transport.disableModern(config, netdev.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - - if len(netdev.FDs) > 0 { - // Note: We are appending to the device params here - deviceParams = append(deviceParams, netdev.mqParameter(config)) - } - - if netdev.Transport.isVirtioPCI(config) && netdev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", netdev.ROMFile)) - } - - if netdev.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", netdev.DevNo)) - } - - return deviceParams -} - -// QemuNetdevParams returns the -netdev parameters for this network device -func (netdev NetDevice) QemuNetdevParams(config *Config) []string { - var netdevParams []string - - netdevType := netdev.Type.QemuNetdevParam(&netdev, config) - if netdevType == "" { - return nil - } - - netdevParams = append(netdevParams, netdevType) - netdevParams = append(netdevParams, fmt.Sprintf("id=%s", netdev.ID)) - - if netdev.VHost { - netdevParams = append(netdevParams, "vhost=on") - if len(netdev.VhostFDs) > 0 { - var fdParams []string - qemuFDs := config.appendFDs(netdev.VhostFDs) - for _, fd := range qemuFDs { - fdParams = append(fdParams, fmt.Sprintf("%d", fd)) - } - netdevParams = append(netdevParams, fmt.Sprintf("vhostfds=%s", strings.Join(fdParams, ":"))) - } - } - - if len(netdev.FDs) > 0 { - var fdParams []string - - qemuFDs := config.appendFDs(netdev.FDs) - for _, fd := range qemuFDs { - fdParams = append(fdParams, fmt.Sprintf("%d", fd)) - } - - netdevParams = append(netdevParams, fmt.Sprintf("fds=%s", strings.Join(fdParams, ":"))) - - } else { - netdevParams = append(netdevParams, fmt.Sprintf("ifname=%s", netdev.IFName)) - if netdev.DownScript != "" { - netdevParams = append(netdevParams, fmt.Sprintf("downscript=%s", netdev.DownScript)) - } - if netdev.Script != "" { - netdevParams = append(netdevParams, fmt.Sprintf("script=%s", netdev.Script)) - } - } - return netdevParams -} - -// QemuParams returns the qemu parameters built out of this network device. -func (netdev NetDevice) QemuParams(config *Config) []string { - var netdevParams []string - var deviceParams []string - var qemuParams []string - - // Macvtap can only be connected via fds - if (netdev.Type == MACVTAP) && (len(netdev.FDs) == 0) { - return nil // implicit error - } - - if netdev.Type.QemuNetdevParam(&netdev, config) != "" { - netdevParams = netdev.QemuNetdevParams(config) - if netdevParams != nil { - qemuParams = append(qemuParams, "-netdev") - qemuParams = append(qemuParams, strings.Join(netdevParams, ",")) - } - } - - if netdev.Type.QemuDeviceParam(&netdev, config) != "" { - deviceParams = netdev.QemuDeviceParams(config) - if deviceParams != nil { - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - } - } - - return qemuParams -} - -// LegacySerialDevice represents a qemu legacy serial device. -type LegacySerialDevice struct { - // ID is the serial device identifier. - // This maps to the char dev associated with the device - // as serial does not have a notion of id - // e.g: - // -chardev stdio,id=char0,mux=on,logfile=serial.log,signal=off -serial chardev:char0 - // -chardev file,id=char0,path=serial.log -serial chardev:char0 - Chardev string -} - -// Valid returns true if the LegacySerialDevice structure is valid and complete. -func (dev LegacySerialDevice) Valid() bool { - return dev.Chardev != "" -} - -// QemuParams returns the qemu parameters built out of this serial device. -func (dev LegacySerialDevice) QemuParams(config *Config) []string { - var deviceParam string - var qemuParams []string - - deviceParam = fmt.Sprintf("chardev:%s", dev.Chardev) - - qemuParams = append(qemuParams, "-serial") - qemuParams = append(qemuParams, deviceParam) - - return qemuParams -} - -/* Not used currently -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (dev LegacySerialDevice) deviceName(config *Config) string { - return dev.Chardev -} -*/ - -// SerialDevice represents a qemu serial device. -type SerialDevice struct { - // Driver is the qemu device driver - Driver DeviceDriver - - // ID is the serial device identifier. - ID string - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport - - // MaxPorts is the maximum number of ports for this device. - MaxPorts uint -} - -// Valid returns true if the SerialDevice structure is valid and complete. -func (dev SerialDevice) Valid() bool { - if dev.Driver == "" || dev.ID == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of this serial device. -func (dev SerialDevice) QemuParams(config *Config) []string { - var deviceParams []string - var qemuParams []string - - deviceParams = append(deviceParams, dev.deviceName(config)) - if s := dev.Transport.disableModern(config, dev.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", dev.ID)) - if dev.Transport.isVirtioPCI(config) && dev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", dev.ROMFile)) - if dev.Driver == VirtioSerial && dev.MaxPorts != 0 { - deviceParams = append(deviceParams, fmt.Sprintf("max_ports=%d", dev.MaxPorts)) - } - } - - if dev.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", dev.DevNo)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (dev SerialDevice) deviceName(config *Config) string { - if dev.Transport == "" { - dev.Transport = dev.Transport.defaultTransport(config) - } - - switch dev.Driver { - case VirtioSerial: - return VirtioSerialTransport[dev.Transport] - } - - return string(dev.Driver) -} - -// BlockDeviceInterface defines the type of interface the device is connected to. -type BlockDeviceInterface string - -// BlockDeviceAIO defines the type of asynchronous I/O the block device should use. -type BlockDeviceAIO string - -// BlockDeviceFormat defines the image format used on a block device. -type BlockDeviceFormat string - -const ( - // NoInterface for block devices with no interfaces. - NoInterface BlockDeviceInterface = "none" - - // SCSI represents a SCSI block device interface. - SCSI BlockDeviceInterface = "scsi" -) - -const ( - // Threads is the pthread asynchronous I/O implementation. - Threads BlockDeviceAIO = "threads" - - // Native is the pthread asynchronous I/O implementation. - Native BlockDeviceAIO = "native" -) - -const ( - // QCOW2 is the Qemu Copy On Write v2 image format. - QCOW2 BlockDeviceFormat = "qcow2" -) - -// BlockDevice represents a qemu block device. -type BlockDevice struct { - Driver DeviceDriver - ID string - File string - Interface BlockDeviceInterface - AIO BlockDeviceAIO - Format BlockDeviceFormat - SCSI bool - WCE bool - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // ShareRW enables multiple qemu instances to share the File - ShareRW bool - - // ReadOnly sets the block device in readonly mode - ReadOnly bool - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// VirtioBlockTransport is a map of the virtio-blk device name that corresponds -// to each transport. -var VirtioBlockTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-blk-pci", - TransportCCW: "virtio-blk-ccw", - TransportMMIO: "virtio-blk-device", -} - -// Valid returns true if the BlockDevice structure is valid and complete. -func (blkdev BlockDevice) Valid() bool { - if blkdev.Driver == "" || blkdev.ID == "" || blkdev.File == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of this block device. -func (blkdev BlockDevice) QemuParams(config *Config) []string { - var blkParams []string - var deviceParams []string - var qemuParams []string - - deviceParams = append(deviceParams, blkdev.deviceName(config)) - if s := blkdev.Transport.disableModern(config, blkdev.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - deviceParams = append(deviceParams, fmt.Sprintf("drive=%s", blkdev.ID)) - if !blkdev.SCSI { - deviceParams = append(deviceParams, "scsi=off") - } - - if !blkdev.WCE { - deviceParams = append(deviceParams, "config-wce=off") - } - - if blkdev.Transport.isVirtioPCI(config) && blkdev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", blkdev.ROMFile)) - } - - if blkdev.Transport.isVirtioCCW(config) { - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", blkdev.DevNo)) - } - - if blkdev.ShareRW { - deviceParams = append(deviceParams, "share-rw=on") - } - - deviceParams = append(deviceParams, fmt.Sprintf("serial=%s", blkdev.ID)) - - blkParams = append(blkParams, fmt.Sprintf("id=%s", blkdev.ID)) - blkParams = append(blkParams, fmt.Sprintf("file=%s", blkdev.File)) - blkParams = append(blkParams, fmt.Sprintf("aio=%s", blkdev.AIO)) - blkParams = append(blkParams, fmt.Sprintf("format=%s", blkdev.Format)) - blkParams = append(blkParams, fmt.Sprintf("if=%s", blkdev.Interface)) - - if blkdev.ReadOnly { - blkParams = append(blkParams, "readonly=on") - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - qemuParams = append(qemuParams, "-drive") - qemuParams = append(qemuParams, strings.Join(blkParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (blkdev BlockDevice) deviceName(config *Config) string { - if blkdev.Transport == "" { - blkdev.Transport = blkdev.Transport.defaultTransport(config) - } - - switch blkdev.Driver { - case VirtioBlock: - return VirtioBlockTransport[blkdev.Transport] - } - - return string(blkdev.Driver) -} - -// PVPanicDevice represents a qemu pvpanic device. -type PVPanicDevice struct { - NoShutdown bool -} - -// Valid always returns true for pvpanic device -func (dev PVPanicDevice) Valid() bool { - return true -} - -// QemuParams returns the qemu parameters built out of this serial device. -func (dev PVPanicDevice) QemuParams(config *Config) []string { - if dev.NoShutdown { - return []string{"-device", "pvpanic", "-no-shutdown"} - } - return []string{"-device", "pvpanic"} -} - -// LoaderDevice represents a qemu loader device. -type LoaderDevice struct { - File string - ID string -} - -// Valid returns true if there is a valid structure defined for LoaderDevice -func (dev LoaderDevice) Valid() bool { - if dev.File == "" { - return false - } - - if dev.ID == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of this loader device. -func (dev LoaderDevice) QemuParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - deviceParams = append(deviceParams, "loader") - deviceParams = append(deviceParams, fmt.Sprintf("file=%s", dev.File)) - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", dev.ID)) - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// VhostUserDevice represents a qemu vhost-user device meant to be passed -// in to the guest -type VhostUserDevice struct { - SocketPath string //path to vhostuser socket on host - CharDevID string - TypeDevID string //variable QEMU parameter based on value of VhostUserType - Address string //used for MAC address in net case - Tag string //virtio-fs volume id for mounting inside guest - CacheSize uint32 //virtio-fs DAX cache size in MiB - SharedVersions bool //enable virtio-fs shared version metadata - VhostUserType DeviceDriver - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the CCW device for s390x. - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// VhostUserNetTransport is a map of the virtio-net device name that -// corresponds to each transport. -var VhostUserNetTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-net-pci", - TransportCCW: "virtio-net-ccw", - TransportMMIO: "virtio-net-device", -} - -// VhostUserSCSITransport is a map of the vhost-user-scsi device name that -// corresponds to each transport. -var VhostUserSCSITransport = map[VirtioTransport]string{ - TransportPCI: "vhost-user-scsi-pci", - TransportCCW: "vhost-user-scsi-ccw", - TransportMMIO: "vhost-user-scsi-device", -} - -// VhostUserBlkTransport is a map of the vhost-user-blk device name that -// corresponds to each transport. -var VhostUserBlkTransport = map[VirtioTransport]string{ - TransportPCI: "vhost-user-blk-pci", - TransportCCW: "vhost-user-blk-ccw", - TransportMMIO: "vhost-user-blk-device", -} - -// VhostUserFSTransport is a map of the vhost-user-fs device name that -// corresponds to each transport. -var VhostUserFSTransport = map[VirtioTransport]string{ - TransportPCI: "vhost-user-fs-pci", - TransportCCW: "vhost-user-fs-ccw", - TransportMMIO: "vhost-user-fs-device", -} - -// Valid returns true if there is a valid structure defined for VhostUserDevice -func (vhostuserDev VhostUserDevice) Valid() bool { - - if vhostuserDev.SocketPath == "" || vhostuserDev.CharDevID == "" { - return false - } - - switch vhostuserDev.VhostUserType { - case VhostUserNet: - if vhostuserDev.TypeDevID == "" || vhostuserDev.Address == "" { - return false - } - case VhostUserSCSI: - if vhostuserDev.TypeDevID == "" { - return false - } - case VhostUserBlk: - case VhostUserFS: - if vhostuserDev.Tag == "" { - return false - } - default: - return false - } - - return true -} - -// QemuNetParams builds QEMU netdev and device parameters for a VhostUserNet device -func (vhostuserDev VhostUserDevice) QemuNetParams(config *Config) []string { - var qemuParams []string - var netParams []string - var deviceParams []string - - driver := vhostuserDev.deviceName(config) - if driver == "" { - return nil - } - - netParams = append(netParams, "type=vhost-user") - netParams = append(netParams, fmt.Sprintf("id=%s", vhostuserDev.TypeDevID)) - netParams = append(netParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) - netParams = append(netParams, "vhostforce") - - deviceParams = append(deviceParams, driver) - deviceParams = append(deviceParams, fmt.Sprintf("netdev=%s", vhostuserDev.TypeDevID)) - deviceParams = append(deviceParams, fmt.Sprintf("mac=%s", vhostuserDev.Address)) - - if vhostuserDev.Transport.isVirtioPCI(config) && vhostuserDev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", vhostuserDev.ROMFile)) - } - - qemuParams = append(qemuParams, "-netdev") - qemuParams = append(qemuParams, strings.Join(netParams, ",")) - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// QemuSCSIParams builds QEMU device parameters for a VhostUserSCSI device -func (vhostuserDev VhostUserDevice) QemuSCSIParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - driver := vhostuserDev.deviceName(config) - if driver == "" { - return nil - } - - deviceParams = append(deviceParams, driver) - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", vhostuserDev.TypeDevID)) - deviceParams = append(deviceParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) - - if vhostuserDev.Transport.isVirtioPCI(config) && vhostuserDev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", vhostuserDev.ROMFile)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// QemuBlkParams builds QEMU device parameters for a VhostUserBlk device -func (vhostuserDev VhostUserDevice) QemuBlkParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - driver := vhostuserDev.deviceName(config) - if driver == "" { - return nil - } - - deviceParams = append(deviceParams, driver) - deviceParams = append(deviceParams, "logical_block_size=4096") - deviceParams = append(deviceParams, "size=512M") - deviceParams = append(deviceParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) - - if vhostuserDev.Transport.isVirtioPCI(config) && vhostuserDev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", vhostuserDev.ROMFile)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// QemuFSParams builds QEMU device parameters for a VhostUserFS device -func (vhostuserDev VhostUserDevice) QemuFSParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - driver := vhostuserDev.deviceName(config) - if driver == "" { - return nil - } - - deviceParams = append(deviceParams, driver) - deviceParams = append(deviceParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) - deviceParams = append(deviceParams, fmt.Sprintf("tag=%s", vhostuserDev.Tag)) - if vhostuserDev.CacheSize != 0 { - deviceParams = append(deviceParams, fmt.Sprintf("cache-size=%dM", vhostuserDev.CacheSize)) - } - if vhostuserDev.SharedVersions { - deviceParams = append(deviceParams, "versiontable=/dev/shm/fuse_shared_versions") - } - if vhostuserDev.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", vhostuserDev.DevNo)) - } - if vhostuserDev.Transport.isVirtioPCI(config) && vhostuserDev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", vhostuserDev.ROMFile)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// QemuParams returns the qemu parameters built out of this vhostuser device. -func (vhostuserDev VhostUserDevice) QemuParams(config *Config) []string { - var qemuParams []string - var charParams []string - var deviceParams []string - - charParams = append(charParams, "socket") - charParams = append(charParams, fmt.Sprintf("id=%s", vhostuserDev.CharDevID)) - charParams = append(charParams, fmt.Sprintf("path=%s", vhostuserDev.SocketPath)) - - qemuParams = append(qemuParams, "-chardev") - qemuParams = append(qemuParams, strings.Join(charParams, ",")) - - switch vhostuserDev.VhostUserType { - case VhostUserNet: - deviceParams = vhostuserDev.QemuNetParams(config) - case VhostUserSCSI: - deviceParams = vhostuserDev.QemuSCSIParams(config) - case VhostUserBlk: - deviceParams = vhostuserDev.QemuBlkParams(config) - case VhostUserFS: - deviceParams = vhostuserDev.QemuFSParams(config) - default: - return nil - } - - if deviceParams != nil { - return append(qemuParams, deviceParams...) - } - - return nil -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (vhostuserDev VhostUserDevice) deviceName(config *Config) string { - if vhostuserDev.Transport == "" { - vhostuserDev.Transport = vhostuserDev.Transport.defaultTransport(config) - } - - switch vhostuserDev.VhostUserType { - case VhostUserNet: - return VhostUserNetTransport[vhostuserDev.Transport] - case VhostUserSCSI: - return VhostUserSCSITransport[vhostuserDev.Transport] - case VhostUserBlk: - return VhostUserBlkTransport[vhostuserDev.Transport] - case VhostUserFS: - return VhostUserFSTransport[vhostuserDev.Transport] - default: - return "" - } -} - -// PCIeRootPortDevice represents a memory balloon device. -type PCIeRootPortDevice struct { - ID string // format: rp{n}, n>=0 - - Bus string // default is pcie.0 - Chassis string // (slot, chassis) pair is mandatory and must be unique for each pcie-root-port, >=0, default is 0x00 - Slot string // >=0, default is 0x00 - - Multifunction bool // true => "on", false => "off", default is off - Addr string // >=0, default is 0x00 - - // The PCIE-PCI bridge can be hot-plugged only into pcie-root-port that has 'bus-reserve' property value to - // provide secondary bus for the hot-plugged bridge. - BusReserve string - Pref64Reserve string // reserve prefetched MMIO aperture, 64-bit - Pref32Reserve string // reserve prefetched MMIO aperture, 32-bit - MemReserve string // reserve non-prefetched MMIO aperture, 32-bit *only* - IOReserve string // IO reservation - - ROMFile string // ROMFile specifies the ROM file being used for this device. - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// QemuParams returns the qemu parameters built out of the PCIeRootPortDevice. -func (b PCIeRootPortDevice) QemuParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - driver := PCIeRootPort - - deviceParams = append(deviceParams, fmt.Sprintf("%s,id=%s", driver, b.ID)) - - if b.Bus == "" { - b.Bus = "pcie.0" - } - deviceParams = append(deviceParams, fmt.Sprintf("bus=%s", b.Bus)) - - if b.Chassis == "" { - b.Chassis = "0x00" - } - deviceParams = append(deviceParams, fmt.Sprintf("chassis=%s", b.Chassis)) - - if b.Slot == "" { - b.Slot = "0x00" - } - deviceParams = append(deviceParams, fmt.Sprintf("slot=%s", b.Slot)) - - multifunction := "off" - if b.Multifunction { - multifunction = "on" - if b.Addr == "" { - b.Addr = "0x00" - } - deviceParams = append(deviceParams, fmt.Sprintf("addr=%s", b.Addr)) - } - deviceParams = append(deviceParams, fmt.Sprintf("multifunction=%v", multifunction)) - - if b.BusReserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("bus-reserve=%s", b.BusReserve)) - } - - if b.Pref64Reserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("pref64-reserve=%s", b.Pref64Reserve)) - } - - if b.Pref32Reserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("pref32-reserve=%s", b.Pref32Reserve)) - } - - if b.MemReserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("mem-reserve=%s", b.MemReserve)) - } - - if b.IOReserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("io-reserve=%s", b.IOReserve)) - } - - if b.Transport.isVirtioPCI(config) && b.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", b.ROMFile)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - return qemuParams -} - -// Valid returns true if the PCIeRootPortDevice structure is valid and complete. -func (b PCIeRootPortDevice) Valid() bool { - // the "pref32-reserve" and "pref64-reserve" hints are mutually exclusive. - if b.Pref64Reserve != "" && b.Pref32Reserve != "" { - return false - } - if b.ID == "" { - return false - } - return true -} - -// VFIODevice represents a qemu vfio device meant for direct access by guest OS. -type VFIODevice struct { - // Bus-Device-Function of device - BDF string - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // VendorID specifies vendor id - VendorID string - - // DeviceID specifies device id - DeviceID string - - // Bus specifies device bus - Bus string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// VFIODeviceTransport is a map of the vfio device name that corresponds to -// each transport. -var VFIODeviceTransport = map[VirtioTransport]string{ - TransportPCI: "vfio-pci", - TransportCCW: "vfio-ccw", - TransportMMIO: "vfio-device", -} - -// Valid returns true if the VFIODevice structure is valid and complete. -func (vfioDev VFIODevice) Valid() bool { - return vfioDev.BDF != "" -} - -// QemuParams returns the qemu parameters built out of this vfio device. -func (vfioDev VFIODevice) QemuParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - driver := vfioDev.deviceName(config) - - deviceParams = append(deviceParams, fmt.Sprintf("%s,host=%s", driver, vfioDev.BDF)) - if vfioDev.Transport.isVirtioPCI(config) { - if vfioDev.VendorID != "" { - deviceParams = append(deviceParams, fmt.Sprintf("x-pci-vendor-id=%s", vfioDev.VendorID)) - } - if vfioDev.DeviceID != "" { - deviceParams = append(deviceParams, fmt.Sprintf("x-pci-device-id=%s", vfioDev.DeviceID)) - } - if vfioDev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", vfioDev.ROMFile)) - } - } - - if vfioDev.Bus != "" { - deviceParams = append(deviceParams, fmt.Sprintf("bus=%s", vfioDev.Bus)) - } - - if vfioDev.Transport.isVirtioCCW(config) { - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", vfioDev.DevNo)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (vfioDev VFIODevice) deviceName(config *Config) string { - if vfioDev.Transport == "" { - vfioDev.Transport = vfioDev.Transport.defaultTransport(config) - } - - return VFIODeviceTransport[vfioDev.Transport] -} - -// SCSIController represents a SCSI controller device. -type SCSIController struct { - ID string - - // Bus on which the SCSI controller is attached, this is optional - Bus string - - // Addr is the PCI address offset, this is optional - Addr string - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // IOThread is the IO thread on which IO will be handled - IOThread string - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// SCSIControllerTransport is a map of the virtio-scsi device name that -// corresponds to each transport. -var SCSIControllerTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-scsi-pci", - TransportCCW: "virtio-scsi-ccw", - TransportMMIO: "virtio-scsi-device", -} - -// Valid returns true if the SCSIController structure is valid and complete. -func (scsiCon SCSIController) Valid() bool { - return scsiCon.ID != "" -} - -// QemuParams returns the qemu parameters built out of this SCSIController device. -func (scsiCon SCSIController) QemuParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - driver := scsiCon.deviceName(config) - deviceParams = append(deviceParams, fmt.Sprintf("%s,id=%s", driver, scsiCon.ID)) - if scsiCon.Bus != "" { - deviceParams = append(deviceParams, fmt.Sprintf("bus=%s", scsiCon.Bus)) - } - if scsiCon.Addr != "" { - deviceParams = append(deviceParams, fmt.Sprintf("addr=%s", scsiCon.Addr)) - } - if s := scsiCon.Transport.disableModern(config, scsiCon.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - if scsiCon.IOThread != "" { - deviceParams = append(deviceParams, fmt.Sprintf("iothread=%s", scsiCon.IOThread)) - } - if scsiCon.Transport.isVirtioPCI(config) && scsiCon.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", scsiCon.ROMFile)) - } - - if scsiCon.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", scsiCon.DevNo)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (scsiCon SCSIController) deviceName(config *Config) string { - if scsiCon.Transport == "" { - scsiCon.Transport = scsiCon.Transport.defaultTransport(config) - } - - return SCSIControllerTransport[scsiCon.Transport] -} - -// BridgeType is the type of the bridge -type BridgeType uint - -const ( - // PCIBridge is a pci bridge - PCIBridge BridgeType = iota - - // PCIEBridge is a pcie bridge - PCIEBridge -) - -// BridgeDevice represents a qemu bridge device like pci-bridge, pxb, etc. -type BridgeDevice struct { - // Type of the bridge - Type BridgeType - - // Bus number where the bridge is plugged, typically pci.0 or pcie.0 - Bus string - - // ID is used to identify the bridge in qemu - ID string - - // Chassis number - Chassis int - - // SHPC is used to enable or disable the standard hot plug controller - SHPC bool - - // PCI Slot - Addr string - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // Address range reservations for devices behind the bridge - // NB: strings seem an odd choice, but if they were integers, - // they'd default to 0 by Go's rules in all the existing users - // who don't set them. 0 is a valid value for certain cases, - // but not you want by default. - IOReserve string - MemReserve string - Pref64Reserve string -} - -// Valid returns true if the BridgeDevice structure is valid and complete. -func (bridgeDev BridgeDevice) Valid() bool { - if bridgeDev.Type != PCIBridge && bridgeDev.Type != PCIEBridge { - return false - } - - if bridgeDev.Bus == "" { - return false - } - - if bridgeDev.ID == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of this bridge device. -func (bridgeDev BridgeDevice) QemuParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - var driver DeviceDriver - - switch bridgeDev.Type { - case PCIEBridge: - driver = PCIePCIBridgeDriver - deviceParams = append(deviceParams, fmt.Sprintf("%s,bus=%s,id=%s", driver, bridgeDev.Bus, bridgeDev.ID)) - default: - driver = PCIBridgeDriver - shpc := "off" - if bridgeDev.SHPC { - shpc = "on" - } - deviceParams = append(deviceParams, fmt.Sprintf("%s,bus=%s,id=%s,chassis_nr=%d,shpc=%s", driver, bridgeDev.Bus, bridgeDev.ID, bridgeDev.Chassis, shpc)) - } - - if bridgeDev.Addr != "" { - addr, err := strconv.Atoi(bridgeDev.Addr) - if err == nil && addr >= 0 { - deviceParams = append(deviceParams, fmt.Sprintf("addr=%x", addr)) - } - } - - var transport VirtioTransport - if transport.isVirtioPCI(config) && bridgeDev.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", bridgeDev.ROMFile)) - } - - if bridgeDev.IOReserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("io-reserve=%s", bridgeDev.IOReserve)) - } - if bridgeDev.MemReserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("mem-reserve=%s", bridgeDev.MemReserve)) - } - if bridgeDev.Pref64Reserve != "" { - deviceParams = append(deviceParams, fmt.Sprintf("pref64-reserve=%s", bridgeDev.Pref64Reserve)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// VSOCKDevice represents a AF_VSOCK socket. -type VSOCKDevice struct { - ID string - - ContextID uint64 - - // VHostFD vhost file descriptor that holds the ContextID - VHostFD *os.File - - // DisableModern prevents qemu from relying on fast MMIO. - DisableModern bool - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// VSOCKDeviceTransport is a map of the vhost-vsock device name that -// corresponds to each transport. -var VSOCKDeviceTransport = map[VirtioTransport]string{ - TransportPCI: "vhost-vsock-pci", - TransportCCW: "vhost-vsock-ccw", - TransportMMIO: "vhost-vsock-device", -} - -const ( - // MinimalGuestCID is the smallest valid context ID for a guest. - MinimalGuestCID uint64 = 3 - - // MaxGuestCID is the largest valid context ID for a guest. - MaxGuestCID uint64 = 1<<32 - 1 -) - -const ( - // VSOCKGuestCID is the VSOCK guest CID parameter. - VSOCKGuestCID = "guest-cid" -) - -// Valid returns true if the VSOCKDevice structure is valid and complete. -func (vsock VSOCKDevice) Valid() bool { - if vsock.ID == "" || vsock.ContextID < MinimalGuestCID || vsock.ContextID > MaxGuestCID { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of the VSOCK device. -func (vsock VSOCKDevice) QemuParams(config *Config) []string { - var deviceParams []string - var qemuParams []string - - driver := vsock.deviceName(config) - deviceParams = append(deviceParams, driver) - if s := vsock.Transport.disableModern(config, vsock.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - if vsock.VHostFD != nil { - qemuFDs := config.appendFDs([]*os.File{vsock.VHostFD}) - deviceParams = append(deviceParams, fmt.Sprintf("vhostfd=%d", qemuFDs[0])) - } - deviceParams = append(deviceParams, fmt.Sprintf("id=%s", vsock.ID)) - deviceParams = append(deviceParams, fmt.Sprintf("%s=%d", VSOCKGuestCID, vsock.ContextID)) - - if vsock.Transport.isVirtioPCI(config) && vsock.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", vsock.ROMFile)) - } - - if vsock.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", vsock.DevNo)) - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (vsock VSOCKDevice) deviceName(config *Config) string { - if vsock.Transport == "" { - vsock.Transport = vsock.Transport.defaultTransport(config) - } - - return VSOCKDeviceTransport[vsock.Transport] -} - -// 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 - // ROMFile specifies the ROM file being used for this device. - ROMFile string - // DevNo identifies the ccw devices for s390x architecture - DevNo string - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// RngDeviceTransport is a map of the virtio-rng device name that corresponds -// to each transport. -var RngDeviceTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-rng-pci", - TransportCCW: "virtio-rng-ccw", - TransportMMIO: "virtio-rng-device", -} - -// Valid returns true if the RngDevice structure is valid and complete. -func (v RngDevice) Valid() bool { - return v.ID != "" -} - -// QemuParams returns the qemu parameters built out of the RngDevice. -func (v RngDevice) QemuParams(config *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, v.deviceName(config)) - deviceParams = append(deviceParams, "rng="+v.ID) - - if v.Transport.isVirtioPCI(config) && v.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", v.ROMFile)) - } - - if v.Transport.isVirtioCCW(config) { - if config.Knobs.IOMMUPlatform { - deviceParams = append(deviceParams, "iommu_platform=on") - } - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", v.DevNo)) - } - - 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 -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (v RngDevice) deviceName(config *Config) string { - if v.Transport == "" { - v.Transport = v.Transport.defaultTransport(config) - } - - return RngDeviceTransport[v.Transport] -} - -// BalloonDevice represents a memory balloon device. -type BalloonDevice struct { - DeflateOnOOM bool - DisableModern bool - ID string - - // ROMFile specifies the ROM file being used for this device. - ROMFile string - - // DevNo identifies the ccw devices for s390x architecture - DevNo string - - // Transport is the virtio transport for this device. - Transport VirtioTransport -} - -// BalloonDeviceTransport is a map of the virtio-balloon device name that -// corresponds to each transport. -var BalloonDeviceTransport = map[VirtioTransport]string{ - TransportPCI: "virtio-balloon-pci", - TransportCCW: "virtio-balloon-ccw", - TransportMMIO: "virtio-balloon-device", -} - -// QemuParams returns the qemu parameters built out of the BalloonDevice. -func (b BalloonDevice) QemuParams(config *Config) []string { - var qemuParams []string - var deviceParams []string - - deviceParams = append(deviceParams, b.deviceName(config)) - - if b.ID != "" { - deviceParams = append(deviceParams, "id="+b.ID) - } - - if b.Transport.isVirtioPCI(config) && b.ROMFile != "" { - deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", b.ROMFile)) - } - - if b.Transport.isVirtioCCW(config) { - deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", b.DevNo)) - } - - if b.DeflateOnOOM { - deviceParams = append(deviceParams, "deflate-on-oom=on") - } else { - deviceParams = append(deviceParams, "deflate-on-oom=off") - } - if s := b.Transport.disableModern(config, b.DisableModern); s != "" { - deviceParams = append(deviceParams, s) - } - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - - return qemuParams -} - -// Valid returns true if the balloonDevice structure is valid and complete. -func (b BalloonDevice) Valid() bool { - return b.ID != "" -} - -// deviceName returns the QEMU device name for the current combination of -// driver and transport. -func (b BalloonDevice) deviceName(config *Config) string { - if b.Transport == "" { - b.Transport = b.Transport.defaultTransport(config) - } - - return BalloonDeviceTransport[b.Transport] -} - -// IommuDev represents a Intel IOMMU Device -type IommuDev struct { - Intremap bool - DeviceIotlb bool - CachingMode bool -} - -// Valid returns true if the IommuDev is valid -func (dev IommuDev) Valid() bool { - return true -} - -// deviceName the qemu device name -func (dev IommuDev) deviceName() string { - return "intel-iommu" -} - -// QemuParams returns the qemu parameters built out of the IommuDev. -func (dev IommuDev) QemuParams(_ *Config) []string { - var qemuParams []string - var deviceParams []string - - deviceParams = append(deviceParams, dev.deviceName()) - if dev.Intremap { - deviceParams = append(deviceParams, "intremap=on") - } else { - deviceParams = append(deviceParams, "intremap=off") - } - - if dev.DeviceIotlb { - deviceParams = append(deviceParams, "device-iotlb=on") - } else { - deviceParams = append(deviceParams, "device-iotlb=off") - } - - if dev.CachingMode { - deviceParams = append(deviceParams, "caching-mode=on") - } else { - deviceParams = append(deviceParams, "caching-mode=off") - } - - qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) - return qemuParams -} - -// RTCBaseType is the qemu RTC base time type. -type RTCBaseType string - -// RTCClock is the qemu RTC clock type. -type RTCClock string - -// RTCDriftFix is the qemu RTC drift fix type. -type RTCDriftFix string - -const ( - // UTC is the UTC base time for qemu RTC. - UTC RTCBaseType = "utc" - - // LocalTime is the local base time for qemu RTC. - LocalTime RTCBaseType = "localtime" -) - -const ( - // Host is for using the host clock as a reference. - Host RTCClock = "host" - - // RT is for using the host monotonic clock as a reference. - RT RTCClock = "rt" - - // VM is for using the guest clock as a reference - VM RTCClock = "vm" -) - -const ( - // Slew is the qemu RTC Drift fix mechanism. - Slew RTCDriftFix = "slew" - - // NoDriftFix means we don't want/need to fix qemu's RTC drift. - NoDriftFix RTCDriftFix = "none" -) - -// RTC represents a qemu Real Time Clock configuration. -type RTC struct { - // Base is the RTC start time. - Base RTCBaseType - - // Clock is the is the RTC clock driver. - Clock RTCClock - - // DriftFix is the drift fixing mechanism. - DriftFix RTCDriftFix -} - -// Valid returns true if the RTC structure is valid and complete. -func (rtc RTC) Valid() bool { - if rtc.Clock != Host && rtc.Clock != RT && rtc.Clock != VM { - return false - } - - if rtc.DriftFix != Slew && rtc.DriftFix != NoDriftFix { - return false - } - - return true -} - -// QMPSocketType is the type of socket used for QMP communication. -type QMPSocketType string - -const ( - // Unix socket for QMP. - Unix QMPSocketType = "unix" -) - -// QMPSocket represents a qemu QMP socket configuration. -type QMPSocket struct { - // Type is the socket type (e.g. "unix"). - Type QMPSocketType - - // Name is the socket name. - Name string - - // Server tells if this is a server socket. - Server bool - - // NoWait tells if qemu should block waiting for a client to connect. - NoWait bool -} - -// Valid returns true if the QMPSocket structure is valid and complete. -func (qmp QMPSocket) Valid() bool { - if qmp.Type == "" || qmp.Name == "" { - return false - } - - if qmp.Type != Unix { - return false - } - - return true -} - -// SMP is the multi processors configuration structure. -type SMP struct { - // CPUs is the number of VCPUs made available to qemu. - CPUs uint32 - - // Cores is the number of cores made available to qemu. - Cores uint32 - - // Threads is the number of threads made available to qemu. - Threads uint32 - - // Sockets is the number of sockets made available to qemu. - Sockets uint32 - - // MaxCPUs is the maximum number of VCPUs that a VM can have. - // This value, if non-zero, MUST BE equal to or greater than CPUs - MaxCPUs uint32 -} - -// Memory is the guest memory configuration structure. -type Memory struct { - // Size is the amount of memory made available to the guest. - // It should be suffixed with M or G for sizes in megabytes or - // gigabytes respectively. - Size string - - // Slots is the amount of memory slots made available to the guest. - Slots uint8 - - // MaxMem is the maximum amount of memory that can be made available - // to the guest through e.g. hot pluggable memory. - MaxMem string - - // Path is the file path of the memory device. It points to a local - // file path used by FileBackedMem. - Path string -} - -// Kernel is the guest kernel configuration structure. -type Kernel struct { - // Path is the guest kernel path on the host filesystem. - Path string - - // InitrdPath is the guest initrd path on the host filesystem. - InitrdPath string - - // Params is the kernel parameters string. - Params string -} - -// FwCfg allows QEMU to pass entries to the guest -// File and Str are mutually exclusive -type FwCfg struct { - Name string - File string - Str string -} - -// Valid returns true if the FwCfg structure is valid and complete. -func (fwcfg FwCfg) Valid() bool { - if fwcfg.Name == "" { - return false - } - - if fwcfg.File != "" && fwcfg.Str != "" { - return false - } - - if fwcfg.File == "" && fwcfg.Str == "" { - return false - } - - return true -} - -// QemuParams returns the qemu parameters built out of the FwCfg object -func (fwcfg FwCfg) QemuParams(config *Config) []string { - var fwcfgParams []string - var qemuParams []string - - for _, f := range config.FwCfg { - if f.Name != "" { - fwcfgParams = append(fwcfgParams, fmt.Sprintf("name=%s", f.Name)) - - if f.File != "" { - fwcfgParams = append(fwcfgParams, fmt.Sprintf("file=%s", f.File)) - } - - if f.Str != "" { - fwcfgParams = append(fwcfgParams, fmt.Sprintf("string=%s", f.Str)) - } - } - - qemuParams = append(qemuParams, "-fw_cfg") - qemuParams = append(qemuParams, strings.Join(fwcfgParams, ",")) - } - - return qemuParams -} - -// Knobs regroups a set of qemu boolean settings -type Knobs struct { - // NoUserConfig prevents qemu from loading user config files. - NoUserConfig bool - - // NoDefaults prevents qemu from creating default devices. - NoDefaults bool - - // NoGraphic completely disables graphic output. - NoGraphic bool - - // Daemonize will turn the qemu process into a daemon - Daemonize bool - - // Both HugePages and MemPrealloc require the Memory.Size of the VM - // to be set, as they need to reserve the memory upfront in order - // for the VM to boot without errors. - // - // HugePages always results in memory pre-allocation. - // However the setup is different from normal pre-allocation. - // Hence HugePages has precedence over MemPrealloc - // HugePages will pre-allocate all the RAM from huge pages - HugePages bool - - // MemPrealloc will allocate all the RAM upfront - MemPrealloc bool - - // FileBackedMem requires Memory.Size and Memory.Path of the VM to - // be set. - FileBackedMem bool - - // MemShared will set the memory device as shared. - MemShared bool - - // Mlock will control locking of memory - Mlock bool - - // Stopped will not start guest CPU at startup - Stopped bool - - // Exit instead of rebooting - // Prevents QEMU from rebooting in the event of a Triple Fault. - NoReboot bool - - // Don’t exit QEMU on guest shutdown, but instead only stop the emulation. - NoShutdown bool - - // IOMMUPlatform will enable IOMMU for supported devices - IOMMUPlatform bool -} - -// IOThread allows IO to be performed on a separate thread. -type IOThread struct { - ID string -} - -const ( - // MigrationFD is the migration incoming type based on open file descriptor. - // Skip default 0 so that it must be set on purpose. - MigrationFD = 1 - // MigrationExec is the migration incoming type based on commands. - MigrationExec = 2 - // MigrationDefer is the defer incoming type - MigrationDefer = 3 -) - -// Incoming controls migration source preparation -type Incoming struct { - // Possible values are MigrationFD, MigrationExec - MigrationType int - // Only valid if MigrationType == MigrationFD - FD *os.File - // Only valid if MigrationType == MigrationExec - Exec string -} - -// Config is the qemu configuration structure. -// It allows for passing custom settings and parameters to the qemu API. -type Config struct { - // Path is the qemu binary path. - Path string - - // Ctx is the context used when launching qemu. - Ctx context.Context - - // User ID. - Uid uint32 - // Group ID. - Gid uint32 - // Supplementary group IDs. - Groups []uint32 - - // Name is the qemu guest name - Name string - - // UUID is the qemu process UUID. - UUID string - - // CPUModel is the CPU model to be used by qemu. - CPUModel string - - // SeccompSandbox is the qemu function which enables the seccomp feature - SeccompSandbox string - - // Machine - Machine Machine - - // QMPSockets is a slice of QMP socket description. - QMPSockets []QMPSocket - - // Devices is a list of devices for qemu to create and drive. - Devices []Device - - // RTC is the qemu Real Time Clock configuration - RTC RTC - - // VGA is the qemu VGA mode. - VGA string - - // Kernel is the guest kernel configuration. - Kernel Kernel - - // Memory is the guest memory configuration. - Memory Memory - - // SMP is the quest multi processors configuration. - SMP SMP - - // GlobalParam is the -global parameter. - GlobalParam string - - // Knobs is a set of qemu boolean settings. - Knobs Knobs - - // Bios is the -bios parameter - Bios string - - // PFlash specifies the parallel flash images (-pflash parameter) - PFlash []string - - // Incoming controls migration source preparation - Incoming Incoming - - // fds is a list of open file descriptors to be passed to the spawned qemu process - fds []*os.File - - // FwCfg is the -fw_cfg parameter - FwCfg []FwCfg - - IOThreads []IOThread - - // PidFile is the -pidfile parameter - PidFile string - - // LogFile is the -D parameter - LogFile string - - qemuParams []string -} - -// appendFDs append a list of file descriptors to the qemu configuration and -// returns a slice of offset file descriptors that will be seen by the qemu process. -func (config *Config) appendFDs(fds []*os.File) []int { - var fdInts []int - - oldLen := len(config.fds) - - config.fds = append(config.fds, fds...) - - // The magic 3 offset comes from https://golang.org/src/os/exec/exec.go: - // ExtraFiles specifies additional open files to be inherited by the - // new process. It does not include standard input, standard output, or - // standard error. If non-nil, entry i becomes file descriptor 3+i. - for i := range fds { - fdInts = append(fdInts, oldLen+3+i) - } - - return fdInts -} - -func (config *Config) appendSeccompSandbox() { - if config.SeccompSandbox != "" { - config.qemuParams = append(config.qemuParams, "-sandbox") - config.qemuParams = append(config.qemuParams, config.SeccompSandbox) - } -} - -func (config *Config) appendName() { - if config.Name != "" { - config.qemuParams = append(config.qemuParams, "-name") - config.qemuParams = append(config.qemuParams, config.Name) - } -} - -func (config *Config) appendMachine() { - if config.Machine.Type != "" { - var machineParams []string - - machineParams = append(machineParams, config.Machine.Type) - - if config.Machine.Acceleration != "" { - machineParams = append(machineParams, fmt.Sprintf("accel=%s", config.Machine.Acceleration)) - } - - if config.Machine.Options != "" { - machineParams = append(machineParams, config.Machine.Options) - } - - config.qemuParams = append(config.qemuParams, "-machine") - config.qemuParams = append(config.qemuParams, strings.Join(machineParams, ",")) - } -} - -func (config *Config) appendCPUModel() { - if config.CPUModel != "" { - config.qemuParams = append(config.qemuParams, "-cpu") - config.qemuParams = append(config.qemuParams, config.CPUModel) - } -} - -func (config *Config) appendQMPSockets() { - for _, q := range config.QMPSockets { - if !q.Valid() { - continue - } - - qmpParams := append([]string{}, fmt.Sprintf("%s:%s", q.Type, q.Name)) - if q.Server { - qmpParams = append(qmpParams, "server=on") - if q.NoWait { - qmpParams = append(qmpParams, "wait=off") - } - } - - config.qemuParams = append(config.qemuParams, "-qmp") - config.qemuParams = append(config.qemuParams, strings.Join(qmpParams, ",")) - } -} - -func (config *Config) appendDevices() { - for _, d := range config.Devices { - if !d.Valid() { - continue - } - - config.qemuParams = append(config.qemuParams, d.QemuParams(config)...) - } -} - -func (config *Config) appendUUID() { - if config.UUID != "" { - config.qemuParams = append(config.qemuParams, "-uuid") - config.qemuParams = append(config.qemuParams, config.UUID) - } -} - -func (config *Config) appendMemory() { - if config.Memory.Size != "" { - var memoryParams []string - - memoryParams = append(memoryParams, config.Memory.Size) - - if config.Memory.Slots > 0 { - memoryParams = append(memoryParams, fmt.Sprintf("slots=%d", config.Memory.Slots)) - } - - if config.Memory.MaxMem != "" { - memoryParams = append(memoryParams, fmt.Sprintf("maxmem=%s", config.Memory.MaxMem)) - } - - config.qemuParams = append(config.qemuParams, "-m") - config.qemuParams = append(config.qemuParams, strings.Join(memoryParams, ",")) - } -} - -func (config *Config) appendCPUs() error { - if config.SMP.CPUs > 0 { - var SMPParams []string - - SMPParams = append(SMPParams, fmt.Sprintf("%d", config.SMP.CPUs)) - - if config.SMP.Cores > 0 { - SMPParams = append(SMPParams, fmt.Sprintf("cores=%d", config.SMP.Cores)) - } - - if config.SMP.Threads > 0 { - SMPParams = append(SMPParams, fmt.Sprintf("threads=%d", config.SMP.Threads)) - } - - if config.SMP.Sockets > 0 { - SMPParams = append(SMPParams, fmt.Sprintf("sockets=%d", config.SMP.Sockets)) - } - - if config.SMP.MaxCPUs > 0 { - if config.SMP.MaxCPUs < config.SMP.CPUs { - return fmt.Errorf("MaxCPUs %d must be equal to or greater than CPUs %d", - config.SMP.MaxCPUs, config.SMP.CPUs) - } - SMPParams = append(SMPParams, fmt.Sprintf("maxcpus=%d", config.SMP.MaxCPUs)) - } - - config.qemuParams = append(config.qemuParams, "-smp") - config.qemuParams = append(config.qemuParams, strings.Join(SMPParams, ",")) - } - - return nil -} - -func (config *Config) appendRTC() { - if !config.RTC.Valid() { - return - } - - var RTCParams []string - - RTCParams = append(RTCParams, fmt.Sprintf("base=%s", string(config.RTC.Base))) - - if config.RTC.DriftFix != "" { - RTCParams = append(RTCParams, fmt.Sprintf("driftfix=%s", config.RTC.DriftFix)) - } - - if config.RTC.Clock != "" { - RTCParams = append(RTCParams, fmt.Sprintf("clock=%s", config.RTC.Clock)) - } - - config.qemuParams = append(config.qemuParams, "-rtc") - config.qemuParams = append(config.qemuParams, strings.Join(RTCParams, ",")) -} - -func (config *Config) appendGlobalParam() { - if config.GlobalParam != "" { - config.qemuParams = append(config.qemuParams, "-global") - config.qemuParams = append(config.qemuParams, config.GlobalParam) - } -} - -func (config *Config) appendPFlashParam() { - for _, p := range config.PFlash { - config.qemuParams = append(config.qemuParams, "-pflash") - config.qemuParams = append(config.qemuParams, p) - } -} - -func (config *Config) appendVGA() { - if config.VGA != "" { - config.qemuParams = append(config.qemuParams, "-vga") - config.qemuParams = append(config.qemuParams, config.VGA) - } -} - -func (config *Config) appendKernel() { - if config.Kernel.Path != "" { - config.qemuParams = append(config.qemuParams, "-kernel") - config.qemuParams = append(config.qemuParams, config.Kernel.Path) - - if config.Kernel.InitrdPath != "" { - config.qemuParams = append(config.qemuParams, "-initrd") - config.qemuParams = append(config.qemuParams, config.Kernel.InitrdPath) - } - - if config.Kernel.Params != "" { - config.qemuParams = append(config.qemuParams, "-append") - config.qemuParams = append(config.qemuParams, config.Kernel.Params) - } - } -} - -func (config *Config) appendMemoryKnobs() { - if config.Memory.Size == "" { - return - } - var objMemParam, numaMemParam string - dimmName := "dimm1" - if config.Knobs.HugePages { - objMemParam = "memory-backend-file,id=" + dimmName + ",size=" + config.Memory.Size + ",mem-path=/dev/hugepages" - numaMemParam = "node,memdev=" + dimmName - } else if config.Knobs.FileBackedMem && config.Memory.Path != "" { - objMemParam = "memory-backend-file,id=" + dimmName + ",size=" + config.Memory.Size + ",mem-path=" + config.Memory.Path - numaMemParam = "node,memdev=" + dimmName - } else { - objMemParam = "memory-backend-ram,id=" + dimmName + ",size=" + config.Memory.Size - numaMemParam = "node,memdev=" + dimmName - } - - if config.Knobs.MemShared { - objMemParam += ",share=on" - } - if config.Knobs.MemPrealloc { - objMemParam += ",prealloc=on" - } - config.qemuParams = append(config.qemuParams, "-object") - config.qemuParams = append(config.qemuParams, objMemParam) - - if isDimmSupported(config) { - config.qemuParams = append(config.qemuParams, "-numa") - config.qemuParams = append(config.qemuParams, numaMemParam) - } else { - config.qemuParams = append(config.qemuParams, "-machine") - config.qemuParams = append(config.qemuParams, "memory-backend="+dimmName) - } -} - -func (config *Config) appendKnobs() { - if config.Knobs.NoUserConfig { - config.qemuParams = append(config.qemuParams, "-no-user-config") - } - - if config.Knobs.NoDefaults { - config.qemuParams = append(config.qemuParams, "-nodefaults") - } - - if config.Knobs.NoGraphic { - config.qemuParams = append(config.qemuParams, "-nographic") - } - - if config.Knobs.NoReboot { - config.qemuParams = append(config.qemuParams, "--no-reboot") - } - - if config.Knobs.NoShutdown { - config.qemuParams = append(config.qemuParams, "--no-shutdown") - } - - if config.Knobs.Daemonize { - config.qemuParams = append(config.qemuParams, "-daemonize") - } - - config.appendMemoryKnobs() - - if config.Knobs.Mlock { - config.qemuParams = append(config.qemuParams, "-overcommit") - config.qemuParams = append(config.qemuParams, "mem-lock=on") - } - - if config.Knobs.Stopped { - config.qemuParams = append(config.qemuParams, "-S") - } -} - -func (config *Config) appendBios() { - if config.Bios != "" { - config.qemuParams = append(config.qemuParams, "-bios") - config.qemuParams = append(config.qemuParams, config.Bios) - } -} - -func (config *Config) appendIOThreads() { - for _, t := range config.IOThreads { - if t.ID != "" { - config.qemuParams = append(config.qemuParams, "-object") - config.qemuParams = append(config.qemuParams, fmt.Sprintf("iothread,id=%s", t.ID)) - } - } -} - -func (config *Config) appendIncoming() { - var uri string - switch config.Incoming.MigrationType { - case MigrationExec: - uri = fmt.Sprintf("exec:%s", config.Incoming.Exec) - case MigrationFD: - chFDs := config.appendFDs([]*os.File{config.Incoming.FD}) - uri = fmt.Sprintf("fd:%d", chFDs[0]) - case MigrationDefer: - uri = "defer" - default: - return - } - config.qemuParams = append(config.qemuParams, "-S", "-incoming", uri) -} - -func (config *Config) appendPidFile() { - if config.PidFile != "" { - config.qemuParams = append(config.qemuParams, "-pidfile") - config.qemuParams = append(config.qemuParams, config.PidFile) - } -} - -func (config *Config) appendLogFile() { - if config.LogFile != "" { - config.qemuParams = append(config.qemuParams, "-D") - config.qemuParams = append(config.qemuParams, config.LogFile) - } -} - -func (config *Config) appendFwCfg(logger QMPLog) { - if logger == nil { - logger = qmpNullLogger{} - } - - for _, f := range config.FwCfg { - if !f.Valid() { - logger.Errorf("fw_cfg is not valid: %+v", config.FwCfg) - continue - } - - config.qemuParams = append(config.qemuParams, f.QemuParams(config)...) - } -} - -// LaunchQemu can be used to launch a new qemu instance. -// -// The Config parameter contains a set of qemu parameters and settings. -// -// This function writes its log output via logger parameter. -// -// The function will block until the launched qemu process exits. "", nil -// will be returned if the launch succeeds. Otherwise a string containing -// the contents of stderr + a Go error object will be returned. -func LaunchQemu(config Config, logger QMPLog) (string, error) { - config.appendName() - config.appendUUID() - config.appendMachine() - config.appendCPUModel() - config.appendQMPSockets() - config.appendMemory() - config.appendDevices() - config.appendRTC() - config.appendGlobalParam() - config.appendPFlashParam() - config.appendVGA() - config.appendKnobs() - config.appendKernel() - config.appendBios() - config.appendIOThreads() - config.appendIncoming() - config.appendPidFile() - config.appendLogFile() - config.appendFwCfg(logger) - config.appendSeccompSandbox() - - if err := config.appendCPUs(); err != nil { - return "", err - } - - ctx := config.Ctx - if ctx == nil { - ctx = context.Background() - } - - attr := syscall.SysProcAttr{} - attr.Credential = &syscall.Credential{ - Uid: config.Uid, - Gid: config.Gid, - Groups: config.Groups, - } - - return LaunchCustomQemu(ctx, config.Path, config.qemuParams, - config.fds, &attr, logger) -} - -// LaunchCustomQemu can be used to launch a new qemu instance. -// -// The path parameter is used to pass the qemu executable path. -// -// params is a slice of options to pass to qemu-system-x86_64 and fds is a -// list of open file descriptors that are to be passed to the spawned qemu -// process. The attrs parameter can be used to control aspects of the -// newly created qemu process, such as the user and group under which it -// runs. It may be nil. -// -// This function writes its log output via logger parameter. -// -// The function will block until the launched qemu process exits. "", nil -// will be returned if the launch succeeds. Otherwise a string containing -// the contents of stderr + a Go error object will be returned. -func LaunchCustomQemu(ctx context.Context, path string, params []string, fds []*os.File, - attr *syscall.SysProcAttr, logger QMPLog) (string, error) { - if logger == nil { - logger = qmpNullLogger{} - } - - errStr := "" - - if path == "" { - path = "qemu-system-x86_64" - } - - /* #nosec */ - cmd := exec.CommandContext(ctx, path, params...) - if len(fds) > 0 { - logger.Infof("Adding extra file %v", fds) - cmd.ExtraFiles = fds - } - - cmd.SysProcAttr = attr - - var stderr bytes.Buffer - cmd.Stderr = &stderr - logger.Infof("launching %s with: %v", path, params) - - err := cmd.Run() - if err != nil { - logger.Errorf("Unable to launch %s: %v", path, err) - errStr = stderr.String() - logger.Errorf("%s", errStr) - } - return errStr, err -} diff --git a/src/runtime/vendor/github.com/kata-containers/govmm/qemu/qmp.go b/src/runtime/vendor/github.com/kata-containers/govmm/qemu/qmp.go deleted file mode 100644 index 2e30c2ba9..000000000 --- a/src/runtime/vendor/github.com/kata-containers/govmm/qemu/qmp.go +++ /dev/null @@ -1,1664 +0,0 @@ -/* -// Copyright contributors to the Virtual Machine Manager for Go project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ - -package qemu - -import ( - "bufio" - "container/list" - "encoding/json" - "errors" - "fmt" - "io" - "net" - "os" - "strconv" - "syscall" - "time" - - "context" - "strings" -) - -// QMPLog is a logging interface used by the qemu package to log various -// interesting pieces of information. Rather than introduce a dependency -// on a given logging package, qemu presents this interface that allows -// clients to provide their own logging type which they can use to -// seamlessly integrate qemu's logs into their own logs. A QMPLog -// implementation can be specified in the QMPConfig structure. -type QMPLog interface { - // V returns true if the given argument is less than or equal - // to the implementation's defined verbosity level. - V(int32) bool - - // Infof writes informational output to the log. A newline will be - // added to the output if one is not provided. - Infof(string, ...interface{}) - - // Warningf writes warning output to the log. A newline will be - // added to the output if one is not provided. - Warningf(string, ...interface{}) - - // Errorf writes error output to the log. A newline will be - // added to the output if one is not provided. - Errorf(string, ...interface{}) -} - -type qmpNullLogger struct{} - -func (l qmpNullLogger) V(level int32) bool { - return false -} - -func (l qmpNullLogger) Infof(format string, v ...interface{}) { -} - -func (l qmpNullLogger) Warningf(format string, v ...interface{}) { -} - -func (l qmpNullLogger) Errorf(format string, v ...interface{}) { -} - -// QMPConfig is a configuration structure that can be used to specify a -// logger and a channel to which logs and QMP events are to be sent. If -// neither of these fields are specified, or are set to nil, no logs will be -// written and no QMP events will be reported to the client. -type QMPConfig struct { - // eventCh can be specified by clients who wish to receive QMP - // events. - EventCh chan<- QMPEvent - - // logger is used by the qmpStart function and all the go routines - // it spawns to log information. - Logger QMPLog - - // specify the capacity of buffer used by receive QMP response. - MaxCapacity int -} - -type qmpEventFilter struct { - eventName string - dataKey string - dataValue string -} - -// QMPEvent contains a single QMP event, sent on the QMPConfig.EventCh channel. -type QMPEvent struct { - // The name of the event, e.g., DEVICE_DELETED - Name string - - // The data associated with the event. The contents of this map are - // unprocessed by the qemu package. It is simply the result of - // unmarshalling the QMP json event. Here's an example map - // map[string]interface{}{ - // "driver": "virtio-blk-pci", - // "drive": "drive_3437843748734873483", - // } - Data map[string]interface{} - - // The event's timestamp converted to a time.Time object. - Timestamp time.Time -} - -type qmpResult struct { - response interface{} - err error -} - -type qmpCommand struct { - ctx context.Context - res chan qmpResult - name string - args map[string]interface{} - filter *qmpEventFilter - resultReceived bool - oob []byte -} - -// QMP is a structure that contains the internal state used by startQMPLoop and -// the go routines it spwans. All the contents of this structure are private. -type QMP struct { - cmdCh chan qmpCommand - conn io.ReadWriteCloser - cfg QMPConfig - connectedCh chan<- *QMPVersion - disconnectedCh chan struct{} - version *QMPVersion -} - -// QMPVersion contains the version number and the capabailities of a QEMU -// instance, as reported in the QMP greeting message. -type QMPVersion struct { - Major int - Minor int - Micro int - Capabilities []string -} - -// CPUProperties contains the properties of a CPU instance -type CPUProperties struct { - Node int `json:"node-id"` - Socket int `json:"socket-id"` - Die int `json:"die-id"` - Core int `json:"core-id"` - Thread int `json:"thread-id"` -} - -// HotpluggableCPU represents a hotpluggable CPU -type HotpluggableCPU struct { - Type string `json:"type"` - VcpusCount int `json:"vcpus-count"` - Properties CPUProperties `json:"props"` - QOMPath string `json:"qom-path"` -} - -// MemoryDevicesData cotains the data describes a memory device -type MemoryDevicesData struct { - Slot int `json:"slot"` - Node int `json:"node"` - Addr uint64 `json:"addr"` - Memdev string `json:"memdev"` - ID string `json:"id"` - Hotpluggable bool `json:"hotpluggable"` - Hotplugged bool `json:"hotplugged"` - Size uint64 `json:"size"` -} - -// MemoryDevices represents memory devices of vm -type MemoryDevices struct { - Data MemoryDevicesData `json:"data"` - Type string `json:"type"` -} - -// CPUInfo represents information about each virtual CPU -type CPUInfo struct { - CPU int `json:"CPU"` - Current bool `json:"current"` - Halted bool `json:"halted"` - QomPath string `json:"qom_path"` - Arch string `json:"arch"` - Pc int `json:"pc"` - ThreadID int `json:"thread_id"` - Props CPUProperties `json:"props"` -} - -// CPUInfoFast represents information about each virtual CPU -type CPUInfoFast struct { - CPUIndex int `json:"cpu-index"` - QomPath string `json:"qom-path"` - Arch string `json:"arch"` - ThreadID int `json:"thread-id"` - Target string `json:"target"` - Props CPUProperties `json:"props"` -} - -// MigrationRAM represents migration ram status -type MigrationRAM struct { - Total int64 `json:"total"` - Remaining int64 `json:"remaining"` - Transferred int64 `json:"transferred"` - TotalTime int64 `json:"total-time"` - SetupTime int64 `json:"setup-time"` - ExpectedDowntime int64 `json:"expected-downtime"` - Duplicate int64 `json:"duplicate"` - Normal int64 `json:"normal"` - NormalBytes int64 `json:"normal-bytes"` - DirtySyncCount int64 `json:"dirty-sync-count"` -} - -// MigrationDisk represents migration disk status -type MigrationDisk struct { - Total int64 `json:"total"` - Remaining int64 `json:"remaining"` - Transferred int64 `json:"transferred"` -} - -// MigrationXbzrleCache represents migration XbzrleCache status -type MigrationXbzrleCache struct { - CacheSize int64 `json:"cache-size"` - Bytes int64 `json:"bytes"` - Pages int64 `json:"pages"` - CacheMiss int64 `json:"cache-miss"` - CacheMissRate int64 `json:"cache-miss-rate"` - Overflow int64 `json:"overflow"` -} - -// MigrationStatus represents migration status of a vm -type MigrationStatus struct { - Status string `json:"status"` - Capabilities []map[string]interface{} `json:"capabilities,omitempty"` - RAM MigrationRAM `json:"ram,omitempty"` - Disk MigrationDisk `json:"disk,omitempty"` - XbzrleCache MigrationXbzrleCache `json:"xbzrle-cache,omitempty"` -} - -// SchemaInfo represents all QMP wire ABI -type SchemaInfo struct { - MetaType string `json:"meta-type"` - Name string `json:"name"` -} - -// StatusInfo represents guest running status -type StatusInfo struct { - Running bool `json:"running"` - SingleStep bool `json:"singlestep"` - Status string `json:"status"` -} - -func (q *QMP) readLoop(fromVMCh chan<- []byte) { - scanner := bufio.NewScanner(q.conn) - if q.cfg.MaxCapacity > 0 { - buffer := make([]byte, q.cfg.MaxCapacity) - scanner.Buffer(buffer, q.cfg.MaxCapacity) - } - - for scanner.Scan() { - line := scanner.Bytes() - // Since []byte channel type transfer slice info(include slice underlying array pointer, len, cap) - // between channel sender and receiver. scanner.Bytes() returned slice's underlying array - // may point to data that will be overwritten by a subsequent call to Scan(reference from: - // https://golang.org/pkg/bufio/#Scanner.Bytes), which may make receiver read mixed data, - // so we need to copy line to new allocated space and then send to channel receiver - sendLine := make([]byte, len(line)) - copy(sendLine, line) - - fromVMCh <- sendLine - } - q.cfg.Logger.Infof("scanner return error: %v", scanner.Err()) - close(fromVMCh) -} - -func (q *QMP) processQMPEvent(cmdQueue *list.List, name interface{}, data interface{}, - timestamp interface{}) { - - strname, ok := name.(string) - if !ok { - return - } - - var eventData map[string]interface{} - if data != nil { - eventData, _ = data.(map[string]interface{}) - } - - cmdEl := cmdQueue.Front() - if cmdEl != nil { - cmd := cmdEl.Value.(*qmpCommand) - filter := cmd.filter - if filter != nil { - if filter.eventName == strname { - match := filter.dataKey == "" - if !match && eventData != nil { - match = eventData[filter.dataKey] == filter.dataValue - } - if match { - if cmd.resultReceived { - q.finaliseCommand(cmdEl, cmdQueue, true) - } else { - cmd.filter = nil - } - } - } - } - } - - if q.cfg.EventCh != nil { - ev := QMPEvent{ - Name: strname, - Data: eventData, - } - if timestamp != nil { - timestamp, ok := timestamp.(map[string]interface{}) - if ok { - seconds, _ := timestamp["seconds"].(float64) - microseconds, _ := timestamp["microseconds"].(float64) - ev.Timestamp = time.Unix(int64(seconds), int64(microseconds)) - } - } - - q.cfg.EventCh <- ev - } -} - -func (q *QMP) finaliseCommandWithResponse(cmdEl *list.Element, cmdQueue *list.List, succeeded bool, response interface{}) { - cmd := cmdEl.Value.(*qmpCommand) - cmdQueue.Remove(cmdEl) - select { - case <-cmd.ctx.Done(): - default: - if succeeded { - cmd.res <- qmpResult{response: response} - } else { - cmd.res <- qmpResult{err: fmt.Errorf("QMP command failed: %v", response)} - } - } - if cmdQueue.Len() > 0 { - q.writeNextQMPCommand(cmdQueue) - } -} - -func (q *QMP) finaliseCommand(cmdEl *list.Element, cmdQueue *list.List, succeeded bool) { - q.finaliseCommandWithResponse(cmdEl, cmdQueue, succeeded, nil) -} - -func (q *QMP) errorDesc(errorData interface{}) (string, error) { - // convert error to json - data, err := json.Marshal(errorData) - if err != nil { - return "", fmt.Errorf("unable to extract error information: %v", err) - } - - // see: https://github.com/qemu/qemu/blob/stable-2.12/qapi/qmp-dispatch.c#L125 - var qmpErr map[string]string - // convert json to qmpError - if err = json.Unmarshal(data, &qmpErr); err != nil { - return "", fmt.Errorf("unable to convert json to qmpError: %v", err) - } - - return qmpErr["desc"], nil -} - -func (q *QMP) processQMPInput(line []byte, cmdQueue *list.List) { - var vmData map[string]interface{} - err := json.Unmarshal(line, &vmData) - if err != nil { - q.cfg.Logger.Warningf("Unable to decode response [%s] from VM: %v", - string(line), err) - return - } - if evname, found := vmData["event"]; found { - q.processQMPEvent(cmdQueue, evname, vmData["data"], vmData["timestamp"]) - return - } - - response, succeeded := vmData["return"] - errData, failed := vmData["error"] - - if !succeeded && !failed { - return - } - - cmdEl := cmdQueue.Front() - if cmdEl == nil { - q.cfg.Logger.Warningf("Unexpected command response received [%s] from VM", - string(line)) - return - } - cmd := cmdEl.Value.(*qmpCommand) - if failed || cmd.filter == nil { - if errData != nil { - desc, err := q.errorDesc(errData) - if err != nil { - q.cfg.Logger.Infof("Get error description failed: %v", err) - } else { - response = desc - } - } - q.finaliseCommandWithResponse(cmdEl, cmdQueue, succeeded, response) - } else { - cmd.resultReceived = true - } -} - -func currentCommandDoneCh(cmdQueue *list.List) <-chan struct{} { - cmdEl := cmdQueue.Front() - if cmdEl == nil { - return nil - } - cmd := cmdEl.Value.(*qmpCommand) - return cmd.ctx.Done() -} - -func (q *QMP) writeNextQMPCommand(cmdQueue *list.List) { - cmdEl := cmdQueue.Front() - cmd := cmdEl.Value.(*qmpCommand) - cmdData := make(map[string]interface{}) - cmdData["execute"] = cmd.name - if cmd.args != nil { - cmdData["arguments"] = cmd.args - } - encodedCmd, err := json.Marshal(&cmdData) - if err != nil { - cmd.res <- qmpResult{ - err: fmt.Errorf("unable to marhsall command %s: %v", - cmd.name, err), - } - cmdQueue.Remove(cmdEl) - } - encodedCmd = append(encodedCmd, '\n') - if unixConn, ok := q.conn.(*net.UnixConn); ok && len(cmd.oob) > 0 { - _, _, err = unixConn.WriteMsgUnix(encodedCmd, cmd.oob, nil) - } else { - _, err = q.conn.Write(encodedCmd) - } - - if err != nil { - cmd.res <- qmpResult{ - err: fmt.Errorf("unable to write command to qmp socket %v", err), - } - cmdQueue.Remove(cmdEl) - } -} - -func failOutstandingCommands(cmdQueue *list.List) { - for e := cmdQueue.Front(); e != nil; e = e.Next() { - cmd := e.Value.(*qmpCommand) - select { - case cmd.res <- qmpResult{ - err: errors.New("exitting QMP loop, command cancelled"), - }: - case <-cmd.ctx.Done(): - } - } -} - -func (q *QMP) cancelCurrentCommand(cmdQueue *list.List) { - cmdEl := cmdQueue.Front() - cmd := cmdEl.Value.(*qmpCommand) - if cmd.resultReceived { - q.finaliseCommand(cmdEl, cmdQueue, false) - } else { - cmd.filter = nil - } -} - -func (q *QMP) parseVersion(version []byte) *QMPVersion { - var qmp map[string]interface{} - err := json.Unmarshal(version, &qmp) - if err != nil { - q.cfg.Logger.Errorf("Invalid QMP greeting: %s", string(version)) - return nil - } - - versionMap := qmp - for _, k := range []string{"QMP", "version", "qemu"} { - versionMap, _ = versionMap[k].(map[string]interface{}) - if versionMap == nil { - return nil - } - } - - micro, _ := versionMap["micro"].(float64) - minor, _ := versionMap["minor"].(float64) - major, _ := versionMap["major"].(float64) - capabilities, _ := qmp["QMP"].(map[string]interface{})["capabilities"].([]interface{}) - stringcaps := make([]string, 0, len(capabilities)) - for _, c := range capabilities { - if cap, ok := c.(string); ok { - stringcaps = append(stringcaps, cap) - } - } - return &QMPVersion{Major: int(major), - Minor: int(minor), - Micro: int(micro), - Capabilities: stringcaps, - } -} - -// The qemu package allows multiple QMP commands to be submitted concurrently -// from different Go routines. Unfortunately, QMP doesn't really support parallel -// commands as there is no way reliable way to associate a command response -// with a request. For this reason we need to submit our commands to -// QMP serially. The qemu package performs this serialisation using a -// queue (cmdQueue owned by mainLoop). We use a queue rather than a simple -// mutex so we can support cancelling of commands (see below) and ordered -// execution of commands, i.e., if command B is issued before command C, -// it should be executed before command C even if both commands are initially -// blocked waiting for command A to finish. This would be hard to achieve with -// a simple mutex. -// -// Cancelling is a little tricky. Commands such as ExecuteQMPCapabilities -// can be cancelled by cancelling or timing out their contexts. When a -// command is cancelled the calling function, e.g., ExecuteQMPCapabilities, -// will return but we may not be able to remove the command's entry from -// the command queue or issue the next command. There are two scenarios -// here. -// -// 1. The command has been processed by QMP, i.e., we have received a -// return or an error, but is still blocking as it is waiting for -// an event. For example, the ExecuteDeviceDel blocks until a DEVICE_DELETED -// event is received. When such a command is cancelled we can remove it -// from the queue and start issuing the next command. When the DEVICE_DELETED -// event eventually arrives it will just be ignored. -// -// 2. The command has not been processed by QMP. In this case the command -// needs to remain on the cmdQueue until the response to this command is -// received from QMP. During this time no new commands can be issued. When the -// response is received, it is discarded (as no one is interested in the result -// any more), the entry is removed from the cmdQueue and we can proceed to -// execute the next command. - -func (q *QMP) mainLoop() { - cmdQueue := list.New().Init() - fromVMCh := make(chan []byte) - go q.readLoop(fromVMCh) - - defer func() { - if q.cfg.EventCh != nil { - close(q.cfg.EventCh) - } - /* #nosec */ - _ = q.conn.Close() - <-fromVMCh - failOutstandingCommands(cmdQueue) - close(q.disconnectedCh) - }() - - var cmdDoneCh <-chan struct{} - var version *QMPVersion - ready := false - - for { - select { - case cmd, ok := <-q.cmdCh: - if !ok { - return - } - _ = cmdQueue.PushBack(&cmd) - - // We only want to execute the new cmd if QMP is - // ready and there are no other commands pending. - // If there are commands pending our new command - // will get run when the pending commands complete. - if ready && cmdQueue.Len() == 1 { - q.writeNextQMPCommand(cmdQueue) - cmdDoneCh = currentCommandDoneCh(cmdQueue) - } - - case line, ok := <-fromVMCh: - if !ok { - return - } - - if !ready { - // Not ready yet. Check if line is the QMP version. - // Sometimes QMP events are thrown before the QMP version, - // hence it's not a guarantee that the first data read from - // the channel is the QMP version. - version = q.parseVersion(line) - if version != nil { - q.connectedCh <- version - ready = true - } - // Do not process QMP input to avoid deadlocks. - break - } - - q.processQMPInput(line, cmdQueue) - cmdDoneCh = currentCommandDoneCh(cmdQueue) - - case <-cmdDoneCh: - q.cancelCurrentCommand(cmdQueue) - cmdDoneCh = currentCommandDoneCh(cmdQueue) - } - } -} - -func startQMPLoop(conn io.ReadWriteCloser, cfg QMPConfig, - connectedCh chan<- *QMPVersion, disconnectedCh chan struct{}) *QMP { - q := &QMP{ - cmdCh: make(chan qmpCommand), - conn: conn, - cfg: cfg, - connectedCh: connectedCh, - disconnectedCh: disconnectedCh, - } - go q.mainLoop() - return q -} - -func (q *QMP) executeCommandWithResponse(ctx context.Context, name string, args map[string]interface{}, - oob []byte, filter *qmpEventFilter) (interface{}, error) { - var err error - var response interface{} - resCh := make(chan qmpResult) - select { - case <-q.disconnectedCh: - err = errors.New("exitting QMP loop, command cancelled") - case q.cmdCh <- qmpCommand{ - ctx: ctx, - res: resCh, - name: name, - args: args, - filter: filter, - oob: oob, - }: - } - - if err != nil { - return response, err - } - - select { - case res := <-resCh: - err = res.err - response = res.response - case <-ctx.Done(): - err = ctx.Err() - } - - return response, err -} - -func (q *QMP) executeCommand(ctx context.Context, name string, args map[string]interface{}, - filter *qmpEventFilter) error { - - _, err := q.executeCommandWithResponse(ctx, name, args, nil, filter) - return err -} - -// QMPStart connects to a unix domain socket maintained by a QMP instance. It -// waits to receive the QMP welcome message via the socket and spawns some go -// routines to manage the socket. The function returns a *QMP which can be -// used by callers to send commands to the QEMU instance or to close the -// socket and all the go routines that have been spawned to monitor it. A -// *QMPVersion is also returned. This structure contains the version and -// capabilities information returned by the QEMU instance in its welcome -// message. -// -// socket contains the path to the domain socket. cfg contains some options -// that can be specified by the caller, namely where the qemu package should -// send logs and QMP events. disconnectedCh is a channel that must be supplied -// by the caller. It is closed when an error occurs openning or writing to -// or reading from the unix domain socket. This implies that the QEMU instance -// that opened the socket has closed. -// -// If this function returns without error, callers should call QMP.Shutdown -// when they wish to stop monitoring the QMP instance. This is not strictly -// necessary if the QEMU instance exits and the disconnectedCh is closed, but -// doing so will not cause any problems. -// -// Commands can be sent to the QEMU instance via the QMP.Execute methods. -// These commands are executed serially, even if the QMP.Execute methods -// are called from different go routines. The QMP.Execute methods will -// block until they have received a success or failure message from QMP, -// i.e., {"return": {}} or {"error":{}}, and in some cases certain events -// are received. -// -// QEMU currently requires that the "qmp_capabilties" command is sent before any -// other command. Therefore you must call qmp.ExecuteQMPCapabilities() before -// you execute any other command. -func QMPStart(ctx context.Context, socket string, cfg QMPConfig, disconnectedCh chan struct{}) (*QMP, *QMPVersion, error) { - if cfg.Logger == nil { - cfg.Logger = qmpNullLogger{} - } - dialer := net.Dialer{Cancel: ctx.Done()} - conn, err := dialer.Dial("unix", socket) - if err != nil { - cfg.Logger.Warningf("Unable to connect to unix socket (%s): %v", socket, err) - close(disconnectedCh) - return nil, nil, err - } - - connectedCh := make(chan *QMPVersion) - - q := startQMPLoop(conn, cfg, connectedCh, disconnectedCh) - select { - case <-ctx.Done(): - q.Shutdown() - <-disconnectedCh - return nil, nil, fmt.Errorf("canceled by caller") - case <-disconnectedCh: - return nil, nil, fmt.Errorf("lost connection to VM") - case q.version = <-connectedCh: - if q.version == nil { - return nil, nil, fmt.Errorf("failed to find QMP version information") - } - } - - if q.version.Major < 5 { - return nil, nil, fmt.Errorf("govmm requires qemu version 5.0 or later, this is qemu (%d.%d)", q.version.Major, q.version.Minor) - } - - return q, q.version, nil -} - -// Shutdown closes the domain socket used to monitor a QEMU instance and -// terminates all the go routines spawned by QMPStart to manage that instance. -// QMP.Shutdown does not shut down the running instance. Calling QMP.Shutdown -// will result in the disconnectedCh channel being closed, indicating that we -// have lost connection to the QMP instance. In this case it does not indicate -// that the instance has quit. -// -// QMP.Shutdown should not be called concurrently with other QMP methods. It -// should not be called twice on the same QMP instance. -// -// Calling QMP.Shutdown after the disconnectedCh channel is closed is permitted but -// will not have any effect. -func (q *QMP) Shutdown() { - close(q.cmdCh) -} - -// ExecuteQMPCapabilities executes the qmp_capabilities command on the instance. -func (q *QMP) ExecuteQMPCapabilities(ctx context.Context) error { - return q.executeCommand(ctx, "qmp_capabilities", nil, nil) -} - -// ExecuteStop sends the stop command to the instance. -func (q *QMP) ExecuteStop(ctx context.Context) error { - return q.executeCommand(ctx, "stop", nil, nil) -} - -// ExecuteCont sends the cont command to the instance. -func (q *QMP) ExecuteCont(ctx context.Context) error { - return q.executeCommand(ctx, "cont", nil, nil) -} - -// ExecuteSystemPowerdown sends the system_powerdown command to the instance. -// This function will block until the SHUTDOWN event is received. -func (q *QMP) ExecuteSystemPowerdown(ctx context.Context) error { - filter := &qmpEventFilter{ - eventName: "POWERDOWN", - } - return q.executeCommand(ctx, "system_powerdown", nil, filter) -} - -// ExecuteQuit sends the quit command to the instance, terminating -// the QMP instance immediately. -func (q *QMP) ExecuteQuit(ctx context.Context) error { - return q.executeCommand(ctx, "quit", nil, nil) -} - -func (q *QMP) blockdevAddBaseArgs(driver, device, blockdevID string, ro bool) (map[string]interface{}, map[string]interface{}) { - var args map[string]interface{} - - blockdevArgs := map[string]interface{}{ - "driver": "raw", - "read-only": ro, - "file": map[string]interface{}{ - "driver": driver, - "filename": device, - }, - } - - blockdevArgs["node-name"] = blockdevID - args = blockdevArgs - - return args, blockdevArgs -} - -// ExecuteBlockdevAdd sends a blockdev-add to the QEMU instance. device is the -// path of the device to add, e.g., /dev/rdb0, and blockdevID is an identifier -// used to name the device. As this identifier will be passed directly to QMP, -// it must obey QMP's naming rules, e,g., it must start with a letter. -func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string, ro bool) error { - args, _ := q.blockdevAddBaseArgs("host_device", device, blockdevID, ro) - - return q.executeCommand(ctx, "blockdev-add", args, nil) -} - -// ExecuteBlockdevAddWithCache has two more parameters direct and noFlush -// than ExecuteBlockdevAdd. -// They are cache-related options for block devices that are described in -// https://github.com/qemu/qemu/blob/master/qapi/block-core.json. -// direct denotes whether use of O_DIRECT (bypass the host page cache) -// is enabled. noFlush denotes whether flush requests for the device are -// ignored. -func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, device, blockdevID string, direct, noFlush, ro bool) error { - args, blockdevArgs := q.blockdevAddBaseArgs("host_device", device, blockdevID, ro) - - blockdevArgs["cache"] = map[string]interface{}{ - "direct": direct, - "no-flush": noFlush, - } - - return q.executeCommand(ctx, "blockdev-add", args, nil) -} - -// ExecuteBlockdevAddWithDriverCache has three one parameter driver -// than ExecuteBlockdevAddWithCache. -// Parameter driver can set the driver of block device. -func (q *QMP) ExecuteBlockdevAddWithDriverCache(ctx context.Context, driver, device, blockdevID string, direct, noFlush, ro bool) error { - args, blockdevArgs := q.blockdevAddBaseArgs(driver, device, blockdevID, ro) - - blockdevArgs["cache"] = map[string]interface{}{ - "direct": direct, - "no-flush": noFlush, - } - - return q.executeCommand(ctx, "blockdev-add", args, nil) -} - -// ExecuteDeviceAdd adds the guest portion of a device to a QEMU instance -// using the device_add command. blockdevID should match the blockdevID passed -// to a previous call to ExecuteBlockdevAdd. devID is the id of the device to -// add. Both strings must be valid QMP identifiers. driver is the name of the -// driver,e.g., virtio-blk-pci, and bus is the name of the bus. bus is optional. -// shared denotes if the drive can be shared allowing it to be passed more than once. -// disableModern indicates if virtio version 1.0 should be replaced by the -// former version 0.9, as there is a KVM bug that occurs when using virtio -// 1.0 in nested environments. -func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, shared, disableModern bool) error { - args := map[string]interface{}{ - "id": devID, - "driver": driver, - "drive": blockdevID, - } - - var transport VirtioTransport - - if transport.isVirtioCCW(nil) { - args["devno"] = bus - } else if bus != "" { - args["bus"] = bus - } - - if shared { - args["share-rw"] = "on" - } - if transport.isVirtioPCI(nil) { - args["romfile"] = romfile - - if disableModern { - args["disable-modern"] = disableModern - } - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteSCSIDeviceAdd adds the guest portion of a block device to a QEMU instance -// using a SCSI driver with the device_add command. blockdevID should match the -// blockdevID passed to a previous call to ExecuteBlockdevAdd. devID is the id of -// the device to add. Both strings must be valid QMP identifiers. driver is the name of the -// scsi driver,e.g., scsi-hd, and bus is the name of a SCSI controller bus. -// scsiID is the SCSI id, lun is logical unit number. scsiID and lun are optional, a negative value -// for scsiID and lun is ignored. shared denotes if the drive can be shared allowing it -// to be passed more than once. -// disableModern indicates if virtio version 1.0 should be replaced by the -// former version 0.9, as there is a KVM bug that occurs when using virtio -// 1.0 in nested environments. -func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, scsiID, lun int, shared, disableModern bool) error { - // TBD: Add drivers for scsi passthrough like scsi-generic and scsi-block - drivers := []string{"scsi-hd", "scsi-cd", "scsi-disk"} - - isSCSIDriver := false - for _, d := range drivers { - if driver == d { - isSCSIDriver = true - break - } - } - - if !isSCSIDriver { - return fmt.Errorf("invalid SCSI driver provided %s", driver) - } - - args := map[string]interface{}{ - "id": devID, - "driver": driver, - "drive": blockdevID, - "bus": bus, - } - - if scsiID >= 0 { - args["scsi-id"] = scsiID - } - if lun >= 0 { - args["lun"] = lun - } - if shared { - args["share-rw"] = "on" - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteBlockdevDel deletes a block device by sending blockdev-del -// command. blockdevID is the id of the block device to be deleted. -// Typically, this will match the id passed to ExecuteBlockdevAdd. It -// must be a valid QMP id. -func (q *QMP) ExecuteBlockdevDel(ctx context.Context, blockdevID string) error { - args := map[string]interface{}{} - - args["node-name"] = blockdevID - return q.executeCommand(ctx, "blockdev-del", args, nil) -} - -// ExecuteChardevDel deletes a char device by sending a chardev-remove command. -// chardevID is the id of the char device to be deleted. Typically, this will -// match the id passed to ExecuteCharDevUnixSocketAdd. It must be a valid QMP id. -func (q *QMP) ExecuteChardevDel(ctx context.Context, chardevID string) error { - args := map[string]interface{}{ - "id": chardevID, - } - - return q.executeCommand(ctx, "chardev-remove", args, nil) -} - -// ExecuteNetdevAdd adds a Net device to a QEMU instance -// using the netdev_add command. netdevID is the id of the device to add. -// Must be valid QMP identifier. -func (q *QMP) ExecuteNetdevAdd(ctx context.Context, netdevType, netdevID, ifname, downscript, script string, queues int) error { - args := map[string]interface{}{ - "type": netdevType, - "id": netdevID, - "ifname": ifname, - "downscript": downscript, - "script": script, - } - if queues > 1 { - args["queues"] = queues - } - - return q.executeCommand(ctx, "netdev_add", args, nil) -} - -// ExecuteNetdevChardevAdd adds a Net device to a QEMU instance -// using the netdev_add command. netdevID is the id of the device to add. -// Must be valid QMP identifier. -func (q *QMP) ExecuteNetdevChardevAdd(ctx context.Context, netdevType, netdevID, chardev string, queues int) error { - args := map[string]interface{}{ - "type": netdevType, - "id": netdevID, - "chardev": chardev, - } - if queues > 1 { - args["queues"] = queues - } - - return q.executeCommand(ctx, "netdev_add", args, nil) -} - -// ExecuteNetdevAddByFds adds a Net device to a QEMU instance -// using the netdev_add command by fds and vhostfds. netdevID is the id of the device to add. -// Must be valid QMP identifier. -func (q *QMP) ExecuteNetdevAddByFds(ctx context.Context, netdevType, netdevID string, fdNames, vhostFdNames []string) error { - fdNameStr := strings.Join(fdNames, ":") - args := map[string]interface{}{ - "type": netdevType, - "id": netdevID, - "fds": fdNameStr, - } - if len(vhostFdNames) > 0 { - vhostFdNameStr := strings.Join(vhostFdNames, ":") - args["vhost"] = true - args["vhostfds"] = vhostFdNameStr - } - - return q.executeCommand(ctx, "netdev_add", args, nil) -} - -// ExecuteNetdevDel deletes a Net device from a QEMU instance -// using the netdev_del command. netdevID is the id of the device to delete. -func (q *QMP) ExecuteNetdevDel(ctx context.Context, netdevID string) error { - args := map[string]interface{}{ - "id": netdevID, - } - return q.executeCommand(ctx, "netdev_del", args, nil) -} - -// ExecuteNetPCIDeviceAdd adds a Net PCI device to a QEMU instance -// using the device_add command. devID is the id of the device to add. -// Must be valid QMP identifier. netdevID is the id of nic added by previous netdev_add. -// queues is the number of queues of a nic. -// disableModern indicates if virtio version 1.0 should be replaced by the -// former version 0.9, as there is a KVM bug that occurs when using virtio -// 1.0 in nested environments. -func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAddr, addr, bus, romfile string, queues int, disableModern bool) error { - args := map[string]interface{}{ - "id": devID, - "driver": VirtioNetPCI, - "romfile": romfile, - } - - if bus != "" { - args["bus"] = bus - } - if addr != "" { - args["addr"] = addr - } - if macAddr != "" { - args["mac"] = macAddr - } - if netdevID != "" { - args["netdev"] = netdevID - } - if disableModern { - args["disable-modern"] = disableModern - } - - if queues > 0 { - // (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq) - // -device virtio-net-pci,mq=on,vectors=2N+2... - // enable mq in guest by 'ethtool -L eth0 combined $queue_num' - // Clearlinux automatically sets up the queues properly - // The agent implementation should do this to ensure that it is - // always set - args["mq"] = "on" - args["vectors"] = 2*queues + 2 - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteNetCCWDeviceAdd adds a Net CCW device to a QEMU instance -// using the device_add command. devID is the id of the device to add. -// Must be valid QMP identifier. netdevID is the id of nic added by previous netdev_add. -// queues is the number of queues of a nic. -func (q *QMP) ExecuteNetCCWDeviceAdd(ctx context.Context, netdevID, devID, macAddr, bus string, queues int) error { - args := map[string]interface{}{ - "id": devID, - "driver": VirtioNetCCW, - "netdev": netdevID, - "mac": macAddr, - "devno": bus, - } - - if queues > 0 { - args["mq"] = "on" - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteDeviceDel deletes guest portion of a QEMU device by sending a -// device_del command. devId is the identifier of the device to delete. -// Typically it would match the devID parameter passed to an earlier call -// to ExecuteDeviceAdd. It must be a valid QMP identidier. -// -// This method blocks until a DEVICE_DELETED event is received for devID. -func (q *QMP) ExecuteDeviceDel(ctx context.Context, devID string) error { - args := map[string]interface{}{ - "id": devID, - } - filter := &qmpEventFilter{ - eventName: "DEVICE_DELETED", - dataKey: "device", - dataValue: devID, - } - return q.executeCommand(ctx, "device_del", args, filter) -} - -// ExecutePCIDeviceAdd is the PCI version of ExecuteDeviceAdd. This function can be used -// to hot plug PCI devices on PCI(E) bridges, unlike ExecuteDeviceAdd this function receive the -// device address on its parent bus. bus is optional. queues specifies the number of queues of -// a block device. shared denotes if the drive can be shared allowing it to be passed more than once. -// disableModern indicates if virtio version 1.0 should be replaced by the -// former version 0.9, as there is a KVM bug that occurs when using virtio -// 1.0 in nested environments. -func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver, addr, bus, romfile string, queues int, shared, disableModern bool) error { - args := map[string]interface{}{ - "id": devID, - "driver": driver, - "drive": blockdevID, - "addr": addr, - } - if bus != "" { - args["bus"] = bus - } - if shared { - args["share-rw"] = "on" - } - if queues > 0 { - args["num-queues"] = strconv.Itoa(queues) - } - - var transport VirtioTransport - - if transport.isVirtioPCI(nil) { - args["romfile"] = romfile - - if disableModern { - args["disable-modern"] = disableModern - } - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecutePCIVhostUserDevAdd adds a vhost-user device to a QEMU instance using the device_add command. -// This function can be used to hot plug vhost-user devices on PCI(E) bridges. -// It receives the bus and the device address on its parent bus. bus is optional. -// devID is the id of the device to add.Must be valid QMP identifier. chardevID -// is the QMP identifier of character device using a unix socket as backend. -// driver is the name of vhost-user driver, like vhost-user-blk-pci. -func (q *QMP) ExecutePCIVhostUserDevAdd(ctx context.Context, driver, devID, chardevID, addr, bus string) error { - args := map[string]interface{}{ - "driver": driver, - "id": devID, - "chardev": chardevID, - "addr": addr, - } - - if bus != "" { - args["bus"] = bus - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteVFIODeviceAdd adds a VFIO device to a QEMU instance using the device_add command. -// devID is the id of the device to add. Must be valid QMP identifier. -// bdf is the PCI bus-device-function of the pci device. -// bus is optional. When hot plugging a PCIe device, the bus can be the ID of the pcie-root-port. -func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, bus, romfile string) error { - var driver string - var transport VirtioTransport - - if transport.isVirtioCCW(nil) { - driver = string(VfioCCW) - } else { - driver = string(VfioPCI) - } - - args := map[string]interface{}{ - "id": devID, - "driver": driver, - "host": bdf, - "romfile": romfile, - } - if bus != "" { - args["bus"] = bus - } - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecutePCIVFIODeviceAdd adds a VFIO device to a QEMU instance using the device_add command. -// This function can be used to hot plug VFIO devices on PCI(E) bridges, unlike -// ExecuteVFIODeviceAdd this function receives the bus and the device address on its parent bus. -// bus is optional. devID is the id of the device to add.Must be valid QMP identifier. bdf is the -// PCI bus-device-function of the pci device. -func (q *QMP) ExecutePCIVFIODeviceAdd(ctx context.Context, devID, bdf, addr, bus, romfile string) error { - args := map[string]interface{}{ - "id": devID, - "driver": VfioPCI, - "host": bdf, - "addr": addr, - "romfile": romfile, - } - - if bus != "" { - args["bus"] = bus - } - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecutePCIVFIOMediatedDeviceAdd adds a VFIO mediated device to a QEMU instance using the device_add command. -// This function can be used to hot plug VFIO mediated devices on PCI(E) bridges or root bus, unlike -// ExecuteVFIODeviceAdd this function receives the bus and the device address on its parent bus. -// devID is the id of the device to add. Must be valid QMP identifier. sysfsdev is the VFIO mediated device. -// Both bus and addr are optional. If they are both set to be empty, the system will pick up an empty slot on root bus. -func (q *QMP) ExecutePCIVFIOMediatedDeviceAdd(ctx context.Context, devID, sysfsdev, addr, bus, romfile string) error { - args := map[string]interface{}{ - "id": devID, - "driver": VfioPCI, - "sysfsdev": sysfsdev, - "romfile": romfile, - } - - if bus != "" { - args["bus"] = bus - } - if addr != "" { - args["addr"] = addr - } - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteAPVFIOMediatedDeviceAdd adds a VFIO mediated AP device to a QEMU instance using the device_add command. -func (q *QMP) ExecuteAPVFIOMediatedDeviceAdd(ctx context.Context, sysfsdev string) error { - args := map[string]interface{}{ - "driver": VfioAP, - "sysfsdev": sysfsdev, - } - return q.executeCommand(ctx, "device_add", args, nil) -} - -// isSocketIDSupported returns if the cpu driver supports the socket id option -func isSocketIDSupported(driver string) bool { - if driver == "host-s390x-cpu" || driver == "host-powerpc64-cpu" { - return false - } - return true -} - -// isThreadIDSupported returns if the cpu driver supports the thread id option -func isThreadIDSupported(driver string) bool { - if driver == "host-s390x-cpu" || driver == "host-powerpc64-cpu" { - return false - } - return true -} - -// isDieIDSupported returns if the cpu driver and the qemu version support the die id option -func (q *QMP) isDieIDSupported(driver string) bool { - return driver == "host-x86_64-cpu" -} - -// ExecuteCPUDeviceAdd adds a CPU to a QEMU instance using the device_add command. -// driver is the CPU model, cpuID must be a unique ID to identify the CPU, socketID is the socket number within -// node/board the CPU belongs to, coreID is the core number within socket the CPU belongs to, threadID is the -// thread number within core the CPU belongs to. Note that socketID and threadID are not a requirement for -// architecures like ppc64le. -func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID, dieID, coreID, threadID, romfile string) error { - args := map[string]interface{}{ - "driver": driver, - "id": cpuID, - "core-id": coreID, - } - - if socketID != "" && isSocketIDSupported(driver) { - args["socket-id"] = socketID - } - - if threadID != "" && isThreadIDSupported(driver) { - args["thread-id"] = threadID - } - - if q.isDieIDSupported(driver) { - if dieID != "" { - args["die-id"] = dieID - } - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteQueryHotpluggableCPUs returns a slice with the list of hotpluggable CPUs -func (q *QMP) ExecuteQueryHotpluggableCPUs(ctx context.Context) ([]HotpluggableCPU, error) { - response, err := q.executeCommandWithResponse(ctx, "query-hotpluggable-cpus", nil, nil, nil) - if err != nil { - return nil, err - } - - // convert response to json - data, err := json.Marshal(response) - if err != nil { - return nil, fmt.Errorf("unable to extract CPU information: %v", err) - } - - var cpus []HotpluggableCPU - // convert json to []HotpluggableCPU - if err = json.Unmarshal(data, &cpus); err != nil { - return nil, fmt.Errorf("unable to convert json to hotpluggable CPU: %v", err) - } - - return cpus, nil -} - -// ExecSetMigrationCaps sets migration capabilities -func (q *QMP) ExecSetMigrationCaps(ctx context.Context, caps []map[string]interface{}) error { - args := map[string]interface{}{ - "capabilities": caps, - } - - return q.executeCommand(ctx, "migrate-set-capabilities", args, nil) -} - -// ExecSetMigrateArguments sets the command line used for migration -func (q *QMP) ExecSetMigrateArguments(ctx context.Context, url string) error { - args := map[string]interface{}{ - "uri": url, - } - - return q.executeCommand(ctx, "migrate", args, nil) -} - -// ExecQueryMemoryDevices returns a slice with the list of memory devices -func (q *QMP) ExecQueryMemoryDevices(ctx context.Context) ([]MemoryDevices, error) { - response, err := q.executeCommandWithResponse(ctx, "query-memory-devices", nil, nil, nil) - if err != nil { - return nil, err - } - - // convert response to json - data, err := json.Marshal(response) - if err != nil { - return nil, fmt.Errorf("unable to extract memory devices information: %v", err) - } - - var memoryDevices []MemoryDevices - // convert json to []MemoryDevices - if err = json.Unmarshal(data, &memoryDevices); err != nil { - return nil, fmt.Errorf("unable to convert json to memory devices: %v", err) - } - - return memoryDevices, nil -} - -// ExecQueryCpus returns a slice with the list of `CpuInfo` -// Since qemu 2.12, we have `query-cpus-fast` as a better choice in production -// we can still choose `ExecQueryCpus` for compatibility though not recommended. -func (q *QMP) ExecQueryCpus(ctx context.Context) ([]CPUInfo, error) { - response, err := q.executeCommandWithResponse(ctx, "query-cpus", nil, nil, nil) - if err != nil { - return nil, err - } - - // convert response to json - data, err := json.Marshal(response) - if err != nil { - return nil, fmt.Errorf("unable to extract memory devices information: %v", err) - } - - var cpuInfo []CPUInfo - // convert json to []CPUInfo - if err = json.Unmarshal(data, &cpuInfo); err != nil { - return nil, fmt.Errorf("unable to convert json to CPUInfo: %v", err) - } - - return cpuInfo, nil -} - -// ExecQueryCpusFast returns a slice with the list of `CpuInfoFast` -// This is introduced since 2.12, it does not incur a performance penalty and -// should be used in production instead of query-cpus. -func (q *QMP) ExecQueryCpusFast(ctx context.Context) ([]CPUInfoFast, error) { - response, err := q.executeCommandWithResponse(ctx, "query-cpus-fast", nil, nil, nil) - if err != nil { - return nil, err - } - - // convert response to json - data, err := json.Marshal(response) - if err != nil { - return nil, fmt.Errorf("unable to extract memory devices information: %v", err) - } - - var cpuInfoFast []CPUInfoFast - // convert json to []CPUInfoFast - if err = json.Unmarshal(data, &cpuInfoFast); err != nil { - return nil, fmt.Errorf("unable to convert json to CPUInfoFast: %v", err) - } - - return cpuInfoFast, nil -} - -// ExecMemdevAdd adds size of MiB memory device to the guest -func (q *QMP) ExecMemdevAdd(ctx context.Context, qomtype, id, mempath string, size int, share bool, driver, driverID, addr, bus string) error { - args := map[string]interface{}{ - "qom-type": qomtype, - "id": id, - "size": uint64(size) << 20, - } - if mempath != "" { - args["mem-path"] = mempath - } - if share { - args["share"] = true - } - err := q.executeCommand(ctx, "object-add", args, nil) - if err != nil { - return err - } - - defer func() { - if err != nil { - q.cfg.Logger.Errorf("Unable to add memory device %s: %v", id, err) - err = q.executeCommand(ctx, "object-del", map[string]interface{}{"id": id}, nil) - if err != nil { - q.cfg.Logger.Warningf("Unable to clean up memory object %s: %v", id, err) - } - } - }() - - args = map[string]interface{}{ - "driver": driver, - "id": driverID, - "memdev": id, - } - - if bus != "" { - args["bus"] = bus - } - if addr != "" { - args["addr"] = addr - } - - err = q.executeCommand(ctx, "device_add", args, nil) - - return err -} - -// ExecHotplugMemory adds size of MiB memory to the guest -func (q *QMP) ExecHotplugMemory(ctx context.Context, qomtype, id, mempath string, size int, share bool) error { - return q.ExecMemdevAdd(ctx, qomtype, id, mempath, size, share, "pc-dimm", "dimm"+id, "", "") -} - -// ExecuteNVDIMMDeviceAdd adds a block device to a QEMU instance using -// a NVDIMM driver with the device_add command. -// id is the id of the device to add. It must be a valid QMP identifier. -// mempath is the path of the device to add, e.g., /dev/rdb0. size is -// the data size of the device. pmem is to guarantee the persistence of QEMU writes -// to the vNVDIMM backend. -func (q *QMP) ExecuteNVDIMMDeviceAdd(ctx context.Context, id, mempath string, size int64, pmem *bool) error { - args := map[string]interface{}{ - "qom-type": "memory-backend-file", - "id": "nvdimmbackmem" + id, - "mem-path": mempath, - "size": size, - "share": true, - } - - if pmem != nil { - args["pmem"] = *pmem - } - - err := q.executeCommand(ctx, "object-add", args, nil) - if err != nil { - return err - } - - args = map[string]interface{}{ - "driver": "nvdimm", - "id": "nvdimm" + id, - "memdev": "nvdimmbackmem" + id, - } - if err = q.executeCommand(ctx, "device_add", args, nil); err != nil { - q.cfg.Logger.Errorf("Unable to hotplug NVDIMM device: %v", err) - err2 := q.executeCommand(ctx, "object-del", map[string]interface{}{"id": "nvdimmbackmem" + id}, nil) - if err2 != nil { - q.cfg.Logger.Warningf("Unable to clean up memory object: %v", err2) - } - } - - return err -} - -// ExecuteBalloon sets the size of the balloon, hence updates the memory -// allocated for the VM. -func (q *QMP) ExecuteBalloon(ctx context.Context, bytes uint64) error { - args := map[string]interface{}{ - "value": bytes, - } - return q.executeCommand(ctx, "balloon", args, nil) -} - -// ExecutePCIVSockAdd adds a vhost-vsock-pci bus -// disableModern indicates if virtio version 1.0 should be replaced by the -// former version 0.9, as there is a KVM bug that occurs when using virtio -// 1.0 in nested environments. -func (q *QMP) ExecutePCIVSockAdd(ctx context.Context, id, guestCID, vhostfd, addr, bus, romfile string, disableModern bool) error { - args := map[string]interface{}{ - "driver": VHostVSockPCI, - "id": id, - "guest-cid": guestCID, - "vhostfd": vhostfd, - "addr": addr, - "romfile": romfile, - } - - if bus != "" { - args["bus"] = bus - } - - if disableModern { - args["disable-modern"] = disableModern - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteGetFD sends a file descriptor via SCM rights and assigns it a name -func (q *QMP) ExecuteGetFD(ctx context.Context, fdname string, fd *os.File) error { - oob := syscall.UnixRights(int(fd.Fd())) - args := map[string]interface{}{ - "fdname": fdname, - } - - _, err := q.executeCommandWithResponse(ctx, "getfd", args, oob, nil) - return err -} - -// ExecuteCharDevUnixSocketAdd adds a character device using as backend a unix socket, -// id is an identifier for the device, path specifies the local path of the unix socket, -// wait is to block waiting for a client to connect, server specifies that the socket is a listening socket. -func (q *QMP) ExecuteCharDevUnixSocketAdd(ctx context.Context, id, path string, wait, server bool) error { - data := map[string]interface{}{ - "server": server, - "addr": map[string]interface{}{ - "type": "unix", - "data": map[string]interface{}{ - "path": path, - }, - }, - } - - // wait is only valid for server mode - if server { - data["wait"] = wait - } - - args := map[string]interface{}{ - "id": id, - "backend": map[string]interface{}{ - "type": "socket", - "data": data, - }, - } - return q.executeCommand(ctx, "chardev-add", args, nil) -} - -// ExecuteVirtSerialPortAdd adds a virtserialport. -// id is an identifier for the virtserialport, name is a name for the virtserialport and -// it will be visible in the VM, chardev is the character device id previously added. -func (q *QMP) ExecuteVirtSerialPortAdd(ctx context.Context, id, name, chardev string) error { - args := map[string]interface{}{ - "driver": VirtioSerialPort, - "id": id, - "name": name, - "chardev": chardev, - } - - return q.executeCommand(ctx, "device_add", args, nil) -} - -// ExecuteQueryMigration queries migration progress. -func (q *QMP) ExecuteQueryMigration(ctx context.Context) (MigrationStatus, error) { - response, err := q.executeCommandWithResponse(ctx, "query-migrate", nil, nil, nil) - if err != nil { - return MigrationStatus{}, err - } - - data, err := json.Marshal(response) - if err != nil { - return MigrationStatus{}, fmt.Errorf("unable to extract migrate status information: %v", err) - } - - var status MigrationStatus - if err = json.Unmarshal(data, &status); err != nil { - return MigrationStatus{}, fmt.Errorf("unable to convert migrate status information: %v", err) - } - - return status, nil -} - -// ExecuteMigrationIncoming start migration from incoming uri. -func (q *QMP) ExecuteMigrationIncoming(ctx context.Context, uri string) error { - args := map[string]interface{}{ - "uri": uri, - } - return q.executeCommand(ctx, "migrate-incoming", args, nil) -} - -// ExecQueryQmpSchema query all QMP wire ABI and returns a slice -func (q *QMP) ExecQueryQmpSchema(ctx context.Context) ([]SchemaInfo, error) { - response, err := q.executeCommandWithResponse(ctx, "query-qmp-schema", nil, nil, nil) - if err != nil { - return nil, err - } - - // convert response to json - data, err := json.Marshal(response) - if err != nil { - return nil, fmt.Errorf("unable to extract memory devices information: %v", err) - } - - var schemaInfo []SchemaInfo - if err = json.Unmarshal(data, &schemaInfo); err != nil { - return nil, fmt.Errorf("unable to convert json to schemaInfo: %v", err) - } - - return schemaInfo, nil -} - -// ExecuteQueryStatus queries guest status -func (q *QMP) ExecuteQueryStatus(ctx context.Context) (StatusInfo, error) { - response, err := q.executeCommandWithResponse(ctx, "query-status", nil, nil, nil) - if err != nil { - return StatusInfo{}, err - } - - data, err := json.Marshal(response) - if err != nil { - return StatusInfo{}, fmt.Errorf("unable to extract migrate status information: %v", err) - } - - var status StatusInfo - if err = json.Unmarshal(data, &status); err != nil { - return StatusInfo{}, fmt.Errorf("unable to convert migrate status information: %v", err) - } - - return status, nil -} - -// ExecQomSet qom-set path property value -func (q *QMP) ExecQomSet(ctx context.Context, path, property string, value uint64) error { - args := map[string]interface{}{ - "path": path, - "property": property, - "value": value, - } - - return q.executeCommand(ctx, "qom-set", args, nil) -} - -// ExecQomGet qom-get path property -func (q *QMP) ExecQomGet(ctx context.Context, path, property string) (interface{}, error) { - args := map[string]interface{}{ - "path": path, - "property": property, - } - - response, err := q.executeCommandWithResponse(ctx, "qom-get", args, nil, nil) - if err != nil { - return "", err - } - - return response, nil -} - -// ExecuteDumpGuestMemory dump guest memory to host -func (q *QMP) ExecuteDumpGuestMemory(ctx context.Context, protocol string, paging bool, format string) error { - args := map[string]interface{}{ - "protocol": protocol, - "paging": paging, - "format": format, - } - - return q.executeCommand(ctx, "dump-guest-memory", args, nil) -} diff --git a/src/runtime/vendor/modules.txt b/src/runtime/vendor/modules.txt index 2f0996ab3..f52a619fc 100644 --- a/src/runtime/vendor/modules.txt +++ b/src/runtime/vendor/modules.txt @@ -206,9 +206,6 @@ github.com/hashicorp/go-multierror github.com/intel-go/cpuid # github.com/josharian/intern v1.0.0 github.com/josharian/intern -# github.com/kata-containers/govmm v0.0.0-20220117131932-0781a21804ee -## explicit -github.com/kata-containers/govmm/qemu # github.com/mailru/easyjson v0.7.6 github.com/mailru/easyjson/buffer github.com/mailru/easyjson/jlexer diff --git a/src/runtime/virtcontainers/qemu.go b/src/runtime/virtcontainers/qemu.go index 37a6d4035..b522928a7 100644 --- a/src/runtime/virtcontainers/qemu.go +++ b/src/runtime/virtcontainers/qemu.go @@ -24,7 +24,7 @@ import ( "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "github.com/sirupsen/logrus" diff --git a/src/runtime/virtcontainers/qemu_amd64.go b/src/runtime/virtcontainers/qemu_amd64.go index c1464809a..874b7461d 100644 --- a/src/runtime/virtcontainers/qemu_amd64.go +++ b/src/runtime/virtcontainers/qemu_amd64.go @@ -14,7 +14,7 @@ import ( "github.com/sirupsen/logrus" "github.com/intel-go/cpuid" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" ) type qemuAmd64 struct { diff --git a/src/runtime/virtcontainers/qemu_amd64_test.go b/src/runtime/virtcontainers/qemu_amd64_test.go index be3246f6f..6495b70cb 100644 --- a/src/runtime/virtcontainers/qemu_amd64_test.go +++ b/src/runtime/virtcontainers/qemu_amd64_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/intel-go/cpuid" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/stretchr/testify/assert" ) diff --git a/src/runtime/virtcontainers/qemu_arch_base.go b/src/runtime/virtcontainers/qemu_arch_base.go index 97cd6eb83..134525c92 100644 --- a/src/runtime/virtcontainers/qemu_arch_base.go +++ b/src/runtime/virtcontainers/qemu_arch_base.go @@ -14,7 +14,7 @@ import ( "runtime" "strings" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" diff --git a/src/runtime/virtcontainers/qemu_arch_base_test.go b/src/runtime/virtcontainers/qemu_arch_base_test.go index 67530ba51..b4b808685 100644 --- a/src/runtime/virtcontainers/qemu_arch_base_test.go +++ b/src/runtime/virtcontainers/qemu_arch_base_test.go @@ -13,7 +13,7 @@ import ( "path/filepath" "testing" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/stretchr/testify/assert" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" diff --git a/src/runtime/virtcontainers/qemu_arm64.go b/src/runtime/virtcontainers/qemu_arm64.go index 452493ce1..7fea89a75 100644 --- a/src/runtime/virtcontainers/qemu_arm64.go +++ b/src/runtime/virtcontainers/qemu_arm64.go @@ -12,7 +12,7 @@ import ( "runtime" "time" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" ) diff --git a/src/runtime/virtcontainers/qemu_arm64_test.go b/src/runtime/virtcontainers/qemu_arm64_test.go index 925b34cdd..9797cf894 100644 --- a/src/runtime/virtcontainers/qemu_arm64_test.go +++ b/src/runtime/virtcontainers/qemu_arm64_test.go @@ -11,7 +11,7 @@ import ( "os" "testing" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/stretchr/testify/assert" ) diff --git a/src/runtime/virtcontainers/qemu_ppc64le.go b/src/runtime/virtcontainers/qemu_ppc64le.go index 00fec3529..356261c79 100644 --- a/src/runtime/virtcontainers/qemu_ppc64le.go +++ b/src/runtime/virtcontainers/qemu_ppc64le.go @@ -9,7 +9,7 @@ import ( "fmt" "time" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/sirupsen/logrus" ) diff --git a/src/runtime/virtcontainers/qemu_ppc64le_test.go b/src/runtime/virtcontainers/qemu_ppc64le_test.go index ffe790d8e..7d70c6a40 100644 --- a/src/runtime/virtcontainers/qemu_ppc64le_test.go +++ b/src/runtime/virtcontainers/qemu_ppc64le_test.go @@ -9,7 +9,7 @@ import ( "fmt" "testing" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/stretchr/testify/assert" ) diff --git a/src/runtime/virtcontainers/qemu_s390x.go b/src/runtime/virtcontainers/qemu_s390x.go index d6c013156..827ced4b7 100644 --- a/src/runtime/virtcontainers/qemu_s390x.go +++ b/src/runtime/virtcontainers/qemu_s390x.go @@ -10,7 +10,7 @@ import ( "fmt" "time" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" diff --git a/src/runtime/virtcontainers/qemu_s390x_test.go b/src/runtime/virtcontainers/qemu_s390x_test.go index 4db63b6d8..c9e1cc2a3 100644 --- a/src/runtime/virtcontainers/qemu_s390x_test.go +++ b/src/runtime/virtcontainers/qemu_s390x_test.go @@ -10,7 +10,7 @@ import ( "fmt" "testing" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/stretchr/testify/assert" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" diff --git a/src/runtime/virtcontainers/qemu_test.go b/src/runtime/virtcontainers/qemu_test.go index b03f156de..2add4a45c 100644 --- a/src/runtime/virtcontainers/qemu_test.go +++ b/src/runtime/virtcontainers/qemu_test.go @@ -12,7 +12,7 @@ import ( "path/filepath" "testing" - govmmQemu "github.com/kata-containers/govmm/qemu" + govmmQemu "github.com/kata-containers/kata-containers/src/runtime/pkg/govmm/qemu" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" From de678a3aaa361e5e417abd2fba5581f764b90ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Tue, 18 Jan 2022 11:20:11 +0100 Subject: [PATCH 2/5] govmm: Remove non-relevant top files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit govmm, from now on, should follow the same guidelines from contributing, copying, and etc as kata-containers does. The go.mod is not needed anymore as the project lives inside the runtime. Signed-off-by: Fabiano Fidêncio --- src/runtime/pkg/govmm/CONTRIBUTING.md | 96 ------------ src/runtime/pkg/govmm/COPYING | 202 -------------------------- src/runtime/pkg/govmm/README.md | 21 --- src/runtime/pkg/govmm/go.mod | 3 - 4 files changed, 322 deletions(-) delete mode 100644 src/runtime/pkg/govmm/CONTRIBUTING.md delete mode 100644 src/runtime/pkg/govmm/COPYING delete mode 100644 src/runtime/pkg/govmm/README.md delete mode 100644 src/runtime/pkg/govmm/go.mod diff --git a/src/runtime/pkg/govmm/CONTRIBUTING.md b/src/runtime/pkg/govmm/CONTRIBUTING.md deleted file mode 100644 index 451903e0a..000000000 --- a/src/runtime/pkg/govmm/CONTRIBUTING.md +++ /dev/null @@ -1,96 +0,0 @@ -# Contributing to Virtual Machine Manager for Go - -Virtual Machine Manager for Go is an open source project licensed under the [Apache v2 License] (https://opensource.org/licenses/Apache-2.0) - -## Coding Style - -Virtual Machine Manager for Go follows the standard formatting recommendations and language idioms set out -in [Effective Go](https://golang.org/doc/effective_go.html) and in the -[Go Code Review Comments wiki](https://github.com/golang/go/wiki/CodeReviewComments). - -## Certificate of Origin - -In order to get a clear contribution chain of trust we use the [signed-off-by language] (https://01.org/community/signed-process) -used by the Linux kernel project. - -## Patch format - -Beside the signed-off-by footer, we expect each patch to comply with the following format: - -``` -Change summary - -More detailed explanation of your changes: Why and how. -Wrap it to 72 characters. -See [here] (http://chris.beams.io/posts/git-commit/) -for some more good advices. - -Fixes #NUMBER (or URL to the issue) - -Signed-off-by: -``` - -For example: - -``` -Fix poorly named identifiers - -One identifier, fnname, in func.go was poorly named. It has been renamed -to fnName. Another identifier retval was not needed and has been removed -entirely. - -Fixes #1 - -Signed-off-by: Mark Ryan -``` - -## New files - -Each Go source file in the Virtual Machine Manager for Go project must -contain the following header: - -``` -/* -// Copyright contributors to the Virtual Machine Manager for Go project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ -``` - -## Contributors File - -This CONTRIBUTORS.md file is a partial list of contributors to the -Virtual Machine Manager for Go project. To see the full list of -contributors, see the revision history in source control. - -Contributors who wish to be recognized in this file should add -themselves (or their employer, as appropriate). - -## Pull requests - -We accept github pull requests. - -## Quality Controls - -We request you give quality assurance some consideration by: - -* Adding go unit tests for changes where it makes sense. -* Enabling [Travis CI](https://travis-ci.org/kata-containers/govmm) on your github fork of Virtual Machine Manager for Go to get continuous integration feedback on your dev/test branches. - -## Issue tracking - -If you have a problem, please let us know. If it's a bug not already documented, by all means please [open an -issue in github](https://github.com/kata-containers/govmm/issues/new) so we all get visibility -the problem and work toward resolution. - -Any security issues discovered with govmm should be reported by following the instructions on https://01.org/security. diff --git a/src/runtime/pkg/govmm/COPYING b/src/runtime/pkg/govmm/COPYING deleted file mode 100644 index d64569567..000000000 --- a/src/runtime/pkg/govmm/COPYING +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/runtime/pkg/govmm/README.md b/src/runtime/pkg/govmm/README.md deleted file mode 100644 index d96c4d9de..000000000 --- a/src/runtime/pkg/govmm/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Virtual Machine Manager for Go - -[![Go Report Card](https://goreportcard.com/badge/github.com/kata-containers/govmm)](https://goreportcard.com/report/github.com/kata-containers/govmm) -[![Build Status](https://travis-ci.org/kata-containers/govmm.svg?branch=master)](https://travis-ci.org/kata-containers/govmm) -[![GoDoc](https://godoc.org/github.com/kata-containers/govmm/qemu?status.svg)](https://godoc.org/github.com/kata-containers/govmm/qemu) -[![Coverage Status](https://coveralls.io/repos/github/kata-containers/govmm/badge.svg?branch=master)](https://coveralls.io/github/kata-containers/govmm?branch=master) - -Virtual Machine Manager for Go (govmm) is a suite of packages that -provide Go APIs for creating and managing virtual machines. There's -currently support for only one hypervisor, qemu/kvm (version 5.0 and -later), support for which is provided by the -github.com/kata-containers/govmm/qemu package. - -The qemu package provides APIs for launching qemu instances and for -managing those instances via QMP, once launched. VM instances can -be stopped, have devices attached to them and monitored for events -via the qemu APIs. - -The qemu package has no external dependencies apart from the Go -standard library and so is nice and easy to vendor inside other -projects. diff --git a/src/runtime/pkg/govmm/go.mod b/src/runtime/pkg/govmm/go.mod deleted file mode 100644 index 377ac043f..000000000 --- a/src/runtime/pkg/govmm/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/kata-containers/govmm - -go 1.16 From 6dd65779863b331adb4efaf9e17c5118dd55b805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Wed, 19 Jan 2022 12:16:46 +0100 Subject: [PATCH 3/5] govmm: Ignore govet checks, at least for now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit govet checks have been ignored on govmm repo, but those are enabled on kata-containers one. So, in order to avoid failing our CIs let's just keep ignoring the checks for the govmm structs and have an issue opened for fixing it whenever someone has cycles to do it. The important bit here is, we're not making anything worse that it already is. :-) Signed-off-by: Fabiano Fidêncio --- src/runtime/pkg/govmm/qemu/qemu.go | 16 ++++++++++++++++ src/runtime/pkg/govmm/qemu/qmp.go | 10 ++++++++++ src/runtime/pkg/govmm/qemu/qmp_test.go | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/src/runtime/pkg/govmm/qemu/qemu.go b/src/runtime/pkg/govmm/qemu/qemu.go index c43ff5795..8e101e9b9 100644 --- a/src/runtime/pkg/govmm/qemu/qemu.go +++ b/src/runtime/pkg/govmm/qemu/qemu.go @@ -250,6 +250,7 @@ const ( ) // Object is a qemu object representation. +// nolint: govet type Object struct { // Driver is the qemu device driver Driver DeviceDriver @@ -439,6 +440,7 @@ const ( ) // FSDevice represents a qemu filesystem configuration. +// nolint: govet type FSDevice struct { // Driver is the qemu device driver Driver DeviceDriver @@ -574,6 +576,7 @@ const ( ) // CharDevice represents a qemu character device. +// nolint: govet type CharDevice struct { Backend CharDeviceBackend @@ -784,6 +787,7 @@ func (n NetDeviceType) QemuDeviceParam(netdev *NetDevice, config *Config) Device } // NetDevice represents a guest networking device +// nolint: govet type NetDevice struct { // Type is the netdev type (e.g. tap). Type NetDeviceType @@ -1041,6 +1045,7 @@ func (dev LegacySerialDevice) deviceName(config *Config) string { */ // SerialDevice represents a qemu serial device. +// nolint: govet type SerialDevice struct { // Driver is the qemu device driver Driver DeviceDriver @@ -1149,6 +1154,7 @@ const ( ) // BlockDevice represents a qemu block device. +// nolint: govet type BlockDevice struct { Driver DeviceDriver ID string @@ -1316,6 +1322,7 @@ func (dev LoaderDevice) QemuParams(config *Config) []string { // VhostUserDevice represents a qemu vhost-user device meant to be passed // in to the guest +// nolint: govet type VhostUserDevice struct { SocketPath string //path to vhostuser socket on host CharDevID string @@ -1567,6 +1574,7 @@ func (vhostuserDev VhostUserDevice) deviceName(config *Config) string { } // PCIeRootPortDevice represents a memory balloon device. +// nolint: govet type PCIeRootPortDevice struct { ID string // format: rp{n}, n>=0 @@ -1747,6 +1755,7 @@ func (vfioDev VFIODevice) deviceName(config *Config) string { } // SCSIController represents a SCSI controller device. +// nolint: govet type SCSIController struct { ID string @@ -1843,6 +1852,7 @@ const ( ) // BridgeDevice represents a qemu bridge device like pci-bridge, pxb, etc. +// nolint: govet type BridgeDevice struct { // Type of the bridge Type BridgeType @@ -1940,6 +1950,7 @@ func (bridgeDev BridgeDevice) QemuParams(config *Config) []string { } // VSOCKDevice represents a AF_VSOCK socket. +// nolint: govet type VSOCKDevice struct { ID string @@ -2036,6 +2047,7 @@ func (vsock VSOCKDevice) deviceName(config *Config) string { } // RngDevice represents a random number generator device. +// nolint: govet type RngDevice struct { // ID is the device ID ID string @@ -2124,6 +2136,7 @@ func (v RngDevice) deviceName(config *Config) string { } // BalloonDevice represents a memory balloon device. +// nolint: govet type BalloonDevice struct { DeflateOnOOM bool DisableModern bool @@ -2358,6 +2371,7 @@ type SMP struct { } // Memory is the guest memory configuration structure. +// nolint: govet type Memory struct { // Size is the amount of memory made available to the guest. // It should be suffixed with M or G for sizes in megabytes or @@ -2505,6 +2519,7 @@ const ( ) // Incoming controls migration source preparation +// nolint: govet type Incoming struct { // Possible values are MigrationFD, MigrationExec MigrationType int @@ -2516,6 +2531,7 @@ type Incoming struct { // Config is the qemu configuration structure. // It allows for passing custom settings and parameters to the qemu API. +// nolint: govet type Config struct { // Path is the qemu binary path. Path string diff --git a/src/runtime/pkg/govmm/qemu/qmp.go b/src/runtime/pkg/govmm/qemu/qmp.go index 2e30c2ba9..83c5293d6 100644 --- a/src/runtime/pkg/govmm/qemu/qmp.go +++ b/src/runtime/pkg/govmm/qemu/qmp.go @@ -96,6 +96,7 @@ type qmpEventFilter struct { } // QMPEvent contains a single QMP event, sent on the QMPConfig.EventCh channel. +// nolint: govet type QMPEvent struct { // The name of the event, e.g., DEVICE_DELETED Name string @@ -118,6 +119,7 @@ type qmpResult struct { err error } +// nolint: govet type qmpCommand struct { ctx context.Context res chan qmpResult @@ -130,6 +132,7 @@ type qmpCommand struct { // QMP is a structure that contains the internal state used by startQMPLoop and // the go routines it spwans. All the contents of this structure are private. +// nolint: govet type QMP struct { cmdCh chan qmpCommand conn io.ReadWriteCloser @@ -141,6 +144,7 @@ type QMP struct { // QMPVersion contains the version number and the capabailities of a QEMU // instance, as reported in the QMP greeting message. +// nolint: govet type QMPVersion struct { Major int Minor int @@ -158,6 +162,7 @@ type CPUProperties struct { } // HotpluggableCPU represents a hotpluggable CPU +// nolint: govet type HotpluggableCPU struct { Type string `json:"type"` VcpusCount int `json:"vcpus-count"` @@ -166,6 +171,7 @@ type HotpluggableCPU struct { } // MemoryDevicesData cotains the data describes a memory device +// nolint: govet type MemoryDevicesData struct { Slot int `json:"slot"` Node int `json:"node"` @@ -178,12 +184,14 @@ type MemoryDevicesData struct { } // MemoryDevices represents memory devices of vm +// nolint: govet type MemoryDevices struct { Data MemoryDevicesData `json:"data"` Type string `json:"type"` } // CPUInfo represents information about each virtual CPU +// nolint: govet type CPUInfo struct { CPU int `json:"CPU"` Current bool `json:"current"` @@ -196,6 +204,7 @@ type CPUInfo struct { } // CPUInfoFast represents information about each virtual CPU +// nolint: govet type CPUInfoFast struct { CPUIndex int `json:"cpu-index"` QomPath string `json:"qom-path"` @@ -252,6 +261,7 @@ type SchemaInfo struct { } // StatusInfo represents guest running status +// nolint: govet type StatusInfo struct { Running bool `json:"running"` SingleStep bool `json:"singlestep"` diff --git a/src/runtime/pkg/govmm/qemu/qmp_test.go b/src/runtime/pkg/govmm/qemu/qmp_test.go index 83259290b..ad3c0092d 100644 --- a/src/runtime/pkg/govmm/qemu/qmp_test.go +++ b/src/runtime/pkg/govmm/qemu/qmp_test.go @@ -61,11 +61,13 @@ func (l qmpTestLogger) Errorf(format string, v ...interface{}) { l.Infof(format, v...) } +// nolint: govet type qmpTestCommand struct { name string args map[string]interface{} } +// nolint: govet type qmpTestEvent struct { name string data map[string]interface{} @@ -73,11 +75,13 @@ type qmpTestEvent struct { after time.Duration } +// nolint: govet type qmpTestResult struct { result string data interface{} } +// nolint: govet type qmpTestCommandBuffer struct { newDataCh chan []byte t *testing.T From 8bcaed0b4f7bb613e1f4a253074ef90c45ae1621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Wed, 19 Jan 2022 13:16:55 +0100 Subject: [PATCH 4/5] govmm: Adapt license headers to kata-containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both projects follow the same license, Apache-2.0, but the header saying that comes from govmm is different from the one expected for the tests present on the kata-containers repo. Signed-off-by: Fabiano Fidêncio --- src/runtime/pkg/govmm/qemu/examples_test.go | 13 +------------ src/runtime/pkg/govmm/qemu/image.go | 13 +------------ src/runtime/pkg/govmm/qemu/qemu.go | 13 +------------ src/runtime/pkg/govmm/qemu/qemu_arch_base_test.go | 13 +------------ src/runtime/pkg/govmm/qemu/qemu_s390x_test.go | 13 +------------ src/runtime/pkg/govmm/qemu/qemu_test.go | 13 +------------ src/runtime/pkg/govmm/qemu/qmp.go | 13 +------------ src/runtime/pkg/govmm/qemu/qmp_test.go | 13 +------------ 8 files changed, 8 insertions(+), 96 deletions(-) diff --git a/src/runtime/pkg/govmm/qemu/examples_test.go b/src/runtime/pkg/govmm/qemu/examples_test.go index 22cc0eff3..03e52b87a 100644 --- a/src/runtime/pkg/govmm/qemu/examples_test.go +++ b/src/runtime/pkg/govmm/qemu/examples_test.go @@ -1,18 +1,7 @@ -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu_test diff --git a/src/runtime/pkg/govmm/qemu/image.go b/src/runtime/pkg/govmm/qemu/image.go index ddee0670e..b17efdd16 100644 --- a/src/runtime/pkg/govmm/qemu/image.go +++ b/src/runtime/pkg/govmm/qemu/image.go @@ -1,18 +1,7 @@ -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu diff --git a/src/runtime/pkg/govmm/qemu/qemu.go b/src/runtime/pkg/govmm/qemu/qemu.go index 8e101e9b9..0ee8347f2 100644 --- a/src/runtime/pkg/govmm/qemu/qemu.go +++ b/src/runtime/pkg/govmm/qemu/qemu.go @@ -1,18 +1,7 @@ -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ // Package qemu provides methods and types for launching and managing QEMU // instances. Instances can be launched with the LaunchQemu function and diff --git a/src/runtime/pkg/govmm/qemu/qemu_arch_base_test.go b/src/runtime/pkg/govmm/qemu/qemu_arch_base_test.go index 667609707..4ef6e3c4e 100644 --- a/src/runtime/pkg/govmm/qemu/qemu_arch_base_test.go +++ b/src/runtime/pkg/govmm/qemu/qemu_arch_base_test.go @@ -1,21 +1,10 @@ //go:build !s390x // +build !s390x -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu diff --git a/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go b/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go index 4b99f7ea5..cb7f794e1 100644 --- a/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go +++ b/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go @@ -1,20 +1,9 @@ // +build s390x -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu diff --git a/src/runtime/pkg/govmm/qemu/qemu_test.go b/src/runtime/pkg/govmm/qemu/qemu_test.go index 2e37b0e16..5b73e9dfc 100644 --- a/src/runtime/pkg/govmm/qemu/qemu_test.go +++ b/src/runtime/pkg/govmm/qemu/qemu_test.go @@ -1,18 +1,7 @@ -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu diff --git a/src/runtime/pkg/govmm/qemu/qmp.go b/src/runtime/pkg/govmm/qemu/qmp.go index 83c5293d6..9bf091af8 100644 --- a/src/runtime/pkg/govmm/qemu/qmp.go +++ b/src/runtime/pkg/govmm/qemu/qmp.go @@ -1,18 +1,7 @@ -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu diff --git a/src/runtime/pkg/govmm/qemu/qmp_test.go b/src/runtime/pkg/govmm/qemu/qmp_test.go index ad3c0092d..23114a0d7 100644 --- a/src/runtime/pkg/govmm/qemu/qmp_test.go +++ b/src/runtime/pkg/govmm/qemu/qmp_test.go @@ -1,18 +1,7 @@ -/* // Copyright contributors to the Virtual Machine Manager for Go project // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// SPDX-License-Identifier: Apache-2.0 // -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ package qemu From 5ce9011a36a04edc1a6abd0e8db56d066aab3db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Wed, 19 Jan 2022 22:02:34 +0100 Subject: [PATCH 5/5] govmm: s390x: Skip broken tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now a bunch of tests are simply not working. Let's skip them all, and re-enable them once kata-containers/kata-containers/issues/3500 gets fixed. Signed-off-by: Fabiano Fidêncio --- src/runtime/pkg/govmm/qemu/qemu_s390x_test.go | 5 ++++- src/runtime/pkg/govmm/qemu/qemu_test.go | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go b/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go index cb7f794e1..be8a3b198 100644 --- a/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go +++ b/src/runtime/pkg/govmm/qemu/qemu_s390x_test.go @@ -13,7 +13,7 @@ import "testing" // See https://wiki.qemu.org/Documentation/Platforms/S390X var ( deviceFSString = "-device virtio-9p-ccw,fsdev=workload9p,mount_tag=rootfs,devno=" + DevNo + " -fsdev local,id=workload9p,path=/var/lib/docker/devicemapper/mnt/e31ebda2,security_model=none,multidevs=remap" - deviceFSIOMMUString = "-device virtio-9p-ccw,fsdev=workload9p,mount_tag=rootfs,iommu_platform=on,devno=" + DevNo + " -fsdev local,id=workload9p,path=/var/lib/docker/devicemapper/mnt/e31ebda2,security_model=none,multidevs=remap" + deviceFSIOMMUString = "-device virtio-9p-ccw,fsdev=workload9p,mount_tag=rootfs,iommu_platform=on,devno=" + DevNo + " -fsdev local,id=workload9p,path=/var/lib/docker/devicemapper/mnt/e31ebda2,security_model=none,multidevs=remap" //nolint deviceNetworkString = "-netdev tap,id=tap0,vhost=on,ifname=ceth0,downscript=no,script=no -device driver=virtio-net-ccw,netdev=tap0,mac=01:02:de:ad:be:ef,devno=" + DevNo deviceNetworkStringMq = "-netdev tap,id=tap0,vhost=on,fds=3:4 -device driver=virtio-net-ccw,netdev=tap0,mac=01:02:de:ad:be:ef,mq=on,devno=" + DevNo deviceSerialString = "-device virtio-serial-ccw,id=serial0,devno=" + DevNo @@ -23,6 +23,7 @@ var ( deviceSCSIControllerBusAddrStr = "-device virtio-scsi-ccw,id=foo,bus=pci.0,addr=00:04.0,iothread=iothread1,devno=" + DevNo deviceBlockString = "-device virtio-blk-ccw,drive=hd0,scsi=off,config-wce=off,devno=" + DevNo + ",share-rw=on,serial=hd0 -drive id=hd0,file=/var/lib/vm.img,aio=threads,format=qcow2,if=none,readonly" devicePCIBridgeString = "-device pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,chassis_nr=5,shpc=on,addr=ff" + devicePCIBridgeStringReserved = "-device pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,chassis_nr=5,shpc=on,addr=ff,io-reserve=4k,mem-reserve=1m,pref64-reserve=1m" devicePCIEBridgeString = "-device pcie-pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,addr=ff" romfile = "" ) @@ -71,6 +72,8 @@ func TestAppendDeviceFSCCW(t *testing.T) { } func TestAppendDeviceFSCCWIOMMU(t *testing.T) { + t.Skip("Skipping on due to: https://github.com/kata-containers/kata-containers/issues/3500") + defaultKnobs := Knobs{ NoUserConfig: true, IOMMUPlatform: true, diff --git a/src/runtime/pkg/govmm/qemu/qemu_test.go b/src/runtime/pkg/govmm/qemu/qemu_test.go index 5b73e9dfc..445bdd089 100644 --- a/src/runtime/pkg/govmm/qemu/qemu_test.go +++ b/src/runtime/pkg/govmm/qemu/qemu_test.go @@ -10,6 +10,7 @@ import ( "io/ioutil" "os" "reflect" + "runtime" "strings" "testing" ) @@ -331,6 +332,10 @@ func TestAppendDeviceSerialPort(t *testing.T) { } func TestAppendDeviceBlock(t *testing.T) { + if runtime.GOARCH == "s390x" { + t.Skip("Skipping on s390x due to: https://github.com/kata-containers/kata-containers/issues/3500") + } + blkdev := BlockDevice{ Driver: VirtioBlock, ID: "hd0", @@ -511,6 +516,9 @@ func TestAppendPCIBridgeDevice(t *testing.T) { } func TestAppendPCIBridgeDeviceWithReservations(t *testing.T) { + if runtime.GOARCH == "s390x" { + t.Skip("Skipping on s390x due to: https://github.com/kata-containers/kata-containers/issues/3500") + } bridge := BridgeDevice{ Type: PCIBridge,