From 845da3e806e9b16831c61f07b33db925eba66607 Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Mon, 14 Jun 2010 03:34:41 +0200
Subject: [PATCH] Fix unsafe variant initializer in _TryOSFromDisk

In case an OS has inconsistent declarations, we might get into a case
where one node reports a valid variants list (with OS API >=15), and
another node has OS API < 15, in which case its supported_variants gets
the default value of None. This leads to the same variable having
inconsistent data types, which leads to subtle bugs later: instead of
reporting something like "Inconsistent OS API versions", the LU exits
with a run-time exception. Furthermore, in another datapath, variants is
initialized to '[]' in case of OS diagnose failures.

The patch changes _TryOSFromDisk to initialize variants to '[]' for
OS api level below 15, and changes the variants calculation in
DiagnoseOS to be more readable.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Guido Trotter <ultrotter@google.com>
---
 lib/backend.py | 2 +-
 lib/cmdlib.py  | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/backend.py b/lib/backend.py
index f1474b71c..769e6a66f 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1851,7 +1851,7 @@ def _TryOSFromDisk(name, base_dir=None):
         return False, ("File '%s' under path '%s' is not executable" %
                        (filename, os_dir))
 
-  variants = None
+  variants = []
   if constants.OS_VARIANTS_FILE in os_files:
     variants_file = os_files[constants.OS_VARIANTS_FILE]
     try:
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 8f58243e3..baa0a9ab8 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -2782,14 +2782,14 @@ class LUDiagnoseOS(NoHooksLU):
         for osl in os_data.values():
           valid = valid and osl and osl[0][1]
           if not valid:
-            variants = None
+            variants = set()
             break
           if calc_variants:
             node_variants = osl[0][3]
             if variants is None:
-              variants = node_variants
+              variants = set(node_variants)
             else:
-              variants = [v for v in variants if v in node_variants]
+              variants.intersection_update(node_variants)
 
       for field in self.op.output_fields:
         if field == "name":
@@ -2802,7 +2802,7 @@ class LUDiagnoseOS(NoHooksLU):
           for node_name, nos_list in os_data.items():
             val[node_name] = nos_list
         elif field == "variants":
-          val =  variants
+          val = list(variants)
         else:
           raise errors.ParameterError(field)
         row.append(val)
-- 
GitLab