root / snf-cyclades-app / synnefo / quotas / __init__.py @ 19b2c29d
History | View | Annotate | Download (13.5 kB)
1 | 629acc65 | Giorgos Korfiatis | # Copyright 2012, 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | bfe7ba3c | Christos Stavrakakis | #
|
3 | bfe7ba3c | Christos Stavrakakis | # Redistribution and use in source and binary forms, with or without
|
4 | bfe7ba3c | Christos Stavrakakis | # modification, are permitted provided that the following conditions
|
5 | bfe7ba3c | Christos Stavrakakis | # are met:
|
6 | bfe7ba3c | Christos Stavrakakis | #
|
7 | bfe7ba3c | Christos Stavrakakis | # 1. Redistributions of source code must retain the above copyright
|
8 | bfe7ba3c | Christos Stavrakakis | # notice, this list of conditions and the following disclaimer.
|
9 | bfe7ba3c | Christos Stavrakakis | #
|
10 | bfe7ba3c | Christos Stavrakakis | # 2. Redistributions in binary form must reproduce the above copyright
|
11 | bfe7ba3c | Christos Stavrakakis | # notice, this list of conditions and the following disclaimer in the
|
12 | bfe7ba3c | Christos Stavrakakis | # documentation and/or other materials provided with the distribution.
|
13 | bfe7ba3c | Christos Stavrakakis | #
|
14 | bfe7ba3c | Christos Stavrakakis | # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
15 | bfe7ba3c | Christos Stavrakakis | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16 | bfe7ba3c | Christos Stavrakakis | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17 | bfe7ba3c | Christos Stavrakakis | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
18 | bfe7ba3c | Christos Stavrakakis | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19 | bfe7ba3c | Christos Stavrakakis | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
20 | bfe7ba3c | Christos Stavrakakis | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
21 | bfe7ba3c | Christos Stavrakakis | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
22 | bfe7ba3c | Christos Stavrakakis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
23 | bfe7ba3c | Christos Stavrakakis | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
24 | bfe7ba3c | Christos Stavrakakis | # SUCH DAMAGE.
|
25 | bfe7ba3c | Christos Stavrakakis | #
|
26 | bfe7ba3c | Christos Stavrakakis | # The views and conclusions contained in the software and documentation are
|
27 | bfe7ba3c | Christos Stavrakakis | # those of the authors and should not be interpreted as representing official
|
28 | bfe7ba3c | Christos Stavrakakis | # policies, either expressed or implied, of GRNET S.A.
|
29 | bfe7ba3c | Christos Stavrakakis | |
30 | 656cf771 | Christos Stavrakakis | from django.utils import simplejson as json |
31 | 2509ce17 | Christos Stavrakakis | from django.db import transaction |
32 | bfe7ba3c | Christos Stavrakakis | |
33 | bd40abfa | Christos Stavrakakis | from snf_django.lib.api import faults |
34 | 8b41683a | Christos Stavrakakis | from synnefo.db.models import (QuotaHolderSerial, VirtualMachine, Network, |
35 | 326c3ec8 | Christos Stavrakakis | IPAddress) |
36 | 6dbd90c0 | Christos Stavrakakis | |
37 | 18c4414d | Giorgos Korfiatis | from synnefo.settings import (CYCLADES_SERVICE_TOKEN as ASTAKOS_TOKEN, |
38 | e407f159 | Ilias Tsitsimpis | ASTAKOS_AUTH_URL) |
39 | 629acc65 | Giorgos Korfiatis | from astakosclient import AstakosClient |
40 | 0dc4b304 | Giorgos Korfiatis | from astakosclient import errors |
41 | bfe7ba3c | Christos Stavrakakis | |
42 | bfe7ba3c | Christos Stavrakakis | import logging |
43 | bfe7ba3c | Christos Stavrakakis | log = logging.getLogger(__name__) |
44 | bfe7ba3c | Christos Stavrakakis | |
45 | e407f159 | Ilias Tsitsimpis | |
46 | 629acc65 | Giorgos Korfiatis | DEFAULT_SOURCE = 'system'
|
47 | 656cf771 | Christos Stavrakakis | RESOURCES = [ |
48 | 656cf771 | Christos Stavrakakis | "cyclades.vm",
|
49 | 5083fc47 | Christos Stavrakakis | "cyclades.total_cpu",
|
50 | 656cf771 | Christos Stavrakakis | "cyclades.cpu",
|
51 | 656cf771 | Christos Stavrakakis | "cyclades.disk",
|
52 | 5083fc47 | Christos Stavrakakis | "cyclades.total_ram",
|
53 | 656cf771 | Christos Stavrakakis | "cyclades.ram",
|
54 | 8b41683a | Christos Stavrakakis | "cyclades.network.private",
|
55 | 8b41683a | Christos Stavrakakis | "cyclades.floating_ip",
|
56 | 656cf771 | Christos Stavrakakis | ] |
57 | bfe7ba3c | Christos Stavrakakis | |
58 | bfe7ba3c | Christos Stavrakakis | |
59 | 629acc65 | Giorgos Korfiatis | class Quotaholder(object): |
60 | 629acc65 | Giorgos Korfiatis | _object = None
|
61 | 629acc65 | Giorgos Korfiatis | |
62 | 629acc65 | Giorgos Korfiatis | @classmethod
|
63 | 629acc65 | Giorgos Korfiatis | def get(cls): |
64 | 629acc65 | Giorgos Korfiatis | if cls._object is None: |
65 | 4fb643b3 | Giorgos Korfiatis | cls._object = AstakosClient(ASTAKOS_TOKEN, |
66 | 4fb643b3 | Giorgos Korfiatis | ASTAKOS_AUTH_URL, |
67 | 4fb643b3 | Giorgos Korfiatis | use_pool=True,
|
68 | 4fb643b3 | Giorgos Korfiatis | retry=3,
|
69 | 4fb643b3 | Giorgos Korfiatis | logger=log) |
70 | 629acc65 | Giorgos Korfiatis | return cls._object
|
71 | bfe7ba3c | Christos Stavrakakis | |
72 | bfe7ba3c | Christos Stavrakakis | |
73 | 0dc4b304 | Giorgos Korfiatis | class AstakosClientExceptionHandler(object): |
74 | 0dc4b304 | Giorgos Korfiatis | def __init__(self, *args, **kwargs): |
75 | 0dc4b304 | Giorgos Korfiatis | pass
|
76 | 0dc4b304 | Giorgos Korfiatis | |
77 | 0dc4b304 | Giorgos Korfiatis | def __enter__(self): |
78 | 0dc4b304 | Giorgos Korfiatis | pass
|
79 | 0dc4b304 | Giorgos Korfiatis | |
80 | 0dc4b304 | Giorgos Korfiatis | def __exit__(self, exc_type, value, traceback): |
81 | 0dc4b304 | Giorgos Korfiatis | if value is not None: # exception |
82 | 0dc4b304 | Giorgos Korfiatis | if not isinstance(value, errors.AstakosClientException): |
83 | 0dc4b304 | Giorgos Korfiatis | return False # reraise |
84 | 0dc4b304 | Giorgos Korfiatis | if exc_type is errors.QuotaLimit: |
85 | 0dc4b304 | Giorgos Korfiatis | msg, details = render_overlimit_exception(value) |
86 | 0dc4b304 | Giorgos Korfiatis | raise faults.OverLimit(msg, details=details)
|
87 | 0dc4b304 | Giorgos Korfiatis | |
88 | 0dc4b304 | Giorgos Korfiatis | log.exception("Unexpected error %s" % value.message)
|
89 | 499d9bfe | Christos Stavrakakis | raise faults.InternalServerError("Unexpected error") |
90 | 499d9bfe | Christos Stavrakakis | |
91 | 499d9bfe | Christos Stavrakakis | |
92 | 16b959ce | Giorgos Korfiatis | def issue_commission(resource, action, name="", force=False, auto_accept=False, |
93 | 16b959ce | Giorgos Korfiatis | action_fields=None):
|
94 | bfe7ba3c | Christos Stavrakakis | """Issue a new commission to the quotaholder.
|
95 | bfe7ba3c | Christos Stavrakakis |
|
96 | bfe7ba3c | Christos Stavrakakis | Issue a new commission to the quotaholder, and create the
|
97 | bfe7ba3c | Christos Stavrakakis | corresponing QuotaHolderSerial object in DB.
|
98 | bfe7ba3c | Christos Stavrakakis |
|
99 | bfe7ba3c | Christos Stavrakakis | """
|
100 | bfe7ba3c | Christos Stavrakakis | |
101 | 16b959ce | Giorgos Korfiatis | provisions = get_commission_info(resource=resource, action=action, |
102 | 16b959ce | Giorgos Korfiatis | action_fields=action_fields) |
103 | 16b959ce | Giorgos Korfiatis | |
104 | 16b959ce | Giorgos Korfiatis | if provisions is None: |
105 | 16b959ce | Giorgos Korfiatis | return None |
106 | 16b959ce | Giorgos Korfiatis | |
107 | 16b959ce | Giorgos Korfiatis | user = resource.userid |
108 | 16b959ce | Giorgos Korfiatis | source = DEFAULT_SOURCE |
109 | 16b959ce | Giorgos Korfiatis | |
110 | 629acc65 | Giorgos Korfiatis | qh = Quotaholder.get() |
111 | 0dc4b304 | Giorgos Korfiatis | if True: # placeholder |
112 | 0dc4b304 | Giorgos Korfiatis | with AstakosClientExceptionHandler():
|
113 | 16b959ce | Giorgos Korfiatis | serial = qh.issue_one_commission(user, source, |
114 | 16b959ce | Giorgos Korfiatis | provisions, name=name, |
115 | 16b959ce | Giorgos Korfiatis | force=force, |
116 | 16b959ce | Giorgos Korfiatis | auto_accept=auto_accept) |
117 | bfe7ba3c | Christos Stavrakakis | |
118 | b14f55b5 | Christos Stavrakakis | if serial:
|
119 | 218de705 | Christos Stavrakakis | serial_info = {"serial": serial}
|
120 | 218de705 | Christos Stavrakakis | if auto_accept:
|
121 | fb540e3a | Giorgos Korfiatis | serial_info["pending"] = False |
122 | 218de705 | Christos Stavrakakis | serial_info["accept"] = True |
123 | 218de705 | Christos Stavrakakis | serial_info["resolved"] = True |
124 | 218de705 | Christos Stavrakakis | return QuotaHolderSerial.objects.create(**serial_info)
|
125 | b14f55b5 | Christos Stavrakakis | else:
|
126 | b14f55b5 | Christos Stavrakakis | raise Exception("No serial") |
127 | bfe7ba3c | Christos Stavrakakis | |
128 | bfe7ba3c | Christos Stavrakakis | |
129 | 41a7fae7 | Christos Stavrakakis | def accept_serial(serial, strict=True): |
130 | fb540e3a | Giorgos Korfiatis | assert serial.pending or serial.accept |
131 | 41a7fae7 | Christos Stavrakakis | response = resolve_commissions(accept=[serial.serial], strict=strict) |
132 | fb540e3a | Giorgos Korfiatis | serial.pending = False
|
133 | 41a7fae7 | Christos Stavrakakis | serial.accept = True
|
134 | 41a7fae7 | Christos Stavrakakis | serial.resolved = True
|
135 | 41a7fae7 | Christos Stavrakakis | serial.save() |
136 | 41a7fae7 | Christos Stavrakakis | return response
|
137 | 41a7fae7 | Christos Stavrakakis | |
138 | 41a7fae7 | Christos Stavrakakis | |
139 | 41a7fae7 | Christos Stavrakakis | def reject_serial(serial, strict=True): |
140 | fb540e3a | Giorgos Korfiatis | assert serial.pending or not serial.accept |
141 | 41a7fae7 | Christos Stavrakakis | response = resolve_commissions(reject=[serial.serial], strict=strict) |
142 | fb540e3a | Giorgos Korfiatis | serial.pending = False
|
143 | fb540e3a | Giorgos Korfiatis | serial.accept = False
|
144 | 41a7fae7 | Christos Stavrakakis | serial.resolved = True
|
145 | 41a7fae7 | Christos Stavrakakis | serial.save() |
146 | 41a7fae7 | Christos Stavrakakis | return response
|
147 | 41a7fae7 | Christos Stavrakakis | |
148 | 41a7fae7 | Christos Stavrakakis | |
149 | 5db3a1e6 | Christos Stavrakakis | def accept_commissions(accepted, strict=True): |
150 | d195e752 | Christos Stavrakakis | return resolve_commissions(accept=accepted, strict=strict)
|
151 | 11a54cb9 | Christos Stavrakakis | |
152 | 11a54cb9 | Christos Stavrakakis | |
153 | 5db3a1e6 | Christos Stavrakakis | def reject_commissions(rejected, strict=True): |
154 | d195e752 | Christos Stavrakakis | return resolve_commissions(reject=rejected, strict=strict)
|
155 | 11a54cb9 | Christos Stavrakakis | |
156 | 11a54cb9 | Christos Stavrakakis | |
157 | d195e752 | Christos Stavrakakis | def resolve_commissions(accept=None, reject=None, strict=True): |
158 | 629acc65 | Giorgos Korfiatis | if accept is None: |
159 | 629acc65 | Giorgos Korfiatis | accept = [] |
160 | 629acc65 | Giorgos Korfiatis | if reject is None: |
161 | 629acc65 | Giorgos Korfiatis | reject = [] |
162 | 11a54cb9 | Christos Stavrakakis | |
163 | 629acc65 | Giorgos Korfiatis | qh = Quotaholder.get() |
164 | 0dc4b304 | Giorgos Korfiatis | with AstakosClientExceptionHandler():
|
165 | 0dc4b304 | Giorgos Korfiatis | response = qh.resolve_commissions(accept, reject) |
166 | 5db3a1e6 | Christos Stavrakakis | |
167 | 3af1fb4b | Christos Stavrakakis | # Update correspodning entries in DB
|
168 | 3af1fb4b | Christos Stavrakakis | QuotaHolderSerial.objects.filter(serial__in=accept).update(accept=True,
|
169 | 3af1fb4b | Christos Stavrakakis | pending=False,
|
170 | 3af1fb4b | Christos Stavrakakis | resolved=True)
|
171 | 3af1fb4b | Christos Stavrakakis | QuotaHolderSerial.objects.filter(serial__in=reject).update(accept=False,
|
172 | 3af1fb4b | Christos Stavrakakis | pending=False,
|
173 | 3af1fb4b | Christos Stavrakakis | resolved=True)
|
174 | 3af1fb4b | Christos Stavrakakis | |
175 | 5db3a1e6 | Christos Stavrakakis | if strict:
|
176 | 5db3a1e6 | Christos Stavrakakis | failed = response["failed"]
|
177 | 5db3a1e6 | Christos Stavrakakis | if failed:
|
178 | 5db3a1e6 | Christos Stavrakakis | log.error("Unexpected error while resolving commissions: %s",
|
179 | 5db3a1e6 | Christos Stavrakakis | failed) |
180 | 5db3a1e6 | Christos Stavrakakis | |
181 | 5db3a1e6 | Christos Stavrakakis | return response
|
182 | 11a54cb9 | Christos Stavrakakis | |
183 | 11a54cb9 | Christos Stavrakakis | |
184 | 2509ce17 | Christos Stavrakakis | def fix_pending_commissions(): |
185 | 2509ce17 | Christos Stavrakakis | (accepted, rejected) = resolve_pending_commissions() |
186 | d195e752 | Christos Stavrakakis | resolve_commissions(accept=accepted, reject=rejected) |
187 | 2509ce17 | Christos Stavrakakis | |
188 | 2509ce17 | Christos Stavrakakis | |
189 | 11a54cb9 | Christos Stavrakakis | def resolve_pending_commissions(): |
190 | 11a54cb9 | Christos Stavrakakis | """Resolve quotaholder pending commissions.
|
191 | 11a54cb9 | Christos Stavrakakis |
|
192 | 11a54cb9 | Christos Stavrakakis | Get pending commissions from the quotaholder and resolve them
|
193 | 11a54cb9 | Christos Stavrakakis | to accepted and rejected, according to the state of the
|
194 | 11a54cb9 | Christos Stavrakakis | QuotaHolderSerial DB table. A pending commission in the quotaholder
|
195 | 11a54cb9 | Christos Stavrakakis | can exist in the QuotaHolderSerial table and be either accepted or
|
196 | 8d5795b4 | Christos Stavrakakis | rejected, or cannot exist in this table, so it is rejected.
|
197 | 11a54cb9 | Christos Stavrakakis |
|
198 | 11a54cb9 | Christos Stavrakakis | """
|
199 | 11a54cb9 | Christos Stavrakakis | |
200 | 11a54cb9 | Christos Stavrakakis | qh_pending = get_quotaholder_pending() |
201 | 11a54cb9 | Christos Stavrakakis | if not qh_pending: |
202 | 11a54cb9 | Christos Stavrakakis | return ([], [])
|
203 | 11a54cb9 | Christos Stavrakakis | |
204 | 11a54cb9 | Christos Stavrakakis | qh_pending.sort() |
205 | 11a54cb9 | Christos Stavrakakis | min_ = qh_pending[0]
|
206 | 11a54cb9 | Christos Stavrakakis | |
207 | 11a54cb9 | Christos Stavrakakis | serials = QuotaHolderSerial.objects.filter(serial__gte=min_, pending=False)
|
208 | 2509ce17 | Christos Stavrakakis | accepted = serials.filter(accept=True).values_list('serial', flat=True) |
209 | 11a54cb9 | Christos Stavrakakis | accepted = filter(lambda x: x in qh_pending, accepted) |
210 | 11a54cb9 | Christos Stavrakakis | |
211 | 11a54cb9 | Christos Stavrakakis | rejected = list(set(qh_pending) - set(accepted)) |
212 | 11a54cb9 | Christos Stavrakakis | |
213 | 11a54cb9 | Christos Stavrakakis | return (accepted, rejected)
|
214 | 11a54cb9 | Christos Stavrakakis | |
215 | 11a54cb9 | Christos Stavrakakis | |
216 | 11a54cb9 | Christos Stavrakakis | def get_quotaholder_pending(): |
217 | 629acc65 | Giorgos Korfiatis | qh = Quotaholder.get() |
218 | e407f159 | Ilias Tsitsimpis | pending_serials = qh.get_pending_commissions() |
219 | 11a54cb9 | Christos Stavrakakis | return pending_serials
|
220 | 5a70b1a3 | Christos Stavrakakis | |
221 | 5a70b1a3 | Christos Stavrakakis | |
222 | 629acc65 | Giorgos Korfiatis | def render_overlimit_exception(e): |
223 | 5a70b1a3 | Christos Stavrakakis | resource_name = {"vm": "Virtual Machine", |
224 | 5a70b1a3 | Christos Stavrakakis | "cpu": "CPU", |
225 | 5a70b1a3 | Christos Stavrakakis | "ram": "RAM", |
226 | 8b41683a | Christos Stavrakakis | "network.private": "Private Network", |
227 | 8b41683a | Christos Stavrakakis | "floating_ip": "Floating IP address"} |
228 | 656cf771 | Christos Stavrakakis | details = json.loads(e.details) |
229 | 629acc65 | Giorgos Korfiatis | data = details['overLimit']['data'] |
230 | 656cf771 | Christos Stavrakakis | usage = data["usage"]
|
231 | 656cf771 | Christos Stavrakakis | limit = data["limit"]
|
232 | 656cf771 | Christos Stavrakakis | available = limit - usage |
233 | 629acc65 | Giorgos Korfiatis | provision = data['provision']
|
234 | 629acc65 | Giorgos Korfiatis | requested = provision['quantity']
|
235 | 629acc65 | Giorgos Korfiatis | resource = provision['resource']
|
236 | 629acc65 | Giorgos Korfiatis | res = resource.replace("cyclades.", "", 1) |
237 | 5a70b1a3 | Christos Stavrakakis | try:
|
238 | 5a70b1a3 | Christos Stavrakakis | resource = resource_name[res] |
239 | 5a70b1a3 | Christos Stavrakakis | except KeyError: |
240 | 5a70b1a3 | Christos Stavrakakis | resource = res |
241 | 5a70b1a3 | Christos Stavrakakis | |
242 | 5a70b1a3 | Christos Stavrakakis | msg = "Resource Limit Exceeded for your account."
|
243 | 5a70b1a3 | Christos Stavrakakis | details = "Limit for resource '%s' exceeded for your account."\
|
244 | 629acc65 | Giorgos Korfiatis | " Available: %s, Requested: %s"\
|
245 | 629acc65 | Giorgos Korfiatis | % (resource, available, requested) |
246 | 5a70b1a3 | Christos Stavrakakis | return msg, details
|
247 | 2509ce17 | Christos Stavrakakis | |
248 | 2509ce17 | Christos Stavrakakis | |
249 | 21eb7404 | Christos Stavrakakis | @transaction.commit_on_success
|
250 | 368d879e | Giorgos Korfiatis | def issue_and_accept_commission(resource, action="BUILD", action_fields=None): |
251 | 2509ce17 | Christos Stavrakakis | """Issue and accept a commission to Quotaholder.
|
252 | 2509ce17 | Christos Stavrakakis |
|
253 | 2509ce17 | Christos Stavrakakis | This function implements the Commission workflow, and must be called
|
254 | 2509ce17 | Christos Stavrakakis | exactly after and in the same transaction that created/updated the
|
255 | 2509ce17 | Christos Stavrakakis | resource. The workflow that implements is the following:
|
256 | 4ed25171 | Christos Stavrakakis | 0) Resolve previous unresolved commission if exists
|
257 | 21eb7404 | Christos Stavrakakis | 1) Issue commission, get a serial and correlate it with the resource
|
258 | 21eb7404 | Christos Stavrakakis | 2) Store the serial in DB as a serial to accept
|
259 | 21eb7404 | Christos Stavrakakis | 3) COMMIT!
|
260 | 21eb7404 | Christos Stavrakakis | 4) Accept commission to QH
|
261 | 2509ce17 | Christos Stavrakakis |
|
262 | 2509ce17 | Christos Stavrakakis | """
|
263 | 368d879e | Giorgos Korfiatis | commission_reason = ("client: api, resource: %s, action: %s"
|
264 | 368d879e | Giorgos Korfiatis | % (resource, action)) |
265 | 21eb7404 | Christos Stavrakakis | serial = handle_resource_commission(resource=resource, action=action, |
266 | 368d879e | Giorgos Korfiatis | action_fields=action_fields, |
267 | 21eb7404 | Christos Stavrakakis | commission_name=commission_reason) |
268 | 4ed25171 | Christos Stavrakakis | |
269 | 21eb7404 | Christos Stavrakakis | # Mark the serial as one to accept and associate it with the resource
|
270 | 21eb7404 | Christos Stavrakakis | serial.pending = False
|
271 | 21eb7404 | Christos Stavrakakis | serial.accept = True
|
272 | 21eb7404 | Christos Stavrakakis | serial.save() |
273 | 21eb7404 | Christos Stavrakakis | transaction.commit() |
274 | 2509ce17 | Christos Stavrakakis | |
275 | 2509ce17 | Christos Stavrakakis | try:
|
276 | 41a7fae7 | Christos Stavrakakis | # Accept the commission to quotaholder
|
277 | 41a7fae7 | Christos Stavrakakis | accept_serial(serial) |
278 | 2509ce17 | Christos Stavrakakis | except:
|
279 | 21eb7404 | Christos Stavrakakis | # Do not crash if we can not accept commission to Quotaholder. Quotas
|
280 | 21eb7404 | Christos Stavrakakis | # have already been reserved and the resource already exists in DB.
|
281 | 21eb7404 | Christos Stavrakakis | # Just log the error
|
282 | 21eb7404 | Christos Stavrakakis | log.exception("Failed to accept commission: %s", serial)
|
283 | 21eb7404 | Christos Stavrakakis | |
284 | 21eb7404 | Christos Stavrakakis | return serial
|
285 | 2509ce17 | Christos Stavrakakis | |
286 | 2509ce17 | Christos Stavrakakis | |
287 | 41a7fae7 | Christos Stavrakakis | def get_commission_info(resource, action, action_fields=None): |
288 | 41a7fae7 | Christos Stavrakakis | if isinstance(resource, VirtualMachine): |
289 | 41a7fae7 | Christos Stavrakakis | flavor = resource.flavor |
290 | 41a7fae7 | Christos Stavrakakis | resources = {"cyclades.vm": 1, |
291 | 5083fc47 | Christos Stavrakakis | "cyclades.total_cpu": flavor.cpu,
|
292 | 41a7fae7 | Christos Stavrakakis | "cyclades.disk": 1073741824 * flavor.disk, |
293 | 5083fc47 | Christos Stavrakakis | "cyclades.total_ram": 1048576 * flavor.ram} |
294 | 5083fc47 | Christos Stavrakakis | online_resources = {"cyclades.cpu": flavor.cpu,
|
295 | 5083fc47 | Christos Stavrakakis | "cyclades.ram": 1048576 * flavor.ram} |
296 | bb649089 | Christos Stavrakakis | if action == "BUILD": |
297 | bb649089 | Christos Stavrakakis | resources.update(online_resources) |
298 | bb649089 | Christos Stavrakakis | return resources
|
299 | 41a7fae7 | Christos Stavrakakis | if action == "START": |
300 | 41a7fae7 | Christos Stavrakakis | if resource.operstate == "STOPPED": |
301 | 41a7fae7 | Christos Stavrakakis | return online_resources
|
302 | 41a7fae7 | Christos Stavrakakis | else:
|
303 | 41a7fae7 | Christos Stavrakakis | return None |
304 | 41a7fae7 | Christos Stavrakakis | elif action == "STOP": |
305 | 41a7fae7 | Christos Stavrakakis | if resource.operstate in ["STARTED", "BUILD", "ERROR"]: |
306 | 41a7fae7 | Christos Stavrakakis | return reverse_quantities(online_resources)
|
307 | 41a7fae7 | Christos Stavrakakis | else:
|
308 | 41a7fae7 | Christos Stavrakakis | return None |
309 | 41a7fae7 | Christos Stavrakakis | elif action == "REBOOT": |
310 | 41a7fae7 | Christos Stavrakakis | if resource.operstate == "STOPPED": |
311 | 41a7fae7 | Christos Stavrakakis | return online_resources
|
312 | 41a7fae7 | Christos Stavrakakis | else:
|
313 | 41a7fae7 | Christos Stavrakakis | return None |
314 | 41a7fae7 | Christos Stavrakakis | elif action == "DESTROY": |
315 | 41a7fae7 | Christos Stavrakakis | if resource.operstate in ["STARTED", "BUILD", "ERROR"]: |
316 | 41a7fae7 | Christos Stavrakakis | resources.update(online_resources) |
317 | 41a7fae7 | Christos Stavrakakis | return reverse_quantities(resources)
|
318 | 41a7fae7 | Christos Stavrakakis | elif action == "RESIZE" and action_fields: |
319 | 41a7fae7 | Christos Stavrakakis | beparams = action_fields.get("beparams")
|
320 | 41a7fae7 | Christos Stavrakakis | cpu = beparams.get("vcpus", flavor.cpu)
|
321 | 41a7fae7 | Christos Stavrakakis | ram = beparams.get("maxmem", flavor.ram)
|
322 | 5083fc47 | Christos Stavrakakis | return {"cyclades.total_cpu": cpu - flavor.cpu, |
323 | 5083fc47 | Christos Stavrakakis | "cyclades.total_ram": 1048576 * (ram - flavor.ram)} |
324 | 41a7fae7 | Christos Stavrakakis | else:
|
325 | 41a7fae7 | Christos Stavrakakis | #["CONNECT", "DISCONNECT", "SET_FIREWALL_PROFILE"]:
|
326 | 41a7fae7 | Christos Stavrakakis | return None |
327 | 16b959ce | Giorgos Korfiatis | elif isinstance(resource, Network): |
328 | 16b959ce | Giorgos Korfiatis | resources = {"cyclades.network.private": 1} |
329 | 16b959ce | Giorgos Korfiatis | if action == "BUILD": |
330 | 16b959ce | Giorgos Korfiatis | return resources
|
331 | 16b959ce | Giorgos Korfiatis | elif action == "DESTROY": |
332 | 16b959ce | Giorgos Korfiatis | return reverse_quantities(resources)
|
333 | 44183264 | Christos Stavrakakis | elif isinstance(resource, IPAddress): |
334 | 44183264 | Christos Stavrakakis | if resource.floating_ip:
|
335 | 44183264 | Christos Stavrakakis | resources = {"cyclades.floating_ip": 1} |
336 | 44183264 | Christos Stavrakakis | if action == "BUILD": |
337 | 44183264 | Christos Stavrakakis | return resources
|
338 | 44183264 | Christos Stavrakakis | elif action == "DESTROY": |
339 | 44183264 | Christos Stavrakakis | return reverse_quantities(resources)
|
340 | 44183264 | Christos Stavrakakis | else:
|
341 | 44183264 | Christos Stavrakakis | return None |
342 | 41a7fae7 | Christos Stavrakakis | |
343 | 41a7fae7 | Christos Stavrakakis | |
344 | 2509ce17 | Christos Stavrakakis | def reverse_quantities(resources): |
345 | 2509ce17 | Christos Stavrakakis | return dict((r, -s) for r, s in resources.items()) |
346 | 41a7fae7 | Christos Stavrakakis | |
347 | 41a7fae7 | Christos Stavrakakis | |
348 | 5c8076b6 | Christos Stavrakakis | def handle_resource_commission(resource, action, commission_name, |
349 | 16b959ce | Giorgos Korfiatis | force=False, auto_accept=False, |
350 | 16b959ce | Giorgos Korfiatis | action_fields=None):
|
351 | 5c8076b6 | Christos Stavrakakis | """Handle a issuing of a commission for a resource.
|
352 | 5c8076b6 | Christos Stavrakakis |
|
353 | 5c8076b6 | Christos Stavrakakis | Create a new commission for a resource based on the action that
|
354 | 5c8076b6 | Christos Stavrakakis | is performed. If the resource has a previous pending commission,
|
355 | 5c8076b6 | Christos Stavrakakis | resolved it before issuing the new one.
|
356 | 5c8076b6 | Christos Stavrakakis |
|
357 | 5c8076b6 | Christos Stavrakakis | """
|
358 | 1fdd8d69 | Christos Stavrakakis | # Try to resolve previous serial:
|
359 | 1fdd8d69 | Christos Stavrakakis | # If action is DESTROY, we must always reject the previous commission,
|
360 | 1fdd8d69 | Christos Stavrakakis | # since multiple DESTROY actions are allowed in the same resource (e.g. VM)
|
361 | 1fdd8d69 | Christos Stavrakakis | # The one who succeeds will be finally accepted, and all other will be
|
362 | 1fdd8d69 | Christos Stavrakakis | # rejected
|
363 | 1fdd8d69 | Christos Stavrakakis | force = force or (action == "DESTROY") |
364 | fb540e3a | Giorgos Korfiatis | resolve_commission(resource.serial, force=force) |
365 | 5c8076b6 | Christos Stavrakakis | |
366 | 16b959ce | Giorgos Korfiatis | serial = issue_commission(resource, action, name=commission_name, |
367 | 16b959ce | Giorgos Korfiatis | force=force, auto_accept=auto_accept, |
368 | 16b959ce | Giorgos Korfiatis | action_fields=action_fields) |
369 | 5c8076b6 | Christos Stavrakakis | resource.serial = serial |
370 | 16b959ce | Giorgos Korfiatis | resource.save() |
371 | 21eb7404 | Christos Stavrakakis | return serial
|
372 | 5c8076b6 | Christos Stavrakakis | |
373 | 5c8076b6 | Christos Stavrakakis | |
374 | fb540e3a | Giorgos Korfiatis | class ResolveError(Exception): |
375 | fb540e3a | Giorgos Korfiatis | pass
|
376 | fb540e3a | Giorgos Korfiatis | |
377 | fb540e3a | Giorgos Korfiatis | |
378 | fb540e3a | Giorgos Korfiatis | def resolve_commission(serial, force=False): |
379 | 5c8076b6 | Christos Stavrakakis | if serial is None or serial.resolved: |
380 | 5c8076b6 | Christos Stavrakakis | return
|
381 | fb540e3a | Giorgos Korfiatis | if serial.pending and not force: |
382 | fb540e3a | Giorgos Korfiatis | m = "Could not resolve commission: serial %s is undecided" % serial
|
383 | fb540e3a | Giorgos Korfiatis | raise ResolveError(m)
|
384 | 41a7fae7 | Christos Stavrakakis | log.warning("Resolving pending commission: %s", serial)
|
385 | 41a7fae7 | Christos Stavrakakis | if not serial.pending and serial.accept: |
386 | 41a7fae7 | Christos Stavrakakis | accept_serial(serial) |
387 | 41a7fae7 | Christos Stavrakakis | else:
|
388 | 41a7fae7 | Christos Stavrakakis | reject_serial(serial) |