github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/peer/node/start.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package node
    18  
    19  import (
    20  	"fmt"
    21  	"net"
    22  	"net/http"
    23  	"os"
    24  	"os/signal"
    25  	"path/filepath"
    26  	"strconv"
    27  	"strings"
    28  	"syscall"
    29  	"time"
    30  
    31  	genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig"
    32  	"github.com/hyperledger/fabric/common/configtx/tool/provisional"
    33  	"github.com/hyperledger/fabric/common/flogging"
    34  	"github.com/hyperledger/fabric/common/localmsp"
    35  	"github.com/hyperledger/fabric/common/util"
    36  	"github.com/hyperledger/fabric/core"
    37  	"github.com/hyperledger/fabric/core/chaincode"
    38  	"github.com/hyperledger/fabric/core/comm"
    39  	"github.com/hyperledger/fabric/core/config"
    40  	"github.com/hyperledger/fabric/core/endorser"
    41  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
    42  	"github.com/hyperledger/fabric/core/peer"
    43  	"github.com/hyperledger/fabric/core/scc"
    44  	"github.com/hyperledger/fabric/events/producer"
    45  	"github.com/hyperledger/fabric/gossip/service"
    46  	"github.com/hyperledger/fabric/msp/mgmt"
    47  	"github.com/hyperledger/fabric/peer/common"
    48  	"github.com/hyperledger/fabric/peer/gossip/mcs"
    49  	cb "github.com/hyperledger/fabric/protos/common"
    50  	pb "github.com/hyperledger/fabric/protos/peer"
    51  	"github.com/spf13/cobra"
    52  	"github.com/spf13/viper"
    53  	"google.golang.org/grpc"
    54  	"google.golang.org/grpc/grpclog"
    55  )
    56  
    57  var chaincodeDevMode bool
    58  var peerDefaultChain bool
    59  var orderingEndpoint string
    60  
    61  // XXXDefaultChannelMSPID should not be defined in production code
    62  // It should only be referenced in tests.  However, it is necessary
    63  // to support the 'default chain' setup so temporarilly adding until
    64  // this concept can be removed to testing scenarios only
    65  const XXXDefaultChannelMSPID = "DEFAULT"
    66  
    67  func startCmd() *cobra.Command {
    68  	// Set the flags on the node start command.
    69  	flags := nodeStartCmd.Flags()
    70  	flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false,
    71  		"Whether peer in chaincode development mode")
    72  	flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", true,
    73  		"Whether to start peer with chain testchainid")
    74  	flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint")
    75  
    76  	return nodeStartCmd
    77  }
    78  
    79  var nodeStartCmd = &cobra.Command{
    80  	Use:   "start",
    81  	Short: "Starts the node.",
    82  	Long:  `Starts a node that interacts with the network.`,
    83  	RunE: func(cmd *cobra.Command, args []string) error {
    84  		return serve(args)
    85  	},
    86  }
    87  
    88  //start chaincodes
    89  func initSysCCs() {
    90  	//deploy system chaincodes
    91  	scc.DeploySysCCs("")
    92  	logger.Infof("Deployed system chaincodess")
    93  }
    94  
    95  func serve(args []string) error {
    96  	ledgermgmt.Initialize()
    97  	// Parameter overrides must be processed before any paramaters are
    98  	// cached. Failures to cache cause the server to terminate immediately.
    99  	if chaincodeDevMode {
   100  		logger.Info("Running in chaincode development mode")
   101  		logger.Info("Disable loading validity system chaincode")
   102  
   103  		viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode)
   104  
   105  	}
   106  
   107  	if err := peer.CacheConfiguration(); err != nil {
   108  		return err
   109  	}
   110  
   111  	peerEndpoint, err := peer.GetPeerEndpoint()
   112  	if err != nil {
   113  		err = fmt.Errorf("Failed to get Peer Endpoint: %s", err)
   114  		return err
   115  	}
   116  
   117  	listenAddr := viper.GetString("peer.listenAddress")
   118  
   119  	secureConfig, err := peer.GetSecureConfig()
   120  	if err != nil {
   121  		logger.Fatalf("Error loading secure config for peer (%s)", err)
   122  	}
   123  	peerServer, err := peer.CreatePeerServer(listenAddr, secureConfig)
   124  	if err != nil {
   125  		logger.Fatalf("Failed to create peer server (%s)", err)
   126  	}
   127  
   128  	if secureConfig.UseTLS {
   129  		logger.Info("Starting peer with TLS enabled")
   130  		// set up CA support
   131  		caSupport := comm.GetCASupport()
   132  		caSupport.ServerRootCAs = secureConfig.ServerRootCAs
   133  	}
   134  
   135  	//TODO - do we need different SSL material for events ?
   136  	ehubGrpcServer, err := createEventHubServer(secureConfig)
   137  	if err != nil {
   138  		grpclog.Fatalf("Failed to create ehub server: %v", err)
   139  	}
   140  
   141  	registerChaincodeSupport(peerServer.Server())
   142  
   143  	logger.Debugf("Running peer")
   144  
   145  	// Register the Admin server
   146  	pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer())
   147  
   148  	// Register the Endorser server
   149  	serverEndorser := endorser.NewEndorserServer()
   150  	pb.RegisterEndorserServer(peerServer.Server(), serverEndorser)
   151  
   152  	// Initialize gossip component
   153  	bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")
   154  
   155  	serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
   156  	if err != nil {
   157  		logger.Panicf("Failed serializing self identity: %v", err)
   158  	}
   159  
   160  	messageCryptoService := mcs.New(
   161  		peer.NewChannelPolicyManagerGetter(),
   162  		localmsp.NewSigner(),
   163  		mgmt.NewDeserializersManager())
   164  	service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(), messageCryptoService, bootstrap...)
   165  	defer service.GetGossipService().Stop()
   166  
   167  	//initialize system chaincodes
   168  	initSysCCs()
   169  
   170  	// Begin startup of default chain
   171  	if peerDefaultChain {
   172  		if orderingEndpoint == "" {
   173  			logger.Panic("No ordering service endpoint provided, please use -o option.")
   174  		}
   175  
   176  		if len(strings.Split(orderingEndpoint, ":")) != 2 {
   177  			logger.Panicf("Invalid format of ordering service endpoint, %s.", orderingEndpoint)
   178  		}
   179  
   180  		chainID := util.GetTestChainID()
   181  
   182  		var block *cb.Block
   183  
   184  		func() {
   185  			defer func() {
   186  				if err := recover(); err != nil {
   187  					logger.Fatalf("Peer configured to start with the default test chain, but supporting configuration files did not match.  Please ensure that configtx.yaml contains the unmodified SampleSingleMSPSolo profile and that sampleconfig/msp is present.\n%s", err)
   188  				}
   189  			}()
   190  
   191  			genConf := genesisconfig.Load(genesisconfig.SampleSingleMSPSoloProfile)
   192  			genConf.Orderer.Addresses = []string{orderingEndpoint}
   193  			genConf.Application.Organizations[0].Name = XXXDefaultChannelMSPID
   194  			genConf.Application.Organizations[0].ID = XXXDefaultChannelMSPID
   195  			block = provisional.New(genConf).GenesisBlockForChannel(chainID)
   196  		}()
   197  
   198  		//this creates testchainid and sets up gossip
   199  		if err = peer.CreateChainFromBlock(block); err == nil {
   200  			logger.Infof("create chain [%s]", chainID)
   201  			scc.DeploySysCCs(chainID)
   202  			logger.Infof("Deployed system chaincodes on %s", chainID)
   203  		} else {
   204  			logger.Errorf("create default chain [%s] failed with %s", chainID, err)
   205  		}
   206  	}
   207  
   208  	//this brings up all the chains (including testchainid)
   209  	peer.Initialize(func(cid string) {
   210  		logger.Debugf("Deploying system CC, for chain <%s>", cid)
   211  		scc.DeploySysCCs(cid)
   212  	})
   213  
   214  	logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]",
   215  		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)
   216  
   217  	// Start the grpc server. Done in a goroutine so we can deploy the
   218  	// genesis block if needed.
   219  	serve := make(chan error)
   220  
   221  	sigs := make(chan os.Signal, 1)
   222  	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
   223  	go func() {
   224  		sig := <-sigs
   225  		logger.Debugf("sig: %s", sig)
   226  		serve <- nil
   227  	}()
   228  
   229  	go func() {
   230  		var grpcErr error
   231  		if grpcErr = peerServer.Start(); grpcErr != nil {
   232  			grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
   233  		} else {
   234  			logger.Info("peer server exited")
   235  		}
   236  		serve <- grpcErr
   237  	}()
   238  
   239  	if err := writePid(config.GetPath("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil {
   240  		return err
   241  	}
   242  
   243  	// Start the event hub server
   244  	if ehubGrpcServer != nil {
   245  		go ehubGrpcServer.Start()
   246  	}
   247  
   248  	// Start profiling http endpoint if enabled
   249  	if viper.GetBool("peer.profile.enabled") {
   250  		go func() {
   251  			profileListenAddress := viper.GetString("peer.profile.listenAddress")
   252  			logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress)
   253  			if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil {
   254  				logger.Errorf("Error starting profiler: %s", profileErr)
   255  			}
   256  		}()
   257  	}
   258  
   259  	logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]",
   260  		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)
   261  
   262  	// set the logging level for specific modules defined in core.yaml.
   263  	// TODO Add calls to set 'ledger' module loggers
   264  	overrideLogModules := []string{"msp", "gossip"}
   265  	for _, module := range overrideLogModules {
   266  		err = common.SetLogLevelFromViper(module)
   267  		if err != nil {
   268  			logger.Warningf("Error setting log level for module '%s': %s", module, err.Error())
   269  		}
   270  	}
   271  
   272  	flogging.SetPeerStartupModulesMap()
   273  
   274  	// Block until grpc server exits
   275  	return <-serve
   276  }
   277  
   278  //NOTE - when we implment JOIN we will no longer pass the chainID as param
   279  //The chaincode support will come up without registering system chaincodes
   280  //which will be registered only during join phase.
   281  func registerChaincodeSupport(grpcServer *grpc.Server) {
   282  	//get user mode
   283  	userRunsCC := chaincode.IsDevMode()
   284  
   285  	//get chaincode startup timeout
   286  	tOut, err := strconv.Atoi(viper.GetString("chaincode.startuptimeout"))
   287  	if err != nil { //what went wrong ?
   288  		logger.Warning("could not retrieve timeout var...setting to 5secs")
   289  		tOut = 5000
   290  	}
   291  	ccStartupTimeout := time.Duration(tOut) * time.Millisecond
   292  
   293  	ccSrv := chaincode.NewChaincodeSupport(peer.GetPeerEndpoint, userRunsCC, ccStartupTimeout)
   294  
   295  	//Now that chaincode is initialized, register all system chaincodes.
   296  	scc.RegisterSysCCs()
   297  
   298  	pb.RegisterChaincodeSupportServer(grpcServer, ccSrv)
   299  }
   300  
   301  func createEventHubServer(secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
   302  	var lis net.Listener
   303  	var err error
   304  	lis, err = net.Listen("tcp", viper.GetString("peer.events.address"))
   305  	if err != nil {
   306  		return nil, fmt.Errorf("failed to listen: %v", err)
   307  	}
   308  
   309  	grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig)
   310  	if err != nil {
   311  		logger.Errorf("Failed to return new GRPC server: %s", err)
   312  		return nil, err
   313  	}
   314  	ehServer := producer.NewEventsServer(
   315  		uint(viper.GetInt("peer.events.buffersize")),
   316  		viper.GetInt("peer.events.timeout"))
   317  
   318  	pb.RegisterEventsServer(grpcServer.Server(), ehServer)
   319  	return grpcServer, nil
   320  }
   321  
   322  func writePid(fileName string, pid int) error {
   323  	err := os.MkdirAll(filepath.Dir(fileName), 0755)
   324  	if err != nil {
   325  		return err
   326  	}
   327  
   328  	fd, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0644)
   329  	if err != nil {
   330  		return err
   331  	}
   332  	defer fd.Close()
   333  	if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
   334  		return fmt.Errorf("can't lock '%s', lock is held", fd.Name())
   335  	}
   336  
   337  	if _, err := fd.Seek(0, 0); err != nil {
   338  		return err
   339  	}
   340  
   341  	if err := fd.Truncate(0); err != nil {
   342  		return err
   343  	}
   344  
   345  	if _, err := fmt.Fprintf(fd, "%d", pid); err != nil {
   346  		return err
   347  	}
   348  
   349  	if err := fd.Sync(); err != nil {
   350  		return err
   351  	}
   352  
   353  	if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_UN); err != nil {
   354  		return fmt.Errorf("can't release lock '%s', lock is held", fd.Name())
   355  	}
   356  	return nil
   357  }