]> git.puffer.fish Git - mirror/frr.git/commitdiff
topotests: add support for frr.conf as a unified config 10668/head
authorJafar Al-Gharaibeh <jafar@atcorp.com>
Sun, 27 Feb 2022 01:59:48 +0000 (19:59 -0600)
committerJafar Al-Gharaibeh <jafar@atcorp.com>
Mon, 28 Feb 2022 02:53:18 +0000 (20:53 -0600)
This PR adds support for configuring topotest routers using a single file.
  instead of:
```
        router.load_config(
    TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
    )
router.load_config(
    TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
    )
router.load_config(
    TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
    )
```
  you can now do:
```
        router.load_frr_config(
    os.path.join(CWD, "{}/frr.conf".format(rname)),
    [TopoRouter.RD_ZEBRA, TopoRouter.RD_OSPF, TopoRouter.RD_BGP]
    )
```
or just:

```
        router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
```
In this latter case, the daemons list will be inferred from frr.conf file.

Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
tests/topotests/lib/topogen.py
tests/topotests/lib/topotest.py

index 33e1388639680a160cbe41c4316ff8d99b0faacc..a83ae7071f7acad2adc9efdeefd91a0f2eca82c4 100644 (file)
@@ -706,6 +706,7 @@ class TopoRouter(TopoGear):
     ]
 
     # Router Daemon enumeration definition.
+    RD_FRR = 0  # not a daemon, but use to setup unified configs
     RD_ZEBRA = 1
     RD_RIP = 2
     RD_RIPNG = 3
@@ -725,6 +726,7 @@ class TopoRouter(TopoGear):
     RD_PATH = 17
     RD_SNMP = 18
     RD = {
+        RD_FRR: "frr",
         RD_ZEBRA: "zebra",
         RD_RIP: "ripd",
         RD_RIPNG: "ripngd",
@@ -789,6 +791,28 @@ class TopoRouter(TopoGear):
         self.logger.info('check capability {} for "{}"'.format(param, daemonstr))
         return self.net.checkCapability(daemonstr, param)
 
+    def load_frr_config(self, source, daemons=None):
+        """
+        Loads the unified configuration file source
+        Start the daemons in the list
+        If daemons is None, try to infer daemons from the config file
+        """
+        self.load_config(self.RD_FRR, source)
+        if not daemons:
+            # Always add zebra
+            self.load_config(self.RD_ZEBRA)
+            for daemon in self.RD:
+                # This will not work for all daemons
+                daemonstr = self.RD.get(daemon).rstrip("d")
+                result = self.run(
+                    "grep 'router {}' {}".format(daemonstr, source)
+                ).strip()
+                if result:
+                    self.load_config(daemon)
+        else:
+            for daemon in daemons:
+                self.load_config(daemon)
+
     def load_config(self, daemon, source=None, param=None):
         """Loads daemon configuration from the specified source
         Possible daemon values are: TopoRouter.RD_ZEBRA, TopoRouter.RD_RIP,
index d3438f67e5525b1545af7c3dc6aaf9ee0f550e36..4e5fe4c90bb9cccf3b4570e692888232f8a5c8f0 100644 (file)
@@ -1319,6 +1319,7 @@ class Router(Node):
         self.daemondir = None
         self.hasmpls = False
         self.routertype = "frr"
+        self.unified_config = None
         self.daemons = {
             "zebra": 0,
             "ripd": 0,
@@ -1521,21 +1522,28 @@ class Router(Node):
                     )
 
         # print "Daemons before:", self.daemons
-        if daemon in self.daemons.keys():
-            self.daemons[daemon] = 1
+        if daemon in self.daemons.keys() or daemon == "frr":
+            if daemon == "frr":
+                self.unified_config = 1
+            else:
+                self.daemons[daemon] = 1
             if param is not None:
                 self.daemons_options[daemon] = param
             conf_file = "/etc/{}/{}.conf".format(self.routertype, daemon)
             if source is None or not os.path.exists(source):
-                self.cmd_raises("rm -f " + conf_file)
-                self.cmd_raises("touch " + conf_file)
+                if daemon == "frr" or not self.unified_config:
+                    self.cmd_raises("rm -f " + conf_file)
+                    self.cmd_raises("touch " + conf_file)
             else:
                 self.cmd_raises("cp {} {}".format(source, conf_file))
-            self.cmd_raises("chown {0}:{0} {1}".format(self.routertype, conf_file))
-            self.cmd_raises("chmod 664 {}".format(conf_file))
+
+            if not self.unified_config or daemon == "frr":
+                self.cmd_raises("chown {0}:{0} {1}".format(self.routertype, conf_file))
+                self.cmd_raises("chmod 664 {}".format(conf_file))
+
             if (daemon == "snmpd") and (self.routertype == "frr"):
                 # /etc/snmp is private mount now
-                self.cmd('echo "agentXSocket /etc/frr/agentx" > /etc/snmp/frr.conf')
+                self.cmd('echo "agentXSocket /etc/frr/agentx" >> /etc/snmp/frr.conf')
                 self.cmd('echo "mibs +ALL" > /etc/snmp/snmp.conf')
 
             if (daemon == "zebra") and (self.daemons["staticd"] == 0):
@@ -1557,11 +1565,18 @@ class Router(Node):
         return self.run_in_window(cmd, title)
 
     def startRouter(self, tgen=None):
-        # Disable integrated-vtysh-config
-        self.cmd(
-            'echo "no service integrated-vtysh-config" >> /etc/%s/vtysh.conf'
-            % self.routertype
-        )
+        if self.unified_config:
+            self.cmd(
+                'echo "service integrated-vtysh-config" >> /etc/%s/vtysh.conf'
+                % self.routertype
+            )
+        else:
+            # Disable integrated-vtysh-config
+            self.cmd(
+                'echo "no service integrated-vtysh-config" >> /etc/%s/vtysh.conf'
+                % self.routertype
+            )
+
         self.cmd(
             "chown %s:%svty /etc/%s/vtysh.conf"
             % (self.routertype, self.routertype, self.routertype)
@@ -1633,6 +1648,9 @@ class Router(Node):
         if "all" in vtysh_routers or self.name in vtysh_routers:
             self.run_in_window("vtysh", title="vt-%s" % self.name)
 
+        if self.unified_config:
+            self.cmd("vtysh -f /etc/frr/frr.conf")
+
         return status
 
     def getStdErr(self, daemon):