Skip to content

Ipv6 implementation #410

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

Merged
merged 9 commits into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 2 additions & 17 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,8 @@ _artifacts/
config/default/manager_image_patch.yaml-e
config/default/manager_pull_policy.yaml-e
test/e2e/config/e2e_conf-envsubst.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-antrea.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-ccm-testing.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-kcp-remediation.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-md-remediation.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-node-drain.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-oracle-linux.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-bare-metal.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-custom-networking-seclist.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-custom-networking-nsg.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-multiple-node-nsg.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-local-vcn-peering.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-cluster-class.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-remote-vcn-peering.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-externally-managed-vcn.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-alternative-region.yaml
test/e2e/data/infrastructure-oci/v1beta1/cluster-template-machine-pool.yaml
test/e2e/data/infrastructure-oci/v1beta*/cluster-template*.yaml


# tilt
tilt-settings.json
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ generate-e2e-templates: $(KUSTOMIZE)
$(KUSTOMIZE) build $(OCI_TEMPLATES)/v1beta2/cluster-template-windows-calico --load-restrictor LoadRestrictionsNone > $(OCI_TEMPLATES)/v1beta2/cluster-template-windows-calico.yaml
$(KUSTOMIZE) build $(OCI_TEMPLATES)/v1beta2/cluster-template-managed-virtual --load-restrictor LoadRestrictionsNone > $(OCI_TEMPLATES)/v1beta2/cluster-template-managed-virtual.yaml
$(KUSTOMIZE) build $(OCI_TEMPLATES)/v1beta2/cluster-template-managed-self-managed-nodes --load-restrictor LoadRestrictionsNone > $(OCI_TEMPLATES)/v1beta2/cluster-template-managed-self-managed-nodes.yaml
$(KUSTOMIZE) build $(OCI_TEMPLATES)/v1beta2/cluster-template-machine-with-ipv6 --load-restrictor LoadRestrictionsNone > $(OCI_TEMPLATES)/v1beta2/cluster-template-machine-with-ipv6.yaml
$(KUSTOMIZE) build $(OCI_TEMPLATES)/v1beta2/cluster-template-with-paravirt-bv --load-restrictor LoadRestrictionsNone > $(OCI_TEMPLATES)/v1beta2/cluster-template-with-paravirt-bv.yaml

.PHONY: test-e2e-run
test-e2e-run: generate-e2e-templates $(GINKGO) $(ENVSUBST) ## Run e2e tests
Expand Down
22 changes: 19 additions & 3 deletions api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type NetworkDetails struct {
// SubnetId defines the ID of the subnet to use. This parameter takes priority over SubnetName.
SubnetId *string `json:"subnetId,omitempty"`

// IPv6 defines if the instance should have an IPv6
AssignIpv6Ip bool `json:"assignIpv6Ip,omitempty"`

// AssignPublicIp defines whether the instance should have a public IP address
AssignPublicIp bool `json:"assignPublicIp,omitempty"`

Expand Down Expand Up @@ -71,6 +74,9 @@ type VnicAttachment struct {
// VnicAttachmentId defines the ID of the VnicAttachment
VnicAttachmentId *string `json:"vnicAttachmentId,omitempty"`

// IPv6 defines if the instance should have an IPv6
AssignIpv6Ip bool `json:"assignIpv6Ip,omitempty"`

// AssignPublicIp defines whether the vnic should have a public IP address
// +optional
AssignPublicIp bool `json:"assignPublicIp,omitempty"`
Expand Down Expand Up @@ -866,6 +872,8 @@ type Subnet struct {
// within this subnet (for example, `bminstance1.subnet123.vcn1.oraclevcn.com`).
// +optional
DnsLabel *string `json:"dnsLabel,omitempty"`

Ipv6CidrBlockHextet *string `json:"ipv6CidrBlockHextet,omitempty"`
}

// NSG defines configuration for a Network Security Group.
Expand Down Expand Up @@ -942,6 +950,14 @@ type VCN struct {
// within this subnet (for example, `bminstance1.subnet123.vcn1.oraclevcn.com`).
// +optional
DnsLabel *string `json:"dnsLabel,omitempty"`

// Configuration to allow OCI to assign IPv6 Prefix.
// +optional
IsOracleGuaAllocationEnabled *bool `json:"isOracleGuaAllocationEnabled,omitempty"`

// Configuration to enable IPv6.
// +optional
IsIpv6Enabled *bool `json:"isIpv6Enabled,omitempty"`
}

// LoadBalancer Configuration
Expand Down Expand Up @@ -1097,7 +1113,7 @@ type RemotePeeringConnection struct {
type VolumeType string

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

Expand All @@ -1115,7 +1131,7 @@ type LaunchVolumeAttachment struct {
Type VolumeType `json:"volumeType,omitempty"`

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

Expand Down Expand Up @@ -1177,7 +1193,7 @@ type LaunchParavirtualizedVolumeAttachment struct {

// 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"`
Expand Down
28 changes: 25 additions & 3 deletions api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ type NetworkDetails struct {
// SubnetId defines the ID of the subnet to use. This parameter takes priority over SubnetName.
SubnetId *string `json:"subnetId,omitempty"`

// AssignIPv6 determines whether to assign a IPv6 address to the instance.
// +optional
AssignIpv6Ip bool `json:"assignIpv6Ip,omitempty"`

// AssignPublicIp defines whether the instance should have a public IP address
AssignPublicIp bool `json:"assignPublicIp,omitempty"`

Expand Down Expand Up @@ -72,6 +76,10 @@ type VnicAttachment struct {
// VnicAttachmentId defines the ID of the VnicAttachment
VnicAttachmentId *string `json:"vnicAttachmentId,omitempty"`

// AssignIPv6 defines whether the vnic should have a IPv6 address
// +optional
AssignIpv6Ip bool `json:"assignIpv6Ip,omitempty"`

// AssignPublicIp defines whether the vnic should have a public IP address
// +optional
AssignPublicIp bool `json:"assignPublicIp,omitempty"`
Expand Down Expand Up @@ -865,6 +873,13 @@ type Subnet struct {
// within this subnet (for example, `bminstance1.subnet123.vcn1.oraclevcn.com`).
// +optional
DnsLabel *string `json:"dnsLabel,omitempty"`

// Use this to enable IPv6 hextet for this subnet. The VCN must be enabled for IPv6.
// You can't change this subnet characteristic later. All subnets are /64 in size. The subnet
// portion of the IPv6 address is the fourth hextet from the left (1111 in the following example).
// Example: `2001:0db8:0123:1111::/64`
// +optional
Ipv6CidrBlockHextet *string `json:"ipv6CidrBlockHextet,omitempty"`
}

// NSG defines configuration for a Network Security Group.
Expand Down Expand Up @@ -935,6 +950,14 @@ type VCN struct {
// within this subnet (for example, `bminstance1.subnet123.vcn1.oraclevcn.com`).
// +optional
DnsLabel *string `json:"dnsLabel,omitempty"`

// Configuration to allow OCI to assign IPv6 Prefix.
// +optional
IsOracleGuaAllocationEnabled *bool `json:"isOracleGuaAllocationEnabled,omitempty"`

// Configuration to enable IPv6.
// +optional
IsIpv6Enabled *bool `json:"isIpv6Enabled,omitempty"`
}

// LoadBalancerType is an enumeration of the supported load balancer types.
Expand Down Expand Up @@ -1167,7 +1190,7 @@ type NetworkSecurityGroup struct {
type VolumeType string

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

Expand All @@ -1186,7 +1209,7 @@ type LaunchVolumeAttachment struct {
Type VolumeType `json:"volumeType,omitempty"`

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

Expand Down Expand Up @@ -1254,7 +1277,6 @@ type LaunchParavirtualizedVolumeAttachment struct {
IsPvEncryptionInTransitEnabled *bool `json:"isPvEncryptionInTransitEnabled,omitempty"`
}


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

Expand Down
15 changes: 8 additions & 7 deletions cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ func (m *MachineScope) GetOrCreateMachine(ctx context.Context) (*core.Instance,
SourceDetails: sourceDetails,
CreateVnicDetails: &core.CreateVnicDetails{
SubnetId: subnetId,
AssignIpv6Ip: common.Bool(m.OCIMachine.Spec.NetworkDetails.AssignIpv6Ip),
AssignPublicIp: common.Bool(m.OCIMachine.Spec.NetworkDetails.AssignPublicIp),
FreeformTags: tags,
DefinedTags: definedTags,
Expand Down Expand Up @@ -1023,13 +1024,13 @@ func getIscsiVolumeAttachment(attachment infrastructurev1beta2.LaunchIscsiVolume

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),
Device: attachment.Device,
DisplayName: attachment.DisplayName,
IsShareable: attachment.IsShareable,
IsReadOnly: attachment.IsReadOnly,
VolumeId: attachment.VolumeId,
IsPvEncryptionInTransitEnabled: attachment.IsPvEncryptionInTransitEnabled,
LaunchCreateVolumeDetails: getLaunchCreateVolumeDetails(attachment.LaunchCreateVolumeFromAttributes),
}
return volumeDetails
}
Expand Down
12 changes: 12 additions & 0 deletions cloud/scope/route_table_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ func (s *ClusterScope) CreateRouteTable(ctx context.Context, routeTableType stri
Description: common.String("traffic to/from internet"),
},
}
resp, err := s.VCNClient.GetVcn(ctx, core.GetVcnRequest{VcnId: s.getVcnId()})
if err != nil {
panic(err)
}
if resp.Vcn.Ipv6CidrBlocks != nil {
routeRules = append(routeRules, core.RouteRule{
DestinationType: core.RouteRuleDestinationTypeCidrBlock,
Destination: common.String("::/0"),
NetworkEntityId: s.OCIClusterAccessor.GetNetworkSpec().Vcn.InternetGateway.Id,
Description: common.String("ipv6 traffic to/from internet"),
})
}
routeTableName = PublicRouteTableName
}
vcnId := s.getVcnId()
Expand Down
34 changes: 34 additions & 0 deletions cloud/scope/subnet_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ package scope

import (
"context"
"fmt"
"net"
"strings"

infrastructurev1beta2 "github.com/oracle/cluster-api-provider-oci/api/v1beta2"
"github.com/oracle/cluster-api-provider-oci/cloud/ociutil"
Expand Down Expand Up @@ -101,6 +104,35 @@ func (s *ClusterScope) CreateSubnet(ctx context.Context, spec infrastructurev1be
} else {
routeTable = s.getRouteTableId(infrastructurev1beta2.Public)
}

resp, err := s.VCNClient.GetVcn(ctx, core.GetVcnRequest{VcnId: s.getVcnId()})

var ipv6subnetCIDR_Ptr *string

if resp.Vcn.Ipv6CidrBlocks != nil {
vcnCIDR := resp.Vcn.Ipv6CidrBlocks[0]

ip, _, err := net.ParseCIDR(vcnCIDR)
if err != nil {
panic(err)
}

// Split into hextets
hextets := strings.Split(ip.String(), ":")

// Modify the 4th hextet (index 3)
originalHextet := hextets[3]
if len(originalHextet) < 4 {
originalHextet = fmt.Sprintf("%04s", originalHextet) // pad with leading zeros if needed
}
newHextet := originalHextet[:2] + *spec.Ipv6CidrBlockHextet
hextets[3] = newHextet

// Reconstruct the IPv6 address with a /64 CIDR
ipv6subnetCIDR := strings.Join(hextets, ":") + "/64"
ipv6subnetCIDR_Ptr = &ipv6subnetCIDR
}

createSubnetDetails := core.CreateSubnetDetails{
CompartmentId: common.String(s.GetCompartmentId()),
CidrBlock: common.String(spec.CIDR),
Expand All @@ -112,7 +144,9 @@ func (s *ClusterScope) CreateSubnet(ctx context.Context, spec infrastructurev1be
FreeformTags: s.GetFreeFormTags(),
DefinedTags: s.GetDefinedTags(),
DnsLabel: spec.DnsLabel,
Ipv6CidrBlock: ipv6subnetCIDR_Ptr,
}

if spec.SecurityList != nil {
createSubnetDetails.SecurityListIds = []string{*spec.SecurityList.ID}
}
Expand Down
14 changes: 8 additions & 6 deletions cloud/scope/vcn_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@ func (s *ClusterScope) UpdateVCN(ctx context.Context, vcn infrastructurev1beta2.

func (s *ClusterScope) CreateVCN(ctx context.Context, spec infrastructurev1beta2.VCN) (*string, error) {
vcnDetails := core.CreateVcnDetails{
CompartmentId: common.String(s.GetCompartmentId()),
DisplayName: common.String(s.GetVcnName()),
CidrBlocks: s.GetVcnCidrs(),
FreeformTags: s.GetFreeFormTags(),
DefinedTags: s.GetDefinedTags(),
DnsLabel: spec.DnsLabel,
CompartmentId: common.String(s.GetCompartmentId()),
DisplayName: common.String(s.GetVcnName()),
CidrBlocks: s.GetVcnCidrs(),
FreeformTags: s.GetFreeFormTags(),
DefinedTags: s.GetDefinedTags(),
DnsLabel: spec.DnsLabel,
IsOracleGuaAllocationEnabled: spec.IsOracleGuaAllocationEnabled,
IsIpv6Enabled: spec.IsIpv6Enabled,
}
vcnResponse, err := s.VCNClient.CreateVcn(ctx, core.CreateVcnRequest{
CreateVcnDetails: vcnDetails,
Expand Down
16 changes: 10 additions & 6 deletions cloud/scope/vcn_reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ func TestClusterScope_CreateVCN(t *testing.T) {
spec: infrastructurev1beta2.OCIClusterSpec{
NetworkSpec: infrastructurev1beta2.NetworkSpec{
Vcn: infrastructurev1beta2.VCN{
Name: "normal",
DnsLabel: common.String("label"),
CIDR: "test-cidr",
Name: "normal",
DnsLabel: common.String("label"),
CIDR: "test-cidr",
IsIpv6Enabled: common.Bool(true),
IsOracleGuaAllocationEnabled: common.Bool(true),
},
},
},
Expand All @@ -85,9 +87,11 @@ func TestClusterScope_CreateVCN(t *testing.T) {
spec: infrastructurev1beta2.OCIClusterSpec{
NetworkSpec: infrastructurev1beta2.NetworkSpec{
Vcn: infrastructurev1beta2.VCN{
Name: "normal",
DnsLabel: common.String("label"),
CIDRS: []string{"test-cidr1", "test-cidr2"},
Name: "normal",
DnsLabel: common.String("label"),
CIDRS: []string{"test-cidr1", "test-cidr2"},
IsIpv6Enabled: common.Bool(true),
IsOracleGuaAllocationEnabled: common.Bool(true),
},
},
},
Expand Down
18 changes: 18 additions & 0 deletions config/crd/bases/infrastructure.cluster.x-k8s.io_ociclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ spec:
vcn:
description: VCN configuration.
properties:
isIpv6Enabled:
description: isIpv6Enabled enables the possibility to assign IPv6 to cluster nodes.
type: boolean
isOracleGuaAllocationEnabled:
description: isOracleGuaAllocationEnabled enables OCI to assign a /56 prefix.
type: boolean
cidr:
description: VCN CIDR. Deprecated, please use NetworkDetails.cidrs
type: string
Expand Down Expand Up @@ -591,6 +597,9 @@ spec:
DNS label to form a fully qualified domain name (FQDN)
for each VNIC within this subnet (for example, `bminstance1.subnet123.vcn1.oraclevcn.com`).
type: string
ipv6CidrBlockHextet:
description: Subnet IPv6 CIDR.
type: string
id:
description: Subnet OCID.
type: string
Expand Down Expand Up @@ -1382,6 +1391,12 @@ spec:
vcn:
description: VCN configuration.
properties:
isIpv6Enabled:
description: isIpv6Enabled enables the possibility to assign IPv6 to cluster nodes.
type: boolean
isOracleGuaAllocationEnabled:
description: isOracleGuaAllocationEnabled enables OCI to assign a /56 prefix.
type: boolean
cidr:
description: VCN CIDR. Deprecated, please use NetworkDetails.cidrs
type: string
Expand Down Expand Up @@ -1866,6 +1881,9 @@ spec:
DNS label to form a fully qualified domain name (FQDN)
for each VNIC within this subnet (for example, `bminstance1.subnet123.vcn1.oraclevcn.com`).
type: string
ipv6CidrBlockHextet:
description: Subnet IPv6 CIDR.
type: string
id:
description: Subnet OCID.
type: string
Expand Down
Loading