Merge branch 'develop'
[snf-image-creator] / image_creator / dialog_menu.py
index 9bc5c40..4f24b1e 100644 (file)
@@ -68,6 +68,8 @@ CONFIGURATION_TASKS = [
     ("File injection", ["EnforcePersonality"], ["windows", "linux"])
 ]
 
+SYSPREP_PARAM_MAXLEN = 20
+
 
 class MetadataMonitor(object):
     """Monitors image metadata chages"""
@@ -215,13 +217,26 @@ def register_image(session):
                  "register it", width=SMALL_WIDTH)
         return False
 
+    name = ""
+    description = session['metadata']['DESCRIPTION'] if 'DESCRIPTION' in \
+        session['metadata'] else ""
+
     while 1:
-        (code, answer) = d.inputbox("Please provide a registration name:",
-                                    width=WIDTH)
+        fields = [
+            ("Registration name:", name, 60),
+            ("Description (optional):", description, 80)]
+
+        (code, output) = d.form(
+            "Please provide the following registration info:", height=11,
+            width=WIDTH, form_height=2, fields=fields)
+
         if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
             return False
 
-        name = answer.strip()
+        name, description = output
+        name = name.strip()
+        description = description.strip()
+
         if len(name) == 0:
             d.msgbox("Registration name cannot be empty", width=SMALL_WIDTH)
             continue
@@ -236,6 +251,7 @@ def register_image(session):
 
         break
 
+    session['metadata']['DESCRIPTION'] = description
     metadata = {}
     metadata.update(session['metadata'])
     if 'task_metadata' in session:
@@ -397,9 +413,9 @@ def kamaki_menu(session):
                 if len(Kamaki.get_clouds()):
                     default_item = "Cloud"
                 else:
-                    default_time = "Add/Edit"
+                    default_item = "Add/Edit"
             else:
-                default_time = "Delete"
+                default_item = "Delete"
         elif choice == "Cloud":
             default_item = "Cloud"
             clouds = Kamaki.get_clouds()
@@ -486,6 +502,15 @@ def add_property(session):
     return True
 
 
+def show_properties_help(session):
+    """Show help for image properties"""
+    d = session['dialog']
+
+    help_file = get_help_file("image_properties")
+    assert os.path.exists(help_file)
+    d.textbox(help_file, title="Image Properties", width=70, height=40)
+
+
 def modify_properties(session):
     """Modify an existing image property"""
     d = session['dialog']
@@ -495,6 +520,19 @@ def modify_properties(session):
         for (key, val) in session['metadata'].items():
             choices.append((str(key), str(val)))
 
+        if len(choices) == 0:
+            code = d.yesno(
+                "No image properties are available. "
+                "Would you like to add a new one?", width=WIDTH, help_button=1)
+            if code == d.DIALOG_OK:
+                if not add_property(session):
+                    return True
+            elif code == d.DIALOG_CANCEL:
+                return True
+            elif code == d.DIALOG_HELP:
+                show_properties_help(session)
+            continue
+
         (code, choice) = d.menu(
             "In this menu you can edit existing image properties or add new "
             "ones. Be careful! Most properties have special meaning and "
@@ -524,9 +562,7 @@ def modify_properties(session):
         elif code == d.DIALOG_EXTRA:
             add_property(session)
         elif code == 'help':
-            help_file = get_help_file("image_properties")
-            assert os.path.exists(help_file)
-            d.textbox(help_file, title="Image Properties", width=70, height=40)
+            show_properties_help(session)
 
 
 def delete_properties(session):
@@ -537,6 +573,11 @@ def delete_properties(session):
     for (key, val) in session['metadata'].items():
         choices.append((key, "%s" % val, 0))
 
+    if len(choices) == 0:
+        d.msgbox("No available images properties to delete!",
+                 width=SMALL_WIDTH)
+        return True
+
     (code, to_delete) = d.checklist("Choose which properties to delete:",
                                     choices=choices, width=WIDTH)
     to_delete = map(lambda x: x.strip('"'), to_delete)  # needed for OpenSUSE
@@ -556,6 +597,12 @@ def delete_properties(session):
 def exclude_tasks(session):
     """Exclude specific tasks from running during image deployment"""
     d = session['dialog']
+    image = session['image']
+
+    if image.is_unsupported():
+        d.msgbox("Image deployment configuration is disabled for unsupported "
+                 "images.", width=SMALL_WIDTH)
+        return False
 
     index = 0
     displayed_index = 1
@@ -620,36 +667,70 @@ def exclude_tasks(session):
 
 
 def sysprep_params(session):
-
+    """Collect the needed sysprep parameters"""
     d = session['dialog']
     image = session['image']
 
     available = image.os.sysprep_params
-    needed = image.os.needed_sysprep_params()
+    needed = image.os.needed_sysprep_params
 
     if len(needed) == 0:
         return True
 
-    fields = []
-    for param in needed:
-        default = available[param.name] if param.name in available else ""
-        fields.append(("%s: " % param.description, default, param.length))
+    def print_form(names, extra_button=False):
+        """print the dialog form providing sysprep_params"""
+        fields = []
+        for name in names:
+            param = needed[name]
+            default = str(available[name]) if name in available else ""
+            fields.append(("%s: " % param.description, default,
+                           SYSPREP_PARAM_MAXLEN))
+
+        kwargs = {}
+        if extra_button:
+            kwargs['extra_button'] = 1
+            kwargs['extra_label'] = "Advanced"
+
+        txt = "Please provide the following system preparation parameters:"
+        return d.form(txt, height=13, width=WIDTH, form_height=len(fields),
+                      fields=fields, **kwargs)
+
+    def check_params(names, values):
+        """check if the provided sysprep parameters have leagal values"""
+        for i in range(len(names)):
+            param = needed[names[i]]
+            try:
+                normalized = param.type(values[i])
+                if param.validate(normalized):
+                    image.os.sysprep_params[names[i]] = normalized
+                    continue
+            except ValueError:
+                pass
+
+            d.msgbox("Invalid value for parameter: `%s'" % names[i],
+                     width=SMALL_WIDTH)
+            return False
+        return True
 
-    txt = "Please provide the following system preparation parameters:"
-    code, output = d.form(txt, height=13, width=WIDTH, form_height=len(fields),
-                          fields=fields)
+    simple_names = [k for k, v in needed.items() if v.default is None]
+    advanced_names = [k for k, v in needed.items() if v.default is not None]
 
-    if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
-        return False
+    while 1:
+        code, output = print_form(simple_names, extra_button=True)
 
-    sysprep_params = {}
-    for i in range(len(fields)):
-        if needed[i].validator(output[i]):
-            image.os.sysprep_params[needed[i].name] = output[i]
-        else:
-            d.msgbox("The value you provided for parameter: %s is not valid" %
-                     name, width=SMALL_WIDTH)
+        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
             return False
+        if code == d.DIALOG_EXTRA:
+            while 1:
+                code, output = print_form(advanced_names)
+                if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+                    break
+                if check_params(advanced_names, output):
+                    break
+            continue
+
+        if check_params(simple_names, output):
+            break
 
     return True