Skip to content

Commit bec1303

Browse files
committed
Revert "Add host resource manager methods (#3700)"
This reverts commit 40590fe.
1 parent cb54139 commit bec1303

File tree

2 files changed

+16
-516
lines changed

2 files changed

+16
-516
lines changed

agent/engine/host_resource_manager.go

+16-296
Original file line numberDiff line numberDiff line change
@@ -16,300 +16,20 @@
1616
package engine
1717

1818
import (
19-
"fmt"
20-
"sync"
21-
2219
"github.com/aws/amazon-ecs-agent/agent/ecs_client/model/ecs"
2320
"github.com/aws/amazon-ecs-agent/agent/utils"
2421
"github.com/aws/amazon-ecs-agent/ecs-agent/logger"
25-
"github.com/aws/amazon-ecs-agent/ecs-agent/logger/field"
2622
)
2723

28-
// TODO remove this once resource, consume are used
29-
//lint:file-ignore U1000 Ignore all unused code
30-
31-
const (
32-
CPU = "CPU"
33-
GPU = "GPU"
34-
MEMORY = "MEMORY"
35-
PORTSTCP = "PORTS_TCP"
36-
PORTSUDP = "PORTS_UDP"
37-
)
38-
39-
// HostResourceManager keeps account of host resources allocated for tasks set to be created/running tasks
24+
// initialHostResource keeps account of each task in
4025
type HostResourceManager struct {
41-
initialHostResource map[string]*ecs.Resource
42-
consumedResource map[string]*ecs.Resource
43-
hostResourceManagerRWLock sync.Mutex
26+
initialHostResource map[string]*ecs.Resource
27+
consumedResource map[string]*ecs.Resource
4428

4529
//task.arn to boolean whether host resources consumed or not
4630
taskConsumed map[string]bool
4731
}
4832

49-
type ResourceNotFoundForTask struct {
50-
resource string
51-
}
52-
53-
func (e *ResourceNotFoundForTask) Error() string {
54-
return fmt.Sprintf("no %s in task resources", e.resource)
55-
}
56-
57-
type InvalidHostResource struct {
58-
resource string
59-
}
60-
61-
func (e *InvalidHostResource) Error() string {
62-
return fmt.Sprintf("no %s resource found in host resources", e.resource)
63-
}
64-
65-
type ResourceIsNilForTask struct {
66-
resource string
67-
}
68-
69-
func (e *ResourceIsNilForTask) Error() string {
70-
return fmt.Sprintf("resource %s is nil in task resources", e.resource)
71-
}
72-
73-
func (h *HostResourceManager) logResources(msg string, taskArn string) {
74-
logger.Debug(msg, logger.Fields{
75-
"taskArn": taskArn,
76-
"CPU": *h.consumedResource[CPU].IntegerValue,
77-
"MEMORY": *h.consumedResource[MEMORY].IntegerValue,
78-
"PORTS_TCP": h.consumedResource[PORTSTCP].StringSetValue,
79-
"PORTS_UDP": h.consumedResource[PORTSUDP].StringSetValue,
80-
"GPU": *h.consumedResource[GPU].IntegerValue,
81-
})
82-
}
83-
84-
func (h *HostResourceManager) consumeIntType(resourceType string, resources map[string]*ecs.Resource) {
85-
*h.consumedResource[resourceType].IntegerValue += *resources[resourceType].IntegerValue
86-
}
87-
88-
func (h *HostResourceManager) consumeStringSetType(resourceType string, resources map[string]*ecs.Resource) {
89-
resource, ok := resources[resourceType]
90-
if ok {
91-
h.consumedResource[resourceType].StringSetValue = append(h.consumedResource[resourceType].StringSetValue, resource.StringSetValue...)
92-
}
93-
}
94-
95-
// Returns if resources consumed or not and error status
96-
// false, nil -> did not consume, task should stay pending
97-
// false, err -> resources map has errors, task should fail as cannot schedule with 'wrong' resource map (this basically never happens)
98-
// true, nil -> successfully consumed, task should progress with task creation
99-
func (h *HostResourceManager) consume(taskArn string, resources map[string]*ecs.Resource) (bool, error) {
100-
h.hostResourceManagerRWLock.Lock()
101-
defer h.hostResourceManagerRWLock.Unlock()
102-
defer h.logResources("Consumed resources after task consume call", taskArn)
103-
104-
// Check if already consumed
105-
_, ok := h.taskConsumed[taskArn]
106-
if ok {
107-
// Nothing to do, already consumed, return
108-
logger.Info("Resources pre-consumed, continue to task creation", logger.Fields{"taskArn": taskArn})
109-
return true, nil
110-
}
111-
112-
ok, err := h.consumable(resources)
113-
if err != nil {
114-
logger.Error("Resources failing to consume, error in task resources", logger.Fields{
115-
"taskArn": taskArn,
116-
field.Error: err,
117-
})
118-
return false, err
119-
}
120-
if ok {
121-
for resourceKey := range resources {
122-
if *resources[resourceKey].Type == "INTEGER" {
123-
// CPU, MEMORY, GPU
124-
h.consumeIntType(resourceKey, resources)
125-
} else if *resources[resourceKey].Type == "STRINGSET" {
126-
// PORTS_TCP, PORTS_UDP
127-
h.consumeStringSetType(resourceKey, resources)
128-
}
129-
}
130-
131-
// Set consumed status
132-
h.taskConsumed[taskArn] = true
133-
logger.Info("Resources successfully consumed, continue to task creation", logger.Fields{"taskArn": taskArn})
134-
return true, nil
135-
}
136-
logger.Info("Resources not consumed, enough resources not available", logger.Fields{"taskArn": taskArn})
137-
return false, nil
138-
}
139-
140-
// Functions checkConsumableIntType and checkConsumableStringSetType to be called
141-
// only after checking for resource map health
142-
func (h *HostResourceManager) checkConsumableIntType(resourceName string, resources map[string]*ecs.Resource) bool {
143-
resourceConsumableStatus := *(h.initialHostResource[resourceName].IntegerValue) >= *(h.consumedResource[resourceName].IntegerValue)+*(resources[resourceName].IntegerValue)
144-
return resourceConsumableStatus
145-
}
146-
147-
func (h *HostResourceManager) checkConsumableStringSetType(resourceName string, resources map[string]*ecs.Resource) bool {
148-
resourceSlice := resources[resourceName].StringSetValue
149-
150-
// (optimizization) Get a resource specific map to ease look up
151-
resourceMap := make(map[string]struct{}, len(resourceSlice))
152-
for _, v := range resourceSlice {
153-
resourceMap[*v] = struct{}{}
154-
}
155-
156-
// Check intersection of resource StringSetValue is empty with consumedResource
157-
for _, obj1 := range h.consumedResource[resourceName].StringSetValue {
158-
_, ok := resourceMap[*obj1]
159-
if ok {
160-
// If resource is already reserved by some other task, this 'resources' object can not be consumed
161-
return false
162-
}
163-
}
164-
return true
165-
}
166-
167-
func checkResourceExistsInt(resourceName string, resources map[string]*ecs.Resource) error {
168-
_, ok := resources[resourceName]
169-
if ok {
170-
if resources[resourceName].IntegerValue == nil {
171-
return &ResourceIsNilForTask{resourceName}
172-
}
173-
} else {
174-
return &ResourceNotFoundForTask{resourceName}
175-
}
176-
return nil
177-
}
178-
179-
func checkResourceExistsStringSet(resourceName string, resources map[string]*ecs.Resource) error {
180-
_, ok := resources[resourceName]
181-
if ok {
182-
for _, obj := range resources[resourceName].StringSetValue {
183-
if obj == nil {
184-
return &ResourceIsNilForTask{resourceName}
185-
}
186-
}
187-
} else {
188-
return &ResourceNotFoundForTask{resourceName}
189-
}
190-
return nil
191-
}
192-
193-
// Checks all resources exists and their values are not nil
194-
func (h *HostResourceManager) checkResourcesHealth(resources map[string]*ecs.Resource) error {
195-
for resourceKey, resourceVal := range resources {
196-
_, ok := h.initialHostResource[resourceKey]
197-
if !ok {
198-
logger.Error(fmt.Sprintf("resource %s not found in ", resourceKey))
199-
return &InvalidHostResource{resourceKey}
200-
}
201-
202-
// CPU, MEMORY, GPU are INTEGER;
203-
// PORTS_TCP, PORTS_UDP are STRINGSET
204-
// Check if either of these data types exist
205-
if resourceVal.Type == nil || !(*resourceVal.Type == "INTEGER" || *resourceVal.Type == "STRINGSET") {
206-
logger.Error(fmt.Sprintf("type not assigned for resource %s", resourceKey))
207-
return fmt.Errorf("invalid resource type for %s", resourceKey)
208-
}
209-
210-
// CPU, MEMORY, GPU
211-
if *resourceVal.Type == "INTEGER" {
212-
err := checkResourceExistsInt(resourceKey, resources)
213-
return err
214-
}
215-
216-
// PORTS_TCP, PORTS_UDP
217-
if *resourceVal.Type == "STRINGSET" {
218-
err := checkResourceExistsStringSet(resourceKey, resources)
219-
return err
220-
}
221-
}
222-
return nil
223-
}
224-
225-
// Helper function for consume to check if resources are consumable with the current account
226-
// we have for the host resources. Should not call host resource manager lock in this func
227-
// return values
228-
func (h *HostResourceManager) consumable(resources map[string]*ecs.Resource) (bool, error) {
229-
err := h.checkResourcesHealth(resources)
230-
if err != nil {
231-
return false, err
232-
}
233-
234-
for resourceKey := range resources {
235-
if *resources[resourceKey].Type == "INTEGER" {
236-
consumable := h.checkConsumableIntType(resourceKey, resources)
237-
if !consumable {
238-
return false, nil
239-
}
240-
}
241-
242-
if *resources[resourceKey].Type == "STRINGSET" {
243-
consumable := h.checkConsumableStringSetType(resourceKey, resources)
244-
if !consumable {
245-
return false, nil
246-
}
247-
}
248-
}
249-
250-
return true, nil
251-
}
252-
253-
// Utility function to manage release of ports
254-
// s2 is contiguous sub slice of s1, each is unique (ports)
255-
// returns a slice after removing s2 from s1, if found
256-
func removeSubSlice(s1 []*string, s2 []*string) []*string {
257-
begin := 0
258-
end := len(s1) - 1
259-
for ; begin < len(s1); begin++ {
260-
if *s1[begin] == *s2[0] {
261-
break
262-
}
263-
}
264-
// no intersection found
265-
if begin == len(s1) {
266-
return s1
267-
}
268-
269-
end = begin + len(s2)
270-
newSlice := append(s1[:begin], s1[end:]...)
271-
return newSlice
272-
}
273-
274-
func (h *HostResourceManager) releaseIntType(resourceType string, resources map[string]*ecs.Resource) {
275-
*h.consumedResource[resourceType].IntegerValue -= *resources[resourceType].IntegerValue
276-
}
277-
278-
func (h *HostResourceManager) releaseStringSetType(resourceType string, resources map[string]*ecs.Resource) {
279-
newSlice := removeSubSlice(h.consumedResource[resourceType].StringSetValue, resources[resourceType].StringSetValue)
280-
h.consumedResource[resourceType].StringSetValue = newSlice
281-
}
282-
283-
// Returns error if task resource map has error, else releases resources
284-
// Task resource map should never have errors as it is made by task ToHostResources method
285-
// In cases releases fails due to errors, those resources will be failed to be released
286-
// by HostResourceManager
287-
func (h *HostResourceManager) release(taskArn string, resources map[string]*ecs.Resource) error {
288-
h.hostResourceManagerRWLock.Lock()
289-
defer h.hostResourceManagerRWLock.Unlock()
290-
defer h.logResources("Consumed resources after task release call", taskArn)
291-
292-
if h.taskConsumed[taskArn] {
293-
err := h.checkResourcesHealth(resources)
294-
if err != nil {
295-
return err
296-
}
297-
298-
for resourceKey := range resources {
299-
if *resources[resourceKey].Type == "INTEGER" {
300-
h.releaseIntType(resourceKey, resources)
301-
}
302-
if *resources[resourceKey].Type == "STRINGSET" {
303-
h.releaseStringSetType(resourceKey, resources)
304-
}
305-
}
306-
307-
// Set consumed status
308-
delete(h.taskConsumed, taskArn)
309-
}
310-
return nil
311-
}
312-
31333
// NewHostResourceManager initialize host resource manager with available host resource values
31434
func NewHostResourceManager(resourceMap map[string]*ecs.Resource) HostResourceManager {
31535
// for resources in resourceMap, some are "available resources" like CPU, mem, while
@@ -319,45 +39,45 @@ func NewHostResourceManager(resourceMap map[string]*ecs.Resource) HostResourceMa
31939
// assigns CPU, MEMORY, PORTS_TCP, PORTS_UDP from host
32040
//CPU
32141
CPUs := int64(0)
322-
consumedResourceMap[CPU] = &ecs.Resource{
323-
Name: utils.Strptr(CPU),
42+
consumedResourceMap["CPU"] = &ecs.Resource{
43+
Name: utils.Strptr("CPU"),
32444
Type: utils.Strptr("INTEGER"),
32545
IntegerValue: &CPUs,
32646
}
32747
//MEMORY
32848
memory := int64(0)
329-
consumedResourceMap[MEMORY] = &ecs.Resource{
330-
Name: utils.Strptr(MEMORY),
49+
consumedResourceMap["MEMORY"] = &ecs.Resource{
50+
Name: utils.Strptr("MEMORY"),
33151
Type: utils.Strptr("INTEGER"),
33252
IntegerValue: &memory,
33353
}
33454
//PORTS_TCP
33555
//Copying ports from host resources as consumed ports for initializing
33656
portsTcp := []*string{}
337-
if resourceMap != nil && resourceMap[PORTSTCP] != nil {
338-
portsTcp = resourceMap[PORTSTCP].StringSetValue
57+
if resourceMap != nil && resourceMap["PORTS_TCP"] != nil {
58+
portsTcp = resourceMap["PORTS_TCP"].StringSetValue
33959
}
340-
consumedResourceMap[PORTSTCP] = &ecs.Resource{
60+
consumedResourceMap["PORTS_TCP"] = &ecs.Resource{
34161
Name: utils.Strptr("PORTS_TCP"),
34262
Type: utils.Strptr("STRINGSET"),
34363
StringSetValue: portsTcp,
34464
}
34565

34666
//PORTS_UDP
34767
portsUdp := []*string{}
348-
if resourceMap != nil && resourceMap[PORTSUDP] != nil {
349-
portsUdp = resourceMap[PORTSUDP].StringSetValue
68+
if resourceMap != nil && resourceMap["PORTS_UDP"] != nil {
69+
portsUdp = resourceMap["PORTS_UDP"].StringSetValue
35070
}
351-
consumedResourceMap[PORTSUDP] = &ecs.Resource{
352-
Name: utils.Strptr(PORTSUDP),
71+
consumedResourceMap["PORTS_UDP"] = &ecs.Resource{
72+
Name: utils.Strptr("PORTS_UDP"),
35373
Type: utils.Strptr("STRINGSET"),
35474
StringSetValue: portsUdp,
35575
}
35676

35777
//GPUs
35878
numGPUs := int64(0)
359-
consumedResourceMap[GPU] = &ecs.Resource{
360-
Name: utils.Strptr(GPU),
79+
consumedResourceMap["GPU"] = &ecs.Resource{
80+
Name: utils.Strptr("GPU"),
36181
Type: utils.Strptr("INTEGER"),
36282
IntegerValue: &numGPUs,
36383
}

0 commit comments

Comments
 (0)