diff options
Diffstat (limited to 'pkg/systemdgen/systemdgen.go')
-rw-r--r-- | pkg/systemdgen/systemdgen.go | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemdgen/systemdgen.go deleted file mode 100644 index 26b3b3756..000000000 --- a/pkg/systemdgen/systemdgen.go +++ /dev/null @@ -1,206 +0,0 @@ -package systemdgen - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - "text/template" - "time" - - "github.com/containers/libpod/version" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// ContainerInfo contains data required for generating a container's systemd -// unit file. -type ContainerInfo struct { - // ServiceName of the systemd service. - ServiceName string - // Name or ID of the container. - ContainerName string - // InfraContainer of the pod. - InfraContainer string - // StopTimeout sets the timeout Podman waits before killing the container - // during service stop. - StopTimeout int - // RestartPolicy of the systemd unit (e.g., no, on-failure, always). - RestartPolicy string - // PIDFile of the service. Required for forking services. Must point to the - // PID of the associated conmon process. - PIDFile string - // GenerateTimestamp, if set the generated unit file has a time stamp. - GenerateTimestamp bool - // BoundToServices are the services this service binds to. Note that this - // service runs after them. - BoundToServices []string - // RequiredServices are services this service requires. Note that this - // service runs before them. - RequiredServices []string - // PodmanVersion for the header. Will be set internally. Will be auto-filled - // if left empty. - PodmanVersion string - // Executable is the path to the podman executable. Will be auto-filled if - // left empty. - Executable string - // TimeStamp at the time of creating the unit file. Will be set internally. - TimeStamp string - // New controls if a new container is created or if an existing one is started. - New bool - // CreateCommand is the full command plus arguments of the process the - // container has been created with. - CreateCommand []string - // RunCommand is a post-processed variant of CreateCommand and used for - // the ExecStart field in generic unit files. - RunCommand string -} - -var restartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"} - -// validateRestartPolicy checks that the user-provided policy is valid. -func validateRestartPolicy(restart string) error { - for _, i := range restartPolicies { - if i == restart { - return nil - } - } - return errors.Errorf("%s is not a valid restart policy", restart) -} - -const containerTemplate = `# {{.ServiceName}}.service -# autogenerated by Podman {{.PodmanVersion}} -{{- if .TimeStamp}} -# {{.TimeStamp}} -{{- end}} - -[Unit] -Description=Podman {{.ServiceName}}.service -Documentation=man:podman-generate-systemd(1) -{{- if .BoundToServices}} -RefuseManualStart=yes -RefuseManualStop=yes -BindsTo={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}} -After={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}} -{{- end}} -{{- if .RequiredServices}} -Requires={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}} -Before={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}} -{{- end}} - -[Service] -Restart={{.RestartPolicy}} -{{- if .New}} -ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid -ExecStart={{.RunCommand}} -ExecStop={{.Executable}} stop --ignore --cidfile /%t/%n-cid {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} -ExecStopPost={{.Executable}} rm --ignore -f --cidfile /%t/%n-cid -PIDFile=/%t/%n-pid -{{- else}} -ExecStart={{.Executable}} start {{.ContainerName}} -ExecStop={{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.ContainerName}} -PIDFile={{.PIDFile}} -{{- end}} -KillMode=none -Type=forking - -[Install] -WantedBy=multi-user.target` - -// Options include different options to control the unit file generation. -type Options struct { - // When set, generate service files in the current working directory and - // return the paths to these files instead of returning all contents in one - // big string. - Files bool - // New controls if a new container is created or if an existing one is started. - New bool -} - -// CreateContainerSystemdUnit creates a systemd unit file for a container. -func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, error) { - if err := validateRestartPolicy(info.RestartPolicy); err != nil { - return "", err - } - - // Make sure the executable is set. - if info.Executable == "" { - executable, err := os.Executable() - if err != nil { - executable = "/usr/bin/podman" - logrus.Warnf("Could not obtain podman executable location, using default %s", executable) - } - info.Executable = executable - } - - // Assemble the ExecStart command when creating a new container. - // - // Note that we cannot catch all corner cases here such that users - // *must* manually check the generated files. A container might have - // been created via a Python script, which would certainly yield an - // invalid `info.CreateCommand`. Hence, we're doing a best effort unit - // generation and don't try aiming at completeness. - if opts.New { - // The create command must at least have three arguments: - // /usr/bin/podman run $IMAGE - index := 2 - if info.CreateCommand[1] == "container" { - index = 3 - } - if len(info.CreateCommand) < index+1 { - return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand) - } - // We're hard-coding the first five arguments and append the - // CreateCommand with a stripped command and subcomand. - command := []string{ - info.Executable, - "run", - "--conmon-pidfile", "/%t/%n-pid", - "--cidfile", "/%t/%n-cid", - "--cgroups=no-conmon", - } - command = append(command, info.CreateCommand[index:]...) - info.RunCommand = strings.Join(command, " ") - info.New = true - } - - if info.PodmanVersion == "" { - info.PodmanVersion = version.Version - } - if info.GenerateTimestamp { - info.TimeStamp = fmt.Sprintf("%v", time.Now().Format(time.UnixDate)) - } - - // Sort the slices to assure a deterministic output. - sort.Strings(info.RequiredServices) - sort.Strings(info.BoundToServices) - - // Generate the template and compile it. - templ, err := template.New("systemd_service_file").Parse(containerTemplate) - if err != nil { - return "", errors.Wrap(err, "error parsing systemd service template") - } - - var buf bytes.Buffer - if err := templ.Execute(&buf, info); err != nil { - return "", err - } - - if !opts.Files { - return buf.String(), nil - } - - buf.WriteByte('\n') - cwd, err := os.Getwd() - if err != nil { - return "", errors.Wrap(err, "error getting current working directory") - } - path := filepath.Join(cwd, fmt.Sprintf("%s.service", info.ServiceName)) - if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil { - return "", errors.Wrap(err, "error generating systemd unit") - } - return path, nil -} |