Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat #388: Add support for paravirtualized launch volume attachment #395

Merged
merged 13 commits into from
Feb 20, 2025
6 changes: 3 additions & 3 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ if "default_registry" in settings:

tilt_helper_dockerfile_header = """
# Tilt image
FROM golang:1.19 as tilt-helper
FROM golang:1.21.8 as tilt-helper
# Support live reloading with Tilt
RUN go install github.com/go-delve/delve/cmd/dlv@latest
RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com/tilt-dev/rerun-process-wrapper/master/restart.sh && \
Expand Down Expand Up @@ -196,7 +196,7 @@ def base64_decode(to_decode):
return str(decode_blob)

def kustomizesub(folder):
yaml = local('hack/kustomize-sub.sh {}'.format(folder), quiet=True)
yaml = local('bash hack/kustomize-sub.sh {}'.format(folder), quiet=True)
return yaml

##############################
Expand All @@ -216,4 +216,4 @@ deploy_capi()

capoci()

waitforsystem()
waitforsystem()
31 changes: 31 additions & 0 deletions api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@ type VolumeType string

const (
IscsiType VolumeType = "iscsi"
ParavirtualizedType VolumeType = "paravirtualized"
)

// EncryptionInTransitTypeEnum Enum with underlying type: string
Expand All @@ -1115,6 +1116,7 @@ type LaunchVolumeAttachment struct {

// The details of iscsi volume attachment.
IscsiAttachment LaunchIscsiVolumeAttachment `json:"launchIscsiVolumeAttachment,omitempty"`
ParavirtualizedAttachment LaunchParavirtualizedVolumeAttachment `json:"launchParavirtualizedVolumeAttachment,omitempty"`
}

// LaunchIscsiVolumeAttachment specifies the iscsi volume attachments to create as part of the launch instance operation.
Expand Down Expand Up @@ -1152,6 +1154,35 @@ type LaunchIscsiVolumeAttachment struct {
EncryptionInTransitType EncryptionInTransitTypeEnum `json:"encryptionInTransitType,omitempty"`
}

// LaunchParavirtualizedVolumeAttachment specifies the paravirtualized volume attachments to create as part of the launch instance operation.
type LaunchParavirtualizedVolumeAttachment struct {
// The device name. To retrieve a list of devices for a given instance, see ListInstanceDevices.
Device *string `json:"device,omitempty"`

// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
DisplayName *string `json:"displayName,omitempty"`

// Whether the attachment was created in read-only mode.
IsReadOnly *bool `json:"isReadOnly,omitempty"`

// Whether the attachment should be created in shareable mode. If an attachment
// is created in shareable mode, then other instances can attach the same volume, provided
// that they also create their attachments in shareable mode. Only certain volume types can
// be attached in shareable mode. Defaults to false if not specified.
IsShareable *bool `json:"isShareable,omitempty"`

// The OCID of the volume. If CreateVolumeDetails is specified, this field must be omitted from the request.
VolumeId *string `json:"volumeId,omitempty"`

// LaunchCreateVolumeFromAttributes The details of the volume to create for CreateVolume operation.
LaunchCreateVolumeFromAttributes LaunchCreateVolumeFromAttributes `json:"launchCreateVolumeFromAttributes,omitempty"`

// Refer the top-level definition of isPvEncryptionInTransitEnabled.
// The default value is False.
IsPvEncryptionInTransitEnabled *bool `json:"isPvEncryptionInTransitEnabled,omitempty"`
}

// LaunchCreateVolumeFromAttributes The details of the volume to create for CreateVolume operation.
type LaunchCreateVolumeFromAttributes struct {

Expand Down
32 changes: 32 additions & 0 deletions api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,7 @@ type VolumeType string

const (
IscsiType VolumeType = "iscsi"
ParavirtualizedType VolumeType = "paravirtualized"
)

// EncryptionInTransitTypeEnum Enum with underlying type: string
Expand All @@ -1186,6 +1187,7 @@ type LaunchVolumeAttachment struct {

// The details of iscsi volume attachment.
IscsiAttachment LaunchIscsiVolumeAttachment `json:"launchIscsiVolumeAttachment,omitempty"`
ParavirtualizedAttachment LaunchParavirtualizedVolumeAttachment `json:"launchParavirtualizedVolumeAttachment,omitempty"`
}

// LaunchIscsiVolumeAttachment specifies the iscsi volume attachments to create as part of the launch instance operation.
Expand Down Expand Up @@ -1223,6 +1225,36 @@ type LaunchIscsiVolumeAttachment struct {
EncryptionInTransitType EncryptionInTransitTypeEnum `json:"encryptionInTransitType,omitempty"`
}

// LaunchParavirtualizedVolumeAttachment specifies the paravirtualized volume attachments to create as part of the launch instance operation.
type LaunchParavirtualizedVolumeAttachment struct {
// The device name. To retrieve a list of devices for a given instance, see ListInstanceDevices.
Device *string `json:"device,omitempty"`

// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
DisplayName *string `json:"displayName,omitempty"`

// Whether the attachment was created in read-only mode.
IsReadOnly *bool `json:"isReadOnly,omitempty"`

// Whether the attachment should be created in shareable mode. If an attachment
// is created in shareable mode, then other instances can attach the same volume, provided
// that they also create their attachments in shareable mode. Only certain volume types can
// be attached in shareable mode. Defaults to false if not specified.
IsShareable *bool `json:"isShareable,omitempty"`

// The OCID of the volume. If CreateVolumeDetails is specified, this field must be omitted from the request.
VolumeId *string `json:"volumeId,omitempty"`

// LaunchCreateVolumeFromAttributes The details of the volume to create for CreateVolume operation.
LaunchCreateVolumeFromAttributes LaunchCreateVolumeFromAttributes `json:"launchCreateVolumeFromAttributes,omitempty"`

// Refer the top-level definition of encryptionInTransitType.
// The default value is False.
IsPvEncryptionInTransitEnabled *bool `json:"isPvEncryptionInTransitEnabled,omitempty"`
}


// LaunchCreateVolumeFromAttributes The details of the volume to create for CreateVolume operation.
type LaunchCreateVolumeFromAttributes struct {

Expand Down
17 changes: 17 additions & 0 deletions cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,10 @@ func (m *MachineScope) getLaunchVolumeAttachments() []core.LaunchAttachVolumeDet
for _, attachment := range volumeAttachmentsInSpec {
if attachment.Type == infrastructurev1beta2.IscsiType {
volumes = append(volumes, getIscsiVolumeAttachment(attachment.IscsiAttachment))
} else if attachment.Type == infrastructurev1beta2.ParavirtualizedType {
volumes = append(volumes, getParavirtualizedVolumeAttachment(attachment.ParavirtualizedAttachment))
} else {
m.Logger.Info("Block Volume attachment type not supported")
}
}
return volumes
Expand All @@ -1017,6 +1021,19 @@ func getIscsiVolumeAttachment(attachment infrastructurev1beta2.LaunchIscsiVolume
return volumeDetails
}

func getParavirtualizedVolumeAttachment(attachment infrastructurev1beta2.LaunchParavirtualizedVolumeAttachment) core.LaunchAttachVolumeDetails {
volumeDetails := core.LaunchAttachParavirtualizedVolumeDetails{
Device: attachment.Device,
DisplayName: attachment.DisplayName,
IsShareable: attachment.IsShareable,
IsReadOnly: attachment.IsReadOnly,
VolumeId: attachment.VolumeId,
IsPvEncryptionInTransitEnabled: attachment.IsPvEncryptionInTransitEnabled,
LaunchCreateVolumeDetails: getLaunchCreateVolumeDetails(attachment.LaunchCreateVolumeFromAttributes),
}
return volumeDetails
}

func getLaunchCreateVolumeDetails(attributes infrastructurev1beta2.LaunchCreateVolumeFromAttributes) core.LaunchCreateVolumeFromAttributes {
return core.LaunchCreateVolumeFromAttributes{
SizeInGBs: attributes.SizeInGBs,
Expand Down
96 changes: 96 additions & 0 deletions cloud/scope/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,102 @@ func TestInstanceReconciliation(t *testing.T) {
OpcRetryToken: ociutil.GetOPCRetryToken("machineuid")})).Return(core.LaunchInstanceResponse{}, nil)
},
},
{
name: "check all params together, with subnet id set, nsg id list",
errorExpected: false,
testSpecificSetup: func(machineScope *MachineScope, computeClient *mock_compute.MockComputeClient) {
setupAllParams(ms)
ms.OCIMachine.Spec.CapacityReservationId = common.String("cap-id")
ms.OCIMachine.Spec.DedicatedVmHostId = common.String("dedicated-host-id")
ms.OCIMachine.Spec.NetworkDetails.HostnameLabel = common.String("hostname-label")
ms.OCIMachine.Spec.NetworkDetails.SubnetId = common.String("subnet-machine-id")
ms.OCIMachine.Spec.NetworkDetails.NSGIds = []string{"nsg-machine-id-1", "nsg-machine-id-2"}
// above array should take precedence
ms.OCIMachine.Spec.NetworkDetails.NSGId = common.String("nsg-machine-id")
ms.OCIMachine.Spec.NetworkDetails.SkipSourceDestCheck = common.Bool(true)
ms.OCIMachine.Spec.NetworkDetails.AssignPrivateDnsRecord = common.Bool(true)
ms.OCIMachine.Spec.NetworkDetails.DisplayName = common.String("display-name")
ms.OCIMachine.Spec.LaunchVolumeAttachment = []infrastructurev1beta2.LaunchVolumeAttachment{
{
Type: infrastructurev1beta2.IscsiType,
IscsiAttachment: infrastructurev1beta2.LaunchIscsiVolumeAttachment{
Device: common.String("/dev/oci"),
IsShareable: common.Bool(true),
LaunchCreateVolumeFromAttributes: infrastructurev1beta2.LaunchCreateVolumeFromAttributes{
DisplayName: common.String("test-volume"),
SizeInGBs: common.Int64(75),
VpusPerGB: common.Int64(20),
},
},
},
}
ms.OCIMachine.Spec.InstanceSourceViaImageDetails = &infrastructurev1beta2.InstanceSourceViaImageConfig{
KmsKeyId: common.String("kms-key-id"),
BootVolumeVpusPerGB: common.Int64(32),
}
computeClient.EXPECT().ListInstances(gomock.Any(), gomock.Eq(core.ListInstancesRequest{
DisplayName: common.String("name"),
CompartmentId: common.String("test"),
})).Return(core.ListInstancesResponse{}, nil)

launchDetails := core.LaunchInstanceDetails{DisplayName: common.String("name"),
CapacityReservationId: common.String("cap-id"),
DedicatedVmHostId: common.String("dedicated-host-id"),
SourceDetails: core.InstanceSourceViaImageDetails{
ImageId: common.String("image"),
BootVolumeSizeInGBs: common.Int64(120),
KmsKeyId: common.String("kms-key-id"),
BootVolumeVpusPerGB: common.Int64(32),
},
CreateVnicDetails: &core.CreateVnicDetails{
SubnetId: common.String("subnet-machine-id"),
AssignPublicIp: common.Bool(false),
DefinedTags: map[string]map[string]interface{}{},
FreeformTags: map[string]string{
ociutil.CreatedBy: ociutil.OCIClusterAPIProvider,
ociutil.ClusterResourceIdentifier: "resource_uid",
},
NsgIds: []string{"nsg-machine-id-1", "nsg-machine-id-2"},
HostnameLabel: common.String("hostname-label"),
SkipSourceDestCheck: common.Bool(true),
AssignPrivateDnsRecord: common.Bool(true),
DisplayName: common.String("display-name"),
},
LaunchVolumeAttachments: []core.LaunchAttachVolumeDetails{
core.LaunchAttachParavirtualizedVolumeDetails{
Device: common.String("/dev/oci"),
IsShareable: common.Bool(true),
IsPvEncryptionInTransitEnabled: common.Bool(false),
LaunchCreateVolumeDetails: core.LaunchCreateVolumeFromAttributes{
DisplayName: common.String("test-volume"),
SizeInGBs: common.Int64(75),
VpusPerGB: common.Int64(20),
},
},
},
Metadata: map[string]string{
"user_data": base64.StdEncoding.EncodeToString([]byte("test")),
},
Shape: common.String("shape"),
ShapeConfig: &core.LaunchInstanceShapeConfigDetails{
Ocpus: common.Float32(2),
MemoryInGBs: common.Float32(100),
BaselineOcpuUtilization: core.LaunchInstanceShapeConfigDetailsBaselineOcpuUtilization8,
},
AvailabilityDomain: common.String("ad2"),
CompartmentId: common.String("test"),
IsPvEncryptionInTransitEnabled: common.Bool(true),
DefinedTags: map[string]map[string]interface{}{},
FreeformTags: map[string]string{
ociutil.CreatedBy: ociutil.OCIClusterAPIProvider,
ociutil.ClusterResourceIdentifier: "resource_uid",
},
}
computeClient.EXPECT().LaunchInstance(gomock.Any(), gomock.Eq(core.LaunchInstanceRequest{
LaunchInstanceDetails: launchDetails,
OpcRetryToken: ociutil.GetOPCRetryToken("machineuid")})).Return(core.LaunchInstanceResponse{}, nil)
},
},
{
name: "shape config is empty",
errorExpected: false,
Expand Down
Loading