Page MenuHomeVyOS Platform

XML (used for CLI definitions)
Updated 1,467 Days AgoPublic

The bash (or better vbash) completion in VyOS is defined in templates. Templates are text files (called node.def) stored in a directory tree. The directory names define the command names, and template files define the command behaviour. Before VyOS 1.2 (crux) this files were created by hand. After a complex redesign process the new style template are automatically generated from a XML input file.

XML interface definitions for VyOS come with a RelaxNG schema and are located in the vyos-1x module. This schema is a slightly modified schema from VyConf alias VyOS 2.0 So VyOS 1.2.x interface definitions will be reusable in Nextgen VyOS Versions with very minimal changes.

The great thing about schemas is not only that people can know the complete grammar for certain, but also that it can be automatically verified. The scripts/build-command-templates script that converts the XML definitions to old style templates also verifies them against the schema, so a bad definition will cause the package build to fail. I do agree that the format is verbose, but there is no other format now that would allow this. Besides, a specialized XML editor can alleviate the issue with verbosity.

Example:

<?xml version="1.0"?>
<!-- Cron configuration -->
<interfaceDefinition>
  <node name="system">
    <children>
      <node name="task-scheduler">
        <properties>
          <help>Task scheduler settings</help>
        </properties>
        <children>
          <tagNode name="task" owner="${vyos_conf_scripts_dir}/task_scheduler.py">
            <properties>
              <help>Scheduled task</help>
              <valueHelp>
                <format>&lt;string&gt;</format>
                <description>Task name</description>
              </valueHelp>
              <priority>999</priority>
            </properties>
            <children>
              <leafNode name="crontab-spec">
                <properties>
                  <help>UNIX crontab time specification string</help>
                </properties>
              </leafNode>
              <leafNode name="interval">
                <properties>
                  <help>Execution interval</help>
                  <valueHelp>
                    <format>&lt;minutes&gt;</format>
                    <description>Execution interval in minutes</description>
                  </valueHelp>
                  <valueHelp>
                    <format>&lt;minutes&gt;m</format>
                    <description>Execution interval in minutes</description>
                  </valueHelp>
                  <valueHelp>
                    <format>&lt;hours&gt;h</format>
                    <description>Execution interval in hours</description>
                  </valueHelp>
                  <valueHelp>
                    <format>&lt;days&gt;d</format>
                    <description>Execution interval in days</description>
                  </valueHelp>
                  <constraint>
                    <regex>[1-9]([0-9]*)([mhd]{0,1})</regex>
                  </constraint>
                </properties>
              </leafNode>
              <node name="executable">
                <properties>
                  <help>Executable path and arguments</help>
                </properties>
                <children>
                  <leafNode name="path">
                    <properties>
                      <help>Path to executable</help>
                    </properties>
                  </leafNode>
                  <leafNode name="arguments">
                    <properties>
                      <help>Arguments passed to the executable</help>
                    </properties>
                  </leafNode>
                </children>
              </node>
            </children>
          </tagNode>
        </children>
      </node>
    </children>
  </node>
</interfaceDefinition>

Command definitions are purely declarative, and cannot contain any logic. All logic for generating config files for target applications, restarting services and so on is implemented in configuration scripts instead.

GNU Preprocessor

XML interface definition files use the xml.in file extension which was implemented in T1843. XML interface definitions tend to have a lot of duplicated code in areas such as:

  • VIF (incl. VIF-S/VIF-C)
  • Address
  • Description
  • Enabled/Disabled

Instead of supplying all those XML nodes multiple times there are now include files with predefined features. Brief overview:

All interface definition XML input files (.in suffix) will be sent to the GCC preprocess and the output is stored in the build/interface-definitions folder. The previously mentioned scripts/build-command-templates script operates on the build/interface-definitions folder to generate all required CLI nodes.

$ make interface_definitions
install -d -m 0755 build/interface-definitions
install -d -m 0755 build/op-mode-definitions
Generating build/interface-definitions/intel_qat.xml from interface-definitions/intel_qat.xml.in
Generating build/interface-definitions/interfaces-bonding.xml from interface-definitions/interfaces-bonding.xml.in
Generating build/interface-definitions/cron.xml from interface-definitions/cron.xml.in
Generating build/interface-definitions/pppoe-server.xml from interface-definitions/pppoe-server.xml.in
Generating build/interface-definitions/mdns-repeater.xml from interface-definitions/mdns-repeater.xml.in
Generating build/interface-definitions/tftp-server.xml from interface-definitions/tftp-server.xml.in
[...]

Guidelines

Use of numbers

Use of numbers in command names should be avoided unless a number is a part of a protocol name or similar. Thus, protocols ospfv3 is perfectly fine, but something like server-1 is questionable at best.

Help String

To ensure uniform look and feel, and improve readability, we should follow a set of guidelines consistently.

Capitalization and punctuation

The first word of every help string must be capitalized. There must not be a period at the end of help strings.

Rationale: this seems to be the unwritten standard in network device CLIs, and a good aesthetic compromise.

Examples:

  • Good: "Frobnication algorithm"
  • Bad: "frobnication algorithm"
  • Bad: "Frobnication algorithm."
  • Horrible: "frobnication algorithm."
Use of abbreviations and acronyms

Abbreviations and acronyms must be capitalized.

Examples:

  • Good: "TCP connection timeout"
  • Bad: "tcp connection timeout"
  • Horrible: "Tcp connection timeout"

Acronyms also must be capitalized to visually distinguish them from normal words:

Examples:

  • Good: RADIUS (as in remote authentication for dial-in user services)
  • Bad: radius (unless it's about the distance between a center of a circle and any of its points)

Some abbreviations are traditionally written in mixed case. Generally, if it contains words "over" or "version", the letter should be lowercase. If there's an accepted spelling (especially if defined by an RFC or another standard), it must be followed.

Examples:

  • Good: PPPoE, IPsec
  • Bad: PPPOE, IPSEC
  • Bad: pppoe, ipsec
Use of verbs

Verbs should be avoided. If a verb can be omitted, omit it.

Examples:

  • Good: "TCP connection timeout"
  • Bad: "Set TCP connection timeout"

If a verb is essential, keep it. For example, in the help text of set system ipv6 disable-forwarding, "Disable IPv6 forwarding on all interfaces" is a perfectly justified wording.

Prefer infinitives

Verbs, when they are necessary, should be in their infinitive form.

Examples:

  • Good: "Disable IPv6 forwarding"
  • Bad: "Disables IPv6 forwarding"

Migrating old CLI

Old concept/syntaxNew syntaxNotes
mynode/node.def<node name="mynode"> </node>Leaf nodes (nodes with values) use <leafNode> tag instead
mynode/node.tag , tag:<tagNode name="mynode> </node>
help: My node<properties> <help>My node</help>
val_help: <format>; some string<properties> <valueHelp> <format> format </format> <description> some string </description>Do not add angle brackets around the format, they will be inserted automatically
syntax:expression: pattern<properties> <constraint> <regex> ...<constraintErrorMessage> will be displayed on failure
syntax:expression: $VAR(@) in "foo", "bar", "baz"NoneUse regex
syntax:expression: exec ...<properties> <constraint> <validator> <name ="foo" argument="bar">"${vyos_libexecdir}/validators/foo bar $VAR(@)" will be executed, <constraintErrorMessage> will be displayed on failure
syntax:expression: (arithmetic expression)NoneExternal arithmetic validator may be added if there's demand, complex validation is better left to commit-time scripts
priority: 999<properties> <priority>999</priority>Please leave a comment explaining why the priority was chosen (e.g. "after interfaces are configured")
multi:<properties> <multi/>Only applicable to leaf nodes
allowed: echo foo bar<properties> <completionHelp> <list> foo bar </list>
allowed: cli-shell-api listNodes vpn ipsec esp-group<properties> <completionHelp> <path> vpn ipsec esp-group </path>
allowed: /path/to/script<properties> <completionHelp> <script> /path/to/script </script> ...
default:NoneMove default values to scripts
commit:expression:NoneAll commit time checks should be in the verify() function of the script
begin:/create:/delete:NoneAll logic should be in the scripts
Last Author
Unknown Object (User)
Last Edited
Mar 22 2020, 12:40 AM

Event Timeline

Unknown Object (User) created this object.Mar 22 2020, 12:40 AM