1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
16
|
|
17
|
|
18
|
|
19
|
from haizea.common.config import ConfigException, Section, Option, Config, OPTTYPE_INT, OPTTYPE_FLOAT, OPTTYPE_STRING, OPTTYPE_BOOLEAN, OPTTYPE_DATETIME, OPTTYPE_TIMEDELTA
|
20
|
from haizea.common.utils import generate_config_name
|
21
|
import haizea.common.constants as constants
|
22
|
import haizea.common.defaults as defaults
|
23
|
import sys
|
24
|
from mx.DateTime import TimeDelta
|
25
|
import ConfigParser
|
26
|
|
27
|
class HaizeaConfig(Config):
|
28
|
|
29
|
sections = []
|
30
|
|
31
|
|
32
|
|
33
|
|
34
|
|
35
|
|
36
|
|
37
|
general = Section("general", required=True,
|
38
|
doc = "This section is used for general options affecting Haizea as a whole.")
|
39
|
general.options = \
|
40
|
[
|
41
|
Option(name = "loglevel",
|
42
|
getter = "loglevel",
|
43
|
type = OPTTYPE_STRING,
|
44
|
required = False,
|
45
|
default = "INFO",
|
46
|
valid = ["STATUS","INFO","DEBUG","VDEBUG"],
|
47
|
doc = """
|
48
|
Controls the level (and amount) of
|
49
|
log messages. Valid values are:
|
50
|
|
51
|
- STATUS: Only print status messages
|
52
|
- INFO: Slightly more verbose that STATUS
|
53
|
- DEBUG: Prints information useful for debugging the scheduler.
|
54
|
- VDEBUG: Prints very verbose information
|
55
|
on the scheduler's internal data structures. Use only
|
56
|
for short runs.
|
57
|
"""),
|
58
|
|
59
|
Option(name = "logfile",
|
60
|
getter = "logfile",
|
61
|
type = OPTTYPE_STRING,
|
62
|
required = False,
|
63
|
default = "/var/tmp/haizea.log",
|
64
|
doc = """
|
65
|
When running Haizea as a daemon, this option specifies the file
|
66
|
that log messages should be written to.
|
67
|
"""),
|
68
|
|
69
|
Option(name = "mode",
|
70
|
getter = "mode",
|
71
|
type = OPTTYPE_STRING,
|
72
|
required = True,
|
73
|
valid = ["simulated","opennebula"],
|
74
|
doc = """
|
75
|
Sets the mode the scheduler will run in.
|
76
|
Currently the only valid values are "simulated" and
|
77
|
"opennebula". The "simulated" mode expects lease
|
78
|
requests to be provided through a trace file, and
|
79
|
all enactment is simulated. The "opennebula" mode
|
80
|
interacts with the OpenNebula virtual infrastructure
|
81
|
manager (http://www.opennebula.org/) to obtain lease
|
82
|
requests and to do enactment on physical resources.
|
83
|
"""),
|
84
|
|
85
|
Option(name = "lease-preparation",
|
86
|
getter = "lease-preparation",
|
87
|
type = OPTTYPE_STRING,
|
88
|
required = False,
|
89
|
default = constants.PREPARATION_UNMANAGED,
|
90
|
valid = [constants.PREPARATION_UNMANAGED,
|
91
|
constants.PREPARATION_TRANSFER],
|
92
|
doc = """
|
93
|
Sets how the scheduler will handle the
|
94
|
preparation overhead of leases. Valid values are:
|
95
|
|
96
|
- unmanaged: The scheduler can assume that there
|
97
|
is no deployment overhead, or that some
|
98
|
other entity is taking care of it (e.g., one
|
99
|
of the enactment backends)
|
100
|
- imagetransfer: A disk image has to be transferred
|
101
|
from a repository node before the lease can start.
|
102
|
"""),
|
103
|
|
104
|
Option(name = "lease-failure-handling",
|
105
|
getter = "lease-failure-handling",
|
106
|
type = OPTTYPE_STRING,
|
107
|
required = False,
|
108
|
default = constants.ONFAILURE_CANCEL,
|
109
|
valid = [constants.ONFAILURE_CANCEL,
|
110
|
constants.ONFAILURE_EXIT,
|
111
|
constants.ONFAILURE_EXIT_RAISE],
|
112
|
doc = """
|
113
|
Sets how the scheduler will handle a failure in
|
114
|
a lease. Valid values are:
|
115
|
|
116
|
- cancel: The lease is cancelled and marked as "FAILED"
|
117
|
- exit: Haizea will exit cleanly, printing relevant debugging
|
118
|
information to its log.
|
119
|
- exit-raise: Haizea will exit by raising an exception. This is
|
120
|
useful for debugging, as IDEs will recognize this as an exception
|
121
|
and will facilitate debugging it.
|
122
|
"""),
|
123
|
|
124
|
Option(name = "datafile",
|
125
|
getter = "datafile",
|
126
|
type = OPTTYPE_STRING,
|
127
|
required = False,
|
128
|
default = None,
|
129
|
doc = """
|
130
|
This is the file where statistics on
|
131
|
the scheduler's run will be saved to (waiting time of leases,
|
132
|
utilization data, etc.). If omitted, no data will be saved.
|
133
|
"""),
|
134
|
|
135
|
Option(name = "attributes",
|
136
|
getter = "attributes",
|
137
|
type = OPTTYPE_STRING,
|
138
|
required = False,
|
139
|
doc = """
|
140
|
This option is used internally by Haizea when using
|
141
|
multiconfiguration files. See the multiconfiguration
|
142
|
documentation for more details.
|
143
|
""")
|
144
|
]
|
145
|
|
146
|
sections.append(general)
|
147
|
|
148
|
|
149
|
|
150
|
|
151
|
|
152
|
|
153
|
|
154
|
scheduling = Section("scheduling", required=True,
|
155
|
doc = "The options in this section control how Haizea schedules leases.")
|
156
|
scheduling.options = \
|
157
|
[
|
158
|
Option(name = "mapper",
|
159
|
getter = "mapper",
|
160
|
type = OPTTYPE_STRING,
|
161
|
required = False,
|
162
|
default = "greedy",
|
163
|
doc = """
|
164
|
VM-to-physical node mapping algorithm used by Haizea. There is currently
|
165
|
only one mapper available (the greedy mapper).
|
166
|
"""),
|
167
|
|
168
|
Option(name = "policy-admission",
|
169
|
getter = "policy.admission",
|
170
|
type = OPTTYPE_STRING,
|
171
|
required = False,
|
172
|
default = "accept-all",
|
173
|
doc = """
|
174
|
Lease admission policy. This controls what leases are accepted by Haizea.
|
175
|
Take into account that this decision takes place before Haizea even
|
176
|
attempts to schedule the lease (so, you can think of lease admission as
|
177
|
"eligibility to be scheduled").
|
178
|
|
179
|
There are two built-in policies:
|
180
|
|
181
|
- accept-all: Accept all leases.
|
182
|
- no-ARs: Accept all leases except advance reservations.
|
183
|
|
184
|
See the Haizea documentation for details on how to write your own
|
185
|
policies.
|
186
|
"""),
|
187
|
|
188
|
Option(name = "policy-preemption",
|
189
|
getter = "policy.preemption",
|
190
|
type = OPTTYPE_STRING,
|
191
|
required = False,
|
192
|
default = "no-preemption",
|
193
|
doc = """
|
194
|
Lease preemption policy. Determines what leases can be preempted. There
|
195
|
are two built-in policies:
|
196
|
|
197
|
- no-preemption: Do not allow any preemptions
|
198
|
- ar-preempts-everything: Allow all ARs to preempt other leases.
|
199
|
|
200
|
See the Haizea documentation for details on how to write your own
|
201
|
policies.
|
202
|
"""),
|
203
|
|
204
|
Option(name = "policy-host-selection",
|
205
|
getter = "policy.host-selection",
|
206
|
type = OPTTYPE_STRING,
|
207
|
required = False,
|
208
|
default = "greedy",
|
209
|
doc = """
|
210
|
Physical host selection policy. controls how Haizea chooses what physical hosts
|
211
|
to map VMs to. This option is closely related to the mapper options
|
212
|
(if the greedy mapper is used, then the greedy host selection policy
|
213
|
should be used, or unexpected results will happen).
|
214
|
|
215
|
The two built-in policies are:
|
216
|
- no-policy: Choose nodes arbitrarily
|
217
|
- greedy: Apply a greedy policy that tries to minimize the number
|
218
|
of preemptions.
|
219
|
|
220
|
See the Haizea documentation for details on how to write your own
|
221
|
policies.
|
222
|
"""),
|
223
|
|
224
|
Option(name = "wakeup-interval",
|
225
|
getter = "wakeup-interval",
|
226
|
type = OPTTYPE_TIMEDELTA,
|
227
|
required = False,
|
228
|
default = TimeDelta(seconds=60),
|
229
|
doc = """
|
230
|
Interval at which Haizea will wake up
|
231
|
to manage resources and process pending requests.
|
232
|
This option is not used when using a simulated clock,
|
233
|
since the clock will skip directly to the time where an
|
234
|
event is happening.
|
235
|
"""),
|
236
|
|
237
|
Option(name = "backfilling",
|
238
|
getter = "backfilling",
|
239
|
type = OPTTYPE_STRING,
|
240
|
required = False,
|
241
|
default = None,
|
242
|
valid = [constants.BACKFILLING_OFF,
|
243
|
constants.BACKFILLING_AGGRESSIVE,
|
244
|
constants.BACKFILLING_CONSERVATIVE,
|
245
|
constants.BACKFILLING_INTERMEDIATE],
|
246
|
doc = """
|
247
|
Backfilling algorithm to use. Valid values are:
|
248
|
|
249
|
- off: don't do backfilling
|
250
|
- aggressive: at most 1 reservation in the future
|
251
|
- conservative: unlimited reservations in the future
|
252
|
- intermediate: N reservations in the future (N is specified
|
253
|
in the backfilling-reservations option)
|
254
|
"""),
|
255
|
|
256
|
Option(name = "backfilling-reservations",
|
257
|
getter = "backfilling-reservations",
|
258
|
type = OPTTYPE_INT,
|
259
|
required = False,
|
260
|
required_if = [(("scheduling","backfilling"),constants.BACKFILLING_INTERMEDIATE)],
|
261
|
doc = """
|
262
|
Number of future reservations to allow when
|
263
|
using the "intermediate" backfilling option.
|
264
|
"""),
|
265
|
|
266
|
Option(name = "suspension",
|
267
|
getter = "suspension",
|
268
|
type = OPTTYPE_STRING,
|
269
|
required = True,
|
270
|
valid = [constants.SUSPENSION_NONE,
|
271
|
constants.SUSPENSION_SERIAL,
|
272
|
constants.SUSPENSION_ALL],
|
273
|
doc = """
|
274
|
Specifies what can be suspended. Valid values are:
|
275
|
|
276
|
- none: suspension is never allowed
|
277
|
- serial-only: only 1-node leases can be suspended
|
278
|
- all: any lease can be suspended
|
279
|
"""),
|
280
|
|
281
|
Option(name = "suspend-rate",
|
282
|
getter = "suspend-rate",
|
283
|
type = OPTTYPE_FLOAT,
|
284
|
required = True,
|
285
|
doc = """
|
286
|
Rate at which VMs are assumed to suspend (in MB of
|
287
|
memory per second)
|
288
|
"""),
|
289
|
|
290
|
Option(name = "resume-rate",
|
291
|
getter = "resume-rate",
|
292
|
type = OPTTYPE_FLOAT,
|
293
|
required = True,
|
294
|
doc = """
|
295
|
Rate at which VMs are assumed to resume (in MB of
|
296
|
memory per second)
|
297
|
"""),
|
298
|
|
299
|
Option(name = "suspendresume-exclusion",
|
300
|
getter = "suspendresume-exclusion",
|
301
|
type = OPTTYPE_STRING,
|
302
|
required = False,
|
303
|
default = constants.SUSPRES_EXCLUSION_LOCAL,
|
304
|
valid = [constants.SUSPRES_EXCLUSION_LOCAL,
|
305
|
constants.SUSPRES_EXCLUSION_GLOBAL],
|
306
|
doc = """
|
307
|
When suspending or resuming a VM, the VM's memory is dumped to a
|
308
|
file on disk. To correctly estimate the time required to suspend
|
309
|
a lease with multiple VMs, Haizea makes sure that no two
|
310
|
suspensions/resumptions happen at the same time (e.g., if eight
|
311
|
memory files were being saved at the same time to disk, the disk's
|
312
|
performance would be reduced in a way that is not as easy to estimate
|
313
|
as if only one file were being saved at a time).
|
314
|
|
315
|
Depending on whether the files are being saved to/read from a global
|
316
|
or local filesystem, this exclusion can be either global or local.
|
317
|
"""),
|
318
|
|
319
|
Option(name = "scheduling-threshold-factor",
|
320
|
getter = "scheduling-threshold-factor",
|
321
|
type = OPTTYPE_INT,
|
322
|
required = False,
|
323
|
default = 1,
|
324
|
doc = """
|
325
|
To avoid thrashing, Haizea will not schedule a lease unless all overheads
|
326
|
can be correctly scheduled (which includes image transfers, suspensions, etc.).
|
327
|
However, this can still result in situations where a lease is prepared,
|
328
|
and then immediately suspended because of a blocking lease in the future.
|
329
|
The scheduling threshold factor can be used to specify that a lease must
|
330
|
not be scheduled unless it is guaranteed to run for a minimum amount of
|
331
|
time (the rationale behind this is that you ideally don't want leases
|
332
|
to be scheduled if they're not going to be active for at least as much time
|
333
|
as was spent in overheads).
|
334
|
|
335
|
The default value is 1, meaning that the lease will be active for at least
|
336
|
as much time T as was spent on overheads (e.g., if preparing the lease requires
|
337
|
60 seconds, and we know that it will have to be suspended, requiring 30 seconds,
|
338
|
Haizea won't schedule the lease unless it can run for at least 90 minutes).
|
339
|
In other words, a scheduling factor of F required a minimum duration of
|
340
|
F*T. A value of 0 could lead to thrashing, since Haizea could end up with
|
341
|
situations where a lease starts and immediately gets suspended.
|
342
|
"""),
|
343
|
|
344
|
Option(name = "override-suspend-time",
|
345
|
getter = "override-suspend-time",
|
346
|
type = OPTTYPE_INT,
|
347
|
required = False,
|
348
|
default = None,
|
349
|
doc = """
|
350
|
Overrides the time it takes to suspend a VM to a fixed value
|
351
|
(i.e., not computed based on amount of memory, enactment overhead, etc.)
|
352
|
"""),
|
353
|
|
354
|
Option(name = "override-resume-time",
|
355
|
getter = "override-resume-time",
|
356
|
type = OPTTYPE_INT,
|
357
|
required = False,
|
358
|
default = None,
|
359
|
doc = """
|
360
|
Overrides the time it takes to suspend a VM to a fixed value
|
361
|
(i.e., not computed based on amount of memory, enactment overhead, etc.)
|
362
|
"""),
|
363
|
|
364
|
Option(name = "force-scheduling-threshold",
|
365
|
getter = "force-scheduling-threshold",
|
366
|
type = OPTTYPE_TIMEDELTA,
|
367
|
required = False,
|
368
|
doc = """
|
369
|
This option can be used to force a specific scheduling threshold time
|
370
|
to be used, instead of calculating one based on overheads.
|
371
|
"""),
|
372
|
|
373
|
Option(name = "migration",
|
374
|
getter = "migration",
|
375
|
type = OPTTYPE_STRING,
|
376
|
required = False,
|
377
|
default = constants.MIGRATE_NO,
|
378
|
valid = [constants.MIGRATE_NO,
|
379
|
constants.MIGRATE_YES,
|
380
|
constants.MIGRATE_YES_NOTRANSFER],
|
381
|
doc = """
|
382
|
Specifies whether leases can be migrated from one
|
383
|
physical node to another. Valid values are:
|
384
|
|
385
|
- no
|
386
|
- yes
|
387
|
- yes-notransfer: migration is performed without
|
388
|
transferring any files.
|
389
|
"""),
|
390
|
|
391
|
Option(name = "non-schedulable-interval",
|
392
|
getter = "non-schedulable-interval",
|
393
|
type = OPTTYPE_TIMEDELTA,
|
394
|
required = False,
|
395
|
default = TimeDelta(seconds=10),
|
396
|
doc = """
|
397
|
The minimum amount of time that must pass between
|
398
|
when a request is scheduled to when it can actually start.
|
399
|
The default should be good for most configurations, but
|
400
|
may need to be increased if you're dealing with exceptionally
|
401
|
high loads.
|
402
|
"""),
|
403
|
|
404
|
Option(name = "shutdown-time",
|
405
|
getter = "shutdown-time",
|
406
|
type = OPTTYPE_TIMEDELTA,
|
407
|
required = False,
|
408
|
default = TimeDelta(seconds=0),
|
409
|
doc = """
|
410
|
The amount of time that will be allocated for a VM to shutdown.
|
411
|
When running in OpenNebula mode, it is advisable to set this to
|
412
|
a few seconds, so no operation gets scheduled right when a
|
413
|
VM is shutting down. The most common scenario is that a VM
|
414
|
will start resuming right when another VM shuts down. However,
|
415
|
since both these activities involve I/O, it can delay the resume
|
416
|
operation and affect Haizea's estimation of how long the resume
|
417
|
will take.
|
418
|
"""),
|
419
|
|
420
|
Option(name = "enactment-overhead",
|
421
|
getter = "enactment-overhead",
|
422
|
type = OPTTYPE_TIMEDELTA,
|
423
|
required = False,
|
424
|
default = TimeDelta(seconds=0),
|
425
|
doc = """
|
426
|
The amount of time that is required to send
|
427
|
an enactment command. This value will affect suspend/resume
|
428
|
estimations and, in OpenNebula mode, will force a pause
|
429
|
of this much time between suspend/resume enactment
|
430
|
commands. When suspending/resuming many VMs at the same time
|
431
|
(which is likely to happen if suspendresume-exclusion is set
|
432
|
to "local"), it will take OpenNebula 1-2 seconds to process
|
433
|
each command (this is a small amount of time, but if 32 VMs
|
434
|
are being suspended at the same time, on in each physical node,
|
435
|
this time can compound up to 32-64 seconds, which has to be
|
436
|
taken into account when estimating when to start a suspend
|
437
|
operation that must be completed before another lease starts).
|
438
|
""")
|
439
|
|
440
|
]
|
441
|
sections.append(scheduling)
|
442
|
|
443
|
|
444
|
|
445
|
|
446
|
|
447
|
|
448
|
|
449
|
simulation = Section("simulation", required=False,
|
450
|
required_if = [(("general","mode"),"simulated")],
|
451
|
doc = "This section is used to specify options when Haizea runs in simulation" )
|
452
|
simulation.options = \
|
453
|
[
|
454
|
Option(name = "clock",
|
455
|
getter = "clock",
|
456
|
type = OPTTYPE_STRING,
|
457
|
required = False,
|
458
|
default = constants.CLOCK_REAL,
|
459
|
valid = [constants.CLOCK_REAL,
|
460
|
constants.CLOCK_SIMULATED],
|
461
|
doc = """
|
462
|
Type of clock to use in simulation:
|
463
|
|
464
|
- simulated: A simulated clock that fastforwards through
|
465
|
time. Can only use the tracefile request
|
466
|
frontend
|
467
|
- real: A real clock is used, but simulated resources and
|
468
|
enactment actions are used. Can only use the RPC
|
469
|
request frontend.
|
470
|
"""),
|
471
|
|
472
|
Option(name = "starttime",
|
473
|
getter = "starttime",
|
474
|
type = OPTTYPE_DATETIME,
|
475
|
required = False,
|
476
|
required_if = [(("simulation","clock"),constants.CLOCK_SIMULATED)],
|
477
|
doc = """
|
478
|
Time at which simulated clock will start.
|
479
|
"""),
|
480
|
|
481
|
Option(name = "resources",
|
482
|
getter = "simul.resources",
|
483
|
type = OPTTYPE_STRING,
|
484
|
required = True,
|
485
|
doc = """
|
486
|
Simulated resources. This option can take two values,
|
487
|
"in-tracefile" (which means that the description of
|
488
|
the simulated site is in the tracefile) or a string
|
489
|
specifying a site with homogeneous resources.
|
490
|
The format is:
|
491
|
|
492
|
<numnodes> [ <resource_type>:<resource_quantity>]+
|
493
|
|
494
|
For example, "4 CPU:100 Memory:1024" describes a site
|
495
|
with four nodes, each with one CPU and 1024 MB of memory.
|
496
|
"""),
|
497
|
|
498
|
Option(name = "imagetransfer-bandwidth",
|
499
|
getter = "imagetransfer-bandwidth",
|
500
|
type = OPTTYPE_INT,
|
501
|
required = True,
|
502
|
doc = """
|
503
|
Bandwidth (in Mbps) available for image transfers.
|
504
|
This would correspond to the outbound network bandwidth of the
|
505
|
node where the images are stored.
|
506
|
"""),
|
507
|
|
508
|
Option(name = "stop-when",
|
509
|
getter = "stop-when",
|
510
|
type = OPTTYPE_STRING,
|
511
|
required = False,
|
512
|
default = constants.STOPWHEN_ALLDONE,
|
513
|
valid = [constants.STOPWHEN_ALLDONE,
|
514
|
constants.STOPWHEN_BESUBMITTED,
|
515
|
constants.STOPWHEN_BEDONE],
|
516
|
doc = """
|
517
|
When using the simulated clock, this specifies when the
|
518
|
simulation must end. Valid options are:
|
519
|
|
520
|
- all-leases-done: All requested leases have been completed
|
521
|
and there are no queued/pending requests.
|
522
|
- besteffort-submitted: When all best-effort leases have been
|
523
|
submitted.
|
524
|
- besteffort-done: When all best-effort leases have been
|
525
|
completed.
|
526
|
"""),
|
527
|
|
528
|
Option(name = "status-message-interval",
|
529
|
getter = "status-message-interval",
|
530
|
type = OPTTYPE_INT,
|
531
|
required = False,
|
532
|
default = None,
|
533
|
doc = """
|
534
|
If specified, the simulated clock will print a status
|
535
|
message with some basic statistics. This is useful to keep track
|
536
|
of long simulations. The interval is specified in minutes.
|
537
|
""")
|
538
|
|
539
|
]
|
540
|
sections.append(simulation)
|
541
|
|
542
|
|
543
|
|
544
|
|
545
|
|
546
|
|
547
|
|
548
|
|
549
|
|
550
|
imgtransfer = Section("deploy-imagetransfer", required=False,
|
551
|
required_if = [(("general","lease-deployment"),"imagetransfer")],
|
552
|
doc = """
|
553
|
When lease deployment with disk image transfers is selected,
|
554
|
this section is used to control image deployment parameters.""")
|
555
|
imgtransfer.options = \
|
556
|
[
|
557
|
Option(name = "transfer-mechanism",
|
558
|
getter = "transfer-mechanism",
|
559
|
type = OPTTYPE_STRING,
|
560
|
required = True,
|
561
|
valid = [constants.TRANSFER_UNICAST,
|
562
|
constants.TRANSFER_MULTICAST],
|
563
|
doc = """
|
564
|
Specifies how disk images are transferred. Valid values are:
|
565
|
|
566
|
- unicast: A disk image can be transferred to just one node at a time
|
567
|
- multicast: A disk image can be multicast to multiple nodes at
|
568
|
the same time.
|
569
|
"""),
|
570
|
|
571
|
Option(name = "avoid-redundant-transfers",
|
572
|
getter = "avoid-redundant-transfers",
|
573
|
type = OPTTYPE_BOOLEAN,
|
574
|
required = False,
|
575
|
default = True,
|
576
|
doc = """
|
577
|
Specifies whether the scheduler should take steps to
|
578
|
detect and avoid redundant transfers (e.g., if two leases are
|
579
|
scheduled on the same node, and they both require the same disk
|
580
|
image, don't transfer the image twice; allow one to "piggyback"
|
581
|
on the other). There is generally no reason to set this option
|
582
|
to False.
|
583
|
"""),
|
584
|
|
585
|
Option(name = "force-imagetransfer-time",
|
586
|
getter = "force-imagetransfer-time",
|
587
|
type = OPTTYPE_TIMEDELTA,
|
588
|
required = False,
|
589
|
doc = """
|
590
|
Forces the image transfer time to a specific amount.
|
591
|
This options is intended for testing purposes.
|
592
|
"""),
|
593
|
|
594
|
Option(name = "diskimage-reuse",
|
595
|
getter = "diskimage-reuse",
|
596
|
type = OPTTYPE_STRING,
|
597
|
required = False,
|
598
|
required_if = None,
|
599
|
default = constants.REUSE_NONE,
|
600
|
valid = [constants.REUSE_NONE,
|
601
|
constants.REUSE_IMAGECACHES],
|
602
|
doc = """
|
603
|
Specifies whether disk image caches should be created
|
604
|
on the nodes, so the scheduler can reduce the number of transfers
|
605
|
by reusing images. Valid values are:
|
606
|
|
607
|
- none: No image reuse
|
608
|
- image-caches: Use image caching algorithm described in Haizea
|
609
|
publications
|
610
|
"""),
|
611
|
|
612
|
Option(name = "diskimage-cache-size",
|
613
|
getter = "diskimage-cache-size",
|
614
|
type = OPTTYPE_INT,
|
615
|
required = False,
|
616
|
required_if = [(("deploy-imagetransfer","diskimage-reuse"),True)],
|
617
|
doc = """
|
618
|
Specifies the size (in MB) of the disk image cache on
|
619
|
each physical node.
|
620
|
""")
|
621
|
]
|
622
|
sections.append(imgtransfer)
|
623
|
|
624
|
|
625
|
|
626
|
|
627
|
|
628
|
|
629
|
|
630
|
tracefile = Section("tracefile", required=False,
|
631
|
doc="""
|
632
|
When reading in requests from a tracefile, this section is used
|
633
|
to specify the tracefile and other parameters.""")
|
634
|
tracefile.options = \
|
635
|
[
|
636
|
Option(name = "tracefile",
|
637
|
getter = "tracefile",
|
638
|
type = OPTTYPE_STRING,
|
639
|
required = True,
|
640
|
doc = """
|
641
|
Path to tracefile to use.
|
642
|
"""),
|
643
|
|
644
|
Option(name = "imagefile",
|
645
|
getter = "imagefile",
|
646
|
type = OPTTYPE_STRING,
|
647
|
required = False,
|
648
|
doc = """
|
649
|
Path to list of images to append to lease requests.
|
650
|
If omitted, the images in the tracefile are used.
|
651
|
"""),
|
652
|
|
653
|
Option(name = "injectionfile",
|
654
|
getter = "injectionfile",
|
655
|
type = OPTTYPE_STRING,
|
656
|
required = False,
|
657
|
doc = """
|
658
|
Path to file with leases to "inject" into the tracefile.
|
659
|
"""),
|
660
|
|
661
|
Option(name = "runtime-slowdown-overhead",
|
662
|
getter = "runtime-slowdown-overhead",
|
663
|
type = OPTTYPE_FLOAT,
|
664
|
required = False,
|
665
|
default = 0,
|
666
|
doc = """
|
667
|
Adds a runtime overhead (in %) to the lease duration.
|
668
|
"""),
|
669
|
|
670
|
Option(name = "add-overhead",
|
671
|
getter = "add-overhead",
|
672
|
type = OPTTYPE_STRING,
|
673
|
required = False,
|
674
|
default = constants.RUNTIMEOVERHEAD_NONE,
|
675
|
valid = [constants.RUNTIMEOVERHEAD_NONE,
|
676
|
constants.RUNTIMEOVERHEAD_ALL,
|
677
|
constants.RUNTIMEOVERHEAD_BE],
|
678
|
doc = """
|
679
|
Specifies what leases will have a runtime overhead added:
|
680
|
|
681
|
- none: No runtime overhead must be added.
|
682
|
- besteffort: Add only to best-effort leases
|
683
|
- all: Add runtime overhead to all leases
|
684
|
"""),
|
685
|
|
686
|
Option(name = "bootshutdown-overhead",
|
687
|
getter = "bootshutdown-overhead",
|
688
|
type = OPTTYPE_TIMEDELTA,
|
689
|
required = False,
|
690
|
default = TimeDelta(seconds=0),
|
691
|
doc = """
|
692
|
Specifies how many seconds will be alloted to
|
693
|
boot and shutdown of the lease.
|
694
|
"""),
|
695
|
|
696
|
Option(name = "override-memory",
|
697
|
getter = "override-memory",
|
698
|
type = OPTTYPE_INT,
|
699
|
required = False,
|
700
|
default = constants.NO_MEMORY_OVERRIDE,
|
701
|
doc = """
|
702
|
Overrides memory requirements specified in tracefile.
|
703
|
"""),
|
704
|
]
|
705
|
sections.append(tracefile)
|
706
|
|
707
|
|
708
|
|
709
|
|
710
|
|
711
|
|
712
|
|
713
|
opennebula = Section("opennebula", required=False,
|
714
|
required_if = [(("general","mode"),"opennebula")],
|
715
|
doc = """
|
716
|
This section is used to specify OpenNebula parameters,
|
717
|
necessary when using Haizea as an OpenNebula scheduling backend.""")
|
718
|
opennebula.options = \
|
719
|
[
|
720
|
Option(name = "host",
|
721
|
getter = "one.host",
|
722
|
type = OPTTYPE_STRING,
|
723
|
required = True,
|
724
|
doc = """
|
725
|
Host where OpenNebula is running.
|
726
|
Typically, OpenNebula and Haizea will be installed
|
727
|
on the same host, so the following option should be
|
728
|
set to 'localhost'. If they're on different hosts,
|
729
|
make sure you modify this option accordingly.
|
730
|
"""),
|
731
|
|
732
|
Option(name = "port",
|
733
|
getter = "one.port",
|
734
|
type = OPTTYPE_INT,
|
735
|
required = False,
|
736
|
default = defaults.OPENNEBULA_RPC_PORT,
|
737
|
doc = """
|
738
|
TCP port of OpenNebula's XML RPC server
|
739
|
"""),
|
740
|
|
741
|
Option(name = "stop-when-no-more-leases",
|
742
|
getter = "stop-when-no-more-leases",
|
743
|
type = OPTTYPE_BOOLEAN,
|
744
|
required = False,
|
745
|
default = False,
|
746
|
doc = """
|
747
|
This option is useful for testing and running experiments.
|
748
|
If set to True, Haizea will stop when there are no more leases
|
749
|
to process (which allows you to tun Haizea and OpenNebula unattended,
|
750
|
and count on it stopping when there are no more leases to process).
|
751
|
For now, this only makes sense if you're seeding Haizea with requests from
|
752
|
the start (otherwise, it will start and immediately stop).
|
753
|
"""),
|
754
|
|
755
|
Option(name = "dry-run",
|
756
|
getter = "dry-run",
|
757
|
type = OPTTYPE_BOOLEAN,
|
758
|
required = False,
|
759
|
default = False,
|
760
|
doc = """
|
761
|
This option is useful for testing.
|
762
|
If set to True, Haizea will fast-forward through time (note that this is
|
763
|
different that using the simulated clock, which has to be used with a tracefile;
|
764
|
with an Haizea/OpenNebula dry run, you will have to seed OpenNebula with requests
|
765
|
before starting Haizea). You will generally want to set stop-when-no-more-leases
|
766
|
when doing a dry-run.
|
767
|
|
768
|
IMPORTANT: Haizea will still send out enactment commands to OpenNebula. Make
|
769
|
sure you replace onevm with a dummy command that does nothing (or that reacts
|
770
|
in some way you want to test; e.g., by emulating a deployment failure, etc.)
|
771
|
"""),
|
772
|
|
773
|
]
|
774
|
sections.append(opennebula)
|
775
|
|
776
|
def __init__(self, config):
|
777
|
Config.__init__(self, config, self.sections)
|
778
|
|
779
|
self.attrs = {}
|
780
|
if self._options["attributes"] != None:
|
781
|
self.attrs = {}
|
782
|
attrs = self._options["attributes"].split(",")
|
783
|
for attr in attrs:
|
784
|
(k,v) = attr.split("=")
|
785
|
self.attrs[k] = v
|
786
|
|
787
|
def get_attr(self, attr):
|
788
|
return self.attrs[attr]
|
789
|
|
790
|
def get_attrs(self):
|
791
|
return self.attrs.keys()
|
792
|
|
793
|
|
794
|
class HaizeaMultiConfig(Config):
|
795
|
|
796
|
MULTI_SEC = "multi"
|
797
|
COMMON_SEC = "common"
|
798
|
TRACEDIR_OPT = "tracedir"
|
799
|
TRACEFILES_OPT = "tracefiles"
|
800
|
INJDIR_OPT = "injectiondir"
|
801
|
INJFILES_OPT = "injectionfiles"
|
802
|
DATADIR_OPT = "datadir"
|
803
|
|
804
|
def __init__(self, config):
|
805
|
|
806
|
Config.__init__(self, config, [])
|
807
|
|
808
|
def get_profiles(self):
|
809
|
sections = set([s.split(":")[0] for s in self.config.sections()])
|
810
|
|
811
|
sections.difference_update([self.COMMON_SEC, self.MULTI_SEC])
|
812
|
return list(sections)
|
813
|
|
814
|
def get_trace_files(self):
|
815
|
dir = self.config.get(self.MULTI_SEC, self.TRACEDIR_OPT)
|
816
|
traces = self.config.get(self.MULTI_SEC, self.TRACEFILES_OPT).split()
|
817
|
return [dir + "/" + t for t in traces]
|
818
|
|
819
|
def get_inject_files(self):
|
820
|
dir = self.config.get(self.MULTI_SEC, self.INJDIR_OPT)
|
821
|
inj = self.config.get(self.MULTI_SEC, self.INJFILES_OPT).split()
|
822
|
inj = [dir + "/" + i for i in inj]
|
823
|
inj.append(None)
|
824
|
return inj
|
825
|
|
826
|
def get_configs(self):
|
827
|
profiles = self.get_profiles()
|
828
|
tracefiles = self.get_trace_files()
|
829
|
injectfiles = self.get_inject_files()
|
830
|
|
831
|
configs = []
|
832
|
for profile in profiles:
|
833
|
for tracefile in tracefiles:
|
834
|
for injectfile in injectfiles:
|
835
|
profileconfig = ConfigParser.ConfigParser()
|
836
|
commonsections = [s for s in self.config.sections() if s.startswith("common:")]
|
837
|
profilesections = [s for s in self.config.sections() if s.startswith(profile +":")]
|
838
|
sections = commonsections + profilesections
|
839
|
for s in sections:
|
840
|
s_noprefix = s.split(":")[1]
|
841
|
items = self.config.items(s)
|
842
|
if not profileconfig.has_section(s_noprefix):
|
843
|
profileconfig.add_section(s_noprefix)
|
844
|
for item in items:
|
845
|
profileconfig.set(s_noprefix, item[0], item[1])
|
846
|
|
847
|
|
848
|
if not profileconfig.has_section("tracefile"):
|
849
|
profileconfig.add_section("tracefile")
|
850
|
|
851
|
|
852
|
profileconfig.set("tracefile", "tracefile", tracefile)
|
853
|
|
854
|
|
855
|
if injectfile != None:
|
856
|
profileconfig.set("tracefile", "injectionfile", injectfile)
|
857
|
|
858
|
|
859
|
datadir = self.config.get(self.MULTI_SEC, self.DATADIR_OPT)
|
860
|
datafilename = generate_config_name(profile, tracefile, injectfile)
|
861
|
datafile = datadir + "/" + datafilename + ".dat"
|
862
|
profileconfig.set("general", "datafile", datafile)
|
863
|
|
864
|
|
865
|
attrs = {"profile":profile,"tracefile":tracefile,"injectfile":injectfile}
|
866
|
|
867
|
attrs_str = ",".join(["%s=%s" % (k,v) for (k,v) in attrs.items()])
|
868
|
if profileconfig.has_option("general", "attributes"):
|
869
|
attrs_str += ",%s" % profileconfig.get("general", "attributes")
|
870
|
profileconfig.set("general", "attributes", attrs_str)
|
871
|
|
872
|
try:
|
873
|
c = HaizeaConfig(profileconfig)
|
874
|
except ConfigException, msg:
|
875
|
print >> sys.stderr, "Error in configuration file:"
|
876
|
print >> sys.stderr, msg
|
877
|
exit(1)
|
878
|
configs.append(c)
|
879
|
|
880
|
return configs
|