pool: clean up erasure code profile on pool deletion
deleting an erasure coded CephBlockPool left the ec profile
orphaned. recreating with different settings failed because
the old profile could not be overridden.
- delete ec profile during CephBlockPool deletion
- disable --format json on ec profile set command
- fix ec profile name mismatch in CephObjectStore deletion
Signed-off-by: Oded Viner <oviner@redhat.com>
(cherry picked from commit b88648d10f)
This commit is contained in:
1 parent
59aced4f24
commit
7ec6cb6aef
5 files changed
+58
-5
No files matched your search
@@ -95,7 +95,9 @@ func CreateErasureCodeProfile(context *clusterd.Context, clusterInfo *ClusterInf
|
||||
|
||||
args := []string{"osd", "erasure-code-profile", "set", profileName, "--force"}
|
||||
args = append(args, profilePairs...)
|
||||
_, err = NewCephCommand(context, clusterInfo, args).Run()
|
||||
cmd := NewCephCommand(context, clusterInfo, args)
|
||||
cmd.JsonOutput = false
|
||||
_, err = cmd.Run()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to set ec-profile")
|
||||
}
|
||||
|
||||
@@ -725,7 +725,9 @@ func DeletePools(ctx *Context, lastStore bool, poolPrefix string) error {
|
||||
return errors.Wrapf(err, "failed to list erasure code profiles for cluster %s", ctx.clusterInfo.Namespace)
|
||||
}
|
||||
// cleans up the EC profile for the data pool only. Metadata pools don't support EC (only replication is supported).
|
||||
ecProfileName := cephclient.GetErasureCodeProfileForPool(ctx.Name)
|
||||
// The profile name must match the full pool name used during creation (e.g., "<store>.rgw.buckets.data_ecprofile").
|
||||
dataPool := poolName(poolPrefix, dataPoolName)
|
||||
ecProfileName := cephclient.GetErasureCodeProfileForPool(dataPool)
|
||||
for i := range erasureCodes {
|
||||
if erasureCodes[i] == ecProfileName {
|
||||
if err := cephclient.DeleteErasureCodeProfile(ctx.Context, ctx.clusterInfo, ecProfileName); err != nil {
|
||||
|
||||
@@ -431,13 +431,13 @@ func deleteStore(t *testing.T, name string, existingStores string, expectedDelet
|
||||
}
|
||||
if args[1] == "erasure-code-profile" {
|
||||
if args[2] == "ls" {
|
||||
return `["default","myobj_ecprofile"]`, nil
|
||||
return `["default","myobj.rgw.buckets.data_ecprofile"]`, nil
|
||||
}
|
||||
if args[2] == "rm" {
|
||||
if args[3] == "myobj_ecprofile" {
|
||||
if args[3] == "myobj.rgw.buckets.data_ecprofile" {
|
||||
deletedErasureCodeProfile = true
|
||||
} else {
|
||||
assert.Fail(t, fmt.Sprintf("the erasure code profile to be deleted should be myobj_ecprofile. Actual: %s ", args[3]))
|
||||
assert.Fail(t, fmt.Sprintf("the erasure code profile to be deleted should be myobj.rgw.buckets.data_ecprofile. Actual: %s ", args[3]))
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -589,6 +589,16 @@ func deletePool(context *clusterd.Context, clusterInfo *cephclient.ClusterInfo,
|
||||
return errors.Wrapf(err, "failed to delete pool %q", p.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the erasure code profile for EC pools so that recreating with
|
||||
// different settings does not fail
|
||||
if p.IsErasureCoded() {
|
||||
ecProfileName := cephclient.GetErasureCodeProfileForPool(p.Name)
|
||||
if err := cephclient.DeleteErasureCodeProfile(context, clusterInfo, ecProfileName); err != nil {
|
||||
logger.Warningf("failed to delete erasure code profile %q for pool %q: %v", ecProfileName, p.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -200,6 +200,45 @@ func TestDeletePool(t *testing.T) {
|
||||
p = &cephv1.NamedPoolSpec{Name: "mypool"}
|
||||
err = deletePool(context, clusterInfo, p)
|
||||
assert.Error(t, err)
|
||||
|
||||
// delete an erasure coded pool should also delete the EC profile
|
||||
ecProfileDeleted := false
|
||||
failOnDelete = false
|
||||
ecExecutor := &exectest.MockExecutor{
|
||||
MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
|
||||
emptyPool := "{\"images\":{\"count\":0,\"provisioned_bytes\":0,\"snap_count\":0},\"trash\":{\"count\":1,\"provisioned_bytes\":2048,\"snap_count\":0}}"
|
||||
if command == "ceph" && args[1] == "lspools" {
|
||||
return `[{"poolnum":1,"poolname":"ecpool"}]`, nil
|
||||
} else if command == "ceph" && args[1] == "pool" && args[2] == "get" {
|
||||
return `{"pool": "ecpool","pool_id": 1,"size":1}`, nil
|
||||
} else if command == "ceph" && args[1] == "pool" && args[2] == "delete" {
|
||||
return "", nil
|
||||
} else if command == "ceph" && args[1] == "erasure-code-profile" && args[2] == "rm" {
|
||||
assert.Equal(t, "ecpool_ecprofile", args[3])
|
||||
ecProfileDeleted = true
|
||||
return "", nil
|
||||
} else if args[0] == "pool" {
|
||||
if args[1] == "stats" {
|
||||
return emptyPool, nil
|
||||
}
|
||||
return "", errors.Errorf("rbd: error opening pool %q: (2) No such file or directory", args[3])
|
||||
}
|
||||
return "", errors.Errorf("unexpected rbd command %q", args)
|
||||
},
|
||||
}
|
||||
ecContext := &clusterd.Context{Executor: ecExecutor}
|
||||
ecPool := &cephv1.NamedPoolSpec{
|
||||
Name: "ecpool",
|
||||
PoolSpec: cephv1.PoolSpec{
|
||||
ErasureCoded: cephv1.ErasureCodedSpec{
|
||||
DataChunks: 2,
|
||||
CodingChunks: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
err = deletePool(ecContext, clusterInfo, ecPool)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, ecProfileDeleted)
|
||||
}
|
||||
|
||||
// TestCephBlockPoolController runs ReconcileCephBlockPool.Reconcile() against a
|
||||
|
||||
Reference in new issue
Block a user