Commit 1a81710f authored by Stavros Sachtouris's avatar Stavros Sachtouris Committed by Christos Stavrakakis
Browse files

Update servers/networks responses for new API

- Reponses for servers and netowrks details (list or solo) are now
consistent to recent backend changes.
- Methods get_nic_from_index and construct_nic_id have been created
- Syntax for nic removal from network/vm has been adjusted
parent 59ffcc20
......@@ -39,8 +39,8 @@ from django.http import HttpResponse
from django.template.loader import render_to_string
from django.utils import simplejson as json
from synnefo.api.faults import BadRequest, ServiceUnavailable
from synnefo.api.util import random_password, get_vm
from synnefo.api.faults import BadRequest, ServiceUnavailable, ItemNotFound
from synnefo.api.util import random_password, get_vm, get_nic_from_index
from synnefo.db.models import NetworkInterface
from synnefo.logic import backend
from synnefo.logic.utils import get_rsapi_state
......@@ -316,9 +316,15 @@ def remove(request, net, args):
# itemNotFound (404),
# overLimit (413)
server_id = args.get('serverRef', None)
if not server_id:
try: #attachment string: nic-<vm-id>-<nic-index>
server_id = args.get('attachment', None).split('-')[1]
nic_index = args.get('attachment', None).split('-')[2]
except IndexError:
raise BadRequest('Malformed Network Interface Id')
if not server_id or not nic_index:
raise BadRequest('Malformed Request.')
vm = get_vm(server_id, request.user_uniq)
backend.disconnect_from_network(vm, net)
nic = get_nic_from_index(vm, nic_index)
backend.disconnect_nic_from_vm(vm, nic)
return HttpResponse(status=202)
......@@ -41,4 +41,4 @@ def not_found(request):
@api_method()
def method_not_allowed(request):
raise BadRequest('Method not allowed.')
raise BadRequest('Method not allowed')
......@@ -62,3 +62,6 @@ class OverLimit(Fault):
class ServiceUnavailable(Fault):
code = 503
class BadMediaType(Fault):
code = 415
......@@ -84,11 +84,16 @@ def network_to_dict(network, user_id, detail=True):
network_id = str(network.id) if not network.public else 'public'
d = {'id': network_id, 'name': network.name}
if detail:
d['cidr'] = network.subnet
d['gateway'] = network.gateway
d['dhcp'] = network.dhcp
d['type'] = network.type
d['updated'] = util.isoformat(network.updated)
d['created'] = util.isoformat(network.created)
d['status'] = network.state
servers = [vm.id for vm in network.machines.filter(userid=user_id)]
d['servers'] = {'values': servers}
attachments = [util.construct_nic_id(nic) for nic in network.nics.filter(machine__userid= user_id)]
d['attachments'] = {'values':attachments}
return d
......
......@@ -107,19 +107,15 @@ def metadata_item_demux(request, server_id, key):
else:
return method_not_allowed(request)
def nic_to_dict(nic):
network = nic.network
network_id = str(network.id) if not network.public else 'public'
d = {'id': network_id, 'name': network.name, 'mac': nic.mac}
ipv4 = nic.ipv4 if nic.ipv4 else None
ipv6 = nic.ipv6 if nic.ipv6 else None
d = {'id': util.construct_nic_id(nic), 'network_id': network_id, 'mac_address': nic.mac, 'ipv4': ipv4, 'ipv6': ipv6}
if nic.firewall_profile:
d['firewallProfile'] = nic.firewall_profile
if nic.ipv4 or nic.ipv6:
d['values'] = []
if nic.ipv4:
d['values'].append({'version': 4, 'addr': nic.ipv4})
if nic.ipv6:
d['values'].append({'version': 6, 'addr': nic.ipv6})
return d
......@@ -139,9 +135,9 @@ def vm_to_dict(vm, detail=False):
if metadata:
d['metadata'] = {'values': metadata}
addresses = [nic_to_dict(nic) for nic in vm.nics.all()]
if addresses:
d['addresses'] = {'values': addresses}
attachments = [nic_to_dict(nic) for nic in vm.nics.all()]
if attachments:
d['attachments'] = {'values': attachments}
return d
......
......@@ -47,12 +47,78 @@ from synnefo.db.models import *
from synnefo.logic.utils import get_rsapi_state
import mock
from synnefo.lib import astakos
from contextlib import contextmanager
# This is a hack to override astakos
# The global variable ASTAKOS_PATCHED_USER keeps the name of
# a dummy user that we provide through replacement of the
# corresponding astakos function with a dummy function.
ASTAKOS_PATCHED_USER = "user"
@contextmanager
def astakos_user(user):
"""
Context manager to mock astakos response.
usage:
with astakos_user("user@user.com"):
.... make api calls .... get_user will act as user@user.com requested the api.
"""
from synnefo.lib import astakos
orig_method = astakos.get_user
global ASTAKOS_PATCHED_USER
ASTAKOS_PATCHED_USER = user
def dummy_get_user(request, *args, **kwargs):
global ASTAKOS_PATCHED_USER
request.user = {'username': ASTAKOS_PATCHED_USER, 'groups': []}
request.user_uniq = ASTAKOS_PATCHED_USER
astakos.get_user = dummy_get_user
yield
astakos.get_user = orig_method
class AaiClient(Client):
def request(self, **request):
request['HTTP_X_AUTH_TOKEN'] = '0000'
return super(AaiClient, self).request(**request)
class NetworksTest(TestCase):
fixtures = ['network_test_data']
def test_attachments_list(self):
with astakos_user("admin@adminland.com"):
r = self.client.get("/api/v1.1/networks")
data = json.loads(r.content)
self.assertEqual(data["networks"]["values"][1]["name"], "network4admin")
#import pdb; pdb.set_trace()
self.assertEqual(len(data["networks"]["values"]), 2)
with astakos_user("user1@userland.com"):
r = self.client.get("/api/v1.1/networks")
data = json.loads(r.content)
self.assertEqual(data["networks"]["values"][1]["name"], "network4user1")
#import pdb; pdb.set_trace()
self.assertEqual(len(data["networks"]["values"]), 2)
def test_create_network(self):
with astakos_user("admin@adminland.com"):
r = self.client.post("/api/v1.1/networks")
class ServersTest(TestCase):
fixtures = ['network_test_data']
def test_attachments_list(self):
with astakos_user("admin@adminland.com"):
r = self.client.get("/api/v1.1/servers")
data = json.loads(r.content)
self.assertEqual(data["servers"]["values"][0]["id"], 1001)
self.assertEqual(len(data["servers"]["values"]), 1)
r = self.client.get("/api/v1.1/servers/1001")
class TestQuota(TestCase):
......@@ -636,13 +702,14 @@ class BaseTestCase(TestCase):
return reply['networks']['values']
def create_network(self, name):
path = '/api/v1.1/networks'
data = json.dumps({'network': {'name': name}})
response = self.client.post(path, data, content_type='application/json')
self.assertEqual(response.status_code, 202)
reply = json.loads(response.content)
self.assertEqual(reply.keys(), ['network'])
return reply
with astakos_user("admin@adminland.com"):
path = '/api/v1.1/networks'
data = json.dumps({'network': {'name': name}})
response = self.client.post(path, data, content_type='application/json')
self.assertEqual(response.status_code, 202)
reply = json.loads(response.content)
self.assertEqual(reply.keys(), ['network'])
return reply
def get_network_details(self, network_id):
path = '/api/v1.1/networks/%s' % network_id
......
......@@ -55,7 +55,7 @@ from django.utils import simplejson as json
from django.utils.cache import add_never_cache_headers
from synnefo.api.faults import (Fault, BadRequest, BuildInProgress,
ItemNotFound, ServiceUnavailable, Unauthorized)
ItemNotFound, ServiceUnavailable, Unauthorized, BadMediaType)
from synnefo.db.models import (Flavor, VirtualMachine, VirtualMachineMetadata,
Network, NetworkInterface)
from synnefo.lib.astakos import get_user
......@@ -214,6 +214,18 @@ def get_nic(machine, network):
except NetworkInterface.DoesNotExist:
raise ItemNotFound('Server not connected to this network.')
def get_nic_from_index(vm, nic_index):
"""Returns the nic_index-th nic of a vm
Error Response Codes: itemNotFound (404), badMediaType (415)
"""
matching_nics = vm.nics.filter(index=nic_index)
matching_nics_len = len(matching_nics)
if matching_nics_len < 1:
raise ItemNotFound('NIC not found on VM')
elif matching_nics_len > 1:
raise BadMediaType('NIC index conflict on VM')
nic = matching_nics[0]
return nic
def get_request_dict(request):
"""Returns data sent by the client as a python dict."""
......@@ -321,7 +333,7 @@ def api_method(http_method=None, atom_allowed=False):
raise Unauthorized('No user found.')
if http_method and request.method != http_method:
raise BadRequest('Method not allowed.')
resp = func(request, *args, **kwargs)
update_response_headers(request, resp)
return resp
......@@ -339,3 +351,6 @@ def api_method(http_method=None, atom_allowed=False):
return render_fault(request, fault)
return wrapper
return decorator
def construct_nic_id(nic):
return "-".join(["nic", unicode(nic.machine.id), unicode(nic.index)])
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