github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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  	"syscall"
    28  	"time"
    29  
    30  	"github.com/hyperledger/fabric/common/configtx"
    31  	"github.com/hyperledger/fabric/common/configtx/test"
    32  	"github.com/hyperledger/fabric/common/configvalues/channel/application"
    33  	"github.com/hyperledger/fabric/common/configvalues/msp"
    34  	"github.com/hyperledger/fabric/common/genesis"
    35  	"github.com/hyperledger/fabric/common/policies"
    36  	"github.com/hyperledger/fabric/common/util"
    37  	"github.com/hyperledger/fabric/core"
    38  	"github.com/hyperledger/fabric/core/chaincode"
    39  	"github.com/hyperledger/fabric/core/comm"
    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  	pb "github.com/hyperledger/fabric/protos/peer"
    50  	"github.com/spf13/cobra"
    51  	"github.com/spf13/viper"
    52  	"google.golang.org/grpc"
    53  	"google.golang.org/grpc/grpclog"
    54  )
    55  
    56  var chaincodeDevMode bool
    57  var peerDefaultChain bool
    58  
    59  func startCmd() *cobra.Command {
    60  	// Set the flags on the node start command.
    61  	flags := nodeStartCmd.Flags()
    62  	flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false,
    63  		"Whether peer in chaincode development mode")
    64  	flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", true,
    65  		"Whether to start peer with chain testchainid")
    66  
    67  	return nodeStartCmd
    68  }
    69  
    70  var nodeStartCmd = &cobra.Command{
    71  	Use:   "start",
    72  	Short: "Starts the node.",
    73  	Long:  `Starts a node that interacts with the network.`,
    74  	RunE: func(cmd *cobra.Command, args []string) error {
    75  		return serve(args)
    76  	},
    77  }
    78  
    79  //start chaincodes
    80  func initSysCCs() {
    81  	//deploy system chaincodes
    82  	scc.DeploySysCCs("")
    83  	logger.Infof("Deployed system chaincodess")
    84  }
    85  
    86  func serve(args []string) error {
    87  	ledgermgmt.Initialize()
    88  	// Parameter overrides must be processed before any paramaters are
    89  	// cached. Failures to cache cause the server to terminate immediately.
    90  	if chaincodeDevMode {
    91  		logger.Info("Running in chaincode development mode")
    92  		logger.Info("Disable loading validity system chaincode")
    93  
    94  		viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode)
    95  
    96  	}
    97  
    98  	if err := peer.CacheConfiguration(); err != nil {
    99  		return err
   100  	}
   101  
   102  	peerEndpoint, err := peer.GetPeerEndpoint()
   103  	if err != nil {
   104  		err = fmt.Errorf("Failed to get Peer Endpoint: %s", err)
   105  		return err
   106  	}
   107  
   108  	listenAddr := viper.GetString("peer.listenAddress")
   109  
   110  	if "" == listenAddr {
   111  		logger.Debug("Listen address not specified, using peer endpoint address")
   112  		listenAddr = peerEndpoint.Address
   113  	}
   114  
   115  	lis, err := net.Listen("tcp", listenAddr)
   116  	if err != nil {
   117  		grpclog.Fatalf("Failed to listen: %v", err)
   118  	}
   119  
   120  	logger.Infof("Security enabled status: %t", core.SecurityEnabled())
   121  
   122  	//Create GRPC server - return if an error occurs
   123  	secureConfig := comm.SecureServerConfig{
   124  		UseTLS: viper.GetBool("peer.tls.enabled"),
   125  	}
   126  	grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig)
   127  	if err != nil {
   128  		fmt.Println("Failed to return new GRPC server: ", err)
   129  		return err
   130  	}
   131  
   132  	//TODO - do we need different SSL material for events ?
   133  	ehubGrpcServer, err := createEventHubServer(secureConfig)
   134  	if err != nil {
   135  		grpclog.Fatalf("Failed to create ehub server: %v", err)
   136  	}
   137  
   138  	registerChaincodeSupport(grpcServer.Server())
   139  
   140  	logger.Debugf("Running peer")
   141  
   142  	// Register the Admin server
   143  	pb.RegisterAdminServer(grpcServer.Server(), core.NewAdminServer())
   144  
   145  	// Register the Endorser server
   146  	serverEndorser := endorser.NewEndorserServer()
   147  	pb.RegisterEndorserServer(grpcServer.Server(), serverEndorser)
   148  
   149  	// Initialize gossip component
   150  	bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")
   151  
   152  	serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
   153  	if err != nil {
   154  		panic(fmt.Sprintf("Failed serializing self identity: %v", err))
   155  	}
   156  
   157  	messageCryptoService := mcs.New(peer.GetPolicyManagerMgmt())
   158  	service.InitGossipService(serializedIdentity, peerEndpoint.Address, grpcServer.Server(), messageCryptoService, bootstrap...)
   159  	defer service.GetGossipService().Stop()
   160  
   161  	//initialize system chaincodes
   162  	initSysCCs()
   163  
   164  	// Begin startup of default chain
   165  	if peerDefaultChain {
   166  		chainID := util.GetTestChainID()
   167  
   168  		// add readers, writers and admin policies for the default chain
   169  		policyTemplate := configtx.NewSimpleTemplate(
   170  			policies.TemplateImplicitMetaAnyPolicy([]string{application.GroupKey}, msp.ReadersPolicyKey),
   171  			policies.TemplateImplicitMetaAnyPolicy([]string{application.GroupKey}, msp.WritersPolicyKey),
   172  			policies.TemplateImplicitMetaMajorityPolicy([]string{application.GroupKey}, msp.AdminsPolicyKey),
   173  		)
   174  
   175  		// We create a genesis block for the test
   176  		// chain with its MSP so that we can transact
   177  		block, err := genesis.NewFactoryImpl(
   178  			configtx.NewCompositeTemplate(
   179  				test.ApplicationOrgTemplate(),
   180  				policyTemplate)).Block(chainID)
   181  		if nil != err {
   182  			panic(fmt.Sprintf("Unable to create genesis block for [%s] due to [%s]", chainID, err))
   183  		}
   184  
   185  		//this creates testchainid and sets up gossip
   186  		if err = peer.CreateChainFromBlock(block); err == nil {
   187  			fmt.Printf("create chain [%s]", chainID)
   188  			scc.DeploySysCCs(chainID)
   189  			logger.Infof("Deployed system chaincodes on %s", chainID)
   190  		} else {
   191  			fmt.Printf("create default chain [%s] failed with %s", chainID, err)
   192  		}
   193  	}
   194  
   195  	//this brings up all the chains (including testchainid)
   196  	peer.Initialize(func(cid string) {
   197  		logger.Debugf("Deploying system CC, for chain <%s>", cid)
   198  		scc.DeploySysCCs(cid)
   199  	})
   200  
   201  	logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]",
   202  		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)
   203  
   204  	// Start the grpc server. Done in a goroutine so we can deploy the
   205  	// genesis block if needed.
   206  	serve := make(chan error)
   207  
   208  	sigs := make(chan os.Signal, 1)
   209  	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
   210  	go func() {
   211  		sig := <-sigs
   212  		fmt.Println()
   213  		fmt.Println(sig)
   214  		serve <- nil
   215  	}()
   216  
   217  	go func() {
   218  		var grpcErr error
   219  		if grpcErr = grpcServer.Start(); grpcErr != nil {
   220  			grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
   221  		} else {
   222  			logger.Info("grpc server exited")
   223  		}
   224  		serve <- grpcErr
   225  	}()
   226  
   227  	if err := writePid(viper.GetString("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil {
   228  		return err
   229  	}
   230  
   231  	// Start the event hub server
   232  	if ehubGrpcServer != nil {
   233  		go ehubGrpcServer.Start()
   234  	}
   235  
   236  	// Start profiling http endpoint if enabled
   237  	if viper.GetBool("peer.profile.enabled") {
   238  		go func() {
   239  			profileListenAddress := viper.GetString("peer.profile.listenAddress")
   240  			logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress)
   241  			if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil {
   242  				logger.Errorf("Error starting profiler: %s", profileErr)
   243  			}
   244  		}()
   245  	}
   246  
   247  	logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]",
   248  		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)
   249  
   250  	// sets the logging level for the 'error' and 'msp' modules to the
   251  	// values from core.yaml. they can also be updated dynamically using
   252  	// "peer logging setlevel <module-name> <log-level>"
   253  	common.SetLogLevelFromViper("error")
   254  	common.SetLogLevelFromViper("msp")
   255  
   256  	// Block until grpc server exits
   257  	return <-serve
   258  }
   259  
   260  //NOTE - when we implment JOIN we will no longer pass the chainID as param
   261  //The chaincode support will come up without registering system chaincodes
   262  //which will be registered only during join phase.
   263  func registerChaincodeSupport(grpcServer *grpc.Server) {
   264  	//get user mode
   265  	userRunsCC := chaincode.IsDevMode()
   266  
   267  	//get chaincode startup timeout
   268  	tOut, err := strconv.Atoi(viper.GetString("chaincode.startuptimeout"))
   269  	if err != nil { //what went wrong ?
   270  		fmt.Printf("could not retrive timeout var...setting to 5secs\n")
   271  		tOut = 5000
   272  	}
   273  	ccStartupTimeout := time.Duration(tOut) * time.Millisecond
   274  
   275  	ccSrv := chaincode.NewChaincodeSupport(peer.GetPeerEndpoint, userRunsCC, ccStartupTimeout)
   276  
   277  	//Now that chaincode is initialized, register all system chaincodes.
   278  	scc.RegisterSysCCs()
   279  
   280  	pb.RegisterChaincodeSupportServer(grpcServer, ccSrv)
   281  }
   282  
   283  func createEventHubServer(secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
   284  	var lis net.Listener
   285  	var err error
   286  	lis, err = net.Listen("tcp", viper.GetString("peer.events.address"))
   287  	if err != nil {
   288  		return nil, fmt.Errorf("failed to listen: %v", err)
   289  	}
   290  
   291  	grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig)
   292  	if err != nil {
   293  		fmt.Println("Failed to return new GRPC server: ", err)
   294  		return nil, err
   295  	}
   296  	ehServer := producer.NewEventsServer(
   297  		uint(viper.GetInt("peer.events.buffersize")),
   298  		viper.GetInt("peer.events.timeout"))
   299  
   300  	pb.RegisterEventsServer(grpcServer.Server(), ehServer)
   301  	return grpcServer, nil
   302  }
   303  
   304  func writePid(fileName string, pid int) error {
   305  	err := os.MkdirAll(filepath.Dir(fileName), 0755)
   306  	if err != nil {
   307  		return err
   308  	}
   309  
   310  	fd, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0644)
   311  	if err != nil {
   312  		return err
   313  	}
   314  	defer fd.Close()
   315  	if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
   316  		return fmt.Errorf("can't lock '%s', lock is held", fd.Name())
   317  	}
   318  
   319  	if _, err := fd.Seek(0, 0); err != nil {
   320  		return err
   321  	}
   322  
   323  	if err := fd.Truncate(0); err != nil {
   324  		return err
   325  	}
   326  
   327  	if _, err := fmt.Fprintf(fd, "%d", pid); err != nil {
   328  		return err
   329  	}
   330  
   331  	if err := fd.Sync(); err != nil {
   332  		return err
   333  	}
   334  
   335  	if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_UN); err != nil {
   336  		return fmt.Errorf("can't release lock '%s', lock is held", fd.Name())
   337  	}
   338  	return nil
   339  }