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 }
// 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 }