sisfc 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.projections.json +12 -0
- data/.travis.yml +6 -0
- data/README.md +37 -19
- data/Rakefile +4 -2
- data/TODO +5 -0
- data/bin/sisfc +29 -6
- data/examples/generator.R +3 -1
- data/examples/simulator.conf +80 -29
- data/lib/sisfc.rb +4 -4
- data/lib/sisfc/configuration.rb +73 -6
- data/lib/sisfc/data_center.rb +42 -29
- data/lib/sisfc/evaluation.rb +23 -15
- data/lib/sisfc/event.rb +9 -6
- data/lib/sisfc/generator.rb +14 -21
- data/lib/sisfc/latency_manager.rb +65 -0
- data/lib/sisfc/logger.rb +28 -0
- data/lib/sisfc/request.rb +42 -85
- data/lib/sisfc/service_type.rb +2 -0
- data/lib/sisfc/simulation.rb +234 -47
- data/lib/sisfc/sorted_array.rb +2 -0
- data/lib/sisfc/statistics.rb +37 -3
- data/lib/sisfc/support/dsl_helper.rb +2 -0
- data/lib/sisfc/version.rb +3 -1
- data/lib/sisfc/vm.rb +46 -27
- data/sisfc.gemspec +9 -5
- data/spec/minitest_helper.rb +9 -0
- data/{test/sisfc/configuration_test.rb → spec/sisfc/configuration_spec.rb} +4 -2
- data/spec/sisfc/data_center_spec.rb +19 -0
- data/{test/sisfc/evaluation_test.rb → spec/sisfc/evaluation_spec.rb} +5 -3
- data/{test/sisfc/generator_test.rb → spec/sisfc/generator_spec.rb} +21 -18
- data/spec/sisfc/latency_manager_spec.rb +13 -0
- data/spec/sisfc/reference_configuration.rb +534 -0
- data/spec/sisfc/request_spec.rb +19 -0
- metadata +115 -49
- data/test/sisfc/reference_configuration.rb +0 -191
- data/test/sisfc/request_test.rb +0 -13
- data/test/test_helper.rb +0 -4
data/lib/sisfc/version.rb
CHANGED
data/lib/sisfc/vm.rb
CHANGED
@@ -1,46 +1,61 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './event'
|
4
|
+
require_relative './logger'
|
2
5
|
require 'erv'
|
3
6
|
|
7
|
+
class RequestInfo < Struct.new(:request, :service_time, :arrival_time)
|
8
|
+
include Comparable
|
9
|
+
def <=> (o)
|
10
|
+
arrival_time <=> o.arrival_time
|
11
|
+
end
|
12
|
+
end
|
4
13
|
|
5
14
|
module SISFC
|
6
15
|
|
7
16
|
class VM
|
17
|
+
include Logging
|
8
18
|
|
9
19
|
# setup readable/accessible attributes
|
10
|
-
|
11
|
-
|
12
|
-
attr_reader *ATTRIBUTES
|
13
|
-
|
14
|
-
def initialize(vmid, opts)
|
15
|
-
# make sure all the required opts were provided
|
16
|
-
[ :dc_id, :vm_size, :service_time_distribution ].each do |k|
|
17
|
-
raise ArgumentError, "opts[:#{k}] missing" unless opts.has_key? k
|
18
|
-
end
|
20
|
+
attr_reader :vmid, :dc_id, :size
|
19
21
|
|
22
|
+
def initialize(vmid, dc_id, size, service_time_distribution, opts={})
|
20
23
|
@vmid = vmid
|
21
|
-
@dcid =
|
22
|
-
@size =
|
23
|
-
@service_times_rv = ERV::RandomVariable.new(
|
24
|
+
@dcid = dc_id
|
25
|
+
@size = size
|
26
|
+
@service_times_rv = ERV::RandomVariable.new(service_time_distribution[@size])
|
24
27
|
|
25
28
|
# initialize request queue and related tracking information
|
26
29
|
@busy = false
|
27
30
|
@request_queue = []
|
28
31
|
|
32
|
+
@trace = opts[:trace] ? true : false
|
33
|
+
@notes = opts[:notes]
|
34
|
+
|
29
35
|
# @request_queue_info = []
|
30
36
|
# @request_currently_servicing = nil
|
31
37
|
end
|
32
38
|
|
33
39
|
def new_request(sim, r, time)
|
34
|
-
# put
|
35
|
-
@request_queue <<
|
40
|
+
# put request w/ metadata at the end of the queue
|
41
|
+
@request_queue << RequestInfo.new(r, @service_times_rv.next, time)
|
42
|
+
|
43
|
+
if @trace
|
44
|
+
@request_queue.each_cons(2) do |x,y|
|
45
|
+
if y[2] < x[2]
|
46
|
+
raise "Inconsistent ordering in request_queue!!!!"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
36
50
|
|
37
51
|
# update queue size tracking information
|
38
|
-
# @request_queue_info << { :
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
try_servicing_new_request(sim, time)
|
52
|
+
# @request_queue_info << { size: @request_queue.size, time: time }
|
53
|
+
if @trace and @request_queue.size % 100 == 0
|
54
|
+
logger.info "VM #{@vmid} with #{@notes} has #{@request_queue.size} requests in queue at time #{time} and is " +
|
55
|
+
(@busy ? "busy" : "not busy")
|
43
56
|
end
|
57
|
+
|
58
|
+
try_servicing_new_request(sim, time) unless @busy
|
44
59
|
end
|
45
60
|
|
46
61
|
def request_finished(sim, time)
|
@@ -64,20 +79,24 @@ module SISFC
|
|
64
79
|
raise "Busy VM (vmid: #{@vmid})!" if @busy
|
65
80
|
|
66
81
|
unless @request_queue.empty?
|
82
|
+
|
67
83
|
# pick request and metadata from the incoming request queue
|
68
|
-
|
84
|
+
ri = @request_queue.shift
|
69
85
|
|
70
|
-
|
71
|
-
|
86
|
+
if @trace
|
87
|
+
logger.info "VM #{@vmid} with #{@notes} fulfilling a new request at time #{time} for #{ri.service_time} seconds"
|
88
|
+
end
|
89
|
+
|
90
|
+
req = ri.request
|
72
91
|
|
73
|
-
# the
|
74
|
-
|
92
|
+
# update the request's queuing information
|
93
|
+
req.update_queuing_time(time - ri.arrival_time)
|
75
94
|
|
76
95
|
# update the request's working information
|
77
|
-
req.step_completed(
|
96
|
+
req.step_completed(ri.service_time)
|
78
97
|
|
79
98
|
# schedule completion of workflow step
|
80
|
-
sim.new_event(Event::ET_WORKFLOW_STEP_COMPLETED, req, time + service_time, self)
|
99
|
+
sim.new_event(Event::ET_WORKFLOW_STEP_COMPLETED, req, time + ri.service_time, self)
|
81
100
|
end
|
82
101
|
end
|
83
102
|
|
data/sisfc.gemspec
CHANGED
@@ -18,10 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency '
|
22
|
-
spec.add_dependency '
|
23
|
-
spec.add_dependency '
|
21
|
+
spec.add_dependency 'as-duration', '~> 0.1.1'
|
22
|
+
spec.add_dependency 'erv', '~> 0.3.5'
|
23
|
+
spec.add_dependency 'ice_nine', '~> 0.11.2'
|
24
24
|
|
25
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
26
|
-
spec.add_development_dependency '
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
26
|
+
spec.add_development_dependency 'dotenv', '~> 2.5'
|
27
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
28
|
+
spec.add_development_dependency 'minitest', '~> 5.11'
|
29
|
+
spec.add_development_dependency 'minitest-reporters', '~> 1.3'
|
30
|
+
spec.add_development_dependency 'minitest-spec-context', '~> 0.0.3'
|
27
31
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest_helper'
|
4
|
+
|
5
|
+
require_relative './reference_configuration'
|
6
|
+
|
7
|
+
|
8
|
+
describe SISFC::DataCenter do
|
9
|
+
it 'should create a valid public Cloud data center' do
|
10
|
+
args = { maximum_vm_capacity: lambda {|vms| true } }
|
11
|
+
dc = SISFC::DataCenter.new(id: :dc_name, name: "Some DC", type: :public, location_id: 1, **args)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should create a valid private Cloud data center' do
|
15
|
+
args = { maximum_vm_capacity: lambda {|vms| true } }
|
16
|
+
dc = SISFC::DataCenter.new(id: :dc_name, name: "Some DC", type: :private, location_id: 1, **args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'minitest_helper'
|
4
|
+
|
5
|
+
require_relative './reference_configuration'
|
4
6
|
|
5
7
|
|
6
8
|
describe SISFC::Evaluator do
|
7
|
-
|
9
|
+
context '.penalties' do
|
8
10
|
EXAMPLE_ALLOCATION = [
|
9
11
|
{ dc_id: 1, vm_size: :medium, vm_num: 20 },
|
10
12
|
{ dc_id: 1, vm_size: :large, vm_num: 30 },
|
@@ -1,20 +1,23 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest_helper'
|
2
4
|
|
3
|
-
require '
|
5
|
+
require 'tempfile'
|
4
6
|
require 'sisfc/generator'
|
5
7
|
|
8
|
+
require_relative './reference_configuration'
|
9
|
+
|
6
10
|
|
7
11
|
describe SISFC::RequestGenerator do
|
8
12
|
|
9
|
-
GENERATION_TIMES
|
10
|
-
|
11
|
-
|
12
|
-
WORKFLOW_IDS = GENERATION_TIMES.map { rand(10) }
|
13
|
+
GENERATION_TIMES = [ Time.now, Time.now + 1.second, Time.now + 2.seconds ].map(&:to_f)
|
14
|
+
WORKFLOW_TYPE_IDS = GENERATION_TIMES.map { rand(10) }
|
15
|
+
CUSTOMER_IDS = GENERATION_TIMES.map { rand(5) }
|
13
16
|
REQUEST_GENERATION_DATA=<<-END
|
14
|
-
Generation Time,
|
15
|
-
#{GENERATION_TIMES[0]},#{
|
16
|
-
#{GENERATION_TIMES[1]},#{
|
17
|
-
#{GENERATION_TIMES[2]},#{
|
17
|
+
Generation Time,Workflow Type ID,Customer ID
|
18
|
+
#{GENERATION_TIMES[0]},#{WORKFLOW_TYPE_IDS[0]},#{CUSTOMER_IDS[0]}
|
19
|
+
#{GENERATION_TIMES[1]},#{WORKFLOW_TYPE_IDS[1]},#{CUSTOMER_IDS[1]}
|
20
|
+
#{GENERATION_TIMES[2]},#{WORKFLOW_TYPE_IDS[2]},#{CUSTOMER_IDS[2]}
|
18
21
|
END
|
19
22
|
|
20
23
|
it 'should read from CSV file' do
|
@@ -27,10 +30,10 @@ describe SISFC::RequestGenerator do
|
|
27
30
|
with_reference_config(request_generation: { filename: tf.path }) do |conf|
|
28
31
|
rg = SISFC::RequestGenerator.new(conf.request_generation)
|
29
32
|
r = rg.generate
|
30
|
-
r
|
31
|
-
r
|
32
|
-
r.
|
33
|
-
r.
|
33
|
+
r[:rid].must_equal 1
|
34
|
+
r[:generation_time].must_equal GENERATION_TIMES[0]
|
35
|
+
r[:workflow_type_id].must_equal WORKFLOW_TYPE_IDS[0]
|
36
|
+
r[:customer_id].must_equal CUSTOMER_IDS[0]
|
34
37
|
end
|
35
38
|
|
36
39
|
ensure
|
@@ -49,10 +52,10 @@ describe SISFC::RequestGenerator do
|
|
49
52
|
with_reference_config(request_generation: { command: "cat #{tf.path}" }) do |conf|
|
50
53
|
rg = SISFC::RequestGenerator.new(conf.request_generation)
|
51
54
|
r = rg.generate
|
52
|
-
r
|
53
|
-
r
|
54
|
-
r.
|
55
|
-
r.
|
55
|
+
r[:rid].must_equal 1
|
56
|
+
r[:generation_time].must_equal GENERATION_TIMES[0]
|
57
|
+
r[:workflow_type_id].must_equal WORKFLOW_TYPE_IDS[0]
|
58
|
+
r[:customer_id].must_equal CUSTOMER_IDS[0]
|
56
59
|
end
|
57
60
|
ensure
|
58
61
|
# delete temporary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest_helper'
|
4
|
+
require 'sisfc/latency_manager'
|
5
|
+
|
6
|
+
require_relative './reference_configuration'
|
7
|
+
|
8
|
+
|
9
|
+
describe SISFC::LatencyManager do
|
10
|
+
it 'should correctly work with reference configuration' do
|
11
|
+
SISFC::LatencyManager.new(LATENCY_MODELS)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,534 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sisfc/configuration'
|
4
|
+
|
5
|
+
START_TIME = Time.utc(1978, 'Aug', 12, 14, 30, 0).to_f
|
6
|
+
DURATION = 1.minute.to_f
|
7
|
+
WARMUP_DURATION = 10.seconds.to_f
|
8
|
+
SIMULATION_CHARACTERIZATION = <<END
|
9
|
+
# start time, duration, and warmup time for simulations
|
10
|
+
start_time Time.utc(1978, 'Aug', 12, 14, 30, 0)
|
11
|
+
duration 1.minute
|
12
|
+
warmup_duration 10.seconds
|
13
|
+
END
|
14
|
+
|
15
|
+
|
16
|
+
# characterization of data centers
|
17
|
+
DATA_CENTERS_CHARACTERIZATION = <<END
|
18
|
+
data_centers \
|
19
|
+
1 => {
|
20
|
+
maximum_vm_capacity: {
|
21
|
+
tiny: 300,
|
22
|
+
small: 300,
|
23
|
+
medium: 300,
|
24
|
+
large: 300,
|
25
|
+
huge: 300,
|
26
|
+
},
|
27
|
+
location_id: 0,
|
28
|
+
},
|
29
|
+
2 => {
|
30
|
+
maximum_vm_capacity: {
|
31
|
+
tiny: 300,
|
32
|
+
small: 300,
|
33
|
+
medium: 300,
|
34
|
+
large: 300,
|
35
|
+
huge: 300,
|
36
|
+
},
|
37
|
+
location_id: 1,
|
38
|
+
},
|
39
|
+
3 => {
|
40
|
+
maximum_vm_capacity: {
|
41
|
+
tiny: 300,
|
42
|
+
small: 300,
|
43
|
+
medium: 300,
|
44
|
+
large: 300,
|
45
|
+
huge: 300,
|
46
|
+
},
|
47
|
+
location_id: 2,
|
48
|
+
},
|
49
|
+
4 => {
|
50
|
+
maximum_vm_capacity: {
|
51
|
+
tiny: 300,
|
52
|
+
small: 300,
|
53
|
+
medium: 300,
|
54
|
+
large: 300,
|
55
|
+
huge: 300,
|
56
|
+
},
|
57
|
+
location_id: 3,
|
58
|
+
},
|
59
|
+
5 => {
|
60
|
+
maximum_vm_capacity: {
|
61
|
+
tiny: 300,
|
62
|
+
small: 300,
|
63
|
+
medium: 300,
|
64
|
+
large: 300,
|
65
|
+
huge: 300,
|
66
|
+
},
|
67
|
+
location_id: 4,
|
68
|
+
}
|
69
|
+
END
|
70
|
+
|
71
|
+
|
72
|
+
LATENCY_MODELS_CHARACTERIZATION = <<END
|
73
|
+
latency_models \
|
74
|
+
[
|
75
|
+
# location 0
|
76
|
+
[
|
77
|
+
{
|
78
|
+
distribution: :gaussian,
|
79
|
+
args: {
|
80
|
+
mean: 0.009,
|
81
|
+
sd: 0.001,
|
82
|
+
},
|
83
|
+
},
|
84
|
+
{
|
85
|
+
distribution: :gaussian,
|
86
|
+
args: {
|
87
|
+
mean: 0.009,
|
88
|
+
sd: 0.001,
|
89
|
+
},
|
90
|
+
},
|
91
|
+
{
|
92
|
+
distribution: :gaussian,
|
93
|
+
args: {
|
94
|
+
mean: 0.009,
|
95
|
+
sd: 0.001,
|
96
|
+
},
|
97
|
+
},
|
98
|
+
{
|
99
|
+
distribution: :gaussian,
|
100
|
+
args: {
|
101
|
+
mean: 0.009,
|
102
|
+
sd: 0.001,
|
103
|
+
},
|
104
|
+
},
|
105
|
+
{
|
106
|
+
distribution: :gaussian,
|
107
|
+
args: {
|
108
|
+
mean: 0.009,
|
109
|
+
sd: 0.001,
|
110
|
+
},
|
111
|
+
},
|
112
|
+
{
|
113
|
+
distribution: :gaussian,
|
114
|
+
args: {
|
115
|
+
mean: 0.009,
|
116
|
+
sd: 0.001,
|
117
|
+
},
|
118
|
+
},
|
119
|
+
{
|
120
|
+
distribution: :gaussian,
|
121
|
+
args: {
|
122
|
+
mean: 0.009,
|
123
|
+
sd: 0.001,
|
124
|
+
},
|
125
|
+
},
|
126
|
+
{
|
127
|
+
distribution: :gaussian,
|
128
|
+
args: {
|
129
|
+
mean: 0.009,
|
130
|
+
sd: 0.001,
|
131
|
+
},
|
132
|
+
},
|
133
|
+
],
|
134
|
+
# location 1
|
135
|
+
[
|
136
|
+
{
|
137
|
+
distribution: :gaussian,
|
138
|
+
args: {
|
139
|
+
mean: 0.009,
|
140
|
+
sd: 0.001,
|
141
|
+
},
|
142
|
+
},
|
143
|
+
{
|
144
|
+
distribution: :gaussian,
|
145
|
+
args: {
|
146
|
+
mean: 0.009,
|
147
|
+
sd: 0.001,
|
148
|
+
},
|
149
|
+
},
|
150
|
+
{
|
151
|
+
distribution: :gaussian,
|
152
|
+
args: {
|
153
|
+
mean: 0.009,
|
154
|
+
sd: 0.001,
|
155
|
+
},
|
156
|
+
},
|
157
|
+
{
|
158
|
+
distribution: :gaussian,
|
159
|
+
args: {
|
160
|
+
mean: 0.009,
|
161
|
+
sd: 0.001,
|
162
|
+
},
|
163
|
+
},
|
164
|
+
{
|
165
|
+
distribution: :gaussian,
|
166
|
+
args: {
|
167
|
+
mean: 0.009,
|
168
|
+
sd: 0.001,
|
169
|
+
},
|
170
|
+
},
|
171
|
+
{
|
172
|
+
distribution: :gaussian,
|
173
|
+
args: {
|
174
|
+
mean: 0.009,
|
175
|
+
sd: 0.001,
|
176
|
+
},
|
177
|
+
},
|
178
|
+
{
|
179
|
+
distribution: :gaussian,
|
180
|
+
args: {
|
181
|
+
mean: 0.009,
|
182
|
+
sd: 0.001,
|
183
|
+
},
|
184
|
+
},
|
185
|
+
],
|
186
|
+
# location 2
|
187
|
+
[
|
188
|
+
{
|
189
|
+
distribution: :gaussian,
|
190
|
+
args: {
|
191
|
+
mean: 0.009,
|
192
|
+
sd: 0.001,
|
193
|
+
},
|
194
|
+
},
|
195
|
+
{
|
196
|
+
distribution: :gaussian,
|
197
|
+
args: {
|
198
|
+
mean: 0.009,
|
199
|
+
sd: 0.001,
|
200
|
+
},
|
201
|
+
},
|
202
|
+
{
|
203
|
+
distribution: :gaussian,
|
204
|
+
args: {
|
205
|
+
mean: 0.009,
|
206
|
+
sd: 0.001,
|
207
|
+
},
|
208
|
+
},
|
209
|
+
{
|
210
|
+
distribution: :gaussian,
|
211
|
+
args: {
|
212
|
+
mean: 0.009,
|
213
|
+
sd: 0.001,
|
214
|
+
},
|
215
|
+
},
|
216
|
+
{
|
217
|
+
distribution: :gaussian,
|
218
|
+
args: {
|
219
|
+
mean: 0.009,
|
220
|
+
sd: 0.001,
|
221
|
+
},
|
222
|
+
},
|
223
|
+
{
|
224
|
+
distribution: :gaussian,
|
225
|
+
args: {
|
226
|
+
mean: 0.009,
|
227
|
+
sd: 0.001,
|
228
|
+
},
|
229
|
+
},
|
230
|
+
],
|
231
|
+
# location 3
|
232
|
+
[
|
233
|
+
{
|
234
|
+
distribution: :gaussian,
|
235
|
+
args: {
|
236
|
+
mean: 0.009,
|
237
|
+
sd: 0.001,
|
238
|
+
},
|
239
|
+
},
|
240
|
+
{
|
241
|
+
distribution: :gaussian,
|
242
|
+
args: {
|
243
|
+
mean: 0.009,
|
244
|
+
sd: 0.001,
|
245
|
+
},
|
246
|
+
},
|
247
|
+
{
|
248
|
+
distribution: :gaussian,
|
249
|
+
args: {
|
250
|
+
mean: 0.009,
|
251
|
+
sd: 0.001,
|
252
|
+
},
|
253
|
+
},
|
254
|
+
{
|
255
|
+
distribution: :gaussian,
|
256
|
+
args: {
|
257
|
+
mean: 0.009,
|
258
|
+
sd: 0.001,
|
259
|
+
},
|
260
|
+
},
|
261
|
+
{
|
262
|
+
distribution: :gaussian,
|
263
|
+
args: {
|
264
|
+
mean: 0.009,
|
265
|
+
sd: 0.001,
|
266
|
+
},
|
267
|
+
},
|
268
|
+
],
|
269
|
+
# location 4
|
270
|
+
[
|
271
|
+
{
|
272
|
+
distribution: :gaussian,
|
273
|
+
args: {
|
274
|
+
mean: 0.009,
|
275
|
+
sd: 0.001,
|
276
|
+
},
|
277
|
+
},
|
278
|
+
{
|
279
|
+
distribution: :gaussian,
|
280
|
+
args: {
|
281
|
+
mean: 0.009,
|
282
|
+
sd: 0.001,
|
283
|
+
},
|
284
|
+
},
|
285
|
+
{
|
286
|
+
distribution: :gaussian,
|
287
|
+
args: {
|
288
|
+
mean: 0.009,
|
289
|
+
sd: 0.001,
|
290
|
+
},
|
291
|
+
},
|
292
|
+
{
|
293
|
+
distribution: :gaussian,
|
294
|
+
args: {
|
295
|
+
mean: 0.009,
|
296
|
+
sd: 0.001,
|
297
|
+
},
|
298
|
+
},
|
299
|
+
],
|
300
|
+
# location 5
|
301
|
+
[
|
302
|
+
{
|
303
|
+
distribution: :gaussian,
|
304
|
+
args: {
|
305
|
+
mean: 0.009,
|
306
|
+
sd: 0.001,
|
307
|
+
},
|
308
|
+
},
|
309
|
+
{
|
310
|
+
distribution: :gaussian,
|
311
|
+
args: {
|
312
|
+
mean: 0.009,
|
313
|
+
sd: 0.001,
|
314
|
+
},
|
315
|
+
},
|
316
|
+
{
|
317
|
+
distribution: :gaussian,
|
318
|
+
args: {
|
319
|
+
mean: 0.009,
|
320
|
+
sd: 0.001,
|
321
|
+
},
|
322
|
+
},
|
323
|
+
],
|
324
|
+
# location 6
|
325
|
+
[
|
326
|
+
{
|
327
|
+
distribution: :gaussian,
|
328
|
+
args: {
|
329
|
+
mean: 0.009,
|
330
|
+
sd: 0.001,
|
331
|
+
},
|
332
|
+
},
|
333
|
+
{
|
334
|
+
distribution: :gaussian,
|
335
|
+
args: {
|
336
|
+
mean: 0.009,
|
337
|
+
sd: 0.001,
|
338
|
+
},
|
339
|
+
},
|
340
|
+
],
|
341
|
+
# location 7
|
342
|
+
[
|
343
|
+
{
|
344
|
+
distribution: :gaussian,
|
345
|
+
args: {
|
346
|
+
mean: 0.009,
|
347
|
+
sd: 0.001,
|
348
|
+
},
|
349
|
+
},
|
350
|
+
],
|
351
|
+
]
|
352
|
+
END
|
353
|
+
|
354
|
+
|
355
|
+
CUSTOMER_CHARACTERIZATION = <<END
|
356
|
+
customers \
|
357
|
+
[
|
358
|
+
# first customer (id: 0) is in location with id=5 (?)
|
359
|
+
{ location_id: 5 },
|
360
|
+
# second customer (id: 1) is in location with id=6 (?)
|
361
|
+
{ location_id: 6 },
|
362
|
+
# third customer (id: 2) is in location with id=7 (?)
|
363
|
+
{ location_id: 7 },
|
364
|
+
# fourth customer (id: 3) is in location with id=8 (?)
|
365
|
+
{ location_id: 8 },
|
366
|
+
]
|
367
|
+
END
|
368
|
+
|
369
|
+
|
370
|
+
# characterization of component types
|
371
|
+
SERVICE_COMPONENT_TYPES_CHARACTERIZATION = <<END
|
372
|
+
service_component_types \
|
373
|
+
'Web Server' => {
|
374
|
+
allowed_vm_types: [ :medium, :large ],
|
375
|
+
service_time_distribution: {
|
376
|
+
medium: { distribution: :gaussian,
|
377
|
+
mean: 0.009, # 1 request processed every 9ms
|
378
|
+
sd: 0.001 },
|
379
|
+
large: { distribution: :gaussian,
|
380
|
+
mean: 0.007, # 1 request processed every 7ms
|
381
|
+
sd: 0.001 } },
|
382
|
+
estimated_workload: 50,
|
383
|
+
},
|
384
|
+
'App Server' => {
|
385
|
+
allowed_vm_types: [ :medium, :large, :huge ],
|
386
|
+
service_time_distribution: {
|
387
|
+
medium: { distribution: :gaussian,
|
388
|
+
mean: 0.015, # 1 request processed every 15ms
|
389
|
+
sd: 0.005 },
|
390
|
+
large: { distribution: :gaussian,
|
391
|
+
mean: 0.012, # 1 request processed every 12ms
|
392
|
+
sd: 0.003 },
|
393
|
+
huge: { distribution: :gaussian,
|
394
|
+
mean: 0.009, # 1 request processed every 7ms
|
395
|
+
sd: 0.002 } },
|
396
|
+
estimated_workload: 70,
|
397
|
+
},
|
398
|
+
'Financial Transaction Server' => {
|
399
|
+
allowed_vm_types: [ :large, :huge ],
|
400
|
+
service_time_distribution: {
|
401
|
+
large: { distribution: :gaussian,
|
402
|
+
mean: 0.015, # 1 request processed every 15ms
|
403
|
+
sd: 0.004 },
|
404
|
+
huge: { distribution: :gaussian,
|
405
|
+
mean: 0.008, # 1 request processed every 8ms
|
406
|
+
sd: 0.003 } },
|
407
|
+
estimated_workload: 80,
|
408
|
+
}
|
409
|
+
END
|
410
|
+
|
411
|
+
|
412
|
+
# workflow (or job) types descriptions
|
413
|
+
WORKFLOW_TYPES_CHARACTERIZATION = <<END
|
414
|
+
workflow_types \
|
415
|
+
1 => {
|
416
|
+
component_sequence: [
|
417
|
+
{ name: 'Web Server' },
|
418
|
+
{ name: 'App Server' },
|
419
|
+
{ name: 'Financial Transaction Server' },
|
420
|
+
],
|
421
|
+
next_component_selection: :random,
|
422
|
+
},
|
423
|
+
2 => {
|
424
|
+
component_sequence: [
|
425
|
+
{ name: 'Web Server' },
|
426
|
+
{ name: 'App Server' },
|
427
|
+
],
|
428
|
+
# next_component_selection: :least_loaded,
|
429
|
+
next_component_selection: :random,
|
430
|
+
}
|
431
|
+
END
|
432
|
+
|
433
|
+
|
434
|
+
CONSTRAINT_CHARACTERIZATION = <<END
|
435
|
+
constraints \
|
436
|
+
'Web Server' => [
|
437
|
+
{ data_center: 1, min: 0, max: 300 },
|
438
|
+
{ data_center: 2, min: 0, max: 300 },
|
439
|
+
{ data_center: 3, min: 0, max: 300 },
|
440
|
+
{ data_center: 4, min: 0, max: 300 },
|
441
|
+
{ data_center: 5, min: 0, max: 300 },
|
442
|
+
],
|
443
|
+
'App Server' => [
|
444
|
+
{ data_center: 1, min: 0, max: 300 },
|
445
|
+
{ data_center: 2, min: 0, max: 300 },
|
446
|
+
{ data_center: 3, min: 0, max: 300 },
|
447
|
+
{ data_center: 4, min: 0, max: 300 },
|
448
|
+
{ data_center: 5, min: 0, max: 300 },
|
449
|
+
],
|
450
|
+
'Financial Transaction Server' => [
|
451
|
+
{ data_center: 1, number: 1 },
|
452
|
+
{ data_center: 2, number: 0 },
|
453
|
+
{ data_center: 3, number: 0 },
|
454
|
+
{ data_center: 4, number: 0 },
|
455
|
+
{ data_center: 5, number: 0 },
|
456
|
+
]
|
457
|
+
END
|
458
|
+
|
459
|
+
|
460
|
+
REQUEST_GENERATION_CHARACTERIZATION = <<END
|
461
|
+
request_generation \
|
462
|
+
command: "<pwd>/generator.R"
|
463
|
+
END
|
464
|
+
|
465
|
+
|
466
|
+
KPI_CUSTOMIZATION_CHARACTERIZATION = <<END
|
467
|
+
kpi_customization \
|
468
|
+
longer_than: [ 2.0, 5.0 ] # count number of requests longer than 2 and 5 seconds respectively
|
469
|
+
END
|
470
|
+
|
471
|
+
|
472
|
+
EVALUATION_CHARACTERIZATION = <<END
|
473
|
+
evaluation \
|
474
|
+
vm_hourly_cost: [
|
475
|
+
{ data_center: 1, vm_type: :medium, cost: 0.160 },
|
476
|
+
{ data_center: 1, vm_type: :large, cost: 0.320 },
|
477
|
+
{ data_center: 2, vm_type: :medium, cost: 0.184 },
|
478
|
+
{ data_center: 2, vm_type: :large, cost: 0.368 }
|
479
|
+
],
|
480
|
+
# 500$ penalties if MTTR takes more than 50 msecs
|
481
|
+
penalties: lambda {|kpis,dc_kpis| 500.0 if kpis[:mttr] > 0.050 }
|
482
|
+
END
|
483
|
+
|
484
|
+
# this is the whole reference configuration
|
485
|
+
# (useful for spec'ing configuration.rb)
|
486
|
+
REFERENCE_CONFIGURATION =
|
487
|
+
SIMULATION_CHARACTERIZATION +
|
488
|
+
DATA_CENTERS_CHARACTERIZATION +
|
489
|
+
LATENCY_MODELS_CHARACTERIZATION +
|
490
|
+
CUSTOMER_CHARACTERIZATION +
|
491
|
+
SERVICE_COMPONENT_TYPES_CHARACTERIZATION +
|
492
|
+
WORKFLOW_TYPES_CHARACTERIZATION +
|
493
|
+
CONSTRAINT_CHARACTERIZATION +
|
494
|
+
REQUEST_GENERATION_CHARACTERIZATION +
|
495
|
+
KPI_CUSTOMIZATION_CHARACTERIZATION +
|
496
|
+
EVALUATION_CHARACTERIZATION
|
497
|
+
|
498
|
+
|
499
|
+
evaluator = Object.new
|
500
|
+
evaluator.extend SISFC::Configurable
|
501
|
+
evaluator.instance_eval(REFERENCE_CONFIGURATION)
|
502
|
+
|
503
|
+
# these are preprocessed portions of the reference configuration
|
504
|
+
# (useful for spec'ing everything else)
|
505
|
+
DATA_CENTERS = evaluator.data_centers
|
506
|
+
SERVICE_COMPONENT_TYPES = evaluator.service_component_types
|
507
|
+
WORKFLOW_TYPES = evaluator.workflow_types
|
508
|
+
EVALUATION = evaluator.evaluation
|
509
|
+
LATENCY_MODELS = evaluator.latency_models
|
510
|
+
|
511
|
+
|
512
|
+
def with_reference_config(opts={})
|
513
|
+
begin
|
514
|
+
# create temporary file with reference configuration
|
515
|
+
tf = Tempfile.open('REFERENCE_CONFIGURATION')
|
516
|
+
tf.write(REFERENCE_CONFIGURATION)
|
517
|
+
tf.close
|
518
|
+
|
519
|
+
# create a configuration object from the reference configuration file
|
520
|
+
conf = SISFC::Configuration.load_from_file(tf.path)
|
521
|
+
|
522
|
+
# apply any change from the opts parameter and validate the modified configuration
|
523
|
+
opts.each do |k,v|
|
524
|
+
conf.send(k, v)
|
525
|
+
end
|
526
|
+
conf.validate
|
527
|
+
|
528
|
+
# pass the configuration object to the block
|
529
|
+
yield conf
|
530
|
+
ensure
|
531
|
+
# delete temporary file
|
532
|
+
tf.delete
|
533
|
+
end
|
534
|
+
end
|