resources.py 2.43 KB
Newer Older
1 2 3 4 5
from __future__ import print_function

import logging
from subprograms import HwlocClient, resources

6 7
logger = logging.getLogger('nrm')

8 9 10 11 12 13

class ResourceManager(object):

    """Manages the query of node resources, the tracking of their use and
    the scheduling of new containers according to partitioning rules."""

14 15
    def __init__(self, hwloc):
        self.hwloc = HwlocClient(hwloc=hwloc)
16 17 18

        # query the node topo, keep track of the critical resources
        self.allresources = self.hwloc.info()
19
        logger.debug("resource info: %r", self.allresources)
20
        self.available = self.allresources
21
        self.allocations = {}
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

    def schedule(self, uuid, request):
        """Schedule a resource request on the available resources.

        Request is a dictionary of the resources asked for."""
        # dumb scheduling, just give the first resources available:
        #  - cpus are exclusive
        #  - memories exclusive if more than one left
        if len(self.available.cpus) >= request.cpus:
            retcpus = self.available.cpus[:request.cpus]
        else:
            retcpus = []
        if len(self.available.mems) > 1:
            retmems = self.available.mems[:request.mems]
        else:
            retmems = self.available.mems
38 39 40 41 42
        ret = resources(retcpus, retmems)
        # make sure we don't remember an error
        if ret.cpus:
            self.update(uuid, ret)
        return ret
43

44 45
    def update(self, uuid, allocation=resources([], [])):
        """Update resource tracking according to new allocation.
46

47 48 49 50 51 52 53 54 55
        The new allocation is saved, and available resources updated."""
        added = {}
        freed = {}
        prev = self.allocations.get(uuid, resources([], []))
        for attr, val in prev._asdict().items():
            added[attr] = set(getattr(allocation, attr)) - set(val)
            freed[attr] = set(val) - set(getattr(allocation, attr))
        if allocation != resources([], []):
            self.allocations[uuid] = allocation
56 57
            logger.info("updated allocation for %r: %r", uuid,
                        self.available)
58 59
        else:
            del self.allocations[uuid]
60
            logger.info("deleted allocation for %r", uuid)
61 62 63 64
        new = {}
        for attr, val in self.available._asdict().items():
            new[attr] = list(set(val) - set(added[attr]) | set(freed[attr]))
        self.available = resources(**new)
65
        logger.info("updated available resources: %r", self.available)