diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
index 04ed2b5..6cd0e88 100755
--- a/virttest/cartesian_config.py
+++ b/virttest/cartesian_config.py
@@ -131,6 +131,10 @@ class ParserError:
             return "%s (%s:%s)" % (self.msg, self.filename, self.linenum)
 
 
+class MissingDefault:
+    pass
+
+
 class MissingIncludeError:
     def __init__(self, line, filename, linenum):
         self.line = line
@@ -225,6 +229,7 @@ class Node(object):
         self.labels = set()
         self.append_to_shortname = False
         self.failed_cases = collections.deque()
+        self.default = False
 
 
     def dump(self, indent, recurse=False):
@@ -407,14 +412,17 @@ class Parser(object):
 
     @see: https://github.com/autotest/autotest/wiki/KVMAutotest-CartesianConfigParametersIntro
     """
-    def __init__(self, filename=None, debug=False):
+    def __init__(self, filename=None, defaults=False, debug=False):
         """
         Initialize the parser and optionally parse a file.
 
         @param filename: Path of the file to parse.
+        @param defaults: If True adds only defaults variant from variants
+                         if there is some.
         @param debug: Whether to turn on debugging output.
         """
         self.node = Node()
+        self.defaults = defaults
         self.debug = debug
         if filename:
             self.parse_file(filename)
@@ -611,10 +619,18 @@ class Parser(object):
 
         # Recurse into children
         count = 0
-        for n in node.children:
-            for d in self.get_dicts(n, ctx, new_content, shortname, dep):
-                count += 1
-                yield d
+        if self.defaults:
+            for n in node.children:
+                for d in self.get_dicts(n, ctx, new_content, shortname, dep):
+                    count += 1
+                    yield d
+                if n.default and count:
+                    break
+        else:
+            for n in node.children:
+                for d in self.get_dicts(n, ctx, new_content, shortname, dep):
+                    count += 1
+                    yield d
         # Reached leaf?
         if not node.children:
             self._debug("    reached leaf, returning it")
@@ -656,7 +672,8 @@ class Parser(object):
         print s % args
 
 
-    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None):
+    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None,
+                        with_default=False):
         """
         Read and parse lines from a FileReader object until a line with an
         indent level lower than or equal to prev_indent is encountered.
@@ -665,8 +682,10 @@ class Parser(object):
         @param node: A node to operate on.
         @param prev_indent: The indent level of the "parent" block.
         @param var_name: Variants name
+        @param with_default: Variants take only default variant.
         @return: A node object.
         """
+        already_default = False
         node4 = Node()
 
         while True:
@@ -694,7 +713,9 @@ class Parser(object):
             node2.labels = node.labels
 
             node3 = self._parse(cr, node2, prev_indent=indent)
-            node3.name = [Label(var_name, n) for n in name.lstrip("@").split(".")]
+            is_default = name.startswith("@")
+            name = name.lstrip("@")
+            node3.name = [Label(var_name, n) for n in name.split(".")]
             node3.dep = [Label(var_name, d) for d in dep.replace(",", " ").split()]
 
             if var_name:
@@ -702,12 +723,33 @@ class Parser(object):
                 op_match = _ops_exp.search(l)
                 node3.content += [(cr.filename, linenum, Op(l, op_match))]
 
-            is_default = name.startswith("@")
-
-            node4.children += [node3]
+            node3.append_to_shortname = not is_default
+
+            if with_default and self.defaults:
+                """
+                Relevant only if defaults is True and
+                variants is with default.
+                """
+                if is_default:
+                    if not already_default:
+                        node3.default = True
+                        already_default = True
+                    else:
+                        raise MissingDefault
+                if node3.default:
+                    # Move default variant in front of rest of all variants.
+                    # Speed optimization.
+                    node4.children.insert(0, node3)
+                else:
+                    node4.children += [node3]
+            else:
+                node4.children += [node3]
             node4.labels.update(node3.labels)
             node4.labels.update(node3.name)
 
+        if with_default and not already_default:
+            raise MissingDefault
+
         return node4
 
 
@@ -751,6 +793,7 @@ class Parser(object):
                                 char in "._-=,"):
                             raise ParserError("Illegal characters in variants",
                                               line, cr.filename, linenum)
+                with_default = False
                 var_name = None
                 if name:
                     block = name.split(",")
@@ -761,12 +804,20 @@ class Parser(object):
                                 raise ParserError("Missing name of variants",
                                                   line, cr.filename, linenum)
                             var_name = oper[1].strip()
+                        elif "with_default" in oper[0]:
+                            with_default = True
                         else:
                             raise ParserError("Ilegal variants param",
                                                line, cr.filename, linenum)
-                node = self._parse_variants(cr, node, prev_indent=indent,
-                                            var_name=var_name)
-                                            var_name=name)
+                try:
+                    node = self._parse_variants(cr, node, prev_indent=indent,
+                                                var_name=var_name,
+                                                with_default=with_default)
+                except MissingDefault:
+                    raise ParserError("There must be exactly one default "
+                                      "variant in variants with param "
+                                      "with_default.",
+                                      line, cr.filename, linenum)
                 continue
 
             # Parse 'include' statements
@@ -1040,12 +1091,15 @@ if __name__ == "__main__":
                       help="show dict contents")
     parser.add_option("-r", "--repr", dest="repr_mode", action="store_true",
                       help="Output parsing results Python format")
+    parser.add_option("-d", "--defaults", dest="defaults", action="store_true",
+                      help="use only default variant of variants if there"
+                           " is some")
 
     options, args = parser.parse_args()
     if not args:
         parser.error("filename required")
 
-    c = Parser(args[0], debug=options.debug)
+    c = Parser(args[0], defaults=options.defaults, debug=options.debug)
     for s in args[1:]:
         c.parse_string(s)
 
