rename.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package daemon // import "github.com/docker/docker/daemon"
  2. import (
  3. "context"
  4. "strings"
  5. "github.com/containerd/containerd/log"
  6. dockercontainer "github.com/docker/docker/container"
  7. "github.com/docker/docker/errdefs"
  8. "github.com/docker/docker/libnetwork"
  9. "github.com/pkg/errors"
  10. )
  11. // ContainerRename changes the name of a container, using the oldName
  12. // to find the container. An error is returned if newName is already
  13. // reserved.
  14. func (daemon *Daemon) ContainerRename(oldName, newName string) error {
  15. var (
  16. sid string
  17. sb *libnetwork.Sandbox
  18. )
  19. if oldName == "" || newName == "" {
  20. return errdefs.InvalidParameter(errors.New("Neither old nor new names may be empty"))
  21. }
  22. if newName[0] != '/' {
  23. newName = "/" + newName
  24. }
  25. container, err := daemon.GetContainer(oldName)
  26. if err != nil {
  27. return err
  28. }
  29. container.Lock()
  30. defer container.Unlock()
  31. oldName = container.Name
  32. oldIsAnonymousEndpoint := container.NetworkSettings.IsAnonymousEndpoint
  33. if oldName == newName {
  34. return errdefs.InvalidParameter(errors.New("Renaming a container with the same name as its current name"))
  35. }
  36. links := map[string]*dockercontainer.Container{}
  37. for k, v := range daemon.linkIndex.children(container) {
  38. if !strings.HasPrefix(k, oldName) {
  39. return errdefs.InvalidParameter(errors.Errorf("Linked container %s does not match parent %s", k, oldName))
  40. }
  41. links[strings.TrimPrefix(k, oldName)] = v
  42. }
  43. if newName, err = daemon.reserveName(container.ID, newName); err != nil {
  44. return errors.Wrap(err, "Error when allocating new name")
  45. }
  46. for k, v := range links {
  47. daemon.containersReplica.ReserveName(newName+k, v.ID)
  48. daemon.linkIndex.link(container, v, newName+k)
  49. }
  50. container.Name = newName
  51. container.NetworkSettings.IsAnonymousEndpoint = false
  52. defer func() {
  53. if err != nil {
  54. container.Name = oldName
  55. container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint
  56. daemon.reserveName(container.ID, oldName)
  57. for k, v := range links {
  58. daemon.containersReplica.ReserveName(oldName+k, v.ID)
  59. daemon.linkIndex.link(container, v, oldName+k)
  60. daemon.linkIndex.unlink(newName+k, v, container)
  61. daemon.containersReplica.ReleaseName(newName + k)
  62. }
  63. daemon.releaseName(newName)
  64. } else {
  65. daemon.releaseName(oldName)
  66. }
  67. }()
  68. for k, v := range links {
  69. daemon.linkIndex.unlink(oldName+k, v, container)
  70. daemon.containersReplica.ReleaseName(oldName + k)
  71. }
  72. if err = container.CheckpointTo(daemon.containersReplica); err != nil {
  73. return err
  74. }
  75. attributes := map[string]string{
  76. "oldName": oldName,
  77. }
  78. if !container.Running {
  79. daemon.LogContainerEventWithAttributes(container, "rename", attributes)
  80. return nil
  81. }
  82. defer func() {
  83. if err != nil {
  84. container.Name = oldName
  85. container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint
  86. if e := container.CheckpointTo(daemon.containersReplica); e != nil {
  87. log.G(context.TODO()).Errorf("%s: Failed in writing to Disk on rename failure: %v", container.ID, e)
  88. }
  89. }
  90. }()
  91. sid = container.NetworkSettings.SandboxID
  92. if sid != "" && daemon.netController != nil {
  93. sb, err = daemon.netController.SandboxByID(sid)
  94. if err != nil {
  95. return err
  96. }
  97. err = sb.Rename(strings.TrimPrefix(container.Name, "/"))
  98. if err != nil {
  99. return err
  100. }
  101. }
  102. daemon.LogContainerEventWithAttributes(container, "rename", attributes)
  103. return nil
  104. }