Skip to content

Commit

Permalink
Added vSphere multi disk support
Browse files Browse the repository at this point in the history
  • Loading branch information
vr4manta committed Sep 23, 2024
1 parent b92f797 commit 50e2f21
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 7 deletions.
11 changes: 11 additions & 0 deletions pkg/asset/machines/vsphere/machines.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,16 @@ func provider(clusterID string, vcenter *vsphere.VCenter, failureDomain vsphere.
networkDeviceSpec[i] = machineapi.NetworkDeviceSpec{NetworkName: network}
}

additionalDisks := []*machineapi.VSphereDisk{}
for i, curDisk := range mpool.AdditionalDisks {
diskName := fmt.Sprintf("Disk_%d", (i + 1))
newDisk := &machineapi.VSphereDisk{
DeviceName: &diskName,
SizeGB: int64(curDisk.DiskSizeGB),
}
additionalDisks = append(additionalDisks, newDisk)
}

return &machineapi.VSphereMachineProviderSpec{
TypeMeta: metav1.TypeMeta{
APIVersion: machineapi.SchemeGroupVersion.String(),
Expand All @@ -358,6 +368,7 @@ func provider(clusterID string, vcenter *vsphere.VCenter, failureDomain vsphere.
NumCoresPerSocket: mpool.NumCoresPerSocket,
MemoryMiB: mpool.MemoryMiB,
DiskGiB: mpool.OSDisk.DiskSizeGB,
Disks: additionalDisks,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/destroy/ovirt/destroyer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"sync"
"time"

"github.com/ovirt/go-ovirt"
ovirtsdk "github.com/ovirt/go-ovirt"
"github.com/sirupsen/logrus"

"github.com/openshift/installer/pkg/asset/installconfig/ovirt"
Expand Down
7 changes: 4 additions & 3 deletions pkg/infrastructure/clusterapi/clusterapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,10 @@ func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset

if p, ok := i.impl.(PostProvider); ok {
postMachineInput := PostProvisionInput{
Client: cl,
InstallConfig: installConfig,
InfraID: clusterID.InfraID,
Client: cl,
InstallConfig: installConfig,
InfraID: clusterID.InfraID,
MachineManifests: machineManifests,
}

timer.StartTimer(postProvisionStage)
Expand Down
7 changes: 4 additions & 3 deletions pkg/infrastructure/clusterapi/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ type PostProvider interface {

// PostProvisionInput collects the args passed to the PostProvision hook.
type PostProvisionInput struct {
Client client.Client
InstallConfig *installconfig.InstallConfig
InfraID string
Client client.Client
InstallConfig *installconfig.InstallConfig
InfraID string
MachineManifests []client.Object
}

// BootstrapDestroyer allows platform-specific behavior when
Expand Down
94 changes: 94 additions & 0 deletions pkg/infrastructure/vsphere/clusterapi/clusterapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package clusterapi

import (
"context"
"errors"
"fmt"
"path"
"strings"

"github.com/sirupsen/logrus"
"github.com/vmware/govmomi/object"
"sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/session"
Expand Down Expand Up @@ -134,6 +136,43 @@ func (p Provider) PreProvision(ctx context.Context, in clusterapi.PreProvisionIn
return nil
}

// InfraReady is called once cluster.Status.InfrastructureReady
// is true, typically after load balancers have been provisioned. It can be used
// to create DNS records.
func (p Provider) InfraReady(ctx context.Context, in clusterapi.InfraReadyInput) error {
return nil
}

// PostProvision should be called to add or update and vSphere resources after provisioning has completed.
func (p Provider) PostProvision(ctx context.Context, in clusterapi.PostProvisionInput) error {
// We will want to check to see if ControlPlane machines need additional disks
cpPool := in.InstallConfig.Config.ControlPlane.Platform.VSphere
if len(cpPool.AdditionalDisks) > 0 {
logrus.Info("Adding additional disks to control plane machines")

for i := range in.MachineManifests {
if vm, ok := in.MachineManifests[i].(*v1beta1.VSphereMachine); ok {
if !strings.HasSuffix(vm.Name, "bootstrap") {
logrus.Infof("Adding additional disks to vm %s", vm.Name)
server := vm.Spec.Server
vctrSession, err := in.InstallConfig.VSphere.Session(context.TODO(), server)

if err != nil {
return err
}
err = addAdditionalDisks(ctx, vm, cpPool, vctrSession)

if err != nil {
return err
}
}
}
}
}

return nil
}

// downloadImage if any failure domains don't have a defined template, this function
// returns true.
func downloadImage(installConfig *installconfig.InstallConfig) bool {
Expand All @@ -144,3 +183,58 @@ func downloadImage(installConfig *installconfig.InstallConfig) bool {
}
return false
}

func addAdditionalDisks(ctx context.Context, machine *v1beta1.VSphereMachine, pool *vsphere.MachinePool, session *session.Session) error {
logrus.Debugf("Getting vm %v", machine.Name)
vm, err := session.Finder.VirtualMachine(ctx, fmt.Sprintf("%s/%s", machine.Spec.Folder, machine.Name))
offset := 1 // For now, we assume only one disk is current attached to VM.

if err != nil {
return err
}

logrus.Debugf("Getting VM devices")
devices, err := vm.Device(ctx)
if err != nil {
return err
}

logrus.Debugf("Getting datastore %v", machine.Spec.Datastore)
ds, err := session.Finder.Datastore(ctx, machine.Spec.Datastore)
if err != nil {
return err
}

// For now, we only do the active scsi controller
logrus.Debug("Getting scsi controller")
controller, err := devices.FindSCSIController("")
if err != nil {
return err
}

for diskIndex, newDisk := range pool.AdditionalDisks {
logrus.Debugf("Attempting to add disk %d with size %dGB", diskIndex, newDisk.DiskSizeGB)

disk := devices.CreateDisk(controller, ds.Reference(), "")

existing := devices.SelectByBackingInfo(disk.Backing)

if len(existing) > 0 {
logrus.Warningf("Disk already present for index %d", diskIndex)
return errors.New("disk already present")
}

disk.CapacityInKB = int64(newDisk.DiskSizeGB) * 1024 * 1024
unitNumber := int32(offset + diskIndex)
disk.VirtualDevice.UnitNumber = &unitNumber

// Add disk using default profile of VM.
logrus.Infof("Adding disk device to vm %v", disk)
err = vm.AddDevice(ctx, disk)
if err != nil {
return err
}
}

return nil
}
17 changes: 17 additions & 0 deletions pkg/types/vsphere/machinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ type MachinePool struct {
// +optional
OSDisk `json:"osDisk"`

// AdditionalDisks defines additional disks to add to vm that are not part of the template.
//
// +optional
AdditionalDisks []AdditionalDisks `json:"additionalDisks"`

// Zones defines available zones
// Zones is available in TechPreview.
//
Expand All @@ -39,6 +44,14 @@ type OSDisk struct {
DiskSizeGB int32 `json:"diskSizeGB"`
}

// AdditionalDisks defines the disk for a virtual machine.
type AdditionalDisks struct {
// DiskSizeGB defines the size of disk in GB.
//
// +optional
DiskSizeGB int32 `json:"diskSizeGB"`
}

// Set sets the values from `required` to `p`.
func (p *MachinePool) Set(required *MachinePool) {
if required == nil || p == nil {
Expand All @@ -64,4 +77,8 @@ func (p *MachinePool) Set(required *MachinePool) {
if len(required.Zones) > 0 {
p.Zones = required.Zones
}

if len(required.AdditionalDisks) > 0 {
p.AdditionalDisks = required.AdditionalDisks
}
}
24 changes: 24 additions & 0 deletions pkg/types/vsphere/validation/featuregates.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func GatedFeatures(c *types.InstallConfig) []featuregates.GatedInstallConfigFeat
}
}

cpDef := c.ControlPlane.Platform.VSphere
computeDefs := c.Compute

return []featuregates.GatedInstallConfigFeature{
{
FeatureGateName: features.FeatureGateVSphereStaticIPs,
Expand All @@ -43,5 +46,26 @@ func GatedFeatures(c *types.InstallConfig) []featuregates.GatedInstallConfigFeat
Condition: nodeNetworkingDefined,
Field: field.NewPath("platform", "vsphere", "nodeNetworking"),
},
{
FeatureGateName: features.FeatureGateVSphereMultiDisk,
Condition: len(cpDef.AdditionalDisks) > 0, // Here we need to check disk count
Field: field.NewPath("controlPlane", "platform", "vsphere", "additionalDisks"),
},
{
FeatureGateName: features.FeatureGateVSphereMultiDisk,
Condition: hasAdditionalDisks(computeDefs), // Here we need to check disk count
Field: field.NewPath("compute", "platform", "vsphere", "additionalDisks"),
},
}
}

func hasAdditionalDisks(pool []types.MachinePool) bool {
foundAdditionalDisks := false
for _, machine := range pool {
if len(machine.Platform.VSphere.AdditionalDisks) > 0 {
foundAdditionalDisks = true
break
}
}
return foundAdditionalDisks
}

0 comments on commit 50e2f21

Please sign in to comment.