[haizea-commit] r610 - branches/TP2.0/src/haizea/core

haizea-commit at mailman.cs.uchicago.edu haizea-commit at mailman.cs.uchicago.edu
Mon Jul 20 11:04:28 CDT 2009


Author: borja
Date: 2009-07-20 11:04:22 -0500 (Mon, 20 Jul 2009)
New Revision: 610

Modified:
   branches/TP2.0/src/haizea/core/leases.py
   branches/TP2.0/src/haizea/core/manager.py
Log:
- Polished up documentation on manager.py
- Documented most of leases.py

Modified: branches/TP2.0/src/haizea/core/leases.py
===================================================================
--- branches/TP2.0/src/haizea/core/leases.py	2009-07-17 15:04:33 UTC (rev 609)
+++ branches/TP2.0/src/haizea/core/leases.py	2009-07-20 16:04:22 UTC (rev 610)
@@ -16,9 +16,21 @@
 # limitations under the License.                                             #
 # -------------------------------------------------------------------------- #
 
-"""This module provides the lease data structures, and a couple of auxiliary
-data structures.
+"""This module provides the lease data structures:
 
+* Lease: Represents a lease
+* LeaseStateMachine: A state machine to keep track of a lease's state
+* Capacity: Used to represent a quantity of resources
+* Timestamp: An exact moment in time
+* Duration: A duration
+* SoftwareEnvironment, UnmanagedSoftwareEnvironment, DiskImageSoftwareEnvironment:
+  Used to represent a lease's required software environment.
+* LeaseWorkload: Represents a collection of lease requests submitted
+  in a specific order.
+* Site: Represents the site with leasable resources.
+* Nodes: Represents a collection of machines ("nodes"). This is used
+  both when specifying a site and when specifying the machines
+  needed by a leases.
 """
 
 from haizea.common.constants import LOGLEVEL_VDEBUG
@@ -30,14 +42,25 @@
 import logging
 import xml.etree.ElementTree as ET
 
-#-------------------------------------------------------------------#
-#                                                                   #
-#                     LEASE DATA STRUCTURES                         #
-#                                                                   #
-#-------------------------------------------------------------------#
 
 
+
 class Lease(object):
+    """A resource lease
+    
+    This is one of the main data structures used in Haizea. A lease
+    is "a negotiated and renegotiable agreement between a resource 
+    provider and a resource consumer, where the former agrees to make 
+    a set of resources available to the latter, based on a set of 
+    lease terms presented by the resource consumer". All the gory
+    details on what this means can be found on the Haizea website
+    and on the Haizea publications.
+    
+    See the __init__ method for a description of the information that
+    is contained in a lease.
+    
+    """
+    
     # Lease states
     STATE_NEW = 0
     STATE_PENDING = 1
@@ -58,6 +81,7 @@
     STATE_DONE = 16
     STATE_FAIL = 17
     
+    # String representation of lease states
     state_str = {STATE_NEW : "New",
                  STATE_PENDING : "Pending",
                  STATE_REJECTED : "Rejected",
@@ -83,6 +107,7 @@
     IMMEDIATE = 3
     UNKNOWN = -1
     
+    # String representation of lease types    
     type_str = {BEST_EFFORT: "Best-effort",
                 ADVANCE_RESERVATION: "AR",
                 IMMEDIATE: "Immediate",
@@ -90,44 +115,174 @@
     
     def __init__(self, submit_time, requested_resources, start, duration, 
                  deadline, preemptible, software):
+        """Constructs a lease.
+        
+        The arguments are the fundamental attributes of a lease.
+        The attributes that are not specified by the arguments are
+        the lease ID (which is an autoincremented integer), the
+        lease state (a lease always starts out in state "NEW").
+        A lease also has several bookkeeping attributes that are
+        only meant to be consumed by other Haizea objects.
+        
+        Arguments:
+        submit_time -- The time at which the lease was submitted
+        requested_resources -- A dictionary (int -> Capacity) mapping
+          each requested node to a capacity (i.e., the amount of
+          resources requested for that node)
+        start -- A Timestamp object containing the requested time.
+        duration -- A Duration object containing the requested duration.
+        deadline -- A Timestamp object containing the deadline by which
+          this lease must be completed.
+        preemptible -- A boolean indicating whether this lease can be
+          preempted or not.
+        software -- A SoftwareEnvironment object specifying the
+          software environment required by the lease.
+        """        
         # Lease ID (read only)
         self.id = get_lease_id()
         
-        # Request attributes (read only)
+        # Lease attributes
         self.submit_time = submit_time
+        self.requested_resources = requested_resources
         self.start = start
         self.duration = duration
-        self.end = None
+        self.deadline = deadline
+        self.preemptible = preemptible
         self.software = software
-        self.requested_resources = requested_resources
-        self.preemptible = preemptible
 
-        # Bookkeeping attributes
-        # (keep track of the lease's state, resource reservations, etc.)
+        # Bookkeeping attributes:
+
+        # Lease state
         self.state = LeaseStateMachine()
+
+        # End of lease (recorded when the lease ends)
+        self.end = None
+        
+        # Number of nodes requested in the lease
         self.numnodes = len(requested_resources)
+        
+        # The following two lists contain all the resource reservations
+        # (or RRs) associated to this lease. These two lists are
+        # basically the link between the lease and Haizea's slot table.
+        
+        # The preparation RRs are reservations that have to be
+        # completed before a lease can first transition into a
+        # READY state (e.g., image transfers)
         self.preparation_rrs = []
+        # The VM RRs are reservations for the VMs that implement
+        # the lease.
         self.vm_rrs = []
 
         # Enactment information. Should only be manipulated by enactment module
         self.enactment_info = None
-        self.vnode_enactment_info = dict([(n+1, None) for n in range(self.numnodes)])
+        self.vnode_enactment_info = dict([(n, None) for n in self.requested_resources.keys()])
         
         self.logger = logging.getLogger("LEASES")
         
+    @classmethod
+    def from_xml_file(cls, xml_file):
+        """Constructs a lease from an XML file.
+        
+        See the Haizea documentation for details on the
+        lease XML format.
+        
+        Argument:
+        xml_file -- XML file containing the lease in XML format.
+        """        
+        cls.from_xml_element(ET.parse(xml_file).getroot())
+
+    @classmethod
+    def from_xml_string(cls, xml_str):
+        """Constructs a lease from an XML string.
+        
+        See the Haizea documentation for details on the
+        lease XML format.
+        
+        Argument:
+        xml_str -- String containing the lease in XML format.
+        """        
+        cls.from_xml_element(ET.parsestring(xml_str))
+        
+    @classmethod
+    def from_xml_element(cls, element):
+        """Constructs a lease from an ElementTree element.
+        
+        See the Haizea documentation for details on the
+        lease XML format.
+        
+        Argument:
+        element -- Element object containing a "<lease>" element.
+        """        
+        submit_time = Parser.DateTimeFromString(element.get("submit-time"))
+        
+        nodes = Nodes.from_xml_element(element.find("nodes"))
+        
+        requested_resources = nodes.get_all_nodes()
+        
+        start = element.find("start")
+        if len(start.getchildren()) == 0:
+            start = Timestamp(None)
+        else:
+            exact = start.find("exact")
+            if exact != None:
+                start = Timestamp(Parser.DateTimeFromString(exact.get("time")))
+            # TODO: Other starting times
+        
+        duration = Duration(Parser.DateTimeDeltaFromString(element.find("duration").get("time")))
+
+        deadline = None
+        
+        preemptible = bool(element.get("preemptible"))
+        
+        software = element.find("software")
+        
+        if software.find("none") != None:
+            software = UnmanagedSoftwareEnvironment()
+        elif software.find("disk-image") != None:
+            disk_image = software.find("disk-image")
+            image_id = disk_image.get("id")
+            image_size = int(disk_image.get("size"))
+            software = DiskImageSoftwareEnvironment(image_id, image_size)
+        
+        return Lease(submit_time, requested_resources, start, duration, 
+                     deadline, preemptible, software)
+
     def get_type(self):
+        """Determines the type of lease
+        
+        Based on the lease's attributes, determines the lease's type.
+        Can return Lease.BEST_EFFORT, Lease.ADVANCE_RESERVATION, or
+        Lease.IMMEDIATE
+        
+        """
         if self.start.requested == None:
             return Lease.BEST_EFFORT
         else:
             return Lease.ADVANCE_RESERVATION
         
     def get_state(self):
+        """Returns the lease's state.
+                
+        """        
         return self.state.get_state()
     
     def set_state(self, state):
+        """Changes the lease's state.
+                
+        The state machine will throw an exception if the 
+        requested transition is illegal.
+        
+        Argument:
+        state -- The new state
+        """        
         self.state.change_state(state)
         
     def print_contents(self, loglevel=LOGLEVEL_VDEBUG):
+        """Prints the lease's attributes to the log.
+                
+        Argument:
+        loglevel -- The loglevel at which to print the information
+        """           
         self.logger.log(loglevel, "__________________________________________________")
         self.logger.log(loglevel, "Lease ID       : %i" % self.id)
         self.logger.log(loglevel, "Type           : %s" % Lease.type_str[self.get_type()])
@@ -141,6 +296,11 @@
         self.logger.log(loglevel, "--------------------------------------------------")
 
     def print_rrs(self, loglevel=LOGLEVEL_VDEBUG):
+        """Prints the lease's resource reservations to the log.
+                
+        Argument:
+        loglevel -- The loglevel at which to print the information
+        """              
         if len(self.preparation_rrs) > 0:
             self.logger.log(loglevel, "DEPLOYMENT RESOURCE RESERVATIONS")
             self.logger.log(loglevel, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
@@ -154,47 +314,121 @@
             self.logger.log(loglevel, "##")
 
     def get_active_vmrrs(self, time):
+        """Returns the active VM resource reservations at a given time
+                
+        Argument:
+        time -- Time to look for active reservations
+        """        
         return [r for r in self.vm_rrs if r.start <= time and time <= r.end and r.state == ResourceReservation.STATE_ACTIVE]
 
     def get_scheduled_reservations(self):
+        """Returns all scheduled reservations
+                
+        """           
         return [r for r in self.preparation_rrs + self.vm_rrs if r.state == ResourceReservation.STATE_SCHEDULED]
 
+    def get_last_vmrr(self):
+        """Returns the last VM reservation for this lease.
+                        
+        """            
+        return self.vm_rrs[-1]    
+
     def get_endtime(self):
+        """Returns the time at which the last VM reservation 
+        for this lease ends.
+        
+        Note that this is not necessarily the time at which the lease
+        will end, just the time at which the last currently scheduled
+        VM will end.
+                
+        """        
         vmrr = self.get_last_vmrr()
         return vmrr.end
-
+    
     def append_vmrr(self, vmrr):
+        """Adds a VM resource reservation to the lease.
+        
+        Argument:
+        vmrr -- The VM RR to add.
+        """             
         self.vm_rrs.append(vmrr)
         
-    def append_preparationrr(self, vmrr):
-        self.preparation_rrs.append(vmrr)
+    def remove_vmrr(self, vmrr):
+        """Removes a VM resource reservation from the lease.
         
+        Argument:
+        vmrr -- The VM RR to remove.
+        """           
+        if not vmrr in self.vm_rrs:
+            raise Exception, "Tried to remove an VM RR not contained in this lease"
+        else:
+            self.vm_rrs.remove(vmrr)
+                    
+    def append_preparationrr(self, preparation_rr):
+        """Adds a preparation resource reservation to the lease.
+        
+        Argument:
+        preparation_rr -- The preparation RR to add.
+        """             
+        self.preparation_rrs.append(preparation_rr)
+        
     def remove_preparationrr(self, preparation_rr):
+        """Removes a preparation resource reservation from the lease.
+        
+        Argument:
+        preparation_rr -- The preparation RR to remove.
+        """        
         if not preparation_rr in self.preparation_rrs:
             raise Exception, "Tried to remove a preparation RR not contained in this lease"
         else:
             self.preparation_rrs.remove(preparation_rr)        
 
-    def get_last_vmrr(self):
-        return self.vm_rrs[-1]
-
-    def update_vmrr(self, rrold, rrnew):
-        self.vm_rrs[self.vm_rrs.index(rrold)] = rrnew
-    
-    def remove_vmrr(self, vmrr):
-        if not vmrr in self.vm_rrs:
-            raise Exception, "Tried to remove an VM RR not contained in this lease"
-        else:
-            self.vm_rrs.remove(vmrr)
-
     def clear_rrs(self):
+        """Removes all resource reservations for this lease
+        (both preparation and VM)
+        
+        """            
         self.preparation_rrs = []
         self.vm_rrs = []
 
     def get_waiting_time(self):
+        """Gets the waiting time for this lease.
+        
+        The waiting time is the difference between the submission
+        time and the time at which the lease start. This method
+        mostly makes sense for best-effort leases, where the
+        starting time is determined by Haizea.
+        
+        """          
         return self.start.actual - self.submit_time
         
     def get_slowdown(self, bound=10):
+        """Determines the bounded slowdown for this lease.
+        
+        Slowdown is a normalized measure of how much time a
+        request takes to make it through a queue (thus, like
+        get_waiting_time, the slowdown makes sense mostly for
+        best-effort leases). Slowdown is equal to the time the
+        lease took to run on a loaded system (i.e., a system where
+        it had to compete with other leases for resources)
+        divided by the time it would take if it just had the
+        system all to itself (i.e., starts running immediately
+        without having to wait in a queue and without the
+        possibility of being preempted).
+        
+        "Bounded" slowdown is one where leases with very short
+        durations are rounded up to a bound, to prevent the
+        metric to be affected by reasonable but disproportionate
+        waiting times (e.g., a 5-second lease with a 15 second
+        waiting time -an arguably reasonable waiting time- has a 
+        slowdown of 4, the same as 10 hour lease having to wait 
+        30 hours for resources).
+        
+        Argument:
+        bound -- The bound, specified in seconds.
+        All leases with a duration less than this
+        parameter are rounded up to the bound.
+        """          
         time_on_dedicated = self.duration.original
         time_on_loaded = self.end - self.submit_time
         bound = TimeDelta(seconds=bound)
@@ -203,82 +437,53 @@
         return time_on_loaded / time_on_dedicated
         
     def add_boot_overhead(self, t):
+        """Adds a boot overhead to the lease.
+        
+        Increments the requested duration to account for the fact 
+        that some time will be spent booting up the resources.
+        
+        Argument:
+        t -- Time to add
+        """          
         self.duration.incr(t)        
 
     def add_runtime_overhead(self, percent):
-        self.duration.incr_by_percent(percent)
+        """Adds a runtime overhead to the lease.
         
-    def from_xml_file(self, xml_file):
-        self.__from_xml(ET.parse(xml_file).getroot())
-
-    def from_xml_string(self, xml):
-        self.__from_xml(ET.parsestring(xml))
+        This method is mostly meant for simulations. Since VMs
+        run slower than physical hardware, this increments the
+        duration of a lease by a percent to observe the effect
+        of having all the leases run slower on account of
+        running on a VM.
         
-    @classmethod
-    def from_xml_element(cls, element):
-        submit_time = Parser.DateTimeFromString(element.get("submit-time"))
+        Note: the whole "runtime overhead" problem is becoming
+        increasingly moot as people have lost their aversion to
+        VMs thanks to the cloud computing craze. Anecdotal evidence
+        suggests that most people don't care that VMs will run
+        X % slower (compared to a physical machine) because they
+        know full well that what they're getting is a virtual
+        machine (the same way a user of an HPC system would know
+        that he/she's getting processors with speed X as opposed to
+        those on some other site, with speed X*0.10)
         
-        nodes = Nodes.from_xml_element(element.find("nodes"))
+        Argument:
+        percent -- Runtime overhead (in percent of requested
+        duration) to add to the lease.
+        """            
+        self.duration.incr_by_percent(percent)
+            
         
-        requested_resources = nodes.get_all_nodes()
-        
-        start = element.find("start")
-        if len(start.getchildren()) == 0:
-            start = Timestamp(None)
-        else:
-            exact = start.find("exact")
-            if exact != None:
-                start = Timestamp(Parser.DateTimeFromString(exact.get("time")))
-            # TODO: Other starting times
-        
-        duration = Duration(Parser.DateTimeDeltaFromString(element.find("duration").get("time")))
-
-        deadline = None
-        
-        preemptible = bool(element.get("preemptible"))
-        
-        software = element.find("software")
-        
-        if software.find("none") != None:
-            software = UnmanagedSoftwareEnvironment()
-        elif software.find("disk-image") != None:
-            disk_image = software.find("disk-image")
-            image_id = disk_image.get("id")
-            image_size = int(disk_image.get("size"))
-            software = DiskImageSoftwareEnvironment(image_id, image_size)
-        
-        return Lease(submit_time, requested_resources, start, duration, 
-                     deadline, preemptible, software)
-
-    def get_leases(self):
-        return self.entries     
-        
-    def xmlrpc_marshall(self):
-        # Convert to something we can send through XMLRPC
-        l = {}
-        l["id"] = self.id
-        l["submit_time"] = xmlrpc_marshall_singlevalue(self.submit_time)
-        l["start_req"] = xmlrpc_marshall_singlevalue(self.start.requested)
-        l["start_sched"] = xmlrpc_marshall_singlevalue(self.start.scheduled)
-        l["start_actual"] = xmlrpc_marshall_singlevalue(self.start.actual)
-        l["duration_req"] = xmlrpc_marshall_singlevalue(self.duration.requested)
-        l["duration_acc"] = xmlrpc_marshall_singlevalue(self.duration.accumulated)
-        l["duration_actual"] = xmlrpc_marshall_singlevalue(self.duration.actual)
-        l["end"] = xmlrpc_marshall_singlevalue(self.end)
-        l["diskimage_id"] = self.diskimage_id
-        l["diskimage_size"] = self.diskimage_size
-        l["numnodes"] = self.numnodes
-        l["resources"] = `self.requested_resources`
-        l["preemptible"] = self.preemptible
-        l["state"] = self.get_state()
-        l["vm_rrs"] = [vmrr.xmlrpc_marshall() for vmrr in self.vm_rrs]
-                
-        return l
+class LeaseStateMachine(StateMachine):
+    """A lease state machine
     
-    def __from_xml(self, leaseworkload_element):
-        pass   
-        
-class LeaseStateMachine(StateMachine):
+    A child of StateMachine, this class simply specifies the valid
+    states and transitions for a lease (the actual state machine code
+    is in StateMachine).
+    
+    See the Haizea documentation for a description of states and
+    valid transitions.
+    
+    """    
     initial_state = Lease.STATE_NEW
     transitions = {Lease.STATE_NEW:                 [(Lease.STATE_PENDING,    "")],
                    
@@ -351,41 +556,161 @@
     def __init__(self):
         StateMachine.__init__(self, LeaseStateMachine.initial_state, LeaseStateMachine.transitions, Lease.state_str)
 
+
 class Capacity(object):
+    """A quantity of resources
+    
+    This class is used to represent a quantity of resources, such
+    as those required by a lease. For example, if a lease needs a
+    single node with 1 CPU and 1024 MB of memory, a single Capacity
+    object would be used containing that information. 
+    
+    Resources in a Capacity object can be multi-instance, meaning
+    that several instances of the same type of resources can be
+    specified. For example, if a node requires 2 CPUs, then this is
+    represented as two instances of the same type of resource. Most
+    resources, however, will be "single instance" (e.g., a physical
+    node only has "one" memory).
+    
+    Note: This class is similar, but distinct from, the ResourceTuple
+    class in the slottable module. The ResourceTuple class can contain
+    the same information, but uses a different internal representation
+    (which is optimized for long-running simulations) and is tightly
+    coupled to the SlotTable class. The Quantity and ResourceTuple
+    classes are kept separate so that the slottable module remains
+    independent from the rest of Haizea (in case we want to switch
+    to a different slottable implementation in the future).
+    
+    """        
     def __init__(self, types):
+        """Constructs an empty Capacity object.
+        
+        All resource types are initially set to be single-instance,
+        with a quantity of 0 for each resource.
+        
+        Argument:
+        types -- List of resource types. e.g., ["CPU", "Memory"]
+        """          
         self.ninstances = dict([(type, 1) for type in types])
         self.quantity = dict([(type, [0]) for type in types])
         
     def get_quantity(self, type):
+        """Gets the quantity of a single-instance resource
+                
+        Argument:
+        type -- The type of resource (using the same name passed
+        when constructing the Capacity object)
+        """               
         return self.get_quantity_instance(type, 1)
     
     def get_quantity_instance(self, type, instance):
+        """Gets the quantity of a specific instance of a 
+        multi-instance resource.
+                        
+        Argument:
+        type -- The type of resource (using the same name passed
+        when constructing the Capacity object)
+        instance -- The instance. Note that instances are numbered
+        from 1.
+        """               
         return self.quantity[type][instance-1]
 
     def set_quantity(self, type, amount):
+        """Sets the quantity of a single-instance resource
+                
+        Argument:
+        type -- The type of resource (using the same name passed
+        when constructing the Capacity object)
+        amount -- The amount to set the resource to.
+        """            
         self.set_quantity_instance(type, 1, amount)
     
     def set_quantity_instance(self, type, instance, amount):
+        """Sets the quantity of a specific instance of a 
+        multi-instance resource.
+                        
+        Argument:
+        type -- The type of resource (using the same name passed
+        when constructing the Capacity object)
+        instance -- The instance. Note that instances are numbered
+        from 1.
+        amount -- The amount to set the instance of the resource to.
+        """        
         self.quantity[type][instance-1] = amount
     
     def set_ninstances(self, type, ninstances):
+        """Changes the number of instances of a resource type.
+                        
+        Note that changing the number of instances will initialize
+        all the instances' amounts to zero. This method should
+        only be called right after constructing a Capacity object.
+        
+        Argument:
+        type -- The type of resource (using the same name passed
+        when constructing the Capacity object)
+        ninstance -- The number of instances
+        """                
         self.ninstances[type] = ninstances
         self.quantity[type] = [0 for i in range(ninstances)]
-        
+       
     def get_resource_types(self):
+        """Returns the types of resources in this capacity..
+                        
+        """            
         return self.quantity.keys()
 
 class Timestamp(object):
+    """An exact point in time.
+    
+    This class is just a wrapper around three DateTimes. When
+    dealing with timestamps in Haizea (such as the requested
+    starting time for a lease), we want to keep track not just
+    of the requested timestamp, but also the scheduled timestamp
+    (which could differ from the requested one) and the
+    actual timestamp (which could differ from the scheduled one).
+    """        
     def __init__(self, requested):
+        """Constructor
+                        
+        Argument:
+        requested -- The requested timestamp
+        """        
         self.requested = requested
         self.scheduled = None
         self.actual = None
 
     def __repr__(self):
+        """Returns a string representation of the Duration"""
         return "REQ: %s  |  SCH: %s  |  ACT: %s" % (self.requested, self.scheduled, self.actual)
         
 class Duration(object):
+    """A duration
+    
+    This class is just a wrapper around five DateTimes. When
+    dealing with durations in Haizea (such as the requested
+    duration for a lease), we want to keep track of the following:
+    
+    - The requested duration
+    - The accumulated duration (when the entire duration of
+    the lease can't be scheduled without interrumption, this
+    keeps track of how much duration has been fulfilled so far)
+    - The actual duration (which might not be the same as the
+    requested duration)
+    
+    For the purposes of simulation, we also want to keep track
+    of the "original" duration (since the requested duration
+    can be modified to simulate certain overheads) and the
+    "known" duration (when simulating lease workloads, this is
+    the actual duration of the lease, which is known a posteriori).
+    """  
+    
     def __init__(self, requested, known=None):
+        """Constructor
+                        
+        Argument:
+        requested -- The requested duration
+        known -- The known duration (ONLY in simulation)
+        """              
         self.original = requested
         self.requested = requested
         self.accumulated = TimeDelta()
@@ -394,39 +719,96 @@
         self.known = known
         
     def incr(self, t):
+        """Increments the requested duration by an amount.
+                        
+        Argument:
+        t -- The time to add to the requested duration.
+        """               
         self.requested += t
         if self.known != None:
             self.known += t
             
     def incr_by_percent(self, pct):
+        """Increments the requested duration by a percentage.
+                        
+        Argument:
+        pct -- The percentage of the requested duration to add.
+        """          
         factor = 1 + float(pct)/100
         self.requested = round_datetime_delta(self.requested * factor)
         if self.known != None:
             self.requested = round_datetime_delta(self.known * factor)
         
     def accumulate_duration(self, t):
+        """Increments the accumulated duration by an amount.
+                        
+        Argument:
+        t -- The time to add to the accumulated duration.
+        """        
         self.accumulated += t
             
     def get_remaining_duration(self):
+        """Returns the amount of time required to fulfil the entire
+        requested duration of the lease.
+                        
+        """         
         return self.requested - self.accumulated
 
-    # ONLY in simulation
     def get_remaining_known_duration(self):
+        """Returns the amount of time required to fulfil the entire
+        known duration of the lease.
+              
+        ONLY for simulations.
+        """           
         return self.known - self.accumulated
             
     def __repr__(self):
+        """Returns a string representation of the Duration"""
         return "REQ: %s  |  ACC: %s  |  ACT: %s  |  KNW: %s" % (self.requested, self.accumulated, self.actual, self.known)
     
 class SoftwareEnvironment(object):
+    """The base class for a lease's software environment"""
+    
     def __init__(self):
+        """Constructor.
+        
+        Does nothing."""
         pass
 
 class UnmanagedSoftwareEnvironment(SoftwareEnvironment):
+    """Represents an "unmanaged" software environment.
+    
+    When a lease has an unmanaged software environment,
+    Haizea does not need to perform any actions to prepare
+    a lease's software environment (it assumes that this
+    task is carried out by an external entity, and that
+    software environments can be assumed to be ready
+    when a lease has to start; e.g., if VM disk images are
+    predeployed on all physical nodes)."""
+    
     def __init__(self):
+        """Constructor.
+        
+        Does nothing."""        
         pass
 
 class DiskImageSoftwareEnvironment(SoftwareEnvironment):
+    """Reprents a software environment encapsulated in a disk image.
+    
+    When a lease's software environment is contained in a disk image,
+    this disk image must be deployed to the physical nodes the lease
+    is mapped to before the lease can start. This means that the
+    preparation for this lease must be handled by a preparation
+    scheduler (see documentation in lease_scheduler) capable of
+    handling a DiskImageSoftwareEnvironment.
+    """
     def __init__(self, image_id, image_size):
+        """Constructor.
+        
+        Arguments:
+        image_id -- A unique identifier for the disk image required
+        by the lease.
+        image_size -- The size, in MB, of the disk image. """         
         self.image_id = image_id
         self.image_size = image_size
 
@@ -482,7 +864,7 @@
     def create_empty_resource_quantity(self):
         return Capacity(self.resource_types)
     
-    def get_resource_types_with_max_instances(self):
+    def get_resource_types(self):
         max_ninstances = dict((rt, 1) for rt in self.resource_types)
         for node_set in self.nodes.node_sets:
             capacity = node_set[1]

Modified: branches/TP2.0/src/haizea/core/manager.py
===================================================================
--- branches/TP2.0/src/haizea/core/manager.py	2009-07-17 15:04:33 UTC (rev 609)
+++ branches/TP2.0/src/haizea/core/manager.py	2009-07-20 16:04:22 UTC (rev 610)
@@ -24,9 +24,9 @@
 
 This module provides the following classes:
 
-* Manager: The resource manager itself. Pretty much everything else
+* Manager: Haizea itself. Pretty much everything else
   is contained in this class.
-* Clock: A base class for the resource manager's clock.
+* Clock: A base class for Haizea's clock.
 * SimulatedClock: A clock for simulations.
 * RealClock: A clock that advances in realtime.
 """
@@ -150,7 +150,7 @@
             resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
     
         # Slot table
-        slottable = SlotTable(site.get_resource_types_with_max_instances())
+        slottable = SlotTable(site.get_resource_types())
         for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
             rt = slottable.create_resource_tuple_from_capacity(n.capacity)
             slottable.add_node(n.id, rt)
@@ -179,11 +179,10 @@
         elif preparation_type == constants.PREPARATION_TRANSFER:
             preparation_scheduler = ImageTransferPreparationScheduler(slottable, resourcepool, deploy_enact)    
     
-        # VM Scheduler
+        # VM mapper and scheduler
         mapper = self.config.get("mapper")
         mapper = mapper_mappings.get(mapper, mapper)
         mapper = import_class(mapper)
-        
         mapper = mapper(slottable, self.policy)
         vm_scheduler = VMScheduler(slottable, resourcepool, mapper)
     
@@ -408,7 +407,7 @@
     def process_starting_reservations(self, time):
         """Process reservations starting/stopping at specified time"""
         
-        # The scheduler takes care of this.
+        # The lease scheduler takes care of this.
         try:
             self.scheduler.process_starting_reservations(time)
         except UnrecoverableError, exc:
@@ -419,7 +418,7 @@
     def process_ending_reservations(self, time):
         """Process reservations starting/stopping at specified time"""
         
-        # The scheduler takes care of this.
+        # The lease scheduler takes care of this.
         try:
             self.scheduler.process_ending_reservations(time)
         except UnrecoverableError, exc:
@@ -460,7 +459,7 @@
         """Return next changepoint in the slot table"""
         return self.scheduler.slottable.get_next_changepoint(self.clock.get_time())
    
-    def exists_leases_in_rm(self):
+    def exists_more_leases(self):
         """Return True if there are any leases still "in the system" """
         return self.scheduler.exists_scheduled_leases() or not self.scheduler.is_queue_empty()
 
@@ -703,7 +702,7 @@
                         
         # If there's no more leases in the system, and no more pending requests,
         # then we're done.
-        if not self.manager.exists_leases_in_rm() and not tracefrontend.exists_more_requests():
+        if not self.manager.exists_more_leases() and not tracefrontend.exists_more_requests():
             self.done = True
         
         # We can also be done if we've specified that we want to stop when
@@ -857,7 +856,7 @@
             # fixed.            
             if self.manager.config._options.has_key("stop-when-no-more-leases"):
                 stop_when_no_more_leases = self.manager.config.get("stop-when-no-more-leases")
-                if stop_when_no_more_leases and not self.manager.exists_leases_in_rm():
+                if stop_when_no_more_leases and not self.manager.exists_more_leases():
                     self.done = True
             
             # Sleep



More information about the Haizea-commit mailing list