Statistics
| Branch: | Tag: | Revision:

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

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.template.loader import render_to_string
40

    
41
from snf_django.lib import api
42

    
43
from synnefo.api import util
44
from synnefo.db.models import NetworkInterface
45
from synnefo.logic import ports
46

    
47
from logging import getLogger
48

    
49
log = getLogger(__name__)
50

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

    
56

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

    
65

    
66
def port_demux(request, port_id):
67

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

    
77

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

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

    
83
    user_ports = NetworkInterface.objects.filter(
84
        machine__userid=request.user_uniq)
85

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

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

    
95
    return HttpResponse(data, status=200)
96

    
97

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

    
104
    port_dict = api.utils.get_attribute(req, "port")
105
    net_id = api.utils.get_attribute(port_dict, "network_id")
106
    dev_id = api.utils.get_attribute(port_dict, "device_id")
107

    
108
    network = util.get_network(net_id, user_id, non_deleted=True)
109

    
110
    ipaddress = None
111
    if network.public:
112
        fixed_ips = api.utils.get_attribute(port_dict, "fixed_ips",
113
                                            required=True)
114
        fip_address = api.utils.get_attribute(fixed_ips[0], 'ip_address',
115
                                              required=True)
116
        ipaddress = util.get_floating_ip_by_address(user_id, fip_address,
117
                                                    for_update=True)
118

    
119
    vm = util.get_vm(dev_id, user_id, for_update=True, non_deleted=True,
120
                     non_suspended=True)
121

    
122
    name = api.utils.get_attribute(port_dict, "name", required=False)
123
    if name is None:
124
        name = ""
125

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

    
137
    new_port = ports.create(network, vm, ipaddress, security_groups=sg_list)
138

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

    
141
    return response
142

    
143

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

    
150

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

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

    
162
    if name:
163
        port.name = name
164

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

    
174
        #clear the old security groups
175
        port.security_groups.clear()
176

    
177
        #add the new groups
178
        port.security_groups.add(*sg_list)
179

    
180
    port.save()
181
    return render_port(request, port_to_dict(port), 200)
182

    
183

    
184
@api.api_method(http_method='DELETE', user_required=True, logger=log)
185
@transaction.commit_on_success
186
def delete_port(request, port_id):
187
    log.info('delete_port %s', port_id)
188
    user_id = request.user_uniq
189
    port = util.get_port(port_id, user_id, for_update=True)
190
    ports.delete(port)
191
    return HttpResponse(status=204)
192

    
193
#util functions
194

    
195

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

    
218
    return d
219

    
220

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