Revision 6edb2627

b/lib/config.py
108 108
      all_reserved.update(holder_reserved)
109 109
    return all_reserved
110 110

  
111
  def GetECReserved(self, ec_id):
112
    ec_reserved = set()
113
    if ec_id in self._ec_reserved:
114
      ec_reserved.update(self._ec_reserved[ec_id])
115
    return ec_reserved
116

  
117

  
111 118
  def Generate(self, existing, generate_one_fn, ec_id):
112 119
    """Generate a new resource of this type
113 120

  
......
178 185
    self._temporary_macs = TemporaryReservationManager()
179 186
    self._temporary_secrets = TemporaryReservationManager()
180 187
    self._temporary_lvs = TemporaryReservationManager()
188
    self._temporary_ips = TemporaryReservationManager()
181 189
    self._all_rms = [self._temporary_ids, self._temporary_macs,
182
                     self._temporary_secrets, self._temporary_lvs]
190
                     self._temporary_secrets, self._temporary_lvs,
191
                     self._temporary_ips]
183 192
    # Note: in order to prevent errors when resolving our name in
184 193
    # _DistributeConfig, we compute it here once and reuse it; it's
185 194
    # better to raise an error before starting to modify the config
......
291 300
    else:
292 301
      self._temporary_macs.Reserve(ec_id, mac)
293 302

  
303
  def _UnlockedCommitTemporaryIps(self, ec_id):
304
    """Commit all reserved IP address to their respective pools
305

  
306
    """
307
    for action, address, net_uuid in self._temporary_ips.GetECReserved(ec_id):
308
      self._UnlockedCommitIp(action, net_uuid, address)
309

  
310
  def _UnlockedCommitIp(self, action, net_uuid, address):
311
    """Commit a reserved IP address to an IP pool.
312

  
313
    The IP address is taken from the network's IP pool and marked as reserved.
314

  
315
    """
316
    nobj = self._UnlockedGetNetwork(net_uuid)
317
    pool = network.AddressPool(nobj)
318
    if action == 'reserve':
319
      pool.Reserve(address)
320
    elif action == 'release':
321
      pool.Release(address)
322

  
323
  def _UnlockedReleaseIp(self, net_uuid, address, ec_id):
324
    """Give a specific IP address back to an IP pool.
325

  
326
    The IP address is returned to the IP pool designated by pool_id and marked
327
    as reserved.
328

  
329
    """
330
    nobj = self._UnlockedGetNetwork(net_uuid)
331
    pool = network.AddressPool(nobj)
332
    self._temporary_ips.Reserve(ec_id, ('release', address, net_uuid))
333

  
334
  @locking.ssynchronized(_config_lock, shared=1)
335
  def ReleaseIp(self, network, address, ec_id):
336
    """Give a specified IP address back to an IP pool.
337

  
338
    This is just a wrapper around _UnlockedReleaseIp.
339

  
340
    """
341
    net_uuid = self._UnlockedLookupNetwork(network)
342
    if net_uuid:
343
      self._UnlockedReleaseIp(net_uuid, address, ec_id)
344

  
345
  @locking.ssynchronized(_config_lock, shared=1)
346
  def GenerateIp(self, net, ec_id):
347
    """Find a free IPv4 address for an instance.
348

  
349
    """
350
    net_uuid = self._UnlockedLookupNetwork(net)
351
    nobj = self._UnlockedGetNetwork(net_uuid)
352
    pool = network.AddressPool(nobj)
353
    gen_free = pool.GenerateFree()
354

  
355
    def gen_one():
356
      try:
357
        ip = gen_free()
358
      except StopIteration:
359
        raise errors.ReservationError("Cannot generate IP. Network is full")
360
      return ("reserve", ip, net_uuid)
361

  
362
    _ ,address, _ = self._temporary_ips.Generate([], gen_one, ec_id)
363
    return address
364

  
365
  def _UnlockedReserveIp(self, net_uuid, address, ec_id):
366
    """Reserve a given IPv4 address for use by an instance.
367

  
368
    """
369
    nobj = self._UnlockedGetNetwork(net_uuid)
370
    pool = network.AddressPool(nobj)
371
    try:
372
      isreserved = pool.IsReserved(address)
373
    except errors.AddressPoolError:
374
      raise errors.ReservationError("IP address not in network")
375
    if isreserved:
376
      raise errors.ReservationError("IP address already in use")
377

  
378
    return self._temporary_ips.Reserve(ec_id, ('reserve', address, net_uuid))
379

  
380

  
381
  @locking.ssynchronized(_config_lock, shared=1)
382
  def ReserveIp(self, net, address, ec_id):
383
    """Reserve a given IPv4 address for use by an instance.
384

  
385
    """
386
    net_uuid = self._UnlockedLookupNetwork(net)
387
    if net_uuid:
388
      return self._UnlockedReserveIp(net_uuid, address, ec_id)
389

  
294 390
  @locking.ssynchronized(_config_lock, shared=1)
295 391
  def ReserveLV(self, lv_name, ec_id):
296 392
    """Reserve an VG/LV pair for an instance.
......
682 778
        else:
683 779
          raise errors.ProgrammerError("NIC mode '%s' not handled" % nic_mode)
684 780

  
685
        _AddIpAddress("%s/%s" % (link, nic.ip),
781
        _AddIpAddress("%s/%s/%s" % (link, nic.ip, nic.network),
686 782
                      "instance:%s/nic:%d" % (instance.name, idx))
687 783

  
688 784
    for ip, owners in ips.items():
......
2390 2486
    del self._config_data.networks[network_uuid]
2391 2487
    self._config_data.cluster.serial_no += 1
2392 2488
    self._WriteConfig()
2489

  
2490
  def _UnlockedGetGroupNetParams(self, net, node):
2491
    """Get the netparams (mode, link) of a network.
2492

  
2493
    Get a network's netparams for a given node.
2494

  
2495
    @type net: string
2496
    @param net: network name
2497
    @type node: string
2498
    @param node: node name
2499
    @rtype: dict or None
2500
    @return: netparams
2501

  
2502
    """
2503
    net_uuid = self._UnlockedLookupNetwork(net)
2504
    if net_uuid is None:
2505
      return None
2506

  
2507
    node_info = self._UnlockedGetNodeInfo(node)
2508
    nodegroup_info = self._UnlockedGetNodeGroup(node_info.group)
2509
    netparams = nodegroup_info.networks.get(net_uuid, None)
2510

  
2511
    return netparams
2512

  
2513
  @locking.ssynchronized(_config_lock, shared=1)
2514
  def GetGroupNetParams(self, net, node):
2515
    """Locking wrapper of _UnlockedGetGroupNetParams()
2516

  
2517
    """
2518
    return self._UnlockedGetGroupNetParams(net, node)
2519

  
2520

  
2521
  @locking.ssynchronized(_config_lock, shared=1)
2522
  def CheckIPInNodeGroup(self, ip, node):
2523
    """Check for conflictig IP.
2524

  
2525
    @type ip: string
2526
    @param ip: ip address
2527
    @type node: string
2528
    @param node: node name
2529
    @rtype: (string, dict) or (None, None)
2530
    @return: (network name, netparams)
2531

  
2532
    """
2533
    if ip is None:
2534
      return (None, None)
2535
    node_info = self._UnlockedGetNodeInfo(node)
2536
    nodegroup_info = self._UnlockedGetNodeGroup(node_info.group)
2537
    for net_uuid in nodegroup_info.networks.keys():
2538
      net_info = self._UnlockedGetNetwork(net_uuid)
2539
      pool = network.AddressPool(net_info)
2540
      if pool._Contains(ip):
2541
        return (net_info.name, nodegroup_info.networks[net_uuid])
2542

  
2543
    return (None, None)

Also available in: Unified diff