Commit 898183fd authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

Do not allow any API action on suspended VMs

Do not allow any modification of any administratively suspended VM through the
API.
parent de1c02ee
......@@ -286,7 +286,6 @@ def get_console(request, vm, args):
@server_action('firewallProfile')
@transaction.commit_on_success
def set_firewall_profile(request, vm, args):
# Normal Response Code: 200
# Error Response Codes: computeFault (400, 500),
......@@ -318,17 +317,14 @@ def add(request, net, args):
# itemNotFound (404),
# overLimit (413)
if net.state != 'ACTIVE':
raise ServiceUnavailable('Network not active yet')
server_id = args.get('serverRef', None)
if not server_id:
raise BadRequest('Malformed Request.')
vm = get_vm(server_id, request.user_uniq)
log.info("Connect VM %s to Network %s", vm, net)
net = Network.objects.get(id=net.id)
if net.state != 'ACTIVE':
raise ServiceUnavailable('Network not active yet')
vm = get_vm(server_id, request.user_uniq, non_suspended=True)
address = None
if net.dhcp:
......@@ -366,10 +362,11 @@ def remove(request, net, args):
if not server_id or not nic_index:
raise BadRequest('Malformed Request.')
vm = get_vm(server_id, request.user_uniq)
vm = get_vm(server_id, request.user_uniq, non_suspended=True)
nic = get_nic_from_index(vm, nic_index)
log.info("Disconnect VM %s NIC %s", vm, str(nic.index))
log.info("Removing NIC %s from VM %s", str(nic.index), vm)
if nic.dirty:
raise BuildInProgress('Machine is busy.')
......
......@@ -304,10 +304,9 @@ def network_action(request, network_id):
if net.deleted:
raise Network.DeletedError
key = req.keys()[0]
val = req[key]
try:
key = req.keys()[0]
val = req[key]
assert isinstance(val, dict)
return network_actions[key](request, net, req[key])
except KeyError:
......
......@@ -131,6 +131,7 @@ def vm_to_dict(vm, detail=False):
d['created'] = util.isoformat(vm.created)
d['flavorRef'] = vm.flavor.id
d['imageRef'] = vm.imageid
d['suspended'] = vm.suspended
metadata = dict((m.meta_key, m.meta_value) for m in vm.metadata.all())
if metadata:
......@@ -418,7 +419,7 @@ def update_server_name(request, server_id):
except (TypeError, KeyError):
raise faults.BadRequest("Malformed request")
vm = util.get_vm(server_id, request.user_uniq)
vm = util.get_vm(server_id, request.user_uniq, non_suspended=True)
vm.name = name
vm.save()
......@@ -438,7 +439,7 @@ def delete_server(request, server_id):
# overLimit (413)
log.info('delete_server %s', server_id)
vm = util.get_vm(server_id, request.user_uniq)
vm = util.get_vm(server_id, request.user_uniq, non_suspended=True)
delete_instance(vm)
return HttpResponse(status=204)
......@@ -447,16 +448,19 @@ def delete_server(request, server_id):
def server_action(request, server_id):
req = util.get_request_dict(request)
log.debug('server_action %s %s', server_id, req)
vm = util.get_vm(server_id, request.user_uniq)
if len(req) != 1:
raise faults.BadRequest("Malformed request")
key = req.keys()[0]
val = req[key]
# Do not allow any action on deleted or suspended VMs
vm = util.get_vm(server_id, request.user_uniq, non_deleted=True,
non_suspended=True)
try:
key = req.keys()[0]
val = req[key]
assert isinstance(val, dict)
return server_actions[key](request, vm, req[key])
return server_actions[key](request, vm, val)
except KeyError:
raise faults.BadRequest("Unknown action")
except AssertionError:
......@@ -536,7 +540,7 @@ def update_metadata(request, server_id):
req = util.get_request_dict(request)
log.info('update_server_metadata %s %s', server_id, req)
vm = util.get_vm(server_id, request.user_uniq)
vm = util.get_vm(server_id, request.user_uniq, non_suspended=True)
try:
metadata = req['metadata']
assert isinstance(metadata, dict)
......@@ -585,7 +589,7 @@ def create_metadata_item(request, server_id, key):
req = util.get_request_dict(request)
log.info('create_server_metadata_item %s %s %s', server_id, key, req)
vm = util.get_vm(server_id, request.user_uniq)
vm = util.get_vm(server_id, request.user_uniq, non_suspended=True)
try:
metadict = req['meta']
assert isinstance(metadict, dict)
......@@ -619,7 +623,7 @@ def delete_metadata_item(request, server_id, key):
# overLimit (413),
log.info('delete_server_metadata_item %s %s', server_id, key)
vm = util.get_vm(server_id, request.user_uniq)
vm = util.get_vm(server_id, request.user_uniq, non_suspended=True)
meta = util.get_vm_meta(vm, key)
meta.delete()
vm.save()
......
......@@ -157,18 +157,21 @@ def encrypt(plaintext):
return b64encode(enc)
def get_vm(server_id, user_id):
"""Return a VirtualMachine instance or raise ItemNotFound."""
def get_vm(server_id, user_id, non_deleted=False, non_suspended=False):
"""Find a VirtualMachine instance based on ID and owner."""
try:
server_id = int(server_id)
return VirtualMachine.objects.get(id=server_id, userid=user_id)
vm = VirtualMachine.objects.get(id=server_id, userid=user_id)
if non_deleted and vm.deleted:
raise VirtualMachine.DeletedError
if non_suspended and vm.suspended:
raise Unauthorized("Administratively Suspended VM")
except ValueError:
raise BadRequest('Invalid server ID.')
except VirtualMachine.DoesNotExist:
raise ItemNotFound('Server not found.')
def get_vm_meta(vm, key):
"""Return a VirtualMachineMetadata instance or raise ItemNotFound."""
......
......@@ -236,7 +236,7 @@ def start_action(vm, action):
if not action in [x[0] for x in VirtualMachine.ACTIONS]:
raise VirtualMachine.InvalidActionError(action)
# No actions to deleted and no actions beside destroy to suspended VMs
# No actions to deleted VMs
if vm.deleted:
raise VirtualMachine.DeletedError
......@@ -250,21 +250,6 @@ def start_action(vm, action):
vm.backendjobstatus = None
vm.backendlogmsg = None
# Update the relevant flags if the VM is being suspended or destroyed.
# Do not set the deleted flag here, see ticket #721.
#
# The deleted flag is set asynchronously, when an OP_INSTANCE_REMOVE
# completes successfully. Hence, a server may be visible for some time
# after a DELETE /servers/id returns HTTP 204.
#
if action == "DESTROY":
# vm.deleted = True
pass
elif action == "SUSPEND":
vm.suspended = True
elif action == "START":
vm.suspended = False
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