forked from TrueCloudLab/frostfs-node
[#979] adm/subnet: Add commands to add/remove nodes
Implement `ManageNodes` operation on morph subnet client. Add `node add` and `node remove` commands to `subnet` section. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
579c3717a5
commit
98e0792b08
2 changed files with 179 additions and 0 deletions
|
@ -646,6 +646,117 @@ var cmdSubnetClientRemove = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
// cmdSubnetNode flags.
|
||||
const (
|
||||
// node ID
|
||||
flagSubnetNode = "id"
|
||||
// ID of the subnet to be managed
|
||||
flagSubnetNodeSubnet = flagSubnet
|
||||
)
|
||||
|
||||
// common executor cmdSubnetNodeAdd and cmdSubnetNodeRemove commands.
|
||||
func manageSubnetNodes(cmd *cobra.Command, rm bool) error {
|
||||
// read private key
|
||||
var key keys.PrivateKey
|
||||
|
||||
err := readSubnetKey(&key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read private key: %w", err)
|
||||
}
|
||||
|
||||
// read ID and encode it
|
||||
var id subnetid.ID
|
||||
|
||||
err = id.UnmarshalText([]byte(viper.GetString(flagSubnetNodeSubnet)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode ID text: %w", err)
|
||||
}
|
||||
|
||||
if subnetid.IsZero(id) {
|
||||
return errZeroSubnet
|
||||
}
|
||||
|
||||
binID, err := id.Marshal()
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal subnet ID: %w", err)
|
||||
}
|
||||
|
||||
// read node ID and encode it
|
||||
binNodeID, err := hex.DecodeString(viper.GetString(flagSubnetNode))
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode node ID text: %w", err)
|
||||
}
|
||||
|
||||
var pubkey keys.PublicKey
|
||||
if err = pubkey.DecodeBytes(binNodeID); err != nil {
|
||||
return fmt.Errorf("node ID format: %w", err)
|
||||
}
|
||||
|
||||
var prm morphsubnet.ManageNodesPrm
|
||||
|
||||
prm.SetSubnet(binID)
|
||||
prm.SetNode(binNodeID)
|
||||
|
||||
if rm {
|
||||
prm.SetRemove()
|
||||
}
|
||||
|
||||
// initialize morph subnet client
|
||||
var cSubnet morphsubnet.Client
|
||||
|
||||
err = initSubnetClient(&cSubnet, &key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("init subnet client: %w", err)
|
||||
}
|
||||
|
||||
_, err = cSubnet.ManageNodes(prm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("morph call: %w", err)
|
||||
}
|
||||
|
||||
var op string
|
||||
|
||||
if rm {
|
||||
op = "Remove"
|
||||
} else {
|
||||
op = "Add"
|
||||
}
|
||||
|
||||
cmd.Printf("%s node request sent successfully.\n", op)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// command to manage subnet nodes.
|
||||
var cmdSubnetNode = &cobra.Command{
|
||||
Use: "node",
|
||||
Short: "Manage nodes of the NeoFS subnet.",
|
||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||
viperBindFlags(cmd,
|
||||
flagSubnetNode,
|
||||
flagSubnetNodeSubnet,
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
// command to add subnet node.
|
||||
var cmdSubnetNodeAdd = &cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add node to the NeoFS subnet.",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return manageSubnetNodes(cmd, false)
|
||||
},
|
||||
}
|
||||
|
||||
// command to remove subnet node.
|
||||
var cmdSubnetNodeRemove = &cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "Remove node from the NeoFS subnet.",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return manageSubnetNodes(cmd, true)
|
||||
},
|
||||
}
|
||||
|
||||
// returns function which calls PreRun on parent if it exists.
|
||||
func inheritPreRun(preRun func(*cobra.Command, []string)) func(*cobra.Command, []string) {
|
||||
return func(cmd *cobra.Command, args []string) {
|
||||
|
@ -718,6 +829,19 @@ func init() {
|
|||
cmdSubnetClientRemove,
|
||||
)
|
||||
|
||||
// subnet node flags
|
||||
nodeFlags := cmdSubnetNode.PersistentFlags()
|
||||
nodeFlags.String(flagSubnetNode, "", "Hex-encoded public key of the node")
|
||||
_ = cmdSubnetAdmin.MarkFlagRequired(flagSubnetNode)
|
||||
nodeFlags.String(flagSubnetNodeSubnet, "", "ID of the subnet to manage nodes")
|
||||
_ = cmdSubnetNode.MarkFlagRequired(flagSubnetNodeSubnet)
|
||||
|
||||
// add all node managing commands to corresponding command section
|
||||
addCommandInheritPreRun(cmdSubnetNode,
|
||||
cmdSubnetNodeAdd,
|
||||
cmdSubnetNodeRemove,
|
||||
)
|
||||
|
||||
// subnet global flags
|
||||
cmdSubnetFlags := cmdSubnet.PersistentFlags()
|
||||
cmdSubnetFlags.StringP(flagSubnetEndpoint, "r", "", "N3 RPC node endpoint")
|
||||
|
@ -735,5 +859,6 @@ func init() {
|
|||
cmdSubnetGet,
|
||||
cmdSubnetAdmin,
|
||||
cmdSubnetClient,
|
||||
cmdSubnetNode,
|
||||
)
|
||||
}
|
||||
|
|
54
pkg/morph/client/subnet/nodes.go
Normal file
54
pkg/morph/client/subnet/nodes.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package morphsubnet
|
||||
|
||||
import "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||
|
||||
// ManageNodesPrm groups parameters of node management in Subnet contract.
|
||||
//
|
||||
// Zero value adds node to subnet. Subnet and node IDs must be specified via setters.
|
||||
type ManageNodesPrm struct {
|
||||
// remove or add node
|
||||
rm bool
|
||||
|
||||
args [2]interface{}
|
||||
}
|
||||
|
||||
// SetRemove marks node to be removed. By default, node is added.
|
||||
func (x *ManageNodesPrm) SetRemove() {
|
||||
x.rm = true
|
||||
}
|
||||
|
||||
// SetSubnet sets identifier of the subnet in a binary NeoFS API protocol format.
|
||||
func (x *ManageNodesPrm) SetSubnet(id []byte) {
|
||||
x.args[0] = id
|
||||
}
|
||||
|
||||
// SetNode sets node's public key in a binary format.
|
||||
func (x *ManageNodesPrm) SetNode(id []byte) {
|
||||
x.args[1] = id
|
||||
}
|
||||
|
||||
// ManageNodesRes groups resulting values of node management methods of Subnet contract.
|
||||
type ManageNodesRes struct{}
|
||||
|
||||
// ManageNodes manages node list of the NeoFS subnet through Subnet contract calls.
|
||||
func (x Client) ManageNodes(prm ManageNodesPrm) (*ManageNodesRes, error) {
|
||||
var method string
|
||||
|
||||
if prm.rm {
|
||||
method = "removeNode"
|
||||
} else {
|
||||
method = "addNode"
|
||||
}
|
||||
|
||||
var prmInvoke client.InvokePrm
|
||||
|
||||
prmInvoke.SetMethod(method)
|
||||
prmInvoke.SetArgs(prm.args[:]...)
|
||||
|
||||
err := x.client.Invoke(prmInvoke)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return new(ManageNodesRes), nil
|
||||
}
|
Loading…
Reference in a new issue