diff --git a/build_debian.sh b/build_debian.sh index 52a84d3ba..5c7a9344f 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -426,6 +426,9 @@ sudo cp files/dhcp/graphserviceurl $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks sudo cp files/dhcp/snmpcommunity $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/ sudo cp files/dhcp/vrf $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/ sudo cp files/dhcp/dhclient.conf $FILESYSTEM_ROOT/etc/dhcp/ +if [ -f files/image_config/ntp/ntp ]; then + sudo cp ./files/image_config/ntp/ntp $FILESYSTEM_ROOT/etc/init.d/ +fi ## Version file sudo mkdir -p $FILESYSTEM_ROOT/etc/sonic diff --git a/files/image_config/interfaces/interfaces.j2 b/files/image_config/interfaces/interfaces.j2 index e0f9a290d..ad7b52026 100644 --- a/files/image_config/interfaces/interfaces.j2 +++ b/files/image_config/interfaces/interfaces.j2 @@ -21,6 +21,14 @@ iface lo {{ 'inet' if prefix | ipv4 else 'inet6' }} static netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }} # {% endfor %} +{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %} +# The loopback network interface for mgmt VRF that is required for applications like NTP + up ip link add lo-m type dummy + up ip addr add 127.0.0.1/8 dev lo-m + up ip link set lo-m up + up ip link set dev lo-m master mgmt + down ip link delete dev lo-m +{% endif %} {% endblock loopback %} {% block mgmt_interface %} diff --git a/files/image_config/ntp/ntp b/files/image_config/ntp/ntp new file mode 100755 index 000000000..976269241 --- /dev/null +++ b/files/image_config/ntp/ntp @@ -0,0 +1,91 @@ +#!/bin/sh + +# This file was originally created automatically as part of default NTP application installation from debian package. +# This is now manually modified for supporting NTP in management VRF. +# When management VRF is enabled, the NTP application should be started using "cgexec -g l3mdev:mgmt". +# Check has been added to verify the management VRF enabled status and use cgexec when it is enabled. +# This file will be copied on top of the etc/init.d/ntp file that gets created during build process. + +### BEGIN INIT INFO +# Provides: ntp +# Required-Start: $network $remote_fs $syslog +# Required-Stop: $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: +# Short-Description: Start NTP daemon +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin + +. /lib/lsb/init-functions + +DAEMON=/usr/sbin/ntpd +PIDFILE=/var/run/ntpd.pid + +test -x $DAEMON || exit 5 + +if [ -r /etc/default/ntp ]; then + . /etc/default/ntp +fi + +if [ -e /run/ntp.conf.dhcp ]; then + NTPD_OPTS="$NTPD_OPTS -c /run/ntp.conf.dhcp" +fi + + +LOCKFILE=/run/lock/ntpdate + +RUNASUSER=ntp +UGID=$(getent passwd $RUNASUSER | cut -f 3,4 -d:) || true +if test "$(uname -s)" = "Linux"; then + NTPD_OPTS="$NTPD_OPTS -u $UGID" +fi + +case $1 in + start) + log_daemon_msg "Starting NTP server" "ntpd" + if [ -z "$UGID" ]; then + log_failure_msg "user \"$RUNASUSER\" does not exist" + exit 1 + fi + ( + flock -w 180 9 + vrfEnabled=$(/usr/local/bin/sonic-cfggen -d -v 'MGMT_VRF_CONFIG["vrf_global"]["mgmtVrfEnabled"]') + if [ "$vrfEnabled" = "true" ] + then + log_daemon_msg "Starting NTP server in mgmt-vrf" "ntpd" + cgexec -g l3mdev:mgmt start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + else + log_daemon_msg "Starting NTP server in default-vrf" "ntpd" + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + fi + ) 9>$LOCKFILE + log_end_msg $? + ;; + stop) + log_daemon_msg "Stopping NTP server" "ntpd" + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --retry=TERM/30/KILL/5 --exec $DAEMON + log_end_msg $? + rm -f $PIDFILE + ;; + restart|force-reload) + $0 stop && sleep 2 && $0 start + ;; + try-restart) + if $0 status >/dev/null; then + $0 restart + else + exit 0 + fi + ;; + reload) + exit 3 + ;; + status) + status_of_proc $DAEMON "NTP server" + ;; + *) + echo "Usage: $0 {start|stop|restart|try-restart|force-reload|status}" + exit 2 + ;; +esac diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index a65f2ef00..bea5f31ee 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -179,6 +179,14 @@ def parse_dpg(dpg, hname): ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text lo_intfs[(intfname, ipprefix)] = {} + mvrfConfigs = child.find(str(QName(ns, "MgmtVrfConfigs"))) + mvrf = {} + if mvrfConfigs != None: + mv = mvrfConfigs.find(str(QName(ns1, "MgmtVrfGlobal"))) + if mv != None: + mvrf_en_flag = mv.find(str(QName(ns, "mgmtVrfEnabled"))).text + mvrf["vrf_global"] = {"mgmtVrfEnabled": mvrf_en_flag} + mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces"))) mgmt_intf = {} for mgmtintf in mgmtintfs.findall(str(QName(ns1, "ManagementIPInterface"))): @@ -305,8 +313,8 @@ def parse_dpg(dpg, hname): except: print >> sys.stderr, "Warning: Ignoring Control Plane ACL %s without type" % aclname - return intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni - return None, None, None, None, None, None, None, None, None + return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni + return None, None, None, None, None, None, None, None, None, None def parse_cpg(cpg, hname): @@ -549,7 +557,7 @@ def parse_xml(filename, platform=None, port_config_file=None): port_alias_map.update(alias_map) for child in root: if child.tag == str(QName(ns, "DpgDec")): - (intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni) = parse_dpg(child, hostname) + (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni) = parse_dpg(child, hostname) elif child.tag == str(QName(ns, "CpgDec")): (bgp_sessions, bgp_asn, bgp_peers_with_range) = parse_cpg(child, hostname) elif child.tag == str(QName(ns, "PngDec")): @@ -593,6 +601,7 @@ def parse_xml(filename, platform=None, port_config_file=None): results['MGMT_PORT'][name]['speed'] = port_speeds_default[alias] results['MGMT_INTERFACE'][(name, key[1])] = mgmt_intf[key] results['LOOPBACK_INTERFACE'] = lo_intfs + results['MGMT_VRF_CONFIG'] = mvrf phyport_intfs = {} vlan_intfs = {} diff --git a/src/sonic-config-engine/tests/sample_output/mvrf_interfaces b/src/sonic-config-engine/tests/sample_output/mvrf_interfaces new file mode 100644 index 000000000..e66b1b252 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/mvrf_interfaces @@ -0,0 +1,69 @@ +# +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +auto mgmt +iface mgmt + vrf-table 5000 +# The loopback network interface +auto lo +iface lo inet loopback +# Use command 'ip addr list dev lo' to check all addresses +iface lo inet static + address 10.1.0.32 + netmask 255.255.255.255 +# +iface lo inet6 static + address fc00:1::32 + netmask 128 +# +iface lo inet static + address 10.10.0.99 + netmask 255.255.255.255 +# +# The loopback network interface for mgmt VRF that is required for applications like NTP + up ip link add lo-m type dummy + up ip addr add 127.0.0.1/8 dev lo-m + up ip link set lo-m up + up ip link set dev lo-m master mgmt + down ip link delete dev lo-m + +# The management network interface +auto eth0 +iface eth0 inet static + address 10.0.0.100 + netmask 255.255.255.0 + vrf mgmt + ########## management network policy routing rules + # management port up rules + up ip -4 route add default via 10.0.0.1 dev eth0 table 5000 metric 201 + up ip -4 route add 10.0.0.0/24 dev eth0 table 5000 + up ip -4 rule add from 10.0.0.100/32 table 5000 + up cgcreate -g l3mdev:mgmt + up cgset -r l3mdev.master-device=mgmt mgmt + # management port down rules + down ip -4 route delete default via 10.0.0.1 dev eth0 table 5000 + down ip -4 route delete 10.0.0.0/24 dev eth0 table 5000 + down ip -4 rule delete from 10.0.0.100/32 table 5000 + down cgdelete -g l3mdev:mgmt +iface eth0 inet6 static + address 2603:10e2:0:2902::8 + netmask 64 + vrf mgmt + ########## management network policy routing rules + # management port up rules + up ip -6 route add default via 2603:10e2:0:2902::1 dev eth0 table 5000 metric 201 + up ip -6 route add 2603:10e2:0:2902::/64 dev eth0 table 5000 + up ip -6 rule add from 2603:10e2:0:2902::8/128 table 5000 + up cgcreate -g l3mdev:mgmt + up cgset -r l3mdev.master-device=mgmt mgmt + # management port down rules + down ip -6 route delete default via 2603:10e2:0:2902::1 dev eth0 table 5000 + down ip -6 route delete 2603:10e2:0:2902::/64 dev eth0 table 5000 + down ip -6 rule delete from 2603:10e2:0:2902::8/128 table 5000 + down cgdelete -g l3mdev:mgmt +# +source /etc/network/interfaces.d/* +# + diff --git a/src/sonic-config-engine/tests/t0-sample-graph-mvrf.xml b/src/sonic-config-engine/tests/t0-sample-graph-mvrf.xml new file mode 100644 index 000000000..5162086d9 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-graph-mvrf.xml @@ -0,0 +1,408 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + LoopbackIP1 + Loopback1 + + 10.10.0.99/32 + + 10.10.0.99/32 + + + + + true + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + HostIP + eth0 + + 2603:10e2:0:2902::8/64 + + 2603:10e2:0:2902::8/64 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + ERSPAN + everflow + Everflow + + + ERSPANv6 + everflowV6 + Everflow + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + NTP + NTP_ACL + NTP + + + SSH + SSH_ACL + SSH + + + SSH + ROUTER-PROTECT + SSH + + + SNMP + ROUTER-PROTECT + SNMP + + + NTP + NTP_ACL + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA05T1 + Ethernet1/33 + true + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py index ed8ad6cbc..1fd9df37e 100644 --- a/src/sonic-config-engine/tests/test_j2files.py +++ b/src/sonic-config-engine/tests/test_j2files.py @@ -12,6 +12,7 @@ class TestJ2Files(TestCase): self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen') self.simple_minigraph = os.path.join(self.test_dir, 'simple-sample-graph.xml') self.t0_minigraph = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.t0_mvrf_minigraph = os.path.join(self.test_dir, 't0-sample-graph-mvrf.xml') self.pc_minigraph = os.path.join(self.test_dir, 'pc-test-graph.xml') self.t0_port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') self.t1_mlnx_minigraph = os.path.join(self.test_dir, 't1-sample-graph-mlnx.xml') @@ -32,6 +33,10 @@ class TestJ2Files(TestCase): self.run_script(argument) self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'interfaces'), self.output_file)) + argument = '-m ' + self.t0_mvrf_minigraph + ' -a \'{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}\' -t ' + interfaces_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', 'mvrf_interfaces'), self.output_file)) + def test_ports_json(self): ports_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ports.json.j2') argument = '-m ' + self.simple_minigraph + ' -p ' + self.t0_port_config + ' -t ' + ports_template + ' > ' + self.output_file