Compare commits

...

59 commits

Author SHA1 Message Date
1ed7ab75fb [#1517] cli: Print the reason of ape manager error
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-22 15:24:32 +03:00
99f9e59de9 [#1514] adm: Remove --alphabet-wallets flag from readonly commands
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 14:37:34 +00:00
256f96e252 [#1514] adm/nns: Rename getRPCClient() to nnsWriter()
Make it more specific and similar to nnsReader().

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 14:37:34 +00:00
e5ea95c045 [#1514] adm/nns: Do not return hash from getRPCClient()
It was unused and we employ better abstractions now.
gopatch:
```
@@
var a, b expression
@@
-a, b, _ := getRPCClient(...)
+a, b := getRPCClient(...)
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 14:37:34 +00:00
9073e555db [#1514] adm/nns: Do not create actor for readonly commands
`nns get-records` and `nns tokens` command do not need to sign anything,
so remove useless actor and use invoker directly.
`NewLocalActor()` is only used in `ape` and `nns` packages. `ape`
package seem to use it correctly, only when alphabet wallets are
provided, so no changes there.
Also, remove --alphabet-wallets flag from commands that do not need it.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 14:37:34 +00:00
2771fdb8c7 [#1514] adm/nns: Use nns.GetAllRecords() wrapper
It was not possible previously, because GetAllRecords() was not declared
safe in frostfs-contract.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 14:37:34 +00:00
efa4ce00b8 [#1514] go.mod: Update frostfs-contract to v0.21.0-rc.3
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 14:37:34 +00:00
f12f04199e [#1516] traverser: Check for placement vector out of range
Placement vector may contain fewer nodes count than it required by policy
due to the outage of the one of the node.

Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-11-21 14:18:55 +03:00
2e2c62147d
[#1513] adm: Move ProtoConfigPath from constants to commonflags package
Refs #932

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-21 09:39:06 +03:00
6ae8667fb4
[#1509] .forgejo: Run actions on push to master
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-20 11:42:12 +03:00
49a4e727fd [#1507] timer/test: Use const for constants
Make it easy to see what the test is about.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-20 08:36:25 +00:00
2e974f734c [#1507] timer/test: Improve test coverage
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-20 08:36:25 +00:00
3042490340 [#1507] timer: Remove unused OnDelta() method
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-20 08:36:25 +00:00
a339b52a60 [#1501] adm: Refactor APE-chains managing subcommands
* Use `cmd/internal/common/ape` parser commands within `ape`
  subcommands
* Use flag names from `cmd/internal/common/ape

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
4ab4ed6f96 [#1501] cli: Refactor bearer subcommand
* Use `cmd/internal/common/ape` parser commands within `generate-ape-override`
  subcommand
* Use flag names from `cmd/internal/common/ape`

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
3b1364e4cf [#1501] cli: Refactor ape-manager subcommands
* Refactor ape-manager subcommands
* Use `cmd/internal/common/ape` parser commands within ape-manager subcommands
* Use flag names from `cmd/internal/common/ape`

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
daff77b273 [#1501] cli: Refactor local override managing subcommands
* Refactor local override managing subcommands
* Use `cmd/internal/common/ape` parser commands within local
  override subcommands
* Use flag names from `cmd/internal/common/ape`

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
7a7ee71a4d [#1501] cmd: Introduce common APE-chain parser commands
* Introduce common parsing commands to use them in `frostfs-cli`
  and `frostfs-adm` APE-related subcommands
* Introduce common flags for these parsing commands

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
ffe9906266 [#1501] cli: Move APE-chain parser methods to pkg/util
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
ae31ef3602 [#1501] cli: Move PrintHumanReadableAPEChain to a common package
* Both `frostfs-cli` and `frostfs-adm` APE-related subcommands use
  `PrintHumanReadableAPEChain` to print a parsed APE-chain. So, it's
  more correct to have it in a common package over `frostfs-cli` and
  `frostfs-adm` folders.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
e2cb0640f1 [#1501] util: Move eACL-to-APE converter to pkg/util
* `ConvertEACLToAPE` is useful method which couldn't be imported
  out of frostfs-node so far as it has been in `internal`
* Since `ConvertEACLToAPE` and related structures and unit-tests
  are placed in `pkg/util`

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-20 07:58:32 +00:00
9f4ce600ac
[#1505] adm: Allow to manage additional keys in frostfsid
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-19 16:25:16 +03:00
d82f0d1926
[#1496] node/control: Await until SetNetmapStatus() persists
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-15 16:36:07 +03:00
acd5babd86
[#1496] morph: Merge InvokeRes and WaitParams
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-15 16:36:07 +03:00
b65874d1c3
[#1496] morph: Return InvokeRes from all invoke*() methods
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-15 16:36:07 +03:00
69c63006da
[#1496] morph: Move tx waiter to morph package
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-15 16:36:07 +03:00
d77a218f7c [#1493] metabase: Merge Inhume() and DropGraves() for tombstones
DropGraves() is only used to drop gravemarks after a tombstone
removal. Thus, it makes sense to do Inhume() and DropGraves() in one
transaction. It has less overhead and no unexpected problems in case
of sudden power failure.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-14 06:47:04 +00:00
44df67492f [#1493] metabase: Split inhumeTx() into 2 functions
No functional changes.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-14 06:47:04 +00:00
1e6f132b4e [#1493] metabase: Pass InhumePrm by value
Unify with the other code, no functional changes.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-14 06:47:04 +00:00
6dc0dc6691 [#1493] shard: Take mode mutex in HandleExpiredTombstones()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-14 06:47:04 +00:00
f7cb6b4d87 [#1482] Makefile: Update golangci-lint
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-11-13 15:01:41 +00:00
7fc6101bec
[#1491] engine/test: Rework engine test utils
- Remove `testNewShard` and `setInitializedShards` because they
violated the default engine workflow. The correct workflow is:
first use `New()`, followed by `Open()`, and then `Init()`. As a
result, adding new logic to `(*StorageEngine).Init` caused several
tests to fail with a panic when attempting to access uninitialized
resources. Now, all engines created with the test utils must be
initialized manually. The new helper method `prepare` can be used
for that purpose.
- Additionally, `setInitializedShards` hardcoded the shard worker
pool size, which prevented it from being configured in tests and
benchmarks. This has been fixed as well.
- Ensure engine initialization is done wherever it was missing.
- Refactor `setShardsNumOpts`, `setShardsNumAdditionalOpts`, and
`setShardsNum`. Make them all depend on `setShardsNumOpts`.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-11-13 14:42:53 +03:00
7ef36749d0
[#1491] engine/test: Move BenchmarkExists to exists_test.go
Move `BenchmarkExists` from `engine_test.go` to `exists_test.go`
for better organization and clarity.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-11-13 14:09:29 +03:00
c6066d6ee4
[#1491] engine/test: Use more suitable testing utils here and there
Use `setShardsNum` instead of `setInitializedShards` wherever possible.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-11-13 14:09:29 +03:00
612b34d570
[#1437] logger: Add caller skip to log original caller position
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:12 +03:00
7429553266
[#1437] node: Fix contextcheck linter
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:10 +03:00
6921a89061
[#1437] ir: Fix contextcheck linters
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:10 +03:00
16598553d9
[#1437] shard: Fix contextcheck linter
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:09 +03:00
c139892117
[#1437] ir: Fix contextcheck linter
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:09 +03:00
62b5181618
[#1437] blobovnicza: Fix contextcheck linter
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:08 +03:00
6db46257c0
[#1437] node: Use ctx for logging
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-13 10:36:07 +03:00
c16dae8b4d
[#1437] logger: Use context to log trace id
Signed-off-by: Dmitrii Stepanov
2024-11-13 10:36:07 +03:00
fd004add00 [#1492] metabase: Fix import formatting
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-13 07:30:25 +00:00
8ed7a676d5 [#1492] metabase: Ensure Unmarshal() is called on a cloned slice
The slice returned from bucket.Get() is only valid during the tx
lifetime. Cloning it is not necessary everywhere, but better safe than
sorry.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-13 07:30:25 +00:00
b451de94c8 [#1492] metabase: Fix typo in objData
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-13 07:30:25 +00:00
f1556e3c42
[#1488] Makefile: Drop all containers created on env-up
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-12 17:24:44 +03:00
e122ff6013
[#1488] dev: Add Jaeger image and enable tracing on debug
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-12 17:24:44 +03:00
e2658c7519
[#1488] tracing: KV attributes for spans from config
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-12 17:24:43 +03:00
c00f4bab18
[#1488] go.mod: Bump observability version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-12 17:24:43 +03:00
46fef276b4 [#1449] tree: Log tree sync with Info level
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-12 12:11:07 +00:00
9bd05e94c8 [#1449] tree: Add ApplyBatch method
Concurrent Apply can lead to child node applies before parent, so
undo/redo operations will perform. This leads to performance degradation
in case of tree with many sublevels.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-11-12 12:11:07 +00:00
16830033f8 [#1483] cli: Remove --basic-acl flag
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-12 12:10:51 +00:00
1cf51a8079 [#1483] cli/docs: Remove set-eacl mention
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-12 12:10:51 +00:00
3324c26fd8 [#1483] morph: Remove container.GetEACL()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-12 12:10:51 +00:00
a692298533 [#1483] node: Remove eACL cache
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-12 12:10:51 +00:00
be2753de00 [#1490] docs: Update description for object.get.priority
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-11-12 13:35:13 +03:00
b543569c3f [#1486] node: Introduce dual service support
* Register GRPC services for both neo.fs.v2 and frost.fs namespaces
* Use this temporary solution until all nodes are updated

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-12 08:43:47 +00:00
80f8a8fd3a
[#1396] cli/playground: Refactor
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-11-12 11:09:27 +03:00
2f3bc6eb84
[#1396] cli/playground: Improve terminal control key handling
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-11-12 11:07:48 +03:00
384 changed files with 3439 additions and 3296 deletions

View file

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

View file

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

View file

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

View file

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

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.61.0 LINT_VERSION ?= 1.62.0
TRUECLOUDLAB_LINT_VERSION ?= 0.0.7 TRUECLOUDLAB_LINT_VERSION ?= 0.0.8
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
@ -282,7 +282,6 @@ env-up: all
# Shutdown dev environment # Shutdown dev environment
env-down: env-down:
docker compose -f dev/docker-compose.yml down docker compose -f dev/docker-compose.yml down -v
docker volume rm -f frostfs-node_neo-go
rm -rf ./$(TMP_DIR)/state rm -rf ./$(TMP_DIR)/state
rm -rf ./$(TMP_DIR)/storage rm -rf ./$(TMP_DIR)/storage

View file

@ -98,7 +98,7 @@ See `frostfs-contract`'s README.md for build instructions.
4. To create container and put object into it run (container and object IDs will be different): 4. To create container and put object into it run (container and object IDs will be different):
``` ```
./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --basic-acl public-read-write --await ./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --await
Enter password > <- press ENTER, the is no password for wallet Enter password > <- press ENTER, the is no password for wallet
CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju

View file

@ -20,6 +20,7 @@ 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,8 +5,8 @@ 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/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -14,26 +14,10 @@ import (
) )
const ( const (
namespaceTarget = "namespace" jsonFlag = "json"
containerTarget = "container" jsonFlagDesc = "Output rule chains in JSON format"
userTarget = "user" addrAdminFlag = "addr"
groupTarget = "group" addrAdminDesc = "The address of the admins wallet"
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 (
@ -101,17 +85,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(targetTypeFlag, "", targetTypeDesc) addRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag) _ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
addRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) addRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetTypeFlagDesc)
_ = addRuleChainCmd.MarkFlagRequired(targetNameFlag) _ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag)
addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) addRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
_ = addRuleChainCmd.MarkFlagRequired(chainIDFlag) _ = addRuleChainCmd.MarkFlagRequired(apeCmd.ChainIDFlag)
addRuleChainCmd.Flags().StringArray(ruleFlag, []string{}, ruleFlagDesc) addRuleChainCmd.Flags().StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc)
addRuleChainCmd.Flags().String(pathFlag, "", pathFlagDesc) addRuleChainCmd.Flags().String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc)
addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) addRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, pathFlag) addRuleChainCmd.MarkFlagsMutuallyExclusive(apeCmd.RuleFlag, apeCmd.PathFlag)
} }
func initRemoveRuleChainCmd() { func initRemoveRuleChainCmd() {
@ -120,26 +104,25 @@ 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(targetTypeFlag, "", targetTypeDesc) removeRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag) _ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) removeRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
_ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag) _ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag)
removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) removeRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) removeRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.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, chainIDFlag) removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, apeCmd.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(targetTypeFlag, "t", "", targetTypeDesc) listRuleChainsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc)
_ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) _ = listRuleChainsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) listRuleChainsCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
_ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag)
listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc) listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc)
listRuleChainsCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) listRuleChainsCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
} }
func initSetAdminCmd() { func initSetAdminCmd() {
@ -161,15 +144,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(targetTypeFlag, "t", "", targetTypeDesc) listTargetsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc)
_ = listTargetsCmd.MarkFlagRequired(targetTypeFlag) _ = listTargetsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
} }
func addRuleChain(cmd *cobra.Command, _ []string) { func addRuleChain(cmd *cobra.Command, _ []string) {
chain := parseChain(cmd) chain := apeCmd.ParseChain(cmd)
target := parseTarget(cmd) target := parseTarget(cmd)
pci, ac := newPolicyContractInterface(cmd) pci, ac := newPolicyContractInterface(cmd)
h, vub, err := pci.AddMorphRuleChain(parseChainName(cmd), target, chain) h, vub, err := pci.AddMorphRuleChain(apeCmd.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)
@ -181,14 +164,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(parseChainName(cmd), target) h, vub, err := pci.RemoveMorphRuleChainsByTarget(apeCmd.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 := parseChainID(cmd) chainID := apeCmd.ParseChainID(cmd)
h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID) h, vub, err := pci.RemoveMorphRuleChain(apeCmd.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)
@ -199,7 +182,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(parseChainName(cmd), target) chains, err := pci.ListMorphRuleChains(apeCmd.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
@ -210,7 +193,7 @@ func listRuleChains(cmd *cobra.Command, _ []string) {
prettyJSONFormat(cmd, chains) prettyJSONFormat(cmd, chains)
} else { } else {
for _, c := range chains { for _, c := range chains {
parseutil.PrintHumanReadableAPEChain(cmd, c) apeCmd.PrintHumanReadableAPEChain(cmd, c)
} }
} }
} }
@ -235,8 +218,7 @@ func getAdmin(cmd *cobra.Command, _ []string) {
} }
func listTargets(cmd *cobra.Command, _ []string) { func listTargets(cmd *cobra.Command, _ []string) {
typ, err := parseTargetType(cmd) typ := apeCmd.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,13 +2,12 @@ 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"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
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"
@ -18,90 +17,29 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
const ( var errUnknownTargetType = errors.New("unknown target type")
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 {
name, _ := cmd.Flags().GetString(targetNameFlag) typ := apeCmd.ParseTargetType(cmd)
typ, err := parseTargetType(cmd) name, _ := cmd.Flags().GetString(apeCmd.TargetNameFlag)
// interpret "root" namespace as empty
if typ == policyengine.Namespace && name == "root" {
name = ""
}
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 { switch typ {
case namespaceTarget: case policyengine.Namespace:
return policyengine.Namespace, nil if name == "root" {
case containerTarget: name = ""
return policyengine.Container, nil }
case userTarget: return policyengine.NamespaceTarget(name)
return policyengine.User, nil case policyengine.Container:
case groupTarget: var cnr cid.ID
return policyengine.Group, nil 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)
} }
return -1, errUnknownTargetType panic("unreachable")
}
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,7 +4,6 @@ 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

@ -0,0 +1,83 @@
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,7 +61,6 @@ 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,
@ -91,7 +90,6 @@ 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,
@ -121,7 +119,6 @@ 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,
@ -151,7 +148,6 @@ 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,
@ -169,7 +165,6 @@ 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() {
@ -193,7 +188,6 @@ 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() {
@ -217,7 +211,6 @@ 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() {
@ -242,7 +235,6 @@ 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,4 +12,6 @@ func init() {
initFrostfsIDAddSubjectToGroupCmd() initFrostfsIDAddSubjectToGroupCmd()
initFrostfsIDRemoveSubjectFromGroupCmd() initFrostfsIDRemoveSubjectFromGroupCmd()
initFrostfsIDListGroupSubjectsCmd() initFrostfsIDListGroupSubjectsCmd()
initFrostfsIDAddSubjectKeyCmd()
initFrostfsIDRemoveSubjectKeyCmd()
} }

View file

@ -38,38 +38,24 @@ 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)
for _, w := range wallets { wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir)
acc, err := GetWalletAccount(w, accName) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err)
commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err)
accounts = append(accounts, acc) for _, w := range wallets {
} acc, err := GetWalletAccount(w, accName)
act, err = actor.New(c, []actor.SignerAccount{{ commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err)
Signer: transaction.Signer{ accounts = append(accounts, acc)
Account: accounts[0].Contract.ScriptHash(), }
Scopes: transaction.Global, act, err = actor.New(c, []actor.SignerAccount{{
}, Signer: transaction.Signer{
Account: accounts[0], Account: accounts[0].Contract.ScriptHash(),
}}) Scopes: transaction.Global,
if err != nil { },
return nil, err Account: accounts[0],
} }})
if err != nil {
return nil, err
} }
return &LocalActor{ return &LocalActor{
neoActor: act, neoActor: act,

View file

@ -8,6 +8,7 @@ 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"
@ -47,7 +48,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(constants.ProtoConfigPath)) cfg, err := config.LoadFile(v.GetString(commonflags.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(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) v.Set(commonflags.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,7 +2,6 @@ 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"
) )
@ -32,7 +31,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(constants.ProtoConfigPath, cmd.Flags().Lookup(constants.ProtoConfigPath)) _ = viper.BindPFlag(commonflags.ProtoConfigPath, cmd.Flags().Lookup(commonflags.ProtoConfigPath))
}, },
RunE: initializeSideChainCmd, RunE: initializeSideChainCmd,
} }
@ -48,7 +47,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(constants.ProtoConfigPath, "", "Path to the consensus node configuration") Cmd.Flags().String(commonflags.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,7 +12,6 @@ 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, _ := getRPCClient(cmd) c, actor := nnsWriter(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, _ := getRPCClient(cmd) c, actor := nnsWriter(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 getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, util.Uint160) { func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) {
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,5 +22,17 @@ func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, uti
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, nnsCs.Hash return client.New(ac, nnsCs.Hash), ac
}
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,7 +8,6 @@ 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"
) )
@ -29,7 +28,6 @@ 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)
@ -61,7 +59,7 @@ func initDelRecordCmd() {
} }
func addRecord(cmd *cobra.Command, _ []string) { func addRecord(cmd *cobra.Command, _ []string) {
c, actor, _ := getRPCClient(cmd) c, actor := nnsWriter(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)
@ -77,16 +75,16 @@ func addRecord(cmd *cobra.Command, _ []string) {
} }
func getRecords(cmd *cobra.Command, _ []string) { func getRecords(cmd *cobra.Command, _ []string) {
c, act, hash := getRPCClient(cmd) c, inv := nnsReader(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 := unwrap.SessionIterator(act.Invoker.Call(hash, "getAllRecords", name)) sid, r, err := c.GetAllRecords(name)
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
defer func() { defer func() {
_ = act.Invoker.TerminateSession(sid) _ = inv.TerminateSession(sid)
}() }()
items, err := act.Invoker.TraverseIterator(sid, &r, 0) items, err := inv.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 {
@ -97,7 +95,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 = act.Invoker.TraverseIterator(sid, &r, 0) items, err = inv.TraverseIterator(sid, &r, 0)
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
} }
} else { } else {
@ -114,7 +112,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
} }
func delRecords(cmd *cobra.Command, _ []string) { func delRecords(cmd *cobra.Command, _ []string) {
c, actor, _ := getRPCClient(cmd) c, actor := nnsWriter(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)
@ -129,7 +127,7 @@ func delRecords(cmd *cobra.Command, _ []string) {
} }
func delRecord(cmd *cobra.Command, _ []string) { func delRecord(cmd *cobra.Command, _ []string) {
c, actor, _ := getRPCClient(cmd) c, actor := nnsWriter(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, _ := getRPCClient(cmd) c, actor := nnsWriter(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,12 +18,11 @@ 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, _, _ := getRPCClient(cmd) c, _ := nnsReader(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) {
@ -41,7 +40,7 @@ func listTokens(cmd *cobra.Command, _ []string) {
} }
} }
func getCnameRecord(c *client.Contract, token []byte) (string, error) { func getCnameRecord(c *client.ContractReader, 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, _ := getRPCClient(cmd) c, actor := nnsWriter(cmd)
name, _ := cmd.Flags().GetString(nnsNameFlag) name, _ := cmd.Flags().GetString(nnsNameFlag)
email, _ := cmd.Flags().GetString(nnsEmailFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag)

View file

@ -72,4 +72,3 @@ All other `object` sub-commands support only static sessions (2).
List of commands supporting sessions (static only): List of commands supporting sessions (static only):
- `create` - `create`
- `delete` - `delete`
- `set-eacl`

View file

@ -1,44 +1,19 @@
package apemanager package apemanager
import ( import (
"encoding/hex" "fmt"
"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"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
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",
@ -49,55 +24,28 @@ var addCmd = &cobra.Command{
} }
func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) { func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) {
typ, _ := cmd.Flags().GetString(targetTypeFlag) t := apeCmd.ParseTarget(cmd)
name, _ := cmd.Flags().GetString(targetNameFlag)
ct.Name = name ct.Name = t.Name
switch typ { switch t.Type {
case namespaceTarget: case engine.Namespace:
ct.TargetType = apeSDK.TargetTypeNamespace ct.TargetType = apeSDK.TargetTypeNamespace
case containerTarget: case engine.Container:
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 userTarget: case engine.User:
ct.TargetType = apeSDK.TargetTypeUser ct.TargetType = apeSDK.TargetTypeUser
case groupTarget: case engine.Group:
ct.TargetType = apeSDK.TargetTypeGroup ct.TargetType = apeSDK.TargetTypeGroup
default: default:
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) commonCmd.ExitOnErr(cmd, "conversion error: %w", fmt.Errorf("unknown type '%c'", t.Type))
} }
return ct return ct
} }
func parseChain(cmd *cobra.Command) apeSDK.Chain { func parseChain(cmd *cobra.Command) apeSDK.Chain {
chainID, _ := cmd.Flags().GetString(chainIDFlag) c := apeCmd.ParseChain(cmd)
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) serialized := c.Bytes()
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,
} }
@ -126,13 +74,13 @@ func initAddCmd() {
commonflags.Init(addCmd) commonflags.Init(addCmd)
ff := addCmd.Flags() ff := addCmd.Flags()
ff.StringArray(ruleFlag, []string{}, "Rule statement") ff.StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc)
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") ff.String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc)
ff.String(chainIDFlag, "", "Assign ID to the parsed chain") ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = addCmd.MarkFlagRequired(targetTypeFlag) _ = addCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) addCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.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))
apeutil.PrintHumanReadableAPEChain(cmd, &chain) apeCmd.PrintHumanReadableAPEChain(cmd, &chain)
} }
} }
@ -43,7 +43,7 @@ func initListCmd() {
commonflags.Init(listCmd) commonflags.Init(listCmd)
ff := listCmd.Flags() ff := listCmd.Flags()
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = listCmd.MarkFlagRequired(targetTypeFlag) _ = listCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
} }

View file

@ -1,29 +1,23 @@
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 ( var removeCmd = &cobra.Command{
errEmptyChainID = errors.New("chain id cannot be empty") Use: "remove",
Short: "Remove rule chain for a target",
removeCmd = &cobra.Command{ Run: remove,
Use: "remove", PersistentPreRun: func(cmd *cobra.Command, _ []string) {
Short: "Remove rule chain for a target", commonflags.Bind(cmd)
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)
@ -31,19 +25,9 @@ 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, _ := cmd.Flags().GetString(chainIDFlag) chainID := apeCmd.ParseChainID(cmd)
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,
@ -58,9 +42,10 @@ func initRemoveCmd() {
commonflags.Init(removeCmd) commonflags.Init(removeCmd)
ff := removeCmd.Flags() ff := removeCmd.Flags()
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = removeCmd.MarkFlagRequired(targetTypeFlag) _ = removeCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
ff.String(chainIDFlag, "", "Chain id") ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") _ = removeCmd.MarkFlagRequired(apeCmd.ChainIDFlag)
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
} }

View file

@ -1,31 +1,20 @@
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 (
chainIDFlag = "chain-id" outputFlag = "output"
chainIDHexFlag = "chain-id-hex"
ruleFlag = "rule"
pathFlag = "path"
outputFlag = "output"
) )
var generateAPEOverrideCmd = &cobra.Command{ var generateAPEOverrideCmd = &cobra.Command{
@ -40,7 +29,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 := parseChain(cmd) c := apeCmd.ParseChain(cmd)
targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag) targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var cid cidSDK.ID var cid cidSDK.ID
@ -77,39 +66,11 @@ 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(ruleFlag, []string{}, "Rule statement") ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement")
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format")
ff.String(chainIDFlag, "", "Assign ID to the parsed chain") ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain")
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(apeCmd.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

@ -15,14 +15,12 @@ import (
containerApi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" containerApi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var ( var (
containerACL string
containerPolicy string containerPolicy string
containerAttributes []string containerAttributes []string
containerAwait bool containerAwait bool
@ -89,9 +87,6 @@ It will be stored in sidechain when inner ring will accepts it.`,
err = parseAttributes(&cnr, containerAttributes) err = parseAttributes(&cnr, containerAttributes)
commonCmd.ExitOnErr(cmd, "", err) commonCmd.ExitOnErr(cmd, "", err)
var basicACL acl.Basic
commonCmd.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL))
tok := getSession(cmd) tok := getSession(cmd)
if tok != nil { if tok != nil {
@ -105,7 +100,6 @@ It will be stored in sidechain when inner ring will accepts it.`,
} }
cnr.SetPlacementPolicy(*placementPolicy) cnr.SetPlacementPolicy(*placementPolicy)
cnr.SetBasicACL(basicACL)
var syncContainerPrm internalclient.SyncContainerPrm var syncContainerPrm internalclient.SyncContainerPrm
syncContainerPrm.SetClient(cli) syncContainerPrm.SetClient(cli)
@ -163,10 +157,6 @@ func initContainerCreateCmd() {
flags.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage) flags.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage)
flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage) flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage) flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
flags.StringVar(&containerACL, "basic-acl", acl.NamePrivate, fmt.Sprintf("HEX encoded basic ACL value or keywords like '%s', '%s', '%s'",
acl.NamePublicRW, acl.NamePrivate, acl.NamePublicROExtended,
))
flags.StringVarP(&containerPolicy, "policy", "p", "", "QL-encoded or JSON-encoded placement policy or path to file with it") flags.StringVarP(&containerPolicy, "policy", "p", "", "QL-encoded or JSON-encoded placement policy or path to file with it")
flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2") flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2")
flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted") flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted")

View file

@ -1,11 +1,10 @@
package container package container
import ( import (
"bufio"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io"
"os" "os"
"strings" "strings"
@ -14,6 +13,7 @@ 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"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"github.com/chzyer/readline"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -163,6 +163,16 @@ func (repl *policyPlaygroundREPL) netMap() netmap.NetMap {
return nm return nm
} }
var policyPlaygroundCompleter = readline.NewPrefixCompleter(
readline.PcItem("list"),
readline.PcItem("ls"),
readline.PcItem("add"),
readline.PcItem("load"),
readline.PcItem("remove"),
readline.PcItem("rm"),
readline.PcItem("eval"),
)
func (repl *policyPlaygroundREPL) run() error { func (repl *policyPlaygroundREPL) run() error {
if len(viper.GetString(commonflags.RPC)) > 0 { if len(viper.GetString(commonflags.RPC)) > 0 {
key := key.GetOrGenerate(repl.cmd) key := key.GetOrGenerate(repl.cmd)
@ -189,22 +199,38 @@ func (repl *policyPlaygroundREPL) run() error {
"rm": repl.handleRemove, "rm": repl.handleRemove,
"eval": repl.handleEval, "eval": repl.handleEval,
} }
for reader := bufio.NewReader(os.Stdin); ; {
fmt.Print("> ") rl, err := readline.NewEx(&readline.Config{
line, err := reader.ReadString('\n') Prompt: "> ",
InterruptPrompt: "^C",
AutoComplete: policyPlaygroundCompleter,
})
if err != nil {
return fmt.Errorf("error initializing readline: %w", err)
}
defer rl.Close()
var exit bool
for {
line, err := rl.Readline()
if err != nil { if err != nil {
if err == io.EOF { if errors.Is(err, readline.ErrInterrupt) {
return nil if exit {
return nil
}
exit = true
continue
} }
return fmt.Errorf("reading line: %v", err) return fmt.Errorf("reading line: %w", err)
} }
exit = false
parts := strings.Fields(line) parts := strings.Fields(line)
if len(parts) == 0 { if len(parts) == 0 {
continue continue
} }
cmd := parts[0] cmd := parts[0]
handler, exists := cmdHandlers[cmd] if handler, exists := cmdHandlers[cmd]; exists {
if exists {
if err := handler(parts[1:]); err != nil { if err := handler(parts[1:]); err != nil {
fmt.Printf("error: %v\n", err) fmt.Printf("error: %v\n", err)
} }

View file

@ -1,23 +1,14 @@
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",
@ -31,41 +22,12 @@ 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 := parseChain(cmd) parsed := apeCmd.ParseChain(cmd)
req := &control.AddChainLocalOverrideRequest{ req := &control.AddChainLocalOverrideRequest{
Body: &control.AddChainLocalOverrideRequest_Body{ Body: &control.AddChainLocalOverrideRequest_Body{
@ -94,13 +56,13 @@ func initControlAddRuleCmd() {
initControlFlags(addRuleCmd) initControlFlags(addRuleCmd)
ff := addRuleCmd.Flags() ff := addRuleCmd.Flags()
ff.StringArray(ruleFlag, []string{}, "Rule statement") ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement")
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format")
ff.String(chainIDFlag, "", "Assign ID to the parsed chain") ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain")
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = addRuleCmd.MarkFlagRequired(targetTypeFlag) _ = addRuleCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) addRuleCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.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(chainIDFlag) chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag)
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) hexEncoded, _ := cmd.Flags().GetBool(apecmd.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()))
util.PrintHumanReadableAPEChain(cmd, &chain) apecmd.PrintHumanReadableAPEChain(cmd, &chain)
} }
func initControGetRuleCmd() { func initControGetRuleCmd() {
initControlFlags(getRuleCmd) initControlFlags(getRuleCmd)
ff := getRuleCmd.Flags() ff := getRuleCmd.Flags()
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc)
_ = getRuleCmd.MarkFlagRequired(targetTypeFlag) _ = getRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag)
ff.String(chainIDFlag, "", "Chain id") ff.String(apecmd.ChainIDFlag, "", "Chain id")
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(apecmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
} }

View file

@ -1,18 +1,16 @@
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"
"github.com/nspcc-dev/neo-go/cli/input" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -23,65 +21,25 @@ var listRulesCmd = &cobra.Command{
Run: listRules, Run: listRules,
} }
const ( var engineToControlSvcType = map[policyengine.TargetType]control.ChainTarget_TargetType{
defaultNamespace = "root" policyengine.Namespace: control.ChainTarget_NAMESPACE,
namespaceTarget = "namespace" policyengine.Container: control.ChainTarget_CONTAINER,
containerTarget = "container" policyengine.User: control.ChainTarget_USER,
userTarget = "user" policyengine.Group: control.ChainTarget_GROUP,
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 {
typ, _ := cmd.Flags().GetString(targetTypeFlag) target := apeCmd.ParseTarget(cmd)
name, _ := cmd.Flags().GetString(targetNameFlag)
switch typ { typ, ok := engineToControlSvcType[target.Type]
case namespaceTarget: if !ok {
if name == "" { commonCmd.ExitOnErr(cmd, "%w", fmt.Errorf("unknown type '%c", target.Type))
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) return &control.ChainTarget{
if len(ln) > 0 && (ln[0] == 'n') { Name: target.Name,
commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined) Type: typ,
}
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) {
@ -117,7 +75,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))
util.PrintHumanReadableAPEChain(cmd, &chain) apeCmd.PrintHumanReadableAPEChain(cmd, &chain)
} }
} }
@ -125,7 +83,7 @@ func initControlListRulesCmd() {
initControlFlags(listRulesCmd) initControlFlags(listRulesCmd)
ff := listRulesCmd.Flags() ff := listRulesCmd.Flags()
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
_ = listRulesCmd.MarkFlagRequired(targetTypeFlag) _ = listRulesCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
} }

View file

@ -2,26 +2,20 @@ 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",
@ -32,15 +26,11 @@ var listTargetsCmd = &cobra.Command{
func listTargets(cmd *cobra.Command, _ []string) { func listTargets(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd) pk := key.Get(cmd)
var cnr cid.ID chainName := apeCmd.ParseChainName(cmd)
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: chainName, ChainName: string(chainName),
}, },
} }
@ -82,7 +72,7 @@ func initControlListTargetsCmd() {
initControlFlags(listTargetsCmd) initControlFlags(listTargetsCmd)
ff := listTargetsCmd.Flags() ff := listTargetsCmd.Flags()
ff.String(chainNameFlag, "", chainNameFlagUsage) ff.String(apeCmd.ChainNameFlag, "", apeCmd.ChainNameFlagDesc)
_ = cobra.MarkFlagRequired(ff, chainNameFlag) _ = cobra.MarkFlagRequired(ff, apeCmd.ChainNameFlag)
} }

View file

@ -6,17 +6,12 @@ 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")
@ -30,8 +25,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(chainIDHexFlag) hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag)
removeAll, _ := cmd.Flags().GetBool(allFlag) removeAll, _ := cmd.Flags().GetBool(apecmd.AllFlag)
if removeAll { if removeAll {
req := &control.RemoveChainLocalOverridesByTargetRequest{ req := &control.RemoveChainLocalOverridesByTargetRequest{
Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{ Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{
@ -52,7 +47,7 @@ func removeRule(cmd *cobra.Command, _ []string) {
return return
} }
chainID, _ := cmd.Flags().GetString(chainIDFlag) chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag)
if chainID == "" { if chainID == "" {
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID) commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
} }
@ -92,11 +87,11 @@ func initControlRemoveRuleCmd() {
initControlFlags(removeRuleCmd) initControlFlags(removeRuleCmd)
ff := removeRuleCmd.Flags() ff := removeRuleCmd.Flags()
ff.String(targetNameFlag, "", targetNameDesc) ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc)
_ = removeRuleCmd.MarkFlagRequired(targetTypeFlag) _ = removeRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag)
ff.String(chainIDFlag, "", "Chain id") ff.String(apecmd.ChainIDFlag, "", apecmd.ChainIDFlagDesc)
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(apecmd.ChainIDHexFlag, false, apecmd.ChainIDHexFlagDesc)
ff.Bool(allFlag, false, "Remove all chains") ff.Bool(apecmd.AllFlag, false, "Remove all chains")
removeRuleCmd.MarkFlagsMutuallyExclusive(allFlag, chainIDFlag) removeRuleCmd.MarkFlagsMutuallyExclusive(apecmd.AllFlag, apecmd.ChainIDFlag)
} }

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/internal/ape" apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/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,6 +1,7 @@
package main package main
import ( import (
"context"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
@ -46,7 +47,7 @@ func reloadConfig() error {
return logPrm.Reload() return logPrm.Reload()
} }
func watchForSignal(cancel func()) { func watchForSignal(ctx context.Context, 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)
@ -58,49 +59,49 @@ func watchForSignal(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(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
cancel() cancel()
shutdown() shutdown(ctx)
log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-intErr: // internal application error case err := <-intErr: // internal application error
log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error())) log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
cancel() cancel()
shutdown() shutdown(ctx)
return return
default: default:
// block until any signal is receieved // block until any signal is receieved
select { select {
case <-ch: case <-ch:
log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
cancel() cancel()
shutdown() shutdown(ctx)
log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-intErr: // internal application error case err := <-intErr: // internal application error
log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error())) log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
cancel() cancel()
shutdown() shutdown(ctx)
return return
case <-sighupCh: case <-sighupCh:
log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { if !innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
log.Info(logs.FrostFSNodeSIGHUPSkip) log.Info(ctx, logs.FrostFSNodeSIGHUPSkip)
break break
} }
err := reloadConfig() err := reloadConfig()
if err != nil { if err != nil {
log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err))
} }
pprofCmp.reload() pprofCmp.reload(ctx)
metricsCmp.reload() metricsCmp.reload(ctx)
log.Info(logs.FrostFSIRReloadExtraWallets) log.Info(ctx, logs.FrostFSIRReloadExtraWallets)
err = innerRing.SetExtraWallets(cfg) err = innerRing.SetExtraWallets(cfg)
if err != nil { if err != nil {
log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err))
} }
innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
} }
} }
} }

View file

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

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() pprofCmp.init(ctx)
metricsCmp = newMetricsComponent() metricsCmp = newMetricsComponent()
metricsCmp.init() metricsCmp.init(ctx)
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() pprofCmp.start(ctx)
metricsCmp.start() metricsCmp.start(ctx)
// start inner ring // start inner ring
err = innerRing.Start(ctx, intErr) err = innerRing.Start(ctx, intErr)
exitErr(err) exitErr(err)
log.Info(logs.CommonApplicationStarted, log.Info(ctx, logs.CommonApplicationStarted,
zap.String("version", misc.Version)) zap.String("version", misc.Version))
watchForSignal(cancel) watchForSignal(ctx, cancel)
<-ctx.Done() // graceful shutdown <-ctx.Done() // graceful shutdown
log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop) log.Debug(ctx, logs.FrostFSNodeWaitingForAllProcessesToStop)
wg.Wait() wg.Wait()
log.Info(logs.FrostFSIRApplicationStopped) log.Info(ctx, logs.FrostFSIRApplicationStopped)
} }
func shutdown() { func shutdown(ctx context.Context) {
innerRing.Stop() innerRing.Stop(ctx)
if err := metricsCmp.shutdown(); err != nil { if err := metricsCmp.shutdown(ctx); err != nil {
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
if err := pprofCmp.shutdown(); err != nil { if err := pprofCmp.shutdown(ctx); err != nil {
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(ctx, 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(logs.FailedToReportStatusToSystemd, zap.Error(err)) log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err))
} }
} }

View file

@ -1,6 +1,7 @@
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"
@ -28,8 +29,8 @@ func newPprofComponent() *pprofComponent {
} }
} }
func (c *pprofComponent) init() { func (c *pprofComponent) init(ctx context.Context) {
c.httpComponent.init() c.httpComponent.init(ctx)
if c.enabled { if c.enabled {
c.blockRate = cfg.GetInt(pprofBlockRateKey) c.blockRate = cfg.GetInt(pprofBlockRateKey)
@ -51,17 +52,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() { func (c *pprofComponent) reload(ctx context.Context) {
log.Info("reload " + c.name) log.Info(ctx, "reload "+c.name)
if c.needReload() { if c.needReload() {
log.Info(c.name + " config updated") log.Info(ctx, c.name+" config updated")
if err := c.shutdown(); err != nil { if err := c.shutdown(ctx); err != nil {
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return return
} }
c.init() c.init(ctx)
c.start() c.start(ctx)
} }
} }

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() defer blz.Close(cmd.Context())
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() defer blz.Close(cmd.Context())
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()) common.ExitOnErr(cmd, blz.Open(cmd.Context()))
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() defer db.Close(cmd.Context())
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() defer db.Close(cmd.Context())
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() defer db.Close(cmd.Context())
var gravePrm meta.GraveyardIterationPrm var gravePrm meta.GraveyardIterationPrm
gravePrm.SetHandler( gravePrm.SetHandler(

View file

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"net" "net"
"strings"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance"
accountingTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/accounting/grpc" accountingTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/accounting/grpc"
@ -30,5 +31,27 @@ func initAccountingService(ctx context.Context, c *cfg) {
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
accountingGRPC.RegisterAccountingServiceServer(s, server) accountingGRPC.RegisterAccountingServiceServer(s, server)
// TODO(@aarifullin): #1487 remove the dual service support.
s.RegisterService(frostFSServiceDesc(accountingGRPC.AccountingService_ServiceDesc), server)
}) })
} }
// frostFSServiceDesc creates a service descriptor with the new namespace for dual service support.
func frostFSServiceDesc(sd grpc.ServiceDesc) *grpc.ServiceDesc {
sdLegacy := new(grpc.ServiceDesc)
*sdLegacy = sd
const (
legacyNamespace = "neo.fs.v2"
apemanagerLegacyNamespace = "frostfs.v2"
newNamespace = "frost.fs"
)
if strings.HasPrefix(sd.ServiceName, legacyNamespace) {
sdLegacy.ServiceName = strings.ReplaceAll(sd.ServiceName, legacyNamespace, newNamespace)
} else if strings.HasPrefix(sd.ServiceName, apemanagerLegacyNamespace) {
sdLegacy.ServiceName = strings.ReplaceAll(sd.ServiceName, apemanagerLegacyNamespace, newNamespace)
}
return sdLegacy
}

View file

@ -26,5 +26,8 @@ func initAPEManagerService(c *cfg) {
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
apemanager_grpc.RegisterAPEManagerServiceServer(s, server) apemanager_grpc.RegisterAPEManagerServiceServer(s, server)
// TODO(@aarifullin): #1487 remove the dual service support.
s.RegisterService(frostFSServiceDesc(apemanager_grpc.APEManagerService_ServiceDesc), server)
}) })
} }

View file

@ -196,31 +196,6 @@ func (s ttlContainerStorage) DeletionInfo(cnr cid.ID) (*container.DelInfo, error
return s.delInfoCache.get(cnr) return s.delInfoCache.get(cnr)
} }
type ttlEACLStorage struct {
*ttlNetCache[cid.ID, *container.EACL]
}
func newCachedEACLStorage(v container.EACLSource, ttl time.Duration) ttlEACLStorage {
const eaclCacheSize = 100
lruCnrCache := newNetworkTTLCache(eaclCacheSize, ttl, func(id cid.ID) (*container.EACL, error) {
return v.GetEACL(id)
}, metrics.NewCacheMetrics("eacl"))
return ttlEACLStorage{lruCnrCache}
}
// GetEACL returns eACL value from the cache. If value is missing in the cache
// or expired, then it returns value from side chain and updates cache.
func (s ttlEACLStorage) GetEACL(cnr cid.ID) (*container.EACL, error) {
return s.get(cnr)
}
// InvalidateEACL removes cached eACL value.
func (s ttlEACLStorage) InvalidateEACL(cnr cid.ID) {
s.remove(cnr)
}
type lruNetmapSource struct { type lruNetmapSource struct {
netState netmap.State netState netmap.State

View file

@ -397,16 +397,16 @@ type internals struct {
} }
// starts node's maintenance. // starts node's maintenance.
func (c *cfg) startMaintenance() { func (c *cfg) startMaintenance(ctx context.Context) {
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(logs.FrostFSNodeStartedLocalNodesMaintenance) c.log.Info(ctx, logs.FrostFSNodeStartedLocalNodesMaintenance)
} }
// stops node's maintenance. // stops node's maintenance.
func (c *internals) stopMaintenance() { func (c *internals) stopMaintenance(ctx context.Context) {
if c.isMaintenance.CompareAndSwap(true, false) { if c.isMaintenance.CompareAndSwap(true, false) {
c.log.Info(logs.FrostFSNodeStoppedLocalNodesMaintenance) c.log.Info(ctx, logs.FrostFSNodeStoppedLocalNodesMaintenance)
} }
} }
@ -642,8 +642,6 @@ type cfgObject struct {
cnrSource container.Source cnrSource container.Source
eaclSource container.EACLSource
cfgAccessPolicyEngine cfgAccessPolicyEngine cfgAccessPolicyEngine cfgAccessPolicyEngine
pool cfgObjectRoutines pool cfgObjectRoutines
@ -707,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.Logger = log.Logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { log.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
})) }))
@ -1091,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(ev event.Event) { addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) {
ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber()) ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber())
}) })
@ -1105,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(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) c.log.Error(ctx, logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err))
} else { } else {
shardsAttached++ shardsAttached++
c.log.Info(logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id)) c.log.Info(ctx, logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id))
} }
} }
if shardsAttached == 0 { if shardsAttached == 0 {
@ -1118,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(logs.FrostFSNodeClosingComponentsOfTheStorageEngine) c.log.Info(ctx, logs.FrostFSNodeClosingComponentsOfTheStorageEngine)
err := ls.Close(context.WithoutCancel(ctx)) err := ls.Close(context.WithoutCancel(ctx))
if err != nil { if err != nil {
c.log.Info(logs.FrostFSNodeStorageEngineClosingFailure, c.log.Info(ctx, logs.FrostFSNodeStorageEngineClosingFailure,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} else { } else {
c.log.Info(logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully) c.log.Info(ctx, logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully)
} }
}) })
} }
func initAccessPolicyEngine(_ context.Context, c *cfg) { func initAccessPolicyEngine(ctx 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(logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) c.log.Warn(ctx, logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed)
localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase() localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase()
} else { } else {
localOverrideDB = chainbase.NewBoltLocalOverrideDatabase( localOverrideDB = chainbase.NewBoltLocalOverrideDatabase(
@ -1159,7 +1157,7 @@ func initAccessPolicyEngine(_ 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(logs.FrostFSNodeAccessPolicyEngineClosingFailure, c.log.Warn(ctx, logs.FrostFSNodeAccessPolicyEngineClosingFailure,
zap.Error(err), zap.Error(err),
) )
} }
@ -1208,10 +1206,10 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) {
c.cfgNetmap.state.setNodeInfo(ni) c.cfgNetmap.state.setNodeInfo(ni)
} }
func (c *cfg) updateContractNodeInfo(epoch uint64) { func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) {
ni, err := c.netmapLocalNodeState(epoch) ni, err := c.netmapLocalNodeState(epoch)
if err != nil { if err != nil {
c.log.Error(logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch,
zap.Uint64("epoch", epoch), zap.Uint64("epoch", epoch),
zap.String("error", err.Error())) zap.String("error", err.Error()))
return return
@ -1223,19 +1221,19 @@ func (c *cfg) updateContractNodeInfo(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(stateSetter func(*netmap.NodeInfo)) error { func (c *cfg) bootstrapWithState(ctx context.Context, 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(prm) return c.cfgNetmap.wrapper.AddPeer(ctx, prm)
} }
// bootstrapOnline calls cfg.bootstrapWithState with "online" state. // bootstrapOnline calls cfg.bootstrapWithState with "online" state.
func bootstrapOnline(c *cfg) error { func bootstrapOnline(ctx context.Context, c *cfg) error {
return c.bootstrapWithState(func(ni *netmap.NodeInfo) { return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) {
ni.SetStatus(netmap.Online) ni.SetStatus(netmap.Online)
}) })
} }
@ -1243,21 +1241,21 @@ func bootstrapOnline(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() error { func (c *cfg) bootstrap(ctx context.Context) 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(logs.FrostFSNodeBootstrappingWithTheMaintenanceState) c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithTheMaintenanceState)
return c.bootstrapWithState(func(ni *netmap.NodeInfo) { return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) {
ni.SetStatus(netmap.Maintenance) ni.SetStatus(netmap.Maintenance)
}) })
} }
c.log.Info(logs.FrostFSNodeBootstrappingWithOnlineState, c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithOnlineState,
zap.Stringer("previous", st), zap.Stringer("previous", st),
) )
return bootstrapOnline(c) return bootstrapOnline(ctx, 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.
@ -1282,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(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
c.shutdown() c.shutdown(ctx)
c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-c.internalErr: // internal application error case err := <-c.internalErr: // internal application error
c.log.Warn(logs.FrostFSNodeInternalApplicationError, c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError,
zap.String("message", err.Error())) zap.String("message", err.Error()))
c.shutdown() c.shutdown(ctx)
c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete) c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete)
return return
default: default:
// block until any signal is receieved // block until any signal is receieved
@ -1302,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(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
c.shutdown() c.shutdown(ctx)
c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
return return
case err := <-c.internalErr: // internal application error case err := <-c.internalErr: // internal application error
c.log.Warn(logs.FrostFSNodeInternalApplicationError, c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError,
zap.String("message", err.Error())) zap.String("message", err.Error()))
c.shutdown() c.shutdown(ctx)
c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete) c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete)
return return
} }
} }
@ -1322,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(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) c.log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
if !c.compareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { if !c.compareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
c.log.Info(logs.FrostFSNodeSIGHUPSkip) c.log.Info(ctx, logs.FrostFSNodeSIGHUPSkip)
return return
} }
defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) defer c.compareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
err := c.reloadAppConfig() err := c.reloadAppConfig()
if err != nil { if err != nil {
c.log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) c.log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err))
return return
} }
@ -1343,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(logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err)) c.log.Error(ctx, logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err))
return return
} }
@ -1364,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(logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err)) c.log.Error(ctx, 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(logs.FrostFSNodeUpdatedConfigurationApplying, c.log.Error(ctx, 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(logs.FailedToUpdateMultinetConfiguration, zap.Error(err)) c.log.Error(ctx, logs.FailedToUpdateMultinetConfiguration, zap.Error(err))
return return
} }
c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) c.log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
} }
func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
@ -1390,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(c) setRuntimeParameters(ctx, c)
return nil return nil
}}) }})
components = append(components, dCmp{"audit", func() error { components = append(components, dCmp{"audit", func() error {
@ -1405,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(logs.FrostFSNodeTracingConfigationUpdated) c.log.Info(ctx, logs.FrostFSNodeTracingConfigationUpdated)
} }
return err return err
}}) }})
@ -1440,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(logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name), c.log.Info(context.Background(), 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)
} }
@ -1476,14 +1474,14 @@ func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoPro
}) })
} }
func (c *cfg) shutdown() { func (c *cfg) shutdown(ctx context.Context) {
old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN) old := c.swapHealthStatus(ctx, control.HealthStatus_SHUTTING_DOWN)
if old == control.HealthStatus_SHUTTING_DOWN { if old == control.HealthStatus_SHUTTING_DOWN {
c.log.Info(logs.FrostFSNodeShutdownSkip) c.log.Info(ctx, logs.FrostFSNodeShutdownSkip)
return return
} }
if old == control.HealthStatus_STARTING { if old == control.HealthStatus_STARTING {
c.log.Warn(logs.FrostFSNodeShutdownWhenNotReady) c.log.Warn(ctx, logs.FrostFSNodeShutdownWhenNotReady)
} }
c.ctxCancel() c.ctxCancel()
@ -1493,6 +1491,6 @@ func (c *cfg) shutdown() {
} }
if err := sdnotify.ClearStatus(); err != nil { if err := sdnotify.ClearStatus(); err != nil {
c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err))
} }
} }

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"strconv"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
"git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/misc"
@ -24,6 +25,7 @@ func ToTracingConfig(c *config.Config) (*tracing.Config, error) {
Service: "frostfs-node", Service: "frostfs-node",
InstanceID: getInstanceIDOrDefault(c), InstanceID: getInstanceIDOrDefault(c),
Version: misc.Version, Version: misc.Version,
Attributes: make(map[string]string),
} }
if trustedCa := config.StringSafe(c.Sub(subsection), "trusted_ca"); trustedCa != "" { if trustedCa := config.StringSafe(c.Sub(subsection), "trusted_ca"); trustedCa != "" {
@ -38,11 +40,30 @@ func ToTracingConfig(c *config.Config) (*tracing.Config, error) {
} }
conf.ServerCaCertPool = certPool conf.ServerCaCertPool = certPool
} }
i := uint64(0)
for ; ; i++ {
si := strconv.FormatUint(i, 10)
ac := c.Sub(subsection).Sub("attributes").Sub(si)
k := config.StringSafe(ac, "key")
if k == "" {
break
}
v := config.StringSafe(ac, "value")
if v == "" {
return nil, fmt.Errorf("empty tracing attribute value for key %s", k)
}
if _, ok := conf.Attributes[k]; ok {
return nil, fmt.Errorf("tracing attribute key %s defined more than once", k)
}
conf.Attributes[k] = v
}
return conf, nil return conf, nil
} }
func getInstanceIDOrDefault(c *config.Config) string { func getInstanceIDOrDefault(c *config.Config) string {
s := config.StringSlice(c.Sub("node"), "addresses") s := config.StringSliceSafe(c.Sub("node"), "addresses")
if len(s) > 0 { if len(s) > 0 {
return s[0] return s[0]
} }

View file

@ -0,0 +1,46 @@
package tracing
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
"github.com/stretchr/testify/require"
)
func TestTracingSection(t *testing.T) {
t.Run("defaults", func(t *testing.T) {
tc, err := ToTracingConfig(configtest.EmptyConfig())
require.NoError(t, err)
require.Equal(t, false, tc.Enabled)
require.Equal(t, tracing.Exporter(""), tc.Exporter)
require.Equal(t, "", tc.Endpoint)
require.Equal(t, "frostfs-node", tc.Service)
require.Equal(t, "", tc.InstanceID)
require.Nil(t, tc.ServerCaCertPool)
require.Empty(t, tc.Attributes)
})
const path = "../../../../config/example/node"
fileConfigTest := func(c *config.Config) {
tc, err := ToTracingConfig(c)
require.NoError(t, err)
require.Equal(t, true, tc.Enabled)
require.Equal(t, tracing.OTLPgRPCExporter, tc.Exporter)
require.Equal(t, "localhost", tc.Endpoint)
require.Equal(t, "frostfs-node", tc.Service)
require.Nil(t, tc.ServerCaCertPool)
require.EqualValues(t, map[string]string{
"key0": "value",
"key1": "value",
}, tc.Attributes)
}
configtest.ForEachFileType(path, fileConfigTest)
t.Run("ENV", func(t *testing.T) {
configtest.ForEnvFileType(t, path, fileConfigTest)
})
}

View file

@ -10,6 +10,8 @@ import (
const ( const (
subsection = "tree" subsection = "tree"
SyncBatchSizeDefault = 1000
) )
// TreeConfig is a wrapper over "tree" config section // TreeConfig is a wrapper over "tree" config section
@ -74,6 +76,17 @@ func (c TreeConfig) SyncInterval() time.Duration {
return config.DurationSafe(c.cfg, "sync_interval") return config.DurationSafe(c.cfg, "sync_interval")
} }
// SyncBatchSize returns the value of "sync_batch_size"
// config parameter from the "tree" section.
//
// Returns `SyncBatchSizeDefault` if config value is not specified.
func (c TreeConfig) SyncBatchSize() int {
if v := config.IntSafe(c.cfg, "sync_batch_size"); v > 0 {
return int(v)
}
return SyncBatchSizeDefault
}
// AuthorizedKeys parses and returns an array of "authorized_keys" config // AuthorizedKeys parses and returns an array of "authorized_keys" config
// parameter from "tree" section. // parameter from "tree" section.
// //

View file

@ -44,6 +44,7 @@ func TestTreeSection(t *testing.T) {
require.Equal(t, 32, treeSec.ReplicationWorkerCount()) require.Equal(t, 32, treeSec.ReplicationWorkerCount())
require.Equal(t, 5*time.Second, treeSec.ReplicationTimeout()) require.Equal(t, 5*time.Second, treeSec.ReplicationTimeout())
require.Equal(t, time.Hour, treeSec.SyncInterval()) require.Equal(t, time.Hour, treeSec.SyncInterval())
require.Equal(t, 2000, treeSec.SyncBatchSize())
require.Equal(t, expectedKeys, treeSec.AuthorizedKeys()) require.Equal(t, expectedKeys, treeSec.AuthorizedKeys())
} }

View file

@ -64,16 +64,15 @@ func initContainerService(_ context.Context, c *cfg) {
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
containerGRPC.RegisterContainerServiceServer(s, server) containerGRPC.RegisterContainerServiceServer(s, server)
// TODO(@aarifullin): #1487 remove the dual service support.
s.RegisterService(frostFSServiceDesc(containerGRPC.ContainerService_ServiceDesc), server)
}) })
c.cfgObject.cfgLocalStorage.localStorage.SetContainerSource(cnrRdr) c.cfgObject.cfgLocalStorage.localStorage.SetContainerSource(cnrRdr)
} }
func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) { func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) {
eACLFetcher := &morphEACLFetcher{
w: client,
}
cnrRdr := new(morphContainerReader) cnrRdr := new(morphContainerReader)
cnrWrt := &morphContainerWriter{ cnrWrt := &morphContainerWriter{
@ -81,8 +80,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
} }
if c.cfgMorph.cacheTTL <= 0 { if c.cfgMorph.cacheTTL <= 0 {
c.cfgObject.eaclSource = eACLFetcher
cnrRdr.eacl = eACLFetcher
c.cfgObject.cnrSource = cnrSrc c.cfgObject.cnrSource = cnrSrc
cnrRdr.src = cnrSrc cnrRdr.src = cnrSrc
cnrRdr.lister = client cnrRdr.lister = client
@ -92,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(e event.Event) { subscribeToContainerCreation(c, func(ctx context.Context, 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.
@ -105,32 +102,28 @@ 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(logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, c.log.Error(ctx, logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification,
zap.Stringer("id", ev.ID), zap.Stringer("id", ev.ID),
zap.Error(err), zap.Error(err),
) )
} }
c.log.Debug(logs.FrostFSNodeContainerCreationEventsReceipt, c.log.Debug(ctx, logs.FrostFSNodeContainerCreationEventsReceipt,
zap.Stringer("id", ev.ID), zap.Stringer("id", ev.ID),
) )
}) })
subscribeToContainerRemoval(c, func(e event.Event) { subscribeToContainerRemoval(c, func(ctx context.Context, e event.Event) {
ev := e.(containerEvent.DeleteSuccess) ev := e.(containerEvent.DeleteSuccess)
containerCache.handleRemoval(ev.ID) containerCache.handleRemoval(ev.ID)
c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, c.log.Debug(ctx, logs.FrostFSNodeContainerRemovalEventsReceipt,
zap.Stringer("id", ev.ID), zap.Stringer("id", ev.ID),
) )
}) })
c.cfgObject.cnrSource = containerCache c.cfgObject.cnrSource = containerCache
} }
cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL)
c.cfgObject.eaclSource = cachedEACLStorage
cnrRdr.lister = client cnrRdr.lister = client
cnrRdr.eacl = c.cfgObject.eaclSource
cnrRdr.src = c.cfgObject.cnrSource cnrRdr.src = c.cfgObject.cnrSource
} }
@ -221,8 +214,6 @@ func (c *cfg) ExternalAddresses() []string {
// implements interface required by container service provided by morph executor. // implements interface required by container service provided by morph executor.
type morphContainerReader struct { type morphContainerReader struct {
eacl containerCore.EACLSource
src containerCore.Source src containerCore.Source
lister interface { lister interface {
@ -238,10 +229,6 @@ func (x *morphContainerReader) DeletionInfo(id cid.ID) (*containerCore.DelInfo,
return x.src.DeletionInfo(id) return x.src.DeletionInfo(id)
} }
func (x *morphContainerReader) GetEACL(id cid.ID) (*containerCore.EACL, error) {
return x.eacl.GetEACL(id)
}
func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) { func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) {
return x.lister.ContainersOf(id) return x.lister.ContainersOf(id)
} }
@ -250,10 +237,10 @@ type morphContainerWriter struct {
neoClient *cntClient.Client neoClient *cntClient.Client
} }
func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) { func (m morphContainerWriter) Put(ctx context.Context, cnr containerCore.Container) (*cid.ID, error) {
return cntClient.Put(m.neoClient, cnr) return cntClient.Put(ctx, m.neoClient, cnr)
} }
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error { func (m morphContainerWriter) Delete(ctx context.Context, witness containerCore.RemovalWitness) error {
return cntClient.Delete(m.neoClient, witness) return cntClient.Delete(ctx, m.neoClient, witness)
} }

View file

@ -16,7 +16,7 @@ import (
const serviceNameControl = "control" const serviceNameControl = "control"
func initControlService(c *cfg) { func initControlService(ctx context.Context, 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(c *cfg) {
lis, err := net.Listen("tcp", endpoint) lis, err := net.Listen("tcp", endpoint)
if err != nil { if err != nil {
c.log.Error(logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err)) c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err))
return return
} }
c.cfgControlService.server = grpc.NewServer() c.cfgControlService.server = grpc.NewServer()
c.onShutdown(func() { c.onShutdown(func() {
stopGRPC("FrostFS Control API", c.cfgControlService.server, c.log) stopGRPC(ctx, "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(logs.FrostFSNodeStartListeningEndpoint, c.log.Info(ctx, 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(st control.HealthStatus) { func (c *cfg) setHealthStatus(ctx context.Context, st control.HealthStatus) {
c.notifySystemd(st) c.notifySystemd(ctx, 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(oldSt, newSt control.HealthStatus) (swapped bool) { func (c *cfg) compareAndSwapHealthStatus(ctx context.Context, 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(newSt) c.notifySystemd(ctx, newSt)
c.metricsCollector.State().SetHealth(int32(newSt)) c.metricsCollector.State().SetHealth(int32(newSt))
} }
return return
} }
func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatus) { func (c *cfg) swapHealthStatus(ctx context.Context, st control.HealthStatus) (old control.HealthStatus) {
old = control.HealthStatus(c.healthStatus.Swap(int32(st))) old = control.HealthStatus(c.healthStatus.Swap(int32(st)))
c.notifySystemd(st) c.notifySystemd(ctx, 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(st control.HealthStatus) { func (c *cfg) notifySystemd(ctx context.Context, st control.HealthStatus) {
if !c.sdNotify { if !c.sdNotify {
return return
} }
@ -113,6 +113,6 @@ func (c *cfg) notifySystemd(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(logs.FailedToReportStatusToSystemd, zap.Error(err)) c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err))
} }
} }

View file

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

View file

@ -20,9 +20,9 @@ type httpComponent struct {
preReload func(c *cfg) preReload func(c *cfg)
} }
func (cmp *httpComponent) init(c *cfg) { func (cmp *httpComponent) init(ctx context.Context, c *cfg) {
if !cmp.enabled { if !cmp.enabled {
c.log.Info(cmp.name + " is disabled") c.log.Info(ctx, cmp.name+" is disabled")
return return
} }
// Init server with parameters // Init server with parameters
@ -39,14 +39,14 @@ func (cmp *httpComponent) init(c *cfg) {
go func() { go func() {
defer c.wg.Done() defer c.wg.Done()
c.log.Info(logs.FrostFSNodeStartListeningEndpoint, c.log.Info(ctx, 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(c, cmp.name, srv.Shutdown) }, func() { stopAndLog(ctx, 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(cmp.cfg) cmp.init(ctx, 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(control.HealthStatus_STARTING) c.setHealthStatus(ctx, control.HealthStatus_STARTING)
initApp(ctx, c) initApp(ctx, c)
bootUp(ctx, c) bootUp(ctx, c)
c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) c.compareAndSwapHealthStatus(ctx, control.HealthStatus_STARTING, control.HealthStatus_READY)
wait(c) wait(c)
} }
func initAndLog(c *cfg, name string, initializer func(*cfg)) { func initAndLog(ctx context.Context, c *cfg, name string, initializer func(*cfg)) {
c.log.Info(fmt.Sprintf("initializing %s service...", name)) c.log.Info(ctx, fmt.Sprintf("initializing %s service...", name))
initializer(c) initializer(c)
c.log.Info(name + " service has been successfully initialized") c.log.Info(ctx, 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(c) setRuntimeParameters(ctx, c)
metrics, _ := metricsComponent(c) metrics, _ := metricsComponent(c)
initAndLog(c, "profiler", initProfilerService) initAndLog(ctx, c, "profiler", func(c *cfg) { initProfilerService(ctx, c) })
initAndLog(c, metrics.name, metrics.init) initAndLog(ctx, c, metrics.name, func(c *cfg) { metrics.init(ctx, c) })
initAndLog(c, "tracing", func(c *cfg) { initTracing(ctx, c) }) initAndLog(ctx, c, "tracing", func(c *cfg) { initTracing(ctx, c) })
initLocalStorage(ctx, c) initLocalStorage(ctx, c)
initAndLog(c, "storage engine", func(c *cfg) { initAndLog(ctx, 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(c, "gRPC", initGRPC) initAndLog(ctx, c, "gRPC", func(c *cfg) { initGRPC(ctx, c) })
initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) initAndLog(ctx, c, "netmap", func(c *cfg) { initNetmapService(ctx, c) })
initAccessPolicyEngine(ctx, c) initAccessPolicyEngine(ctx, c)
initAndLog(c, "access policy engine", func(c *cfg) { initAndLog(ctx, 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(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) initAndLog(ctx, c, "accounting", func(c *cfg) { initAccountingService(ctx, c) })
initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) }) initAndLog(ctx, c, "container", func(c *cfg) { initContainerService(ctx, c) })
initAndLog(c, "session", initSessionService) initAndLog(ctx, c, "session", initSessionService)
initAndLog(c, "object", initObjectService) initAndLog(ctx, c, "object", initObjectService)
initAndLog(c, "tree", initTreeService) initAndLog(ctx, c, "tree", initTreeService)
initAndLog(c, "apemanager", initAPEManagerService) initAndLog(ctx, c, "apemanager", initAPEManagerService)
initAndLog(c, "control", initControlService) initAndLog(ctx, c, "control", func(c *cfg) { initControlService(ctx, c) })
initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) }) initAndLog(ctx, 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(fmt.Sprintf("starting %s service...", name)) c.log.Info(ctx, fmt.Sprintf("starting %s service...", name))
starter(ctx, c) starter(ctx, c)
if logSuccess { if logSuccess {
c.log.Info(name + " service started successfully") c.log.Info(ctx, name+" service started successfully")
} }
} }
func stopAndLog(c *cfg, name string, stopper func() error) { func stopAndLog(ctx context.Context, c *cfg, name string, stopper func(context.Context) error) {
c.log.Debug(fmt.Sprintf("shutting down %s service", name)) c.log.Debug(ctx, fmt.Sprintf("shutting down %s service", name))
err := stopper() err := stopper(ctx)
if err != nil { if err != nil {
c.log.Debug(fmt.Sprintf("could not shutdown %s server", name), c.log.Debug(ctx, fmt.Sprintf("could not shutdown %s server", name),
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
c.log.Debug(name + " service has been stopped") c.log.Debug(ctx, 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(c) }) runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(ctx, c) })
runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit)
bootstrapNode(c) bootstrapNode(ctx, c)
startWorkers(ctx, c) startWorkers(ctx, c)
} }
func wait(c *cfg) { func wait(c *cfg) {
c.log.Info(logs.CommonApplicationStarted, c.log.Info(context.Background(), 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(logs.FrostFSNodeInternalApplicationError, c.log.Warn(context.Background(), logs.FrostFSNodeInternalApplicationError,
zap.String("message", err.Error())) zap.String("message", err.Error()))
} }
}() }()
c.log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop) c.log.Debug(context.Background(), logs.FrostFSNodeWaitingForAllProcessesToStop)
c.wg.Wait() c.wg.Wait()

View file

@ -17,11 +17,7 @@ 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"
) )
@ -48,7 +44,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) {
fatalOnErr(err) fatalOnErr(err)
} }
c.log.Info(logs.FrostFSNodeNotarySupport, c.log.Info(ctx, logs.FrostFSNodeNotarySupport,
zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled),
) )
@ -64,7 +60,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(logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL)) c.log.Debug(ctx, logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL))
} }
if c.cfgMorph.cacheTTL < 0 { if c.cfgMorph.cacheTTL < 0 {
@ -102,7 +98,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(logs.FrostFSNodeFailedToCreateNeoRPCClient, c.log.Info(ctx, logs.FrostFSNodeFailedToCreateNeoRPCClient,
zap.Any("endpoints", addresses), zap.Any("endpoints", addresses),
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -111,12 +107,12 @@ func initMorphClient(ctx context.Context, c *cfg) {
} }
c.onShutdown(func() { c.onShutdown(func() {
c.log.Info(logs.FrostFSNodeClosingMorphComponents) c.log.Info(ctx, logs.FrostFSNodeClosingMorphComponents)
cli.Close() cli.Close()
}) })
if err := cli.SetGroupSignerScope(); err != nil { if err := cli.SetGroupSignerScope(); err != nil {
c.log.Info(logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err)) c.log.Info(ctx, logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err))
} }
c.cfgMorph.client = cli c.cfgMorph.client = cli
@ -129,14 +125,14 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
return return
} }
tx, vub, err := makeNotaryDeposit(c) tx, vub, err := makeNotaryDeposit(ctx, 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(logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade) c.log.Info(ctx, logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade)
return return
} }
@ -144,7 +140,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
fatalOnErr(err) fatalOnErr(err)
} }
func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) { func makeNotaryDeposit(ctx context.Context, 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:
@ -161,51 +157,16 @@ func makeNotaryDeposit(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(depositAmount) return c.cfgMorph.client.DepositEndlessNotary(ctx, 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 {
w, err := waiter.NewPollingBased(&waiterClient{c: c.cfgMorph.client}) if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil {
if err != nil { return err
return fmt.Errorf("could not create notary deposit waiter: %w", err)
} }
res, err := w.WaitAny(ctx, vub, tx)
if err != nil { c.log.Info(ctx, logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted)
if errors.Is(err, waiter.ErrTxNotAccepted) { return nil
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) {
@ -217,7 +178,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(logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
} }
subs, err = subscriber.New(ctx, &subscriber.Params{ subs, err = subscriber.New(ctx, &subscriber.Params{
@ -246,7 +207,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(logs.FrostFSNodeNewEpochEventFromSidechain, c.log.Info(ctx, logs.FrostFSNodeNewEpochEventFromSidechain,
zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()), zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()),
) )
} }
@ -256,12 +217,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(block *block.Block) { registerBlockHandler(lis, func(ctx context.Context, block *block.Block) {
c.log.Debug(logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) c.log.Debug(ctx, 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(logs.FrostFSNodeCantUpdatePersistentState, c.log.Warn(ctx, 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(c) initNetmapState(ctx, c)
server := netmapTransportGRPC.New( server := netmapTransportGRPC.New(
netmapService.NewSignService( netmapService.NewSignService(
@ -166,35 +166,38 @@ func initNetmapService(ctx context.Context, c *cfg) {
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
netmapGRPC.RegisterNetmapServiceServer(s, server) netmapGRPC.RegisterNetmapServiceServer(s, server)
// TODO(@aarifullin): #1487 remove the dual service support.
s.RegisterService(frostFSServiceDesc(netmapGRPC.NetmapService_ServiceDesc), server)
}) })
addNewEpochNotificationHandlers(c) addNewEpochNotificationHandlers(c)
} }
func addNewEpochNotificationHandlers(c *cfg) { func addNewEpochNotificationHandlers(c *cfg) {
addNewEpochNotificationHandler(c, func(ev event.Event) { addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) {
c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber()) c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber())
}) })
addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) {
e := ev.(netmapEvent.NewEpoch).EpochNumber() e := ev.(netmapEvent.NewEpoch).EpochNumber()
c.updateContractNodeInfo(e) c.updateContractNodeInfo(ctx, 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(); err != nil { if err := c.bootstrap(ctx); err != nil {
c.log.Warn(logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) c.log.Warn(ctx, logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err))
} }
}) })
if c.cfgMorph.notaryEnabled { if c.cfgMorph.notaryEnabled {
addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) {
_, _, err := makeNotaryDeposit(c) _, _, err := makeNotaryDeposit(ctx, c)
if err != nil { if err != nil {
c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit, c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
@ -204,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(c *cfg) { func bootstrapNode(ctx context.Context, c *cfg) {
if c.needBootstrap() { if c.needBootstrap() {
if c.IsMaintenance() { if c.IsMaintenance() {
c.log.Info(logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) c.log.Info(ctx, logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap)
return return
} }
err := c.bootstrap() err := c.bootstrap(ctx)
fatalOnErrDetails("bootstrap error", err) fatalOnErrDetails("bootstrap error", err)
} }
} }
@ -237,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(c *cfg) { func initNetmapState(ctx context.Context, 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(epoch) ni, err = c.netmapInitLocalNodeState(ctx, epoch)
fatalOnErrDetails("could not init network state", err) fatalOnErrDetails("could not init network state", err)
stateWord := nodeState(ni) stateWord := nodeState(ni)
c.log.Info(logs.FrostFSNodeInitialNetworkState, c.log.Info(ctx, logs.FrostFSNodeInitialNetworkState,
zap.Uint64("epoch", epoch), zap.Uint64("epoch", epoch),
zap.String("state", stateWord), zap.String("state", stateWord),
) )
@ -276,7 +279,7 @@ func nodeState(ni *netmapSDK.NodeInfo) string {
return "undefined" return "undefined"
} }
func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) { func (c *cfg) netmapInitLocalNodeState(ctx context.Context, 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
@ -304,7 +307,7 @@ func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error
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(logs.CandidateStatusPriority, c.log.Info(ctx, logs.CandidateStatusPriority,
zap.String("netmap", nmState), zap.String("netmap", nmState),
zap.String("candidate", candidateState)) zap.String("candidate", candidateState))
} }
@ -350,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(st control.NetmapStatus) error { func (c *cfg) SetNetmapStatus(ctx context.Context, 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(false) return c.setMaintenanceStatus(ctx, false)
case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE: case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE:
} }
c.stopMaintenance() c.stopMaintenance(ctx)
if !c.needBootstrap() { if !c.needBootstrap() {
return errRelayBootstrap return errRelayBootstrap
@ -367,12 +370,12 @@ func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error {
if st == control.NetmapStatus_ONLINE { if st == control.NetmapStatus_ONLINE {
c.cfgNetmap.reBoostrapTurnedOff.Store(false) c.cfgNetmap.reBoostrapTurnedOff.Store(false)
return bootstrapOnline(c) return bootstrapOnline(ctx, c)
} }
c.cfgNetmap.reBoostrapTurnedOff.Store(true) c.cfgNetmap.reBoostrapTurnedOff.Store(true)
return c.updateNetMapState(func(*nmClient.UpdatePeerPrm) {}) return c.updateNetMapState(ctx, func(*nmClient.UpdatePeerPrm) {})
} }
func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) { func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
@ -384,11 +387,11 @@ func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
return st, epoch, nil return st, epoch, nil
} }
func (c *cfg) ForceMaintenance() error { func (c *cfg) ForceMaintenance(ctx context.Context) error {
return c.setMaintenanceStatus(true) return c.setMaintenanceStatus(ctx, true)
} }
func (c *cfg) setMaintenanceStatus(force bool) error { func (c *cfg) setMaintenanceStatus(ctx context.Context, 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)
@ -397,10 +400,10 @@ func (c *cfg) setMaintenanceStatus(force bool) error {
} }
if err == nil || force { if err == nil || force {
c.startMaintenance() c.startMaintenance(ctx)
if err == nil { if err == nil {
err = c.updateNetMapState((*nmClient.UpdatePeerPrm).SetMaintenance) err = c.updateNetMapState(ctx, (*nmClient.UpdatePeerPrm).SetMaintenance)
} }
if err != nil { if err != nil {
@ -413,13 +416,16 @@ func (c *cfg) setMaintenanceStatus(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(stateSetter func(*nmClient.UpdatePeerPrm)) error { func (c *cfg) updateNetMapState(ctx context.Context, 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)
_, err := c.cfgNetmap.wrapper.UpdatePeerState(prm) res, err := c.cfgNetmap.wrapper.UpdatePeerState(ctx, prm)
return err if err != nil {
return err
}
return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res)
} }
type netInfo struct { type netInfo struct {

View file

@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"net" "net"
@ -14,7 +13,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache"
objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc" objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc"
@ -37,7 +35,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
@ -61,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(logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
@ -69,11 +66,11 @@ func (c *cfg) MaxObjectSize() uint64 {
return sz return sz
} }
func (s *objectSvc) Put() (objectService.PutObjectStream, error) { func (s *objectSvc) Put(_ context.Context) (objectService.PutObjectStream, error) {
return s.put.Put() return s.put.Put()
} }
func (s *objectSvc) Patch() (objectService.PatchObjectStream, error) { func (s *objectSvc) Patch(_ context.Context) (objectService.PatchObjectStream, error) {
return s.patch.Patch() return s.patch.Patch()
} }
@ -218,12 +215,15 @@ func initObjectService(c *cfg) {
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
objectGRPC.RegisterObjectServiceServer(s, server) objectGRPC.RegisterObjectServiceServer(s, server)
// TODO(@aarifullin): #1487 remove the dual service support.
s.RegisterService(frostFSServiceDesc(objectGRPC.ObjectService_ServiceDesc), server)
}) })
} }
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(logs.FrostFSNodePolicerIsDisabled) c.log.Warn(context.Background(), 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(logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage, c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
} }
@ -481,29 +481,6 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object
) )
} }
type morphEACLFetcher struct {
w *cntClient.Client
}
func (s *morphEACLFetcher) GetEACL(cnr cid.ID) (*containercore.EACL, error) {
eaclInfo, err := s.w.GetEACL(cnr)
if err != nil {
return nil, err
}
binTable, err := eaclInfo.Value.Marshal()
if err != nil {
return nil, fmt.Errorf("marshal eACL table: %w", err)
}
if !eaclInfo.Signature.Verify(binTable) {
// TODO(@cthulhu-rider): #468 use "const" error
return nil, errors.New("invalid signature of the eACL table")
}
return eaclInfo, nil
}
type engineWithoutNotifications struct { type engineWithoutNotifications struct {
engine *engine.StorageEngine engine *engine.StorageEngine
} }

View file

@ -1,17 +1,18 @@
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(c *cfg) { func initProfilerService(ctx context.Context, c *cfg) {
tuneProfilers(c) tuneProfilers(c)
pprof, _ := pprofComponent(c) pprof, _ := pprofComponent(c)
pprof.init(c) pprof.init(ctx, c)
} }
func pprofComponent(c *cfg) (*httpComponent, bool) { func pprofComponent(c *cfg) (*httpComponent, bool) {

View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"os" "os"
"runtime/debug" "runtime/debug"
@ -9,17 +10,17 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func setRuntimeParameters(c *cfg) { func setRuntimeParameters(ctx context.Context, 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(logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT) c.log.Warn(ctx, 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(logs.RuntimeSoftMemoryLimitUpdated, c.log.Info(ctx, 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(ev event.Event) { addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) {
c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber()) c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber())
}) })
@ -61,5 +61,8 @@ func initSessionService(c *cfg) {
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
sessionGRPC.RegisterSessionServiceServer(s, server) sessionGRPC.RegisterSessionServiceServer(s, server)
// TODO(@aarifullin): #1487 remove the dual service support.
s.RegisterService(frostFSServiceDesc(sessionGRPC.SessionService_ServiceDesc), server)
}) })
} }

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(logs.FrostFSNodeFailedInitTracing, zap.Error(err)) c.log.Error(ctx, 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(logs.FrostFSNodeFailedInitTracing, zap.Error(err)) c.log.Error(ctx, 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(logs.FrostFSNodeFailedShutdownTracing, zap.Error(err)) c.log.Error(ctx, 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(logs.FrostFSNodeTreeServiceIsNotEnabledSkipInitialization) c.log.Info(context.Background(), logs.FrostFSNodeTreeServiceIsNotEnabledSkipInitialization)
return return
} }
@ -62,6 +62,7 @@ func initTreeService(c *cfg) {
tree.WithReplicationTimeout(treeConfig.ReplicationTimeout()), tree.WithReplicationTimeout(treeConfig.ReplicationTimeout()),
tree.WithReplicationChannelCapacity(treeConfig.ReplicationChannelCapacity()), tree.WithReplicationChannelCapacity(treeConfig.ReplicationChannelCapacity()),
tree.WithReplicationWorkerCount(treeConfig.ReplicationWorkerCount()), tree.WithReplicationWorkerCount(treeConfig.ReplicationWorkerCount()),
tree.WithSyncBatchSize(treeConfig.SyncBatchSize()),
tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()), tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()),
tree.WithMetrics(c.metricsCollector.TreeService()), tree.WithMetrics(c.metricsCollector.TreeService()),
tree.WithAPELocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage()), tree.WithAPELocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage()),
@ -79,10 +80,10 @@ func initTreeService(c *cfg) {
})) }))
if d := treeConfig.SyncInterval(); d == 0 { if d := treeConfig.SyncInterval(); d == 0 {
addNewEpochNotificationHandler(c, func(_ event.Event) { addNewEpochNotificationHandler(c, func(ctx context.Context, _ event.Event) {
err := c.treeService.SynchronizeAll() err := c.treeService.SynchronizeAll()
if err != nil { if err != nil {
c.log.Error(logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) c.log.Error(ctx, logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err))
} }
}) })
} else { } else {
@ -93,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(logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) c.log.Error(context.Background(), logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err))
if errors.Is(err, tree.ErrShuttingDown) { if errors.Is(err, tree.ErrShuttingDown) {
return return
} }
@ -102,15 +103,15 @@ func initTreeService(c *cfg) {
}() }()
} }
subscribeToContainerRemoval(c, func(e event.Event) { subscribeToContainerRemoval(c, func(ctx context.Context, 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(logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID)) c.log.Debug(ctx, logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID))
err := c.treeService.DropTree(context.Background(), ev.ID, "") err := c.treeService.DropTree(ctx, 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(logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, c.log.Error(ctx, logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved,
zap.Stringer("cid", ev.ID), zap.Stringer("cid", ev.ID),
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }

View file

@ -0,0 +1,167 @@
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

@ -0,0 +1,19 @@
package ape
const (
RuleFlag = "rule"
RuleFlagDesc = "Rule statement"
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"
)

View file

@ -26,13 +26,15 @@ 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 {
@ -41,6 +43,9 @@ 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
} }

View file

@ -31,6 +31,7 @@ FROSTFS_TREE_REPLICATION_CHANNEL_CAPACITY=32
FROSTFS_TREE_REPLICATION_WORKER_COUNT=32 FROSTFS_TREE_REPLICATION_WORKER_COUNT=32
FROSTFS_TREE_REPLICATION_TIMEOUT=5s FROSTFS_TREE_REPLICATION_TIMEOUT=5s
FROSTFS_TREE_SYNC_INTERVAL=1h FROSTFS_TREE_SYNC_INTERVAL=1h
FROSTFS_TREE_SYNC_BATCH_SIZE=2000
FROSTFS_TREE_AUTHORIZED_KEYS="0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0 02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56" FROSTFS_TREE_AUTHORIZED_KEYS="0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0 02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56"
# gRPC section # gRPC section
@ -202,6 +203,10 @@ FROSTFS_TRACING_ENABLED=true
FROSTFS_TRACING_ENDPOINT="localhost" FROSTFS_TRACING_ENDPOINT="localhost"
FROSTFS_TRACING_EXPORTER="otlp_grpc" FROSTFS_TRACING_EXPORTER="otlp_grpc"
FROSTFS_TRACING_TRUSTED_CA="" FROSTFS_TRACING_TRUSTED_CA=""
FROSTFS_TRACING_ATTRIBUTES_0_KEY=key0
FROSTFS_TRACING_ATTRIBUTES_0_VALUE=value
FROSTFS_TRACING_ATTRIBUTES_1_KEY=key1
FROSTFS_TRACING_ATTRIBUTES_1_VALUE=value
FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824 FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824

View file

@ -69,6 +69,7 @@
"replication_worker_count": 32, "replication_worker_count": 32,
"replication_timeout": "5s", "replication_timeout": "5s",
"sync_interval": "1h", "sync_interval": "1h",
"sync_batch_size": 2000,
"authorized_keys": [ "authorized_keys": [
"0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0", "0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0",
"02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56" "02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56"
@ -258,9 +259,19 @@
}, },
"tracing": { "tracing": {
"enabled": true, "enabled": true,
"endpoint": "localhost:9090", "endpoint": "localhost",
"exporter": "otlp_grpc", "exporter": "otlp_grpc",
"trusted_ca": "/etc/ssl/tracing.pem" "trusted_ca": "",
"attributes":[
{
"key": "key0",
"value": "value"
},
{
"key": "key1",
"value": "value"
}
]
}, },
"runtime": { "runtime": {
"soft_memory_limit": 1073741824 "soft_memory_limit": 1073741824

View file

@ -59,6 +59,7 @@ tree:
replication_channel_capacity: 32 replication_channel_capacity: 32
replication_timeout: 5s replication_timeout: 5s
sync_interval: 1h sync_interval: 1h
sync_batch_size: 2000
authorized_keys: # list of hex-encoded public keys that have rights to use the Tree Service with frostfs-cli authorized_keys: # list of hex-encoded public keys that have rights to use the Tree Service with frostfs-cli
- 0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0 - 0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0
- 02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56 - 02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56
@ -238,6 +239,11 @@ tracing:
exporter: "otlp_grpc" exporter: "otlp_grpc"
endpoint: "localhost" endpoint: "localhost"
trusted_ca: "" trusted_ca: ""
attributes:
- key: key0
value: value
- key: key1
value: value
runtime: runtime:
soft_memory_limit: 1gb soft_memory_limit: 1gb

View file

@ -78,7 +78,12 @@
"FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s1/pilorama1", "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s1/pilorama1",
"FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ENABLED":"true",
"FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9090", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9090",
"FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s",
"FROSTFS_TRACING_ENABLED":"true",
"FROSTFS_TRACING_EXPORTER":"otlp_grpc",
"FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317",
"FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip",
"FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8080"
}, },
"postDebugTask": "env-down" "postDebugTask": "env-down"
}, },
@ -129,7 +134,12 @@
"FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s2/pilorama1", "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s2/pilorama1",
"FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ENABLED":"true",
"FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9091", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9091",
"FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s",
"FROSTFS_TRACING_ENABLED":"true",
"FROSTFS_TRACING_EXPORTER":"otlp_grpc",
"FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317",
"FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip",
"FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8082"
}, },
"postDebugTask": "env-down" "postDebugTask": "env-down"
}, },
@ -180,7 +190,12 @@
"FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s3/pilorama1", "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s3/pilorama1",
"FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ENABLED":"true",
"FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9092", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9092",
"FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s",
"FROSTFS_TRACING_ENABLED":"true",
"FROSTFS_TRACING_EXPORTER":"otlp_grpc",
"FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317",
"FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip",
"FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8084"
}, },
"postDebugTask": "env-down" "postDebugTask": "env-down"
}, },
@ -231,7 +246,12 @@
"FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s4/pilorama1", "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s4/pilorama1",
"FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ENABLED":"true",
"FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9093", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9093",
"FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s",
"FROSTFS_TRACING_ENABLED":"true",
"FROSTFS_TRACING_EXPORTER":"otlp_grpc",
"FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317",
"FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip",
"FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8086"
}, },
"postDebugTask": "env-down" "postDebugTask": "env-down"
} }

View file

@ -14,3 +14,15 @@ services:
- ./neo-go/node-wallet.json:/wallets/node-wallet.json - ./neo-go/node-wallet.json:/wallets/node-wallet.json
- ./neo-go/config.yml:/wallets/config.yml - ./neo-go/config.yml:/wallets/config.yml
- ./neo-go/wallet.json:/wallets/wallet.json - ./neo-go/wallet.json:/wallets/wallet.json
jaeger:
image: jaegertracing/all-in-one:latest
container_name: jaeger
ports:
- '4317:4317' #OTLP over gRPC
- '4318:4318' #OTLP over HTTP
- '16686:16686' #frontend
stop_signal: SIGKILL
environment:
- COLLECTOR_OTLP_ENABLED=true
- SPAN_STORAGE_TYPE=badger
- BADGER_EPHEMERAL=true

View file

@ -412,12 +412,12 @@ object:
- $attribute:ClusterName - $attribute:ClusterName
``` ```
| Parameter | Type | Default value | Description | | Parameter | Type | Default value | Description |
|-----------------------------|------------|---------------|------------------------------------------------------------------------------------------------------| |-----------------------------|------------|---------------|------------------------------------------------------------------------------------------------|
| `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | | `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. |
| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | | `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. |
| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | | `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. |
| `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET and SEARCH requests. | | `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET requests. |
# `runtime` section # `runtime` section
Contains runtime parameters. Contains runtime parameters.

4
go.mod
View file

@ -4,10 +4,10 @@ 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.20.0 git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4
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-20240909114314-666d326cc573 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823
git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/hrw v1.2.1
git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972

BIN
go.sum

Binary file not shown.

View file

@ -1,6 +1,8 @@
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"
@ -17,15 +19,15 @@ type Target interface {
String() string String() string
} }
func LogRequest(log *logger.Logger, operation string, req Request, target Target, status bool) { func LogRequest(ctx context.Context, 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(log, operation, key, target, status) LogRequestWithKey(ctx, log, operation, key, target, status)
} }
func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target Target, status bool) { func LogRequestWithKey(ctx context.Context, 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)
@ -37,7 +39,7 @@ func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target
object = target.String() object = target.String()
} }
log.Info(logs.AuditEventLogRecord, log.Info(ctx, 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

@ -58,16 +58,3 @@ type EACL struct {
// Session within which Value was set. Nil means session absence. // Session within which Value was set. Nil means session absence.
Session *session.Container Session *session.Container
} }
// EACLSource is the interface that wraps
// basic methods of extended ACL table source.
type EACLSource interface {
// GetEACL reads the table from the source by identifier.
// It returns any error encountered.
//
// GetEACL must return exactly one non-nil value.
//
// Must return apistatus.ErrEACLNotFound if requested
// eACL table is not in source.
GetEACL(cid.ID) (*EACL, error)
}

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(obj); err != nil { if err := v.validateSignatureKey(ctx, 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(obj *objectSDK.Object) error { func (v *FormatValidator) validateSignatureKey(ctx context.Context, 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(obj *objectSDK.Object) error {
ownerID := obj.OwnerID() ownerID := obj.OwnerID()
if token == nil && obj.ECHeader() != nil { if token == nil && obj.ECHeader() != nil {
role, err := v.isIROrContainerNode(obj, binKey) role, err := v.isIROrContainerNode(ctx, obj, binKey)
if err != nil { if err != nil {
return err return err
} }
@ -172,7 +172,7 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error {
} }
if v.verifyTokenIssuer { if v.verifyTokenIssuer {
role, err := v.isIROrContainerNode(obj, binKey) role, err := v.isIROrContainerNode(ctx, obj, binKey)
if err != nil { if err != nil {
return err return err
} }
@ -190,7 +190,7 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error {
return nil return nil
} }
func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (acl.Role, error) { func (v *FormatValidator) isIROrContainerNode(ctx context.Context, 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(obj *objectSDK.Object, signerKey [
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(signerKey, cnrID, cnr.Value) res, err := v.senderClassifier.IsInnerRingOrContainerNode(ctx, 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.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(logger.NewLoggerWrapper(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.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))),
) )
tok := sessiontest.Object() tok := sessiontest.Object()
@ -339,7 +339,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) {
}, },
}, },
), ),
WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(logger.NewLoggerWrapper(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.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(logger.NewLoggerWrapper(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.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(logger.NewLoggerWrapper(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.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))),
) )
require.Error(t, v.Validate(context.Background(), obj, false)) require.Error(t, v.Validate(context.Background(), obj, false))

View file

@ -2,6 +2,7 @@ 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"
@ -40,6 +41,7 @@ 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,
@ -57,14 +59,14 @@ func (c SenderClassifier) Classify(
}, nil }, nil
} }
return c.IsInnerRingOrContainerNode(ownerKeyInBytes, idCnr, cnr) return c.IsInnerRingOrContainerNode(ctx, ownerKeyInBytes, idCnr, cnr)
} }
func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) { func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, 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(logs.V2CantCheckIfRequestFromInnerRing, c.log.Debug(ctx, logs.V2CantCheckIfRequestFromInnerRing,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} else if isInnerRingNode { } else if isInnerRingNode {
return &ClassifyResult{ return &ClassifyResult{
@ -81,7 +83,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idC
// 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(logs.V2CantCheckIfRequestFromContainerNode, c.log.Debug(ctx, 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() (util.Uint256, error) depositor func(context.Context) (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(args *emitTimerArgs) *timer.BlockTimer { func newEmissionTimer(ctx context.Context, args *emitTimerArgs) *timer.BlockTimer {
return timer.NewBlockTimer( return timer.NewBlockTimer(
timer.StaticBlockMeter(args.emitDuration), timer.StaticBlockMeter(args.emitDuration),
func() { func() {
args.ap.HandleGasEmission(timerEvent.NewAlphabetEmitTick{}) args.ap.HandleGasEmission(ctx, timerEvent.NewAlphabetEmitTick{})
}, },
) )
} }

View file

@ -35,7 +35,7 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
) )
func (s *Server) initNetmapProcessor(cfg *viper.Viper, func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper,
alphaSync event.Handler, alphaSync event.Handler,
) error { ) error {
locodeValidator, err := s.newLocodeValidator(cfg) locodeValidator, err := s.newLocodeValidator(cfg)
@ -48,10 +48,13 @@ func (s *Server) initNetmapProcessor(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: cfg.GetInt("workers.netmap"), PoolSize: poolSize,
NetmapClient: netmap.NewNetmapClient(s.netmapClient), NetmapClient: netmap.NewNetmapClient(s.netmapClient),
EpochTimer: s, EpochTimer: s,
EpochState: s, EpochState: s,
@ -97,7 +100,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(logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error())) s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error()))
} }
mainnetChain.from = fromMainChainBlock mainnetChain.from = fromMainChainBlock
@ -137,12 +140,12 @@ func (s *Server) enableNotarySupport() error {
return nil return nil
} }
func (s *Server) initNotaryConfig() { func (s *Server) initNotaryConfig(ctx context.Context) {
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(logs.InnerringNotarySupport, s.log.Info(ctx, 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),
) )
@ -152,8 +155,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(event.Event) { alphaSync = func(ctx context.Context, _ event.Event) {
s.log.Debug(logs.InnerringAlphabetKeysSyncIsDisabled) s.log.Debug(ctx, logs.InnerringAlphabetKeysSyncIsDisabled)
} }
} else { } else {
// create governance processor // create governance processor
@ -196,16 +199,16 @@ func (s *Server) createIRFetcher() irFetcher {
return irf return irf
} }
func (s *Server) initTimers(cfg *viper.Viper) { func (s *Server) initTimers(ctx context.Context, cfg *viper.Viper) {
s.epochTimer = newEpochTimer(&epochTimerArgs{ s.epochTimer = newEpochTimer(&epochTimerArgs{
newEpochHandlers: s.newEpochTickHandlers(), newEpochHandlers: s.newEpochTickHandlers(ctx),
epoch: s, epoch: s,
}) })
s.addBlockTimer(s.epochTimer) s.addBlockTimer(s.epochTimer)
// initialize emission timer // initialize emission timer
emissionTimer := newEmissionTimer(&emitTimerArgs{ emissionTimer := newEmissionTimer(ctx, &emitTimerArgs{
ap: s.alphabetProcessor, ap: s.alphabetProcessor,
emitDuration: cfg.GetUint32("timers.emit"), emitDuration: cfg.GetUint32("timers.emit"),
}) })
@ -213,18 +216,20 @@ func (s *Server) initTimers(cfg *viper.Viper) {
s.addBlockTimer(emissionTimer) s.addBlockTimer(emissionTimer)
} }
func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error { func (s *Server) initAlphabetProcessor(ctx context.Context, 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: cfg.GetInt("workers.alphabet"), PoolSize: poolSize,
AlphabetContracts: s.contracts.alphabet, AlphabetContracts: s.contracts.alphabet,
NetmapClient: s.netmapClient, NetmapClient: s.netmapClient,
MorphClient: s.morphClient, MorphClient: s.morphClient,
@ -239,12 +244,14 @@ func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error {
return err return err
} }
func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client, frostfsIDClient *frostfsid.Client) error { func (s *Server) initContainerProcessor(ctx context.Context, 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: cfg.GetInt("workers.container"), PoolSize: poolSize,
AlphabetState: s, AlphabetState: s,
ContainerClient: cnrClient, ContainerClient: cnrClient,
MorphClient: cnrClient.Morph(), MorphClient: cnrClient.Morph(),
@ -258,12 +265,14 @@ func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.C
return bindMorphProcessor(containerProcessor, s) return bindMorphProcessor(containerProcessor, s)
} }
func (s *Server) initBalanceProcessor(cfg *viper.Viper, frostfsCli *frostfsClient.Client) error { func (s *Server) initBalanceProcessor(ctx context.Context, 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: cfg.GetInt("workers.balance"), PoolSize: poolSize,
FrostFSClient: frostfsCli, FrostFSClient: frostfsCli,
BalanceSC: s.contracts.balance, BalanceSC: s.contracts.balance,
AlphabetState: s, AlphabetState: s,
@ -276,15 +285,17 @@ func (s *Server) initBalanceProcessor(cfg *viper.Viper, frostfsCli *frostfsClien
return bindMorphProcessor(balanceProcessor, s) return bindMorphProcessor(balanceProcessor, s)
} }
func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error { func (s *Server) initFrostFSMainnetProcessor(ctx context.Context, 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: cfg.GetInt("workers.frostfs"), PoolSize: poolSize,
FrostFSContract: s.contracts.frostfs, FrostFSContract: s.contracts.frostfs,
BalanceClient: s.balanceClient, BalanceClient: s.balanceClient,
NetmapClient: s.netmapClient, NetmapClient: s.netmapClient,
@ -304,10 +315,10 @@ func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error {
return bindMainnetProcessor(frostfsProcessor, s) return bindMainnetProcessor(frostfsProcessor, s)
} }
func (s *Server) initGRPCServer(cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error { func (s *Server) initGRPCServer(ctx context.Context, 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(logs.InnerringNoControlServerEndpointSpecified) s.log.Info(ctx, logs.InnerringNoControlServerEndpointSpecified)
return nil return nil
} }
@ -403,7 +414,7 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) {
return result, nil return result, nil
} }
func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClients) error { func (s *Server) initProcessors(ctx context.Context, cfg *viper.Viper, morphClients *serverMorphClients) error {
irf := s.createIRFetcher() irf := s.createIRFetcher()
s.statusIndex = newInnerRingIndexer( s.statusIndex = newInnerRingIndexer(
@ -418,27 +429,27 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien
return err return err
} }
err = s.initNetmapProcessor(cfg, alphaSync) err = s.initNetmapProcessor(ctx, cfg, alphaSync)
if err != nil { if err != nil {
return err return err
} }
err = s.initContainerProcessor(cfg, morphClients.CnrClient, morphClients.FrostFSIDClient) err = s.initContainerProcessor(ctx, cfg, morphClients.CnrClient, morphClients.FrostFSIDClient)
if err != nil { if err != nil {
return err return err
} }
err = s.initBalanceProcessor(cfg, morphClients.FrostFSClient) err = s.initBalanceProcessor(ctx, cfg, morphClients.FrostFSClient)
if err != nil { if err != nil {
return err return err
} }
err = s.initFrostFSMainnetProcessor(cfg) err = s.initFrostFSMainnetProcessor(ctx, cfg)
if err != nil { if err != nil {
return err return err
} }
err = s.initAlphabetProcessor(cfg) err = s.initAlphabetProcessor(ctx, cfg)
return err return err
} }
@ -446,7 +457,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(logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
} }
morphChain := &chainParams{ morphChain := &chainParams{
@ -471,7 +482,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(logs.InnerringFailedToSetGroupSignerScope, zap.Error(err)) morphChain.log.Info(ctx, 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(control.HealthStatus_STARTING) s.setHealthStatus(ctx, control.HealthStatus_STARTING)
defer func() { defer func() {
if err == nil { if err == nil {
s.setHealthStatus(control.HealthStatus_READY) s.setHealthStatus(ctx, 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() err = s.initConfigFromBlockchain(ctx)
if err != nil { if err != nil {
return err return err
} }
if s.IsAlphabet() { if s.IsAlphabet(ctx) {
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(prm) err = s.voteForSidechainValidator(ctx, 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(logs.InnerringCantVoteForPreparedValidators, s.log.Warn(ctx, logs.InnerringCantVoteForPreparedValidators,
zap.String("error", err.Error())) zap.String("error", err.Error()))
} }
s.tickInitialExpoch() s.tickInitialExpoch(ctx)
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(b *block.Block) { s.morphListener.RegisterBlockHandler(func(ctx context.Context, b *block.Block) {
s.log.Debug(logs.InnerringNewBlock, s.log.Debug(ctx, 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(logs.InnerringCantUpdatePersistentState, s.log.Warn(ctx, 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(b *block.Block) { s.mainnetListener.RegisterBlockHandler(func(ctx context.Context, 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(logs.InnerringCantUpdatePersistentState, s.log.Warn(ctx, 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() { func (s *Server) tickInitialExpoch(ctx context.Context) {
initialEpochTicker := timer.NewOneTickTimer( initialEpochTicker := timer.NewOneTickTimer(
timer.StaticBlockMeter(s.initialEpochTickDelta), timer.StaticBlockMeter(s.initialEpochTickDelta),
func() { func() {
s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{}) s.netmapProcessor.HandleNewEpochTick(ctx, 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() { func (s *Server) Stop(ctx context.Context) {
s.setHealthStatus(control.HealthStatus_SHUTTING_DOWN) s.setHealthStatus(ctx, 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(logs.InnerringCloserError, s.log.Warn(ctx, 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(control.HealthStatus_HEALTH_STATUS_UNDEFINED) server.setHealthStatus(ctx, 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() server.initNotaryConfig(ctx)
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(cfg, morphClients) err = server.initProcessors(ctx, cfg, morphClients)
if err != nil { if err != nil {
return nil, err return nil, err
} }
server.initTimers(cfg) server.initTimers(ctx, cfg)
err = server.initGRPCServer(cfg, log, audit) err = server.initGRPCServer(ctx, 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: &logger.Logger{Logger: p.log.With(zap.String("chain", p.name))}, 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() error { func (s *Server) initConfigFromBlockchain(ctx context.Context) 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() error {
return err return err
} }
s.log.Debug(logs.InnerringReadConfigFromBlockchain, s.log.Debug(ctx, logs.InnerringReadConfigFromBlockchain,
zap.Bool("active", s.IsActive()), zap.Bool("active", s.IsActive(ctx)),
zap.Bool("alphabet", s.IsAlphabet()), zap.Bool("alphabet", s.IsAlphabet(ctx)),
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(ev event.Event) { return func(ctx context.Context, ev event.Event) {
if s.IsAlphabet() { if s.IsAlphabet(ctx) {
f(ev) f(ctx, ev)
} }
} }
} }
func (s *Server) newEpochTickHandlers() []newEpochHandler { func (s *Server) newEpochTickHandlers(ctx context.Context) []newEpochHandler {
newEpochHandlers := []newEpochHandler{ newEpochHandlers := []newEpochHandler{
func() { func() {
s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{}) s.netmapProcessor.HandleNewEpochTick(ctx, timerEvent.NewEpochTick{})
}, },
} }

View file

@ -28,38 +28,39 @@ const (
gasDivisor = 2 gasDivisor = 2
) )
func (s *Server) depositMainNotary() (tx util.Uint256, err error) { func (s *Server) depositMainNotary(ctx context.Context) (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() (util.Uint256, error) { func (s *Server) depositSideNotary(ctx context.Context) (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(depositAmount) tx, _, err := s.morphClient.DepositEndlessNotary(ctx, depositAmount)
return tx, err return tx, err
} }
func (s *Server) notaryHandler(_ event.Event) { func (s *Server) notaryHandler(ctx context.Context, _ event.Event) {
if !s.mainNotaryConfig.disabled { if !s.mainNotaryConfig.disabled {
_, err := s.depositMainNotary() _, err := s.depositMainNotary(ctx)
if err != nil { if err != nil {
s.log.Error(logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err))
} }
} }
if _, err := s.depositSideNotary(); err != nil { if _, err := s.depositSideNotary(ctx); err != nil {
s.log.Error(logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err))
} }
} }
@ -72,7 +73,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() tx, err := deposit(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -81,11 +82,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(logs.InnerringNotaryDepositHasAlreadyBeenMade) s.log.Info(ctx, logs.InnerringNotaryDepositHasAlreadyBeenMade)
return nil return nil
} }
s.log.Info(msg) s.log.Info(ctx, msg)
return await(ctx, tx) return await(ctx, tx)
} }

View file

@ -1,6 +1,8 @@
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"
@ -8,16 +10,16 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (ap *Processor) HandleGasEmission(ev event.Event) { func (ap *Processor) HandleGasEmission(ctx context.Context, ev event.Event) {
_ = ev.(timers.NewAlphabetEmitTick) _ = ev.(timers.NewAlphabetEmitTick)
ap.log.Info(logs.AlphabetTick, zap.String("type", "alphabet gas emit")) ap.log.Info(ctx, 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", ap.processEmit) err := processors.SubmitEvent(ap.pool, ap.metrics, "alphabet_emit_gas", func() bool { return ap.processEmit(ctx) })
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(logs.AlphabetAlphabetProcessorWorkerPoolDrained, ap.log.Warn(ctx, logs.AlphabetAlphabetProcessorWorkerPoolDrained,
zap.Int("capacity", ap.pool.Cap())) zap.Int("capacity", ap.pool.Cap()))
} }
} }

View file

@ -1,11 +1,13 @@
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"
@ -60,7 +62,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(timers.NewAlphabetEmitTick{}) processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{})
processor.WaitPoolRunning() processor.WaitPoolRunning()
@ -137,7 +139,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(timers.NewAlphabetEmitTick{}) processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{})
processor.WaitPoolRunning() processor.WaitPoolRunning()
@ -198,7 +200,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(timers.NewAlphabetEmitTick{}) processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{})
processor.WaitPoolRunning() processor.WaitPoolRunning()
@ -219,7 +221,7 @@ type testIndexer struct {
index int index int
} }
func (i *testIndexer) AlphabetIndex() int { func (i *testIndexer) AlphabetIndex(context.Context) int {
return i.index return i.index
} }
@ -246,7 +248,7 @@ type testMorphClient struct {
batchTransferedGas []batchTransferGas batchTransferedGas []batchTransferGas
} }
func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (client.InvokeRes, error) {
c.invokedMethods = append(c.invokedMethods, c.invokedMethods = append(c.invokedMethods,
invokedMethod{ invokedMethod{
contract: contract, contract: contract,
@ -254,7 +256,7 @@ func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, metho
method: method, method: method,
args: args, args: args,
}) })
return 0, nil return client.InvokeRes{}, 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,6 +1,7 @@
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"
@ -13,39 +14,39 @@ import (
const emitMethod = "emit" const emitMethod = "emit"
func (ap *Processor) processEmit() bool { func (ap *Processor) processEmit(ctx context.Context) bool {
index := ap.irList.AlphabetIndex() index := ap.irList.AlphabetIndex(ctx)
if index < 0 { if index < 0 {
ap.log.Info(logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) ap.log.Info(ctx, 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(logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, ap.log.Debug(ctx, 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(contract, 0, emitMethod) _, err := ap.morphClient.Invoke(ctx, contract, 0, emitMethod)
if err != nil { if err != nil {
ap.log.Warn(logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error()))
return false return false
} }
if ap.storageEmission == 0 { if ap.storageEmission == 0 {
ap.log.Info(logs.AlphabetStorageNodeEmissionIsOff) ap.log.Info(ctx, 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(logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes,
zap.String("error", err.Error())) zap.String("error", err.Error()))
return false return false
@ -58,7 +59,7 @@ func (ap *Processor) processEmit() bool {
ap.pwLock.RUnlock() ap.pwLock.RUnlock()
extraLen := len(pw) extraLen := len(pw)
ap.log.Debug(logs.AlphabetGasEmission, ap.log.Debug(ctx, logs.AlphabetGasEmission,
zap.Int("network_map", nmLen), zap.Int("network_map", nmLen),
zap.Int("extra_wallets", extraLen)) zap.Int("extra_wallets", extraLen))
@ -68,20 +69,20 @@ func (ap *Processor) processEmit() bool {
gasPerNode := fixedn.Fixed8(ap.storageEmission / uint64(nmLen+extraLen)) gasPerNode := fixedn.Fixed8(ap.storageEmission / uint64(nmLen+extraLen))
ap.transferGasToNetmapNodes(nmNodes, gasPerNode) ap.transferGasToNetmapNodes(ctx, nmNodes, gasPerNode)
ap.transferGasToExtraNodes(pw, gasPerNode) ap.transferGasToExtraNodes(ctx, pw, gasPerNode)
return true return true
} }
func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerNode fixedn.Fixed8) { func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, 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(logs.AlphabetCantParseNodePublicKey, ap.log.Warn(ctx, logs.AlphabetCantParseNodePublicKey,
zap.String("error", err.Error())) zap.String("error", err.Error()))
continue continue
@ -89,7 +90,7 @@ func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerN
err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode) err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode)
if err != nil { if err != nil {
ap.log.Warn(logs.AlphabetCantTransferGas, ap.log.Warn(ctx, 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()),
@ -98,7 +99,7 @@ func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerN
} }
} }
func (ap *Processor) transferGasToExtraNodes(pw []util.Uint160, gasPerNode fixedn.Fixed8) { func (ap *Processor) transferGasToExtraNodes(ctx context.Context, 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 {
@ -106,7 +107,7 @@ func (ap *Processor) transferGasToExtraNodes(pw []util.Uint160, gasPerNode fixed
for i, addr := range pw { for i, addr := range pw {
receiversLog[i] = addr.StringLE() receiversLog[i] = addr.StringLE()
} }
ap.log.Warn(logs.AlphabetCantTransferGasToWallet, ap.log.Warn(ctx, 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() int AlphabetIndex(context.Context) 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(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (client.InvokeRes, 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,8 +85,6 @@ 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,6 +1,7 @@
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"
@ -10,20 +11,20 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (bp *Processor) handleLock(ev event.Event) { func (bp *Processor) handleLock(ctx context.Context, ev event.Event) {
lock := ev.(balanceEvent.Lock) lock := ev.(balanceEvent.Lock)
bp.log.Info(logs.Notification, bp.log.Info(ctx, 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(&lock) return bp.processLock(ctx, &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(logs.BalanceBalanceWorkerPoolDrained, bp.log.Warn(ctx, logs.BalanceBalanceWorkerPoolDrained,
zap.Int("capacity", bp.pool.Cap())) zap.Int("capacity", bp.pool.Cap()))
} }
} }

View file

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

View file

@ -1,6 +1,8 @@
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"
@ -9,9 +11,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(lock *balanceEvent.Lock) bool { func (bp *Processor) processLock(ctx context.Context, lock *balanceEvent.Lock) bool {
if !bp.alphabetState.IsAlphabet() { if !bp.alphabetState.IsAlphabet(ctx) {
bp.log.Info(logs.BalanceNonAlphabetModeIgnoreBalanceLock) bp.log.Info(ctx, logs.BalanceNonAlphabetModeIgnoreBalanceLock)
return true return true
} }
@ -23,9 +25,9 @@ func (bp *Processor) processLock(lock *balanceEvent.Lock) bool {
prm.SetLock(lock.LockAccount()) prm.SetLock(lock.LockAccount())
prm.SetHash(lock.TxHash()) prm.SetHash(lock.TxHash())
err := bp.frostfsClient.Cheque(prm) err := bp.frostfsClient.Cheque(ctx, prm)
if err != nil { if err != nil {
bp.log.Error(logs.BalanceCantSendLockAssetTx, zap.Error(err)) bp.log.Error(ctx, 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,13 +12,12 @@ 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() bool IsAlphabet(context.Context) bool
} }
// PrecisionConverter converts balance amount values. // PrecisionConverter converts balance amount values.
@ -27,7 +26,7 @@ type (
} }
FrostFSClient interface { FrostFSClient interface {
Cheque(p frostfscontract.ChequePrm) error Cheque(ctx context.Context, p frostfscontract.ChequePrm) error
} }
// Processor of events produced by balance contract in the morphchain. // Processor of events produced by balance contract in the morphchain.
@ -68,8 +67,6 @@ 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,6 +1,7 @@
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"
@ -11,40 +12,40 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (cp *Processor) handlePut(ev event.Event) { func (cp *Processor) handlePut(ctx context.Context, ev event.Event) {
put := ev.(putEvent) put := ev.(putEvent)
id := sha256.Sum256(put.Container()) id := sha256.Sum256(put.Container())
cp.log.Info(logs.Notification, cp.log.Info(ctx, 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(put) return cp.processContainerPut(ctx, 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(logs.ContainerContainerProcessorWorkerPoolDrained, cp.log.Warn(ctx, logs.ContainerContainerProcessorWorkerPoolDrained,
zap.Int("capacity", cp.pool.Cap())) zap.Int("capacity", cp.pool.Cap()))
} }
} }
func (cp *Processor) handleDelete(ev event.Event) { func (cp *Processor) handleDelete(ctx context.Context, ev event.Event) {
del := ev.(containerEvent.Delete) del := ev.(containerEvent.Delete)
cp.log.Info(logs.Notification, cp.log.Info(ctx, 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(del) return cp.processContainerDelete(ctx, 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(logs.ContainerContainerProcessorWorkerPoolDrained, cp.log.Warn(ctx, logs.ContainerContainerProcessorWorkerPoolDrained,
zap.Int("capacity", cp.pool.Cap())) zap.Int("capacity", cp.pool.Cap()))
} }
} }

View file

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

View file

@ -1,6 +1,7 @@
package container package container
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
@ -36,27 +37,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(put putEvent) bool { func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool {
if !cp.alphabetState.IsAlphabet() { if !cp.alphabetState.IsAlphabet(ctx) {
cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerPut) cp.log.Info(ctx, logs.ContainerNonAlphabetModeIgnoreContainerPut)
return true return true
} }
ctx := &putContainerContext{ pctx := &putContainerContext{
e: put, e: put,
} }
err := cp.checkPutContainer(ctx) err := cp.checkPutContainer(pctx)
if err != nil { if err != nil {
cp.log.Error(logs.ContainerPutContainerCheckFailed, cp.log.Error(ctx, logs.ContainerPutContainerCheckFailed,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
return false return false
} }
if err := cp.morphClient.NotarySignAndInvokeTX(ctx.e.NotaryRequest().MainTransaction); err != nil { if err := cp.morphClient.NotarySignAndInvokeTX(pctx.e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(logs.ContainerCouldNotApprovePutContainer, cp.log.Error(ctx, logs.ContainerCouldNotApprovePutContainer,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
return false return false
@ -103,15 +104,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(e containerEvent.Delete) bool { func (cp *Processor) processContainerDelete(ctx context.Context, e containerEvent.Delete) bool {
if !cp.alphabetState.IsAlphabet() { if !cp.alphabetState.IsAlphabet(ctx) {
cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerDelete) cp.log.Info(ctx, logs.ContainerNonAlphabetModeIgnoreContainerDelete)
return true return true
} }
err := cp.checkDeleteContainer(e) err := cp.checkDeleteContainer(e)
if err != nil { if err != nil {
cp.log.Error(logs.ContainerDeleteContainerCheckFailed, cp.log.Error(ctx, logs.ContainerDeleteContainerCheckFailed,
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -119,7 +120,7 @@ func (cp *Processor) processContainerDelete(e containerEvent.Delete) bool {
} }
if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil { if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(logs.ContainerCouldNotApproveDeleteContainer, cp.log.Error(ctx, 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,13 +15,12 @@ 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() bool IsAlphabet(context.Context) bool
} }
ContClient interface { ContClient interface {
@ -97,8 +96,6 @@ 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)

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