Commit 4a8ac60f authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

cyclades: Fix wrong quotas when creating server

Catch exception when talking to Ganeti inside 'server_command',
otherwise the pending commission will be rejected. Also, accept the
commission in case of build, because the VM will be created in DB.
parent fb0b3f29
......@@ -69,11 +69,14 @@ def handle_vm_quotas(vm, job_id, job_opcode, job_status, job_fields):
"""
if job_status not in ["success", "error", "canceled"]:
return
return vm
# Check successful completion of a job will trigger any quotable change in
# the VM state.
action = utils.get_action_from_opcode(job_opcode, job_fields)
if action == "BUILD":
# Quotas for new VMs are automatically accepted by the API
return vm
commission_info = quotas.get_commission_info(vm, action=action,
action_fields=job_fields)
......@@ -83,7 +86,7 @@ def handle_vm_quotas(vm, job_id, job_opcode, job_status, job_fields):
# if fails, must be accepted, as the user must manually remove the
# failed server
serial = vm.serial
if job_status == "success" or job_opcode == "OP_INSTANCE_CREATE":
if job_status == "success":
quotas.accept_serial(serial)
elif job_status in ["error", "canceled"]:
log.debug("Job %s failed. Rejecting related serial %s", job_id,
......
......@@ -109,6 +109,13 @@ def server_command(action):
transaction.commit()
raise
if action == "BUILD" and vm.serial is not None:
# XXX: Special case for server creation: we must accept the
# commission because the VM has been stored in DB. Also, if
# communication with Ganeti fails, the job will never reach
# Ganeti, and the commission will never be resolved.
quotas.accept_serial(vm.serial)
log.info("user: %s, vm: %s, action: %s, job_id: %s, serial: %s",
user_id, vm.id, action, job_id, vm.serial)
......@@ -166,15 +173,8 @@ def create(userid, name, password, flavor, image, metadata={},
meta_value=val,
vm=vm)
try:
# Create the server in Ganeti.
create_server(vm, nics, flavor, image, personality, password)
except:
log.exception("Failed create instance '%s'", vm)
vm.operstate = "ERROR"
vm.backendlogmsg = "Failed to send job to Ganeti."
vm.save()
vm.nics.all().update(state="ERROR")
# Create the server in Ganeti.
create_server(vm, nics, flavor, image, personality, password)
return vm
......@@ -212,7 +212,16 @@ def create_server(vm, nics, flavor, image, personality, password):
'img_properties': json.dumps(image['metadata']),
})
# send job to Ganeti
jobID = backend.create_instance(vm, nics, flavor, image)
try:
jobID = backend.create_instance(vm, nics, flavor, image)
except:
log.exception("Failed create instance '%s'", vm)
jobID = None
vm.operstate = "ERROR"
vm.backendlogmsg = "Failed to send job to Ganeti."
vm.save()
vm.nics.all().update(state="ERROR")
# At this point the job is enqueued in the Ganeti backend
vm.backendjobid = jobID
vm.save()
......
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