root / snf-cyclades-app / synnefo / neutron / router_views.py @ 2e0916f2
History | View | Annotate | Download (10.3 kB)
1 |
from django.http import HttpResponse |
---|---|
2 |
from django.utils import simplejson as json |
3 |
from django.db import transaction |
4 |
from django.db.models import Q |
5 |
from synnefo.db.pools import EmptyPool |
6 |
from synnefo.db.utils import validate_mac |
7 |
from django.conf import settings |
8 |
from snf_django.lib import api |
9 |
from snf_django.lib.api import utils |
10 |
from synnefo.logic import backend |
11 |
from django.template.loader import render_to_string |
12 |
from synnefo.api import util |
13 |
|
14 |
from synnefo.db.models import VirtualMachine |
15 |
import models |
16 |
from logging import getLogger |
17 |
|
18 |
import network_views as nv |
19 |
#from synnefo.logic import servers
|
20 |
|
21 |
log = getLogger(__name__) |
22 |
|
23 |
|
24 |
def demux(request): |
25 |
if request.method == 'GET': |
26 |
#return HttpResponse("list routers")
|
27 |
return list_routers(request)
|
28 |
elif request.method == 'POST': |
29 |
#return create_router(request)
|
30 |
return HttpResponse("create router") |
31 |
else:
|
32 |
return api.api_method_not_allowed(request)
|
33 |
|
34 |
|
35 |
def router_demux(request, offset): |
36 |
if request.method == 'GET': |
37 |
#return HttpResponse("get single router")
|
38 |
return get_router(request, offset)
|
39 |
elif request.method == 'DELETE': |
40 |
#return HttpResponse("delete router")
|
41 |
return delete_router(request, offset)
|
42 |
elif request.method == 'PUT': |
43 |
#return HttpResponse("put router")
|
44 |
return update_router(request,offset)
|
45 |
else:
|
46 |
return api.api_method_not_allowed(request)
|
47 |
|
48 |
|
49 |
def rinterface_demux(request, offset1, offset2): |
50 |
if request.method == 'PUT': |
51 |
if offset2 == "add_router_interface": |
52 |
#return HttpResponse("add interface")
|
53 |
return add_interface(request, offset2)
|
54 |
elif offset2 == "remove_router_interface": |
55 |
#return HttpResponse("remove interface")
|
56 |
return remove_interface(request, offset22)
|
57 |
else:
|
58 |
return api.api_method_not_allowed(request)
|
59 |
|
60 |
|
61 |
@api.api_method(http_method='GET', user_required=True, logger=log) |
62 |
def list_routers(request): |
63 |
log.debug('list_routers')
|
64 |
|
65 |
user_routers = VirtualMachine.objects.filter(userid=request.user_uniq, router=True)
|
66 |
|
67 |
user_routers = utils.filter_modified_since(request, objects=user_routers) |
68 |
|
69 |
routers = [router_to_dict(router) |
70 |
for router in user_routers.order_by('id')] |
71 |
|
72 |
if request.serialization == 'xml': |
73 |
data = render_to_string('list_routers.xml', {
|
74 |
'routers': routers})
|
75 |
else:
|
76 |
data = json.dumps({"routers": routers})
|
77 |
|
78 |
return HttpResponse(data, status=200) |
79 |
|
80 |
'''
|
81 |
@api.api_method(http_method='POST', user_required=True, logger=log)
|
82 |
@transaction.commit_manually
|
83 |
def create_router(request):
|
84 |
user_id = request.user_uniq
|
85 |
req = utils.get_request_dict(request)
|
86 |
|
87 |
try:
|
88 |
server = req['router']
|
89 |
name = server['name']
|
90 |
except (KeyError, AssertionError):
|
91 |
raise api.faults.BadRequest("Malformed request")
|
92 |
metadata = server.get('metadata', {})
|
93 |
assert isinstance(metadata, dict)
|
94 |
image_id = server['imageRef']
|
95 |
flavor_id = server['flavorRef']
|
96 |
personality = server.get('personality', [])
|
97 |
assert isinstance(personality, list)
|
98 |
private_networks = server.get("networks", [])
|
99 |
assert isinstance(private_networks, list)
|
100 |
floating_ips = server.get("floating_ips", [])
|
101 |
assert isinstance(floating_ips, list)
|
102 |
# Verify that personalities are well-formed
|
103 |
util.verify_personality(personality)
|
104 |
# Get image information
|
105 |
image = util.get_image_dict(image_id, user_id)
|
106 |
# Get flavor (ensure it is active)
|
107 |
flavor = util.get_flavor(flavor_id, include_deleted=False)
|
108 |
# Generate password
|
109 |
password = util.random_password()
|
110 |
vm = servers.create(user_id,
|
111 |
name,
|
112 |
#password,
|
113 |
#flavor,
|
114 |
#image,
|
115 |
#metadata=metadata,
|
116 |
#personality=personality,
|
117 |
#private_networks=private_networks,
|
118 |
#floating_ips=floating_ips
|
119 |
)
|
120 |
|
121 |
server = router_to_dict(vm, detail=True)
|
122 |
server['status'] = 'BUILD'
|
123 |
server['adminPass'] = password
|
124 |
|
125 |
response = render_router(request, server, status=202)
|
126 |
|
127 |
return response
|
128 |
|
129 |
|
130 |
'''
|
131 |
@api.api_method(http_method='GET', user_required=True, logger=log) |
132 |
def get_router(request, router_id): |
133 |
log.debug('get_router_details %s', router_id)
|
134 |
router = util.get_vm(router_id, request.user_uniq) |
135 |
|
136 |
router_dict = router_to_dict(router) |
137 |
return render_router(request, router_dict)
|
138 |
|
139 |
|
140 |
@api.api_method(http_method='DELETE', user_required=True, logger=log) |
141 |
@transaction.commit_on_success
|
142 |
def delete_router(request, router_id): |
143 |
log.debug('delete router %s', router_id)
|
144 |
router = util.get_vm(router_id, request.user_uniq) |
145 |
|
146 |
if router.neutron_networks.filter(public=False): |
147 |
return HttpResponse("There are internal interfaces on the router", status=409) |
148 |
|
149 |
#servers.destroy(router)
|
150 |
|
151 |
router.deleted = True
|
152 |
router.save() |
153 |
return HttpResponse(status=204) |
154 |
|
155 |
|
156 |
@api.api_method(http_method='PUT', user_required=True, logger=log) |
157 |
def update_router(request, router_id): |
158 |
log.debug('update router %s', router_id)
|
159 |
router = util.get_vm(router_id, request.user_uniq) |
160 |
|
161 |
req = utils.get_request_dict(request) |
162 |
try:
|
163 |
server = req['router']
|
164 |
except (KeyError, AssertionError): |
165 |
raise api.faults.BadRequest("Malformed request") |
166 |
|
167 |
try:
|
168 |
name = server['name']
|
169 |
router.name = name |
170 |
except KeyError: |
171 |
pass
|
172 |
|
173 |
try:
|
174 |
net = server['external_gateway_info']['network_id'] |
175 |
|
176 |
#find the new network
|
177 |
new_net = nv.get_network_fromdb(net, request.user_uniq) |
178 |
|
179 |
#disconnect from the old net
|
180 |
external_net = router.neutron_networks.filter(public=True)
|
181 |
if external_net:
|
182 |
#servers.disconnect(router, external_net[0])
|
183 |
mock_disconnect(router, external_net[0])
|
184 |
|
185 |
#connect to the new net
|
186 |
#servers.connect(router, new_net)
|
187 |
mock_connect(router, new_net) |
188 |
except KeyError: |
189 |
pass
|
190 |
|
191 |
router.save() |
192 |
routerdict = router_to_dict(router) |
193 |
return render_router(request, routerdict, 200) |
194 |
|
195 |
|
196 |
@api.api_method(http_method='PUT', user_required=True, logger=log) |
197 |
def add_interface(request, router_id): |
198 |
log.debug('add interface to router %s', router_id)
|
199 |
router = util.get_vm(router_id, request.user_uniq) |
200 |
|
201 |
router_info = utils.get_request_dict(request) |
202 |
|
203 |
subnet = False
|
204 |
try:
|
205 |
subnet_id = router_info["subnet_id"]
|
206 |
subnet = True
|
207 |
subnet_obj = subnet_views.get_subnet_fromdb(subnet_id, |
208 |
request.user_unique) |
209 |
except KeyError: |
210 |
pass
|
211 |
|
212 |
try:
|
213 |
port_id = router_info['port_id']
|
214 |
if subnet:
|
215 |
raise api.faults.BadRequest("Both subnet and port provided") |
216 |
try:
|
217 |
nic_obj = models.NetworkInteface.objects.get(id=port_id) |
218 |
except (ValueError, models.NetworkInteraface.DoesNotExist): |
219 |
raise api.faults.ItemNotFound('Port not found') |
220 |
if not nic_obj.ipv4: |
221 |
raise api.faults.BadRequest("No ip-address") |
222 |
if nic_obj.machine:
|
223 |
return HttpResponse(status=409) |
224 |
except KeyError: |
225 |
if not subnet: |
226 |
raise api.faults.BadRequest("Malformed request") |
227 |
|
228 |
if subnet:
|
229 |
#create nic with the subnet and add to the vm
|
230 |
nic = models.NetworkInteface(machine=router, |
231 |
subnet=subnet_obj, |
232 |
network=subnet_obj.network |
233 |
ipv4=subnet.gateway |
234 |
) |
235 |
nic.save() |
236 |
port_id = nic.id |
237 |
else:
|
238 |
#connect the nic
|
239 |
nic_obj.machine = router |
240 |
nic_obj.save() |
241 |
subnet_id = nic.subnet.id |
242 |
|
243 |
res = {"port_id":port_db.id,
|
244 |
"subnet_id":subnet_db.id
|
245 |
} |
246 |
|
247 |
data = json.dumps(res) |
248 |
return HttpResponse(data, status=200) |
249 |
|
250 |
@api.api_method(http_method='PUT', user_required=True, logger=log) |
251 |
def remove_interface(request, router_id): |
252 |
|
253 |
log.debug('remove interface from router %s', router_id)
|
254 |
router = util.get_vm(router_id, request.user_uniq) |
255 |
|
256 |
info = utils.get_request_dict(request) |
257 |
|
258 |
subnet = False
|
259 |
try:
|
260 |
subnet_id = info["subnet_id"]
|
261 |
subnet = True
|
262 |
subnet_db = subnet_views.get_subnet_fromdb(subnet_id, |
263 |
request.user_unique) |
264 |
except KeyError: |
265 |
pass
|
266 |
|
267 |
port = False
|
268 |
try:
|
269 |
port_id = info['port_id']
|
270 |
port = True
|
271 |
try:
|
272 |
nic_obj = models.NetworkInteface.objects.get(id=port_id) |
273 |
except (ValueError, models.NetworkInteraface.DoesNotExist): |
274 |
raise api.faults.ItemNotFound('Port not found') |
275 |
except KeyError: |
276 |
pass
|
277 |
|
278 |
if port and subnet: |
279 |
#validate port-subnet combination else return 409
|
280 |
#subnet must be the first of the port
|
281 |
if not port_db is subnet_db: |
282 |
return HttpResponse(status=409) |
283 |
|
284 |
if subnet:
|
285 |
#get the port
|
286 |
if not port_db: |
287 |
port_db = subnet_db.neutron_nics.get(machine=router) |
288 |
elif port:
|
289 |
#get the subnet
|
290 |
if not subnet_db: |
291 |
subnet_db = port_db.subnet |
292 |
else:
|
293 |
raise api.faults.BadRequest("Malformed request") |
294 |
|
295 |
res = {"id":str(router.id), |
296 |
"tenant_id":request.user_uniq,
|
297 |
"port_id":port_db.id,
|
298 |
"subnet_id":subnet_db.id
|
299 |
} |
300 |
|
301 |
port_db.delete() # need to add backend stuff
|
302 |
data = json.dumps(res) |
303 |
return HttpResponse(data, status=200) |
304 |
|
305 |
|
306 |
# util functions
|
307 |
|
308 |
|
309 |
def router_to_dict(router): |
310 |
d = {'id': str(router.id), 'name': router.name} |
311 |
d['user_id'] = router.userid
|
312 |
d['tenant_id'] = router.userid
|
313 |
d['admin_state_up'] = True |
314 |
external_net = router.neutron_networks.filter(public=True)
|
315 |
if external_net:
|
316 |
external_net = external_net[0]
|
317 |
d['external_gateway_info'] = {'network_id': external_net.id} |
318 |
else:
|
319 |
d['external_gateway_info'] = None |
320 |
return d
|
321 |
|
322 |
|
323 |
def render_router(request, routerdict, status=200): |
324 |
if request.serialization == 'xml': |
325 |
data = render_to_string('router.xml', {'router': routerdict}) |
326 |
else:
|
327 |
data = json.dumps({'router': routerdict})
|
328 |
return HttpResponse(data, status=status)
|
329 |
|
330 |
|
331 |
# mock functions
|
332 |
|
333 |
def mock_disconnect(router, net): |
334 |
nic = models.NetworkInterface.objects.get(network=net, machine=router) |
335 |
nic.delete() |
336 |
|
337 |
def mock_connect(router, net): |
338 |
nic = models.NetworkInterface(network=net, machine=router) |
339 |
nic.save() |