Merge pull request #5058 from travisn/object-no-pools

Allow creation of object store with pre-existing pools
This commit is contained in:
Travis Nielsen authored and GitHub committed 2020-03-24 09:19:55 -06:00
commit 006b835711
5 files changed
+84 -22

No files matched your search

+6 -6
View File
@@ -236,25 +236,26 @@ func (r *ReconcileCephObjectStore) reconcile(request reconcile.Request) (reconci
return r.setFailedStatus(cephObjectStore, "failed to reconcile service", err)
}
// RECONCILE POOLS
logger.Debug("reconciling object store pools")
objContext := NewContext(r.context, cephObjectStore.Name, cephObjectStore.Namespace)
// RECONCILE POOLS
logger.Info("reconciling object store pools")
metadataPoolToModel := *cephObjectStore.Spec.MetadataPool.ToModel("")
dataPoolToModel := *cephObjectStore.Spec.DataPool.ToModel("")
err = createPools(objContext, metadataPoolToModel, dataPoolToModel)
err = createPools(objContext, cephObjectStore.Spec, metadataPoolToModel, dataPoolToModel)
if err != nil {
return r.setFailedStatus(cephObjectStore, "failed to create object pools", err)
}
// RECONCILE REALM
logger.Debug("reconciling object store realms")
logger.Info("reconciling object store realms")
err = reconcileRealm(objContext, serviceIP, cephObjectStore.Spec.Gateway.Port)
if err != nil {
return r.setFailedStatus(cephObjectStore, "failed to create object store realm", err)
}
// CREATE/UPDATE
logger.Debug("reconciling object store deployments")
logger.Info("reconciling object store deployments")
reconcileResponse, err = r.reconcileCreateObjectStore(cephObjectStore)
if err != nil {
return r.setFailedStatus(cephObjectStore, "failed to create object store deployments", err)
@@ -270,7 +271,6 @@ func (r *ReconcileCephObjectStore) reconcile(request reconcile.Request) (reconci
// Return and do not requeue
logger.Debug("done reconciling")
return reconcile.Result{}, nil
}
func (r *ReconcileCephObjectStore) reconcileCreateObjectStore(cephObjectStore *cephv1.CephObjectStore) (reconcile.Result, error) {
+29 -5
View File
@@ -23,6 +23,7 @@ import (
"strings"
"github.com/pkg/errors"
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
ceph "github.com/rook/rook/pkg/daemon/ceph/client"
"github.com/rook/rook/pkg/daemon/ceph/model"
)
@@ -56,7 +57,7 @@ type realmType struct {
Realms []string `json:"realms"`
}
func deleteRealmAndPools(context *Context, preservePoolsOnDelete bool) error {
func deleteRealmAndPools(context *Context, spec cephv1.ObjectStoreSpec) error {
stores, err := getObjectStores(context)
if err != nil {
return errors.Wrapf(err, "failed to detect object stores during deletion")
@@ -73,8 +74,8 @@ func deleteRealmAndPools(context *Context, preservePoolsOnDelete bool) error {
lastStore = true
}
if !preservePoolsOnDelete {
err = deletePools(context, lastStore)
if !spec.PreservePoolsOnDelete {
err = deletePools(context, spec, lastStore)
if err != nil {
return errors.Wrapf(err, "failed to delete object store pools")
}
@@ -203,7 +204,12 @@ func getObjectStores(context *Context) ([]string, error) {
return r.Realms, nil
}
func deletePools(context *Context, lastStore bool) error {
func deletePools(context *Context, spec cephv1.ObjectStoreSpec, lastStore bool) error {
if emptyPool(spec.DataPool) && emptyPool(spec.MetadataPool) {
logger.Info("skipping removal of pools since not specified in the object store")
return nil
}
pools := append(metadataPools, dataPools...)
if lastStore {
pools = append(pools, rootPool)
@@ -235,7 +241,25 @@ func deletePools(context *Context, lastStore bool) error {
return nil
}
func createPools(context *Context, metadataSpec, dataSpec model.Pool) error {
func createPools(context *Context, spec cephv1.ObjectStoreSpec, metadataSpec, dataSpec model.Pool) error {
if emptyPool(spec.DataPool) && emptyPool(spec.MetadataPool) {
logger.Info("no pools specified for the object store, checking for their existence...")
pools := append(metadataPools, dataPools...)
pools = append(pools, rootPool)
var missingPools []string
for _, pool := range pools {
poolName := poolName(context.Name, pool)
_, err := ceph.GetPoolDetails(context.Context, context.ClusterName, poolName)
if err != nil {
logger.Debugf("failed to find pool %q. %v", poolName, err)
missingPools = append(missingPools, poolName)
}
}
if len(missingPools) > 0 {
return fmt.Errorf("object store pools are missing: %v", missingPools)
}
}
if err := createSimilarPools(context, append(metadataPools, rootPool), metadataSpec); err != nil {
return errors.Wrapf(err, "failed to create metadata pools")
}
+19 -6
View File
@@ -21,6 +21,7 @@ import (
"testing"
"github.com/pkg/errors"
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
"github.com/rook/rook/pkg/clusterd"
exectest "github.com/rook/rook/pkg/util/exec/test"
"github.com/stretchr/testify/assert"
@@ -152,18 +153,30 @@ func deleteStore(t *testing.T, name string, existingStores string, expectedDelet
executor.MockExecuteCommandWithCombinedOutput = executorFunc
context := &Context{Context: &clusterd.Context{Executor: executor}, Name: "myobj", ClusterName: "ns"}
// Delete an object store
err := deleteRealmAndPools(context, false)
// Delete an object store without deleting the pools
spec := cephv1.ObjectStoreSpec{}
err := deleteRealmAndPools(context, spec)
assert.Nil(t, err)
expectedPoolsDeleted := 6
if expectedDeleteRootPool {
expectedPoolsDeleted++
}
expectedPoolsDeleted := 0
assert.Equal(t, expectedPoolsDeleted, poolsDeleted)
assert.Equal(t, expectedPoolsDeleted, rulesDeleted)
assert.True(t, realmDeleted)
assert.True(t, zoneGroupDeleted)
assert.True(t, zoneDeleted)
assert.Equal(t, false, deletedErasureCodeProfile)
// Delete an object store with the pools
spec = cephv1.ObjectStoreSpec{
MetadataPool: cephv1.PoolSpec{Replicated: cephv1.ReplicatedSpec{Size: 1}},
DataPool: cephv1.PoolSpec{Replicated: cephv1.ReplicatedSpec{Size: 1}},
}
err = deleteRealmAndPools(context, spec)
assert.Nil(t, err)
expectedPoolsDeleted = 6
if expectedDeleteRootPool {
expectedPoolsDeleted++
}
assert.Equal(t, expectedPoolsDeleted, poolsDeleted)
assert.Equal(t, expectedDeleteRootPool, deletedRootPool)
assert.Equal(t, true, deletedErasureCodeProfile)
}
+17 -5
View File
@@ -19,6 +19,7 @@ package object
import (
"fmt"
"reflect"
"strings"
"github.com/banzaicloud/k8s-objectmatcher/patch"
@@ -281,7 +282,7 @@ func (c *clusterConfig) deleteStore() error {
// Delete the realm and pools
objContext := NewContext(c.context, c.store.Name, c.store.Namespace)
err := deleteRealmAndPools(objContext, c.store.Spec.PreservePoolsOnDelete)
err := deleteRealmAndPools(objContext, c.store.Spec)
if err != nil {
return errors.Wrap(err, "failed to delete the realm and pools")
}
@@ -310,11 +311,18 @@ func validateStore(context *clusterd.Context, s *cephv1.CephObjectStore) error {
if securePort < 0 || securePort > 65535 {
return errors.Errorf("securePort value of %d must be between 0 and 65535", securePort)
}
if err := pool.ValidatePoolSpec(context, s.Namespace, &s.Spec.MetadataPool); err != nil {
return errors.Wrapf(err, "invalid metadata pool spec")
// Validate the pool settings, but allow for empty pools specs in case they have already been created
// such as by the ceph mgr
if !emptyPool(s.Spec.MetadataPool) {
if err := pool.ValidatePoolSpec(context, s.Namespace, &s.Spec.MetadataPool); err != nil {
return errors.Wrap(err, "invalid metadata pool spec")
}
}
if err := pool.ValidatePoolSpec(context, s.Namespace, &s.Spec.DataPool); err != nil {
return errors.Wrapf(err, "invalid data pool spec")
if !emptyPool(s.Spec.DataPool) {
if err := pool.ValidatePoolSpec(context, s.Namespace, &s.Spec.DataPool); err != nil {
return errors.Wrap(err, "invalid data pool spec")
}
}
return nil
@@ -323,3 +331,7 @@ func validateStore(context *clusterd.Context, s *cephv1.CephObjectStore) error {
func (c *clusterConfig) generateSecretName(id string) string {
return fmt.Sprintf("%s-%s-%s-keyring", AppName, c.store.Name, id)
}
func emptyPool(pool cephv1.PoolSpec) bool {
return reflect.DeepEqual(pool, cephv1.PoolSpec{})
}
+13
View File
@@ -140,3 +140,16 @@ func TestGenerateSecretName(t *testing.T) {
secret := c.generateSecretName("a")
assert.Equal(t, "rook-ceph-rgw-default-a-keyring", secret)
}
func TestEmptyPoolSpec(t *testing.T) {
assert.True(t, emptyPool(cephv1.PoolSpec{}))
p := cephv1.PoolSpec{FailureDomain: "foo"}
assert.False(t, emptyPool(p))
p = cephv1.PoolSpec{Replicated: cephv1.ReplicatedSpec{Size: 1}}
assert.False(t, emptyPool(p))
p = cephv1.PoolSpec{ErasureCoded: cephv1.ErasureCodedSpec{CodingChunks: 1}}
assert.False(t, emptyPool(p))
}