Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node local status #2261

Merged
merged 53 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
bc89a4d
node local init
arturrez Oct 2, 2024
37da482
hardcode etna devnet config
arturrez Oct 2, 2024
9459b43
wip
arturrez Oct 3, 2024
3ddc12c
rm not needed utils
arturrez Oct 3, 2024
34f9382
Merge branch 'acp-77' into node-create-local
arturrez Oct 3, 2024
035cb92
ready for draft PR
arturrez Oct 3, 2024
3b1e676
nits
arturrez Oct 3, 2024
495d59c
refactor - wip
arturrez Oct 4, 2024
1d52dd5
make sure we can resume without prompts
arturrez Oct 5, 2024
1c1d061
add custom network and local cluster
arturrez Oct 5, 2024
ac37dce
devnet instead of custom network, rm custom
arturrez Oct 5, 2024
9acca2e
Merge branch 'acp-77' into node-create-local
arturrez Oct 8, 2024
64ba256
go mod tidy
arturrez Oct 8, 2024
71e313b
upgrade.json for etna devnet
arturrez Oct 8, 2024
884043e
more local cluster
arturrez Oct 9, 2024
74b9a7c
separate between local network and local cluster
felipemadero Oct 10, 2024
dce0e98
Merge branch 'acp-77' into node-create-local
felipemadero Oct 10, 2024
23b4e86
working
felipemadero Oct 10, 2024
b8f20ca
nit
felipemadero Oct 10, 2024
e225ed5
fix plugin
felipemadero Oct 10, 2024
7a12d78
nit
felipemadero Oct 10, 2024
93a3cfe
improve snapshot management
felipemadero Oct 10, 2024
c617154
fix bug
felipemadero Oct 10, 2024
c6ed553
nit
felipemadero Oct 10, 2024
afb44a1
proper etna devnet boostrappers
arturrez Oct 10, 2024
f2653d8
fix bug with local rootdir
arturrez Oct 11, 2024
3b3d699
remove global node config stuff
felipemadero Oct 11, 2024
3b4cdfe
destroy node data and processes if bad start
felipemadero Oct 11, 2024
61eb94d
nit
felipemadero Oct 11, 2024
46fa068
always use fresh staking keys
felipemadero Oct 11, 2024
ac2bdc3
nit
felipemadero Oct 11, 2024
ea9d1b9
so less flags
felipemadero Oct 11, 2024
02f02ab
add back fast boot time
felipemadero Oct 11, 2024
c788f4a
Merge branch 'node-create-local-fix' into node-create-local
felipemadero Oct 11, 2024
27ecc41
add checks for local cluster. minor refactor (#2239)
arturrez Oct 12, 2024
046ccb6
bump anr
felipemadero Oct 12, 2024
f134935
fixes for convert flow
felipemadero Oct 12, 2024
719aea1
add check for already initialized error on PoA init
felipemadero Oct 13, 2024
2aa05d1
nit
felipemadero Oct 13, 2024
72c1464
use anr main
felipemadero Oct 14, 2024
f22c1fd
Merge branch 'acp-77' into node-create-local
sukantoraymond Oct 15, 2024
c44c41b
fix merge
sukantoraymond Oct 15, 2024
de1a9f5
Local mkdir rootdir (#2245)
arturrez Oct 15, 2024
05c5218
update anr
sukantoraymond Oct 15, 2024
071da19
add `node local status` command
arturrez Oct 16, 2024
007df3c
add logging.Green.Wrap(
arturrez Oct 16, 2024
3de3b85
Merge branch 'acp-77' into node-local-improv
arturrez Oct 16, 2024
120abbc
lint
arturrez Oct 16, 2024
a65bf9c
fix merge
arturrez Oct 16, 2024
bbaf3f8
make `node status` works with local clusters
arturrez Oct 16, 2024
59bc9cc
detect Stopped state for local clusterName passed as arg
arturrez Oct 16, 2024
d2ed2c5
add stopped status to all local clusters
arturrez Oct 16, 2024
0e647ab
undo change
sukantoraymond Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions cmd/blockchaincmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/ava-labs/avalanchego/api/info"
"os"
"path/filepath"
"strings"
"time"

"github.com/ava-labs/avalanche-cli/pkg/evm"
"github.com/ava-labs/avalanchego/api/info"

"github.com/ava-labs/avalanche-cli/pkg/evm"
"github.com/ava-labs/avalanche-cli/pkg/node"
"github.com/ava-labs/avalanchego/vms/platformvm/warp/message"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -135,9 +135,10 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`,
cmd.Flags().StringVar(&icmSpec.RegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to an interchain messenger registry bytecode file")
cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators, leave Node-ID and BLS values empty if using --generate-node-id=true")
cmd.Flags().BoolVar(&generateNodeID, "generate-node-id", false, "whether to create new node id for bootstrap validators (Node-ID and BLS values in bootstrap JSON file will be overridden if --bootstrap-filepath flag is used)")
cmd.Flags().StringSliceVar(&bootstrapEndpoints, "bootstrap-enu dpoints", nil, "take validator node info from the given endpoints")
cmd.Flags().StringSliceVar(&bootstrapEndpoints, "bootstrap-endpoints", nil, "take validator node info from the given endpoints")
cmd.Flags().BoolVar(&useLocalMachine, "use-local-machine", false, "use local machine as a blockchain validator")
cmd.Flags().StringVar(&localMachineCluster, "local-machine-cluster", "", "existing local machine to be used as a blockchain validator")

return cmd
}

Expand Down Expand Up @@ -489,21 +490,16 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
if localMachineCluster != "" {
// don't destroy cluster if local cluster name is provided
clusterName = localMachineCluster
} else {
// destroy any cluster with same name before we start local node
// we don't want to reuse snapshots from previous sessions
if utils.DirectoryExists(app.GetLocalDir(clusterName)) {
_ = node.DestroyLocalNode(app, clusterName)
}
} else if utils.DirectoryExists(app.GetLocalDir(clusterName)) {
_ = node.DestroyLocalNode(app, clusterName)
}
// destroy any cluster with same name before we start local node
// we don't want to reuse snapshots from previous sessions
// TODO: replace bootstrapEndpoints with dynamic port number
bootstrapEndpoints = []string{"http://127.0.0.1:9650"}
anrSettings := node.ANRSettings{}
avagoVersionSettings := node.AvalancheGoVersionSettings{}
useEtnaDevnet := false
if network.Kind == models.EtnaDevnet {
useEtnaDevnet = true
}
useEtnaDevnet := network.Kind == models.EtnaDevnet
if avagoBinaryPath == "" {
ux.Logger.PrintToUser("Local build of Avalanche Go is required to create an Avalanche node using local machine")
ux.Logger.PrintToUser("Please download Avalanche Go repo at https://github.com/ava-labs/avalanchego and build from source through ./scripts/build.sh")
Expand All @@ -519,7 +515,6 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
return err
}
}

if len(bootstrapEndpoints) > 0 {
var changeAddr string
for _, endpoint := range bootstrapEndpoints {
Expand All @@ -545,8 +540,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
ChangeOwnerAddr: changeAddr,
})
}
}
if len(bootstrapValidators) == 0 {
} else {
bootstrapValidators, err = promptBootstrapValidators(network)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion cmd/nodecmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ func addNodeToClustersConfig(network models.Network, nodeID, clusterName string,
}
clusterConfig := clustersConfig.Clusters[clusterName]
// if supplied network in argument is empty, don't change current cluster network in cluster_config.json
if network != models.UndefinedNetwork {
if !network.IsUndefined() {
clusterConfig.Network = network
}
clusterConfig.HTTPAccess = constants.HTTPAccess(publicHTTPPortAccess)
Expand Down
34 changes: 0 additions & 34 deletions cmd/nodecmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package nodecmd
import (
"errors"
"fmt"
"github.com/ava-labs/avalanche-cli/pkg/models"
"os"
"strings"

Expand Down Expand Up @@ -325,36 +324,3 @@ func getClusterMonitoringNode(clusterName string) (string, error) {
}
return clustersConfig.Clusters[clusterName].MonitoringInstance, nil
}

func checkCluster(clusterName string) error {
_, err := getClusterNodes(clusterName)
return err
}

func checkClusterExists(clusterName string) (bool, error) {
clustersConfig := models.ClustersConfig{}
if app.ClustersConfigExists() {
var err error
clustersConfig, err = app.LoadClustersConfig()
if err != nil {
return false, err
}
}
_, ok := clustersConfig.Clusters[clusterName]
return ok, nil
}

func getClusterNodes(clusterName string) ([]string, error) {
if exists, err := checkClusterExists(clusterName); err != nil || !exists {
return nil, fmt.Errorf("cluster %q not found", clusterName)
}
clustersConfig, err := app.LoadClustersConfig()
if err != nil {
return nil, err
}
clusterNodes := clustersConfig.Clusters[clusterName].Nodes
if len(clusterNodes) == 0 {
return nil, fmt.Errorf("no nodes found in cluster %s", clusterName)
}
return clusterNodes, nil
}
10 changes: 6 additions & 4 deletions cmd/nodecmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ func list(_ *cobra.Command, _ []string) error {
if err := node.CheckCluster(app, clusterName); err != nil {
return err
}
cloudIDs := clusterConf.GetCloudIDs()
nodeIDs := []string{}
for _, cloudID := range clusterConf.GetCloudIDs() {
for _, cloudID := range cloudIDs {
nodeIDStr := "----------------------------------------"
if clusterConf.IsAvalancheGoHost(cloudID) {
if nodeID, err := getNodeID(app.GetNodeInstanceDirPath(cloudID)); err != nil {
Expand All @@ -56,11 +57,12 @@ func list(_ *cobra.Command, _ []string) error {
}
nodeIDs = append(nodeIDs, nodeIDStr)
}
if clusterConf.External {
switch {
case clusterConf.External:
ux.Logger.PrintToUser("cluster %q (%s) EXTERNAL", clusterName, clusterConf.Network.Kind.String())
} else if clusterConf.Local {
case clusterConf.Local:
ux.Logger.PrintToUser("cluster %q (%s) LOCAL", clusterName, clusterConf.Network.Kind.String())
} else {
default:
ux.Logger.PrintToUser("Cluster %q (%s)", clusterName, clusterConf.Network.Kind.String())
}
for i, cloudID := range clusterConf.GetCloudIDs() {
Expand Down
20 changes: 20 additions & 0 deletions cmd/nodecmd/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ The node local command suite provides a collection of commands related to local
cmd.AddCommand(newLocalDestroyCmd())
// node local track
cmd.AddCommand(newLocalTrackCmd())
// node local status
cmd.AddCommand(newLocalStatusCmd())
return cmd
}

Expand Down Expand Up @@ -110,6 +112,16 @@ func newLocalDestroyCmd() *cobra.Command {
}
}

func newLocalStatusCmd() *cobra.Command {
return &cobra.Command{
Use: "status",
Short: "(ALPHA Warning) Get status of local node",
Long: `Get status of local node.`,
Args: cobra.MaximumNArgs(1),
RunE: localStatus,
}
}

func localStartNode(_ *cobra.Command, args []string) error {
clusterName := args[0]
anrSettings := node.ANRSettings{
Expand Down Expand Up @@ -143,6 +155,14 @@ func localTrack(_ *cobra.Command, args []string) error {
return node.TrackSubnetWithLocalMachine(app, args[0], args[1])
}

func localStatus(_ *cobra.Command, args []string) error {
clusterName := ""
if len(args) > 0 {
clusterName = args[0]
}
return node.LocalStatus(app, clusterName)
}

func notImplementedForLocal(what string) error {
ux.Logger.PrintToUser("Unsupported cmd: %s is not supported by local clusters", logging.LightBlue.Wrap(what))
return nil
Expand Down
4 changes: 2 additions & 2 deletions internal/mocks/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/models/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func NewNetwork(kind NetworkKind, id uint32, endpoint string, clusterName string
}
}

func (n Network) IsUndefined() bool {
return n.Kind == Undefined
}

func NewLocalNetwork() Network {
return NewNetwork(Local, constants.LocalNetworkID, constants.LocalAPIEndpoint, "")
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/node/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
"encoding/json"
"errors"
"fmt"
"sync"
"time"

"github.com/ava-labs/avalanche-cli/pkg/binutils"
"github.com/ava-labs/avalanche-cli/pkg/subnet"
"github.com/ava-labs/avalanche-cli/pkg/vm"
"sync"
"time"

"github.com/ava-labs/avalanche-cli/pkg/ansible"

Expand Down Expand Up @@ -58,12 +59,12 @@ func GetClusterNodes(app *application.Avalanche, clusterName string) ([]string,
if exists, err := CheckClusterExists(app, clusterName); err != nil || !exists {
return nil, fmt.Errorf("cluster %q not found", clusterName)
}
clustersConfig, err := app.LoadClustersConfig()
clusterConfig, err := app.GetClusterConfig(clusterName)
if err != nil {
return nil, err
}
clusterNodes := clustersConfig.Clusters[clusterName].Nodes
if len(clusterNodes) == 0 {
clusterNodes := clusterConfig.Nodes
if len(clusterNodes) == 0 && !clusterConfig.Local {
return nil, fmt.Errorf("no nodes found in cluster %s", clusterName)
}
return clusterNodes, nil
Expand Down Expand Up @@ -416,7 +417,6 @@ func promptAvalancheGoVersionChoice(app *application.Avalanche, latestReleaseVer
ux.Logger.PrintToUser(fmt.Sprintf("no subnet named %s found", useAvalanchegoVersionFromSubnet))
}
return AvalancheGoVersionSettings{UseAvalanchegoVersionFromSubnet: useAvalanchegoVersionFromSubnet}, nil

}
}

Expand Down
83 changes: 79 additions & 4 deletions pkg/node/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ package node

import (
"fmt"
"os"
"path/filepath"
"slices"

"github.com/ava-labs/avalanche-cli/pkg/application"
"github.com/ava-labs/avalanche-cli/pkg/binutils"
"github.com/ava-labs/avalanche-cli/pkg/constants"
Expand All @@ -16,9 +20,8 @@ import (
"github.com/ava-labs/avalanche-network-runner/client"
anrutils "github.com/ava-labs/avalanche-network-runner/utils"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"
"os"
"path/filepath"
)

func TrackSubnetWithLocalMachine(app *application.Avalanche, clusterName, blockchainName string) error {
Expand Down Expand Up @@ -296,7 +299,7 @@ func StartLocalNode(app *application.Avalanche, clusterName string, useEtnaDevne
spinner := spinSession.SpinToUser("Booting Network. Wait until healthy...")
if _, err := cli.Start(ctx, avalancheGoBinPath, anrOpts...); err != nil {
ux.SpinFailWithError(spinner, "", err)
DestroyLocalNode(app, clusterName)
_ = DestroyLocalNode(app, clusterName)
return fmt.Errorf("failed to start local avalanchego: %w", err)
}
ux.SpinComplete(spinner)
Expand Down Expand Up @@ -393,7 +396,7 @@ func addLocalClusterConfig(app *application.Avalanche, network models.Network) e
}

func DestroyLocalNode(app *application.Avalanche, clusterName string) error {
StopLocalNode(app)
_ = StopLocalNode(app)

rootDir := app.GetLocalDir(clusterName)
if err := os.RemoveAll(rootDir); err != nil {
Expand Down Expand Up @@ -447,3 +450,75 @@ func StopLocalNode(app *application.Avalanche) error {
ux.Logger.GreenCheckmarkToUser("avalanchego stopped")
return nil
}

func listLocalClusters(app *application.Avalanche, clusterNamesToInclude []string) (map[string]string, error) {
localClusters := map[string]string{} // map[clusterName]rootDir
clustersConfig, err := app.GetClustersConfig()
if err != nil {
return localClusters, err
}
for clusterName := range clustersConfig.Clusters {
if len(clusterNamesToInclude) == 0 || slices.Contains(clusterNamesToInclude, clusterName) {
if ok, err := checkClusterIsLocal(app, clusterName); err == nil && ok {
localClusters[clusterName] = app.GetLocalDir(clusterName)
}
}
}
return localClusters, nil
}

func LocalStatus(app *application.Avalanche, clusterName string) error {
clustersToList := make([]string, 0)
if clusterName != "" {
if ok, err := checkClusterIsLocal(app, clusterName); err != nil || !ok {
return fmt.Errorf("local cluster %q not found", clusterName)
}
clustersToList = append(clustersToList, clusterName)
}

// get currently running local cluster
ctx, cancel := utils.GetANRContext()
defer cancel()
currentlyRunningRootDir := ""
isHealthy := false
cli, _ := binutils.NewGRPCClientWithEndpoint( // ignore error as ANR might be not running
binutils.LocalClusterGRPCServerEndpoint,
binutils.WithAvoidRPCVersionCheck(true),
binutils.WithDialTimeout(constants.FastGRPCDialTimeout),
)
if cli != nil {
status, _ := cli.Status(ctx) // ignore error as ANR might be not running
if status != nil && status.ClusterInfo != nil {
if status.ClusterInfo.RootDataDir != "" {
currentlyRunningRootDir = status.ClusterInfo.RootDataDir
}
isHealthy = status.ClusterInfo.Healthy
}
}
localClusters, err := listLocalClusters(app, clustersToList)
if err != nil {
return fmt.Errorf("failed to list local clusters: %w", err)
}
if clusterName != "" {
ux.Logger.PrintToUser("%s %s", logging.LightBlue.Wrap("Local cluster:"), logging.Green.Wrap(clusterName))
} else {
ux.Logger.PrintToUser(logging.LightBlue.Wrap("Local clusters:"))
}
for clusterName, rootDir := range localClusters {
currenlyRunning := ""
healthStatus := ""
if rootDir == currentlyRunningRootDir {
currenlyRunning = fmt.Sprintf(" [%s]", logging.Blue.Wrap("Running"))
if isHealthy {
healthStatus = fmt.Sprintf(" [%s]", logging.Green.Wrap("Healthy"))
} else {
healthStatus = fmt.Sprintf(" [%s]", logging.Red.Wrap("Unhealthy"))
}
} else {
currenlyRunning = fmt.Sprintf(" [%s]", logging.Black.Wrap("Stopped"))
}
ux.Logger.PrintToUser("- %s: %s %s %s", clusterName, rootDir, currenlyRunning, healthStatus)
}

return nil
}
Loading