blob: 572205d59ed40602b10fb0e30ed11e5d58c1319e [file] [log] [blame]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from collections import namedtuple
from numbers import Number
from enum import Enum, unique
from gen.apache.aurora.api.ttypes import Resource
ResourceDetails = namedtuple('ResourceDetails', ['resource_type', 'value'])
@unique
class ResourceType(Enum):
"""Describes Aurora resource types and their traits."""
CPUS = ('numCpus', 'CPU', ' core(s)', float, 1)
RAM_MB = ('ramMb', 'RAM', ' MB', int, 2)
DISK_MB = ('diskMb', 'Disk', ' MB', int, 3)
PORTS = ('namedPort', 'Port', '', str, 4)
GPUS = ('numGpus', 'GPU', ' GPU(s)', int, 5)
def __init__(self, field, display_name, display_unit, value_type, display_position):
self._field = field
self._display_name = display_name
self._display_unit = display_unit
self._value_type = value_type
self._display_position = display_position
@property
def field(self):
return self._field
@property
def display_name(self):
return self._display_name
@property
def display_unit(self):
return self._display_unit
@property
def value_type(self):
return self._value_type
@property
def display_position(self):
return self._display_position
def resource_value(self, resource):
return resource.__dict__.get(self._field)
@classmethod
def from_resource(cls, resource):
for _, member in cls.__members__.items():
if resource.__dict__.get(member.field) is not None:
return member
else:
raise ValueError("Unknown resource: %s" % resource)
class ResourceManager(object):
"""Provides helper methods for working with Aurora resources."""
@classmethod
def resource_details(cls, resources):
result = []
if resources:
for resource in list(resources):
r_type = ResourceType.from_resource(resource)
result.append(ResourceDetails(r_type, r_type.resource_value(resource)))
return sorted(result, key=lambda rd: rd.resource_type.display_position)
return result
@classmethod
def resource_details_from_quota(cls, quota):
return cls.resource_details(quota.resources)
@classmethod
def resource_details_from_task(cls, task):
return cls.resource_details(cls._backfill_resources(task))
@classmethod
def quantity_of(cls, resource_details, resource_type):
result = 0.0
for d in resource_details:
if d.resource_type is resource_type:
result += d.value if isinstance(d.value, Number) else 1
return result
@classmethod
def _backfill_resources(cls, r_object):
resources = list(r_object.resources) if r_object.resources else None
if resources is None:
resources = [
Resource(numCpus=r_object.numCpus),
Resource(ramMb=r_object.ramMb),
Resource(diskMb=r_object.diskMb)
]
if hasattr(r_object, 'requestedPorts'):
resources += [Resource(namedPort=p) for p in r_object.requestedPorts or []]
return resources