Skip to content

Commit 96735d2

Browse files
committed
[FAB-11833] Say hello to Raft OSN
This change set: 1) Wires the consenter into the registrar 2) Wires the communication to the consenter and to the registrar, in preperation for multi-node Raft. This makes a new chain configure the communication layer of the cluster according to the TLS certificates of the channel. 3) Adds a unit test that spawns a Raft OSN Change-Id: I3923f6f5e0fae6428c2be2e056b82355332f3324 Signed-off-by: yacovm <yacovm@il.ibm.com>
1 parent 41c8f12 commit 96735d2

File tree

20 files changed

+738
-173
lines changed

20 files changed

+738
-173
lines changed

orderer/common/cluster/comm.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ func (rm RemoteNode) String() string {
5858
rm.ID, rm.Endpoint, DERtoPEM(rm.ServerTLSCert), DERtoPEM(rm.ClientTLSCert))
5959
}
6060

61+
//go:generate mockery -dir . -name Communicator -case underscore -output ./mocks/
62+
6163
// Communicator defines communication for a consenter
6264
type Communicator interface {
6365
// Remote returns a RemoteContext for the given RemoteNode ID in the context
@@ -67,7 +69,7 @@ type Communicator interface {
6769
// Configure configures the communication to connect to all
6870
// given members, and disconnect from any members not among the given
6971
// members.
70-
Configure(channel string, members []*RemoteNode)
72+
Configure(channel string, members []RemoteNode)
7173
// Shutdown shuts down the communicator
7274
Shutdown()
7375
}

orderer/common/cluster/mocks/remote_communicator.go renamed to orderer/common/cluster/mocks/communicator.go

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

orderer/common/cluster/rpc.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@ import (
1414
"google.golang.org/grpc"
1515
)
1616

17-
//go:generate mockery -dir . -name RemoteCommunicator -case underscore -output ./mocks/
18-
19-
// RemoteCommunicator communicates to remote nodes
20-
type RemoteCommunicator interface {
21-
// Remote returns a RemoteContext for the given node ID in the context
22-
// of the given channel, or error if connection cannot be established, or
23-
// the channel wasn't configured
24-
Remote(channel string, id uint64) (*RemoteContext, error)
25-
}
26-
2717
//go:generate mockery -dir . -name SubmitClient -case underscore -output ./mocks/
2818

2919
// SubmitClient is the Submit gRPC stream
@@ -48,7 +38,7 @@ type Client interface {
4838
type RPC struct {
4939
stream orderer.Cluster_SubmitClient
5040
Channel string
51-
Comm RemoteCommunicator
41+
Comm Communicator
5242
}
5343

5444
// Step sends a StepRequest to the given destination node and returns the response

orderer/common/cluster/rpc_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func TestRPCStep(t *testing.T) {
4848
} {
4949
testcase := testcase
5050
t.Run(testcase.name, func(t *testing.T) {
51-
comm := &mocks.RemoteCommunicator{}
51+
comm := &mocks.Communicator{}
5252
client := &mocks.ClusterClient{}
5353
client.On("Step", mock.Anything, mock.Anything).Return(testcase.stepReturns...)
5454
comm.On("Remote", "mychannel", uint64(1)).Return(&cluster.RemoteContext{
@@ -79,7 +79,7 @@ func TestRPCSubmitSend(t *testing.T) {
7979
submitRequest := &orderer.SubmitRequest{Channel: "mychannel"}
8080
submitResponse := &orderer.SubmitResponse{Status: common.Status_SUCCESS}
8181

82-
comm := &mocks.RemoteCommunicator{}
82+
comm := &mocks.Communicator{}
8383
stream := &mocks.SubmitClient{}
8484
client := &mocks.ClusterClient{}
8585

orderer/common/localconfig/config.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type Cluster struct {
6262
ClientCertificate string
6363
ClientPrivateKey string
6464
DialTimeout time.Duration
65+
RPCTimeout time.Duration
6566
}
6667

6768
// Keepalive contains configuration for gRPC servers.
@@ -269,8 +270,12 @@ func Load() (*TopLevel, error) {
269270
func (c *TopLevel) completeInitialization(configDir string) {
270271
defer func() {
271272
// Translate any paths for cluster TLS configuration if applicable
272-
coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientPrivateKey)
273-
coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientCertificate)
273+
if c.General.Cluster.ClientPrivateKey != "" {
274+
coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientPrivateKey)
275+
}
276+
if c.General.Cluster.ClientCertificate != "" {
277+
coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientCertificate)
278+
}
274279
c.General.Cluster.RootCAs = translateCAs(configDir, c.General.Cluster.RootCAs)
275280
// Translate any paths for general TLS configuration
276281
c.General.TLS.RootCAs = translateCAs(configDir, c.General.TLS.RootCAs)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package server_test
8+
9+
import (
10+
"fmt"
11+
"io/ioutil"
12+
"os"
13+
"os/exec"
14+
"path/filepath"
15+
"testing"
16+
"time"
17+
18+
. "github.com/onsi/gomega"
19+
"github.com/onsi/gomega/gbytes"
20+
"github.com/onsi/gomega/gexec"
21+
)
22+
23+
func TestSpawnEtcdRaft(t *testing.T) {
24+
gt := NewGomegaWithT(t)
25+
26+
// Create tempdir to be used to store the genesis block for the system channel
27+
tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch")
28+
gt.Expect(err).NotTo(HaveOccurred())
29+
defer os.RemoveAll(tempDir)
30+
31+
// Set the fabric root folder for easy navigation to sampleconfig folder
32+
fabricRootDir, err := filepath.Abs(filepath.Join("..", "..", ".."))
33+
gt.Expect(err).NotTo(HaveOccurred())
34+
35+
// Build the configtxgen binary
36+
configtxgen, err := gexec.Build("github.com/hyperledger/fabric/common/tools/configtxgen")
37+
gt.Expect(err).NotTo(HaveOccurred())
38+
39+
// Build the orderer binary
40+
orderer, err := gexec.Build("github.com/hyperledger/fabric/orderer")
41+
gt.Expect(err).NotTo(HaveOccurred())
42+
43+
defer gexec.CleanupBuildArtifacts()
44+
45+
// Create the genesis block for the system channel
46+
genesisBlockPath := filepath.Join(tempDir, "genesis.block")
47+
cmd := exec.Command(configtxgen, "-channelID", "system", "-profile", "SampleDevModeEtcdRaft",
48+
"-outputBlock", genesisBlockPath)
49+
cmd.Env = append(cmd.Env, fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")))
50+
configtxgenProcess, err := gexec.Start(cmd, nil, nil)
51+
gt.Expect(err).NotTo(HaveOccurred())
52+
53+
gt.Eventually(configtxgenProcess, time.Minute).Should(gexec.Exit(0))
54+
gt.Expect(configtxgenProcess.Err).To(gbytes.Say("Writing genesis block"))
55+
56+
// Launch the OSN
57+
ordererProcess := launchOrderer(gt, cmd, orderer, tempDir, genesisBlockPath, fabricRootDir)
58+
gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("Beginning to serve requests"))
59+
gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader"))
60+
ordererProcess.Kill()
61+
}
62+
63+
func launchOrderer(gt *GomegaWithT, cmd *exec.Cmd, orderer, tempDir, genesisBlockPath, fabricRootDir string) *gexec.Session {
64+
cwd, err := filepath.Abs(".")
65+
gt.Expect(err).NotTo(HaveOccurred())
66+
67+
// Launch the orderer process
68+
cmd = exec.Command(orderer)
69+
cmd.Env = []string{
70+
"ORDERER_GENERAL_LISTENPORT=5611",
71+
"ORDERER_GENERAL_GENESISPROFILE=SampleDevModeEtcdRaft",
72+
"ORDERER_GENERAL_GENESISMETHOD=file",
73+
"ORDERER_GENERAL_SYSTEMCHANNEL=system",
74+
"ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED=true",
75+
"ORDERER_GENERAL_TLS_ENABLED=true",
76+
fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")),
77+
fmt.Sprintf("ORDERER_GENERAL_GENESISFILE=%s", genesisBlockPath),
78+
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(cwd, "testdata", "tls", "server.crt")),
79+
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "tls", "server.key")),
80+
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "tls", "ca.crt")),
81+
fmt.Sprintf("ORDERER_GENERAL_TLS_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "tls", "ca.crt")),
82+
fmt.Sprintf("ORDERER_GENERAL_TLS_CERTIFICATE=%s", filepath.Join(cwd, "testdata", "tls", "server.crt")),
83+
fmt.Sprintf("ORDERER_GENERAL_TLS_PRIVATEKEY=%s", filepath.Join(cwd, "testdata", "tls", "server.key")),
84+
fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")),
85+
}
86+
sess, err := gexec.Start(cmd, nil, nil)
87+
gt.Expect(err).NotTo(HaveOccurred())
88+
return sess
89+
}

0 commit comments

Comments
 (0)