diff --git a/api/core/v1alpha2/virtual_disk.go b/api/core/v1alpha2/virtual_disk.go index c7275c7da..05e580360 100644 --- a/api/core/v1alpha2/virtual_disk.go +++ b/api/core/v1alpha2/virtual_disk.go @@ -27,7 +27,20 @@ const ( VirtualDiskResource = "virtualdisks" ) -// VirtualDisk is a disk ready to be bound by a VM +// The `VirtualDisk` resource describes the desired virtual machine disk configuration. A `VirtualDisk` can be mounted statically in the virtual machine by specifying it in the `.spec.blockDeviceRefs` disk list, or mounted on-the-fly using the `VirtualMachineBlockDeviceAttachments` resource. +// +// Once `VirtualDisk` is created, only the disk size `.spec.persistentVolumeClaim.size` can be changed, all other fields are immutable. +// +kubebuilder:object:root=true +// +kubebuilder:metadata:labels={heritage=deckhouse,module=virtualization} +// +kubebuilder:resource:categories={virtualization,all},scope=Namespaced,shortName={vd,vds},singular=virtualdisk +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Capacity",type=string,JSONPath=`.status.capacity` +// +kubebuilder:printcolumn:name="Progress",type=string,JSONPath=`.status.progress`,priority=1 +// +kubebuilder:printcolumn:name="StorageClass",type=string,JSONPath=`.spec.persistentVolumeClaim.storageClassName`,priority=1 +// +kubebuilder:printcolumn:name="TargetPVC",type=string,JSONPath=`.status.target.persistentVolumeClaimName`,priority=1 +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:validation:XValidation:rule="self.metadata.name.size() <= 128",message="The name must be no longer than 128 characters." // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type VirtualDisk struct { @@ -40,40 +53,60 @@ type VirtualDisk struct { type VirtualDiskSpec struct { DataSource *VirtualDiskDataSource `json:"dataSource,omitempty"` - PersistentVolumeClaim VirtualDiskPersistentVolumeClaim `json:"persistentVolumeClaim"` + PersistentVolumeClaim VirtualDiskPersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"` } type VirtualDiskStatus struct { DownloadSpeed *StatusSpeed `json:"downloadSpeed,omitempty"` - Capacity string `json:"capacity,omitempty"` - Target DiskTarget `json:"target"` - Progress string `json:"progress,omitempty"` + // Requested capacity of the PVC in human-readable format. + // +kubebuilder:example:="50G" + Capacity string `json:"capacity,omitempty"` + Target DiskTarget `json:"target,omitempty"` + // Progress of copying an image from source to PVC. Appears only during the `Provisioning' phase. + Progress string `json:"progress,omitempty"` // Deprecated: use ImageUploadURLs instead. - UploadCommand string `json:"uploadCommand,omitempty"` - ImageUploadURLs *ImageUploadURLs `json:"imageUploadURLs,omitempty"` - Phase DiskPhase `json:"phase"` + UploadCommand string `json:"uploadCommand,omitempty"` + ImageUploadURLs *ImageUploadURLs `json:"imageUploadURLs,omitempty"` + Phase DiskPhase `json:"phase,omitempty"` + // A list of `VirtualMachines` that use the disk + // +kubebuilder:example:={{name: VM100}} AttachedToVirtualMachines []AttachedVirtualMachine `json:"attachedToVirtualMachines,omitempty"` - Stats VirtualDiskStats `json:"stats"` + Stats VirtualDiskStats `json:"stats,omitempty"` SourceUID *types.UID `json:"sourceUID,omitempty"` - Conditions []metav1.Condition `json:"conditions,omitempty"` - ObservedGeneration int64 `json:"observedGeneration,omitempty"` - StorageClassName string `json:"storageClassName,omitempty"` + // The latest available observations of an object's current state. + Conditions []metav1.Condition `json:"conditions,omitempty"` + // The generation last processed by the controller. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // The name of the StorageClass used by the PersistentVolumeClaim if `Kubernetes` storage type used. + StorageClassName string `json:"storageClassName,omitempty"` } +// VirtualDisk statistics type VirtualDiskStats struct { - CreationDuration VirtualDiskStatsCreationDuration `json:"creationDuration"` + // The waiting time for the virtual disk creation. + CreationDuration VirtualDiskStatsCreationDuration `json:"creationDuration,omitempty"` } type VirtualDiskStatsCreationDuration struct { + // The waiting time for dependent resources. + // +nullable WaitingForDependencies *metav1.Duration `json:"waitingForDependencies,omitempty"` - DVCRProvisioning *metav1.Duration `json:"dvcrProvisioning,omitempty"` - TotalProvisioning *metav1.Duration `json:"totalProvisioning,omitempty"` + // Duration of the loading into DVCR. + // +nullable + DVCRProvisioning *metav1.Duration `json:"dvcrProvisioning,omitempty"` + // The duration of resource creation from the moment dependencies are ready until the resource transitions to the Ready state. + // +nullable + TotalProvisioning *metav1.Duration `json:"totalProvisioning,omitempty"` } +// A list of `VirtualMachines` that use the disk type AttachedVirtualMachine struct { - Name string `json:"name"` + Name string `json:"name,omitempty"` } +// +kubebuilder:validation:XValidation:rule="self.type == 'HTTP' ? has(self.http) && !has(self.containerImage) && !has(self.objectRef) : true",message="HTTP requires http and cannot have ContainerImage or ObjectRef" +// +kubebuilder:validation:XValidation:rule="self.type == 'ContainerImage' ? has(self.containerImage) && !has(self.http) && !has(self.objectRef) : true",message="ContainerImage requires containerImage and cannot have HTTP or ObjectRef" +// +kubebuilder:validation:XValidation:rule="self.type == 'ObjectRef' ? has(self.objectRef) && !has(self.http) && !has(self.containerImage) : true",message="ObjectRef requires objectRef and cannot have HTTP or ContainerImage" type VirtualDiskDataSource struct { Type DataSourceType `json:"type,omitempty"` HTTP *DataSourceHTTP `json:"http,omitempty"` @@ -93,11 +126,15 @@ type VirtualDiskContainerImage struct { CABundle []byte `json:"caBundle,omitempty"` } +// Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot` to create a disk. type VirtualDiskObjectRef struct { - Kind VirtualDiskObjectRefKind `json:"kind,omitempty"` - Name string `json:"name,omitempty"` + // A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot`. + Kind VirtualDiskObjectRefKind `json:"kind"` + // A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot`. + Name string `json:"name"` } +// +kubebuilder:validation:Enum:={ClusterVirtualImage,VirtualImage,VirtualDiskSnapshot} type VirtualDiskObjectRefKind string const ( @@ -107,12 +144,36 @@ const ( ) type DiskTarget struct { + // Created PersistentVolumeClaim name for Kubernetes storage. PersistentVolumeClaim string `json:"persistentVolumeClaimName,omitempty"` } +// Settings for creating PVCs to store the disk. type VirtualDiskPersistentVolumeClaim struct { - StorageClass *string `json:"storageClassName,omitempty"` - Size *resource.Quantity `json:"size,omitempty"` + // The name of the StorageClass required by the claim. More info — https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + // + // When creating disks, the user can specify the required StorageClass to create the disk, or not explicitly, in which case the default StorageClass will be used. + // + // The disk features and virtual machine behavior depend on the selected StorageClass. + // + // The `VolumeBindingMode` parameter in the StorageClass affects the disk creation process: + // - `Immediate` - The disk will be created and available for use immediately after creation. + // - `WaitForFirstConsumer` - The disk will be created only when it is used in a virtual machine. In this case, the disk will be created on the host where the virtual machine will be started. + // + // StorageClass can support different storage settings: + // - Creating a block device (`Block`) or file system (`FileSystem`). + // - Multiple Access (`ReadWriteMany`) or Single Access (`ReadWriteOnce`). `ReadWriteMany` disks support multiple access, which enables live migration of virtual machines. In contrast, `ReadWriteOnce` disks, which are limited to access from only one host, cannot provide this capability. + // + // For known storage types, the platform will independently determine the most effective settings when creating disks (in descending order of priority): + // 1. `Block` + `ReadWriteMany` + // 2. `FileSystem` + `ReadWriteMany` + // 3. `Block` + `ReadWriteOnce` + // 4. `FileSystem` + `ReadWriteOnce` + StorageClass *string `json:"storageClassName,omitempty"` + // Desired size for PVC to store the disk. If the disk is created from an image, the size must be at least as large as the original unpacked image. + // + // This parameter can be omitted if the `.spec.dataSource` block is specified, in which case the controller will determine the disk size automatically, based on the size of the extracted image from the source specified in `.spec.dataSource`. + Size *resource.Quantity `json:"size,omitempty"` } // VirtualDiskList contains a list of VirtualDisk @@ -123,6 +184,17 @@ type VirtualDiskList struct { Items []VirtualDisk `json:"items"` } +// Current status of `VirtualDisk` resource: +// * Pending - The resource has been created and is on a waiting queue. +// * Provisioning - The process of resource creation (copying/downloading/filling the PVC with data/extending PVC) is in progress. +// * WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`. +// * WaitForFirstConsumer - Waiting for the virtual machine that uses the disk is scheduled. +// * Ready - The resource is created and ready to use. +// * Resizing — The process of resource resizing is in progress. +// * Failed - There was a problem when creating a resource. +// * PVCLost - The child PVC of the resource is missing. The resource cannot be used. +// * Terminating - The process of resource deletion is in progress. +// +kubebuilder:validation:Enum:={Pending,Provisioning,WaitForUserUpload,Ready,Failed,Terminating,PVCLost,WaitForFirstConsumer,Resizing} type DiskPhase string const ( diff --git a/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go b/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go index 94f516741..0b8ca7672 100644 --- a/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go +++ b/api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go @@ -674,17 +674,16 @@ func schema_virtualization_api_core_v1alpha2_AttachedVirtualMachine(ref common.R return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "A list of `VirtualMachines` that use the disk", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Type: []string{"string"}, + Format: "", }, }, }, - Required: []string{"name"}, }, }, } @@ -1390,8 +1389,9 @@ func schema_virtualization_api_core_v1alpha2_DiskTarget(ref common.ReferenceCall Properties: map[string]spec.Schema{ "persistentVolumeClaimName": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Created PersistentVolumeClaim name for Kubernetes storage.", + Type: []string{"string"}, + Format: "", }, }, }, @@ -2094,7 +2094,7 @@ func schema_virtualization_api_core_v1alpha2_VirtualDisk(ref common.ReferenceCal return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "VirtualDisk is a disk ready to be bound by a VM", + Description: "The `VirtualDisk` resource describes the desired virtual machine disk configuration. A `VirtualDisk` can be mounted statically in the virtual machine by specifying it in the `.spec.blockDeviceRefs` disk list, or mounted on-the-fly using the `VirtualMachineBlockDeviceAttachments` resource.\n\nOnce `VirtualDisk` is created, only the disk size `.spec.persistentVolumeClaim.size` can be changed, all other fields are immutable.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { @@ -2263,21 +2263,27 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskObjectRef(ref common.Ref return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot` to create a disk.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot`.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "name": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot`.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, }, + Required: []string{"kind", "name"}, }, }, } @@ -2287,17 +2293,20 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskPersistentVolumeClaim(re return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Settings for creating PVCs to store the disk.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "storageClassName": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "The name of the StorageClass required by the claim. More info — https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1\n\nWhen creating disks, the user can specify the required StorageClass to create the disk, or not explicitly, in which case the default StorageClass will be used.\n\nThe disk features and virtual machine behavior depend on the selected StorageClass.\n\nThe `VolumeBindingMode` parameter in the StorageClass affects the disk creation process: - `Immediate` - The disk will be created and available for use immediately after creation. - `WaitForFirstConsumer` - The disk will be created only when it is used in a virtual machine. In this case, the disk will be created on the host where the virtual machine will be started.\n\nStorageClass can support different storage settings: - Creating a block device (`Block`) or file system (`FileSystem`). - Multiple Access (`ReadWriteMany`) or Single Access (`ReadWriteOnce`). `ReadWriteMany` disks support multiple access, which enables live migration of virtual machines. In contrast, `ReadWriteOnce` disks, which are limited to access from only one host, cannot provide this capability.\n\nFor known storage types, the platform will independently determine the most effective settings when creating disks (in descending order of priority): 1. `Block` + `ReadWriteMany` 2. `FileSystem` + `ReadWriteMany` 3. `Block` + `ReadWriteOnce` 4. `FileSystem` + `ReadWriteOnce`", + Type: []string{"string"}, + Format: "", }, }, "size": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + Description: "Desired size for PVC to store the disk. If the disk is created from an image, the size must be at least as large as the original unpacked image.\n\nThis parameter can be omitted if the `.spec.dataSource` block is specified, in which case the controller will determine the disk size automatically, based on the size of the extracted image from the source specified in `.spec.dataSource`.", + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), }, }, }, @@ -2510,7 +2519,6 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskSpec(ref common.Referenc }, }, }, - Required: []string{"persistentVolumeClaim"}, }, }, Dependencies: []string{ @@ -2522,16 +2530,17 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStats(ref common.Referen return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "VirtualDisk statistics", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "creationDuration": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskStatsCreationDuration"), + Description: "The waiting time for the virtual disk creation.", + Default: map[string]interface{}{}, + Ref: ref("github.com/deckhouse/virtualization/api/core/v1alpha2.VirtualDiskStatsCreationDuration"), }, }, }, - Required: []string{"creationDuration"}, }, }, Dependencies: []string{ @@ -2547,17 +2556,20 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStatsCreationDuration(re Properties: map[string]spec.Schema{ "waitingForDependencies": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + Description: "The waiting time for dependent resources.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), }, }, "dvcrProvisioning": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + Description: "Duration of the loading into DVCR.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), }, }, "totalProvisioning": { SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + Description: "The duration of resource creation from the moment dependencies are ready until the resource transitions to the Ready state.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), }, }, }, @@ -2581,8 +2593,9 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref common.Refere }, "capacity": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Requested capacity of the PVC in human-readable format.", + Type: []string{"string"}, + Format: "", }, }, "target": { @@ -2593,8 +2606,9 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref common.Refere }, "progress": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Progress of copying an image from source to PVC. Appears only during the `Provisioning' phase.", + Type: []string{"string"}, + Format: "", }, }, "uploadCommand": { @@ -2611,14 +2625,14 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref common.Refere }, "phase": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Type: []string{"string"}, + Format: "", }, }, "attachedToVirtualMachines": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of `VirtualMachines` that use the disk", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2643,7 +2657,8 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref common.Refere }, "conditions": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "The latest available observations of an object's current state.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2656,18 +2671,19 @@ func schema_virtualization_api_core_v1alpha2_VirtualDiskStatus(ref common.Refere }, "observedGeneration": { SchemaProps: spec.SchemaProps{ - Type: []string{"integer"}, - Format: "int64", + Description: "The generation last processed by the controller.", + Type: []string{"integer"}, + Format: "int64", }, }, "storageClassName": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "The name of the StorageClass used by the PersistentVolumeClaim if `Kubernetes` storage type used.", + Type: []string{"string"}, + Format: "", }, }, }, - Required: []string{"target", "phase", "stats"}, }, }, Dependencies: []string{ diff --git a/api/scripts/update-codegen.sh b/api/scripts/update-codegen.sh index 9350b274d..53de4bb5e 100755 --- a/api/scripts/update-codegen.sh +++ b/api/scripts/update-codegen.sh @@ -37,6 +37,7 @@ function source::settings { "VirtualMachineSnapshot" "VirtualMachineRestore" "VirtualMachineOperation" + "VirtualDisk" "VirtualImage" "ClusterVirtualImage") source "${CODEGEN_PKG}/kube_codegen.sh" diff --git a/crds/virtualdisks.yaml b/crds/virtualdisks.yaml index 42f084ab7..00be74069 100644 --- a/crds/virtualdisks.yaml +++ b/crds/virtualdisks.yaml @@ -1,117 +1,143 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: virtualdisks.virtualization.deckhouse.io + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 labels: heritage: deckhouse module: virtualization + name: virtualdisks.virtualization.deckhouse.io spec: group: virtualization.deckhouse.io - scope: Namespaced names: categories: - - all - virtualization - plural: virtualdisks - singular: virtualdisk + - all kind: VirtualDisk + listKind: VirtualDiskList + plural: virtualdisks shortNames: - vd - vds - preserveUnknownFields: false + singular: virtualdisk + scope: Namespaced versions: - - name: v1alpha2 - served: true - storage: true + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .status.capacity + name: Capacity + type: string + - jsonPath: .status.progress + name: Progress + priority: 1 + type: string + - jsonPath: .spec.persistentVolumeClaim.storageClassName + name: StorageClass + priority: 1 + type: string + - jsonPath: .status.target.persistentVolumeClaimName + name: TargetPVC + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 schema: openAPIV3Schema: - type: object - description: | + description: |- The `VirtualDisk` resource describes the desired virtual machine disk configuration. A `VirtualDisk` can be mounted statically in the virtual machine by specifying it in the `.spec.blockDeviceRefs` disk list, or mounted on-the-fly using the `VirtualMachineBlockDeviceAttachments` resource. Once `VirtualDisk` is created, only the disk size `.spec.persistentVolumeClaim.size` can be changed, all other fields are immutable. - required: - - spec - x-kubernetes-validations: - - rule: "self.metadata.name.size() <= 128" - message: "The name must be no longer than 128 characters." properties: - spec: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: type: object + spec: properties: - persistentVolumeClaim: - type: object - description: | - Settings for creating PVCs to store the disk. - properties: - size: - type: string - description: | - Desired size for PVC to store the disk. If the disk is created from an image, the size must be at least as large as the original unpacked image. - - This parameter can be omitted if the `.spec.dataSource` block is specified, in which case the controller will determine the disk size automatically, based on the size of the extracted image from the source specified in `.spec.dataSource`. - pattern: "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$" - storageClassName: - type: string - description: | - The name of the StorageClass required by the claim. More info — https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - - When creating disks, the user can specify the required StorageClass to create the disk, or not explicitly, in which case the default StorageClass will be used. - - The disk features and virtual machine behavior depend on the selected StorageClass. - - The `VolumeBindingMode` parameter in the StorageClass affects the disk creation process: - - `Immediate` - The disk will be created and available for use immediately after creation. - - `WaitForFirstConsumer` - The disk will be created only when it is used in a virtual machine. In this case, the disk will be created on the host where the virtual machine will be started. - - StorageClass can support different storage settings: - - Creating a block device (`Block`) or file system (`FileSystem`). - - Multiple Access (`ReadWriteMany`) or Single Access (`ReadWriteOnce`). `ReadWriteMany` disks support multiple access, which enables live migration of virtual machines. In contrast, `ReadWriteOnce` disks, which are limited to access from only one host, cannot provide this capability. - - For known storage types, the platform will independently determine the most effective settings when creating disks (in descending order of priority): - 1. `Block` + `ReadWriteMany` - 2. `FileSystem` + `ReadWriteMany` - 3. `Block` + `ReadWriteOnce` - 4. `FileSystem` + `ReadWriteOnce` dataSource: - type: object - description: | - An origin of the disk. If empty or absent, empty disk will be created. - required: - - type properties: - type: - type: string - enum: - - "HTTP" - - "ContainerImage" - - "ObjectRef" - - "Upload" - description: | - The type of an origin of the disk. Options are: - - * `HTTP` — create an image from a file published on http/https service at a given url - * `ContainerImage` — create the image from image stored in container registry. - * `ObjectRef` — fill the disk from another existing resource. - * `Upload` — fill the disk with data, uploaded by user via the special interface. - http: + containerImage: + description: + Use an image stored in external container registry. + Only TLS enabled registries are supported. Use caBundle field + to provide custom CA chain if needed. + properties: + caBundle: + description: + The CA chain in base64 format to verify the container + registry. + example: YWFhCg== + format: byte + type: string + image: + description: The container registry address of an image. + example: registry.example.com/images/slackware:15 + pattern: ^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$ + type: string + imagePullSecret: + properties: + name: + description: + A name of the secret containing registry + credentials which must be located in the same namespace. + type: string + type: object + required: + - image type: object - description: | + http: + description: |- Fill the image with data from some external url. Supported schemas are: * http * https For https schema there is an option to skip TLS verification. - required: - - url properties: - url: + caBundle: + description: The CA chain in base64 format to verify the url. + example: YWFhCg== + format: byte type: string - example: "https://mirror.example.com/images/slackware-15.qcow.gz" - # https://regex101.com/r/2zx8as/1 - pattern: ^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$ - description: | + checksum: + description: + A checksum of the file, provided by the url, + to verify if it was downloaded correctly or wasn't changed. + The file should match all specified checksums. + properties: + md5: + example: f3b59bed9f91e32fac1210184fcff6f5 + maxLength: 32 + minLength: 32 + pattern: ^[0-9a-fA-F]{32}$ + type: string + sha256: + example: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5 + maxLength: 64 + minLength: 64 + pattern: ^[0-9a-fA-F]{64}$ + type: string + type: object + url: + description: |- The http url with an image. The following formats are supported: * qcow2 * vmdk @@ -121,114 +147,127 @@ spec: these formats can also be compressed with the following formats: * gz * xz - caBundle: + example: https://mirror.example.com/images/slackware-15.qcow.gz + pattern: ^http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$ type: string - format: byte - description: | - A certificate bundle in Base64 format to verify the TLS certificate of the server hosting the image. - example: | - YWFhCg== - checksum: - type: object - description: | - A checksum of the file, provided by the url, to verify if it was downloaded correctly or wasn't changed. The file should match all specified checksums. - properties: - md5: - description: "" - type: string - pattern: ^[0-9a-fA-F]{32}$ - minLength: 32 - maxLength: 32 - example: f3b59bed9f91e32fac1210184fcff6f5 - sha256: - description: "" - type: string - pattern: ^[0-9a-fA-F]{64}$ - minLength: 64 - maxLength: 64 - example: 78be890d71dde316c412da2ce8332ba47b9ce7a29d573801d2777e01aa20b9b5 - containerImage: - type: object required: - - image - description: | - Use an image stored in external container registry. Only TLS enabled registries are supported. Use caBundle field to provide custom CA chain if needed. - properties: - image: - type: string - example: "registry.example.com/images/slackware:15" - # https://regex101.com/r/NXfP8Y/1 - pattern: ^(?P(?:(?P(?:(?:localhost|[\w-]+(?:\.[\w-]+)+)(?::\d+)?)|[\w]+:\d+)/)?(?P[a-z0-9_.-]+(?:/[a-z0-9_.-]+)*))(?::(?P[\w][\w.-]{0,127}))?(?:@(?P[A-Za-z][A-Za-z0-9]*(?:[+.-_][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,}))?$ - description: | - The container registry address of an image. - imagePullSecret: - type: object - properties: - name: - type: string - description: | - A name of the secret containing registry credentials. - caBundle: - type: string - format: byte - description: | - The CA chain in base64 format to verify the container registry. - example: | - YWFhCg== - objectRef: + - url type: object - description: | - Use an existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot` to create a disk. - required: ["kind", "name"] + objectRef: + description: + Use an existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDiskSnapshot` to create a disk. properties: kind: - type: string - description: A kind of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot`. + description: + A kind of existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDiskSnapshot`. enum: - - "VirtualImage" - - "ClusterVirtualImage" - - "VirtualDiskSnapshot" + - ClusterVirtualImage + - VirtualImage + - VirtualDiskSnapshot + type: string name: + description: + A name of existing `VirtualImage`, `ClusterVirtualImage` + or `VirtualDiskSnapshot`. type: string - description: | - A name of existing `VirtualImage`, `ClusterVirtualImage` or `VirtualDiskSnapshot`. - oneOf: - - properties: - type: - enum: ["HTTP"] - http: {} - required: ["http"] - - properties: - type: - enum: ["ContainerImage"] - containerImage: {} - required: ["containerImage"] - - properties: - type: - enum: ["ObjectRef"] - objectRef: {} - required: ["objectRef"] - - properties: - type: - enum: ["Upload"] - status: + required: + - kind + - name + type: object + type: + description: |- + The type of an origin of the image. Options are: + + * `HTTP` — create an image from a file published on http/https service at a given url + * `ContainerImage` — create the image from image stored in container registry. + * `ObjectRef` — fill the disk from another existing resource. + * `Upload` — fill the image with data, uploaded by user via the special interface. + enum: + - HTTP + - ContainerImage + - ObjectRef + - Upload + type: string + type: object + x-kubernetes-validations: + - message: HTTP requires http and cannot have ContainerImage or ObjectRef + rule: + "self.type == 'HTTP' ? has(self.http) && !has(self.containerImage) + && !has(self.objectRef) : true" + - message: + ContainerImage requires containerImage and cannot have + HTTP or ObjectRef + rule: + "self.type == 'ContainerImage' ? has(self.containerImage) + && !has(self.http) && !has(self.objectRef) : true" + - message: ObjectRef requires objectRef and cannot have HTTP or ContainerImage + rule: + "self.type == 'ObjectRef' ? has(self.objectRef) && !has(self.http) + && !has(self.containerImage) : true" + persistentVolumeClaim: + description: Settings for creating PVCs to store the disk. + properties: + size: + anyOf: + - type: integer + - type: string + description: |- + Desired size for PVC to store the disk. If the disk is created from an image, the size must be at least as large as the original unpacked image. + + This parameter can be omitted if the `.spec.dataSource` block is specified, in which case the controller will determine the disk size automatically, based on the size of the extracted image from the source specified in `.spec.dataSource`. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + storageClassName: + description: |- + The name of the StorageClass required by the claim. More info — https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + + When creating disks, the user can specify the required StorageClass to create the disk, or not explicitly, in which case the default StorageClass will be used. + + The disk features and virtual machine behavior depend on the selected StorageClass. + + The `VolumeBindingMode` parameter in the StorageClass affects the disk creation process: + - `Immediate` - The disk will be created and available for use immediately after creation. + - `WaitForFirstConsumer` - The disk will be created only when it is used in a virtual machine. In this case, the disk will be created on the host where the virtual machine will be started. + + StorageClass can support different storage settings: + - Creating a block device (`Block`) or file system (`FileSystem`). + - Multiple Access (`ReadWriteMany`) or Single Access (`ReadWriteOnce`). `ReadWriteMany` disks support multiple access, which enables live migration of virtual machines. In contrast, `ReadWriteOnce` disks, which are limited to access from only one host, cannot provide this capability. + + For known storage types, the platform will independently determine the most effective settings when creating disks (in descending order of priority): + 1. `Block` + `ReadWriteMany` + 2. `FileSystem` + `ReadWriteMany` + 3. `Block` + `ReadWriteOnce` + 4. `FileSystem` + `ReadWriteOnce` + type: string + type: object type: object + status: properties: + attachedToVirtualMachines: + description: A list of `VirtualMachines` that use the disk + example: + - name: VM100 + items: + description: A list of `VirtualMachines` that use the disk + properties: + name: + type: string + type: object + type: array + capacity: + description: Requested capacity of the PVC in human-readable format. + example: 50G + type: string conditions: - description: | - The latest available observations of an object's current state. + description: + The latest available observations of an object's current + state. items: description: - "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -269,12 +308,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -287,42 +321,46 @@ spec: type: object type: array downloadSpeed: - type: object - description: | - Image download speed from an external source. Appears only during the `Provisioning' phase. + description: + Image download speed from an external source. Appears + only during the `Provisioning` phase. properties: avg: - type: string + description: Average download speed. example: 1 Mbps - description: | - Average download speed. - current: type: string - example: 5 Mbps - description: Current download speed. avgBytes: - type: string - example: 1012345 description: Average download speed in bytes per second. - currentBytes: + example: 1012345 type: string - example: 5123456 + current: + description: Current download speed. + example: 5 Mbps + type: string + currentBytes: description: Current download speed in bytes per second. - capacity: - type: string - example: 50G - description: | - Requested capacity of the PVC in human-readable format. - target: + example: 5123456 + type: string type: object + imageUploadURLs: properties: - persistentVolumeClaimName: + external: + description: + Command to upload the image using `Ingress` from + outside the cluster. + type: string + inCluster: + description: + Command to upload the image using `Service` within + the cluster. type: string - description: | - Created PersistentVolumeClaim name for Kubernetes storage. + type: object + observedGeneration: + description: The generation last processed by the controller. + format: int64 + type: integer phase: - type: string - description: | + description: |- Current status of `VirtualDisk` resource: * Pending - The resource has been created and is on a waiting queue. * Provisioning - The process of resource creation (copying/downloading/filling the PVC with data/extending PVC) is in progress. @@ -334,103 +372,74 @@ spec: * PVCLost - The child PVC of the resource is missing. The resource cannot be used. * Terminating - The process of resource deletion is in progress. enum: - [ - "Pending", - "Provisioning", - "WaitForUserUpload", - "WaitForFirstConsumer", - "Ready", - "Resizing", - "Failed", - "PVCLost", - "Terminating", - ] + - Pending + - Provisioning + - WaitForUserUpload + - Ready + - Failed + - Terminating + - PVCLost + - WaitForFirstConsumer + - Resizing + type: string progress: + description: + Progress of copying an image from source to PVC. Appears + only during the `Provisioning' phase. type: string - description: | - Progress of copying an image from source to PVC. Appears only during the `Provisioning' phase. - uploadCommand: + sourceUID: + description: |- + UID is a type that holds unique ID values, including UUIDs. Because we + don't ONLY use UUIDs, this is an alias to string. Being a type captures + intent and helps make sure that UIDs and names do not get conflated. type: string - description: | - Deprecated. Use imageUploadURLs instead. - imageUploadURLs: - type: object - properties: - external: - type: string - description: | - Command to upload the image using `Ingress` from outside the cluster. - inCluster: - type: string - description: | - Command to upload the image using `Service` within the cluster. - attachedToVirtualMachines: - type: array - description: | - A list of `VirtualMachines` that use the disk - example: [{ name: "VM100" }] - items: - type: object - properties: - name: - type: string stats: - type: object - description: "VirtualDisk statistics" + description: VirtualDisk statistics properties: creationDuration: - type: object - description: | - The waiting time for the virtual disk creation. + description: The waiting time for the virtual disk creation. properties: - waitingForDependencies: - type: string - description: | - The waiting time for dependent resources. - nullable: true dvcrProvisioning: - type: string - description: | - Duration of the loading into DVCR. + description: Duration of the loading into DVCR. nullable: true + type: string totalProvisioning: + description: + The duration of resource creation from the moment + dependencies are ready until the resource transitions to + the Ready state. + nullable: true type: string - description: | - The duration of resource creation from the moment dependencies are ready until the resource transitions to the Ready state. + waitingForDependencies: + description: The waiting time for dependent resources. nullable: true - sourceUID: - type: string - description: | - The UID of the source (`VirtualImage` or `ClusterVirtualImage`) used when creating the virtual disk. + type: string + type: object + type: object storageClassName: + description: + The name of the StorageClass used by the PersistentVolumeClaim + if `Kubernetes` storage type used. type: string - description: | - The name of the `StorageClass` used by the `PersistentVolumeClaim`. - observedGeneration: - type: integer - description: | - The generation last processed by the controller. - additionalPrinterColumns: - - name: Phase - type: string - jsonPath: .status.phase - - name: Capacity - type: string - jsonPath: .status.capacity - - name: Progress - type: string - jsonPath: .status.progress - priority: 1 - - name: StorageClass - jsonPath: .spec.persistentVolumeClaim.storageClassName - type: string - priority: 1 - - name: TargetPVC - jsonPath: .status.target.persistentVolumeClaimName - type: string - priority: 1 - - name: Age - type: date - jsonPath: .metadata.creationTimestamp + target: + properties: + persistentVolumeClaimName: + description: + Created PersistentVolumeClaim name for Kubernetes + storage. + type: string + type: object + uploadCommand: + description: "Deprecated: use ImageUploadURLs instead." + type: string + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: The name must be no longer than 128 characters. + rule: self.metadata.name.size() <= 128 + served: true + storage: true subresources: status: {}