Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
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
}