Updating ContainerConfig to use engine-api

Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
This commit is contained in:
Nishant Totla 2016-03-10 14:10:37 -08:00
parent a6c1f1463c
commit 79575f3df6
No known key found for this signature in database
GPG Key ID: 7EA5781C9B3D0C19
7 changed files with 90 additions and 109 deletions

View File

@ -388,7 +388,7 @@ func getContainersJSON(c *context, w http.ResponseWriter, r *http.Request) {
} else if len(filters.Get("name")) > 0 { } else if len(filters.Get("name")) > 0 {
continue continue
} }
if !filters.Match("id", container.Id) { if !filters.Match("id", container.ID) {
continue continue
} }
if !filters.MatchKVList("label", container.Config.Labels) { if !filters.MatchKVList("label", container.Config.Labels) {
@ -427,7 +427,7 @@ func getContainersJSON(c *context, w http.ResponseWriter, r *http.Request) {
out := []*dockerclient.Container{} out := []*dockerclient.Container{}
for _, container := range candidates { for _, container := range candidates {
if before != nil { if before != nil {
if container.Id == before.Id { if container.ID == before.ID {
before = nil before = nil
} }
continue continue
@ -490,7 +490,7 @@ func getContainerJSON(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
resp, err := client.Get(scheme + "://" + container.Engine.Addr + "/containers/" + container.Id + "/json") resp, err := client.Get(scheme + "://" + container.Engine.Addr + "/containers/" + container.ID + "/json")
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
@ -526,12 +526,17 @@ func getContainerJSON(c *context, w http.ResponseWriter, r *http.Request) {
func postContainersCreate(c *context, w http.ResponseWriter, r *http.Request) { func postContainersCreate(c *context, w http.ResponseWriter, r *http.Request) {
r.ParseForm() r.ParseForm()
var ( var (
config = dockerclient.ContainerConfig{ oldConfig = dockerclient.ContainerConfig{
HostConfig: dockerclient.HostConfig{ HostConfig: dockerclient.HostConfig{
MemorySwappiness: -1, MemorySwappiness: -1,
}, },
} }
name = r.Form.Get("name") name = r.Form.Get("name")
config = cluster.ContainerConfig{
HostConfig: containertypes.HostConfig{
MemorySwappiness: -1,
},
}
) )
if err := json.NewDecoder(r.Body).Decode(&config); err != nil { if err := json.NewDecoder(r.Body).Decode(&config); err != nil {
@ -539,13 +544,13 @@ func postContainersCreate(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
// Pass auth information along if present // Pass auth information along if present
var authConfig *dockerclient.AuthConfig var authConfig *apitypes.AuthConfig
buf, err := base64.URLEncoding.DecodeString(r.Header.Get("X-Registry-Auth")) buf, err := base64.URLEncoding.DecodeString(r.Header.Get("X-Registry-Auth"))
if err == nil { if err == nil {
authConfig = &dockerclient.AuthConfig{} authConfig = &apitypes.AuthConfig{}
json.Unmarshal(buf, authConfig) json.Unmarshal(buf, authConfig)
} }
containerConfig := cluster.BuildContainerConfig(config) containerConfig := cluster.BuildContainerConfig(config.Config, config.HostConfig, config.NetworkingConfig)
if err := containerConfig.Validate(); err != nil { if err := containerConfig.Validate(); err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
return return
@ -563,7 +568,7 @@ func postContainersCreate(c *context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, "{%q:%q}", "Id", container.Id) fmt.Fprintf(w, "{%q:%q}", "Id", container.ID)
return return
} }
@ -820,7 +825,7 @@ func postContainersExec(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
resp, err := client.Post(scheme+"://"+container.Engine.Addr+"/containers/"+container.Id+"/exec", "application/json", r.Body) resp, err := client.Post(scheme+"://"+container.Engine.Addr+"/containers/"+container.ID+"/exec", "application/json", r.Body)
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
@ -1044,7 +1049,7 @@ func proxyContainer(c *context, w http.ResponseWriter, r *http.Request) {
// Set the full container ID in the proxied URL path. // Set the full container ID in the proxied URL path.
if name != "" { if name != "" {
r.URL.Path = strings.Replace(r.URL.Path, name, container.Id, 1) r.URL.Path = strings.Replace(r.URL.Path, name, container.ID, 1)
} }
err = proxy(container.Engine, w, r) err = proxy(container.Engine, w, r)
@ -1067,7 +1072,7 @@ func proxyContainerAndForceRefresh(c *context, w http.ResponseWriter, r *http.Re
// Set the full container ID in the proxied URL path. // Set the full container ID in the proxied URL path.
if name != "" { if name != "" {
r.URL.Path = strings.Replace(r.URL.Path, name, container.Id, 1) r.URL.Path = strings.Replace(r.URL.Path, name, container.ID, 1)
} }
cb := func(resp *http.Response) { cb := func(resp *http.Response) {
@ -1200,7 +1205,7 @@ func postCommit(c *context, w http.ResponseWriter, r *http.Request) {
} }
// Set the full container ID in the proxied URL path. // Set the full container ID in the proxied URL path.
if name != "" { if name != "" {
r.URL.RawQuery = strings.Replace(r.URL.RawQuery, name, container.Id, 1) r.URL.RawQuery = strings.Replace(r.URL.RawQuery, name, container.ID, 1)
} }
cb := func(resp *http.Response) { cb := func(resp *http.Response) {
@ -1317,7 +1322,7 @@ func proxyHijack(c *context, w http.ResponseWriter, r *http.Request) {
} }
// Set the full container ID in the proxied URL path. // Set the full container ID in the proxied URL path.
if name != "" { if name != "" {
r.URL.Path = strings.Replace(r.URL.Path, name, container.Id, 1) r.URL.Path = strings.Replace(r.URL.Path, name, container.ID, 1)
} }
err = hijack(c.tlsConfig, container.Engine.Addr, w, r) err = hijack(c.tlsConfig, container.Engine.Addr, w, r)

View File

@ -6,7 +6,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/samalba/dockerclient" "github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/network"
) )
// SwarmLabelNamespace defines the key prefix in all custom labels // SwarmLabelNamespace defines the key prefix in all custom labels
@ -15,7 +16,10 @@ const SwarmLabelNamespace = "com.docker.swarm"
// ContainerConfig is exported // ContainerConfig is exported
// TODO store affinities and constraints in their own fields // TODO store affinities and constraints in their own fields
type ContainerConfig struct { type ContainerConfig struct {
dockerclient.ContainerConfig // dockerclient.ContainerConfig
container.Config
container.HostConfig
network.NetworkingConfig
} }
func parseEnv(e string) (bool, string, string) { func parseEnv(e string) (bool, string, string) {
@ -26,44 +30,8 @@ func parseEnv(e string) (bool, string, string) {
return false, "", "" return false, "", ""
} }
// FIXME: Temporary fix to handle forward/backward compatibility between Docker <1.6 and >=1.7 // BuildContainerConfig creates a cluster.ContainerConfig from a Config, HostConfig, and NetworkingConfig
// ContainerConfig should be handling converting to/from different docker versions func BuildContainerConfig(c container.Config, h container.HostConfig, n network.NetworkingConfig) *ContainerConfig {
func consolidateResourceFields(c *dockerclient.ContainerConfig) {
if c.Memory != c.HostConfig.Memory {
if c.Memory != 0 {
c.HostConfig.Memory = c.Memory
} else {
c.Memory = c.HostConfig.Memory
}
}
if c.MemorySwap != c.HostConfig.MemorySwap {
if c.MemorySwap != 0 {
c.HostConfig.MemorySwap = c.MemorySwap
} else {
c.MemorySwap = c.HostConfig.MemorySwap
}
}
if c.CpuShares != c.HostConfig.CpuShares {
if c.CpuShares != 0 {
c.HostConfig.CpuShares = c.CpuShares
} else {
c.CpuShares = c.HostConfig.CpuShares
}
}
if c.Cpuset != c.HostConfig.CpusetCpus {
if c.Cpuset != "" {
c.HostConfig.CpusetCpus = c.Cpuset
} else {
c.Cpuset = c.HostConfig.CpusetCpus
}
}
}
// BuildContainerConfig creates a cluster.ContainerConfig from a dockerclient.ContainerConfig
func BuildContainerConfig(c dockerclient.ContainerConfig) *ContainerConfig {
var ( var (
affinities []string affinities []string
constraints []string constraints []string
@ -128,9 +96,7 @@ func BuildContainerConfig(c dockerclient.ContainerConfig) *ContainerConfig {
} }
} }
consolidateResourceFields(&c) return &ContainerConfig{c, h, n}
return &ContainerConfig{c}
} }
func (c *ContainerConfig) extractExprs(key string) []string { func (c *ContainerConfig) extractExprs(key string) []string {

View File

@ -4,21 +4,21 @@ import (
"strings" "strings"
"github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/stringid"
"github.com/samalba/dockerclient" "github.com/docker/engine-api/types"
) )
// Container is exported // Container is exported
type Container struct { type Container struct {
dockerclient.Container types.Container
Config *ContainerConfig Config *ContainerConfig
Info dockerclient.ContainerInfo Info types.ContainerJSON
Engine *Engine Engine *Engine
} }
// Refresh container // Refresh container
func (c *Container) Refresh() (*Container, error) { func (c *Container) Refresh() (*Container, error) {
return c.Engine.refreshContainer(c.Id, true) return c.Engine.refreshContainer(c.ID, true)
} }
// Containers represents a list of containers // Containers represents a list of containers
@ -33,7 +33,7 @@ func (containers Containers) Get(IDOrName string) *Container {
// Match exact or short Container ID. // Match exact or short Container ID.
for _, container := range containers { for _, container := range containers {
if container.Id == IDOrName || stringid.TruncateID(container.Id) == IDOrName { if container.ID == IDOrName || stringid.TruncateID(container.ID) == IDOrName {
return container return container
} }
} }
@ -68,7 +68,7 @@ func (containers Containers) Get(IDOrName string) *Container {
// Match Container ID prefix. // Match Container ID prefix.
for _, container := range containers { for _, container := range containers {
if strings.HasPrefix(container.Id, IDOrName) { if strings.HasPrefix(container.ID, IDOrName) {
candidates = append(candidates, container) candidates = append(candidates, container)
} }
} }

View File

@ -20,6 +20,7 @@ import (
engineapi "github.com/docker/engine-api/client" engineapi "github.com/docker/engine-api/client"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters" "github.com/docker/engine-api/types/filters"
networktypes "github.com/docker/engine-api/types/network"
engineapinop "github.com/docker/swarm/api/nopclient" engineapinop "github.com/docker/swarm/api/nopclient"
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
"github.com/samalba/dockerclient/nopclient" "github.com/samalba/dockerclient/nopclient"
@ -627,7 +628,11 @@ func (e *Engine) RefreshVolumes() error {
// true, each container will be inspected. // true, each container will be inspected.
// FIXME: unexport this method after mesos scheduler stops using it directly // FIXME: unexport this method after mesos scheduler stops using it directly
func (e *Engine) RefreshContainers(full bool) error { func (e *Engine) RefreshContainers(full bool) error {
containers, err := e.client.ListContainers(true, false, "") opts := types.ContainerListOptions{
All: true,
Size: false,
}
containers, err := e.apiClient.ContainerList(opts)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return err return err
@ -637,7 +642,7 @@ func (e *Engine) RefreshContainers(full bool) error {
for _, c := range containers { for _, c := range containers {
mergedUpdate, err := e.updateContainer(c, merged, full) mergedUpdate, err := e.updateContainer(c, merged, full)
if err != nil { if err != nil {
log.WithFields(log.Fields{"name": e.Name, "id": e.ID}).Errorf("Unable to update state of container %q: %v", c.Id, err) log.WithFields(log.Fields{"name": e.Name, "id": e.ID}).Errorf("Unable to update state of container %q: %v", c.ID, err)
} else { } else {
merged = mergedUpdate merged = mergedUpdate
} }
@ -653,7 +658,14 @@ func (e *Engine) RefreshContainers(full bool) error {
// Refresh the status of a container running on the engine. If `full` is true, // Refresh the status of a container running on the engine. If `full` is true,
// the container will be inspected. // the container will be inspected.
func (e *Engine) refreshContainer(ID string, full bool) (*Container, error) { func (e *Engine) refreshContainer(ID string, full bool) (*Container, error) {
containers, err := e.client.ListContainers(true, false, fmt.Sprintf("{%q:[%q]}", "id", ID)) filterArgs := filters.NewArgs()
filterArgs.Add("id", ID)
opts := types.ContainerListOptions{
All: true,
Size: false,
Filter: filterArgs,
}
containers, err := e.apiClient.ContainerList(opts)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return nil, err return nil, err
@ -676,16 +688,16 @@ func (e *Engine) refreshContainer(ID string, full bool) (*Container, error) {
_, err = e.updateContainer(containers[0], e.containers, full) _, err = e.updateContainer(containers[0], e.containers, full)
e.RLock() e.RLock()
container := e.containers[containers[0].Id] container := e.containers[containers[0].ID]
e.RUnlock() e.RUnlock()
return container, err return container, err
} }
func (e *Engine) updateContainer(c dockerclient.Container, containers map[string]*Container, full bool) (map[string]*Container, error) { func (e *Engine) updateContainer(c types.Container, containers map[string]*Container, full bool) (map[string]*Container, error) {
var container *Container var container *Container
e.RLock() e.RLock()
if current, exists := e.containers[c.Id]; exists { if current, exists := e.containers[c.ID]; exists {
// The container is already known. // The container is already known.
container = current container = current
// Restarting is a transit state. Unfortunately Docker doesn't always emit // Restarting is a transit state. Unfortunately Docker doesn't always emit
@ -708,30 +720,30 @@ func (e *Engine) updateContainer(c dockerclient.Container, containers map[string
// Update ContainerInfo. // Update ContainerInfo.
if full { if full {
info, err := e.client.InspectContainer(c.Id) info, err := e.apiClient.ContainerInspect(c.ID)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Convert the ContainerConfig from inspect into our own // Convert the ContainerConfig from inspect into our own
// cluster.ContainerConfig. // cluster.ContainerConfig.
if info.HostConfig != nil {
info.Config.HostConfig = *info.HostConfig
}
container.Config = BuildContainerConfig(*info.Config)
// FIXME remove "duplicate" lines and move this to cluster/config.go info.HostConfig.CPUShares = info.HostConfig.CPUShares * int64(e.Cpus) / 1024.0
container.Config.CpuShares = container.Config.CpuShares * int64(e.Cpus) / 1024.0 networkingConfig := networktypes.NetworkingConfig{
container.Config.HostConfig.CpuShares = container.Config.CpuShares EndpointsConfig: info.NetworkSettings.Networks,
}
container.Config = BuildContainerConfig(*info.Config, *info.HostConfig, networkingConfig)
// FIXME remove "duplicate" line and move this to cluster/config.go
container.Config.CPUShares = container.Config.CPUShares * int64(e.Cpus) / 1024.0
// Save the entire inspect back into the container. // Save the entire inspect back into the container.
container.Info = *info container.Info = info
} }
// Update its internal state. // Update its internal state.
e.Lock() e.Lock()
container.Container = c container.Container = c
containers[container.Id] = container containers[container.ID] = container
e.Unlock() e.Unlock()
return containers, nil return containers, nil
@ -829,7 +841,7 @@ func (e *Engine) UsedCpus() int64 {
var r int64 var r int64
e.RLock() e.RLock()
for _, c := range e.containers { for _, c := range e.containers {
r += c.Config.CpuShares r += c.Config.CPUShares
} }
e.RUnlock() e.RUnlock()
return r return r
@ -848,23 +860,21 @@ func (e *Engine) TotalCpus() int {
// Create a new container // Create a new container
func (e *Engine) Create(config *ContainerConfig, name string, pullImage bool, authConfig *dockerclient.AuthConfig) (*Container, error) { func (e *Engine) Create(config *ContainerConfig, name string, pullImage bool, authConfig *dockerclient.AuthConfig) (*Container, error) {
var ( var (
err error err error
id string createResp types.ContainerCreateResponse
client = e.client
) )
// Convert our internal ContainerConfig into something Docker will // Convert our internal ContainerConfig into something Docker will
// understand. Start by making a copy of the internal ContainerConfig as // understand. Start by making a copy of the internal ContainerConfig as
// we don't want to mess with the original. // we don't want to mess with the original.
dockerConfig := config.ContainerConfig dockerConfig := config
// nb of CPUs -> real CpuShares // nb of CPUs -> real CpuShares
// FIXME remove "duplicate" lines and move this to cluster/config.go // FIXME remove "duplicate" lines and move this to cluster/config.go
dockerConfig.CpuShares = int64(math.Ceil(float64(config.CpuShares*1024) / float64(e.Cpus))) dockerConfig.CPUShares = int64(math.Ceil(float64(config.CPUShares*1024) / float64(e.Cpus)))
dockerConfig.HostConfig.CpuShares = dockerConfig.CpuShares
id, err = client.CreateContainer(&dockerConfig, name, nil) createResp, err = e.apiClient.ContainerCreate(&dockerConfig.Config, &dockerConfig.HostConfig, &dockerConfig.NetworkingConfig, name)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
// If the error is other than not found, abort immediately. // If the error is other than not found, abort immediately.
@ -876,7 +886,7 @@ func (e *Engine) Create(config *ContainerConfig, name string, pullImage bool, au
return nil, err return nil, err
} }
// ...And try again. // ...And try again.
id, err = client.CreateContainer(&dockerConfig, name, nil) createResp, err = e.apiClient.ContainerCreate(&dockerConfig.Config, &dockerConfig.HostConfig, &dockerConfig.NetworkingConfig, name)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return nil, err return nil, err
@ -885,12 +895,12 @@ func (e *Engine) Create(config *ContainerConfig, name string, pullImage bool, au
// Register the container immediately while waiting for a state refresh. // Register the container immediately while waiting for a state refresh.
// Force a state refresh to pick up the newly created container. // Force a state refresh to pick up the newly created container.
e.refreshContainer(id, true) e.refreshContainer(createResp.ID, true)
e.RefreshVolumes() e.RefreshVolumes()
e.RefreshNetworks() e.RefreshNetworks()
e.Lock() e.Lock()
container := e.containers[id] container := e.containers[createResp.ID]
e.Unlock() e.Unlock()
if container == nil { if container == nil {
@ -901,7 +911,7 @@ func (e *Engine) Create(config *ContainerConfig, name string, pullImage bool, au
// RemoveContainer removes a container from the engine. // RemoveContainer removes a container from the engine.
func (e *Engine) RemoveContainer(container *Container, force, volumes bool) error { func (e *Engine) RemoveContainer(container *Container, force, volumes bool) error {
err := e.client.RemoveContainer(container.Id, force, volumes) err := e.client.RemoveContainer(container.ID, force, volumes)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return err return err
@ -911,7 +921,7 @@ func (e *Engine) RemoveContainer(container *Container, force, volumes bool) erro
// will rewrite this. // will rewrite this.
e.Lock() e.Lock()
defer e.Unlock() defer e.Unlock()
delete(e.containers, container.Id) delete(e.containers, container.ID)
return nil return nil
} }
@ -1112,10 +1122,10 @@ func (e *Engine) AddContainer(container *Container) error {
e.Lock() e.Lock()
defer e.Unlock() defer e.Unlock()
if _, ok := e.containers[container.Id]; ok { if _, ok := e.containers[container.ID]; ok {
return errors.New("container already exists") return errors.New("container already exists")
} }
e.containers[container.Id] = container e.containers[container.ID] = container
return nil return nil
} }
@ -1132,10 +1142,10 @@ func (e *Engine) removeContainer(container *Container) error {
e.Lock() e.Lock()
defer e.Unlock() defer e.Unlock()
if _, ok := e.containers[container.Id]; !ok { if _, ok := e.containers[container.ID]; !ok {
return errors.New("container not found") return errors.New("container not found")
} }
delete(e.containers, container.Id) delete(e.containers, container.ID)
return nil return nil
} }
@ -1162,14 +1172,14 @@ func (e *Engine) StartContainer(id string, hostConfig *dockerclient.HostConfig)
// RenameContainer renames a container // RenameContainer renames a container
func (e *Engine) RenameContainer(container *Container, newName string) error { func (e *Engine) RenameContainer(container *Container, newName string) error {
// send rename request // send rename request
err := e.client.RenameContainer(container.Id, newName) err := e.client.RenameContainer(container.ID, newName)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return err return err
} }
// refresh container // refresh container
_, err = e.refreshContainer(container.Id, true) _, err = e.refreshContainer(container.ID, true)
return err return err
} }

View File

@ -45,10 +45,10 @@ func (w *Watchdog) removeDuplicateContainers(e *Engine) {
for _, containerInCluster := range w.cluster.Containers() { for _, containerInCluster := range w.cluster.Containers() {
if containerInCluster.Config.SwarmID() == container.Config.SwarmID() && containerInCluster.Engine.ID != container.Engine.ID { if containerInCluster.Config.SwarmID() == container.Config.SwarmID() && containerInCluster.Engine.ID != container.Engine.ID {
log.Debugf("container %s was rescheduled on node %s, removing it", container.Id, containerInCluster.Engine.Name) log.Debugf("container %s was rescheduled on node %s, removing it", container.ID, containerInCluster.Engine.Name)
// container already exists in the cluster, destroy it // container already exists in the cluster, destroy it
if err := e.RemoveContainer(container, true, true); err != nil { if err := e.RemoveContainer(container, true, true); err != nil {
log.Errorf("Failed to remove duplicate container %s on node %s: %v", container.Id, containerInCluster.Engine.Name, err) log.Errorf("Failed to remove duplicate container %s on node %s: %v", container.ID, containerInCluster.Engine.Name, err)
} }
} }
} }
@ -65,7 +65,7 @@ func (w *Watchdog) rescheduleContainers(e *Engine) {
// Skip containers which don't have an "on-node-failure" reschedule policy. // Skip containers which don't have an "on-node-failure" reschedule policy.
if !c.Config.HasReschedulePolicy("on-node-failure") { if !c.Config.HasReschedulePolicy("on-node-failure") {
log.Debugf("Skipping rescheduling of %s based on rescheduling policies", c.Id) log.Debugf("Skipping rescheduling of %s based on rescheduling policies", c.ID)
continue continue
} }
@ -78,15 +78,15 @@ func (w *Watchdog) rescheduleContainers(e *Engine) {
newContainer, err := w.cluster.CreateContainer(c.Config, c.Info.Name, nil) newContainer, err := w.cluster.CreateContainer(c.Config, c.Info.Name, nil)
if err != nil { if err != nil {
log.Errorf("Failed to reschedule container %s: %v", c.Id, err) log.Errorf("Failed to reschedule container %s: %v", c.ID, err)
// add the container back, so we can retry later // add the container back, so we can retry later
c.Engine.AddContainer(c) c.Engine.AddContainer(c)
} else { } else {
log.Infof("Rescheduled container %s from %s to %s as %s", c.Id, c.Engine.Name, newContainer.Engine.Name, newContainer.Id) log.Infof("Rescheduled container %s from %s to %s as %s", c.ID, c.Engine.Name, newContainer.Engine.Name, newContainer.ID)
if c.Info.State.Running { if c.Info.State.Running {
log.Infof("Container %s was running, starting container %s", c.Id, newContainer.Id) log.Infof("Container %s was running, starting container %s", c.ID, newContainer.ID)
if err := w.cluster.StartContainer(newContainer, nil); err != nil { if err := w.cluster.StartContainer(newContainer, nil); err != nil {
log.Errorf("Failed to start rescheduled container %s: %v", newContainer.Id, err) log.Errorf("Failed to start rescheduled container %s: %v", newContainer.ID, err)
} }
} }
} }

View File

@ -56,7 +56,7 @@ func (n *Node) Container(IDOrName string) *cluster.Container {
func (n *Node) AddContainer(container *cluster.Container) error { func (n *Node) AddContainer(container *cluster.Container) error {
if container.Config != nil { if container.Config != nil {
memory := container.Config.Memory memory := container.Config.Memory
cpus := container.Config.CpuShares cpus := container.Config.CPUShares
if n.TotalMemory-memory < 0 || n.TotalCpus-cpus < 0 { if n.TotalMemory-memory < 0 || n.TotalCpus-cpus < 0 {
return errors.New("not enough resources") return errors.New("not enough resources")
} }

View File

@ -44,7 +44,7 @@ func weighNodes(config *cluster.ContainerConfig, nodes []*node.Node, healthiness
nodeCpus := node.TotalCpus nodeCpus := node.TotalCpus
// Skip nodes that are smaller than the requested resources. // Skip nodes that are smaller than the requested resources.
if nodeMemory < int64(config.Memory) || nodeCpus < config.CpuShares { if nodeMemory < int64(config.Memory) || nodeCpus < config.CPUShares {
continue continue
} }
@ -53,8 +53,8 @@ func weighNodes(config *cluster.ContainerConfig, nodes []*node.Node, healthiness
memoryScore int64 = 100 memoryScore int64 = 100
) )
if config.CpuShares > 0 { if config.CPUShares > 0 {
cpuScore = (node.UsedCpus + config.CpuShares) * 100 / nodeCpus cpuScore = (node.UsedCpus + config.CPUShares) * 100 / nodeCpus
} }
if config.Memory > 0 { if config.Memory > 0 {
memoryScore = (node.UsedMemory + config.Memory) * 100 / nodeMemory memoryScore = (node.UsedMemory + config.Memory) * 100 / nodeMemory