Skip to content
This repository was archived by the owner on Apr 11, 2019. It is now read-only.

Schedule

Michael Smart edited this page Jan 20, 2015 · 1 revision

Schedule

All AMs manage reservations for resources. It may be that resources can only be used exclusively or that can only booked right now and not in advance. Anyway, this plugin supports in managing these reservations. It takes a big burden from the developer because it takes care of persistance, detects booking collisions and offers the needed methods for management.

Operation

Best-effort or preorder

The schedule plugin can be used in two ways. Either as best-effort booking system. In a best-effort scheme, all operations (such as provision or delete) apply to the current time. This means, if the client wants to provision a resource until time X, it is implied that the start time for the reservation is now. The other option to manage reservations is to use prebookings. In this case, the start time can be given explicitly and it is possible to book a resource in advance.

Please find more information on bounded and unbounded resources in the Quickstart PDF.

Multiple schedules

The schedule plugin supports multiple different subjects. Distinct schedule subjects make distinct schedules. Conceptionally, two different subjects mean two distinct databases. Usually, you would create one Schedule instance per resource type/classification and re-use this instance. However, if you create multiple instances, nothing really bad happens.

Example:

    import uuid
    import eisoil.core.pluginmanager as pm
    
    Schedule = pm.getService('schedule')
    ip_schedule = Schedule("IPLease", 100) # create a schedule for IPs
    vm_schedule = Schedule("VM", 100) # create a schedule object for VMs

    ip1 = ip_schedule.reserve(resource_id='192.168.1.1') # create a reservation with mostly default values
    ip2 = ip_schedule.reserve(resource_id='192.168.1.2')
    vm1 = vm_schedule.reserve(resource_id=str(uuid.uuid4())) # e.g. 'ec1f33f0-8443-11e3-baa7-0800200c9a66'

    print len(ip_schedule.find()) # -> 2 (192.168.1.1, 192.168.1.2)
    print len(vm_schedule.find()) # -> 1 (ec1f33f0-8443-11e3-baa7-0800200c9a66)

Fields

The schedule plugin prescribes only the bare minimal of fields to manage reservations. Yet, by the means of resource_spec it provides a field where the AM developer can store whatever he/she needs. This saves the developer the trouble of dealing with the database. He/She can use this plugin and have all the relevant information associated with the reservation.

Aside from the schedule's subject, each reservation may have the following fields:

  • reservation_id (int) Is used to identify specific a reservation record. The unique numbering is done automatically.
  • resource_id (str) Is a mean to identify a specific resource and is user specified. (see Constraints below)
  • resource_spec (optional dict / pickle) This can be used to save additional information for the reservation (e.g. resource configuration). If you are a 100% aware how pickle works, you may put arbitrary objects in this field.
  • user_id (optional str) Can be used to specify the user's identity. The format is to be determined by the AM developer.
  • slice_id (optional str) Can be used to distiguish projects, experiments and such. The format is to be determined by the AM developer (e.g. slice's name, a uuid).
  • start_time (datetime) When the reservation starts (defaults to datetime.utcnow()).
  • end_time (datetime) When the reservation ends (defaults to start_time + the {default_duration} given in Schedule's init method (number in seconds).

Note on times: For specifying time always use the pyhton class datetime. UTC is assumed as timezone.
Note on periods: When finding records and specifying a period (by giving start_time and end_time), all touching reservations will be returned. This means, that you do not only get records which are fully within the given period.

Whenever you receive a reservation from the plugin, the returned object will be a value object. This means that it is not bound to the database and you can not accidentally change the database's content. The returned reservation is of the class AttributeDict (see schedule/attributedict.py). This class behaves like a dict, but you can access/mutate the keys as properties.
Tip: You can use the str(my_reservation) method to see all info contained in the reservation.

Example

    Schedule = pm.getService('schedule')
    ip_schedule = Schedule("IPLease", 100) # create a schedule for a resource with default reservation duration of 100 sec
    
    # create
    ip1 = ip_schedule.reserve(resource_id='192.168.1.1') # simple creation
    ip2 = ip_schedule.reserve(
        resource_id='192.168.1.2',
        resource_spec={"additional_information" : [1,2,3] },
        slice_id='pizza',
        user_id='tom',
        start_time=datetime.utcnow(),
        end_time=datetime.utcnow() + timedelta(0,0,10,0)
        )
    
    # inspect
    print ip2          # -> {"reservation_id" : 5, "resource_id" : "192.168.1.2", "slice_id" : "pizza", ...}
    print ip2.user_id  # -> "tom"
    
    # find
    ip_schedule.find() # finds all entries
    ip_schedule.find(user_id='tom') # finds all reservations by tom
    ip_schedule.find(start_time=datetime.utcnow()) # finds all current reservations
    ip_schedule.find(start_time=datetime.utcnow(), slice_id='pizza') # finds all current reservations which belong to the pizza slice
    
    # update
    the_first = ip_schedule.find()[0]
    # leave the first reservation as is, but change the user_id and resource_spec
    ip_schedule.update(the_first.reservation_id, user_id='manfred', resource_spec={'a' : 'b'})
    
    # remove reservation
    ip_schedule.cancel(ip1.reservation_id)

Constraints

There shall never be two reservations for the same subject and resource_id at any given time. Hence the following code will throw an ScheduleOverbookingError:

    Schedule = pm.getService('schedule')
    sch_ex = pm.getService('scheduleexceptions')
    ip_schedule = Schedule("IPLease", 100)
    
    ipSchedule.reserve(resource_id='192.168.10.1', start_time=datetime.utcnow())
    try:
      ipSchedule.reserve(resource_id='192.168.10.1', start_time=datetime.utcnow())
    except sch_ex.ScheduleOverbookingError, e:
      print "I told you so!"

There is no such thing as an available flag. If there is a reservation in the database, it means, that the resource is blocked for that time. Yet, if you want to have unbounded resources, you can simply use unique resource_ids.

Clone this wiki locally