Revision 72dea98f snf-cyclades-app/synnefo/logic/backend.py
b/snf-cyclades-app/synnefo/logic/backend.py | ||
---|---|---|
35 | 35 |
from datetime import datetime |
36 | 36 |
|
37 | 37 |
from synnefo.db.models import (Backend, VirtualMachine, Network, |
38 |
FloatingIP, |
|
38 | 39 |
BackendNetwork, BACKEND_STATUSES, |
39 | 40 |
pooled_rapi_client, VirtualMachineDiagnostic, |
40 | 41 |
Flavor) |
... | ... | |
160 | 161 |
# See ticket #799 for all the details. |
161 | 162 |
if status == 'success' or (status == 'error' and |
162 | 163 |
vm.operstate == 'ERROR'): |
163 |
_process_net_status(vm, etime, nics=[]) |
|
164 |
# VM has been deleted. Release the instance IPs |
|
165 |
release_instance_ips(vm, []) |
|
166 |
# And delete the releated NICs (must be performed after release!) |
|
167 |
vm.nics.all().delete() |
|
164 | 168 |
vm.deleted = True |
165 | 169 |
vm.operstate = state_for_success |
166 | 170 |
vm.backendtime = etime |
... | ... | |
220 | 224 |
# guarantee that no deadlock will occur with Backend allocator. |
221 | 225 |
Backend.objects.select_for_update().get(id=vm.backend_id) |
222 | 226 |
|
223 |
release_instance_nics(vm) |
|
227 |
# NICs have changed. Release the instance IPs |
|
228 |
release_instance_ips(vm, ganeti_nics) |
|
229 |
# And delete the releated NICs (must be performed after release!) |
|
230 |
vm.nics.all().delete() |
|
224 | 231 |
|
225 | 232 |
for nic in ganeti_nics: |
226 | 233 |
ipv4 = nic.get('ipv4', '') |
... | ... | |
286 | 293 |
return False |
287 | 294 |
|
288 | 295 |
|
289 |
def release_instance_nics(vm): |
|
290 |
for nic in vm.nics.all(): |
|
291 |
net = nic.network |
|
292 |
if nic.ipv4: |
|
293 |
net.release_address(nic.ipv4) |
|
294 |
nic.delete() |
|
295 |
net.save() |
|
296 |
def release_instance_ips(vm, ganeti_nics): |
|
297 |
old_addresses = set(vm.nics.values_list("network", "ipv4")) |
|
298 |
new_addresses = set(map(lambda nic: (nic["network"], nic["ipv4"]), |
|
299 |
ganeti_nics)) |
|
300 |
to_release = old_addresses - new_addresses |
|
301 |
for (network_id, ipv4) in to_release: |
|
302 |
if ipv4: |
|
303 |
net = Network.objects.get(id=network_id) |
|
304 |
# Important: Take exclusive lock in pool before checking if there |
|
305 |
# is a floating IP with this ipv4 address, otherwise there is a |
|
306 |
# race condition, where you may release a floating IP that has been |
|
307 |
# created after search floating IPs and before you get exclusively |
|
308 |
# the pool |
|
309 |
pool = net.get_pool() |
|
310 |
try: |
|
311 |
floating_ip = net.floating_ips.select_for_update()\ |
|
312 |
.get(ipv4=ipv4, machine=vm, |
|
313 |
deleted=False) |
|
314 |
floating_ip.machine = None |
|
315 |
floating_ip.save() |
|
316 |
except FloatingIP.DoesNotExist: |
|
317 |
net.release_address(ipv4) |
|
318 |
pool.save() |
|
296 | 319 |
|
297 | 320 |
|
298 | 321 |
@transaction.commit_on_success |
Also available in: Unified diff