Example #1
0
func (j *StartedContainerStateRequest) Execute(resp jobs.Response) {
	unitName := j.Id.UnitNameFor()
	unitPath := j.Id.UnitPathFor()

	inState, tooSoon := inStateOrTooSoon(j.Id, unitName, true, false, rateLimitChanges)
	if inState {
		w := resp.SuccessWithWrite(jobs.ResponseAccepted, true, false)
		fmt.Fprintf(w, "Container %s starting\n", j.Id)
		return
	}
	if tooSoon {
		resp.Failure(ErrStartRequestThrottled)
		return
	}

	if errs := csystemd.SetUnitStartOnBoot(j.Id, true); errs != nil {
		log.Print("alter_container_state: Unable to persist whether the unit is started on boot: ", errs)
		resp.Failure(ErrContainerStartFailed)
		return
	}

	if err := systemd.EnableAndReloadUnit(systemd.Connection(), unitName, unitPath); err != nil {
		if systemd.IsNoSuchUnit(err) || systemd.IsFileNotFound(err) {
			resp.Failure(ErrContainerNotFound)
			return
		}
		log.Printf("alter_container_state: Could not enable container %s: %v", unitName, err)
		resp.Failure(ErrContainerStartFailed)
		return
	}

	if err := systemd.Connection().StartUnitJob(unitName, "replace"); err != nil {
		log.Printf("alter_container_state: Could not start container %s: %v", unitName, err)
		resp.Failure(ErrContainerStartFailed)
		return
	}

	w := resp.SuccessWithWrite(jobs.ResponseAccepted, true, false)
	fmt.Fprintf(w, "Container %s starting\n", j.Id)
}
Example #2
0
func (j *StoppedContainerStateRequest) Execute(resp jobs.Response) {
	unitName := j.Id.UnitNameFor()

	inState, tooSoon := inStateOrTooSoon(j.Id, unitName, false, false, rateLimitChanges)
	if inState {
		w := resp.SuccessWithWrite(jobs.ResponseAccepted, true, false)
		fmt.Fprintf(w, "Container %s is stopped\n", j.Id)
		return
	}
	if tooSoon {
		resp.Failure(ErrStopRequestThrottled)
		return
	}

	if errs := csystemd.SetUnitStartOnBoot(j.Id, false); errs != nil {
		log.Print("alter_container_state: Unable to persist whether the unit is started on boot: ", errs)
		resp.Failure(ErrContainerStopFailed)
		return
	}

	w := resp.SuccessWithWrite(jobs.ResponseAccepted, true, false)

	done := make(chan time.Time)
	ioerr := make(chan error)
	go func() {
		ioerr <- systemd.WriteLogsTo(w, unitName, 0, done)
	}()

	joberr := make(chan error)
	go func() {
		status, err := systemd.Connection().StopUnit(unitName, "replace")
		if err == nil && status != "done" {
			err = errors.New(fmt.Sprintf("Job status 'done' != %s", status))
		}
		joberr <- err
	}()

	var err error
	select {
	case err = <-ioerr:
		log.Printf("alter_container_state: Client hung up")
		close(ioerr)
	case err = <-joberr:
		log.Printf("alter_container_state: Stop job done")
	case <-time.After(15 * time.Second):
		log.Printf("alter_container_state: Timeout waiting for stop completion")
	}
	close(done)

	select {
	case <-ioerr:
	}

	switch {
	case systemd.IsNoSuchUnit(err):
		if _, err := os.Stat(j.Id.UnitPathFor()); err == nil {
			fmt.Fprintf(w, "Container %s is stopped\n", j.Id)
		} else {
			fmt.Fprintf(w, "No such container %s\n", j.Id)
		}
	case err != nil:
		fmt.Fprintf(w, "Could not stop container: %s\n", err.Error())
	default:
		fmt.Fprintf(w, "Container %s is stopped\n", j.Id)
	}
}
Example #3
0
func (j *DeleteContainerRequest) Execute(resp JobResponse) {
	unitName := j.Id.UnitNameFor()
	unitPath := j.Id.UnitPathFor()
	unitDefinitionsPath := j.Id.VersionedUnitsPathFor()
	idleFlagPath := j.Id.IdleUnitPathFor()
	socketUnitPath := j.Id.SocketUnitPathFor()
	homeDirPath := j.Id.BaseHomePath()
	networkLinksPath := j.Id.NetworkLinksPathFor()

	_, err := systemd.Connection().GetUnitProperties(unitName)
	switch {
	case systemd.IsNoSuchUnit(err):
		resp.Success(JobResponseOk)
		return
	case err != nil:
		resp.Failure(ErrDeleteContainerFailed)
		return
	}

	if err := systemd.Connection().StopUnitJob(unitName, "fail"); err != nil {
		log.Printf("delete_container: Unable to queue stop unit job: %v", err)
	}

	ports, err := containers.GetExistingPorts(j.Id)
	if err != nil {
		if !os.IsNotExist(err) {
			log.Printf("delete_container: Unable to read existing port definitions: %v", err)
		}
		ports = port.PortPairs{}
	}

	if err := port.ReleaseExternalPorts(ports); err != nil {
		log.Printf("delete_container: Unable to release ports: %v", err)
	}

	if err := os.Remove(unitPath); err != nil && !os.IsNotExist(err) {
		resp.Failure(ErrDeleteContainerFailed)
		return
	}

	if err := os.Remove(idleFlagPath); err != nil && !os.IsNotExist(err) {
		resp.Failure(ErrDeleteContainerFailed)
		return
	}

	if err := j.Id.SetUnitStartOnBoot(false); err != nil {
		log.Printf("delete_container: Unable to clear unit boot state: %v", err)
	}

	if err := os.Remove(socketUnitPath); err != nil && !os.IsNotExist(err) {
		log.Printf("delete_container: Unable to remove socket unit path: %v", err)
	}

	if err := os.Remove(networkLinksPath); err != nil && !os.IsNotExist(err) {
		log.Printf("delete_container: Unable to remove network links file: %v", err)
	}

	if err := os.RemoveAll(unitDefinitionsPath); err != nil {
		log.Printf("delete_container: Unable to remove definitions for container: %v", err)
	}

	if err := os.RemoveAll(filepath.Dir(homeDirPath)); err != nil {
		log.Printf("delete_container: Unable to remove home directory: %v", err)
	}

	if _, err := systemd.Connection().DisableUnitFiles([]string{unitPath, socketUnitPath}, false); err != nil {
		log.Printf("delete_container: Some units have not been disabled: %v", err)
	}

	if err := systemd.Connection().Reload(); err != nil {
		log.Printf("delete_container: Some units have not been disabled: %v", err)
	}

	resp.Success(JobResponseOk)
}