示例#1
0
def term_barcode_mx_date(barcode):
    "Возвращает дату/время генерации ШК типа mx.DateTime.DateTime"

    d0 = DateTime(2010, 1, 1, 0, 0, 0)
    minutes = numeral_systems.any_to_dec(barcode[7:12], 36)

    return d0 + TimeDelta(minutes=minutes)
示例#2
0
def StrTomxTime(_timeStr, fmt={'hour':'%H', 'min':'%M'}, delim=":"):
    format = fmt['hour']+delim+fmt['min']
    #_time = Time(*time.strptime(_timeStr,format)[3:5])
    h,m=time.strptime(_timeStr,format)[3:5]
    _time = TimeDelta(hours=h,minutes=m)
            #strptime(abs,'%H:%M',today(second=0))
    #_time = Time()
    return _time
示例#3
0
 def get_worktime(self, daytype):
     """
     return a TimeDelta representing the amount of work time on datetime.
     """
     res = TimeDelta(0)
     intervals = self._get_intervals(daytype)
     for from_time, to_time in intervals:
         res += to_time - from_time
     return res
示例#4
0
    def wakeup_interval_changed_callback(self, *args):
        h, m, s = (
            self.builder.get_object('wakeup-interval-hours').get_text(),
            self.builder.get_object('wakeup-interval-minutes').get_text(),
            self.builder.get_object('wakeup-interval-seconds').get_text())

        if not h:
            h = 0
        if not s:
            s = 0
        if not m:
            m = 0
        try:
            self.config._options['wakeup-interval'] = TimeDelta(seconds=int(s),
                                                                minutes=int(m),
                                                                hours=int(h))
        except:
            print "Invalid Wakeup interval value"
            self.config._options['wakeup-interval'] = TimeDelta(seconds=10)
示例#5
0
 def __init__(self, manager, quantum, non_sched, fastforward = False):
     """Initializes the real clock.
     
     Arguments:
     manager -- the resource manager
     quantum -- interval between clock wakeups
     fastforward -- if True, the clock won't actually sleep
                    for the duration of the quantum."""
     Clock.__init__(self, manager)
     self.fastforward = fastforward
     if not self.fastforward:
         self.lastwakeup = None
     else:
         self.lastwakeup = round_datetime(now())
     self.logger = logging.getLogger("CLOCK")
     self.starttime = self.get_time()
     self.nextschedulable = None
     self.nextperiodicwakeup = None
     self.quantum = TimeDelta(seconds=quantum)
     self.non_sched = TimeDelta(seconds=non_sched)
示例#6
0
 def estimate_migration_time(self, lease):
     migration = get_config().get("migration")
     if migration == constants.MIGRATE_YES:
         vmrr = lease.get_last_vmrr()
         images_in_pnode = dict([(pnode, 0)
                                 for pnode in set(vmrr.nodes.values())])
         for (vnode, pnode) in vmrr.nodes.items():
             images_in_pnode[pnode] += lease.software.image_size
         max_to_transfer = max(images_in_pnode.values())
         bandwidth = self.resourcepool.info.get_migration_bandwidth()
         return estimate_transfer_time(max_to_transfer, bandwidth)
     elif migration == constants.MIGRATE_YES_NOTRANSFER:
         return TimeDelta(seconds=0)
示例#7
0
    def __load_option(self, sec, opt):
        # Load a single option
        secname = sec.name
        optname = opt.name

        has_option = self.config.has_option(secname, optname)

        if not has_option:
            if opt.required:
                raise ConfigException, "Required option '%s.%s' not found" % (
                    secname, optname)
            if opt.required_if != None:
                for req in opt.required_if:
                    (condsec, condopt) = req[0]
                    condvalue = req[1]

                    if self.config.has_option(
                            condsec, condopt) and self.config.get(
                                condsec, condopt) == condvalue:
                        raise ConfigException, "Option '%s.%s' is required when %s.%s==%s" % (
                            secname, optname, condsec, condopt, condvalue)

            value = opt.default
        else:
            if opt.type == OPTTYPE_INT:
                value = self.config.getint(secname, optname)
            elif opt.type == OPTTYPE_FLOAT:
                value = self.config.getfloat(secname, optname)
            elif opt.type == OPTTYPE_STRING:
                value = self.config.get(secname, optname)
            elif opt.type == OPTTYPE_BOOLEAN:
                value = self.config.getboolean(secname, optname)
            elif opt.type == OPTTYPE_DATETIME:
                value = self.config.get(secname, optname)
                value = ISO.ParseDateTime(value)
            elif opt.type == OPTTYPE_TIMEDELTA:
                value = self.config.getint(secname, optname)
                value = TimeDelta(seconds=value)

            if opt.valid != None:
                if not value in opt.valid:
                    raise ConfigException, "Invalid value specified for '%s.%s'. Valid values are %s" % (
                        secname, optname, opt.valid)

        self._options[opt.getter] = value
示例#8
0
    def enactment_overhead_changed_callback(self, *args):
        h, m, s = (
            self.builder.get_object('enactment-overhead-hours').get_text(),
            self.builder.get_object('enactment-overhead-minutes').get_text(),
            self.builder.get_object('enactment-overhead-seconds').get_text())

        if not h:
            h = 0
        if not s:
            s = 0
        if not m:
            m = 0
        try:
            self.config._options['enactment-overhead'] = TimeDelta(
                seconds=int(s), minutes=int(m), hours=int(h))
        except:
            print "Invalid enactment-overhead value"
            self.config._options['enactment-overhead'] = None
示例#9
0
    def shutdown_time_changed_callback(self, *args):
        h, m, s = (self.builder.get_object('shutdown-time-hours').get_text(),
                   self.builder.get_object('shutdown-time-minutes').get_text(),
                   self.builder.get_object('shutdown-time-seconds').get_text())

        if not h:
            h = 0
        if not s:
            s = 0
        if not m:
            m = 0
        try:
            self.config._options['shutdown-time'] = TimeDelta(seconds=int(s),
                                                              minutes=int(m),
                                                              hours=int(h))
        except:
            print "Invalid shutdown-time value"
            self.config._options['shutdown-time'] = None
示例#10
0
    def force_scheduling_threshold_changed_callback(self, *args):
        h, m, s = (self.builder.get_object(
            'force-scheduling-threshold-hours').get_text(),
                   self.builder.get_object(
                       'force-scheduling-threshold-minutes').get_text(),
                   self.builder.get_object(
                       'force-scheduling-threshold-seconds').get_text())

        if not h:
            h = 0
        if not s:
            s = 0
        if not m:
            m = 0
        try:
            self.config._options['force-scheduling-threshold'] = TimeDelta(
                seconds=int(s), minutes=int(m), hours=int(h))
        except:
            print "Invalid Wakeup interval value"
            self.config._options['force-scheduling-threshold'] = None
示例#11
0
def adjustDateTime(adjustDelta, dateTime):
    """
    sometimes a DateTime object has to be adjusted, when illegal components were specified
    adjustDateTime corrects DateTime object with specifications obtained from
    fixTimeComponents()

    input: adjustFlags is tuple/list of flags for adjusting ( increaseDay, increaseHour, increaseMin )
    output: corrected DateTime object
    """

    # Increase day
    dateTime += DateTimeDelta(adjustDelta[0])

    # Increase hour
    dateTime += TimeDelta(adjustDelta[1])

    # Increase minute
    dateTime += DateTimeDeltaFromSeconds(60.0 * adjustDelta[2])

    return dateTime
示例#12
0
    def run(self):
        self.parse_options()

        infile = self.opt.inf
        outfile = self.opt.outf

        root = ET.Element("lease-workload")
        root.set("name", infile)
        description = ET.SubElement(root, "description")
        time = TimeDelta(seconds=0)
        lease_id = 1
        requests = ET.SubElement(root, "lease-requests")

        infile = open(infile, "r")
        for line in infile:
            if line[0] != '#' and len(line.strip()) != 0:
                fields = line.split()
                submit_time = int(fields[0])
                start_time = int(fields[1])
                duration = int(fields[2])
                real_duration = int(fields[3])
                num_nodes = int(fields[4])
                cpu = int(fields[5])
                mem = int(fields[6])
                disk = int(fields[7])
                vm_image = fields[8]
                vm_imagesize = int(fields[9])

                lease_request = ET.SubElement(requests, "lease-request")
                lease_request.set("arrival",
                                  str(TimeDelta(seconds=submit_time)))
                if real_duration != duration:
                    realduration = ET.SubElement(lease_request, "realduration")
                    realduration.set("time",
                                     str(TimeDelta(seconds=real_duration)))

                lease = ET.SubElement(lease_request, "lease")
                lease.set("id", ` lease_id `)

                nodes = ET.SubElement(lease, "nodes")
                node_set = ET.SubElement(nodes, "node-set")
                node_set.set("numnodes", ` num_nodes `)
                res = ET.SubElement(node_set, "res")
                res.set("type", "CPU")
                if cpu == 1:
                    res.set("amount", "100")
                else:
                    pass
                res = ET.SubElement(node_set, "res")
                res.set("type", "Memory")
                res.set("amount", ` mem `)

                start = ET.SubElement(lease, "start")
                if start_time == -1:
                    lease.set("preemptible", "true")
                else:
                    lease.set("preemptible", "false")
                    exact = ET.SubElement(start, "exact")
                    exact.set("time", str(TimeDelta(seconds=start_time)))

                duration_elem = ET.SubElement(lease, "duration")
                duration_elem.set("time", str(TimeDelta(seconds=duration)))

                software = ET.SubElement(lease, "software")
                diskimage = ET.SubElement(software, "disk-image")
                diskimage.set("id", vm_image)
                diskimage.set("size", ` vm_imagesize `)

                lease_id += 1
        tree = ET.ElementTree(root)
        print ET.tostring(root)
   def __init__(self, parent, bd=4, relief=RAISED):
      Frame.__init__(self, parent)      
      ##################################################################################
      # Some variables for our use in the program
      snooze_min = 15
      armed = False
      go_time = now() + TimeDelta(8,0,0)
      dt = TimeDelta(8,0,0)
      Update_per_sec = 2
      
      ##################################################################################
      # Define some functions that may be handy to make the functions of an alarm clock

      def run_alarm():
         update_fields()
         if self.armed:
            if self.go_time < now():
               sound_alarm()
            self.after(1000 / Update_per_sec, run_alarm)   # run N times per second  
   
      # Runs the command in the "Halt Command" field when we snooze or halt the alarm
      def halt_alarm():
         self.armed = False 
         dt = TimeDelta(0,0,0)
         update_fields()
         os.system(halt_field.get() + '&')
   
      def snooze_alarm():
         self.go_time = now() + TimeDelta(0,snooze_min,1)
         self.dt = TimeDelta(0,snooze_min)
         halt_alarm()
         self.armed = True
         run_alarm()
   
      # Runs the command in the "Alarm Command" field when the alarm is to go off
      def sound_alarm():
         self.armed = False
         dt = TimeDelta(0,0,0)
         update_fields()
         os.system(run_field.get() + '&')
   
      # Refreshes the display fields to we can see the time count down
      def update_fields():
         # find the new dt
         self.dt = self.go_time - now()
         # Clear the fields and then...
         time_field_hour.delete(0,END)
         time_field_min.delete(0,END)
         time_field_sec.delete(0,END)
         dt_field_hour.delete(0,END)
         dt_field_min.delete(0,END)
         dt_field_sec.delete(0,END)
         # fill them in again
         time_field_hour.insert(0,self.go_time.hour)
         time_field_min.insert(0,self.go_time.minute)
         time_field_sec.insert(0,int(self.go_time.second))
         dt_field_hour.insert(0,self.dt.hour)
         dt_field_min.insert(0,self.dt.minute)
         dt_field_sec.insert(0,int(self.dt.second))

      # Sets the time the alarm will go off   
      def set_time():
         h = int(time_field_hour.get())
         m = int(time_field_min.get())
         s = int(time_field_sec.get())
         self.go_time = DateTime(now().year,now().month,now().day,h,m,s)
         if self.go_time < now():
            self.go_time = DateTime(now().year, now().month, now().day + 1, h, m, s)
         self.dt = self.go_time - now()
         self.armed = True
         run_alarm()

      # Sets the alarm to go off after so long
      def set_dt():
         self.dt = TimeDelta(int(dt_field_hour.get()),int(dt_field_min.get()),int(dt_field_sec.get()))
         self.go_time = now() + self.dt
         self.armed = True
         run_alarm()

      ##################################################################################
      # Here we build the GUI and make the button point to functions that do stuff for us.

      # This field takes the time we want the alarm to go off
      tmp_time = now() + TimeDelta(8,0,0)        #Find sugested 8 hours from now
      time_field_hour = Entry(self, width=2)    #Make the entry field
      time_field_hour.insert(0, tmp_time.hour)  #Put the reccomended hour in
      time_field_min = Entry(self, width=2)
      time_field_min.insert(0, tmp_time.minute)
      time_field_sec = Entry(self, width=2)
      time_field_sec.insert(0, tmp_time.minute)
      time_field_label = Label(self, text="Alarm Time:")
      set_time_button = Button(self, text="Set Time", command=set_time)
     
      # This takes the amount of time we want to elapse before the alarm goes off
      dt_field_hour = Entry(self, width=2)
      dt_field_hour.insert(0, 8)
      dt_field_min = Entry(self, width=2)
      dt_field_min.insert(0, 0)
      dt_field_sec = Entry(self, width=2)
      dt_field_sec.insert(0, 0)
      dt_field_label = Label(self, text="Countdown:")
      set_dt_button = Button(self, text="Set Countdown", command=set_dt)
     
      # This field runs a command inserted into this field
      run_field = Entry(self)
      run_field.insert(0,'totem --play')
      run_field_label = Label(self, text="Alarm Command:")
   
      halt_field = Entry(self)
      halt_field.insert(0,'totem --pause')
      halt_field_label = Label(self, text="Stop Command:")
            
      # The quit button.  Closes the window and exits the program
      quit_button = Button(self, text="Quit", command=root.quit)
      
      # The stop alarm button.  Stops the alarm clock
      stop_button = Button(self, text="Stop Alarm", fg="red", command=halt_alarm)
      
      # This button starts the snooze sequence
      snooze_button = Button(self, text="Snooze " + str(snooze_min) + " min.", fg="red", command=snooze_alarm)
          
      #Set everything's location
      time_field_label.grid(row=0, column=0, sticky=W)
      time_field_hour.grid(row=0, column=1, sticky=W)
      Label(self, text=":").grid(row=0, column=2, sticky=W)
      time_field_min.grid(row=0, column=3, sticky=W)
      Label(self, text=":").grid(row=0, column=4, sticky=W)
      time_field_sec.grid(row=0, column=5, sticky=W)
      set_time_button.grid(row=0, column=6, sticky=EW)

      dt_field_label.grid(row=1, column=0, sticky=W)
      dt_field_hour.grid(row=1, column=1, sticky=W)
      Label(self, text=":").grid(row=1, column=2, sticky=W)
      dt_field_min.grid(row=1, column=3, sticky=W)
      Label(self, text=":").grid(row=1, column=4, sticky=W)
      dt_field_sec.grid(row=1, column=5, sticky=W)
      set_dt_button.grid(row=1, column=6, sticky=EW)

      rows = 7
      columns = 7

      run_field_label.grid(row=2, column=0, sticky=W)
      run_field.grid(row=2, column=1, columnspan=columns-1, sticky=EW)
      halt_field_label.grid(row=3, column=0, sticky=W)
      halt_field.grid(row=3, column=1, columnspan=columns-1, sticky=EW)
      snooze_button.grid(row=4, columnspan=columns, sticky=NSEW)
      stop_button.grid(row=5, columnspan=columns, sticky=NSEW)
      quit_button.grid(row=6, columnspan=columns, sticky=NSEW)
示例#14
0
def LastTodayTime():
    return today() + TimeDelta(hours=23, minutes=59, seconds=59)
 def halt_alarm():
    self.armed = False 
    dt = TimeDelta(0,0,0)
    update_fields()
    os.system(halt_field.get() + '&')
示例#16
0
 def estimate_migration_time(self, lease):
     return TimeDelta(seconds=0)
示例#17
0
from mx.DateTime import now, TimeDelta

if 0:
    # Force import of the datetime module
    d = now()
    d.pydate()

td = TimeDelta(3)
print td
td1 = td.rebuild()
print td1
pytime = td.pytime()
print pytime
pydelta = td.pytimedelta()
print pydelta
 def snooze_alarm():
    self.go_time = now() + TimeDelta(0,snooze_min,1)
    self.dt = TimeDelta(0,snooze_min)
    halt_alarm()
    self.armed = True
    run_alarm()
 def set_dt():
    self.dt = TimeDelta(int(dt_field_hour.get()),int(dt_field_min.get()),int(dt_field_sec.get()))
    self.go_time = now() + self.dt
    self.armed = True
    run_alarm()
 def sound_alarm():
    self.armed = False
    dt = TimeDelta(0,0,0)
    update_fields()
    os.system(run_field.get() + '&')
示例#21
0
文件: pgdb.py 项目: zkbt/MITTENS
def Time(hour, minute, second):
	return TimeDelta(hour, minute, second)
示例#22
0
class HaizeaConfig(Config):

    sections = []

    # ============================= #
    #                               #
    #        GENERAL OPTIONS        #
    #                               #
    # ============================= #

    general = Section(
        "general",
        required=True,
        doc=
        "This section is used for general options affecting Haizea as a whole."
    )
    general.options = \
    [
     Option(name        = "loglevel",
            getter      = "loglevel",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "INFO",
            valid       = ["STATUS","INFO","DEBUG","VDEBUG"],
            doc         = """
            Controls the level (and amount) of 
            log messages. Valid values are:
            
             - STATUS: Only print status messages
             - INFO: Slightly more verbose that STATUS
             - DEBUG: Prints information useful for debugging the scheduler.
             - VDEBUG: Prints very verbose information
               on the scheduler's internal data structures. Use only
               for short runs.        
            """),

     Option(name        = "logfile",
            getter      = "logfile",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "/var/tmp/haizea.log",
            doc         = """
            When running Haizea as a daemon, this option specifies the file
            that log messages should be written to.        
            """),

     Option(name        = "mode",
            getter      = "mode",
            type        = OPTTYPE_STRING,
            required    = True,
            valid       = ["simulated","opennebula"],
            doc         = """
            Sets the mode the scheduler will run in.
            Currently the only valid values are "simulated" and
            "opennebula". The "simulated" mode expects lease
            requests to be provided through a trace file, and
            all enactment is simulated. The "opennebula" mode
            interacts with the OpenNebula virtual infrastructure
            manager (http://www.opennebula.org/) to obtain lease
            requests and to do enactment on physical resources.                
            """),

     Option(name        = "lease-preparation",
            getter      = "lease-preparation",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.PREPARATION_UNMANAGED,
            valid       = [constants.PREPARATION_UNMANAGED,
                           constants.PREPARATION_TRANSFER],
            doc         = """
            Sets how the scheduler will handle the
            preparation overhead of leases. Valid values are:
            
             - unmanaged: The scheduler can assume that there
               is no deployment overhead, or that some
               other entity is taking care of it (e.g., one
               of the enactment backends)
             - imagetransfer: A disk image has to be transferred
               from a repository node before the lease can start.
            """),

     Option(name        = "lease-failure-handling",
            getter      = "lease-failure-handling",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.ONFAILURE_CANCEL,
            valid       = [constants.ONFAILURE_CANCEL,
                           constants.ONFAILURE_EXIT,
                           constants.ONFAILURE_EXIT_RAISE],
            doc         = """
            Sets how the scheduler will handle a failure in
            a lease. Valid values are:
            
             - cancel: The lease is cancelled and marked as "FAILED"
             - exit: Haizea will exit cleanly, printing relevant debugging
               information to its log.
             - exit-raise: Haizea will exit by raising an exception. This is
               useful for debugging, as IDEs will recognize this as an exception
               and will facilitate debugging it.
            """),

     Option(name        = "persistence-file",
            getter      = "persistence-file",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = defaults.PERSISTENCE_LOCATION,
            doc         = """
            This is the file where lease information, along with some
            additional scheduling information, is persisted to. If set
            to "none", no information will be persisted to disk, and
            Haizea will run entirely in-memory (this is advisable
            when running in simulation, as persisting to disk adds
            considerable overhead, compared to running in-memory).
            """)

    ]

    sections.append(general)

    # ============================= #
    #                               #
    #      SCHEDULING OPTIONS       #
    #                               #
    # ============================= #

    scheduling = Section(
        "scheduling",
        required=True,
        doc="The options in this section control how Haizea schedules leases.")
    scheduling.options = \
    [
     Option(name        = "mapper",
            getter      = "mapper",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "greedy",
            doc         = """
            VM-to-physical node mapping algorithm used by Haizea. There is currently
            only one mapper available (the greedy mapper).
            """),

     Option(name        = "policy-admission",
            getter      = "policy.admission",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "accept-all",
            doc         = """
            Lease admission policy. This controls what leases are accepted by Haizea. 
            Take into account that this decision takes place before Haizea even 
            attempts to schedule the lease (so, you can think of lease admission as 
            "eligibility to be scheduled"). 
            
            There are two built-in policies:
            
             - accept-all: Accept all leases.
             - no-ARs: Accept all leases except advance reservations.
             
            See the Haizea documentation for details on how to write your own
            policies.
            """),

     Option(name        = "policy-preemption",
            getter      = "policy.preemption",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "no-preemption",
            doc         = """
            Lease preemption policy. Determines what leases can be preempted. There
            are two built-in policies:
            
             - no-preemption: Do not allow any preemptions
             - ar-preempts-everything: Allow all ARs to preempt other leases.
            
            See the Haizea documentation for details on how to write your own
            policies.
            """),
     Option(name        = "policy-matchmaking",
            getter      = "policy.matchmaking",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "condor",
            doc         = ""),

     Option(name        = "policy-host-selection",
            getter      = "policy.host-selection",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = "greedy",
            doc         = """
            Physical host selection policy. controls how Haizea chooses what physical hosts 
            to map VMs to. This option is closely related to the mapper options 
            (if the greedy mapper is used, then the greedy host selection policy
            should be used, or unexpected results will happen). 
            
            The two built-in policies are:
             - no-policy: Choose nodes arbitrarily
             - greedy: Apply a greedy policy that tries to minimize the number
               of preemptions.
            
            See the Haizea documentation for details on how to write your own
            policies.
            """),

     Option(name        = "wakeup-interval",
            getter      = "wakeup-interval",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            default     = TimeDelta(seconds=60),
            doc         = """
            Interval at which Haizea will wake up
            to manage resources and process pending requests.
            This option is not used when using a simulated clock,
            since the clock will skip directly to the time where an
            event is happening.
            """),

     Option(name        = "backfilling",
            getter      = "backfilling",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = None,
            valid       = [constants.BACKFILLING_OFF,
                           constants.BACKFILLING_AGGRESSIVE,
                           constants.BACKFILLING_CONSERVATIVE,
                           constants.BACKFILLING_INTERMEDIATE],
            doc         = """
            Backfilling algorithm to use. Valid values are:
            
             - off: don't do backfilling
             - aggressive: at most 1 reservation in the future
             - conservative: unlimited reservations in the future
             - intermediate: N reservations in the future (N is specified
               in the backfilling-reservations option)
            """),

     Option(name        = "backfilling-reservations",
            getter      = "backfilling-reservations",
            type        = OPTTYPE_INT,
            required    = False,
            required_if = [(("scheduling","backfilling"),constants.BACKFILLING_INTERMEDIATE)],
            doc         = """
            Number of future reservations to allow when
            using the "intermediate" backfilling option.
            """),

     Option(name        = "suspension",
            getter      = "suspension",
            type        = OPTTYPE_STRING,
            required    = True,
            valid       = [constants.SUSPENSION_NONE,
                           constants.SUSPENSION_SERIAL,
                           constants.SUSPENSION_ALL],
            doc         = """
            Specifies what can be suspended. Valid values are:
            
             - none: suspension is never allowed
             - serial-only: only 1-node leases can be suspended
             - all: any lease can be suspended                
            """),

     Option(name        = "suspend-rate",
            getter      = "suspend-rate",
            type        = OPTTYPE_FLOAT,
            required    = True,
            doc         = """
            Rate at which VMs are assumed to suspend (in MB of
            memory per second)                
            """),

     Option(name        = "resume-rate",
            getter      = "resume-rate",
            type        = OPTTYPE_FLOAT,
            required    = True,
            doc         = """
            Rate at which VMs are assumed to resume (in MB of
            memory per second)                
            """),

     Option(name        = "suspendresume-exclusion",
            getter      = "suspendresume-exclusion",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.SUSPRES_EXCLUSION_LOCAL,
            valid       = [constants.SUSPRES_EXCLUSION_LOCAL,
                           constants.SUSPRES_EXCLUSION_GLOBAL],
            doc         = """
            When suspending or resuming a VM, the VM's memory is dumped to a
            file on disk. To correctly estimate the time required to suspend
            a lease with multiple VMs, Haizea makes sure that no two 
            suspensions/resumptions happen at the same time (e.g., if eight
            memory files were being saved at the same time to disk, the disk's
            performance would be reduced in a way that is not as easy to estimate
            as if only one file were being saved at a time).
            
            Depending on whether the files are being saved to/read from a global
            or local filesystem, this exclusion can be either global or local.                        
            """),

     Option(name        = "scheduling-threshold-factor",
            getter      = "scheduling-threshold-factor",
            type        = OPTTYPE_INT,
            required    = False,
            default     = 1,
            doc         = """
            To avoid thrashing, Haizea will not schedule a lease unless all overheads
            can be correctly scheduled (which includes image transfers, suspensions, etc.).
            However, this can still result in situations where a lease is prepared,
            and then immediately suspended because of a blocking lease in the future.
            The scheduling threshold factor can be used to specify that a lease must
            not be scheduled unless it is guaranteed to run for a minimum amount of
            time (the rationale behind this is that you ideally don't want leases
            to be scheduled if they're not going to be active for at least as much time
            as was spent in overheads).
            
            The default value is 1, meaning that the lease will be active for at least
            as much time T as was spent on overheads (e.g., if preparing the lease requires
            60 seconds, and we know that it will have to be suspended, requiring 30 seconds,
            Haizea won't schedule the lease unless it can run for at least 90 minutes).
            In other words, a scheduling factor of F required a minimum duration of 
            F*T. A value of 0 could lead to thrashing, since Haizea could end up with
            situations where a lease starts and immediately gets suspended.               
            """),

     Option(name        = "override-suspend-time",
            getter      = "override-suspend-time",
            type        = OPTTYPE_INT,
            required    = False,
            default     = None,
            doc         = """
            Overrides the time it takes to suspend a VM to a fixed value
            (i.e., not computed based on amount of memory, enactment overhead, etc.)
            """),

     Option(name        = "override-resume-time",
            getter      = "override-resume-time",
            type        = OPTTYPE_INT,
            required    = False,
            default     = None,
            doc         = """
            Overrides the time it takes to suspend a VM to a fixed value
            (i.e., not computed based on amount of memory, enactment overhead, etc.)
            """),

     Option(name        = "force-scheduling-threshold",
            getter      = "force-scheduling-threshold",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            doc         = """
            This option can be used to force a specific scheduling threshold time
            to be used, instead of calculating one based on overheads.                
            """),

     Option(name        = "migration",
            getter      = "migration",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.MIGRATE_NO,
            valid       = [constants.MIGRATE_NO,
                           constants.MIGRATE_YES,
                           constants.MIGRATE_YES_NOTRANSFER],
            doc         = """
            Specifies whether leases can be migrated from one
            physical node to another. Valid values are: 
            
             - no
             - yes
             - yes-notransfer: migration is performed without
               transferring any files. 
            """),

     Option(name        = "non-schedulable-interval",
            getter      = "non-schedulable-interval",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            default     = TimeDelta(seconds=10),
            doc         = """
            The minimum amount of time that must pass between
            when a request is scheduled to when it can actually start.
            The default should be good for most configurations, but
            may need to be increased if you're dealing with exceptionally
            high loads.                
            """),

     Option(name        = "shutdown-time",
            getter      = "shutdown-time",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            default     = TimeDelta(seconds=0),
            doc         = """
            The amount of time that will be allocated for a VM to shutdown.
            When running in OpenNebula mode, it is advisable to set this to
            a few seconds, so no operation gets scheduled right when a
            VM is shutting down. The most common scenario is that a VM
            will start resuming right when another VM shuts down. However,
            since both these activities involve I/O, it can delay the resume
            operation and affect Haizea's estimation of how long the resume
            will take.
            """),

     Option(name        = "enactment-overhead",
            getter      = "enactment-overhead",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            default     = TimeDelta(seconds=0),
            doc         = """
            The amount of time that is required to send
            an enactment command. This value will affect suspend/resume
            estimations and, in OpenNebula mode, will force a pause
            of this much time between suspend/resume enactment
            commands. When suspending/resuming many VMs at the same time
            (which is likely to happen if suspendresume-exclusion is set
            to "local"), it will take OpenNebula 1-2 seconds to process
            each command (this is a small amount of time, but if 32 VMs
            are being suspended at the same time, on in each physical node,
            this time can compound up to 32-64 seconds, which has to be
            taken into account when estimating when to start a suspend
            operation that must be completed before another lease starts).
            """)

    ]
    sections.append(scheduling)

    # ============================= #
    #                               #
    #      SIMULATION OPTIONS       #
    #                               #
    # ============================= #

    simulation = Section(
        "simulation",
        required=False,
        required_if=[(("general", "mode"), "simulated")],
        doc=
        "This section is used to specify options when Haizea runs in simulation"
    )
    simulation.options = \
    [
     Option(name        = "clock",
            getter      = "clock",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.CLOCK_REAL,
            valid       = [constants.CLOCK_REAL,
                           constants.CLOCK_SIMULATED],
            doc         = """
            Type of clock to use in simulation:
            
             - simulated: A simulated clock that fastforwards through
               time. Can only use the tracefile request
               frontend
             - real: A real clock is used, but simulated resources and
               enactment actions are used. Can only use the RPC
               request frontend.                
            """),

     Option(name        = "starttime",
            getter      = "starttime",
            type        = OPTTYPE_DATETIME,
            required    = False,
            required_if = [(("simulation","clock"),constants.CLOCK_SIMULATED)],
            doc         = """
            Time at which simulated clock will start.                
            """),

     Option(name        = "resources",
            getter      = "simul.resources",
            type        = OPTTYPE_STRING,
            required    = True,
            doc         = """
            Simulated resources. This option can take two values,
            "in-tracefile" (which means that the description of
            the simulated site is in the tracefile) or a string 
            specifying a site with homogeneous resources. 
            The format is:
        
            <numnodes> [ <resource_type>:<resource_quantity>]+
        
            For example, "4  CPU:100 Memory:1024" describes a site
            with four nodes, each with one CPU and 1024 MB of memory.
            """),

     Option(name        = "imagetransfer-bandwidth",
            getter      = "imagetransfer-bandwidth",
            type        = OPTTYPE_INT,
            required    = True,
            doc         = """
            Bandwidth (in Mbps) available for image transfers.
            This would correspond to the outbound network bandwidth of the
            node where the images are stored.                
            """),

     Option(name        = "stop-when",
            getter      = "stop-when",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.STOPWHEN_ALLDONE,
            valid       = [constants.STOPWHEN_ALLDONE,
                           constants.STOPWHEN_BESUBMITTED,
                           constants.STOPWHEN_BEDONE],
            doc         = """
            When using the simulated clock, this specifies when the
            simulation must end. Valid options are:
            
             - all-leases-done: All requested leases have been completed
               and there are no queued/pending requests.
             - besteffort-submitted: When all best-effort leases have been
               submitted.
             - besteffort-done: When all best-effort leases have been
               completed.                
            """),

     Option(name        = "status-message-interval",
            getter      = "status-message-interval",
            type        = OPTTYPE_INT,
            required    = False,
            default     = None,
            doc         = """
            If specified, the simulated clock will print a status
            message with some basic statistics. This is useful to keep track
            of long simulations. The interval is specified in minutes.                
            """)

    ]
    sections.append(simulation)

    # ============================= #
    #                               #
    #      ACCOUNTING OPTIONS       #
    #                               #
    # ============================= #

    accounting = Section(
        "accounting",
        required=True,
        doc=
        "Haizea can collect information while running, and save that information to a file for off-line processing. This section includes options controlling this feature."
    )

    accounting.options = \
    [
     Option(name        = "datafile",
            getter      = "datafile",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = None,
            doc         = """
            This is the file where statistics on
            the scheduler's run will be saved to (waiting time of leases,
            utilization data, etc.). If omitted, no data will be saved.
            """),

     Option(name        = "probes",
            getter      = "accounting-probes",
            type        = OPTTYPE_STRING,
            required    = False,
            doc         = """
            Accounting probes.
            
            There are four built-in probes:
            
             - AR: Collects information on AR leases.
             - best-effort: Collects information on best effort leases.
             - immediate: Collects information immediate leases.
             - utilization: Collects information on resource utilization.
             
            See the Haizea documentation for details on how to write your
            own accounting probes.
      
            """),

     Option(name        = "attributes",
            getter      = "attributes",
            type        = OPTTYPE_STRING,
            required    = False,
            doc         = """
            This option is used internally by Haizea when using
            multiconfiguration files. See the multiconfiguration
            documentation for more details.        
            """)
    ]

    sections.append(accounting)

    # ============================= #
    #                               #
    #      DEPLOYMENT OPTIONS       #
    #     (w/ image transfers)      #
    #                               #
    # ============================= #

    imgtransfer = Section("deploy-imagetransfer",
                          required=False,
                          required_if=[(("general", "lease-deployment"),
                                        "imagetransfer")],
                          doc="""
                         When lease deployment with disk image transfers is selected,
                         this section is used to control image deployment parameters."""
                          )
    imgtransfer.options = \
    [
     Option(name        = "transfer-mechanism",
            getter      = "transfer-mechanism",
            type        = OPTTYPE_STRING,
            required    = True,
            valid       = [constants.TRANSFER_UNICAST,
                           constants.TRANSFER_MULTICAST],
            doc         = """
            Specifies how disk images are transferred. Valid values are:
            
             - unicast: A disk image can be transferred to just one node at a time
             - multicast: A disk image can be multicast to multiple nodes at 
               the same time.                
            """),

     Option(name        = "avoid-redundant-transfers",
            getter      = "avoid-redundant-transfers",
            type        = OPTTYPE_BOOLEAN,
            required    = False,
            default     = True,
            doc         = """
            Specifies whether the scheduler should take steps to
            detect and avoid redundant transfers (e.g., if two leases are
            scheduled on the same node, and they both require the same disk
            image, don't transfer the image twice; allow one to "piggyback"
            on the other). There is generally no reason to set this option
            to False.
            """),

     Option(name        = "force-imagetransfer-time",
            getter      = "force-imagetransfer-time",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            doc         = """
            Forces the image transfer time to a specific amount.
            This options is intended for testing purposes.                
            """),

     Option(name        = "diskimage-reuse",
            getter      = "diskimage-reuse",
            type        = OPTTYPE_STRING,
            required    = False,
            required_if = None,
            default     = constants.REUSE_NONE,
            valid       = [constants.REUSE_NONE,
                           constants.REUSE_IMAGECACHES],
            doc         = """
            Specifies whether disk image caches should be created
            on the nodes, so the scheduler can reduce the number of transfers
            by reusing images. Valid values are:
            
             - none: No image reuse
             - image-caches: Use image caching algorithm described in Haizea
               publications
            """),

     Option(name        = "diskimage-cache-size",
            getter      = "diskimage-cache-size",
            type        = OPTTYPE_INT,
            required    = False,
            required_if = [(("deploy-imagetransfer","diskimage-reuse"),True)],
            doc         = """
            Specifies the size (in MB) of the disk image cache on
            each physical node.                
            """)
    ]
    sections.append(imgtransfer)

    # ============================= #
    #                               #
    #      TRACEFILE OPTIONS        #
    #                               #
    # ============================= #

    tracefile = Section("tracefile",
                        required=False,
                        doc="""
                        When reading in requests from a tracefile, this section is used
                        to specify the tracefile and other parameters.""")
    tracefile.options = \
    [
     Option(name        = "tracefile",
            getter      = "tracefile",
            type        = OPTTYPE_STRING,
            required    = True,
            doc         = """
            Path to tracefile to use.                
            """),

     Option(name        = "imagefile",
            getter      = "imagefile",
            type        = OPTTYPE_STRING,
            required    = False,
            doc         = """
            Path to list of images to append to lease requests.
            If omitted, the images in the tracefile are used.                
            """),

     Option(name        = "injectionfile",
            getter      = "injectionfile",
            type        = OPTTYPE_STRING,
            required    = False,
            doc         = """
            Path to file with leases to "inject" into the tracefile.                
            """),

     Option(name        = "runtime-slowdown-overhead",
            getter      = "runtime-slowdown-overhead",
            type        = OPTTYPE_FLOAT,
            required    = False,
            default     = 0,
            doc         = """
            Adds a runtime overhead (in %) to the lease duration.                
            """),

     Option(name        = "add-overhead",
            getter      = "add-overhead",
            type        = OPTTYPE_STRING,
            required    = False,
            default     = constants.RUNTIMEOVERHEAD_NONE,
            valid       = [constants.RUNTIMEOVERHEAD_NONE,
                           constants.RUNTIMEOVERHEAD_ALL,
                           constants.RUNTIMEOVERHEAD_BE],
            doc         = """
            Specifies what leases will have a runtime overhead added:
            
             - none: No runtime overhead must be added.
             - besteffort: Add only to best-effort leases
             - all: Add runtime overhead to all leases                
            """),

     Option(name        = "bootshutdown-overhead",
            getter      = "bootshutdown-overhead",
            type        = OPTTYPE_TIMEDELTA,
            required    = False,
            default     = TimeDelta(seconds=0),
            doc         = """
            Specifies how many seconds will be alloted to
            boot and shutdown of the lease.                
            """),

     Option(name        = "override-memory",
            getter      = "override-memory",
            type        = OPTTYPE_INT,
            required    = False,
            default     = constants.NO_MEMORY_OVERRIDE,
            doc         = """
            Overrides memory requirements specified in tracefile.
            """),
    ]
    sections.append(tracefile)

    # ============================= #
    #                               #
    #      OPENNEBULA OPTIONS       #
    #                               #
    # ============================= #

    opennebula = Section("opennebula",
                         required=False,
                         required_if=[(("general", "mode"), "opennebula")],
                         doc="""
                         This section is used to specify OpenNebula parameters,
                         necessary when using Haizea as an OpenNebula scheduling backend."""
                         )
    opennebula.options = \
    [
     Option(name        = "host",
            getter      = "one.host",
            type        = OPTTYPE_STRING,
            required    = True,
            doc         = """
            Host where OpenNebula is running.
            Typically, OpenNebula and Haizea will be installed
            on the same host, so the following option should be
            set to 'localhost'. If they're on different hosts,
            make sure you modify this option accordingly.             
            """),

     Option(name        = "port",
            getter      = "one.port",
            type        = OPTTYPE_INT,
            required    = False,
            default     = defaults.OPENNEBULA_RPC_PORT,
            doc         = """
            TCP port of OpenNebula's XML RPC server             
            """),

     Option(name        = "stop-when-no-more-leases",
            getter      = "stop-when-no-more-leases",
            type        = OPTTYPE_BOOLEAN,
            required    = False,
            default     = False,
            doc         = """
            This option is useful for testing and running experiments.
            If set to True, Haizea will stop when there are no more leases
            to process (which allows you to tun Haizea and OpenNebula unattended,
            and count on it stopping when there are no more leases to process).
            For now, this only makes sense if you're seeding Haizea with requests from
            the start (otherwise, it will start and immediately stop).
            """),

     Option(name        = "dry-run",
            getter      = "dry-run",
            type        = OPTTYPE_BOOLEAN,
            required    = False,
            default     = False,
            doc         = """
            This option is useful for testing.
            If set to True, Haizea will fast-forward through time (note that this is
            different that using the simulated clock, which has to be used with a tracefile;
            with an Haizea/OpenNebula dry run, you will have to seed OpenNebula with requests
            before starting Haizea). You will generally want to set stop-when-no-more-leases
            when doing a dry-run.
            
            IMPORTANT: Haizea will still send out enactment commands to OpenNebula. Make
            sure you replace onevm with a dummy command that does nothing (or that reacts
            in some way you want to test; e.g., by emulating a deployment failure, etc.)
            """),

    ]
    sections.append(opennebula)

    def __init__(self, config):
        Config.__init__(self, config, self.sections)

        self.attrs = {}
        if self._options["attributes"] != None:
            attrs = self._options["attributes"].split(",")
            for attr in attrs:
                (k, v) = attr.split("=")
                self.attrs[k] = v

    def get_attr(self, attr):
        return self.attrs[attr]

    def get_attrs(self):
        return self.attrs.keys()