Project

General

Profile

root / trunk / src / haizea / core / scheduler / policy.py @ 632

1
# -------------------------------------------------------------------------- #
2
# Copyright 2006-2008, University of Chicago                                 #
3
# Copyright 2008, Distributed Systems Architecture Group, Universidad        #
4
# Complutense de Madrid (dsa-research.org)                                   #
5
#                                                                            #
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
7
# not use this file except in compliance with the License. You may obtain    #
8
# a copy of the License at                                                   #
9
#                                                                            #
10
# http://www.apache.org/licenses/LICENSE-2.0                                 #
11
#                                                                            #
12
# Unless required by applicable law or agreed to in writing, software        #
13
# distributed under the License is distributed on an "AS IS" BASIS,          #
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
15
# See the License for the specific language governing permissions and        #
16
# limitations under the License.                                             #
17
# -------------------------------------------------------------------------- #
18

    
19
"""Haizea uses a policy manager that allows certain scheduling decisions to
20
be delegated to pluggable policies. This is done so scheduling policies
21
can be (1) modified without having to modify core components of Haizea, and
22
(2) implemented by writing a single Python class that implements a given
23
interface for pluggable policies.
24

25
Three policies are currently pluggable: lease preemptability ("Can lease X
26
preempt lease Y?"), host selection ("I want to deploy a VM, what host should
27
I select for this?") and lease admission ("Should I accept/reject this lease
28
request?"). Haizea provides several simple policy modules in the
29
haizea.policies package. The policy to use is selected in the configuration
30
file. See the Haizea Documentation for more details on how this is done.
31

32
This module provides Haizea's policy manager and the base classes for
33
pluggable policies.  
34
"""
35

    
36

    
37
from haizea.common.utils import abstract
38
from haizea.core.leases import Lease
39
from mx.DateTime import DateTimeDelta
40
import operator
41

    
42
class PolicyManager(object):
43
    """The Policy Manager
44
    
45
    This class manages the policy modules and provides methods to
46
    access these modules.
47
    
48
    """    
49
    def __init__(self, admission, preemption, host_selection):
50
        """Constructor
51
        
52
        Expects fully-constructed policies (these are currently
53
        loaded in the Manager class, based on the config file).
54
        
55
        Arguments:
56
        admission -- A child of LeaseAdmissionPolicy
57
        preemption -- A child of PreemptabilityPolicy
58
        host_selection -- A child of HostSelectionPolicy
59
        
60
        """
61
        self.admission = admission
62
        self.preemption = preemption
63
        self.host_selection = host_selection
64
    
65
    def sort_leases(self, preemptor, preemptees, time):
66
        """Sorts a list of leases by their preemptability
67
        
68
        Takes a list of leases (the "preemptees"), determines their preemptability
69
        by another lease (the "preemptor"), and returns a list with the
70
        leases sorted by decreasing preemptability score (most preemptable
71
        leases first)
72
        
73
        See documentation of PreemptabilityPolicy.get_lease_preemptability_score
74
        for more details on the preemptability score.
75
        
76
        Argument
77
        preemptor -- Preemptor lease
78
        preemptees -- List of preemptee leases
79
        time -- Time at which preemption would take place        
80
        """              
81
        leases_score = [(preemptee, self.get_lease_preemptability_score(preemptor,preemptee, time)) for preemptee in preemptees]
82
        leases_score = [(preemptee,score) for preemptee,score in leases_score if score != -1]
83
        leases_score.sort(key=operator.itemgetter(1), reverse=True)
84
        return [preemptee for preemptee,score in leases_score]
85

    
86

    
87
    def sort_hosts(self, nodes, time, lease):
88
        """Sorts a list of hosts by their score
89
        
90
        Takes a list of hosts, determines their score, and sorts them in
91
        order of decreasing score (most desireable hosts first)
92
        
93
        See documentation of HostSelectionPolicy.get_host_score for more details.
94
        
95
        Arguments:
96
        nodes -- List of physical node (the integer identifier used in the slot table)
97
        time -- Time at which the lease might be scheduled
98
        lease -- Lease that is being scheduled.
99
        """        
100
        nodes_score = [(node, self.get_host_score(node, time, lease)) for node in nodes]
101
        nodes_score.sort(key=operator.itemgetter(1), reverse=True)
102
        return [node for node,score in nodes_score]
103
    
104
    
105
    def accept_lease(self, lease):
106
        """Lease admission function
107
        
108
        Returns True if the lease can be accepted, False if it should be rejected.
109
        
110
        Argument
111
        lease -- Lease request
112
        """        
113
        return self.admission.accept_lease(lease)
114
    
115
    
116
    def get_lease_preemptability_score(self, preemptor, preemptee, time):
117
        """Computes the lease preemptability score
118
        
119
        See documentation of PreemptabilityPolicy.get_lease_preemptability_score
120
        for more details.
121
        
122
        Arguments:
123
        preemptor -- Preemptor lease
124
        preemptee -- Preemptee lease
125
        time -- Time at which preemption would take place
126
        """                
127
        return self.preemption.get_lease_preemptability_score(preemptor, preemptee, time)
128

    
129

    
130
    def get_host_score(self, node, time, lease):
131
        """Computes the score of a host
132
        
133
        See documentation of HostSelectionPolicy.get_host_score for more details.
134
        
135
        Arguments:
136
        node -- Physical node (the integer identifier used in the slot table)
137
        time -- Time at which the lease might be scheduled
138
        lease -- Lease that is being scheduled.
139
        """               
140
        return self.host_selection.get_host_score(node, time, lease)
141
    
142
    
143

    
144
class LeaseAdmissionPolicy(object):
145
    """Lease Admission policy
146
    
147
    This is the parent class of lease admission policies. A lease admission
148
    policy determines whether a given lease request should be accepted or not
149
    by Haizea. Note that this is distinct from whether the lease can be
150
    scheduled or not (although this could certainly be a part of the
151
    policy); the policy simply decides whether the lease can be considered for
152
    scheduling or not. For example, a user could submit an AR lease that must
153
    start in 5 hours, but the policy could dictate that all ARs must be notified
154
    at least 24 hours in advance (and the lease would be rejected, regardless of
155
    whether there was resources available for it in 5 hours). Similarly, an
156
    AR lease could be requested 48 hours in advance, be accepted by the lease
157
    admission policy, but then be rejected by the scheduler if there are no
158
    resources available.
159
    
160
    """       
161
    def __init__(self, slottable):
162
        """Constructor
163
        
164
        Argument
165
        slottable -- A fully constructed SlotTable
166
        """
167
        self.slottable = slottable
168
    
169
    
170
    def accept_lease(self, lease):
171
        """Lease admission function
172
        
173
        Returns True if the lease can be accepted, False if it should be rejected.
174
        
175
        Argument
176
        lease -- Lease request
177
        """        
178
        abstract()
179
    
180
    
181
    
182
class PreemptabilityPolicy(object):
183
    """Lease Preemptability policy
184
    
185
    This is the parent class of lease preemptability policies. This type of
186
    policy is used to determine whether a lease can be preempted by another
187
    lease at a given time. However, the policy doesn't return True or False but,
188
    rather, a "preemptability score" (see get_lease_preemptability_score for
189
    more details)
190
    
191
    """           
192
    def __init__(self, slottable):
193
        """Constructor
194
        
195
        Argument
196
        slottable -- A fully constructed SlotTable
197
        """        
198
        self.slottable = slottable
199
    
200
    
201
    def get_lease_preemptability_score(self, preemptor, preemptee, time):
202
        """Computes the lease preemptability score
203
        
204
        Given a lease that needs to preempt resources (the "preemptor"),
205
        another lease (the "preemptee") that may be preempted by it, and a time,
206
        this method determines the preemptability score of the preemptee or
207
        "how preemptable is the preemptee by the preemptor at the given time".
208
        The score can be the following:
209
        
210
        -1 : Cannot be preempted under any circumstances
211
        0.0 <= x <= 1.0: Lease can be preempted. The higher the score,
212
        the "more preemptable" it is (this is a relative measure; the score
213
        should be used to determine which of several leases is a better
214
        candidate for preemption)
215
        
216
        Arguments:
217
        preemptor -- Preemptor lease
218
        preemptee -- Preemptee lease
219
        time -- Time at which preemption would take place
220
        """             
221
        abstract()    
222

    
223

    
224
    def _get_aging_factor(self, lease, time):
225
        """Returns an aging factor for the preemptability score
226
        
227
        This is a convenience function that can be used to "age" a
228
        preemptability score (allowing leases that have been submitted
229
        long ago to avoid preemption). The method returns a factor
230
        between 0 and 1 that can be multiplied by the score, reducing
231
        the score based on the lease's "age".
232
        
233
        Currently, this method uses a hard-coded horizon of 31 days
234
        (any lease older than 7 days cannot be preempted, and leases
235
        less than 7 days are assigned a factor proportional to their age)
236
        
237
        Arguments:
238
        lease -- Lease that is going to be preempted
239
        time -- Time at which preemption would take place        
240
        """            
241
        # TODO: Make horizon configurable
242
        horizon = time - DateTimeDelta(7)
243
        if lease.submit_time <= horizon:
244
            return -1
245
        else:
246
            seconds = (time - lease.submit_time).seconds
247
            horizon_seconds = DateTimeDelta(31).seconds
248
            return float(horizon_seconds - seconds) / horizon_seconds        
249
        
250
        
251
class HostSelectionPolicy(object):
252
    """Host Selection policy
253
    
254
    This is the parent class of host selection policies. When mapping VMs
255
    to physical hosts, this policy determines what hosts are more desireable.
256
    For example, an energy-saving policy might value hosts that already have
257
    VMs running (to leave as many empty machines as possible, which could then
258
    be turned off), whereas another policy might prefer empty hosts to make
259
    sure that VMs are spread out across nodes.
260
    
261
    To do this, the policy will assign a score to each host. See the documentation
262
    for get_host_score for more details.
263
        
264
    """             
265
    def __init__(self, slottable):
266
        """Constructor
267
        
268
        Argument
269
        slottable -- A fully constructed SlotTable
270
        """        
271
        self.slottable = slottable
272
    
273
    
274
    def get_host_score(self, node, time, lease):
275
        """Computes the score of a host
276
        
277
        Given a physical host, a time, and a lease we would like to
278
        schedule at that time, this method returns a score indicating
279
        how desireable that host is for that lease at that time.
280
        The score can be between 0.0 and 1.0. The higher the score,
281
        the "more desireable" the physical host is (this is a relative measure; 
282
        the score should be used to determine which of several physical hosts
283
        is more desireable for this lease).
284
        
285
        Arguments:
286
        node -- Physical node (the integer identifier used in the slot table)
287
        time -- Time at which the lease might be scheduled
288
        lease -- Lease that is being scheduled.
289
        """               
290
        abstract()