KVM

From KVM

Contents

The Cartesian Product KVM Test Config File Format

This is the format used by test configuration files in the kvm test. It was designed to meet several requirements:

  • Support for quick definition of multiple test scenarios (drive format, ACPI support, SMP configuration and other QEMU params) for all guests and tests
  • Support for exceptions applying to specific guests/tests/scenarios
  • Support for dependencies between tests
  • Unification of the various config files previously used into a single (hopefully simple) framework


Detailed Description

  • The parser relies on indentation.
  • The parser produces a list of dictionaries (dicts). Each dictionary contains a set of key-value pairs.
  • Each dict contains at least three keys: name, shortname and depend. The values of name and shortname are strings, and the value of depend is a list of strings.
  • A list of dictionaries will henceforth be referred to as a frame.
  • The initial frame contains a single dict, whose name and shortname are empty strings, and whose depend is an empty list.
  • Parsing dict contents:
    • The dict parser operates on a frame, which will henceforth be referred to as the current frame.
    • A statement of the form <key> = <value> sets the value of <key> to <value> in all dicts of the current frame. If a dict lacks <key>, it will be created.
    • A statement of the form <key> += <value> appends <value> to the value of <key> in all dicts of the current frame. If a dict lacks <key>, it will be created.
    • A statement of the form <key> <= <value> pre-pends <value> to the value of <key> in all dicts of the current frame. If a dict lacks <key>, it will be created.
    • A statement of the form <key> ?= <value> sets the value of <key> to <value>, in all dicts of the current frame, but only if <key> exists in the dict. The operators ?+= and ?<= are also supported.
    • A statement of the form no <regex> removes from the current frame all dicts whose name field matches <regex>.
    • A statement of the form only <regex> removes from the current frame all dicts whose name field does not match <regex>.
    • Exceptions:
      • Single line exceptions have the format <regex>: <key> <operator> <value> where <operator> is any of the operators listed above (e.g. =, +=, ?<=). The statement following the regular expression <regex> will apply only to the dicts in the current frame whose name partially matches <regex> (i.e. contains a substring that matches <regex>).
      • A multi-line exception block is opened by a line of the format <regex>:. The text following this line should be indented. The statements in a multi-line exception block may be assignment statements (such as <key> = <value>) or no or only statements. Nested multi-line exceptions are allowed.
  • Parsing variants:
    • A variants block is opened by a variants: statement. The contents of the block should follow the variants: line and should be indented.
    • A line in a variants block should be of the format - <variant_name>:. The contents of this variant should be specified following that line, and should be indented. The contents are parsed by the dict parser described above; they may be of the format <key> <op> <value>. They may also contain variants: statements, or whatever the dict parser recognizes.
    • Each variant in a variants block inherits a copy of the frame in which the variants: statement appears. The 'current frame', which may be modified by the dict parser, becomes this copy.
    • The name of the variant (specified in the line - <variant_name>:) is pre-pended to the name field of each dict of the variant's frame, along with a separator dot ('.').
    • If the name of the variant is not preceeded by a @ (i.e. - @<variant_name>:), it is pre-pended to the shortname field of each dict of the variant's frame. In other words, if a variant's name is preceeded by a @, it is omitted from the shortname field.
    • The frames of the variants defined in the variants block are joined into a single frame which replaces the frame in which the variants: statement appears.


Examples

A single dictionary

The following file: results in the following list of dictionaries (a single dictionary):

key1 = value1
key2 = value2
key3 = value3

Dictionary #0:
    depend = []
    key1 = value1
    key2 = value2
    key3 = value3
    name = 
    shortname =

Adding a variants block

The following file: results in the following list:

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
    - two:
    - three:

Dictionary #0:
    depend = []
    key1 = value1
    key2 = value2
    key3 = value3
    name = one
    shortname = one
Dictionary #1:
    depend = []
    key1 = value1
    key2 = value2
    key3 = value3
    name = two
    shortname = two
Dictionary #2:
    depend = []
    key1 = value1
    key2 = value2
    key3 = value3
    name = three
    shortname = three

Modifying dictionaries inside a variant

The following file: results in the following list:

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
        key1 = Hello World
        key2 <= some_prefix_
    - two:
        key2 <= another_prefix_
    - three:

Dictionary #0:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = one
    shortname = one
Dictionary #1:
    depend = []
    key1 = value1
    key2 = another_prefix_value2
    key3 = value3
    name = two
    shortname = two
Dictionary #2:
    depend = []
    key1 = value1
    key2 = value2
    key3 = value3
    name = three
    shortname = three

Adding dependencies

The following file: results in the following list:

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
        key1 = Hello World
        key2 <= some_prefix_
    - two: one
        key2 <= another_prefix_
    - three: one two

Dictionary #0:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = one
    shortname = one
Dictionary #1:
    depend = ['one']
    key1 = value1
    key2 = another_prefix_value2
    key3 = value3
    name = two
    shortname = two
Dictionary #2:
    depend = ['one', 'two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = three
    shortname = three

Multiple variants blocks

The following file: results in the following list:

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
        key1 = Hello World
        key2 <= some_prefix_
    - two: one
        key2 <= another_prefix_
    - three: one two

variants:
    - A:
    - B:

Dictionary #0:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = A.one
    shortname = A.one
Dictionary #1:
    depend = ['A.one']
    key1 = value1
    key2 = another_prefix_value2
    key3 = value3
    name = A.two
    shortname = A.two
Dictionary #2:
    depend = ['A.one', 'A.two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = A.three
    shortname = A.three
Dictionary #3:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = B.one
    shortname = B.one
Dictionary #4:
    depend = ['B.one']
    key1 = value1
    key2 = another_prefix_value2
    key3 = value3
    name = B.two
    shortname = B.two
Dictionary #5:
    depend = ['B.one', 'B.two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = B.three
    shortname = B.three

Using no and only

The following file: results in the following list:

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
        key1 = Hello World
        key2 <= some_prefix_
    - two: one
        key2 <= another_prefix_
    - three: one two

variants:
    - A:
        no one
    - B:
        only one|three

Dictionary #0:
    depend = ['A.one']
    key1 = value1
    key2 = another_prefix_value2
    key3 = value3
    name = A.two
    shortname = A.two
Dictionary #1:
    depend = ['A.one', 'A.two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = A.three
    shortname = A.three
Dictionary #2:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = B.one
    shortname = B.one
Dictionary #3:
    depend = ['B.one', 'B.two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = B.three
    shortname = B.three

Using @

The following file: results in the following list (note the difference between the name and shortname fields):

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
        key1 = Hello World
        key2 <= some_prefix_
    - two: one
        key2 <= another_prefix_
    - three: one two

variants:
    - @A:
        no one
    - B:
        only one|three

Dictionary #0:
    depend = ['A.one']
    key1 = value1
    key2 = another_prefix_value2
    key3 = value3
    name = A.two
    shortname = two
Dictionary #1:
    depend = ['A.one', 'A.two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = A.three
    shortname = three
Dictionary #2:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = B.one
    shortname = B.one
Dictionary #3:
    depend = ['B.one', 'B.two']
    key1 = value1
    key2 = value2
    key3 = value3
    name = B.three
    shortname = B.three

Using exceptions

The following file: results in the following list:

key1 = value1
key2 = value2
key3 = value3

variants:
    - one:
        key1 = Hello World
        key2 <= some_prefix_
    - two: one
        key2 <= another_prefix_
    - three: one two

variants:
    - @A:
        no one
    - B:
        only one|three

three: key4 = some_value

A:
    no two
    key5 = yet_another_value

Dictionary #0:
    depend = ['A.one', 'A.two']
    key1 = value1
    key2 = value2
    key3 = value3
    key4 = some_value
    key5 = yet_another_value
    name = A.three
    shortname = three
Dictionary #1:
    depend = []
    key1 = Hello World
    key2 = some_prefix_value2
    key3 = value3
    name = B.one
    shortname = B.one
Dictionary #2:
    depend = ['B.one', 'B.two']
    key1 = value1
    key2 = value2
    key3 = value3
    key4 = some_value
    name = B.three
    shortname = B.three


Experimenting with test config files

You may use the parser to experiment with config files in order to easily define your desired tests. The parser script may be invoked with a command line parameter, which indicates the name of the file to parse. The parser displays the resulting list of dictionaries, as well as some debugging output which may help you understand what's going on. For example, while parsing the last example file, the parser prints the following:

key1 = value1                                      ---> Parsing operator (1 dicts in current context)
key2 = value2                                      ---> Parsing operator (1 dicts in current context)
key3 = value3                                      ---> Parsing operator (1 dicts in current context)
variants:                                          ---> Entering variants block (1 dicts in current context)
    - one:                                         ---> Entering variant 'one' (variant inherits 1 dicts)
        key1 = Hello World                         ---> Parsing operator (1 dicts in current context)
        key2 <= some_prefix_                       ---> Parsing operator (1 dicts in current context)
    - two: one                                     ---> Entering variant 'two' (variant inherits 1 dicts)
        key2 <= another_prefix_                    ---> Parsing operator (1 dicts in current context)
    - three: one two                               ---> Entering variant 'three' (variant inherits 1 dicts)
variants:                                          ---> Entering variants block (3 dicts in current context)
    - @A:                                          ---> Entering variant 'A' (variant inherits 3 dicts)
        no one                                     ---> Parsing no/only (3 dicts in current context, 2 remain)
    - B:                                           ---> Entering variant 'B' (variant inherits 3 dicts)
        only one|three                             ---> Parsing no/only (3 dicts in current context, 2 remain)
three: key4 = some_value                           ---> Parsing operator (4 dicts in current context)
A:                                                 ---> Entering multi-line exception block (4 dicts in current context outside exception)
Views Article Discussion Edit History
Personal tools:  Log in / create account
Toolbox What links here Related changes Upload file Special pages Printable version