Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / ports.py @ 0069a20c

History | View | Annotate | Download (7.3 kB)

1 5db2001a Marios Kogias
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2 5db2001a Marios Kogias
#
3 5db2001a Marios Kogias
# Redistribution and use in source and binary forms, with or
4 5db2001a Marios Kogias
# without modification, are permitted provided that the following
5 5db2001a Marios Kogias
# conditions are met:
6 5db2001a Marios Kogias
#
7 5db2001a Marios Kogias
#   1. Redistributions of source code must retain the above
8 5db2001a Marios Kogias
#      copyright notice, this list of conditions and the following
9 5db2001a Marios Kogias
#      disclaimer.
10 5db2001a Marios Kogias
#
11 5db2001a Marios Kogias
#   2. Redistributions in binary form must reproduce the above
12 5db2001a Marios Kogias
#      copyright notice, this list of conditions and the following
13 5db2001a Marios Kogias
#      disclaimer in the documentation and/or other materials
14 5db2001a Marios Kogias
#      provided with the distribution.
15 5db2001a Marios Kogias
#
16 5db2001a Marios Kogias
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 5db2001a Marios Kogias
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 5db2001a Marios Kogias
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 5db2001a Marios Kogias
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 5db2001a Marios Kogias
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 5db2001a Marios Kogias
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 5db2001a Marios Kogias
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 5db2001a Marios Kogias
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 5db2001a Marios Kogias
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 5db2001a Marios Kogias
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 5db2001a Marios Kogias
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 5db2001a Marios Kogias
# POSSIBILITY OF SUCH DAMAGE.
28 5db2001a Marios Kogias
#
29 5db2001a Marios Kogias
# The views and conclusions contained in the software and
30 5db2001a Marios Kogias
# documentation are those of the authors and should not be
31 5db2001a Marios Kogias
# interpreted as representing official policies, either expressed
32 5db2001a Marios Kogias
# or implied, of GRNET S.A.
33 5db2001a Marios Kogias
34 593851e0 Buildbot
from django.conf import settings
35 593851e0 Buildbot
from django.conf.urls import patterns
36 593851e0 Buildbot
from django.http import HttpResponse
37 593851e0 Buildbot
from django.utils import simplejson as json
38 593851e0 Buildbot
from django.db import transaction
39 593851e0 Buildbot
from django.db.models import Q
40 593851e0 Buildbot
from django.template.loader import render_to_string
41 5db2001a Marios Kogias
42 5db2001a Marios Kogias
from snf_django.lib import api
43 5db2001a Marios Kogias
44 593851e0 Buildbot
from synnefo.api import util
45 593851e0 Buildbot
from synnefo.db.models import NetworkInterface, SecurityGroup, IPAddress
46 f16aa9e6 Marios Kogias
from synnefo.logic import ports
47 593851e0 Buildbot
48 593851e0 Buildbot
from logging import getLogger
49 593851e0 Buildbot
50 593851e0 Buildbot
log = getLogger(__name__)
51 593851e0 Buildbot
52 593851e0 Buildbot
urlpatterns = patterns(
53 593851e0 Buildbot
    'synnefo.api.ports',
54 593851e0 Buildbot
    (r'^(?:/|.json|.xml)?$', 'demux'),
55 593851e0 Buildbot
    (r'^/([-\w]+)(?:/|.json|.xml)?$', 'port_demux'))
56 593851e0 Buildbot
57 5db2001a Marios Kogias
58 593851e0 Buildbot
def demux(request):
59 593851e0 Buildbot
    if request.method == 'GET':
60 593851e0 Buildbot
        return list_ports(request)
61 593851e0 Buildbot
    elif request.method == 'POST':
62 593851e0 Buildbot
        return create_port(request)
63 593851e0 Buildbot
    else:
64 593851e0 Buildbot
        return api.api_method_not_allowed(request)
65 593851e0 Buildbot
66 593851e0 Buildbot
67 5db2001a Marios Kogias
def port_demux(request, port_id):
68 593851e0 Buildbot
69 593851e0 Buildbot
    if request.method == 'GET':
70 5db2001a Marios Kogias
        return get_port_details(request, port_id)
71 593851e0 Buildbot
    elif request.method == 'DELETE':
72 5db2001a Marios Kogias
        return delete_port(request, port_id)
73 593851e0 Buildbot
    elif request.method == 'PUT':
74 5db2001a Marios Kogias
        return update_port(request, port_id)
75 593851e0 Buildbot
    else:
76 593851e0 Buildbot
        return api.api_method_not_allowed(request)
77 593851e0 Buildbot
78 593851e0 Buildbot
79 593851e0 Buildbot
@api.api_method(http_method='GET', user_required=True, logger=log)
80 593851e0 Buildbot
def list_ports(request, detail=False):
81 593851e0 Buildbot
82 593851e0 Buildbot
    log.debug('list_ports detail=%s', detail)
83 593851e0 Buildbot
84 593851e0 Buildbot
    user_ports = NetworkInterface.objects.filter(
85 593851e0 Buildbot
        network__userid=request.user_uniq)
86 593851e0 Buildbot
87 5db2001a Marios Kogias
    port_dicts = [port_to_dict(port, detail)
88 593851e0 Buildbot
             for port in user_ports.order_by('id')]
89 593851e0 Buildbot
90 593851e0 Buildbot
    if request.serialization == 'xml':
91 5db2001a Marios Kogias
        data = render_to_string('list_ports.xml', {
92 5db2001a Marios Kogias
            "ports": port_dicts})
93 593851e0 Buildbot
    else:
94 5db2001a Marios Kogias
        data = json.dumps({'ports': port_dicts})
95 593851e0 Buildbot
96 593851e0 Buildbot
    return HttpResponse(data, status=200)
97 593851e0 Buildbot
98 593851e0 Buildbot
99 593851e0 Buildbot
@api.api_method(http_method='POST', user_required=True, logger=log)
100 593851e0 Buildbot
def create_port(request):
101 593851e0 Buildbot
    '''
102 593851e0 Buildbot
    '''
103 593851e0 Buildbot
    user_id = request.user_uniq
104 5db2001a Marios Kogias
    req = api.utils.get_request_dict(request)
105 593851e0 Buildbot
    log.info('create_port %s', req)
106 593851e0 Buildbot
107 f16aa9e6 Marios Kogias
    port_dict = api.utils.get_attribute(req, "port")
108 f16aa9e6 Marios Kogias
    net_id = api.utils.get_attribute(port_dict, "network_id")
109 f16aa9e6 Marios Kogias
    dev_id = api.utils.get_attribute(port_dict, "device_id")
110 f16aa9e6 Marios Kogias
111 f16aa9e6 Marios Kogias
    network = util.get_network(net_id, request.user_uniq, non_deleted=True)
112 f16aa9e6 Marios Kogias
113 f16aa9e6 Marios Kogias
    if network.public:
114 f16aa9e6 Marios Kogias
        raise api.faults.Forbidden('forbidden')
115 f16aa9e6 Marios Kogias
116 f16aa9e6 Marios Kogias
117 f16aa9e6 Marios Kogias
    vm = util.get_vm(dev_id, request.user_uniq)
118 f16aa9e6 Marios Kogias
119 f16aa9e6 Marios Kogias
    name = api.utils.get_attribute(port_dict, "name", required=False)
120 f16aa9e6 Marios Kogias
121 f16aa9e6 Marios Kogias
    if name is None:
122 f16aa9e6 Marios Kogias
        name = ""
123 f16aa9e6 Marios Kogias
124 f16aa9e6 Marios Kogias
    security_groups = api.utils.get_attribute(port_dict,
125 f16aa9e6 Marios Kogias
                                              "security_groups",
126 f16aa9e6 Marios Kogias
                                              required=False)
127 f16aa9e6 Marios Kogias
    #validate security groups
128 f16aa9e6 Marios Kogias
    # like get security group from db
129 a1713485 Marios Kogias
    sg_list = []
130 f16aa9e6 Marios Kogias
    if security_groups:
131 f16aa9e6 Marios Kogias
        for gid in security_groups:
132 a1713485 Marios Kogias
            sg = util.get_security_group(int(gid))
133 a1713485 Marios Kogias
            sg_list.append(sg)
134 f16aa9e6 Marios Kogias
135 0069a20c Marios Kogias
    new_port = ports.create(network, vm, security_groups=sg_list)
136 593851e0 Buildbot
137 5db2001a Marios Kogias
    response = render_port(request, port_to_dict(new_port), status=201)
138 593851e0 Buildbot
139 593851e0 Buildbot
    return response
140 593851e0 Buildbot
141 593851e0 Buildbot
142 5db2001a Marios Kogias
@api.api_method(http_method='GET', user_required=True, logger=log)
143 5db2001a Marios Kogias
def get_port_details(request, port_id):
144 5db2001a Marios Kogias
    log.debug('get_port_details %s', port_id)
145 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq)
146 5db2001a Marios Kogias
    return render_port(request, port_to_dict(port))
147 5db2001a Marios Kogias
148 5db2001a Marios Kogias
149 5db2001a Marios Kogias
@api.api_method(http_method='PUT', user_required=True, logger=log)
150 5db2001a Marios Kogias
def update_port(request, port_id):
151 5db2001a Marios Kogias
    '''
152 5db2001a Marios Kogias
    You can update only name, security_groups
153 5db2001a Marios Kogias
    '''
154 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq, for_update=True)
155 5db2001a Marios Kogias
    req = api.utils.get_request_dict(request)
156 5db2001a Marios Kogias
157 5db2001a Marios Kogias
    port_info = api.utils.get_attribute(req, "port", required=True)
158 5db2001a Marios Kogias
    name = api.utils.get_attribute(port_info, "name", required=False)
159 5db2001a Marios Kogias
160 5db2001a Marios Kogias
    if name:
161 5db2001a Marios Kogias
        port.name = name
162 5db2001a Marios Kogias
163 5db2001a Marios Kogias
    security_groups = api.utils.get_attribute(port_info, "security_groups",
164 5db2001a Marios Kogias
                                              required=False)
165 5db2001a Marios Kogias
    if security_groups:
166 5db2001a Marios Kogias
        sg_list = []
167 5db2001a Marios Kogias
        #validate security groups
168 5db2001a Marios Kogias
        for gid in security_groups:
169 a1713485 Marios Kogias
            sg = util.get_security_group(int(gid))
170 a1713485 Marios Kogias
            sg_list.append(sg)
171 5db2001a Marios Kogias
172 5db2001a Marios Kogias
        #clear the old security groups
173 5db2001a Marios Kogias
        port.security_groups.clear()
174 5db2001a Marios Kogias
175 5db2001a Marios Kogias
        #add the new groups
176 5db2001a Marios Kogias
        port.security_groups.add(*sg_list)
177 5db2001a Marios Kogias
178 5db2001a Marios Kogias
    port.save()
179 5db2001a Marios Kogias
    return render_port(request, port_to_dict(port), 200)
180 5db2001a Marios Kogias
181 5db2001a Marios Kogias
182 5db2001a Marios Kogias
@api.api_method(http_method='DELETE', user_required=True, logger=log)
183 5db2001a Marios Kogias
@transaction.commit_on_success
184 5db2001a Marios Kogias
def delete_port(request, port_id):
185 5db2001a Marios Kogias
    log.info('delete_port %s', port_id)
186 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq, for_update=True)
187 5db2001a Marios Kogias
    '''
188 5db2001a Marios Kogias
    FIXME delete the port
189 5db2001a Marios Kogias
    skip the backend part...
190 5db2001a Marios Kogias
    release the ips associated with the port
191 5db2001a Marios Kogias
    '''
192 5db2001a Marios Kogias
    return HttpResponse(status=204)
193 5db2001a Marios Kogias
194 593851e0 Buildbot
#util functions
195 593851e0 Buildbot
196 593851e0 Buildbot
197 593851e0 Buildbot
def port_to_dict(port, detail=True):
198 593851e0 Buildbot
    d = {'id': str(port.id), 'name': port.name}
199 593851e0 Buildbot
    if detail:
200 593851e0 Buildbot
        d['user_id'] = port.network.userid
201 593851e0 Buildbot
        d['tenant_id'] = port.network.userid
202 593851e0 Buildbot
        d['device_id'] = str(port.machine.id)
203 593851e0 Buildbot
        d['admin_state_up'] = True
204 593851e0 Buildbot
        d['mac_address'] = port.mac
205 593851e0 Buildbot
        d['status'] = port.state
206 593851e0 Buildbot
        d['device_owner'] = port.device_owner
207 593851e0 Buildbot
        d['network_id'] = str(port.network.id)
208 5db2001a Marios Kogias
        d['updated'] = api.utils.isoformat(port.updated)
209 5db2001a Marios Kogias
        d['created'] = api.utils.isoformat(port.created)
210 593851e0 Buildbot
        d['fixed_ips'] = []
211 593851e0 Buildbot
        for ip in port.ips.all():
212 593851e0 Buildbot
            d['fixed_ips'].append({"ip_address": ip.address,
213 5db2001a Marios Kogias
                                      "subnet": str(ip.subnet.id)})
214 5db2001a Marios Kogias
        sg_list = list(port.security_groups.values_list('id', flat=True))
215 5db2001a Marios Kogias
        d['security_groups'] = map(str, sg_list)
216 5db2001a Marios Kogias
217 593851e0 Buildbot
    return d
218 593851e0 Buildbot
219 593851e0 Buildbot
220 593851e0 Buildbot
def render_port(request, portdict, status=200):
221 593851e0 Buildbot
    if request.serialization == 'xml':
222 5db2001a Marios Kogias
        data = render_to_string('port.xml', {'port': portdict})
223 593851e0 Buildbot
    else:
224 593851e0 Buildbot
        data = json.dumps({'port': portdict})
225 593851e0 Buildbot
    return HttpResponse(data, status=status)