diff --git a/lntest/harness_net.go b/lntest/harness_net.go index 8e257f463..4bdc8dbe8 100644 --- a/lntest/harness_net.go +++ b/lntest/harness_net.go @@ -275,7 +275,9 @@ func (n *NetworkHarness) Stop() { // extraArgsEtcd returns extra args for configuring LND to use an external etcd // database (for remote channel DB and wallet DB). -func extraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool) []string { +func extraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool, + leaderSessionTTL int) []string { + extraArgs := []string{ "--db.backend=etcd", fmt.Sprintf("--db.etcd.host=%v", etcdCfg.Host), @@ -289,10 +291,13 @@ func extraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool) []string { } if cluster { - extraArgs = append(extraArgs, "--cluster.enable-leader-election") - extraArgs = append( - extraArgs, fmt.Sprintf("--cluster.id=%v", name), - ) + clusterArgs := []string{ + "--cluster.enable-leader-election", + fmt.Sprintf("--cluster.id=%v", name), + fmt.Sprintf("--cluster.leader-session-ttl=%v", + leaderSessionTTL), + } + extraArgs = append(extraArgs, clusterArgs...) } return extraArgs @@ -302,13 +307,13 @@ func extraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool) []string { // etcd database as its (remote) channel and wallet DB. The passsed cluster // flag indicates that we'd like the node to join the cluster leader election. func (n *NetworkHarness) NewNodeWithSeedEtcd(name string, etcdCfg *etcd.Config, - password []byte, entropy []byte, statelessInit, cluster bool) ( - *HarnessNode, []string, []byte, error) { + password []byte, entropy []byte, statelessInit, cluster bool, + leaderSessionTTL int) (*HarnessNode, []string, []byte, error) { // We don't want to use the embedded etcd instance. const dbBackend = BackendBbolt - extraArgs := extraArgsEtcd(etcdCfg, name, cluster) + extraArgs := extraArgsEtcd(etcdCfg, name, cluster, leaderSessionTTL) return n.newNodeWithSeed( name, extraArgs, password, entropy, statelessInit, dbBackend, ) @@ -320,12 +325,13 @@ func (n *NetworkHarness) NewNodeWithSeedEtcd(name string, etcdCfg *etcd.Config, // If the wait flag is false then we won't wait until RPC is available (this is // useful when the node is not expected to become the leader right away). func (n *NetworkHarness) NewNodeEtcd(name string, etcdCfg *etcd.Config, - password []byte, cluster, wait bool) (*HarnessNode, error) { + password []byte, cluster, wait bool, leaderSessionTTL int) ( + *HarnessNode, error) { // We don't want to use the embedded etcd instance. const dbBackend = BackendBbolt - extraArgs := extraArgsEtcd(etcdCfg, name, cluster) + extraArgs := extraArgsEtcd(etcdCfg, name, cluster, leaderSessionTTL) return n.newNode(name, extraArgs, true, password, dbBackend, wait) } diff --git a/lntest/itest/lnd_etcd_failover_test.go b/lntest/itest/lnd_etcd_failover_test.go index ad02197d2..3be233303 100644 --- a/lntest/itest/lnd_etcd_failover_test.go +++ b/lntest/itest/lnd_etcd_failover_test.go @@ -81,12 +81,15 @@ func testEtcdFailoverCase(net *lntest.NetworkHarness, ht *harnessTest, } defer cleanup() + // Make leader election session TTL 5 sec to make the test run fast. + const leaderSessionTTL = 5 + observer, err := cluster.MakeLeaderElector( ctxb, cluster.EtcdLeaderElector, "observer", - lncfg.DefaultEtcdElectionPrefix, etcdCfg, + lncfg.DefaultEtcdElectionPrefix, leaderSessionTTL, etcdCfg, ) if err != nil { - ht.Fatalf("Cannot start election observer") + ht.Fatalf("Cannot start election observer: %v", err) } password := []byte("the quick brown fox jumps the lazy dog") @@ -96,6 +99,7 @@ func testEtcdFailoverCase(net *lntest.NetworkHarness, ht *harnessTest, carol1, _, _, err := net.NewNodeWithSeedEtcd( "Carol-1", etcdCfg, password, entropy[:], stateless, cluster, + leaderSessionTTL, ) if err != nil { ht.Fatalf("unable to start Carol-1: %v", err) @@ -122,7 +126,7 @@ func testEtcdFailoverCase(net *lntest.NetworkHarness, ht *harnessTest, // At this point Carol-1 is the elected leader, while Carol-2 will wait // to become the leader when Carol-1 stops. carol2, err := net.NewNodeEtcd( - "Carol-2", etcdCfg, password, cluster, false, + "Carol-2", etcdCfg, password, cluster, false, leaderSessionTTL, ) if err != nil { ht.Fatalf("Unable to start Carol-2: %v", err) @@ -145,17 +149,14 @@ func testEtcdFailoverCase(net *lntest.NetworkHarness, ht *harnessTest, ) // Shut down or kill Carol-1 and wait for Carol-2 to become the leader. - var failoverTimeout time.Duration + failoverTimeout := time.Duration(2*leaderSessionTTL) * time.Second if kill { err = net.KillNode(carol1) if err != nil { ht.Fatalf("Can't kill Carol-1: %v", err) } - - failoverTimeout = 2 * time.Minute } else { shutdownAndAssert(net, ht, carol1) - failoverTimeout = 30 * time.Second } err = carol2.WaitUntilLeader(failoverTimeout)