From 2abc8f5797be8f13efb4ef00bea32ec44a281cb8 Mon Sep 17 00:00:00 2001
From: Apollon Oikonomopoulos <apollon@noc.grnet.gr>
Date: Mon, 22 Nov 2010 17:41:03 +0200
Subject: [PATCH] LUCreateInstance: Retrieve IPs from an IP pool

A new ip keyword is added ("pool") to signify that LUCreateInstance should get
the instance's IP from an IP pool (rather than manually or by DNS resolution).

IP and link checks are re-ordered so that a NIC's link is available at the time
of IP address validation.

Signed-off-by: Apollon Oikonomopoulos <apollon@noc.grnet.gr>
---
 lib/cmdlib.py    | 51 +++++++++++++++++++++++++++++++-----------------
 lib/constants.py |  2 ++
 2 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 34f012f66..22879aec7 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -7720,6 +7720,24 @@ class LUInstanceCreate(LogicalUnit):
       if nic_mode is None:
         nic_mode = cluster.nicparams[constants.PP_DEFAULT][constants.NIC_MODE]
 
+      # bridge verification
+      bridge = nic.get("bridge", None)
+      link = nic.get("link", None)
+      if bridge and link:
+        raise errors.OpPrereqError("Cannot pass 'bridge' and 'link'"
+                                   " at the same time", errors.ECODE_INVAL)
+      elif bridge and nic_mode == constants.NIC_MODE_ROUTED:
+        raise errors.OpPrereqError("Cannot pass 'bridge' on a routed nic",
+                                   errors.ECODE_INVAL)
+      elif bridge:
+        link = bridge
+
+      nicparams = {}
+      if nic_mode_req:
+        nicparams[constants.NIC_MODE] = nic_mode_req
+      if link:
+        nicparams[constants.NIC_LINK] = link
+
       # in routed mode, for the first nic, the default ip is 'auto'
       if nic_mode == constants.NIC_MODE_ROUTED and idx == 0:
         default_ip_mode = constants.VALUE_AUTO
@@ -7736,11 +7754,26 @@ class LUInstanceCreate(LogicalUnit):
                                      " have been skipped",
                                      errors.ECODE_INVAL)
         nic_ip = self.hostname1.ip
+        try:
+          self.cfg.ReserveIp(link, nic_ip, self.proc.GetECId())
+        except errors.ReservationError:
+          raise errors.OpPrereqError("IP address %s already in use"
+                                     " in cluster" % nic_ip,
+                                     errors.ECODE_NOTUNIQUE)
+      elif ip.lower() == constants.NIC_IP_POOL:
+        nic_ip = self.cfg.GenerateIp(link, self.proc.GetECId())
+        logging.info("Chose ip %s from pool %s" % (nic_ip, link))
       else:
         if not netutils.IPAddress.IsValid(ip):
           raise errors.OpPrereqError("Invalid IP address '%s'" % ip,
                                      errors.ECODE_INVAL)
         nic_ip = ip
+        try:
+          self.cfg.ReserveIp(link, nic_ip, self.proc.GetECId())
+        except errors.ReservationError:
+          raise errors.OpPrereqError("IP address %s already in use"
+                                     " in cluster" % nic_ip,
+                                     errors.ECODE_NOTUNIQUE)
 
       # TODO: check the ip address for uniqueness
       if nic_mode == constants.NIC_MODE_ROUTED and not nic_ip:
@@ -7759,24 +7792,6 @@ class LUInstanceCreate(LogicalUnit):
                                      " in cluster" % mac,
                                      errors.ECODE_NOTUNIQUE)
 
-      # bridge verification
-      bridge = nic.get("bridge", None)
-      link = nic.get("link", None)
-      if bridge and link:
-        raise errors.OpPrereqError("Cannot pass 'bridge' and 'link'"
-                                   " at the same time", errors.ECODE_INVAL)
-      elif bridge and nic_mode == constants.NIC_MODE_ROUTED:
-        raise errors.OpPrereqError("Cannot pass 'bridge' on a routed nic",
-                                   errors.ECODE_INVAL)
-      elif bridge:
-        link = bridge
-
-      nicparams = {}
-      if nic_mode_req:
-        nicparams[constants.NIC_MODE] = nic_mode_req
-      if link:
-        nicparams[constants.NIC_LINK] = link
-
       check_params = cluster.SimpleFillNIC(nicparams)
       objects.NIC.CheckParameterSyntax(check_params)
       self.nics.append(objects.NIC(mac=mac, ip=nic_ip, nicparams=nicparams))
diff --git a/lib/constants.py b/lib/constants.py
index 2c1d91c1b..85e6dcd23 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -738,6 +738,8 @@ NIC_LINK = "link"
 NIC_MODE_BRIDGED = "bridged"
 NIC_MODE_ROUTED = "routed"
 
+NIC_IP_POOL = "pool"
+
 NIC_VALID_MODES = frozenset([NIC_MODE_BRIDGED, NIC_MODE_ROUTED])
 
 NICS_PARAMETER_TYPES = {
-- 
GitLab