mirror of
https://github.com/luxfi/netrunner.git
synced 2026-07-27 00:04:23 +00:00
Merge branch 'main' into move-restart-to-local
This commit is contained in:
@@ -389,7 +389,7 @@ avalanche-network-runner control add-node \
|
||||
--avalanchego-path ${AVALANCHEGO_EXEC_PATH}
|
||||
```
|
||||
|
||||
You can also provide additional flags that specify the node's config, and what custom VMs it supports:
|
||||
You can also provide additional flags that specify the node's config:
|
||||
|
||||
```
|
||||
--node-config '{"index-enabled":false, "api-admin-enabled":true,"network-peer-list-gossip-frequency":"300ms"}'
|
||||
@@ -460,7 +460,7 @@ avalanche-network-runner server \
|
||||
curl -X POST -k http://localhost:8081/v1/ping -d ''
|
||||
```
|
||||
|
||||
To start the cluster with custom VMs:
|
||||
To start the cluster with custom chains:
|
||||
|
||||
```bash
|
||||
# or download from https://github.com/ava-labs/subnet-cli/releases
|
||||
@@ -490,7 +490,7 @@ find ${HOME}/go/src/github.com/ava-labs/avalanchego/build
|
||||
# .../build/plugins/evm
|
||||
# .../build/avalanchego
|
||||
|
||||
# generate the genesis for the custom VM
|
||||
# generate the genesis for the custom chain
|
||||
export CHAIN_ID=99999
|
||||
export GENESIS_ADDRESS="0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
|
||||
cat <<EOF > /tmp/subnet-evm.genesis.json
|
||||
@@ -574,7 +574,7 @@ avalanche-network-runner server \
|
||||
curl -X POST -k http://localhost:8081/v1/ping -d ''
|
||||
```
|
||||
|
||||
To start the cluster with custom VMs:
|
||||
To start the cluster with custom chains:
|
||||
|
||||
```bash
|
||||
# or download from https://github.com/ava-labs/subnet-cli/releases
|
||||
@@ -603,7 +603,7 @@ find ${HOME}/go/src/github.com/ava-labs/avalanchego/build
|
||||
# .../build/plugins/evm
|
||||
# .../build/avalanchego
|
||||
|
||||
# generate the genesis for the custom VM
|
||||
# generate the genesis for the custom chain
|
||||
cd ${HOME}/go/src/github.com/ava-labs/blobvm
|
||||
go install -v ./cmd/blob-cli
|
||||
echo "[]" > /tmp/alloc.json
|
||||
|
||||
+7
-7
@@ -117,8 +117,8 @@ func (c *client) Start(ctx context.Context, execPath string, opts ...OpOption) (
|
||||
if ret.rootDataDir != "" {
|
||||
req.RootDataDir = &ret.rootDataDir
|
||||
}
|
||||
if ret.pluginDir != "" {
|
||||
req.PluginDir = &ret.pluginDir
|
||||
if ret.buildDir != "" {
|
||||
req.BuildDir = &ret.buildDir
|
||||
}
|
||||
if len(ret.blockchainSpecs) > 0 {
|
||||
req.BlockchainSpecs = ret.blockchainSpecs
|
||||
@@ -296,8 +296,8 @@ func (c *client) LoadSnapshot(ctx context.Context, snapshotName string, opts ...
|
||||
if ret.execPath != "" {
|
||||
req.ExecPath = &ret.execPath
|
||||
}
|
||||
if ret.pluginDir != "" {
|
||||
req.PluginDir = &ret.pluginDir
|
||||
if ret.buildDir != "" {
|
||||
req.BuildDir = &ret.buildDir
|
||||
}
|
||||
if ret.rootDataDir != "" {
|
||||
req.RootDataDir = &ret.rootDataDir
|
||||
@@ -335,7 +335,7 @@ type Op struct {
|
||||
whitelistedSubnets string
|
||||
globalNodeConfig string
|
||||
rootDataDir string
|
||||
pluginDir string
|
||||
buildDir string
|
||||
blockchainSpecs []*rpcpb.BlockchainSpec
|
||||
customNodeConfigs map[string]string
|
||||
numSubnets uint32
|
||||
@@ -380,9 +380,9 @@ func WithRootDataDir(rootDataDir string) OpOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithPluginDir(pluginDir string) OpOption {
|
||||
func WithBuildDir(buildDir string) OpOption {
|
||||
return func(op *Op) {
|
||||
op.pluginDir = pluginDir
|
||||
op.buildDir = buildDir
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ func NewCommand() *cobra.Command {
|
||||
var (
|
||||
avalancheGoBinPath string
|
||||
numNodes uint32
|
||||
pluginDir string
|
||||
buildDir string
|
||||
globalNodeConfig string
|
||||
addNodeConfig string
|
||||
blockchainSpecsStr string
|
||||
@@ -104,10 +104,10 @@ func newStartCommand() *cobra.Command {
|
||||
"number of nodes of the network",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&pluginDir,
|
||||
"plugin-dir",
|
||||
&buildDir,
|
||||
"build-dir",
|
||||
"",
|
||||
"[optional] plugin directory",
|
||||
"[optional] build directory",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&rootDataDir,
|
||||
@@ -157,7 +157,7 @@ func startFunc(cmd *cobra.Command, args []string) error {
|
||||
|
||||
opts := []client.OpOption{
|
||||
client.WithNumNodes(numNodes),
|
||||
client.WithPluginDir(pluginDir),
|
||||
client.WithBuildDir(buildDir),
|
||||
client.WithWhitelistedSubnets(whitelistedSubnets),
|
||||
client.WithRootDataDir(rootDataDir),
|
||||
}
|
||||
@@ -765,10 +765,10 @@ func newLoadSnapshotCommand() *cobra.Command {
|
||||
"avalanchego binary path",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&pluginDir,
|
||||
"plugin-dir",
|
||||
&buildDir,
|
||||
"build-dir",
|
||||
"",
|
||||
"plugin directory",
|
||||
"build directory",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&rootDataDir,
|
||||
@@ -800,7 +800,7 @@ func loadSnapshotFunc(cmd *cobra.Command, args []string) error {
|
||||
|
||||
opts := []client.OpOption{
|
||||
client.WithExecPath(avalancheGoBinPath),
|
||||
client.WithPluginDir(pluginDir),
|
||||
client.WithBuildDir(buildDir),
|
||||
client.WithRootDataDir(rootDataDir),
|
||||
}
|
||||
|
||||
|
||||
+16
-14
@@ -38,7 +38,7 @@ const (
|
||||
validationDuration = 365 * 24 * time.Hour
|
||||
// weight assigned to subnet validators
|
||||
subnetValidatorsWeight = 1000
|
||||
// check period for blockchain logs while waiting for custom VMs to be ready
|
||||
// check period for blockchain logs while waiting for custom chains to be ready
|
||||
blockchainLogPullFrequency = time.Second
|
||||
// check period while waiting for all validators to be ready
|
||||
waitForValidatorsPullFrequency = time.Second
|
||||
@@ -50,7 +50,7 @@ var (
|
||||
)
|
||||
|
||||
type blockchainInfo struct {
|
||||
vmName string
|
||||
chainName string
|
||||
vmID ids.ID
|
||||
subnetID ids.ID
|
||||
blockchainID ids.ID
|
||||
@@ -79,12 +79,12 @@ func (ln *localNetwork) CreateBlockchains(
|
||||
) error {
|
||||
ln.lock.Lock()
|
||||
defer ln.lock.Unlock()
|
||||
chainInfos, err := ln.installCustomVMs(ctx, chainSpecs)
|
||||
chainInfos, err := ln.installCustomChains(ctx, chainSpecs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ln.waitForCustomVMsReady(ctx, chainInfos); err != nil {
|
||||
if err := ln.waitForCustomChainsReady(ctx, chainInfos); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -102,14 +102,14 @@ func (ln *localNetwork) CreateSubnets(
|
||||
return nil
|
||||
}
|
||||
|
||||
// provisions local cluster and install custom VMs if applicable
|
||||
// provisions local cluster and install custom chains if applicable
|
||||
// assumes the local cluster is already set up and healthy
|
||||
func (ln *localNetwork) installCustomVMs(
|
||||
func (ln *localNetwork) installCustomChains(
|
||||
ctx context.Context,
|
||||
chainSpecs []network.BlockchainSpec,
|
||||
) ([]blockchainInfo, error) {
|
||||
println()
|
||||
color.Outf("{{blue}}{{bold}}create and install custom VMs{{/}}\n")
|
||||
color.Outf("{{blue}}{{bold}}create and install custom chains{{/}}\n")
|
||||
|
||||
clientURI, err := ln.getClientURI()
|
||||
if err != nil {
|
||||
@@ -215,7 +215,9 @@ func (ln *localNetwork) installCustomVMs(
|
||||
return nil, err
|
||||
}
|
||||
chainInfos[i] = blockchainInfo{
|
||||
vmName: chainSpec.VmName,
|
||||
// we keep a record of VM name in blockchain name field,
|
||||
// as there is no way to recover VM name from VM ID
|
||||
chainName: chainSpec.VmName,
|
||||
vmID: vmID,
|
||||
subnetID: subnetID,
|
||||
blockchainID: blockchainIDs[i],
|
||||
@@ -324,12 +326,12 @@ func (ln *localNetwork) installSubnets(
|
||||
return subnetIDs, nil
|
||||
}
|
||||
|
||||
func (ln *localNetwork) waitForCustomVMsReady(
|
||||
func (ln *localNetwork) waitForCustomChainsReady(
|
||||
ctx context.Context,
|
||||
chainInfos []blockchainInfo,
|
||||
) error {
|
||||
println()
|
||||
color.Outf("{{blue}}{{bold}}waiting for custom VMs to report healthy...{{/}}\n")
|
||||
color.Outf("{{blue}}{{bold}}waiting for custom chains to report healthy...{{/}}\n")
|
||||
|
||||
if err := ln.healthy(ctx); err != nil {
|
||||
return err
|
||||
@@ -349,7 +351,7 @@ func (ln *localNetwork) waitForCustomVMsReady(
|
||||
}
|
||||
|
||||
for nodeName, node := range ln.nodes {
|
||||
zap.L().Info("inspecting node log directory for custom VM logs",
|
||||
zap.L().Info("inspecting node log directory for custom chain logs",
|
||||
zap.String("node-name", nodeName),
|
||||
zap.String("log-dir", node.GetLogsDir()),
|
||||
)
|
||||
@@ -387,10 +389,10 @@ func (ln *localNetwork) waitForCustomVMsReady(
|
||||
}
|
||||
|
||||
println()
|
||||
color.Outf("{{green}}{{bold}}all custom VMs are running!!!{{/}}\n")
|
||||
color.Outf("{{green}}{{bold}}all custom chains are running!!!{{/}}\n")
|
||||
|
||||
println()
|
||||
color.Outf("{{green}}{{bold}}all custom VMs are ready on RPC server-side -- network-runner RPC client can poll and query the cluster status{{/}}\n")
|
||||
color.Outf("{{green}}{{bold}}all custom chains are ready on RPC server-side -- network-runner RPC client can poll and query the cluster status{{/}}\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -728,7 +730,7 @@ func createBlockchains(
|
||||
testKeyAddr ids.ShortID,
|
||||
) ([]ids.ID, error) {
|
||||
println()
|
||||
color.Outf("{{green}}creating blockchain for each custom VM{{/}}\n")
|
||||
color.Outf("{{green}}creating each custom chain{{/}}\n")
|
||||
blockchainIDs := make([]ids.ID, len(chainSpecs))
|
||||
for i, chainSpec := range chainSpecs {
|
||||
vmName := chainSpec.VmName
|
||||
|
||||
+417
-410
File diff suppressed because it is too large
Load Diff
+22
-16
@@ -152,15 +152,18 @@ message ClusterInfo {
|
||||
// Maps from the node ID to its attached peer infos.
|
||||
map<string, ListOfAttachedPeerInfo> attached_peer_infos = 6;
|
||||
|
||||
// Set to "true" once custom VMs are ready.
|
||||
bool custom_vms_healthy = 7;
|
||||
// The map of custom VM IDs in "ids.ID" format to its VM information.
|
||||
map<string, CustomVmInfo> custom_vms = 8;
|
||||
// Set to "true" once custom blockchains are ready.
|
||||
bool custom_chains_healthy = 7;
|
||||
// The map of blockchain IDs in "ids.ID" format to its blockchain information.
|
||||
map<string, CustomChainInfo> custom_chains = 8;
|
||||
repeated string subnets = 9;
|
||||
}
|
||||
|
||||
message CustomVmInfo {
|
||||
string vm_name = 1;
|
||||
message CustomChainInfo {
|
||||
// Blockchain name given to the create blockchain TX
|
||||
// Currently used to keep a record of the VM name,
|
||||
// which is not saved anywhere and can't be recovered from VM ID
|
||||
string chain_name = 1;
|
||||
|
||||
// VM ID in "ids.ID" format.
|
||||
string vm_id = 2;
|
||||
@@ -170,8 +173,8 @@ message CustomVmInfo {
|
||||
string subnet_id = 3;
|
||||
|
||||
// Create blockchain transaction ID -- blockchain ID>
|
||||
// The blockchain ID is used for RPC endpoints for the custom VM.
|
||||
string blockchain_id = 4;
|
||||
// The blockchain ID is used for RPC endpoints.
|
||||
string chain_id = 4;
|
||||
}
|
||||
|
||||
message NodeInfo {
|
||||
@@ -181,7 +184,7 @@ message NodeInfo {
|
||||
string id = 4;
|
||||
string log_dir = 5;
|
||||
string db_dir = 6;
|
||||
string plugin_dir = 7;
|
||||
string build_dir = 7;
|
||||
string whitelisted_subnets = 8;
|
||||
bytes config = 9;
|
||||
}
|
||||
@@ -202,18 +205,21 @@ message StartRequest {
|
||||
// Used for both database and log files.
|
||||
optional string root_data_dir = 5;
|
||||
|
||||
// Plugin directory to load all custom VM executables.
|
||||
// Must be non-empty to install custom VMs.
|
||||
optional string plugin_dir = 6;
|
||||
// Build directory that contains the subdir 'plugins' from which to load all custom VM executables.
|
||||
// If not specified, will be derived from the exec_path (its basedir)
|
||||
optional string build_dir = 6;
|
||||
|
||||
// The list of custom VM name, its genesis file path, and (optional) subnet id to use.
|
||||
// The list of custom chain's VM name, genesis file path, and (optional) subnet id to use.
|
||||
//
|
||||
// subnet id must be always nil when using StartRequest, as the network is empty and has no preloaded
|
||||
// subnet ids available.
|
||||
//
|
||||
// The matching file with the name in "ids.ID" format must exist.
|
||||
// e.g., ids.ToID(hashing.ComputeHash256("subnetevm")).String()
|
||||
// e.g., subnet-cli create VMID subnetevm
|
||||
//
|
||||
// If this field is set to none (by default), the node/network-runner
|
||||
// does not install the custom VM and does not create the subnet,
|
||||
// does not install the custom chain and does not create the subnet,
|
||||
// even if the VM binary exists on the local plugins directory.
|
||||
repeated BlockchainSpec blockchain_specs = 7;
|
||||
|
||||
@@ -238,7 +244,7 @@ message BlockchainSpec {
|
||||
}
|
||||
|
||||
message CreateBlockchainsRequest {
|
||||
// The list of custom VM name, its genesis file path, and (optional) subnet id to use.
|
||||
// The list of custom chain's VM name, genesis file path, and (optional) subnet id to use.
|
||||
//
|
||||
// The matching file with the name in "ids.ID" format must exist.
|
||||
// e.g., ids.ToID(hashing.ComputeHash256("subnetevm")).String()
|
||||
@@ -356,7 +362,7 @@ message SaveSnapshotResponse {
|
||||
message LoadSnapshotRequest {
|
||||
string snapshot_name = 1;
|
||||
optional string exec_path = 2;
|
||||
optional string plugin_dir = 3;
|
||||
optional string build_dir = 3;
|
||||
optional string root_data_dir = 4;
|
||||
map<string, string> chain_configs = 5;
|
||||
optional string global_node_config = 6;
|
||||
|
||||
+19
-12
@@ -3,24 +3,31 @@ set -e
|
||||
|
||||
export RUN_E2E="true"
|
||||
# e.g.,
|
||||
# ./scripts/tests.e2e.sh 1.7.9 1.7.10
|
||||
# ./scripts/tests.e2e.sh 1.7.12 1.7.13
|
||||
if ! [[ "$0" =~ scripts/tests.e2e.sh ]]; then
|
||||
echo "must be run from repository root"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
VERSION_1=$1
|
||||
if [[ -z "${VERSION_1}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2]" >> /dev/stderr
|
||||
exit 255
|
||||
fi
|
||||
DEFAULT_VERSION_1=1.7.12
|
||||
DEFAULT_VERSION_2=1.7.13
|
||||
|
||||
VERSION_2=$2
|
||||
if [[ -z "${VERSION_2}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2]" >> /dev/stderr
|
||||
exit 255
|
||||
if [ $# == 0 ]; then
|
||||
VERSION_1=$DEFAULT_VERSION_1
|
||||
VERSION_2=$DEFAULT_VERSION_2
|
||||
else
|
||||
VERSION_1=$1
|
||||
if [[ -z "${VERSION_1}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2]" >> /dev/stderr
|
||||
exit 255
|
||||
fi
|
||||
VERSION_2=$2
|
||||
if [[ -z "${VERSION_2}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2]" >> /dev/stderr
|
||||
exit 255
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Running e2e tests with:"
|
||||
|
||||
+33
-52
@@ -43,8 +43,8 @@ var ignoreFields = map[string]struct{}{
|
||||
type localNetwork struct {
|
||||
logger logging.Logger
|
||||
|
||||
execPath string
|
||||
pluginDir string
|
||||
execPath string
|
||||
buildDir string
|
||||
|
||||
cfg network.Config
|
||||
|
||||
@@ -57,9 +57,9 @@ type localNetwork struct {
|
||||
options localNetworkOptions
|
||||
|
||||
// map from blockchain ID to blockchain info
|
||||
customVMBlockchainIDToInfo map[ids.ID]vmInfo
|
||||
customChainIDToInfo map[ids.ID]chainInfo
|
||||
|
||||
customVMRestartMu *sync.RWMutex
|
||||
customChainRestartMu *sync.RWMutex
|
||||
|
||||
stopCh chan struct{}
|
||||
startDoneCh chan struct{}
|
||||
@@ -75,8 +75,8 @@ type localNetwork struct {
|
||||
chainConfigs map[string]string
|
||||
}
|
||||
|
||||
type vmInfo struct {
|
||||
info *rpcpb.CustomVmInfo
|
||||
type chainInfo struct {
|
||||
info *rpcpb.CustomChainInfo
|
||||
subnetID ids.ID
|
||||
blockchainID ids.ID
|
||||
}
|
||||
@@ -89,13 +89,13 @@ type localNetworkOptions struct {
|
||||
redirectNodesOutput bool
|
||||
globalNodeConfig string
|
||||
|
||||
pluginDir string
|
||||
buildDir string
|
||||
customNodeConfigs map[string]string
|
||||
|
||||
// chain configs to be added to the network, besides the ones in default config, or saved snapshot
|
||||
chainConfigs map[string]string
|
||||
|
||||
// to block racey restart while installing custom VMs
|
||||
// to block racey restart while installing custom chains
|
||||
restartMu *sync.RWMutex
|
||||
|
||||
snapshotsDir string
|
||||
@@ -118,12 +118,12 @@ func newLocalNetwork(opts localNetworkOptions) (*localNetwork, error) {
|
||||
|
||||
execPath: opts.execPath,
|
||||
|
||||
pluginDir: opts.pluginDir,
|
||||
buildDir: getBuildDir(opts.execPath, opts.buildDir),
|
||||
|
||||
options: opts,
|
||||
|
||||
customVMBlockchainIDToInfo: make(map[ids.ID]vmInfo),
|
||||
customVMRestartMu: opts.restartMu,
|
||||
customChainIDToInfo: make(map[ids.ID]chainInfo),
|
||||
customChainRestartMu: opts.restartMu,
|
||||
|
||||
stopCh: make(chan struct{}),
|
||||
startDoneCh: make(chan struct{}),
|
||||
@@ -169,17 +169,12 @@ func (lc *localNetwork) createConfig() error {
|
||||
return fmt.Errorf("failed merging provided configs: %w", err)
|
||||
}
|
||||
|
||||
// avalanchego expects buildDir (parent dir of pluginDir) to be provided at cmdline
|
||||
buildDir, err := getBuildDir(lc.execPath, lc.pluginDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.NodeConfigs[i].ConfigFile, err = createConfigFileString(mergedConfig, logDir, dbDir, buildDir, lc.options.whitelistedSubnets)
|
||||
cfg.NodeConfigs[i].ConfigFile, err = createConfigFileString(mergedConfig, logDir, dbDir, lc.buildDir, lc.options.whitelistedSubnets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.NodeConfigs[i].BinaryPath = lc.options.execPath
|
||||
cfg.NodeConfigs[i].BinaryPath = lc.execPath
|
||||
cfg.NodeConfigs[i].RedirectStdout = lc.options.redirectNodesOutput
|
||||
cfg.NodeConfigs[i].RedirectStderr = lc.options.redirectNodesOutput
|
||||
}
|
||||
@@ -221,21 +216,17 @@ func mergeNodeConfig(baseConfig map[string]interface{}, globalConfig map[string]
|
||||
return baseConfig, nil
|
||||
}
|
||||
|
||||
// generates buildDir from pluginDir, and if not available, from execPath
|
||||
// if givenBuildDir is empty, generates it from execPath
|
||||
// returns error if pluginDir is non empty and invalid
|
||||
func getBuildDir(execPath string, pluginDir string) (string, error) {
|
||||
func getBuildDir(execPath string, givenBuildDir string) string {
|
||||
buildDir := ""
|
||||
if execPath != "" {
|
||||
buildDir = filepath.Dir(execPath)
|
||||
}
|
||||
if pluginDir != "" {
|
||||
pluginDir := filepath.Clean(pluginDir)
|
||||
if filepath.Base(pluginDir) != "plugins" {
|
||||
return "", fmt.Errorf("plugin dir %q is not named plugins", pluginDir)
|
||||
}
|
||||
buildDir = filepath.Dir(pluginDir)
|
||||
if givenBuildDir != "" {
|
||||
buildDir = givenBuildDir
|
||||
}
|
||||
return buildDir, nil
|
||||
return buildDir
|
||||
}
|
||||
|
||||
// createConfigFileString finalizes the config setup and returns the node config JSON string
|
||||
@@ -252,7 +243,7 @@ func createConfigFileString(configFileMap map[string]interface{}, logDir string,
|
||||
if buildDir != "" {
|
||||
configFileMap[config.BuildDirKey] = buildDir
|
||||
}
|
||||
// need to whitelist subnet ID to create custom VM chain
|
||||
// need to whitelist subnet ID to create custom chain
|
||||
// ref. vms/platformvm/createChain
|
||||
if whitelistedSubnets != "" {
|
||||
configFileMap[config.WhitelistedSubnetsKey] = whitelistedSubnets
|
||||
@@ -320,7 +311,7 @@ func (lc *localNetwork) createBlockchains(
|
||||
ctx, lc.startCtxCancel = context.WithCancel(argCtx)
|
||||
|
||||
if len(chainSpecs) == 0 {
|
||||
color.Outf("{{orange}}{{bold}}custom VM not specified, skipping installation and its health checks...{{/}}\n")
|
||||
color.Outf("{{orange}}{{bold}}custom chain not specified, skipping installation and its health checks...{{/}}\n")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -403,11 +394,6 @@ func (lc *localNetwork) loadSnapshot(
|
||||
) error {
|
||||
color.Outf("{{blue}}{{bold}}create and run local network from snapshot{{/}}\n")
|
||||
|
||||
buildDir, err := getBuildDir(lc.execPath, lc.pluginDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var globalNodeConfig map[string]interface{}
|
||||
if lc.options.globalNodeConfig != "" {
|
||||
if err := json.Unmarshal([]byte(lc.options.globalNodeConfig), &globalNodeConfig); err != nil {
|
||||
@@ -421,7 +407,7 @@ func (lc *localNetwork) loadSnapshot(
|
||||
lc.options.rootDataDir,
|
||||
lc.options.snapshotsDir,
|
||||
lc.execPath,
|
||||
buildDir,
|
||||
lc.buildDir,
|
||||
lc.options.chainConfigs,
|
||||
globalNodeConfig,
|
||||
)
|
||||
@@ -462,12 +448,12 @@ func (lc *localNetwork) updateSubnetInfo(ctx context.Context) error {
|
||||
}
|
||||
for _, blockchain := range blockchains {
|
||||
if blockchain.Name != "C-Chain" && blockchain.Name != "X-Chain" {
|
||||
lc.customVMBlockchainIDToInfo[blockchain.ID] = vmInfo{
|
||||
info: &rpcpb.CustomVmInfo{
|
||||
VmName: blockchain.Name,
|
||||
VmId: blockchain.VMID.String(),
|
||||
SubnetId: blockchain.SubnetID.String(),
|
||||
BlockchainId: blockchain.ID.String(),
|
||||
lc.customChainIDToInfo[blockchain.ID] = chainInfo{
|
||||
info: &rpcpb.CustomChainInfo{
|
||||
ChainName: blockchain.Name,
|
||||
VmId: blockchain.VMID.String(),
|
||||
SubnetId: blockchain.SubnetID.String(),
|
||||
ChainId: blockchain.ID.String(),
|
||||
},
|
||||
subnetID: blockchain.SubnetID,
|
||||
blockchainID: blockchain.ID,
|
||||
@@ -486,8 +472,8 @@ func (lc *localNetwork) updateSubnetInfo(ctx context.Context) error {
|
||||
}
|
||||
for _, nodeName := range lc.nodeNames {
|
||||
nodeInfo := lc.nodeInfos[nodeName]
|
||||
for blockchainID, vmInfo := range lc.customVMBlockchainIDToInfo {
|
||||
color.Outf("{{blue}}{{bold}}[blockchain RPC for %q] \"%s/ext/bc/%s\"{{/}}\n", vmInfo.info.VmId, nodeInfo.GetUri(), blockchainID)
|
||||
for chainID, chainInfo := range lc.customChainIDToInfo {
|
||||
color.Outf("{{blue}}{{bold}}[blockchain RPC for %q] \"%s/ext/bc/%s\"{{/}}\n", chainInfo.info.VmId, nodeInfo.GetUri(), chainID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -522,7 +508,6 @@ func (lc *localNetwork) updateNodeInfo() error {
|
||||
for _, name := range lc.nodeNames {
|
||||
node := nodes[name]
|
||||
configFile := []byte(node.GetConfigFile())
|
||||
var pluginDir string
|
||||
var whitelistedSubnets string
|
||||
var configFileMap map[string]interface{}
|
||||
if err := json.Unmarshal(configFile, &configFileMap); err != nil {
|
||||
@@ -535,10 +520,6 @@ func (lc *localNetwork) updateNodeInfo() error {
|
||||
return fmt.Errorf("unexpected type for %q expected string got %T", config.WhitelistedSubnetsKey, whitelistedSubnetsIntf)
|
||||
}
|
||||
}
|
||||
buildDir := node.GetBuildDir()
|
||||
if buildDir != "" {
|
||||
pluginDir = filepath.Join(buildDir, "plugins")
|
||||
}
|
||||
|
||||
lc.nodeInfos[name] = &rpcpb.NodeInfo{
|
||||
Name: node.GetName(),
|
||||
@@ -548,16 +529,16 @@ func (lc *localNetwork) updateNodeInfo() error {
|
||||
LogDir: node.GetLogsDir(),
|
||||
DbDir: node.GetDbDir(),
|
||||
Config: []byte(node.GetConfigFile()),
|
||||
PluginDir: pluginDir,
|
||||
BuildDir: node.GetBuildDir(),
|
||||
WhitelistedSubnets: whitelistedSubnets,
|
||||
}
|
||||
|
||||
// update default exec and pluginDir if empty (snapshots started without this params)
|
||||
// update default exec and buildDir if empty (snapshots started without this params)
|
||||
if lc.execPath == "" {
|
||||
lc.execPath = node.GetBinaryPath()
|
||||
}
|
||||
if lc.pluginDir == "" {
|
||||
lc.pluginDir = pluginDir
|
||||
if lc.buildDir == "" {
|
||||
lc.buildDir = node.GetBuildDir()
|
||||
}
|
||||
// update default chain configs if empty
|
||||
if lc.chainConfigs == nil {
|
||||
|
||||
+32
-41
@@ -72,17 +72,16 @@ type server struct {
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidVMName = errors.New("invalid VM name")
|
||||
ErrInvalidPort = errors.New("invalid port")
|
||||
ErrClosed = errors.New("server closed")
|
||||
ErrPluginDirEmptyButCustomVMsNotEmpty = errors.New("empty plugin-dir but non-empty custom VMs")
|
||||
ErrPluginDirNonEmptyButCustomVMsEmpty = errors.New("non-empty plugin-dir but empty custom VM")
|
||||
ErrNotEnoughNodesForStart = errors.New("not enough nodes specified for start")
|
||||
ErrAlreadyBootstrapped = errors.New("already bootstrapped")
|
||||
ErrNotBootstrapped = errors.New("not bootstrapped")
|
||||
ErrPeerNotFound = errors.New("peer not found")
|
||||
ErrStatusCanceled = errors.New("gRPC stream status canceled")
|
||||
ErrNoBlockchainSpec = errors.New("no blockchain spec was provided")
|
||||
ErrInvalidVMName = errors.New("invalid VM name")
|
||||
ErrInvalidPort = errors.New("invalid port")
|
||||
ErrClosed = errors.New("server closed")
|
||||
ErrNotEnoughNodesForStart = errors.New("not enough nodes specified for start")
|
||||
ErrAlreadyBootstrapped = errors.New("already bootstrapped")
|
||||
ErrNotBootstrapped = errors.New("not bootstrapped")
|
||||
ErrNodeNotFound = errors.New("node not found")
|
||||
ErrPeerNotFound = errors.New("peer not found")
|
||||
ErrStatusCanceled = errors.New("gRPC stream status canceled")
|
||||
ErrNoBlockchainSpec = errors.New("no blockchain spec was provided")
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -250,13 +249,8 @@ func (s *server) Start(ctx context.Context, req *rpcpb.StartRequest) (*rpcpb.Sta
|
||||
if err := utils.CheckExecPath(req.GetExecPath()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pluginDir := ""
|
||||
if req.GetPluginDir() != "" {
|
||||
pluginDir = req.GetPluginDir()
|
||||
}
|
||||
if pluginDir == "" {
|
||||
pluginDir = filepath.Join(filepath.Dir(req.GetExecPath()), "plugins")
|
||||
}
|
||||
buildDir := getBuildDir(req.GetExecPath(), req.GetBuildDir())
|
||||
pluginDir := filepath.Join(buildDir, "plugins")
|
||||
chainSpecs := []network.BlockchainSpec{}
|
||||
if len(req.GetBlockchainSpecs()) > 0 {
|
||||
zap.L().Info("plugin dir", zap.String("plugin-dir", pluginDir))
|
||||
@@ -267,7 +261,7 @@ func (s *server) Start(ctx context.Context, req *rpcpb.StartRequest) (*rpcpb.Sta
|
||||
}
|
||||
vmName := spec.VmName
|
||||
vmGenesisFilePath := spec.Genesis
|
||||
zap.L().Info("checking custom VM ID before installation", zap.String("vm-id", vmName))
|
||||
zap.L().Info("checking custom chain's VM ID before installation", zap.String("vm-id", vmName))
|
||||
vmID, err := utils.VMID(vmName)
|
||||
if err != nil {
|
||||
zap.L().Warn("failed to convert VM name to VM ID",
|
||||
@@ -333,7 +327,7 @@ func (s *server) Start(ctx context.Context, req *rpcpb.StartRequest) (*rpcpb.Sta
|
||||
zap.String("whitelistedSubnets", whitelistedSubnets),
|
||||
zap.Int32("pid", pid),
|
||||
zap.String("rootDataDir", rootDataDir),
|
||||
zap.String("pluginDir", pluginDir),
|
||||
zap.String("buildDir", buildDir),
|
||||
zap.Any("chainConfigs", req.ChainConfigs),
|
||||
zap.String("defaultNodeConfig", globalNodeConfig),
|
||||
)
|
||||
@@ -353,7 +347,7 @@ func (s *server) Start(ctx context.Context, req *rpcpb.StartRequest) (*rpcpb.Sta
|
||||
numNodes: numNodes,
|
||||
whitelistedSubnets: whitelistedSubnets,
|
||||
redirectNodesOutput: s.cfg.RedirectNodesOutput,
|
||||
pluginDir: pluginDir,
|
||||
buildDir: buildDir,
|
||||
globalNodeConfig: globalNodeConfig,
|
||||
customNodeConfigs: customNodeConfigs,
|
||||
chainConfigs: req.ChainConfigs,
|
||||
@@ -378,7 +372,7 @@ func (s *server) Start(ctx context.Context, req *rpcpb.StartRequest) (*rpcpb.Sta
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// start non-blocking to install local cluster + custom VMs (if applicable)
|
||||
// start non-blocking to install local cluster + custom chains (if applicable)
|
||||
// the user is expected to poll cluster status
|
||||
readyCh := make(chan struct{})
|
||||
go s.network.startWait(ctx, chainSpecs, readyCh)
|
||||
@@ -389,9 +383,9 @@ func (s *server) Start(ctx context.Context, req *rpcpb.StartRequest) (*rpcpb.Sta
|
||||
go func() {
|
||||
s.waitChAndUpdateClusterInfo("waiting for local cluster readiness", readyCh, false)
|
||||
if len(req.GetBlockchainSpecs()) == 0 {
|
||||
zap.L().Info("no custom VM installation request, skipping its readiness check")
|
||||
zap.L().Info("no custom chain installation request, skipping its readiness check")
|
||||
} else {
|
||||
s.waitChAndUpdateClusterInfo("waiting for custom VMs readiness", readyCh, true)
|
||||
s.waitChAndUpdateClusterInfo("waiting for custom chains readiness", readyCh, true)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -417,10 +411,10 @@ func (s *server) waitChAndUpdateClusterInfo(waitMsg string, readyCh chan struct{
|
||||
s.clusterInfo.NodeNames = s.network.nodeNames
|
||||
s.clusterInfo.NodeInfos = s.network.nodeInfos
|
||||
if updateCustomVmsInfo {
|
||||
s.clusterInfo.CustomVmsHealthy = true
|
||||
s.clusterInfo.CustomVms = make(map[string]*rpcpb.CustomVmInfo)
|
||||
for blockchainID, vmInfo := range s.network.customVMBlockchainIDToInfo {
|
||||
s.clusterInfo.CustomVms[blockchainID.String()] = vmInfo.info
|
||||
s.clusterInfo.CustomChainsHealthy = true
|
||||
s.clusterInfo.CustomChains = make(map[string]*rpcpb.CustomChainInfo)
|
||||
for chainID, chainInfo := range s.network.customChainIDToInfo {
|
||||
s.clusterInfo.CustomChains[chainID.String()] = chainInfo.info
|
||||
}
|
||||
s.clusterInfo.Subnets = s.network.subnets
|
||||
}
|
||||
@@ -448,11 +442,12 @@ func (s *server) CreateBlockchains(ctx context.Context, req *rpcpb.CreateBlockch
|
||||
return nil, ErrNoBlockchainSpec
|
||||
}
|
||||
|
||||
pluginDir := filepath.Join(s.network.buildDir, "plugins")
|
||||
chainSpecs := []network.BlockchainSpec{}
|
||||
for i := range req.GetBlockchainSpecs() {
|
||||
vmName := req.GetBlockchainSpecs()[i].VmName
|
||||
vmGenesisFilePath := req.GetBlockchainSpecs()[i].Genesis
|
||||
zap.L().Info("checking custom VM ID before installation", zap.String("vm-id", vmName))
|
||||
zap.L().Info("checking custom chain's VM ID before installation", zap.String("vm-id", vmName))
|
||||
vmID, err := utils.VMID(vmName)
|
||||
if err != nil {
|
||||
zap.L().Warn("failed to convert VM name to VM ID",
|
||||
@@ -462,7 +457,7 @@ func (s *server) CreateBlockchains(ctx context.Context, req *rpcpb.CreateBlockch
|
||||
return nil, ErrInvalidVMName
|
||||
}
|
||||
if err := utils.CheckPluginPaths(
|
||||
filepath.Join(s.network.pluginDir, vmID.String()),
|
||||
filepath.Join(pluginDir, vmID.String()),
|
||||
vmGenesisFilePath,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -503,9 +498,9 @@ func (s *server) CreateBlockchains(ctx context.Context, req *rpcpb.CreateBlockch
|
||||
}
|
||||
}
|
||||
|
||||
s.clusterInfo.CustomVmsHealthy = false
|
||||
s.clusterInfo.CustomChainsHealthy = false
|
||||
|
||||
// start non-blocking to install custom VMs (if applicable)
|
||||
// start non-blocking to install custom chains (if applicable)
|
||||
// the user is expected to poll cluster status
|
||||
readyCh := make(chan struct{})
|
||||
go s.network.createBlockchains(ctx, chainSpecs, readyCh)
|
||||
@@ -514,7 +509,7 @@ func (s *server) CreateBlockchains(ctx context.Context, req *rpcpb.CreateBlockch
|
||||
// the user is expected to poll this latest information
|
||||
// to decide cluster/subnet readiness
|
||||
go func() {
|
||||
s.waitChAndUpdateClusterInfo("waiting for custom VMs readiness", readyCh, true)
|
||||
s.waitChAndUpdateClusterInfo("waiting for custom chains readiness", readyCh, true)
|
||||
}()
|
||||
|
||||
return &rpcpb.CreateBlockchainsResponse{ClusterInfo: s.clusterInfo}, nil
|
||||
@@ -552,7 +547,7 @@ func (s *server) CreateSubnets(ctx context.Context, req *rpcpb.CreateSubnetsRequ
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.clusterInfo.Healthy = false
|
||||
s.clusterInfo.CustomVmsHealthy = false
|
||||
s.clusterInfo.CustomChainsHealthy = false
|
||||
|
||||
// start non-blocking to add subnets
|
||||
// the user is expected to poll cluster status
|
||||
@@ -563,7 +558,7 @@ func (s *server) CreateSubnets(ctx context.Context, req *rpcpb.CreateSubnetsRequ
|
||||
// the user is expected to poll this latest information
|
||||
// to decide cluster/subnet readiness
|
||||
go func() {
|
||||
s.waitChAndUpdateClusterInfo("waiting for custom VMs readiness", readyCh, true)
|
||||
s.waitChAndUpdateClusterInfo("waiting for custom chains readiness", readyCh, true)
|
||||
}()
|
||||
|
||||
return &rpcpb.CreateSubnetsResponse{ClusterInfo: s.clusterInfo}, nil
|
||||
@@ -744,11 +739,7 @@ func (s *server) AddNode(ctx context.Context, req *rpcpb.AddNodeRequest) (*rpcpb
|
||||
|
||||
// use same configs from other nodes
|
||||
whitelistedSubnets = s.network.options.whitelistedSubnets
|
||||
buildDir, err := getBuildDir(execPath, s.network.pluginDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buildDir := getBuildDir(execPath, s.network.buildDir)
|
||||
rootDataDir := s.clusterInfo.RootDataDir
|
||||
|
||||
logDir := filepath.Join(rootDataDir, req.Name, "log")
|
||||
@@ -1015,7 +1006,7 @@ func (s *server) LoadSnapshot(ctx context.Context, req *rpcpb.LoadSnapshotReques
|
||||
|
||||
s.network, err = newLocalNetwork(localNetworkOptions{
|
||||
execPath: req.GetExecPath(),
|
||||
pluginDir: req.GetPluginDir(),
|
||||
buildDir: req.GetBuildDir(),
|
||||
rootDataDir: rootDataDir,
|
||||
chainConfigs: req.ChainConfigs,
|
||||
globalNodeConfig: req.GetGlobalNodeConfig(),
|
||||
|
||||
+13
-7
@@ -134,7 +134,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
|
||||
ginkgo.By("start request with invalid custom VM path should fail", func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
_, err := cli.Start(ctx, execPath1,
|
||||
client.WithPluginDir(os.TempDir()),
|
||||
client.WithBuildDir(os.TempDir()),
|
||||
client.WithBlockchainSpecs([]*rpcpb.BlockchainSpec{
|
||||
{
|
||||
VmName: "invalid",
|
||||
@@ -146,14 +146,17 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
|
||||
})
|
||||
|
||||
ginkgo.By("start request with invalid custom VM name format should fail", func() {
|
||||
f, err := os.CreateTemp(os.TempDir(), strings.Repeat("a", 33))
|
||||
pluginsPath := filepath.Join(os.TempDir(), "plugins")
|
||||
err := os.MkdirAll(pluginsPath, fs.ModePerm)
|
||||
gomega.Ω(err).Should(gomega.BeNil())
|
||||
f, err := os.CreateTemp(pluginsPath, strings.Repeat("a", 33))
|
||||
gomega.Ω(err).Should(gomega.BeNil())
|
||||
filePath := f.Name()
|
||||
gomega.Ω(f.Close()).Should(gomega.BeNil())
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
_, err = cli.Start(ctx, execPath1,
|
||||
client.WithPluginDir(filepath.Dir(filePath)),
|
||||
client.WithBuildDir(filepath.Dir(filepath.Dir(filePath))),
|
||||
client.WithBlockchainSpecs([]*rpcpb.BlockchainSpec{
|
||||
{
|
||||
VmName: filepath.Base(filePath),
|
||||
@@ -169,12 +172,15 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
|
||||
ginkgo.By("start request with invalid custom VM genesis path should fail", func() {
|
||||
vmID, err := utils.VMID("hello")
|
||||
gomega.Ω(err).Should(gomega.BeNil())
|
||||
filePath := filepath.Join(os.TempDir(), vmID.String())
|
||||
pluginsPath := filepath.Join(os.TempDir(), "plugins")
|
||||
err = os.MkdirAll(pluginsPath, fs.ModePerm)
|
||||
gomega.Ω(err).Should(gomega.BeNil())
|
||||
filePath := filepath.Join(pluginsPath, vmID.String())
|
||||
gomega.Ω(os.WriteFile(filePath, []byte{0}, fs.ModePerm)).Should(gomega.BeNil())
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
_, err = cli.Start(ctx, execPath1,
|
||||
client.WithPluginDir(filepath.Dir(filePath)),
|
||||
client.WithBuildDir(filepath.Dir(filepath.Dir(filePath))),
|
||||
client.WithBlockchainSpecs([]*rpcpb.BlockchainSpec{
|
||||
{
|
||||
VmName: "hello",
|
||||
@@ -422,7 +428,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
|
||||
status, err := cli.Status(ctx)
|
||||
cancel()
|
||||
gomega.Ω(err).Should(gomega.BeNil())
|
||||
created = status.ClusterInfo.CustomVmsHealthy
|
||||
created = status.ClusterInfo.CustomChainsHealthy
|
||||
if created {
|
||||
continueLoop = false
|
||||
}
|
||||
@@ -505,7 +511,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
|
||||
status, err := cli.Status(ctx)
|
||||
cancel()
|
||||
gomega.Ω(err).Should(gomega.BeNil())
|
||||
created = status.ClusterInfo.CustomVmsHealthy
|
||||
created = status.ClusterInfo.CustomChainsHealthy
|
||||
if created {
|
||||
continueLoop = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user