Project

General

Profile

root / trunk / src / haizea / core / configfile.py @ 641

1
# -------------------------------------------------------------------------- #
2
# Copyright 2006-2009, University of Chicago                                 #
3
# Copyright 2008-2009, Distributed Systems Architecture Group, Universidad   #
4
# Complutense de Madrid (dsa-research.org)                                   #
5
#                                                                            #
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
7
# not use this file except in compliance with the License. You may obtain    #
8
# a copy of the License at                                                   #
9
#                                                                            #
10
# http://www.apache.org/licenses/LICENSE-2.0                                 #
11
#                                                                            #
12
# Unless required by applicable law or agreed to in writing, software        #
13
# distributed under the License is distributed on an "AS IS" BASIS,          #
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
15
# See the License for the specific language governing permissions and        #
16
# limitations under the License.                                             #
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
    #        GENERAL OPTIONS        #
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
    #      SCHEDULING OPTIONS       #
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
    #      SIMULATION OPTIONS       #
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
    #      DEPLOYMENT OPTIONS       #
546
    #     (w/ image transfers)      #
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
    #      TRACEFILE OPTIONS        #
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
    #      OPENNEBULA OPTIONS       #
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
        # TODO: Define "multi" section as a Section object
806
        Config.__init__(self, config, [])
807
        
808
    def get_profiles(self):
809
        sections = set([s.split(":")[0] for s in self.config.sections()])
810
        # Remove multi and common sections
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
                    # The tracefile section may have not been created
848
                    if not profileconfig.has_section("tracefile"):
849
                        profileconfig.add_section("tracefile")
850

    
851
                    # Add tracefile option
852
                    profileconfig.set("tracefile", "tracefile", tracefile)
853
                    
854
                    # Add injected file option
855
                    if injectfile != None:
856
                        profileconfig.set("tracefile", "injectionfile", injectfile)
857

    
858
                    # Add datafile option
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
                    # Set "attributes" option (only used internally)
865
                    attrs = {"profile":profile,"tracefile":tracefile,"injectfile":injectfile}
866
                    # TODO: Load additional attributes from trace/injfiles
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