Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.6 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
    sg_list = []
125
    security_groups = api.utils.get_attribute(port_dict,
126
                                              "security_groups",
127
                                              required=False)
128
    #validate security groups
129
    # like get security group from db
130
    if security_groups:
131
        for gid in security_groups:
132
            try:
133
                sg = SecurityGroup.objects.get(id=int(gid))
134
                sg_list.append(sg)
135
            except (ValueError, SecurityGroup.DoesNotExist):
136
                raise api.faults.ItemNotFound("Not valid security group")
137

    
138
    new_port = ports.create(user_id, network, vm, security_groups=sg_list)
139

    
140
    response = render_port(request, port_to_dict(new_port), status=201)
141

    
142
    return response
143

    
144

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

    
151

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

    
160
    port_info = api.utils.get_attribute(req, "port", required=True)
161
    name = api.utils.get_attribute(port_info, "name", required=False)
162

    
163
    if name:
164
        port.name = name
165

    
166
    security_groups = api.utils.get_attribute(port_info, "security_groups",
167
                                              required=False)
168
    if security_groups:
169
        sg_list = []
170
        #validate security groups
171
        # like get security group from db
172
        for gid in security_groups:
173
            try:
174
                sg = SecurityGroup.objects.get(id=int(gid))
175
                sg_list.append(sg)
176
            except (ValueError, SecurityGroup.DoesNotExist):
177
                raise api.faults.ItemNotFound("Not valid security group")
178

    
179
        #clear the old security groups
180
        port.security_groups.clear()
181

    
182
        #add the new groups
183
        port.security_groups.add(*sg_list)
184

    
185
    port.save()
186
    return render_port(request, port_to_dict(port), 200)
187

    
188

    
189
@api.api_method(http_method='DELETE', user_required=True, logger=log)
190
@transaction.commit_on_success
191
def delete_port(request, port_id):
192
    log.info('delete_port %s', port_id)
193
    port = util.get_port(port_id, request.user_uniq, for_update=True)
194
    '''
195
    FIXME delete the port
196
    skip the backend part...
197
    release the ips associated with the port
198
    '''
199
    return HttpResponse(status=204)
200

    
201
#util functions
202

    
203

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

    
224
    return d
225

    
226

    
227
def render_port(request, portdict, status=200):
228
    if request.serialization == 'xml':
229
        data = render_to_string('port.xml', {'port': portdict})
230
    else:
231
        data = json.dumps({'port': portdict})
232
    return HttpResponse(data, status=status)