github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/peer/node/start.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package node
     8  
     9  import (
    10  	"fmt"
    11  	"net"
    12  	"net/http"
    13  	"os"
    14  	"os/signal"
    15  	"path/filepath"
    16  	"syscall"
    17  	"time"
    18  
    19  	"github.com/hyperledger/fabric/common/flogging"
    20  	"github.com/hyperledger/fabric/common/localmsp"
    21  	"github.com/hyperledger/fabric/core"
    22  	"github.com/hyperledger/fabric/core/chaincode"
    23  	"github.com/hyperledger/fabric/core/comm"
    24  	"github.com/hyperledger/fabric/core/common/ccprovider"
    25  	"github.com/hyperledger/fabric/core/config"
    26  	"github.com/hyperledger/fabric/core/endorser"
    27  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
    28  	"github.com/hyperledger/fabric/core/peer"
    29  	"github.com/hyperledger/fabric/core/scc"
    30  	"github.com/hyperledger/fabric/events/producer"
    31  	"github.com/hyperledger/fabric/gossip/service"
    32  	"github.com/hyperledger/fabric/msp/mgmt"
    33  	"github.com/hyperledger/fabric/peer/common"
    34  	peergossip "github.com/hyperledger/fabric/peer/gossip"
    35  	"github.com/hyperledger/fabric/peer/version"
    36  	pb "github.com/hyperledger/fabric/protos/peer"
    37  	"github.com/spf13/cobra"
    38  	"github.com/spf13/viper"
    39  	"google.golang.org/grpc"
    40  	"google.golang.org/grpc/grpclog"
    41  )
    42  
    43  var chaincodeDevMode bool
    44  var peerDefaultChain bool
    45  var orderingEndpoint string
    46  
    47  // XXXDefaultChannelMSPID should not be defined in production code
    48  // It should only be referenced in tests.  However, it is necessary
    49  // to support the 'default chain' setup so temporarily adding until
    50  // this concept can be removed to testing scenarios only
    51  const XXXDefaultChannelMSPID = "DEFAULT"
    52  
    53  func startCmd() *cobra.Command {
    54  	// Set the flags on the node start command.
    55  	flags := nodeStartCmd.Flags()
    56  	flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false,
    57  		"Whether peer in chaincode development mode")
    58  	flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", false,
    59  		"Whether to start peer with chain testchainid")
    60  	flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint")
    61  
    62  	return nodeStartCmd
    63  }
    64  
    65  var nodeStartCmd = &cobra.Command{
    66  	Use:   "start",
    67  	Short: "Starts the node.",
    68  	Long:  `Starts a node that interacts with the network.`,
    69  	RunE: func(cmd *cobra.Command, args []string) error {
    70  		return serve(args)
    71  	},
    72  }
    73  
    74  //start chaincodes
    75  func initSysCCs() {
    76  	//deploy system chaincodes
    77  	scc.DeploySysCCs("")
    78  	logger.Infof("Deployed system chaincodess")
    79  }
    80  
    81  func serve(args []string) error {
    82  	logger.Infof("Starting %s", version.GetInfo())
    83  	ledgermgmt.Initialize()
    84  	// Parameter overrides must be processed before any parameters are
    85  	// cached. Failures to cache cause the server to terminate immediately.
    86  	if chaincodeDevMode {
    87  		logger.Info("Running in chaincode development mode")
    88  		logger.Info("Disable loading validity system chaincode")
    89  
    90  		viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode)
    91  
    92  	}
    93  
    94  	if err := peer.CacheConfiguration(); err != nil {
    95  		return err
    96  	}
    97  
    98  	peerEndpoint, err := peer.GetPeerEndpoint()
    99  	if err != nil {
   100  		err = fmt.Errorf("Failed to get Peer Endpoint: %s", err)
   101  		return err
   102  	}
   103  
   104  	listenAddr := viper.GetString("peer.listenAddress")
   105  
   106  	secureConfig, err := peer.GetSecureConfig()
   107  	if err != nil {
   108  		logger.Fatalf("Error loading secure config for peer (%s)", err)
   109  	}
   110  	peerServer, err := peer.CreatePeerServer(listenAddr, secureConfig)
   111  	if err != nil {
   112  		logger.Fatalf("Failed to create peer server (%s)", err)
   113  	}
   114  
   115  	if secureConfig.UseTLS {
   116  		logger.Info("Starting peer with TLS enabled")
   117  		// set up CA support
   118  		caSupport := comm.GetCASupport()
   119  		caSupport.ServerRootCAs = secureConfig.ServerRootCAs
   120  	}
   121  
   122  	//TODO - do we need different SSL material for events ?
   123  	ehubGrpcServer, err := createEventHubServer(secureConfig)
   124  	if err != nil {
   125  		grpclog.Fatalf("Failed to create ehub server: %v", err)
   126  	}
   127  
   128  	// enable the cache of chaincode info
   129  	ccprovider.EnableCCInfoCache()
   130  
   131  	registerChaincodeSupport(peerServer.Server())
   132  
   133  	logger.Debugf("Running peer")
   134  
   135  	// Register the Admin server
   136  	pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer())
   137  
   138  	// Register the Endorser server
   139  	serverEndorser := endorser.NewEndorserServer()
   140  	pb.RegisterEndorserServer(peerServer.Server(), serverEndorser)
   141  
   142  	// Initialize gossip component
   143  	bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")
   144  
   145  	serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
   146  	if err != nil {
   147  		logger.Panicf("Failed serializing self identity: %v", err)
   148  	}
   149  
   150  	messageCryptoService := peergossip.NewMCS(
   151  		peer.NewChannelPolicyManagerGetter(),
   152  		localmsp.NewSigner(),
   153  		mgmt.NewDeserializersManager())
   154  	secAdv := peergossip.NewSecurityAdvisor(mgmt.NewDeserializersManager())
   155  
   156  	// callback function for secure dial options for gossip service
   157  	secureDialOpts := func() []grpc.DialOption {
   158  		var dialOpts []grpc.DialOption
   159  		// set max send/recv msg sizes
   160  		dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize()),
   161  			grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize())))
   162  		// set the keepalive options
   163  		dialOpts = append(dialOpts, comm.ClientKeepaliveOptions()...)
   164  
   165  		if comm.TLSEnabled() {
   166  			tlsCert := peerServer.ServerCertificate()
   167  			dialOpts = append(dialOpts, grpc.WithTransportCredentials(comm.GetCASupport().GetPeerCredentials(tlsCert)))
   168  		} else {
   169  			dialOpts = append(dialOpts, grpc.WithInsecure())
   170  		}
   171  		return dialOpts
   172  	}
   173  	service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(),
   174  		messageCryptoService, secAdv, secureDialOpts, bootstrap...)
   175  	defer service.GetGossipService().Stop()
   176  
   177  	//initialize system chaincodes
   178  	initSysCCs()
   179  
   180  	//this brings up all the chains (including testchainid)
   181  	peer.Initialize(func(cid string) {
   182  		logger.Debugf("Deploying system CC, for chain <%s>", cid)
   183  		scc.DeploySysCCs(cid)
   184  	})
   185  
   186  	logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]",
   187  		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)
   188  
   189  	// Start the grpc server. Done in a goroutine so we can deploy the
   190  	// genesis block if needed.
   191  	serve := make(chan error)
   192  
   193  	sigs := make(chan os.Signal, 1)
   194  	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
   195  	go func() {
   196  		sig := <-sigs
   197  		logger.Debugf("sig: %s", sig)
   198  		serve <- nil
   199  	}()
   200  
   201  	go func() {
   202  		var grpcErr error
   203  		if grpcErr = peerServer.Start(); grpcErr != nil {
   204  			grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
   205  		} else {
   206  			logger.Info("peer server exited")
   207  		}
   208  		serve <- grpcErr
   209  	}()
   210  
   211  	if err := writePid(config.GetPath("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil {
   212  		return err
   213  	}
   214  
   215  	// Start the event hub server
   216  	if ehubGrpcServer != nil {
   217  		go ehubGrpcServer.Start()
   218  	}
   219  
   220  	// Start profiling http endpoint if enabled
   221  	if viper.GetBool("peer.profile.enabled") {
   222  		go func() {
   223  			profileListenAddress := viper.GetString("peer.profile.listenAddress")
   224  			logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress)
   225  			if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil {
   226  				logger.Errorf("Error starting profiler: %s", profileErr)
   227  			}
   228  		}()
   229  	}
   230  
   231  	logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]",
   232  		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)
   233  
   234  	// set the logging level for specific modules defined via environment
   235  	// variables or core.yaml
   236  	overrideLogModules := []string{"msp", "gossip", "ledger", "cauthdsl", "policies", "grpc"}
   237  	for _, module := range overrideLogModules {
   238  		err = common.SetLogLevelFromViper(module)
   239  		if err != nil {
   240  			logger.Warningf("Error setting log level for module '%s': %s", module, err.Error())
   241  		}
   242  	}
   243  
   244  	flogging.SetPeerStartupModulesMap()
   245  
   246  	// Block until grpc server exits
   247  	return <-serve
   248  }
   249  
   250  //NOTE - when we implment JOIN we will no longer pass the chainID as param
   251  //The chaincode support will come up without registering system chaincodes
   252  //which will be registered only during join phase.
   253  func registerChaincodeSupport(grpcServer *grpc.Server) {
   254  	//get user mode
   255  	userRunsCC := chaincode.IsDevMode()
   256  
   257  	//get chaincode startup timeout
   258  	ccStartupTimeout := viper.GetDuration("chaincode.startuptimeout")
   259  	if ccStartupTimeout < time.Duration(5)*time.Second {
   260  		logger.Warningf("Invalid chaincode startup timeout value %s (should be at least 5s); defaulting to 5s", ccStartupTimeout)
   261  		ccStartupTimeout = time.Duration(5) * time.Second
   262  	} else {
   263  		logger.Debugf("Chaincode startup timeout value set to %s", ccStartupTimeout)
   264  	}
   265  
   266  	ccSrv := chaincode.NewChaincodeSupport(peer.GetPeerEndpoint, userRunsCC, ccStartupTimeout)
   267  
   268  	//Now that chaincode is initialized, register all system chaincodes.
   269  	scc.RegisterSysCCs()
   270  
   271  	pb.RegisterChaincodeSupportServer(grpcServer, ccSrv)
   272  }
   273  
   274  func createEventHubServer(secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
   275  	var lis net.Listener
   276  	var err error
   277  	lis, err = net.Listen("tcp", viper.GetString("peer.events.address"))
   278  	if err != nil {
   279  		return nil, fmt.Errorf("failed to listen: %v", err)
   280  	}
   281  
   282  	grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig)
   283  	if err != nil {
   284  		logger.Errorf("Failed to return new GRPC server: %s", err)
   285  		return nil, err
   286  	}
   287  	ehServer := producer.NewEventsServer(
   288  		uint(viper.GetInt("peer.events.buffersize")),
   289  		viper.GetDuration("peer.events.timeout"))
   290  
   291  	pb.RegisterEventsServer(grpcServer.Server(), ehServer)
   292  	return grpcServer, nil
   293  }
   294  
   295  func writePid(fileName string, pid int) error {
   296  	err := os.MkdirAll(filepath.Dir(fileName), 0755)
   297  	if err != nil {
   298  		return err
   299  	}
   300  
   301  	fd, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0644)
   302  	if err != nil {
   303  		return err
   304  	}
   305  	defer fd.Close()
   306  	if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
   307  		return fmt.Errorf("can't lock '%s', lock is held", fd.Name())
   308  	}
   309  
   310  	if _, err := fd.Seek(0, 0); err != nil {
   311  		return err
   312  	}
   313  
   314  	if err := fd.Truncate(0); err != nil {
   315  		return err
   316  	}
   317  
   318  	if _, err := fmt.Fprintf(fd, "%d", pid); err != nil {
   319  		return err
   320  	}
   321  
   322  	if err := fd.Sync(); err != nil {
   323  		return err
   324  	}
   325  
   326  	if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_UN); err != nil {
   327  		return fmt.Errorf("can't release lock '%s', lock is held", fd.Name())
   328  	}
   329  	return nil
   330  }