if nodes and reqs:
if recover:
raise RuntimeError, "Impossible to recover: unassigned host for Nodes %r" % (nodes,)
+
+ def pickbest(fullset, nreq, node=nodes[0]):
+ if len(fullset) > nreq:
+ fullset = zip(node.rate_nodes(fullset),fullset)
+ fullset.sort(reverse=True)
+ del fullset[nreq:]
+ return set(map(operator.itemgetter(1),fullset))
+ else:
+ return fullset
try:
- solution = resourcealloc.alloc(reqs)
+ solution = resourcealloc.alloc(reqs, sample=pickbest)
except resourcealloc.ResourceAllocationError:
# Failed, try again with all nodes
reqs = []
candidates -= reserved
reqs.append(candidates)
- solution = resourcealloc.alloc(reqs)
+ solution = resourcealloc.alloc(reqs, sample=pickbest)
to_provision.update(solution)
# Do assign nodes
'maxLoad' : ('load%(timeframe)s', '[value'),
'minCpu' : ('cpu%(timeframe)s', ']value'),
'maxCpu' : ('cpu%(timeframe)s', '[value'),
- }
+ }
+
+ RATE_FACTORS = (
+ # (<tag name>, <weight>, <default>)
+ ('bw%(timeframe)s', -0.001, 1024.0),
+ ('cpu%(timeframe)s', 0.1, 40.0),
+ ('load%(timeframe)s', -0.2, 3.0),
+ ('reliability%(timeframe)s', 1, 100.0),
+ )
DEPENDS_PIDFILE = '/tmp/nepi-depends.pid'
DEPENDS_LOGFILE = '/tmp/nepi-depends.log'
self._node_id = None
self.__dict__.update(self.__orig_attrs)
+ def rate_nodes(self, nodes):
+ rates = collections.defaultdict(int)
+ tags = collections.defaultdict(dict)
+ replacements = {'timeframe':self.timeframe}
+ tagnames = [ tagname % replacements
+ for tagname, weight, default in self.RATE_FACTORS ]
+
+ taginfo = self._api.GetNodeTags(
+ node_id=list(nodes),
+ tagname=tagnames,
+ fields=('node_id','tagname','value'))
+
+ for node, tagname, value in taginfo:
+ tags[tagname][int(node)] = float(value)
+
+ for tagname, weight, default in self.RATE_FACTORS:
+ taginfo = tags[tagname].get
+ for node in nodes:
+ rates[node] += weight * taginfo(node,default)
+
+ return map(rates.__getitem__, nodes)
+
def fetch_node_info(self):
orig_attrs = {}
logstream.write(message)
logstream.write('\n')
-def alloc(requests, logstream = None, nonseparable = False, saveinteresting = None, backtracklim = 100000000, verbose = True):
+def alloc(requests, logstream = None, nonseparable = False, saveinteresting = None, backtracklim = 100000000, verbose = True, sample = random.sample):
"""
Takes an iterable over requests, which are iterables of candidate node ids,
and returns a specific node id for each request (if successful).
part = Pavail[i]
if len(part) < nreq:
raise AssertionError, "Cannot allocate resources for supposedly valid solution!"
- assigned = set(random.sample(part, nreq))
+ assigned = set(sample(part, nreq))
psol |= assigned
part -= assigned
solution[c] = psol