Customize YANG RPC Output on Devices Running Junos OS
Learn about the Junos OS ODL extension statements that you can include in custom YANG RPCs to define the CLI format for RPC output.
You can create custom RPCs in YANG for devices running Junos OS or devices running Junos OS Evolved. Creating custom RPCs enables you to precisely define the input parameters and operations and the output fields and formatting for specific operational tasks on your devices.
When you execute an RPC on a device running Junos OS, it returns the RPC reply as an XML
document. The Junos OS Output Definition Language (ODL) defines the transformation of XML
data into formatted ASCII output. The device displays this text output when you execute a
command in the CLI or request RPC output in text format. The Junos OS ODL extensions module
defines YANG extensions for the Junos OS ODL, which you can include in custom RPCs to
specify the CLI formatting for the output. For a summary of all the statements and their
placement within the RPC output statement, see Understanding Junos OS YANG Extensions for Formatting RPC Output.
The following sections outline how to use the Junos OS ODL extension statements. Closely related
statements are presented in the same section, and in some instances, a statement might be
included in more than one section. The examples assume that the enclosing YANG module
imports the Junos OS ODL extensions module and binds it to the junos-odl
prefix.
blank-line
The blank-line statement inserts
a line between each repetition of data when the RPC reply returns
the same set of information for multiple entities. For example, if
the RPC reply returns data for multiple interfaces, the formatted
ASCII output inserts a blank line between each interface’s set
of data.
Physical interface: ge-0/0/0, Enabled, Physical link is Up Interface index: 150, SNMP ifIndex: 528 ... Physical interface: ge-0/0/1, Enabled, Physical link is Up Interface index: 151, SNMP ifIndex: 529 ...
To insert a blank line between each entity’s data
set, include the blank-line statement directly
under the format statement.
rpc get-xyz-information {
output {
container xyz-information {
// leaf definitions
junos-odl:format xyz-information-format {
junos-odl:blank-line;
// CLI formatting
}
}
}
}capitalize
The capitalize statement capitalizes the first word of a node’s value in an
output field. It does not affect the capitalization of a node’s formal name. For
example, if the RPC output includes a state node with the value
online, the capitalize statement capitalizes the
value in the output.
State: Online
To capitalize the first word of the node’s value, include
the capitalize statement within the format statement. The placement of the statement determines
the statement’s scope and whether it affects a single field,
all fields in a single line, or all lines.
rpc get-xyz-information {
output {
container xyz-information {
leaf state {
junos-odl:formal-name "State";
type string;
description "Interface state";
}
junos-odl:format xyz-information-format {
junos-odl:header "xyz information\n";
junos-odl:line {
junos-odl:field "state" {
junos-odl:leading;
junos-odl:colon;
junos-odl:capitalize;
}
}
}
}
}
}colon, formal-name, and leading
A node’s formal name, or label, is the text that precedes a node’s contents in the output. To
create a label for a node, you must include the formal-name
statement in the definition of the leaf node. Additionally, you must include the
leading statement in the formatting instructions for that node’s
output field.
In the following example, the version node has the formal name
Version:
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
junos-odl:formal-name "Version";
type string;
description "Version";
}
...
}
}
}The colon statement inserts a colon after the node’s label in an output field.
If the formatting instructions include both the colon and
leading statements, the output inserts the node’s label and a
colon before the node’s value. For example:
Version: value
To insert the label and a colon in the output field,
include the leading and colon statements within the format statement.
The placement of the statements determines the scope and whether the
statements affect a single field, all fields in a single line, or
all lines.
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
junos-odl:formal-name "Version";
type string;
description "Version";
}
junos-odl:format xyz-information-format {
junos-odl:line {
junos-odl:field "version" {
junos-odl:colon;
junos-odl:leading;
}
}
}
}
}
}When you execute the RPC, the output for that field includes the label and a colon.
Version: value
comma
The comma statement appends a comma to the node’s value in the output. It is
used with the space statement to create comma-delimited fields in a
line of output. For example:
value1, Label2: value2, value3
To generate a comma and a space after a node’s value in
the output field, include the comma and space statements within the format statement. The placement of the statements within the format statement determines the scope. Placing the
statements within a single field generates a comma and space for that
field only. Placing the statements directly under the format statement applies the formatting to all fields.
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
type string;
description "Version";
}
// additional leaf definitions
junos-odl:format xyz-information-format {
junos-odl:comma;
junos-odl:space;
junos-odl:line {
junos-odl:field "version";
// additional fields
}
}
}
}
}If you omit the comma statement in
the formatting instructions in this example, the fields are separated
using only a space. Junos OS automatically omits the comma and space
after the last field in a line of output.
default-text
The default-text statement specifies the text to display in the formatted ASCII
output when the node corresponding to an output field is missing.
To define the string to display when the node mapped to a field is missing, include the
default-text statement and string within the
field statement for that node.
rpc get-xyz-information {
output {
container xyz-information {
leaf my-model {
type string;
description "Model";
}
junos-odl:format xyz-information-format {
junos-odl:line {
junos-odl:field "my-model" {
junos-odl:default-text "Model number not available.";
}
}
}
}
}
}When the node is missing in the RPC reply, the CLI output displays the default text.
Model number not available.
The device only displays the default text when the node is missing. It does not display the text for nodes that are present but empty.
explicit
The explicit statement is only used in Junos OS RPCs. You cannot include this
statement in custom RPCs.
field and line
The line and field statements define lines in the RPC’s
formatted ASCII output and the fields within those lines. You can also use these
statements with the picture statement to create a more structured
table that defines strict column widths and text justification.
To define a line in the formatted ASCII output, include
the line statement within the format statement. Within the line statement, include field statements that
map the leaf nodes in the output tree to fields in the line. The field statement’s argument is the leaf identifier.
Fields must be emitted in the same order as you defined the leaf statements.
The CLI output for the following RPC is a single line with three
values. Note that you can include other ODL statements within the field and line statements
to customize the formatting for either a single field or all fields
within that line, respectively.
rpc get-xyz-information {
output {
container xyz-information {
leaf my-version {
type string;
description "Version";
}
leaf my-model {
type string;
description "Model";
}
leaf comment {
type string;
description "Comment";
}
junos-odl:format xyz-information-format {
junos-odl:comma;
junos-odl:space;
junos-odl:line {
junos-odl:field "my-version" {
junos-odl:capitalize;
}
junos-odl:field "my-model";
junos-odl:field "comment";
}
}
}
}
}fieldwrap and wordwrap
The fieldwrap and wordwrap statements enable you to more logically wrap content when a line’s
width is greater than the width of the display. By default, content
that extends past the edge of the display wraps at the point where
it meets the right margin, without concern for word boundaries.
The fieldwrap statement wraps a field’s
complete contents to the next line when the current line is so long
that it extends past the right edge of the display. If you do not
use this statement, the string wraps automatically but without regard
for appropriate word breaks or the prevailing margin.
Consider the following lines of output:
Output errors: Carrier transitions: 1, Errors: 0, Collisions: 0, Drops: 0, Aged packets: 0
If the display is narrower than usual, the line could wrap in the middle of a word as shown in the following sample output:
Output errors: Carrier transitions: 1, Errors: 0, Collisions: 0, Dro ps: 0, Aged packets: 0
When you include the fieldwrap statement for a field, the entire field is moved
to the next line.
Output errors: Carrier transitions: 1, Errors: 0, Collisions: 0, Drops: 0, Aged packets: 0
You should only use the wordwrap statement on the rightmost column in a table to
wrap sections of a multiword value to subsequent lines when the current line is too
long. This statement effectively creates a column of text. In the following example,
the wordwrap statement divides the description string at word
boundaries:
Packet type Total Last 5 seconds Description
Sent Received Sent Received
Hello 0 0 4 5 Establish and maintain
neighbor relationships.
DbD 20 25 0 0 (Database description packets)
Describe the contents of
the topological database.
LSReq 6 5 0 0 (Link-State Request packets)
Request a precise instance
of the database.
To improve the wrapping behavior in the RPC’s formatted
ASCII output, include the fieldwrap statement
in each field’s formatting instructions. To wrap the rightmost
column in a table, include the wordwrap statement in the rightmost field’s formatting instructions.
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
type string;
description "Version";
}
leaf desc {
type string;
description "Description";
}
junos-odl:format xyz-information-format {
junos-odl:picture "@<<<<<<<<<<<<<<@<<<<<<<<<<<<<<";
junos-odl:line {
junos-odl:field "version" {
junos-odl:fieldwrap;
}
junos-odl:field "desc" {
junos-odl:wordwrap;
}
}
}
}
}
}float, header, picture, and truncate
You can create tables in the RPC’s formatted ASCII output
by defining a header statement, a picture statement, and one or more line statements. The optional header statement
defines the column headings for a table, but it can also just define
general text. The picture statement graphically
depicts the placement, justification, and width of the columns in
a table. The line and field statements define the table rows and their fields.
The argument for the picture statement
is a string that includes the at (@), less than (<), greater than
(>), and vertical bar (|) symbols to define the placement, justification,
and width of the table columns. The @ symbol defines the leftmost
position in a column that a value in a field can occupy. The <,
>, and | symbols indicate left, right, and center justification, respectively.
Repeating the <, >, or | symbol defines the column width. Table 1 summarizes
the symbols. You can also insert one or more blank spaces between
columns.
Symbol |
Description |
|---|---|
@ |
Defines the leftmost position in a column that a value in a field can occupy. |
| |
Centers the contents of the field. Repeated symbols define the column width. |
< |
Left justifies the contents of the field. Repeated symbols define the column width. |
> |
Right justifies the contents of the field. Repeated symbols define the column width. |
The following picture statement
defines a left-justified column, a centered column, and a right-justified
column that are each six characters wide and separated by a single
space:
junos-odl:picture " @<<<<< @||||| @>>>>>";
To define a table row, include the line statement, and map leaf nodes to fields in the line. The field statement’s argument is the leaf identifier.
junos-odl:line {
junos-odl:field "slot";
junos-odl:field "state";
junos-odl:field "comment";
}
Sometimes a table field must include one of several mutually exclusive values. In the
picture statement, you can repeat the @ symbol for each potential
value. Then you include the float statement within the
field statement for each mutually exclusive value after the first
value. Then if the first element does not have a value, subsequent possible elements
with the float statement are tested until a value is returned. The
value floats into the position defined by the first @ symbol instead of leaving a
blank field.
For example, the following picture statement causes the output to include one of two mutually exclusive
values in the second column:
junos-odl:picture " @<<<<< @@<<<<<";
junos-odl:line {
junos-odl:field "slot";
junos-odl:field "state";
junos-odl:field "comment"{
junos-odl:float;
}
}You can also use the float statement
when you know a tag corresponding to a specific table field might
be missing in certain situations, and you want to eliminate the extra
blank space.
The truncate statement guarantees that a field’s value does not exceed the width
of the column defined by the picture statement. The
truncate statement causes the output to omit any characters in
the node’s value that would cause it to exceed the width of the field. If you omit
the truncate statement, and the output exceeds the width of the
field, the complete contents are displayed, which might distort the table. You should
use this statement with care, particularly with numbers, because the output does not
indicate when it truncates a value.
The CLI formatting for the following RPC defines a small table with two columns. The
comment field includes the float and
truncate statements. If the state output element
contains a value, the output places the value in the second column. However, if the
state output element is empty, the output places the value for
the comment node, if one exists, in the table's second column. If
the comment exceeds the width of that column, the output truncates it to fit the
column width.
rpc get-xyz-information {
output {
container xyz-information {
leaf slot {
type string;
description "Slot number";
}
leaf state {
type string;
description "State";
}
leaf comment {
type string;
}
junos-odl:format xyz-information-format {
junos-odl:header "Slot State \n";
junos-odl:picture "@<<<<< @@|||||||||||||||||||";
junos-odl:line {
junos-odl:field "slot";
junos-odl:field "state";
junos-odl:field "comment"{
junos-odl:float;
junos-odl:truncate;
}
}
}
}
}
}format
When you execute an RPC on a device running Junos OS or a device running Junos OS Evolved, it
returns the RPC reply as an XML document. Container and leaf nodes under the RPC
output statement translate into XML elements in the RPC reply. In
YANG RPCs for Junos devices, you can also define custom formatted ASCII output. The
device displays the formatted ASCII output when you execute the RPC in the CLI or
when you request RPC output in text format.
To create custom command output for a specific RPC output container, define the
format statement. The format statement defines
the CLI formatting for the parent container. The RPC reply does not include it as a
node in the XML data. Within the format statement, map the data for
the parent container to output fields, and use statements from the Junos OS ODL
extensions module to specify how to display the output for that parent container.
rpc get-xyz-information {
output {
container xyz-information {
// leaf definitions
junos-odl:format xyz-information-format {
// CLI formatting for the parent container
}
}
}
}header and header-group
The header statement enables you to define a header string that precedes a set
of fields in the RPC’s formatted ASCII output. The header-group
statement emits only the first header string when the output would include two or
more headers in the same header group.
To define a header string and associate it with a header
group, include the header and header-group statements, respectively, within the format statement. The header-group argument is a user-defined string that identifies a particular header
group. Every format statement that includes
the header-group statement with the same
identifier belongs to the same header group. The following example
defines a format statement associated with
the header group color-tags.
junos-odl:format red-format {
junos-odl:header-group "color-tags";
junos-odl:header "Color tags\n";
...
}When multiple format statements are associated with the same header group, and
the tags emitted by two or more of those statements are present in the output, the
CLI output only emits the first header it encounters. The output suppresses any
subsequent headers belonging to that header group.
To emit only the first header string for a header group, include the
header-group statement and identifier in all
format statements belonging to that header group. The following
sample RPC output statement associates two containers and their
format statements with the header group color-tags.
output {
container red-group {
container red {
leaf redtag1 {
type string;
}
leaf redtag2 {
type string;
}
junos-odl:format red-format {
junos-odl:header-group "color-tags";
junos-odl:header "Color tags\n";
junos-odl:picture "@<<<<<<<<<<<< @<<<<<<<<<<<<";
junos-odl:indent 5;
junos-odl:line {
junos-odl:field "redtag1";
junos-odl:field "redtag2";
}
}
}
}
container blue-group {
container blue {
leaf bluetag1 {
type string;
}
leaf bluetag2 {
type string;
}
junos-odl:format blue-format {
junos-odl:header-group "color-tags";
junos-odl:header "Color tags\n";
junos-odl:picture "@<<<<<<<<<<<< @<<<<<<<<<<<<";
junos-odl:indent 5;
junos-odl:line {
junos-odl:field "bluetag1";
junos-odl:field "bluetag2";
}
}
}
}
}
Consider an RPC reply with the following XML tags:
<rpc-reply>
<red-group>
<red>
<redtag1>red-1</redtag1>
<redtag2>red-2</redtag2>
</red>
</red-group>
<blue-group>
<blue>
<bluetag1>blue-1</bluetag1>
<bluetag2>blue-2</bluetag2>
</blue>
</blue-group>
</rpc-reply>When the device renders the output and the same header-group statement is
present in each format statement, it emits only the first header
string in the output. In this case, the format statement with the
identifier red-format defines the first header string.
Color tags
red-1 red-2
blue-1 blue-2If you omit the header-group statement from the format
statement, the output includes the header string defined for each set of fields.
Color tags
red-1 red-2
Color tags
blue-1 blue-2indent
The indent statement causes
all of the lines in the scope of the statement other than the header
row to be indented by the specified number of characters.
To indent lines, include the indent statement and the number of spaces to indent
the lines at the top level of the format statement. The formatted
ASCII output for the following RPC indents the line by 10 spaces.
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
type string;
description "Version";
}
leaf model {
type string;
description "Model";
}
junos-odl:format xyz-information-format {
junos-odl:header "xyz information\n";
junos-odl:indent 10;
junos-odl:line {
junos-odl:field "version";
junos-odl:field "model";
}
}
}
}
}When you execute the RPC, the output left justifies the header and indents the line containing the two fields by ten spaces.
xyz information
version modelno-line-break
The no-line-break statement displays multiple values on the same line in the
case where the output emits multiple entities with the same tag names. When you
include the no-line-break statement, the output places repeated
formats on the same line. If you omit the statement, the output places repeated
formats on separate lines.
For example, you might want to display all interface errors together on the same line.
Interface errors: BPI-B1 0 BIP-B2 0 REI-L 0 BIP-B3 0 REI-P 0
To place the tags for multiple entities within the same
line of output, include the no-line-break statement in the format statement for
that container.
rpc get-if-errors {
output {
container if-error-information {
container if-errors {
leaf if-error-name {
type string;
description "Interface error name";
}
leaf if-error-count {
type integer;
description "Interface error count";
}
junos-odl:format if-errors-format {
junos-odl:no-line-break;
junos-odl:space;
junos-odl:header "Interface errors:\n";
junos-odl:line {
junos-odl:field "if-error-name";
junos-odl:field "if-error-count";
}
}
}
}
}
}If the RPC output returns multiple entities, the output places each repeated set of fields on the same line.
Interface errors: BPI-B1 0 BIP-B2 0 REI-L 0 BIP-B3 0 REI-P 0
If you omit the no-line-break statement, the output places each repeated set of fields on its
own line.
Interface errors: BPI-B1 0 BIP-B2 0 REI-L 0 BIP-B3 0 REI-P 0
space
The space statement appends
a space to the node’s value in the RPC’s formatted ASCII
output. For example:
value1 value2 Label3: value3
The space statement is often used with the comma statement to
delimit fields in a line of output with a comma followed by a space.
To generate a space after a value in the output field, include
the space statement within the format statement. The placement of a statement determines
the statement’s scope. Placing the statement within a single
field generates a space after that field only.
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
type string;
description "Version";
}
// additional leaf definitions
junos-odl:format xyz-information-format {
junos-odl:space;
junos-odl:line {
junos-odl:field "version";
// additional fields
}
}
}
}
}style
The style statement defines one of
several formats for the RPC output. For detailed information about
using the style statement to create different
levels of output, see Define Different Levels of Output in Custom YANG RPCs for Junos Devices.
template
The template statement explicitly defines the format for an output field for a
given node. The definition includes the output string and placement of the node’s
value within the string. If you define the template statement for a
leaf node, the corresponding output field automatically uses the template string.
To create a template string for a node, you must include
the template statement in the definition
of the node, and define the string. The placeholders %s and %d within the string
define the type and placement of the node’s value. Use %s to insert a string value, and %d to insert an integer value. For example:
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
junos-odl:template " Version: %s";
type string;
description "Version";
}
}
}
}If you define a template statement
for a node, the output field for that node automatically uses the
template text.
rpc get-xyz-information {
output {
container xyz-information {
leaf version {
junos-odl:template " Version: %s";
type string;
description "Version";
}
junos-odl:format xyz-information-format {
junos-odl:line {
junos-odl:field "version";
// additional fields
}
}
}
}
}When you execute the RPC, the template is used in the output for that field.
Version: value
If a leaf statement defines both a template and a formal-name statement, and the leading statement is included in the formatting instructions
for that field, the output uses the text defined for the formal-name statement and not the text defined for
the template statement.