From 4cc83e2e97d8ace96450968b1d3f7a2c052fc4ea Mon Sep 17 00:00:00 2001
From: Nikos Skalkotos <skalkoto@grnet.gr>
Date: Fri, 21 Nov 2014 13:19:37 +0200
Subject: [PATCH] Add support list sysprep parameters

The type for those parameters is list:<type>
---
 image_creator/dialog_menu.py      |   3 +-
 image_creator/dialog_util.py      | 101 +++++++++++++++++++++++++-----
 image_creator/os_type/__init__.py |  57 ++++++++++++-----
 3 files changed, 128 insertions(+), 33 deletions(-)

diff --git a/image_creator/dialog_menu.py b/image_creator/dialog_menu.py
index 284d2c0..c38e2a8 100644
--- a/image_creator/dialog_menu.py
+++ b/image_creator/dialog_menu.py
@@ -656,7 +656,8 @@ def sysprep_params(session):
             if param.hidden:
                 continue
 
-            value = str(param.value)
+            value = "|".join([str(i) for i in param.value]) if param.is_list \
+                else str(param.value)
             if len(value) == 0:
                 value = "<not_set>"
             choices.append((name, value))
diff --git a/image_creator/dialog_util.py b/image_creator/dialog_util.py
index 6d93a3e..e85f84c 100644
--- a/image_creator/dialog_util.py
+++ b/image_creator/dialog_util.py
@@ -334,40 +334,107 @@ def edit_cloud(session, name):
     return True
 
 
+def _get_sysprep_param_value(session, param, default, title=None,
+                             delete=False):
+    """Get the value of a sysprep parameter"""
+    d = session['dialog']
+
+    if param.type in ("file", "dir"):
+        if not title:
+            title = "Please select a %s to use for the `%s' parameter" % \
+                ('file' if param.type == 'file' else 'directory', param.name)
+        ftype = "br" if param.type == 'file' else 'd'
+
+        value = select_file(d, ftype=ftype, title=title)
+    else:
+        if not title:
+            title = ("Please provide a new value for configuration parameter: "
+                     "`%s' or press <Delete> to completely delete it." %
+                     param.name)
+        (code, answer) = d.inputbox(title, width=WIDTH, init=str(default),
+                                    extra_button=int(delete),
+                                    extra_label="Delete")
+
+        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+            return (None, False)
+        if code == d.DIALOG_EXTRA:
+            return ("", True)
+
+        value = answer.strip()
+
+    return (value, False)
+
+
 def update_sysprep_param(session, name, title=None):
     """Modify the value of a sysprep parameter"""
+
     d = session['dialog']
     image = session['image']
 
     param = image.os.sysprep_params[name]
 
+    default_item = 1
     while 1:
-        if param.type in ("file", "dir"):
-            if not title:
-                title = "Please select a %s to use for the `%s' parameter" % \
-                    ('file' if param.type == 'file' else 'directory', name)
-            ftype = "br" if param.type == 'file' else 'd'
-
-            value = select_file(d, ftype=ftype, title=title)
-            if value is None:
-                return False
+        value = []
+        for i in param.value:
+            value.append(i)
+        if param.is_list:
+            choices = [(str(i+1), str(value[i])) for i in xrange(len(value))]
+            if len(choices) == 0:
+                action = 'add'
+                default_value = ""
+            else:
+                (code, choice) = d.menu(
+                    "Please press <Edit> to edit or remove a value or <Add> "
+                    "to add a new one. Press <Back> to go back.", height=18,
+                    width=WIDTH, choices=choices, menu_height=10,
+                    ok_label="Edit", extra_button=1, extra_label="Add",
+                    cancel="Back", default_item=str(default_item), title=name)
+
+                if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+                    return True
+                elif code == d.DIALOG_EXTRA:
+                    action = 'add'
+                    default_value = ""
+                elif code == d.DIALOG_OK:
+                    action = 'edit'
+                    choice = int(choice)
+                    default_value = choices[choice-1][1]
+                    default_item = choice
         else:
-            if not title:
-                title = "Please provide a new value for configuration " \
-                        "parameter: `%s'" % name
-            (code, answer) = d.inputbox(
-                title, width=WIDTH, init=str(param.value))
+            default_value = param.value
+            action = 'edit'
 
-            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+        (new_value, delete) = _get_sysprep_param_value(
+            session, param, default_value, title,
+            delete=(param.is_list and action == 'edit'))
+
+        if new_value is None:
+            if not param.is_list or len(param.value) == 0:
                 return False
+            continue
 
-            value = answer.strip()
+        if param.is_list:
+            if action == 'add':
+                value = value + [new_value]
+            if action == 'edit':
+                if delete:
+                    del value[choice-1]
+                else:
+                    value[choice-1] = new_value
 
         if param.set_value(value) is False:
             d.msgbox("Error: %s" % param.error, width=WIDTH)
             param.error = None
             continue
-        break
+        elif param.is_list:
+            if action == 'add':
+                default_item = len(param.value)
+            elif delete:
+                default_item = (default_item - 1) if default_item > 1 else 1
+
+        if not param.is_list or len(param.value) == 0:
+            break
 
     return True
 
diff --git a/image_creator/os_type/__init__.py b/image_creator/os_type/__init__.py
index 10944a8..e65e753 100644
--- a/image_creator/os_type/__init__.py
+++ b/image_creator/os_type/__init__.py
@@ -98,11 +98,11 @@ def sysprep(message, enabled=True, **kwargs):
 class SysprepParam(object):
     """This class represents a system preparation parameter"""
 
-    def __init__(self, type, default, description, **kwargs):
+    def __init__(self, name, type, default, description, **kwargs):
 
-        assert hasattr(self, "_check_%s" % type), "Invalid type: %s" % type
-
-        self.type = type
+        self.name = name
+        self.is_list = type.startswith('list:')
+        self.type = type.split(':', 1)[1] if self.is_list else type
         self.default = default
         self.description = description
         self.value = default
@@ -110,15 +110,25 @@ class SysprepParam(object):
         self.check = kwargs['check'] if 'check' in kwargs else lambda x: x
         self.hidden = kwargs['hidden'] if 'hidden' in kwargs else False
 
+        assert hasattr(self, "_check_%s" % self.type), \
+            "Invalid type: %s" % self.type
+
     def set_value(self, value):
         """Update the value of the parameter"""
 
         check_type = getattr(self, "_check_%s" % self.type)
-        try:
-            self.value = self.check(check_type(value))
-        except ValueError as e:
-            self.error = e.message
-            return False
+
+        tmp = []
+
+        for item in value if self.is_list else [value]:
+            try:
+                tmp.append(self.check(check_type(item)))
+            except ValueError as e:
+                self.error = e.message
+                return False
+
+        self.value = tmp if self.is_list else tmp[0]
+
         return True
 
     def _check_posint(self, value):
@@ -185,7 +195,7 @@ def add_sysprep_param(name, type, default, descr, **kwargs):
                 self.sysprep_params = {}
 
             self.sysprep_params[name] = \
-                SysprepParam(type, default, descr, **extra)
+                SysprepParam(name, type, default, descr, **extra)
             init(self, *args, **kwargs)
         return inner
     return wrapper
@@ -223,6 +233,19 @@ class OSBase(object):
                     self.out.warn("Ignoring invalid `%s' parameter." % key)
                     continue
                 param = self.sysprep_params[key]
+                if param.is_list:
+                    def split_in_comma(val):
+                        tmp = val.split(',')
+                        prev = ""
+                        for i in xrange(len(tmp)):
+                            item = prev + tmp[i]
+                            if item.endswith('\\'):
+                                prev = item[:-1]
+                                continue
+                            prev = ""
+                            yield item
+                    val = list(split_in_comma(val))
+
                 if not param.set_value(val):
                     raise FatalError("Invalid value for sysprep parameter: "
                                      "`%s'. Reason: %s" % (key, param.error))
@@ -401,15 +424,19 @@ class OSBase(object):
 
         wrapper = textwrap.TextWrapper()
         wrapper.subsequent_indent = "             "
-        wrapper.width = 72
+        wrapper.width = 80
 
         for name, param in public_params:
             if param.hidden:
                 continue
-            self.out.output("NAME:        %s" % name)
-            self.out.output("VALUE:       %s" % param.value)
-            self.out.output(
-                wrapper.fill("DESCRIPTION: %s" % param.description))
+            self.out.output("NAME:".ljust(13) + name)
+            self.out.output(wrapper.fill("DESCRIPTION:".ljust(13) +
+                            "%s" % param.description))
+            self.out.output("TYPE:".ljust(13) + "%s%s" %
+                            ("list:" if param.is_list else "", param.type))
+            self.out.output("VALUE:".ljust(13) +
+                            ("\n".ljust(14).join(param.value) if param.is_list
+                             else param.value))
             self.out.output()
 
     def do_sysprep(self):
-- 
GitLab