diff --git a/api/apps/v1alpha1/vmdisk/types.go b/api/apps/v1alpha1/vmdisk/types.go index aefac1e4..c493f49c 100644 --- a/api/apps/v1alpha1/vmdisk/types.go +++ b/api/apps/v1alpha1/vmdisk/types.go @@ -32,21 +32,28 @@ type ConfigSpec struct { } type Source struct { + // Clone an existing vm-disk. + Disk *SourceDisk `json:"disk,omitempty"` // Download image from an HTTP source. Http *SourceHTTP `json:"http,omitempty"` - // Use image by name. + // Use image by name from default collection. Image *SourceImage `json:"image,omitempty"` // Upload local image. Upload *SourceUpload `json:"upload,omitempty"` } +type SourceDisk struct { + // Name of the vm-disk to clone. + Name string `json:"name"` +} + type SourceHTTP struct { // URL to download the image. Url string `json:"url"` } type SourceImage struct { - // Name of the image to use (uploaded as "golden image" or from the list: `ubuntu`, `fedora`, `cirros`, `alpine`, `talos`). + // Name of the image to use. Name string `json:"name"` } diff --git a/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go b/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go index e8ca986e..301bb1d9 100644 --- a/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go +++ b/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go @@ -70,6 +70,11 @@ func (in *ConfigSpec) DeepCopy() *ConfigSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Source) DeepCopyInto(out *Source) { *out = *in + if in.Disk != nil { + in, out := &in.Disk, &out.Disk + *out = new(SourceDisk) + **out = **in + } if in.Http != nil { in, out := &in.Http, &out.Http *out = new(SourceHTTP) @@ -97,6 +102,21 @@ func (in *Source) DeepCopy() *Source { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SourceDisk) DeepCopyInto(out *SourceDisk) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceDisk. +func (in *SourceDisk) DeepCopy() *SourceDisk { + if in == nil { + return nil + } + out := new(SourceDisk) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SourceHTTP) DeepCopyInto(out *SourceHTTP) { *out = *in diff --git a/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go b/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go index 00b2a710..86d5ddfc 100644 --- a/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go +++ b/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go @@ -63,9 +63,14 @@ func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { *out = make([]Disk, len(*in)) copy(*out, *in) } + if in.Networks != nil { + in, out := &in.Networks, &out.Networks + *out = make([]Network, len(*in)) + copy(*out, *in) + } if in.Subnets != nil { in, out := &in.Subnets, &out.Subnets - *out = make([]Subnet, len(*in)) + *out = make([]Network, len(*in)) copy(*out, *in) } if in.Gpus != nil { @@ -121,6 +126,21 @@ func (in *GPU) DeepCopy() *GPU { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Network) DeepCopyInto(out *Network) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network. +func (in *Network) DeepCopy() *Network { + if in == nil { + return nil + } + out := new(Network) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Resources) DeepCopyInto(out *Resources) { *out = *in @@ -138,18 +158,3 @@ func (in *Resources) DeepCopy() *Resources { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Subnet) DeepCopyInto(out *Subnet) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subnet. -func (in *Subnet) DeepCopy() *Subnet { - if in == nil { - return nil - } - out := new(Subnet) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go b/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go index cd718167..3cda29c4 100644 --- a/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go +++ b/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go @@ -58,6 +58,16 @@ func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { *out = make([]Subnet, len(*in)) copy(*out, *in) } + if in.Peers != nil { + in, out := &in.Peers, &out.Peers + *out = make([]Peer, len(*in)) + copy(*out, *in) + } + if in.Routes != nil { + in, out := &in.Routes, &out.Routes + *out = make([]Route, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. @@ -70,6 +80,36 @@ func (in *ConfigSpec) DeepCopy() *ConfigSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Peer) DeepCopyInto(out *Peer) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Peer. +func (in *Peer) DeepCopy() *Peer { + if in == nil { + return nil + } + out := new(Peer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Route) DeepCopyInto(out *Route) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. +func (in *Route) DeepCopy() *Route { + if in == nil { + return nil + } + out := new(Route) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Subnet) DeepCopyInto(out *Subnet) { *out = *in diff --git a/api/backups/v1alpha1/zz_generated.deepcopy.go b/api/backups/v1alpha1/zz_generated.deepcopy.go index b7387772..89f6171f 100644 --- a/api/backups/v1alpha1/zz_generated.deepcopy.go +++ b/api/backups/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,21 @@ //go:build !ignore_autogenerated +/* +Copyright 2025 The Cozystack Authors. + +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. +*/ + // Code generated by controller-gen. DO NOT EDIT. package v1alpha1 @@ -645,4 +661,3 @@ func (in *RestoreJobStatus) DeepCopy() *RestoreJobStatus { in.DeepCopyInto(out) return out } - diff --git a/hack/cdi_golden_image_create.sh b/hack/cdi_golden_image_create.sh index be1558d0..f19f9970 100644 --- a/hack/cdi_golden_image_create.sh +++ b/hack/cdi_golden_image_create.sh @@ -16,7 +16,7 @@ kubectl create -f - < 39 +# Rename DataVolumes/PVCs in cozy-public from vm-image- to vm-default-images-. +# +# The vm-disk package previously looked up golden images with the prefix "vm-image-". +# The new vm-default-images package uses the prefix "vm-default-images-". +# This migration renames any existing DataVolumes so that live vm-disk resources +# continue to resolve their source PVC after upgrade. + +set -euo pipefail + +NAMESPACE="cozy-public" + +# Skip if CDI DataVolume CRD is not installed +if ! kubectl api-resources --api-group=cdi.kubevirt.io -o name 2>/dev/null | grep -q '^datavolumes\.'; then + echo "CDI DataVolume CRD not found, skipping rename" + kubectl create configmap -n cozy-system cozystack-version \ + --from-literal=version=39 --dry-run=client -o yaml | kubectl apply -f- + exit 0 +fi + +# Find DataVolumes whose name starts with "vm-image-" +DVNAMES=$(kubectl get datavolumes.cdi.kubevirt.io -n "$NAMESPACE" \ + -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null \ + | grep '^vm-image-' || true) + +if [ -z "$DVNAMES" ]; then + echo "No vm-image-* DataVolumes found in $NAMESPACE, nothing to rename" +else + for DVNAME in $DVNAMES; do + NEWNAME="vm-default-images-${DVNAME#vm-image-}" + echo "Renaming DataVolume $DVNAME -> $NEWNAME in namespace $NAMESPACE" + + # Export existing DV spec, swap name, and apply as new object + kubectl get datavolumes.cdi.kubevirt.io -n "$NAMESPACE" "$DVNAME" -o json \ + | jq --arg new "$NEWNAME" ' + del(.metadata.resourceVersion, .metadata.uid, .metadata.creationTimestamp, + .metadata.generation, .metadata.selfLink, .metadata.managedFields, + .status) + | .metadata.name = $new + ' \ + | kubectl apply -f - + + # Delete the old DataVolume + kubectl delete datavolumes.cdi.kubevirt.io -n "$NAMESPACE" "$DVNAME" --ignore-not-found=true + echo "Renamed $DVNAME -> $NEWNAME" + done +fi + +# Stamp version +kubectl create configmap -n cozy-system cozystack-version \ + --from-literal=version=39 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/sources/vm-default-images.yaml b/packages/core/platform/sources/vm-default-images.yaml new file mode 100644 index 00000000..16cd6a94 --- /dev/null +++ b/packages/core/platform/sources/vm-default-images.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.vm-default-images +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.kubevirt-cdi + components: + - name: vm-default-images + path: system/vm-default-images + install: + namespace: cozy-system + releaseName: vm-default-images diff --git a/packages/core/platform/templates/bundles/iaas.yaml b/packages/core/platform/templates/bundles/iaas.yaml index bd002c16..ced0a322 100644 --- a/packages/core/platform/templates/bundles/iaas.yaml +++ b/packages/core/platform/templates/bundles/iaas.yaml @@ -8,6 +8,7 @@ {{- end -}} {{include "cozystack.platform.package" (list "cozystack.kubevirt" "default" $ $kubevirtComponents) }} {{include "cozystack.platform.package.default" (list "cozystack.kubevirt-cdi" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.vm-default-images" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.gpu-operator" $) }} {{include "cozystack.platform.package.default" (list "cozystack.kamaji" $) }} {{include "cozystack.platform.package.default" (list "cozystack.capi-operator" $) }} diff --git a/packages/core/platform/values.yaml b/packages/core/platform/values.yaml index 77eb00d7..c21b4f35 100644 --- a/packages/core/platform/values.yaml +++ b/packages/core/platform/values.yaml @@ -6,7 +6,7 @@ sourceRef: migrations: enabled: false image: ghcr.io/cozystack/cozystack/platform-migrations:v1.2.1@sha256:e8fcf006a4451fc0e961455e9b27a61b7103ee49b1a81fe5e4662ffed093fad6 - targetVersion: 38 + targetVersion: 39 # Bundle deployment configuration bundles: system: diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml index 6e031a84..d48df533 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml @@ -142,14 +142,6 @@ spec: required: - uri type: object - underlyingResources: - description: |- - Holds application-specific resource metadata discovered during backup. - The payload is a self-typed JSON object carrying an inlined TypeMeta - (kind/apiVersion) so the consuming controller can dispatch on the - application kind. - type: object - x-kubernetes-preserve-unknown-fields: true conditions: description: Conditions represents the latest available observations of a Backup's state. @@ -213,6 +205,14 @@ spec: Phase is a simple, high-level summary of the backup's state. Typical values are: Pending, Ready, Failed. type: string + underlyingResources: + description: |- + UnderlyingResources holds application-specific resource metadata discovered + during backup (e.g., VM disks, network configuration). The payload is a + self-typed JSON object carrying an inlined TypeMeta (kind/apiVersion) so + the consuming controller can dispatch on the application kind. + type: object + x-kubernetes-preserve-unknown-fields: true type: object type: object selectableFields: diff --git a/packages/system/vm-default-images/Chart.yaml b/packages/system/vm-default-images/Chart.yaml new file mode 100644 index 00000000..aac0ccca --- /dev/null +++ b/packages/system/vm-default-images/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: vm-default-images +description: Global Golden Image collection for virtual machines +type: application +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/vm-default-images/Makefile b/packages/system/vm-default-images/Makefile new file mode 100644 index 00000000..a3f9fac7 --- /dev/null +++ b/packages/system/vm-default-images/Makefile @@ -0,0 +1,4 @@ +export NAME=vm-default-images +export NAMESPACE=cozy-system + +include ../../../hack/package.mk diff --git a/packages/system/vm-default-images/templates/dv.yaml b/packages/system/vm-default-images/templates/dv.yaml new file mode 100644 index 00000000..84b9a758 --- /dev/null +++ b/packages/system/vm-default-images/templates/dv.yaml @@ -0,0 +1,45 @@ +{{- range .Values.images }} +--- +apiVersion: cdi.kubevirt.io/v1beta1 +kind: DataVolume +metadata: + annotations: + vm-default-images.cozystack.io/name: {{ .name | quote }} + {{- with .os }} + {{- with .family }} + vm-default-images.cozystack.io/os-family: {{ . | quote }} + {{- end }} + {{- with .name }} + vm-default-images.cozystack.io/os-name: {{ . | quote }} + {{- end }} + {{- with .version }} + vm-default-images.cozystack.io/os-version: {{ . | quote }} + {{- end }} + {{- end }} + {{- with .architecture }} + vm-default-images.cozystack.io/architecture: {{ . | quote }} + {{- end }} + {{- with .description }} + vm-default-images.cozystack.io/description: {{ . | quote }} + {{- end }} + cdi.kubevirt.io/storage.bind.immediate.requested: "true" + cdi.kubevirt.io/storage.usePopulator: "true" + labels: + app.kubernetes.io/managed-by: cozystack + name: vm-default-images-{{ required "A valid .name entry required for each image!" .name }} + namespace: cozy-public +spec: + contentType: kubevirt + source: + http: + url: {{ required (printf "A valid .url entry required for image '%s'!" .name) .url | quote }} + storage: + resources: + requests: + storage: {{ default "5Gi" .storage }} + {{- if .storageClass }} + storageClassName: {{ .storageClass }} + {{- else if $.Values.storageClass }} + storageClassName: {{ $.Values.storageClass }} + {{- end }} +{{- end }} diff --git a/packages/system/vm-default-images/values.yaml b/packages/system/vm-default-images/values.yaml new file mode 100644 index 00000000..9d777f0b --- /dev/null +++ b/packages/system/vm-default-images/values.yaml @@ -0,0 +1,169 @@ +## +## @section Global Golden Image Collection +## + +## @param {string} storageClass - Default StorageClass for all images. If empty, uses the cluster default StorageClass. +## NOTE: The default set of images requires approximately 320Gi of storage (16 images × 20Gi each). +## Adjust the image list or per-image storage sizes to match your cluster capacity. +storageClass: "replicated" + +## @typedef {struct} ImageOS - Operating system metadata for a Golden Image. +## @field {string} [family] - OS family (e.g. "Linux", "Windows"). +## @field {string} [name] - OS distribution name (e.g. "Ubuntu", "Fedora"). +## @field {string} [version] - OS version (e.g. "24.04", "40"). + +## @typedef {struct} GlobalImage - A global Golden Image entry. +## @field {string} name - Unique image name used to reference this image in vm-disk (e.g. "ubuntu"). +## @field {string} url - HTTP(S) URL to download the image from. +## @field {quantity} storage - Storage size to allocate for this image. +## @field {string} storageClass - StorageClass used to store the image (overrides global default). +## @field {ImageOS} [os] - Operating system metadata. +## @field {string} [architecture] - CPU architecture (e.g. "amd64", "arm64"). +## @field {string} [description] - Human-readable description. + +## @param {[]GlobalImage} images - List of global Golden Images to provision in the cozy-public namespace. +images: + - name: ubuntu-22.04 + url: https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img + storage: 20Gi + os: + family: Linux + name: Ubuntu + version: "22.04" + architecture: amd64 + description: "Ubuntu 22.04 LTS (Jammy Jellyfish) cloud image" + - name: ubuntu-24.04 + url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img + storage: 20Gi + os: + family: Linux + name: Ubuntu + version: "24.04" + architecture: amd64 + description: "Ubuntu 24.04 LTS (Noble Numbat) cloud image" + - name: rocky-8 + url: https://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base.latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: Rocky Linux + version: "8" + architecture: amd64 + description: "Rocky Linux 8 GenericCloud image" + - name: rocky-9 + url: https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: Rocky Linux + version: "9" + architecture: amd64 + description: "Rocky Linux 9 GenericCloud image" + - name: rocky-10 + url: https://dl.rockylinux.org/pub/rocky/10/images/x86_64/Rocky-10-GenericCloud-Base.latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: Rocky Linux + version: "10" + architecture: amd64 + description: "Rocky Linux 10 GenericCloud image" + - name: almalinux-8 + url: https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: AlmaLinux + version: "8" + architecture: amd64 + description: "AlmaLinux 8 GenericCloud image" + - name: almalinux-9 + url: https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: AlmaLinux + version: "9" + architecture: amd64 + description: "AlmaLinux 9 GenericCloud image" + - name: almalinux-10 + url: https://repo.almalinux.org/almalinux/10/cloud/x86_64/images/AlmaLinux-10-GenericCloud-latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: AlmaLinux + version: "10" + architecture: amd64 + description: "AlmaLinux 10 GenericCloud image" + - name: debian-12 + url: https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2 + storage: 20Gi + os: + family: Linux + name: Debian + version: "12" + architecture: amd64 + description: "Debian 12 (Bookworm) generic cloud image" + - name: debian-13 + url: https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2 + storage: 20Gi + os: + family: Linux + name: Debian + version: "13" + architecture: amd64 + description: "Debian 13 (Trixie) generic cloud image" + - name: centos-stream-9 + url: https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: CentOS + version: "9" + architecture: amd64 + description: "CentOS Stream 9 GenericCloud image" + - name: centos-stream-10 + url: https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-GenericCloud-10-latest.x86_64.qcow2 + storage: 20Gi + os: + family: Linux + name: CentOS + version: "10" + architecture: amd64 + description: "CentOS Stream 10 GenericCloud image" + - name: opensuse-leap-15.6 + url: https://download.opensuse.org/repositories/Cloud:/Images:/Leap_15.6/images/openSUSE-Leap-15.6.x86_64-NoCloud.qcow2 + storage: 20Gi + os: + family: Linux + name: openSUSE + version: "15.6" + architecture: amd64 + description: "openSUSE Leap 15.6 NoCloud image" + - name: opensuse-leap-16.0 + url: https://download.opensuse.org/repositories/openSUSE:/Leap:/16.0:/Images/images/Leap-16.0-Minimal-VM.x86_64-Cloud.qcow2 + storage: 20Gi + os: + family: Linux + name: openSUSE + version: "16.0" + architecture: amd64 + description: "openSUSE Leap 16.0 Minimal VM cloud image" + - name: ubuntu-20.04 + url: https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img + storage: 20Gi + os: + family: Linux + name: Ubuntu + version: "20.04" + architecture: amd64 + description: "Ubuntu 20.04 LTS (Focal Fossa) cloud image" + - name: alpine-3.21 + url: https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/nocloud_alpine-3.21.6-x86_64-bios-cloudinit-r0.qcow2 + storage: 20Gi + os: + family: Linux + name: Alpine + version: "3.21" + architecture: amd64 + description: "Alpine Linux 3.21 cloud image (cloud-init)" diff --git a/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml b/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml index 4d0d7e37..3ce046ed 100644 --- a/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml +++ b/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml @@ -8,7 +8,7 @@ spec: singular: vmdisk plural: vmdisks openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"source":{"description":"The source image location used to create a disk.","type":"object","default":{},"properties":{"http":{"description":"Download image from an HTTP source.","type":"object","required":["url"],"properties":{"url":{"description":"URL to download the image.","type":"string"}}},"image":{"description":"Use image by name.","type":"object","required":["name"],"properties":{"name":{"description":"Name of the image to use (uploaded as \"golden image\" or from the list: `ubuntu`, `fedora`, `cirros`, `alpine`, `talos`).","type":"string"}}},"upload":{"description":"Upload local image.","type":"object"}}},"optical":{"description":"Defines if disk should be considered optical.","type":"boolean","default":false},"storage":{"description":"The size of the disk allocated for the virtual machine.","default":"5Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated"}}} + {"title":"Chart Values","type":"object","properties":{"source":{"description":"The source image location used to create a disk.","type":"object","default":{},"properties":{"disk":{"description":"Clone an existing vm-disk.","type":"object","required":["name"],"properties":{"name":{"description":"Name of the vm-disk to clone.","type":"string"}}},"http":{"description":"Download image from an HTTP source.","type":"object","required":["url"],"properties":{"url":{"description":"URL to download the image.","type":"string"}}},"image":{"description":"Use image by name from default collection.","type":"object","required":["name"],"properties":{"name":{"description":"Name of the image to use.","type":"string"}}},"upload":{"description":"Upload local image.","type":"object"}}},"optical":{"description":"Defines if disk should be considered optical.","type":"boolean","default":false},"storage":{"description":"The size of the disk allocated for the virtual machine.","default":"5Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated"}}} release: prefix: vm-disk- labels: