From 7dd999fc05acd270972bde65f1c2a918d5466144 Mon Sep 17 00:00:00 2001
From: Manuel Franceschini <livewire@google.com>
Date: Fri, 27 Aug 2010 10:52:46 +0200
Subject: [PATCH] Handle ENOENT case in ssconf.GetPrimaryIPFamily

This patch adds an optional default parameter to SimpleStore._ReadFile. This
can be used to default the return value of this method in case the ssconf file
is not present.

In this particular case it is used to return AF_INET in case
ssconf_primary_ip_familiy is absent. This is the case when upgrading
from 2.2 -> 2.3. This is intended behaviour as it is suboptimal to copy
the ssconf file manually to the nodes during an upgrade using
cfgupgrade.

In the concrete case of an upgrade from 2.2 -> 2.3 cfgupgrade will just
add the primary_ip_family parameter to the cluster configuration and the
daemons will start with default family AF_INET. This is perfectly fine,
since there is no AF_INET6 2.2 clusters. After that, the admin is
required (as in an major upgrade) to run 'gnt-cluster redist-conf' which
will write ssconf_primary_ip_family on all nodes.

Signed-off-by: Manuel Franceschini <livewire@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 lib/daemon.py | 15 ++++++---------
 lib/ssconf.py |  8 ++++++--
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/lib/daemon.py b/lib/daemon.py
index 6a1367092..6f67dc6ab 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -543,15 +543,12 @@ def GenericMain(daemon_name, optionparser, dirs, check_fn, exec_fn,
 
   if daemon_name in constants.DAEMONS_PORTS:
     default_bind_address = constants.IP4_ADDRESS_ANY
-    try:
-      family = ssconf.SimpleStore().GetPrimaryIPFamily()
-      if family == netutils.IP6Address.family:
-        default_bind_address = constants.IP6_ADDRESS_ANY
-    except errors.ConfigurationError:
-      # This case occurs when adding a node, as there is no ssconf available
-      # when noded is first started. In that case, however, the correct
-      # bind_address must be passed
-      pass
+    family = ssconf.SimpleStore().GetPrimaryIPFamily()
+    # family will default to AF_INET if there is no ssconf file (e.g. when
+    # upgrading a cluster from 2.2 -> 2.3. This is intended, as Ganeti clusters
+    # <= 2.2 can not be AF_INET6
+    if family == netutils.IP6Address.family:
+      default_bind_address = constants.IP6_ADDRESS_ANY
 
     default_port = netutils.GetDaemonPort(daemon_name)
 
diff --git a/lib/ssconf.py b/lib/ssconf.py
index 0449f8081..c759f8e4b 100644
--- a/lib/ssconf.py
+++ b/lib/ssconf.py
@@ -29,6 +29,7 @@ configuration data, which is mostly static and available to all nodes.
 import sys
 import re
 import os
+import errno
 
 from ganeti import errors
 from ganeti import constants
@@ -307,7 +308,7 @@ class SimpleStore(object):
     filename = self._cfg_dir + '/' + self._SS_FILEPREFIX + key
     return filename
 
-  def _ReadFile(self, key):
+  def _ReadFile(self, key, default=None):
     """Generic routine to read keys.
 
     This will read the file which holds the value requested. Errors
@@ -318,6 +319,8 @@ class SimpleStore(object):
     try:
       data = utils.ReadFile(filename, size=self._MAX_SIZE)
     except EnvironmentError, err:
+      if err.errno == errno.ENOENT and default is not None:
+        return default
       raise errors.ConfigurationError("Can't read from the ssconf file:"
                                       " '%s'" % str(err))
     data = data.rstrip('\n')
@@ -466,7 +469,8 @@ class SimpleStore(object):
 
     """
     try:
-      return int(self._ReadFile(constants.SS_PRIMARY_IP_FAMILY))
+      return int(self._ReadFile(constants.SS_PRIMARY_IP_FAMILY,
+                                default=netutils.IP4Address.family))
     except (ValueError, TypeError), err:
       raise errors.ConfigurationError("Error while trying to parse primary ip"
                                       " family: %s" % err)
-- 
GitLab