Revision of neto_table file -- tabular Netomata network description from Fri 09 Oct 09 - 12:57pm

The revisions let you track differences between multiple versions of a post.

Description

Netomata tabular network description files (which are commonly named with the extension .neto_table) are used as input by Netomata tools such as ncg, and describe parts of a particular network configuration. They are a specialized form of input for descriptions that make most sense when represented in tabular form (for example, lists of interfaces on a particular device, and associated parameters for each interface).

Anything in a neto_table file could be expressed in a neto file instead; a neto_table file is simply a more concise and natural form of expressing some types of data.

Structure

A neto_table file consists of three types of lines: comments, header lines, and data lines. Comments begin with '#', and extend to the end of the line. Header lines are lines that begin with special characters (either '@', '+', or '%'). Data lines are any lines that are neither header lines nor comments.

Header lines define a set of actions, which are applied to each data line in turn; the header lines, taken as a set, describe how to convert a given data line into entries in the Netomata tree-structured description of the network.

Lines that end with '\' are treated as if they continued on the next line; before processing continues, the current line is joined with the next, and the '\' and embedded newline characters are removed.

Format

Data Lines

Data lines are broken into fields by strings of one or more tabs. All data lines must have the same number of fields, which must match the number of fields in the '%' header line (which specifies the name of each field). This has some important consequences:

  • You can't have tabs within a field in a data line, since tabs are used to separate one field from the next.
  • You can't have a "blank" or "null" value for any field in a data line, since adjacent tabs will be treated as a single field separator. There has to be something in the field, even if it's a "-" or a word like "UNUSED" or "NULL" or similar.

Header Lines

Header lines take one of the following forms:

% field1 [ field2 ... ]

A '%' line defines the names of the fields in the data lines. As with data lines, the field names are separated by strings of one or more tabs. Each neto_table file must have exactly one '%' line. The number of fields in each data line must match the number of fields named on the '%' line. The name of each field must be unique.

+ key

Creates a new (empty) node, and names it key.

+ key < source_key

Creates a copy of the node named by source_key as new node, and names it key.

@ key = value

Sets key to be value.

< key filename ...

Creates a node named key, and populates it by processing the neto-format file(s) named by filename ... into it.

In processing '+', '@', and '<' lines:
  • keys and source_keys can be simple keys or composite keys (see the discussion of simple and composite keys in the Special Keys section of the neto file documentation)
  • keys, source_keys, and values can use the construct '%{field}' to obtain the value of the named field from the current data line.
  • A value containing [%= ... %] is treated as an ERB (Embedded Ruby) block, and is fed through the ERB interpreter once for each data line; the value for such a string is the ERB interpreter's output, not the ERB template itself. See the discussion of ERB Blocks in the neto file format documentation. (Note that '%{field}' string substitution is performed on the ERB block before ERB is invoked, which can be used as a way to pass the value of fields from the current data line into the ERB block.)

Examples

Example 1

Consider the following simple neto_table file, which populates the "!vlans!" section of the data tree with the list of VLANs and their associated parameters for a particular network:
@ !vlans!(+)!id = %{id}
@ !vlans!(id=%{id})!active = %{active}
@ !vlans!(id=%{id})!type = %{type}
@ !vlans!(id=%{id})!vlan_ip = [%= ip_union(@target["(...)!base_ip"], "0.0.%{id}.0") %]
@ !vlans!(id=%{id})!netmask = %{netmask}
@ !vlans!(id=%{id})!name = %{name}
@ !vlans!(id=%{id})!description = %{description}
#
% id    active  type    netmask         name            description
# --    ------  ----    -------         ----            -----------
2       yes     switch  255.255.255.0   ISP-FW          ISP-to-Firewall
3       yes     switch  255.255.255.0   FW-LB           Firewall-to-LoadBal
4       yes     admin   255.255.255.0   LB-Rtr          LoadBal-to-Router
16      yes     admin   255.255.240.0   Management      Management
32      yes     admin   255.255.240.0   Bulk            Bulk
48      yes     admin   255.255.240.0   IPMI            IPMI
81      yes     env     255.255.255.0   Production      Production
82      yes     env     255.255.255.0   Pre-Prod        Pre-Prod
83      yes     env     255.255.255.0   Demo            Demo
84      yes     env     255.255.255.0   Dev             Dev
85      yes     env     255.255.255.0   QA              QA
86      yes     env     255.255.255.0   Test            Test
128     yes     switch  255.255.255.0   Corporate       Corporate
This is equivalent to the following neto file:
# first line of data from table
!vlans!(+)!id = 2
!vlans!(id=2)!active = yes
!vlans!(id=2)!type = switch
!vlans!(id=2)!vlan_ip = [%= ip_union(@target["(...)!base_ip"], "0.0.2.0") %]
!vlans!(id=2)!netmask = 255.255.255.0
!vlans!(id=2)!name = ISP-FW
!vlans!(id=2)!description = ISP-to-Firewall
# second line of data from table
!vlans!(+)!id = 3
!vlans!(id=3)!active = yes
!vlans!(id=3)!type = switch
!vlans!(id=3)!vlan_ip = [%= ip_union(@target["(...)!base_ip"], "0.0.3.0") %]
!vlans!(id=3)!netmask = 255.255.255.0
!vlans!(id=3)!name = FW-LB
!vlans!(id=3)!description = Firewall-to-LoadBal
# third line of data from table
!vlans!(+)!id = 4
!vlans!(id=4)!active = yes
!vlans!(id=4)!type = admin
!vlans!(id=4)!vlan_ip = [%= ip_union(@target["(...)!base_ip"], "0.0.4.0") %]
!vlans!(id=4)!netmask = 255.255.255.0
!vlans!(id=4)!name = LB-Rtr
!vlans!(id=4)!description = LoadBal-to-Router
# fourth line of data from table
!vlans!(+)!id = 16
!vlans!(id=16)!active = yes
!vlans!(id=16)!type = admin
!vlans!(id=16)!vlan_ip = [%= ip_union(@target["(...)!base_ip"], "0.0.16.0") %]
!vlans!(id=16)!netmask = 255.255.240.0
!vlans!(id=16)!name = Management
!vlans!(id=16)!description = Management
# and so forth ...

Example 2

Consider the following more complex neto_table file, which generates the interface entries for two separate switches (named "switch-1" and "switch-2") that make up a redundant switch pair in a web hosting environment. In this example, each host has two data Ethernet ports, one of which is connected to each switch; each host also an IPMI management Ethernet port, with the management port on odd-numbered hosts being connected to switch-1, and that on even-numbered hosts being connected to switch-2. Each switch's base node ("!devices!(name=switch-1)", for example) is presumed to already exist, and contain a "templates!interfaces!..." section with template nodes of various types.
+ !devices!(name=switch-1)!interfaces!(+) < \
        (...)!templates!interfaces!(name=%{type})
@ !devices!(name=switch-1)!interfaces!(>)!name = %{name}
@ !devices!(name=switch-1)!interfaces!(name=%{name})!type = %{type}
@ !devices!(name=switch-1)!interfaces!(name=%{name})!target = %{target1}
@ !devices!(name=switch-1)!interfaces!(name=%{name})!active = %{active1}
#
+ !devices!(name=switch-2)!interfaces!(+) < \
        (...)!templates!interfaces!(name=%{type})
@ !devices!(name=switch-2)!interfaces!(>)!name = %{name}
@ !devices!(name=switch-2)!interfaces!(name=%{name})!type = %{type}
@ !devices!(name=switch-2)!interfaces!(name=%{name})!target = %{target2}
@ !devices!(name=switch-2)!interfaces!(name=%{name})!active = %{active2}
#
% name  type    target1         active1 target2         active2
# ----  ----    ------          ------- ------          -------
Gig1/1  host    host-1a         yes     host-1b         yes
Gig1/2  host    host-2a         yes     host-2b         yes
Gig1/3  host    host-3a         yes     host-3b         yes
Gig1/4  host    host-4a         yes     host-4b         yes
Gig1/25 ipmi    host-1m         yes     host-2m         yes
Gig1/26 ipmi    host-3m         yes     host-4m         yes
This is equivalent to the following neto file:
# first data line, first set of header lines (for switch-1)
!devices!(name=switch-1)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-1)!interfaces!(>)!name = Gig1/1
!devices!(name=switch-1)!interfaces!(name=Gig1/1)!type = host
!devices!(name=switch-1)!interfaces!(name=Gig1/1)!target = host-1a
!devices!(name=switch-1)!interfaces!(name=Gig1/1)!active = yes
# first data line, second set of header lines (for switch-2)
!devices!(name=switch-2)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-2)!interfaces!(>)!name = Gig1/1
!devices!(name=switch-2)!interfaces!(name=Gig1/1)!type = host
!devices!(name=switch-2)!interfaces!(name=Gig1/1)!target = host-1b
!devices!(name=switch-2)!interfaces!(name=Gig1/1)!active = yes
# second data line, first set of header lines (for switch-1)
!devices!(name=switch-1)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-1)!interfaces!(>)!name = Gig1/2
!devices!(name=switch-1)!interfaces!(name=Gig1/2)!type = host
!devices!(name=switch-1)!interfaces!(name=Gig1/2)!target = host-2a
!devices!(name=switch-1)!interfaces!(name=Gig1/2)!active = yes
# second data line, second set of header lines (for switch-2)
!devices!(name=switch-2)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-2)!interfaces!(>)!name = Gig1/2
!devices!(name=switch-2)!interfaces!(name=Gig1/2)!type = host
!devices!(name=switch-2)!interfaces!(name=Gig1/2)!target = host-2b
!devices!(name=switch-2)!interfaces!(name=Gig1/2)!active = yes
# third data line, first set of header lines (for switch-1)
!devices!(name=switch-1)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-1)!interfaces!(>)!name = Gig1/3
!devices!(name=switch-1)!interfaces!(name=Gig1/3)!type = host
!devices!(name=switch-1)!interfaces!(name=Gig1/3)!target = host-3a
!devices!(name=switch-1)!interfaces!(name=Gig1/3)!active = yes
# third data line, second set of header lines (for switch-2)
!devices!(name=switch-2)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-2)!interfaces!(>)!name = Gig1/3
!devices!(name=switch-2)!interfaces!(name=Gig1/3)!type = host
!devices!(name=switch-2)!interfaces!(name=Gig1/3)!target = host-3b
!devices!(name=switch-2)!interfaces!(name=Gig1/3)!active = yes
# fourth data line, first set of header lines (for switch-1)
!devices!(name=switch-1)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-1)!interfaces!(>)!name = Gig1/4
!devices!(name=switch-1)!interfaces!(name=Gig1/4)!type = host
!devices!(name=switch-1)!interfaces!(name=Gig1/4)!target = host-4a
!devices!(name=switch-1)!interfaces!(name=Gig1/4)!active = yes
# fourth data line, second set of header lines (for switch-2)
!devices!(name=switch-2)!interfaces!(+) < (...)!templates!interfaces!(name=host) {
}
!devices!(name=switch-2)!interfaces!(>)!name = Gig1/4
!devices!(name=switch-2)!interfaces!(name=Gig1/4)!type = host
!devices!(name=switch-2)!interfaces!(name=Gig1/4)!target = host-4b
!devices!(name=switch-2)!interfaces!(name=Gig1/4)!active = yes
# fifth data line, first set of header lines (for switch-1)
!devices!(name=switch-1)!interfaces!(+) < (...)!templates!interfaces!(name=ipmi) {
}
!devices!(name=switch-1)!interfaces!(>)!name = Gig1/25
!devices!(name=switch-1)!interfaces!(name=Gig1/25)!type = ipmi
!devices!(name=switch-1)!interfaces!(name=Gig1/25)!target = host-1m
!devices!(name=switch-1)!interfaces!(name=Gig1/25)!active = yes
# fifth data line, second set of header lines (for switch-2)
!devices!(name=switch-2)!interfaces!(+) < (...)!templates!interfaces!(name=ipmi) {
}
!devices!(name=switch-2)!interfaces!(>)!name = Gig1/25
!devices!(name=switch-2)!interfaces!(name=Gig1/25)!type = ipmi
!devices!(name=switch-2)!interfaces!(name=Gig1/25)!target = host-2m
!devices!(name=switch-2)!interfaces!(name=Gig1/25)!active = yes
# sixth data line, first set of header lines (for switch-1)
!devices!(name=switch-1)!interfaces!(+) < (...)!templates!interfaces!(name=ipmi) {
}
!devices!(name=switch-1)!interfaces!(>)!name = Gig1/26
!devices!(name=switch-1)!interfaces!(name=Gig1/26)!type = ipmi
!devices!(name=switch-1)!interfaces!(name=Gig1/26)!target = host-3m
!devices!(name=switch-1)!interfaces!(name=Gig1/26)!active = yes
# sixth data line, second set of header lines (for switch-2)
!devices!(name=switch-2)!interfaces!(+) < (...)!templates!interfaces!(name=ipmi) {
}
!devices!(name=switch-2)!interfaces!(>)!name = Gig1/26
!devices!(name=switch-2)!interfaces!(name=Gig1/26)!type = ipmi
!devices!(name=switch-2)!interfaces!(name=Gig1/26)!target = host-4m
!devices!(name=switch-2)!interfaces!(name=Gig1/26)!active = yes

History

ncg was originally written in 2008 by Brent Chapman of Netomata, Inc.

Bugs

Please report any you find by email to bugs@netomata.com.

Author

Brent Chapman of Netomata, Inc.

Copyright

Copyright (C) 2009 Netomata, Inc. All Rights Reserved.

See Also

ncg program, ncg file format, neto file format.

Version

This documentation is for ncg version 0.10.x.