Skip to content

Commit

Permalink
Add ephemeral storage support to the AdditionalBlockDevices
Browse files Browse the repository at this point in the history
Fixes: #1692
  • Loading branch information
EmilienM committed Oct 12, 2023
1 parent ca07cfc commit 26f74c3
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 23 deletions.
40 changes: 37 additions & 3 deletions api/v1alpha7/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ limitations under the License.

package v1alpha7

// BlockDeviceType defines the type of block device to create.
// +kubebuilder:validation:Enum=volume;local
type BlockDeviceType string

const (
// LocalBlockDevice is an ephemeral block deviced attached to the server.
LocalBlockDevice BlockDeviceType = "local"

// VolumeBlockDevice is a volume block device attached to the server.
VolumeBlockDevice BlockDeviceType = "volume"
)

// OpenStackMachineTemplateResource describes the data needed to create a OpenStackMachine from a template.
type OpenStackMachineTemplateResource struct {
// Spec is the specification of the desired behavior of the machine.
Expand Down Expand Up @@ -163,18 +175,40 @@ type RootVolume struct {
AvailabilityZone string `json:"availabilityZone,omitempty"`
}

// AdditionalBlockDevice is a block device to attach to the server.
type AdditionalBlockDevice struct {
// Name of the Cinder volume in the context of a machine.
// It will be combined with the machine name to make the actual volume name.
// Type is the type of block device to create.
// This can be either "volume" or "local".
// +kubebuilder:validation:Required
// +unionDiscriminator
Type BlockDeviceType `json:"type"`

// Name of the block device in the context of a machine.
// It will be combined with the machine name to make the actual cinder
// volume name, and will be used for tagging the block device.
Name string `json:"name"`
// Size is the size in GB of the volume.

// Size is the size in GB of the block device.
Size int `json:"diskSize"`

// VolumeType is the volume type of the volume.
// If omitted, the default type will be used.
// +unionMember=volume,optional
// +optional
VolumeType string `json:"volumeType,omitempty"`

// AvailabilityZone is the volume availability zone to create the volume in.
// If omitted, the availability zone of the server will be used.
// +unionMember=volume,optional
// +optional
AvailabilityZone string `json:"availabilityZone,omitempty"`

// GuestFormat tells Nova how/if to format the device prior to attaching, should be only used with
// blank local images. Denotes a swap disk if the value is swap.
// We can't have more than one AdditionalBlockDevice with GuestFormat=swap.
// +unionMember=local,optional
// +optional
GuestFormat string `json:"guestFormat,omitempty"`
}

// NetworkStatus contains basic information about an existing neutron network.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3774,19 +3774,36 @@ spec:
description: AdditionalBlockDevices is a list of specifications
for additional block devices to attach to the server instance
items:
description: AdditionalBlockDevice is a block device to
attach to the server.
properties:
availabilityZone:
description: AvailabilityZone is the volume availability
zone to create the volume in. If omitted, the availability
zone of the server will be used.
type: string
diskSize:
description: Size is the size in GB of the volume.
description: Size is the size in GB of the block device.
type: integer
guestFormat:
description: GuestFormat tells Nova how/if to format
the device prior to attaching, should be only used
with blank local images. Denotes a swap disk if the
value is swap. We can't have more than one AdditionalBlockDevice
with GuestFormat=swap.
type: string
name:
description: Name of the Cinder volume in the context
description: Name of the block device in the context
of a machine. It will be combined with the machine
name to make the actual volume name.
name to make the actual cinder volume name, and will
be used for tagging the block device.
type: string
type:
description: Type is the type of block device to create.
This can be either "volume" or "local".
enum:
- volume
- local
type: string
volumeType:
description: VolumeType is the volume type of the volume.
Expand All @@ -3795,6 +3812,7 @@ spec:
required:
- diskSize
- name
- type
type: object
type: array
x-kubernetes-list-map-keys:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,8 @@ spec:
for additional block devices to attach to the server
instance
items:
description: AdditionalBlockDevice is a block device
to attach to the server.
properties:
availabilityZone:
description: AvailabilityZone is the volume
Expand All @@ -1623,13 +1625,31 @@ spec:
will be used.
type: string
diskSize:
description: Size is the size in GB of the volume.
description: Size is the size in GB of the block
device.
type: integer
guestFormat:
description: GuestFormat tells Nova how/if to
format the device prior to attaching, should
be only used with blank local images. Denotes
a swap disk if the value is swap. We can't
have more than one AdditionalBlockDevice with
GuestFormat=swap.
type: string
name:
description: Name of the Cinder volume in the
description: Name of the block device in the
context of a machine. It will be combined
with the machine name to make the actual volume
name.
with the machine name to make the actual cinder
volume name, and will be used for tagging
the block device.
type: string
type:
description: Type is the type of block device
to create. This can be either "volume" or
"local".
enum:
- volume
- local
type: string
volumeType:
description: VolumeType is the volume type of
Expand All @@ -1639,6 +1659,7 @@ spec:
required:
- diskSize
- name
- type
type: object
type: array
x-kubernetes-list-map-keys:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1163,19 +1163,35 @@ spec:
description: AdditionalBlockDevices is a list of specifications for
additional block devices to attach to the server instance
items:
description: AdditionalBlockDevice is a block device to attach to
the server.
properties:
availabilityZone:
description: AvailabilityZone is the volume availability zone
to create the volume in. If omitted, the availability zone
of the server will be used.
type: string
diskSize:
description: Size is the size in GB of the volume.
description: Size is the size in GB of the block device.
type: integer
guestFormat:
description: GuestFormat tells Nova how/if to format the device
prior to attaching, should be only used with blank local images.
Denotes a swap disk if the value is swap. We can't have more
than one AdditionalBlockDevice with GuestFormat=swap.
type: string
name:
description: Name of the Cinder volume in the context of a machine.
description: Name of the block device in the context of a machine.
It will be combined with the machine name to make the actual
volume name.
cinder volume name, and will be used for tagging the block
device.
type: string
type:
description: Type is the type of block device to create. This
can be either "volume" or "local".
enum:
- volume
- local
type: string
volumeType:
description: VolumeType is the volume type of the volume. If
Expand All @@ -1184,6 +1200,7 @@ spec:
required:
- diskSize
- name
- type
type: object
type: array
x-kubernetes-list-map-keys:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -962,19 +962,36 @@ spec:
description: AdditionalBlockDevices is a list of specifications
for additional block devices to attach to the server instance
items:
description: AdditionalBlockDevice is a block device to
attach to the server.
properties:
availabilityZone:
description: AvailabilityZone is the volume availability
zone to create the volume in. If omitted, the availability
zone of the server will be used.
type: string
diskSize:
description: Size is the size in GB of the volume.
description: Size is the size in GB of the block device.
type: integer
guestFormat:
description: GuestFormat tells Nova how/if to format
the device prior to attaching, should be only used
with blank local images. Denotes a swap disk if the
value is swap. We can't have more than one AdditionalBlockDevice
with GuestFormat=swap.
type: string
name:
description: Name of the Cinder volume in the context
description: Name of the block device in the context
of a machine. It will be combined with the machine
name to make the actual volume name.
name to make the actual cinder volume name, and will
be used for tagging the block device.
type: string
type:
description: Type is the type of block device to create.
This can be either "volume" or "local".
enum:
- volume
- local
type: string
volumeType:
description: VolumeType is the volume type of the volume.
Expand All @@ -983,6 +1000,7 @@ spec:
required:
- diskSize
- name
- type
type: object
type: array
x-kubernetes-list-map-keys:
Expand Down
36 changes: 30 additions & 6 deletions pkg/cloud/services/compute/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst

if hasRootVolume(instanceSpec) {
rootVolumeToBlockDevice := infrav1.AdditionalBlockDevice{
Type: infrav1.VolumeBlockDevice,
Name: "root",
AvailabilityZone: instanceSpec.RootVolume.AvailabilityZone,
Size: instanceSpec.RootVolume.Size,
Expand All @@ -489,18 +490,41 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst
})
}

var swapFound bool
for _, blockDeviceSpec := range instanceSpec.AdditionalBlockDevices {
blockDevice, err := s.getOrCreateVolumeBuilder(eventObject, instanceSpec, blockDeviceSpec, "", fmt.Sprintf("Additional block device for %s", instanceSpec.Name))
if err != nil {
return []bootfromvolume.BlockDevice{}, err
var bdUUID string
var sourceType bootfromvolume.SourceType
var destinationType bootfromvolume.DestinationType
if blockDeviceSpec.Type == infrav1.VolumeBlockDevice {
blockDevice, err := s.getOrCreateVolumeBuilder(eventObject, instanceSpec, blockDeviceSpec, "", fmt.Sprintf("Additional block device for %s", instanceSpec.Name))
if err != nil {
return []bootfromvolume.BlockDevice{}, err
}
bdUUID = blockDevice.ID
sourceType = bootfromvolume.SourceVolume
destinationType = bootfromvolume.DestinationVolume
} else if blockDeviceSpec.Type == infrav1.LocalBlockDevice {
sourceType = bootfromvolume.SourceBlank
destinationType = bootfromvolume.DestinationLocal
if blockDeviceSpec.GuestFormat == "swap" {
if swapFound {
return []bootfromvolume.BlockDevice{}, fmt.Errorf("only one swap block device is allowed for instance %s", instanceSpec.Name)
}
swapFound = true
}
} else {
return []bootfromvolume.BlockDevice{}, fmt.Errorf("invalid block device type %s", blockDeviceSpec.Type)
}

blockDevices = append(blockDevices, bootfromvolume.BlockDevice{
SourceType: bootfromvolume.SourceVolume,
DestinationType: bootfromvolume.DestinationVolume,
UUID: blockDevice.ID,
SourceType: sourceType,
DestinationType: destinationType,
UUID: bdUUID,
BootIndex: -1,
DeleteOnTermination: true,
VolumeSize: blockDeviceSpec.Size,
Tag: blockDeviceSpec.Name,
GuestFormat: blockDeviceSpec.GuestFormat,
})
}

Expand Down
Loading

0 comments on commit 26f74c3

Please sign in to comment.