root / snf-cyclades-app / synnefo / quotas / __init__.py @ 368d879e
History | View | Annotate | Download (12.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 | 629acc65 | Giorgos Korfiatis | from astakosclient.errors import AstakosClientException, QuotaLimit |
41 | 499d9bfe | Christos Stavrakakis | from functools import wraps |
42 | bfe7ba3c | Christos Stavrakakis | |
43 | bfe7ba3c | Christos Stavrakakis | import logging |
44 | bfe7ba3c | Christos Stavrakakis | log = logging.getLogger(__name__) |
45 | bfe7ba3c | Christos Stavrakakis | |
46 | e407f159 | Ilias Tsitsimpis | |
47 | 629acc65 | Giorgos Korfiatis | DEFAULT_SOURCE = 'system'
|
48 | 656cf771 | Christos Stavrakakis | RESOURCES = [ |
49 | 656cf771 | Christos Stavrakakis | "cyclades.vm",
|
50 | 656cf771 | Christos Stavrakakis | "cyclades.cpu",
|
51 | 41a7fae7 | Christos Stavrakakis | "cyclades.active_cpu",
|
52 | 656cf771 | Christos Stavrakakis | "cyclades.disk",
|
53 | 656cf771 | Christos Stavrakakis | "cyclades.ram",
|
54 | 41a7fae7 | Christos Stavrakakis | "cyclades.active_ram",
|
55 | 8b41683a | Christos Stavrakakis | "cyclades.network.private",
|
56 | 8b41683a | Christos Stavrakakis | "cyclades.floating_ip",
|
57 | 656cf771 | Christos Stavrakakis | ] |
58 | bfe7ba3c | Christos Stavrakakis | |
59 | bfe7ba3c | Christos Stavrakakis | |
60 | 629acc65 | Giorgos Korfiatis | class Quotaholder(object): |
61 | 629acc65 | Giorgos Korfiatis | _object = None
|
62 | 629acc65 | Giorgos Korfiatis | |
63 | 629acc65 | Giorgos Korfiatis | @classmethod
|
64 | 629acc65 | Giorgos Korfiatis | def get(cls): |
65 | 629acc65 | Giorgos Korfiatis | if cls._object is None: |
66 | 4fb643b3 | Giorgos Korfiatis | cls._object = AstakosClient(ASTAKOS_TOKEN, |
67 | 4fb643b3 | Giorgos Korfiatis | ASTAKOS_AUTH_URL, |
68 | 4fb643b3 | Giorgos Korfiatis | use_pool=True,
|
69 | 4fb643b3 | Giorgos Korfiatis | retry=3,
|
70 | 4fb643b3 | Giorgos Korfiatis | logger=log) |
71 | 629acc65 | Giorgos Korfiatis | return cls._object
|
72 | bfe7ba3c | Christos Stavrakakis | |
73 | bfe7ba3c | Christos Stavrakakis | |
74 | 499d9bfe | Christos Stavrakakis | def handle_astakosclient_error(func): |
75 | 499d9bfe | Christos Stavrakakis | """Decorator for converting astakosclient errors to 500."""
|
76 | 499d9bfe | Christos Stavrakakis | @wraps(func)
|
77 | 499d9bfe | Christos Stavrakakis | def wrapper(*args, **kwargs): |
78 | 499d9bfe | Christos Stavrakakis | try:
|
79 | 499d9bfe | Christos Stavrakakis | return func(*args, **kwargs)
|
80 | 499d9bfe | Christos Stavrakakis | except AstakosClientException:
|
81 | 499d9bfe | Christos Stavrakakis | log.exception("Unexpected error")
|
82 | 499d9bfe | Christos Stavrakakis | raise faults.InternalServerError("Unexpected error") |
83 | 499d9bfe | Christos Stavrakakis | return wrapper
|
84 | 499d9bfe | Christos Stavrakakis | |
85 | 499d9bfe | Christos Stavrakakis | |
86 | 499d9bfe | Christos Stavrakakis | @handle_astakosclient_error
|
87 | 16b959ce | Giorgos Korfiatis | def issue_commission(resource, action, name="", force=False, auto_accept=False, |
88 | 16b959ce | Giorgos Korfiatis | action_fields=None):
|
89 | bfe7ba3c | Christos Stavrakakis | """Issue a new commission to the quotaholder.
|
90 | bfe7ba3c | Christos Stavrakakis |
|
91 | bfe7ba3c | Christos Stavrakakis | Issue a new commission to the quotaholder, and create the
|
92 | bfe7ba3c | Christos Stavrakakis | corresponing QuotaHolderSerial object in DB.
|
93 | bfe7ba3c | Christos Stavrakakis |
|
94 | bfe7ba3c | Christos Stavrakakis | """
|
95 | bfe7ba3c | Christos Stavrakakis | |
96 | 16b959ce | Giorgos Korfiatis | provisions = get_commission_info(resource=resource, action=action, |
97 | 16b959ce | Giorgos Korfiatis | action_fields=action_fields) |
98 | 16b959ce | Giorgos Korfiatis | |
99 | 16b959ce | Giorgos Korfiatis | if provisions is None: |
100 | 16b959ce | Giorgos Korfiatis | return None |
101 | 16b959ce | Giorgos Korfiatis | |
102 | 16b959ce | Giorgos Korfiatis | user = resource.userid |
103 | 16b959ce | Giorgos Korfiatis | source = DEFAULT_SOURCE |
104 | 16b959ce | Giorgos Korfiatis | |
105 | 629acc65 | Giorgos Korfiatis | qh = Quotaholder.get() |
106 | 629acc65 | Giorgos Korfiatis | try:
|
107 | 16b959ce | Giorgos Korfiatis | if True: # placeholder |
108 | 16b959ce | Giorgos Korfiatis | serial = qh.issue_one_commission(user, source, |
109 | 16b959ce | Giorgos Korfiatis | provisions, name=name, |
110 | 16b959ce | Giorgos Korfiatis | force=force, |
111 | 16b959ce | Giorgos Korfiatis | auto_accept=auto_accept) |
112 | 629acc65 | Giorgos Korfiatis | except QuotaLimit as e: |
113 | 629acc65 | Giorgos Korfiatis | msg, details = render_overlimit_exception(e) |
114 | 629acc65 | Giorgos Korfiatis | raise faults.OverLimit(msg, details=details)
|
115 | bfe7ba3c | Christos Stavrakakis | |
116 | b14f55b5 | Christos Stavrakakis | if serial:
|
117 | 218de705 | Christos Stavrakakis | serial_info = {"serial": serial}
|
118 | 218de705 | Christos Stavrakakis | if auto_accept:
|
119 | fb540e3a | Giorgos Korfiatis | serial_info["pending"] = False |
120 | 218de705 | Christos Stavrakakis | serial_info["accept"] = True |
121 | 218de705 | Christos Stavrakakis | serial_info["resolved"] = True |
122 | 218de705 | Christos Stavrakakis | return QuotaHolderSerial.objects.create(**serial_info)
|
123 | b14f55b5 | Christos Stavrakakis | else:
|
124 | b14f55b5 | Christos Stavrakakis | raise Exception("No serial") |
125 | bfe7ba3c | Christos Stavrakakis | |
126 | bfe7ba3c | Christos Stavrakakis | |
127 | 41a7fae7 | Christos Stavrakakis | def accept_serial(serial, strict=True): |
128 | fb540e3a | Giorgos Korfiatis | assert serial.pending or serial.accept |
129 | 41a7fae7 | Christos Stavrakakis | response = resolve_commissions(accept=[serial.serial], strict=strict) |
130 | fb540e3a | Giorgos Korfiatis | serial.pending = False
|
131 | 41a7fae7 | Christos Stavrakakis | serial.accept = True
|
132 | 41a7fae7 | Christos Stavrakakis | serial.resolved = True
|
133 | 41a7fae7 | Christos Stavrakakis | serial.save() |
134 | 41a7fae7 | Christos Stavrakakis | return response
|
135 | 41a7fae7 | Christos Stavrakakis | |
136 | 41a7fae7 | Christos Stavrakakis | |
137 | 41a7fae7 | Christos Stavrakakis | def reject_serial(serial, strict=True): |
138 | fb540e3a | Giorgos Korfiatis | assert serial.pending or not serial.accept |
139 | 41a7fae7 | Christos Stavrakakis | response = resolve_commissions(reject=[serial.serial], strict=strict) |
140 | fb540e3a | Giorgos Korfiatis | serial.pending = False
|
141 | fb540e3a | Giorgos Korfiatis | serial.accept = False
|
142 | 41a7fae7 | Christos Stavrakakis | serial.resolved = True
|
143 | 41a7fae7 | Christos Stavrakakis | serial.save() |
144 | 41a7fae7 | Christos Stavrakakis | return response
|
145 | 41a7fae7 | Christos Stavrakakis | |
146 | 41a7fae7 | Christos Stavrakakis | |
147 | 5db3a1e6 | Christos Stavrakakis | def accept_commissions(accepted, strict=True): |
148 | d195e752 | Christos Stavrakakis | return resolve_commissions(accept=accepted, strict=strict)
|
149 | 11a54cb9 | Christos Stavrakakis | |
150 | 11a54cb9 | Christos Stavrakakis | |
151 | 5db3a1e6 | Christos Stavrakakis | def reject_commissions(rejected, strict=True): |
152 | d195e752 | Christos Stavrakakis | return resolve_commissions(reject=rejected, strict=strict)
|
153 | 11a54cb9 | Christos Stavrakakis | |
154 | 11a54cb9 | Christos Stavrakakis | |
155 | 499d9bfe | Christos Stavrakakis | @handle_astakosclient_error
|
156 | d195e752 | Christos Stavrakakis | def resolve_commissions(accept=None, reject=None, strict=True): |
157 | 629acc65 | Giorgos Korfiatis | if accept is None: |
158 | 629acc65 | Giorgos Korfiatis | accept = [] |
159 | 629acc65 | Giorgos Korfiatis | if reject is None: |
160 | 629acc65 | Giorgos Korfiatis | reject = [] |
161 | 11a54cb9 | Christos Stavrakakis | |
162 | 629acc65 | Giorgos Korfiatis | qh = Quotaholder.get() |
163 | e407f159 | Ilias Tsitsimpis | response = qh.resolve_commissions(accept, reject) |
164 | 5db3a1e6 | Christos Stavrakakis | |
165 | 5db3a1e6 | Christos Stavrakakis | if strict:
|
166 | 5db3a1e6 | Christos Stavrakakis | failed = response["failed"]
|
167 | 5db3a1e6 | Christos Stavrakakis | if failed:
|
168 | 5db3a1e6 | Christos Stavrakakis | log.error("Unexpected error while resolving commissions: %s",
|
169 | 5db3a1e6 | Christos Stavrakakis | failed) |
170 | 5db3a1e6 | Christos Stavrakakis | |
171 | 5db3a1e6 | Christos Stavrakakis | return response
|
172 | 11a54cb9 | Christos Stavrakakis | |
173 | 11a54cb9 | Christos Stavrakakis | |
174 | 2509ce17 | Christos Stavrakakis | def fix_pending_commissions(): |
175 | 2509ce17 | Christos Stavrakakis | (accepted, rejected) = resolve_pending_commissions() |
176 | d195e752 | Christos Stavrakakis | resolve_commissions(accept=accepted, reject=rejected) |
177 | 2509ce17 | Christos Stavrakakis | |
178 | 2509ce17 | Christos Stavrakakis | |
179 | 11a54cb9 | Christos Stavrakakis | def resolve_pending_commissions(): |
180 | 11a54cb9 | Christos Stavrakakis | """Resolve quotaholder pending commissions.
|
181 | 11a54cb9 | Christos Stavrakakis |
|
182 | 11a54cb9 | Christos Stavrakakis | Get pending commissions from the quotaholder and resolve them
|
183 | 11a54cb9 | Christos Stavrakakis | to accepted and rejected, according to the state of the
|
184 | 11a54cb9 | Christos Stavrakakis | QuotaHolderSerial DB table. A pending commission in the quotaholder
|
185 | 11a54cb9 | Christos Stavrakakis | can exist in the QuotaHolderSerial table and be either accepted or
|
186 | 8d5795b4 | Christos Stavrakakis | rejected, or cannot exist in this table, so it is rejected.
|
187 | 11a54cb9 | Christos Stavrakakis |
|
188 | 11a54cb9 | Christos Stavrakakis | """
|
189 | 11a54cb9 | Christos Stavrakakis | |
190 | 11a54cb9 | Christos Stavrakakis | qh_pending = get_quotaholder_pending() |
191 | 11a54cb9 | Christos Stavrakakis | if not qh_pending: |
192 | 11a54cb9 | Christos Stavrakakis | return ([], [])
|
193 | 11a54cb9 | Christos Stavrakakis | |
194 | 11a54cb9 | Christos Stavrakakis | qh_pending.sort() |
195 | 11a54cb9 | Christos Stavrakakis | min_ = qh_pending[0]
|
196 | 11a54cb9 | Christos Stavrakakis | |
197 | 11a54cb9 | Christos Stavrakakis | serials = QuotaHolderSerial.objects.filter(serial__gte=min_, pending=False)
|
198 | 2509ce17 | Christos Stavrakakis | accepted = serials.filter(accept=True).values_list('serial', flat=True) |
199 | 11a54cb9 | Christos Stavrakakis | accepted = filter(lambda x: x in qh_pending, accepted) |
200 | 11a54cb9 | Christos Stavrakakis | |
201 | 11a54cb9 | Christos Stavrakakis | rejected = list(set(qh_pending) - set(accepted)) |
202 | 11a54cb9 | Christos Stavrakakis | |
203 | 11a54cb9 | Christos Stavrakakis | return (accepted, rejected)
|
204 | 11a54cb9 | Christos Stavrakakis | |
205 | 11a54cb9 | Christos Stavrakakis | |
206 | 11a54cb9 | Christos Stavrakakis | def get_quotaholder_pending(): |
207 | 629acc65 | Giorgos Korfiatis | qh = Quotaholder.get() |
208 | e407f159 | Ilias Tsitsimpis | pending_serials = qh.get_pending_commissions() |
209 | 11a54cb9 | Christos Stavrakakis | return pending_serials
|
210 | 5a70b1a3 | Christos Stavrakakis | |
211 | 5a70b1a3 | Christos Stavrakakis | |
212 | 629acc65 | Giorgos Korfiatis | def render_overlimit_exception(e): |
213 | 5a70b1a3 | Christos Stavrakakis | resource_name = {"vm": "Virtual Machine", |
214 | 5a70b1a3 | Christos Stavrakakis | "cpu": "CPU", |
215 | 5a70b1a3 | Christos Stavrakakis | "ram": "RAM", |
216 | 8b41683a | Christos Stavrakakis | "network.private": "Private Network", |
217 | 8b41683a | Christos Stavrakakis | "floating_ip": "Floating IP address"} |
218 | 656cf771 | Christos Stavrakakis | details = json.loads(e.details) |
219 | 629acc65 | Giorgos Korfiatis | data = details['overLimit']['data'] |
220 | 656cf771 | Christos Stavrakakis | usage = data["usage"]
|
221 | 656cf771 | Christos Stavrakakis | limit = data["limit"]
|
222 | 656cf771 | Christos Stavrakakis | available = limit - usage |
223 | 629acc65 | Giorgos Korfiatis | provision = data['provision']
|
224 | 629acc65 | Giorgos Korfiatis | requested = provision['quantity']
|
225 | 629acc65 | Giorgos Korfiatis | resource = provision['resource']
|
226 | 629acc65 | Giorgos Korfiatis | res = resource.replace("cyclades.", "", 1) |
227 | 5a70b1a3 | Christos Stavrakakis | try:
|
228 | 5a70b1a3 | Christos Stavrakakis | resource = resource_name[res] |
229 | 5a70b1a3 | Christos Stavrakakis | except KeyError: |
230 | 5a70b1a3 | Christos Stavrakakis | resource = res |
231 | 5a70b1a3 | Christos Stavrakakis | |
232 | 5a70b1a3 | Christos Stavrakakis | msg = "Resource Limit Exceeded for your account."
|
233 | 5a70b1a3 | Christos Stavrakakis | details = "Limit for resource '%s' exceeded for your account."\
|
234 | 629acc65 | Giorgos Korfiatis | " Available: %s, Requested: %s"\
|
235 | 629acc65 | Giorgos Korfiatis | % (resource, available, requested) |
236 | 5a70b1a3 | Christos Stavrakakis | return msg, details
|
237 | 2509ce17 | Christos Stavrakakis | |
238 | 2509ce17 | Christos Stavrakakis | |
239 | 21eb7404 | Christos Stavrakakis | @transaction.commit_on_success
|
240 | 368d879e | Giorgos Korfiatis | def issue_and_accept_commission(resource, action="BUILD", action_fields=None): |
241 | 2509ce17 | Christos Stavrakakis | """Issue and accept a commission to Quotaholder.
|
242 | 2509ce17 | Christos Stavrakakis |
|
243 | 2509ce17 | Christos Stavrakakis | This function implements the Commission workflow, and must be called
|
244 | 2509ce17 | Christos Stavrakakis | exactly after and in the same transaction that created/updated the
|
245 | 2509ce17 | Christos Stavrakakis | resource. The workflow that implements is the following:
|
246 | 4ed25171 | Christos Stavrakakis | 0) Resolve previous unresolved commission if exists
|
247 | 21eb7404 | Christos Stavrakakis | 1) Issue commission, get a serial and correlate it with the resource
|
248 | 21eb7404 | Christos Stavrakakis | 2) Store the serial in DB as a serial to accept
|
249 | 21eb7404 | Christos Stavrakakis | 3) COMMIT!
|
250 | 21eb7404 | Christos Stavrakakis | 4) Accept commission to QH
|
251 | 2509ce17 | Christos Stavrakakis |
|
252 | 2509ce17 | Christos Stavrakakis | """
|
253 | 368d879e | Giorgos Korfiatis | commission_reason = ("client: api, resource: %s, action: %s"
|
254 | 368d879e | Giorgos Korfiatis | % (resource, action)) |
255 | 21eb7404 | Christos Stavrakakis | serial = handle_resource_commission(resource=resource, action=action, |
256 | 368d879e | Giorgos Korfiatis | action_fields=action_fields, |
257 | 21eb7404 | Christos Stavrakakis | commission_name=commission_reason) |
258 | 4ed25171 | Christos Stavrakakis | |
259 | 21eb7404 | Christos Stavrakakis | # Mark the serial as one to accept and associate it with the resource
|
260 | 21eb7404 | Christos Stavrakakis | serial.pending = False
|
261 | 21eb7404 | Christos Stavrakakis | serial.accept = True
|
262 | 21eb7404 | Christos Stavrakakis | serial.save() |
263 | 21eb7404 | Christos Stavrakakis | transaction.commit() |
264 | 2509ce17 | Christos Stavrakakis | |
265 | 2509ce17 | Christos Stavrakakis | try:
|
266 | 41a7fae7 | Christos Stavrakakis | # Accept the commission to quotaholder
|
267 | 41a7fae7 | Christos Stavrakakis | accept_serial(serial) |
268 | 2509ce17 | Christos Stavrakakis | except:
|
269 | 21eb7404 | Christos Stavrakakis | # Do not crash if we can not accept commission to Quotaholder. Quotas
|
270 | 21eb7404 | Christos Stavrakakis | # have already been reserved and the resource already exists in DB.
|
271 | 21eb7404 | Christos Stavrakakis | # Just log the error
|
272 | 21eb7404 | Christos Stavrakakis | log.exception("Failed to accept commission: %s", serial)
|
273 | 21eb7404 | Christos Stavrakakis | |
274 | 21eb7404 | Christos Stavrakakis | return serial
|
275 | 2509ce17 | Christos Stavrakakis | |
276 | 2509ce17 | Christos Stavrakakis | |
277 | 41a7fae7 | Christos Stavrakakis | def get_commission_info(resource, action, action_fields=None): |
278 | 41a7fae7 | Christos Stavrakakis | if isinstance(resource, VirtualMachine): |
279 | 41a7fae7 | Christos Stavrakakis | flavor = resource.flavor |
280 | 41a7fae7 | Christos Stavrakakis | resources = {"cyclades.vm": 1, |
281 | 41a7fae7 | Christos Stavrakakis | "cyclades.cpu": flavor.cpu,
|
282 | 41a7fae7 | Christos Stavrakakis | "cyclades.disk": 1073741824 * flavor.disk, |
283 | 41a7fae7 | Christos Stavrakakis | "cyclades.ram": 1048576 * flavor.ram} |
284 | 41a7fae7 | Christos Stavrakakis | online_resources = {"cyclades.active_cpu": flavor.cpu,
|
285 | 41a7fae7 | Christos Stavrakakis | "cyclades.active_ram": 1048576 * flavor.ram} |
286 | bb649089 | Christos Stavrakakis | if action == "BUILD": |
287 | bb649089 | Christos Stavrakakis | resources.update(online_resources) |
288 | bb649089 | Christos Stavrakakis | return resources
|
289 | 41a7fae7 | Christos Stavrakakis | if action == "START": |
290 | 41a7fae7 | Christos Stavrakakis | if resource.operstate == "STOPPED": |
291 | 41a7fae7 | Christos Stavrakakis | return online_resources
|
292 | 41a7fae7 | Christos Stavrakakis | else:
|
293 | 41a7fae7 | Christos Stavrakakis | return None |
294 | 41a7fae7 | Christos Stavrakakis | elif action == "STOP": |
295 | 41a7fae7 | Christos Stavrakakis | if resource.operstate in ["STARTED", "BUILD", "ERROR"]: |
296 | 41a7fae7 | Christos Stavrakakis | return reverse_quantities(online_resources)
|
297 | 41a7fae7 | Christos Stavrakakis | else:
|
298 | 41a7fae7 | Christos Stavrakakis | return None |
299 | 41a7fae7 | Christos Stavrakakis | elif action == "REBOOT": |
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 == "DESTROY": |
305 | 41a7fae7 | Christos Stavrakakis | if resource.operstate in ["STARTED", "BUILD", "ERROR"]: |
306 | 41a7fae7 | Christos Stavrakakis | resources.update(online_resources) |
307 | 41a7fae7 | Christos Stavrakakis | return reverse_quantities(resources)
|
308 | 41a7fae7 | Christos Stavrakakis | elif action == "RESIZE" and action_fields: |
309 | 41a7fae7 | Christos Stavrakakis | beparams = action_fields.get("beparams")
|
310 | 41a7fae7 | Christos Stavrakakis | cpu = beparams.get("vcpus", flavor.cpu)
|
311 | 41a7fae7 | Christos Stavrakakis | ram = beparams.get("maxmem", flavor.ram)
|
312 | 41a7fae7 | Christos Stavrakakis | return {"cyclades.cpu": cpu - flavor.cpu, |
313 | 41a7fae7 | Christos Stavrakakis | "cyclades.ram": 1048576 * (ram - flavor.ram)} |
314 | 41a7fae7 | Christos Stavrakakis | else:
|
315 | 41a7fae7 | Christos Stavrakakis | #["CONNECT", "DISCONNECT", "SET_FIREWALL_PROFILE"]:
|
316 | 41a7fae7 | Christos Stavrakakis | return None |
317 | 16b959ce | Giorgos Korfiatis | elif isinstance(resource, Network): |
318 | 16b959ce | Giorgos Korfiatis | resources = {"cyclades.network.private": 1} |
319 | 16b959ce | Giorgos Korfiatis | if action == "BUILD": |
320 | 16b959ce | Giorgos Korfiatis | return resources
|
321 | 16b959ce | Giorgos Korfiatis | elif action == "DESTROY": |
322 | 16b959ce | Giorgos Korfiatis | return reverse_quantities(resources)
|
323 | 16b959ce | Giorgos Korfiatis | elif isinstance(resource, FloatingIP): |
324 | 16b959ce | Giorgos Korfiatis | resources = {"cyclades.floating_ip": 1} |
325 | 16b959ce | Giorgos Korfiatis | if action == "BUILD": |
326 | 16b959ce | Giorgos Korfiatis | return resources
|
327 | 16b959ce | Giorgos Korfiatis | elif action == "DESTROY": |
328 | 16b959ce | Giorgos Korfiatis | return reverse_quantities(resources)
|
329 | 41a7fae7 | Christos Stavrakakis | |
330 | 41a7fae7 | Christos Stavrakakis | |
331 | 2509ce17 | Christos Stavrakakis | def reverse_quantities(resources): |
332 | 2509ce17 | Christos Stavrakakis | return dict((r, -s) for r, s in resources.items()) |
333 | 41a7fae7 | Christos Stavrakakis | |
334 | 41a7fae7 | Christos Stavrakakis | |
335 | 5c8076b6 | Christos Stavrakakis | def handle_resource_commission(resource, action, commission_name, |
336 | 16b959ce | Giorgos Korfiatis | force=False, auto_accept=False, |
337 | 16b959ce | Giorgos Korfiatis | action_fields=None):
|
338 | 5c8076b6 | Christos Stavrakakis | """Handle a issuing of a commission for a resource.
|
339 | 5c8076b6 | Christos Stavrakakis |
|
340 | 5c8076b6 | Christos Stavrakakis | Create a new commission for a resource based on the action that
|
341 | 5c8076b6 | Christos Stavrakakis | is performed. If the resource has a previous pending commission,
|
342 | 5c8076b6 | Christos Stavrakakis | resolved it before issuing the new one.
|
343 | 5c8076b6 | Christos Stavrakakis |
|
344 | 5c8076b6 | Christos Stavrakakis | """
|
345 | 5c8076b6 | Christos Stavrakakis | # Try to resolve previous serial
|
346 | fb540e3a | Giorgos Korfiatis | resolve_commission(resource.serial, force=force) |
347 | 5c8076b6 | Christos Stavrakakis | |
348 | 16b959ce | Giorgos Korfiatis | serial = issue_commission(resource, action, name=commission_name, |
349 | 16b959ce | Giorgos Korfiatis | force=force, auto_accept=auto_accept, |
350 | 16b959ce | Giorgos Korfiatis | action_fields=action_fields) |
351 | 5c8076b6 | Christos Stavrakakis | resource.serial = serial |
352 | 16b959ce | Giorgos Korfiatis | resource.save() |
353 | 21eb7404 | Christos Stavrakakis | return serial
|
354 | 5c8076b6 | Christos Stavrakakis | |
355 | 5c8076b6 | Christos Stavrakakis | |
356 | fb540e3a | Giorgos Korfiatis | class ResolveError(Exception): |
357 | fb540e3a | Giorgos Korfiatis | pass
|
358 | fb540e3a | Giorgos Korfiatis | |
359 | fb540e3a | Giorgos Korfiatis | |
360 | fb540e3a | Giorgos Korfiatis | def resolve_commission(serial, force=False): |
361 | 5c8076b6 | Christos Stavrakakis | if serial is None or serial.resolved: |
362 | 5c8076b6 | Christos Stavrakakis | return
|
363 | fb540e3a | Giorgos Korfiatis | if serial.pending and not force: |
364 | fb540e3a | Giorgos Korfiatis | m = "Could not resolve commission: serial %s is undecided" % serial
|
365 | fb540e3a | Giorgos Korfiatis | raise ResolveError(m)
|
366 | 41a7fae7 | Christos Stavrakakis | log.warning("Resolving pending commission: %s", serial)
|
367 | 41a7fae7 | Christos Stavrakakis | if not serial.pending and serial.accept: |
368 | 41a7fae7 | Christos Stavrakakis | accept_serial(serial) |
369 | 41a7fae7 | Christos Stavrakakis | else:
|
370 | 41a7fae7 | Christos Stavrakakis | reject_serial(serial) |