Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.3 kB)

1
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from django.conf import settings
35
from django.conf.urls import patterns
36
from django.http import HttpResponse
37
from django.utils import simplejson as json
38
from django.db import transaction
39
from django.db.models import Q
40
from django.template.loader import render_to_string
41

    
42
from snf_django.lib import api
43

    
44
from synnefo.api import util
45
from synnefo.db.models import NetworkInterface, SecurityGroup, IPAddress
46
from synnefo.logic import ports
47

    
48
from logging import getLogger
49

    
50
log = getLogger(__name__)
51

    
52
urlpatterns = patterns(
53
    'synnefo.api.ports',
54
    (r'^(?:/|.json|.xml)?$', 'demux'),
55
    (r'^/([-\w]+)(?:/|.json|.xml)?$', 'port_demux'))
56

    
57

    
58
def demux(request):
59
    if request.method == 'GET':
60
        return list_ports(request)
61
    elif request.method == 'POST':
62
        return create_port(request)
63
    else:
64
        return api.api_method_not_allowed(request)
65

    
66

    
67
def port_demux(request, port_id):
68

    
69
    if request.method == 'GET':
70
        return get_port_details(request, port_id)
71
    elif request.method == 'DELETE':
72
        return delete_port(request, port_id)
73
    elif request.method == 'PUT':
74
        return update_port(request, port_id)
75
    else:
76
        return api.api_method_not_allowed(request)
77

    
78

    
79
@api.api_method(http_method='GET', user_required=True, logger=log)
80
def list_ports(request, detail=False):
81

    
82
    log.debug('list_ports detail=%s', detail)
83

    
84
    user_ports = NetworkInterface.objects.filter(
85
        network__userid=request.user_uniq)
86

    
87
    port_dicts = [port_to_dict(port, detail)
88
             for port in user_ports.order_by('id')]
89

    
90
    if request.serialization == 'xml':
91
        data = render_to_string('list_ports.xml', {
92
            "ports": port_dicts})
93
    else:
94
        data = json.dumps({'ports': port_dicts})
95

    
96
    return HttpResponse(data, status=200)
97

    
98

    
99
@api.api_method(http_method='POST', user_required=True, logger=log)
100
def create_port(request):
101
    '''
102
    '''
103
    user_id = request.user_uniq
104
    req = api.utils.get_request_dict(request)
105
    log.info('create_port %s', req)
106

    
107
    port_dict = api.utils.get_attribute(req, "port")
108
    net_id = api.utils.get_attribute(port_dict, "network_id")
109
    dev_id = api.utils.get_attribute(port_dict, "device_id")
110

    
111
    network = util.get_network(net_id, request.user_uniq, non_deleted=True)
112

    
113
    if network.public:
114
        raise api.faults.Forbidden('forbidden')
115

    
116

    
117
    vm = util.get_vm(dev_id, request.user_uniq)
118

    
119
    name = api.utils.get_attribute(port_dict, "name", required=False)
120

    
121
    if name is None:
122
        name = ""
123

    
124
    security_groups = api.utils.get_attribute(port_dict,
125
                                              "security_groups",
126
                                              required=False)
127
    #validate security groups
128
    # like get security group from db
129
    sg_list = []
130
    if security_groups:
131
        for gid in security_groups:
132
            sg = util.get_security_group(int(gid))
133
            sg_list.append(sg)
134

    
135
    new_port = ports.create(network, vm, security_groups=sg_list)
136

    
137
    response = render_port(request, port_to_dict(new_port), status=201)
138

    
139
    return response
140

    
141

    
142
@api.api_method(http_method='GET', user_required=True, logger=log)
143
def get_port_details(request, port_id):
144
    log.debug('get_port_details %s', port_id)
145
    port = util.get_port(port_id, request.user_uniq)
146
    return render_port(request, port_to_dict(port))
147

    
148

    
149
@api.api_method(http_method='PUT', user_required=True, logger=log)
150
def update_port(request, port_id):
151
    '''
152
    You can update only name, security_groups
153
    '''
154
    port = util.get_port(port_id, request.user_uniq, for_update=True)
155
    req = api.utils.get_request_dict(request)
156

    
157
    port_info = api.utils.get_attribute(req, "port", required=True)
158
    name = api.utils.get_attribute(port_info, "name", required=False)
159

    
160
    if name:
161
        port.name = name
162

    
163
    security_groups = api.utils.get_attribute(port_info, "security_groups",
164
                                              required=False)
165
    if security_groups:
166
        sg_list = []
167
        #validate security groups
168
        for gid in security_groups:
169
            sg = util.get_security_group(int(gid))
170
            sg_list.append(sg)
171

    
172
        #clear the old security groups
173
        port.security_groups.clear()
174

    
175
        #add the new groups
176
        port.security_groups.add(*sg_list)
177

    
178
    port.save()
179
    return render_port(request, port_to_dict(port), 200)
180

    
181

    
182
@api.api_method(http_method='DELETE', user_required=True, logger=log)
183
@transaction.commit_on_success
184
def delete_port(request, port_id):
185
    log.info('delete_port %s', port_id)
186
    port = util.get_port(port_id, request.user_uniq, for_update=True)
187
    '''
188
    FIXME delete the port
189
    skip the backend part...
190
    release the ips associated with the port
191
    '''
192
    return HttpResponse(status=204)
193

    
194
#util functions
195

    
196

    
197
def port_to_dict(port, detail=True):
198
    d = {'id': str(port.id), 'name': port.name}
199
    if detail:
200
        d['user_id'] = port.network.userid
201
        d['tenant_id'] = port.network.userid
202
        d['device_id'] = str(port.machine.id)
203
        d['admin_state_up'] = True
204
        d['mac_address'] = port.mac
205
        d['status'] = port.state
206
        d['device_owner'] = port.device_owner
207
        d['network_id'] = str(port.network.id)
208
        d['updated'] = api.utils.isoformat(port.updated)
209
        d['created'] = api.utils.isoformat(port.created)
210
        d['fixed_ips'] = []
211
        for ip in port.ips.all():
212
            d['fixed_ips'].append({"ip_address": ip.address,
213
                                      "subnet": str(ip.subnet.id)})
214
        sg_list = list(port.security_groups.values_list('id', flat=True))
215
        d['security_groups'] = map(str, sg_list)
216

    
217
    return d
218

    
219

    
220
def render_port(request, portdict, status=200):
221
    if request.serialization == 'xml':
222
        data = render_to_string('port.xml', {'port': portdict})
223
    else:
224
        data = json.dumps({'port': portdict})
225
    return HttpResponse(data, status=status)