Commit c2f4dab0 authored by Valentin Reis's avatar Valentin Reis

Adding some of the power-expe code.

parent e992a7f1
Pipeline #4566 failed with stages
in 2 minutes and 18 seconds
......@@ -2,10 +2,12 @@ from __future__ import print_function
import logging
import time
import math
logger = logging.getLogger('nrm')
logger_power = logging.getLogger('power')
class Action(object):
"""Information about a control action."""
......@@ -15,6 +17,7 @@ class Action(object):
self.command = command
self.delta = delta
class PowerActuator(object):
"""Actuator in charge of power control."""
......@@ -41,7 +44,41 @@ class PowerActuator(object):
action.command, action.delta, action.target)
# sensor_manager is a SensorManager, which is not only about sensing
# but also about setting power limits.
# self.sensor_manager.set_powerlimit(action.target, action.command)
self.sensor_manager.set_powerlimit(action.target, action.command)
def update(self, action):
pass
class DiscretizedPowerActuator(object):
"""Actuator in charge of power control via discretization."""
def __init__(self, sm, lowerboundwatts, k):
self.sensor_manager = sm
self.lowerboundwatts = lowerboundwatts # the minimal cpu wattage
self.k = k # the number of arms
def available_actions(self):
actions = []
pl = self.sensor_manager.get_powerlimits()
logger.info("BanditPowerActuator: power limits %r", pl)
maxW = int(pl[[k for k, i in pl.items()][0]]['maxW'])
if maxW < self.lowerboundwatts:
logger.error("BanditPowerActuator: The provided power lowerbound\
is higher than the available maximum CPU wattage.")
rangeW = maxW - self.lowerboundwatts
arms = [self.lowerboundwatts + (float(a)*rangeW/float(self.k))
for a in range(1, self.k+1)]
logger.info("BanditPowerActuator: discretized power limits: %r:", arms)
actions = [Action([k for k, i in pl.items()][0], int(math.floor(a)), 0)
for a in arms]
return(actions)
def execute(self, action):
logger.info("changing power limit: %r, %r",
action.command, action.delta)
self.sensor_manager.set_powerlimit(action.target, action.command)
def update(self, action):
pass
......@@ -51,34 +88,18 @@ class Controller(object):
"""Implements a control loop for resource management."""
def __init__(self, actuators):
def __init__(self, actuators, strategy):
self.actuators = actuators
def planify(self, target, machineinfo):
"""Plan the next action for the control loop."""
# current_e = float(machineinfo['energy']['energy']['cumulative']['package-0'])/(1000*1000) # in joules
current_p = float(machineinfo['energy']['power']['p0'])/(1000*1000) # in joules
current_p = float(machineinfo['energy']['power']['p1'])/(1000*1000) # in joules
logger_power.info("%s %s %s" % (time.time(),current_p,current_p))
return (None,None)
# direction = None
# if total_power < target:
# direction = 'i'
# elif total_power > target:
# direction = 'd'
# if direction:
# actions = []
# for act in self.actuators:
# newactions = act.available_actions(direction)
# actions.extend([(a, act) for a in newactions])
# if actions:
# # TODO: better choice
# actions.sort(key=lambda x: x[0].delta)
# return actions.pop(0)
# else:
# return (None, None)
# current_e = float(machineinfo['energy']['energy']
# ['cumulative']['package-0'])/(1000*1000) # in joules
# In joules:
current_p = float(machineinfo['energy']['power']['p0'])/(1000*1000)
current_p = float(machineinfo['energy']['power']['p1'])/(1000*1000)
logger_power.info("%s %s %s" % (time.time(), current_p, current_p))
return (None, None)
def execute(self, action, actuator):
"""Build the action for the appropriate manager."""
......
......@@ -2,7 +2,7 @@ from __future__ import print_function
from applications import ApplicationManager
from containers import ContainerManager
from controller import Controller, PowerActuator
from controller import Controller, PowerActuator, DiscretizedPowerActuator
from powerpolicy import PowerPolicyManager
from functools import partial
import json
......@@ -169,7 +169,9 @@ class Daemon(object):
logger.info("sending sensor message: %r", msg)
def do_control(self):
logger.info("Asking controller to plan for target %s using machine info %s" % (self.target, self.machine_info))
logger.info(
"Asking controller to plan for target %s using machine info %s"
% (self.target, self.machine_info))
plan = self.controller.planify(self.target, self.machine_info)
logger.info("Controller chose plan " + str(plan))
action, actuator = plan
......@@ -259,7 +261,6 @@ class Daemon(object):
def do_shutdown(self):
self.sensor_manager.stop()
ioloop.IOLoop.current().stop()
context.term()
def main(self):
# Bind address for downstream clients
......@@ -303,7 +304,8 @@ class Daemon(object):
self.container_manager = ContainerManager(self.resource_manager)
self.application_manager = ApplicationManager()
self.sensor_manager = SensorManager()
pa = PowerActuator(self.sensor_manager)
pa = PowerActuator(self.sensor_manager,
strategy=self.config['powerlevel'])
self.controller = Controller([pa])
self.sensor_manager.start()
......@@ -322,7 +324,6 @@ class Daemon(object):
signal.signal(signal.SIGCHLD, self.do_signal)
ioloop.IOLoop.current().start()
context.term()
def runner(config):
......
......@@ -4,6 +4,7 @@ import logging
import xml.etree.ElementTree
import tornado.process as process
import subprocess
import os
logger = logging.getLogger('nrm')
resources = collections.namedtuple("Resources", ["cpus", "mems"])
......@@ -42,7 +43,14 @@ class NodeOSClient(object):
def __init__(self):
"""Load client configuration."""
self.prefix = "argo_nodeos_config"
if 'ARGO_NODEOS_CONFIG' in os.environ:
logger.info("NodeOSClient: bypassing argo_nodeos_config with %s\n"
% os.environ['ARGO_NODEOS_CONFIG'])
self.prefix = os.environ['ARGO_NODEOS_CONFIG']
else:
logger.info("NodeOSClient: using argo_nodeos_config from path")
self.prefix = "argo_nodeos_config"
def getavailable(self):
"""Gather available resources."""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment