Statistics
| Branch: | Tag: | Revision:

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

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 86961519 Christos Stavrakakis
#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 86961519 Christos Stavrakakis
from synnefo.db.models import NetworkInterface
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 86961519 Christos Stavrakakis
        machine__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 86961519 Christos Stavrakakis
    vm = util.get_vm(dev_id, user_id, non_deleted=True, non_suspended=True)
114 f16aa9e6 Marios Kogias
115 f16aa9e6 Marios Kogias
    name = api.utils.get_attribute(port_dict, "name", required=False)
116 f16aa9e6 Marios Kogias
    if name is None:
117 f16aa9e6 Marios Kogias
        name = ""
118 f16aa9e6 Marios Kogias
119 f16aa9e6 Marios Kogias
    security_groups = api.utils.get_attribute(port_dict,
120 f16aa9e6 Marios Kogias
                                              "security_groups",
121 f16aa9e6 Marios Kogias
                                              required=False)
122 f16aa9e6 Marios Kogias
    #validate security groups
123 f16aa9e6 Marios Kogias
    # like get security group from db
124 a1713485 Marios Kogias
    sg_list = []
125 f16aa9e6 Marios Kogias
    if security_groups:
126 f16aa9e6 Marios Kogias
        for gid in security_groups:
127 a1713485 Marios Kogias
            sg = util.get_security_group(int(gid))
128 a1713485 Marios Kogias
            sg_list.append(sg)
129 f16aa9e6 Marios Kogias
130 0069a20c Marios Kogias
    new_port = ports.create(network, vm, security_groups=sg_list)
131 593851e0 Buildbot
132 5db2001a Marios Kogias
    response = render_port(request, port_to_dict(new_port), status=201)
133 593851e0 Buildbot
134 593851e0 Buildbot
    return response
135 593851e0 Buildbot
136 593851e0 Buildbot
137 5db2001a Marios Kogias
@api.api_method(http_method='GET', user_required=True, logger=log)
138 5db2001a Marios Kogias
def get_port_details(request, port_id):
139 5db2001a Marios Kogias
    log.debug('get_port_details %s', port_id)
140 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq)
141 5db2001a Marios Kogias
    return render_port(request, port_to_dict(port))
142 5db2001a Marios Kogias
143 5db2001a Marios Kogias
144 5db2001a Marios Kogias
@api.api_method(http_method='PUT', user_required=True, logger=log)
145 5db2001a Marios Kogias
def update_port(request, port_id):
146 5db2001a Marios Kogias
    '''
147 5db2001a Marios Kogias
    You can update only name, security_groups
148 5db2001a Marios Kogias
    '''
149 5db2001a Marios Kogias
    port = util.get_port(port_id, request.user_uniq, for_update=True)
150 5db2001a Marios Kogias
    req = api.utils.get_request_dict(request)
151 5db2001a Marios Kogias
152 5db2001a Marios Kogias
    port_info = api.utils.get_attribute(req, "port", required=True)
153 5db2001a Marios Kogias
    name = api.utils.get_attribute(port_info, "name", required=False)
154 5db2001a Marios Kogias
155 5db2001a Marios Kogias
    if name:
156 5db2001a Marios Kogias
        port.name = name
157 5db2001a Marios Kogias
158 5db2001a Marios Kogias
    security_groups = api.utils.get_attribute(port_info, "security_groups",
159 5db2001a Marios Kogias
                                              required=False)
160 5db2001a Marios Kogias
    if security_groups:
161 5db2001a Marios Kogias
        sg_list = []
162 5db2001a Marios Kogias
        #validate security groups
163 5db2001a Marios Kogias
        for gid in security_groups:
164 a1713485 Marios Kogias
            sg = util.get_security_group(int(gid))
165 a1713485 Marios Kogias
            sg_list.append(sg)
166 5db2001a Marios Kogias
167 5db2001a Marios Kogias
        #clear the old security groups
168 5db2001a Marios Kogias
        port.security_groups.clear()
169 5db2001a Marios Kogias
170 5db2001a Marios Kogias
        #add the new groups
171 5db2001a Marios Kogias
        port.security_groups.add(*sg_list)
172 5db2001a Marios Kogias
173 5db2001a Marios Kogias
    port.save()
174 5db2001a Marios Kogias
    return render_port(request, port_to_dict(port), 200)
175 5db2001a Marios Kogias
176 5db2001a Marios Kogias
177 5db2001a Marios Kogias
@api.api_method(http_method='DELETE', user_required=True, logger=log)
178 5db2001a Marios Kogias
@transaction.commit_on_success
179 5db2001a Marios Kogias
def delete_port(request, port_id):
180 5db2001a Marios Kogias
    log.info('delete_port %s', port_id)
181 86961519 Christos Stavrakakis
    user_id = request.user_uniq
182 86961519 Christos Stavrakakis
    port = util.get_port(port_id, user_id, for_update=True)
183 86961519 Christos Stavrakakis
    ports.delete(port)
184 5db2001a Marios Kogias
    return HttpResponse(status=204)
185 5db2001a Marios Kogias
186 593851e0 Buildbot
#util functions
187 593851e0 Buildbot
188 593851e0 Buildbot
189 593851e0 Buildbot
def port_to_dict(port, detail=True):
190 593851e0 Buildbot
    d = {'id': str(port.id), 'name': port.name}
191 593851e0 Buildbot
    if detail:
192 86961519 Christos Stavrakakis
        user_id = port.machine.id
193 86961519 Christos Stavrakakis
        d['user_id'] = user_id
194 86961519 Christos Stavrakakis
        d['tenant_id'] = user_id
195 593851e0 Buildbot
        d['device_id'] = str(port.machine.id)
196 86961519 Christos Stavrakakis
        # TODO: Change this based on the status of VM
197 593851e0 Buildbot
        d['admin_state_up'] = True
198 593851e0 Buildbot
        d['mac_address'] = port.mac
199 593851e0 Buildbot
        d['status'] = port.state
200 593851e0 Buildbot
        d['device_owner'] = port.device_owner
201 593851e0 Buildbot
        d['network_id'] = str(port.network.id)
202 5db2001a Marios Kogias
        d['updated'] = api.utils.isoformat(port.updated)
203 5db2001a Marios Kogias
        d['created'] = api.utils.isoformat(port.created)
204 593851e0 Buildbot
        d['fixed_ips'] = []
205 593851e0 Buildbot
        for ip in port.ips.all():
206 593851e0 Buildbot
            d['fixed_ips'].append({"ip_address": ip.address,
207 9f6760ee Christos Stavrakakis
                                   "subnet": str(ip.subnet.id)})
208 5db2001a Marios Kogias
        sg_list = list(port.security_groups.values_list('id', flat=True))
209 5db2001a Marios Kogias
        d['security_groups'] = map(str, sg_list)
210 5db2001a Marios Kogias
211 593851e0 Buildbot
    return d
212 593851e0 Buildbot
213 593851e0 Buildbot
214 593851e0 Buildbot
def render_port(request, portdict, status=200):
215 593851e0 Buildbot
    if request.serialization == 'xml':
216 5db2001a Marios Kogias
        data = render_to_string('port.xml', {'port': portdict})
217 593851e0 Buildbot
    else:
218 593851e0 Buildbot
        data = json.dumps({'port': portdict})
219 593851e0 Buildbot
    return HttpResponse(data, status=status)