Ejemplo n.º 1
0
func (p *XPod) doStopPod(graceful int) error {
	var err error

	p.statusLock.Lock()
	if p.status != S_POD_RUNNING && p.status != S_POD_STARTING {
		err = fmt.Errorf("only alived pod could be stopped, current %d", p.status)
	} else {
		p.status = S_POD_STOPPING
	}
	p.statusLock.Unlock()
	if err != nil {
		p.Log(ERROR, err)
		return err
	}

	var errChan = make(chan error, 1)

	p.Log(INFO, "going to stop pod")
	go func(sb *hypervisor.Vm) {
		//lock all resource action of the pod, but don't block list/read query
		p.resourceLock.Lock()
		defer p.resourceLock.Unlock()

		//whatever the result of stop container, go on shutdown vm
		p.stopAllContainers(graceful)

		p.Log(INFO, "all container killed (or failed), now shutdown sandbox")
		result := sb.Shutdown()
		if result.IsSuccess() {
			p.Log(INFO, "pod is stopped")
			errChan <- nil
			return
		}

		err := fmt.Errorf("failed to shuting down: %s", result.Message())
		p.Log(ERROR, err)
		errChan <- err
	}(p.sandbox)

	select {
	case err = <-errChan:
		if err != nil {
			p.Log(WARNING, "force quit sandbox due to %v", err)
			p.ForceQuit()
		}
	case <-utils.Timeout(graceful):
		p.Log(WARNING, "force quit sandbox due to timeout")
		p.ForceQuit()
	}

	return nil
}
Ejemplo n.º 2
0
func (p *XPod) waitStopDone(timeout int, comments string) bool {
	select {
	case s, ok := <-p.stoppedChan:
		if ok {
			p.Log(DEBUG, "got stop msg and push it again: %s", comments)
			select {
			case p.stoppedChan <- s:
			default:
			}
		}
		p.Log(DEBUG, "wait stop done: %s", comments)
		return true
	case <-utils.Timeout(timeout):
		p.Log(DEBUG, "wait stop timeout: %s", comments)
		return false
	}
}
Ejemplo n.º 3
0
func (p *XPod) stopContainers(cList []string, cMap map[string]bool, graceful int) (error, map[string]error) {
	type containerException struct {
		id  string
		err error
	}

	p.Log(INFO, "begin stop containers %s", cList)
	resChan := p.sandbox.WaitProcess(true, cList, graceful)
	errChan := make(chan *containerException, 1)

	for _, cid := range cList {
		c, ok := p.containers[cid]
		if !ok {
			p.Log(WARNING, "no container %s to be stopped", cid)
			delete(cMap, cid)
			continue
		}
		if !c.IsRunning() {
			c.Log(DEBUG, "container state %v is not running(3), ignore during stop", c.CurrentState())
			delete(cMap, cid)
			continue
		}
		go func(c *Container) {
			c.Log(DEBUG, "now, stop container")
			err := c.terminate()
			if err != nil {
				errChan <- &containerException{
					id:  c.Id(),
					err: err,
				}
			}
		}(c)
	}

	if len(cMap) > 0 && resChan == nil {
		err := fmt.Errorf("cannot wait containers %v", cList)
		p.Log(ERROR, err)
		return err, nil
	}

	timeout := utils.Timeout(graceful)
	errMap := map[string]error{}

	for len(cMap) > 0 {
		select {
		case ex, ok := <-resChan:
			if !ok {
				err := fmt.Errorf("chan broken while waiting containers: %#v", cMap)
				p.Log(WARNING, err)
				break //break the select
			}
			p.Log(DEBUG, "container %s stopped (%v)", ex.Id, ex.Code)
			if _, exist := errMap[ex.Id]; exist { //if it exited, ignore the exceptions
				delete(errMap, ex.Id)
			}
			delete(cMap, ex.Id)
		case ex := <-errChan:
			if cMap[ex.id] { //if not waited (maybe already exit, ignore the exception)
				p.Log(WARNING, "fail during killing container %s: %v", ex.id, ex.err)
				errMap[ex.id] = ex.err
				delete(cMap, ex.id)
			}
		case <-timeout:
			err := fmt.Errorf("timeout while waiting containers: %#v of [%v]", cMap, cList)
			p.Log(ERROR, err)
			return err, errMap
		}
	}

	p.Log(INFO, "complete stop containers %s", cList)
	return nil, errMap
}