137 |
137 |
self._cfg_file = cfg_file
|
138 |
138 |
self._temporary_ids = TemporaryReservationManager()
|
139 |
139 |
self._temporary_drbds = {}
|
140 |
|
self._temporary_macs = set()
|
|
140 |
self._temporary_macs = TemporaryReservationManager()
|
141 |
141 |
# Note: in order to prevent errors when resolving our name in
|
142 |
142 |
# _DistributeConfig, we compute it here once and reuse it; it's
|
143 |
143 |
# better to raise an error before starting to modify the config
|
... | ... | |
154 |
154 |
"""
|
155 |
155 |
return os.path.exists(constants.CLUSTER_CONF_FILE)
|
156 |
156 |
|
|
157 |
def _GenerateOneMAC(self):
|
|
158 |
"""Generate one mac address
|
|
159 |
|
|
160 |
"""
|
|
161 |
prefix = self._config_data.cluster.mac_prefix
|
|
162 |
byte1 = random.randrange(0, 256)
|
|
163 |
byte2 = random.randrange(0, 256)
|
|
164 |
byte3 = random.randrange(0, 256)
|
|
165 |
mac = "%s:%02x:%02x:%02x" % (prefix, byte1, byte2, byte3)
|
|
166 |
return mac
|
|
167 |
|
157 |
168 |
@locking.ssynchronized(_config_lock, shared=1)
|
158 |
|
def GenerateMAC(self):
|
|
169 |
def GenerateMAC(self, ec_id):
|
159 |
170 |
"""Generate a MAC for an instance.
|
160 |
171 |
|
161 |
172 |
This should check the current instances for duplicates.
|
162 |
173 |
|
163 |
174 |
"""
|
164 |
|
prefix = self._config_data.cluster.mac_prefix
|
165 |
|
all_macs = self._AllMACs()
|
166 |
|
retries = 64
|
167 |
|
while retries > 0:
|
168 |
|
byte1 = random.randrange(0, 256)
|
169 |
|
byte2 = random.randrange(0, 256)
|
170 |
|
byte3 = random.randrange(0, 256)
|
171 |
|
mac = "%s:%02x:%02x:%02x" % (prefix, byte1, byte2, byte3)
|
172 |
|
if mac not in all_macs and mac not in self._temporary_macs:
|
173 |
|
break
|
174 |
|
retries -= 1
|
175 |
|
else:
|
176 |
|
raise errors.ConfigurationError("Can't generate unique MAC")
|
177 |
|
self._temporary_macs.add(mac)
|
178 |
|
return mac
|
|
175 |
existing = self._AllMACs()
|
|
176 |
return self._temporary_ids.Generate(existing, self._GenerateOneMAC, ec_id)
|
179 |
177 |
|
180 |
178 |
@locking.ssynchronized(_config_lock, shared=1)
|
181 |
|
def IsMacInUse(self, mac):
|
182 |
|
"""Predicate: check if the specified MAC is in use in the Ganeti cluster.
|
|
179 |
def ReserveMAC(self, mac, ec_id):
|
|
180 |
"""Reserve a MAC for an instance.
|
183 |
181 |
|
184 |
182 |
This only checks instances managed by this cluster, it does not
|
185 |
183 |
check for potential collisions elsewhere.
|
186 |
184 |
|
187 |
185 |
"""
|
188 |
186 |
all_macs = self._AllMACs()
|
189 |
|
return mac in all_macs or mac in self._temporary_macs
|
|
187 |
if mac in all_macs:
|
|
188 |
raise errors.ReservationError("mac already in use")
|
|
189 |
else:
|
|
190 |
self._temporary_macs.Reserve(mac, ec_id)
|
190 |
191 |
|
191 |
192 |
@locking.ssynchronized(_config_lock, shared=1)
|
192 |
193 |
def GenerateDRBDSecret(self):
|
... | ... | |
799 |
800 |
self._config_data.instances[instance.name] = instance
|
800 |
801 |
self._config_data.cluster.serial_no += 1
|
801 |
802 |
self._UnlockedReleaseDRBDMinors(instance.name)
|
802 |
|
for nic in instance.nics:
|
803 |
|
self._temporary_macs.discard(nic.mac)
|
804 |
803 |
self._WriteConfig()
|
805 |
804 |
|
806 |
805 |
def _EnsureUUID(self, item, ec_id):
|
... | ... | |
1420 |
1419 |
|
1421 |
1420 |
if isinstance(target, objects.Instance):
|
1422 |
1421 |
self._UnlockedReleaseDRBDMinors(target.name)
|
1423 |
|
for nic in target.nics:
|
1424 |
|
self._temporary_macs.discard(nic.mac)
|
1425 |
1422 |
|
1426 |
1423 |
self._WriteConfig(feedback_fn=feedback_fn)
|
1427 |
1424 |
|
... | ... | |
1431 |
1428 |
|
1432 |
1429 |
"""
|
1433 |
1430 |
self._temporary_ids.DropECReservations(ec_id)
|
|
1431 |
self._temporary_macs.DropECReservations(ec_id)
|
1434 |
1432 |
|