Revision 3524241a snf-cyclades-app/synnefo/db/models.py

b/snf-cyclades-app/synnefo/db/models.py
35 35
from django.db import transaction
36 36

  
37 37
import utils
38

  
38
from contextlib import contextmanager
39 39
from hashlib import sha1
40 40
from synnefo.api.faults import ServiceUnavailable
41
from synnefo.util.rapi import GanetiRapiClient
42 41
from synnefo import settings as snf_settings
43 42
from aes_encrypt import encrypt_db_charfield, decrypt_db_charfield
44 43

  
45 44
from synnefo.db.managers import ForUpdateManager, ProtectedDeleteManager
46 45
from synnefo.db import pools
47 46

  
48
BACKEND_CLIENTS = {}  # {hash:Backend client}
49
BACKEND_HASHES = {}   # {Backend.id:hash}
47
from synnefo.logic.rapi_pool import (get_rapi_client,
48
                                     put_rapi_client)
50 49

  
51 50
import logging
52 51
log = logging.getLogger(__name__)
53 52

  
54 53

  
55
def get_client(hash, backend):
56
    """Get a cached backend client or create a new one.
57

  
58
    @param hash: The hash of the backend
59
    @param backend: Either a backend object or backend ID
60
    """
61

  
62
    if backend is None:
63
        raise Exception("Backend is None. Cannot create a client.")
64

  
65
    if hash in BACKEND_CLIENTS:
66
        # Return cached client
67
        return BACKEND_CLIENTS[hash]
68

  
69
    # Always get a new instance to ensure latest credentials
70
    if isinstance(backend, Backend):
71
        backend = backend.id
72

  
73
    backend = Backend.objects.get(id=backend)
74
    hash = backend.hash
75
    clustername = backend.clustername
76
    port = backend.port
77
    user = backend.username
78
    password = backend.password
79

  
80
    # Check client for updated hash
81
    if hash in BACKEND_CLIENTS:
82
        return BACKEND_CLIENTS[hash]
83

  
84
    # Delete old version of the client
85
    if backend in BACKEND_HASHES:
86
        del BACKEND_CLIENTS[BACKEND_HASHES[backend]]
87

  
88
    # Create the new client
89
    client = GanetiRapiClient(clustername, port, user, password)
90

  
91
    # Store the client and the hash
92
    BACKEND_CLIENTS[hash] = client
93
    BACKEND_HASHES[backend] = hash
94

  
95
    return client
96

  
97

  
98
def clear_client_cache():
99
    BACKEND_CLIENTS.clear()
100
    BACKEND_HASHES.clear()
101

  
102

  
103 54
class Flavor(models.Model):
104 55
    cpu = models.IntegerField('Number of CPUs', default=0)
105 56
    ram = models.IntegerField('RAM size in MiB', default=0)
......
161 112
    def backend_id(self):
162 113
        return self.id
163 114

  
164
    @property
165
    def client(self):
115
    def get_client(self):
166 116
        """Get or create a client. """
167
        if not self.offline:
168
            return get_client(self.hash, self)
169
        else:
117
        if self.offline:
170 118
            raise ServiceUnavailable
119
        return get_rapi_client(self.id, self.hash,
120
                               self.username,
121
                               self.password)
122

  
123
    @staticmethod
124
    def put_client(client):
125
            put_rapi_client(client)
171 126

  
172 127
    def create_hash(self):
173 128
        """Create a hash for this backend. """
......
265 220
        ('OP_INSTANCE_FAILOVER', 'Failover Instance')
266 221
    )
267 222

  
268

  
269 223
    # The operating state of a VM,
270 224
    # upon the successful completion of a backend operation.
271 225
    # IMPORTANT: Make sure all keys have a corresponding
......
333 287
    buildpercentage = models.IntegerField(default=0)
334 288
    backendtime = models.DateTimeField(default=datetime.datetime.min)
335 289

  
336
    @property
337
    def client(self):
338
        if self.backend and not self.backend.offline:
339
            return get_client(self.backend_hash, self.backend_id)
290
    def get_client(self):
291
        if self.backend:
292
            return self.backend.get_rapi_client()
340 293
        else:
341 294
            raise ServiceUnavailable
342 295

  
296
    @staticmethod
297
    def put_client(client):
298
            put_rapi_client(client)
299

  
343 300
    # Error classes
344 301
    class InvalidBackendIdError(Exception):
345 302
        def __init__(self, value):
......
716 673

  
717 674
class IPPoolTable(PoolTable):
718 675
    manager = pools.IPPool
676

  
677

  
678
@contextmanager
679
def pooled_rapi_client(obj):
680
        if isinstance(obj, VirtualMachine):
681
            backend = obj.backend
682
        else:
683
            backend = obj
684

  
685
        if backend.offline:
686
            raise ServiceUnavailable
687

  
688
        b = backend
689
        client = get_rapi_client(b.id, b.hash, b.clustername, b.port,
690
                                 b.username, b.password)
691
        yield client
692
        put_rapi_client(client)

Also available in: Unified diff