Project

General

Profile

root / branches / 1.1 / src / haizea / core / scheduler / policy.py @ 842

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

    
19
"""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 mx.DateTime import DateTimeDelta
39
import operator
40

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

    
87

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

    
130

    
131
    def get_host_score(self, node, time, lease):
132
        """Computes the score of a host
133
        
134
        See documentation of HostSelectionPolicy.get_host_score for more details.
135
        
136
        Arguments:
137
        node -- Physical node (the integer identifier used in the slot table)
138
        time -- Time at which the lease might be scheduled
139
        lease -- Lease that is being scheduled.
140
        """               
141
        return self.host_selection.get_host_score(node, time, lease)
142
    
143
    
144
    def price_lease(self, lease, preempted_leases):
145
        """Computes the price of a lease
146
    
147
         See documentation of PricingPolicy.price_lease for more details.
148
        
149
        Arguments:
150
        lease -- Lease that is being scheduled.
151
        preempted_leases -- Leases that would have to be preempted to support this lease.
152
        """
153
        return self.pricing.price_lease(lease, preempted_leases)  
154

    
155

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

    
235

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

    
322
    def price_lease(self, lease, preempted_leases):
323
        """Computes the price of a lease
324
        
325
        Arguments:
326
        lease -- Lease that is being scheduled.
327
        preempted_leases -- Leases that would have to be preempted to support this lease.
328
        """
329
        abstract()
330
        
331
    def feedback(self, lease):
332
        """Called after a lease has been accepted or rejected, to provide
333
        feeback to the pricing policy.
334
        
335
        Arguments:
336
        lease -- Lease that has been accepted/rejected
337
        """
338
        pass