Revision bfb3f9c2 snf-cyclades-app/synnefo/logic/backend.py

b/snf-cyclades-app/synnefo/logic/backend.py
37 37
from synnefo.db.models import (Backend, VirtualMachine, Network,
38 38
                               BackendNetwork, BACKEND_STATUSES,
39 39
                               pooled_rapi_client, VirtualMachineDiagnostic,
40
                               Flavor, IPAddressLog)
40
                               Flavor, IPAddress, IPAddressLog)
41 41
from synnefo.logic import utils, ips
42 42
from synnefo import quotas
43 43
from synnefo.api.util import release_resource
......
266 266
                # Update the NIC in DB with the values from Ganeti NIC
267 267
                setattr(db_nic, f, ganeti_nic[f])
268 268
                db_nic.save()
269

  
269 270
            # Special case where the IPv4 address has changed, because you
270 271
            # need to release the old IPv4 address and reserve the new one
271 272
            ipv4_address = ganeti_nic["ipv4_address"]
272 273
            if db_nic.ipv4_address != ipv4_address:
273
                remove_nic_ips(db_nic)
274
                if ipv4_address:
275
                    network = ganeti_nic["network"]
276
                    ipaddress = ips.allocate_ip(network, vm.userid,
277
                                                address=ipv4_address)
278
                    ipaddress.nic = nic
279
                    ipaddress.save()
274
                change_address_of_port(db_nic, vm.userid,
275
                                       old_address=db_nic.ipv4_address,
276
                                       new_address=ipv4_address,
277
                                       version=4)
278

  
279
            ipv6_address = ganeti_nic["ipv6_address"]
280
            if db_nic.ipv6_address != ipv6_address:
281
                change_address_of_port(db_nic, vm.userid,
282
                                       old_address=db_nic.ipv6_address,
283
                                       new_address=ipv6_address,
284
                                       version=6)
280 285

  
281 286
    vm.backendtime = etime
282 287
    vm.save()
283 288

  
284 289

  
290
def change_address_of_port(port, userid, old_address, new_address, version):
291
    """Change."""
292
    if old_address is not None:
293
        msg = ("IPv%s Address of server '%s' changed from '%s' to '%s'"
294
               % (version, port.machine_id, old_address, new_address))
295
        log.critical(msg)
296

  
297
    # Remove the old IP address
298
    remove_nic_ips(port, version=version)
299

  
300
    if version == 4:
301
        ipaddress = ips.allocate_ip(port.network, userid, address=new_address)
302
        ipaddress.nic = port
303
        ipaddress.save()
304
    elif version == 6:
305
        subnet6 = port.network.subnet6
306
        ipaddress = IPAddress.objects.create(userid=userid,
307
                                             network=port.network,
308
                                             subnet=subnet6,
309
                                             nic=port,
310
                                             address=new_address)
311
    else:
312
        raise ValueError("Unknown version: %s" % version)
313

  
314
    # New address log
315
    ip_log = IPAddressLog.objects.create(server_id=port.machine_id,
316
                                         network_id=port.network_id,
317
                                         address=new_address,
318
                                         active=True)
319
    log.info("Created IP log entry '%s' for address '%s' to server '%s'",
320
             ip_log.id, new_address, port.machine_id)
321

  
322
    return ipaddress
323

  
324

  
285 325
def nics_are_equal(db_nic, gnt_nic):
286 326
    for field in NIC_FIELDS:
287 327
        if getattr(db_nic, field) != gnt_nic[field]:
......
308 348
        mac = gnic.get('mac')
309 349
        ipv4 = gnic.get('ip')
310 350
        subnet6 = network.subnet6
311
        ipv6 = mac2eui64(mac, subnet6) if subnet6 else None
351
        ipv6 = mac2eui64(mac, subnet6.cidr) if subnet6 else None
312 352

  
313 353
        firewall = gnic.get('firewall')
314 354
        firewall_profile = _reverse_tags.get(firewall)
......
328 368
    return dict(new_nics)
329 369

  
330 370

  
331
def remove_nic_ips(nic):
371
def remove_nic_ips(nic, version=None):
332 372
    """Remove IP addresses associated with a NetworkInterface.
333 373

  
334 374
    Remove all IP addresses that are associated with the NetworkInterface
335 375
    object, by returning them to the pool and deleting the IPAddress object. If
336 376
    the IP is a floating IP, then it is just disassociated from the NIC.
377
    If version is specified, then only IP addressses of that version will be
378
    removed.
337 379

  
338 380
    """
339

  
340 381
    for ip in nic.ips.all():
382
        if version and ip.ipversion != version:
383
            continue
384

  
341 385
        # Update the DB table holding the logging of all IP addresses
342
        update_ip_address_log(nic, ip)
386
        terminate_active_ipaddress_log(nic, ip)
343 387

  
344
        if ip.ipversion == 4:
345
            if ip.floating_ip:
346
                ip.nic = None
347
                ip.save()
348
            else:
349
                ip.release_address()
350
        if not ip.floating_ip:
388
        if ip.floating_ip:
389
            ip.nic = None
390
            ip.save()
391
        else:
392
            # Release the IPv4 address
393
            ip.release_address()
351 394
            ip.delete()
352 395

  
353 396

  
354
def update_ip_address_log(nic, ip):
397
def terminate_active_ipaddress_log(nic, ip):
355 398
    """Update DB logging entry for this IP address."""
356 399
    if not ip.network.public or nic.machine is None:
357 400
        return

Also available in: Unified diff