Statistics
| Branch: | Tag: | Revision:

root / lib / network.py @ 63c73073

History | View | Annotate | Download (6.2 kB)

1 1de1cf25 Apollon Oikonomopoulos
#
2 1de1cf25 Apollon Oikonomopoulos
#
3 1de1cf25 Apollon Oikonomopoulos
4 861a92b4 Dimitris Aragiorgis
# Copyright (C) 2011, 2012 Google Inc.
5 1de1cf25 Apollon Oikonomopoulos
#
6 1de1cf25 Apollon Oikonomopoulos
# This program is free software; you can redistribute it and/or modify
7 1de1cf25 Apollon Oikonomopoulos
# it under the terms of the GNU General Public License as published by
8 1de1cf25 Apollon Oikonomopoulos
# the Free Software Foundation; either version 2 of the License, or
9 1de1cf25 Apollon Oikonomopoulos
# (at your option) any later version.
10 1de1cf25 Apollon Oikonomopoulos
#
11 1de1cf25 Apollon Oikonomopoulos
# This program is distributed in the hope that it will be useful, but
12 1de1cf25 Apollon Oikonomopoulos
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 1de1cf25 Apollon Oikonomopoulos
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 1de1cf25 Apollon Oikonomopoulos
# General Public License for more details.
15 1de1cf25 Apollon Oikonomopoulos
#
16 1de1cf25 Apollon Oikonomopoulos
# You should have received a copy of the GNU General Public License
17 1de1cf25 Apollon Oikonomopoulos
# along with this program; if not, write to the Free Software
18 1de1cf25 Apollon Oikonomopoulos
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 1de1cf25 Apollon Oikonomopoulos
# 02110-1301, USA.
20 1de1cf25 Apollon Oikonomopoulos
21 1de1cf25 Apollon Oikonomopoulos
22 5b34cc22 Michael Hanselmann
"""IP address pool management functions.
23 1de1cf25 Apollon Oikonomopoulos

24 1de1cf25 Apollon Oikonomopoulos
"""
25 1de1cf25 Apollon Oikonomopoulos
26 1de1cf25 Apollon Oikonomopoulos
import ipaddr
27 1de1cf25 Apollon Oikonomopoulos
28 1de1cf25 Apollon Oikonomopoulos
from bitarray import bitarray
29 1de1cf25 Apollon Oikonomopoulos
30 1de1cf25 Apollon Oikonomopoulos
from ganeti import errors
31 1de1cf25 Apollon Oikonomopoulos
32 3c286190 Dimitris Aragiorgis
33 1de1cf25 Apollon Oikonomopoulos
class AddressPool(object):
34 5b34cc22 Michael Hanselmann
  """Address pool class, wrapping an C{objects.Network} object.
35 1de1cf25 Apollon Oikonomopoulos

36 1de1cf25 Apollon Oikonomopoulos
  This class provides methods to manipulate address pools, backed by
37 1de1cf25 Apollon Oikonomopoulos
  L{objects.Network} objects.
38 1de1cf25 Apollon Oikonomopoulos

39 1de1cf25 Apollon Oikonomopoulos
  """
40 5b34cc22 Michael Hanselmann
  FREE = bitarray("0")
41 5b34cc22 Michael Hanselmann
  RESERVED = bitarray("1")
42 861a92b4 Dimitris Aragiorgis
43 1de1cf25 Apollon Oikonomopoulos
  def __init__(self, network):
44 5b34cc22 Michael Hanselmann
    """Initialize a new IPv4 address pool from an L{objects.Network} object.
45 1de1cf25 Apollon Oikonomopoulos

46 1de1cf25 Apollon Oikonomopoulos
    @type network: L{objects.Network}
47 1de1cf25 Apollon Oikonomopoulos
    @param network: the network object from which the pool will be generated
48 1de1cf25 Apollon Oikonomopoulos

49 1de1cf25 Apollon Oikonomopoulos
    """
50 1de1cf25 Apollon Oikonomopoulos
    self.network = None
51 1de1cf25 Apollon Oikonomopoulos
    self.gateway = None
52 1de1cf25 Apollon Oikonomopoulos
    self.network6 = None
53 1de1cf25 Apollon Oikonomopoulos
    self.gateway6 = None
54 1de1cf25 Apollon Oikonomopoulos
55 1de1cf25 Apollon Oikonomopoulos
    self.net = network
56 1de1cf25 Apollon Oikonomopoulos
57 1de1cf25 Apollon Oikonomopoulos
    self.network = ipaddr.IPNetwork(self.net.network)
58 1de1cf25 Apollon Oikonomopoulos
    if self.net.gateway:
59 1de1cf25 Apollon Oikonomopoulos
      self.gateway = ipaddr.IPAddress(self.net.gateway)
60 1de1cf25 Apollon Oikonomopoulos
61 1de1cf25 Apollon Oikonomopoulos
    if self.net.network6:
62 1de1cf25 Apollon Oikonomopoulos
      self.network6 = ipaddr.IPv6Network(self.net.network6)
63 1de1cf25 Apollon Oikonomopoulos
    if self.net.gateway6:
64 1de1cf25 Apollon Oikonomopoulos
      self.gateway6 = ipaddr.IPv6Address(self.net.gateway6)
65 1de1cf25 Apollon Oikonomopoulos
66 1de1cf25 Apollon Oikonomopoulos
    if self.net.reservations:
67 1de1cf25 Apollon Oikonomopoulos
      self.reservations = bitarray(self.net.reservations)
68 1de1cf25 Apollon Oikonomopoulos
    else:
69 1de1cf25 Apollon Oikonomopoulos
      self.reservations = bitarray(self.network.numhosts)
70 beb81ea5 Dimitris Aragiorgis
      # pylint: disable=E1103
71 1de1cf25 Apollon Oikonomopoulos
      self.reservations.setall(False)
72 1de1cf25 Apollon Oikonomopoulos
73 1de1cf25 Apollon Oikonomopoulos
    if self.net.ext_reservations:
74 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations = bitarray(self.net.ext_reservations)
75 1de1cf25 Apollon Oikonomopoulos
    else:
76 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations = bitarray(self.network.numhosts)
77 beb81ea5 Dimitris Aragiorgis
      # pylint: disable=E1103
78 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations.setall(False)
79 1de1cf25 Apollon Oikonomopoulos
80 1de1cf25 Apollon Oikonomopoulos
    assert len(self.reservations) == self.network.numhosts
81 1de1cf25 Apollon Oikonomopoulos
    assert len(self.ext_reservations) == self.network.numhosts
82 1de1cf25 Apollon Oikonomopoulos
83 beb81ea5 Dimitris Aragiorgis
  def Contains(self, address):
84 1de1cf25 Apollon Oikonomopoulos
    if address is None:
85 1de1cf25 Apollon Oikonomopoulos
      return False
86 1de1cf25 Apollon Oikonomopoulos
    addr = ipaddr.IPAddress(address)
87 1de1cf25 Apollon Oikonomopoulos
88 1de1cf25 Apollon Oikonomopoulos
    return addr in self.network
89 1de1cf25 Apollon Oikonomopoulos
90 1de1cf25 Apollon Oikonomopoulos
  def _GetAddrIndex(self, address):
91 1de1cf25 Apollon Oikonomopoulos
    addr = ipaddr.IPAddress(address)
92 1de1cf25 Apollon Oikonomopoulos
93 1de1cf25 Apollon Oikonomopoulos
    if not addr in self.network:
94 1de1cf25 Apollon Oikonomopoulos
      raise errors.AddressPoolError("%s does not contain %s" %
95 1de1cf25 Apollon Oikonomopoulos
                                    (self.network, addr))
96 1de1cf25 Apollon Oikonomopoulos
97 1de1cf25 Apollon Oikonomopoulos
    return int(addr) - int(self.network.network)
98 1de1cf25 Apollon Oikonomopoulos
99 beb81ea5 Dimitris Aragiorgis
  def Update(self):
100 5b34cc22 Michael Hanselmann
    """Write address pools back to the network object.
101 5b34cc22 Michael Hanselmann

102 5b34cc22 Michael Hanselmann
    """
103 beb81ea5 Dimitris Aragiorgis
    # pylint: disable=E1103
104 1de1cf25 Apollon Oikonomopoulos
    self.net.ext_reservations = self.ext_reservations.to01()
105 1de1cf25 Apollon Oikonomopoulos
    self.net.reservations = self.reservations.to01()
106 1de1cf25 Apollon Oikonomopoulos
107 1de1cf25 Apollon Oikonomopoulos
  def _Mark(self, address, value=True, external=False):
108 1de1cf25 Apollon Oikonomopoulos
    idx = self._GetAddrIndex(address)
109 1de1cf25 Apollon Oikonomopoulos
    if external:
110 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations[idx] = value
111 1de1cf25 Apollon Oikonomopoulos
    else:
112 1de1cf25 Apollon Oikonomopoulos
      self.reservations[idx] = value
113 beb81ea5 Dimitris Aragiorgis
    self.Update()
114 1de1cf25 Apollon Oikonomopoulos
115 1de1cf25 Apollon Oikonomopoulos
  def _GetSize(self):
116 3c286190 Dimitris Aragiorgis
    return 2 ** (32 - self.network.prefixlen)
117 1de1cf25 Apollon Oikonomopoulos
118 1de1cf25 Apollon Oikonomopoulos
  @property
119 1de1cf25 Apollon Oikonomopoulos
  def all_reservations(self):
120 5b34cc22 Michael Hanselmann
    """Return a combined map of internal and external reservations.
121 5b34cc22 Michael Hanselmann

122 5b34cc22 Michael Hanselmann
    """
123 1de1cf25 Apollon Oikonomopoulos
    return (self.reservations | self.ext_reservations)
124 1de1cf25 Apollon Oikonomopoulos
125 1de1cf25 Apollon Oikonomopoulos
  def Validate(self):
126 1de1cf25 Apollon Oikonomopoulos
    assert self.net.family == 4
127 1de1cf25 Apollon Oikonomopoulos
    assert len(self.reservations) == self._GetSize()
128 1de1cf25 Apollon Oikonomopoulos
    assert len(self.ext_reservations) == self._GetSize()
129 6e8091f9 Dimitris Aragiorgis
    all_res = self.reservations & self.ext_reservations
130 6e8091f9 Dimitris Aragiorgis
    assert not all_res.any()
131 1de1cf25 Apollon Oikonomopoulos
132 1de1cf25 Apollon Oikonomopoulos
    if self.gateway is not None:
133 1de1cf25 Apollon Oikonomopoulos
      assert self.net.family == self.gateway.version
134 1de1cf25 Apollon Oikonomopoulos
      assert self.gateway in self.network
135 1de1cf25 Apollon Oikonomopoulos
136 1de1cf25 Apollon Oikonomopoulos
    if self.network6 and self.gateway6:
137 1de1cf25 Apollon Oikonomopoulos
      assert self.gateway6 in self.network6
138 1de1cf25 Apollon Oikonomopoulos
139 1de1cf25 Apollon Oikonomopoulos
    return True
140 1de1cf25 Apollon Oikonomopoulos
141 1de1cf25 Apollon Oikonomopoulos
  def IsFull(self):
142 5b34cc22 Michael Hanselmann
    """Check whether the network is full.
143 5b34cc22 Michael Hanselmann

144 5b34cc22 Michael Hanselmann
    """
145 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.all()
146 1de1cf25 Apollon Oikonomopoulos
147 1de1cf25 Apollon Oikonomopoulos
  def GetReservedCount(self):
148 5b34cc22 Michael Hanselmann
    """Get the count of reserved addresses.
149 5b34cc22 Michael Hanselmann

150 5b34cc22 Michael Hanselmann
    """
151 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.count(True)
152 1de1cf25 Apollon Oikonomopoulos
153 1de1cf25 Apollon Oikonomopoulos
  def GetFreeCount(self):
154 5b34cc22 Michael Hanselmann
    """Get the count of unused addresses.
155 5b34cc22 Michael Hanselmann

156 5b34cc22 Michael Hanselmann
    """
157 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.count(False)
158 1de1cf25 Apollon Oikonomopoulos
159 1de1cf25 Apollon Oikonomopoulos
  def GetMap(self):
160 5b34cc22 Michael Hanselmann
    """Return a textual representation of the network's occupation status.
161 5b34cc22 Michael Hanselmann

162 5b34cc22 Michael Hanselmann
    """
163 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.to01().replace("1", "X").replace("0", ".")
164 1de1cf25 Apollon Oikonomopoulos
165 1de1cf25 Apollon Oikonomopoulos
  def IsReserved(self, address):
166 5b34cc22 Michael Hanselmann
    """Checks if the given IP is reserved.
167 5b34cc22 Michael Hanselmann

168 5b34cc22 Michael Hanselmann
    """
169 1de1cf25 Apollon Oikonomopoulos
    idx = self._GetAddrIndex(address)
170 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations[idx]
171 1de1cf25 Apollon Oikonomopoulos
172 1de1cf25 Apollon Oikonomopoulos
  def Reserve(self, address, external=False):
173 5b34cc22 Michael Hanselmann
    """Mark an address as used.
174 5b34cc22 Michael Hanselmann

175 5b34cc22 Michael Hanselmann
    """
176 1de1cf25 Apollon Oikonomopoulos
    if self.IsReserved(address):
177 1de1cf25 Apollon Oikonomopoulos
      raise errors.AddressPoolError("%s is already reserved" % address)
178 1de1cf25 Apollon Oikonomopoulos
    self._Mark(address, external=external)
179 1de1cf25 Apollon Oikonomopoulos
180 1de1cf25 Apollon Oikonomopoulos
  def Release(self, address, external=False):
181 5b34cc22 Michael Hanselmann
    """Release a given address reservation.
182 5b34cc22 Michael Hanselmann

183 5b34cc22 Michael Hanselmann
    """
184 1de1cf25 Apollon Oikonomopoulos
    self._Mark(address, value=False, external=external)
185 1de1cf25 Apollon Oikonomopoulos
186 1de1cf25 Apollon Oikonomopoulos
  def GetFreeAddress(self):
187 5b34cc22 Michael Hanselmann
    """Returns the first available address.
188 5b34cc22 Michael Hanselmann

189 5b34cc22 Michael Hanselmann
    """
190 1de1cf25 Apollon Oikonomopoulos
    if self.IsFull():
191 1de1cf25 Apollon Oikonomopoulos
      raise errors.AddressPoolError("%s is full" % self.network)
192 1de1cf25 Apollon Oikonomopoulos
193 1de1cf25 Apollon Oikonomopoulos
    idx = self.all_reservations.index(False)
194 1de1cf25 Apollon Oikonomopoulos
    address = str(self.network[idx])
195 1de1cf25 Apollon Oikonomopoulos
    self.Reserve(address)
196 1de1cf25 Apollon Oikonomopoulos
    return address
197 1de1cf25 Apollon Oikonomopoulos
198 1de1cf25 Apollon Oikonomopoulos
  def GenerateFree(self):
199 5b34cc22 Michael Hanselmann
    """Returns the first free address of the network.
200 5b34cc22 Michael Hanselmann

201 5b34cc22 Michael Hanselmann
    @raise errors.AddressPoolError: Pool is full
202 1f1d3bf2 Dimitris Aragiorgis

203 1f1d3bf2 Dimitris Aragiorgis
    """
204 861a92b4 Dimitris Aragiorgis
    idx = self.all_reservations.search(self.FREE, 1)
205 55f70aef Dimitris Aragiorgis
    if idx:
206 55f70aef Dimitris Aragiorgis
      return str(self.network[idx[0]])
207 55f70aef Dimitris Aragiorgis
    else:
208 55f70aef Dimitris Aragiorgis
      raise errors.AddressPoolError("%s is full" % self.network)
209 1de1cf25 Apollon Oikonomopoulos
210 1de1cf25 Apollon Oikonomopoulos
  def GetExternalReservations(self):
211 5b34cc22 Michael Hanselmann
    """Returns a list of all externally reserved addresses.
212 5b34cc22 Michael Hanselmann

213 5b34cc22 Michael Hanselmann
    """
214 861a92b4 Dimitris Aragiorgis
    # pylint: disable=E1103
215 861a92b4 Dimitris Aragiorgis
    idxs = self.ext_reservations.search(self.RESERVED)
216 1de1cf25 Apollon Oikonomopoulos
    return [str(self.network[idx]) for idx in idxs]
217 1de1cf25 Apollon Oikonomopoulos
218 1de1cf25 Apollon Oikonomopoulos
  @classmethod
219 1de1cf25 Apollon Oikonomopoulos
  def InitializeNetwork(cls, net):
220 5b34cc22 Michael Hanselmann
    """Initialize an L{objects.Network} object.
221 1de1cf25 Apollon Oikonomopoulos

222 5b34cc22 Michael Hanselmann
    Reserve the network, broadcast and gateway IP addresses.
223 1de1cf25 Apollon Oikonomopoulos

224 1de1cf25 Apollon Oikonomopoulos
    """
225 1de1cf25 Apollon Oikonomopoulos
    obj = cls(net)
226 beb81ea5 Dimitris Aragiorgis
    obj.Update()
227 1de1cf25 Apollon Oikonomopoulos
    for ip in [obj.network[0], obj.network[-1]]:
228 1de1cf25 Apollon Oikonomopoulos
      obj.Reserve(ip, external=True)
229 1de1cf25 Apollon Oikonomopoulos
    if obj.net.gateway is not None:
230 1de1cf25 Apollon Oikonomopoulos
      obj.Reserve(obj.net.gateway, external=True)
231 1de1cf25 Apollon Oikonomopoulos
    obj.Validate()
232 1de1cf25 Apollon Oikonomopoulos
    return obj