aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSander Vrijders <sander.vrijders@intec.ugent.be>2017-05-11 13:15:10 +0000
committerSander Vrijders <sander.vrijders@intec.ugent.be>2017-05-11 13:15:10 +0000
commitbb0fb67c1fc525e0b9aa17b5e39d385c8601dfae (patch)
treefb4936363884896463aa446ac5baa5f79a7e1061
parentbf9a98603c8fc8dd8f15a7d54ffb2111fc6428a9 (diff)
parent10da73cd31a26ad2b4a95bb1ec3d02f6afc57dc6 (diff)
downloadrumba-bb0fb67c1fc525e0b9aa17b5e39d385c8601dfae.tar.gz
rumba-bb0fb67c1fc525e0b9aa17b5e39d385c8601dfae.zip
Merge branch 'sander' into 'master'
StoryBoard API proposal See merge request !45
-rwxr-xr-xexamples/example.py20
-rw-r--r--rumba/model.py127
2 files changed, 136 insertions, 11 deletions
diff --git a/examples/example.py b/examples/example.py
index 56193c2..1acc883 100755
--- a/examples/example.py
+++ b/examples/example.py
@@ -17,7 +17,6 @@ import rumba.prototypes.irati as irati
import rumba.log as log
-
log.set_logging_level('DEBUG')
n1 = NormalDIF("n1", policies = {"rmt.pff": "lfa",
@@ -27,19 +26,16 @@ e1 = ShimEthDIF("e1")
a = Node("a",
difs = [n1, e1],
- dif_registrations = {n1 : [e1]},
- registrations = {"a.crap" : [n1]},
- bindings = {"a.crap" : "/usr/bin/crap"})
+ dif_registrations = {n1 : [e1]})
b = Node("b",
difs = [e1, n1],
- dif_registrations = {n1 : [e1]})
+ dif_registrations = {n1 : [e1]},
+ client = True)
-tb = qemu.Testbed(exp_name = "example1",
- username = "root",
- password = "root",
- bzimage = '/home/vmaffione/git/rlite/demo/buildroot/bzImage',
- initramfs = '/home/vmaffione/git/rlite/demo/buildroot/rootfs.cpio')
+tb = jfed.Testbed(exp_name = "example1",
+ username = "user1",
+ cert_file = "/home/user1/cert.pem")
exp = rl.Experiment(tb, nodes = [a, b])
@@ -48,5 +44,9 @@ print(exp)
try:
exp.swap_in()
exp.bootstrap_prototype()
+ c1 = Client("rinaperf", options ="-t perf -s 1000 -c 10000")
+ s1 = Server("rinaperf", arrival_rate=2, mean_duration=5, options = "-l", nodes = [a], clients = [c1])
+ sb = StoryBoard(exp, 3600, servers = [s1])
+ sb.start()
finally:
exp.swap_out()
diff --git a/rumba/model.py b/rumba/model.py
index 0b9fc7a..285d937 100644
--- a/rumba/model.py
+++ b/rumba/model.py
@@ -20,6 +20,9 @@
# MA 02110-1301 USA
import abc
+import random
+
+import time
import rumba.log as log
@@ -152,7 +155,7 @@ class SSHConfig:
#
class Node:
def __init__(self, name, difs=None, dif_registrations=None,
- registrations=None, bindings=None):
+ registrations=None, bindings=None, client=False):
self.name = name
if difs is None:
difs = list()
@@ -170,6 +173,7 @@ class Node:
self.bindings = bindings
self.ssh_config = SSHConfig(name)
self.ipcps = []
+ self.client = client
self._validate()
@@ -564,3 +568,124 @@ class Experiment:
def swap_out(self):
# Undo the testbed (testbed-specific)
self.testbed.swap_out(self)
+
+
+# Base class for client programs
+#
+# @ap: Application Process binary
+# @options: Options to pass to the binary
+#
+class Client(object):
+ def __init__(self, ap, options=None):
+ self.ap = ap
+ self.options = options
+
+ def start_process(self, node, duration, start_time):
+ return ClientProcess(self.ap, node, duration, start_time, self.options)
+
+
+# Base class for client processes
+#
+# @ap: Application Process binary
+# @node: The node on which this process should run
+# @duration: The time (in seconds) this process should run
+# @start_time: The time at which this process is started.
+# @options: Options to pass to the binary
+#
+class ClientProcess(Client):
+ def __init__(self, ap, node, duration, start_time, options=None):
+ super(ClientProcess, self).__init__(ap, options=options)
+ self.node = node
+ self.duration = duration
+ self.start_time = start_time
+ self.run()
+ self.running = True
+
+ def run(self):
+ pass # TODO to be implemented
+
+ def stop(self):
+ pass # TODO to be implemented
+
+ def check(self, now):
+ if not self.running:
+ return
+ if now - self.start_time >= self.duration:
+ self.stop()
+
+
+# Base class for server programs
+#
+# @ap: Application Process binary
+# @arrival_rate: Average requests/s to be received by this server
+# @mean_duration: Average duration of a client connection (in seconds)
+# @options: Options to pass to the binary
+# @max_clients: Maximum number of clients to serve
+# @clients: Client binaries that will use this server
+# @nodes: Specific nodes to start this server on
+#
+class Server:
+ def __init__(self, ap, arrival_rate, mean_duration,
+ options=None, max_clients=None,
+ clients=None, nodes=None):
+ self.ap = ap
+ self.options = options
+ self.max_clients = max_clients
+ if clients is None:
+ clients = list()
+ self.clients = clients
+ self.nodes = nodes
+ self.arrival_rate = arrival_rate # mean requests/s
+ self.mean_duration = mean_duration # in seconds
+
+ def add_client(self, client):
+ self.clients.append(client)
+
+ def del_client(self, client):
+ self.clients.remove(client)
+
+ def add_node(self, node):
+ self.nodes.append(node)
+
+ def del_node(self, node):
+ self.nodes.remove(node)
+
+ def get_new_clients(self, interval):
+ """
+ Returns a list of clients of size appropriate to the server's rate.
+
+ The list's size should be a sample from Poisson(arrival_rate) over
+ interval seconds.
+ Hence, the average size should be interval * arrival_rate.
+ """
+ pass
+
+ def make_client_process(self):
+ """Returns a client of this server"""
+ if len(self.clients) == 0:
+ raise Exception("Server %s has empty client list," % (self,))
+ pass # TODO should return a ClientProcess
+
+
+# Base class for ARCFIRE storyboards
+#
+# @experiment: Experiment to use as input
+# @duration: Duration of the whole storyboard
+# @servers: App servers available in the network
+#
+class StoryBoard:
+ def __init__(self, experiment, duration, servers=None):
+ self.experiment = experiment
+ self.duration = duration
+ if servers is None:
+ servers = list()
+ self.servers = servers
+
+ def add_server(self, server):
+ self.servers.append(server)
+
+ def del_server(self, server):
+ self.servers.remove(server)
+
+ def start(self):
+ pass