forked from TrueCloudLab/frostfs-node
[#755] neofs-adm: allow to restore containers
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
a013dcbab5
commit
5072b703bc
2 changed files with 92 additions and 0 deletions
|
@ -6,11 +6,13 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
@ -96,6 +98,81 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
|
|||
return ioutil.WriteFile(filename, out, 0o660)
|
||||
}
|
||||
|
||||
func restoreContainers(cmd *cobra.Command, _ []string) error {
|
||||
filename, err := cmd.Flags().GetString(containerDumpFlag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid filename: %w", err)
|
||||
}
|
||||
|
||||
wCtx, err := newInitializeContext(cmd, viper.GetViper())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nnsCs, err := wCtx.Client.GetContractStateByID(1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get NNS contract state: %w", err)
|
||||
}
|
||||
|
||||
ch, err := nnsResolveHash(wCtx.Client, nnsCs.Hash, containerContract+".neofs")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't fetch container contract hash: %w", err)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't read dump file: %w", err)
|
||||
}
|
||||
|
||||
var containers []Container
|
||||
err = json.Unmarshal(data, &containers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse dump file: %w", err)
|
||||
}
|
||||
|
||||
bw := io.NewBufBinWriter()
|
||||
for _, cnt := range containers {
|
||||
hv := hash.Sha256(cnt.Value)
|
||||
bw.Reset()
|
||||
emit.AppCall(bw.BinWriter, ch, "get", callflag.All, hv.BytesBE())
|
||||
res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't check if container is already restored: %w", err)
|
||||
}
|
||||
if len(res.Stack) == 0 {
|
||||
return errors.New("empty stack")
|
||||
}
|
||||
|
||||
old := new(Container)
|
||||
if err := old.FromStackItem(res.Stack[0]); err != nil {
|
||||
return fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
||||
}
|
||||
if len(old.Value) != 0 {
|
||||
id := cid.New()
|
||||
id.SetSHA256(hv)
|
||||
cmd.Printf("Container %s is already deployed.\n", id)
|
||||
continue
|
||||
}
|
||||
|
||||
bw.Reset()
|
||||
emit.AppCall(bw.BinWriter, ch, "put", callflag.All,
|
||||
cnt.Value, cnt.Signature, cnt.PublicKey, cnt.Token)
|
||||
if ea := cnt.EACL; ea != nil {
|
||||
emit.AppCall(bw.BinWriter, ch, "setEACL", callflag.All,
|
||||
ea.Value, ea.Signature, ea.PublicKey, ea.Token)
|
||||
}
|
||||
if bw.Err != nil {
|
||||
panic(bw.Err)
|
||||
}
|
||||
|
||||
if err := wCtx.sendCommitteeTx(bw.Bytes(), -1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return wCtx.awaitTx()
|
||||
}
|
||||
|
||||
// Container represents container struct in contract storage.
|
||||
type Container struct {
|
||||
Value []byte `json:"value"`
|
||||
|
|
|
@ -121,6 +121,16 @@ var (
|
|||
},
|
||||
RunE: dumpContainers,
|
||||
}
|
||||
|
||||
restoreContainersCmd = &cobra.Command{
|
||||
Use: "restore-containers",
|
||||
Short: "Restore NeoFS containers from file.",
|
||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||
},
|
||||
RunE: restoreContainers,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -159,4 +169,9 @@ func init() {
|
|||
RootCmd.AddCommand(dumpContainersCmd)
|
||||
dumpContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||
dumpContainersCmd.Flags().String(containerDumpFlag, "", "file where to save dumped containers")
|
||||
|
||||
RootCmd.AddCommand(restoreContainersCmd)
|
||||
restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir")
|
||||
restoreContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||
restoreContainersCmd.Flags().String(containerDumpFlag, "", "file to restore containers from")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue