forked from TrueCloudLab/frostfs-node
[#1120] cli: Add explain to object nodes
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
654384990c
commit
a45b548a6f
1 changed files with 77 additions and 18 deletions
|
@ -29,6 +29,7 @@ import (
|
|||
|
||||
const (
|
||||
verifyPresenceAllFlag = "verify-presence-all"
|
||||
explainFlag = "explain"
|
||||
)
|
||||
|
||||
var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint")
|
||||
|
@ -50,6 +51,11 @@ type boolError struct {
|
|||
err error
|
||||
}
|
||||
|
||||
type objectPlacement struct {
|
||||
requiredNodes []netmapSDK.NodeInfo
|
||||
confirmedNodes []netmapSDK.NodeInfo
|
||||
}
|
||||
|
||||
var objectNodesCmd = &cobra.Command{
|
||||
Use: "nodes",
|
||||
Short: "List of nodes where the object is stored",
|
||||
|
@ -71,7 +77,8 @@ func initObjectNodesCmd() {
|
|||
flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
|
||||
_ = objectGetCmd.MarkFlagRequired(commonflags.OIDFlag)
|
||||
|
||||
flags.Bool("verify-presence-all", false, "Verify the actual presence of the object on all netmap nodes")
|
||||
flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes")
|
||||
flags.Bool(explainFlag, false, "Show detailed information about the object placement")
|
||||
}
|
||||
|
||||
func objectNodes(cmd *cobra.Command, _ []string) {
|
||||
|
@ -86,11 +93,11 @@ func objectNodes(cmd *cobra.Command, _ []string) {
|
|||
|
||||
placementPolicy, netmap := getPlacementPolicyAndNetmap(cmd, cnrID, cli)
|
||||
|
||||
requiredPlacement := getRequiredPlacement(cmd, objects, placementPolicy, netmap)
|
||||
requiredNodes, objectsPlacement := getRequiredPlacement(cmd, objects, placementPolicy, netmap)
|
||||
|
||||
actualPlacement := getActualPlacement(cmd, netmap, requiredPlacement, pk, objects)
|
||||
actualPlacement := getActualPlacement(cmd, netmap, requiredNodes, pk, objects, objectsPlacement)
|
||||
|
||||
printPlacement(cmd, netmap, requiredPlacement, actualPlacement)
|
||||
printPlacement(cmd, netmap, requiredNodes, actualPlacement, objID, objects, objectsPlacement)
|
||||
}
|
||||
|
||||
func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) []phyObject {
|
||||
|
@ -249,15 +256,16 @@ func getNetMap(ctx context.Context, cli *client.Client) (*netmapSDK.NetMap, erro
|
|||
return &nm, nil
|
||||
}
|
||||
|
||||
func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo {
|
||||
func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) {
|
||||
if policy.IsECPlacement(placementPolicy) {
|
||||
return getECRequiredPlacement(cmd, objects, placementPolicy, netmap)
|
||||
}
|
||||
return getReplicaRequiredPlacement(cmd, objects, placementPolicy, netmap)
|
||||
}
|
||||
|
||||
func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo {
|
||||
func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) {
|
||||
nodes := make(map[uint64]netmapSDK.NodeInfo)
|
||||
objectsNodes := make(map[oid.ID]objectPlacement)
|
||||
placementBuilder := placement.NewNetworkMapBuilder(netmap)
|
||||
for _, object := range objects {
|
||||
placement, err := placementBuilder.BuildPlacement(object.containerID, &object.objectID, placementPolicy)
|
||||
|
@ -270,23 +278,29 @@ func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placem
|
|||
break
|
||||
}
|
||||
nodes[n.Hash()] = n
|
||||
|
||||
op := objectsNodes[object.objectID]
|
||||
op.requiredNodes = append(op.requiredNodes, n)
|
||||
objectsNodes[object.objectID] = op
|
||||
|
||||
nodeIdx++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes
|
||||
return nodes, objectsNodes
|
||||
}
|
||||
|
||||
func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo {
|
||||
func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) {
|
||||
nodes := make(map[uint64]netmapSDK.NodeInfo)
|
||||
objectsNodes := make(map[oid.ID]objectPlacement)
|
||||
for _, object := range objects {
|
||||
getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, nodes)
|
||||
getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, nodes, objectsNodes)
|
||||
}
|
||||
return nodes
|
||||
return nodes, objectsNodes
|
||||
}
|
||||
|
||||
func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, nodes map[uint64]netmapSDK.NodeInfo) {
|
||||
func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, nodes map[uint64]netmapSDK.NodeInfo, objectNodes map[oid.ID]objectPlacement) {
|
||||
placementObjectID := object.objectID
|
||||
if object.ecHeader != nil {
|
||||
placementObjectID = object.ecHeader.parent
|
||||
|
@ -299,6 +313,10 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem
|
|||
if object.storedOnAllContainerNodes {
|
||||
for _, node := range vector {
|
||||
nodes[node.Hash()] = node
|
||||
|
||||
op := objectNodes[object.objectID]
|
||||
op.requiredNodes = append(op.requiredNodes, node)
|
||||
objectNodes[object.objectID] = op
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -308,12 +326,16 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem
|
|||
nodeIdx := chunkIdx % len(vector)
|
||||
node := vector[nodeIdx]
|
||||
nodes[node.Hash()] = node
|
||||
|
||||
op := objectNodes[object.objectID]
|
||||
op.requiredNodes = append(op.requiredNodes, node)
|
||||
objectNodes[object.objectID] = op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo,
|
||||
pk *ecdsa.PrivateKey, objects []phyObject,
|
||||
pk *ecdsa.PrivateKey, objects []phyObject, objectNodes map[oid.ID]objectPlacement,
|
||||
) map[uint64]boolError {
|
||||
result := make(map[uint64]boolError)
|
||||
resultMtx := &sync.Mutex{}
|
||||
|
@ -348,6 +370,11 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPl
|
|||
v.value, v.err = isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk)
|
||||
resultMtx.Lock()
|
||||
defer resultMtx.Unlock()
|
||||
if v.err == nil && v.value {
|
||||
op := objectNodes[object.objectID]
|
||||
op.confirmedNodes = append(op.confirmedNodes, cand)
|
||||
objectNodes[object.objectID] = op
|
||||
}
|
||||
if prev, exists := result[cand.Hash()]; exists && (prev.err != nil || prev.value) {
|
||||
return nil
|
||||
}
|
||||
|
@ -418,12 +445,12 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID,
|
|||
return false, err
|
||||
}
|
||||
|
||||
func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, actualPlacement map[uint64]boolError) {
|
||||
func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo,
|
||||
actualPlacement map[uint64]boolError, objID oid.ID, objects []phyObject, objectNodes map[oid.ID]objectPlacement,
|
||||
) {
|
||||
w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug)
|
||||
defer func() {
|
||||
commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", w.Flush())
|
||||
}()
|
||||
fmt.Fprintln(w, "Node ID\tShould contain object\tActually contains object\t")
|
||||
_, err := fmt.Fprintln(w, "Node ID\tShould contain object\tActually contains object\t")
|
||||
commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", err)
|
||||
for _, n := range netmap.Nodes() {
|
||||
nodeID := hex.EncodeToString(n.PublicKey())
|
||||
_, required := requiredPlacement[n.Hash()]
|
||||
|
@ -436,6 +463,38 @@ func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacem
|
|||
actualStr = strconv.FormatBool(actual.value)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t\n", nodeID, strconv.FormatBool(required), actualStr)
|
||||
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t\n", nodeID, strconv.FormatBool(required), actualStr)
|
||||
commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", err)
|
||||
}
|
||||
commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", w.Flush())
|
||||
|
||||
if explain, _ := cmd.Flags().GetBool(explainFlag); !explain {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects))
|
||||
|
||||
for _, object := range objects {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "- %s\n", object.objectID)
|
||||
if object.ecHeader != nil {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "\tEC index: %d\n", object.ecHeader.index)
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "\tEC parent: %s\n", object.ecHeader.parent.EncodeToString())
|
||||
}
|
||||
op, ok := objectNodes[object.objectID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(op.requiredNodes) > 0 {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "\tRequired nodes:\n")
|
||||
for _, node := range op.requiredNodes {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "\t\t- %s\n", hex.EncodeToString(node.PublicKey()))
|
||||
}
|
||||
}
|
||||
if len(op.confirmedNodes) > 0 {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "\tActual nodes:\n")
|
||||
for _, node := range op.confirmedNodes {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "\t\t- %s\n", hex.EncodeToString(node.PublicKey()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue