Revision 6c0a75db

b/lib/cmdlib.py
40 40
import shutil
41 41
import itertools
42 42
import operator
43
import ipaddr
43 44

  
44 45
from ganeti import ssh
45 46
from ganeti import utils
......
61 62
from ganeti import runtime
62 63
from ganeti import pathutils
63 64
from ganeti import vcluster
65
from ganeti import network
64 66
from ganeti.masterd import iallocator
65 67

  
66 68
import ganeti.masterd.instance # pylint: disable=W0611
......
15303 15305

  
15304 15306
# Network LUs
15305 15307
class LUNetworkAdd(LogicalUnit):
15308
  """Logical unit for creating networks.
15309

  
15310
  """
15311
  HPATH = "network-add"
15312
  HTYPE = constants.HTYPE_NETWORK
15313
  REQ_BGL = False
15314

  
15306 15315
  def BuildHooksNodes(self):
15307
    pass
15316
    """Build hooks nodes.
15317

  
15318
    """
15319
    mn = self.cfg.GetMasterNode()
15320
    return ([mn], [mn])
15321

  
15322
  def ExpandNames(self):
15323
    self.network_uuid = self.cfg.GenerateUniqueID(self.proc.GetECId())
15324
    self.needed_locks = {}
15325
    self.add_locks[locking.LEVEL_NETWORK] = self.network_uuid
15326

  
15327
  def CheckPrereq(self):
15328
    """Check prerequisites.
15329

  
15330
    This checks that the given group name is not an existing node group
15331
    already.
15332

  
15333
    """
15334
    if self.op.network is None:
15335
      raise errors.OpPrereqError("Network must be given",
15336
                                 errors.ECODE_INVAL)
15337

  
15338
    uuid = self.cfg.LookupNetwork(self.op.network_name)
15339

  
15340
    if uuid:
15341
      raise errors.OpPrereqError("Network '%s' already defined" %
15342
                                 self.op.network, errors.ECODE_EXISTS)
15343

  
15308 15344

  
15309 15345
  def BuildHooksEnv(self):
15310
    pass
15346
    """Build hooks env.
15347

  
15348
    """
15349
    env = {
15350
      "NETWORK_NAME": self.op.network_name,
15351
      "NETWORK_SUBNET": self.op.network,
15352
      "NETWORK_GATEWAY": self.op.gateway,
15353
      "NETWORK_SUBNET6": self.op.network6,
15354
      "NETWORK_GATEWAY6": self.op.gateway6,
15355
      "NETWORK_MAC_PREFIX": self.op.mac_prefix,
15356
      "NETWORK_TYPE": self.op.network_type,
15357
      }
15358
    return env
15359

  
15360
  def Exec(self, feedback_fn):
15361
    """Add the ip pool to the cluster.
15362

  
15363
    """
15364
    nobj = objects.Network(name=self.op.network_name,
15365
                           network=self.op.network,
15366
                           gateway=self.op.gateway,
15367
                           network6=self.op.network6,
15368
                           gateway6=self.op.gateway6,
15369
                           mac_prefix=self.op.mac_prefix,
15370
                           network_type=self.op.network_type,
15371
                           uuid=self.network_uuid,
15372
                           family=4)
15373
    # Initialize the associated address pool
15374
    try:
15375
      pool = network.AddressPool.InitializeNetwork(nobj)
15376
    except errors.AddressPoolError, e:
15377
      raise errors.OpExecError("Cannot create IP pool for this network. %s" % e)
15378

  
15379
    # Check if we need to reserve the nodes and the cluster master IP
15380
    # These may not be allocated to any instances in routed mode, as
15381
    # they wouldn't function anyway.
15382
    for node in self.cfg.GetAllNodesInfo().values():
15383
      for ip in [node.primary_ip, node.secondary_ip]:
15384
        try:
15385
          pool.Reserve(ip)
15386
          self.LogInfo("Reserved node %s's IP (%s)", node.name, ip)
15387

  
15388
        except errors.AddressPoolError:
15389
          pass
15390

  
15391
    master_ip = self.cfg.GetClusterInfo().master_ip
15392
    try:
15393
      pool.Reserve(master_ip)
15394
      self.LogInfo("Reserved cluster master IP (%s)", master_ip)
15395
    except errors.AddressPoolError:
15396
      pass
15397

  
15398
    if self.op.add_reserved_ips:
15399
      for ip in self.op.add_reserved_ips:
15400
        try:
15401
          pool.Reserve(ip, external=True)
15402
        except errors.AddressPoolError, e:
15403
          raise errors.OpExecError("Cannot reserve IP %s. %s " % (ip, e))
15404

  
15405
    self.cfg.AddNetwork(nobj, self.proc.GetECId(), check_uuid=False)
15406
    del self.remove_locks[locking.LEVEL_NETWORK]
15311 15407

  
15312 15408

  
15313 15409
class LUNetworkRemove(LogicalUnit):
15314
  def BuildHooksNodes(self):
15315
    pass
15410
  HPATH = "network-remove"
15411
  HTYPE = constants.HTYPE_NETWORK
15412
  REQ_BGL = False
15413

  
15414
  def ExpandNames(self):
15415
    self.network_uuid = self.cfg.LookupNetwork(self.op.network_name)
15416

  
15417
    self.needed_locks = {
15418
      locking.LEVEL_NETWORK: [self.network_uuid],
15419
      }
15420

  
15421

  
15422
  def CheckPrereq(self):
15423
    """Check prerequisites.
15424

  
15425
    This checks that the given network name exists as a network, that is
15426
    empty (i.e., contains no nodes), and that is not the last group of the
15427
    cluster.
15428

  
15429
    """
15430
    if not self.network_uuid:
15431
      raise errors.OpPrereqError("Network %s not found" % self.op.network_name,
15432
                                 errors.ECODE_INVAL)
15433

  
15434
    # Verify that the network is not conncted.
15435
    node_groups = [group.name
15436
                   for group in self.cfg.GetAllNodeGroupsInfo().values()
15437
                   for network in group.networks.keys()
15438
                   if network == self.network_uuid]
15439

  
15440
    if node_groups:
15441
      self.LogWarning("Nework '%s' is connected to the following"
15442
                      " node groups: %s" % (self.op.network_name,
15443
                      utils.CommaJoin(utils.NiceSort(node_groups))))
15444
      raise errors.OpPrereqError("Network still connected",
15445
                                 errors.ECODE_STATE)
15316 15446

  
15317 15447
  def BuildHooksEnv(self):
15318
    pass
15448
    """Build hooks env.
15449

  
15450
    """
15451
    return {
15452
      "NETWORK_NAME": self.op.network_name,
15453
      }
15454

  
15455
  def BuildHooksNodes(self):
15456
    """Build hooks nodes.
15457

  
15458
    """
15459
    mn = self.cfg.GetMasterNode()
15460
    return ([mn], [mn])
15461

  
15462
  def Exec(self, feedback_fn):
15463
    """Remove the network.
15464

  
15465
    """
15466
    try:
15467
      self.cfg.RemoveNetwork(self.network_uuid)
15468
    except errors.ConfigurationError:
15469
      raise errors.OpExecError("Network '%s' with UUID %s disappeared" %
15470
                               (self.op.network_name, self.network_uuid))
15319 15471

  
15320 15472

  
15321 15473
class LUNetworkSetParams(LogicalUnit):
b/lib/config.py
51 51
from ganeti import netutils
52 52
from ganeti import runtime
53 53
from ganeti import pathutils
54
from ganeti import network
54 55

  
55 56

  
56 57
_config_lock = locking.SharedLock("ConfigWriter")
......
2094 2095
    nodegroups = ["%s %s" % (nodegroup.uuid, nodegroup.name) for nodegroup in
2095 2096
                  self._config_data.nodegroups.values()]
2096 2097
    nodegroups_data = fn(utils.NiceSort(nodegroups))
2098
    networks = ["%s %s" % (net.uuid, net.name) for net in
2099
                self._config_data.networks.values()]
2100
    networks_data = fn(utils.NiceSort(networks))
2097 2101

  
2098 2102
    ssconf_values = {
2099 2103
      constants.SS_CLUSTER_NAME: cluster.cluster_name,
......
2118 2122
      constants.SS_MAINTAIN_NODE_HEALTH: str(cluster.maintain_node_health),
2119 2123
      constants.SS_UID_POOL: uid_pool,
2120 2124
      constants.SS_NODEGROUPS: nodegroups_data,
2125
      constants.SS_NETWORKS: networks_data,
2121 2126
      }
2122 2127
    bad_values = [(k, v) for k, v in ssconf_values.items()
2123 2128
                  if not isinstance(v, (str, basestring))]
......
2245 2250
    """
2246 2251
    for rm in self._all_rms:
2247 2252
      rm.DropECReservations(ec_id)
2253

  
2254
  @locking.ssynchronized(_config_lock, shared=1)
2255
  def GetAllNetworksInfo(self):
2256
    """Get the configuration of all networks
2257

  
2258
    """
2259
    return dict(self._config_data.networks)
2260

  
2261
  def _UnlockedGetNetworkList(self):
2262
    """Get the list of networks.
2263

  
2264
    This function is for internal use, when the config lock is already held.
2265

  
2266
    """
2267
    return self._config_data.networks.keys()
2268

  
2269
  @locking.ssynchronized(_config_lock, shared=1)
2270
  def GetNetworkList(self):
2271
    """Get the list of networks.
2272

  
2273
    @return: array of networks, ex. ["main", "vlan100", "200]
2274

  
2275
    """
2276
    return self._UnlockedGetNetworkList()
2277

  
2278
  @locking.ssynchronized(_config_lock, shared=1)
2279
  def GetNetworkNames(self):
2280
    """Get a list of network names
2281

  
2282
    """
2283
    names = [network.name
2284
             for network in self._config_data.networks.values()]
2285
    return names
2286

  
2287
  def _UnlockedGetNetwork(self, uuid):
2288
    """Returns information about a network.
2289

  
2290
    This function is for internal use, when the config lock is already held.
2291

  
2292
    """
2293
    if uuid not in self._config_data.networks:
2294
      return None
2295

  
2296
    return self._config_data.networks[uuid]
2297

  
2298
  @locking.ssynchronized(_config_lock, shared=1)
2299
  def GetNetwork(self, uuid):
2300
    """Returns information about a network.
2301

  
2302
    It takes the information from the configuration file.
2303

  
2304
    @param uuid: UUID of the network
2305

  
2306
    @rtype: L{objects.Network}
2307
    @return: the network object
2308

  
2309
    """
2310
    return self._UnlockedGetNetwork(uuid)
2311

  
2312
  @locking.ssynchronized(_config_lock)
2313
  def AddNetwork(self, net, ec_id, check_uuid=True):
2314
    """Add a network to the configuration.
2315

  
2316
    @type net: L{objects.Network}
2317
    @param net: the Network object to add
2318
    @type ec_id: string
2319
    @param ec_id: unique id for the job to use when creating a missing UUID
2320

  
2321
    """
2322
    self._UnlockedAddNetwork(net, ec_id, check_uuid)
2323
    self._WriteConfig()
2324

  
2325
  def _UnlockedAddNetwork(self, net, ec_id, check_uuid):
2326
    """Add a network to the configuration.
2327

  
2328
    """
2329
    logging.info("Adding network %s to configuration", net.name)
2330

  
2331
    if check_uuid:
2332
      self._EnsureUUID(net, ec_id)
2333

  
2334
    existing_uuid = self._UnlockedLookupNetwork(net.name)
2335
    if existing_uuid:
2336
      raise errors.OpPrereqError("Desired network name '%s' already"
2337
                                 " exists as a network (UUID: %s)" %
2338
                                 (net.name, existing_uuid),
2339
                                 errors.ECODE_EXISTS)
2340
    net.serial_no = 1
2341
    self._config_data.networks[net.uuid] = net
2342
    self._config_data.cluster.serial_no += 1
2343

  
2344
  def _UnlockedLookupNetwork(self, target):
2345
    """Lookup a network's UUID.
2346

  
2347
    @type target: string
2348
    @param target: network name or UUID
2349
    @rtype: string
2350
    @return: network UUID
2351
    @raises errors.OpPrereqError: when the target network cannot be found
2352

  
2353
    """
2354
    if target in self._config_data.networks:
2355
      return target
2356
    for net in self._config_data.networks.values():
2357
      if net.name == target:
2358
        return net.uuid
2359
    return None
2360

  
2361
  @locking.ssynchronized(_config_lock, shared=1)
2362
  def LookupNetwork(self, target):
2363
    """Lookup a network's UUID.
2364

  
2365
    This function is just a wrapper over L{_UnlockedLookupNetwork}.
2366

  
2367
    @type target: string
2368
    @param target: network name or UUID
2369
    @rtype: string
2370
    @return: network UUID
2371

  
2372
    """
2373
    return self._UnlockedLookupNetwork(target)
2374

  
2375
  @locking.ssynchronized(_config_lock)
2376
  def RemoveNetwork(self, network_uuid):
2377
    """Remove a network from the configuration.
2378

  
2379
    @type network_uuid: string
2380
    @param network_uuid: the UUID of the network to remove
2381

  
2382
    """
2383
    logging.info("Removing network %s from configuration", network_uuid)
2384

  
2385
    if network_uuid not in self._config_data.networks:
2386
      raise errors.ConfigurationError("Unknown network '%s'" % network_uuid)
2387

  
2388
    del self._config_data.networks[network_uuid]
2389
    self._config_data.cluster.serial_no += 1
2390
    self._WriteConfig()
b/lib/locking.py
1477 1477
#: Level for node resources, used for operations with possibly high impact on
1478 1478
#: the node's disks.
1479 1479
LEVEL_NODE_RES = 4
1480
LEVEL_NETWORK = 5
1480 1481

  
1481 1482
LEVELS = [
1482 1483
  LEVEL_CLUSTER,
......
1484 1485
  LEVEL_NODEGROUP,
1485 1486
  LEVEL_NODE,
1486 1487
  LEVEL_NODE_RES,
1488
  LEVEL_NETWORK,
1487 1489
  ]
1488 1490

  
1489 1491
# Lock levels which are modifiable
......
1492 1494
  LEVEL_NODE,
1493 1495
  LEVEL_NODEGROUP,
1494 1496
  LEVEL_INSTANCE,
1497
  LEVEL_NETWORK,
1495 1498
  ])
1496 1499

  
1497 1500
#: Lock level names (make sure to use singular form)
......
1501 1504
  LEVEL_NODEGROUP: "nodegroup",
1502 1505
  LEVEL_NODE: "node",
1503 1506
  LEVEL_NODE_RES: "node-res",
1507
  LEVEL_NETWORK: "network",
1504 1508
  }
1505 1509

  
1506 1510
# Constant for the big ganeti lock
......
1518 1522
  """
1519 1523
  _instance = None
1520 1524

  
1521
  def __init__(self, nodes, nodegroups, instances):
1525
  def __init__(self, nodes, nodegroups, instances, networks):
1522 1526
    """Constructs a new GanetiLockManager object.
1523 1527

  
1524 1528
    There should be only a GanetiLockManager object at any time, so this
......
1543 1547
      LEVEL_NODE: LockSet(nodes, "node", monitor=self._monitor),
1544 1548
      LEVEL_NODE_RES: LockSet(nodes, "node-res", monitor=self._monitor),
1545 1549
      LEVEL_NODEGROUP: LockSet(nodegroups, "nodegroup", monitor=self._monitor),
1546
      LEVEL_INSTANCE: LockSet(instances, "instance",
1547
                              monitor=self._monitor),
1550
      LEVEL_INSTANCE: LockSet(instances, "instance", monitor=self._monitor),
1551
      LEVEL_NETWORK: LockSet(networks, "network", monitor=self._monitor),
1548 1552
      }
1549 1553

  
1550 1554
    assert compat.all(ls.name == LEVEL_NAMES[level]
b/lib/server/masterd.py
487 487
    self.glm = locking.GanetiLockManager(
488 488
      self.cfg.GetNodeList(),
489 489
      self.cfg.GetNodeGroupList(),
490
      self.cfg.GetInstanceList())
490
      self.cfg.GetInstanceList(),
491
      self.cfg.GetNetworkList())
491 492

  
492 493
    self.cfg.SetContext(self)
493 494

  

Also available in: Unified diff