Revision 198d91c3
b/snf-cyclades-app/synnefo/db/models.py | ||
---|---|---|
743 | 743 |
|
744 | 744 |
@contextmanager |
745 | 745 |
def pooled_rapi_client(obj): |
746 |
if isinstance(obj, VirtualMachine):
|
|
746 |
if isinstance(obj, (VirtualMachine, BackendNetwork)):
|
|
747 | 747 |
backend = obj.backend |
748 | 748 |
else: |
749 | 749 |
backend = obj |
b/snf-cyclades-app/synnefo/logic/backend.py | ||
---|---|---|
41 | 41 |
from synnefo import quotas |
42 | 42 |
from synnefo.api.util import release_resource |
43 | 43 |
from synnefo.util.mac2eui64 import mac2eui64 |
44 |
from synnefo.logic.rapi import GanetiApiError |
|
44 | 45 |
|
45 | 46 |
from logging import getLogger |
46 | 47 |
log = getLogger(__name__) |
... | ... | |
87 | 88 |
vm.operstate = 'ERROR' |
88 | 89 |
vm.backendtime = etime |
89 | 90 |
elif opcode == 'OP_INSTANCE_REMOVE': |
90 |
# Set the deleted flag explicitly, cater for admin-initiated removals |
|
91 | 91 |
# Special case: OP_INSTANCE_REMOVE fails for machines in ERROR, |
92 | 92 |
# when no instance exists at the Ganeti backend. |
93 |
# See ticket #799 for all the details. |
|
94 |
# |
|
95 |
if (status == 'success' or |
|
96 |
(status == 'error' and (vm.operstate == 'ERROR' or |
|
97 |
vm.action == 'DESTROY'))): |
|
93 |
if status == "success" or (status == "error" and |
|
94 |
not vm_exists_in_backend(vm)): |
|
98 | 95 |
_process_net_status(vm, etime, nics=[]) |
99 | 96 |
vm.deleted = True |
100 | 97 |
vm.operstate = state_for_success |
... | ... | |
233 | 230 |
back_network.backendtime = etime |
234 | 231 |
|
235 | 232 |
if opcode == 'OP_NETWORK_REMOVE': |
236 |
if (status == 'success' or
|
|
237 |
(status == 'error' and (back_network.operstate == 'ERROR' or
|
|
238 |
network.action == 'DESTROY'))):
|
|
233 |
network_is_deleted = (status == "success")
|
|
234 |
if network_is_deleted or (status == "error" and not
|
|
235 |
network_exists_in_backend(back_network)):
|
|
239 | 236 |
back_network.operstate = state_for_success |
240 | 237 |
back_network.deleted = True |
241 | 238 |
back_network.backendtime = etime |
... | ... | |
489 | 486 |
|
490 | 487 |
def get_instance_info(vm): |
491 | 488 |
with pooled_rapi_client(vm) as client: |
492 |
return client.GetInstanceInfo(vm.backend_vm_id) |
|
489 |
return client.GetInstance(vm.backend_vm_id) |
|
490 |
|
|
491 |
|
|
492 |
def vm_exists_in_backend(vm): |
|
493 |
try: |
|
494 |
get_instance_info(vm) |
|
495 |
return True |
|
496 |
except GanetiApiError as e: |
|
497 |
if e.code == 404: |
|
498 |
return False |
|
499 |
raise e |
|
500 |
|
|
501 |
|
|
502 |
def get_network_info(backend_network): |
|
503 |
with pooled_rapi_client(backend_network) as client: |
|
504 |
return client.GetNetwork(backend_network.network.backend_id) |
|
505 |
|
|
506 |
|
|
507 |
def network_exists_in_backend(backend_network): |
|
508 |
try: |
|
509 |
get_network_info(backend_network) |
|
510 |
return True |
|
511 |
except GanetiApiError as e: |
|
512 |
if e.code == 404: |
|
513 |
return False |
|
493 | 514 |
|
494 | 515 |
|
495 | 516 |
def create_network(network, backend, connect=True): |
b/snf-cyclades-app/synnefo/logic/tests.py | ||
---|---|---|
44 | 44 |
from synnefo.logic.callbacks import (update_db, update_network, |
45 | 45 |
update_build_progress) |
46 | 46 |
from snf_django.utils.testing import mocked_quotaholder |
47 |
from synnefo.logic.rapi import GanetiApiError |
|
47 | 48 |
|
48 | 49 |
now = datetime.now |
49 | 50 |
from time import time |
... | ... | |
145 | 146 |
# Check that nics are deleted |
146 | 147 |
self.assertFalse(db_vm.nics.all()) |
147 | 148 |
|
149 |
@patch("synnefo.logic.rapi_pool.GanetiRapiClient") |
|
150 |
def test_remove_error(self, rapi, client): |
|
151 |
vm = mfactory.VirtualMachineFactory() |
|
152 |
# Also create a NIC |
|
153 |
msg = self.create_msg(operation='OP_INSTANCE_REMOVE', |
|
154 |
status="error", |
|
155 |
instance=vm.backend_vm_id) |
|
156 |
rapi().GetInstance.return_value = {} |
|
157 |
update_db(client, msg) |
|
158 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
159 |
self.assertFalse(db_vm.deleted) |
|
160 |
|
|
161 |
rapi().GetInstance.side_effect = GanetiApiError(msg="msg", |
|
162 |
code=503) |
|
163 |
update_db(client, msg) |
|
164 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
165 |
self.assertFalse(db_vm.deleted) |
|
166 |
|
|
167 |
rapi().GetInstance.side_effect = GanetiApiError(msg="msg", |
|
168 |
code=404) |
|
169 |
with mocked_quotaholder(): |
|
170 |
update_db(client, msg) |
|
171 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
172 |
self.assertTrue(db_vm.deleted) |
|
173 |
|
|
148 | 174 |
def test_create(self, client): |
149 | 175 |
vm = mfactory.VirtualMachineFactory() |
150 | 176 |
msg = self.create_msg(operation='OP_INSTANCE_CREATE', |
... | ... | |
418 | 444 |
pool = MacPrefixPoolTable.get_pool() |
419 | 445 |
self.assertTrue(pool.is_available(net.mac_prefix)) |
420 | 446 |
|
447 |
@patch("synnefo.logic.rapi_pool.GanetiRapiClient") |
|
448 |
def test_remove_error(self, rapi, client): |
|
449 |
mfactory.MacPrefixPoolTableFactory() |
|
450 |
mfactory.BridgePoolTableFactory() |
|
451 |
bn = mfactory.BackendNetworkFactory(operstate='ACTIVE') |
|
452 |
network = bn.network |
|
453 |
msg = self.create_msg(operation='OP_NETWORK_REMOVE', |
|
454 |
network=network.backend_id, |
|
455 |
status="error", |
|
456 |
cluster=bn.backend.clustername) |
|
457 |
rapi().GetNetwork.return_value = {} |
|
458 |
update_network(client, msg) |
|
459 |
bn = BackendNetwork.objects.get(id=bn.id) |
|
460 |
self.assertNotEqual(bn.operstate, "DELETED") |
|
461 |
rapi().GetNetwork.side_effect = GanetiApiError(msg="foo", code=404) |
|
462 |
with mocked_quotaholder(): |
|
463 |
update_network(client, msg) |
|
464 |
bn = BackendNetwork.objects.get(id=bn.id) |
|
465 |
self.assertEqual(bn.operstate, "DELETED") |
|
466 |
|
|
421 | 467 |
def test_remove_offline_backend(self, client): |
422 | 468 |
"""Test network removing when a backend is offline""" |
423 | 469 |
mfactory.BridgePoolTableFactory() |
Also available in: Unified diff