Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / ports.py @ 9f6760ee

History | View | Annotate | Download (7.2 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.template.loader import render_to_string
40 5db2001a Marios Kogias
41 5db2001a Marios Kogias
from snf_django.lib import api
42 5db2001a Marios Kogias
43 593851e0 Buildbot
from synnefo.api import util
44 593851e0 Buildbot
from synnefo.db.models import NetworkInterface, SecurityGroup, IPAddress
45 f16aa9e6 Marios Kogias
from synnefo.logic import ports
46 593851e0 Buildbot
47 593851e0 Buildbot
from logging import getLogger
48 593851e0 Buildbot
49 593851e0 Buildbot
log = getLogger(__name__)
50 593851e0 Buildbot
51 593851e0 Buildbot
urlpatterns = patterns(
52 593851e0 Buildbot
    'synnefo.api.ports',
53 593851e0 Buildbot
    (r'^(?:/|.json|.xml)?$', 'demux'),
54 593851e0 Buildbot
    (r'^/([-\w]+)(?:/|.json|.xml)?$', 'port_demux'))
55 593851e0 Buildbot
56 5db2001a Marios Kogias
57 593851e0 Buildbot
def demux(request):
58 593851e0 Buildbot
    if request.method == 'GET':
59 593851e0 Buildbot
        return list_ports(request)
60 593851e0 Buildbot
    elif request.method == 'POST':
61 593851e0 Buildbot
        return create_port(request)
62 593851e0 Buildbot
    else:
63 593851e0 Buildbot
        return api.api_method_not_allowed(request)
64 593851e0 Buildbot
65 593851e0 Buildbot
66 5db2001a Marios Kogias
def port_demux(request, port_id):
67 593851e0 Buildbot
68 593851e0 Buildbot
    if request.method == 'GET':
69 5db2001a Marios Kogias
        return get_port_details(request, port_id)
70 593851e0 Buildbot
    elif request.method == 'DELETE':
71 5db2001a Marios Kogias
        return delete_port(request, port_id)
72 593851e0 Buildbot
    elif request.method == 'PUT':
73 5db2001a Marios Kogias
        return update_port(request, port_id)
74 593851e0 Buildbot
    else:
75 593851e0 Buildbot
        return api.api_method_not_allowed(request)
76 593851e0 Buildbot
77 593851e0 Buildbot
78 593851e0 Buildbot
@api.api_method(http_method='GET', user_required=True, logger=log)
79 593851e0 Buildbot
def list_ports(request, detail=False):
80 593851e0 Buildbot
81 593851e0 Buildbot
    log.debug('list_ports detail=%s', detail)
82 593851e0 Buildbot
83 593851e0 Buildbot
    user_ports = NetworkInterface.objects.filter(
84 593851e0 Buildbot
        network__userid=request.user_uniq)
85 593851e0 Buildbot
86 5db2001a Marios Kogias
    port_dicts = [port_to_dict(port, detail)
87 9f6760ee Christos Stavrakakis
                  for port in user_ports.order_by('id')]
88 593851e0 Buildbot
89 593851e0 Buildbot
    if request.serialization == 'xml':
90 5db2001a Marios Kogias
        data = render_to_string('list_ports.xml', {
91 5db2001a Marios Kogias
            "ports": port_dicts})
92 593851e0 Buildbot
    else:
93 5db2001a Marios Kogias
        data = json.dumps({'ports': port_dicts})
94 593851e0 Buildbot
95 593851e0 Buildbot
    return HttpResponse(data, status=200)
96 593851e0 Buildbot
97 593851e0 Buildbot
98 593851e0 Buildbot
@api.api_method(http_method='POST', user_required=True, logger=log)
99 593851e0 Buildbot
def create_port(request):
100 593851e0 Buildbot
    user_id = request.user_uniq
101 5db2001a Marios Kogias
    req = api.utils.get_request_dict(request)
102 593851e0 Buildbot
    log.info('create_port %s', req)
103 593851e0 Buildbot
104 f16aa9e6 Marios Kogias
    port_dict = api.utils.get_attribute(req, "port")
105 f16aa9e6 Marios Kogias
    net_id = api.utils.get_attribute(port_dict, "network_id")
106 f16aa9e6 Marios Kogias
    dev_id = api.utils.get_attribute(port_dict, "device_id")
107 f16aa9e6 Marios Kogias
108 9f6760ee Christos Stavrakakis
    network = util.get_network(net_id, user_id, non_deleted=True)
109 f16aa9e6 Marios Kogias
110 f16aa9e6 Marios Kogias
    if network.public:
111 f16aa9e6 Marios Kogias
        raise api.faults.Forbidden('forbidden')
112 f16aa9e6 Marios Kogias
113 9f6760ee Christos Stavrakakis
    vm = util.get_vm(dev_id, user_id)
114 f16aa9e6 Marios Kogias
115 f16aa9e6 Marios Kogias
    name = api.utils.get_attribute(port_dict, "name", required=False)
116 f16aa9e6 Marios Kogias
117 f16aa9e6 Marios Kogias
    if name is None:
118 f16aa9e6 Marios Kogias
        name = ""
119 f16aa9e6 Marios Kogias
120 f16aa9e6 Marios Kogias
    security_groups = api.utils.get_attribute(port_dict,
121 f16aa9e6 Marios Kogias
                                              "security_groups",
122 f16aa9e6 Marios Kogias
                                              required=False)
123 f16aa9e6 Marios Kogias
    #validate security groups
124 f16aa9e6 Marios Kogias
    # like get security group from db
125 a1713485 Marios Kogias
    sg_list = []
126 f16aa9e6 Marios Kogias
    if security_groups:
127 f16aa9e6 Marios Kogias
        for gid in security_groups:
128 a1713485 Marios Kogias
            sg = util.get_security_group(int(gid))
129 a1713485 Marios Kogias
            sg_list.append(sg)
130 f16aa9e6 Marios Kogias
131 0069a20c Marios Kogias
    new_port = ports.create(network, vm, security_groups=sg_list)
132 593851e0 Buildbot
133 5db2001a Marios Kogias
    response = render_port(request, port_to_dict(new_port), status=201)
134 593851e0 Buildbot
135 593851e0 Buildbot
    return response
136 593851e0 Buildbot
137 593851e0 Buildbot
138 5db2001a Marios Kogias
@api.api_method(http_method='GET', user_required=True, logger=log)
139 5db2001a Marios Kogias
def get_port_details(request, port_id):
140 5db2001a Marios Kogias
    log.debug('get_port_details %s', port_id)
141 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq)
142 5db2001a Marios Kogias
    return render_port(request, port_to_dict(port))
143 5db2001a Marios Kogias
144 5db2001a Marios Kogias
145 5db2001a Marios Kogias
@api.api_method(http_method='PUT', user_required=True, logger=log)
146 5db2001a Marios Kogias
def update_port(request, port_id):
147 5db2001a Marios Kogias
    '''
148 5db2001a Marios Kogias
    You can update only name, security_groups
149 5db2001a Marios Kogias
    '''
150 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq, for_update=True)
151 5db2001a Marios Kogias
    req = api.utils.get_request_dict(request)
152 5db2001a Marios Kogias
153 5db2001a Marios Kogias
    port_info = api.utils.get_attribute(req, "port", required=True)
154 5db2001a Marios Kogias
    name = api.utils.get_attribute(port_info, "name", required=False)
155 5db2001a Marios Kogias
156 5db2001a Marios Kogias
    if name:
157 5db2001a Marios Kogias
        port.name = name
158 5db2001a Marios Kogias
159 5db2001a Marios Kogias
    security_groups = api.utils.get_attribute(port_info, "security_groups",
160 5db2001a Marios Kogias
                                              required=False)
161 5db2001a Marios Kogias
    if security_groups:
162 5db2001a Marios Kogias
        sg_list = []
163 5db2001a Marios Kogias
        #validate security groups
164 5db2001a Marios Kogias
        for gid in security_groups:
165 a1713485 Marios Kogias
            sg = util.get_security_group(int(gid))
166 a1713485 Marios Kogias
            sg_list.append(sg)
167 5db2001a Marios Kogias
168 5db2001a Marios Kogias
        #clear the old security groups
169 5db2001a Marios Kogias
        port.security_groups.clear()
170 5db2001a Marios Kogias
171 5db2001a Marios Kogias
        #add the new groups
172 5db2001a Marios Kogias
        port.security_groups.add(*sg_list)
173 5db2001a Marios Kogias
174 5db2001a Marios Kogias
    port.save()
175 5db2001a Marios Kogias
    return render_port(request, port_to_dict(port), 200)
176 5db2001a Marios Kogias
177 5db2001a Marios Kogias
178 5db2001a Marios Kogias
@api.api_method(http_method='DELETE', user_required=True, logger=log)
179 5db2001a Marios Kogias
@transaction.commit_on_success
180 5db2001a Marios Kogias
def delete_port(request, port_id):
181 5db2001a Marios Kogias
    log.info('delete_port %s', port_id)
182 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq, for_update=True)
183 5db2001a Marios Kogias
    '''
184 5db2001a Marios Kogias
    FIXME delete the port
185 5db2001a Marios Kogias
    skip the backend part...
186 5db2001a Marios Kogias
    release the ips associated with the port
187 5db2001a Marios Kogias
    '''
188 5db2001a Marios Kogias
    return HttpResponse(status=204)
189 5db2001a Marios Kogias
190 593851e0 Buildbot
#util functions
191 593851e0 Buildbot
192 593851e0 Buildbot
193 593851e0 Buildbot
def port_to_dict(port, detail=True):
194 593851e0 Buildbot
    d = {'id': str(port.id), 'name': port.name}
195 593851e0 Buildbot
    if detail:
196 593851e0 Buildbot
        d['user_id'] = port.network.userid
197 593851e0 Buildbot
        d['tenant_id'] = port.network.userid
198 593851e0 Buildbot
        d['device_id'] = str(port.machine.id)
199 593851e0 Buildbot
        d['admin_state_up'] = True
200 593851e0 Buildbot
        d['mac_address'] = port.mac
201 593851e0 Buildbot
        d['status'] = port.state
202 593851e0 Buildbot
        d['device_owner'] = port.device_owner
203 593851e0 Buildbot
        d['network_id'] = str(port.network.id)
204 5db2001a Marios Kogias
        d['updated'] = api.utils.isoformat(port.updated)
205 5db2001a Marios Kogias
        d['created'] = api.utils.isoformat(port.created)
206 593851e0 Buildbot
        d['fixed_ips'] = []
207 593851e0 Buildbot
        for ip in port.ips.all():
208 593851e0 Buildbot
            d['fixed_ips'].append({"ip_address": ip.address,
209 9f6760ee Christos Stavrakakis
                                   "subnet": str(ip.subnet.id)})
210 5db2001a Marios Kogias
        sg_list = list(port.security_groups.values_list('id', flat=True))
211 5db2001a Marios Kogias
        d['security_groups'] = map(str, sg_list)
212 5db2001a Marios Kogias
213 593851e0 Buildbot
    return d
214 593851e0 Buildbot
215 593851e0 Buildbot
216 593851e0 Buildbot
def render_port(request, portdict, status=200):
217 593851e0 Buildbot
    if request.serialization == 'xml':
218 5db2001a Marios Kogias
        data = render_to_string('port.xml', {'port': portdict})
219 593851e0 Buildbot
    else:
220 593851e0 Buildbot
        data = json.dumps({'port': portdict})
221 593851e0 Buildbot
    return HttpResponse(data, status=status)