Commit db8afb92 authored by Christos Stavrakakis's avatar Christos Stavrakakis

cyclades: Delete volumes after quota handling

When processing an 'OP_INSTANCE_REMOVE' job, delete the volumes after
handling of the quotas. Otherwise, the quota mechanism will see no
active volumes and the quotas will get unsynchronized.
parent a151e001
......@@ -173,6 +173,7 @@ def process_op_status(vm, etime, jobid, opcode, status, logmsg, nics=None,
disk_changes = update_vm_disks(vm, disks, etime)
job_fields["disks"] = disk_changes
vm_deleted = False
# Special case: if OP_INSTANCE_CREATE fails --> ERROR
if opcode == 'OP_INSTANCE_CREATE' and status in (rapi.JOB_STATUS_CANCELED,
rapi.JOB_STATUS_ERROR):
......@@ -187,9 +188,7 @@ def process_op_status(vm, etime, jobid, opcode, status, logmsg, nics=None,
# See ticket #799 for all the details.
if (status == rapi.JOB_STATUS_SUCCESS or
(status == rapi.JOB_STATUS_ERROR and not vm_exists_in_backend(vm))):
# server has been deleted, so delete the server's attachments
vm.volumes.all().update(deleted=True, status="DELETED",
machine=None)
vm_deleted = True
for nic in vm.nics.all():
# but first release the IP
remove_nic_ips(nic)
......@@ -210,6 +209,9 @@ def process_op_status(vm, etime, jobid, opcode, status, logmsg, nics=None,
# Update VM's state and flavor after handling of quotas, since computation
# of quotas depends on these attributes
if vm_deleted:
vm.volumes.filter(deleted=False).update(deleted=True, status="DELETED",
machine=None)
if new_operstate is not None:
vm.operstate = new_operstate
if new_flavor is not None:
......
......@@ -119,14 +119,16 @@ class UpdateDBTest(TestCase):
self.assertEqual(db_vm.operstate, 'STARTED')
def test_remove(self, client):
vm = mfactory.VirtualMachineFactory()
vm = mfactory.VirtualMachineFactory(flavor__cpu=1, flavor__ram=128)
mfactory.VolumeFactory(userid=vm.userid, machine=vm, size=1)
mfactory.VolumeFactory(userid=vm.userid, machine=vm, size=3)
# Also create a NIC
ip = mfactory.IPv4AddressFactory(nic__machine=vm)
nic = ip.nic
nic.network.get_ip_pools()[0].reserve(nic.ipv4_address)
msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
instance=vm.backend_vm_id)
with mocked_quotaholder():
with mocked_quotaholder() as m:
update_db(client, msg)
self.assertTrue(client.basic_ack.called)
db_vm = VirtualMachine.objects.get(id=vm.id)
......@@ -135,6 +137,17 @@ class UpdateDBTest(TestCase):
# Check that nics are deleted
self.assertFalse(db_vm.nics.all())
self.assertTrue(nic.network.get_ip_pools()[0].is_available(ip.address))
# Check that volumes are deleted
self.assertFalse(db_vm.volumes.filter(deleted=False))
# Check quotas
name, args, kwargs = m.mock_calls[0]
for (userid, res), value in args[1].items():
if res == 'cyclades.disk':
self.assertEqual(value, -4 << 30)
elif res == 'cyclades.cpu':
self.assertEqual(value, -1)
elif res == 'cyclades.ram':
self.assertEqual(value, -128 << 20)
vm2 = mfactory.VirtualMachineFactory()
fp1 = mfactory.IPv4AddressFactory(nic__machine=vm2, floating_ip=True,
network__floating_ip_pool=True)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment