Commit e9848601 authored by Swann Perarnau's avatar Swann Perarnau

Merge branch 'power-cli' into 'master'

Basic implementation of the command line interface, power API improvements

See merge request !2
parents 15437f00 63db906e
#!/usr/bin/env python2
from __future__ import print_function
import argparse
import logging
import uuid
import signal
import zmq
class CommandLineInterface(object):
"""Implements a command line interface to the NRM."""
def __init__(self):
self.logger = logging.getLogger(__name__)
def do_signal(self):
pass
def setup(self):
# SUB port to the upstream API (connected to its PUB port)
upstream_sub_port = 2345
# PUB port to the upstream API (connected to its SUB port)
upstream_pub_port = 3456
self.context = zmq.Context()
self.upstream_pub_socket = self.context.socket(zmq.PUB)
self.upstream_sub_socket = self.context.socket(zmq.SUB)
upstream_pub_param = "tcp://*:%d" % (upstream_pub_port)
upstream_sub_param = "tcp://localhost:%d" % (upstream_sub_port)
self.upstream_pub_socket.bind(upstream_pub_param)
self.upstream_sub_socket.connect(upstream_sub_param)
# we want to receive everything for now
upstream_sub_filter = ""
self.upstream_sub_socket.setsockopt(zmq.SUBSCRIBE, upstream_sub_filter)
self.logger.info("upstream pub socket bound to: %s",
upstream_pub_param)
self.logger.info("upstream sub socket connected to: %s",
upstream_sub_param)
# take care of signals
signal.signal(signal.SIGINT, self.do_signal)
# create a uuid for this client instance
self.uuid = str(uuid.uuid4())
self.logger.info("client uuid: %r", self.uuid)
def do_run(self, argv):
pass
def do_setpower(self, argv):
""" Connect to the NRM and ask to change the power limit.
The NRM should answer on the pub socket with an acknowledgment."""
# build the command as a JSON dict giving enough info. This is an
# idempotent command, so we will repeat the command if we don't get a
# timely answer.
# TODO: check that the level makes a little bit of sense in the first
# place
command = {'command': 'setpower',
'limit': argv.limit,
}
while(True):
self.upstream_pub_socket.send_json(command)
msg = self.upstream_sub_socket.recv_json()
self.logger.info("new message: %r", msg)
# ignore other messages
if isinstance(msg, dict) and msg.get('type') == 'power':
if msg['limit'] == argv.limit:
self.logger.info("command received by the daemon")
break
def main(self):
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose",
help="verbose logging information",
action='store_true')
subparsers = parser.add_subparsers()
# run container
parser_run = subparsers.add_parser("run")
parser_run.add_argument("container")
parser_run.set_defaults(func=self.do_run)
# setpowerlimit
parser_setpower = subparsers.add_parser("setpower")
parser_setpower.add_argument("-f", "--follow",
help="listen for power changes",
action='store_true')
parser_setpower.add_argument("limit",
help="set new power limit",
type=float)
parser_setpower.set_defaults(func=self.do_setpower)
args = parser.parse_args()
if args.verbose:
self.logger.setLevel(logging.DEBUG)
self.setup()
args.func(args)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
cli = CommandLineInterface()
cli.main()
from __future__ import print_function
import json
import logging
import re
import signal
......@@ -95,18 +96,26 @@ class Daemon(object):
self.logger.info("application now in state: %s",
application.state)
def do_upstream_receive(self, msg):
self.logger.info("receiving upstream message: %r", msg)
self.target = int(msg.split()[1])
self.logger.info("target measure: %g", self.target)
def do_upstream_receive(self, parts):
self.logger.info("receiving upstream message: %r", parts)
if len(parts) != 1:
self.logger.error("unexpected msg length, droping it: %r", parts)
return
msg = json.loads(parts[0])
if isinstance(msg, dict) and msg.get('command') == 'setpower':
self.target = float(msg['limit'])
self.logger.info("new target measure: %g", self.target)
def do_sensor(self):
self.machine_info = self.sensor.do_update()
self.logger.info("current state: %r", self.machine_info)
total_power = self.machine_info['energy']['power']['total']
msg = "23.45 %g" % (total_power)
self.upstream_pub.send_string(msg)
self.logger.info("Sending power values: %r", msg)
msg = {'type': 'power',
'total': total_power,
'limit': self.target
}
self.upstream_pub.send_json(msg)
self.logger.info("sending sensor message: %r", msg)
def do_control(self):
total_power = self.machine_info['energy']['power']['total']
......@@ -154,7 +163,7 @@ class Daemon(object):
downstream_socket.bind(downstream_bind_param)
upstream_pub_socket.bind(upstream_pub_param)
upstream_sub_socket.connect(upstream_sub_param)
upstream_sub_filter = "34.56 "
upstream_sub_filter = ""
upstream_sub_socket.setsockopt(zmq.SUBSCRIBE, upstream_sub_filter)
self.logger.info("downstream socket bound to: %s",
......
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