47 lines
1.7 KiB
Python
47 lines
1.7 KiB
Python
from colony.core.network.advice import assignable_roles
|
|
from colony.settings import setting
|
|
|
|
|
|
class RolePolicy:
|
|
decline_cooldown = 60
|
|
|
|
def decide(self, role_name, held, scores, roles):
|
|
raise NotImplementedError
|
|
|
|
def should_keep(self, role_name, scores):
|
|
return True
|
|
|
|
|
|
class DefaultRolePolicy(RolePolicy):
|
|
def __init__(self, max_roles=None, deny=None, min_scores=None, decline_cooldown=None):
|
|
self.max_roles = setting("role_policy.max_roles", max_roles)
|
|
self.deny = set(setting("role_policy.deny", deny))
|
|
raw_minimums = setting("role_policy.min_scores", min_scores)
|
|
self.min_scores = {role: dict(minimums) for role, minimums in dict(raw_minimums).items()}
|
|
self.decline_cooldown = setting("role_policy.decline_cooldown", decline_cooldown)
|
|
|
|
def _violation(self, role_name, scores):
|
|
if role_name in self.deny:
|
|
return "role is on the deny list"
|
|
for key, minimum in self.min_scores.get(role_name, {}).items():
|
|
if scores.get(key, 0) < minimum:
|
|
return f"{key} score is below {minimum}"
|
|
return None
|
|
|
|
def decide(self, role_name, held, scores, roles):
|
|
reason = self._violation(role_name, scores)
|
|
if reason:
|
|
return False, reason
|
|
|
|
if self.max_roles is not None:
|
|
assigned = [name for name in held if name in assignable_roles(roles)]
|
|
if len(assigned) >= self.max_roles:
|
|
return False, "node already holds the maximum number of roles"
|
|
|
|
return True, "accepted"
|
|
|
|
def should_keep(self, role_name, scores):
|
|
if not scores:
|
|
return role_name not in self.deny
|
|
return self._violation(role_name, scores) is None
|