@@ -81,6 +81,35 @@ const (
81
81
82
82
// clusterNameKey cluster Key, set on RBD image.
83
83
clusterNameKey = "csi.ceph.com/cluster/name"
84
+
85
+ // Qos parameters name of StorageClass.
86
+ baseReadIOPS = "BaseReadIOPS"
87
+ baseWriteIOPS = "BaseWriteIOPS"
88
+ baseReadBytesPerSecond = "BaseReadBytesPerSecond"
89
+ baseWriteBytesPerSecond = "BaseWriteBytesPerSecond"
90
+ readIopsPerGB = "ReadIopsPerGB"
91
+ writeIopsPerGB = "WriteIopsPerGB"
92
+ readBpsPerGB = "ReadBpsPerGB"
93
+ writeBpsPerGB = "WriteBpsPerGB"
94
+ baseVolSizeBytes = "BaseVolSizeBytes"
95
+
96
+ // Qos type name of rbd image.
97
+ rbdQosReadIopsLimit = "rbd_qos_read_iops_limit"
98
+ rbdQosWriteIopsLimit = "rbd_qos_write_iops_limit"
99
+ rbdQosReadBpsLimit = "rbd_qos_read_bps_limit"
100
+ rbdQosWriteBpsLimit = "rbd_qos_write_bps_limit"
101
+ metadataConfPrefix = "conf_"
102
+
103
+ // The params use to calc qos based on capacity.
104
+ rbdBaseQosReadIopsLimit = "rbd_base_qos_read_iops_limit"
105
+ rbdBaseQosWriteIopsLimit = "rbd_base_qos_write_iops_limit"
106
+ rbdBaseQosReadBpsLimit = "rbd_base_qos_read_bps_limit"
107
+ rbdBaseQosWriteBpsLimit = "rbd_base_qos_write_bps_limit"
108
+ rbdReadIopsPerGB = "rbd_read_iops_per_gb"
109
+ rbdWriteIopsPerGB = "rbd_write_iops_per_gb"
110
+ rbdReadBpsPerGB = "rbd_read_bps_per_gb"
111
+ rbdWriteBpsPerGB = "rbd_write_bps_per_gb"
112
+ rbdBaseQosVolSize = "rbd_base_qos_vol_size"
84
113
)
85
114
86
115
// rbdImage contains common attributes and methods for the rbdVolume and
@@ -148,6 +177,9 @@ type rbdImage struct {
148
177
EnableMetadata bool
149
178
// ParentInTrash indicates the parent image is in trash.
150
179
ParentInTrash bool
180
+
181
+ // RBD QoS configuration
182
+ QosParameters map [string ]string
151
183
}
152
184
153
185
// check that rbdVolume implements the types.Volume interface.
@@ -212,6 +244,14 @@ type migrationVolID struct {
212
244
clusterID string
213
245
}
214
246
247
+ type rbdQos struct {
248
+ rbdQosType string
249
+ rbdBaseQosLimit string
250
+ rbdQosPerGBType string
251
+ rbdQosPerGB string
252
+ provide bool
253
+ }
254
+
215
255
var (
216
256
supportedFeatures = map [string ]imageFeature {
217
257
librbd .FeatureNameLayering : {
@@ -2273,3 +2313,151 @@ func (ri *rbdImage) GetClusterID(ctx context.Context) (string, error) {
2273
2313
2274
2314
return ri .ClusterID , nil
2275
2315
}
2316
+
2317
+ func calcQosBasedOnCapacity (
2318
+ ctx context.Context ,
2319
+ rbdVol * rbdVolume ,
2320
+ qosParam rbdQos ,
2321
+ baseQosVolSize string ,
2322
+ ) error {
2323
+ if rbdVol .QosParameters == nil {
2324
+ rbdVol .QosParameters = make (map [string ]string )
2325
+ }
2326
+
2327
+ // Don't set qos if base limit empty
2328
+ if qosParam .rbdBaseQosLimit == "" {
2329
+ return nil
2330
+ }
2331
+ baseQosLimit , err := strconv .ParseInt (qosParam .rbdBaseQosLimit , 10 , 64 )
2332
+ if err != nil {
2333
+ log .ErrorLog (ctx , "%v" , err )
2334
+
2335
+ return err
2336
+ }
2337
+
2338
+ // if provide qosPerGB and baseQosVolSize, we will set qos based on capacity,
2339
+ // otherwise, we only set base qos limit.
2340
+ if qosParam .rbdQosPerGB != "" && baseQosVolSize != "" {
2341
+ qosPerGB , err := strconv .ParseInt (qosParam .rbdQosPerGB , 10 , 64 )
2342
+ if err != nil {
2343
+ log .ErrorLog (ctx , "%v" , err )
2344
+
2345
+ return err
2346
+ }
2347
+
2348
+ baseQosVolSizeInt , err := strconv .ParseInt (baseQosVolSize , 10 , 64 )
2349
+ if err != nil {
2350
+ log .ErrorLog (ctx , "%v" , err )
2351
+
2352
+ return err
2353
+ }
2354
+
2355
+ if rbdVol .VolSize <= baseQosVolSizeInt {
2356
+ rbdVol .QosParameters [qosParam .rbdQosType ] = qosParam .rbdBaseQosLimit
2357
+ } else {
2358
+ capacityQos := (rbdVol .VolSize - baseQosVolSizeInt ) / int64 (oneGB ) * qosPerGB
2359
+ finalQosLimit := baseQosLimit + capacityQos
2360
+ rbdVol .QosParameters [qosParam .rbdQosType ] = strconv .FormatInt (finalQosLimit , 10 )
2361
+ }
2362
+ } else {
2363
+ rbdVol .QosParameters [qosParam .rbdQosType ] = qosParam .rbdBaseQosLimit
2364
+ }
2365
+
2366
+ return nil
2367
+ }
2368
+
2369
+ func setRbdImageQos (
2370
+ ctx context.Context ,
2371
+ rbdVol * rbdVolume ,
2372
+ ) error {
2373
+ for k , v := range rbdVol .QosParameters {
2374
+ err := rbdVol .SetMetadata (metadataConfPrefix + k , v )
2375
+ if err != nil {
2376
+ log .ErrorLog (ctx , "failed to set rbd qos, %s: %s, %v" , k , v , err )
2377
+
2378
+ return err
2379
+ }
2380
+ }
2381
+
2382
+ return nil
2383
+ }
2384
+
2385
+ func getRbdImageQos (
2386
+ ctx context.Context ,
2387
+ rbdVol * rbdVolume ,
2388
+ ) (map [string ]rbdQos , string , error ) {
2389
+ QosParams := map [string ]struct {
2390
+ rbdQosType string
2391
+ rbdQosPerGBType string
2392
+ }{
2393
+ rbdBaseQosReadIopsLimit : {rbdQosReadIopsLimit , rbdReadIopsPerGB },
2394
+ rbdBaseQosWriteIopsLimit : {rbdQosWriteIopsLimit , rbdWriteIopsPerGB },
2395
+ rbdBaseQosReadBpsLimit : {rbdQosReadBpsLimit , rbdReadBpsPerGB },
2396
+ rbdBaseQosWriteBpsLimit : {rbdQosWriteBpsLimit , rbdWriteBpsPerGB },
2397
+ }
2398
+ rbdQosParameters := make (map [string ]rbdQos )
2399
+ for k , param := range QosParams {
2400
+ baseLimit , err := rbdVol .GetMetadata (k )
2401
+ if errors .Is (err , librbd .ErrNotFound ) {
2402
+ // if base qos dose not exist, skipping.
2403
+ continue
2404
+ } else if err != nil {
2405
+ log .ErrorLog (ctx , "failed to get metadata: %v" , err )
2406
+
2407
+ return nil , "" , err
2408
+ }
2409
+ perGBLimit , err := rbdVol .GetMetadata (param .rbdQosPerGBType )
2410
+ if errors .Is (err , librbd .ErrNotFound ) {
2411
+ // rbdQosPerGBType does not exist, set it empty.
2412
+ perGBLimit = ""
2413
+ } else if err != nil {
2414
+ log .ErrorLog (ctx , "failed to get metadata: %v" , err )
2415
+
2416
+ return nil , "" , err
2417
+ }
2418
+ rbdQosParameters [k ] = rbdQos {param .rbdQosType , baseLimit , param .rbdQosPerGBType , perGBLimit , true }
2419
+ }
2420
+ baseQosVolSize , err := rbdVol .GetMetadata (rbdBaseQosVolSize )
2421
+ if errors .Is (err , librbd .ErrNotFound ) {
2422
+ // rbdBaseQosVolSize does not exist, set it empty.
2423
+ baseQosVolSize = ""
2424
+ } else if err != nil {
2425
+ log .ErrorLog (ctx , "failed to get metadata: %v" , err )
2426
+
2427
+ return nil , "" , err
2428
+ }
2429
+
2430
+ return rbdQosParameters , baseQosVolSize , nil
2431
+ }
2432
+
2433
+ func saveQosToRbdImage (
2434
+ ctx context.Context ,
2435
+ rbdVol * rbdVolume ,
2436
+ params map [string ]string ,
2437
+ ) error {
2438
+ needSaveQosParameters := map [string ]string {
2439
+ baseReadIOPS : rbdBaseQosReadIopsLimit ,
2440
+ baseWriteIOPS : rbdBaseQosWriteIopsLimit ,
2441
+ baseReadBytesPerSecond : rbdBaseQosReadBpsLimit ,
2442
+ baseWriteBytesPerSecond : rbdBaseQosWriteBpsLimit ,
2443
+ readIopsPerGB : rbdReadIopsPerGB ,
2444
+ writeIopsPerGB : rbdWriteIopsPerGB ,
2445
+ readBpsPerGB : rbdReadBpsPerGB ,
2446
+ writeBpsPerGB : rbdWriteBpsPerGB ,
2447
+ baseVolSizeBytes : rbdBaseQosVolSize ,
2448
+ }
2449
+ for k , v := range params {
2450
+ if param , ok := needSaveQosParameters [k ]; ok {
2451
+ if v != "" {
2452
+ err := rbdVol .SetMetadata (param , v )
2453
+ if err != nil {
2454
+ log .ErrorLog (ctx , "failed to save metadata, %s: %s, %v" , k , v , err )
2455
+
2456
+ return err
2457
+ }
2458
+ }
2459
+ }
2460
+ }
2461
+
2462
+ return nil
2463
+ }
0 commit comments