func (chaincodeSupport *ChaincodeSupport) stopChaincode(context context.Context, cID *pb.ChaincodeID) error {
	chaincode := cID.Name
	if chaincode == "" {
		return fmt.Errorf("chaincode name not set")
	}

	vmname := container.GetVMFromName(chaincode)

	//stop the chaincode
	sir := container.StopImageReq{ID: vmname, Timeout: 0}

	_, err := container.VMCProcess(context, "Docker", sir)
	if err != nil {
		err = fmt.Errorf("Error stopping container: %s", err)
		//but proceed to cleanup
	}

	chaincodeSupport.handlerMap.Lock()
	if _, ok := chaincodeSupport.chaincodeHasBeenLaunched(chaincode); !ok {
		//nothing to do
		chaincodeSupport.handlerMap.Unlock()
		return nil
	}

	delete(chaincodeSupport.handlerMap.chaincodeMap, chaincode)

	chaincodeSupport.handlerMap.Unlock()

	return err
}
// DeployChaincode deploys the chaincode if not in development mode where user is running the chaincode.
func (chaincodeSupport *ChaincodeSupport) DeployChaincode(context context.Context, t *pb.Transaction) (*pb.ChaincodeDeploymentSpec, error) {
	if chaincodeSupport.userRunsCC {
		chaincodeLog.Debug("user runs chaincode, not deploying chaincode")
		return nil, nil
	}

	//build the chaincode
	cds := &pb.ChaincodeDeploymentSpec{}
	err := proto.Unmarshal(t.Payload, cds)
	if err != nil {
		return nil, err
	}
	cID := cds.ChaincodeSpec.ChaincodeID
	chaincode := cID.Name
	if err != nil {
		return cds, err
	}
	chaincodeSupport.handlerMap.Lock()
	//if its in the map, there must be a connected stream...and we are trying to build the code ?!
	if _, ok := chaincodeSupport.chaincodeHasBeenLaunched(chaincode); ok {
		chaincodeLog.Debug("deploy ?!! there's a chaincode with that name running: %s", chaincode)
		chaincodeSupport.handlerMap.Unlock()
		return cds, fmt.Errorf("deploy attempted but a chaincode with same name running %s", chaincode)
	}
	chaincodeSupport.handlerMap.Unlock()

	//openchain.yaml in the container likely will not have the right url:version. We know the right
	//values, lets construct and pass as envs
	var targz io.Reader = bytes.NewBuffer(cds.CodePackage)
	envs := []string{"OPENCHAIN_CHAINCODE_ID_NAME=" + chaincode, "OPENCHAIN_PEER_ADDRESS=" + chaincodeSupport.peerAddress}
	toks := strings.Split(cID.Path, "/")
	if toks == nil {
		return cds, fmt.Errorf("cannot get path components from %s", chaincode)
	}

	//TODO : chaincode executable will be same as the name of the last folder (golang thing...)
	//       need to revisit executable name assignment
	//e.g, for path (http(s)://)github.com/openblockchain/obc-peer/openchain/example/chaincode/chaincode_example01
	//     exec is "chaincode_example01"
	exec := []string{chaincodeSupport.chaincodeInstallPath + toks[len(toks)-1]}
	chaincodeLog.Debug("Executable is %s", exec[0])

	vmname := container.GetVMFromName(chaincode)

	cir := &container.CreateImageReq{ID: vmname, Args: exec, Reader: targz, Env: envs}

	chaincodeLog.Debug("deploying chaincode %s", vmname)
	//create image and create container
	_, err = container.VMCProcess(context, "Docker", cir)
	if err != nil {
		err = fmt.Errorf("Error starting container: %s", err)
	}

	return cds, err
}
// launchAndWaitForRegister will launch container if not already running
func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(context context.Context, cID *pb.ChaincodeID, uuid string) (bool, error) {
	chaincode := cID.Name
	if chaincode == "" {
		return false, fmt.Errorf("chaincode name not set")
	}

	chaincodeSupport.handlerMap.Lock()
	var ok bool
	//if its in the map, there must be a connected stream...nothing to do
	if _, ok = chaincodeSupport.chaincodeHasBeenLaunched(chaincode); ok {
		chaincodeLog.Debug("chaincode is running and ready: %s", chaincode)
		chaincodeSupport.handlerMap.Unlock()
		return true, nil
	}
	alreadyRunning := false
	notfy := chaincodeSupport.preLaunchSetup(chaincode)
	chaincodeSupport.handlerMap.Unlock()

	//launch the chaincode
	//creat a StartImageReq obj and send it to VMCProcess
	vmname := container.GetVMFromName(chaincode)
	chaincodeLog.Debug("start container: %s", vmname)
	sir := container.StartImageReq{ID: vmname, Detach: true}
	resp, err := container.VMCProcess(context, "Docker", sir)
	if err != nil || (resp != nil && resp.(container.VMCResp).Err != nil) {
		if err == nil {
			err = resp.(container.VMCResp).Err
		}
		err = fmt.Errorf("Error starting container: %s", err)
		chaincodeSupport.handlerMap.Lock()
		delete(chaincodeSupport.handlerMap.chaincodeMap, chaincode)
		chaincodeSupport.handlerMap.Unlock()
		return alreadyRunning, err
	}

	//wait for REGISTER state
	select {
	case ok := <-notfy:
		if !ok {
			err = fmt.Errorf("registration failed for %s(tx:%s)", vmname, uuid)
		}
	case <-time.After(chaincodeSupport.ccStartupTimeout):
		err = fmt.Errorf("Timeout expired while starting chaincode %s(tx:%s)", vmname, uuid)
	}
	if err != nil {
		chaincodeLog.Debug("stopping due to error while launching %s", err)
		errIgnore := chaincodeSupport.stopChaincode(context, cID)
		if errIgnore != nil {
			chaincodeLog.Debug("error on stop %s(%s)", errIgnore, err)
		}
	}
	return alreadyRunning, err
}
Example #4
0
// DeployChaincode deploys the chaincode if not in development mode where user is running the chaincode.
func (chaincodeSupport *ChaincodeSupport) DeployChaincode(context context.Context, t *pb.Transaction) (*pb.ChaincodeDeploymentSpec, error) {
	if chaincodeSupport.userRunsCC {
		chaincodeLog.Debug("user runs chaincode, not deploying chaincode")
		return nil, nil
	}

	//build the chaincode
	cds := &pb.ChaincodeDeploymentSpec{}
	err := proto.Unmarshal(t.Payload, cds)
	if err != nil {
		return nil, err
	}
	cID := cds.ChaincodeSpec.ChaincodeID
	chaincode := cID.Name
	if err != nil {
		return cds, err
	}
	chaincodeSupport.handlerMap.Lock()
	//if its in the map, there must be a connected stream...and we are trying to build the code ?!
	if _, ok := chaincodeSupport.chaincodeHasBeenLaunched(chaincode); ok {
		chaincodeLog.Debug("deploy ?!! there's a chaincode with that name running: %s", chaincode)
		chaincodeSupport.handlerMap.Unlock()
		return cds, fmt.Errorf("deploy attempted but a chaincode with same name running %s", chaincode)
	}
	chaincodeSupport.handlerMap.Unlock()

	args, envs, err := chaincodeSupport.getArgsAndEnv(cID)
	if err != nil {
		return cds, fmt.Errorf("error getting args for chaincode %s", err)
	}

	vmname := container.GetVMFromName(chaincode)
	var targz io.Reader = bytes.NewBuffer(cds.CodePackage)
	cir := &container.CreateImageReq{ID: vmname, Args: args, Reader: targz, Env: envs}

	chaincodeLog.Debug("deploying chaincode %s", vmname)
	//create image and create container
	_, err = container.VMCProcess(context, "Docker", cir)
	if err != nil {
		err = fmt.Errorf("Error starting container: %s", err)
	}

	return cds, err
}