func (instance *LeverInstance) termContainer(kill bool) error { var sig dockerapi.Signal if kill { sig = dockerapi.SIGKILL } else { sig = dockerapi.SIGTERM } err := instance.docker.KillContainer( dockerapi.KillContainerOptions{ ID: instance.containerID, Signal: sig, }) if err != nil { return err } exited := make(chan struct{}) go func() { instance.docker.WaitContainer(instance.containerID) err := dockerutil.RemoveDockerContainer( instance.docker, instance.containerID) if err != nil { instance.logger.WithFields( "err", err, "containerID", instance.containerID, ).Error("Error trying to remove container after it exited") } close(exited) }() if !kill { go func() { timer := time.NewTimer(10 * time.Second) select { case <-timer.C: instance.logger.Info( "Instance did not exit on term signal and had to be killed") instance.docker.KillContainer( dockerapi.KillContainerOptions{ ID: instance.containerID, Signal: dockerapi.SIGKILL, }) case <-exited: } }() } return nil }
// EnsureInfrastructureInitialized verifies that all the necessary // infrastructure is registered, managed and ready to be used. func (manager *Manager) EnsureInfrastructureInitialized( info *InstanceInfo) ( envNetworkIP string, ownIP string, instanceAddr string, keepAlive KeepAliveFun, err error) { entry, err := manager.getEnvironment(info.Environment) if err != nil { return "", "", "", nil, err } defer entry.envLock.Unlock() instance, ok := entry.leverInstances[info.InstanceID] if ok { // Instance already managed. manager.logger.WithFields("leverInstanceID", info.InstanceID).Debug( "Instance already managed") keepAlive = func( resourceName, levResResourceID, levResSessionID string) { instance.KeepAlive(resourceName, levResResourceID, levResSessionID) } return entry.networkIP, entry.ownIP, instance.InstanceAddr(), keepAlive, nil } // Instance is new. manager.logger.WithFields("leverInstanceID", info.InstanceID).Debug( "Instance is new") if info.ContainerID == "" { // We don't have the container ID. Cannot initialize instance. return "", "", "", nil, fmt.Errorf("Need container ID") } // Connect the container to the env network bridge so we can talk to it // (forward RPCs). instanceIPv4, err := dockerutil.ConnectToDockerEnvNetwork( manager.docker, info.ContainerID, entry.networkID) if err != nil { manager.logger.WithFields( "err", err, "leverEnv", info.Environment, "containerID", info.ContainerID, ).Error("Error connecting instance to env network") removeErr := dockerutil.RemoveDockerContainer( manager.docker, info.ContainerID) if removeErr != nil { manager.logger.WithFields( "containerID", info.ContainerID, "err", removeErr, ).Error("Error trying to remove container after previous error") } return "", "", "", nil, err } instanceAddr = instanceIPv4 + ":" + core.InstanceListenPortFlag.Get() leverURL := &core.LeverURL{ Environment: info.Environment, Service: info.Service, } if core.IsAdmin(leverURL) { // Admin environment. Also connect it to the regional network. _, err := dockerutil.ConnectToDockerEnvNetwork( manager.docker, info.ContainerID, RegionalNetworkFlag.Get()) if err != nil { manager.logger.WithFields( "err", err, "leverEnv", info.Environment, "containerID", info.ContainerID, ).Error("Error connecting admin instance to regional network") removeErr := dockerutil.RemoveDockerContainer( manager.docker, info.ContainerID) if removeErr != nil { manager.logger.WithFields( "containerID", info.ContainerID, "err", removeErr, ).Error( "Error trying to remove container after previous error") } return "", "", "", nil, err } } // Add the instance ID to the local serving ID map. manager.servingIDsLock.Lock() _, ok = manager.servingIDs[info.ServingID] if !ok { manager.servingIDs[info.ServingID] = make(map[string]struct{}) } manager.servingIDs[info.ServingID][info.InstanceID] = struct{}{} manager.servingIDsLock.Unlock() // Start managing instance. instance = NewLeverInstance( info, instanceAddr, manager.proxyInAddr, manager.grpcPool, manager.docker, func(instanceID string, err error) { manager.logger.WithFields("leverInstanceID", instanceID).Debug( "Instance closed") manager.onInstanceClose( entry, info.Environment, instanceID, info.ServingID, err) }) entry.leverInstances[info.InstanceID] = instance keepAlive = func(resourceName, levResResourceID, levResSessionID string) { instance.KeepAlive(resourceName, levResResourceID, levResSessionID) } return entry.networkIP, entry.ownIP, instanceAddr, keepAlive, nil }