rename.go 3.3 KB

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