Skip to content
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
100 changes: 98 additions & 2 deletions api/v1/storagepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"strings"

lclient "github.com/LINBIT/golinstor/client"
"golang.org/x/exp/slices"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

type LinstorStoragePool struct {
Expand Down Expand Up @@ -104,14 +106,90 @@ func (p *LinstorStoragePool) PoolName() string {
return ""
}

func (p *LinstorStoragePool) PvCreateArguments() []string {
switch {
case p.LvmPool != nil:
return p.LvmPool.PhysicalVolumeCreateArguments
case p.LvmThinPool != nil:
return p.LvmThinPool.PhysicalVolumeCreateArguments
default:
return nil
}
}

func (p *LinstorStoragePool) VgCreateArguments() []string {
switch {
case p.LvmPool != nil:
return p.LvmPool.VolumeGroupCreateArguments
case p.LvmThinPool != nil:
return p.LvmThinPool.VolumeGroupCreateArguments
default:
return nil
}
}

func (p *LinstorStoragePool) LvCreateArguments() []string {
switch {
case p.LvmThinPool != nil:
return p.LvmThinPool.LogicalVolumeCreateArguments
default:
return nil
}
}

func (p *LinstorStoragePool) ZpoolCreateArguments() []string {
switch {
case p.ZfsPool != nil:
if len(p.ZfsPool.ZpoolCreateArguments) == 0 {
return []string{"-o", "failmode=continue"}
}

return p.ZfsPool.ZpoolCreateArguments
case p.ZfsThinPool != nil:
if len(p.ZfsThinPool.ZpoolCreateArguments) == 0 {
return []string{"-o", "failmode=continue"}
}

return p.ZfsThinPool.ZpoolCreateArguments
default:
return nil
}
}

type LinstorStoragePoolLvm struct {
// VolumeGroup is the name of the Volume Group (VG) to use.
VolumeGroup string `json:"volumeGroup,omitempty"`

// PhysicalVolumeCreateArguments are arguments to pass to "pvcreate".
// This has no effect on an existing VG, it only applies the VG initially gets created.
// +kubebuilder:validation:Optional
PhysicalVolumeCreateArguments []string `json:"physicalVolumeCreateArguments,omitempty"`

// VolumeGroupCreateArguments are arguments to pass to "vgcreate".
// This has no effect on an existing VG, it only applies the VG initially gets created.
// +kubebuilder:validation:Optional
VolumeGroupCreateArguments []string `json:"volumeGroupCreateArguments,omitempty"`
}

type LinstorStoragePoolLvmThin struct {
VolumeGroup string `json:"volumeGroup,omitempty"`
// ThinPool is the name of the thinpool LV (without VG prefix).
ThinPool string `json:"thinPool,omitempty"`

// PhysicalVolumeCreateArguments are arguments to pass to "pvcreate".
// This has no effect on an existing VG, it only applies the VG initially gets created.
// +kubebuilder:validation:Optional
PhysicalVolumeCreateArguments []string `json:"physicalVolumeCreateArguments,omitempty"`

// VolumeGroupCreateArguments are arguments to pass to "vgcreate".
// This has no effect on an existing VG, it only applies the VG initially gets created.
// +kubebuilder:validation:Optional
VolumeGroupCreateArguments []string `json:"volumeGroupCreateArguments,omitempty"`

// LogicalVolumeCreateArguments are arguments to pass to "lvcreate".
// This has no effect on an existing thinpool, it only applies the thinpool initially gets created.
// +kubebuilder:validation:Optional
LogicalVolumeCreateArguments []string `json:"logicalVolumeCreateArguments,omitempty"`
}

type LinstorStoragePoolFile struct {
Expand All @@ -122,6 +200,15 @@ type LinstorStoragePoolFile struct {
type LinstorStoragePoolZfs struct {
// ZPool is the name of the ZFS zpool.
ZPool string `json:"zPool,omitempty"`

// ZpoolCreateArguments are arguments to pass to "zpool create".
// This has no effect on an existing zpool, it only applies the zpool initially gets created.
//
// If not set, "-o failmode=continue" is automatically added to ensure a failed zpool does not stop replication
// to and from other nodes in the cluster.
//
// +kubebuilder:validation:Optional
ZpoolCreateArguments []string `json:"zpoolCreateArguments,omitempty"`
}

type LinstorStoragePoolSource struct {
Expand All @@ -139,8 +226,9 @@ func (l *LinstorStoragePoolFile) DirectoryOrDefault(name string) string {
return l.Directory
}

func (l *LinstorStoragePoolZfs) Validate(oldSP *LinstorStoragePool, fieldPrefix *field.Path, name string, thin bool) field.ErrorList {
func (l *LinstorStoragePoolZfs) Validate(oldSP *LinstorStoragePool, fieldPrefix *field.Path, name string, thin bool) (admission.Warnings, field.ErrorList) {
var result field.ErrorList
var warnings admission.Warnings

if oldSP != nil {
if thin && oldSP.ZfsThinPool == nil {
Expand All @@ -150,7 +238,15 @@ func (l *LinstorStoragePoolZfs) Validate(oldSP *LinstorStoragePool, fieldPrefix
}
}

return result
if oldSP != nil && thin && oldSP.ZfsThinPool != nil && !slices.Equal(l.ZpoolCreateArguments, oldSP.ZfsThinPool.ZpoolCreateArguments) {
warnings = append(warnings, fmt.Sprintf("%s: Update will only apply to new nodes", fieldPrefix.Child("zpoolCreateArguments")))
}

if oldSP != nil && !thin && oldSP.ZfsPool != nil && !slices.Equal(l.ZpoolCreateArguments, oldSP.ZfsPool.ZpoolCreateArguments) {
warnings = append(warnings, fmt.Sprintf("%s: Update will only apply to new nodes", fieldPrefix.Child("zpoolCreateArguments")))
}

return warnings, result
}

func (s *LinstorStoragePoolSource) Validate(oldSP *LinstorStoragePool, knownDevices sets.Set[string], fieldPrefix *field.Path) field.ErrorList {
Expand Down
38 changes: 34 additions & 4 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading