Revision 36b66e6e lib/config.py

b/lib/config.py
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

  

Also available in: Unified diff