func (finder *Finder) newInstance( env, service string, version int64) ( levInstTarget *LevInstTarget, targetNode string, levInstResource *scale.Resource, success bool, err error) { // Note: This process only takes place for the very first instance within // a service. The non-first instances do not have a resource entry // and they are found via service lookup through DNS. levInstResourceID := makeLevInstResourceID(env, service, version) levInstResource, success, err = scale.ConstructResource( leverutil.ServiceFlag.Get(), levInstResourceID, InstanceConstructTimeoutFlag.Get()) if err != nil { finder.logger.WithFields("err", err).Error( "Failed to construct new instance") return nil, "", nil, false, err } if !success { // Failed to get lock. Someone else constructed instance. levInstTarget = new(LevInstTarget) err = json.Unmarshal([]byte(levInstResource.GetTarget()), levInstTarget) if err != nil { finder.logger.WithFields("err", err).Panic("Failed to decode json") } finder.logger.WithFields( "leverEnv", env, "leverService", service, "leverInstanceID", levInstTarget.InstanceID, ).Debug("Reusing instance") return levInstTarget, levInstResource.GetTargetNode(), levInstResource, false, nil } // Read the entry point from the config. codeDir := dockerutil.CodeDirPath(env, service, version) leverConfig, err := core.ReadLeverConfig(codeDir) if err != nil { finder.logger.WithFields("err", err).Error( "Failed to read lever.json") return nil, "", nil, false, err } // TODO: If somehow first RPC fails and service no longer // contacted afterwards, then the container remains hanging // forever. Need a way to kill it / make it expire after a // while for this situation. // Idea: Poll docker every ~30s for instances that we are not // handling and register those. instanceID := leverutil.RandomID() // TODO: Collisions possible. leverURL := &core.LeverURL{ Environment: env, Service: service, } isAdmin := core.IsAdmin(leverURL) containerID, node, err := dockerutil.StartDockerContainer( finder.docker, env, service, instanceID, version, isAdmin, leverConfig) if err != nil { finder.logger.WithFields( "err", err, "leverEnv", env, "leverService", service, "leverInstanceID", instanceID, ).Error("Unable to start container") return nil, "", nil, false, err } hostAddr, err := GetHostAddrOnNode(node) if err != nil { finder.logger.WithFields("err", err).Error( "Failed to get Host addr on node") return nil, "", nil, false, err } finder.logger.WithFields( "leverEnv", env, "leverService", service, "leverInstanceID", instanceID, "containerID", containerID, "node", node, ).Debug("Creating new instance") levInstTarget = &LevInstTarget{ HostAddr: hostAddr, InstanceID: instanceID, ContainerID: containerID, } target, err := json.Marshal(levInstTarget) if err != nil { finder.logger.WithFields("err", err).Panic("Failed to encode json") } err = levInstResource.DoneConstructing( string(target), node, 2*hostman.InstanceExpiryTimeFlag.Get()) if err != nil { finder.logger.WithFields("err", err).Error( "Failed to register new instance") return nil, "", nil, false, err } return levInstTarget, node, levInstResource, true, nil }
func (finder *Finder) newResource( env, service, servingID, resource string, version int64) ( levResTarget *LevResTarget, levResResource *scale.Resource, isNewInstance bool, err error) { levResResourceID := makeLevResResourceID(env, service, resource, version) var success bool levResResource, success, err = scale.ConstructResource( leverutil.ServiceFlag.Get(), levResResourceID, ResourceConstructTimeoutFlag.Get()) if err != nil { finder.logger.WithFields("err", err).Error( "Failed to construct resource") return nil, nil, false, err } if !success { // Failed to get lock. Someone else constructed resource. levResTarget = new(LevResTarget) err = json.Unmarshal([]byte(levResResource.GetTarget()), levResTarget) if err != nil { finder.logger.WithFields("err", err).Panic("Failed to decode json") } finder.logger.WithFields( "leverEnv", env, "leverService", service, "leverResource", resource, "leverInstanceID", levResTarget.InstanceID, ).Debug("Reusing resource") return levResTarget, levResResource, false, nil } levInstTarget, targetNode, levInstResource, isNewInstance, err := finder.getInstance(env, service, servingID, version) if err != nil { return nil, nil, false, err } finder.logger.WithFields( "leverEnv", env, "leverService", service, "leverResource", resource, "leverInstanceID", levInstTarget.InstanceID, ).Debug("Registering new resource") var levInstSessionID string if levInstResource != nil { levInstSessionID = levInstResource.GetSessionID() } levResTarget = &LevResTarget{ HostAddr: levInstTarget.HostAddr, ContainerID: levInstTarget.ContainerID, InstanceID: levInstTarget.InstanceID, LevInstSessionID: levInstSessionID, } target, err := json.Marshal(levResTarget) if err != nil { finder.logger.WithFields("err", err).Panic("Failed to encode json") } err = levResResource.DoneConstructing( string(target), targetNode, 2*hostman.ResourceExpiryTimeFlag.Get()) if err != nil { finder.logger.WithFields("err", err).Error( "Could not register Lever resource") return nil, nil, false, err } return levResTarget, levResResource, isNewInstance, nil }