From 5daaecdaa133bf5e3ce6b7acfcb5455cd0923faa Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 5 Jan 2016 10:24:20 -0800 Subject: [PATCH 1/2] do not save image affinity on reschedule Signed-off-by: Victor Vieux --- cluster/config.go | 16 ++++++++++++++++ cluster/swarm/cluster.go | 14 +++++++++----- test/integration/api/run.bats | 10 +++++++--- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/cluster/config.go b/cluster/config.go index ce085dd1e3..94e8dc097f 100644 --- a/cluster/config.go +++ b/cluster/config.go @@ -159,6 +159,22 @@ func (c *ContainerConfig) AddAffinity(affinity string) error { return nil } +// RemoveAffinity from config +func (c *ContainerConfig) RemoveAffinity(affinity string) error { + affinities := []string{} + for _, a := range c.extractExprs("affinities") { + if a != affinity { + affinities = append(affinities, a) + } + } + labels, err := json.Marshal(affinities) + if err != nil { + return err + } + c.Labels[SwarmLabelNamespace+".affinities"] = string(labels) + return nil +} + // HaveNodeConstraint in config func (c *ContainerConfig) HaveNodeConstraint() bool { constraints := c.extractExprs("constraints") diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index c29dcf7f99..2b8907aa81 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -118,12 +118,12 @@ func (c *Cluster) generateUniqueID() string { func (c *Cluster) CreateContainer(config *cluster.ContainerConfig, name string, authConfig *dockerclient.AuthConfig) (*cluster.Container, error) { container, err := c.createContainer(config, name, false, authConfig) - // fails with image not found, then try to reschedule with image-affinity + // fails with image not found, then try to reschedule with image affinity if err != nil { bImageNotFoundError, _ := regexp.MatchString(`image \S* not found`, err.Error()) if bImageNotFoundError && !config.HaveNodeConstraint() { // Check if the image exists in the cluster - // If exists, retry with a image-affinity + // If exists, retry with a image affinity if c.Image(config.Image) != nil { container, err = c.createContainer(config, name, true, authConfig) } @@ -145,12 +145,16 @@ func (c *Cluster) createContainer(config *cluster.ContainerConfig, name string, swarmID := c.generateUniqueID() config.SetSwarmID(swarmID) - configTemp := config if withImageAffinity { - configTemp.AddAffinity("image==" + config.Image) + config.AddAffinity("image==" + config.Image) + } + + nodes, err := c.scheduler.SelectNodesForContainer(c.listNodes(), config) + + if withImageAffinity { + config.RemoveAffinity("image==" + config.Image) } - nodes, err := c.scheduler.SelectNodesForContainer(c.listNodes(), configTemp) if err != nil { c.scheduler.Unlock() return nil, err diff --git a/test/integration/api/run.bats b/test/integration/api/run.bats index 40cf7a082e..c540170c7f 100644 --- a/test/integration/api/run.bats +++ b/test/integration/api/run.bats @@ -101,7 +101,7 @@ function teardown() { [[ "${output}" == *"\"StopSignal\": \"SIGKILL\""* ]] } -@test "docker run - reschedule with soft-image-affinity" { +@test "docker run - reschedule with image affinity" { start_docker_with_busybox 1 start_docker 1 @@ -115,15 +115,19 @@ function teardown() { # try to create container on node-1, node-1 does not have busyboxabcde and will pull it # but can not find busyboxabcde in dockerhub - # then will retry with soft-image-affinity + # then will retry with image affinity docker_swarm run -d --name test_container -e constraint:node==~node-1 busyboxabcde sleep 1000 # check container running on node-0 run docker_swarm ps [[ "${output}" == *"node-0/test_container"* ]] + + # check the image affinity wasn't saved + run docker_swarm inspect test_container + [[ "${output}" != *"image==busyboxabcde"* ]] } -@test "docker run - reschedule with soft-image-affinity and node constraint" { +@test "docker run - reschedule with image affinity and node constraint" { start_docker_with_busybox 1 start_docker 1 From 2449a352ef291ff8aec32025b8b965b97ffef805 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 5 Jan 2016 10:31:47 -0800 Subject: [PATCH 2/2] add unit test Signed-off-by: Victor Vieux --- cluster/config_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cluster/config_test.go b/cluster/config_test.go index 82a9827f12..92cd7041e2 100644 --- a/cluster/config_test.go +++ b/cluster/config_test.go @@ -90,6 +90,20 @@ func TestAddAffinity(t *testing.T) { assert.Len(t, config.Affinities(), 1) } +func TestRemoveAffinity(t *testing.T) { + config := BuildContainerConfig(dockerclient.ContainerConfig{}) + assert.Empty(t, config.Affinities()) + + config.AddAffinity("image==~testimage1") + config.AddAffinity("image==~testimage2") + assert.Len(t, config.Affinities(), 2) + + config.RemoveAffinity("image==~testimage1") + assert.Len(t, config.Affinities(), 1) + + assert.Equal(t, config.Affinities()[0], "image==~testimage2") +} + func TestHaveNodeConstraint(t *testing.T) { config := BuildContainerConfig(dockerclient.ContainerConfig{}) assert.False(t, config.HaveNodeConstraint())