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) |