Skip to content

Commit 3ddce5f

Browse files
Merge pull request #728 from qJkee/OCPEDGE-1230
OCPEDGE-1230: add metadata size field
2 parents ede5f97 + ae77860 commit 3ddce5f

14 files changed

+354
-42
lines changed

api/v1alpha1/lvmcluster_types.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,38 @@ type ThinPoolConfig struct {
6868
// It can be between 64Ki and 1Gi due to the underlying limitations of lvm2.
6969
// +optional
7070
ChunkSize *resource.Quantity `json:"chunkSize,omitempty"`
71+
72+
// MetadataSize specifies metadata size for thin pool. It used only when MetadataSizeCalculationPolicy
73+
// is set to Static. No MetadataSize with a MetadataSizeCalculationPolicy set to Static will result in
74+
// default metadata size of 1Gi. It can be between 2Mi and 16Gi due to the underlying limitations of lvm2.
75+
// +optional
76+
MetadataSize *resource.Quantity `json:"metadataSize,omitempty"`
77+
78+
// MetadataSizeCalculationPolicy specifies the policy to calculate metadata size for the underlying volume.
79+
// When set to Host, the metadata size is calculated based on lvm2 default settings
80+
// When set to Static, the metadata size is calculated based on the static size attribute provided within MetadataSize
81+
// +kubebuilder:default=Host
82+
// +kubebuilder:validation:Enum=Host;Static
83+
// +required
84+
MetadataSizeCalculationPolicy MetadataSizePolicy `json:"metadataSizeCalculationPolicy,omitempty"`
7185
}
7286

87+
// MetadataSizePolicy specifies the policy to calculate the metadata size for the underlying volume.
88+
type MetadataSizePolicy string
89+
90+
const (
91+
// MetadataSizePolicyHost calculates the metadata size based on the lvm2 default settings.
92+
MetadataSizePolicyHost MetadataSizePolicy = "Host"
93+
// MetadataSizePolicyStatic calculates the metadata size based on a static size attribute.
94+
MetadataSizePolicyStatic MetadataSizePolicy = "Static"
95+
)
96+
97+
var (
98+
ThinPoolMetadataSizeMinimum = resource.MustParse("2Mi")
99+
ThinPoolMetadataSizeMaximum = resource.MustParse("16Gi")
100+
ThinPoolMetadataSizeDefault = resource.MustParse("1Gi")
101+
)
102+
73103
// ChunkSizeCalculationPolicy specifies the policy to calculate the chunk size for the underlying volume.
74104
// for more information, see man lvm.
75105
type ChunkSizeCalculationPolicy string

api/v1alpha1/lvmcluster_webhook.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ var (
5656
ErrEmptyPathsWithMultipleDeviceClasses = errors.New("path list should not be empty when there are multiple deviceClasses")
5757
ErrDuplicateLVMCluster = errors.New("duplicate LVMClusters are not allowed, remove the old LVMCluster or work with the existing instance")
5858
ErrThinPoolConfigCannotBeChanged = errors.New("ThinPoolConfig can not be changed")
59+
ErrThinPoolMetadataSizeCanOnlyBeIncreased = errors.New("thin pool metadata size can only be increased")
5960
ErrNodeSelectorCannotBeChanged = errors.New("NodeSelector can not be changed")
6061
ErrDevicePathsCannotBeAddedInUpdate = errors.New("device paths can not be added after a device class has been initialized")
6162
ErrForceWipeOptionCannotBeChanged = errors.New("ForceWipeDevicesAndDestroyAllData can not be changed")
@@ -126,6 +127,11 @@ func (v *lvmClusterValidator) ValidateCreate(ctx context.Context, obj runtime.Ob
126127
return warnings, err
127128
}
128129

130+
metadataWarnings, err := v.verifyMetadataSize(l)
131+
if err != nil {
132+
return warnings, err
133+
}
134+
warnings = append(warnings, metadataWarnings...)
129135
return warnings, nil
130136
}
131137

@@ -197,6 +203,21 @@ func (v *lvmClusterValidator) ValidateUpdate(_ context.Context, old, new runtime
197203
} else if !reflect.DeepEqual(newThinPoolConfig.ChunkSize, oldThinPoolConfig.ChunkSize) {
198204
return warnings, fmt.Errorf("ThinPoolConfig.ChunkSize is invalid: %w", ErrThinPoolConfigCannotBeChanged)
199205
}
206+
207+
if newThinPoolConfig.MetadataSizeCalculationPolicy == MetadataSizePolicyStatic {
208+
if newThinPoolConfig.MetadataSize == nil {
209+
warnings = append(warnings, "thin pool metadata size is unset. LVMS operator will automatically set it to 1Gb and grow metadata size if needed")
210+
newThinPoolConfig.MetadataSize = &ThinPoolMetadataSizeDefault
211+
}
212+
if oldThinPoolConfig.MetadataSizeCalculationPolicy == MetadataSizePolicyStatic {
213+
if oldThinPoolConfig.MetadataSize == nil {
214+
oldThinPoolConfig.MetadataSize = &ThinPoolMetadataSizeDefault
215+
}
216+
if newThinPoolConfig.MetadataSize.Value() < oldThinPoolConfig.MetadataSize.Value() {
217+
return warnings, fmt.Errorf("ThinPoolConfig.MetadataSize is invalid: %w", ErrThinPoolMetadataSizeCanOnlyBeIncreased)
218+
}
219+
}
220+
}
200221
}
201222

202223
newNodeSelector := deviceClass.NodeSelector
@@ -518,3 +539,28 @@ func (v *lvmClusterValidator) verifyChunkSize(l *LVMCluster) error {
518539

519540
return nil
520541
}
542+
543+
func (v *lvmClusterValidator) verifyMetadataSize(l *LVMCluster) ([]string, error) {
544+
warnings := make([]string, 0)
545+
for _, dc := range l.Spec.Storage.DeviceClasses {
546+
if dc.ThinPoolConfig == nil {
547+
continue
548+
}
549+
if dc.ThinPoolConfig.MetadataSizeCalculationPolicy == MetadataSizePolicyHost && dc.ThinPoolConfig.MetadataSize != nil {
550+
return warnings, fmt.Errorf("metadata size can not be set when metadata size calculation policy is set to Host")
551+
}
552+
if dc.ThinPoolConfig.MetadataSizeCalculationPolicy == MetadataSizePolicyStatic && dc.ThinPoolConfig.MetadataSize == nil {
553+
warnings = append(warnings, "metadata size in unset. LVMS will set it to 1Gi by default")
554+
dc.ThinPoolConfig.MetadataSize = &ThinPoolMetadataSizeDefault
555+
}
556+
if dc.ThinPoolConfig.MetadataSize != nil {
557+
if dc.ThinPoolConfig.ChunkSize.Cmp(ThinPoolMetadataSizeMinimum) < 0 {
558+
return warnings, fmt.Errorf("metadata size must be greater than or equal to %s", ThinPoolMetadataSizeMinimum.String())
559+
}
560+
if dc.ThinPoolConfig.MetadataSize.Cmp(ThinPoolMetadataSizeMaximum) > 0 {
561+
return warnings, fmt.Errorf("metadata size must be less than or equal to %s", ThinPoolMetadataSizeMaximum.String())
562+
}
563+
}
564+
}
565+
return warnings, nil
566+
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/manifests/lvm.topolvm.io_lvmclusters.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,26 @@ spec:
213213
- Host
214214
- Static
215215
type: string
216+
metadataSize:
217+
anyOf:
218+
- type: integer
219+
- type: string
220+
description: |-
221+
MetadataSize specifies metadata size for thin pool. It used only when MetadataSizeCalculationPolicy
222+
is set to Static. No MetadataSize with a MetadataSizeCalculationPolicy set to Static will result in
223+
default metadata size of 1Gi. It can be between 2Mi and 16Gi due to the underlying limitations of lvm2.
224+
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
225+
x-kubernetes-int-or-string: true
226+
metadataSizeCalculationPolicy:
227+
default: Host
228+
description: |-
229+
MetadataSizeCalculationPolicy specifies the policy to calculate metadata size for the underlying volume.
230+
When set to Host, the metadata size is calculated based on lvm2 default settings
231+
When set to Static, the metadata size is calculated based on the static size attribute provided within MetadataSize
232+
enum:
233+
- Host
234+
- Static
235+
type: string
216236
name:
217237
description: Name specifies a name for the thin pool.
218238
type: string
@@ -235,6 +255,7 @@ spec:
235255
type: integer
236256
required:
237257
- chunkSizeCalculationPolicy
258+
- metadataSizeCalculationPolicy
238259
- name
239260
- overprovisionRatio
240261
type: object

bundle/manifests/lvm.topolvm.io_lvmvolumegroups.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,26 @@ spec:
176176
- Host
177177
- Static
178178
type: string
179+
metadataSize:
180+
anyOf:
181+
- type: integer
182+
- type: string
183+
description: |-
184+
MetadataSize specifies metadata size for thin pool. It used only when MetadataSizeCalculationPolicy
185+
is set to Static. No MetadataSize with a MetadataSizeCalculationPolicy set to Static will result in
186+
default metadata size of 1Gi. It can be between 2Mi and 16Gi due to the underlying limitations of lvm2.
187+
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
188+
x-kubernetes-int-or-string: true
189+
metadataSizeCalculationPolicy:
190+
default: Host
191+
description: |-
192+
MetadataSizeCalculationPolicy specifies the policy to calculate metadata size for the underlying volume.
193+
When set to Host, the metadata size is calculated based on lvm2 default settings
194+
When set to Static, the metadata size is calculated based on the static size attribute provided within MetadataSize
195+
enum:
196+
- Host
197+
- Static
198+
type: string
179199
name:
180200
description: Name specifies a name for the thin pool.
181201
type: string
@@ -197,6 +217,7 @@ spec:
197217
type: integer
198218
required:
199219
- chunkSizeCalculationPolicy
220+
- metadataSizeCalculationPolicy
200221
- name
201222
- overprovisionRatio
202223
type: object

0 commit comments

Comments
 (0)