Commit 256039b8 authored by Marios Kogias's avatar Marios Kogias
Browse files

cyclades: Add /ports api call

parent 898a6d9d
from django.conf import settings
from django.conf.urls import patterns
from django.http import HttpResponse
from django.utils import simplejson as json
from django.db import transaction
from django.db.models import Q
from synnefo.db.pools import EmptyPool
from synnefo.db.utils import validate_mac
from django.conf import settings
from snf_django.lib import api
from snf_django.lib.api import utils
from synnefo.logic import backend
from django.template.loader import render_to_string
from synnefo.api import util
from synnefo.db.models import NetworkInterface, SecurityGroup, IPAddress
from logging import getLogger
log = getLogger(__name__)
urlpatterns = patterns(
'synnefo.api.ports',
(r'^(?:/|.json|.xml)?$', 'demux'),
(r'^/([-\w]+)(?:/|.json|.xml)?$', 'port_demux'))
def demux(request):
if request.method == 'GET':
#return HttpResponse("list ports")
return list_ports(request)
elif request.method == 'POST':
return create_port(request)
#return HttpResponse("create port")
else:
return api.api_method_not_allowed(request)
def port_demux(request, offset):
if request.method == 'GET':
#return HttpResponse("get single port")
return get_port(request, offset)
elif request.method == 'DELETE':
#return HttpResponse("delete port")
return delete_port(request, offset)
elif request.method == 'PUT':
#return HttpResponse("put port")
return update_port(request, offset)
else:
return api.api_method_not_allowed(request)
@api.api_method(http_method='GET', user_required=True, logger=log)
def list_ports(request, detail=False):
log.debug('list_ports detail=%s', detail)
user_ports = NetworkInterface.objects.filter(
network__userid=request.user_uniq)
ports = [port_to_dict(port, detail)
for port in user_ports.order_by('id')]
if request.serialization == 'xml':
data = render_to_string('list_networks.xml', {
"ports": ports})
else:
data = json.dumps({'ports': ports})
return HttpResponse(data, status=200)
@api.api_method(http_method='GET', user_required=True, logger=log)
def get_port(request, port_id):
log.debug('get_port_details %s', port_id)
port = util.get_port(port_id, request.user_uniq)
portdict = port_to_dict(port)
return render_port(request, portdict)
@api.api_method(http_method='DELETE', user_required=True, logger=log)
@transaction.commit_on_success
def delete_port(request, port_id):
log.info('delete_port %s', port_id)
port = util.get_port(port_id, request.user_uniq, for_update=True)
'''
FIXME delete the port
skip the backend part...
release the ips associated with the port
'''
return HttpResponse(status=204)
@api.api_method(http_method='PUT', user_required=True, logger=log)
def update_port(request, port_id):
'''
You can update only name, security_groups
'''
port = util.get_port(port_id, request.user_uniq, for_update=True)
info = utils.get_request_dict(request)
try:
info = info["port"]
except KeyError:
raise api.faults.BadRequest("Malformed request")
try:
name = info['name']
port.name = name
except KeyError:
pass
sg_list = []
try:
s_groups = info['security_groups']
#validate security groups
# like get security group from db
for gid in s_groups:
try:
sg = SecurityGroup.objects.get(id=int(gid))
sg_list.append(sg)
except (ValueError, SecurityGroup.DoesNotExist):
raise api.faults.ItemNotFound("Not valid security group")
#clear the old security groups
port.security_groups.clear()
#add the new groups
for group in sg_list:
port.security_groups.add(group)
except KeyError:
pass
port.save()
portdict = port_to_dict(port)
return render_port(request, portdict, 200)
@api.api_method(http_method='POST', user_required=True, logger=log)
@transaction.commit_manually
def create_port(request):
'''
'''
user_id = request.user_uniq
req = utils.get_request_dict(request)
log.info('create_port %s', req)
try:
try:
info = req['port']
net_id = info['network_id']
dev_id = info['device_id']
except KeyError:
raise api.faults.BadRequest("Malformed request")
net = util.get_network(net_id, request.user_uniq)
vm = util.get_vm(dev_id, request.user_uniq)
try:
name = info['name']
except KeyError:
name = "random_name"
sg_list = []
try:
s_groups = info['security_groups']
#validate security groups
# like get security group from db
for gid in s_groups:
try:
sg = SecurityGroup.objects.get(id=int(gid))
sg_list.append(sg)
except (ValueError, SecurityGroup.DoesNotExist):
raise api.faults.ItemNotFound("Not valid security group")
except KeyError:
pass
#create the port
new_port = NetworkInterface.objects.create(name=name,
network=net,
machine=vm,
device_owner="vm",
state="BUILDING")
#add the security groups
new_port.security_groups.add(*sg_list)
#add every to every subnet of the network
for subn in net.subnets.all():
IPAddress.objects.create(subnet=subn,
network=net,
nic=new_port,
userid=user_id,
address="192.168.0."+str(subn.id) # FIXME
)
except:
transaction.rollback()
log.info("roll")
raise
else:
transaction.commit()
log.info("commit")
portdict = port_to_dict(new_port)
response = render_port(request, portdict, status=201)
return response
#util functions
def port_to_dict(port, detail=True):
d = {'id': str(port.id), 'name': port.name}
if detail:
d['user_id'] = port.network.userid
d['tenant_id'] = port.network.userid
d['device_id'] = str(port.machine.id)
d['admin_state_up'] = True
d['mac_address'] = port.mac
d['status'] = port.state
d['device_owner'] = port.device_owner
d['network_id'] = str(port.network.id)
d['fixed_ips'] = []
for ip in port.ips.all():
d['fixed_ips'].append({"ip_address": ip.address,
"subnet": ip.subnet.id})
d['security_groups'] = [str(sg.id)
for sg in port.security_groups.all()]
return d
def render_port(request, portdict, status=200):
if request.serialization == 'xml':
data = render_to_string('network.xml', {'port': portdict})
else:
data = json.dumps({'port': portdict})
return HttpResponse(data, status=status)
......@@ -34,6 +34,7 @@
# Import TestCases
from .servers import *
from .networks import *
from .ports import *
from .flavors import *
from .images import *
from .versions import *
......
......@@ -40,7 +40,6 @@ class NetworkTest(BaseAPITest):
test_net = dbmf.NetworkFactory.create()
url = join_urls(NETWORKS_URL, str(test_net.id))
response = self.get(url, user=test_net.userid)
print response.content
# validate response
res = json.loads(response.content)
net = res['network']
......
from snf_django.utils.testing import BaseAPITest
from django.utils import simplejson as json
from synnefo.cyclades_settings import cyclades_services
from synnefo.lib.services import get_service_path
from synnefo.lib import join_urls
import json
import synnefo.db.models_factory as dbmf
COMPUTE_URL = get_service_path(cyclades_services, 'compute',
version='v2.0')
PORTS_URL = join_urls(COMPUTE_URL, "ports/")
class PortTest(BaseAPITest):
def test_get_ports(self):
url = join_urls(PORTS_URL)
response = self.get(url)
self.assertEqual(response.status_code, 200)
ports = json.loads(response.content)
self.assertEqual(ports, {"ports": []})
def test_get_port_unfound(self):
url = join_urls(PORTS_URL, "123")
response = self.get(url)
self.assertEqual(response.status_code, 404)
def test_get_port(self):
nic = dbmf.NetworkInterfaceFactory.create()
url = join_urls(PORTS_URL, str(nic.id))
response = self.get(url, user=nic.network.userid)
self.assertEqual(response.status_code, 200)
def test_delete_port(self):
nic = dbmf.NetworkInterfaceFactory.create(device_owner='vm')
url = join_urls(PORTS_URL, str(nic.id))
response = self.delete(url, user=nic.network.userid)
self.assertEqual(response.status_code, 204)
def test_update_port_name(self):
nic = dbmf.NetworkInterfaceFactory.create(device_owner='vm')
url = join_urls(PORTS_URL, str(nic.id))
request = {'port': {"name": "test-name"}}
response = self.put(url, params=json.dumps(request),
user=nic.network.userid)
self.assertEqual(response.status_code, 200)
res = json.loads(response.content)
self.assertEqual(res['port']['name'], "test-name")
def test_update_port_sg_unfound(self):
sg1 = dbmf.SecurityGroupFactory.create()
nic =dbmf.NetworkInterfaceFactory.create(device_owner='vm')
nic.security_groups.add(sg1)
nic.save()
url = join_urls(PORTS_URL, str(nic.id))
request = {'port': {"security_groups": ["123"]}}
response = self.put(url, params=json.dumps(request),
user=nic.network.userid)
self.assertEqual(response.status_code, 404)
def test_update_port_sg(self):
sg1 = dbmf.SecurityGroupFactory.create()
sg2 = dbmf.SecurityGroupFactory.create()
sg3 = dbmf.SecurityGroupFactory.create()
nic = dbmf.NetworkInterfaceFactory.create(device_owner='vm')
nic.security_groups.add(sg1)
nic.save()
url = join_urls(PORTS_URL, str(nic.id))
request = {'port': {"security_groups": [str(sg2.id), str(sg3.id)]}}
response = self.put(url, params=json.dumps(request),
user=nic.network.userid)
res = json.loads(response.content)
self.assertEqual(res['port']['security_groups'],
[str(sg2.id), str(sg3.id)])
def test_create_port_no_network(self):
request = {
"port": {
"device_id": "123",
"name": "port1",
"network_id": "123"
}
}
response = self.post(PORTS_URL, params=json.dumps(request))
self.assertEqual(response.status_code, 404)
def test_create_port(self):
net = dbmf.NetworkFactory.create()
subnet1 = dbmf.IPv4SubnetFactory.create(network=net)
subnet2 = dbmf.IPv6SubnetFactory.create(network=net)
sg1 = dbmf.SecurityGroupFactory.create()
sg2 = dbmf.SecurityGroupFactory.create()
vm = dbmf.VirtualMachineFactory.create(userid=net.userid)
request = {
"port": {
"name": "port1",
"network_id": str(net.id),
"device_id": str(vm.id),
"security_groups": [str(sg1.id), str(sg2.id)]
}
}
response = self.post(PORTS_URL, params=json.dumps(request),
user=net.userid)
self.assertEqual(response.status_code, 201)
......@@ -35,7 +35,7 @@ from django.conf.urls import include, patterns
from snf_django.lib.api import api_endpoint_not_found
from synnefo.api import (servers, flavors, images, networks, extensions,
floating_ips)
ports, floating_ips)
from synnefo.api.versions import versions_list, version_details
......@@ -48,6 +48,7 @@ api20_patterns = patterns(
(r'^flavors', include(flavors)),
(r'^images', include(images)),
(r'^networks', include(networks)),
(r'^ports', include(ports)),
(r'^extensions', include(extensions)),
(r'^os-floating-ips', include(floating_ips.ips_urlpatterns)),
(r'^os-floating-ip-pools', include(floating_ips.pools_urlpatterns)),
......
......@@ -226,7 +226,6 @@ def get_network(network_id, user_id, for_update=False, non_deleted=False):
def get_network(network_id, user_id, public=False, for_update=False):
"""
Return a Network instance or raise ItemNotFound.
This is the same as util.get_network
"""
try:
objects = Network.objects
......@@ -238,6 +237,23 @@ def get_network(network_id, user_id, public=False, for_update=False):
except (ValueError, Network.DoesNotExist):
raise faults.ItemNotFound('Network not found.')
def get_port(port_id, user_id, for_update=False):
"""
Return a NetworkInteface instance or raise ItemNotFound.
"""
try:
objects = NetworkInterface.objects
if for_update:
objects = objects.select_for_update()
port = objects.get(network__userid=user_id, id=port_id)
if (port.device_owner != "vm") and for_update:
raise api.faults.BadRequest('Can not update non vm port')
return port
except (ValueError, NetworkInterface.DoesNotExist):
raise faults.ItemNotFound('Port not found.')
def get_floating_ip(user_id, ipv4, for_update=False):
try:
......
......@@ -239,6 +239,12 @@ class FloatingIPFactory(IPv4AddressFactory):
floating_ip = True
class SecurityGroupFactory(factory.DjangoModelFactory):
FACTORY_FOR = models.SecurityGroup
name = factory.LazyAttribute(lambda self: random_string(30))
class BridgePoolTableFactory(factory.DjangoModelFactory):
FACTORY_FOR = models.BridgePoolTable
......
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