Skip to content

Commit aa352b7

Browse files
committed
Merge branch 'update-0.2'
2 parents e862ec8 + b0b56ef commit aa352b7

37 files changed

+3044
-23
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,5 @@ target/
5959

6060
.DS_Store
6161
conf/gvas.yaml
62+
docs/slate
63+
.ipynb_checkpoints

conf/gvas-example.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,30 @@
1313
## Set application environment
1414
debug: True
1515
testing: False
16+
17+
## Visualization parameters
18+
vizualization:
19+
# The Seaborn style can be one of darkgrid, whitegrid, dark, white, ticks
20+
style: whitegrid
21+
22+
# The Seaborn context can be one of paper, notebook, talk, poster
23+
context: paper
24+
25+
# The Seaborn palette can be one of null, deep, muted, pastel, bright, dark, or colorblind
26+
palette: null
27+
28+
## Global simulation parameters
29+
random_seed: 42
30+
max_sim_time: 1000
31+
32+
defaults:
33+
network:
34+
capacity: 500
35+
base_latency: 10
36+
cluster:
37+
size: 4
38+
rack:
39+
size: 96
40+
node:
41+
cpus: 4
42+
memory: 16

gvas/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
__version_info__ = {
2626
'major': 0,
27-
'minor': 1,
27+
'minor': 2,
2828
'micro': 0,
2929
'releaselevel': 'final',
3030
'serial': 0,

gvas/base.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# gvas.base
2+
# The base API for simulation processes and scripts.
3+
#
4+
# Author: Benjamin Bengfort <[email protected]>
5+
# Created: Mon Nov 23 17:40:57 2015 -0500
6+
#
7+
# Copyright (C) 2015 University of Maryland
8+
# For license information, see LICENSE.txt
9+
#
10+
# ID: base.py [] [email protected] $
11+
12+
"""
13+
The base API for simulation processes and scripts.
14+
"""
15+
16+
##########################################################################
17+
## Imports
18+
##########################################################################
19+
20+
import simpy
21+
import random
22+
23+
from gvas.config import settings
24+
from gvas.dynamo import Sequence
25+
26+
##########################################################################
27+
## Base Process Objects
28+
##########################################################################
29+
30+
31+
class Process(object):
32+
"""
33+
Base process object.
34+
"""
35+
36+
def __init__(self, env):
37+
self.env = env
38+
self.action = env.process(self.run())
39+
40+
def run(self):
41+
raise NotImplementedError("Processes must implement a run method.")
42+
43+
44+
class NamedProcess(Process):
45+
"""
46+
A process with a sequence counter and self identification.
47+
"""
48+
49+
counter = Sequence()
50+
51+
def __init__(self, env):
52+
self._id = self.counter.next()
53+
super(NamedProcess, self).__init__(env)
54+
55+
@property
56+
def name(self):
57+
return "{} #{}".format(self.__class__.__name__, self._id)
58+
59+
60+
##########################################################################
61+
## Base Simulation Script
62+
##########################################################################
63+
64+
class Simulation(object):
65+
"""
66+
Defines a script that every simulation implements.
67+
"""
68+
69+
def __init__(self, **kwargs):
70+
"""
71+
Instantiates the simpy environment and other configurations.
72+
"""
73+
random.seed(kwargs.get('random_seed', settings.random_seed))
74+
75+
self.max_sim_time = kwargs.get('max_sim_time', settings.max_sim_time)
76+
self.env = simpy.Environment()
77+
78+
def script(self):
79+
"""
80+
Use the environment to generate a script.
81+
"""
82+
raise NotImplementedError("Every simulation requires a script.")
83+
84+
def run(self):
85+
"""
86+
The entry point for all simulations.
87+
"""
88+
self.script()
89+
self.env.run(until=self.max_sim_time)

gvas/cluster/__init__.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# gvas.cluster
2+
# Simulation classes to model distributed system components.
3+
#
4+
# Author: Allen Leis <[email protected]>
5+
# Created: Fri Dec 04 16:48:51 2015 -0500
6+
#
7+
# Copyright (C) 2015 Allen Leis
8+
# For license information, see LICENSE.txt
9+
#
10+
# ID: __init__.py [] [email protected] $
11+
12+
"""
13+
Simulation classes to model distributed system components.
14+
"""
15+
16+
##########################################################################
17+
# Imports
18+
##########################################################################
19+
20+
from .cluster import Cluster
21+
from .rack import Rack
22+
from .node import Node
23+
from .program import Program
24+
25+
##########################################################################
26+
# Execution
27+
##########################################################################
28+
29+
if __name__ == '__main__':
30+
pass

gvas/cluster/base.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# gvas.cluster.base
2+
# Base classes for cluster simulation framework.
3+
#
4+
# Author: Allen Leis <[email protected]>
5+
# Created: Fri Dec 04 16:49:32 2015 -0500
6+
#
7+
# Copyright (C) 2015 Allen Leis
8+
# For license information, see LICENSE.txt
9+
#
10+
# ID: base.py [] [email protected] $
11+
12+
"""
13+
Base classes for cluster simulation framework.
14+
"""
15+
16+
##########################################################################
17+
# Imports
18+
##########################################################################
19+
20+
from gvas.base import NamedProcess
21+
from .network import Network
22+
23+
##########################################################################
24+
# Classes
25+
##########################################################################
26+
27+
class Machine(NamedProcess):
28+
29+
def __init__(self, env, *args, **kwargs):
30+
self._network = Network.create(env, parent=self).next()
31+
super(Machine, self).__init__(env)
32+
33+
@classmethod
34+
def create(self, *args, **kwargs):
35+
"""
36+
Generalized factory method to return a generator that can produce
37+
new instances.
38+
"""
39+
raise NotImplementedError('Subclasses should override this method.')
40+
41+
def send(self, *args, **kwargs):
42+
"""
43+
Generalized method to put message onto the contained network.
44+
"""
45+
raise NotImplementedError('Subclasses should override this method.')
46+
47+
def recv(self, *args, **kwargs):
48+
"""
49+
Generalized method to obtain a message from the contained network.
50+
"""
51+
raise NotImplementedError('Subclasses should override this method.')
52+
53+
@property
54+
def network(self):
55+
"""
56+
Returns a reference to the underlying Network instance
57+
"""
58+
return self._network
59+
60+
61+
##########################################################################
62+
# Execution
63+
##########################################################################
64+
65+
if __name__ == '__main__':
66+
pass

gvas/cluster/cluster.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# gvas.cluster.cluster
2+
# Simulation class to model a cluster of resources.
3+
#
4+
# Author: Allen Leis <[email protected]>
5+
# Created: Fri Dec 04 16:50:27 2015 -0500
6+
#
7+
# Copyright (C) 2015 Allen Leis
8+
# For license information, see LICENSE.txt
9+
#
10+
# ID: cluster.py [] [email protected] $
11+
12+
"""
13+
Simulation class to model a cluster of resources.
14+
"""
15+
16+
##########################################################################
17+
# Imports
18+
##########################################################################
19+
20+
from gvas.config import settings
21+
from gvas.exceptions import ClusterLacksCapacity
22+
from .base import Machine
23+
from .rack import Rack
24+
from .node import Node
25+
26+
##########################################################################
27+
# Classes
28+
##########################################################################
29+
30+
class Cluster(Machine):
31+
32+
def __init__(self, env, *args, **kwargs):
33+
rack_options = kwargs.get('rack_options', {})
34+
node_options = kwargs.get('node_options', {})
35+
self.rack_generator = kwargs.get(
36+
'rack_generator',
37+
Rack.create(
38+
env,
39+
cluster=self,
40+
node_options=node_options,
41+
**rack_options
42+
)
43+
)
44+
self.size = kwargs.get(
45+
'size',
46+
settings.defaults.cluster.size
47+
)
48+
node_options = kwargs.get('node_options', {})
49+
self.node_generator = kwargs.get(
50+
'node_generator',
51+
Node.create(env, **node_options)
52+
)
53+
54+
racks = [self.rack_generator.next() for i in range(self.size)]
55+
self.racks = dict((r.id, r) for r in racks)
56+
super(self.__class__, self).__init__(env, *args, **kwargs)
57+
58+
@classmethod
59+
def create(cls, env, *args, **kwargs):
60+
"""
61+
Generalized factory method to return a generator that can produce
62+
new instances.
63+
"""
64+
while True:
65+
yield cls(env, *args, **kwargs)
66+
67+
def filter(self, evaluator):
68+
"""
69+
Uses the evaluator function to test against the Node instances and
70+
return a list of matches.
71+
"""
72+
pass
73+
74+
def first(self, evaluator):
75+
"""
76+
Uses the evaluator function to test against the Node instances and
77+
return the first match.
78+
"""
79+
pass
80+
81+
def send(self, *args, **kwargs):
82+
"""
83+
Generalized method to put message onto the contained network.
84+
"""
85+
pass
86+
87+
def recv(self, *args, **kwargs):
88+
"""
89+
Generalized method to obtain a message from the contained network.
90+
"""
91+
pass
92+
93+
def add(self, node=None, rack=None, rack_id=None):
94+
"""
95+
Adds a node to the cluster. Will add the node to the specified rack or
96+
rack_id. Otherwise, will choose the first rack with available space.
97+
"""
98+
if not rack:
99+
if rack_id:
100+
rack = self.racks[rack_id]
101+
rack = self.first_available_rack
102+
103+
if not node:
104+
node = self.node_generator.next()
105+
106+
rack.add(node)
107+
return node
108+
109+
110+
def remove(self, node):
111+
"""
112+
Removes a node from the cluster.
113+
"""
114+
pass
115+
116+
def run(self):
117+
"""
118+
Method to kickoff process simulation.
119+
"""
120+
# TODO: placeholder code
121+
yield self.env.timeout(1)
122+
123+
@property
124+
def id(self):
125+
"""
126+
The unqiue identifier for this instance.
127+
128+
Note that the _id property is initially set in the NamedProcess
129+
ancestor class and so all subclasses may share the same Sequence.
130+
"""
131+
return self._id
132+
133+
@property
134+
def first_available_rack(self):
135+
"""
136+
137+
"""
138+
ids = sorted(self.racks.keys())
139+
140+
for id in ids:
141+
if not self.racks[id].full:
142+
return self.racks[id]
143+
144+
else:
145+
raise ClusterLacksCapacity()
146+
147+
148+
149+
150+
151+
152+
153+
154+
##########################################################################
155+
# Execution
156+
##########################################################################
157+
158+
if __name__ == '__main__':
159+
pass

0 commit comments

Comments
 (0)