Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / subnets.py @ 9d1e6480

History | View | Annotate | Download (9.3 kB)

1 16f7d0d9 Dionysis Grigoropoulos
# Copyright 2013 GRNET S.A. All rights reserved.
2 16f7d0d9 Dionysis Grigoropoulos
#
3 16f7d0d9 Dionysis Grigoropoulos
# Redistribution and use in source and binary forms, with or
4 16f7d0d9 Dionysis Grigoropoulos
# without modification, are permitted provided that the following
5 16f7d0d9 Dionysis Grigoropoulos
# conditions are met:
6 16f7d0d9 Dionysis Grigoropoulos
#
7 16f7d0d9 Dionysis Grigoropoulos
#   1. Redistributions of source code must retain the above
8 16f7d0d9 Dionysis Grigoropoulos
#      copyright notice, this list of conditions and the following
9 16f7d0d9 Dionysis Grigoropoulos
#      disclaimer.
10 16f7d0d9 Dionysis Grigoropoulos
#
11 16f7d0d9 Dionysis Grigoropoulos
#   2. Redistributions in binary form must reproduce the above
12 16f7d0d9 Dionysis Grigoropoulos
#      copyright notice, this list of conditions and the following
13 16f7d0d9 Dionysis Grigoropoulos
#      disclaimer in the documentation and/or other materials
14 16f7d0d9 Dionysis Grigoropoulos
#      provided with the distribution.
15 16f7d0d9 Dionysis Grigoropoulos
#
16 16f7d0d9 Dionysis Grigoropoulos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 16f7d0d9 Dionysis Grigoropoulos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 16f7d0d9 Dionysis Grigoropoulos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 16f7d0d9 Dionysis Grigoropoulos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 16f7d0d9 Dionysis Grigoropoulos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 16f7d0d9 Dionysis Grigoropoulos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 16f7d0d9 Dionysis Grigoropoulos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 16f7d0d9 Dionysis Grigoropoulos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 16f7d0d9 Dionysis Grigoropoulos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 16f7d0d9 Dionysis Grigoropoulos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 16f7d0d9 Dionysis Grigoropoulos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 16f7d0d9 Dionysis Grigoropoulos
# POSSIBILITY OF SUCH DAMAGE.
28 16f7d0d9 Dionysis Grigoropoulos
#
29 16f7d0d9 Dionysis Grigoropoulos
# The views and conclusions contained in the software and
30 16f7d0d9 Dionysis Grigoropoulos
# documentation are those of the authors and should not be
31 16f7d0d9 Dionysis Grigoropoulos
# interpreted as representing official policies, either expressed
32 16f7d0d9 Dionysis Grigoropoulos
# or implied, of GRNET S.A.
33 16f7d0d9 Dionysis Grigoropoulos
34 16f7d0d9 Dionysis Grigoropoulos
from logging import getLogger
35 16f7d0d9 Dionysis Grigoropoulos
from snf_django.lib import api
36 16f7d0d9 Dionysis Grigoropoulos
from snf_django.lib.api import faults
37 16f7d0d9 Dionysis Grigoropoulos
38 6a959c73 Dionysis Grigoropoulos
from django.conf.urls import patterns
39 16f7d0d9 Dionysis Grigoropoulos
from django.http import HttpResponse
40 16f7d0d9 Dionysis Grigoropoulos
from django.utils import simplejson as json
41 16f7d0d9 Dionysis Grigoropoulos
42 16f7d0d9 Dionysis Grigoropoulos
from snf_django.lib.api import utils
43 4445f97a Dionysis Grigoropoulos
from synnefo.db.models import Subnet, Network, IPPoolTable
44 9cd6d7e9 Dionysis Grigoropoulos
from synnefo.logic import networks, subnets
45 16f7d0d9 Dionysis Grigoropoulos
46 a996065e Dionysis Grigoropoulos
from ipaddr import IPv4Network, IPv6Network, IPv4Address, IPAddress, IPNetwork
47 16f7d0d9 Dionysis Grigoropoulos
48 16f7d0d9 Dionysis Grigoropoulos
log = getLogger(__name__)
49 16f7d0d9 Dionysis Grigoropoulos
50 16f7d0d9 Dionysis Grigoropoulos
51 6a959c73 Dionysis Grigoropoulos
urlpatterns = patterns(
52 6a959c73 Dionysis Grigoropoulos
    'synnefo.api.subnets',
53 6a959c73 Dionysis Grigoropoulos
    (r'^(?:/|.json|.xml)?$', 'demux'),
54 6a959c73 Dionysis Grigoropoulos
    (r'^/([-\w]+)(?:/|.json|.xml)?$', 'subnet_demux'))
55 6a959c73 Dionysis Grigoropoulos
56 6a959c73 Dionysis Grigoropoulos
57 16f7d0d9 Dionysis Grigoropoulos
def demux(request):
58 16f7d0d9 Dionysis Grigoropoulos
    if request.method == 'GET':
59 16f7d0d9 Dionysis Grigoropoulos
        return list_subnets(request)
60 16f7d0d9 Dionysis Grigoropoulos
    elif request.method == 'POST':
61 16f7d0d9 Dionysis Grigoropoulos
        return create_subnet(request)
62 16f7d0d9 Dionysis Grigoropoulos
    else:
63 16f7d0d9 Dionysis Grigoropoulos
        return api.api_method_not_allowed(request)
64 16f7d0d9 Dionysis Grigoropoulos
65 16f7d0d9 Dionysis Grigoropoulos
66 16f7d0d9 Dionysis Grigoropoulos
def subnet_demux(request, sub_id):
67 16f7d0d9 Dionysis Grigoropoulos
    if request.method == 'GET':
68 16f7d0d9 Dionysis Grigoropoulos
        return get_subnet(request, sub_id)
69 16f7d0d9 Dionysis Grigoropoulos
    elif request.method == 'DELETE':
70 16f7d0d9 Dionysis Grigoropoulos
        return delete_subnet(request, sub_id)
71 16f7d0d9 Dionysis Grigoropoulos
    elif request.method == 'PUT':
72 16f7d0d9 Dionysis Grigoropoulos
        return update_subnet(request, sub_id)
73 16f7d0d9 Dionysis Grigoropoulos
    else:
74 16f7d0d9 Dionysis Grigoropoulos
        return api.api_method_not_allowed(request)
75 16f7d0d9 Dionysis Grigoropoulos
76 16f7d0d9 Dionysis Grigoropoulos
77 16f7d0d9 Dionysis Grigoropoulos
@api.api_method(http_method='GET', user_required=True, logger=log)
78 16f7d0d9 Dionysis Grigoropoulos
def list_subnets(request):
79 16f7d0d9 Dionysis Grigoropoulos
    """List all subnets of a user"""
80 5d83d2ff Dionysis Grigoropoulos
    subnet_list = subnets.list_subnets(request.user_uniq)
81 5d83d2ff Dionysis Grigoropoulos
    subnets_dict = [subnet_to_dict(sub)
82 5d83d2ff Dionysis Grigoropoulos
                    for sub in subnet_list.order_by('id')]
83 5d83d2ff Dionysis Grigoropoulos
84 16f7d0d9 Dionysis Grigoropoulos
    data = json.dumps({'subnets': subnets_dict})
85 16f7d0d9 Dionysis Grigoropoulos
86 16f7d0d9 Dionysis Grigoropoulos
    return HttpResponse(data, status=200)
87 16f7d0d9 Dionysis Grigoropoulos
88 16f7d0d9 Dionysis Grigoropoulos
89 16f7d0d9 Dionysis Grigoropoulos
@api.api_method(http_method='POST', user_required=True, logger=log)
90 16f7d0d9 Dionysis Grigoropoulos
def create_subnet(request):
91 a996065e Dionysis Grigoropoulos
    """
92 a996065e Dionysis Grigoropoulos
    Create a subnet
93 a996065e Dionysis Grigoropoulos
    network_id and the desired cidr are mandatory, everything else is optional
94 a996065e Dionysis Grigoropoulos
    """
95 16f7d0d9 Dionysis Grigoropoulos
    dictionary = utils.get_request_dict(request)
96 16f7d0d9 Dionysis Grigoropoulos
    log.info('create subnet %s', dictionary)
97 16f7d0d9 Dionysis Grigoropoulos
98 16f7d0d9 Dionysis Grigoropoulos
    try:
99 16f7d0d9 Dionysis Grigoropoulos
        subnet = dictionary['subnet']
100 16f7d0d9 Dionysis Grigoropoulos
        network_id = subnet['network_id']
101 16f7d0d9 Dionysis Grigoropoulos
        cidr = subnet['cidr']
102 16f7d0d9 Dionysis Grigoropoulos
    except KeyError:
103 16f7d0d9 Dionysis Grigoropoulos
        raise api.faults.BadRequest("Malformed request")
104 16f7d0d9 Dionysis Grigoropoulos
105 16f7d0d9 Dionysis Grigoropoulos
    allocation_pools = subnet.get('allocation_pools', None)
106 4445f97a Dionysis Grigoropoulos
    if allocation_pools is not None:
107 9cd6d7e9 Dionysis Grigoropoulos
        pool = parse_ip_pools(allocation_pools)
108 9cd6d7e9 Dionysis Grigoropoulos
        allocation_pools = string_to_ipaddr(pool)
109 9cd6d7e9 Dionysis Grigoropoulos
110 5d83d2ff Dionysis Grigoropoulos
    name = subnet.get('name', None)
111 5d83d2ff Dionysis Grigoropoulos
    ipversion = subnet.get('ip_version', 4)
112 5d83d2ff Dionysis Grigoropoulos
    gateway = subnet.get('gateway_ip', None)
113 5d83d2ff Dionysis Grigoropoulos
    dhcp = subnet.get('enable_dhcp', True)
114 5d83d2ff Dionysis Grigoropoulos
    slac = subnet.get('enable_slac', None)
115 5d83d2ff Dionysis Grigoropoulos
    dns = subnet.get('dns_nameservers', None)
116 5d83d2ff Dionysis Grigoropoulos
    hosts = subnet.get('host_routes', None)
117 5d83d2ff Dionysis Grigoropoulos
118 9cd6d7e9 Dionysis Grigoropoulos
    sub = subnets.create_subnet(network_id=network_id,
119 9cd6d7e9 Dionysis Grigoropoulos
                                cidr=cidr,
120 9cd6d7e9 Dionysis Grigoropoulos
                                name=name,
121 9cd6d7e9 Dionysis Grigoropoulos
                                ipversion=ipversion,
122 9cd6d7e9 Dionysis Grigoropoulos
                                gateway=gateway,
123 9cd6d7e9 Dionysis Grigoropoulos
                                dhcp=dhcp,
124 9cd6d7e9 Dionysis Grigoropoulos
                                slac=slac,
125 9cd6d7e9 Dionysis Grigoropoulos
                                dns_nameservers=dns,
126 9cd6d7e9 Dionysis Grigoropoulos
                                allocation_pools=allocation_pools,
127 9cd6d7e9 Dionysis Grigoropoulos
                                host_routes=hosts,
128 9cd6d7e9 Dionysis Grigoropoulos
                                user_id=request.user_uniq)
129 16f7d0d9 Dionysis Grigoropoulos
130 16f7d0d9 Dionysis Grigoropoulos
    subnet_dict = subnet_to_dict(sub)
131 16f7d0d9 Dionysis Grigoropoulos
    data = json.dumps({'subnet': subnet_dict})
132 16f7d0d9 Dionysis Grigoropoulos
    return HttpResponse(data, status=200)
133 16f7d0d9 Dionysis Grigoropoulos
134 16f7d0d9 Dionysis Grigoropoulos
135 16f7d0d9 Dionysis Grigoropoulos
@api.api_method(http_method='GET', user_required=True, logger=log)
136 16f7d0d9 Dionysis Grigoropoulos
def get_subnet(request, sub_id):
137 16f7d0d9 Dionysis Grigoropoulos
    """Show info of a specific subnet"""
138 16f7d0d9 Dionysis Grigoropoulos
    user_id = request.user_uniq
139 9cd6d7e9 Dionysis Grigoropoulos
    subnet = subnets.get_subnet(sub_id)
140 16f7d0d9 Dionysis Grigoropoulos
141 16f7d0d9 Dionysis Grigoropoulos
    if subnet.network.userid != user_id:
142 16f7d0d9 Dionysis Grigoropoulos
        raise api.failts.Unauthorized("You're not allowed to view this subnet")
143 16f7d0d9 Dionysis Grigoropoulos
144 5d83d2ff Dionysis Grigoropoulos
    subnet_dict = subnet_to_dict(subnet)
145 16f7d0d9 Dionysis Grigoropoulos
    data = json.dumps({'subnet': subnet_dict})
146 16f7d0d9 Dionysis Grigoropoulos
    return HttpResponse(data, status=200)
147 16f7d0d9 Dionysis Grigoropoulos
148 16f7d0d9 Dionysis Grigoropoulos
149 16f7d0d9 Dionysis Grigoropoulos
@api.api_method(http_method='DELETE', user_required=True, logger=log)
150 16f7d0d9 Dionysis Grigoropoulos
def delete_subnet(request, sub_id):
151 16f7d0d9 Dionysis Grigoropoulos
    """
152 16f7d0d9 Dionysis Grigoropoulos
    Delete a subnet, raises BadRequest
153 16f7d0d9 Dionysis Grigoropoulos
    A subnet is deleted ONLY when the network that it belongs to is deleted
154 16f7d0d9 Dionysis Grigoropoulos
    """
155 16f7d0d9 Dionysis Grigoropoulos
    raise api.faults.BadRequest("Deletion of a subnet is not supported")
156 16f7d0d9 Dionysis Grigoropoulos
157 16f7d0d9 Dionysis Grigoropoulos
158 16f7d0d9 Dionysis Grigoropoulos
@api.api_method(http_method='PUT', user_required=True, logger=log)
159 16f7d0d9 Dionysis Grigoropoulos
def update_subnet(request, sub_id):
160 16f7d0d9 Dionysis Grigoropoulos
    """
161 16f7d0d9 Dionysis Grigoropoulos
    Update the fields of a subnet
162 16f7d0d9 Dionysis Grigoropoulos
    Only the name can be updated, everything else returns BadRequest
163 16f7d0d9 Dionysis Grigoropoulos
    """
164 16f7d0d9 Dionysis Grigoropoulos
165 16f7d0d9 Dionysis Grigoropoulos
    dictionary = utils.get_request_dict(request)
166 16f7d0d9 Dionysis Grigoropoulos
    user_id = request.user_uniq
167 16f7d0d9 Dionysis Grigoropoulos
168 16f7d0d9 Dionysis Grigoropoulos
    try:
169 16f7d0d9 Dionysis Grigoropoulos
        subnet = dictionary['subnet']
170 16f7d0d9 Dionysis Grigoropoulos
    except KeyError:
171 16f7d0d9 Dionysis Grigoropoulos
        raise api.faults.BadRequest("Malformed request")
172 16f7d0d9 Dionysis Grigoropoulos
173 5d83d2ff Dionysis Grigoropoulos
    if len(subnet) != 1 or "name" not in subnet:
174 16f7d0d9 Dionysis Grigoropoulos
        raise api.faults.BadRequest("Only the name of subnet can be updated")
175 16f7d0d9 Dionysis Grigoropoulos
176 16f7d0d9 Dionysis Grigoropoulos
    name = subnet.get("name", None)
177 16f7d0d9 Dionysis Grigoropoulos
178 9cd6d7e9 Dionysis Grigoropoulos
    subnet_dict = subnet_to_dict(subnets.update_subnet(sub_id, name))
179 16f7d0d9 Dionysis Grigoropoulos
    data = json.dumps({'subnet': subnet_dict})
180 16f7d0d9 Dionysis Grigoropoulos
    return HttpResponse(data, status=200)
181 16f7d0d9 Dionysis Grigoropoulos
182 16f7d0d9 Dionysis Grigoropoulos
183 16f7d0d9 Dionysis Grigoropoulos
#Utility functions
184 16f7d0d9 Dionysis Grigoropoulos
def subnet_to_dict(subnet):
185 16f7d0d9 Dionysis Grigoropoulos
    """Returns a dictionary containing the info of a subnet"""
186 911a1bc1 Dionysis Grigoropoulos
    dns = check_empty_lists(subnet.dns_nameservers)
187 911a1bc1 Dionysis Grigoropoulos
    hosts = check_empty_lists(subnet.host_routes)
188 4445f97a Dionysis Grigoropoulos
    allocation_pools = subnet.ip_pools.all()
189 4445f97a Dionysis Grigoropoulos
    pools = list()
190 4445f97a Dionysis Grigoropoulos
191 4445f97a Dionysis Grigoropoulos
    if allocation_pools:
192 4445f97a Dionysis Grigoropoulos
        for pool in allocation_pools:
193 4445f97a Dionysis Grigoropoulos
            cidr = IPNetwork(pool.base)
194 4445f97a Dionysis Grigoropoulos
            start = str(cidr.network + pool.offset)
195 4445f97a Dionysis Grigoropoulos
            end = str(cidr.network + pool.offset + pool.size - 1)
196 868e4ce0 Dionysis Grigoropoulos
            pools.append({"start": start, "end": end})
197 911a1bc1 Dionysis Grigoropoulos
198 911a1bc1 Dionysis Grigoropoulos
    dictionary = dict({'id': str(subnet.id),
199 911a1bc1 Dionysis Grigoropoulos
                       'network_id': str(subnet.network.id),
200 911a1bc1 Dionysis Grigoropoulos
                       'name': subnet.name if subnet.name is not None else "",
201 911a1bc1 Dionysis Grigoropoulos
                       'tenant_id': subnet.network.userid,
202 911a1bc1 Dionysis Grigoropoulos
                       'user_id': subnet.network.userid,
203 16f7d0d9 Dionysis Grigoropoulos
                       'gateway_ip': subnet.gateway,
204 911a1bc1 Dionysis Grigoropoulos
                       'ip_version': subnet.ipversion,
205 911a1bc1 Dionysis Grigoropoulos
                       'cidr': subnet.cidr,
206 16f7d0d9 Dionysis Grigoropoulos
                       'enable_dhcp': subnet.dhcp,
207 911a1bc1 Dionysis Grigoropoulos
                       'dns_nameservers': dns,
208 911a1bc1 Dionysis Grigoropoulos
                       'host_routes': hosts,
209 4445f97a Dionysis Grigoropoulos
                       'allocation_pools': pools if pools is not None else []})
210 97ca522f Dionysis Grigoropoulos
211 97ca522f Dionysis Grigoropoulos
    if subnet.ipversion == 6:
212 097009bf Dionysis Grigoropoulos
        dictionary['enable_slac'] = subnet.dhcp
213 97ca522f Dionysis Grigoropoulos
214 16f7d0d9 Dionysis Grigoropoulos
    return dictionary
215 16f7d0d9 Dionysis Grigoropoulos
216 16f7d0d9 Dionysis Grigoropoulos
217 4445f97a Dionysis Grigoropoulos
def string_to_ipaddr(pools):
218 4445f97a Dionysis Grigoropoulos
    """
219 4445f97a Dionysis Grigoropoulos
    Convert [["192.168.42.1", "192.168.42.15"],
220 4445f97a Dionysis Grigoropoulos
            ["192.168.42.30", "192.168.42.60"]]
221 4445f97a Dionysis Grigoropoulos
    to
222 4445f97a Dionysis Grigoropoulos
            [[IPv4Address('192.168.42.1'), IPv4Address('192.168.42.15')],
223 4445f97a Dionysis Grigoropoulos
            [IPv4Address('192.168.42.30'), IPv4Address('192.168.42.60')]]
224 4445f97a Dionysis Grigoropoulos
    and sort the output
225 4445f97a Dionysis Grigoropoulos
    """
226 4445f97a Dionysis Grigoropoulos
    pool_list = [(map(lambda ip_str: IPAddress(ip_str), pool))
227 4445f97a Dionysis Grigoropoulos
                 for pool in pools]
228 4445f97a Dionysis Grigoropoulos
    pool_list.sort()
229 4445f97a Dionysis Grigoropoulos
    return pool_list
230 4445f97a Dionysis Grigoropoulos
231 4445f97a Dionysis Grigoropoulos
232 911a1bc1 Dionysis Grigoropoulos
def check_empty_lists(value):
233 911a1bc1 Dionysis Grigoropoulos
    """Check if value is Null/None, in which case we return an empty list"""
234 911a1bc1 Dionysis Grigoropoulos
    if value is None:
235 911a1bc1 Dionysis Grigoropoulos
        return []
236 911a1bc1 Dionysis Grigoropoulos
    return value
237 911a1bc1 Dionysis Grigoropoulos
238 911a1bc1 Dionysis Grigoropoulos
239 16f7d0d9 Dionysis Grigoropoulos
def check_name_length(name):
240 16f7d0d9 Dionysis Grigoropoulos
    """Check if the length of a name is within acceptable value"""
241 16f7d0d9 Dionysis Grigoropoulos
    if len(str(name)) > Subnet.SUBNET_NAME_LENGTH:
242 16f7d0d9 Dionysis Grigoropoulos
        raise api.faults.BadRequest("Subnet name too long")
243 16f7d0d9 Dionysis Grigoropoulos
    return name
244 16f7d0d9 Dionysis Grigoropoulos
245 16f7d0d9 Dionysis Grigoropoulos
246 16f7d0d9 Dionysis Grigoropoulos
def get_subnet_fromdb(subnet_id, user_id, for_update=False):
247 16f7d0d9 Dionysis Grigoropoulos
    """
248 16f7d0d9 Dionysis Grigoropoulos
    Return a Subnet instance or raise ItemNotFound.
249 16f7d0d9 Dionysis Grigoropoulos
    This is the same as util.get_network
250 16f7d0d9 Dionysis Grigoropoulos
    """
251 16f7d0d9 Dionysis Grigoropoulos
    try:
252 16f7d0d9 Dionysis Grigoropoulos
        subnet_id = int(subnet_id)
253 16f7d0d9 Dionysis Grigoropoulos
        if for_update:
254 16f7d0d9 Dionysis Grigoropoulos
            return Subnet.objects.select_for_update().get(id=subnet_id,
255 16f7d0d9 Dionysis Grigoropoulos
                                                          network__userid=
256 16f7d0d9 Dionysis Grigoropoulos
                                                          user_id)
257 16f7d0d9 Dionysis Grigoropoulos
        return Subnet.objects.get(id=subnet_id, network__userid=user_id)
258 16f7d0d9 Dionysis Grigoropoulos
    except (ValueError, Subnet.DoesNotExist):
259 911a1bc1 Dionysis Grigoropoulos
        raise api.faults.ItemNotFound('Subnet not found')
260 812a1114 Dionysis Grigoropoulos
261 812a1114 Dionysis Grigoropoulos
262 812a1114 Dionysis Grigoropoulos
def parse_ip_pools(pools):
263 812a1114 Dionysis Grigoropoulos
    """
264 812a1114 Dionysis Grigoropoulos
    Convert [{'start': '192.168.42.1', 'end': '192.168.42.15'},
265 812a1114 Dionysis Grigoropoulos
             {'start': '192.168.42.30', 'end': '192.168.42.60'}]
266 812a1114 Dionysis Grigoropoulos
    to
267 812a1114 Dionysis Grigoropoulos
            [["192.168.42.1", "192.168.42.15"],
268 812a1114 Dionysis Grigoropoulos
             ["192.168.42.30", "192.168.42.60"]]
269 812a1114 Dionysis Grigoropoulos
    """
270 812a1114 Dionysis Grigoropoulos
    pool_list = list()
271 812a1114 Dionysis Grigoropoulos
    for pool in pools:
272 911a1bc1 Dionysis Grigoropoulos
        parse = [pool["start"], pool["end"]]
273 911a1bc1 Dionysis Grigoropoulos
        pool_list.append(parse)
274 812a1114 Dionysis Grigoropoulos
    return pool_list