Revision 3165f027 snf-cyclades-app/synnefo/db/models.py
b/snf-cyclades-app/synnefo/db/models.py | ||
---|---|---|
32 | 32 |
from django.conf import settings |
33 | 33 |
from django.db import models |
34 | 34 |
from django.db import IntegrityError |
35 |
from django.db import transaction |
|
36 |
|
|
37 |
import utils |
|
35 | 38 |
|
36 | 39 |
from hashlib import sha1 |
37 | 40 |
from synnefo.api.faults import ServiceUnavailable |
... | ... | |
124 | 127 |
null=True) |
125 | 128 |
# Sha1 is up to 40 characters long |
126 | 129 |
hash = models.CharField('Hash', max_length=40, editable=False, null=False) |
130 |
# Unique index of the Backend, used for the mac-prefixes of the |
|
131 |
# BackendNetworks |
|
132 |
index = models.PositiveIntegerField('Index', null=False, unique=True, |
|
133 |
default=0) |
|
127 | 134 |
drained = models.BooleanField('Drained', default=False, null=False) |
128 | 135 |
offline = models.BooleanField('Offline', default=False, null=False) |
129 | 136 |
# Last refresh of backend resources |
... | ... | |
192 | 199 |
self.virtual_machines.all().backend = None |
193 | 200 |
super(Backend, self).delete(*args, **kwargs) |
194 | 201 |
|
202 |
def __init__(self, *args, **kwargs): |
|
203 |
super(Backend, self).__init__(*args, **kwargs) |
|
204 |
if not self.pk: |
|
205 |
# Generate a unique index for the Backend |
|
206 |
indexes = Backend.objects.all().values_list('index', flat=True) |
|
207 |
first_free = [x for x in xrange(0, 16) if x not in indexes][0] |
|
208 |
self.index = first_free |
|
209 |
|
|
195 | 210 |
|
196 | 211 |
# A backend job may be in one of the following possible states |
197 | 212 |
BACKEND_STATUSES = ( |
... | ... | |
437 | 452 |
type = models.CharField(choices=NETWORK_TYPES, max_length=50, |
438 | 453 |
default='PRIVATE_PHYSICAL_VLAN') |
439 | 454 |
link = models.CharField('Network Link', max_length=128, null=True) |
440 |
mac_prefix = models.CharField('MAC Prefix', max_length=32, null=True)
|
|
455 |
mac_prefix = models.CharField('MAC Prefix', max_length=32, null=False)
|
|
441 | 456 |
public = models.BooleanField(default=False) |
442 | 457 |
created = models.DateTimeField(auto_now_add=True) |
443 | 458 |
updated = models.DateTimeField(auto_now=True) |
... | ... | |
495 | 510 |
def __unicode__(self): |
496 | 511 |
return self.name |
497 | 512 |
|
513 |
@transaction.commit_on_success |
|
498 | 514 |
def update_state(self): |
499 | 515 |
"""Update state of the Network. |
500 | 516 |
|
... | ... | |
528 | 544 |
|
529 | 545 |
self.save() |
530 | 546 |
|
547 |
def __init__(self, *args, **kwargs): |
|
548 |
super(Network, self).__init__(*args, **kwargs) |
|
549 |
if not self.mac_prefix: |
|
550 |
# Allocate a MAC prefix for just created Network instances |
|
551 |
mac_prefix = MacPrefixPool.get_available().value |
|
552 |
self.mac_prefix = mac_prefix |
|
553 |
|
|
531 | 554 |
def save(self, *args, **kwargs): |
532 | 555 |
pk = self.pk |
533 | 556 |
super(Network, self).save(*args, **kwargs) |
... | ... | |
596 | 619 |
created = models.DateTimeField(auto_now_add=True) |
597 | 620 |
updated = models.DateTimeField(auto_now=True) |
598 | 621 |
deleted = models.BooleanField('Deleted', default=False) |
622 |
mac_prefix = models.CharField('MAC Prefix', max_length=32, null=False) |
|
599 | 623 |
operstate = models.CharField(choices=OPER_STATES, max_length=30, |
600 | 624 |
default='PENDING') |
601 | 625 |
backendjobid = models.PositiveIntegerField(null=True) |
... | ... | |
607 | 631 |
backendtime = models.DateTimeField(null=False, |
608 | 632 |
default=datetime.datetime.min) |
609 | 633 |
|
634 |
def __init__(self, *args, **kwargs): |
|
635 |
"""Initialize state for just created BackendNetwork instances.""" |
|
636 |
super(BackendNetwork, self).__init__(*args, **kwargs) |
|
637 |
if not self.mac_prefix: |
|
638 |
# Generate the MAC prefix of the BackendNetwork, by combining |
|
639 |
# the Network prefix with the index of the Backend |
|
640 |
net_prefix = self.network.mac_prefix |
|
641 |
backend_suffix = hex(self.backend.index).replace('0x', '') |
|
642 |
mac_prefix = net_prefix + backend_suffix |
|
643 |
try: |
|
644 |
utils.validate_mac(mac_prefix + ":00:00:00") |
|
645 |
except utils.InvalidMacAddress: |
|
646 |
raise utils.InvalidMacAddress("Invalid MAC prefix '%s'" % \ |
|
647 |
mac_prefix) |
|
648 |
self.mac_prefix = mac_prefix |
|
649 |
|
|
610 | 650 |
def save(self, *args, **kwargs): |
611 | 651 |
super(BackendNetwork, self).save(*args, **kwargs) |
612 | 652 |
self.network.update_state() |
... | ... | |
628 | 668 |
created = models.DateTimeField(auto_now_add=True) |
629 | 669 |
updated = models.DateTimeField(auto_now=True) |
630 | 670 |
index = models.IntegerField(null=False) |
631 |
mac = models.CharField(max_length=32, null=True) |
|
671 |
mac = models.CharField(max_length=32, null=False, unique=True)
|
|
632 | 672 |
ipv4 = models.CharField(max_length=15, null=True) |
633 | 673 |
ipv6 = models.CharField(max_length=100, null=True) |
634 | 674 |
firewall_profile = models.CharField(choices=FIREWALL_PROFILES, |
... | ... | |
703 | 743 |
|
704 | 744 |
|
705 | 745 |
class MacPrefixPool(Pool): |
706 |
max_index = snf_settings.PRIVATE_MAC_FILTERED_MAX_PREFIX_NUMBER
|
|
746 |
max_index = snf_settings.MAC_POOL_LIMIT
|
|
707 | 747 |
|
708 | 748 |
@staticmethod |
709 | 749 |
def value_from_index(index): |
710 | 750 |
"""Convert number to mac prefix |
711 | 751 |
|
712 | 752 |
""" |
713 |
high = snf_settings.PRIVATE_MAC_FILTERED_BASE_MAC_PREFIX
|
|
714 |
a = hex(int(high.replace(":", ""), 16) + index).replace("0x", '')
|
|
753 |
base = snf_settings.MAC_POOL_BASE
|
|
754 |
a = hex(int(base.replace(":", ""), 16) + index).replace("0x", '')
|
|
715 | 755 |
mac_prefix = ":".join([a[x:x + 2] for x in xrange(0, len(a), 2)]) |
716 | 756 |
return mac_prefix |
Also available in: Unified diff