Commit 6a449eea authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

cyclades: Optimize network related DB queries

Use 'prefetch_related' and 'select_related' to optimize DB queries.
parent 36ea7dda
......@@ -87,13 +87,15 @@ def list_networks(request, detail=False):
user_networks = Network.objects.filter(Q(userid=request.user_uniq) |
Q(public=True))\
.prefetch_related("subnets")
.order_by('id')
if detail:
user_networks = user_networks.prefetch_related("subnets")
user_networks = api.utils.filter_modified_since(request,
objects=user_networks)
network_dicts = [network_to_dict(network, detail)
for network in user_networks.order_by('id')]
for network in user_networks]
if request.serialization == 'xml':
data = render_to_string('list_networks.xml', {
......@@ -167,6 +169,12 @@ def network_to_dict(network, detail=True):
d = {'id': str(network.id), 'name': network.name}
d['links'] = util.network_to_links(network.id)
if detail:
# Loop over subnets. Do not perform any extra query because of prefetch
# related!
subnet_ids = []
for subnet in network.subnets.all():
subnet_ids.append(network.id)
state = "SNF:DRAINED" if network.drained else network.state
d['user_id'] = network.userid
d['tenant_id'] = network.userid
......@@ -177,7 +185,7 @@ def network_to_dict(network, detail=True):
d['public'] = network.public
d['router:external'] = network.external_router
d['admin_state_up'] = True
d['subnets'] = list(network.subnets.values_list('id', flat=True))
d['subnets'] = subnet_ids
d['SNF:floating_ip_pool'] = network.floating_ip_pool
return d
......
......@@ -85,6 +85,9 @@ def list_ports(request, detail=False):
user_ports = NetworkInterface.objects.filter(userid=request.user_uniq)
if detail:
user_ports = user_ports.prefetch_related("ips")
port_dicts = [port_to_dict(port, detail)
for port in user_ports.order_by('id')]
......@@ -246,15 +249,16 @@ def port_to_dict(port, detail=True):
d['mac_address'] = port.mac
d['status'] = port.state
d['device_owner'] = port.device_owner
d['network_id'] = str(port.network.id)
d['network_id'] = str(port.network_id)
d['updated'] = api.utils.isoformat(port.updated)
d['created'] = api.utils.isoformat(port.created)
d['fixed_ips'] = []
for ip in port.ips.all():
d['fixed_ips'].append({"ip_address": ip.address,
"subnet": str(ip.subnet.id)})
sg_list = list(port.security_groups.values_list('id', flat=True))
d['security_groups'] = map(str, sg_list)
"subnet": str(ip.subnet_id)})
# Avoid extra queries until security groups are implemented!
#sg_list = list(port.security_groups.values_list('id', flat=True))
d['security_groups'] = []
return d
......
......@@ -37,9 +37,10 @@ from snf_django.lib import api
from django.conf.urls import patterns
from django.http import HttpResponse
from django.utils import simplejson as json
from django.db.models import Q
from snf_django.lib.api import utils
#from synnefo.db.models import Subnet
from synnefo.db.models import Subnet
from synnefo.logic import subnets
from synnefo.api import util
......@@ -77,9 +78,17 @@ def subnet_demux(request, sub_id):
@api.api_method(http_method='GET', user_required=True, logger=log)
def list_subnets(request):
"""List all subnets of a user"""
subnet_list = subnets.list_subnets(request.user_uniq)
subnets_dict = [subnet_to_dict(sub)
for sub in subnet_list.order_by('id')]
userid = request.user_uniq
subnets_list = Subnet.objects.filter(Q(network__public=True) |
(Q(network__userid=userid) &
Q(network__public=False)))\
.order_by("id")
subnets_list = subnets_list.prefetch_related("ip_pools")\
.select_related("network")
subnets_list = api.utils.filter_modified_since(request,
objects=subnets_list)
subnets_dict = [subnet_to_dict(sub) for sub in subnets_list]
data = json.dumps({'subnets': subnets_dict})
......@@ -155,7 +164,7 @@ def create_subnet(request):
def get_subnet(request, sub_id):
"""Show info of a specific subnet"""
user_id = request.user_uniq
subnet = subnets.get_subnet(sub_id)
subnet = subnets.get_subnet(sub_id, prefetch_related=True)
if (subnet.network.userid != user_id) and (subnet.network.public is False):
raise api.faults.Unauthorized("You're not allowed to view this subnet")
......@@ -210,7 +219,7 @@ def subnet_to_dict(subnet):
network = subnet.network
d = {'id': str(subnet.id),
'network_id': str(network.id),
'network_id': str(subnet.network_id),
'name': subnet.name if subnet.name is not None else "",
'tenant_id': network.userid,
'user_id': network.userid,
......
......@@ -148,16 +148,18 @@ def _create_subnet(network_id, user_id, cidr, name, ipversion=4, gateway=None,
return sub
def get_subnet(sub_id):
def get_subnet(sub_id, prefetch_related=False):
"""Show info of a specific subnet"""
log.debug('get_subnet %s', sub_id)
try:
subnet = Subnet.objects.get(id=sub_id)
subnets = Subnet.objects
if prefetch_related:
subnets = subnets.select_related("network")
subnets = subnets.prefetch_related("ip_pools")
return subnets.get(id=sub_id)
except Subnet.DoesNotExist:
raise api.faults.ItemNotFound("Subnet not found")
return subnet
def delete_subnet():
"""Delete a subnet, raises BadRequest
......
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