49 |
49 |
from ganeti import uidpool
|
50 |
50 |
from ganeti import netutils
|
51 |
51 |
from ganeti import runtime
|
|
52 |
from ganeti import ippool
|
52 |
53 |
|
53 |
54 |
|
54 |
55 |
_config_lock = locking.SharedLock("ConfigWriter")
|
... | ... | |
148 |
149 |
self._temporary_macs = TemporaryReservationManager()
|
149 |
150 |
self._temporary_secrets = TemporaryReservationManager()
|
150 |
151 |
self._temporary_lvs = TemporaryReservationManager()
|
|
152 |
self._temporary_ips = TemporaryReservationManager()
|
151 |
153 |
self._all_rms = [self._temporary_ids, self._temporary_macs,
|
152 |
|
self._temporary_secrets, self._temporary_lvs]
|
|
154 |
self._temporary_secrets, self._temporary_lvs,
|
|
155 |
self._temporary_ips]
|
153 |
156 |
# Note: in order to prevent errors when resolving our name in
|
154 |
157 |
# _DistributeConfig, we compute it here once and reuse it; it's
|
155 |
158 |
# better to raise an error before starting to modify the config
|
... | ... | |
214 |
217 |
else:
|
215 |
218 |
self._temporary_macs.Reserve(ec_id, mac)
|
216 |
219 |
|
|
220 |
def _UnlockedCommitIp(self, link, address):
|
|
221 |
"""Commit a reserved IP address to an IP pool.
|
|
222 |
|
|
223 |
The IP address is taken from the IP pool designated by link and marked
|
|
224 |
as reserved.
|
|
225 |
|
|
226 |
"""
|
|
227 |
if link is None:
|
|
228 |
nicparams = self._config_data.cluster.nicparams[constants.VALUE_DEFAULT]
|
|
229 |
link = nicparams[constants.NIC_LINK]
|
|
230 |
|
|
231 |
if link not in self._config_data.cluster.networks or\
|
|
232 |
"4" not in self._config_data.cluster.networks[link]:
|
|
233 |
return False
|
|
234 |
|
|
235 |
netdict = self._config_data.cluster.networks[link]["4"]
|
|
236 |
network = ippool.IPv4Network.fromdict(netdict)
|
|
237 |
try:
|
|
238 |
addr = network.reserve(address)
|
|
239 |
except ippool.IPv4PoolError, err:
|
|
240 |
raise errors.ConfigurationError("Unable to reserve IP: %s", str(err))
|
|
241 |
|
|
242 |
self._config_data.cluster.networks[link]["4"] = network.todict()
|
|
243 |
|
|
244 |
@locking.ssynchronized(_config_lock)
|
|
245 |
def CommitIp(self, link, address):
|
|
246 |
"""Commit a reserved IP to an IP pool
|
|
247 |
|
|
248 |
This is just a wrapper around _UnlockedCommitIp.
|
|
249 |
|
|
250 |
"""
|
|
251 |
self._UnlockedCommitIp(self, link)
|
|
252 |
self._WriteConfig()
|
|
253 |
|
|
254 |
def _UnlockedReleaseIp(self, link, address):
|
|
255 |
"""Give a specific IP address back to an IP pool.
|
|
256 |
|
|
257 |
The IP address is returned to the IP pool designated by pool_id and marked
|
|
258 |
as reserved.
|
|
259 |
|
|
260 |
"""
|
|
261 |
if link is None:
|
|
262 |
nicparams = self._config_data.cluster.nicparams[constants.VALUE_DEFAULT]
|
|
263 |
link = nicparams[constants.NIC_LINK]
|
|
264 |
|
|
265 |
if link not in self._config_data.cluster.networks or\
|
|
266 |
"4" not in self._config_data.cluster.networks[link]:
|
|
267 |
return
|
|
268 |
|
|
269 |
netdict = self._config_data.cluster.networks[link]["4"]
|
|
270 |
network = ippool.IPv4Network.fromdict(netdict)
|
|
271 |
network.release(address)
|
|
272 |
self._config_data.cluster.networks[link]["4"] = network.todict()
|
|
273 |
|
|
274 |
@locking.ssynchronized(_config_lock)
|
|
275 |
def ReleaseIp(self, link, address):
|
|
276 |
"""Give a specified IP address back to an IP pool.
|
|
277 |
|
|
278 |
This is just a wrapper around _UnlockedReleaseIp.
|
|
279 |
|
|
280 |
"""
|
|
281 |
self._UnlockedReleaseIp(link, address)
|
|
282 |
self._WriteConfig()
|
|
283 |
|
|
284 |
@locking.ssynchronized(_config_lock, shared=1)
|
|
285 |
def GenerateIp(self, link, ec_id):
|
|
286 |
"""Find a free IPv4 address for an instance.
|
|
287 |
|
|
288 |
"""
|
|
289 |
if link is None:
|
|
290 |
nicparams = self._config_data.cluster.nicparams[constants.VALUE_DEFAULT]
|
|
291 |
link = nicparams[constants.NIC_LINK]
|
|
292 |
|
|
293 |
if link not in self._config_data.cluster.networks or\
|
|
294 |
"4" not in self._config_data.cluster.networks[link]:
|
|
295 |
raise errors.OpPrereqError("No network defined on link %s exists" % link,
|
|
296 |
errors.ECODE_INVAL)
|
|
297 |
netdict = self._config_data.cluster.networks[link]["4"]
|
|
298 |
network = ippool.IPv4Network.fromdict(netdict)
|
|
299 |
return self._temporary_ips.Generate([], network.generate_free(), ec_id)
|
|
300 |
|
|
301 |
@locking.ssynchronized(_config_lock, shared=1)
|
|
302 |
def ReserveIp(self, link, address, ec_id):
|
|
303 |
"""Reserve a given IPv4 address for use by an instance.
|
|
304 |
|
|
305 |
"""
|
|
306 |
if link is None:
|
|
307 |
nicparams = self._config_data.cluster.nicparams[constants.VALUE_DEFAULT]
|
|
308 |
link = nicparams[constants.NIC_LINK]
|
|
309 |
|
|
310 |
if link not in self._config_data.cluster.networks or\
|
|
311 |
"4" not in self._config_data.cluster.networks[link]:
|
|
312 |
return
|
|
313 |
netdict = self._config_data.cluster.networks[link]["4"]
|
|
314 |
network = ippool.IPv4Network.fromdict(netdict)
|
|
315 |
network.reserve(address)
|
|
316 |
return self._temporary_ips.Reserve(address, ec_id)
|
|
317 |
|
217 |
318 |
@locking.ssynchronized(_config_lock, shared=1)
|
218 |
319 |
def ReserveLV(self, lv_name, ec_id):
|
219 |
320 |
"""Reserve an VG/LV pair for an instance.
|
... | ... | |
1087 |
1188 |
raise errors.ConfigurationError("Cannot add instance %s:"
|
1088 |
1189 |
" MAC address '%s' already in use." %
|
1089 |
1190 |
(instance.name, nic.mac))
|
|
1191 |
# Commit all IP addresses to the respective address pools
|
|
1192 |
self._UnlockedCommitIp(nic.nicparams.get(constants.NIC_LINK, None),
|
|
1193 |
nic.ip)
|
1090 |
1194 |
|
1091 |
1195 |
self._EnsureUUID(instance, ec_id)
|
1092 |
1196 |
|
... | ... | |
1141 |
1245 |
"""
|
1142 |
1246 |
if instance_name not in self._config_data.instances:
|
1143 |
1247 |
raise errors.ConfigurationError("Unknown instance '%s'" % instance_name)
|
|
1248 |
for nic in self._config_data.instances[instance_name].nics:
|
|
1249 |
# Return all IP addresses to the respective address pools
|
|
1250 |
self._UnlockedReleaseIp(nic.nicparams.get(constants.NIC_LINK, None),
|
|
1251 |
nic.ip)
|
1144 |
1252 |
del self._config_data.instances[instance_name]
|
1145 |
1253 |
self._config_data.cluster.serial_no += 1
|
1146 |
1254 |
self._WriteConfig()
|