forked from nspcc-dev/neofs-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce tool to migrate objects from Blobovnicza tree to Peapod
Add `cmd/blobovnicza-to-peapod` application which accepts YAML configuration file of the storage node and, for each configured shard, overtakes data from Blobovnicza tree to Peapod created in the parent directory. The tool is going to be used for phased and safe rejection of the Blobovnicza trees and the transition to Peapods. Refs nspcc-dev#2453. Signed-off-by: Leonard Lyubich <[email protected]>
- Loading branch information
1 parent
eb3bf7a
commit 327fb86
Showing
4 changed files
with
228 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"io/fs" | ||
"log" | ||
"path/filepath" | ||
|
||
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config" | ||
engineconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine" | ||
shardconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard" | ||
blobovniczaconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/blobovnicza" | ||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree" | ||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common" | ||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/compression" | ||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/peapod" | ||
) | ||
|
||
func main() { | ||
nodeCfgPath := flag.String("config", "", "Path to storage node's YAML configuration file") | ||
|
||
flag.Parse() | ||
|
||
if *nodeCfgPath == "" { | ||
log.Fatal("missing storage node config flag") | ||
} | ||
|
||
appCfg := config.New(config.Prm{}, config.WithConfigFile(*nodeCfgPath)) | ||
|
||
err := engineconfig.IterateShards(appCfg, false, func(sc *shardconfig.Config) error { | ||
log.Println("processing shard...") | ||
|
||
var bbcz common.Storage | ||
var perm fs.FileMode | ||
storagesCfg := sc.BlobStor().Storages() | ||
|
||
for i := range storagesCfg { | ||
if storagesCfg[i].Type() == blobovniczatree.Type { | ||
bbczCfg := blobovniczaconfig.From((*config.Config)(storagesCfg[i])) | ||
|
||
perm = storagesCfg[i].Perm() | ||
bbcz = blobovniczatree.NewBlobovniczaTree( | ||
blobovniczatree.WithRootPath(storagesCfg[i].Path()), | ||
blobovniczatree.WithPermissions(storagesCfg[i].Perm()), | ||
blobovniczatree.WithBlobovniczaSize(bbczCfg.Size()), | ||
blobovniczatree.WithBlobovniczaShallowDepth(bbczCfg.ShallowDepth()), | ||
blobovniczatree.WithBlobovniczaShallowWidth(bbczCfg.ShallowWidth()), | ||
blobovniczatree.WithOpenedCacheSize(bbczCfg.OpenedCacheSize())) | ||
|
||
break | ||
} | ||
} | ||
|
||
if bbcz == nil { | ||
log.Println("Blobovnicza is not configured for the current shard, going to next one...") | ||
return nil | ||
} | ||
|
||
bbczPath := bbcz.Path() | ||
if !filepath.IsAbs(bbczPath) { | ||
log.Fatalf("Blobobvnicza tree path '%s' is not absolute, make it like this in the config file first\n", bbczPath) | ||
} | ||
|
||
ppdPath := filepath.Join(filepath.Dir(bbcz.Path()), "peapod.db") | ||
ppd := peapod.New(ppdPath, perm) | ||
|
||
var compressCfg compression.Config | ||
compressCfg.Enabled = sc.Compress() | ||
compressCfg.UncompressableContentTypes = sc.UncompressableContentTypes() | ||
|
||
err := compressCfg.Init() | ||
if err != nil { | ||
log.Fatal("init compression config for the current shard: ", err) | ||
} | ||
|
||
bbcz.SetCompressor(&compressCfg) | ||
ppd.SetCompressor(&compressCfg) | ||
|
||
log.Printf("migrating data from Blobovnicza tree '%s' to Peapod '%s'...\n", bbcz.Path(), ppd.Path()) | ||
|
||
err = common.Copy(ppd, bbcz) | ||
if err != nil { | ||
log.Fatal("migration failed: ", err) | ||
} | ||
|
||
log.Println("data successfully migrated in the current shard, going to the next one...") | ||
|
||
return nil | ||
}) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
log.Println("data successfully migrated in all shards, you may now re-configure node to work with Peapod") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package common_test | ||
|
||
import ( | ||
"crypto/rand" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree" | ||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common" | ||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/peapod" | ||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" | ||
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestCopy(t *testing.T) { | ||
dir := t.TempDir() | ||
const nObjects = 100 | ||
|
||
src := blobovniczatree.NewBlobovniczaTree( | ||
blobovniczatree.WithBlobovniczaShallowWidth(2), | ||
blobovniczatree.WithBlobovniczaShallowDepth(3), | ||
blobovniczatree.WithRootPath(filepath.Join(dir, "blobovnicza")), | ||
) | ||
|
||
require.NoError(t, src.Open(false)) | ||
require.NoError(t, src.Init()) | ||
|
||
mObjs := make(map[oid.Address][]byte, nObjects) | ||
|
||
for i := 0; i < nObjects; i++ { | ||
addr := oidtest.Address() | ||
data := make([]byte, 32) | ||
rand.Read(data) | ||
mObjs[addr] = data | ||
|
||
_, err := src.Put(common.PutPrm{ | ||
Address: addr, | ||
RawData: data, | ||
}) | ||
require.NoError(t, err) | ||
} | ||
|
||
require.NoError(t, src.Close()) | ||
|
||
dst := peapod.New(filepath.Join(dir, "peapod.db"), 0600) | ||
|
||
err := common.Copy(dst, src) | ||
require.NoError(t, err) | ||
|
||
require.NoError(t, dst.Open(true)) | ||
t.Cleanup(func() { _ = dst.Close() }) | ||
|
||
_, err = dst.Iterate(common.IteratePrm{ | ||
Handler: func(el common.IterationElement) error { | ||
data, ok := mObjs[el.Address] | ||
require.True(t, ok) | ||
require.Equal(t, data, el.ObjectData) | ||
return nil | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
} |