21a809d9 |
package daemon
|
c79b9bab |
import ( |
ca5ede2d |
"strings"
|
87a12421 |
"github.com/docker/docker/api/errdefs" |
3f6e3a08 |
dockercontainer "github.com/docker/docker/container" |
8e0bbb28 |
"github.com/docker/libnetwork" |
ebcb7d6b |
"github.com/pkg/errors" |
1009e6a4 |
"github.com/sirupsen/logrus" |
c79b9bab |
)
|
abd72d40 |
// ContainerRename changes the name of a container, using the oldName
// to find the container. An error is returned if newName is already
// reserved. |
b08f071e |
func (daemon *Daemon) ContainerRename(oldName, newName string) error { |
8e0bbb28 |
var ( |
6bb0d181 |
sid string
sb libnetwork.Sandbox |
8e0bbb28 |
)
|
49c4de4a |
if oldName == "" || newName == "" { |
87a12421 |
return errdefs.InvalidParameter(errors.New("Neither old nor new names may be empty")) |
21a809d9 |
}
|
3e8c16ef |
if newName[0] != '/' {
newName = "/" + newName
}
|
d7d512bb |
container, err := daemon.GetContainer(oldName) |
d25a6537 |
if err != nil { |
c79b9bab |
return err |
21a809d9 |
}
|
cc234068 |
container.Lock()
defer container.Unlock()
|
a9228163 |
oldName = container.Name |
be072a89 |
oldIsAnonymousEndpoint := container.NetworkSettings.IsAnonymousEndpoint |
a9228163 |
|
3e8c16ef |
if oldName == newName { |
87a12421 |
return errdefs.InvalidParameter(errors.New("Renaming a container with the same name as its current name")) |
3e8c16ef |
}
|
3f6e3a08 |
links := map[string]*dockercontainer.Container{}
for k, v := range daemon.linkIndex.children(container) {
if !strings.HasPrefix(k, oldName) { |
87a12421 |
return errdefs.InvalidParameter(errors.Errorf("Linked container %s does not match parent %s", k, oldName)) |
3f6e3a08 |
}
links[strings.TrimPrefix(k, oldName)] = v
}
|
b08f071e |
if newName, err = daemon.reserveName(container.ID, newName); err != nil { |
ebcb7d6b |
return errors.Wrap(err, "Error when allocating new name") |
21a809d9 |
} |
a9228163 |
|
3f6e3a08 |
for k, v := range links { |
1128fc1a |
daemon.containersReplica.ReserveName(newName+k, v.ID) |
3f6e3a08 |
daemon.linkIndex.link(container, v, newName+k)
}
|
a9228163 |
container.Name = newName |
be072a89 |
container.NetworkSettings.IsAnonymousEndpoint = false |
a9228163 |
|
8e0bbb28 |
defer func() {
if err != nil {
container.Name = oldName |
be072a89 |
container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint |
8e0bbb28 |
daemon.reserveName(container.ID, oldName) |
3f6e3a08 |
for k, v := range links { |
1128fc1a |
daemon.containersReplica.ReserveName(oldName+k, v.ID) |
3f6e3a08 |
daemon.linkIndex.link(container, v, oldName+k)
daemon.linkIndex.unlink(newName+k, v, container) |
1128fc1a |
daemon.containersReplica.ReleaseName(newName + k) |
3f6e3a08 |
} |
0f9f9950 |
daemon.releaseName(newName) |
8e0bbb28 |
}
}() |
c5c72cf1 |
|
3f6e3a08 |
for k, v := range links {
daemon.linkIndex.unlink(oldName+k, v, container) |
1128fc1a |
daemon.containersReplica.ReleaseName(oldName + k) |
3f6e3a08 |
} |
0f9f9950 |
daemon.releaseName(oldName) |
edad5270 |
if err = container.CheckpointTo(daemon.containersReplica); err != nil { |
8e0bbb28 |
return err
}
|
1d8ccc6a |
attributes := map[string]string{
"oldName": oldName,
}
|
8e0bbb28 |
if !container.Running { |
1d8ccc6a |
daemon.LogContainerEventWithAttributes(container, "rename", attributes) |
8e0bbb28 |
return nil
}
defer func() {
if err != nil {
container.Name = oldName |
be072a89 |
container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint |
edad5270 |
if e := container.CheckpointTo(daemon.containersReplica); e != nil { |
8e0bbb28 |
logrus.Errorf("%s: Failed in writing to Disk on rename failure: %v", container.ID, e)
}
}
}()
sid = container.NetworkSettings.SandboxID |
b9ab1295 |
if sid != "" && daemon.netController != nil { |
f21fb216 |
sb, err = daemon.netController.SandboxByID(sid)
if err != nil {
return err
} |
8e0bbb28 |
|
f21fb216 |
err = sb.Rename(strings.TrimPrefix(container.Name, "/"))
if err != nil {
return err
} |
c5c72cf1 |
} |
1d8ccc6a |
daemon.LogContainerEventWithAttributes(container, "rename", attributes) |
c79b9bab |
return nil |
21a809d9 |
} |