Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / ippool.py @ 8a4a931d

History | View | Annotate | Download (2.5 kB)

1
import ipaddr
2

    
3
from bitarray import bitarray
4
from base64 import b64encode, b64decode
5

    
6

    
7
class IPPool(object):
8
    def __init__(self, network):
9
        self.net = network
10
        self.network = ipaddr.IPNetwork(self.net.subnet)
11

    
12
        gateway = self.net.gateway
13
        self.gateway = gateway and ipaddr.IPAddress(gateway) or None
14

    
15
        if self.net.reservations:
16
            self.reservations = bitarray()
17
            self.reservations.fromstring(b64decode(self.net.reservations))
18
        else:
19
            numhosts = self.network.numhosts
20
            self.reservations = bitarray(numhosts)
21
            self.reservations.setall(False)
22
            self.reservations[0] = True
23
            self.reservations[numhosts - 1] = True
24
            # if self.net.type == 'PUBLIC_ROUTED':
25
            #     self.reservations[numhosts - 2] = True
26

    
27
    def _contains(self, address):
28
        if address is None:
29
            return False
30
        addr = ipaddr.IPAddress(address)
31

    
32
        return (addr in self.network)
33

    
34
    def _address_index(self, address):
35
        """Convert IP address to bitarray index
36

37
        """
38
        if not self._contains(address):
39
            raise Exception("%s does not contain %s" % (str(self.network), address))
40
        addr = ipaddr.IPAddress(address)
41

    
42
        return int(addr) - int(self.network.network)
43

    
44
    def _mark(self, address, value):
45
        index = self._address_index(address)
46
        self.reservations[index] = value
47

    
48
    def reserve(self, address):
49
        self._mark(address, True)
50

    
51
    def release(self, address):
52
        self._mark(address, False)
53

    
54
    def is_reserved(self, address):
55
        index = self._address_index(address)
56
        return self.reservations[index]
57

    
58
    def is_full(self):
59
        return self.reservations.all()
60

    
61
    def count_reserved(self):
62
        return self.reservations.count(True)
63

    
64
    def count_free(self):
65
        return self.reservations.count(False)
66

    
67
    def get_map(self):
68
        return self.reservations.to01().replace("1", "X").replace("0", ".")
69

    
70
    def get_free_address(self):
71
        if self.is_full():
72
            raise IPPool.IPPoolExhausted("%s if full" % str(self.network))
73

    
74
        index = self.reservations.index(False)
75
        address = str(self.network[index])
76
        self.reserve(address)
77
        return address
78

    
79
    def save(self):
80
        self._update_network()
81
        self.net.save()
82

    
83
    def _update_network(self):
84
        self.net.reservations = b64encode(self.reservations.tostring())
85

    
86
    class IPPoolExhausted(Exception):
87
        pass