lxd/daemon.go
func (d *Daemon) Stop() error {
	logger.Info("Starting shutdown sequence")
	errs := []error{}
	trackError := func(err error) {
		if err != nil {
			errs = append(errs, err)
		}
	}

	if d.endpoints != nil {
		trackError(d.endpoints.Down())
	}

	trackError(d.tasks.Stop(3 * time.Second))        // Give tasks a bit of time to cleanup.
	trackError(d.clusterTasks.Stop(3 * time.Second)) // Give tasks a bit of time to cleanup.

	shouldUnmount := false
	if d.cluster != nil {
		// It might be that database nodes are all down, in that case
		// we don't want to wait too much.
		//
		// FIXME: it should be possible to provide a context or a
		//        timeout for database queries.
		ch := make(chan bool)
		go func() {
			n, err := d.numRunningContainers()
			ch <- err != nil || n == 0
		}()
		select {
		case shouldUnmount = <-ch:
		case <-time.After(2 * time.Second):
			shouldUnmount = true
		}

		logger.Infof("Closing the database")
		err := d.cluster.Close()
		// If we got io.EOF the network connection was interrupted and
		// it's likely that the other node shutdown. Let's just log the
		// event and return cleanly.
		if errors.Cause(err) == driver.ErrBadConn {
			logger.Debugf("Could not close remote database cleanly: %v", err)
		} else {
			trackError(err)
		}
	}
	if d.db != nil {
		trackError(d.db.Close())
	}

	if d.gateway != nil {
		trackError(d.gateway.Shutdown())
	}
	if d.endpoints != nil {
		trackError(d.endpoints.Down())
	}

	if d.endpoints != nil {
		trackError(d.endpoints.Down())
	}

	if shouldUnmount {
		logger.Infof("Unmounting temporary filesystems")

		syscall.Unmount(shared.VarPath("devlxd"), syscall.MNT_DETACH)
		syscall.Unmount(shared.VarPath("shmounts"), syscall.MNT_DETACH)

		logger.Infof("Done unmounting temporary filesystems")
	} else {
		logger.Debugf(
			"Not unmounting temporary filesystems (containers are still running)")
	}

	var err error
	if n := len(errs); n > 0 {
		format := "%v"
		if n > 1 {
			format += fmt.Sprintf(" (and %d more errors)", n)
		}
		err = fmt.Errorf(format, errs[0])
	}
	if err != nil {
		logger.Errorf("Failed to cleanly shutdown daemon: %v", err)
	}
	return err
}
func (d *Daemon) Stop() error {
	logger.Info("Starting shutdown sequence")
	errs := []error{}
	trackError := func(err error) {
		if err != nil {
			errs = append(errs, err)
		}
	}

	if d.endpoints != nil {
		trackError(d.endpoints.Down())
	}

	trackError(d.tasks.Stop(3 * time.Second))        // Give tasks a bit of time to cleanup.
	trackError(d.clusterTasks.Stop(3 * time.Second)) // Give tasks a bit of time to cleanup.

	shouldUnmount := false
	if d.cluster != nil {
		// It might be that database nodes are all down, in that case
		// we don't want to wait too much.
		//
		// FIXME: it should be possible to provide a context or a
		//        timeout for database queries.
		ch := make(chan bool)
		go func() {
			n, err := d.numRunningContainers()
			ch <- err != nil || n == 0
		}()
		select {
		case shouldUnmount = <-ch:
		case <-time.After(2 * time.Second):
			shouldUnmount = true
		}

		logger.Infof("Closing the database")
		err := d.cluster.Close()
		// If we got io.EOF the network connection was interrupted and
		// it's likely that the other node shutdown. Let's just log the
		// event and return cleanly.
		if errors.Cause(err) == driver.ErrBadConn {
			logger.Debugf("Could not close remote database cleanly: %v", err)
		} else {
			trackError(err)
		}
	}
	if d.db != nil {
		trackError(d.db.Close())
	}

	if d.gateway != nil {
		trackError(d.gateway.Shutdown())
	}
	if d.endpoints != nil {
		trackError(d.endpoints.Down())
	}

	if d.endpoints != nil {
		trackError(d.endpoints.Down())
	}

	if shouldUnmount {
		logger.Infof("Unmounting temporary filesystems")

		syscall.Unmount(shared.VarPath("devlxd"), syscall.MNT_DETACH)
		syscall.Unmount(shared.VarPath("shmounts"), syscall.MNT_DETACH)

		logger.Infof("Done unmounting temporary filesystems")
	} else {
		logger.Debugf(
			"Not unmounting temporary filesystems (containers are still running)")
	}

	var err error
	if n := len(errs); n > 0 {
		format := "%v"
		if n > 1 {
			format += fmt.Sprintf(" (and %d more errors)", n)
		}
		err = fmt.Errorf(format, errs[0])
	}
	if err != nil {
		logger.Errorf("Failed to cleanly shutdown daemon: %v", err)
	}
	return err
}
func ( d * Daemon ) Stop ( ) error { logger . Info ( " " ) errs := [ ] error { } trackError := func ( err error ) { if err != nil { errs = append ( errs , err ) } } if d . endpoints != nil { trackError ( d . endpoints . Down ( ) ) } trackError ( d . tasks . Stop ( 3 * time . Second ) ) // Give tasks a bit of time to cleanup. trackError ( d . clusterTasks . Stop ( 3 * time . Second ) ) // Give tasks a bit of time to cleanup. shouldUnmount := false if d . cluster != nil { // It might be that database nodes are all down, in that case // we don't want to wait too much. // // FIXME: it should be possible to provide a context or a //        timeout for database queries. ch := make ( chan bool ) go func ( ) { n , err := d . numRunningContainers ( ) ch <- err != nil || n == 0 } ( ) select { case shouldUnmount = <- ch : case <- time . After ( 2 * time . Second ) : shouldUnmount = true } logger . Infof ( " " ) err := d . cluster . Close ( ) // If we got io.EOF the network connection was interrupted and // it's likely that the other node shutdown. Let's just log the // event and return cleanly. if errors . Cause ( err ) == driver . ErrBadConn { logger . Debugf ( " " , err ) } else { trackError ( err ) } } if d . db != nil { trackError ( d . db . Close ( ) ) } if d . gateway != nil { trackError ( d . gateway . Shutdown ( ) ) } if d . endpoints != nil { trackError ( d . endpoints . Down ( ) ) } if d . endpoints != nil { trackError ( d . endpoints . Down ( ) ) } if shouldUnmount { logger . Infof ( " " ) syscall . Unmount ( shared . VarPath ( " " ) , syscall . MNT_DETACH ) syscall . Unmount ( shared . VarPath ( " " ) , syscall . MNT_DETACH ) logger . Infof ( " " ) } else { logger . Debugf ( " " ) } var err error if n := len ( errs ) ; n > 0 { format := " " if n > 1 { format += fmt . Sprintf ( " " , n ) } err = fmt . Errorf ( format , errs [ 0 ] ) } if err != nil { logger . Errorf ( " " , err ) } return err }
// Stop stops the shared daemon.
Stop stops the shared daemon .