rename.go 3.1 KB

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