diff --git a/ncm-network/src/main/pan/components/network/config.pan b/ncm-network/src/main/pan/components/network/config.pan
old mode 100755
new mode 100644
diff --git a/ncm-network/src/main/pan/components/network/core-schema-legacy.pan b/ncm-network/src/main/pan/components/network/core-schema-legacy.pan
new file mode 100644
index 0000000000..b1745ee243
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/core-schema-legacy.pan
@@ -0,0 +1,473 @@
+declaration template components/network/core-schema-legacy;
+
+include 'pan/types';
+include 'quattor/functions/network';
+
+type network_valid_routing_table = string with exists("/system/network/routing_table/" + SELF);
+
+type network_ip_cmd_prefix = string with {is_ipv4_netmask_pair(SELF) || is_ipv6_network_block(SELF)};
+
+@documentation{
+ Add route (IPv4 of IPv6)
+ Presence of ':' in any of the values indicates this is IPv6 related.
+}
+type structure_route = {
+ @{The ADDRESS in ADDRESS/PREFIX via GATEWAY}
+ "address" ? string with {SELF == 'default' || is_ip(SELF)}
+ @{The PREFIX in ADDRESS/PREFIX via GATEWAY}
+ "prefix" ? long
+ @{The GATEWAY in ADDRESS/PREFIX via GATEWAY}
+ "gateway" ? type_ip
+ @{alternative notation for prefix (cannot be combined with prefix)}
+ "netmask" ? type_ip
+ @{routing table}
+ "table" ? network_valid_routing_table
+ @{pretend that the nexthop is directly attached to this link}
+ "onlink" ? boolean
+ @{route add command options to use (cannot be combined with other options)}
+ "command" ? string with !match(SELF, '[;]')
+} with {
+ if (exists(SELF['command'])) {
+ module = value('/software/components/network/ncm-module', '');
+ if (module == 'nmstate') error("Command routes are not supported by the nmstate backend");
+ if (length(SELF) != 1) error("Cannot use command and any of the other attributes as route");
+ } else {
+ if (!exists(SELF['address']))
+ error("Address is mandatory for route (in absence of command)");
+ if (exists(SELF['prefix']) && exists(SELF['netmask']))
+ error("Use either prefix or netmask as route");
+ };
+
+ if (exists(SELF['prefix'])) {
+ pref = SELF['prefix'];
+ ipv6 = false;
+ foreach (k; v; SELF) {
+ if (match(to_string(v), ':')) {
+ ipv6 = true;
+ };
+ };
+ if (ipv6) {
+ if (!is_ipv6_prefix_length(pref)) {
+ error("Prefix %s is not a valid IPv6 prefix", pref);
+ };
+ } else {
+ if (!is_ipv4_prefix_length(pref)) {
+ error("Prefix %s is not a valid IPv4 prefix", pref);
+ };
+ };
+ };
+
+ true;
+};
+
+@documentation{
+ Add rule (IPv4 of IPv6)
+ Presence of ':' in any of the values indicates this is IPv6 related.
+}
+type structure_rule = {
+ @{to selector}
+ "to" ? network_ip_cmd_prefix
+ @{from selector}
+ "from" ? network_ip_cmd_prefix
+ @{not action (false value means no not action; also the default when not is not defined)}
+ "not" ? boolean
+ @{routing table action}
+ "table" ? network_valid_routing_table
+ @{priority, The priority of the rule over the others. Required by Network Manager when setting routing rules.}
+ "priority" ? long(0..0xffffffff)
+ @{rule add options to use (cannot be combined with other options)}
+ "command" ? string with !match(SELF, '[;]')
+} with {
+ module = value('/software/components/network/ncm-module', '');
+ if (exists(SELF['command'])) {
+ if (module == 'nmstate') error("Command rule are not supported by the nmstate backend");
+ if (length(SELF) != 1) error("Cannot use command and any of the other attributes as rule");
+ } else {
+ if (!exists(SELF['to']) && !exists(SELF['from'])) {
+ error("Rule requires selector to or from (or use command)");
+ };
+ if (!exists(SELF['table'])) {
+ error("Rule requires action table (or use command)");
+ };
+ };
+ true;
+};
+
+@documentation{
+ Interface alias
+}
+type structure_interface_alias = {
+ "ip" ? type_ip
+ "netmask" : type_ip
+ "broadcast" ? type_ip
+ "fqdn" ? type_fqdn
+};
+
+
+############################################################
+#
+# Defines virtual IP addresses as loopback interface
+#
+############################################################
+@documentation{
+ Define vip interfaces for configuring loopback interface. Used with frr/zebra configuration
+}
+
+type structure_vip = {
+ "interfaces" : valid_interface[]
+ "ip" : type_ip
+ "fqdn" ? type_fqdn
+ "netmask" ? type_ip
+ "broadcast" ? type_ip
+};
+
+@documentation{
+ Describes the bonding options for configuring channel bonding on EL5 and similar.
+}
+type structure_bonding_options = {
+ "mode" : long(0..6)
+ "miimon" : long
+ "updelay" ? long
+ "downdelay" ? long
+ "primary" ? valid_interface
+ "lacp_rate" ? long(0..1)
+ "xmit_hash_policy" ? string with match (SELF, '^(0|1|2|layer(2|2\+3|3\+4))$')
+} with {
+ if ( SELF['mode'] == 1 || SELF['mode'] == 5 || SELF['mode'] == 6 ) {
+ if ( ! exists(SELF["primary"]) ) {
+ error("Bonding configured but no primary is defined.");
+ };
+ } else {
+ if ( exists(SELF["primary"]) ) {
+ error("Primary is defined but this is not allowed with this bonding mode.");
+ };
+ };
+ true;
+};
+
+@documentation{
+ describes the bridging options
+ (the parameters for /sys/class/net/
/brport)
+}
+type structure_bridging_options = {
+ "bpdu_guard" ? long
+ "flush" ? long
+ "hairpin_mode" ? long
+ "multicast_fast_leave" ? long
+ "multicast_router" ? long
+ "path_cost" ? long
+ "priority" ? long
+ "root_block" ? long
+};
+
+@documentation{
+ interface ethtool offload
+}
+type structure_ethtool_offload = {
+ "rx" ? string with match (SELF, '^(on|off)$')
+ "tx" ? string with match (SELF, '^(on|off)$')
+ @{Set the TCP segment offload parameter to "off" or "on"}
+ "tso" ? string with match (SELF, '^(on|off)$')
+ "gro" ? string with match (SELF, '^(on|off)$')
+ "gso" ? string with match (SELF, '^(on|off)$')
+};
+
+@documentation{
+ Set the ethernet transmit or receive buffer ring counts.
+ See ethtool --show-ring for the values.
+}
+type structure_ethtool_ring = {
+ "rx" ? long
+ "tx" ? long
+ "rx-mini" ? long
+ "rx-jumbo" ? long
+};
+
+@documentation{
+ Set the number of channels.
+ See ethtool --show-channels for the values.
+}
+type structure_ethtool_channels = {
+ "rx" ? long(0..)
+ "tx" ? long(0..)
+ "other" ? long(0..)
+ "combined" ? long(0..)
+};
+
+@documentation{
+ ethtool wol p|u|m|b|a|g|s|d...
+ from the man page
+ Sets Wake-on-LAN options. Not all devices support this. The argument to this option is a string
+ of characters specifying which options to enable.
+ p Wake on phy activity
+ u Wake on unicast messages
+ m Wake on multicast messages
+ b Wake on broadcast messages
+ a Wake on ARP
+ g Wake on MagicPacket(tm)
+ s Enable SecureOn(tm) password for MagicPacket(tm)
+ d Disable (wake on nothing). This option clears all previous option
+}
+type structure_ethtool_wol = string with match (SELF, '^(p|u|m|b|a|g|s|d)+$');
+
+@documentation{
+ ethtool
+}
+type structure_ethtool = {
+ "wol" ? structure_ethtool_wol
+ "autoneg" ? string with match (SELF, '^(on|off)$')
+ "duplex" ? string with match (SELF, '^(half|full)$')
+ "speed" ? long
+ "channels" ? structure_ethtool_channels
+};
+
+@documentation{
+ interface plugin for vxlan support via initscripts-vxlan
+}
+type structure_interface_plugin_vxlan = {
+ @{VXLAN Network Identifier (or VXLAN Segment ID); derived from devicename vxlan[0-9] if not defined}
+ 'vni' ? long(0..16777216)
+ @{multicast ip to join}
+ 'group' ? type_ip
+ @{destination IP address to use in outgoing packets}
+ 'remote' ? type_ip
+ @{source IP address to use in outgoing packets}
+ 'local' ? type_ip
+ @{UDP destination port}
+ 'dstport' ? long(2..65535)
+ @{Group Policy extension}
+ 'gbp' ? boolean
+} with {
+ if (exists(SELF['group']) && exists(SELF['remote'])) {
+ error('Cannot define both group and remote for vxlan');
+ };
+ if (!exists(SELF['group']) && !exists(SELF['remote'])) {
+ error('Must define either group or remote for vxlan');
+ };
+ true;
+};
+
+@documentation{
+ interface plugin via custom ifup/down[-pre]-local hooks
+}
+type structure_interface_plugin = {
+ @{VXLAN support via initscripts-vxlan}
+ "vxlan" ? structure_interface_plugin_vxlan
+};
+
+@documentation{
+ interface
+}
+type structure_interface = {
+ "ip" ? type_ip
+ "gateway" ? type_ip
+ "netmask" ? type_ip
+ "broadcast" ? type_ip
+ "driver" ? string
+ "bootproto" ? string with match(SELF, '^(static|bootp|dhcp|none)$')
+ "onboot" ? boolean
+ "type" ? string with match(SELF, '^(Ethernet|Bridge|Tap|xDSL|IPIP|OVS(Bridge|Port|IntPort|Bond|Tunnel|PatchPort))$')
+ "device" ? string
+ "master" ? string
+ "mtu" ? long
+ @{Routes for this interface.
+ These values are used to generate the /etc/sysconfig/network-scripts/route[6]- files
+ as used by ifup-routes when using ncm-network.
+ This allows for mixed IPv4 and IPv6 configuration}
+ "route" ? structure_route[]
+ @{Rules for this interface.
+ These values are used to generate the /etc/sysconfig/network-scripts/rule[6]- files
+ as used by ifup-routes when using ncm-network.
+ This allows for mixed IPv4 and IPv6 configuration}
+ "rule" ? structure_rule[]
+ @{Aliases for this interface.
+ These values are used to generate the /etc/sysconfig/network-scripts/ifcfg-: files
+ as used by ifup-aliases when using ncm-network.}
+ "aliases" ? structure_interface_alias{}
+ @{Explicitly set the MAC address. The MAC address is taken from /hardware/cards/nic//hwaddr.}
+ "set_hwaddr" ? boolean
+ "bridge" ? valid_interface
+ "bonding_opts" ? structure_bonding_options
+
+ "offload" ? structure_ethtool_offload
+ "ring" ? structure_ethtool_ring
+ "ethtool" ? structure_ethtool
+
+ @{Is a VLAN device. If the device name starts with vlan, this is always true.}
+ "vlan" ? boolean
+ @{If the device name starts with vlan, this has to be set.
+ It is set (but ignored by ifup) if it the device is not named vlan}
+ "physdev" ? valid_interface
+
+ "fqdn" ? string
+ "network_environment" ? string
+ "network_type" ? string
+ "nmcontrolled" ? boolean
+ @{Set DEFROUTE, is the default for ipv6_defroute}
+ "defroute" ? boolean
+
+ "linkdelay" ? long # LINKDELAY
+ "stp" ? boolean # enable/disable stp on bridge (true: STP=on)
+ "delay" ? long # brctl setfd DELAY
+ "bridging_opts" ? structure_bridging_options
+
+ "bond_ifaces" ? string[]
+ "ovs_bridge" ? valid_interface
+ "ovs_extra" ? string
+ "ovs_opts" ? string # See ovs-vswitchd.conf.db(5) for documentation
+ "ovs_patch_peer" ? string
+ "ovs_tunnel_opts" ? string # See ovs-vswitchd.conf.db(5) for documentation
+ "ovs_tunnel_type" ? string with match(SELF, '^(gre|vxlan)$')
+
+ "ipv4_failure_fatal" ? boolean
+ "ipv6_autoconf" ? boolean
+ "ipv6_failure_fatal" ? boolean
+ "ipv6_mtu" ? long(1280..65536)
+ "ipv6_privacy" ? string with match(SELF, '^rfc3041$')
+ "ipv6_rtr" ? boolean
+ @{Set IPV6_DEFROUTE, defaults to defroute value}
+ "ipv6_defroute" ? boolean
+ "ipv6addr" ? type_network_name
+ "ipv6addr_secondaries" ? type_network_name[]
+ "ipv6init" ? boolean
+
+ @{tunnel IP}
+ "my_inner_ipaddr" ? type_ip
+ @{tunnel IP netmask prefix}
+ "my_inner_prefix" ? long(0..32)
+ @{primary local IP address}
+ "my_outer_ipaddr" ? type_ip
+ @{remote peer primary IP address}
+ "peer_outer_ipaddr" ? type_ip
+
+ "plugin" ? structure_interface_plugin
+} with {
+ if ( exists(SELF['ovs_bridge']) && exists(SELF['type']) && SELF['type'] == 'OVSBridge') {
+ error("An OVSBridge interface cannot have the ovs_bridge option defined");
+ };
+ if ( exists(SELF['ovs_tunnel_type']) && (!exists(SELF['type']) || SELF['type'] != 'OVSTunnel')) {
+ error("ovs_tunnel_bridge is defined but the type of interface is not defined as OVSTunnel");
+ };
+ if ( exists(SELF['ovs_tunnel_opts']) && (!exists(SELF['type']) || SELF['type'] != 'OVSTunnel')) {
+ error("ovs_tunnel_opts is defined but the type of interface is not defined as OVSTunnel");
+ };
+ if ( exists(SELF['ovs_patch_peer']) && (!exists(SELF['type']) || SELF['type'] != 'OVSPatchPort')) {
+ error("ovs_patch_peer is defined but the type of interface is not defined as OVSPatchPort");
+ };
+ if ( exists(SELF['bond_ifaces']) ) {
+ if ( (!exists(SELF['type']) || SELF['type'] != 'OVSBond') ) {
+ error("bond_ifaces is defined but the type of interface is not defined as OVSBond");
+ };
+ foreach (i; iface; SELF['bond_ifaces']) {
+ if ( !exists("/system/network/interfaces/" + iface) ) {
+ error("The " + iface + " interface is used by bond_ifaces, but does not exist");
+ };
+ };
+ };
+ if (exists(SELF['ip']) && exists(SELF['netmask'])) {
+ if (exists(SELF['gateway']) && ! ip_in_network(SELF['gateway'], SELF['ip'], SELF['netmask'])) {
+ error('networkinterface has gateway %s not reachable from ip %s with netmask %s',
+ SELF['gateway'], SELF['ip'], SELF['netmask']);
+ };
+ if (exists(SELF['broadcast']) && ! ip_in_network(SELF['broadcast'], SELF['ip'], SELF['netmask'])) {
+ error('networkinterface has broadcast %s not reachable from ip %s with netmask %s',
+ SELF['broadcast'], SELF['ip'], SELF['netmask']);
+ };
+ };
+ if (exists(SELF['plugin']) && exists(SELF['plugin']['vxlan']) && ! exists(SELF['physdev'])) {
+ error('vxlan plugin requires physdev');
+ };
+
+ foreach (i; name; list('my_inner_ipaddr', 'my_inner_prefix', 'my_outer_ipaddr', 'peer_outer_ipaddr')) {
+ if ( exists(SELF[name]) && (!exists(SELF['type']) || SELF['type'] != 'IPIP')) {
+ error("%s is defined but the type of interface is not defined as IPIP", name);
+ };
+ };
+
+ if ( exists(SELF['type']) && SELF['type'] == 'IPIP' ) {
+ foreach (i; name; list('my_inner_ipaddr', 'my_inner_prefix', 'my_outer_ipaddr')) {
+ if (!exists(SELF[name])) {
+ error("Type IPIP but %s is not defined.", name);
+ };
+ };
+ };
+
+ true;
+};
+
+
+@documentation{
+ router
+}
+type structure_router = string[];
+
+@documentation{
+ IPv6 global settings
+}
+type structure_ipv6 = {
+ "enabled" ? boolean
+ "default_gateway" ? type_ip
+ "gatewaydev" ? valid_interface # sets IPV6_DEFAULTDEV
+};
+
+@documentation{
+ Host network configuration
+
+ These values are used to generate /etc/sysconfig/network
+ when using ncm-network (unless specified otherwise).
+}
+type structure_network = {
+ "domainname" : type_fqdn
+ "hostname" : type_shorthostname
+ "realhostname" ? string with is_shorthostname(SELF) || is_fqdn(SELF)
+ "default_gateway" ? type_ip
+ @{When default_gateway is not set, the component will try to guess the default
+ gateway using the first configured gateway set on an interface.
+ The default is true for backward compatible behaviour.}
+ "guess_default_gateway" ? boolean
+ "gatewaydev" ? valid_interface
+ @{Per interface network settings.
+ These values are used to generate the /etc/sysconfig/network-scripts/ifcfg- files
+ when using ncm-network.}
+ "interfaces" : structure_interface{}
+ "nameserver" ? type_ip[]
+ "nisdomain" ? string(1..64) with match(SELF, '^\S+$')
+ @{Setting nozeroconf to true stops an interface from being assigned an automatic address in the 169.254.0.0 subnet.}
+ "nozeroconf" ? boolean
+ @{The default behaviour for all interfaces wrt setting the MAC address (see interface set_hwaddr attribute).
+ The component default is false.}
+ "set_hwaddr" ? boolean
+ "nmcontrolled" ? boolean
+ "allow_nm" ? boolean
+ @{let NetworkManager manage the dns (only for nmstate)}
+ "nm_manage_dns" : boolean = false
+ @{let ncm-network cleanup inactive connections (only for nmstate)}
+ "nm_clean_inactive_conn" : boolean = true
+ "primary_ip" ? string
+ "routers" ? structure_router{}
+ "ipv6" ? structure_ipv6
+ "manage_vips" : boolean = false
+ "vips" ? structure_vip{}
+ @{Manage custom routing table entries; key is the name; value is the id}
+ "routing_table" ? long(1..252){} with {
+ if (exists(SELF['main']) || exists(SELF['local']) || exists(SELF['default']) || exists(SELF['unspec'])) {
+ error("No reserved names in routing table");
+ };
+ true;
+ }
+} with {
+ if (exists(SELF['default_gateway'])) {
+ reachable = false;
+ # is there any interface that can reach it?
+ foreach (name; data; SELF['interfaces']) {
+ if (exists(data['ip']) && exists(data['netmask']) &&
+ ip_in_network(SELF['default_gateway'], data['ip'], data['netmask'])) {
+ reachable = true;
+ };
+ };
+ if (!reachable) {
+ error("No interface with ip/mask found to reach default gateway");
+ };
+ };
+ true;
+};
diff --git a/ncm-network/src/main/pan/components/network/core-schema.pan b/ncm-network/src/main/pan/components/network/core-schema.pan
index 0839ff6e3a..e74ef85ca8 100644
--- a/ncm-network/src/main/pan/components/network/core-schema.pan
+++ b/ncm-network/src/main/pan/components/network/core-schema.pan
@@ -2,474 +2,7 @@
declaration template components/network/core-schema;
-include 'pan/types';
-include 'quattor/functions/network';
+final variable QUATTOR_TYPES_NETWORK_LEGACY ?= true;
-type network_valid_routing_table = string with exists("/system/network/routing_table/" + SELF);
-
-type network_ip_cmd_prefix = string with {is_ipv4_netmask_pair(SELF) || is_ipv6_network_block(SELF)};
-
-@documentation{
- Add route (IPv4 of IPv6)
- Presence of ':' in any of the values indicates this is IPv6 related.
-}
-type structure_route = {
- @{The ADDRESS in ADDRESS/PREFIX via GATEWAY}
- "address" ? string with {SELF == 'default' || is_ip(SELF)}
- @{The PREFIX in ADDRESS/PREFIX via GATEWAY}
- "prefix" ? long
- @{The GATEWAY in ADDRESS/PREFIX via GATEWAY}
- "gateway" ? type_ip
- @{alternative notation for prefix (cannot be combined with prefix)}
- "netmask" ? type_ip
- @{routing table}
- "table" ? network_valid_routing_table
- @{pretend that the nexthop is directly attached to this link}
- "onlink" ? boolean
- @{route add command options to use (cannot be combined with other options)}
- "command" ? string with !match(SELF, '[;]')
-} with {
- if (exists(SELF['command'])) {
- module = value('/software/components/network/ncm-module', '');
- if (module == 'nmstate') error("Command routes are not supported by the nmstate backend");
- if (length(SELF) != 1) error("Cannot use command and any of the other attributes as route");
- } else {
- if (!exists(SELF['address']))
- error("Address is mandatory for route (in absence of command)");
- if (exists(SELF['prefix']) && exists(SELF['netmask']))
- error("Use either prefix or netmask as route");
- };
-
- if (exists(SELF['prefix'])) {
- pref = SELF['prefix'];
- ipv6 = false;
- foreach (k; v; SELF) {
- if (match(to_string(v), ':')) {
- ipv6 = true;
- };
- };
- if (ipv6) {
- if (!is_ipv6_prefix_length(pref)) {
- error("Prefix %s is not a valid IPv6 prefix", pref);
- };
- } else {
- if (!is_ipv4_prefix_length(pref)) {
- error("Prefix %s is not a valid IPv4 prefix", pref);
- };
- };
- };
-
- true;
-};
-
-@documentation{
- Add rule (IPv4 of IPv6)
- Presence of ':' in any of the values indicates this is IPv6 related.
-}
-type structure_rule = {
- @{to selector}
- "to" ? network_ip_cmd_prefix
- @{from selector}
- "from" ? network_ip_cmd_prefix
- @{not action (false value means no not action; also the default when not is not defined)}
- "not" ? boolean
- @{routing table action}
- "table" ? network_valid_routing_table
- @{priority, The priority of the rule over the others. Required by Network Manager when setting routing rules.}
- "priority" ? long(0..0xffffffff)
- @{rule add options to use (cannot be combined with other options)}
- "command" ? string with !match(SELF, '[;]')
-} with {
- module = value('/software/components/network/ncm-module', '');
- if (exists(SELF['command'])) {
- if (module == 'nmstate') error("Command rule are not supported by the nmstate backend");
- if (length(SELF) != 1) error("Cannot use command and any of the other attributes as rule");
- } else {
- if (!exists(SELF['to']) && !exists(SELF['from'])) {
- error("Rule requires selector to or from (or use command)");
- };
- if (!exists(SELF['table'])) {
- error("Rule requires action table (or use command)");
- };
- };
- true;
-};
-
-@documentation{
- Interface alias
-}
-type structure_interface_alias = {
- "ip" ? type_ip
- "netmask" : type_ip
- "broadcast" ? type_ip
- "fqdn" ? type_fqdn
-};
-
-
-############################################################
-#
-# Defines virtual IP addresses as loopback interface
-#
-############################################################
-@documentation{
- Define vip interfaces for configuring loopback interface. Used with frr/zebra configuration
-}
-
-type structure_vip = {
- "interfaces" : valid_interface[]
- "ip" : type_ip
- "fqdn" ? type_fqdn
- "netmask" ? type_ip
- "broadcast" ? type_ip
-};
-
-@documentation{
- Describes the bonding options for configuring channel bonding on EL5 and similar.
-}
-type structure_bonding_options = {
- "mode" : long(0..6)
- "miimon" : long
- "updelay" ? long
- "downdelay" ? long
- "primary" ? valid_interface
- "lacp_rate" ? long(0..1)
- "xmit_hash_policy" ? string with match (SELF, '^(0|1|2|layer(2|2\+3|3\+4))$')
-} with {
- if ( SELF['mode'] == 1 || SELF['mode'] == 5 || SELF['mode'] == 6 ) {
- if ( ! exists(SELF["primary"]) ) {
- error("Bonding configured but no primary is defined.");
- };
- } else {
- if ( exists(SELF["primary"]) ) {
- error("Primary is defined but this is not allowed with this bonding mode.");
- };
- };
- true;
-};
-
-@documentation{
- describes the bridging options
- (the parameters for /sys/class/net/
/brport)
-}
-type structure_bridging_options = {
- "bpdu_guard" ? long
- "flush" ? long
- "hairpin_mode" ? long
- "multicast_fast_leave" ? long
- "multicast_router" ? long
- "path_cost" ? long
- "priority" ? long
- "root_block" ? long
-};
-
-@documentation{
- interface ethtool offload
-}
-type structure_ethtool_offload = {
- "rx" ? string with match (SELF, '^(on|off)$')
- "tx" ? string with match (SELF, '^(on|off)$')
- @{Set the TCP segment offload parameter to "off" or "on"}
- "tso" ? string with match (SELF, '^(on|off)$')
- "gro" ? string with match (SELF, '^(on|off)$')
- "gso" ? string with match (SELF, '^(on|off)$')
-};
-
-@documentation{
- Set the ethernet transmit or receive buffer ring counts.
- See ethtool --show-ring for the values.
-}
-type structure_ethtool_ring = {
- "rx" ? long
- "tx" ? long
- "rx-mini" ? long
- "rx-jumbo" ? long
-};
-
-@documentation{
- Set the number of channels.
- See ethtool --show-channels for the values.
-}
-type structure_ethtool_channels = {
- "rx" ? long(0..)
- "tx" ? long(0..)
- "other" ? long(0..)
- "combined" ? long(0..)
-};
-
-@documentation{
- ethtool wol p|u|m|b|a|g|s|d...
- from the man page
- Sets Wake-on-LAN options. Not all devices support this. The argument to this option is a string
- of characters specifying which options to enable.
- p Wake on phy activity
- u Wake on unicast messages
- m Wake on multicast messages
- b Wake on broadcast messages
- a Wake on ARP
- g Wake on MagicPacket(tm)
- s Enable SecureOn(tm) password for MagicPacket(tm)
- d Disable (wake on nothing). This option clears all previous option
-}
-type structure_ethtool_wol = string with match (SELF, '^(p|u|m|b|a|g|s|d)+$');
-
-@documentation{
- ethtool
-}
-type structure_ethtool = {
- "wol" ? structure_ethtool_wol
- "autoneg" ? string with match (SELF, '^(on|off)$')
- "duplex" ? string with match (SELF, '^(half|full)$')
- "speed" ? long
- "channels" ? structure_ethtool_channels
-};
-
-@documentation{
- interface plugin for vxlan support via initscripts-vxlan
-}
-type structure_interface_plugin_vxlan = {
- @{VXLAN Network Identifier (or VXLAN Segment ID); derived from devicename vxlan[0-9] if not defined}
- 'vni' ? long(0..16777216)
- @{multicast ip to join}
- 'group' ? type_ip
- @{destination IP address to use in outgoing packets}
- 'remote' ? type_ip
- @{source IP address to use in outgoing packets}
- 'local' ? type_ip
- @{UDP destination port}
- 'dstport' ? long(2..65535)
- @{Group Policy extension}
- 'gbp' ? boolean
-} with {
- if (exists(SELF['group']) && exists(SELF['remote'])) {
- error('Cannot define both group and remote for vxlan');
- };
- if (!exists(SELF['group']) && !exists(SELF['remote'])) {
- error('Must define either group or remote for vxlan');
- };
- true;
-};
-
-@documentation{
- interface plugin via custom ifup/down[-pre]-local hooks
-}
-type structure_interface_plugin = {
- @{VXLAN support via initscripts-vxlan}
- "vxlan" ? structure_interface_plugin_vxlan
-};
-
-@documentation{
- interface
-}
-type structure_interface = {
- "ip" ? type_ip
- "gateway" ? type_ip
- "netmask" ? type_ip
- "broadcast" ? type_ip
- "driver" ? string
- "bootproto" ? string with match(SELF, '^(static|bootp|dhcp|none)$')
- "onboot" ? boolean
- "type" ? string with match(SELF, '^(Ethernet|Bridge|Tap|xDSL|IPIP|OVS(Bridge|Port|IntPort|Bond|Tunnel|PatchPort))$')
- "device" ? string
- "master" ? string
- "mtu" ? long
- @{Routes for this interface.
- These values are used to generate the /etc/sysconfig/network-scripts/route[6]- files
- as used by ifup-routes when using ncm-network.
- This allows for mixed IPv4 and IPv6 configuration}
- "route" ? structure_route[]
- @{Rules for this interface.
- These values are used to generate the /etc/sysconfig/network-scripts/rule[6]- files
- as used by ifup-routes when using ncm-network.
- This allows for mixed IPv4 and IPv6 configuration}
- "rule" ? structure_rule[]
- @{Aliases for this interface.
- These values are used to generate the /etc/sysconfig/network-scripts/ifcfg-: files
- as used by ifup-aliases when using ncm-network.}
- "aliases" ? structure_interface_alias{}
- @{Explicitly set the MAC address. The MAC address is taken from /hardware/cards/nic//hwaddr.}
- "set_hwaddr" ? boolean
- "bridge" ? valid_interface
- "bonding_opts" ? structure_bonding_options
-
- "offload" ? structure_ethtool_offload
- "ring" ? structure_ethtool_ring
- "ethtool" ? structure_ethtool
-
- @{Is a VLAN device. If the device name starts with vlan, this is always true.}
- "vlan" ? boolean
- @{If the device name starts with vlan, this has to be set.
- It is set (but ignored by ifup) if it the device is not named vlan}
- "physdev" ? valid_interface
-
- "fqdn" ? string
- "network_environment" ? string
- "network_type" ? string
- "nmcontrolled" ? boolean
- @{Set DEFROUTE, is the default for ipv6_defroute}
- "defroute" ? boolean
-
- "linkdelay" ? long # LINKDELAY
- "stp" ? boolean # enable/disable stp on bridge (true: STP=on)
- "delay" ? long # brctl setfd DELAY
- "bridging_opts" ? structure_bridging_options
-
- "bond_ifaces" ? string[]
- "ovs_bridge" ? valid_interface
- "ovs_extra" ? string
- "ovs_opts" ? string # See ovs-vswitchd.conf.db(5) for documentation
- "ovs_patch_peer" ? string
- "ovs_tunnel_opts" ? string # See ovs-vswitchd.conf.db(5) for documentation
- "ovs_tunnel_type" ? string with match(SELF, '^(gre|vxlan)$')
-
- "ipv4_failure_fatal" ? boolean
- "ipv6_autoconf" ? boolean
- "ipv6_failure_fatal" ? boolean
- "ipv6_mtu" ? long(1280..65536)
- "ipv6_privacy" ? string with match(SELF, '^rfc3041$')
- "ipv6_rtr" ? boolean
- @{Set IPV6_DEFROUTE, defaults to defroute value}
- "ipv6_defroute" ? boolean
- "ipv6addr" ? type_network_name
- "ipv6addr_secondaries" ? type_network_name[]
- "ipv6init" ? boolean
-
- @{tunnel IP}
- "my_inner_ipaddr" ? type_ip
- @{tunnel IP netmask prefix}
- "my_inner_prefix" ? long(0..32)
- @{primary local IP address}
- "my_outer_ipaddr" ? type_ip
- @{remote peer primary IP address}
- "peer_outer_ipaddr" ? type_ip
-
- "plugin" ? structure_interface_plugin
-} with {
- if ( exists(SELF['ovs_bridge']) && exists(SELF['type']) && SELF['type'] == 'OVSBridge') {
- error("An OVSBridge interface cannot have the ovs_bridge option defined");
- };
- if ( exists(SELF['ovs_tunnel_type']) && (!exists(SELF['type']) || SELF['type'] != 'OVSTunnel')) {
- error("ovs_tunnel_bridge is defined but the type of interface is not defined as OVSTunnel");
- };
- if ( exists(SELF['ovs_tunnel_opts']) && (!exists(SELF['type']) || SELF['type'] != 'OVSTunnel')) {
- error("ovs_tunnel_opts is defined but the type of interface is not defined as OVSTunnel");
- };
- if ( exists(SELF['ovs_patch_peer']) && (!exists(SELF['type']) || SELF['type'] != 'OVSPatchPort')) {
- error("ovs_patch_peer is defined but the type of interface is not defined as OVSPatchPort");
- };
- if ( exists(SELF['bond_ifaces']) ) {
- if ( (!exists(SELF['type']) || SELF['type'] != 'OVSBond') ) {
- error("bond_ifaces is defined but the type of interface is not defined as OVSBond");
- };
- foreach (i; iface; SELF['bond_ifaces']) {
- if ( !exists("/system/network/interfaces/" + iface) ) {
- error("The " + iface + " interface is used by bond_ifaces, but does not exist");
- };
- };
- };
- if (exists(SELF['ip']) && exists(SELF['netmask'])) {
- if (exists(SELF['gateway']) && ! ip_in_network(SELF['gateway'], SELF['ip'], SELF['netmask'])) {
- error('networkinterface has gateway %s not reachable from ip %s with netmask %s',
- SELF['gateway'], SELF['ip'], SELF['netmask']);
- };
- if (exists(SELF['broadcast']) && ! ip_in_network(SELF['broadcast'], SELF['ip'], SELF['netmask'])) {
- error('networkinterface has broadcast %s not reachable from ip %s with netmask %s',
- SELF['broadcast'], SELF['ip'], SELF['netmask']);
- };
- };
- if (exists(SELF['plugin']) && exists(SELF['plugin']['vxlan']) && ! exists(SELF['physdev'])) {
- error('vxlan plugin requires physdev');
- };
-
- foreach (i; name; list('my_inner_ipaddr', 'my_inner_prefix', 'my_outer_ipaddr', 'peer_outer_ipaddr')) {
- if ( exists(SELF[name]) && (!exists(SELF['type']) || SELF['type'] != 'IPIP')) {
- error("%s is defined but the type of interface is not defined as IPIP", name);
- };
- };
-
- if ( exists(SELF['type']) && SELF['type'] == 'IPIP' ) {
- foreach (i; name; list('my_inner_ipaddr', 'my_inner_prefix', 'my_outer_ipaddr')) {
- if (!exists(SELF[name])) {
- error("Type IPIP but %s is not defined.", name);
- };
- };
- };
-
- true;
-};
-
-
-@documentation{
- router
-}
-type structure_router = string[];
-
-@documentation{
- IPv6 global settings
-}
-type structure_ipv6 = {
- "enabled" ? boolean
- "default_gateway" ? type_ip
- "gatewaydev" ? valid_interface # sets IPV6_DEFAULTDEV
-};
-
-@documentation{
- Host network configuration
-
- These values are used to generate /etc/sysconfig/network
- when using ncm-network (unless specified otherwise).
-}
-type structure_network = {
- "domainname" : type_fqdn
- "hostname" : type_shorthostname
- "realhostname" ? string with is_shorthostname(SELF) || is_fqdn(SELF)
- "default_gateway" ? type_ip
- @{When default_gateway is not set, the component will try to guess the default
- gateway using the first configured gateway set on an interface.
- The default is true for backward compatible behaviour.}
- "guess_default_gateway" ? boolean
- "gatewaydev" ? valid_interface
- @{Per interface network settings.
- These values are used to generate the /etc/sysconfig/network-scripts/ifcfg- files
- when using ncm-network.}
- "interfaces" : structure_interface{}
- "nameserver" ? type_ip[]
- "nisdomain" ? string(1..64) with match(SELF, '^\S+$')
- @{Setting nozeroconf to true stops an interface from being assigned an automatic address in the 169.254.0.0 subnet.}
- "nozeroconf" ? boolean
- @{The default behaviour for all interfaces wrt setting the MAC address (see interface set_hwaddr attribute).
- The component default is false.}
- "set_hwaddr" ? boolean
- "nmcontrolled" ? boolean
- "allow_nm" ? boolean
- @{let NetworkManager manage the dns (only for nmstate)}
- "nm_manage_dns" : boolean = false
- @{let ncm-network cleanup inactive connections (only for nmstate)}
- "nm_clean_inactive_conn" : boolean = true
- "primary_ip" ? string
- "routers" ? structure_router{}
- "ipv6" ? structure_ipv6
- "manage_vips" : boolean = false
- "vips" ? structure_vip{}
- @{Manage custom routing table entries; key is the name; value is the id}
- "routing_table" ? long(1..252){} with {
- if (exists(SELF['main']) || exists(SELF['local']) || exists(SELF['default']) || exists(SELF['unspec'])) {
- error("No reserved names in routing table");
- };
- true;
- }
-} with {
- if (exists(SELF['default_gateway'])) {
- reachable = false;
- # is there any interface that can reach it?
- foreach (name; data; SELF['interfaces']) {
- if (exists(data['ip']) && exists(data['netmask']) &&
- ip_in_network(SELF['default_gateway'], data['ip'], data['netmask'])) {
- reachable = true;
- };
- };
- if (!reachable) {
- error("No interface with ip/mask found to reach default gateway");
- };
- };
- true;
-};
+include if (QUATTOR_TYPES_NETWORK_LEGACY) 'components/network/core-schema-legacy'
+ else 'components/network/types/network';
diff --git a/ncm-network/src/main/pan/components/network/schema.pan b/ncm-network/src/main/pan/components/network/schema.pan
old mode 100755
new mode 100644
diff --git a/ncm-network/src/main/pan/components/network/types/network.pan b/ncm-network/src/main/pan/components/network/types/network.pan
new file mode 100644
index 0000000000..9abd28c550
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network.pan
@@ -0,0 +1,97 @@
+declaration template components/network/types/network;
+
+include 'pan/types';
+include 'quattor/functions/network';
+
+final variable QUATTOR_TYPES_NETWORK_BACKEND ?= 'initscripts';
+
+include format('components/network/types/network/backend/%s', QUATTOR_TYPES_NETWORK_BACKEND);
+
+include 'components/network/types/network/interface';
+
+@documentation{
+ Define vip interfaces for configuring loopback interface. Used with frr/zebra configuration
+}
+type network_vip = {
+ "interfaces" : valid_interface[]
+ "ip" : type_ip
+ "fqdn" ? type_fqdn
+ "netmask" ? type_ip
+ "broadcast" ? type_ip
+};
+
+@documentation{
+ router
+}
+type network_router = string[];
+
+@documentation{
+ IPv6 global settings
+}
+type network_ipv6 = {
+ "enabled" ? boolean
+ "default_gateway" ? type_ip
+ "gatewaydev" ? valid_interface # sets IPV6_DEFAULTDEV
+};
+
+@documentation{
+ Host network configuration
+
+ These values are used to generate /etc/sysconfig/network
+ when using ncm-network (unless specified otherwise).
+}
+type structure_network = {
+ "domainname" : type_fqdn
+ "hostname" : type_shorthostname
+ "realhostname" ? string with is_shorthostname(SELF) || is_fqdn(SELF)
+ "default_gateway" ? type_ip
+ @{When default_gateway is not set, the component will try to guess the default
+ gateway using the first configured gateway set on an interface.
+ The default is true for backward compatible behaviour.}
+ "guess_default_gateway" ? boolean
+ "gatewaydev" ? valid_interface
+ @{Per interface network settings.
+ These values are used to generate the /etc/sysconfig/network-scripts/ifcfg- files
+ when using ncm-network.}
+ "interfaces" : network_interface{}
+ "nameserver" ? type_ip[]
+ "nisdomain" ? string(1..64) with match(SELF, '^\S+$')
+ @{Setting nozeroconf to true stops an interface from being assigned an automatic address in the 169.254.0.0 subnet.}
+ "nozeroconf" ? boolean
+ @{The default behaviour for all interfaces wrt setting the MAC address (see interface set_hwaddr attribute).
+ The component default is false.}
+ "set_hwaddr" ? boolean
+ "nmcontrolled" ? boolean
+ "allow_nm" ? boolean
+ @{let NetworkManager manage the dns (only for nmstate)}
+ "nm_manage_dns" : boolean = false
+ @{let ncm-network cleanup inactive connections (only for nmstate)}
+ "nm_clean_inactive_conn" : boolean = true
+ "primary_ip" ? string
+ "routers" ? network_router{}
+ "ipv6" ? network_ipv6
+ "manage_vips" : boolean = false
+ "vips" ? network_vip{}
+ @{Manage custom routing table entries; key is the name; value is the id}
+ "routing_table" ? long(1..252){} with {
+ if (exists(SELF['main']) || exists(SELF['local']) || exists(SELF['default']) || exists(SELF['unspec'])) {
+ error("No reserved names in routing table");
+ };
+ true;
+ }
+} with {
+ if (exists(SELF['default_gateway'])) {
+ reachable = false;
+ # is there any interface that can reach it?
+ foreach (name; data; SELF['interfaces']) {
+ if (exists(data['ip']) && exists(data['netmask']) &&
+ ip_in_network(SELF['default_gateway'], data['ip'], data['netmask'])) {
+ reachable = true;
+ };
+ };
+ if (!reachable) {
+ error("No interface with ip/mask found to reach default gateway");
+ };
+ };
+ true;
+};
diff --git a/ncm-network/src/main/pan/components/network/types/network/backend/initscripts.pan b/ncm-network/src/main/pan/components/network/types/network/backend/initscripts.pan
new file mode 100644
index 0000000000..489692dcd8
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/backend/initscripts.pan
@@ -0,0 +1,3 @@
+declaration template components/network/types/network/backend/initscripts;
+
+@{implement types specific for initscripts / network.pm}
diff --git a/ncm-network/src/main/pan/components/network/types/network/backend/nmstate.pan b/ncm-network/src/main/pan/components/network/types/network/backend/nmstate.pan
new file mode 100644
index 0000000000..a2d478bba7
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/backend/nmstate.pan
@@ -0,0 +1,3 @@
+declaration template components/network/types/network/backend/nmstate;
+
+@{implement types specific for nmstate / nmstate.pm}
diff --git a/ncm-network/src/main/pan/components/network/types/network/ethtool.pan b/ncm-network/src/main/pan/components/network/types/network/ethtool.pan
new file mode 100644
index 0000000000..4ebfc110d7
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/ethtool.pan
@@ -0,0 +1,68 @@
+declaration template components/network/types/network/ethtool;
+
+@documentation{
+ interface ethtool offload
+}
+type network_ethtool_offload = {
+ "rx" ? choice('on', 'off')
+ "tx" ? choice('on', 'off')
+ @{Set the TCP segment offload parameter to "off" or "on"}
+ "tso" ? choice('on', 'off')
+ "gro" ? choice('on', 'off')
+ "gso" ? choice('on', 'off')
+};
+
+@documentation{
+ Set the ethernet transmit or receive buffer ring counts.
+ See ethtool --show-ring for the values.
+}
+type network_ethtool_ring = {
+ "rx" ? long
+ "tx" ? long
+ "rx-mini" ? long
+ "rx-jumbo" ? long
+};
+
+@documentation{
+ Set the number of channels.
+ See ethtool --show-channels for the values.
+}
+type network_ethtool_channels = {
+ "rx" ? long(0..)
+ "tx" ? long(0..)
+ "other" ? long(0..)
+ "combined" ? long(0..)
+};
+
+@documentation{
+ ethtool wol p|u|m|b|a|g|s|d...
+ from the man page
+ Sets Wake-on-LAN options. Not all devices support this. The argument to this option is a string
+ of characters specifying which options to enable.
+ p Wake on phy activity
+ u Wake on unicast messages
+ m Wake on multicast messages
+ b Wake on broadcast messages
+ a Wake on ARP
+ g Wake on MagicPacket(tm)
+ s Enable SecureOn(tm) password for MagicPacket(tm)
+ d Disable (wake on nothing). This option clears all previous option
+}
+type network_ethtool_wol = string with match (SELF, '^(p|u|m|b|a|g|s|d)+$');
+
+@documentation{
+ ethtool
+}
+type network_ethtool = {
+ "wol" ? network_ethtool_wol
+ "autoneg" ? choice('on', 'off')
+ "duplex" ? choice('half', 'full')
+ "speed" ? long
+ "channels" ? network_ethtool_channels
+};
+
+type network_interface_ethtool = {
+ "offload" ? network_ethtool_offload
+ "ring" ? network_ethtool_ring
+ "ethtool" ? network_ethtool
+};
diff --git a/ncm-network/src/main/pan/components/network/types/network/interface.pan b/ncm-network/src/main/pan/components/network/types/network/interface.pan
new file mode 100644
index 0000000000..1db7af1edc
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/interface.pan
@@ -0,0 +1,171 @@
+declaration template components/network/types/network/interface;
+
+@{Generate error if network backend is not supported.
+ First argument is the component backend (ncm-module).
+ Optional 2nd is extra message
+}
+function network_exclude_backend = {
+ module = value('/software/components/network/ncm-module', '');
+ msg = if (ARGC < 2) '' else format(': %s', ARGV[1]);
+ if (module == ARGV[0]) {
+ error("Not supported in backend module %s%s", module, msg)
+ };
+ true;
+};
+
+include 'components/network/types/network/ethtool';
+include 'components/network/types/network/route';
+include 'components/network/types/network/rule';
+include 'components/network/types/network/ovs';
+include 'components/network/types/network/tunnel';
+
+
+@documentation{
+ Interface alias
+}
+type network_interface_alias = {
+ "ip" ? type_ip
+ "netmask" : type_ip
+ "broadcast" ? type_ip
+ "fqdn" ? type_fqdn
+};
+
+@documentation{
+ Describes the bonding options for configuring channel bonding on EL5 and similar.
+}
+type network_bonding_options = {
+ "mode" : long(0..6)
+ "miimon" : long
+ "updelay" ? long
+ "downdelay" ? long
+ "primary" ? valid_interface
+ "lacp_rate" ? long(0..1)
+ "xmit_hash_policy" ? choice('0', '1', '2', 'layer2', 'layer2+3', 'layer3+4')
+} with {
+ if ( SELF['mode'] == 1 || SELF['mode'] == 5 || SELF['mode'] == 6 ) {
+ if ( ! exists(SELF["primary"]) ) {
+ error("Bonding configured but no primary is defined.");
+ };
+ } else {
+ if ( exists(SELF["primary"]) ) {
+ error("Primary is defined but this is not allowed with this bonding mode.");
+ };
+ };
+ true;
+};
+
+@documentation{
+ describes the bridging options
+ (the parameters for /sys/class/net/
/brport)
+}
+type network_bridging_options = {
+ "bpdu_guard" ? long
+ "flush" ? long
+ "hairpin_mode" ? long
+ "multicast_fast_leave" ? long
+ "multicast_router" ? long
+ "path_cost" ? long
+ "priority" ? long
+ "root_block" ? long
+};
+
+
+type network_interface_type = choice(
+ 'Ethernet', 'Bridge', 'Tap', 'xDSL', 'IPIP', 'Infiniband',
+ 'OVSBridge', 'OVSPort', 'OVSIntPort', 'OVSBond', 'OVSTunnel', 'OVSPatchPort'
+ );
+
+@documentation{
+ network interface
+}
+type network_interface = {
+ "ip" ? type_ip
+ "gateway" ? type_ip
+ "netmask" ? type_ip
+ "broadcast" ? type_ip
+ "driver" ? string
+ "bootproto" ? choice('static', 'bootp', 'dhcp', 'none')
+ "onboot" ? boolean
+ "type" ? network_interface_type
+ "device" ? string
+ "mtu" ? long
+ "master" ? string
+ "bonding_opts" ? network_bonding_options
+ @{Routes for this interface.
+ These values are used to generate the /etc/sysconfig/network-scripts/route[6]- files
+ as used by ifup-routes when using ncm-network.
+ This allows for mixed IPv4 and IPv6 configuration}
+ "route" ? network_route[]
+ @{Rules for this interface.
+ These values are used to generate the /etc/sysconfig/network-scripts/rule[6]- files
+ as used by ifup-routes when using ncm-network.
+ This allows for mixed IPv4 and IPv6 configuration}
+ "rule" ? network_rule[]
+ @{Aliases for this interface.
+ These values are used to generate the /etc/sysconfig/network-scripts/ifcfg-: files
+ as used by ifup-aliases when using ncm-network.}
+ "aliases" ? network_interface_alias{}
+ @{Explicitly set the MAC address. The MAC address is taken from /hardware/cards/nic//hwaddr.}
+ "set_hwaddr" ? boolean
+
+
+ @{Is a VLAN device. If the device name starts with vlan, this is always true.}
+ "vlan" ? boolean
+ @{If the device name starts with vlan, this has to be set.
+ It is set (but ignored by ifup) if it the device is not named vlan}
+ "physdev" ? valid_interface
+
+ "fqdn" ? string
+ "network_environment" ? string
+ "network_type" ? string
+ "nmcontrolled" ? boolean
+ @{Set DEFROUTE, is the default for ipv6_defroute}
+ "defroute" ? boolean
+
+ "bridge" ? valid_interface
+ "linkdelay" ? long # LINKDELAY
+ "stp" ? boolean # enable/disable stp on bridge (true: STP=on)
+ "delay" ? long # brctl setfd DELAY
+ "bridging_opts" ? network_bridging_options
+
+ "bond_ifaces" ? string[]
+
+ "ipv4_failure_fatal" ? boolean
+ "ipv6_autoconf" ? boolean
+ "ipv6_failure_fatal" ? boolean
+ "ipv6_mtu" ? long(1280..65536)
+ "ipv6_privacy" ? choice('rfc3041')
+ "ipv6_rtr" ? boolean
+ @{Set IPV6_DEFROUTE, defaults to defroute value}
+ "ipv6_defroute" ? boolean
+ "ipv6addr" ? type_network_name
+ "ipv6addr_secondaries" ? type_network_name[]
+ "ipv6init" ? boolean
+
+ include network_interface_ethtool
+ include network_interface_ovs
+ include network_interface_tunnel
+} with {
+ network_interface_ovs_validate(SELF);
+ network_interface_tunnel_validate(SELF);
+
+ if ( exists(SELF['bond_ifaces']) ) {
+ foreach (i; iface; SELF['bond_ifaces']) {
+ if ( !exists("/system/network/interfaces/" + iface) ) {
+ error("The " + iface + " interface is used by bond_ifaces, but does not exist");
+ };
+ };
+ };
+ if (exists(SELF['ip']) && exists(SELF['netmask'])) {
+ if (exists(SELF['gateway']) && ! ip_in_network(SELF['gateway'], SELF['ip'], SELF['netmask'])) {
+ error('networkinterface has gateway %s not reachable from ip %s with netmask %s',
+ SELF['gateway'], SELF['ip'], SELF['netmask']);
+ };
+ if (exists(SELF['broadcast']) && ! ip_in_network(SELF['broadcast'], SELF['ip'], SELF['netmask'])) {
+ error('networkinterface has broadcast %s not reachable from ip %s with netmask %s',
+ SELF['broadcast'], SELF['ip'], SELF['netmask']);
+ };
+ };
+
+ true;
+};
diff --git a/ncm-network/src/main/pan/components/network/types/network/ovs.pan b/ncm-network/src/main/pan/components/network/types/network/ovs.pan
new file mode 100644
index 0000000000..7ed759b877
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/ovs.pan
@@ -0,0 +1,35 @@
+declaration template components/network/types/network/ovs;
+
+
+type network_interface_ovs = {
+ "ovs_bridge" ? valid_interface
+ "ovs_extra" ? string
+ "ovs_opts" ? string # See ovs-vswitchd.conf.db(5) for documentation
+ "ovs_patch_peer" ? string
+ "ovs_tunnel_opts" ? string # See ovs-vswitchd.conf.db(5) for documentation
+ "ovs_tunnel_type" ? choice('gre', 'vxlan')
+};
+
+
+@{validate the network_interface ovs config. error on error}
+function network_interface_ovs_validate = {
+ nwcfg = ARGV[0];
+ if ( exists(SELF['ovs_bridge']) && exists(SELF['type']) && SELF['type'] == 'OVSBridge') {
+ error("An OVSBridge interface cannot have the ovs_bridge option defined");
+ };
+ if ( exists(SELF['ovs_tunnel_type']) && (!exists(SELF['type']) || SELF['type'] != 'OVSTunnel')) {
+ error("ovs_tunnel_bridge is defined but the type of interface is not defined as OVSTunnel");
+ };
+ if ( exists(SELF['ovs_tunnel_opts']) && (!exists(SELF['type']) || SELF['type'] != 'OVSTunnel')) {
+ error("ovs_tunnel_opts is defined but the type of interface is not defined as OVSTunnel");
+ };
+ if ( exists(SELF['ovs_patch_peer']) && (!exists(SELF['type']) || SELF['type'] != 'OVSPatchPort')) {
+ error("ovs_patch_peer is defined but the type of interface is not defined as OVSPatchPort");
+ };
+ if ( exists(SELF['bond_ifaces']) ) {
+ if ( (!exists(SELF['type']) || SELF['type'] != 'OVSBond') ) {
+ error("bond_ifaces is defined but the type of interface is not defined as OVSBond");
+ };
+ };
+ true;
+};
diff --git a/ncm-network/src/main/pan/components/network/types/network/route.pan b/ncm-network/src/main/pan/components/network/types/network/route.pan
new file mode 100644
index 0000000000..40c06c549b
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/route.pan
@@ -0,0 +1,55 @@
+declaration template components/network/types/network/route;
+
+type network_valid_routing_table = string with exists("/system/network/routing_table/" + SELF);
+
+@documentation{
+ Add route (IPv4 of IPv6)
+ Presence of ':' in any of the values indicates this is IPv6 related.
+}
+type network_route = {
+ @{The ADDRESS in ADDRESS/PREFIX via GATEWAY}
+ "address" ? string with {SELF == 'default' || is_ip(SELF)}
+ @{The PREFIX in ADDRESS/PREFIX via GATEWAY}
+ "prefix" ? long
+ @{The GATEWAY in ADDRESS/PREFIX via GATEWAY}
+ "gateway" ? type_ip
+ @{alternative notation for prefix (cannot be combined with prefix)}
+ "netmask" ? type_ip
+ @{routing table}
+ "table" ? network_valid_routing_table
+ @{pretend that the nexthop is directly attached to this link}
+ "onlink" ? boolean
+ @{route add command options to use (cannot be combined with other options)}
+ "command" ? string with !match(SELF, '[;]')
+} with {
+ if (exists(SELF['command'])) {
+ network_exclude_backend('nmstate', 'command routes');
+ if (length(SELF) != 1) error("Cannot use command and any of the other attributes as route");
+ } else {
+ if (!exists(SELF['address']))
+ error("Address is mandatory for route (in absence of command)");
+ if (exists(SELF['prefix']) && exists(SELF['netmask']))
+ error("Use either prefix or netmask as route");
+ };
+
+ if (exists(SELF['prefix'])) {
+ pref = SELF['prefix'];
+ ipv6 = false;
+ foreach (k; v; SELF) {
+ if (match(to_string(v), ':')) {
+ ipv6 = true;
+ };
+ };
+ if (ipv6) {
+ if (!is_ipv6_prefix_length(pref)) {
+ error("Prefix %s is not a valid IPv6 prefix", pref);
+ };
+ } else {
+ if (!is_ipv4_prefix_length(pref)) {
+ error("Prefix %s is not a valid IPv4 prefix", pref);
+ };
+ };
+ };
+
+ true;
+};
diff --git a/ncm-network/src/main/pan/components/network/types/network/rule.pan b/ncm-network/src/main/pan/components/network/types/network/rule.pan
new file mode 100644
index 0000000000..b4a70e24b1
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/rule.pan
@@ -0,0 +1,35 @@
+declaration template components/network/types/network/rule;
+
+type network_ip_cmd_prefix = string with {is_ipv4_netmask_pair(SELF) || is_ipv6_network_block(SELF)};
+
+@documentation{
+ Add rule (IPv4 of IPv6)
+ Presence of ':' in any of the values indicates this is IPv6 related.
+}
+type network_rule = {
+ @{to selector}
+ "to" ? network_ip_cmd_prefix
+ @{from selector}
+ "from" ? network_ip_cmd_prefix
+ @{not action (false value means no not action; also the default when not is not defined)}
+ "not" ? boolean
+ @{routing table action}
+ "table" ? network_valid_routing_table
+ @{priority, The priority of the rule over the others. Required by Network Manager when setting routing rules.}
+ "priority" ? long(0..0xffffffff)
+ @{rule add options to use (cannot be combined with other options)}
+ "command" ? string with !match(SELF, '[;]')
+} with {
+ if (exists(SELF['command'])) {
+ network_exclude_backend('nmstate', 'command rules');
+ if (length(SELF) != 1) error("Cannot use command and any of the other attributes as rule");
+ } else {
+ if (!exists(SELF['to']) && !exists(SELF['from'])) {
+ error("Rule requires selector to or from (or use command)");
+ };
+ if (!exists(SELF['table'])) {
+ error("Rule requires action table (or use command)");
+ };
+ };
+ true;
+};
diff --git a/ncm-network/src/main/pan/components/network/types/network/tunnel.pan b/ncm-network/src/main/pan/components/network/types/network/tunnel.pan
new file mode 100644
index 0000000000..c0def8d35d
--- /dev/null
+++ b/ncm-network/src/main/pan/components/network/types/network/tunnel.pan
@@ -0,0 +1,75 @@
+declaration template components/network/types/network/tunnel;
+
+@documentation{
+ interface plugin for vxlan support via initscripts-vxlan
+}
+type network_interface_plugin_vxlan = {
+ @{VXLAN Network Identifier (or VXLAN Segment ID); derived from devicename vxlan[0-9] if not defined}
+ 'vni' ? long(0..16777216)
+ @{multicast ip to join}
+ 'group' ? type_ip
+ @{destination IP address to use in outgoing packets}
+ 'remote' ? type_ip
+ @{source IP address to use in outgoing packets}
+ 'local' ? type_ip
+ @{UDP destination port}
+ 'dstport' ? long(2..65535)
+ @{Group Policy extension}
+ 'gbp' ? boolean
+} with {
+ if (exists(SELF['group']) && exists(SELF['remote'])) {
+ error('Cannot define both group and remote for vxlan');
+ };
+ if (!exists(SELF['group']) && !exists(SELF['remote'])) {
+ error('Must define either group or remote for vxlan');
+ };
+ true;
+};
+
+# moved here, because this probably no nmstate equivalent to plugins
+# vxlan doesn't need one in any case
+@documentation{
+ interface plugin via custom ifup/down[-pre]-local hooks
+}
+type network_interface_plugin = {
+ @{VXLAN support via initscripts-vxlan}
+ "vxlan" ? network_interface_plugin_vxlan
+};
+
+
+type network_interface_tunnel = {
+ @{tunnel IP}
+ "my_inner_ipaddr" ? type_ip
+ @{tunnel IP netmask prefix}
+ "my_inner_prefix" ? long(0..32)
+ @{primary local IP address}
+ "my_outer_ipaddr" ? type_ip
+ @{remote peer primary IP address}
+ "peer_outer_ipaddr" ? type_ip
+
+ "plugin" ? network_interface_plugin
+};
+
+
+@{validate the network_interface tunnel config. error on error}
+function network_interface_tunnel_validate = {
+ nwcfg = ARGV[0];
+ if (exists(nwcfg['plugin']) && exists(nwcfg['plugin']['vxlan']) && ! exists(nwcfg['physdev'])) {
+ error('vxlan plugin requires physdev');
+ };
+
+ foreach (i; name; list('my_inner_ipaddr', 'my_inner_prefix', 'my_outer_ipaddr', 'peer_outer_ipaddr')) {
+ if ( exists(nwcfg[name]) && (!exists(nwcfg['type']) || nwcfg['type'] != 'IPIP')) {
+ error("%s is defined but the type of interface is not defined as IPIP", name);
+ };
+ };
+
+ if ( exists(nwcfg['type']) && nwcfg['type'] == 'IPIP' ) {
+ foreach (i; name; list('my_inner_ipaddr', 'my_inner_prefix', 'my_outer_ipaddr')) {
+ if (!exists(nwcfg[name])) {
+ error("Type IPIP but %s is not defined.", name);
+ };
+ };
+ };
+ true;
+};
diff --git a/ncm-network/src/main/perl/network.pm b/ncm-network/src/main/perl/network.pm
index a2ad136ef4..55ada87f0b 100755
--- a/ncm-network/src/main/perl/network.pm
+++ b/ncm-network/src/main/perl/network.pm
@@ -1004,6 +1004,7 @@ sub make_ifcfg
&$makeline('device', def => $ifacename);
+ $iface->{type} = 'Ethernet' if ($iface->{type} || '') eq 'Infiniband';
&$makeline('type', def => 'Ethernet');
if ( ($iface->{type} || '') =~ m/^OVS/) {
diff --git a/ncm-network/src/main/perl/nmstate.pm b/ncm-network/src/main/perl/nmstate.pm
index 44f00a39d6..55d5595f96 100644
--- a/ncm-network/src/main/perl/nmstate.pm
+++ b/ncm-network/src/main/perl/nmstate.pm
@@ -122,7 +122,7 @@ sub make_nm_ip_rule
$thisrule{'ip-to'} = $rule->{to} if $rule->{to};
$thisrule{'ip-from'} = $rule->{from} if $rule->{from};
push (@rule_entry, \%thisrule);
-
+
# Add a default absent rule to match table defined. This will clear any existing rules for this table, instead of merging.
if ($rule->{table}) {
$rule_entry_absent{'state'} = "absent";
@@ -320,6 +320,7 @@ sub find_vlan_id {
}
return $vlanid;
}
+
# Check if given ip belongs to a network
sub ip_in_network {
my ($self, $check_ip, $ip, $netmask) = @_;
@@ -354,7 +355,22 @@ sub generate_nmstate_config
# this will be empty if the interface isnt a bond interface.
# we can use this to determine if this interface is bond interface.
my $bonded_eth = get_bonded_eth($self, $name, $net->{interfaces});
- if ($is_eth) {
+
+ my $vlan_id = $self->find_vlan_id($name, $iface->{device});
+
+ if (lc($iface->{type} || '') eq 'infiniband') {
+ $ifaceconfig->{type} = "infiniband";
+ my $ib = {};
+ my $pkey = $vlan_id || 65535;
+ if ($vlan_id) {
+ my $ibdev = $name;
+ $ibdev =~ s/\.\d+$//;
+ $ib->{'base-iface'} = $ibdev;
+ };
+ $ib->{pkey} = "0x" . sprintf("%04x", $pkey);
+ $ib->{mode} = 'datagram'; # TODO: add connected mode, but who still uses that
+ $ifaceconfig->{infiniband} = $ib;
+ } elsif ($is_eth) {
$ifaceconfig->{type} = "ethernet";
if ($is_partof_bond) {
# no ipv4 address for bonded eth, plus in nmstate bonded eth is controlled by controller. no config is required.
@@ -362,7 +378,6 @@ sub generate_nmstate_config
$ifaceconfig->{state} = "up";
}
} elsif ($is_vlan_eth) {
- my $vlan_id = $self->find_vlan_id($name, $iface->{device});
# if vlan_id is empty, error
if (! $vlan_id) {
$self->error("Could not find vlan id for vlan device $name");
@@ -370,7 +385,7 @@ sub generate_nmstate_config
$ifaceconfig->{type} = "vlan";
$ifaceconfig->{vlan}->{'base-iface'} = $iface->{physdev};
$ifaceconfig->{vlan}->{'id'} = $vlan_id;
- } elsif ($bonded_eth) {
+ } elsif (@$bonded_eth) {
# if bond device
$ifaceconfig->{type} = "bond";
$ifaceconfig->{'link-aggregation'} = $iface->{link_aggregation};
@@ -579,7 +594,7 @@ sub nmstate_apply
if (@ifaces) {
$self->info("Applying changes using $NMSTATECTL ", join(', ', @ifaces));
- my @cmds;
+ my @cmds;
foreach my $iface (@ifaces) {
# apply config using nmstatectl
my $ymlfile = $self->iface_filename($iface);
@@ -709,7 +724,7 @@ sub Configure
$exifiles->{$dummy_filename} = $self->nmstate_file_dump($dummy_filename, $nmstate_dummy_cfg);
}
};
-
+
my $dev2mac = $self->make_dev2mac();
# We now have a map with files and values.
diff --git a/ncm-network/src/test/perl/nmstate_advance.t b/ncm-network/src/test/perl/nmstate_advance.t
index 8bde514c63..13f20dcd0e 100644
--- a/ncm-network/src/test/perl/nmstate_advance.t
+++ b/ncm-network/src/test/perl/nmstate_advance.t
@@ -181,6 +181,53 @@ interfaces:
type: dummy
EOF
+Readonly my $IB_YML => < < <