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) }
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) } }
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) }