From ebb8fd576b3003846b69f864f25cf2e2598fe841 Mon Sep 17 00:00:00 2001 From: Jose Carlos Venegas Munoz Date: Tue, 17 Mar 2020 21:00:19 +0000 Subject: [PATCH 1/5] versions: Update clh to latest master Use latest master to enable memory hotplug. Changes: c1e6d00 ci: Add memory resizing use case to vhost-user tests 890582b ci: Factorize kernel command line 4de2584 ci: Fix mmio tests with direct kernel boot f268246 ci: Factorize integration tests booting from vhost-user-blk 5a5b3cf ci: Factorize vhost-user-blk integration tests dd8debf ci: Run vhost-user-blk tests for mmio builds 0c9c72c ci: Unify vhost-user-blk integration tests c95851f ci: Run vhost-user-net tests for mmio transport 68293fc ci: Factorize vhost-user-net one step further d75e745 vm-virtio: vhost-user: Send memory update to the backend 7ff82af vm-virtio: vhost-user: Factorize SET_MEM_TABLE setup e54f8ec vmm: Update memory through DeviceManager bc874a9 vm-virtio: Add update_memory() to VirtioDevice trait 93becca build(deps): bump backtrace from 0.3.45 to 0.3.46 feb8d7a vmm: Separate seccomp filters between VMM and API threads 5120c27 main: Add seccomp support f1a23d7 vmm: api: Add seccomp to the HTTP API thread db62cb3 vmm: Add seccomp filter to the VMM thread cb98d90 vmm: Create new seccomp_filter module 708f02d vmm: Pull seccomp crate from Firecracker 18fbd30 vhost-user-fs: return correct result of fs_slave_io() bbc385c devices: ioapic: Remove unused MsiMessage structure 2fc86ff dev_cli: Always pull the latest container image 4b462a5 Dockerfile: Add cpio and bsdtar to the container image 8acc15a build: Bump vm-memory and linux-loader dependencies 38ed560 build(deps): bump thiserror from 1.0.12 to 1.0.13 9f67de4 build(deps): bump proc-macro-hack from 0.5.12 to 0.5.14 ebab809 build(deps): bump thiserror from 1.0.11 to 1.0.12 c67e407 build(deps): bump syn from 1.0.16 to 1.0.17 bdcfe1e tests: Add "discard_writes" pmem test 7098602 tests: Make the test_virtio_pmem test use a temporary file f7197e8 vmm: Add a "discard_writes=" to --pmem d11a67b vmm: Use more generic MmapRegion constructor 7257e89 vmm: Add "readonly" parameter MemoryManager::create_userspace_mapping 03cb26c release: v0.6.0 3e9a39c github: Upload the ch-remote asset c503118 vmm: fix a corrupted stack caused by get_win_size 0788600 build: Remove "pvh_boot" feature flag 477bc17 bin: Share VFIO device syntax between cloud-hypervisor and ch-remote 96be2db build(deps): bump serde_derive from 1.0.104 to 1.0.105 5a335fc build(deps): bump serde from 1.0.104 to 1.0.105 a31ffef openapi: Add hotplug_size for memory hotplug 87990f9 vmm: Add virtio-pci device to B/D/F hash table fb185fa vmm: Always return PCI B/D/F from add_virtio_pci_device 462082c build(deps): bump arc-swap from 0.4.4 to 0.4.5 c821e96 vhost_user_fs: Implement support for FUSE_LSEEK 5aa9abc docs: Add document for vhost-user-net test with OVS/DPDK 6329219 vm-virtio: queue: Use a SeqCst fence on get_used_event 63eeed2 vm: Comment on the VM config update from memory hotplug 0895bcb build(deps): bump proc-macro-hack from 0.5.11 to 0.5.12 0541f5a build(deps): bump proc-macro-nested from 0.1.3 to 0.1.4 51f51ea build(deps): bump libc from 0.2.67 to 0.2.68 9cf67d1 arch: x86: Always set the bootloader type ad35470 arch: x86: Extract common bootparams settings 28a5f9d vmm: acpi: Remove unused IORT related structures 5c1207c vhost-user-fs: handle FS_IO request f61f78e build(deps): bump anyhow from 1.0.26 to 1.0.27 efb2447 pvh: Add integration test to validate PVH boot da084fa pvh: Add unit tests for initial sregs and control registers 64941bf pvh: Add unit tests for start_info and memory map structures 9e247c4 pvh: Introduce "pvh_boot" feature a22bc35 pvh: Write start_info structure to guest memory 840a9a9 pvh: Initialize vCPU regs/sregs for PVH boot 24f0e42 pvh: Introduce EntryPoint struct 98b9568 pvh: Add definitions for PVH boot protocol support 6e6ef83 build: Fix log dependency 291f1ce build(deps): bump linux-loader from `0c754f3` to `0ce5bfa` 07cc73b vhost_user_fs: add a flag to disable extended attributes 710520e vhost_user_fs: Process requests in parallel with a thread pool 90309b5 vm-virtio: queue: Add methods to switch a descriptor context 2294c2d Add .rustfmt.toml to the project 48c4885 vhost_user_fs: replace HandleData's File Mutex with RwLock 134e64c arch, qcow: Fix 1.42.0 clippy warnings 6ea85ca resources: Dockerfile: Update Rust toolchain 4579afa vmm: For --disk error if socket and path is specified 7e599b4 vmm: Make disk path optional 477d924 github: Build from a rust toolchain matrix 4f2469e main: Remove "--vhost-user-net" 8d785bb pci: Fix the PciBus using HashMap instead of Vec 04f2ccd build(deps): bump ryu from 1.0.2 to 1.0.3 02265bb build(deps): bump regex-syntax from 0.6.16 to 0.6.17 40b38a4 openapi: Make desired_ram int64 format ca3b39c bin: Fix wrapping in help strings ee1ba56 build: Use "wrap_help" feature for clap 3957d1e vhost_user_backend: call get_used_event from needs_notification 536323d vm-virtio: queue: hint that get_used_event should be inlined 401e1d2 vm-virtio: queue: fix a barrier comment at update_avail_event e0bdfe8 vm-virtio: queue: add a missing memory barrier in get_used_event df2570a resources: Simplify kernel config filename 9ab648b resources: Enable VIRTIO_MEM support 0339853 ci: Bump to kernel 5.6-rc4 abccf76 tests: Use ch-remote to add/remove devices in test_vfio 5c3ce9d tests: Extend ch-remote helper to support optional single argument 9a7d9c9 ch-remote: Support removing VFIO devices 0d53ba4 ch-remote: Support adding VFIO devices babefbd main: Remove spurious second help line for "--device" 63c5d09 github: Trigger the build job on PRs 8cbb6d0 github: Replace Travis CI with github actions efba48d vmm: Don't put a VFIO device behind the vIOMMU by default 34412c9 vmm: Add id option to VFIO hotplug 18dc916 vmm: Switch to the micro-http package 9023444 vmm: Add id field to --device through CLI f4a956a vmm: Remove 32 bits MMIO range from correct address space 432eb5b vmm: Free PCI BARs when unplugging PCI device f0dff8b vfio: pci: Remove KVM user memory region when cleaning up 34d1f43 vfio: pci: Implement free_bars() from the PciDevice trait b8e1cf2 vm-allocator: Add new function to free 32 bits MMIO address space f3dc245 pci: Extend PciDevice trait with new free_bars() method 911a2d6 tests: Use ch-remote to resize the VM 21160f7 ch-remote: Add "resize" command bb2d04b ch-remote: Add support for sending a request body bde4f73 ch-remote: Refactor HTTP response handling 6ed23bb build(deps): bump micro_http from `9bbde4f` to `6b3e5f0` 5edd812 build(deps): bump backtrace-sys from 0.1.33 to 0.1.34 f727714 ci: Add integration test for VFIO hot-unplug b50cbe5 pci: Give PCI device ID back when removing a device df71aae pci: Make the device ID allocation smarter e514b12 vmm: Update VmConfig when removing VFIO device 81173bf vmm: Add id field to DeviceConfig structure 6cbdb9a vmm: api: Introduce new "remove-device" HTTP endpoint 991f3bb vmm: Remove VFIO device from everywhere it is referenced 6adebbc vmm: Detect when guest notifies about ejecting PCI device 0e21c32 devices: Add new method to remove all occurrences of a BusDevice f8e2008 pci: Add a function to remove a PciDevice from the bus 08604ac vmm: Store PCI devices as Any devices from DeviceManager 0f99d3f vmm: Store VFIO device's name and its PCI b/d/f 13a61c4 build(deps): bump rand_chacha from 0.2.1 to 0.2.2 fcd605a build(deps): bump micro_http from `6d416af` to `9bbde4f` 30b6954 vm-virtio: Consume pause events to prevent infinite epoll_wait calls 16fd506 tests: Use new ch-remote for pause/resume integration test ba8cd4d bin: Introduce "ch-remote" for controlling VMM 06cd31c build(deps): bump micro_http from `02def92` to `6d416af` 7e941c9 build(deps): bump linux-loader from `8cb7c66` to `0c754f3` Signed-off-by: Jose Carlos Venegas Munoz --- versions.yaml | 2 +- .../pkg/cloud-hypervisor/client/README.md | 2 + .../cloud-hypervisor/client/api/openapi.yaml | 115 ++++++++++++------ .../cloud-hypervisor/client/api_default.go | 66 ++++++++++ .../client/docs/DefaultApi.md | 33 +++++ .../client/docs/DeviceConfig.md | 1 + .../client/docs/MemoryConfig.md | 1 + .../client/docs/PmemConfig.md | 1 + .../client/docs/VmRemoveDevice.md | 11 ++ .../cloud-hypervisor/client/docs/VmResize.md | 2 +- .../client/model_device_config.go | 1 + .../client/model_memory_config.go | 1 + .../client/model_pmem_config.go | 1 + .../client/model_vm_remove_device.go | 14 +++ .../client/model_vm_resize.go | 3 +- .../cloud-hypervisor/cloud-hypervisor.yaml | 32 +++++ 16 files changed, 248 insertions(+), 38 deletions(-) create mode 100644 virtcontainers/pkg/cloud-hypervisor/client/docs/VmRemoveDevice.md create mode 100644 virtcontainers/pkg/cloud-hypervisor/client/model_vm_remove_device.go diff --git a/versions.yaml b/versions.yaml index d25f837190..bacfb07491 100644 --- a/versions.yaml +++ b/versions.yaml @@ -75,7 +75,7 @@ assets: url: "https://github.com/cloud-hypervisor/cloud-hypervisor" uscan-url: >- https://github.com/cloud-hypervisor/cloud-hypervisor/tags.*/v?(\d\S+)\.tar\.gz - version: "df794993f8abe20f829275c77fb2a52ed485f70a" + version: "c1e6d0022b220ecba25a10f61d0025a408d90a94" firecracker: description: "Firecracker micro-VMM" diff --git a/virtcontainers/pkg/cloud-hypervisor/client/README.md b/virtcontainers/pkg/cloud-hypervisor/client/README.md index 8872c9ecdb..c6b967cd29 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/README.md +++ b/virtcontainers/pkg/cloud-hypervisor/client/README.md @@ -42,6 +42,7 @@ Class | Method | HTTP request | Description *DefaultApi* | [**ShutdownVMM**](docs/DefaultApi.md#shutdownvmm) | **Put** /vmm.shutdown | Shuts the cloud-hypervisor VMM. *DefaultApi* | [**VmAddDevicePut**](docs/DefaultApi.md#vmadddeviceput) | **Put** /vm.add-device | Add a new device to the VM *DefaultApi* | [**VmInfoGet**](docs/DefaultApi.md#vminfoget) | **Get** /vm.info | Returns general information about the cloud-hypervisor Virtual Machine (VM) instance. +*DefaultApi* | [**VmRemoveDevicePut**](docs/DefaultApi.md#vmremovedeviceput) | **Put** /vm.remove-device | Remove a device from the VM *DefaultApi* | [**VmResizePut**](docs/DefaultApi.md#vmresizeput) | **Put** /vm.resize | Resize the VM *DefaultApi* | [**VmmPingGet**](docs/DefaultApi.md#vmmpingget) | **Get** /vmm.ping | Ping the VMM to check for API server availability @@ -62,6 +63,7 @@ Class | Method | HTTP request | Description - [VmAddDevice](docs/VmAddDevice.md) - [VmConfig](docs/VmConfig.md) - [VmInfo](docs/VmInfo.md) + - [VmRemoveDevice](docs/VmRemoveDevice.md) - [VmResize](docs/VmResize.md) - [VmmPingResponse](docs/VmmPingResponse.md) - [VsockConfig](docs/VsockConfig.md) diff --git a/virtcontainers/pkg/cloud-hypervisor/client/api/openapi.yaml b/virtcontainers/pkg/cloud-hypervisor/client/api/openapi.yaml index d9da94bc9c..5dcc8f25a5 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/api/openapi.yaml +++ b/virtcontainers/pkg/cloud-hypervisor/client/api/openapi.yaml @@ -143,6 +143,21 @@ paths: "404": description: The new device could not be added to the VM instance. summary: Add a new device to the VM + /vm.remove-device: + put: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/VmRemoveDevice' + description: The identifier of the device + required: true + responses: + "204": + description: The device was successfully removed from the VM instance. + "404": + description: The device could not be removed from the VM instance. + summary: Remove a device from the VM components: schemas: VmmPingResponse: @@ -168,12 +183,13 @@ components: mergeable: false file: file size: 1 + hotplug_size: 5 disks: - path: path num_queues: 5 readonly: false iommu: false - queue_size: 5 + queue_size: 2 vhost_socket: vhost_socket vhost_user: false direct: false @@ -183,7 +199,7 @@ components: num_queues: 5 readonly: false iommu: false - queue_size: 5 + queue_size: 2 vhost_socket: vhost_socket vhost_user: false direct: false @@ -195,8 +211,10 @@ components: devices: - path: path iommu: false + id: id - path: path iommu: false + id: id kernel: path: path rng: @@ -204,15 +222,15 @@ components: src: /dev/urandom fs: - sock: sock - num_queues: 9 - queue_size: 3 - cache_size: 2 + num_queues: 3 + queue_size: 2 + cache_size: 4 dax: true tag: tag - sock: sock - num_queues: 9 - queue_size: 3 - cache_size: 2 + num_queues: 3 + queue_size: 2 + cache_size: 4 dax: true tag: tag vsock: @@ -225,12 +243,14 @@ components: pmem: - mergeable: false file: file - size: 4 + size: 7 iommu: false + discard_writes: false - mergeable: false file: file - size: 4 + size: 7 iommu: false + discard_writes: false cmdline: args: args iommu: false @@ -240,18 +260,18 @@ components: iommu: false net: - tap: tap - num_queues: 2 + num_queues: 7 iommu: false - queue_size: 7 + queue_size: 9 vhost_socket: vhost_socket vhost_user: false ip: 192.168.249.1 mac: mac mask: 255.255.255.0 - tap: tap - num_queues: 2 + num_queues: 7 iommu: false - queue_size: 7 + queue_size: 9 vhost_socket: vhost_socket vhost_user: false ip: 192.168.249.1 @@ -282,12 +302,13 @@ components: mergeable: false file: file size: 1 + hotplug_size: 5 disks: - path: path num_queues: 5 readonly: false iommu: false - queue_size: 5 + queue_size: 2 vhost_socket: vhost_socket vhost_user: false direct: false @@ -297,7 +318,7 @@ components: num_queues: 5 readonly: false iommu: false - queue_size: 5 + queue_size: 2 vhost_socket: vhost_socket vhost_user: false direct: false @@ -309,8 +330,10 @@ components: devices: - path: path iommu: false + id: id - path: path iommu: false + id: id kernel: path: path rng: @@ -318,15 +341,15 @@ components: src: /dev/urandom fs: - sock: sock - num_queues: 9 - queue_size: 3 - cache_size: 2 + num_queues: 3 + queue_size: 2 + cache_size: 4 dax: true tag: tag - sock: sock - num_queues: 9 - queue_size: 3 - cache_size: 2 + num_queues: 3 + queue_size: 2 + cache_size: 4 dax: true tag: tag vsock: @@ -339,12 +362,14 @@ components: pmem: - mergeable: false file: file - size: 4 + size: 7 iommu: false + discard_writes: false - mergeable: false file: file - size: 4 + size: 7 iommu: false + discard_writes: false cmdline: args: args iommu: false @@ -354,18 +379,18 @@ components: iommu: false net: - tap: tap - num_queues: 2 + num_queues: 7 iommu: false - queue_size: 7 + queue_size: 9 vhost_socket: vhost_socket vhost_user: false ip: 192.168.249.1 mac: mac mask: 255.255.255.0 - tap: tap - num_queues: 2 + num_queues: 7 iommu: false - queue_size: 7 + queue_size: 9 vhost_socket: vhost_socket vhost_user: false ip: 192.168.249.1 @@ -439,10 +464,14 @@ components: mergeable: false file: file size: 1 + hotplug_size: 5 properties: size: format: int64 type: integer + hotplug_size: + format: int64 + type: integer file: type: string mergeable: @@ -475,7 +504,7 @@ components: num_queues: 5 readonly: false iommu: false - queue_size: 5 + queue_size: 2 vhost_socket: vhost_socket vhost_user: false direct: false @@ -516,9 +545,9 @@ components: NetConfig: example: tap: tap - num_queues: 2 + num_queues: 7 iommu: false - queue_size: 7 + queue_size: 9 vhost_socket: vhost_socket vhost_user: false ip: 192.168.249.1 @@ -568,9 +597,9 @@ components: FsConfig: example: sock: sock - num_queues: 9 - queue_size: 3 - cache_size: 2 + num_queues: 3 + queue_size: 2 + cache_size: 4 dax: true tag: tag properties: @@ -598,8 +627,9 @@ components: example: mergeable: false file: file - size: 4 + size: 7 iommu: false + discard_writes: false properties: file: type: string @@ -612,6 +642,9 @@ components: mergeable: default: false type: boolean + discard_writes: + default: false + type: boolean required: - file - size @@ -641,12 +674,15 @@ components: example: path: path iommu: false + id: id properties: path: type: string iommu: default: false type: boolean + id: + type: string required: - path type: object @@ -680,6 +716,8 @@ components: minimum: 1 type: integer desired_ram: + description: desired memory ram in bytes + format: int64 type: integer type: object VmAddDevice: @@ -689,3 +727,10 @@ components: path: type: string type: object + VmRemoveDevice: + example: + id: id + properties: + id: + type: string + type: object diff --git a/virtcontainers/pkg/cloud-hypervisor/client/api_default.go b/virtcontainers/pkg/cloud-hypervisor/client/api_default.go index c73202bf7e..87da4ded9b 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/api_default.go +++ b/virtcontainers/pkg/cloud-hypervisor/client/api_default.go @@ -680,6 +680,72 @@ func (a *DefaultApiService) VmInfoGet(ctx _context.Context) (VmInfo, *_nethttp.R return localVarReturnValue, localVarHTTPResponse, nil } +/* +VmRemoveDevicePut Remove a device from the VM + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param vmRemoveDevice The identifier of the device +*/ +func (a *DefaultApiService) VmRemoveDevicePut(ctx _context.Context, vmRemoveDevice VmRemoveDevice) (*_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPut + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/vm.remove-device" + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = &vmRemoveDevice + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + /* VmResizePut Resize the VM * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). diff --git a/virtcontainers/pkg/cloud-hypervisor/client/docs/DefaultApi.md b/virtcontainers/pkg/cloud-hypervisor/client/docs/DefaultApi.md index 74c9e3a3f1..3aafd1396d 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/docs/DefaultApi.md +++ b/virtcontainers/pkg/cloud-hypervisor/client/docs/DefaultApi.md @@ -14,6 +14,7 @@ Method | HTTP request | Description [**ShutdownVMM**](DefaultApi.md#ShutdownVMM) | **Put** /vmm.shutdown | Shuts the cloud-hypervisor VMM. [**VmAddDevicePut**](DefaultApi.md#VmAddDevicePut) | **Put** /vm.add-device | Add a new device to the VM [**VmInfoGet**](DefaultApi.md#VmInfoGet) | **Get** /vm.info | Returns general information about the cloud-hypervisor Virtual Machine (VM) instance. +[**VmRemoveDevicePut**](DefaultApi.md#VmRemoveDevicePut) | **Put** /vm.remove-device | Remove a device from the VM [**VmResizePut**](DefaultApi.md#VmResizePut) | **Put** /vm.resize | Resize the VM [**VmmPingGet**](DefaultApi.md#VmmPingGet) | **Get** /vmm.ping | Ping the VMM to check for API server availability @@ -307,6 +308,38 @@ No authorization required [[Back to README]](../README.md) +## VmRemoveDevicePut + +> VmRemoveDevicePut(ctx, vmRemoveDevice) + +Remove a device from the VM + +### Required Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. +**vmRemoveDevice** | [**VmRemoveDevice**](VmRemoveDevice.md)| The identifier of the device | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: Not defined + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) +[[Back to Model list]](../README.md#documentation-for-models) +[[Back to README]](../README.md) + + ## VmResizePut > VmResizePut(ctx, vmResize) diff --git a/virtcontainers/pkg/cloud-hypervisor/client/docs/DeviceConfig.md b/virtcontainers/pkg/cloud-hypervisor/client/docs/DeviceConfig.md index 8408a8d569..b3fd114bda 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/docs/DeviceConfig.md +++ b/virtcontainers/pkg/cloud-hypervisor/client/docs/DeviceConfig.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Path** | **string** | | **Iommu** | **bool** | | [optional] [default to false] +**Id** | **string** | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/virtcontainers/pkg/cloud-hypervisor/client/docs/MemoryConfig.md b/virtcontainers/pkg/cloud-hypervisor/client/docs/MemoryConfig.md index caf8720566..4934190083 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/docs/MemoryConfig.md +++ b/virtcontainers/pkg/cloud-hypervisor/client/docs/MemoryConfig.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Size** | **int64** | | +**HotplugSize** | **int64** | | [optional] **File** | **string** | | [optional] **Mergeable** | **bool** | | [optional] [default to false] diff --git a/virtcontainers/pkg/cloud-hypervisor/client/docs/PmemConfig.md b/virtcontainers/pkg/cloud-hypervisor/client/docs/PmemConfig.md index 62d7164e9b..a84de72ae6 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/docs/PmemConfig.md +++ b/virtcontainers/pkg/cloud-hypervisor/client/docs/PmemConfig.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **Size** | **int64** | | **Iommu** | **bool** | | [optional] [default to false] **Mergeable** | **bool** | | [optional] [default to false] +**DiscardWrites** | **bool** | | [optional] [default to false] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/virtcontainers/pkg/cloud-hypervisor/client/docs/VmRemoveDevice.md b/virtcontainers/pkg/cloud-hypervisor/client/docs/VmRemoveDevice.md new file mode 100644 index 0000000000..07c5a78f11 --- /dev/null +++ b/virtcontainers/pkg/cloud-hypervisor/client/docs/VmRemoveDevice.md @@ -0,0 +1,11 @@ +# VmRemoveDevice + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/virtcontainers/pkg/cloud-hypervisor/client/docs/VmResize.md b/virtcontainers/pkg/cloud-hypervisor/client/docs/VmResize.md index 252a74bbff..0adf6f7167 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/docs/VmResize.md +++ b/virtcontainers/pkg/cloud-hypervisor/client/docs/VmResize.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **DesiredVcpus** | **int32** | | [optional] -**DesiredRam** | **int32** | | [optional] +**DesiredRam** | **int64** | desired memory ram in bytes | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/virtcontainers/pkg/cloud-hypervisor/client/model_device_config.go b/virtcontainers/pkg/cloud-hypervisor/client/model_device_config.go index 4f2ab08ecf..d0fa7d6e1a 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/model_device_config.go +++ b/virtcontainers/pkg/cloud-hypervisor/client/model_device_config.go @@ -12,4 +12,5 @@ package openapi type DeviceConfig struct { Path string `json:"path"` Iommu bool `json:"iommu,omitempty"` + Id string `json:"id,omitempty"` } diff --git a/virtcontainers/pkg/cloud-hypervisor/client/model_memory_config.go b/virtcontainers/pkg/cloud-hypervisor/client/model_memory_config.go index ad1a888813..e96e903209 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/model_memory_config.go +++ b/virtcontainers/pkg/cloud-hypervisor/client/model_memory_config.go @@ -11,6 +11,7 @@ package openapi // MemoryConfig struct for MemoryConfig type MemoryConfig struct { Size int64 `json:"size"` + HotplugSize int64 `json:"hotplug_size,omitempty"` File string `json:"file,omitempty"` Mergeable bool `json:"mergeable,omitempty"` } diff --git a/virtcontainers/pkg/cloud-hypervisor/client/model_pmem_config.go b/virtcontainers/pkg/cloud-hypervisor/client/model_pmem_config.go index 4732ce997d..a1a26ff778 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/model_pmem_config.go +++ b/virtcontainers/pkg/cloud-hypervisor/client/model_pmem_config.go @@ -14,4 +14,5 @@ type PmemConfig struct { Size int64 `json:"size"` Iommu bool `json:"iommu,omitempty"` Mergeable bool `json:"mergeable,omitempty"` + DiscardWrites bool `json:"discard_writes,omitempty"` } diff --git a/virtcontainers/pkg/cloud-hypervisor/client/model_vm_remove_device.go b/virtcontainers/pkg/cloud-hypervisor/client/model_vm_remove_device.go new file mode 100644 index 0000000000..4a0cb6cf2c --- /dev/null +++ b/virtcontainers/pkg/cloud-hypervisor/client/model_vm_remove_device.go @@ -0,0 +1,14 @@ +/* + * Cloud Hypervisor API + * + * Local HTTP based API for managing and inspecting a cloud-hypervisor virtual machine. + * + * API version: 0.3.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package openapi +// VmRemoveDevice struct for VmRemoveDevice +type VmRemoveDevice struct { + Id string `json:"id,omitempty"` +} diff --git a/virtcontainers/pkg/cloud-hypervisor/client/model_vm_resize.go b/virtcontainers/pkg/cloud-hypervisor/client/model_vm_resize.go index 0747108e3c..ec0e4e9db0 100644 --- a/virtcontainers/pkg/cloud-hypervisor/client/model_vm_resize.go +++ b/virtcontainers/pkg/cloud-hypervisor/client/model_vm_resize.go @@ -11,5 +11,6 @@ package openapi // VmResize struct for VmResize type VmResize struct { DesiredVcpus int32 `json:"desired_vcpus,omitempty"` - DesiredRam int32 `json:"desired_ram,omitempty"` + // desired memory ram in bytes + DesiredRam int64 `json:"desired_ram,omitempty"` } diff --git a/virtcontainers/pkg/cloud-hypervisor/cloud-hypervisor.yaml b/virtcontainers/pkg/cloud-hypervisor/cloud-hypervisor.yaml index fdbc088671..fb3ec6dc6f 100644 --- a/virtcontainers/pkg/cloud-hypervisor/cloud-hypervisor.yaml +++ b/virtcontainers/pkg/cloud-hypervisor/cloud-hypervisor.yaml @@ -155,6 +155,22 @@ paths: 404: description: The new device could not be added to the VM instance. + /vm.remove-device: + put: + summary: Remove a device from the VM + requestBody: + description: The identifier of the device + content: + application/json: + schema: + $ref: '#/components/schemas/VmRemoveDevice' + required: true + responses: + 204: + description: The device was successfully removed from the VM instance. + 404: + description: The device could not be removed from the VM instance. + components: schemas: @@ -253,6 +269,9 @@ components: type: integer format: int64 default: 512 MB + hotplug_size: + type: integer + format: int64 file: type: string mergeable: @@ -391,6 +410,9 @@ components: mergeable: type: boolean default: false + discard_writes: + type: boolean + default: false ConsoleConfig: required: @@ -416,6 +438,8 @@ components: iommu: type: boolean default: false + id: + type: string VsockConfig: required: @@ -442,10 +466,18 @@ components: minimum: 1 type: integer desired_ram: + description: desired memory ram in bytes type: integer + format: int64 VmAddDevice: type: object properties: path: type: string + + VmRemoveDevice: + type: object + properties: + id: + type: string From 5e7d25385917061f502d213b39f54ee1603d874f Mon Sep 17 00:00:00 2001 From: Jose Carlos Venegas Munoz Date: Tue, 24 Mar 2020 20:43:07 +0000 Subject: [PATCH 2/5] clh: add vmInfo method API VMInfo call is done more than one time. This leads to have similar code in multiple times, create context, defer, do call. Move the logic to one function. Signed-off-by: Jose Carlos Venegas Munoz --- virtcontainers/clh.go | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/virtcontainers/clh.go b/virtcontainers/clh.go index 10a6048a0c..4e411bb9e7 100644 --- a/virtcontainers/clh.go +++ b/virtcontainers/clh.go @@ -432,14 +432,11 @@ func (clh *cloudHypervisor) resizeVCPUs(reqVCPUs uint32) (currentVCPUs uint32, n cl := clh.client() // Retrieve the number of current vCPUs via HTTP API - ctx, cancel := context.WithTimeout(context.Background(), clhAPITimeout*time.Second) - info, _, err := cl.VmInfoGet(ctx) + info, err := clh.vmInfo() if err != nil { - clh.Logger().WithField("function", "resizeVCPUs").WithError(openAPIClientError(err)).Info("[clh] VmInfoGet failed") + clh.Logger().WithField("function", "resizeVCPUs").WithError(err).Info("[clh] vmInfo failed") return 0, 0, openAPIClientError(err) } - // Reset the timer after the first HTTP API call - cancel() currentVCPUs = uint32(info.Config.Cpus.BootVcpus) newVCPUs = currentVCPUs @@ -461,7 +458,7 @@ func (clh *cloudHypervisor) resizeVCPUs(reqVCPUs uint32) (currentVCPUs uint32, n } // Resize (hot-plug) vCPUs via HTTP API - ctx, cancel = context.WithTimeout(context.Background(), clhAPITimeout*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), clhAPITimeout*time.Second) defer cancel() if _, err = cl.VmResizePut(ctx, chclient.VmResize{DesiredVcpus: int32(reqVCPUs)}); err != nil { return currentVCPUs, newVCPUs, errors.Wrap(err, "[clh] VmResizePut failed") @@ -960,10 +957,10 @@ func (clh *cloudHypervisor) bootVM(ctx context.Context) error { return openAPIClientError(err) } - info, _, err := cl.VmInfoGet(ctx) + info, err := clh.vmInfo() if err != nil { - return openAPIClientError(err) + return err } clh.Logger().Debugf("VM state after create: %#v", info) @@ -979,10 +976,10 @@ func (clh *cloudHypervisor) bootVM(ctx context.Context) error { return openAPIClientError(err) } - info, _, err = cl.VmInfoGet(ctx) + info, err = clh.vmInfo() if err != nil { - return openAPIClientError(err) + return err } clh.Logger().Debugf("VM state after boot: %#v", info) @@ -1120,3 +1117,17 @@ func (clh *cloudHypervisor) cleanupVM(force bool) error { return nil } + +// vmInfo ask to hypervisor for current VM status +func (clh *cloudHypervisor) vmInfo() (chclient.VmInfo, error) { + cl := clh.client() + ctx, cancelInfo := context.WithTimeout(context.Background(), clhAPITimeout*time.Second) + defer cancelInfo() + + info, _, err := cl.VmInfoGet(ctx) + if err != nil { + clh.Logger().WithError(openAPIClientError(err)).Warn("VmInfoGet failed") + } + return info, openAPIClientError(err) + +} From b6a7d8d63a23aedbe9baa06a2a833217db94b01a Mon Sep 17 00:00:00 2001 From: Jose Carlos Venegas Munoz Date: Tue, 24 Mar 2020 23:27:47 +0000 Subject: [PATCH 3/5] utils: Add memory unit abstraction Add MemUnit to help to manage memory, this will handle memory units internally and provide proper methods to convert to different units. Signed-off-by: Jose Carlos Venegas Munoz --- virtcontainers/utils/utils.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/virtcontainers/utils/utils.go b/virtcontainers/utils/utils.go index 6be68f4286..85c554896a 100644 --- a/virtcontainers/utils/utils.go +++ b/virtcontainers/utils/utils.go @@ -240,3 +240,38 @@ func SupportsVsocks() bool { var StartCmd = func(c *exec.Cmd) error { return c.Start() } + +// AlignMem align memory provided to a block size +func (m MemUnit) AlignMem(blockSize MemUnit) MemUnit { + memSize := m + if m < blockSize { + memSize = blockSize + + } + + remainder := memSize % blockSize + + if remainder != 0 { + // Align memory to memoryBlockSizeMB + memSize += blockSize - remainder + + } + return memSize +} + +type MemUnit uint64 + +func (m MemUnit) ToMiB() uint64 { + return m.ToBytes() / (1 * MiB).ToBytes() +} + +func (m MemUnit) ToBytes() uint64 { + return uint64(m) +} + +const ( + Byte MemUnit = 1 + KiB = Byte << 10 + MiB = KiB << 10 + GiB = MiB << 10 +) From 2f948738e48ed9badeb5383f3105aec5ea923d30 Mon Sep 17 00:00:00 2001 From: Jose Carlos Venegas Munoz Date: Tue, 24 Mar 2020 23:31:55 +0000 Subject: [PATCH 4/5] clh: Use MemUnit to create VM Provide memory in bytes using the new memory unit abstraction. Signed-off-by: Jose Carlos Venegas Munoz --- virtcontainers/clh.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/virtcontainers/clh.go b/virtcontainers/clh.go index 4e411bb9e7..5989432107 100644 --- a/virtcontainers/clh.go +++ b/virtcontainers/clh.go @@ -214,7 +214,8 @@ func (clh *cloudHypervisor) createSandbox(ctx context.Context, id string, networ clh.Logger().WithField("function", "createSandbox").WithError(err).Info("Sandbox not found creating ") // Set initial memomory size of the virtual machine - clh.vmconfig.Memory.Size = int64(clh.config.MemorySize) << utils.MibToBytesShift + // Convert to int64 openApiClient only support int64 + clh.vmconfig.Memory.Size = int64((utils.MemUnit(clh.config.MemorySize) * utils.MiB).ToBytes()) clh.vmconfig.Memory.File = "/dev/shm" // Set initial amount of cpu's for the virtual machine clh.vmconfig.Cpus = chclient.CpusConfig{ From aab82f67459a179f90f617b0947c666b6dc8fc46 Mon Sep 17 00:00:00 2001 From: Jose Carlos Venegas Munoz Date: Tue, 24 Mar 2020 23:33:50 +0000 Subject: [PATCH 5/5] clh: Add memory hotplug Request memory to resize memory to hypervisor. Depends-on: github.com/kata-containers/tests#2413 Fixes: #2526 Signed-off-by: Jose Carlos Venegas Munoz --- virtcontainers/clh.go | 71 ++++++++++++++++++++++++++++++++++++-- virtcontainers/clh_test.go | 61 ++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 2 deletions(-) diff --git a/virtcontainers/clh.go b/virtcontainers/clh.go index 5989432107..588d4b9278 100644 --- a/virtcontainers/clh.go +++ b/virtcontainers/clh.go @@ -217,6 +217,13 @@ func (clh *cloudHypervisor) createSandbox(ctx context.Context, id string, networ // Convert to int64 openApiClient only support int64 clh.vmconfig.Memory.Size = int64((utils.MemUnit(clh.config.MemorySize) * utils.MiB).ToBytes()) clh.vmconfig.Memory.File = "/dev/shm" + hostMemKb, err := getHostMemorySizeKb(procMemInfo) + if err != nil { + return nil + } + + // OpenAPI only supports int64 values + clh.vmconfig.Memory.HotplugSize = int64((utils.MemUnit(hostMemKb) * utils.KiB).ToBytes()) // Set initial amount of cpu's for the virtual machine clh.vmconfig.Cpus = chclient.CpusConfig{ // cast to int32, as openAPI has a limitation that it does not support unsigned values @@ -425,8 +432,68 @@ func (clh *cloudHypervisor) hypervisorConfig() HypervisorConfig { } func (clh *cloudHypervisor) resizeMemory(reqMemMB uint32, memoryBlockSizeMB uint32, probe bool) (uint32, memoryDevice, error) { - clh.Logger().WithField("function", "resizeMemory").Warn("not supported") - return 0, memoryDevice{}, nil + + // TODO: Add support for virtio-mem + + if probe { + return 0, memoryDevice{}, errors.New("probe memory is not supported for cloud-hypervisor") + } + + if reqMemMB == 0 { + // This is a corner case if requested to resize to 0 means something went really wrong. + return 0, memoryDevice{}, errors.New("Can not resize memory to 0") + } + + info, err := clh.vmInfo() + if err != nil { + return 0, memoryDevice{}, err + } + + currentMem := utils.MemUnit(info.Config.Memory.Size) * utils.Byte + newMem := utils.MemUnit(reqMemMB) * utils.MiB + + // Early check to verify if boot memory is the same as requested + if currentMem == newMem { + clh.Logger().WithField("memory", reqMemMB).Debugf("VM already has requested memory") + return uint32(currentMem.ToMiB()), memoryDevice{}, nil + } + + if currentMem > newMem { + clh.Logger().Warn("Remove memory is not supported, nothing to do") + return uint32(currentMem.ToMiB()), memoryDevice{}, nil + } + + blockSize := utils.MemUnit(memoryBlockSizeMB) * utils.MiB + hotplugSize := (newMem - currentMem).AlignMem(blockSize) + + // Update memory request to increase memory aligned block + alignedRequest := currentMem + hotplugSize + if newMem != alignedRequest { + clh.Logger().WithFields(log.Fields{"request": newMem, "aligned-request": alignedRequest}).Debug("aligning VM memory request") + newMem = alignedRequest + } + + // Check if memory is the same as requested, a second check is done + // to consider the memory request now that is updated to be memory aligned + if currentMem == newMem { + clh.Logger().WithFields(log.Fields{"current-memory": currentMem, "new-memory": newMem}).Debug("VM already has requested memory(after alignment)") + return uint32(currentMem.ToMiB()), memoryDevice{}, nil + } + + cl := clh.client() + ctx, cancelResize := context.WithTimeout(context.Background(), clhAPITimeout*time.Second) + defer cancelResize() + + // OpenApi does not support uint64, convert to int64 + resize := chclient.VmResize{DesiredRam: int64(newMem.ToBytes())} + clh.Logger().WithFields(log.Fields{"current-memory": currentMem, "new-memory": newMem}).Debug("updating VM memory") + if _, err = cl.VmResizePut(ctx, resize); err != nil { + clh.Logger().WithFields(log.Fields{"current-memory": currentMem, "new-memory": newMem}).Warnf("failed to update memory %s", openAPIClientError(err)) + err = fmt.Errorf("Failed to resize memory from %d to %d: %s", currentMem, newMem, openAPIClientError(err)) + return uint32(currentMem.ToMiB()), memoryDevice{}, openAPIClientError(err) + } + + return uint32(newMem.ToMiB()), memoryDevice{sizeMB: int(hotplugSize.ToMiB())}, nil } func (clh *cloudHypervisor) resizeVCPUs(reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) { diff --git a/virtcontainers/clh_test.go b/virtcontainers/clh_test.go index 7668e1c7b6..86ff9a1c2f 100644 --- a/virtcontainers/clh_test.go +++ b/virtcontainers/clh_test.go @@ -10,15 +10,22 @@ import ( "net/http" "os" "path/filepath" + "reflect" "testing" "github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/persist" chclient "github.com/kata-containers/runtime/virtcontainers/pkg/cloud-hypervisor/client" + "github.com/kata-containers/runtime/virtcontainers/utils" "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) +const ( + FAIL = true + PASS = !FAIL +) + func newClhConfig() (HypervisorConfig, error) { setupClh() @@ -255,3 +262,57 @@ func TestClooudHypervisorStartSandbox(t *testing.T) { err = clh.startSandbox(10) assert.NoError(err) } + +func TestCloudHypervisorResizeMemory(t *testing.T) { + assert := assert.New(t) + clhConfig, err := newClhConfig() + type args struct { + reqMemMB uint32 + memoryBlockSizeMB uint32 + } + tests := []struct { + name string + args args + expectedMemDev memoryDevice + wantErr bool + }{ + {"Resize to zero", args{0, 128}, memoryDevice{probe: false, sizeMB: 0}, FAIL}, + {"Resize to aligned size", args{clhConfig.MemorySize + 128, 128}, memoryDevice{probe: false, sizeMB: 128}, PASS}, + {"Resize to aligned size", args{clhConfig.MemorySize + 129, 128}, memoryDevice{probe: false, sizeMB: 256}, PASS}, + {"Resize to NOT aligned size", args{clhConfig.MemorySize + 125, 128}, memoryDevice{probe: false, sizeMB: 128}, PASS}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.NoError(err) + clh := cloudHypervisor{} + + mockClient := &clhClientMock{} + mockClient.vmInfo.Config.Memory.Size = int64(utils.MemUnit(clhConfig.MemorySize) * utils.MiB) + mockClient.vmInfo.Config.Memory.HotplugSize = int64(40 * utils.GiB.ToBytes()) + + clh.APIClient = mockClient + clh.config = clhConfig + + newMem, memDev, err := clh.resizeMemory(tt.args.reqMemMB, tt.args.memoryBlockSizeMB, false) + + if (err != nil) != tt.wantErr { + t.Errorf("cloudHypervisor.resizeMemory() error = %v, expected to fail = %v", err, tt.wantErr) + return + } + + if err != nil { + return + } + + expectedMem := clhConfig.MemorySize + uint32(tt.expectedMemDev.sizeMB) + + if newMem != expectedMem { + t.Errorf("cloudHypervisor.resizeMemory() got = %+v, want %+v", newMem, expectedMem) + } + + if !reflect.DeepEqual(memDev, tt.expectedMemDev) { + t.Errorf("cloudHypervisor.resizeMemory() got = %+v, want %+v", memDev, tt.expectedMemDev) + } + }) + } +}