list.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // +build linux
  2. package runc
  3. import (
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "text/tabwriter"
  9. "time"
  10. "encoding/json"
  11. "github.com/codegangsta/cli"
  12. "github.com/opencontainers/runc/libcontainer/utils"
  13. )
  14. const formatOptions = `table or json`
  15. // containerState represents the platform agnostic pieces relating to a
  16. // running container's status and state
  17. type containerState struct {
  18. // ID is the container ID
  19. ID string `json:"id"`
  20. // InitProcessPid is the init process id in the parent namespace
  21. InitProcessPid int `json:"pid"`
  22. // Status is the current status of the container, running, paused, ...
  23. Status string `json:"status"`
  24. // Bundle is the path on the filesystem to the bundle
  25. Bundle string `json:"bundle"`
  26. // Created is the unix timestamp for the creation time of the container in UTC
  27. Created time.Time `json:"created"`
  28. }
  29. var listCommand = cli.Command{
  30. Name: "list",
  31. Usage: "lists containers started by runc with the given root",
  32. Flags: []cli.Flag{
  33. cli.StringFlag{
  34. Name: "format, f",
  35. Value: "",
  36. Usage: `select one of: ` + formatOptions + `.
  37. The default format is table. The following will output the list of containers
  38. in json format:
  39. # runc list -f json`,
  40. },
  41. },
  42. Action: func(context *cli.Context) {
  43. s, err := getContainers(context)
  44. if err != nil {
  45. fatal(err)
  46. }
  47. switch context.String("format") {
  48. case "", "table":
  49. w := tabwriter.NewWriter(os.Stdout, 12, 1, 3, ' ', 0)
  50. fmt.Fprint(w, "ID\tPID\tSTATUS\tBUNDLE\tCREATED\n")
  51. for _, item := range s {
  52. fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\n",
  53. item.ID,
  54. item.InitProcessPid,
  55. item.Status,
  56. item.Bundle,
  57. item.Created.Format(time.RFC3339Nano))
  58. }
  59. if err := w.Flush(); err != nil {
  60. fatal(err)
  61. }
  62. case "json":
  63. data, err := json.Marshal(s)
  64. if err != nil {
  65. fatal(err)
  66. }
  67. os.Stdout.Write(data)
  68. default:
  69. fatalf("invalid format option")
  70. }
  71. },
  72. }
  73. func getContainers(context *cli.Context) ([]containerState, error) {
  74. factory, err := loadFactory(context)
  75. if err != nil {
  76. return nil, err
  77. }
  78. root := context.GlobalString("root")
  79. absRoot, err := filepath.Abs(root)
  80. if err != nil {
  81. return nil, err
  82. }
  83. list, err := ioutil.ReadDir(absRoot)
  84. if err != nil {
  85. fatal(err)
  86. }
  87. var s []containerState
  88. for _, item := range list {
  89. if item.IsDir() {
  90. container, err := factory.Load(item.Name())
  91. if err != nil {
  92. return nil, err
  93. }
  94. containerStatus, err := container.Status()
  95. if err != nil {
  96. return nil, err
  97. }
  98. state, err := container.State()
  99. if err != nil {
  100. return nil, err
  101. }
  102. s = append(s, containerState{
  103. ID: state.BaseState.ID,
  104. InitProcessPid: state.BaseState.InitProcessPid,
  105. Status: containerStatus.String(),
  106. Bundle: utils.SearchLabels(state.Config.Labels, "bundle"),
  107. Created: state.BaseState.Created})
  108. }
  109. }
  110. return s, nil
  111. }