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