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/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 diff --git a/src/runtime/pkg/govmm/qemu/examples_test.go b/src/runtime/pkg/govmm/qemu/examples_test.go index 1946aeef8..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 @@ -21,7 +10,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/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 c43ff5795..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 @@ -250,6 +239,7 @@ const ( ) // Object is a qemu object representation. +// nolint: govet type Object struct { // Driver is the qemu device driver Driver DeviceDriver @@ -439,6 +429,7 @@ const ( ) // FSDevice represents a qemu filesystem configuration. +// nolint: govet type FSDevice struct { // Driver is the qemu device driver Driver DeviceDriver @@ -574,6 +565,7 @@ const ( ) // CharDevice represents a qemu character device. +// nolint: govet type CharDevice struct { Backend CharDeviceBackend @@ -784,6 +776,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 +1034,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 +1143,7 @@ const ( ) // BlockDevice represents a qemu block device. +// nolint: govet type BlockDevice struct { Driver DeviceDriver ID string @@ -1316,6 +1311,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 +1563,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 +1744,7 @@ func (vfioDev VFIODevice) deviceName(config *Config) string { } // SCSIController represents a SCSI controller device. +// nolint: govet type SCSIController struct { ID string @@ -1843,6 +1841,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 +1939,7 @@ func (bridgeDev BridgeDevice) QemuParams(config *Config) []string { } // VSOCKDevice represents a AF_VSOCK socket. +// nolint: govet type VSOCKDevice struct { ID string @@ -2036,6 +2036,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 +2125,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 +2360,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 +2508,7 @@ const ( ) // Incoming controls migration source preparation +// nolint: govet type Incoming struct { // Possible values are MigrationFD, MigrationExec MigrationType int @@ -2516,6 +2520,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/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..be8a3b198 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 @@ -24,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 @@ -34,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 = "" ) @@ -82,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 2e37b0e16..445bdd089 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 @@ -21,6 +10,7 @@ import ( "io/ioutil" "os" "reflect" + "runtime" "strings" "testing" ) @@ -342,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", @@ -522,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, diff --git a/src/runtime/pkg/govmm/qemu/qmp.go b/src/runtime/pkg/govmm/qemu/qmp.go index 2e30c2ba9..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 @@ -96,6 +85,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 +108,7 @@ type qmpResult struct { err error } +// nolint: govet type qmpCommand struct { ctx context.Context res chan qmpResult @@ -130,6 +121,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 +133,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 +151,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 +160,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 +173,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 +193,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 +250,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..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 @@ -61,11 +50,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 +64,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 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"