Compare commits

..

No commits in common. "master" and "feat/tracing_attrs" have entirely different histories.

364 changed files with 3064 additions and 3141 deletions

View file

@ -1,10 +1,6 @@
name: Build name: Build
on: on: [pull_request]
pull_request:
push:
branches:
- master
jobs: jobs:
build: build:

View file

@ -1,10 +1,5 @@
name: Pre-commit hooks name: Pre-commit hooks
on: [pull_request]
on:
pull_request:
push:
branches:
- master
jobs: jobs:
precommit: precommit:

View file

@ -1,10 +1,5 @@
name: Tests and linters name: Tests and linters
on: [pull_request]
on:
pull_request:
push:
branches:
- master
jobs: jobs:
lint: lint:

View file

@ -1,10 +1,5 @@
name: Vulncheck name: Vulncheck
on: [pull_request]
on:
pull_request:
push:
branches:
- master
jobs: jobs:
vulncheck: vulncheck:

View file

@ -9,30 +9,6 @@ Changelog for FrostFS Node
### Removed ### Removed
### Updated ### Updated
## [v0.44.0] - 2024-25-11 - Rongbuk
### Added
- Allow to prioritize nodes during GET traversal via attributes (#1439)
- Add metrics for the frostfsid cache (#1464)
- Customize constant attributes attached to every tracing span (#1488)
- Manage additional keys in the `frostfsid` contract (#1505)
- Describe `--rule` flag in detail for `frostfs-cli ape-manager` subcommands (#1519)
### Changed
- Support richer interaction with the console in `frostfs-cli container policy-playground` (#1396)
- Print address in base58 format in `frostfs-adm morph policy set-admin` (#1515)
### Fixed
- Fix EC object search (#1408)
- Fix EC object put when one of the nodes is unavailable (#1427)
### Removed
- Drop most of the eACL-related code (#1425)
- Remove `--basic-acl` flag from `frostfs-cli container create` (#1483)
### Upgrading from v0.43.0
The metabase schema has changed completely, resync is required.
## [v0.42.0] ## [v0.42.0]
### Added ### Added

View file

@ -8,8 +8,8 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs
HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')"
GO_VERSION ?= 1.22 GO_VERSION ?= 1.22
LINT_VERSION ?= 1.62.0 LINT_VERSION ?= 1.61.0
TRUECLOUDLAB_LINT_VERSION ?= 0.0.8 TRUECLOUDLAB_LINT_VERSION ?= 0.0.7
PROTOC_VERSION ?= 25.0 PROTOC_VERSION ?= 25.0
PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go) PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go)
PROTOC_OS_VERSION=osx-x86_64 PROTOC_OS_VERSION=osx-x86_64

View file

@ -1 +1 @@
v0.44.0 v0.42.0

View file

@ -20,7 +20,6 @@ const (
AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" AlphabetWalletsFlagDesc = "Path to alphabet wallets dir"
LocalDumpFlag = "local-dump" LocalDumpFlag = "local-dump"
ProtoConfigPath = "protocol"
ContractsInitFlag = "contracts" ContractsInitFlag = "contracts"
ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)"
ContractsURLFlag = "contracts-url" ContractsURLFlag = "contracts-url"

View file

@ -5,19 +5,35 @@ import (
"encoding/json" "encoding/json"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
const ( const (
jsonFlag = "json" namespaceTarget = "namespace"
jsonFlagDesc = "Output rule chains in JSON format" containerTarget = "container"
addrAdminFlag = "addr" userTarget = "user"
addrAdminDesc = "The address of the admins wallet" groupTarget = "group"
jsonFlag = "json"
jsonFlagDesc = "Output rule chains in JSON format"
chainIDFlag = "chain-id"
chainIDDesc = "Rule chain ID"
ruleFlag = "rule"
ruleFlagDesc = "Rule chain in text format"
pathFlag = "path"
pathFlagDesc = "path to encoded chain in JSON or binary format"
targetNameFlag = "target-name"
targetNameDesc = "Resource name in APE resource name format"
targetTypeFlag = "target-type"
targetTypeDesc = "Resource type(container/namespace)"
addrAdminFlag = "addr"
addrAdminDesc = "The address of the admins wallet"
chainNameFlag = "chain-name"
chainNameFlagDesc = "Chain name(ingress|s3)"
) )
var ( var (
@ -85,17 +101,17 @@ func initAddRuleChainCmd() {
addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
addRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc)
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag)
addRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetTypeFlagDesc) addRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc)
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag) _ = addRuleChainCmd.MarkFlagRequired(targetNameFlag)
addRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc)
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.ChainIDFlag) _ = addRuleChainCmd.MarkFlagRequired(chainIDFlag)
addRuleChainCmd.Flags().StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc) addRuleChainCmd.Flags().StringArray(ruleFlag, []string{}, ruleFlagDesc)
addRuleChainCmd.Flags().String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc) addRuleChainCmd.Flags().String(pathFlag, "", pathFlagDesc)
addRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc) addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
addRuleChainCmd.MarkFlagsMutuallyExclusive(apeCmd.RuleFlag, apeCmd.PathFlag) addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, pathFlag)
} }
func initRemoveRuleChainCmd() { func initRemoveRuleChainCmd() {
@ -104,25 +120,26 @@ func initRemoveRuleChainCmd() {
removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
removeRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc)
_ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag)
removeRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc)
_ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag) _ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag)
removeRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc)
removeRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc) removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target") removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target")
removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, apeCmd.ChainIDFlag) removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, chainIDFlag)
} }
func initListRuleChainsCmd() { func initListRuleChainsCmd() {
Cmd.AddCommand(listRuleChainsCmd) Cmd.AddCommand(listRuleChainsCmd)
listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
listRuleChainsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc) listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc)
_ = listRuleChainsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag)
listRuleChainsCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc)
_ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag)
listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc) listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc)
listRuleChainsCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc) listRuleChainsCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
} }
func initSetAdminCmd() { func initSetAdminCmd() {
@ -144,15 +161,15 @@ func initListTargetsCmd() {
Cmd.AddCommand(listTargetsCmd) Cmd.AddCommand(listTargetsCmd)
listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
listTargetsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc) listTargetsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc)
_ = listTargetsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = listTargetsCmd.MarkFlagRequired(targetTypeFlag)
} }
func addRuleChain(cmd *cobra.Command, _ []string) { func addRuleChain(cmd *cobra.Command, _ []string) {
chain := apeCmd.ParseChain(cmd) chain := parseChain(cmd)
target := parseTarget(cmd) target := parseTarget(cmd)
pci, ac := newPolicyContractInterface(cmd) pci, ac := newPolicyContractInterface(cmd)
h, vub, err := pci.AddMorphRuleChain(apeCmd.ParseChainName(cmd), target, chain) h, vub, err := pci.AddMorphRuleChain(parseChainName(cmd), target, chain)
cmd.Println("Waiting for transaction to persist...") cmd.Println("Waiting for transaction to persist...")
_, err = ac.Wait(h, vub, err) _, err = ac.Wait(h, vub, err)
commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err) commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err)
@ -164,14 +181,14 @@ func removeRuleChain(cmd *cobra.Command, _ []string) {
pci, ac := newPolicyContractInterface(cmd) pci, ac := newPolicyContractInterface(cmd)
removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag) removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag)
if removeAll { if removeAll {
h, vub, err := pci.RemoveMorphRuleChainsByTarget(apeCmd.ParseChainName(cmd), target) h, vub, err := pci.RemoveMorphRuleChainsByTarget(parseChainName(cmd), target)
cmd.Println("Waiting for transaction to persist...") cmd.Println("Waiting for transaction to persist...")
_, err = ac.Wait(h, vub, err) _, err = ac.Wait(h, vub, err)
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
cmd.Println("All chains for target removed successfully") cmd.Println("All chains for target removed successfully")
} else { } else {
chainID := apeCmd.ParseChainID(cmd) chainID := parseChainID(cmd)
h, vub, err := pci.RemoveMorphRuleChain(apeCmd.ParseChainName(cmd), target, chainID) h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID)
cmd.Println("Waiting for transaction to persist...") cmd.Println("Waiting for transaction to persist...")
_, err = ac.Wait(h, vub, err) _, err = ac.Wait(h, vub, err)
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
@ -182,7 +199,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) {
func listRuleChains(cmd *cobra.Command, _ []string) { func listRuleChains(cmd *cobra.Command, _ []string) {
target := parseTarget(cmd) target := parseTarget(cmd)
pci, _ := newPolicyContractReaderInterface(cmd) pci, _ := newPolicyContractReaderInterface(cmd)
chains, err := pci.ListMorphRuleChains(apeCmd.ParseChainName(cmd), target) chains, err := pci.ListMorphRuleChains(parseChainName(cmd), target)
commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err) commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err)
if len(chains) == 0 { if len(chains) == 0 {
return return
@ -193,14 +210,14 @@ func listRuleChains(cmd *cobra.Command, _ []string) {
prettyJSONFormat(cmd, chains) prettyJSONFormat(cmd, chains)
} else { } else {
for _, c := range chains { for _, c := range chains {
apeCmd.PrintHumanReadableAPEChain(cmd, c) parseutil.PrintHumanReadableAPEChain(cmd, c)
} }
} }
} }
func setAdmin(cmd *cobra.Command, _ []string) { func setAdmin(cmd *cobra.Command, _ []string) {
s, _ := cmd.Flags().GetString(addrAdminFlag) s, _ := cmd.Flags().GetString(addrAdminFlag)
addr, err := address.StringToUint160(s) addr, err := util.Uint160DecodeStringLE(s)
commonCmd.ExitOnErr(cmd, "can't decode admin addr: %w", err) commonCmd.ExitOnErr(cmd, "can't decode admin addr: %w", err)
pci, ac := newPolicyContractInterface(cmd) pci, ac := newPolicyContractInterface(cmd)
h, vub, err := pci.SetAdmin(addr) h, vub, err := pci.SetAdmin(addr)
@ -214,11 +231,12 @@ func getAdmin(cmd *cobra.Command, _ []string) {
pci, _ := newPolicyContractReaderInterface(cmd) pci, _ := newPolicyContractReaderInterface(cmd)
addr, err := pci.GetAdmin() addr, err := pci.GetAdmin()
commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err) commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err)
cmd.Println(address.Uint160ToString(addr)) cmd.Println(addr.StringLE())
} }
func listTargets(cmd *cobra.Command, _ []string) { func listTargets(cmd *cobra.Command, _ []string) {
typ := apeCmd.ParseTargetType(cmd) typ, err := parseTargetType(cmd)
commonCmd.ExitOnErr(cmd, "parse target type error: %w", err)
pci, inv := newPolicyContractReaderInterface(cmd) pci, inv := newPolicyContractReaderInterface(cmd)
sid, it, err := pci.ListTargetsIterator(typ) sid, it, err := pci.ListTargetsIterator(typ)

View file

@ -2,12 +2,13 @@ package ape
import ( import (
"errors" "errors"
"strings"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
@ -17,29 +18,90 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var errUnknownTargetType = errors.New("unknown target type") const (
ingress = "ingress"
s3 = "s3"
)
var mChainName = map[string]apechain.Name{
ingress: apechain.Ingress,
s3: apechain.S3,
}
var (
errUnknownTargetType = errors.New("unknown target type")
errChainIDCannotBeEmpty = errors.New("chain id cannot be empty")
errRuleIsNotParsed = errors.New("rule is not passed")
errUnsupportedChainName = errors.New("unsupported chain name")
)
func parseTarget(cmd *cobra.Command) policyengine.Target { func parseTarget(cmd *cobra.Command) policyengine.Target {
typ := apeCmd.ParseTargetType(cmd) name, _ := cmd.Flags().GetString(targetNameFlag)
name, _ := cmd.Flags().GetString(apeCmd.TargetNameFlag) typ, err := parseTargetType(cmd)
switch typ {
case policyengine.Namespace: // interpret "root" namespace as empty
if name == "root" { if typ == policyengine.Namespace && name == "root" {
name = "" name = ""
}
return policyengine.NamespaceTarget(name)
case policyengine.Container:
var cnr cid.ID
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
return policyengine.ContainerTarget(name)
case policyengine.User:
return policyengine.UserTarget(name)
case policyengine.Group:
return policyengine.GroupTarget(name)
default:
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
} }
panic("unreachable")
commonCmd.ExitOnErr(cmd, "read target type error: %w", err)
return policyengine.Target{
Name: name,
Type: typ,
}
}
func parseTargetType(cmd *cobra.Command) (policyengine.TargetType, error) {
typ, _ := cmd.Flags().GetString(targetTypeFlag)
switch typ {
case namespaceTarget:
return policyengine.Namespace, nil
case containerTarget:
return policyengine.Container, nil
case userTarget:
return policyengine.User, nil
case groupTarget:
return policyengine.Group, nil
}
return -1, errUnknownTargetType
}
func parseChainID(cmd *cobra.Command) apechain.ID {
chainID, _ := cmd.Flags().GetString(chainIDFlag)
if chainID == "" {
commonCmd.ExitOnErr(cmd, "read chain id error: %w",
errChainIDCannotBeEmpty)
}
return apechain.ID(chainID)
}
func parseChain(cmd *cobra.Command) *apechain.Chain {
chain := new(apechain.Chain)
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules))
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath))
} else {
commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed)
}
chain.ID = parseChainID(cmd)
cmd.Println("Parsed chain:")
parseutil.PrintHumanReadableAPEChain(cmd, chain)
return chain
}
func parseChainName(cmd *cobra.Command) apechain.Name {
chainName, _ := cmd.Flags().GetString(chainNameFlag)
apeChainName, ok := mChainName[strings.ToLower(chainName)]
if !ok {
commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName)
}
return apeChainName
} }
// invokerAdapter adapats invoker.Invoker to ContractStorageInvoker interface. // invokerAdapter adapats invoker.Invoker to ContractStorageInvoker interface.

View file

@ -4,6 +4,7 @@ import "time"
const ( const (
ConsensusAccountName = "consensus" ConsensusAccountName = "consensus"
ProtoConfigPath = "protocol"
// MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size // MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size
// of the invocation script. // of the invocation script.

View file

@ -1,83 +0,0 @@
package frostfsid
import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
frostfsidAddSubjectKeyCmd = &cobra.Command{
Use: "add-subject-key",
Short: "Add a public key to the subject in frostfsid contract",
PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
},
Run: frostfsidAddSubjectKey,
}
frostfsidRemoveSubjectKeyCmd = &cobra.Command{
Use: "remove-subject-key",
Short: "Remove a public key from the subject in frostfsid contract",
PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
},
Run: frostfsidRemoveSubjectKey,
}
)
func initFrostfsIDAddSubjectKeyCmd() {
Cmd.AddCommand(frostfsidAddSubjectKeyCmd)
ff := frostfsidAddSubjectKeyCmd.Flags()
ff.StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
ff.String(subjectAddressFlag, "", "Subject address")
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectAddressFlag)
ff.String(subjectKeyFlag, "", "Public key to add")
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectKeyFlag)
}
func initFrostfsIDRemoveSubjectKeyCmd() {
Cmd.AddCommand(frostfsidRemoveSubjectKeyCmd)
ff := frostfsidRemoveSubjectKeyCmd.Flags()
ff.StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
ff.String(subjectAddressFlag, "", "Subject address")
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectAddressFlag)
ff.String(subjectKeyFlag, "", "Public key to remove")
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectKeyFlag)
}
func frostfsidAddSubjectKey(cmd *cobra.Command, _ []string) {
addr := getFrostfsIDSubjectAddress(cmd)
pub := getFrostfsIDSubjectKey(cmd)
ffsid, err := newFrostfsIDClient(cmd)
commonCmd.ExitOnErr(cmd, "init contract client: %w", err)
ffsid.addCall(ffsid.roCli.AddSubjectKeyCall(addr, pub))
err = ffsid.sendWait()
commonCmd.ExitOnErr(cmd, "add subject key: %w", err)
}
func frostfsidRemoveSubjectKey(cmd *cobra.Command, _ []string) {
addr := getFrostfsIDSubjectAddress(cmd)
pub := getFrostfsIDSubjectKey(cmd)
ffsid, err := newFrostfsIDClient(cmd)
commonCmd.ExitOnErr(cmd, "init contract client: %w", err)
ffsid.addCall(ffsid.roCli.RemoveSubjectKeyCall(addr, pub))
err = ffsid.sendWait()
commonCmd.ExitOnErr(cmd, "remove subject key: %w", err)
}

View file

@ -61,6 +61,7 @@ var (
Use: "list-namespaces", Use: "list-namespaces",
Short: "List all namespaces in frostfsid", Short: "List all namespaces in frostfsid",
PreRun: func(cmd *cobra.Command, _ []string) { PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
}, },
Run: frostfsidListNamespaces, Run: frostfsidListNamespaces,
@ -90,6 +91,7 @@ var (
Use: "list-subjects", Use: "list-subjects",
Short: "List subjects in namespace", Short: "List subjects in namespace",
PreRun: func(cmd *cobra.Command, _ []string) { PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
}, },
Run: frostfsidListSubjects, Run: frostfsidListSubjects,
@ -119,6 +121,7 @@ var (
Use: "list-groups", Use: "list-groups",
Short: "List groups in namespace", Short: "List groups in namespace",
PreRun: func(cmd *cobra.Command, _ []string) { PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
}, },
Run: frostfsidListGroups, Run: frostfsidListGroups,
@ -148,6 +151,7 @@ var (
Use: "list-group-subjects", Use: "list-group-subjects",
Short: "List subjects in group", Short: "List subjects in group",
PreRun: func(cmd *cobra.Command, _ []string) { PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
}, },
Run: frostfsidListGroupSubjects, Run: frostfsidListGroupSubjects,
@ -165,6 +169,7 @@ func initFrostfsIDCreateNamespaceCmd() {
func initFrostfsIDListNamespacesCmd() { func initFrostfsIDListNamespacesCmd() {
Cmd.AddCommand(frostfsidListNamespacesCmd) Cmd.AddCommand(frostfsidListNamespacesCmd)
frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
frostfsidListNamespacesCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
} }
func initFrostfsIDCreateSubjectCmd() { func initFrostfsIDCreateSubjectCmd() {
@ -188,6 +193,7 @@ func initFrostfsIDListSubjectsCmd() {
frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects")
frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
frostfsidListSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
} }
func initFrostfsIDCreateGroupCmd() { func initFrostfsIDCreateGroupCmd() {
@ -211,6 +217,7 @@ func initFrostfsIDListGroupsCmd() {
Cmd.AddCommand(frostfsidListGroupsCmd) Cmd.AddCommand(frostfsidListGroupsCmd)
frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups")
frostfsidListGroupsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
} }
func initFrostfsIDAddSubjectToGroupCmd() { func initFrostfsIDAddSubjectToGroupCmd() {
@ -235,6 +242,7 @@ func initFrostfsIDListGroupSubjectsCmd() {
frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name")
frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id")
frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
frostfsidListGroupSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
} }
func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) {

View file

@ -12,6 +12,4 @@ func init() {
initFrostfsIDAddSubjectToGroupCmd() initFrostfsIDAddSubjectToGroupCmd()
initFrostfsIDRemoveSubjectFromGroupCmd() initFrostfsIDRemoveSubjectFromGroupCmd()
initFrostfsIDListGroupSubjectsCmd() initFrostfsIDListGroupSubjectsCmd()
initFrostfsIDAddSubjectKeyCmd()
initFrostfsIDRemoveSubjectKeyCmd()
} }

View file

@ -38,24 +38,38 @@ func NewLocalActor(cmd *cobra.Command, c actor.RPCActor, accName string) (*Local
walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag))
var act *actor.Actor var act *actor.Actor
var accounts []*wallet.Account var accounts []*wallet.Account
if walletDir == "" {
account, err := wallet.NewAccount()
commonCmd.ExitOnErr(cmd, "unable to create dummy account: %w", err)
act, err = actor.New(c, []actor.SignerAccount{{
Signer: transaction.Signer{
Account: account.Contract.ScriptHash(),
Scopes: transaction.Global,
},
Account: account,
}})
if err != nil {
return nil, err
}
} else {
wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir)
commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err)
wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir) for _, w := range wallets {
commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) acc, err := GetWalletAccount(w, accName)
commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err)
for _, w := range wallets { accounts = append(accounts, acc)
acc, err := GetWalletAccount(w, accName) }
commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err) act, err = actor.New(c, []actor.SignerAccount{{
accounts = append(accounts, acc) Signer: transaction.Signer{
} Account: accounts[0].Contract.ScriptHash(),
act, err = actor.New(c, []actor.SignerAccount{{ Scopes: transaction.Global,
Signer: transaction.Signer{ },
Account: accounts[0].Contract.ScriptHash(), Account: accounts[0],
Scopes: transaction.Global, }})
}, if err != nil {
Account: accounts[0], return nil, err
}}) }
if err != nil {
return nil, err
} }
return &LocalActor{ return &LocalActor{
neoActor: act, neoActor: act,

View file

@ -8,7 +8,6 @@ import (
"sort" "sort"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
@ -48,7 +47,7 @@ type LocalClient struct {
} }
func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) { func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) {
cfg, err := config.LoadFile(v.GetString(commonflags.ProtoConfigPath)) cfg, err := config.LoadFile(v.GetString(constants.ProtoConfigPath))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -62,7 +62,7 @@ func testInitialize(t *testing.T, committeeSize int) {
v := viper.GetViper() v := viper.GetViper()
require.NoError(t, generateTestData(testdataDir, committeeSize)) require.NoError(t, generateTestData(testdataDir, committeeSize))
v.Set(commonflags.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) v.Set(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName))
// Set to the path or remove the next statement to download from the network. // Set to the path or remove the next statement to download from the network.
require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath)) require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath))

View file

@ -2,6 +2,7 @@ package initialize
import ( import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -31,7 +32,7 @@ var Cmd = &cobra.Command{
_ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) _ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag))
_ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) _ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag))
_ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) _ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag))
_ = viper.BindPFlag(commonflags.ProtoConfigPath, cmd.Flags().Lookup(commonflags.ProtoConfigPath)) _ = viper.BindPFlag(constants.ProtoConfigPath, cmd.Flags().Lookup(constants.ProtoConfigPath))
}, },
RunE: initializeSideChainCmd, RunE: initializeSideChainCmd,
} }
@ -47,7 +48,7 @@ func initInitCmd() {
// Defaults are taken from neo-preodolenie. // Defaults are taken from neo-preodolenie.
Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee")
Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee")
Cmd.Flags().String(commonflags.ProtoConfigPath, "", "Path to the consensus node configuration") Cmd.Flags().String(constants.ProtoConfigPath, "", "Path to the consensus node configuration")
Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file")
Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag) Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag)
} }

View file

@ -12,6 +12,7 @@ var (
Short: "List netmap candidates nodes", Short: "List netmap candidates nodes",
PreRun: func(cmd *cobra.Command, _ []string) { PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
}, },
Run: listNetmapCandidatesNodes, Run: listNetmapCandidatesNodes,
} }

View file

@ -24,7 +24,7 @@ func initRegisterCmd() {
} }
func registerDomain(cmd *cobra.Command, _ []string) { func registerDomain(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
email, _ := cmd.Flags().GetString(nnsEmailFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag)
@ -53,7 +53,7 @@ func initDeleteCmd() {
} }
func deleteDomain(cmd *cobra.Command, _ []string) { func deleteDomain(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
h, vub, err := c.DeleteDomain(name) h, vub, err := c.DeleteDomain(name)

View file

@ -5,13 +5,13 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, util.Uint160) {
v := viper.GetViper() v := viper.GetViper()
c, err := helper.GetN3Client(v) c, err := helper.GetN3Client(v)
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
@ -22,17 +22,5 @@ func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) {
r := management.NewReader(ac.Invoker) r := management.NewReader(ac.Invoker)
nnsCs, err := helper.GetContractByID(r, 1) nnsCs, err := helper.GetContractByID(r, 1)
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
return client.New(ac, nnsCs.Hash), ac return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash
}
func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) {
c, err := helper.GetN3Client(viper.GetViper())
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
inv := invoker.New(c, nil)
r := management.NewReader(inv)
nnsCs, err := helper.GetContractByID(r, 1)
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
return client.NewReader(inv, nnsCs.Hash), inv
} }

View file

@ -8,6 +8,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -28,6 +29,7 @@ func initAddRecordCmd() {
func initGetRecordsCmd() { func initGetRecordsCmd() {
Cmd.AddCommand(getRecordsCmd) Cmd.AddCommand(getRecordsCmd)
getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
getRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc)
getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc)
@ -59,7 +61,7 @@ func initDelRecordCmd() {
} }
func addRecord(cmd *cobra.Command, _ []string) { func addRecord(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
data, _ := cmd.Flags().GetString(nnsRecordDataFlag) data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
@ -75,16 +77,16 @@ func addRecord(cmd *cobra.Command, _ []string) {
} }
func getRecords(cmd *cobra.Command, _ []string) { func getRecords(cmd *cobra.Command, _ []string) {
c, inv := nnsReader(cmd) c, act, hash := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
if recordType == "" { if recordType == "" {
sid, r, err := c.GetAllRecords(name) sid, r, err := unwrap.SessionIterator(act.Invoker.Call(hash, "getAllRecords", name))
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
defer func() { defer func() {
_ = inv.TerminateSession(sid) _ = act.Invoker.TerminateSession(sid)
}() }()
items, err := inv.TraverseIterator(sid, &r, 0) items, err := act.Invoker.TraverseIterator(sid, &r, 0)
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
for len(items) != 0 { for len(items) != 0 {
for j := range items { for j := range items {
@ -95,7 +97,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())), recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())),
string(bs)) string(bs))
} }
items, err = inv.TraverseIterator(sid, &r, 0) items, err = act.Invoker.TraverseIterator(sid, &r, 0)
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
} }
} else { } else {
@ -112,7 +114,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
} }
func delRecords(cmd *cobra.Command, _ []string) { func delRecords(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
typ, err := getRecordType(recordType) typ, err := getRecordType(recordType)
@ -127,7 +129,7 @@ func delRecords(cmd *cobra.Command, _ []string) {
} }
func delRecord(cmd *cobra.Command, _ []string) { func delRecord(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
data, _ := cmd.Flags().GetString(nnsRecordDataFlag) data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)

View file

@ -14,7 +14,7 @@ func initRenewCmd() {
} }
func renewDomain(cmd *cobra.Command, _ []string) { func renewDomain(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
h, vub, err := c.Renew(name) h, vub, err := c.Renew(name)
commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err) commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err)

View file

@ -18,11 +18,12 @@ const (
func initTokensCmd() { func initTokensCmd() {
Cmd.AddCommand(tokensCmd) Cmd.AddCommand(tokensCmd)
tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc) tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc)
} }
func listTokens(cmd *cobra.Command, _ []string) { func listTokens(cmd *cobra.Command, _ []string) {
c, _ := nnsReader(cmd) c, _, _ := getRPCClient(cmd)
it, err := c.Tokens() it, err := c.Tokens()
commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err) commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err)
for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) { for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) {
@ -40,7 +41,7 @@ func listTokens(cmd *cobra.Command, _ []string) {
} }
} }
func getCnameRecord(c *client.ContractReader, token []byte) (string, error) { func getCnameRecord(c *client.Contract, token []byte) (string, error) {
items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME))) items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME)))
// GetRecords returns the error "not an array" if the domain does not contain records. // GetRecords returns the error "not an array" if the domain does not contain records.

View file

@ -30,7 +30,7 @@ func initUpdateCmd() {
} }
func updateSOA(cmd *cobra.Command, _ []string) { func updateSOA(cmd *cobra.Command, _ []string) {
c, actor := nnsWriter(cmd) c, actor, _ := getRPCClient(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
email, _ := cmd.Flags().GetString(nnsEmailFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag)

View file

@ -1,19 +1,44 @@
package apemanager package apemanager
import ( import (
"fmt" "encoding/hex"
"errors"
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const (
chainIDFlag = "chain-id"
chainIDHexFlag = "chain-id-hex"
ruleFlag = "rule"
pathFlag = "path"
)
const (
targetNameFlag = "target-name"
targetNameDesc = "Resource name in APE resource name format"
targetTypeFlag = "target-type"
targetTypeDesc = "Resource type(container/namespace)"
)
const (
namespaceTarget = "namespace"
containerTarget = "container"
userTarget = "user"
groupTarget = "group"
)
var errUnknownTargetType = errors.New("unknown target type")
var addCmd = &cobra.Command{ var addCmd = &cobra.Command{
Use: "add", Use: "add",
Short: "Add rule chain for a target", Short: "Add rule chain for a target",
@ -24,28 +49,55 @@ var addCmd = &cobra.Command{
} }
func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) { func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) {
t := apeCmd.ParseTarget(cmd) typ, _ := cmd.Flags().GetString(targetTypeFlag)
name, _ := cmd.Flags().GetString(targetNameFlag)
ct.Name = t.Name ct.Name = name
switch t.Type { switch typ {
case engine.Namespace: case namespaceTarget:
ct.TargetType = apeSDK.TargetTypeNamespace ct.TargetType = apeSDK.TargetTypeNamespace
case engine.Container: case containerTarget:
var cnr cid.ID
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
ct.TargetType = apeSDK.TargetTypeContainer ct.TargetType = apeSDK.TargetTypeContainer
case engine.User: case userTarget:
ct.TargetType = apeSDK.TargetTypeUser ct.TargetType = apeSDK.TargetTypeUser
case engine.Group: case groupTarget:
ct.TargetType = apeSDK.TargetTypeGroup ct.TargetType = apeSDK.TargetTypeGroup
default: default:
commonCmd.ExitOnErr(cmd, "conversion error: %w", fmt.Errorf("unknown type '%c'", t.Type)) commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
} }
return ct return ct
} }
func parseChain(cmd *cobra.Command) apeSDK.Chain { func parseChain(cmd *cobra.Command) apeSDK.Chain {
c := apeCmd.ParseChain(cmd) chainID, _ := cmd.Flags().GetString(chainIDFlag)
serialized := c.Bytes() hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
chainIDRaw := []byte(chainID)
if hexEncoded {
var err error
chainIDRaw, err = hex.DecodeString(chainID)
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
}
chain := new(apechain.Chain)
chain.ID = apechain.ID(chainIDRaw)
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules))
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath))
} else {
commonCmd.ExitOnErr(cmd, "parser error: %w", errors.New("rule is not passed"))
}
cmd.Println("Parsed chain:")
util.PrintHumanReadableAPEChain(cmd, chain)
serialized := chain.Bytes()
return apeSDK.Chain{ return apeSDK.Chain{
Raw: serialized, Raw: serialized,
} }
@ -74,13 +126,13 @@ func initAddCmd() {
commonflags.Init(addCmd) commonflags.Init(addCmd)
ff := addCmd.Flags() ff := addCmd.Flags()
ff.StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc) ff.StringArray(ruleFlag, []string{}, "Rule statement")
ff.String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc) ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = addCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = addCmd.MarkFlagRequired(targetTypeFlag)
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc) ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
addCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag) addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
} }

View file

@ -4,8 +4,8 @@ import (
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -35,7 +35,7 @@ func list(cmd *cobra.Command, _ []string) {
for _, respChain := range resp.Chains { for _, respChain := range resp.Chains {
var chain apechain.Chain var chain apechain.Chain
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw)) commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw))
apeCmd.PrintHumanReadableAPEChain(cmd, &chain) apeutil.PrintHumanReadableAPEChain(cmd, &chain)
} }
} }
@ -43,7 +43,7 @@ func initListCmd() {
commonflags.Init(listCmd) commonflags.Init(listCmd)
ff := listCmd.Flags() ff := listCmd.Flags()
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = listCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = listCmd.MarkFlagRequired(targetTypeFlag)
} }

View file

@ -1,23 +1,29 @@
package apemanager package apemanager
import ( import (
"encoding/hex"
"errors"
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var removeCmd = &cobra.Command{ var (
Use: "remove", errEmptyChainID = errors.New("chain id cannot be empty")
Short: "Remove rule chain for a target",
Run: remove, removeCmd = &cobra.Command{
PersistentPreRun: func(cmd *cobra.Command, _ []string) { Use: "remove",
commonflags.Bind(cmd) Short: "Remove rule chain for a target",
}, Run: remove,
} PersistentPreRun: func(cmd *cobra.Command, _ []string) {
commonflags.Bind(cmd)
},
}
)
func remove(cmd *cobra.Command, _ []string) { func remove(cmd *cobra.Command, _ []string) {
target := parseTarget(cmd) target := parseTarget(cmd)
@ -25,9 +31,19 @@ func remove(cmd *cobra.Command, _ []string) {
key := key.Get(cmd) key := key.Get(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
chainID := apeCmd.ParseChainID(cmd) chainID, _ := cmd.Flags().GetString(chainIDFlag)
if chainID == "" {
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
}
chainIDRaw := []byte(chainID) chainIDRaw := []byte(chainID)
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
if hexEncoded {
var err error
chainIDRaw, err = hex.DecodeString(chainID)
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
}
_, err := cli.APEManagerRemoveChain(cmd.Context(), client_sdk.PrmAPEManagerRemoveChain{ _, err := cli.APEManagerRemoveChain(cmd.Context(), client_sdk.PrmAPEManagerRemoveChain{
ChainTarget: target, ChainTarget: target,
ChainID: chainIDRaw, ChainID: chainIDRaw,
@ -42,10 +58,9 @@ func initRemoveCmd() {
commonflags.Init(removeCmd) commonflags.Init(removeCmd)
ff := removeCmd.Flags() ff := removeCmd.Flags()
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = removeCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = removeCmd.MarkFlagRequired(targetTypeFlag)
ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) ff.String(chainIDFlag, "", "Chain id")
_ = removeCmd.MarkFlagRequired(apeCmd.ChainIDFlag) ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
} }

View file

@ -1,20 +1,31 @@
package bearer package bearer
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var (
errChainIDCannotBeEmpty = errors.New("chain id cannot be empty")
errRuleIsNotParsed = errors.New("rule is not passed")
)
const ( const (
outputFlag = "output" chainIDFlag = "chain-id"
chainIDHexFlag = "chain-id-hex"
ruleFlag = "rule"
pathFlag = "path"
outputFlag = "output"
) )
var generateAPEOverrideCmd = &cobra.Command{ var generateAPEOverrideCmd = &cobra.Command{
@ -29,7 +40,7 @@ Generated APE override can be dumped to a file in JSON format that is passed to
} }
func genereateAPEOverride(cmd *cobra.Command, _ []string) { func genereateAPEOverride(cmd *cobra.Command, _ []string) {
c := apeCmd.ParseChain(cmd) c := parseChain(cmd)
targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag) targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var cid cidSDK.ID var cid cidSDK.ID
@ -66,11 +77,39 @@ func init() {
ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.") ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.")
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag) _ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag)
ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement") ff.StringArray(ruleFlag, []string{}, "Rule statement")
ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format") ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain") ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override") ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override")
_ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag) _ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag)
} }
func parseChainID(cmd *cobra.Command) apechain.ID {
chainID, _ := cmd.Flags().GetString(chainIDFlag)
if chainID == "" {
commonCmd.ExitOnErr(cmd, "read chain id error: %w",
errChainIDCannotBeEmpty)
}
return apechain.ID(chainID)
}
func parseChain(cmd *cobra.Command) *apechain.Chain {
chain := new(apechain.Chain)
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules))
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath))
} else {
commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed)
}
chain.ID = parseChainID(cmd)
cmd.Println("Parsed chain:")
parseutil.PrintHumanReadableAPEChain(cmd, chain)
return chain
}

View file

@ -1,14 +1,23 @@
package control package control
import ( import (
"encoding/hex"
"errors"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const (
ruleFlag = "rule"
pathFlag = "path"
)
var addRuleCmd = &cobra.Command{ var addRuleCmd = &cobra.Command{
Use: "add-rule", Use: "add-rule",
Short: "Add local override", Short: "Add local override",
@ -22,12 +31,41 @@ control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ..
Run: addRule, Run: addRule,
} }
func parseChain(cmd *cobra.Command) *apechain.Chain {
chainID, _ := cmd.Flags().GetString(chainIDFlag)
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
chainIDRaw := []byte(chainID)
if hexEncoded {
var err error
chainIDRaw, err = hex.DecodeString(chainID)
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
}
chain := new(apechain.Chain)
chain.ID = apechain.ID(chainIDRaw)
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules))
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath))
} else {
commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed"))
}
cmd.Println("Parsed chain:")
util.PrintHumanReadableAPEChain(cmd, chain)
return chain
}
func addRule(cmd *cobra.Command, _ []string) { func addRule(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd) pk := key.Get(cmd)
target := parseTarget(cmd) target := parseTarget(cmd)
parsed := apeCmd.ParseChain(cmd) parsed := parseChain(cmd)
req := &control.AddChainLocalOverrideRequest{ req := &control.AddChainLocalOverrideRequest{
Body: &control.AddChainLocalOverrideRequest_Body{ Body: &control.AddChainLocalOverrideRequest_Body{
@ -56,13 +94,13 @@ func initControlAddRuleCmd() {
initControlFlags(addRuleCmd) initControlFlags(addRuleCmd)
ff := addRuleCmd.Flags() ff := addRuleCmd.Flags()
ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement") ff.StringArray(ruleFlag, []string{}, "Rule statement")
ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format") ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain") ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = addRuleCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = addRuleCmd.MarkFlagRequired(targetTypeFlag)
ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
addRuleCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag) addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
} }

View file

@ -4,8 +4,8 @@ import (
"encoding/hex" "encoding/hex"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apecmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
@ -24,8 +24,8 @@ func getRule(cmd *cobra.Command, _ []string) {
target := parseTarget(cmd) target := parseTarget(cmd)
chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag) chainID, _ := cmd.Flags().GetString(chainIDFlag)
hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
if hexEncoded { if hexEncoded {
chainIDBytes, err := hex.DecodeString(chainID) chainIDBytes, err := hex.DecodeString(chainID)
@ -56,16 +56,16 @@ func getRule(cmd *cobra.Command, _ []string) {
var chain apechain.Chain var chain apechain.Chain
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain()))
apecmd.PrintHumanReadableAPEChain(cmd, &chain) util.PrintHumanReadableAPEChain(cmd, &chain)
} }
func initControGetRuleCmd() { func initControGetRuleCmd() {
initControlFlags(getRuleCmd) initControlFlags(getRuleCmd)
ff := getRuleCmd.Flags() ff := getRuleCmd.Flags()
ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = getRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag) _ = getRuleCmd.MarkFlagRequired(targetTypeFlag)
ff.String(apecmd.ChainIDFlag, "", "Chain id") ff.String(chainIDFlag, "", "Chain id")
ff.Bool(apecmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
} }

View file

@ -1,16 +1,18 @@
package control package control
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/nspcc-dev/neo-go/cli/input"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -21,25 +23,65 @@ var listRulesCmd = &cobra.Command{
Run: listRules, Run: listRules,
} }
var engineToControlSvcType = map[policyengine.TargetType]control.ChainTarget_TargetType{ const (
policyengine.Namespace: control.ChainTarget_NAMESPACE, defaultNamespace = "root"
policyengine.Container: control.ChainTarget_CONTAINER, namespaceTarget = "namespace"
policyengine.User: control.ChainTarget_USER, containerTarget = "container"
policyengine.Group: control.ChainTarget_GROUP, userTarget = "user"
} groupTarget = "group"
)
const (
targetNameFlag = "target-name"
targetNameDesc = "Resource name in APE resource name format"
targetTypeFlag = "target-type"
targetTypeDesc = "Resource type(container/namespace)"
)
var (
errSettingDefaultValueWasDeclined = errors.New("setting default value was declined")
errUnknownTargetType = errors.New("unknown target type")
)
func parseTarget(cmd *cobra.Command) *control.ChainTarget { func parseTarget(cmd *cobra.Command) *control.ChainTarget {
target := apeCmd.ParseTarget(cmd) typ, _ := cmd.Flags().GetString(targetTypeFlag)
name, _ := cmd.Flags().GetString(targetNameFlag)
typ, ok := engineToControlSvcType[target.Type] switch typ {
if !ok { case namespaceTarget:
commonCmd.ExitOnErr(cmd, "%w", fmt.Errorf("unknown type '%c", target.Type)) if name == "" {
} ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace))
commonCmd.ExitOnErr(cmd, "read line error: %w", err)
return &control.ChainTarget{ ln = strings.ToLower(ln)
Name: target.Name, if len(ln) > 0 && (ln[0] == 'n') {
Type: typ, commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined)
}
name = defaultNamespace
}
return &control.ChainTarget{
Name: name,
Type: control.ChainTarget_NAMESPACE,
}
case containerTarget:
var cnr cid.ID
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
return &control.ChainTarget{
Name: name,
Type: control.ChainTarget_CONTAINER,
}
case userTarget:
return &control.ChainTarget{
Name: name,
Type: control.ChainTarget_USER,
}
case groupTarget:
return &control.ChainTarget{
Name: name,
Type: control.ChainTarget_GROUP,
}
default:
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
} }
return nil
} }
func listRules(cmd *cobra.Command, _ []string) { func listRules(cmd *cobra.Command, _ []string) {
@ -75,7 +117,7 @@ func listRules(cmd *cobra.Command, _ []string) {
for _, c := range chains { for _, c := range chains {
var chain apechain.Chain var chain apechain.Chain
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c))
apeCmd.PrintHumanReadableAPEChain(cmd, &chain) util.PrintHumanReadableAPEChain(cmd, &chain)
} }
} }
@ -83,7 +125,7 @@ func initControlListRulesCmd() {
initControlFlags(listRulesCmd) initControlFlags(listRulesCmd)
ff := listRulesCmd.Flags() ff := listRulesCmd.Flags()
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = listRulesCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) _ = listRulesCmd.MarkFlagRequired(targetTypeFlag)
} }

View file

@ -2,20 +2,26 @@ package control
import ( import (
"bytes" "bytes"
"crypto/sha256"
"fmt" "fmt"
"strconv" "strconv"
"text/tabwriter" "text/tabwriter"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
const (
chainNameFlag = "chain-name"
chainNameFlagUsage = "Chain name(ingress|s3)"
)
var listTargetsCmd = &cobra.Command{ var listTargetsCmd = &cobra.Command{
Use: "list-targets", Use: "list-targets",
Short: "List local targets", Short: "List local targets",
@ -26,11 +32,15 @@ var listTargetsCmd = &cobra.Command{
func listTargets(cmd *cobra.Command, _ []string) { func listTargets(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd) pk := key.Get(cmd)
chainName := apeCmd.ParseChainName(cmd) var cnr cid.ID
chainName, _ := cmd.Flags().GetString(chainNameFlag)
rawCID := make([]byte, sha256.Size)
cnr.Encode(rawCID)
req := &control.ListTargetsLocalOverridesRequest{ req := &control.ListTargetsLocalOverridesRequest{
Body: &control.ListTargetsLocalOverridesRequest_Body{ Body: &control.ListTargetsLocalOverridesRequest_Body{
ChainName: string(chainName), ChainName: chainName,
}, },
} }
@ -72,7 +82,7 @@ func initControlListTargetsCmd() {
initControlFlags(listTargetsCmd) initControlFlags(listTargetsCmd)
ff := listTargetsCmd.Flags() ff := listTargetsCmd.Flags()
ff.String(apeCmd.ChainNameFlag, "", apeCmd.ChainNameFlagDesc) ff.String(chainNameFlag, "", chainNameFlagUsage)
_ = cobra.MarkFlagRequired(ff, apeCmd.ChainNameFlag) _ = cobra.MarkFlagRequired(ff, chainNameFlag)
} }

View file

@ -6,12 +6,17 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apecmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const (
chainIDFlag = "chain-id"
chainIDHexFlag = "chain-id-hex"
allFlag = "all"
)
var ( var (
errEmptyChainID = errors.New("chain id cannot be empty") errEmptyChainID = errors.New("chain id cannot be empty")
@ -25,8 +30,8 @@ var (
func removeRule(cmd *cobra.Command, _ []string) { func removeRule(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd) pk := key.Get(cmd)
hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
removeAll, _ := cmd.Flags().GetBool(apecmd.AllFlag) removeAll, _ := cmd.Flags().GetBool(allFlag)
if removeAll { if removeAll {
req := &control.RemoveChainLocalOverridesByTargetRequest{ req := &control.RemoveChainLocalOverridesByTargetRequest{
Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{ Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{
@ -47,7 +52,7 @@ func removeRule(cmd *cobra.Command, _ []string) {
return return
} }
chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag) chainID, _ := cmd.Flags().GetString(chainIDFlag)
if chainID == "" { if chainID == "" {
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID) commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
} }
@ -87,11 +92,11 @@ func initControlRemoveRuleCmd() {
initControlFlags(removeRuleCmd) initControlFlags(removeRuleCmd)
ff := removeRuleCmd.Flags() ff := removeRuleCmd.Flags()
ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = removeRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag) _ = removeRuleCmd.MarkFlagRequired(targetTypeFlag)
ff.String(apecmd.ChainIDFlag, "", apecmd.ChainIDFlagDesc) ff.String(chainIDFlag, "", "Chain id")
ff.Bool(apecmd.ChainIDHexFlag, false, apecmd.ChainIDHexFlagDesc) ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
ff.Bool(apecmd.AllFlag, false, "Remove all chains") ff.Bool(allFlag, false, "Remove all chains")
removeRuleCmd.MarkFlagsMutuallyExclusive(apecmd.AllFlag, apecmd.ChainIDFlag) removeRuleCmd.MarkFlagsMutuallyExclusive(allFlag, chainIDFlag)
} }

View file

@ -1,14 +1,16 @@
package ape package util
import ( import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"strconv"
"strings" "strings"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/flynn-archive/go-shlex" "github.com/flynn-archive/go-shlex"
"github.com/spf13/cobra"
) )
var ( var (
@ -25,6 +27,38 @@ var (
errFailedToParseAllAny = errors.New("any/all is not parsed") errFailedToParseAllAny = errors.New("any/all is not parsed")
) )
// PrintHumanReadableAPEChain print APE chain rules.
func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
cmd.Println("Chain ID: " + string(chain.ID))
cmd.Printf(" HEX: %x\n", chain.ID)
cmd.Println("Rules:")
for _, rule := range chain.Rules {
cmd.Println("\n\tStatus: " + rule.Status.String())
cmd.Println("\tAny: " + strconv.FormatBool(rule.Any))
cmd.Println("\tConditions:")
for _, c := range rule.Condition {
var ot string
switch c.Kind {
case apechain.KindResource:
ot = "Resource"
case apechain.KindRequest:
ot = "Request"
default:
panic("unknown object type")
}
cmd.Println(fmt.Sprintf("\t\t%s %s %s %s", ot, c.Key, c.Op, c.Value))
}
cmd.Println("\tActions:\tInverted:" + strconv.FormatBool(rule.Actions.Inverted))
for _, name := range rule.Actions.Names {
cmd.Println("\t\t" + name)
}
cmd.Println("\tResources:\tInverted:" + strconv.FormatBool(rule.Resources.Inverted))
for _, name := range rule.Resources.Names {
cmd.Println("\t\t" + name)
}
}
}
func ParseAPEChainBinaryOrJSON(chain *apechain.Chain, path string) error { func ParseAPEChainBinaryOrJSON(chain *apechain.Chain, path string) error {
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {

View file

@ -1,4 +1,4 @@
package ape package util
import ( import (
"fmt" "fmt"

View file

@ -6,7 +6,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"context"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
@ -47,7 +46,7 @@ func reloadConfig() error {
return logPrm.Reload() return logPrm.Reload()
} }
func watchForSignal(ctx context.Context, cancel func()) { func watchForSignal(cancel func()) {
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
@ -59,49 +58,49 @@ func watchForSignal(ctx context.Context, cancel func()) {
// signals causing application to shut down should have priority over // signals causing application to shut down should have priority over
// reconfiguration signal // reconfiguration signal
case <-ch: case <-ch:
log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
cancel() cancel()
shutdown(ctx) shutdown()
log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-intErr: // internal application error case err := <-intErr: // internal application error
log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error())) log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
cancel() cancel()
shutdown(ctx) shutdown()
return return
default: default:
// block until any signal is receieved // block until any signal is receieved
select { select {
case <-ch: case <-ch:
log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
cancel() cancel()
shutdown(ctx) shutdown()
log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-intErr: // internal application error case err := <-intErr: // internal application error
log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error())) log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
cancel() cancel()
shutdown(ctx) shutdown()
return return
case <-sighupCh: case <-sighupCh:
log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
if !innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
log.Info(ctx, logs.FrostFSNodeSIGHUPSkip) log.Info(logs.FrostFSNodeSIGHUPSkip)
break break
} }
err := reloadConfig() err := reloadConfig()
if err != nil { if err != nil {
log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
} }
pprofCmp.reload(ctx) pprofCmp.reload()
metricsCmp.reload(ctx) metricsCmp.reload()
log.Info(ctx, logs.FrostFSIRReloadExtraWallets) log.Info(logs.FrostFSIRReloadExtraWallets)
err = innerRing.SetExtraWallets(cfg) err = innerRing.SetExtraWallets(cfg)
if err != nil { if err != nil {
log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
} }
innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
} }
} }
} }

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@ -25,8 +24,8 @@ const (
shutdownTimeoutKeyPostfix = ".shutdown_timeout" shutdownTimeoutKeyPostfix = ".shutdown_timeout"
) )
func (c *httpComponent) init(ctx context.Context) { func (c *httpComponent) init() {
log.Info(ctx, "init "+c.name) log.Info("init " + c.name)
c.enabled = cfg.GetBool(c.name + enabledKeyPostfix) c.enabled = cfg.GetBool(c.name + enabledKeyPostfix)
c.address = cfg.GetString(c.name + addressKeyPostfix) c.address = cfg.GetString(c.name + addressKeyPostfix)
c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix) c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix)
@ -40,14 +39,14 @@ func (c *httpComponent) init(ctx context.Context) {
httputil.WithShutdownTimeout(c.shutdownDur), httputil.WithShutdownTimeout(c.shutdownDur),
) )
} else { } else {
log.Info(ctx, c.name+" is disabled, skip") log.Info(c.name + " is disabled, skip")
c.srv = nil c.srv = nil
} }
} }
func (c *httpComponent) start(ctx context.Context) { func (c *httpComponent) start() {
if c.srv != nil { if c.srv != nil {
log.Info(ctx, "start "+c.name) log.Info("start " + c.name)
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
@ -56,10 +55,10 @@ func (c *httpComponent) start(ctx context.Context) {
} }
} }
func (c *httpComponent) shutdown(ctx context.Context) error { func (c *httpComponent) shutdown() error {
if c.srv != nil { if c.srv != nil {
log.Info(ctx, "shutdown "+c.name) log.Info("shutdown " + c.name)
return c.srv.Shutdown(ctx) return c.srv.Shutdown()
} }
return nil return nil
} }
@ -71,17 +70,17 @@ func (c *httpComponent) needReload() bool {
return enabled != c.enabled || enabled && (address != c.address || dur != c.shutdownDur) return enabled != c.enabled || enabled && (address != c.address || dur != c.shutdownDur)
} }
func (c *httpComponent) reload(ctx context.Context) { func (c *httpComponent) reload() {
log.Info(ctx, "reload "+c.name) log.Info("reload " + c.name)
if c.needReload() { if c.needReload() {
log.Info(ctx, c.name+" config updated") log.Info(c.name + " config updated")
if err := c.shutdown(ctx); err != nil { if err := c.shutdown(); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} else { } else {
c.init(ctx) c.init()
c.start(ctx) c.start()
} }
} }
} }

View file

@ -87,48 +87,48 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
pprofCmp = newPprofComponent() pprofCmp = newPprofComponent()
pprofCmp.init(ctx) pprofCmp.init()
metricsCmp = newMetricsComponent() metricsCmp = newMetricsComponent()
metricsCmp.init(ctx) metricsCmp.init()
audit.Store(cfg.GetBool("audit.enabled")) audit.Store(cfg.GetBool("audit.enabled"))
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit) innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit)
exitErr(err) exitErr(err)
pprofCmp.start(ctx) pprofCmp.start()
metricsCmp.start(ctx) metricsCmp.start()
// start inner ring // start inner ring
err = innerRing.Start(ctx, intErr) err = innerRing.Start(ctx, intErr)
exitErr(err) exitErr(err)
log.Info(ctx, logs.CommonApplicationStarted, log.Info(logs.CommonApplicationStarted,
zap.String("version", misc.Version)) zap.String("version", misc.Version))
watchForSignal(ctx, cancel) watchForSignal(cancel)
<-ctx.Done() // graceful shutdown <-ctx.Done() // graceful shutdown
log.Debug(ctx, logs.FrostFSNodeWaitingForAllProcessesToStop) log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop)
wg.Wait() wg.Wait()
log.Info(ctx, logs.FrostFSIRApplicationStopped) log.Info(logs.FrostFSIRApplicationStopped)
} }
func shutdown(ctx context.Context) { func shutdown() {
innerRing.Stop(ctx) innerRing.Stop()
if err := metricsCmp.shutdown(ctx); err != nil { if err := metricsCmp.shutdown(); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
if err := pprofCmp.shutdown(ctx); err != nil { if err := pprofCmp.shutdown(); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
if err := sdnotify.ClearStatus(); err != nil { if err := sdnotify.ClearStatus(); err != nil {
log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err))
} }
} }

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"context"
"runtime" "runtime"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
@ -29,8 +28,8 @@ func newPprofComponent() *pprofComponent {
} }
} }
func (c *pprofComponent) init(ctx context.Context) { func (c *pprofComponent) init() {
c.httpComponent.init(ctx) c.httpComponent.init()
if c.enabled { if c.enabled {
c.blockRate = cfg.GetInt(pprofBlockRateKey) c.blockRate = cfg.GetInt(pprofBlockRateKey)
@ -52,17 +51,17 @@ func (c *pprofComponent) needReload() bool {
c.enabled && (c.blockRate != blockRate || c.mutexRate != mutexRate) c.enabled && (c.blockRate != blockRate || c.mutexRate != mutexRate)
} }
func (c *pprofComponent) reload(ctx context.Context) { func (c *pprofComponent) reload() {
log.Info(ctx, "reload "+c.name) log.Info("reload " + c.name)
if c.needReload() { if c.needReload() {
log.Info(ctx, c.name+" config updated") log.Info(c.name + " config updated")
if err := c.shutdown(ctx); err != nil { if err := c.shutdown(); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return return
} }
c.init(ctx) c.init()
c.start(ctx) c.start()
} }
} }

View file

@ -28,7 +28,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) {
common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
blz := openBlobovnicza(cmd) blz := openBlobovnicza(cmd)
defer blz.Close(cmd.Context()) defer blz.Close()
var prm blobovnicza.GetPrm var prm blobovnicza.GetPrm
prm.SetAddress(addr) prm.SetAddress(addr)

View file

@ -32,7 +32,7 @@ func listFunc(cmd *cobra.Command, _ []string) {
} }
blz := openBlobovnicza(cmd) blz := openBlobovnicza(cmd)
defer blz.Close(cmd.Context()) defer blz.Close()
err := blobovnicza.IterateAddresses(context.Background(), blz, wAddr) err := blobovnicza.IterateAddresses(context.Background(), blz, wAddr)
common.ExitOnErr(cmd, common.Errf("blobovnicza iterator failure: %w", err)) common.ExitOnErr(cmd, common.Errf("blobovnicza iterator failure: %w", err))

View file

@ -27,7 +27,7 @@ func openBlobovnicza(cmd *cobra.Command) *blobovnicza.Blobovnicza {
blobovnicza.WithPath(vPath), blobovnicza.WithPath(vPath),
blobovnicza.WithReadOnly(true), blobovnicza.WithReadOnly(true),
) )
common.ExitOnErr(cmd, blz.Open(cmd.Context())) common.ExitOnErr(cmd, blz.Open())
return blz return blz
} }

View file

@ -31,7 +31,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) {
common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
db := openMeta(cmd) db := openMeta(cmd)
defer db.Close(cmd.Context()) defer db.Close()
storageID := meta.StorageIDPrm{} storageID := meta.StorageIDPrm{}
storageID.SetAddress(addr) storageID.SetAddress(addr)

View file

@ -19,7 +19,7 @@ func init() {
func listGarbageFunc(cmd *cobra.Command, _ []string) { func listGarbageFunc(cmd *cobra.Command, _ []string) {
db := openMeta(cmd) db := openMeta(cmd)
defer db.Close(cmd.Context()) defer db.Close()
var garbPrm meta.GarbageIterationPrm var garbPrm meta.GarbageIterationPrm
garbPrm.SetHandler( garbPrm.SetHandler(

View file

@ -19,7 +19,7 @@ func init() {
func listGraveyardFunc(cmd *cobra.Command, _ []string) { func listGraveyardFunc(cmd *cobra.Command, _ []string) {
db := openMeta(cmd) db := openMeta(cmd)
defer db.Close(cmd.Context()) defer db.Close()
var gravePrm meta.GraveyardIterationPrm var gravePrm meta.GraveyardIterationPrm
gravePrm.SetHandler( gravePrm.SetHandler(

View file

@ -397,16 +397,16 @@ type internals struct {
} }
// starts node's maintenance. // starts node's maintenance.
func (c *cfg) startMaintenance(ctx context.Context) { func (c *cfg) startMaintenance() {
c.isMaintenance.Store(true) c.isMaintenance.Store(true)
c.cfgNetmap.state.setControlNetmapStatus(control.NetmapStatus_MAINTENANCE) c.cfgNetmap.state.setControlNetmapStatus(control.NetmapStatus_MAINTENANCE)
c.log.Info(ctx, logs.FrostFSNodeStartedLocalNodesMaintenance) c.log.Info(logs.FrostFSNodeStartedLocalNodesMaintenance)
} }
// stops node's maintenance. // stops node's maintenance.
func (c *internals) stopMaintenance(ctx context.Context) { func (c *internals) stopMaintenance() {
if c.isMaintenance.CompareAndSwap(true, false) { if c.isMaintenance.CompareAndSwap(true, false) {
c.log.Info(ctx, logs.FrostFSNodeStoppedLocalNodesMaintenance) c.log.Info(logs.FrostFSNodeStoppedLocalNodesMaintenance)
} }
} }
@ -705,7 +705,7 @@ func initCfg(appCfg *config.Config) *cfg {
log, err := logger.NewLogger(logPrm) log, err := logger.NewLogger(logPrm)
fatalOnErr(err) fatalOnErr(err)
if loggerconfig.ToLokiConfig(appCfg).Enabled { if loggerconfig.ToLokiConfig(appCfg).Enabled {
log.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { log.Logger = log.Logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg)) lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg))
return lokiCore return lokiCore
})) }))
@ -1089,7 +1089,7 @@ func (c *cfg) LocalAddress() network.AddressGroup {
func initLocalStorage(ctx context.Context, c *cfg) { func initLocalStorage(ctx context.Context, c *cfg) {
ls := engine.New(c.engineOpts()...) ls := engine.New(c.engineOpts()...)
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) { addNewEpochAsyncNotificationHandler(c, func(ev event.Event) {
ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber()) ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber())
}) })
@ -1103,10 +1103,10 @@ func initLocalStorage(ctx context.Context, c *cfg) {
shard.WithTombstoneSource(c.createTombstoneSource()), shard.WithTombstoneSource(c.createTombstoneSource()),
shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)))...) shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)))...)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) c.log.Error(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err))
} else { } else {
shardsAttached++ shardsAttached++
c.log.Info(ctx, logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id)) c.log.Info(logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id))
} }
} }
if shardsAttached == 0 { if shardsAttached == 0 {
@ -1116,23 +1116,23 @@ func initLocalStorage(ctx context.Context, c *cfg) {
c.cfgObject.cfgLocalStorage.localStorage = ls c.cfgObject.cfgLocalStorage.localStorage = ls
c.onShutdown(func() { c.onShutdown(func() {
c.log.Info(ctx, logs.FrostFSNodeClosingComponentsOfTheStorageEngine) c.log.Info(logs.FrostFSNodeClosingComponentsOfTheStorageEngine)
err := ls.Close(context.WithoutCancel(ctx)) err := ls.Close(context.WithoutCancel(ctx))
if err != nil { if err != nil {
c.log.Info(ctx, logs.FrostFSNodeStorageEngineClosingFailure, c.log.Info(logs.FrostFSNodeStorageEngineClosingFailure,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} else { } else {
c.log.Info(ctx, logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully) c.log.Info(logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully)
} }
}) })
} }
func initAccessPolicyEngine(ctx context.Context, c *cfg) { func initAccessPolicyEngine(_ context.Context, c *cfg) {
var localOverrideDB chainbase.LocalOverrideDatabase var localOverrideDB chainbase.LocalOverrideDatabase
if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" { if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" {
c.log.Warn(ctx, logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) c.log.Warn(logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed)
localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase() localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase()
} else { } else {
localOverrideDB = chainbase.NewBoltLocalOverrideDatabase( localOverrideDB = chainbase.NewBoltLocalOverrideDatabase(
@ -1157,7 +1157,7 @@ func initAccessPolicyEngine(ctx context.Context, c *cfg) {
c.onShutdown(func() { c.onShutdown(func() {
if err := ape.LocalOverrideDatabaseCore().Close(); err != nil { if err := ape.LocalOverrideDatabaseCore().Close(); err != nil {
c.log.Warn(ctx, logs.FrostFSNodeAccessPolicyEngineClosingFailure, c.log.Warn(logs.FrostFSNodeAccessPolicyEngineClosingFailure,
zap.Error(err), zap.Error(err),
) )
} }
@ -1206,10 +1206,10 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) {
c.cfgNetmap.state.setNodeInfo(ni) c.cfgNetmap.state.setNodeInfo(ni)
} }
func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) { func (c *cfg) updateContractNodeInfo(epoch uint64) {
ni, err := c.netmapLocalNodeState(epoch) ni, err := c.netmapLocalNodeState(epoch)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, c.log.Error(logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch,
zap.Uint64("epoch", epoch), zap.Uint64("epoch", epoch),
zap.String("error", err.Error())) zap.String("error", err.Error()))
return return
@ -1221,19 +1221,19 @@ func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) {
// bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract // bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract
// with the binary-encoded information from the current node's configuration. // with the binary-encoded information from the current node's configuration.
// The state is set using the provided setter which MUST NOT be nil. // The state is set using the provided setter which MUST NOT be nil.
func (c *cfg) bootstrapWithState(ctx context.Context, stateSetter func(*netmap.NodeInfo)) error { func (c *cfg) bootstrapWithState(stateSetter func(*netmap.NodeInfo)) error {
ni := c.cfgNodeInfo.localInfo ni := c.cfgNodeInfo.localInfo
stateSetter(&ni) stateSetter(&ni)
prm := nmClient.AddPeerPrm{} prm := nmClient.AddPeerPrm{}
prm.SetNodeInfo(ni) prm.SetNodeInfo(ni)
return c.cfgNetmap.wrapper.AddPeer(ctx, prm) return c.cfgNetmap.wrapper.AddPeer(prm)
} }
// bootstrapOnline calls cfg.bootstrapWithState with "online" state. // bootstrapOnline calls cfg.bootstrapWithState with "online" state.
func bootstrapOnline(ctx context.Context, c *cfg) error { func bootstrapOnline(c *cfg) error {
return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) { return c.bootstrapWithState(func(ni *netmap.NodeInfo) {
ni.SetStatus(netmap.Online) ni.SetStatus(netmap.Online)
}) })
} }
@ -1241,21 +1241,21 @@ func bootstrapOnline(ctx context.Context, c *cfg) error {
// bootstrap calls bootstrapWithState with: // bootstrap calls bootstrapWithState with:
// - "maintenance" state if maintenance is in progress on the current node // - "maintenance" state if maintenance is in progress on the current node
// - "online", otherwise // - "online", otherwise
func (c *cfg) bootstrap(ctx context.Context) error { func (c *cfg) bootstrap() error {
// switch to online except when under maintenance // switch to online except when under maintenance
st := c.cfgNetmap.state.controlNetmapStatus() st := c.cfgNetmap.state.controlNetmapStatus()
if st == control.NetmapStatus_MAINTENANCE { if st == control.NetmapStatus_MAINTENANCE {
c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithTheMaintenanceState) c.log.Info(logs.FrostFSNodeBootstrappingWithTheMaintenanceState)
return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) { return c.bootstrapWithState(func(ni *netmap.NodeInfo) {
ni.SetStatus(netmap.Maintenance) ni.SetStatus(netmap.Maintenance)
}) })
} }
c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithOnlineState, c.log.Info(logs.FrostFSNodeBootstrappingWithOnlineState,
zap.Stringer("previous", st), zap.Stringer("previous", st),
) )
return bootstrapOnline(ctx, c) return bootstrapOnline(c)
} }
// needBootstrap checks if local node should be registered in network on bootup. // needBootstrap checks if local node should be registered in network on bootup.
@ -1280,19 +1280,19 @@ func (c *cfg) signalWatcher(ctx context.Context) {
// signals causing application to shut down should have priority over // signals causing application to shut down should have priority over
// reconfiguration signal // reconfiguration signal
case <-ch: case <-ch:
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
c.shutdown(ctx) c.shutdown()
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-c.internalErr: // internal application error case err := <-c.internalErr: // internal application error
c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError, c.log.Warn(logs.FrostFSNodeInternalApplicationError,
zap.String("message", err.Error())) zap.String("message", err.Error()))
c.shutdown(ctx) c.shutdown()
c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete) c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete)
return return
default: default:
// block until any signal is receieved // block until any signal is receieved
@ -1300,19 +1300,19 @@ func (c *cfg) signalWatcher(ctx context.Context) {
case <-sighupCh: case <-sighupCh:
c.reloadConfig(ctx) c.reloadConfig(ctx)
case <-ch: case <-ch:
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
c.shutdown(ctx) c.shutdown()
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-c.internalErr: // internal application error case err := <-c.internalErr: // internal application error
c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError, c.log.Warn(logs.FrostFSNodeInternalApplicationError,
zap.String("message", err.Error())) zap.String("message", err.Error()))
c.shutdown(ctx) c.shutdown()
c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete) c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete)
return return
} }
} }
@ -1320,17 +1320,17 @@ func (c *cfg) signalWatcher(ctx context.Context) {
} }
func (c *cfg) reloadConfig(ctx context.Context) { func (c *cfg) reloadConfig(ctx context.Context) {
c.log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) c.log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
if !c.compareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { if !c.compareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
c.log.Info(ctx, logs.FrostFSNodeSIGHUPSkip) c.log.Info(logs.FrostFSNodeSIGHUPSkip)
return return
} }
defer c.compareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
err := c.reloadAppConfig() err := c.reloadAppConfig()
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) c.log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
return return
} }
@ -1341,7 +1341,7 @@ func (c *cfg) reloadConfig(ctx context.Context) {
logPrm, err := c.loggerPrm() logPrm, err := c.loggerPrm()
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err)) c.log.Error(logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err))
return return
} }
@ -1362,25 +1362,25 @@ func (c *cfg) reloadConfig(ctx context.Context) {
err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg) err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err)) c.log.Error(logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err))
return return
} }
for _, component := range components { for _, component := range components {
err = component.reloadFunc() err = component.reloadFunc()
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeUpdatedConfigurationApplying, c.log.Error(logs.FrostFSNodeUpdatedConfigurationApplying,
zap.String("component", component.name), zap.String("component", component.name),
zap.Error(err)) zap.Error(err))
} }
} }
if err := c.dialerSource.Update(internalNetConfig(c.appCfg, c.metricsCollector.MultinetMetrics())); err != nil { if err := c.dialerSource.Update(internalNetConfig(c.appCfg, c.metricsCollector.MultinetMetrics())); err != nil {
c.log.Error(ctx, logs.FailedToUpdateMultinetConfiguration, zap.Error(err)) c.log.Error(logs.FailedToUpdateMultinetConfiguration, zap.Error(err))
return return
} }
c.log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
} }
func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
@ -1388,7 +1388,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
components = append(components, dCmp{"logger", logPrm.Reload}) components = append(components, dCmp{"logger", logPrm.Reload})
components = append(components, dCmp{"runtime", func() error { components = append(components, dCmp{"runtime", func() error {
setRuntimeParameters(ctx, c) setRuntimeParameters(c)
return nil return nil
}}) }})
components = append(components, dCmp{"audit", func() error { components = append(components, dCmp{"audit", func() error {
@ -1403,7 +1403,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
} }
updated, err := tracing.Setup(ctx, *traceConfig) updated, err := tracing.Setup(ctx, *traceConfig)
if updated { if updated {
c.log.Info(ctx, logs.FrostFSNodeTracingConfigationUpdated) c.log.Info(logs.FrostFSNodeTracingConfigationUpdated)
} }
return err return err
}}) }})
@ -1438,7 +1438,7 @@ func (c *cfg) reloadPools() error {
func (c *cfg) reloadPool(p *ants.Pool, newSize int, name string) { func (c *cfg) reloadPool(p *ants.Pool, newSize int, name string) {
oldSize := p.Cap() oldSize := p.Cap()
if oldSize != newSize { if oldSize != newSize {
c.log.Info(context.Background(), logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name), c.log.Info(logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name),
zap.Int("old", oldSize), zap.Int("new", newSize)) zap.Int("old", oldSize), zap.Int("new", newSize))
p.Tune(newSize) p.Tune(newSize)
} }
@ -1474,14 +1474,14 @@ func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoPro
}) })
} }
func (c *cfg) shutdown(ctx context.Context) { func (c *cfg) shutdown() {
old := c.swapHealthStatus(ctx, control.HealthStatus_SHUTTING_DOWN) old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN)
if old == control.HealthStatus_SHUTTING_DOWN { if old == control.HealthStatus_SHUTTING_DOWN {
c.log.Info(ctx, logs.FrostFSNodeShutdownSkip) c.log.Info(logs.FrostFSNodeShutdownSkip)
return return
} }
if old == control.HealthStatus_STARTING { if old == control.HealthStatus_STARTING {
c.log.Warn(ctx, logs.FrostFSNodeShutdownWhenNotReady) c.log.Warn(logs.FrostFSNodeShutdownWhenNotReady)
} }
c.ctxCancel() c.ctxCancel()
@ -1491,6 +1491,6 @@ func (c *cfg) shutdown(ctx context.Context) {
} }
if err := sdnotify.ClearStatus(); err != nil { if err := sdnotify.ClearStatus(); err != nil {
c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err))
} }
} }

View file

@ -89,7 +89,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
if c.cfgMorph.containerCacheSize > 0 { if c.cfgMorph.containerCacheSize > 0 {
containerCache := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL, c.cfgMorph.containerCacheSize) containerCache := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL, c.cfgMorph.containerCacheSize)
subscribeToContainerCreation(c, func(ctx context.Context, e event.Event) { subscribeToContainerCreation(c, func(e event.Event) {
ev := e.(containerEvent.PutSuccess) ev := e.(containerEvent.PutSuccess)
// read owner of the created container in order to update the reading cache. // read owner of the created container in order to update the reading cache.
@ -102,21 +102,21 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
} else { } else {
// unlike removal, we expect successful receive of the container // unlike removal, we expect successful receive of the container
// after successful creation, so logging can be useful // after successful creation, so logging can be useful
c.log.Error(ctx, logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, c.log.Error(logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification,
zap.Stringer("id", ev.ID), zap.Stringer("id", ev.ID),
zap.Error(err), zap.Error(err),
) )
} }
c.log.Debug(ctx, logs.FrostFSNodeContainerCreationEventsReceipt, c.log.Debug(logs.FrostFSNodeContainerCreationEventsReceipt,
zap.Stringer("id", ev.ID), zap.Stringer("id", ev.ID),
) )
}) })
subscribeToContainerRemoval(c, func(ctx context.Context, e event.Event) { subscribeToContainerRemoval(c, func(e event.Event) {
ev := e.(containerEvent.DeleteSuccess) ev := e.(containerEvent.DeleteSuccess)
containerCache.handleRemoval(ev.ID) containerCache.handleRemoval(ev.ID)
c.log.Debug(ctx, logs.FrostFSNodeContainerRemovalEventsReceipt, c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt,
zap.Stringer("id", ev.ID), zap.Stringer("id", ev.ID),
) )
}) })
@ -237,10 +237,10 @@ type morphContainerWriter struct {
neoClient *cntClient.Client neoClient *cntClient.Client
} }
func (m morphContainerWriter) Put(ctx context.Context, cnr containerCore.Container) (*cid.ID, error) { func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) {
return cntClient.Put(ctx, m.neoClient, cnr) return cntClient.Put(m.neoClient, cnr)
} }
func (m morphContainerWriter) Delete(ctx context.Context, witness containerCore.RemovalWitness) error { func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
return cntClient.Delete(ctx, m.neoClient, witness) return cntClient.Delete(m.neoClient, witness)
} }

View file

@ -16,7 +16,7 @@ import (
const serviceNameControl = "control" const serviceNameControl = "control"
func initControlService(ctx context.Context, c *cfg) { func initControlService(c *cfg) {
endpoint := controlconfig.GRPC(c.appCfg).Endpoint() endpoint := controlconfig.GRPC(c.appCfg).Endpoint()
if endpoint == controlconfig.GRPCEndpointDefault { if endpoint == controlconfig.GRPCEndpointDefault {
return return
@ -46,21 +46,21 @@ func initControlService(ctx context.Context, c *cfg) {
lis, err := net.Listen("tcp", endpoint) lis, err := net.Listen("tcp", endpoint)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err)) c.log.Error(logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err))
return return
} }
c.cfgControlService.server = grpc.NewServer() c.cfgControlService.server = grpc.NewServer()
c.onShutdown(func() { c.onShutdown(func() {
stopGRPC(ctx, "FrostFS Control API", c.cfgControlService.server, c.log) stopGRPC("FrostFS Control API", c.cfgControlService.server, c.log)
}) })
control.RegisterControlServiceServer(c.cfgControlService.server, ctlSvc) control.RegisterControlServiceServer(c.cfgControlService.server, ctlSvc)
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
runAndLog(ctx, c, serviceNameControl, false, func(context.Context, *cfg) { runAndLog(ctx, c, serviceNameControl, false, func(context.Context, *cfg) {
c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint, c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
zap.String("service", serviceNameControl), zap.String("service", serviceNameControl),
zap.String("endpoint", endpoint)) zap.String("endpoint", endpoint))
fatalOnErr(c.cfgControlService.server.Serve(lis)) fatalOnErr(c.cfgControlService.server.Serve(lis))
@ -72,23 +72,23 @@ func (c *cfg) NetmapStatus() control.NetmapStatus {
return c.cfgNetmap.state.controlNetmapStatus() return c.cfgNetmap.state.controlNetmapStatus()
} }
func (c *cfg) setHealthStatus(ctx context.Context, st control.HealthStatus) { func (c *cfg) setHealthStatus(st control.HealthStatus) {
c.notifySystemd(ctx, st) c.notifySystemd(st)
c.healthStatus.Store(int32(st)) c.healthStatus.Store(int32(st))
c.metricsCollector.State().SetHealth(int32(st)) c.metricsCollector.State().SetHealth(int32(st))
} }
func (c *cfg) compareAndSwapHealthStatus(ctx context.Context, oldSt, newSt control.HealthStatus) (swapped bool) { func (c *cfg) compareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) {
if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped { if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped {
c.notifySystemd(ctx, newSt) c.notifySystemd(newSt)
c.metricsCollector.State().SetHealth(int32(newSt)) c.metricsCollector.State().SetHealth(int32(newSt))
} }
return return
} }
func (c *cfg) swapHealthStatus(ctx context.Context, st control.HealthStatus) (old control.HealthStatus) { func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatus) {
old = control.HealthStatus(c.healthStatus.Swap(int32(st))) old = control.HealthStatus(c.healthStatus.Swap(int32(st)))
c.notifySystemd(ctx, st) c.notifySystemd(st)
c.metricsCollector.State().SetHealth(int32(st)) c.metricsCollector.State().SetHealth(int32(st))
return return
} }
@ -97,7 +97,7 @@ func (c *cfg) HealthStatus() control.HealthStatus {
return control.HealthStatus(c.healthStatus.Load()) return control.HealthStatus(c.healthStatus.Load())
} }
func (c *cfg) notifySystemd(ctx context.Context, st control.HealthStatus) { func (c *cfg) notifySystemd(st control.HealthStatus) {
if !c.sdNotify { if !c.sdNotify {
return return
} }
@ -113,6 +113,6 @@ func (c *cfg) notifySystemd(ctx context.Context, st control.HealthStatus) {
err = sdnotify.Status(fmt.Sprintf("%v", st)) err = sdnotify.Status(fmt.Sprintf("%v", st))
} }
if err != nil { if err != nil {
c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err))
} }
} }

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"net" "net"
@ -19,11 +18,11 @@ import (
const maxRecvMsgSize = 256 << 20 const maxRecvMsgSize = 256 << 20
func initGRPC(ctx context.Context, c *cfg) { func initGRPC(c *cfg) {
var endpointsToReconnect []string var endpointsToReconnect []string
var successCount int var successCount int
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
serverOpts, ok := getGrpcServerOpts(ctx, c, sc) serverOpts, ok := getGrpcServerOpts(c, sc)
if !ok { if !ok {
return return
} }
@ -31,7 +30,7 @@ func initGRPC(ctx context.Context, c *cfg) {
lis, err := net.Listen("tcp", sc.Endpoint()) lis, err := net.Listen("tcp", sc.Endpoint())
if err != nil { if err != nil {
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint()) c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint())
c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err))
endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint()) endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint())
return return
} }
@ -40,7 +39,7 @@ func initGRPC(ctx context.Context, c *cfg) {
srv := grpc.NewServer(serverOpts...) srv := grpc.NewServer(serverOpts...)
c.onShutdown(func() { c.onShutdown(func() {
stopGRPC(ctx, "FrostFS Public API", srv, c.log) stopGRPC("FrostFS Public API", srv, c.log)
}) })
c.cfgGRPC.append(sc.Endpoint(), lis, srv) c.cfgGRPC.append(sc.Endpoint(), lis, srv)
@ -53,11 +52,11 @@ func initGRPC(ctx context.Context, c *cfg) {
c.cfgGRPC.reconnectTimeout = grpcconfig.ReconnectTimeout(c.appCfg) c.cfgGRPC.reconnectTimeout = grpcconfig.ReconnectTimeout(c.appCfg)
for _, endpoint := range endpointsToReconnect { for _, endpoint := range endpointsToReconnect {
scheduleReconnect(ctx, endpoint, c) scheduleReconnect(endpoint, c)
} }
} }
func scheduleReconnect(ctx context.Context, endpoint string, c *cfg) { func scheduleReconnect(endpoint string, c *cfg) {
c.wg.Add(1) c.wg.Add(1)
go func() { go func() {
defer c.wg.Done() defer c.wg.Done()
@ -66,7 +65,7 @@ func scheduleReconnect(ctx context.Context, endpoint string, c *cfg) {
for { for {
select { select {
case <-t.C: case <-t.C:
if tryReconnect(ctx, endpoint, c) { if tryReconnect(endpoint, c) {
return return
} }
case <-c.done: case <-c.done:
@ -76,20 +75,20 @@ func scheduleReconnect(ctx context.Context, endpoint string, c *cfg) {
}() }()
} }
func tryReconnect(ctx context.Context, endpoint string, c *cfg) bool { func tryReconnect(endpoint string, c *cfg) bool {
c.log.Info(ctx, logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) c.log.Info(logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint))
serverOpts, found := getGRPCEndpointOpts(ctx, endpoint, c) serverOpts, found := getGRPCEndpointOpts(endpoint, c)
if !found { if !found {
c.log.Warn(ctx, logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) c.log.Warn(logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint))
return true return true
} }
lis, err := net.Listen("tcp", endpoint) lis, err := net.Listen("tcp", endpoint)
if err != nil { if err != nil {
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint) c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint)
c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err))
c.log.Warn(ctx, logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout)) c.log.Warn(logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout))
return false return false
} }
c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint) c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint)
@ -97,16 +96,16 @@ func tryReconnect(ctx context.Context, endpoint string, c *cfg) bool {
srv := grpc.NewServer(serverOpts...) srv := grpc.NewServer(serverOpts...)
c.onShutdown(func() { c.onShutdown(func() {
stopGRPC(ctx, "FrostFS Public API", srv, c.log) stopGRPC("FrostFS Public API", srv, c.log)
}) })
c.cfgGRPC.appendAndHandle(endpoint, lis, srv) c.cfgGRPC.appendAndHandle(endpoint, lis, srv)
c.log.Info(ctx, logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) c.log.Info(logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint))
return true return true
} }
func getGRPCEndpointOpts(ctx context.Context, endpoint string, c *cfg) (result []grpc.ServerOption, found bool) { func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, found bool) {
unlock := c.LockAppConfigShared() unlock := c.LockAppConfigShared()
defer unlock() defer unlock()
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
@ -117,7 +116,7 @@ func getGRPCEndpointOpts(ctx context.Context, endpoint string, c *cfg) (result [
return return
} }
var ok bool var ok bool
result, ok = getGrpcServerOpts(ctx, c, sc) result, ok = getGrpcServerOpts(c, sc)
if !ok { if !ok {
return return
} }
@ -126,7 +125,7 @@ func getGRPCEndpointOpts(ctx context.Context, endpoint string, c *cfg) (result [
return return
} }
func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) { func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) {
serverOpts := []grpc.ServerOption{ serverOpts := []grpc.ServerOption{
grpc.MaxRecvMsgSize(maxRecvMsgSize), grpc.MaxRecvMsgSize(maxRecvMsgSize),
grpc.ChainUnaryInterceptor( grpc.ChainUnaryInterceptor(
@ -144,7 +143,7 @@ func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]gr
if tlsCfg != nil { if tlsCfg != nil {
cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile()) cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile())
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) c.log.Error(logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err))
return nil, false return nil, false
} }
@ -175,38 +174,38 @@ func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]gr
return serverOpts, true return serverOpts, true
} }
func serveGRPC(ctx context.Context, c *cfg) { func serveGRPC(c *cfg) {
c.cfgGRPC.performAndSave(func(e string, l net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(e string, l net.Listener, s *grpc.Server) {
c.wg.Add(1) c.wg.Add(1)
go func() { go func() {
defer func() { defer func() {
c.log.Info(ctx, logs.FrostFSNodeStopListeningGRPCEndpoint, c.log.Info(logs.FrostFSNodeStopListeningGRPCEndpoint,
zap.Stringer("endpoint", l.Addr()), zap.Stringer("endpoint", l.Addr()),
) )
c.wg.Done() c.wg.Done()
}() }()
c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint, c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
zap.String("service", "gRPC"), zap.String("service", "gRPC"),
zap.Stringer("endpoint", l.Addr()), zap.Stringer("endpoint", l.Addr()),
) )
if err := s.Serve(l); err != nil { if err := s.Serve(l); err != nil {
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e) c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e)
c.log.Error(ctx, logs.FrostFSNodeGRPCServerError, zap.Error(err)) c.log.Error(logs.FrostFSNodeGRPCServerError, zap.Error(err))
c.cfgGRPC.dropConnection(e) c.cfgGRPC.dropConnection(e)
scheduleReconnect(ctx, e, c) scheduleReconnect(e, c)
} }
}() }()
}) })
} }
func stopGRPC(ctx context.Context, name string, s *grpc.Server, l *logger.Logger) { func stopGRPC(name string, s *grpc.Server, l *logger.Logger) {
l = l.With(zap.String("name", name)) l = &logger.Logger{Logger: l.With(zap.String("name", name))}
l.Info(ctx, logs.FrostFSNodeStoppingGRPCServer) l.Info(logs.FrostFSNodeStoppingGRPCServer)
// GracefulStop() may freeze forever, see #1270 // GracefulStop() may freeze forever, see #1270
done := make(chan struct{}) done := make(chan struct{})
@ -218,9 +217,9 @@ func stopGRPC(ctx context.Context, name string, s *grpc.Server, l *logger.Logger
select { select {
case <-done: case <-done:
case <-time.After(1 * time.Minute): case <-time.After(1 * time.Minute):
l.Info(ctx, logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop) l.Info(logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop)
s.Stop() s.Stop()
} }
l.Info(ctx, logs.FrostFSNodeGRPCServerStoppedSuccessfully) l.Info(logs.FrostFSNodeGRPCServerStoppedSuccessfully)
} }

View file

@ -20,9 +20,9 @@ type httpComponent struct {
preReload func(c *cfg) preReload func(c *cfg)
} }
func (cmp *httpComponent) init(ctx context.Context, c *cfg) { func (cmp *httpComponent) init(c *cfg) {
if !cmp.enabled { if !cmp.enabled {
c.log.Info(ctx, cmp.name+" is disabled") c.log.Info(cmp.name + " is disabled")
return return
} }
// Init server with parameters // Init server with parameters
@ -39,14 +39,14 @@ func (cmp *httpComponent) init(ctx context.Context, c *cfg) {
go func() { go func() {
defer c.wg.Done() defer c.wg.Done()
c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint, c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
zap.String("service", cmp.name), zap.String("service", cmp.name),
zap.String("endpoint", cmp.address)) zap.String("endpoint", cmp.address))
fatalOnErr(srv.Serve()) fatalOnErr(srv.Serve())
}() }()
c.closers = append(c.closers, closer{ c.closers = append(c.closers, closer{
cmp.name, cmp.name,
func() { stopAndLog(ctx, c, cmp.name, srv.Shutdown) }, func() { stopAndLog(c, cmp.name, srv.Shutdown) },
}) })
} }
@ -62,7 +62,7 @@ func (cmp *httpComponent) reload(ctx context.Context) error {
// Cleanup // Cleanup
delCloser(cmp.cfg, cmp.name) delCloser(cmp.cfg, cmp.name)
// Init server with new parameters // Init server with new parameters
cmp.init(ctx, cmp.cfg) cmp.init(cmp.cfg)
// Start worker // Start worker
if cmp.enabled { if cmp.enabled {
startWorker(ctx, cmp.cfg, *getWorker(cmp.cfg, cmp.name)) startWorker(ctx, cmp.cfg, *getWorker(cmp.cfg, cmp.name))

View file

@ -61,21 +61,21 @@ func main() {
var ctx context.Context var ctx context.Context
ctx, c.ctxCancel = context.WithCancel(context.Background()) ctx, c.ctxCancel = context.WithCancel(context.Background())
c.setHealthStatus(ctx, control.HealthStatus_STARTING) c.setHealthStatus(control.HealthStatus_STARTING)
initApp(ctx, c) initApp(ctx, c)
bootUp(ctx, c) bootUp(ctx, c)
c.compareAndSwapHealthStatus(ctx, control.HealthStatus_STARTING, control.HealthStatus_READY) c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY)
wait(c) wait(c)
} }
func initAndLog(ctx context.Context, c *cfg, name string, initializer func(*cfg)) { func initAndLog(c *cfg, name string, initializer func(*cfg)) {
c.log.Info(ctx, fmt.Sprintf("initializing %s service...", name)) c.log.Info(fmt.Sprintf("initializing %s service...", name))
initializer(c) initializer(c)
c.log.Info(ctx, name+" service has been successfully initialized") c.log.Info(name + " service has been successfully initialized")
} }
func initApp(ctx context.Context, c *cfg) { func initApp(ctx context.Context, c *cfg) {
@ -85,72 +85,72 @@ func initApp(ctx context.Context, c *cfg) {
c.wg.Done() c.wg.Done()
}() }()
setRuntimeParameters(ctx, c) setRuntimeParameters(c)
metrics, _ := metricsComponent(c) metrics, _ := metricsComponent(c)
initAndLog(ctx, c, "profiler", func(c *cfg) { initProfilerService(ctx, c) }) initAndLog(c, "profiler", initProfilerService)
initAndLog(ctx, c, metrics.name, func(c *cfg) { metrics.init(ctx, c) }) initAndLog(c, metrics.name, metrics.init)
initAndLog(ctx, c, "tracing", func(c *cfg) { initTracing(ctx, c) }) initAndLog(c, "tracing", func(c *cfg) { initTracing(ctx, c) })
initLocalStorage(ctx, c) initLocalStorage(ctx, c)
initAndLog(ctx, c, "storage engine", func(c *cfg) { initAndLog(c, "storage engine", func(c *cfg) {
fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open(ctx)) fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open(ctx))
fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx)) fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx))
}) })
initAndLog(ctx, c, "gRPC", func(c *cfg) { initGRPC(ctx, c) }) initAndLog(c, "gRPC", initGRPC)
initAndLog(ctx, c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) })
initAccessPolicyEngine(ctx, c) initAccessPolicyEngine(ctx, c)
initAndLog(ctx, c, "access policy engine", func(c *cfg) { initAndLog(c, "access policy engine", func(c *cfg) {
fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx)) fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx))
fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init()) fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init())
}) })
initAndLog(ctx, c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) initAndLog(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) })
initAndLog(ctx, c, "container", func(c *cfg) { initContainerService(ctx, c) }) initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) })
initAndLog(ctx, c, "session", initSessionService) initAndLog(c, "session", initSessionService)
initAndLog(ctx, c, "object", initObjectService) initAndLog(c, "object", initObjectService)
initAndLog(ctx, c, "tree", initTreeService) initAndLog(c, "tree", initTreeService)
initAndLog(ctx, c, "apemanager", initAPEManagerService) initAndLog(c, "apemanager", initAPEManagerService)
initAndLog(ctx, c, "control", func(c *cfg) { initControlService(ctx, c) }) initAndLog(c, "control", initControlService)
initAndLog(ctx, c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) }) initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) })
} }
func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starter func(context.Context, *cfg)) { func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starter func(context.Context, *cfg)) {
c.log.Info(ctx, fmt.Sprintf("starting %s service...", name)) c.log.Info(fmt.Sprintf("starting %s service...", name))
starter(ctx, c) starter(ctx, c)
if logSuccess { if logSuccess {
c.log.Info(ctx, name+" service started successfully") c.log.Info(name + " service started successfully")
} }
} }
func stopAndLog(ctx context.Context, c *cfg, name string, stopper func(context.Context) error) { func stopAndLog(c *cfg, name string, stopper func() error) {
c.log.Debug(ctx, fmt.Sprintf("shutting down %s service", name)) c.log.Debug(fmt.Sprintf("shutting down %s service", name))
err := stopper(ctx) err := stopper()
if err != nil { if err != nil {
c.log.Debug(ctx, fmt.Sprintf("could not shutdown %s server", name), c.log.Debug(fmt.Sprintf("could not shutdown %s server", name),
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
c.log.Debug(ctx, name+" service has been stopped") c.log.Debug(name + " service has been stopped")
} }
func bootUp(ctx context.Context, c *cfg) { func bootUp(ctx context.Context, c *cfg) {
runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(ctx, c) }) runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(c) })
runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit)
bootstrapNode(ctx, c) bootstrapNode(c)
startWorkers(ctx, c) startWorkers(ctx, c)
} }
func wait(c *cfg) { func wait(c *cfg) {
c.log.Info(context.Background(), logs.CommonApplicationStarted, c.log.Info(logs.CommonApplicationStarted,
zap.String("version", misc.Version)) zap.String("version", misc.Version))
<-c.done // graceful shutdown <-c.done // graceful shutdown
@ -160,12 +160,12 @@ func wait(c *cfg) {
go func() { go func() {
defer drain.Done() defer drain.Done()
for err := range c.internalErr { for err := range c.internalErr {
c.log.Warn(context.Background(), logs.FrostFSNodeInternalApplicationError, c.log.Warn(logs.FrostFSNodeInternalApplicationError,
zap.String("message", err.Error())) zap.String("message", err.Error()))
} }
}() }()
c.log.Debug(context.Background(), logs.FrostFSNodeWaitingForAllProcessesToStop) c.log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop)
c.wg.Wait() c.wg.Wait()

View file

@ -17,7 +17,11 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand"
"github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -44,7 +48,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) {
fatalOnErr(err) fatalOnErr(err)
} }
c.log.Info(ctx, logs.FrostFSNodeNotarySupport, c.log.Info(logs.FrostFSNodeNotarySupport,
zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled),
) )
@ -60,7 +64,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) {
msPerBlock, err := c.cfgMorph.client.MsPerBlock() msPerBlock, err := c.cfgMorph.client.MsPerBlock()
fatalOnErr(err) fatalOnErr(err)
c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond
c.log.Debug(ctx, logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL)) c.log.Debug(logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL))
} }
if c.cfgMorph.cacheTTL < 0 { if c.cfgMorph.cacheTTL < 0 {
@ -98,7 +102,7 @@ func initMorphClient(ctx context.Context, c *cfg) {
client.WithDialerSource(c.dialerSource), client.WithDialerSource(c.dialerSource),
) )
if err != nil { if err != nil {
c.log.Info(ctx, logs.FrostFSNodeFailedToCreateNeoRPCClient, c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient,
zap.Any("endpoints", addresses), zap.Any("endpoints", addresses),
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -107,12 +111,12 @@ func initMorphClient(ctx context.Context, c *cfg) {
} }
c.onShutdown(func() { c.onShutdown(func() {
c.log.Info(ctx, logs.FrostFSNodeClosingMorphComponents) c.log.Info(logs.FrostFSNodeClosingMorphComponents)
cli.Close() cli.Close()
}) })
if err := cli.SetGroupSignerScope(); err != nil { if err := cli.SetGroupSignerScope(); err != nil {
c.log.Info(ctx, logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err)) c.log.Info(logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err))
} }
c.cfgMorph.client = cli c.cfgMorph.client = cli
@ -125,14 +129,14 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
return return
} }
tx, vub, err := makeNotaryDeposit(ctx, c) tx, vub, err := makeNotaryDeposit(c)
fatalOnErr(err) fatalOnErr(err)
if tx.Equals(util.Uint256{}) { if tx.Equals(util.Uint256{}) {
// non-error deposit with an empty TX hash means // non-error deposit with an empty TX hash means
// that the deposit has already been made; no // that the deposit has already been made; no
// need to wait it. // need to wait it.
c.log.Info(ctx, logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade) c.log.Info(logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade)
return return
} }
@ -140,7 +144,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
fatalOnErr(err) fatalOnErr(err)
} }
func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error) { func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) {
const ( const (
// gasMultiplier defines how many times more the notary // gasMultiplier defines how many times more the notary
// balance must be compared to the GAS balance of the node: // balance must be compared to the GAS balance of the node:
@ -157,16 +161,51 @@ func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error
return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err) return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err)
} }
return c.cfgMorph.client.DepositEndlessNotary(ctx, depositAmount) return c.cfgMorph.client.DepositEndlessNotary(depositAmount)
}
var (
errNotaryDepositFail = errors.New("notary deposit tx has faulted")
errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network")
)
type waiterClient struct {
c *client.Client
}
func (w *waiterClient) Context() context.Context {
return context.Background()
}
func (w *waiterClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) {
return w.c.GetApplicationLog(hash, trig)
}
func (w *waiterClient) GetBlockCount() (uint32, error) {
return w.c.BlockCount()
}
func (w *waiterClient) GetVersion() (*result.Version, error) {
return w.c.GetVersion()
} }
func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error {
if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil { w, err := waiter.NewPollingBased(&waiterClient{c: c.cfgMorph.client})
return err if err != nil {
return fmt.Errorf("could not create notary deposit waiter: %w", err)
} }
res, err := w.WaitAny(ctx, vub, tx)
c.log.Info(ctx, logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) if err != nil {
return nil if errors.Is(err, waiter.ErrTxNotAccepted) {
return errNotaryDepositTimeout
}
return fmt.Errorf("could not wait for notary deposit persists in chain: %w", err)
}
if res.Execution.VMState.HasFlag(vmstate.Halt) {
c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted)
return nil
}
return errNotaryDepositFail
} }
func listenMorphNotifications(ctx context.Context, c *cfg) { func listenMorphNotifications(ctx context.Context, c *cfg) {
@ -178,7 +217,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey) fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey)
if err != nil { if err != nil {
fromSideChainBlock = 0 fromSideChainBlock = 0
c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) c.log.Warn(logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
} }
subs, err = subscriber.New(ctx, &subscriber.Params{ subs, err = subscriber.New(ctx, &subscriber.Params{
@ -207,7 +246,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
setNetmapNotificationParser(c, newEpochNotification, func(src *state.ContainedNotificationEvent) (event.Event, error) { setNetmapNotificationParser(c, newEpochNotification, func(src *state.ContainedNotificationEvent) (event.Event, error) {
res, err := netmapEvent.ParseNewEpoch(src) res, err := netmapEvent.ParseNewEpoch(src)
if err == nil { if err == nil {
c.log.Info(ctx, logs.FrostFSNodeNewEpochEventFromSidechain, c.log.Info(logs.FrostFSNodeNewEpochEventFromSidechain,
zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()), zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()),
) )
} }
@ -217,12 +256,12 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
registerNotificationHandlers(c.cfgNetmap.scriptHash, lis, c.cfgNetmap.parsers, c.cfgNetmap.subscribers) registerNotificationHandlers(c.cfgNetmap.scriptHash, lis, c.cfgNetmap.parsers, c.cfgNetmap.subscribers)
registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers) registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers)
registerBlockHandler(lis, func(ctx context.Context, block *block.Block) { registerBlockHandler(lis, func(block *block.Block) {
c.log.Debug(ctx, logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) c.log.Debug(logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index))
err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index) err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index)
if err != nil { if err != nil {
c.log.Warn(ctx, logs.FrostFSNodeCantUpdatePersistentState, c.log.Warn(logs.FrostFSNodeCantUpdatePersistentState,
zap.String("chain", "side"), zap.String("chain", "side"),
zap.Uint32("block_index", block.Index)) zap.Uint32("block_index", block.Index))
} }

View file

@ -145,7 +145,7 @@ func initNetmapService(ctx context.Context, c *cfg) {
c.initMorphComponents(ctx) c.initMorphComponents(ctx)
initNetmapState(ctx, c) initNetmapState(c)
server := netmapTransportGRPC.New( server := netmapTransportGRPC.New(
netmapService.NewSignService( netmapService.NewSignService(
@ -175,29 +175,29 @@ func initNetmapService(ctx context.Context, c *cfg) {
} }
func addNewEpochNotificationHandlers(c *cfg) { func addNewEpochNotificationHandlers(c *cfg) {
addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) { addNewEpochNotificationHandler(c, func(ev event.Event) {
c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber()) c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber())
}) })
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) { addNewEpochAsyncNotificationHandler(c, func(ev event.Event) {
e := ev.(netmapEvent.NewEpoch).EpochNumber() e := ev.(netmapEvent.NewEpoch).EpochNumber()
c.updateContractNodeInfo(ctx, e) c.updateContractNodeInfo(e)
if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470 if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470
return return
} }
if err := c.bootstrap(ctx); err != nil { if err := c.bootstrap(); err != nil {
c.log.Warn(ctx, logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) c.log.Warn(logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err))
} }
}) })
if c.cfgMorph.notaryEnabled { if c.cfgMorph.notaryEnabled {
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) { addNewEpochAsyncNotificationHandler(c, func(_ event.Event) {
_, _, err := makeNotaryDeposit(ctx, c) _, _, err := makeNotaryDeposit(c)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit, c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
@ -207,13 +207,13 @@ func addNewEpochNotificationHandlers(c *cfg) {
// bootstrapNode adds current node to the Network map. // bootstrapNode adds current node to the Network map.
// Must be called after initNetmapService. // Must be called after initNetmapService.
func bootstrapNode(ctx context.Context, c *cfg) { func bootstrapNode(c *cfg) {
if c.needBootstrap() { if c.needBootstrap() {
if c.IsMaintenance() { if c.IsMaintenance() {
c.log.Info(ctx, logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) c.log.Info(logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap)
return return
} }
err := c.bootstrap(ctx) err := c.bootstrap()
fatalOnErrDetails("bootstrap error", err) fatalOnErrDetails("bootstrap error", err)
} }
} }
@ -240,17 +240,17 @@ func setNetmapNotificationParser(c *cfg, sTyp string, p event.NotificationParser
// initNetmapState inits current Network map state. // initNetmapState inits current Network map state.
// Must be called after Morph components initialization. // Must be called after Morph components initialization.
func initNetmapState(ctx context.Context, c *cfg) { func initNetmapState(c *cfg) {
epoch, err := c.cfgNetmap.wrapper.Epoch() epoch, err := c.cfgNetmap.wrapper.Epoch()
fatalOnErrDetails("could not initialize current epoch number", err) fatalOnErrDetails("could not initialize current epoch number", err)
var ni *netmapSDK.NodeInfo var ni *netmapSDK.NodeInfo
ni, err = c.netmapInitLocalNodeState(ctx, epoch) ni, err = c.netmapInitLocalNodeState(epoch)
fatalOnErrDetails("could not init network state", err) fatalOnErrDetails("could not init network state", err)
stateWord := nodeState(ni) stateWord := nodeState(ni)
c.log.Info(ctx, logs.FrostFSNodeInitialNetworkState, c.log.Info(logs.FrostFSNodeInitialNetworkState,
zap.Uint64("epoch", epoch), zap.Uint64("epoch", epoch),
zap.String("state", stateWord), zap.String("state", stateWord),
) )
@ -279,7 +279,7 @@ func nodeState(ni *netmapSDK.NodeInfo) string {
return "undefined" return "undefined"
} }
func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netmapSDK.NodeInfo, error) { func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) {
nmNodes, err := c.cfgNetmap.wrapper.GetCandidates() nmNodes, err := c.cfgNetmap.wrapper.GetCandidates()
if err != nil { if err != nil {
return nil, err return nil, err
@ -307,7 +307,7 @@ func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netm
if nmState != candidateState { if nmState != candidateState {
// This happens when the node was switched to maintenance without epoch tick. // This happens when the node was switched to maintenance without epoch tick.
// We expect it to continue staying in maintenance. // We expect it to continue staying in maintenance.
c.log.Info(ctx, logs.CandidateStatusPriority, c.log.Info(logs.CandidateStatusPriority,
zap.String("netmap", nmState), zap.String("netmap", nmState),
zap.String("candidate", candidateState)) zap.String("candidate", candidateState))
} }
@ -353,16 +353,16 @@ func addNewEpochAsyncNotificationHandler(c *cfg, h event.Handler) {
var errRelayBootstrap = errors.New("setting netmap status is forbidden in relay mode") var errRelayBootstrap = errors.New("setting netmap status is forbidden in relay mode")
func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) error { func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error {
switch st { switch st {
default: default:
return fmt.Errorf("unsupported status %v", st) return fmt.Errorf("unsupported status %v", st)
case control.NetmapStatus_MAINTENANCE: case control.NetmapStatus_MAINTENANCE:
return c.setMaintenanceStatus(ctx, false) return c.setMaintenanceStatus(false)
case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE: case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE:
} }
c.stopMaintenance(ctx) c.stopMaintenance()
if !c.needBootstrap() { if !c.needBootstrap() {
return errRelayBootstrap return errRelayBootstrap
@ -370,12 +370,12 @@ func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) erro
if st == control.NetmapStatus_ONLINE { if st == control.NetmapStatus_ONLINE {
c.cfgNetmap.reBoostrapTurnedOff.Store(false) c.cfgNetmap.reBoostrapTurnedOff.Store(false)
return bootstrapOnline(ctx, c) return bootstrapOnline(c)
} }
c.cfgNetmap.reBoostrapTurnedOff.Store(true) c.cfgNetmap.reBoostrapTurnedOff.Store(true)
return c.updateNetMapState(ctx, func(*nmClient.UpdatePeerPrm) {}) return c.updateNetMapState(func(*nmClient.UpdatePeerPrm) {})
} }
func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) { func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
@ -387,11 +387,11 @@ func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
return st, epoch, nil return st, epoch, nil
} }
func (c *cfg) ForceMaintenance(ctx context.Context) error { func (c *cfg) ForceMaintenance() error {
return c.setMaintenanceStatus(ctx, true) return c.setMaintenanceStatus(true)
} }
func (c *cfg) setMaintenanceStatus(ctx context.Context, force bool) error { func (c *cfg) setMaintenanceStatus(force bool) error {
netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration() netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration()
if err != nil { if err != nil {
err = fmt.Errorf("read network settings to check maintenance allowance: %w", err) err = fmt.Errorf("read network settings to check maintenance allowance: %w", err)
@ -400,10 +400,10 @@ func (c *cfg) setMaintenanceStatus(ctx context.Context, force bool) error {
} }
if err == nil || force { if err == nil || force {
c.startMaintenance(ctx) c.startMaintenance()
if err == nil { if err == nil {
err = c.updateNetMapState(ctx, (*nmClient.UpdatePeerPrm).SetMaintenance) err = c.updateNetMapState((*nmClient.UpdatePeerPrm).SetMaintenance)
} }
if err != nil { if err != nil {
@ -416,16 +416,13 @@ func (c *cfg) setMaintenanceStatus(ctx context.Context, force bool) error {
// calls UpdatePeerState operation of Netmap contract's client for the local node. // calls UpdatePeerState operation of Netmap contract's client for the local node.
// State setter is used to specify node state to switch to. // State setter is used to specify node state to switch to.
func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient.UpdatePeerPrm)) error { func (c *cfg) updateNetMapState(stateSetter func(*nmClient.UpdatePeerPrm)) error {
var prm nmClient.UpdatePeerPrm var prm nmClient.UpdatePeerPrm
prm.SetKey(c.key.PublicKey().Bytes()) prm.SetKey(c.key.PublicKey().Bytes())
stateSetter(&prm) stateSetter(&prm)
res, err := c.cfgNetmap.wrapper.UpdatePeerState(ctx, prm) _, err := c.cfgNetmap.wrapper.UpdatePeerState(prm)
if err != nil { return err
return err
}
return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res)
} }
type netInfo struct { type netInfo struct {

View file

@ -58,7 +58,7 @@ type objectSvc struct {
func (c *cfg) MaxObjectSize() uint64 { func (c *cfg) MaxObjectSize() uint64 {
sz, err := c.cfgNetmap.wrapper.MaxObjectSize() sz, err := c.cfgNetmap.wrapper.MaxObjectSize()
if err != nil { if err != nil {
c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, c.log.Error(logs.FrostFSNodeCouldNotGetMaxObjectSizeValue,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
@ -66,11 +66,11 @@ func (c *cfg) MaxObjectSize() uint64 {
return sz return sz
} }
func (s *objectSvc) Put(_ context.Context) (objectService.PutObjectStream, error) { func (s *objectSvc) Put() (objectService.PutObjectStream, error) {
return s.put.Put() return s.put.Put()
} }
func (s *objectSvc) Patch(_ context.Context) (objectService.PatchObjectStream, error) { func (s *objectSvc) Patch() (objectService.PatchObjectStream, error) {
return s.patch.Patch() return s.patch.Patch()
} }
@ -223,7 +223,7 @@ func initObjectService(c *cfg) {
func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.ClientCache) { func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.ClientCache) {
if policerconfig.UnsafeDisable(c.appCfg) { if policerconfig.UnsafeDisable(c.appCfg) {
c.log.Warn(context.Background(), logs.FrostFSNodePolicerIsDisabled) c.log.Warn(logs.FrostFSNodePolicerIsDisabled)
return return
} }
@ -287,7 +287,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl
_, err := ls.Inhume(ctx, inhumePrm) _, err := ls.Inhume(ctx, inhumePrm)
if err != nil { if err != nil {
c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage, c.log.Warn(logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }

View file

@ -1,18 +1,17 @@
package main package main
import ( import (
"context"
"runtime" "runtime"
profilerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler" profilerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler"
httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http" httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http"
) )
func initProfilerService(ctx context.Context, c *cfg) { func initProfilerService(c *cfg) {
tuneProfilers(c) tuneProfilers(c)
pprof, _ := pprofComponent(c) pprof, _ := pprofComponent(c)
pprof.init(ctx, c) pprof.init(c)
} }
func pprofComponent(c *cfg) (*httpComponent, bool) { func pprofComponent(c *cfg) (*httpComponent, bool) {

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"context"
"os" "os"
"runtime/debug" "runtime/debug"
@ -10,17 +9,17 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func setRuntimeParameters(ctx context.Context, c *cfg) { func setRuntimeParameters(c *cfg) {
if len(os.Getenv("GOMEMLIMIT")) != 0 { if len(os.Getenv("GOMEMLIMIT")) != 0 {
// default limit < yaml limit < app env limit < GOMEMLIMIT // default limit < yaml limit < app env limit < GOMEMLIMIT
c.log.Warn(ctx, logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT) c.log.Warn(logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT)
return return
} }
memLimitBytes := runtime.GCMemoryLimitBytes(c.appCfg) memLimitBytes := runtime.GCMemoryLimitBytes(c.appCfg)
previous := debug.SetMemoryLimit(memLimitBytes) previous := debug.SetMemoryLimit(memLimitBytes)
if memLimitBytes != previous { if memLimitBytes != previous {
c.log.Info(ctx, logs.RuntimeSoftMemoryLimitUpdated, c.log.Info(logs.RuntimeSoftMemoryLimitUpdated,
zap.Int64("new_value", memLimitBytes), zap.Int64("new_value", memLimitBytes),
zap.Int64("old_value", previous)) zap.Int64("old_value", previous))
} }

View file

@ -48,7 +48,7 @@ func initSessionService(c *cfg) {
_ = c.privateTokenStore.Close() _ = c.privateTokenStore.Close()
}) })
addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) { addNewEpochNotificationHandler(c, func(ev event.Event) {
c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber()) c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber())
}) })

View file

@ -13,12 +13,12 @@ import (
func initTracing(ctx context.Context, c *cfg) { func initTracing(ctx context.Context, c *cfg) {
conf, err := tracingconfig.ToTracingConfig(c.appCfg) conf, err := tracingconfig.ToTracingConfig(c.appCfg)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeFailedInitTracing, zap.Error(err)) c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err))
return return
} }
_, err = tracing.Setup(ctx, *conf) _, err = tracing.Setup(ctx, *conf)
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeFailedInitTracing, zap.Error(err)) c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err))
return return
} }
@ -29,7 +29,7 @@ func initTracing(ctx context.Context, c *cfg) {
defer cancel() defer cancel()
err := tracing.Shutdown(ctx) // cfg context cancels before close err := tracing.Shutdown(ctx) // cfg context cancels before close
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeFailedShutdownTracing, zap.Error(err)) c.log.Error(logs.FrostFSNodeFailedShutdownTracing, zap.Error(err))
} }
}, },
}) })

View file

@ -44,7 +44,7 @@ func (c cnrSource) List() ([]cid.ID, error) {
func initTreeService(c *cfg) { func initTreeService(c *cfg) {
treeConfig := treeconfig.Tree(c.appCfg) treeConfig := treeconfig.Tree(c.appCfg)
if !treeConfig.Enabled() { if !treeConfig.Enabled() {
c.log.Info(context.Background(), logs.FrostFSNodeTreeServiceIsNotEnabledSkipInitialization) c.log.Info(logs.FrostFSNodeTreeServiceIsNotEnabledSkipInitialization)
return return
} }
@ -80,10 +80,10 @@ func initTreeService(c *cfg) {
})) }))
if d := treeConfig.SyncInterval(); d == 0 { if d := treeConfig.SyncInterval(); d == 0 {
addNewEpochNotificationHandler(c, func(ctx context.Context, _ event.Event) { addNewEpochNotificationHandler(c, func(_ event.Event) {
err := c.treeService.SynchronizeAll() err := c.treeService.SynchronizeAll()
if err != nil { if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) c.log.Error(logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err))
} }
}) })
} else { } else {
@ -94,7 +94,7 @@ func initTreeService(c *cfg) {
for range tick.C { for range tick.C {
err := c.treeService.SynchronizeAll() err := c.treeService.SynchronizeAll()
if err != nil { if err != nil {
c.log.Error(context.Background(), logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) c.log.Error(logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err))
if errors.Is(err, tree.ErrShuttingDown) { if errors.Is(err, tree.ErrShuttingDown) {
return return
} }
@ -103,15 +103,15 @@ func initTreeService(c *cfg) {
}() }()
} }
subscribeToContainerRemoval(c, func(ctx context.Context, e event.Event) { subscribeToContainerRemoval(c, func(e event.Event) {
ev := e.(containerEvent.DeleteSuccess) ev := e.(containerEvent.DeleteSuccess)
// This is executed asynchronously, so we don't care about the operation taking some time. // This is executed asynchronously, so we don't care about the operation taking some time.
c.log.Debug(ctx, logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID)) c.log.Debug(logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID))
err := c.treeService.DropTree(ctx, ev.ID, "") err := c.treeService.DropTree(context.Background(), ev.ID, "")
if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) { if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) {
// Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged. // Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged.
c.log.Error(ctx, logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, c.log.Error(logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved,
zap.Stringer("cid", ev.ID), zap.Stringer("cid", ev.ID),
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }

View file

@ -1,167 +0,0 @@
package ape
import (
"encoding/hex"
"errors"
"fmt"
"strconv"
"strings"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
"github.com/nspcc-dev/neo-go/cli/input"
"github.com/spf13/cobra"
)
const (
defaultNamespace = "root"
namespaceTarget = "namespace"
containerTarget = "container"
userTarget = "user"
groupTarget = "group"
Ingress = "ingress"
S3 = "s3"
)
var mChainName = map[string]apechain.Name{
Ingress: apechain.Ingress,
S3: apechain.S3,
}
var (
errSettingDefaultValueWasDeclined = errors.New("setting default value was declined")
errUnknownTargetType = errors.New("unknown target type")
errUnsupportedChainName = errors.New("unsupported chain name")
)
// PrintHumanReadableAPEChain print APE chain rules.
func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
cmd.Println("Chain ID: " + string(chain.ID))
cmd.Printf(" HEX: %x\n", chain.ID)
cmd.Println("Rules:")
for _, rule := range chain.Rules {
cmd.Println("\n\tStatus: " + rule.Status.String())
cmd.Println("\tAny: " + strconv.FormatBool(rule.Any))
cmd.Println("\tConditions:")
for _, c := range rule.Condition {
var ot string
switch c.Kind {
case apechain.KindResource:
ot = "Resource"
case apechain.KindRequest:
ot = "Request"
default:
panic("unknown object type")
}
cmd.Println(fmt.Sprintf("\t\t%s %s %s %s", ot, c.Key, c.Op, c.Value))
}
cmd.Println("\tActions:\tInverted:" + strconv.FormatBool(rule.Actions.Inverted))
for _, name := range rule.Actions.Names {
cmd.Println("\t\t" + name)
}
cmd.Println("\tResources:\tInverted:" + strconv.FormatBool(rule.Resources.Inverted))
for _, name := range rule.Resources.Names {
cmd.Println("\t\t" + name)
}
}
}
// ParseTarget handles target parsing of an APE chain.
func ParseTarget(cmd *cobra.Command) engine.Target {
typ := ParseTargetType(cmd)
name, _ := cmd.Flags().GetString(TargetNameFlag)
switch typ {
case engine.Namespace:
if name == "" {
ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace))
commonCmd.ExitOnErr(cmd, "read line error: %w", err)
ln = strings.ToLower(ln)
if len(ln) > 0 && (ln[0] == 'n') {
commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined)
}
name = defaultNamespace
}
return engine.NamespaceTarget(name)
case engine.Container:
var cnr cid.ID
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
return engine.ContainerTarget(name)
case engine.User:
return engine.UserTarget(name)
case engine.Group:
return engine.GroupTarget(name)
default:
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
}
panic("unreachable")
}
// ParseTargetType handles target type parsing of an APE chain.
func ParseTargetType(cmd *cobra.Command) engine.TargetType {
typ, _ := cmd.Flags().GetString(TargetTypeFlag)
switch typ {
case namespaceTarget:
return engine.Namespace
case containerTarget:
return engine.Container
case userTarget:
return engine.User
case groupTarget:
return engine.Group
default:
commonCmd.ExitOnErr(cmd, "parse target type error: %w", errUnknownTargetType)
}
panic("unreachable")
}
// ParseChainID handles the parsing of APE-chain identifier.
// For some subcommands, chain ID is optional as an input parameter and should be generated by
// the service instead.
func ParseChainID(cmd *cobra.Command) (id apechain.ID) {
chainID, _ := cmd.Flags().GetString(ChainIDFlag)
id = apechain.ID(chainID)
hexEncoded, _ := cmd.Flags().GetBool(ChainIDHexFlag)
if !hexEncoded {
return
}
chainIDRaw, err := hex.DecodeString(chainID)
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
id = apechain.ID(chainIDRaw)
return
}
// ParseChain parses an APE chain which can be provided either as a rule statement
// or loaded from a binary/JSON file path.
func ParseChain(cmd *cobra.Command) *apechain.Chain {
chain := new(apechain.Chain)
chain.ID = ParseChainID(cmd)
if rules, _ := cmd.Flags().GetStringArray(RuleFlag); len(rules) > 0 {
commonCmd.ExitOnErr(cmd, "parser error: %w", apeutil.ParseAPEChain(chain, rules))
} else if encPath, _ := cmd.Flags().GetString(PathFlag); encPath != "" {
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", apeutil.ParseAPEChainBinaryOrJSON(chain, encPath))
} else {
commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed"))
}
cmd.Println("Parsed chain:")
PrintHumanReadableAPEChain(cmd, chain)
return chain
}
// ParseChainName parses chain name: the place in the request lifecycle where policy is applied.
func ParseChainName(cmd *cobra.Command) apechain.Name {
chainName, _ := cmd.Flags().GetString(ChainNameFlag)
apeChainName, ok := mChainName[strings.ToLower(chainName)]
if !ok {
commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName)
}
return apeChainName
}

View file

@ -1,79 +0,0 @@
package ape
const (
RuleFlag = "rule"
PathFlag = "path"
PathFlagDesc = "Path to encoded chain in JSON or binary format"
TargetNameFlag = "target-name"
TargetNameFlagDesc = "Resource name in APE resource name format"
TargetTypeFlag = "target-type"
TargetTypeFlagDesc = "Resource type(container/namespace)"
ChainIDFlag = "chain-id"
ChainIDFlagDesc = "Chain id"
ChainIDHexFlag = "chain-id-hex"
ChainIDHexFlagDesc = "Flag to parse chain ID as hex"
ChainNameFlag = "chain-name"
ChainNameFlagDesc = "Chain name(ingress|s3)"
AllFlag = "all"
)
const RuleFlagDesc = `Defines an Access Policy Engine (APE) rule in the format:
<status>[:status_detail] <action>... <condition>... <resource>...
Status:
- allow Permits specified actions
- deny Prohibits specified actions
- deny:QuotaLimitReached Denies access due to quota limits
Actions:
Object operations:
- Object.Put, Object.Get, etc.
- Object.* (all object operations)
Container operations:
- Container.Put, Container.Get, etc.
- Container.* (all container operations)
Conditions:
ResourceCondition:
Format: ResourceCondition:"key"=value, "key"!=value
Reserved properties (use '\' before '$'):
- $Object:version
- $Object:objectID
- $Object:containerID
- $Object:ownerID
- $Object:creationEpoch
- $Object:payloadLength
- $Object:payloadHash
- $Object:objectType
- $Object:homomorphicHash
RequestCondition:
Format: RequestCondition:"key"=value, "key"!=value
Reserved properties (use '\' before '$'):
- $Actor:publicKey
- $Actor:role
Example:
ResourceCondition:"check_key"!="check_value" RequestCondition:"$Actor:role"=others
Resources:
For objects:
- namespace/cid/oid (specific object)
- namespace/cid/* (all objects in container)
- namespace/* (all objects in namespace)
- * (all objects)
- /* (all objects in root namespace)
- /cid/* (all objects in root container)
- /cid/oid (specific object in root container)
For containers:
- namespace/cid (specific container)
- namespace/* (all containers in namespace)
- * (all containers)
- /cid (root container)
- /* (all root containers)
Notes:
- Cannot mix object and container operations in one rule
- Default behavior is Any=false unless 'any' is specified
- Use 'all' keyword to explicitly set Any=false`

View file

@ -26,15 +26,13 @@ func ExitOnErr(cmd *cobra.Command, errFmt string, err error) {
_ = iota _ = iota
internal internal
aclDenied aclDenied
apemanagerDenied
) )
var ( var (
code int code int
internalErr = new(sdkstatus.ServerInternal) internalErr = new(sdkstatus.ServerInternal)
accessErr = new(sdkstatus.ObjectAccessDenied) accessErr = new(sdkstatus.ObjectAccessDenied)
apemanagerErr = new(sdkstatus.APEManagerAccessDenied)
) )
switch { switch {
@ -43,9 +41,6 @@ func ExitOnErr(cmd *cobra.Command, errFmt string, err error) {
case errors.As(err, &accessErr): case errors.As(err, &accessErr):
code = aclDenied code = aclDenied
err = fmt.Errorf("%w: %s", err, accessErr.Reason()) err = fmt.Errorf("%w: %s", err, accessErr.Reason())
case errors.As(err, &apemanagerErr):
code = apemanagerDenied
err = fmt.Errorf("%w: %s", err, apemanagerErr.Reason())
default: default:
code = internal code = internal
} }

2
go.mod
View file

@ -4,7 +4,7 @@ go 1.22
require ( require (
code.gitea.io/sdk/gitea v0.17.1 code.gitea.io/sdk/gitea v0.17.1
git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4 git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88

BIN
go.sum

Binary file not shown.

View file

@ -1,8 +1,6 @@
package audit package audit
import ( import (
"context"
crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
@ -19,15 +17,15 @@ type Target interface {
String() string String() string
} }
func LogRequest(ctx context.Context, log *logger.Logger, operation string, req Request, target Target, status bool) { func LogRequest(log *logger.Logger, operation string, req Request, target Target, status bool) {
var key []byte var key []byte
if req != nil { if req != nil {
key = req.GetVerificationHeader().GetBodySignature().GetKey() key = req.GetVerificationHeader().GetBodySignature().GetKey()
} }
LogRequestWithKey(ctx, log, operation, key, target, status) LogRequestWithKey(log, operation, key, target, status)
} }
func LogRequestWithKey(ctx context.Context, log *logger.Logger, operation string, key []byte, target Target, status bool) { func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target Target, status bool) {
object, subject := NotDefined, NotDefined object, subject := NotDefined, NotDefined
publicKey := crypto.UnmarshalPublicKey(key) publicKey := crypto.UnmarshalPublicKey(key)
@ -39,7 +37,7 @@ func LogRequestWithKey(ctx context.Context, log *logger.Logger, operation string
object = target.String() object = target.String()
} }
log.Info(ctx, logs.AuditEventLogRecord, log.Info(logs.AuditEventLogRecord,
zap.String("operation", operation), zap.String("operation", operation),
zap.String("object", object), zap.String("object", object),
zap.String("subject", subject), zap.String("subject", subject),

View file

@ -117,7 +117,7 @@ func (v *FormatValidator) Validate(ctx context.Context, obj *objectSDK.Object, u
} }
if !unprepared { if !unprepared {
if err := v.validateSignatureKey(ctx, obj); err != nil { if err := v.validateSignatureKey(obj); err != nil {
return fmt.Errorf("(%T) could not validate signature key: %w", v, err) return fmt.Errorf("(%T) could not validate signature key: %w", v, err)
} }
@ -134,7 +134,7 @@ func (v *FormatValidator) Validate(ctx context.Context, obj *objectSDK.Object, u
return nil return nil
} }
func (v *FormatValidator) validateSignatureKey(ctx context.Context, obj *objectSDK.Object) error { func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error {
sig := obj.Signature() sig := obj.Signature()
if sig == nil { if sig == nil {
return errMissingSignature return errMissingSignature
@ -156,7 +156,7 @@ func (v *FormatValidator) validateSignatureKey(ctx context.Context, obj *objectS
ownerID := obj.OwnerID() ownerID := obj.OwnerID()
if token == nil && obj.ECHeader() != nil { if token == nil && obj.ECHeader() != nil {
role, err := v.isIROrContainerNode(ctx, obj, binKey) role, err := v.isIROrContainerNode(obj, binKey)
if err != nil { if err != nil {
return err return err
} }
@ -172,7 +172,7 @@ func (v *FormatValidator) validateSignatureKey(ctx context.Context, obj *objectS
} }
if v.verifyTokenIssuer { if v.verifyTokenIssuer {
role, err := v.isIROrContainerNode(ctx, obj, binKey) role, err := v.isIROrContainerNode(obj, binKey)
if err != nil { if err != nil {
return err return err
} }
@ -190,7 +190,7 @@ func (v *FormatValidator) validateSignatureKey(ctx context.Context, obj *objectS
return nil return nil
} }
func (v *FormatValidator) isIROrContainerNode(ctx context.Context, obj *objectSDK.Object, signerKey []byte) (acl.Role, error) { func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (acl.Role, error) {
cnrID, containerIDSet := obj.ContainerID() cnrID, containerIDSet := obj.ContainerID()
if !containerIDSet { if !containerIDSet {
return acl.RoleOthers, errNilCID return acl.RoleOthers, errNilCID
@ -204,7 +204,7 @@ func (v *FormatValidator) isIROrContainerNode(ctx context.Context, obj *objectSD
return acl.RoleOthers, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) return acl.RoleOthers, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err)
} }
res, err := v.senderClassifier.IsInnerRingOrContainerNode(ctx, signerKey, cnrID, cnr.Value) res, err := v.senderClassifier.IsInnerRingOrContainerNode(signerKey, cnrID, cnr.Value)
if err != nil { if err != nil {
return acl.RoleOthers, err return acl.RoleOthers, err
} }

View file

@ -65,7 +65,7 @@ func TestFormatValidator_Validate(t *testing.T) {
epoch: curEpoch, epoch: curEpoch,
}), }),
WithLockSource(ls), WithLockSource(ls),
WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
) )
ownerKey, err := keys.NewPrivateKey() ownerKey, err := keys.NewPrivateKey()
@ -290,7 +290,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) {
}), }),
WithLockSource(ls), WithLockSource(ls),
WithVerifySessionTokenIssuer(false), WithVerifySessionTokenIssuer(false),
WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
) )
tok := sessiontest.Object() tok := sessiontest.Object()
@ -339,7 +339,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) {
}, },
}, },
), ),
WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
) )
tok := sessiontest.Object() tok := sessiontest.Object()
@ -417,7 +417,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) {
currentEpoch: curEpoch, currentEpoch: curEpoch,
}, },
), ),
WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
) )
require.NoError(t, v.Validate(context.Background(), obj, false)) require.NoError(t, v.Validate(context.Background(), obj, false))
@ -491,7 +491,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) {
currentEpoch: curEpoch, currentEpoch: curEpoch,
}, },
), ),
WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
) )
require.NoError(t, v.Validate(context.Background(), obj, false)) require.NoError(t, v.Validate(context.Background(), obj, false))
@ -567,7 +567,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) {
currentEpoch: curEpoch, currentEpoch: curEpoch,
}, },
), ),
WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
) )
require.Error(t, v.Validate(context.Background(), obj, false)) require.Error(t, v.Validate(context.Background(), obj, false))

View file

@ -2,7 +2,6 @@ package object
import ( import (
"bytes" "bytes"
"context"
"crypto/sha256" "crypto/sha256"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
@ -41,7 +40,6 @@ type ClassifyResult struct {
} }
func (c SenderClassifier) Classify( func (c SenderClassifier) Classify(
ctx context.Context,
ownerID *user.ID, ownerID *user.ID,
ownerKey *keys.PublicKey, ownerKey *keys.PublicKey,
idCnr cid.ID, idCnr cid.ID,
@ -59,14 +57,14 @@ func (c SenderClassifier) Classify(
}, nil }, nil
} }
return c.IsInnerRingOrContainerNode(ctx, ownerKeyInBytes, idCnr, cnr) return c.IsInnerRingOrContainerNode(ownerKeyInBytes, idCnr, cnr)
} }
func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) { func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) {
isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes) isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes)
if err != nil { if err != nil {
// do not throw error, try best case matching // do not throw error, try best case matching
c.log.Debug(ctx, logs.V2CantCheckIfRequestFromInnerRing, c.log.Debug(logs.V2CantCheckIfRequestFromInnerRing,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} else if isInnerRingNode { } else if isInnerRingNode {
return &ClassifyResult{ return &ClassifyResult{
@ -83,7 +81,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK
// error might happen if request has `RoleOther` key and placement // error might happen if request has `RoleOther` key and placement
// is not possible for previous epoch, so // is not possible for previous epoch, so
// do not throw error, try best case matching // do not throw error, try best case matching
c.log.Debug(ctx, logs.V2CantCheckIfRequestFromContainerNode, c.log.Debug(logs.V2CantCheckIfRequestFromContainerNode,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} else if isContainerNode { } else if isContainerNode {
return &ClassifyResult{ return &ClassifyResult{

View file

@ -29,7 +29,7 @@ type (
emitDuration uint32 // in blocks emitDuration uint32 // in blocks
} }
depositor func(context.Context) (util.Uint256, error) depositor func() (util.Uint256, error)
awaiter func(context.Context, util.Uint256) error awaiter func(context.Context, util.Uint256) error
) )
@ -66,11 +66,11 @@ func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
) )
} }
func newEmissionTimer(ctx context.Context, args *emitTimerArgs) *timer.BlockTimer { func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer {
return timer.NewBlockTimer( return timer.NewBlockTimer(
timer.StaticBlockMeter(args.emitDuration), timer.StaticBlockMeter(args.emitDuration),
func() { func() {
args.ap.HandleGasEmission(ctx, timerEvent.NewAlphabetEmitTick{}) args.ap.HandleGasEmission(timerEvent.NewAlphabetEmitTick{})
}, },
) )
} }

View file

@ -35,7 +35,7 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
) )
func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper, func (s *Server) initNetmapProcessor(cfg *viper.Viper,
alphaSync event.Handler, alphaSync event.Handler,
) error { ) error {
locodeValidator, err := s.newLocodeValidator(cfg) locodeValidator, err := s.newLocodeValidator(cfg)
@ -48,13 +48,10 @@ func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper,
var netMapCandidateStateValidator statevalidation.NetMapCandidateValidator var netMapCandidateStateValidator statevalidation.NetMapCandidateValidator
netMapCandidateStateValidator.SetNetworkSettings(netSettings) netMapCandidateStateValidator.SetNetworkSettings(netSettings)
poolSize := cfg.GetInt("workers.netmap")
s.log.Debug(ctx, logs.NetmapNetmapWorkerPool, zap.Int("size", poolSize))
s.netmapProcessor, err = netmap.New(&netmap.Params{ s.netmapProcessor, err = netmap.New(&netmap.Params{
Log: s.log, Log: s.log,
Metrics: s.irMetrics, Metrics: s.irMetrics,
PoolSize: poolSize, PoolSize: cfg.GetInt("workers.netmap"),
NetmapClient: netmap.NewNetmapClient(s.netmapClient), NetmapClient: netmap.NewNetmapClient(s.netmapClient),
EpochTimer: s, EpochTimer: s,
EpochState: s, EpochState: s,
@ -100,7 +97,7 @@ func (s *Server) initMainnet(ctx context.Context, cfg *viper.Viper, morphChain *
fromMainChainBlock, err := s.persistate.UInt32(persistateMainChainLastBlockKey) fromMainChainBlock, err := s.persistate.UInt32(persistateMainChainLastBlockKey)
if err != nil { if err != nil {
fromMainChainBlock = 0 fromMainChainBlock = 0
s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error())) s.log.Warn(logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error()))
} }
mainnetChain.from = fromMainChainBlock mainnetChain.from = fromMainChainBlock
@ -140,12 +137,12 @@ func (s *Server) enableNotarySupport() error {
return nil return nil
} }
func (s *Server) initNotaryConfig(ctx context.Context) { func (s *Server) initNotaryConfig() {
s.mainNotaryConfig = notaryConfigs( s.mainNotaryConfig = notaryConfigs(
!s.withoutMainNet && s.mainnetClient.ProbeNotary(), // if mainnet disabled then notary flag must be disabled too !s.withoutMainNet && s.mainnetClient.ProbeNotary(), // if mainnet disabled then notary flag must be disabled too
) )
s.log.Info(ctx, logs.InnerringNotarySupport, s.log.Info(logs.InnerringNotarySupport,
zap.Bool("sidechain_enabled", true), zap.Bool("sidechain_enabled", true),
zap.Bool("mainchain_enabled", !s.mainNotaryConfig.disabled), zap.Bool("mainchain_enabled", !s.mainNotaryConfig.disabled),
) )
@ -155,8 +152,8 @@ func (s *Server) createAlphaSync(cfg *viper.Viper, frostfsCli *frostfsClient.Cli
var alphaSync event.Handler var alphaSync event.Handler
if s.withoutMainNet || cfg.GetBool("governance.disable") { if s.withoutMainNet || cfg.GetBool("governance.disable") {
alphaSync = func(ctx context.Context, _ event.Event) { alphaSync = func(event.Event) {
s.log.Debug(ctx, logs.InnerringAlphabetKeysSyncIsDisabled) s.log.Debug(logs.InnerringAlphabetKeysSyncIsDisabled)
} }
} else { } else {
// create governance processor // create governance processor
@ -199,16 +196,16 @@ func (s *Server) createIRFetcher() irFetcher {
return irf return irf
} }
func (s *Server) initTimers(ctx context.Context, cfg *viper.Viper) { func (s *Server) initTimers(cfg *viper.Viper) {
s.epochTimer = newEpochTimer(&epochTimerArgs{ s.epochTimer = newEpochTimer(&epochTimerArgs{
newEpochHandlers: s.newEpochTickHandlers(ctx), newEpochHandlers: s.newEpochTickHandlers(),
epoch: s, epoch: s,
}) })
s.addBlockTimer(s.epochTimer) s.addBlockTimer(s.epochTimer)
// initialize emission timer // initialize emission timer
emissionTimer := newEmissionTimer(ctx, &emitTimerArgs{ emissionTimer := newEmissionTimer(&emitTimerArgs{
ap: s.alphabetProcessor, ap: s.alphabetProcessor,
emitDuration: cfg.GetUint32("timers.emit"), emitDuration: cfg.GetUint32("timers.emit"),
}) })
@ -216,20 +213,18 @@ func (s *Server) initTimers(ctx context.Context, cfg *viper.Viper) {
s.addBlockTimer(emissionTimer) s.addBlockTimer(emissionTimer)
} }
func (s *Server) initAlphabetProcessor(ctx context.Context, cfg *viper.Viper) error { func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error {
parsedWallets, err := parseWalletAddressesFromStrings(cfg.GetStringSlice("emit.extra_wallets")) parsedWallets, err := parseWalletAddressesFromStrings(cfg.GetStringSlice("emit.extra_wallets"))
if err != nil { if err != nil {
return err return err
} }
poolSize := cfg.GetInt("workers.alphabet")
s.log.Debug(ctx, logs.AlphabetAlphabetWorkerPool, zap.Int("size", poolSize))
// create alphabet processor // create alphabet processor
s.alphabetProcessor, err = alphabet.New(&alphabet.Params{ s.alphabetProcessor, err = alphabet.New(&alphabet.Params{
ParsedWallets: parsedWallets, ParsedWallets: parsedWallets,
Log: s.log, Log: s.log,
Metrics: s.irMetrics, Metrics: s.irMetrics,
PoolSize: poolSize, PoolSize: cfg.GetInt("workers.alphabet"),
AlphabetContracts: s.contracts.alphabet, AlphabetContracts: s.contracts.alphabet,
NetmapClient: s.netmapClient, NetmapClient: s.netmapClient,
MorphClient: s.morphClient, MorphClient: s.morphClient,
@ -244,14 +239,12 @@ func (s *Server) initAlphabetProcessor(ctx context.Context, cfg *viper.Viper) er
return err return err
} }
func (s *Server) initContainerProcessor(ctx context.Context, cfg *viper.Viper, cnrClient *container.Client, frostfsIDClient *frostfsid.Client) error { func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client, frostfsIDClient *frostfsid.Client) error {
poolSize := cfg.GetInt("workers.container")
s.log.Debug(ctx, logs.ContainerContainerWorkerPool, zap.Int("size", poolSize))
// container processor // container processor
containerProcessor, err := cont.New(&cont.Params{ containerProcessor, err := cont.New(&cont.Params{
Log: s.log, Log: s.log,
Metrics: s.irMetrics, Metrics: s.irMetrics,
PoolSize: poolSize, PoolSize: cfg.GetInt("workers.container"),
AlphabetState: s, AlphabetState: s,
ContainerClient: cnrClient, ContainerClient: cnrClient,
MorphClient: cnrClient.Morph(), MorphClient: cnrClient.Morph(),
@ -265,14 +258,12 @@ func (s *Server) initContainerProcessor(ctx context.Context, cfg *viper.Viper, c
return bindMorphProcessor(containerProcessor, s) return bindMorphProcessor(containerProcessor, s)
} }
func (s *Server) initBalanceProcessor(ctx context.Context, cfg *viper.Viper, frostfsCli *frostfsClient.Client) error { func (s *Server) initBalanceProcessor(cfg *viper.Viper, frostfsCli *frostfsClient.Client) error {
poolSize := cfg.GetInt("workers.balance")
s.log.Debug(ctx, logs.BalanceBalanceWorkerPool, zap.Int("size", poolSize))
// create balance processor // create balance processor
balanceProcessor, err := balance.New(&balance.Params{ balanceProcessor, err := balance.New(&balance.Params{
Log: s.log, Log: s.log,
Metrics: s.irMetrics, Metrics: s.irMetrics,
PoolSize: poolSize, PoolSize: cfg.GetInt("workers.balance"),
FrostFSClient: frostfsCli, FrostFSClient: frostfsCli,
BalanceSC: s.contracts.balance, BalanceSC: s.contracts.balance,
AlphabetState: s, AlphabetState: s,
@ -285,17 +276,15 @@ func (s *Server) initBalanceProcessor(ctx context.Context, cfg *viper.Viper, fro
return bindMorphProcessor(balanceProcessor, s) return bindMorphProcessor(balanceProcessor, s)
} }
func (s *Server) initFrostFSMainnetProcessor(ctx context.Context, cfg *viper.Viper) error { func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error {
if s.withoutMainNet { if s.withoutMainNet {
return nil return nil
} }
poolSize := cfg.GetInt("workers.frostfs")
s.log.Debug(ctx, logs.FrostFSFrostfsWorkerPool, zap.Int("size", poolSize))
frostfsProcessor, err := frostfs.New(&frostfs.Params{ frostfsProcessor, err := frostfs.New(&frostfs.Params{
Log: s.log, Log: s.log,
Metrics: s.irMetrics, Metrics: s.irMetrics,
PoolSize: poolSize, PoolSize: cfg.GetInt("workers.frostfs"),
FrostFSContract: s.contracts.frostfs, FrostFSContract: s.contracts.frostfs,
BalanceClient: s.balanceClient, BalanceClient: s.balanceClient,
NetmapClient: s.netmapClient, NetmapClient: s.netmapClient,
@ -315,10 +304,10 @@ func (s *Server) initFrostFSMainnetProcessor(ctx context.Context, cfg *viper.Vip
return bindMainnetProcessor(frostfsProcessor, s) return bindMainnetProcessor(frostfsProcessor, s)
} }
func (s *Server) initGRPCServer(ctx context.Context, cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error { func (s *Server) initGRPCServer(cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error {
controlSvcEndpoint := cfg.GetString("control.grpc.endpoint") controlSvcEndpoint := cfg.GetString("control.grpc.endpoint")
if controlSvcEndpoint == "" { if controlSvcEndpoint == "" {
s.log.Info(ctx, logs.InnerringNoControlServerEndpointSpecified) s.log.Info(logs.InnerringNoControlServerEndpointSpecified)
return nil return nil
} }
@ -414,7 +403,7 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) {
return result, nil return result, nil
} }
func (s *Server) initProcessors(ctx context.Context, cfg *viper.Viper, morphClients *serverMorphClients) error { func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClients) error {
irf := s.createIRFetcher() irf := s.createIRFetcher()
s.statusIndex = newInnerRingIndexer( s.statusIndex = newInnerRingIndexer(
@ -429,27 +418,27 @@ func (s *Server) initProcessors(ctx context.Context, cfg *viper.Viper, morphClie
return err return err
} }
err = s.initNetmapProcessor(ctx, cfg, alphaSync) err = s.initNetmapProcessor(cfg, alphaSync)
if err != nil { if err != nil {
return err return err
} }
err = s.initContainerProcessor(ctx, cfg, morphClients.CnrClient, morphClients.FrostFSIDClient) err = s.initContainerProcessor(cfg, morphClients.CnrClient, morphClients.FrostFSIDClient)
if err != nil { if err != nil {
return err return err
} }
err = s.initBalanceProcessor(ctx, cfg, morphClients.FrostFSClient) err = s.initBalanceProcessor(cfg, morphClients.FrostFSClient)
if err != nil { if err != nil {
return err return err
} }
err = s.initFrostFSMainnetProcessor(ctx, cfg) err = s.initFrostFSMainnetProcessor(cfg)
if err != nil { if err != nil {
return err return err
} }
err = s.initAlphabetProcessor(ctx, cfg) err = s.initAlphabetProcessor(cfg)
return err return err
} }
@ -457,7 +446,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
fromSideChainBlock, err := s.persistate.UInt32(persistateSideChainLastBlockKey) fromSideChainBlock, err := s.persistate.UInt32(persistateSideChainLastBlockKey)
if err != nil { if err != nil {
fromSideChainBlock = 0 fromSideChainBlock = 0
s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) s.log.Warn(logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
} }
morphChain := &chainParams{ morphChain := &chainParams{
@ -482,7 +471,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
return nil, err return nil, err
} }
if err := s.morphClient.SetGroupSignerScope(); err != nil { if err := s.morphClient.SetGroupSignerScope(); err != nil {
morphChain.log.Info(ctx, logs.InnerringFailedToSetGroupSignerScope, zap.Error(err)) morphChain.log.Info(logs.InnerringFailedToSetGroupSignerScope, zap.Error(err))
} }
return morphChain, nil return morphChain, nil

View file

@ -140,10 +140,10 @@ var (
// Start runs all event providers. // Start runs all event providers.
func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
s.setHealthStatus(ctx, control.HealthStatus_STARTING) s.setHealthStatus(control.HealthStatus_STARTING)
defer func() { defer func() {
if err == nil { if err == nil {
s.setHealthStatus(ctx, control.HealthStatus_READY) s.setHealthStatus(control.HealthStatus_READY)
} }
}() }()
@ -152,12 +152,12 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
return err return err
} }
err = s.initConfigFromBlockchain(ctx) err = s.initConfigFromBlockchain()
if err != nil { if err != nil {
return err return err
} }
if s.IsAlphabet(ctx) { if s.IsAlphabet() {
err = s.initMainNotary(ctx) err = s.initMainNotary(ctx)
if err != nil { if err != nil {
return err return err
@ -173,14 +173,14 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
prm.Validators = s.predefinedValidators prm.Validators = s.predefinedValidators
// vote for sidechain validator if it is prepared in config // vote for sidechain validator if it is prepared in config
err = s.voteForSidechainValidator(ctx, prm) err = s.voteForSidechainValidator(prm)
if err != nil { if err != nil {
// we don't stop inner ring execution on this error // we don't stop inner ring execution on this error
s.log.Warn(ctx, logs.InnerringCantVoteForPreparedValidators, s.log.Warn(logs.InnerringCantVoteForPreparedValidators,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }
s.tickInitialExpoch(ctx) s.tickInitialExpoch()
morphErr := make(chan error) morphErr := make(chan error)
mainnnetErr := make(chan error) mainnnetErr := make(chan error)
@ -217,14 +217,14 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
} }
func (s *Server) registerMorphNewBlockEventHandler() { func (s *Server) registerMorphNewBlockEventHandler() {
s.morphListener.RegisterBlockHandler(func(ctx context.Context, b *block.Block) { s.morphListener.RegisterBlockHandler(func(b *block.Block) {
s.log.Debug(ctx, logs.InnerringNewBlock, s.log.Debug(logs.InnerringNewBlock,
zap.Uint32("index", b.Index), zap.Uint32("index", b.Index),
) )
err := s.persistate.SetUInt32(persistateSideChainLastBlockKey, b.Index) err := s.persistate.SetUInt32(persistateSideChainLastBlockKey, b.Index)
if err != nil { if err != nil {
s.log.Warn(ctx, logs.InnerringCantUpdatePersistentState, s.log.Warn(logs.InnerringCantUpdatePersistentState,
zap.String("chain", "side"), zap.String("chain", "side"),
zap.Uint32("block_index", b.Index)) zap.Uint32("block_index", b.Index))
} }
@ -235,10 +235,10 @@ func (s *Server) registerMorphNewBlockEventHandler() {
func (s *Server) registerMainnetNewBlockEventHandler() { func (s *Server) registerMainnetNewBlockEventHandler() {
if !s.withoutMainNet { if !s.withoutMainNet {
s.mainnetListener.RegisterBlockHandler(func(ctx context.Context, b *block.Block) { s.mainnetListener.RegisterBlockHandler(func(b *block.Block) {
err := s.persistate.SetUInt32(persistateMainChainLastBlockKey, b.Index) err := s.persistate.SetUInt32(persistateMainChainLastBlockKey, b.Index)
if err != nil { if err != nil {
s.log.Warn(ctx, logs.InnerringCantUpdatePersistentState, s.log.Warn(logs.InnerringCantUpdatePersistentState,
zap.String("chain", "main"), zap.String("chain", "main"),
zap.Uint32("block_index", b.Index)) zap.Uint32("block_index", b.Index))
} }
@ -283,11 +283,11 @@ func (s *Server) initSideNotary(ctx context.Context) error {
) )
} }
func (s *Server) tickInitialExpoch(ctx context.Context) { func (s *Server) tickInitialExpoch() {
initialEpochTicker := timer.NewOneTickTimer( initialEpochTicker := timer.NewOneTickTimer(
timer.StaticBlockMeter(s.initialEpochTickDelta), timer.StaticBlockMeter(s.initialEpochTickDelta),
func() { func() {
s.netmapProcessor.HandleNewEpochTick(ctx, timerEvent.NewEpochTick{}) s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{})
}) })
s.addBlockTimer(initialEpochTicker) s.addBlockTimer(initialEpochTicker)
} }
@ -299,15 +299,15 @@ func (s *Server) startWorkers(ctx context.Context) {
} }
// Stop closes all subscription channels. // Stop closes all subscription channels.
func (s *Server) Stop(ctx context.Context) { func (s *Server) Stop() {
s.setHealthStatus(ctx, control.HealthStatus_SHUTTING_DOWN) s.setHealthStatus(control.HealthStatus_SHUTTING_DOWN)
go s.morphListener.Stop() go s.morphListener.Stop()
go s.mainnetListener.Stop() go s.mainnetListener.Stop()
for _, c := range s.closers { for _, c := range s.closers {
if err := c(); err != nil { if err := c(); err != nil {
s.log.Warn(ctx, logs.InnerringCloserError, s.log.Warn(logs.InnerringCloserError,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
@ -349,7 +349,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan
return nil, err return nil, err
} }
server.setHealthStatus(ctx, control.HealthStatus_HEALTH_STATUS_UNDEFINED) server.setHealthStatus(control.HealthStatus_HEALTH_STATUS_UNDEFINED)
// parse notary support // parse notary support
server.feeConfig = config.NewFeeConfig(cfg) server.feeConfig = config.NewFeeConfig(cfg)
@ -376,7 +376,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan
return nil, err return nil, err
} }
server.initNotaryConfig(ctx) server.initNotaryConfig()
err = server.initContracts(cfg) err = server.initContracts(cfg)
if err != nil { if err != nil {
@ -400,14 +400,14 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan
return nil, err return nil, err
} }
err = server.initProcessors(ctx, cfg, morphClients) err = server.initProcessors(cfg, morphClients)
if err != nil { if err != nil {
return nil, err return nil, err
} }
server.initTimers(ctx, cfg) server.initTimers(cfg)
err = server.initGRPCServer(ctx, cfg, log, audit) err = server.initGRPCServer(cfg, log, audit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -438,7 +438,7 @@ func createListener(ctx context.Context, cli *client.Client, p *chainParams) (ev
} }
listener, err := event.NewListener(event.ListenerParams{ listener, err := event.NewListener(event.ListenerParams{
Logger: p.log.With(zap.String("chain", p.name)), Logger: &logger.Logger{Logger: p.log.With(zap.String("chain", p.name))},
Subscriber: sub, Subscriber: sub,
}) })
if err != nil { if err != nil {
@ -573,7 +573,7 @@ func parseMultinetConfig(cfg *viper.Viper, m metrics.MultinetMetrics) internalNe
return nc return nc
} }
func (s *Server) initConfigFromBlockchain(ctx context.Context) error { func (s *Server) initConfigFromBlockchain() error {
// get current epoch // get current epoch
epoch, err := s.netmapClient.Epoch() epoch, err := s.netmapClient.Epoch()
if err != nil { if err != nil {
@ -602,9 +602,9 @@ func (s *Server) initConfigFromBlockchain(ctx context.Context) error {
return err return err
} }
s.log.Debug(ctx, logs.InnerringReadConfigFromBlockchain, s.log.Debug(logs.InnerringReadConfigFromBlockchain,
zap.Bool("active", s.IsActive(ctx)), zap.Bool("active", s.IsActive()),
zap.Bool("alphabet", s.IsAlphabet(ctx)), zap.Bool("alphabet", s.IsAlphabet()),
zap.Uint64("epoch", epoch), zap.Uint64("epoch", epoch),
zap.Uint32("precision", balancePrecision), zap.Uint32("precision", balancePrecision),
zap.Uint32("init_epoch_tick_delta", s.initialEpochTickDelta), zap.Uint32("init_epoch_tick_delta", s.initialEpochTickDelta),
@ -635,17 +635,17 @@ func (s *Server) nextEpochBlockDelta() (uint32, error) {
// onlyAlphabet wrapper around event handler that executes it // onlyAlphabet wrapper around event handler that executes it
// only if inner ring node is alphabet node. // only if inner ring node is alphabet node.
func (s *Server) onlyAlphabetEventHandler(f event.Handler) event.Handler { func (s *Server) onlyAlphabetEventHandler(f event.Handler) event.Handler {
return func(ctx context.Context, ev event.Event) { return func(ev event.Event) {
if s.IsAlphabet(ctx) { if s.IsAlphabet() {
f(ctx, ev) f(ev)
} }
} }
} }
func (s *Server) newEpochTickHandlers(ctx context.Context) []newEpochHandler { func (s *Server) newEpochTickHandlers() []newEpochHandler {
newEpochHandlers := []newEpochHandler{ newEpochHandlers := []newEpochHandler{
func() { func() {
s.netmapProcessor.HandleNewEpochTick(ctx, timerEvent.NewEpochTick{}) s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{})
}, },
} }

View file

@ -28,39 +28,38 @@ const (
gasDivisor = 2 gasDivisor = 2
) )
func (s *Server) depositMainNotary(ctx context.Context) (tx util.Uint256, err error) { func (s *Server) depositMainNotary() (tx util.Uint256, err error) {
depositAmount, err := client.CalculateNotaryDepositAmount(s.mainnetClient, gasMultiplier, gasDivisor) depositAmount, err := client.CalculateNotaryDepositAmount(s.mainnetClient, gasMultiplier, gasDivisor)
if err != nil { if err != nil {
return util.Uint256{}, fmt.Errorf("could not calculate main notary deposit amount: %w", err) return util.Uint256{}, fmt.Errorf("could not calculate main notary deposit amount: %w", err)
} }
return s.mainnetClient.DepositNotary( return s.mainnetClient.DepositNotary(
ctx,
depositAmount, depositAmount,
uint32(s.epochDuration.Load())+notaryExtraBlocks, uint32(s.epochDuration.Load())+notaryExtraBlocks,
) )
} }
func (s *Server) depositSideNotary(ctx context.Context) (util.Uint256, error) { func (s *Server) depositSideNotary() (util.Uint256, error) {
depositAmount, err := client.CalculateNotaryDepositAmount(s.morphClient, gasMultiplier, gasDivisor) depositAmount, err := client.CalculateNotaryDepositAmount(s.morphClient, gasMultiplier, gasDivisor)
if err != nil { if err != nil {
return util.Uint256{}, fmt.Errorf("could not calculate side notary deposit amount: %w", err) return util.Uint256{}, fmt.Errorf("could not calculate side notary deposit amount: %w", err)
} }
tx, _, err := s.morphClient.DepositEndlessNotary(ctx, depositAmount) tx, _, err := s.morphClient.DepositEndlessNotary(depositAmount)
return tx, err return tx, err
} }
func (s *Server) notaryHandler(ctx context.Context, _ event.Event) { func (s *Server) notaryHandler(_ event.Event) {
if !s.mainNotaryConfig.disabled { if !s.mainNotaryConfig.disabled {
_, err := s.depositMainNotary(ctx) _, err := s.depositMainNotary()
if err != nil { if err != nil {
s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) s.log.Error(logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err))
} }
} }
if _, err := s.depositSideNotary(ctx); err != nil { if _, err := s.depositSideNotary(); err != nil {
s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) s.log.Error(logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err))
} }
} }
@ -73,7 +72,7 @@ func (s *Server) awaitSideNotaryDeposit(ctx context.Context, tx util.Uint256) er
} }
func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaiter, msg string) error { func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaiter, msg string) error {
tx, err := deposit(ctx) tx, err := deposit()
if err != nil { if err != nil {
return err return err
} }
@ -82,11 +81,11 @@ func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaite
// non-error deposit with an empty TX hash means // non-error deposit with an empty TX hash means
// that the deposit has already been made; no // that the deposit has already been made; no
// need to wait it. // need to wait it.
s.log.Info(ctx, logs.InnerringNotaryDepositHasAlreadyBeenMade) s.log.Info(logs.InnerringNotaryDepositHasAlreadyBeenMade)
return nil return nil
} }
s.log.Info(ctx, msg) s.log.Info(msg)
return await(ctx, tx) return await(ctx, tx)
} }

View file

@ -1,8 +1,6 @@
package alphabet package alphabet
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
@ -10,16 +8,16 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (ap *Processor) HandleGasEmission(ctx context.Context, ev event.Event) { func (ap *Processor) HandleGasEmission(ev event.Event) {
_ = ev.(timers.NewAlphabetEmitTick) _ = ev.(timers.NewAlphabetEmitTick)
ap.log.Info(ctx, logs.AlphabetTick, zap.String("type", "alphabet gas emit")) ap.log.Info(logs.AlphabetTick, zap.String("type", "alphabet gas emit"))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(ap.pool, ap.metrics, "alphabet_emit_gas", func() bool { return ap.processEmit(ctx) }) err := processors.SubmitEvent(ap.pool, ap.metrics, "alphabet_emit_gas", ap.processEmit)
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
ap.log.Warn(ctx, logs.AlphabetAlphabetProcessorWorkerPoolDrained, ap.log.Warn(logs.AlphabetAlphabetProcessorWorkerPoolDrained,
zap.Int("capacity", ap.pool.Cap())) zap.Int("capacity", ap.pool.Cap()))
} }
} }

View file

@ -1,13 +1,11 @@
package alphabet_test package alphabet_test
import ( import (
"context"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -62,7 +60,7 @@ func TestProcessorEmitsGasToNetmapAndAlphabet(t *testing.T) {
processor, err := alphabet.New(params) processor, err := alphabet.New(params)
require.NoError(t, err, "failed to create processor instance") require.NoError(t, err, "failed to create processor instance")
processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{}) processor.HandleGasEmission(timers.NewAlphabetEmitTick{})
processor.WaitPoolRunning() processor.WaitPoolRunning()
@ -139,7 +137,7 @@ func TestProcessorEmitsGasToNetmapIfNoParsedWallets(t *testing.T) {
processor, err := alphabet.New(params) processor, err := alphabet.New(params)
require.NoError(t, err, "failed to create processor instance") require.NoError(t, err, "failed to create processor instance")
processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{}) processor.HandleGasEmission(timers.NewAlphabetEmitTick{})
processor.WaitPoolRunning() processor.WaitPoolRunning()
@ -200,7 +198,7 @@ func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) {
processor, err := alphabet.New(params) processor, err := alphabet.New(params)
require.NoError(t, err, "failed to create processor instance") require.NoError(t, err, "failed to create processor instance")
processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{}) processor.HandleGasEmission(timers.NewAlphabetEmitTick{})
processor.WaitPoolRunning() processor.WaitPoolRunning()
@ -221,7 +219,7 @@ type testIndexer struct {
index int index int
} }
func (i *testIndexer) AlphabetIndex(context.Context) int { func (i *testIndexer) AlphabetIndex() int {
return i.index return i.index
} }
@ -248,7 +246,7 @@ type testMorphClient struct {
batchTransferedGas []batchTransferGas batchTransferedGas []batchTransferGas
} }
func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (client.InvokeRes, error) { func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) {
c.invokedMethods = append(c.invokedMethods, c.invokedMethods = append(c.invokedMethods,
invokedMethod{ invokedMethod{
contract: contract, contract: contract,
@ -256,7 +254,7 @@ func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee f
method: method, method: method,
args: args, args: args,
}) })
return client.InvokeRes{}, nil return 0, nil
} }
func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error { func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error {

View file

@ -1,7 +1,6 @@
package alphabet package alphabet
import ( import (
"context"
"crypto/elliptic" "crypto/elliptic"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
@ -14,39 +13,39 @@ import (
const emitMethod = "emit" const emitMethod = "emit"
func (ap *Processor) processEmit(ctx context.Context) bool { func (ap *Processor) processEmit() bool {
index := ap.irList.AlphabetIndex(ctx) index := ap.irList.AlphabetIndex()
if index < 0 { if index < 0 {
ap.log.Info(ctx, logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) ap.log.Info(logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent)
return true return true
} }
contract, ok := ap.alphabetContracts.GetByIndex(index) contract, ok := ap.alphabetContracts.GetByIndex(index)
if !ok { if !ok {
ap.log.Debug(ctx, logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, ap.log.Debug(logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent,
zap.Int("index", index)) zap.Int("index", index))
return false return false
} }
// there is no signature collecting, so we don't need extra fee // there is no signature collecting, so we don't need extra fee
_, err := ap.morphClient.Invoke(ctx, contract, 0, emitMethod) _, err := ap.morphClient.Invoke(contract, 0, emitMethod)
if err != nil { if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) ap.log.Warn(logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error()))
return false return false
} }
if ap.storageEmission == 0 { if ap.storageEmission == 0 {
ap.log.Info(ctx, logs.AlphabetStorageNodeEmissionIsOff) ap.log.Info(logs.AlphabetStorageNodeEmissionIsOff)
return true return true
} }
networkMap, err := ap.netmapClient.NetMap() networkMap, err := ap.netmapClient.NetMap()
if err != nil { if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, ap.log.Warn(logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
@ -59,7 +58,7 @@ func (ap *Processor) processEmit(ctx context.Context) bool {
ap.pwLock.RUnlock() ap.pwLock.RUnlock()
extraLen := len(pw) extraLen := len(pw)
ap.log.Debug(ctx, logs.AlphabetGasEmission, ap.log.Debug(logs.AlphabetGasEmission,
zap.Int("network_map", nmLen), zap.Int("network_map", nmLen),
zap.Int("extra_wallets", extraLen)) zap.Int("extra_wallets", extraLen))
@ -69,20 +68,20 @@ func (ap *Processor) processEmit(ctx context.Context) bool {
gasPerNode := fixedn.Fixed8(ap.storageEmission / uint64(nmLen+extraLen)) gasPerNode := fixedn.Fixed8(ap.storageEmission / uint64(nmLen+extraLen))
ap.transferGasToNetmapNodes(ctx, nmNodes, gasPerNode) ap.transferGasToNetmapNodes(nmNodes, gasPerNode)
ap.transferGasToExtraNodes(ctx, pw, gasPerNode) ap.transferGasToExtraNodes(pw, gasPerNode)
return true return true
} }
func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []netmap.NodeInfo, gasPerNode fixedn.Fixed8) { func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerNode fixedn.Fixed8) {
for i := range nmNodes { for i := range nmNodes {
keyBytes := nmNodes[i].PublicKey() keyBytes := nmNodes[i].PublicKey()
key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256()) key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256())
if err != nil { if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantParseNodePublicKey, ap.log.Warn(logs.AlphabetCantParseNodePublicKey,
zap.String("error", err.Error())) zap.String("error", err.Error()))
continue continue
@ -90,7 +89,7 @@ func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []net
err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode) err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode)
if err != nil { if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantTransferGas, ap.log.Warn(logs.AlphabetCantTransferGas,
zap.String("receiver", key.Address()), zap.String("receiver", key.Address()),
zap.Int64("amount", int64(gasPerNode)), zap.Int64("amount", int64(gasPerNode)),
zap.String("error", err.Error()), zap.String("error", err.Error()),
@ -99,7 +98,7 @@ func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []net
} }
} }
func (ap *Processor) transferGasToExtraNodes(ctx context.Context, pw []util.Uint160, gasPerNode fixedn.Fixed8) { func (ap *Processor) transferGasToExtraNodes(pw []util.Uint160, gasPerNode fixedn.Fixed8) {
if len(pw) > 0 { if len(pw) > 0 {
err := ap.morphClient.BatchTransferGas(pw, gasPerNode) err := ap.morphClient.BatchTransferGas(pw, gasPerNode)
if err != nil { if err != nil {
@ -107,7 +106,7 @@ func (ap *Processor) transferGasToExtraNodes(ctx context.Context, pw []util.Uint
for i, addr := range pw { for i, addr := range pw {
receiversLog[i] = addr.StringLE() receiversLog[i] = addr.StringLE()
} }
ap.log.Warn(ctx, logs.AlphabetCantTransferGasToWallet, ap.log.Warn(logs.AlphabetCantTransferGasToWallet,
zap.Strings("receivers", receiversLog), zap.Strings("receivers", receiversLog),
zap.Int64("amount", int64(gasPerNode)), zap.Int64("amount", int64(gasPerNode)),
zap.String("error", err.Error()), zap.String("error", err.Error()),

View file

@ -1,26 +1,26 @@
package alphabet package alphabet
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"go.uber.org/zap"
) )
type ( type (
// Indexer is a callback interface for inner ring global state. // Indexer is a callback interface for inner ring global state.
Indexer interface { Indexer interface {
AlphabetIndex(context.Context) int AlphabetIndex() int
} }
// Contracts is an interface of the storage // Contracts is an interface of the storage
@ -40,7 +40,7 @@ type (
} }
morphClient interface { morphClient interface {
Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (client.InvokeRes, error) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error)
TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error
BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error
} }
@ -85,6 +85,8 @@ func New(p *Params) (*Processor, error) {
return nil, errors.New("ir/alphabet: global state is not set") return nil, errors.New("ir/alphabet: global state is not set")
} }
p.Log.Debug(logs.AlphabetAlphabetWorkerPool, zap.Int("size", p.PoolSize))
pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true))
if err != nil { if err != nil {
return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err) return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err)

View file

@ -1,7 +1,6 @@
package balance package balance
import ( import (
"context"
"encoding/hex" "encoding/hex"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
@ -11,20 +10,20 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (bp *Processor) handleLock(ctx context.Context, ev event.Event) { func (bp *Processor) handleLock(ev event.Event) {
lock := ev.(balanceEvent.Lock) lock := ev.(balanceEvent.Lock)
bp.log.Info(ctx, logs.Notification, bp.log.Info(logs.Notification,
zap.String("type", "lock"), zap.String("type", "lock"),
zap.String("value", hex.EncodeToString(lock.ID()))) zap.String("value", hex.EncodeToString(lock.ID())))
// send an event to the worker pool // send an event to the worker pool
err := processors.SubmitEvent(bp.pool, bp.metrics, "lock", func() bool { err := processors.SubmitEvent(bp.pool, bp.metrics, "lock", func() bool {
return bp.processLock(ctx, &lock) return bp.processLock(&lock)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
bp.log.Warn(ctx, logs.BalanceBalanceWorkerPoolDrained, bp.log.Warn(logs.BalanceBalanceWorkerPoolDrained,
zap.Int("capacity", bp.pool.Cap())) zap.Int("capacity", bp.pool.Cap()))
} }
} }

View file

@ -1,7 +1,6 @@
package balance package balance
import ( import (
"context"
"testing" "testing"
"time" "time"
@ -31,7 +30,7 @@ func TestProcessorCallsFrostFSContractForLockEvent(t *testing.T) {
}) })
require.NoError(t, err, "failed to create processor") require.NoError(t, err, "failed to create processor")
processor.handleLock(context.Background(), balanceEvent.Lock{}) processor.handleLock(balanceEvent.Lock{})
for processor.pool.Running() > 0 { for processor.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -57,7 +56,7 @@ func TestProcessorDoesntCallFrostFSContractIfNotAlphabet(t *testing.T) {
}) })
require.NoError(t, err, "failed to create processor") require.NoError(t, err, "failed to create processor")
processor.handleLock(context.Background(), balanceEvent.Lock{}) processor.handleLock(balanceEvent.Lock{})
for processor.pool.Running() > 0 { for processor.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -70,7 +69,7 @@ type testAlphabetState struct {
isAlphabet bool isAlphabet bool
} }
func (s *testAlphabetState) IsAlphabet(context.Context) bool { func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet return s.isAlphabet
} }
@ -84,7 +83,7 @@ type testFrostFSContractClient struct {
chequeCalls int chequeCalls int
} }
func (c *testFrostFSContractClient) Cheque(_ context.Context, p frostfscontract.ChequePrm) error { func (c *testFrostFSContractClient) Cheque(p frostfscontract.ChequePrm) error {
c.chequeCalls++ c.chequeCalls++
return nil return nil
} }

View file

@ -1,8 +1,6 @@
package balance package balance
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
frostfsContract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" frostfsContract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs"
balanceEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/balance" balanceEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/balance"
@ -11,9 +9,9 @@ import (
// Process lock event by invoking Cheque method in main net to send assets // Process lock event by invoking Cheque method in main net to send assets
// back to the withdraw issuer. // back to the withdraw issuer.
func (bp *Processor) processLock(ctx context.Context, lock *balanceEvent.Lock) bool { func (bp *Processor) processLock(lock *balanceEvent.Lock) bool {
if !bp.alphabetState.IsAlphabet(ctx) { if !bp.alphabetState.IsAlphabet() {
bp.log.Info(ctx, logs.BalanceNonAlphabetModeIgnoreBalanceLock) bp.log.Info(logs.BalanceNonAlphabetModeIgnoreBalanceLock)
return true return true
} }
@ -25,9 +23,9 @@ func (bp *Processor) processLock(ctx context.Context, lock *balanceEvent.Lock) b
prm.SetLock(lock.LockAccount()) prm.SetLock(lock.LockAccount())
prm.SetHash(lock.TxHash()) prm.SetHash(lock.TxHash())
err := bp.frostfsClient.Cheque(ctx, prm) err := bp.frostfsClient.Cheque(prm)
if err != nil { if err != nil {
bp.log.Error(ctx, logs.BalanceCantSendLockAssetTx, zap.Error(err)) bp.log.Error(logs.BalanceCantSendLockAssetTx, zap.Error(err))
return false return false
} }

View file

@ -1,10 +1,10 @@
package balance package balance
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
@ -12,12 +12,13 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"go.uber.org/zap"
) )
type ( type (
// AlphabetState is a callback interface for inner ring global state. // AlphabetState is a callback interface for inner ring global state.
AlphabetState interface { AlphabetState interface {
IsAlphabet(context.Context) bool IsAlphabet() bool
} }
// PrecisionConverter converts balance amount values. // PrecisionConverter converts balance amount values.
@ -26,7 +27,7 @@ type (
} }
FrostFSClient interface { FrostFSClient interface {
Cheque(ctx context.Context, p frostfscontract.ChequePrm) error Cheque(p frostfscontract.ChequePrm) error
} }
// Processor of events produced by balance contract in the morphchain. // Processor of events produced by balance contract in the morphchain.
@ -67,6 +68,8 @@ func New(p *Params) (*Processor, error) {
return nil, errors.New("ir/balance: balance precision converter is not set") return nil, errors.New("ir/balance: balance precision converter is not set")
} }
p.Log.Debug(logs.BalanceBalanceWorkerPool, zap.Int("size", p.PoolSize))
pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true))
if err != nil { if err != nil {
return nil, fmt.Errorf("ir/balance: can't create worker pool: %w", err) return nil, fmt.Errorf("ir/balance: can't create worker pool: %w", err)

View file

@ -1,7 +1,6 @@
package container package container
import ( import (
"context"
"crypto/sha256" "crypto/sha256"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
@ -12,40 +11,40 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (cp *Processor) handlePut(ctx context.Context, ev event.Event) { func (cp *Processor) handlePut(ev event.Event) {
put := ev.(putEvent) put := ev.(putEvent)
id := sha256.Sum256(put.Container()) id := sha256.Sum256(put.Container())
cp.log.Info(ctx, logs.Notification, cp.log.Info(logs.Notification,
zap.String("type", "container put"), zap.String("type", "container put"),
zap.String("id", base58.Encode(id[:]))) zap.String("id", base58.Encode(id[:])))
// send an event to the worker pool // send an event to the worker pool
err := processors.SubmitEvent(cp.pool, cp.metrics, "container_put", func() bool { err := processors.SubmitEvent(cp.pool, cp.metrics, "container_put", func() bool {
return cp.processContainerPut(ctx, put) return cp.processContainerPut(put)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
cp.log.Warn(ctx, logs.ContainerContainerProcessorWorkerPoolDrained, cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained,
zap.Int("capacity", cp.pool.Cap())) zap.Int("capacity", cp.pool.Cap()))
} }
} }
func (cp *Processor) handleDelete(ctx context.Context, ev event.Event) { func (cp *Processor) handleDelete(ev event.Event) {
del := ev.(containerEvent.Delete) del := ev.(containerEvent.Delete)
cp.log.Info(ctx, logs.Notification, cp.log.Info(logs.Notification,
zap.String("type", "container delete"), zap.String("type", "container delete"),
zap.String("id", base58.Encode(del.ContainerID()))) zap.String("id", base58.Encode(del.ContainerID())))
// send an event to the worker pool // send an event to the worker pool
err := processors.SubmitEvent(cp.pool, cp.metrics, "container_delete", func() bool { err := processors.SubmitEvent(cp.pool, cp.metrics, "container_delete", func() bool {
return cp.processContainerDelete(ctx, del) return cp.processContainerDelete(del)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
cp.log.Warn(ctx, logs.ContainerContainerProcessorWorkerPoolDrained, cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained,
zap.Int("capacity", cp.pool.Cap())) zap.Int("capacity", cp.pool.Cap()))
} }
} }

View file

@ -1,7 +1,6 @@
package container package container
import ( import (
"context"
"crypto/ecdsa" "crypto/ecdsa"
"encoding/hex" "encoding/hex"
"testing" "testing"
@ -72,7 +71,7 @@ func TestPutEvent(t *testing.T) {
nr: nr, nr: nr,
} }
proc.handlePut(context.Background(), event) proc.handlePut(event)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -144,7 +143,7 @@ func TestDeleteEvent(t *testing.T) {
Signature: signature, Signature: signature,
} }
proc.handleDelete(context.Background(), ev) proc.handleDelete(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -161,7 +160,7 @@ type testAlphabetState struct {
isAlphabet bool isAlphabet bool
} }
func (s *testAlphabetState) IsAlphabet(context.Context) bool { func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet return s.isAlphabet
} }

View file

@ -1,7 +1,6 @@
package container package container
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
@ -37,27 +36,27 @@ var errContainerAndOwnerNamespaceDontMatch = errors.New("container and owner nam
// Process a new container from the user by checking the container sanity // Process a new container from the user by checking the container sanity
// and sending approve tx back to the morph. // and sending approve tx back to the morph.
func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool { func (cp *Processor) processContainerPut(put putEvent) bool {
if !cp.alphabetState.IsAlphabet(ctx) { if !cp.alphabetState.IsAlphabet() {
cp.log.Info(ctx, logs.ContainerNonAlphabetModeIgnoreContainerPut) cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerPut)
return true return true
} }
pctx := &putContainerContext{ ctx := &putContainerContext{
e: put, e: put,
} }
err := cp.checkPutContainer(pctx) err := cp.checkPutContainer(ctx)
if err != nil { if err != nil {
cp.log.Error(ctx, logs.ContainerPutContainerCheckFailed, cp.log.Error(logs.ContainerPutContainerCheckFailed,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
return false return false
} }
if err := cp.morphClient.NotarySignAndInvokeTX(pctx.e.NotaryRequest().MainTransaction); err != nil { if err := cp.morphClient.NotarySignAndInvokeTX(ctx.e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(ctx, logs.ContainerCouldNotApprovePutContainer, cp.log.Error(logs.ContainerCouldNotApprovePutContainer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
return false return false
@ -104,15 +103,15 @@ func (cp *Processor) checkPutContainer(ctx *putContainerContext) error {
// Process delete container operation from the user by checking container sanity // Process delete container operation from the user by checking container sanity
// and sending approve tx back to morph. // and sending approve tx back to morph.
func (cp *Processor) processContainerDelete(ctx context.Context, e containerEvent.Delete) bool { func (cp *Processor) processContainerDelete(e containerEvent.Delete) bool {
if !cp.alphabetState.IsAlphabet(ctx) { if !cp.alphabetState.IsAlphabet() {
cp.log.Info(ctx, logs.ContainerNonAlphabetModeIgnoreContainerDelete) cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerDelete)
return true return true
} }
err := cp.checkDeleteContainer(e) err := cp.checkDeleteContainer(e)
if err != nil { if err != nil {
cp.log.Error(ctx, logs.ContainerDeleteContainerCheckFailed, cp.log.Error(logs.ContainerDeleteContainerCheckFailed,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -120,7 +119,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven
} }
if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil { if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(ctx, logs.ContainerCouldNotApproveDeleteContainer, cp.log.Error(logs.ContainerCouldNotApproveDeleteContainer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )

View file

@ -1,11 +1,11 @@
package container package container
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
@ -15,12 +15,13 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"go.uber.org/zap"
) )
type ( type (
// AlphabetState is a callback interface for inner ring global state. // AlphabetState is a callback interface for inner ring global state.
AlphabetState interface { AlphabetState interface {
IsAlphabet(context.Context) bool IsAlphabet() bool
} }
ContClient interface { ContClient interface {
@ -96,6 +97,8 @@ func New(p *Params) (*Processor, error) {
return nil, errors.New("ir/container: FrostFSID client is not set") return nil, errors.New("ir/container: FrostFSID client is not set")
} }
p.Log.Debug(logs.ContainerContainerWorkerPool, zap.Int("size", p.PoolSize))
pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true))
if err != nil { if err != nil {
return nil, fmt.Errorf("ir/container: can't create worker pool: %w", err) return nil, fmt.Errorf("ir/container: can't create worker pool: %w", err)

View file

@ -2,7 +2,6 @@ package frostfs
import ( import (
"bytes" "bytes"
"context"
"encoding/hex" "encoding/hex"
"slices" "slices"
@ -13,67 +12,67 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (np *Processor) handleDeposit(ctx context.Context, ev event.Event) { func (np *Processor) handleDeposit(ev event.Event) {
deposit := ev.(frostfsEvent.Deposit) deposit := ev.(frostfsEvent.Deposit)
depositIDBin := bytes.Clone(deposit.ID()) depositIDBin := bytes.Clone(deposit.ID())
slices.Reverse(depositIDBin) slices.Reverse(depositIDBin)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "deposit"), zap.String("type", "deposit"),
zap.String("id", hex.EncodeToString(depositIDBin))) zap.String("id", hex.EncodeToString(depositIDBin)))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_deposit", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_deposit", func() bool {
return np.processDeposit(ctx, deposit) return np.processDeposit(deposit)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleWithdraw(ctx context.Context, ev event.Event) { func (np *Processor) handleWithdraw(ev event.Event) {
withdraw := ev.(frostfsEvent.Withdraw) withdraw := ev.(frostfsEvent.Withdraw)
withdrawBin := bytes.Clone(withdraw.ID()) withdrawBin := bytes.Clone(withdraw.ID())
slices.Reverse(withdrawBin) slices.Reverse(withdrawBin)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "withdraw"), zap.String("type", "withdraw"),
zap.String("id", hex.EncodeToString(withdrawBin))) zap.String("id", hex.EncodeToString(withdrawBin)))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_withdraw", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_withdraw", func() bool {
return np.processWithdraw(ctx, withdraw) return np.processWithdraw(withdraw)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleCheque(ctx context.Context, ev event.Event) { func (np *Processor) handleCheque(ev event.Event) {
cheque := ev.(frostfsEvent.Cheque) cheque := ev.(frostfsEvent.Cheque)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "cheque"), zap.String("type", "cheque"),
zap.String("id", hex.EncodeToString(cheque.ID()))) zap.String("id", hex.EncodeToString(cheque.ID())))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_cheque", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_cheque", func() bool {
return np.processCheque(ctx, cheque) return np.processCheque(cheque)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleConfig(ctx context.Context, ev event.Event) { func (np *Processor) handleConfig(ev event.Event) {
cfg := ev.(frostfsEvent.Config) cfg := ev.(frostfsEvent.Config)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "set config"), zap.String("type", "set config"),
zap.String("key", hex.EncodeToString(cfg.Key())), zap.String("key", hex.EncodeToString(cfg.Key())),
zap.String("value", hex.EncodeToString(cfg.Value()))) zap.String("value", hex.EncodeToString(cfg.Value())))
@ -81,11 +80,11 @@ func (np *Processor) handleConfig(ctx context.Context, ev event.Event) {
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_config", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_config", func() bool {
return np.processConfig(ctx, cfg) return np.processConfig(cfg)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }

View file

@ -1,7 +1,6 @@
package frostfs package frostfs
import ( import (
"context"
"testing" "testing"
"time" "time"
@ -37,7 +36,7 @@ func TestHandleDeposit(t *testing.T) {
AmountValue: 1000, AmountValue: 1000,
} }
proc.handleDeposit(context.Background(), ev) proc.handleDeposit(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -58,7 +57,7 @@ func TestHandleDeposit(t *testing.T) {
es.epochCounter = 109 es.epochCounter = 109
proc.handleDeposit(context.Background(), ev) proc.handleDeposit(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -99,7 +98,7 @@ func TestHandleWithdraw(t *testing.T) {
AmountValue: 1000, AmountValue: 1000,
} }
proc.handleWithdraw(context.Background(), ev) proc.handleWithdraw(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -140,7 +139,7 @@ func TestHandleCheque(t *testing.T) {
LockValue: util.Uint160{200}, LockValue: util.Uint160{200},
} }
proc.handleCheque(context.Background(), ev) proc.handleCheque(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -177,7 +176,7 @@ func TestHandleConfig(t *testing.T) {
TxHashValue: util.Uint256{100}, TxHashValue: util.Uint256{100},
} }
proc.handleConfig(context.Background(), ev) proc.handleConfig(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -226,7 +225,7 @@ type testAlphabetState struct {
isAlphabet bool isAlphabet bool
} }
func (s *testAlphabetState) IsAlphabet(context.Context) bool { func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet return s.isAlphabet
} }
@ -242,17 +241,17 @@ type testBalaceClient struct {
burn []balance.BurnPrm burn []balance.BurnPrm
} }
func (c *testBalaceClient) Mint(_ context.Context, p balance.MintPrm) error { func (c *testBalaceClient) Mint(p balance.MintPrm) error {
c.mint = append(c.mint, p) c.mint = append(c.mint, p)
return nil return nil
} }
func (c *testBalaceClient) Lock(_ context.Context, p balance.LockPrm) error { func (c *testBalaceClient) Lock(p balance.LockPrm) error {
c.lock = append(c.lock, p) c.lock = append(c.lock, p)
return nil return nil
} }
func (c *testBalaceClient) Burn(_ context.Context, p balance.BurnPrm) error { func (c *testBalaceClient) Burn(p balance.BurnPrm) error {
c.burn = append(c.burn, p) c.burn = append(c.burn, p)
return nil return nil
} }
@ -261,7 +260,7 @@ type testNetmapClient struct {
config []nmClient.SetConfigPrm config []nmClient.SetConfigPrm
} }
func (c *testNetmapClient) SetConfig(_ context.Context, p nmClient.SetConfigPrm) error { func (c *testNetmapClient) SetConfig(p nmClient.SetConfigPrm) error {
c.config = append(c.config, p) c.config = append(c.config, p)
return nil return nil
} }

View file

@ -1,8 +1,6 @@
package frostfs package frostfs
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance"
frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs"
@ -17,9 +15,9 @@ const (
// Process deposit event by invoking a balance contract and sending native // Process deposit event by invoking a balance contract and sending native
// gas in the sidechain. // gas in the sidechain.
func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.Deposit) bool { func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool {
if !np.alphabetState.IsAlphabet(ctx) { if !np.alphabetState.IsAlphabet() {
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreDeposit) np.log.Info(logs.FrostFSNonAlphabetModeIgnoreDeposit)
return true return true
} }
@ -30,9 +28,9 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De
prm.SetID(deposit.ID()) prm.SetID(deposit.ID())
// send transferX to a balance contract // send transferX to a balance contract
err := np.balanceClient.Mint(ctx, prm) err := np.balanceClient.Mint(prm)
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err)) np.log.Error(logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err))
} }
curEpoch := np.epochState.EpochCounter() curEpoch := np.epochState.EpochCounter()
@ -46,7 +44,7 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De
val, ok := np.mintEmitCache.Get(receiver.String()) val, ok := np.mintEmitCache.Get(receiver.String())
if ok && val+np.mintEmitThreshold >= curEpoch { if ok && val+np.mintEmitThreshold >= curEpoch {
np.log.Warn(ctx, logs.FrostFSDoubleMintEmissionDeclined, np.log.Warn(logs.FrostFSDoubleMintEmissionDeclined,
zap.Stringer("receiver", receiver), zap.Stringer("receiver", receiver),
zap.Uint64("last_emission", val), zap.Uint64("last_emission", val),
zap.Uint64("current_epoch", curEpoch)) zap.Uint64("current_epoch", curEpoch))
@ -58,12 +56,12 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De
// before gas transfer check if the balance is greater than the threshold // before gas transfer check if the balance is greater than the threshold
balance, err := np.morphClient.GasBalance() balance, err := np.morphClient.GasBalance()
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err)) np.log.Error(logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err))
return false return false
} }
if balance < np.gasBalanceThreshold { if balance < np.gasBalanceThreshold {
np.log.Warn(ctx, logs.FrostFSGasBalanceThresholdHasBeenReached, np.log.Warn(logs.FrostFSGasBalanceThresholdHasBeenReached,
zap.Int64("balance", balance), zap.Int64("balance", balance),
zap.Int64("threshold", np.gasBalanceThreshold)) zap.Int64("threshold", np.gasBalanceThreshold))
@ -72,7 +70,7 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De
err = np.morphClient.TransferGas(receiver, np.mintEmitValue) err = np.morphClient.TransferGas(receiver, np.mintEmitValue)
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantTransferNativeGasToReceiver, np.log.Error(logs.FrostFSCantTransferNativeGasToReceiver,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
@ -84,16 +82,16 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De
} }
// Process withdraw event by locking assets in the balance account. // Process withdraw event by locking assets in the balance account.
func (np *Processor) processWithdraw(ctx context.Context, withdraw frostfsEvent.Withdraw) bool { func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool {
if !np.alphabetState.IsAlphabet(ctx) { if !np.alphabetState.IsAlphabet() {
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreWithdraw) np.log.Info(logs.FrostFSNonAlphabetModeIgnoreWithdraw)
return true return true
} }
// create lock account // create lock account
lock, err := util.Uint160DecodeBytesBE(withdraw.ID()[:util.Uint160Size]) lock, err := util.Uint160DecodeBytesBE(withdraw.ID()[:util.Uint160Size])
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantCreateLockAccount, zap.Error(err)) np.log.Error(logs.FrostFSCantCreateLockAccount, zap.Error(err))
return false return false
} }
@ -107,9 +105,9 @@ func (np *Processor) processWithdraw(ctx context.Context, withdraw frostfsEvent.
prm.SetAmount(np.converter.ToBalancePrecision(withdraw.Amount())) prm.SetAmount(np.converter.ToBalancePrecision(withdraw.Amount()))
prm.SetDueEpoch(int64(curEpoch + lockAccountLifetime)) prm.SetDueEpoch(int64(curEpoch + lockAccountLifetime))
err = np.balanceClient.Lock(ctx, prm) err = np.balanceClient.Lock(prm)
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err)) np.log.Error(logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err))
return false return false
} }
@ -118,9 +116,9 @@ func (np *Processor) processWithdraw(ctx context.Context, withdraw frostfsEvent.
// Process cheque event by transferring assets from the lock account back to // Process cheque event by transferring assets from the lock account back to
// the reserve account. // the reserve account.
func (np *Processor) processCheque(ctx context.Context, cheque frostfsEvent.Cheque) bool { func (np *Processor) processCheque(cheque frostfsEvent.Cheque) bool {
if !np.alphabetState.IsAlphabet(ctx) { if !np.alphabetState.IsAlphabet() {
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreCheque) np.log.Info(logs.FrostFSNonAlphabetModeIgnoreCheque)
return true return true
} }
@ -130,9 +128,9 @@ func (np *Processor) processCheque(ctx context.Context, cheque frostfsEvent.Cheq
prm.SetAmount(np.converter.ToBalancePrecision(cheque.Amount())) prm.SetAmount(np.converter.ToBalancePrecision(cheque.Amount()))
prm.SetID(cheque.ID()) prm.SetID(cheque.ID())
err := np.balanceClient.Burn(ctx, prm) err := np.balanceClient.Burn(prm)
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err)) np.log.Error(logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err))
return false return false
} }

View file

@ -1,8 +1,6 @@
package frostfs package frostfs
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs"
@ -11,9 +9,9 @@ import (
// Process config event by setting configuration value from the mainchain in // Process config event by setting configuration value from the mainchain in
// the sidechain. // the sidechain.
func (np *Processor) processConfig(ctx context.Context, config frostfsEvent.Config) bool { func (np *Processor) processConfig(config frostfsEvent.Config) bool {
if !np.alphabetState.IsAlphabet(ctx) { if !np.alphabetState.IsAlphabet() {
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreConfig) np.log.Info(logs.FrostFSNonAlphabetModeIgnoreConfig)
return true return true
} }
@ -24,9 +22,9 @@ func (np *Processor) processConfig(ctx context.Context, config frostfsEvent.Conf
prm.SetValue(config.Value()) prm.SetValue(config.Value())
prm.SetHash(config.TxHash()) prm.SetHash(config.TxHash())
err := np.netmapClient.SetConfig(ctx, prm) err := np.netmapClient.SetConfig(prm)
if err != nil { if err != nil {
np.log.Error(ctx, logs.FrostFSCantRelaySetConfigEvent, zap.Error(err)) np.log.Error(logs.FrostFSCantRelaySetConfigEvent, zap.Error(err))
return false return false
} }

View file

@ -1,11 +1,11 @@
package frostfs package frostfs
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance"
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
@ -16,6 +16,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"go.uber.org/zap"
) )
type ( type (
@ -26,7 +27,7 @@ type (
// AlphabetState is a callback interface for inner ring global state. // AlphabetState is a callback interface for inner ring global state.
AlphabetState interface { AlphabetState interface {
IsAlphabet(context.Context) bool IsAlphabet() bool
} }
// PrecisionConverter converts balance amount values. // PrecisionConverter converts balance amount values.
@ -35,13 +36,13 @@ type (
} }
BalanceClient interface { BalanceClient interface {
Mint(ctx context.Context, p balance.MintPrm) error Mint(p balance.MintPrm) error
Lock(ctx context.Context, p balance.LockPrm) error Lock(p balance.LockPrm) error
Burn(ctx context.Context, p balance.BurnPrm) error Burn(p balance.BurnPrm) error
} }
NetmapClient interface { NetmapClient interface {
SetConfig(ctx context.Context, p nmClient.SetConfigPrm) error SetConfig(p nmClient.SetConfigPrm) error
} }
MorphClient interface { MorphClient interface {
@ -109,6 +110,8 @@ func New(p *Params) (*Processor, error) {
return nil, errors.New("ir/frostfs: balance precision converter is not set") return nil, errors.New("ir/frostfs: balance precision converter is not set")
} }
p.Log.Debug(logs.FrostFSFrostfsWorkerPool, zap.Int("size", p.PoolSize))
pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true))
if err != nil { if err != nil {
return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err) return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err)

View file

@ -1,8 +1,6 @@
package governance package governance
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
@ -13,7 +11,7 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (gp *Processor) HandleAlphabetSync(ctx context.Context, e event.Event) { func (gp *Processor) HandleAlphabetSync(e event.Event) {
var ( var (
typ string typ string
hash util.Uint256 hash util.Uint256
@ -34,16 +32,16 @@ func (gp *Processor) HandleAlphabetSync(ctx context.Context, e event.Event) {
return return
} }
gp.log.Info(ctx, logs.GovernanceNewEvent, zap.String("type", typ)) gp.log.Info(logs.GovernanceNewEvent, zap.String("type", typ))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(gp.pool, gp.metrics, "alphabet_sync", func() bool { err := processors.SubmitEvent(gp.pool, gp.metrics, "alphabet_sync", func() bool {
return gp.processAlphabetSync(ctx, hash) return gp.processAlphabetSync(hash)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
gp.log.Warn(ctx, logs.GovernanceGovernanceWorkerPoolDrained, gp.log.Warn(logs.GovernanceGovernanceWorkerPoolDrained,
zap.Int("capacity", gp.pool.Cap())) zap.Int("capacity", gp.pool.Cap()))
} }
} }

View file

@ -1,7 +1,6 @@
package governance package governance
import ( import (
"context"
"encoding/binary" "encoding/binary"
"sort" "sort"
"testing" "testing"
@ -58,7 +57,7 @@ func TestHandleAlphabetSyncEvent(t *testing.T) {
txHash: util.Uint256{100}, txHash: util.Uint256{100},
} }
proc.HandleAlphabetSync(context.Background(), ev) proc.HandleAlphabetSync(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -134,7 +133,7 @@ func TestHandleAlphabetDesignateEvent(t *testing.T) {
Role: noderoles.NeoFSAlphabet, Role: noderoles.NeoFSAlphabet,
} }
proc.HandleAlphabetSync(context.Background(), ev) proc.HandleAlphabetSync(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -219,7 +218,7 @@ type testAlphabetState struct {
isAlphabet bool isAlphabet bool
} }
func (s *testAlphabetState) IsAlphabet(context.Context) bool { func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet return s.isAlphabet
} }
@ -227,7 +226,7 @@ type testVoter struct {
votes []VoteValidatorPrm votes []VoteValidatorPrm
} }
func (v *testVoter) VoteForSidechainValidator(_ context.Context, prm VoteValidatorPrm) error { func (v *testVoter) VoteForSidechainValidator(prm VoteValidatorPrm) error {
v.votes = append(v.votes, prm) v.votes = append(v.votes, prm)
return nil return nil
} }
@ -251,12 +250,12 @@ func (c *testMorphClient) Committee() (res keys.PublicKeys, err error) {
return c.commiteeKeys, nil return c.commiteeKeys, nil
} }
func (c *testMorphClient) UpdateNeoFSAlphabetList(_ context.Context, prm client.UpdateAlphabetListPrm) error { func (c *testMorphClient) UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error {
c.alphabetUpdates = append(c.alphabetUpdates, prm) c.alphabetUpdates = append(c.alphabetUpdates, prm)
return nil return nil
} }
func (c *testMorphClient) UpdateNotaryList(_ context.Context, prm client.UpdateNotaryListPrm) error { func (c *testMorphClient) UpdateNotaryList(prm client.UpdateNotaryListPrm) error {
c.notaryUpdates = append(c.notaryUpdates, prm) c.notaryUpdates = append(c.notaryUpdates, prm)
return nil return nil
} }
@ -278,7 +277,7 @@ type testFrostFSClient struct {
updates []frostfscontract.AlphabetUpdatePrm updates []frostfscontract.AlphabetUpdatePrm
} }
func (c *testFrostFSClient) AlphabetUpdate(_ context.Context, p frostfscontract.AlphabetUpdatePrm) error { func (c *testFrostFSClient) AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error {
c.updates = append(c.updates, p) c.updates = append(c.updates, p)
return nil return nil
} }

View file

@ -1,7 +1,6 @@
package governance package governance
import ( import (
"context"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"sort" "sort"
@ -19,39 +18,39 @@ const (
alphabetUpdateIDPrefix = "AlphabetUpdate" alphabetUpdateIDPrefix = "AlphabetUpdate"
) )
func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint256) bool { func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool {
if !gp.alphabetState.IsAlphabet(ctx) { if !gp.alphabetState.IsAlphabet() {
gp.log.Info(ctx, logs.GovernanceNonAlphabetModeIgnoreAlphabetSync) gp.log.Info(logs.GovernanceNonAlphabetModeIgnoreAlphabetSync)
return true return true
} }
mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList() mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList()
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromMainNet, gp.log.Error(logs.GovernanceCantFetchAlphabetListFromMainNet,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
} }
sidechainAlphabet, err := gp.morphClient.Committee() sidechainAlphabet, err := gp.morphClient.Committee()
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromSideChain, gp.log.Error(logs.GovernanceCantFetchAlphabetListFromSideChain,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
} }
newAlphabet, err := newAlphabetList(sidechainAlphabet, mainnetAlphabet) newAlphabet, err := newAlphabetList(sidechainAlphabet, mainnetAlphabet)
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain, gp.log.Error(logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
} }
if newAlphabet == nil { if newAlphabet == nil {
gp.log.Info(ctx, logs.GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged) gp.log.Info(logs.GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged)
return true return true
} }
gp.log.Info(ctx, logs.GovernanceAlphabetListHasBeenChangedStartingUpdate, gp.log.Info(logs.GovernanceAlphabetListHasBeenChangedStartingUpdate,
zap.String("side_chain_alphabet", prettyKeys(sidechainAlphabet)), zap.String("side_chain_alphabet", prettyKeys(sidechainAlphabet)),
zap.String("new_alphabet", prettyKeys(newAlphabet)), zap.String("new_alphabet", prettyKeys(newAlphabet)),
) )
@ -62,22 +61,22 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25
} }
// 1. Vote to sidechain committee via alphabet contracts. // 1. Vote to sidechain committee via alphabet contracts.
err = gp.voter.VoteForSidechainValidator(ctx, votePrm) err = gp.voter.VoteForSidechainValidator(votePrm)
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantVoteForSideChainCommittee, gp.log.Error(logs.GovernanceCantVoteForSideChainCommittee,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }
// 2. Update NeoFSAlphabet role in the sidechain. // 2. Update NeoFSAlphabet role in the sidechain.
gp.updateNeoFSAlphabetRoleInSidechain(ctx, sidechainAlphabet, newAlphabet, txHash) gp.updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAlphabet, txHash)
// 3. Update notary role in the sidechain. // 3. Update notary role in the sidechain.
gp.updateNotaryRoleInSidechain(ctx, newAlphabet, txHash) gp.updateNotaryRoleInSidechain(newAlphabet, txHash)
// 4. Update FrostFS contract in the mainnet. // 4. Update FrostFS contract in the mainnet.
gp.updateFrostFSContractInMainnet(ctx, newAlphabet) gp.updateFrostFSContractInMainnet(newAlphabet)
gp.log.Info(ctx, logs.GovernanceFinishedAlphabetListUpdate) gp.log.Info(logs.GovernanceFinishedAlphabetListUpdate)
return true return true
} }
@ -94,24 +93,24 @@ func prettyKeys(keys keys.PublicKeys) string {
return strings.TrimRight(sb.String(), delimiter) return strings.TrimRight(sb.String(), delimiter)
} }
func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sidechainAlphabet, newAlphabet keys.PublicKeys, txHash util.Uint256) { func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAlphabet keys.PublicKeys, txHash util.Uint256) {
innerRing, err := gp.irFetcher.InnerRingKeys() innerRing, err := gp.irFetcher.InnerRingKeys()
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantFetchInnerRingListFromSideChain, gp.log.Error(logs.GovernanceCantFetchInnerRingListFromSideChain,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return return
} }
newInnerRing, err := updateInnerRing(innerRing, sidechainAlphabet, newAlphabet) newInnerRing, err := updateInnerRing(innerRing, sidechainAlphabet, newAlphabet)
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys, gp.log.Error(logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return return
} }
sort.Sort(newInnerRing) sort.Sort(newInnerRing)
gp.log.Info(ctx, logs.GovernanceUpdateOfTheInnerRingList, gp.log.Info(logs.GovernanceUpdateOfTheInnerRingList,
zap.String("before", prettyKeys(innerRing)), zap.String("before", prettyKeys(innerRing)),
zap.String("after", prettyKeys(newInnerRing)), zap.String("after", prettyKeys(newInnerRing)),
) )
@ -120,26 +119,26 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sid
updPrm.SetList(newInnerRing) updPrm.SetList(newInnerRing)
updPrm.SetHash(txHash) updPrm.SetHash(txHash)
if err = gp.morphClient.UpdateNeoFSAlphabetList(ctx, updPrm); err != nil { if err = gp.morphClient.UpdateNeoFSAlphabetList(updPrm); err != nil {
gp.log.Error(ctx, logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys, gp.log.Error(logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }
} }
func (gp *Processor) updateNotaryRoleInSidechain(ctx context.Context, newAlphabet keys.PublicKeys, txHash util.Uint256) { func (gp *Processor) updateNotaryRoleInSidechain(newAlphabet keys.PublicKeys, txHash util.Uint256) {
updPrm := client.UpdateNotaryListPrm{} updPrm := client.UpdateNotaryListPrm{}
updPrm.SetList(newAlphabet) updPrm.SetList(newAlphabet)
updPrm.SetHash(txHash) updPrm.SetHash(txHash)
err := gp.morphClient.UpdateNotaryList(ctx, updPrm) err := gp.morphClient.UpdateNotaryList(updPrm)
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantUpdateListOfNotaryNodesInSideChain, gp.log.Error(logs.GovernanceCantUpdateListOfNotaryNodesInSideChain,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }
} }
func (gp *Processor) updateFrostFSContractInMainnet(ctx context.Context, newAlphabet keys.PublicKeys) { func (gp *Processor) updateFrostFSContractInMainnet(newAlphabet keys.PublicKeys) {
epoch := gp.epochState.EpochCounter() epoch := gp.epochState.EpochCounter()
buf := make([]byte, 8) buf := make([]byte, 8)
@ -152,9 +151,9 @@ func (gp *Processor) updateFrostFSContractInMainnet(ctx context.Context, newAlph
prm.SetID(id) prm.SetID(id)
prm.SetPubs(newAlphabet) prm.SetPubs(newAlphabet)
err := gp.frostfsClient.AlphabetUpdate(ctx, prm) err := gp.frostfsClient.AlphabetUpdate(prm)
if err != nil { if err != nil {
gp.log.Error(ctx, logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract, gp.log.Error(logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }
} }

View file

@ -1,7 +1,6 @@
package governance package governance
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
@ -26,7 +25,7 @@ const ProcessorPoolSize = 1
type ( type (
// AlphabetState is a callback interface for innerring global state. // AlphabetState is a callback interface for innerring global state.
AlphabetState interface { AlphabetState interface {
IsAlphabet(context.Context) bool IsAlphabet() bool
} }
) )
@ -39,7 +38,7 @@ type VoteValidatorPrm struct {
// Voter is a callback interface for alphabet contract voting. // Voter is a callback interface for alphabet contract voting.
type Voter interface { type Voter interface {
VoteForSidechainValidator(context.Context, VoteValidatorPrm) error VoteForSidechainValidator(VoteValidatorPrm) error
} }
type ( type (
@ -56,7 +55,7 @@ type (
} }
FrostFSClient interface { FrostFSClient interface {
AlphabetUpdate(ctx context.Context, p frostfscontract.AlphabetUpdatePrm) error AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error
} }
NetmapClient interface { NetmapClient interface {
@ -70,8 +69,8 @@ type (
MorphClient interface { MorphClient interface {
Committee() (res keys.PublicKeys, err error) Committee() (res keys.PublicKeys, err error)
UpdateNeoFSAlphabetList(ctx context.Context, prm client.UpdateAlphabetListPrm) error UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error
UpdateNotaryList(ctx context.Context, prm client.UpdateNotaryListPrm) error UpdateNotaryList(prm client.UpdateNotaryListPrm) error
} }
// Processor of events related to governance in the network. // Processor of events related to governance in the network.

View file

@ -1,7 +1,6 @@
package netmap package netmap
import ( import (
"context"
"encoding/hex" "encoding/hex"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
@ -12,93 +11,93 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (np *Processor) HandleNewEpochTick(ctx context.Context, ev event.Event) { func (np *Processor) HandleNewEpochTick(ev event.Event) {
_ = ev.(timerEvent.NewEpochTick) _ = ev.(timerEvent.NewEpochTick)
np.log.Info(ctx, logs.NetmapTick, zap.String("type", "epoch")) np.log.Info(logs.NetmapTick, zap.String("type", "epoch"))
// send an event to the worker pool // send an event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch_tick", func() bool { return np.processNewEpochTick(ctx) }) err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch_tick", np.processNewEpochTick)
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, np.log.Warn(logs.NetmapNetmapWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleNewEpoch(ctx context.Context, ev event.Event) { func (np *Processor) handleNewEpoch(ev event.Event) {
epochEvent := ev.(netmapEvent.NewEpoch) epochEvent := ev.(netmapEvent.NewEpoch)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "new epoch"), zap.String("type", "new epoch"),
zap.Uint64("value", epochEvent.EpochNumber())) zap.Uint64("value", epochEvent.EpochNumber()))
// send an event to the worker pool // send an event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch", func() bool {
return np.processNewEpoch(ctx, epochEvent) return np.processNewEpoch(epochEvent)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, np.log.Warn(logs.NetmapNetmapWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleAddPeer(ctx context.Context, ev event.Event) { func (np *Processor) handleAddPeer(ev event.Event) {
newPeer := ev.(netmapEvent.AddPeer) newPeer := ev.(netmapEvent.AddPeer)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "add peer"), zap.String("type", "add peer"),
) )
// send an event to the worker pool // send an event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "netmap_add_peer", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "netmap_add_peer", func() bool {
return np.processAddPeer(ctx, newPeer) return np.processAddPeer(newPeer)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, np.log.Warn(logs.NetmapNetmapWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleUpdateState(ctx context.Context, ev event.Event) { func (np *Processor) handleUpdateState(ev event.Event) {
updPeer := ev.(netmapEvent.UpdatePeer) updPeer := ev.(netmapEvent.UpdatePeer)
np.log.Info(ctx, logs.Notification, np.log.Info(logs.Notification,
zap.String("type", "update peer state"), zap.String("type", "update peer state"),
zap.String("key", hex.EncodeToString(updPeer.PublicKey().Bytes()))) zap.String("key", hex.EncodeToString(updPeer.PublicKey().Bytes())))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "netmap_update_peer", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "netmap_update_peer", func() bool {
return np.processUpdatePeer(ctx, updPeer) return np.processUpdatePeer(updPeer)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, np.log.Warn(logs.NetmapNetmapWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }
func (np *Processor) handleCleanupTick(ctx context.Context, ev event.Event) { func (np *Processor) handleCleanupTick(ev event.Event) {
if !np.netmapSnapshot.enabled { if !np.netmapSnapshot.enabled {
np.log.Debug(ctx, logs.NetmapNetmapCleanUpRoutineIsDisabled518) np.log.Debug(logs.NetmapNetmapCleanUpRoutineIsDisabled518)
return return
} }
cleanup := ev.(netmapCleanupTick) cleanup := ev.(netmapCleanupTick)
np.log.Info(ctx, logs.NetmapTick, zap.String("type", "netmap cleaner")) np.log.Info(logs.NetmapTick, zap.String("type", "netmap cleaner"))
// send event to the worker pool // send event to the worker pool
err := processors.SubmitEvent(np.pool, np.metrics, "netmap_cleanup_tick", func() bool { err := processors.SubmitEvent(np.pool, np.metrics, "netmap_cleanup_tick", func() bool {
return np.processNetmapCleanupTick(ctx, cleanup) return np.processNetmapCleanupTick(cleanup)
}) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, np.log.Warn(logs.NetmapNetmapWorkerPoolDrained,
zap.Int("capacity", np.pool.Cap())) zap.Int("capacity", np.pool.Cap()))
} }
} }

View file

@ -1,7 +1,6 @@
package netmap package netmap
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
"time" "time"
@ -39,7 +38,7 @@ func TestNewEpochTick(t *testing.T) {
require.NoError(t, err, "failed to create processor") require.NoError(t, err, "failed to create processor")
ev := timerEvent.NewEpochTick{} ev := timerEvent.NewEpochTick{}
proc.HandleNewEpochTick(context.Background(), ev) proc.HandleNewEpochTick(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -91,7 +90,7 @@ func TestNewEpoch(t *testing.T) {
Num: 101, Num: 101,
Hash: util.Uint256{101}, Hash: util.Uint256{101},
} }
proc.handleNewEpoch(context.Background(), ev) proc.handleNewEpoch(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -131,7 +130,7 @@ func TestAddPeer(t *testing.T) {
MainTransaction: &transaction.Transaction{}, MainTransaction: &transaction.Transaction{},
}, },
} }
proc.handleAddPeer(context.Background(), ev) proc.handleAddPeer(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -146,7 +145,7 @@ func TestAddPeer(t *testing.T) {
MainTransaction: &transaction.Transaction{}, MainTransaction: &transaction.Transaction{},
}, },
} }
proc.handleAddPeer(context.Background(), ev) proc.handleAddPeer(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -189,7 +188,7 @@ func TestUpdateState(t *testing.T) {
MainTransaction: &transaction.Transaction{}, MainTransaction: &transaction.Transaction{},
}, },
} }
proc.handleUpdateState(context.Background(), ev) proc.handleUpdateState(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -233,7 +232,7 @@ func TestCleanupTick(t *testing.T) {
txHash: util.Uint256{123}, txHash: util.Uint256{123},
} }
proc.handleCleanupTick(context.Background(), ev) proc.handleCleanupTick(ev)
for proc.pool.Running() > 0 { for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
@ -341,7 +340,7 @@ type testAlphabetState struct {
isAlphabet bool isAlphabet bool
} }
func (s *testAlphabetState) IsAlphabet(context.Context) bool { func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet return s.isAlphabet
} }
@ -365,7 +364,7 @@ type testNetmapClient struct {
invokedTxs []*transaction.Transaction invokedTxs []*transaction.Transaction
} }
func (c *testNetmapClient) MorphNotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { func (c *testNetmapClient) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error {
c.notaryInvokes = append(c.notaryInvokes, notaryInvoke{ c.notaryInvokes = append(c.notaryInvokes, notaryInvoke{
contract: contract, contract: contract,
fee: fee, fee: fee,
@ -396,7 +395,7 @@ func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) {
return c.netmap, nil return c.netmap, nil
} }
func (c *testNetmapClient) NewEpoch(_ context.Context, epoch uint64) error { func (c *testNetmapClient) NewEpoch(epoch uint64) error {
c.newEpochs = append(c.newEpochs, epoch) c.newEpochs = append(c.newEpochs, epoch)
return nil return nil
} }
@ -414,6 +413,6 @@ type testEventHandler struct {
handledEvents []event.Event handledEvents []event.Event
} }
func (h *testEventHandler) Handle(_ context.Context, e event.Event) { func (h *testEventHandler) Handle(e event.Event) {
h.handledEvents = append(h.handledEvents, e) h.handledEvents = append(h.handledEvents, e)
} }

View file

@ -1,17 +1,15 @@
package netmap package netmap
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"go.uber.org/zap" "go.uber.org/zap"
) )
func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapCleanupTick) bool { func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool {
if !np.alphabetState.IsAlphabet(ctx) { if !np.alphabetState.IsAlphabet() {
np.log.Info(ctx, logs.NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick) np.log.Info(logs.NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick)
return true return true
} }
@ -19,13 +17,13 @@ func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapClea
err := np.netmapSnapshot.forEachRemoveCandidate(ev.epoch, func(s string) error { err := np.netmapSnapshot.forEachRemoveCandidate(ev.epoch, func(s string) error {
key, err := keys.NewPublicKeyFromString(s) key, err := keys.NewPublicKeyFromString(s)
if err != nil { if err != nil {
np.log.Warn(ctx, logs.NetmapCantDecodePublicKeyOfNetmapNode, np.log.Warn(logs.NetmapCantDecodePublicKeyOfNetmapNode,
zap.String("key", s)) zap.String("key", s))
return nil return nil
} }
np.log.Info(ctx, logs.NetmapVoteToRemoveNodeFromNetmap, zap.String("key", s)) np.log.Info(logs.NetmapVoteToRemoveNodeFromNetmap, zap.String("key", s))
// In notary environments we call UpdateStateIR method instead of UpdateState. // In notary environments we call UpdateStateIR method instead of UpdateState.
// It differs from UpdateState only by name, so we can do this in the same form. // It differs from UpdateState only by name, so we can do this in the same form.
@ -33,7 +31,6 @@ func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapClea
const methodUpdateStateNotary = "updateStateIR" const methodUpdateStateNotary = "updateStateIR"
err = np.netmapClient.MorphNotaryInvoke( err = np.netmapClient.MorphNotaryInvoke(
ctx,
np.netmapClient.ContractAddress(), np.netmapClient.ContractAddress(),
0, 0,
uint32(ev.epoch), uint32(ev.epoch),
@ -42,13 +39,13 @@ func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapClea
int64(v2netmap.Offline), key.Bytes(), int64(v2netmap.Offline), key.Bytes(),
) )
if err != nil { if err != nil {
np.log.Error(ctx, logs.NetmapCantInvokeNetmapUpdateState, zap.Error(err)) np.log.Error(logs.NetmapCantInvokeNetmapUpdateState, zap.Error(err))
} }
return nil return nil
}) })
if err != nil { if err != nil {
np.log.Warn(ctx, logs.NetmapCantIterateOnNetmapCleanerCache, np.log.Warn(logs.NetmapCantIterateOnNetmapCleanerCache,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
} }

Some files were not shown because too many files have changed in this diff Show more