Revision 9068cd85
b/db/models.py | ||
---|---|---|
308 | 308 |
null=True) |
309 | 309 |
backendlogmsg = models.TextField(null=True) |
310 | 310 |
|
311 |
buildpercentage = models.IntegerField(null=True) |
|
312 |
|
|
311 | 313 |
# Error classes |
312 | 314 |
class InvalidBackendIdError(Exception): |
313 | 315 |
def __init__(self, value): |
... | ... | |
334 | 336 |
|
335 | 337 |
class BuildingError(Exception): |
336 | 338 |
pass |
339 |
|
|
340 |
class IllegalState(Exception): |
|
341 |
pass |
|
337 | 342 |
|
338 | 343 |
def __init__(self, *args, **kw): |
339 | 344 |
"""Initialize state for just created VM instances.""" |
b/logic/backend.py | ||
---|---|---|
134 | 134 |
firewall_profile=firewall_profile) |
135 | 135 |
vm.save() |
136 | 136 |
|
137 |
@transaction.commit_on_success |
|
138 |
def process_progress_update(vm, pr_percentage): |
|
139 |
|
|
140 |
if not type(pr_percentage) == int: |
|
141 |
raise TypeError("Percentage not an integer") |
|
142 |
|
|
143 |
if pr_percentage < 0 or pr_percentage > 100: |
|
144 |
raise Exception("Percentage not in range (0, 100)") |
|
145 |
|
|
146 |
last_update = vm.buildpercentage |
|
147 |
|
|
148 |
if last_update > pr_percentage: |
|
149 |
raise Exception("Build percentage should increase monotonically" \ |
|
150 |
" (old=%d, new=%d)"%(last_update, pr_percentage)) |
|
151 |
|
|
152 |
if not vm.operstate == 'BUILD': |
|
153 |
raise VirtualMachine.IllegalState("VM is not in building state") |
|
154 |
|
|
155 |
vm.buildpercentage = pr_percentage |
|
156 |
vm.save() |
|
137 | 157 |
|
138 | 158 |
def start_action(vm, action): |
139 | 159 |
"""Update the state of a VM when a new action is initiated.""" |
b/logic/callbacks.py | ||
---|---|---|
134 | 134 |
_logger.debug("Request to update credits") |
135 | 135 |
message.channel.basic_ack(message.delivery_tag) |
136 | 136 |
|
137 |
|
|
138 |
def update_build_progress(message): |
|
139 |
"""Process a progress update message""" |
|
140 |
try: |
|
141 |
msg = json.loads(message.body) |
|
142 |
|
|
143 |
if msg['type'] != "ganeti-create-progess": |
|
144 |
_logger.error("Message is of unknown type %s", msg["type"]) |
|
145 |
return |
|
146 |
|
|
147 |
# XXX: The following assumes names like snf-12 |
|
148 |
instid = msg['instance'].split('-')[1] |
|
149 |
|
|
150 |
vm = VirtualMachine.objects.get(id = instid) |
|
151 |
|
|
152 |
backend.process_net_status(vm, msg['percentage']) |
|
153 |
|
|
154 |
_logger.debug("Done processing ganeti-create-progess msg for vm %s.", |
|
155 |
msg["instance"]) |
|
156 |
message.channel.basic_ack(message.delivery_tag) |
|
157 |
|
|
158 |
except KeyError: |
|
159 |
_logger.error("Malformed incoming JSON, missing attributes: %s", |
|
160 |
message.body) |
|
161 |
except VirtualMachine.IllegalState: |
|
162 |
_logger.error("Build progress message for non-building VM %s: %s"% |
|
163 |
(instid, message.body)) |
|
164 |
except Exception as e: |
|
165 |
_logger.exception("Unexpected error") |
|
166 |
raise |
|
167 |
|
|
168 |
|
|
137 | 169 |
def trigger_status_update(message): |
138 | 170 |
""" |
139 | 171 |
Triggers a status update job for a specific VM id. |
b/logic/dispatcher.py | ||
---|---|---|
155 | 155 |
|
156 | 156 |
QUEUE_GANETI_EVENTS_OP = "%s-events-op" % prefix |
157 | 157 |
QUEUE_GANETI_EVENTS_NET = "%s-events-net" % prefix |
158 |
QUEUE_GANETI_BUILD_PROGR = "%s-events-progress" % prefix |
|
158 | 159 |
QUEUE_CRON_CREDITS = "%s-credits" % prefix |
159 | 160 |
QUEUE_EMAIL = "%s-email" % prefix |
160 | 161 |
QUEUE_RECONC = "%s-reconciliation" % prefix |
... | ... | |
162 | 163 |
QUEUE_DEBUG = "debug" # Debug queue, retrieves all messages |
163 | 164 |
|
164 | 165 |
QUEUES = (QUEUE_GANETI_EVENTS_OP, QUEUE_GANETI_EVENTS_NET, |
165 |
QUEUE_CRON_CREDITS, QUEUE_EMAIL, QUEUE_RECONC) |
|
166 |
QUEUE_CRON_CREDITS, QUEUE_EMAIL, QUEUE_RECONC, |
|
167 |
QUEUE_GANETI_BUILD_PROGR) |
|
166 | 168 |
|
167 | 169 |
# notifications of type "ganeti-op-status" |
168 | 170 |
DB_HANDLER_KEY_OP ='ganeti.%s.event.op' % prefix |
169 | 171 |
# notifications of type "ganeti-net-status" |
170 | 172 |
DB_HANDLER_KEY_NET ='ganeti.%s.event.net' % prefix |
173 |
# Build process monitoring event |
|
174 |
BUILD_MONITOR_HANDLER = 'ganeti.%s.event.progress' %prefix |
|
171 | 175 |
|
172 | 176 |
BINDINGS = [ |
173 |
# Queue # Exchange # RouteKey # Handler |
|
174 |
(QUEUE_GANETI_EVENTS_OP, settings.EXCHANGE_GANETI, DB_HANDLER_KEY_OP, 'update_db'), |
|
175 |
(QUEUE_GANETI_EVENTS_NET, settings.EXCHANGE_GANETI, DB_HANDLER_KEY_NET, 'update_net'), |
|
176 |
(QUEUE_CRON_CREDITS, settings.EXCHANGE_CRON, '*.credits.*', 'update_credits'), |
|
177 |
(QUEUE_EMAIL, settings.EXCHANGE_API, '*.email.*', 'send_email'), |
|
178 |
(QUEUE_EMAIL, settings.EXCHANGE_CRON, '*.email.*', 'send_email'), |
|
179 |
(QUEUE_RECONC, settings.EXCHANGE_CRON, 'reconciliation.*', 'trigger_status_update'), |
|
177 |
# Queue # Exchange # RouteKey # Handler |
|
178 |
(QUEUE_GANETI_EVENTS_OP, settings.EXCHANGE_GANETI, DB_HANDLER_KEY_OP, 'update_db'), |
|
179 |
(QUEUE_GANETI_EVENTS_NET, settings.EXCHANGE_GANETI, DB_HANDLER_KEY_NET, 'update_net'), |
|
180 |
(QUEUE_GANETI_BUILD_PROGR,settings.EXCHANGE_GANETI, BUILD_MONITOR_HANDLER, 'update_build_progress'), |
|
181 |
(QUEUE_CRON_CREDITS, settings.EXCHANGE_CRON, '*.credits.*', 'update_credits'), |
|
182 |
(QUEUE_EMAIL, settings.EXCHANGE_API, '*.email.*', 'send_email'), |
|
183 |
(QUEUE_EMAIL, settings.EXCHANGE_CRON, '*.email.*', 'send_email'), |
|
184 |
(QUEUE_RECONC, settings.EXCHANGE_CRON, 'reconciliation.*', 'trigger_status_update'), |
|
180 | 185 |
] |
181 | 186 |
|
182 | 187 |
if settings.DEBUG is True: |
b/logic/tests.py | ||
---|---|---|
317 | 317 |
|
318 | 318 |
username = users.create_uname(u'Γεώργιος Παπαγεωργίου') |
319 | 319 |
self.assertEquals(username, u'παπαγεωγ') |
320 |
|
|
321 |
class ProcessProgressUpdateTestCase(TestCase): |
|
322 |
fixtures = [ 'db_test_data' ] |
|
323 |
|
|
324 |
def test_progress_update(self): |
|
325 |
|
|
326 |
# A VM in status BUILDING |
|
327 |
vm = VirtualMachine.objects.get(pk=30002) |
|
328 |
|
|
329 |
backend.process_progress_update(vm, 12) |
|
330 |
self.assertEquals(vm.buildpercentage, 12) |
|
331 |
|
|
332 |
self.assertRaises(Exception, backend.process_progress_update, vm, 10) |
|
333 |
self.assertRaises(Exception, backend.process_progress_update, vm, -1) |
|
334 |
self.assertRaises(Exception, backend.process_progress_update, vm, 102) |
|
335 |
self.assertRaises(TypeError, backend.process_progress_update, vm, '1') |
|
336 |
|
|
337 |
# A VM in status RUNNING |
|
338 |
vm = VirtualMachine.objects.get(pk=30000) |
|
339 |
self.assertRaises(VirtualMachine.IllegalState, |
|
340 |
backend.process_progress_update, vm, 1) |
Also available in: Unified diff