diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index a93ba27f48a7a..3cb6f18333146 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" @@ -372,8 +373,8 @@ func TestValidateManifest(t *testing.T) { Image: "image", Command: []string{"foo", "bar"}, WorkingDir: "/tmp", - Memory: 1, - CPU: 1, + Memory: *resource.Q("1"), + CPU: *resource.Q("1"), Ports: []api.Port{ {Name: "p1", ContainerPort: 80, HostPort: 8080}, {Name: "p2", ContainerPort: 81}, @@ -623,7 +624,7 @@ func TestValidatePodUpdate(t *testing.T) { Containers: []api.Container{ { Image: "foo:V1", - CPU: 100, + CPU: *resource.Q("100m"), }, }, }, @@ -634,7 +635,7 @@ func TestValidatePodUpdate(t *testing.T) { Containers: []api.Container{ { Image: "foo:V2", - CPU: 1000, + CPU: *resource.Q("1000m"), }, }, }, @@ -1300,8 +1301,8 @@ func TestValidateMinionUpdate(t *testing.T) { }, Spec: api.NodeSpec{ Capacity: api.ResourceList{ - "cpu": util.NewIntOrStringFromInt(10000), - "memory": util.NewIntOrStringFromInt(100), + api.ResourceCPU: *resource.Q("10000"), + api.ResourceMemory: *resource.Q("100"), }, }, }, api.Node{ @@ -1310,8 +1311,8 @@ func TestValidateMinionUpdate(t *testing.T) { }, Spec: api.NodeSpec{ Capacity: api.ResourceList{ - "cpu": util.NewIntOrStringFromInt(100), - "memory": util.NewIntOrStringFromInt(10000), + api.ResourceCPU: *resource.Q("100"), + api.ResourceMemory: *resource.Q("10000"), }, }, }, true}, @@ -1322,8 +1323,8 @@ func TestValidateMinionUpdate(t *testing.T) { }, Spec: api.NodeSpec{ Capacity: api.ResourceList{ - "cpu": util.NewIntOrStringFromInt(10000), - "memory": util.NewIntOrStringFromInt(100), + api.ResourceCPU: *resource.Q("10000"), + api.ResourceMemory: *resource.Q("100"), }, }, }, api.Node{ @@ -1333,8 +1334,8 @@ func TestValidateMinionUpdate(t *testing.T) { }, Spec: api.NodeSpec{ Capacity: api.ResourceList{ - "cpu": util.NewIntOrStringFromInt(100), - "memory": util.NewIntOrStringFromInt(10000), + api.ResourceCPU: *resource.Q("100"), + api.ResourceMemory: *resource.Q("10000"), }, }, }, true}, diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index b6180fc17aedf..4283d5217aa01 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -28,9 +28,9 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" - "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/version" @@ -96,7 +96,7 @@ func (c *testClient) Setup() *testClient { func (c *testClient) Validate(t *testing.T, received runtime.Object, err error) { c.ValidateCommon(t, err) - if c.Response.Body != nil && !reflect.DeepEqual(c.Response.Body, received) { + if c.Response.Body != nil && !api.Semantic.DeepEqual(c.Response.Body, received) { t.Errorf("bad response for request %#v: expected %#v, got %#v", c.Request, c.Response.Body, received) } } @@ -734,8 +734,8 @@ func TestCreateMinion(t *testing.T) { }, Spec: api.NodeSpec{ Capacity: api.ResourceList{ - resources.CPU: util.NewIntOrStringFromInt(1000), - resources.Memory: util.NewIntOrStringFromInt(1024 * 1024), + api.ResourceCPU: *resource.Q("1000m"), + api.ResourceMemory: *resource.Q("1Mi"), }, }, } diff --git a/pkg/cloudprovider/gce/gce.go b/pkg/cloudprovider/gce/gce.go index 991b49186bde6..5916918f9cbe6 100644 --- a/pkg/cloudprovider/gce/gce.go +++ b/pkg/cloudprovider/gce/gce.go @@ -28,13 +28,13 @@ import ( "strings" "time" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" + "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" + "code.google.com/p/goauth2/compute/serviceaccount" compute "code.google.com/p/google-api-go-client/compute/v1" container "code.google.com/p/google-api-go-client/container/v1beta1" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" - "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/golang/glog" ) @@ -338,11 +338,12 @@ func (gce *GCECloud) List(filter string) ([]string, error) { return instances, nil } -func makeResources(cpu float32, memory float32) *api.NodeResources { +// cpu is in cores, memory is in GiB +func makeResources(cpu float64, memory float64) *api.NodeResources { return &api.NodeResources{ Capacity: api.ResourceList{ - resources.CPU: util.NewIntOrStringFromInt(int(cpu * 1000)), - resources.Memory: util.NewIntOrStringFromInt(int(memory * 1024 * 1024 * 1024)), + api.ResourceCPU: *resource.NewMilliQuantity(int64(cpu*1000), resource.DecimalSI), + api.ResourceMemory: *resource.NewQuantity(int64(memory*1024*1024*1024), resource.BinarySI), }, } } @@ -359,6 +360,7 @@ func (gce *GCECloud) GetNodeResources(name string) (*api.NodeResources, error) { if err != nil { return nil, err } + // TODO: actually read machine size instead of this awful hack. switch canonicalizeMachineType(res.MachineType) { case "f1-micro": return makeResources(1, 0.6), nil diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 2cc6ae01273d4..bc16d9f5ea98e 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -398,7 +398,7 @@ func makePortsAndBindings(container *api.Container) (map[docker.Port]struct{}, m return exposedPorts, portBindings } -func milliCPUToShares(milliCPU int) int { +func milliCPUToShares(milliCPU int64) int64 { if milliCPU == 0 { // zero milliCPU means unset. Use kernel default. return 0 @@ -537,8 +537,8 @@ func (kl *Kubelet) runContainer(pod *api.BoundPod, container *api.Container, pod ExposedPorts: exposedPorts, Hostname: pod.Name, Image: container.Image, - Memory: int64(container.Memory), - CPUShares: int64(milliCPUToShares(container.CPU)), + Memory: container.Memory.Value(), + CPUShares: milliCPUToShares(container.CPU.MilliValue()), WorkingDir: container.WorkingDir, }, } diff --git a/pkg/scheduler/predicates.go b/pkg/scheduler/predicates.go index 6768016b832b0..9e4aa2ec738d3 100644 --- a/pkg/scheduler/predicates.go +++ b/pkg/scheduler/predicates.go @@ -22,7 +22,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" - "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" "github.com/golang/glog" ) @@ -89,15 +88,15 @@ type ResourceFit struct { } type resourceRequest struct { - milliCPU int - memory int + milliCPU int64 + memory int64 } func getResourceRequest(pod *api.Pod) resourceRequest { result := resourceRequest{} for ix := range pod.Spec.Containers { - result.memory += pod.Spec.Containers[ix].Memory - result.milliCPU += pod.Spec.Containers[ix].CPU + result.memory += pod.Spec.Containers[ix].Memory.Value() + result.milliCPU += pod.Spec.Containers[ix].CPU.MilliValue() } return result } @@ -113,17 +112,16 @@ func (r *ResourceFit) PodFitsResources(pod api.Pod, existingPods []api.Pod, node if err != nil { return false, err } - milliCPURequested := 0 - memoryRequested := 0 + milliCPURequested := int64(0) + memoryRequested := int64(0) for ix := range existingPods { existingRequest := getResourceRequest(&existingPods[ix]) milliCPURequested += existingRequest.milliCPU memoryRequested += existingRequest.memory } - // TODO: convert to general purpose resource matching, when pods ask for resources - totalMilliCPU := int(resources.GetFloatResource(info.Spec.Capacity, resources.CPU, 0) * 1000) - totalMemory := resources.GetIntegerResource(info.Spec.Capacity, resources.Memory, 0) + totalMilliCPU := info.Spec.Capacity.Get(api.ResourceCPU).MilliValue() + totalMemory := info.Spec.Capacity.Get(api.ResourceMemory).Value() fitsCPU := totalMilliCPU == 0 || (totalMilliCPU-milliCPURequested) >= podRequest.milliCPU fitsMemory := totalMemory == 0 || (totalMemory-memoryRequested) >= podRequest.memory diff --git a/pkg/scheduler/predicates_test.go b/pkg/scheduler/predicates_test.go index 106efbcb426fc..5fe556207f10d 100644 --- a/pkg/scheduler/predicates_test.go +++ b/pkg/scheduler/predicates_test.go @@ -21,8 +21,7 @@ import ( "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" ) type FakeNodeInfo api.Node @@ -32,17 +31,11 @@ func (n FakeNodeInfo) GetNodeInfo(nodeName string) (*api.Node, error) { return &node, nil } -func makeResources(milliCPU int, memory int) api.NodeResources { +func makeResources(milliCPU int64, memory int64) api.NodeResources { return api.NodeResources{ Capacity: api.ResourceList{ - resources.CPU: util.IntOrString{ - IntVal: milliCPU, - Kind: util.IntstrInt, - }, - resources.Memory: util.IntOrString{ - IntVal: memory, - Kind: util.IntstrInt, - }, + api.ResourceCPU: *resource.NewMilliQuantity(milliCPU, resource.DecimalSI), + api.ResourceMemory: *resource.NewQuantity(memory, resource.BinarySI), }, } } @@ -51,8 +44,8 @@ func newResourcePod(usage ...resourceRequest) api.Pod { containers := []api.Container{} for _, req := range usage { containers = append(containers, api.Container{ - Memory: req.memory, - CPU: req.milliCPU, + Memory: *resource.NewQuantity(req.memory, resource.BinarySI), + CPU: *resource.NewMilliQuantity(req.milliCPU, resource.DecimalSI), }) } return api.Pod{ diff --git a/pkg/scheduler/priorities.go b/pkg/scheduler/priorities.go index c2ec09bbdec7f..dc3250cb8a2c7 100644 --- a/pkg/scheduler/priorities.go +++ b/pkg/scheduler/priorities.go @@ -18,13 +18,12 @@ package scheduler import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" "github.com/golang/glog" ) // the unused capacity is calculated on a scale of 0-10 // 0 being the lowest priority and 10 being the highest -func calculateScore(requested, capacity int, node string) int { +func calculateScore(requested, capacity int64, node string) int { if capacity == 0 { return 0 } @@ -32,30 +31,39 @@ func calculateScore(requested, capacity int, node string) int { glog.Errorf("Combined requested resources from existing pods exceeds capacity on minion: %s", node) return 0 } - return ((capacity - requested) * 10) / capacity + return int(((capacity - requested) * 10) / capacity) } // Calculate the occupancy on a node. 'node' has information about the resources on the node. // 'pods' is a list of pods currently scheduled on the node. func calculateOccupancy(pod api.Pod, node api.Node, pods []api.Pod) HostPriority { - totalCPU := 0 - totalMemory := 0 + totalMilliCPU := int64(0) + totalMemory := int64(0) for _, existingPod := range pods { for _, container := range existingPod.Spec.Containers { - totalCPU += container.CPU - totalMemory += container.Memory + totalMilliCPU += container.CPU.MilliValue() + totalMemory += container.Memory.Value() } } // Add the resources requested by the current pod being scheduled. // This also helps differentiate between differently sized, but empty, minions. for _, container := range pod.Spec.Containers { - totalCPU += container.CPU - totalMemory += container.Memory + totalMilliCPU += container.CPU.MilliValue() + totalMemory += container.Memory.Value() } - cpuScore := calculateScore(totalCPU, resources.GetIntegerResource(node.Spec.Capacity, resources.CPU, 0), node.Name) - memoryScore := calculateScore(totalMemory, resources.GetIntegerResource(node.Spec.Capacity, resources.Memory, 0), node.Name) - glog.V(4).Infof("Least Requested Priority, AbsoluteRequested: (%d, %d) Score:(%d, %d)", totalCPU, totalMemory, cpuScore, memoryScore) + capacityMilliCPU := node.Spec.Capacity.Get(api.ResourceCPU).MilliValue() + capacityMemory := node.Spec.Capacity.Get(api.ResourceMemory).Value() + + cpuScore := calculateScore(totalMilliCPU, capacityMilliCPU, node.Name) + memoryScore := calculateScore(totalMemory, capacityMemory, node.Name) + glog.V(4).Infof( + "%v -> %v: Least Requested Priority, AbsoluteRequested: (%d, %d) / (%d, %d) Score: (%d, %d)", + pod.Name, node.Name, + totalMilliCPU, totalMemory, + capacityMilliCPU, capacityMemory, + cpuScore, memoryScore, + ) return HostPriority{ host: node.Name, diff --git a/pkg/scheduler/priorities_test.go b/pkg/scheduler/priorities_test.go index 327d877f44d57..1081709d90c49 100644 --- a/pkg/scheduler/priorities_test.go +++ b/pkg/scheduler/priorities_test.go @@ -21,17 +21,16 @@ import ( "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/resources" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" ) -func makeMinion(node string, cpu, memory int) api.Node { +func makeMinion(node string, milliCPU, memory int64) api.Node { return api.Node{ ObjectMeta: api.ObjectMeta{Name: node}, Spec: api.NodeSpec{ Capacity: api.ResourceList{ - resources.CPU: util.NewIntOrStringFromInt(cpu), - resources.Memory: util.NewIntOrStringFromInt(memory), + api.ResourceCPU: *resource.NewMilliQuantity(milliCPU, resource.DecimalSI), + api.ResourceMemory: *resource.NewQuantity(memory, resource.BinarySI), }, }, } @@ -57,14 +56,14 @@ func TestLeastRequested(t *testing.T) { } cpuOnly := api.PodSpec{ Containers: []api.Container{ - {CPU: 1000}, - {CPU: 2000}, + {CPU: *resource.Q("1000m")}, + {CPU: *resource.Q("2000m")}, }, } cpuAndMemory := api.PodSpec{ Containers: []api.Container{ - {CPU: 1000, Memory: 2000}, - {CPU: 2000, Memory: 3000}, + {CPU: *resource.Q("1000m"), Memory: *resource.Q("2000")}, + {CPU: *resource.Q("2000m"), Memory: *resource.Q("3000")}, }, } tests := []struct {