Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / backend_allocator.py @ ad297723

History | View | Annotate | Download (4.1 kB)

1 cc7c0f44 Christos Stavrakakis
# Copyright 2011 GRNET S.A. All rights reserved.
2 cc7c0f44 Christos Stavrakakis
#
3 cc7c0f44 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or without
4 cc7c0f44 Christos Stavrakakis
# modification, are permitted provided that the following conditions
5 cc7c0f44 Christos Stavrakakis
# are met:
6 cc7c0f44 Christos Stavrakakis
#
7 cc7c0f44 Christos Stavrakakis
#   1. Redistributions of source code must retain the above copyright
8 cc7c0f44 Christos Stavrakakis
#      notice, this list of conditions and the following disclaimer.
9 cc7c0f44 Christos Stavrakakis
#
10 cc7c0f44 Christos Stavrakakis
#  2. Redistributions in binary form must reproduce the above copyright
11 cc7c0f44 Christos Stavrakakis
#     notice, this list of conditions and the following disclaimer in the
12 cc7c0f44 Christos Stavrakakis
#     documentation and/or other materials provided with the distribution.
13 cc7c0f44 Christos Stavrakakis
#
14 cc7c0f44 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 cc7c0f44 Christos Stavrakakis
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 cc7c0f44 Christos Stavrakakis
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 cc7c0f44 Christos Stavrakakis
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 cc7c0f44 Christos Stavrakakis
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 cc7c0f44 Christos Stavrakakis
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 cc7c0f44 Christos Stavrakakis
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 cc7c0f44 Christos Stavrakakis
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 cc7c0f44 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 cc7c0f44 Christos Stavrakakis
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 cc7c0f44 Christos Stavrakakis
# SUCH DAMAGE.
25 cc7c0f44 Christos Stavrakakis
#
26 cc7c0f44 Christos Stavrakakis
# The views and conclusions contained in the software and documentation are
27 cc7c0f44 Christos Stavrakakis
# those of the authors and should not be interpreted as representing official
28 cc7c0f44 Christos Stavrakakis
# policies, either expressed or implied, of GRNET S.A.
29 cc7c0f44 Christos Stavrakakis
30 cc7c0f44 Christos Stavrakakis
import datetime
31 cc7c0f44 Christos Stavrakakis
from django.utils import importlib
32 cc7c0f44 Christos Stavrakakis
33 cc7c0f44 Christos Stavrakakis
from synnefo import settings
34 cc7c0f44 Christos Stavrakakis
from synnefo.db.models import Backend
35 cc7c0f44 Christos Stavrakakis
from synnefo.logic.backend import update_resources
36 cc7c0f44 Christos Stavrakakis
37 cc7c0f44 Christos Stavrakakis
38 cc7c0f44 Christos Stavrakakis
class BackendAllocator():
39 cc7c0f44 Christos Stavrakakis
    """Wrapper class for instance allocation.
40 cc7c0f44 Christos Stavrakakis

41 cc7c0f44 Christos Stavrakakis
    """
42 cc7c0f44 Christos Stavrakakis
    def __init__(self):
43 cc7c0f44 Christos Stavrakakis
        self.strategy_mod =\
44 cc7c0f44 Christos Stavrakakis
            importlib.import_module(settings.BACKEND_ALLOCATOR_MODULE)
45 cc7c0f44 Christos Stavrakakis
46 cc7c0f44 Christos Stavrakakis
    def allocate(self, flavor):
47 cc7c0f44 Christos Stavrakakis
        # Get the size of the vm
48 cc7c0f44 Christos Stavrakakis
        disk = flavor_disk(flavor)
49 cc7c0f44 Christos Stavrakakis
        ram = flavor.ram
50 cc7c0f44 Christos Stavrakakis
        cpu = flavor.cpu
51 cc7c0f44 Christos Stavrakakis
        vm = {'ram': ram, 'disk': disk, 'cpu': cpu}
52 cc7c0f44 Christos Stavrakakis
53 cc7c0f44 Christos Stavrakakis
        # Refresh backends, if needed
54 cc7c0f44 Christos Stavrakakis
        refresh_backends_stats()
55 cc7c0f44 Christos Stavrakakis
56 cc7c0f44 Christos Stavrakakis
        # Get available backends
57 cc7c0f44 Christos Stavrakakis
        available_backends = get_available_backends()
58 cc7c0f44 Christos Stavrakakis
59 cc7c0f44 Christos Stavrakakis
        if not available_backends:
60 cc7c0f44 Christos Stavrakakis
            return None
61 cc7c0f44 Christos Stavrakakis
62 cc7c0f44 Christos Stavrakakis
        # Find the best backend to host the vm, based on the allocation
63 cc7c0f44 Christos Stavrakakis
        # strategy
64 cc7c0f44 Christos Stavrakakis
        backend_id = self.strategy_mod.allocate(available_backends, vm)
65 cc7c0f44 Christos Stavrakakis
66 cc7c0f44 Christos Stavrakakis
        backend = Backend.objects.get(id=backend_id)
67 cc7c0f44 Christos Stavrakakis
        # Reduce the free resources of the selected backend by the size of
68 cc7c0f44 Christos Stavrakakis
        # the vm
69 cc7c0f44 Christos Stavrakakis
        reduce_backend_resources(backend, vm)
70 cc7c0f44 Christos Stavrakakis
71 cc7c0f44 Christos Stavrakakis
        return backend
72 cc7c0f44 Christos Stavrakakis
73 cc7c0f44 Christos Stavrakakis
74 cc7c0f44 Christos Stavrakakis
def get_available_backends():
75 cc7c0f44 Christos Stavrakakis
    """Get available backends from db.
76 cc7c0f44 Christos Stavrakakis

77 cc7c0f44 Christos Stavrakakis
    """
78 cc7c0f44 Christos Stavrakakis
    attrs = ['mfree', 'mtotal', 'dfree', 'dtotal', 'pinst_cnt', 'ctotal']
79 cc7c0f44 Christos Stavrakakis
    backends = {}
80 cc7c0f44 Christos Stavrakakis
    for b in Backend.objects.filter(drained=False, offline=False):
81 cc7c0f44 Christos Stavrakakis
        backend = {}
82 cc7c0f44 Christos Stavrakakis
        for a in attrs:
83 cc7c0f44 Christos Stavrakakis
            backend[a] = getattr(b, a)
84 cc7c0f44 Christos Stavrakakis
        backends[b.id] = backend
85 cc7c0f44 Christos Stavrakakis
    return backends
86 cc7c0f44 Christos Stavrakakis
87 cc7c0f44 Christos Stavrakakis
88 cc7c0f44 Christos Stavrakakis
def flavor_disk(flavor):
89 cc7c0f44 Christos Stavrakakis
    """ Get flavor's 'real' disk size
90 cc7c0f44 Christos Stavrakakis

91 cc7c0f44 Christos Stavrakakis
    """
92 cc7c0f44 Christos Stavrakakis
    if flavor.disk_template == 'drbd':
93 cc7c0f44 Christos Stavrakakis
        return flavor.disk * 1024 * 2
94 cc7c0f44 Christos Stavrakakis
    else:
95 cc7c0f44 Christos Stavrakakis
        return flavor.disk * 1024
96 cc7c0f44 Christos Stavrakakis
97 cc7c0f44 Christos Stavrakakis
98 cc7c0f44 Christos Stavrakakis
def reduce_backend_resources(backend, vm):
99 cc7c0f44 Christos Stavrakakis
    """ Conservatively update the resources of a backend.
100 cc7c0f44 Christos Stavrakakis

101 cc7c0f44 Christos Stavrakakis
    Reduce the free resources of the backend by the size of the of the vm that
102 cc7c0f44 Christos Stavrakakis
    will host. This is an underestimation of the backend capabilities.
103 cc7c0f44 Christos Stavrakakis

104 cc7c0f44 Christos Stavrakakis
    """
105 cc7c0f44 Christos Stavrakakis
106 cc7c0f44 Christos Stavrakakis
    new_mfree = backend.mfree - vm['ram']
107 cc7c0f44 Christos Stavrakakis
    new_dfree = backend.dfree - vm['disk']
108 cc7c0f44 Christos Stavrakakis
    backend.mfree = 0 if new_mfree < 0 else new_mfree
109 cc7c0f44 Christos Stavrakakis
    backend.dfree = 0 if new_dfree < 0 else new_dfree
110 cc7c0f44 Christos Stavrakakis
    backend.pinst_cnt += 1
111 cc7c0f44 Christos Stavrakakis
112 cc7c0f44 Christos Stavrakakis
    backend.save()
113 cc7c0f44 Christos Stavrakakis
114 cc7c0f44 Christos Stavrakakis
115 cc7c0f44 Christos Stavrakakis
def refresh_backends_stats():
116 cc7c0f44 Christos Stavrakakis
    """ Refresh the statistics of the backends.
117 cc7c0f44 Christos Stavrakakis

118 cc7c0f44 Christos Stavrakakis
    Set db backend state to the actual state of the backend, if
119 cc7c0f44 Christos Stavrakakis
    BACKEND_REFRESH_MIN time has passed.
120 cc7c0f44 Christos Stavrakakis

121 cc7c0f44 Christos Stavrakakis
    """
122 cc7c0f44 Christos Stavrakakis
123 cc7c0f44 Christos Stavrakakis
    now = datetime.datetime.now()
124 cc7c0f44 Christos Stavrakakis
    delta = datetime.timedelta(minutes=settings.BACKEND_REFRESH_MIN)
125 cc7c0f44 Christos Stavrakakis
    for b in Backend.objects.filter(drained=False, offline=False):
126 cc7c0f44 Christos Stavrakakis
        if now > b.updated + delta:
127 cc7c0f44 Christos Stavrakakis
            update_resources(b)