containers.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package compute
  15. import (
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. "os/exec"
  20. "strings"
  21. "github.com/ghodss/yaml"
  22. "yunion.io/x/jsonutils"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/onecloud/cmd/climc/shell"
  25. computeapi "yunion.io/x/onecloud/pkg/apis/compute"
  26. "yunion.io/x/onecloud/pkg/mcclient"
  27. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  28. options "yunion.io/x/onecloud/pkg/mcclient/options/compute"
  29. "yunion.io/x/onecloud/pkg/util/pod/stream/cp"
  30. )
  31. func init() {
  32. cmd := shell.NewResourceCmd(&modules.Containers)
  33. cmd.Create(new(options.ContainerCreateOptions))
  34. cmd.List(new(options.ContainerListOptions))
  35. cmd.Show(new(options.ContainerShowOptions))
  36. cmd.GetMetadata(new(options.ServerIdOptions))
  37. cmd.BatchDelete(new(options.ContainerDeleteOptions))
  38. cmd.BatchPerform("stop", new(options.ContainerStopOptions))
  39. cmd.BatchPerform("start", new(options.ContainerStartOptions))
  40. cmd.BatchPerform("restart", new(options.ContainerRestartOptions))
  41. cmd.BatchPerform("syncstatus", new(options.ContainerIdsOptions))
  42. cmd.Perform("save-volume-mount-image", new(options.ContainerSaveVolumeMountImage))
  43. cmd.Perform("exec-sync", new(options.ContainerExecSyncOptions))
  44. cmd.BatchPerform("set-resources-limit", new(options.ContainerSetResourcesLimitOptions))
  45. cmd.Perform("commit", new(options.ContainerCommitOptions))
  46. cmd.Perform("add-volume-mount-post-overlay", new(options.ContainerAddVolumeMountPostOverlayOptions))
  47. cmd.Perform("remove-volume-mount-post-overlay", new(options.ContainerRemoveVolumeMountPostOverlayOptions))
  48. type UpdateSpecOptions struct {
  49. ID string `help:"ID or name of server" json:"-"`
  50. }
  51. R(&UpdateSpecOptions{}, "container-update-spec", "Update spec of a container", func(s *mcclient.ClientSession, opts *UpdateSpecOptions) error {
  52. result, err := modules.Containers.Get(s, opts.ID, nil)
  53. if err != nil {
  54. return errors.Wrap(err, "get container id")
  55. }
  56. yamlBytes := result.YAMLString()
  57. tempfile, err := ioutil.TempFile("", fmt.Sprintf("container-%s*.yaml", opts.ID))
  58. if err != nil {
  59. return err
  60. }
  61. defer os.Remove(tempfile.Name())
  62. if _, err := tempfile.Write([]byte(yamlBytes)); err != nil {
  63. return err
  64. }
  65. if err := tempfile.Close(); err != nil {
  66. return err
  67. }
  68. cmd := exec.Command("vim", tempfile.Name())
  69. cmd.Stdin = os.Stdin
  70. cmd.Stdout = os.Stdout
  71. if err := cmd.Run(); err != nil {
  72. return err
  73. }
  74. content, err := ioutil.ReadFile(tempfile.Name())
  75. if err != nil {
  76. return err
  77. }
  78. jsonBytes, err := yaml.YAMLToJSON(content)
  79. if err != nil {
  80. return err
  81. }
  82. body, err := jsonutils.Parse(jsonBytes)
  83. if err != nil {
  84. return err
  85. }
  86. if _, err := modules.Containers.Update(s, opts.ID, body); err != nil {
  87. return errors.Wrap(err, "update spec")
  88. }
  89. return nil
  90. })
  91. type SetSpecOptions struct {
  92. ID string `help:"ID or name of server" json:"-"`
  93. EnableSimulateCpu bool `help:"Enable simulating /sys/devices/system/cpu directory"`
  94. }
  95. R(&SetSpecOptions{}, "container-set-spec", "Set spec of a container", func(s *mcclient.ClientSession, opts *SetSpecOptions) error {
  96. result, err := modules.Containers.Get(s, opts.ID, nil)
  97. if err != nil {
  98. return errors.Wrap(err, "get container id")
  99. }
  100. spec := new(computeapi.ContainerSpec)
  101. if err := result.Unmarshal(spec, "spec"); err != nil {
  102. return errors.Wrap(err, "unmarshal to spec")
  103. }
  104. spec.SimulateCpu = opts.EnableSimulateCpu
  105. result.(*jsonutils.JSONDict).Set("spec", jsonutils.Marshal(spec))
  106. if _, err := modules.Containers.Update(s, opts.ID, result); err != nil {
  107. return errors.Wrap(err, "update spec")
  108. }
  109. return nil
  110. })
  111. R(new(options.ContainerExecOptions), "container-exec", "Container exec", func(s *mcclient.ClientSession, opts *options.ContainerExecOptions) error {
  112. man := modules.Containers
  113. return man.Exec(s, opts.ID, opts.ToAPIInput())
  114. })
  115. R(new(options.ContainerLogOptions), "container-log", "Get container log", func(s *mcclient.ClientSession, opts *options.ContainerLogOptions) error {
  116. man := modules.Containers
  117. input, err := opts.ToAPIInput()
  118. if err != nil {
  119. return err
  120. }
  121. if err := man.LogToWriter(s, opts.ID, input, os.Stdout); err != nil {
  122. return errors.Wrap(err, "get container log")
  123. }
  124. return nil
  125. })
  126. R(new(options.ContainerCopyOptions), "container-cp", "Container copy", func(s *mcclient.ClientSession, opts *options.ContainerCopyOptions) error {
  127. parts := strings.Split(opts.CONTAINER_ID_FILE, ":")
  128. if len(parts) != 2 {
  129. return fmt.Errorf("invalid container id: %s", opts.CONTAINER_ID_FILE)
  130. }
  131. if opts.RawFile {
  132. fr, err := os.Open(opts.SRC_FILE)
  133. if err != nil {
  134. return errors.Wrapf(err, "open file: %v", opts.SRC_FILE)
  135. }
  136. defer fr.Close()
  137. if err := modules.Containers.CopyTo(s, parts[0], parts[1], fr); err != nil {
  138. return errors.Wrapf(err, "copy file to container")
  139. }
  140. return nil
  141. } else {
  142. return cp.NewCopy().CopyToContainer(s, opts.SRC_FILE, cp.ContainerFileOpt{
  143. ContainerId: parts[0],
  144. File: parts[1],
  145. })
  146. }
  147. })
  148. R(new(options.ContainerCopyOptions), "container-cp-from", "Container copy", func(s *mcclient.ClientSession, opts *options.ContainerCopyOptions) error {
  149. parts := strings.Split(opts.SRC_FILE, ":")
  150. if len(parts) != 2 {
  151. return fmt.Errorf("invalid container id: %s", opts.CONTAINER_ID_FILE)
  152. }
  153. ctrId := parts[0]
  154. ctrFile := parts[1]
  155. destFile := opts.CONTAINER_ID_FILE
  156. if opts.RawFile {
  157. fw, err := os.Create(destFile)
  158. if err != nil {
  159. return errors.Wrapf(err, "open file: %v", destFile)
  160. }
  161. defer fw.Close()
  162. if err := modules.Containers.CopyFrom(s, ctrId, ctrFile, fw); err != nil {
  163. return errors.Wrap(err, "copy from")
  164. }
  165. return nil
  166. } else {
  167. return cp.NewCopy().CopyFromContainer(s, cp.ContainerFileOpt{
  168. ContainerId: ctrId,
  169. File: ctrFile,
  170. }, destFile)
  171. }
  172. })
  173. }