From 6de7c41dff317d4a28be278d82fe6a1c1767b6da Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Tue, 18 Nov 2008 10:00:28 +0000
Subject: [PATCH] Add a FieldSet class for variable parameter sets

This patch adds a _FieldSet class that can be used for the new variable
parameter sets: e.g. the sda_size will change to disk/0.size (or
similar) and we need to both check validity and extract the index of the
parameter easily.

The patch also sorts the unittest list in Makefile.am.

Reviewed-by: ultrotter
---
 Makefile.am                    | 17 ++++++-----
 lib/cmdlib.py                  | 43 ++++++++++++++++++++++++++
 test/ganeti.cmdlib_unittest.py | 55 ++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+), 8 deletions(-)
 create mode 100755 test/ganeti.cmdlib_unittest.py

diff --git a/Makefile.am b/Makefile.am
index 2e63c6dc0..0474980c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -191,18 +191,19 @@ TEST_FILES = \
 	test/data/proc_drbd8.txt
 
 dist_TESTS = \
+	test/ganeti.bdev_unittest.py \
+	test/ganeti.cli_unittest.py \
+	test/ganeti.cmdlib_unittest.py \
 	test/ganeti.config_unittest.py \
+	test/ganeti.constants_unittest.py \
 	test/ganeti.hooks_unittest.py \
-	test/ganeti.utils_unittest.py \
-	test/ganeti.bdev_unittest.py \
-	test/ganeti.ssh_unittest.py \
+	test/ganeti.http_unittest.py \
 	test/ganeti.locking_unittest.py \
-	test/ganeti.serializer_unittest.py \
-	test/ganeti.workerpool_unittest.py \
 	test/ganeti.rapi.resources_unittest.py \
-	test/ganeti.http_unittest.py \
-	test/ganeti.constants_unittest.py \
-	test/ganeti.cli_unittest.py
+	test/ganeti.serializer_unittest.py \
+	test/ganeti.ssh_unittest.py \
+	test/ganeti.utils_unittest.py \
+	test/ganeti.workerpool_unittest.py
 
 nodist_TESTS =
 
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 5f1517bcc..6fd79e897 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -32,6 +32,7 @@ import re
 import platform
 import logging
 import copy
+import itertools
 
 from ganeti import ssh
 from ganeti import utils
@@ -322,6 +323,48 @@ class NoHooksLU(LogicalUnit):
   HTYPE = None
 
 
+class _FieldSet(object):
+  """A simple field set.
+
+  Among the features are:
+    - checking if a string is among a list of static string or regex objects
+    - checking if a whole list of string matches
+    - returning the matching groups from a regex match
+
+  Internally, all fields are held as regular expression objects.
+
+  """
+  def __init__(self, *items):
+    self.items = [re.compile("^%s$" % value) for value in items]
+
+  def Extend(self, other_set):
+    """Extend the field set with the items from another one"""
+    self.items.extend(other_set.items)
+
+  def Matches(self, field):
+    """Checks if a field matches the current set
+
+    @type field: str
+    @param field: the string to match
+    @return: either False or a regular expression match object
+
+    """
+    for m in itertools.ifilter(None, (val.match(field) for val in self.items)):
+      return m
+    return False
+
+  def NonMatching(self, items):
+    """Returns the list of fields not matching the current set
+
+    @type items: list
+    @param items: the list of fields to check
+    @rtype: list
+    @return: list of non-matching fields
+
+    """
+    return [val for val in items if not self.Matches(val)]
+
+
 def _GetWantedNodes(lu, nodes):
   """Returns list of checked and expanded node names.
 
diff --git a/test/ganeti.cmdlib_unittest.py b/test/ganeti.cmdlib_unittest.py
new file mode 100755
index 000000000..1fcf43a62
--- /dev/null
+++ b/test/ganeti.cmdlib_unittest.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+#
+
+# Copyright (C) 2008 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 0.0510-1301, USA.
+
+
+"""Script for unittesting the cmdlib module"""
+
+
+import os
+import unittest
+import time
+import Queue
+
+from ganeti import cmdlib
+from ganeti import errors
+
+
+class FieldSetTestCase(unittest.TestCase):
+  """Test case for FieldSets"""
+
+  def testSimpleMatch(self):
+    f = cmdlib._FieldSet("a", "b", "c", "def")
+    self.failUnless(f.Matches("a"))
+    self.failIf(f.Matches("d"), "Substring matched")
+    self.failIf(f.Matches("defghi"), "Prefix string matched")
+    self.failIf(f.NonMatching(["b", "c"]))
+    self.failIf(f.NonMatching(["a", "b", "c", "def"]))
+    self.failUnless(f.NonMatching(["a", "d"]))
+
+  def testRegexMatch(self):
+    f = cmdlib._FieldSet("a", "b([0-9]+)", "c")
+    self.failUnless(f.Matches("b1"))
+    self.failUnless(f.Matches("b99"))
+    self.failIf(f.Matches("b/1"))
+    self.failIf(f.NonMatching(["b12", "c"]))
+    self.failUnless(f.NonMatching(["a", "1"]))
+
+if __name__ == '__main__':
+  unittest.main()
-- 
GitLab