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

support resource pool #119

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions api/v1beta1/proxmoxcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type ProxmoxClusterSpec struct {

// storage is used for storing cloud init snippet
Storage Storage `json:"storage,omitempty"`

// resource pool to be used for cappx managed vms by default
ResourcePool string `json:"resourcePool,omitempty"`
}

// ProxmoxClusterStatus defines the observed state of ProxmoxCluster
Expand Down
4 changes: 4 additions & 0 deletions api/v1beta1/proxmoxmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type ProxmoxMachineSpec struct {
// cappx will use random storage if empty
Storage string `json:"storage,omitempty"`

// Resource Pool that vm will be added to.
// Use ProxmoxCluster.spec.resroucePool if empty
ResourcePool string `json:"resourcePool,omitempty"`

// +kubebuilder:validation:Minimum:=0
// VMID is proxmox qemu's id
VMID *int `json:"vmID,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions cloud/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type ClusterGetter interface {
// FailureDomains() clusterv1.FailureDomains
ControlPlaneEndpoint() clusterv1.APIEndpoint
Storage() infrav1.Storage
ResourcePool() string
}

type ClusterSettter interface {
Expand All @@ -62,6 +63,7 @@ type MachineGetter interface {
GetInstanceStatus() *infrav1.InstanceStatus
GetClusterStorage() infrav1.Storage
GetStorage() string
GetResourcePool() string
GetCloudInit() infrav1.CloudInit
GetNetwork() infrav1.Network
GetHardware() infrav1.Hardware
Expand Down
21 changes: 15 additions & 6 deletions cloud/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ func (s *ClusterScope) Namespace() string {
return s.Cluster.Namespace
}

func (s *ClusterScope) CloudClient() *proxmox.Service {
return s.ProxmoxServices.Compute
}

func (s *ClusterScope) ControlPlaneEndpoint() clusterv1.APIEndpoint {
return s.ProxmoxCluster.Spec.ControlPlaneEndpoint
}
Expand All @@ -105,12 +109,13 @@ func (s *ClusterScope) Storage() infrav1.Storage {
return s.ProxmoxCluster.Spec.Storage
}

func (s *ClusterScope) CloudClient() *proxmox.Service {
return s.ProxmoxServices.Compute
}

func (s *ClusterScope) Close() error {
return s.PatchObject()
// retrun default values if it's not specified
func (s *ClusterScope) ResourcePool() string {
if s.ProxmoxCluster.Spec.ResourcePool == "" {
// use cluster name as default value
s.ProxmoxCluster.Spec.ResourcePool = s.Name()
}
return s.ProxmoxCluster.Spec.ResourcePool
}

func (s *ClusterScope) SetReady() {
Expand All @@ -125,6 +130,10 @@ func (s *ClusterScope) SetStorage(storage infrav1.Storage) {
s.ProxmoxCluster.Spec.Storage = storage
}

func (s *ClusterScope) Close() error {
return s.PatchObject()
}

// PatchObject persists the cluster configuration and status.
func (s *ClusterScope) PatchObject() error {
return s.patchHelper.Patch(context.TODO(), s.ProxmoxCluster)
Expand Down
97 changes: 51 additions & 46 deletions cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ type MachineScope struct {
SchedulerManager *scheduler.Manager
}

func (m *MachineScope) Name() string {
return m.ProxmoxMachine.Name
}

func (m *MachineScope) Namespace() string {
return m.ProxmoxMachine.Namespace
}

func (m *MachineScope) Annotations() map[string]string {
return m.ProxmoxMachine.Annotations
}

func (m *MachineScope) CloudClient() *proxmox.Service {
return m.ClusterGetter.CloudClient()
}
Expand All @@ -96,41 +108,50 @@ func (m *MachineScope) GetScheduler(client *proxmox.Service) *scheduler.Schedule
return sched
}

// return ProxmoxCluster.spec.storage
func (m *MachineScope) GetClusterStorage() infrav1.Storage {
return m.ClusterGetter.Storage()
}

func (m *MachineScope) GetStorage() string {
return m.ProxmoxMachine.Spec.Storage
func (m *MachineScope) GetVMID() *int {
return m.ProxmoxMachine.Spec.VMID
}

func (m *MachineScope) Name() string {
return m.ProxmoxMachine.Name
func (m *MachineScope) NodeName() string {
return m.ProxmoxMachine.Spec.Node
}

func (m *MachineScope) Namespace() string {
return m.ProxmoxMachine.Namespace
func (m *MachineScope) GetImage() infrav1.Image {
return m.ProxmoxMachine.Spec.Image
}

func (m *MachineScope) Annotations() map[string]string {
return m.ProxmoxMachine.Annotations
func (m *MachineScope) GetStorage() string {
return m.ProxmoxMachine.Spec.Storage
}

func (m *MachineScope) NodeName() string {
return m.ProxmoxMachine.Spec.Node
// return ProxmoxCluster.spec.resourcePool if empty
func (m *MachineScope) GetResourcePool() string {
if m.ProxmoxMachine.Spec.ResourcePool == "" {
m.ProxmoxMachine.Spec.ResourcePool = m.ClusterGetter.ResourcePool()
}
return m.ProxmoxMachine.Spec.ResourcePool
}

func (m *MachineScope) SetNodeName(name string) {
m.ProxmoxMachine.Spec.Node = name
func (m *MachineScope) GetCloudInit() infrav1.CloudInit {
return m.ProxmoxMachine.Spec.CloudInit
}

func (m *MachineScope) SetStorage(name string) {
m.ProxmoxMachine.Spec.Storage = name
func (m *MachineScope) GetNetwork() infrav1.Network {
return m.ProxmoxMachine.Spec.Network
}

// func (m *MachineScope) Client() Compute {
// return m.ClusterGetter.Client()
// }
func (m *MachineScope) GetHardware() infrav1.Hardware {
return m.ProxmoxMachine.Spec.Hardware
}

func (m *MachineScope) GetOptions() infrav1.Options {
return m.ProxmoxMachine.Spec.Options
}

func (m *MachineScope) GetBootstrapData() (string, error) {
if m.Machine.Spec.Bootstrap.DataSecretName == nil {
Expand All @@ -151,19 +172,10 @@ func (m *MachineScope) GetBootstrapData() (string, error) {
return string(value), nil
}

func (m *MachineScope) Close() error {
return m.PatchObject()
}

func (m *MachineScope) GetInstanceStatus() *infrav1.InstanceStatus {
return m.ProxmoxMachine.Status.InstanceStatus
}

// SetInstanceStatus sets the ProxmoxMachine instance status.
func (m *MachineScope) SetInstanceStatus(v infrav1.InstanceStatus) {
m.ProxmoxMachine.Status.InstanceStatus = &v
}

func (m *MachineScope) GetBiosUUID() *string {
parsed, err := noderefutil.NewProviderID(m.GetProviderID()) //nolint: staticcheck
if err != nil {
Expand All @@ -179,28 +191,12 @@ func (m *MachineScope) GetProviderID() string {
return ""
}

func (m *MachineScope) GetVMID() *int {
return m.ProxmoxMachine.Spec.VMID
}

func (m *MachineScope) GetImage() infrav1.Image {
return m.ProxmoxMachine.Spec.Image
}

func (m *MachineScope) GetCloudInit() infrav1.CloudInit {
return m.ProxmoxMachine.Spec.CloudInit
}

func (m *MachineScope) GetNetwork() infrav1.Network {
return m.ProxmoxMachine.Spec.Network
}

func (m *MachineScope) GetHardware() infrav1.Hardware {
return m.ProxmoxMachine.Spec.Hardware
func (m *MachineScope) SetNodeName(name string) {
m.ProxmoxMachine.Spec.Node = name
}

func (m *MachineScope) GetOptions() infrav1.Options {
return m.ProxmoxMachine.Spec.Options
func (m *MachineScope) SetStorage(name string) {
m.ProxmoxMachine.Spec.Storage = name
}

// SetProviderID sets the ProxmoxMachine providerID in spec.
Expand All @@ -221,6 +217,11 @@ func (m *MachineScope) SetConfigStatus(config api.VirtualMachineConfig) {
m.ProxmoxMachine.Status.Config = config
}

// SetInstanceStatus sets the ProxmoxMachine instance status.
func (m *MachineScope) SetInstanceStatus(v infrav1.InstanceStatus) {
m.ProxmoxMachine.Status.InstanceStatus = &v
}

func (m *MachineScope) SetReady() {
m.ProxmoxMachine.Status.Ready = true
}
Expand All @@ -233,6 +234,10 @@ func (m *MachineScope) SetFailureReason(v capierrors.MachineStatusError) {
m.ProxmoxMachine.Status.FailureReason = &v
}

func (m *MachineScope) Close() error {
return m.PatchObject()
}

// PatchObject persists the cluster configuration and status.
func (s *MachineScope) PatchObject() error {
return s.patchHelper.Patch(context.TODO(), s.ProxmoxMachine)
Expand Down
12 changes: 12 additions & 0 deletions cloud/services/compute/instance/pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package instance

import "context"

// add vm to resource pool
func (s *Service) reconcileResourcePool(ctx context.Context) error {
pool, err := s.client.Pool(ctx, s.scope.GetResourcePool())
if err != nil {
return err
}
return pool.AddVMs(ctx, []int{*s.scope.GetVMID()})
}
8 changes: 7 additions & 1 deletion cloud/services/compute/instance/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func (s *Service) Reconcile(ctx context.Context) error {
return err
}

log.Info(fmt.Sprintf("Reconciled instance: bios-uuid=%s", *uuid))
if err := s.scope.SetProviderID(*uuid); err != nil {
return err
}
Expand All @@ -46,6 +45,13 @@ func (s *Service) Reconcile(ctx context.Context) error {
return err
}
s.scope.SetConfigStatus(*config)

// add vm to resource pool
if err := s.reconcileResourcePool(ctx); err != nil {
return err
}

log.Info("Reconciled instance")
return nil
}

Expand Down
84 changes: 84 additions & 0 deletions cloud/services/compute/resourcepool/reconcile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package resourcepool

import (
"context"
"fmt"

"github.com/sp-yduck/proxmox-go/api"
"github.com/sp-yduck/proxmox-go/proxmox"
"github.com/sp-yduck/proxmox-go/rest"
"sigs.k8s.io/controller-runtime/pkg/log"
)

const (
DefaultBasePath = "/var/lib/vz"
)

func (s *Service) Reconcile(ctx context.Context) error {
log := log.FromContext(ctx)
log.Info("Reconciling resource pool")

pool, err := s.createOrGetResourcePool(ctx)
if err != nil {
return err
}

if err := pool.AddStorages(ctx, []string{s.scope.Storage().Name}); err != nil {
log.Error(err, "failed to add sotrage to pool")
return err
}

log.Info("Reconciled resource pool")
return nil
}

func (s *Service) Delete(ctx context.Context) error {
log := log.FromContext(ctx)
log.Info("Deleteing resource pool")
return s.deleteResourcePool(ctx)
}

func (s *Service) createOrGetResourcePool(ctx context.Context) (*proxmox.Pool, error) {
log := log.FromContext(ctx)

pool, err := s.client.Pool(ctx, s.scope.ResourcePool())
if err != nil {
if rest.IsNotFound(err) {
log.Info("resource pool not found. it will be created")
return s.createResourcePool(ctx)
}
log.Error(err, "failed to get resource pool")
return nil, err
}
return pool, nil
}

func (s *Service) createResourcePool(ctx context.Context) (*proxmox.Pool, error) {
pool := api.ResourcePool{
PoolID: s.scope.ResourcePool(),
Comment: fmt.Sprintf("Default Resource Pool used for %s cluster", s.scope.Name()),
}
return s.client.CreatePool(ctx, pool)
}

func (s *Service) deleteResourcePool(ctx context.Context) error {
log := log.FromContext(ctx)
poolid := s.scope.ResourcePool()
pool, err := s.client.Pool(ctx, poolid)
if err != nil {
if rest.IsNotFound(err) {
log.Info("resource pool not found or already deleted")
return nil
}
return err
}
members, err := pool.GetMembers(ctx)
if err != nil {
return err
}
if len(members) != 0 {
log.Info("resource pool not empty, skipping deletion")
return nil
}
return s.client.DeletePool(ctx, poolid)
}
Loading