sisfc 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|