Revision 92d2d1ce snf-cyclades-app/synnefo/logic/servers.py
b/snf-cyclades-app/synnefo/logic/servers.py | ||
---|---|---|
13 | 13 |
from synnefo.logic import backend |
14 | 14 |
from synnefo.logic.backend_allocator import BackendAllocator |
15 | 15 |
from synnefo.db.models import (NetworkInterface, VirtualMachine, Network, |
16 |
VirtualMachineMetadata, IPAddress) |
|
16 |
VirtualMachineMetadata, IPAddress, Subnet) |
|
17 |
from synnefo.db import query as db_query |
|
17 | 18 |
|
18 | 19 |
from vncauthproxy.client import request_forwarding as request_vnc_forwarding |
19 | 20 |
|
... | ... | |
242 | 243 |
""" |
243 | 244 |
attachments = [] |
244 | 245 |
for network_id in settings.DEFAULT_INSTANCE_NETWORKS: |
245 |
network, address = None, None |
|
246 |
network, ipaddress = None, None
|
|
246 | 247 |
if network_id == "SNF:ANY_PUBLIC": |
247 |
network, address = util.allocate_public_address(backend=vm.backend) |
|
248 |
ipaddress = util.allocate_public_address(backend=vm.backend, |
|
249 |
userid=userid) |
|
250 |
network = ipaddress.network |
|
248 | 251 |
else: |
249 | 252 |
try: |
250 | 253 |
network = Network.objects.get(id=network_id, deleted=False) |
... | ... | |
254 | 257 |
" network '%s'" % network_id |
255 | 258 |
log.error(msg) |
256 | 259 |
raise Exception(msg) |
257 |
if network.subnet is not None and network.dhcp: |
|
258 |
address = util.get_network_free_address(network) |
|
259 |
attachments.append((network, address)) |
|
260 |
try: |
|
261 |
subnet = network.subnets.get(ipversion=4, dhcp=True) |
|
262 |
ipaddress = util.get_network_free_address(subnet, userid) |
|
263 |
except Subnet.DoesNotExist: |
|
264 |
ipaddress = None |
|
265 |
attachments.append((network, ipaddress)) |
|
260 | 266 |
for address in floating_ips: |
261 |
floating_ip = add_floating_ip_to_vm(vm=vm, address=address) |
|
262 |
network = floating_ip.network |
|
263 |
attachments.append((network, address)) |
|
267 |
floating_ip = get_floating_ip(userid=vm.userid, address=address) |
|
268 |
attachments.append((floating_ip.network, floating_ip)) |
|
264 | 269 |
for network_id in private_networks: |
265 |
network, address = None, None |
|
266 | 270 |
network = util.get_network(network_id, userid, non_deleted=True) |
267 | 271 |
if network.public: |
268 | 272 |
raise faults.Forbidden("Can not connect to public network") |
269 |
if network.dhcp: |
|
270 |
address = util.get_network_free_address(network) |
|
271 |
attachments.append((network, address)) |
|
273 |
attachments.append((network, ipaddress)) |
|
272 | 274 |
|
273 | 275 |
nics = [] |
274 |
for index, (network, address) in enumerate(attachments): |
|
276 |
for index, (network, ipaddress) in enumerate(attachments):
|
|
275 | 277 |
# Create VM's public NIC. Do not wait notification form ganeti |
276 | 278 |
# hooks to create this NIC, because if the hooks never run (e.g. |
277 | 279 |
# building error) the VM's public IP address will never be |
278 | 280 |
# released! |
279 |
nic = NetworkInterface.objects.create(machine=vm, network=network,
|
|
280 |
index=index, ipv4=address,
|
|
281 |
nic = NetworkInterface.objects.create(userid=userid, machine=vm,
|
|
282 |
network=network, index=index,
|
|
281 | 283 |
state="BUILDING") |
284 |
if ipaddress is not None: |
|
285 |
ipaddress.nic = nic |
|
286 |
ipaddress.save() |
|
282 | 287 |
nics.append(nic) |
283 | 288 |
return nics |
284 | 289 |
|
... | ... | |
427 | 432 |
|
428 | 433 |
@server_command("CONNECT") |
429 | 434 |
def add_floating_ip(vm, address): |
430 |
floating_ip = add_floating_ip_to_vm(vm, address)
|
|
435 |
floating_ip = get_floating_ip(userid=vm.userid, address=address)
|
|
431 | 436 |
nic = NetworkInterface.objects.create(machine=vm, |
432 | 437 |
network=floating_ip.network, |
433 | 438 |
ipv4=floating_ip.ipv4, |
... | ... | |
438 | 443 |
return backend.connect_to_network(vm, nic) |
439 | 444 |
|
440 | 445 |
|
441 |
def add_floating_ip_to_vm(vm, address):
|
|
442 |
"""Get a floating IP by it's address and add it to VirtualMachine.
|
|
446 |
def get_floating_ip(userid, address):
|
|
447 |
"""Get a floating IP by it's address. |
|
443 | 448 |
|
444 |
Helper function for looking up a IPAddress by it's address and associating |
|
445 |
it with a VirtualMachine object (without adding the NIC in the Ganeti |
|
446 |
backend!). This function also checks if the floating IP is currently used |
|
447 |
by any instance and if it is available in the Backend that hosts the VM. |
|
449 |
Helper function for looking up a IPAddress by it's address. This function |
|
450 |
also checks if the floating IP is currently used by any instance. |
|
448 | 451 |
|
449 | 452 |
""" |
450 |
user_id = vm.userid |
|
451 | 453 |
try: |
452 | 454 |
# Get lock in VM, to guarantee that floating IP will only by assigned |
453 | 455 |
# once |
454 |
floating_ip = IPAddress.objects.select_for_update()\
|
|
455 |
.get(userid=user_id, ipv4=address,
|
|
456 |
deleted=False)
|
|
456 |
floating_ip = db_query.get_user_floating_ip(userid=userid,
|
|
457 |
address=address,
|
|
458 |
for_update=True)
|
|
457 | 459 |
except IPAddress.DoesNotExist: |
458 |
raise faults.ItemNotFound("Floating IP '%s' does not exist" % address) |
|
460 |
raise faults.ItemNotFound("Floating IP with address '%s' does not" |
|
461 |
" exist" % address) |
|
459 | 462 |
|
460 |
if floating_ip.in_use():
|
|
463 |
if floating_ip.nic is not None:
|
|
461 | 464 |
raise faults.Conflict("Floating IP '%s' already in use" % |
462 | 465 |
floating_ip.id) |
463 | 466 |
|
464 |
bnet = floating_ip.network.backend_networks.filter(backend=vm.backend_id) |
|
465 |
if not bnet.exists(): |
|
466 |
msg = "Network '%s' is a floating IP pool, but it not connected"\ |
|
467 |
" to backend '%s'" % (floating_ip.network, vm.backend) |
|
468 |
raise faults.ServiceUnavailable(msg) |
|
469 |
|
|
470 |
floating_ip.machine = vm |
|
471 |
floating_ip.save() |
|
472 | 467 |
return floating_ip |
473 | 468 |
|
474 | 469 |
|
475 | 470 |
@server_command("DISCONNECT") |
476 | 471 |
def remove_floating_ip(vm, address): |
477 |
user_id = vm.userid |
|
478 | 472 |
try: |
479 |
floating_ip = IPAddress.objects.select_for_update()\
|
|
480 |
.get(userid=user_id, ipv4=address,
|
|
481 |
deleted=False, machine=vm)
|
|
473 |
floating_ip = db_query.get_server_floating_ip(server=vm,
|
|
474 |
address=address,
|
|
475 |
for_update=True)
|
|
482 | 476 |
except IPAddress.DoesNotExist: |
483 |
raise faults.ItemNotFound("Floating IP '%s' does not exist" % address) |
|
484 |
|
|
485 |
try: |
|
486 |
nic = NetworkInterface.objects.get(machine=vm, ipv4=address) |
|
487 |
except NetworkInterface.DoesNotExist: |
|
488 |
raise faults.ItemNotFound("Floating IP '%s' is not attached to" |
|
489 |
"VM '%s'" % (floating_ip, vm)) |
|
477 |
raise faults.BadRequest("Server '%s' has no floating ip with" |
|
478 |
" address '%s'" % (vm, address)) |
|
490 | 479 |
|
480 |
nic = floating_ip.nic |
|
491 | 481 |
log.info("Removing NIC %s from VM %s. Floating IP '%s'", str(nic.index), |
492 | 482 |
vm, floating_ip) |
493 | 483 |
|
Also available in: Unified diff