Statistics
| Branch: | Tag: | Revision:

root / lib / network.py @ 595149d5

History | View | Annotate | Download (6.7 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 9842f020 Helga Velroyen
IPV4_NETWORK_MIN_SIZE = 30
33 9842f020 Helga Velroyen
IPV4_NETWORK_MIN_NUM_HOSTS = 2 ** (32 - IPV4_NETWORK_MIN_SIZE)
34 9842f020 Helga Velroyen
35 3c286190 Dimitris Aragiorgis
36 1de1cf25 Apollon Oikonomopoulos
class AddressPool(object):
37 5b34cc22 Michael Hanselmann
  """Address pool class, wrapping an C{objects.Network} object.
38 1de1cf25 Apollon Oikonomopoulos

39 1de1cf25 Apollon Oikonomopoulos
  This class provides methods to manipulate address pools, backed by
40 1de1cf25 Apollon Oikonomopoulos
  L{objects.Network} objects.
41 1de1cf25 Apollon Oikonomopoulos

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

49 1de1cf25 Apollon Oikonomopoulos
    @type network: L{objects.Network}
50 1de1cf25 Apollon Oikonomopoulos
    @param network: the network object from which the pool will be generated
51 1de1cf25 Apollon Oikonomopoulos

52 1de1cf25 Apollon Oikonomopoulos
    """
53 1de1cf25 Apollon Oikonomopoulos
    self.network = None
54 1de1cf25 Apollon Oikonomopoulos
    self.gateway = None
55 1de1cf25 Apollon Oikonomopoulos
    self.network6 = None
56 1de1cf25 Apollon Oikonomopoulos
    self.gateway6 = None
57 1de1cf25 Apollon Oikonomopoulos
58 1de1cf25 Apollon Oikonomopoulos
    self.net = network
59 1de1cf25 Apollon Oikonomopoulos
60 1de1cf25 Apollon Oikonomopoulos
    self.network = ipaddr.IPNetwork(self.net.network)
61 9842f020 Helga Velroyen
    if self.network.numhosts < IPV4_NETWORK_MIN_NUM_HOSTS:
62 9842f020 Helga Velroyen
      raise errors.AddressPoolError("A network with only %s host(s) is too"
63 9842f020 Helga Velroyen
                                    " small, please specify at least a /%s"
64 9842f020 Helga Velroyen
                                    " network" %
65 9842f020 Helga Velroyen
                                    (str(self.network.numhosts),
66 9842f020 Helga Velroyen
                                     IPV4_NETWORK_MIN_SIZE))
67 1de1cf25 Apollon Oikonomopoulos
    if self.net.gateway:
68 1de1cf25 Apollon Oikonomopoulos
      self.gateway = ipaddr.IPAddress(self.net.gateway)
69 1de1cf25 Apollon Oikonomopoulos
70 1de1cf25 Apollon Oikonomopoulos
    if self.net.network6:
71 1de1cf25 Apollon Oikonomopoulos
      self.network6 = ipaddr.IPv6Network(self.net.network6)
72 1de1cf25 Apollon Oikonomopoulos
    if self.net.gateway6:
73 1de1cf25 Apollon Oikonomopoulos
      self.gateway6 = ipaddr.IPv6Address(self.net.gateway6)
74 1de1cf25 Apollon Oikonomopoulos
75 1de1cf25 Apollon Oikonomopoulos
    if self.net.reservations:
76 1de1cf25 Apollon Oikonomopoulos
      self.reservations = bitarray(self.net.reservations)
77 1de1cf25 Apollon Oikonomopoulos
    else:
78 1de1cf25 Apollon Oikonomopoulos
      self.reservations = bitarray(self.network.numhosts)
79 beb81ea5 Dimitris Aragiorgis
      # pylint: disable=E1103
80 1de1cf25 Apollon Oikonomopoulos
      self.reservations.setall(False)
81 1de1cf25 Apollon Oikonomopoulos
82 1de1cf25 Apollon Oikonomopoulos
    if self.net.ext_reservations:
83 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations = bitarray(self.net.ext_reservations)
84 1de1cf25 Apollon Oikonomopoulos
    else:
85 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations = bitarray(self.network.numhosts)
86 beb81ea5 Dimitris Aragiorgis
      # pylint: disable=E1103
87 1de1cf25 Apollon Oikonomopoulos
      self.ext_reservations.setall(False)
88 1de1cf25 Apollon Oikonomopoulos
89 1de1cf25 Apollon Oikonomopoulos
    assert len(self.reservations) == self.network.numhosts
90 1de1cf25 Apollon Oikonomopoulos
    assert len(self.ext_reservations) == self.network.numhosts
91 1de1cf25 Apollon Oikonomopoulos
92 beb81ea5 Dimitris Aragiorgis
  def Contains(self, address):
93 1de1cf25 Apollon Oikonomopoulos
    if address is None:
94 1de1cf25 Apollon Oikonomopoulos
      return False
95 1de1cf25 Apollon Oikonomopoulos
    addr = ipaddr.IPAddress(address)
96 1de1cf25 Apollon Oikonomopoulos
97 1de1cf25 Apollon Oikonomopoulos
    return addr in self.network
98 1de1cf25 Apollon Oikonomopoulos
99 1de1cf25 Apollon Oikonomopoulos
  def _GetAddrIndex(self, address):
100 1de1cf25 Apollon Oikonomopoulos
    addr = ipaddr.IPAddress(address)
101 1de1cf25 Apollon Oikonomopoulos
102 1de1cf25 Apollon Oikonomopoulos
    if not addr in self.network:
103 1de1cf25 Apollon Oikonomopoulos
      raise errors.AddressPoolError("%s does not contain %s" %
104 1de1cf25 Apollon Oikonomopoulos
                                    (self.network, addr))
105 1de1cf25 Apollon Oikonomopoulos
106 1de1cf25 Apollon Oikonomopoulos
    return int(addr) - int(self.network.network)
107 1de1cf25 Apollon Oikonomopoulos
108 beb81ea5 Dimitris Aragiorgis
  def Update(self):
109 5b34cc22 Michael Hanselmann
    """Write address pools back to the network object.
110 5b34cc22 Michael Hanselmann

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

131 5b34cc22 Michael Hanselmann
    """
132 1de1cf25 Apollon Oikonomopoulos
    return (self.reservations | self.ext_reservations)
133 1de1cf25 Apollon Oikonomopoulos
134 1de1cf25 Apollon Oikonomopoulos
  def Validate(self):
135 1de1cf25 Apollon Oikonomopoulos
    assert self.net.family == 4
136 1de1cf25 Apollon Oikonomopoulos
    assert len(self.reservations) == self._GetSize()
137 1de1cf25 Apollon Oikonomopoulos
    assert len(self.ext_reservations) == self._GetSize()
138 6e8091f9 Dimitris Aragiorgis
    all_res = self.reservations & self.ext_reservations
139 6e8091f9 Dimitris Aragiorgis
    assert not all_res.any()
140 1de1cf25 Apollon Oikonomopoulos
141 1de1cf25 Apollon Oikonomopoulos
    if self.gateway is not None:
142 1de1cf25 Apollon Oikonomopoulos
      assert self.net.family == self.gateway.version
143 1de1cf25 Apollon Oikonomopoulos
      assert self.gateway in self.network
144 1de1cf25 Apollon Oikonomopoulos
145 1de1cf25 Apollon Oikonomopoulos
    if self.network6 and self.gateway6:
146 1de1cf25 Apollon Oikonomopoulos
      assert self.gateway6 in self.network6
147 1de1cf25 Apollon Oikonomopoulos
148 1de1cf25 Apollon Oikonomopoulos
    return True
149 1de1cf25 Apollon Oikonomopoulos
150 1de1cf25 Apollon Oikonomopoulos
  def IsFull(self):
151 5b34cc22 Michael Hanselmann
    """Check whether the network is full.
152 5b34cc22 Michael Hanselmann

153 5b34cc22 Michael Hanselmann
    """
154 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.all()
155 1de1cf25 Apollon Oikonomopoulos
156 1de1cf25 Apollon Oikonomopoulos
  def GetReservedCount(self):
157 5b34cc22 Michael Hanselmann
    """Get the count of reserved addresses.
158 5b34cc22 Michael Hanselmann

159 5b34cc22 Michael Hanselmann
    """
160 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.count(True)
161 1de1cf25 Apollon Oikonomopoulos
162 1de1cf25 Apollon Oikonomopoulos
  def GetFreeCount(self):
163 5b34cc22 Michael Hanselmann
    """Get the count of unused addresses.
164 5b34cc22 Michael Hanselmann

165 5b34cc22 Michael Hanselmann
    """
166 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.count(False)
167 1de1cf25 Apollon Oikonomopoulos
168 1de1cf25 Apollon Oikonomopoulos
  def GetMap(self):
169 5b34cc22 Michael Hanselmann
    """Return a textual representation of the network's occupation status.
170 5b34cc22 Michael Hanselmann

171 5b34cc22 Michael Hanselmann
    """
172 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations.to01().replace("1", "X").replace("0", ".")
173 1de1cf25 Apollon Oikonomopoulos
174 1de1cf25 Apollon Oikonomopoulos
  def IsReserved(self, address):
175 5b34cc22 Michael Hanselmann
    """Checks if the given IP is reserved.
176 5b34cc22 Michael Hanselmann

177 5b34cc22 Michael Hanselmann
    """
178 1de1cf25 Apollon Oikonomopoulos
    idx = self._GetAddrIndex(address)
179 1de1cf25 Apollon Oikonomopoulos
    return self.all_reservations[idx]
180 1de1cf25 Apollon Oikonomopoulos
181 1de1cf25 Apollon Oikonomopoulos
  def Reserve(self, address, external=False):
182 5b34cc22 Michael Hanselmann
    """Mark an address as used.
183 5b34cc22 Michael Hanselmann

184 5b34cc22 Michael Hanselmann
    """
185 1de1cf25 Apollon Oikonomopoulos
    if self.IsReserved(address):
186 1de1cf25 Apollon Oikonomopoulos
      raise errors.AddressPoolError("%s is already reserved" % address)
187 1de1cf25 Apollon Oikonomopoulos
    self._Mark(address, external=external)
188 1de1cf25 Apollon Oikonomopoulos
189 1de1cf25 Apollon Oikonomopoulos
  def Release(self, address, external=False):
190 5b34cc22 Michael Hanselmann
    """Release a given address reservation.
191 5b34cc22 Michael Hanselmann

192 5b34cc22 Michael Hanselmann
    """
193 1de1cf25 Apollon Oikonomopoulos
    self._Mark(address, value=False, external=external)
194 1de1cf25 Apollon Oikonomopoulos
195 1de1cf25 Apollon Oikonomopoulos
  def GetFreeAddress(self):
196 5b34cc22 Michael Hanselmann
    """Returns the first available address.
197 5b34cc22 Michael Hanselmann

198 5b34cc22 Michael Hanselmann
    """
199 1de1cf25 Apollon Oikonomopoulos
    if self.IsFull():
200 1de1cf25 Apollon Oikonomopoulos
      raise errors.AddressPoolError("%s is full" % self.network)
201 1de1cf25 Apollon Oikonomopoulos
202 1de1cf25 Apollon Oikonomopoulos
    idx = self.all_reservations.index(False)
203 1de1cf25 Apollon Oikonomopoulos
    address = str(self.network[idx])
204 1de1cf25 Apollon Oikonomopoulos
    self.Reserve(address)
205 1de1cf25 Apollon Oikonomopoulos
    return address
206 1de1cf25 Apollon Oikonomopoulos
207 1de1cf25 Apollon Oikonomopoulos
  def GenerateFree(self):
208 5b34cc22 Michael Hanselmann
    """Returns the first free address of the network.
209 5b34cc22 Michael Hanselmann

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

212 1f1d3bf2 Dimitris Aragiorgis
    """
213 861a92b4 Dimitris Aragiorgis
    idx = self.all_reservations.search(self.FREE, 1)
214 55f70aef Dimitris Aragiorgis
    if idx:
215 55f70aef Dimitris Aragiorgis
      return str(self.network[idx[0]])
216 55f70aef Dimitris Aragiorgis
    else:
217 55f70aef Dimitris Aragiorgis
      raise errors.AddressPoolError("%s is full" % self.network)
218 1de1cf25 Apollon Oikonomopoulos
219 1de1cf25 Apollon Oikonomopoulos
  def GetExternalReservations(self):
220 5b34cc22 Michael Hanselmann
    """Returns a list of all externally reserved addresses.
221 5b34cc22 Michael Hanselmann

222 5b34cc22 Michael Hanselmann
    """
223 861a92b4 Dimitris Aragiorgis
    # pylint: disable=E1103
224 861a92b4 Dimitris Aragiorgis
    idxs = self.ext_reservations.search(self.RESERVED)
225 1de1cf25 Apollon Oikonomopoulos
    return [str(self.network[idx]) for idx in idxs]
226 1de1cf25 Apollon Oikonomopoulos
227 1de1cf25 Apollon Oikonomopoulos
  @classmethod
228 1de1cf25 Apollon Oikonomopoulos
  def InitializeNetwork(cls, net):
229 5b34cc22 Michael Hanselmann
    """Initialize an L{objects.Network} object.
230 1de1cf25 Apollon Oikonomopoulos

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

233 1de1cf25 Apollon Oikonomopoulos
    """
234 1de1cf25 Apollon Oikonomopoulos
    obj = cls(net)
235 beb81ea5 Dimitris Aragiorgis
    obj.Update()
236 1de1cf25 Apollon Oikonomopoulos
    for ip in [obj.network[0], obj.network[-1]]:
237 1de1cf25 Apollon Oikonomopoulos
      obj.Reserve(ip, external=True)
238 1de1cf25 Apollon Oikonomopoulos
    if obj.net.gateway is not None:
239 1de1cf25 Apollon Oikonomopoulos
      obj.Reserve(obj.net.gateway, external=True)
240 1de1cf25 Apollon Oikonomopoulos
    obj.Validate()
241 1de1cf25 Apollon Oikonomopoulos
    return obj