Repository: sonic-net/sonic-mgmt

Issue:
[dualtor] Missing Loopback2 interface in device minigraph
<!--
If you are reporting a new issue, make sure that we do not have any duplicates
already open. You can ensure this by searching the issue list for this
repository. If there is a duplicate, please close your issue and add a comment
to the existing issue instead.

If you suspect your issue is a bug, please edit your issue description to
include the BUG REPORT INFORMATION shown below. If you fail to provide this
information within 7 days, we cannot debug your issue and will close it. We
will, however, reopen it if you later provide the information.

For more information about reporting issues, see
https://github.com/Azure/SONiC/wiki#report-issues

---------------------------------------------------
GENERAL SUPPORT INFORMATION
---------------------------------------------------

The GitHub issue tracker is for bug reports and feature requests.
General support can be found at the following locations:

- SONiC Support Forums - https://groups.google.com/forum/#!forum/sonicproject

---------------------------------------------------
BUG REPORT INFORMATION
---------------------------------------------------
Use the commands below to provide key information from your environment:
You do NOT have to include this information if this is a FEATURE REQUEST
-->

**Description**
Minigraph generated for Dual ToR devices does not have `Loopback2` interface.
The `linkmrgd` waits on `Loopback2` interface to perform the probe and to indicate subsequent switchover tasks.
Further, APP DB is missing *MUX* keys.

<!--
Briefly describe the problem you are having in a few paragraphs.
-->

**Steps to reproduce the issue:**
1. Manual switchover using CLI in dual TOR on standby TOR.
2. The switchover fails to happen.
3.

**Describe the results you received:**
ToR switchover failed.

**Describe the results you expected:**
Switchover should work. APP DB should contain *MUX* keys.

**Additional information you deem important:**
<!--
software/ASIC/Hardware Flatform version and info
-->
    **Output of `show version`:**

    ```
    (paste your output here)
    ```

    **Attach debug file `sudo generate_dump`:**

    ```
    (paste your output here)
    ```



Discussion:

Resolving patch:
diff --git a/ansible/library/dual_tor_facts.py b/ansible/library/dual_tor_facts.py
--- a/ansible/library/dual_tor_facts.py
+++ b/ansible/library/dual_tor_facts.py
@@ -33,19 +33,26 @@ def parse_loopback_ips(self):
         '''
         Parses the IPv4 and IPv6 loopback IPs for the DUTs
 
-        Similar to `parse_tor_position`, the ToR which comes first alphabetically is always assigned the first IP
+        Similar to `parse_tor_position`, the ToR which comes first in the testbed file is always assigned the first IP
         '''
 
         loopback_ips = defaultdict(dict)
-
-        ipv4_loopbacks = sorted(self.vm_config['DUT']['loopback']['ipv4'])
-        ipv6_loopbacks = sorted(self.vm_config['DUT']['loopback']['ipv6'])
-
-        for i, dut in enumerate(sorted(self.testbed_facts['duts'])):
-            loopback_ips[dut]['ipv4'] = ipv4_loopbacks[i]
-            loopback_ips[dut]['ipv6'] = ipv6_loopbacks[i] 
-
-        self.dual_tor_facts['loopback'] = loopback_ips     
+        addl_loopback_ips = defaultdict(dict)
+
+        for dut_num, dut in enumerate(self.testbed_facts['duts']):
+            loopback_ips[dut]['ipv4'] = self.vm_config['DUT']['loopback']['ipv4'][dut_num]
+            loopback_ips[dut]['ipv6'] = self.vm_config['DUT']['loopback']['ipv6'][dut_num] 
+
+            for loopback_num in range(1, 3): # Generate two additional loopback IPs, Loopback1 and Loopback2
+                loopback_key = 'loopback{}'.format(loopback_num)
+                loopback_dict = {}
+                loopback_dict['ipv4'] = self.vm_config['DUT'][loopback_key]['ipv4'][dut_num]
+                loopback_dict['ipv6'] = self.vm_config['DUT'][loopback_key]['ipv6'][dut_num]
+                loopback_dict['host_ip_base_index'] = loopback_num * 2
+                addl_loopback_ips[dut][loopback_num] = loopback_dict
+
+        self.dual_tor_facts['loopback'] = loopback_ips 
+        self.dual_tor_facts['addl_loopbacks'] = addl_loopback_ips
 
     def generate_cable_names(self):
         cables = []


Test patch: