Add FRR nodes

The patch adds node with FRR installed

Related-Prod: PRODX-11698
Change-Id: I09302b618ef88b28945074c96e4cafb3493ca5b0
diff --git a/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-vsrx1.yaml b/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-vsrx1.yaml
index e5b688e..6c271cb 100644
--- a/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-vsrx1.yaml
+++ b/de/heat-templates/env/mstr1-wrkr3-cmp2-gtw0-vsrx1.yaml
@@ -18,6 +18,7 @@
   gtw_size: 0
   lma_size: 0
   osd_size: 0
+  frr_size: 1
   ucp_boot_timeout: 3600
   cluster_public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCp0evjOaK8c8SKYK4r2+0BN7g+8YSvQ2n8nFgOURCyvkJqOHi1qPGZmuN0CclYVdVuZiXbWw3VxRbSW3EH736VzgY1U0JmoTiSamzLHaWsXvEIW8VCi7boli539QJP0ikJiBaNAgZILyCrVPN+A6mfqtacs1KXdZ0zlMq1BPtFciR1JTCRcVs5vP2Wwz5QtY2jMIh3aiwkePjMTQPcfmh1TkOlxYu5IbQyZ3G1ahA0mNKI9a0dtF282av/F6pwB/N1R1nEZ/9VtcN2I1mf1NW/tTHEEcTzXYo1R/8K9vlqAN8QvvGLZtZduGviNVNoNWvoxaXxDt8CPv2B2NCdQFZp
   private_floating_network_cidr: '10.11.12.0/24'
diff --git a/de/heat-templates/scripts/instance_boot.sh b/de/heat-templates/scripts/instance_boot.sh
index 5397f1e..aa9a595 100644
--- a/de/heat-templates/scripts/instance_boot.sh
+++ b/de/heat-templates/scripts/instance_boot.sh
@@ -86,6 +86,11 @@
 fi
 SINGLE_NODE=${SINGLE_NODE:-true}
 
+#FRR Options
+FRR_BGP_AS_NUMBER=${FRR_BGP_AS_NUMBER:-64512}
+FRR_ROUTER_ID=${TUNNEL_INTERFACE_IP}
+FRR_BAGP_SOURCE_ADDRESS=${TUNNEL_INTERFACE_IP}
+
 function retry {
     local retries=$1
     shift
@@ -657,6 +662,55 @@
 
 }
 
+function install_frr {
+    function _install_frr_packages {
+        curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add -
+        FRRVER="frr-stable"
+        echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee -a /etc/apt/sources.list.d/frr.list
+        apt update
+        apt install -y frr frr-pythontools
+    }
+    retry 3 "Can't install frr packages" _install_frr_packages
+
+    sed -i 's/^bgpd=no/bgpd=yes/g' /etc/frr/daemons
+
+    cat << EOF > /etc/frr/frr.conf
+log syslog informational
+no ipv6 forwarding
+service integrated-vtysh-config
+!
+router bgp ${FRR_BGP_AS_NUMBER}
+ bgp router-id ${FRR_ROUTER_ID}
+ no bgp default ipv4-unicast
+ bgp cluster-id ${FRR_ROUTER_ID}
+ coalesce-time 1000
+ neighbor fabric peer-group
+ neighbor fabric remote-as ${FRR_BGP_AS_NUMBER}
+ neighbor fabric update-source ${FRR_BAGP_SOURCE_ADDRESS}
+ neighbor fabric capability extended-nexthop
+ bgp listen range 10.0.0.0/8 peer-group fabric
+ !
+ address-family ipv4 unicast
+  neighbor fabric activate
+ exit-address-family
+ !
+ address-family ipv4 vpn
+  neighbor fabric activate
+ exit-address-family
+ !
+ address-family l2vpn evpn
+  neighbor fabric activate
+  advertise-all-vni
+  advertise-default-gw
+ exit-address-family
+!
+line vty
+!
+EOF
+
+    systemctl restart frr
+}
+
 case "$NODE_TYPE" in
     # Please keep the "prepare_metadata_files", "disable-rp-filter", "network_config" and "prepare_network" functions
     # at the very beginning in the same order.
@@ -754,6 +808,23 @@
         configure_contrack
         disable_iptables_for_bridges
         ;;
+    frr)
+        prepare_metadata_files
+        disable_rp_filter
+        network_config
+        prepare_network
+        prepare_docker_config
+        install_required_packages
+        configure_ntp
+        configure_atop
+        install_docker
+        cache_images
+        download_bundles
+        workaround_default_forward_policy
+        configure_contrack
+        disable_iptables_for_bridges
+        install_frr
+        ;;
     *)
         echo "Usage: $0 {ucp|master|worker}"
         exit 1
diff --git a/de/heat-templates/top.yaml b/de/heat-templates/top.yaml
index 7864c06..6295833 100644
--- a/de/heat-templates/top.yaml
+++ b/de/heat-templates/top.yaml
@@ -58,6 +58,10 @@
     type: number
     description: Number of gtw workers to deploy
     default: 0
+  frr_size:
+    type: number
+    description: Number of frr nodes to deploy
+    default: 0
   ntw_size:
     type: number
     description: Number of contrail nodes to deploy
@@ -197,6 +201,9 @@
   spare_metadata:
     type: json
     default: {}
+  frr_metadata:
+    type: json
+    default: {}
   ntw_metadata:
     type: json
     default: {}
@@ -230,6 +237,9 @@
   spares_flavor:
     type: string
     default: 'system.compact.openstack.control'
+  frrs_flavor:
+    type: string
+    default: 'system.compact.openstack.control'
   ntws_flavor:
     type: string
     default: 'system.compact.openstack.control'
@@ -659,6 +669,52 @@
           tun_subnet_id: { get_attr: [tun_network, tun_subnet_id] }
           hardware_metadata: { get_param: hardware_metadata}
 
+  frrs:  # spares for osds/cmps
+    type: OS::Heat::ResourceGroup
+    depends_on:
+     - ucp
+    properties:
+      count: { get_param: frr_size }
+      resource_def:
+        type: MCP2::SrvInstancesCephOSD
+        properties:
+          metadata: { get_param: frr_metadata }
+          node_type: "frr"
+          key_name: { get_attr: [keypair_name, value] }
+          image: { get_param: image }
+          flavor: { get_param: frrs_flavor }
+          docker_ee_url: { get_param: docker_ee_url }
+          docker_ee_release: { get_param: docker_ee_release }
+          docker_ucp_image: { get_param: docker_ucp_image}
+          docker_default_address_pool: { get_param: docker_default_address_pool }
+          accessible_network: { get_attr: [accessible_network, public_network] }
+          private_floating_network: { get_attr: [private_floating_network, private_floating_network_id] }
+          private_floating_subnet_id: { get_attr: [private_floating_network, private_floating_subnet_id] }
+          private_floating_interface: { get_param: private_floating_interface }
+          private_floating_network_cidr: { get_param: private_floating_network_cidr }
+          accessible_subnet_id: { get_attr: [accessible_network, accessible_subnet_id]}
+          public_net_id: { get_param: public_net_id }
+          control_network_cidr: { get_param: control_network_cidr }
+          ucp_master_host: { get_attr: [ucp, server_private_ip] }
+          functions_override: { get_param: functions_override }
+          storage_frontend_interface: { get_param: storage_frontend_interface }
+          storage_frontend_network: { get_attr: [storage_network, storage_frontend_network_id] }
+          storage_frontend_subnet_id: { get_attr: [storage_network, storage_frontend_subnet_id] }
+          storage_frontend_network_cidr: { get_param: storage_frontend_network_cidr }
+          storage_backend_interface: { get_param: storage_backend_interface }
+          storage_backend_network: { get_attr: [storage_network, storage_backend_network_id] }
+          storage_backend_subnet_id: { get_attr: [storage_network, storage_backend_subnet_id] }
+          storage_backend_network_cidr: { get_param: storage_backend_network_cidr }
+          ironic_baremetal_network: { get_attr: [ironic_baremetal_network, ironic_baremetal_network_id] }
+          ironic_baremetal_subnet_id: { get_attr: [ironic_baremetal_network, ironic_baremetal_subnet_id] }
+          ironic_baremetal_network_cidr: { get_param: ironic_baremetal_network_cidr }
+          ironic_baremetal_tunnel_cidr: { get_param: ironic_baremetal_tunnel_cidr }
+          ironic_mt_enabled: { get_param: ironic_mt_enabled }
+          tungstenfabric_enabled: { get_param: tungstenfabric_enabled }
+          tun_network: { get_attr: [tun_network, tun_network_id] }
+          tun_subnet_id: { get_attr: [tun_network, tun_subnet_id] }
+          hardware_metadata: { get_param: hardware_metadata}
+
   spares:  # spares for osds/cmps
     type: OS::Heat::ResourceGroup
     depends_on:
@@ -820,6 +876,12 @@
   vbmc_ironic_baremetal_ips:
     description: The IPs of ironic baremetal network assigned to vbmc hosts.
     value: { get_attr: [vbmcs, server_ironic_baremetal_ip] }
+  frrs_ips:
+    description: Private IP addresses of the deployed FRR instances
+    value: { get_attr: [frrs, server_public_ip] }
+  frrs_tunnel_ips:
+    description: The tunnel IPs of FRR nodes
+    value: { get_attr: [frrs, server_tunnel_ip] }
   worker_private_floating_ips:
     description: IPs might be used as gateway
     value: {if: [aio_deploy, {get_attr: [ucp, server_private_floating_ip]}, {get_attr: [workers, server_private_floating_ip]}]}