Add BGP VPN Interconnection Service

The service aims at supporting inter-connection between L3VPNs
and Neutron resources, i.e. Networks, Routers and Ports.
The framework is generic to also support E-VPN [RFC7432],
which inherits the same protocol architecture as BGP/MPLS IP VPNs.

Related-Prod: PROD-17612
Change-Id: I236016669160f5bc6b52d5563b6471be820ec271
diff --git a/.kitchen.yml b/.kitchen.yml
index 0bd9fa3..843d75e 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -98,6 +98,11 @@
       pillars-from-files:
         neutron.sls: tests/pillar/compute_ovn.sls
 
+  - name: compute_bgpvpn
+    provisioner:
+      pillars-from-files:
+        neutron.sls: tests/pillar/compute_bgpvpn.sls
+
   - name: control_cluster
     provisioner:
       pillars-from-files:
@@ -143,6 +148,11 @@
       pillars-from-files:
         neutron.sls: tests/pillar/control_ovn.sls
 
+  - name: control_bgpvpn
+    provisioner:
+      pillars-from-files:
+        neutron.sls: tests/pillar/control_bgpvpn.sls
+
   - name: gateway_dvr
     provisioner:
       pillars-from-files:
diff --git a/README.rst b/README.rst
index afcc972..0209dd6 100644
--- a/README.rst
+++ b/README.rst
@@ -747,6 +747,28 @@
       gateway:
         vlan_aware_vms: true
 
+Neutron with BGP VPN
+---------------------------
+
+.. code-block:: yaml
+
+    neutron:
+      server:
+        version: pike
+        bgp_vpn:
+          enabled: false
+          driver: bagpipe # Options: bagpipe/opencontrail/opendaylight
+      ....
+      compute:
+        version: pike
+        bgp_vpn:
+          enabled: false
+          driver: bagpipe # Options: bagpipe/opencontrail/opendaylight
+        backend:
+          extension:
+            bagpipe_bgpvpn:
+              enabled: True
+
 Neutron with DHCP agent on compute node
 ---------------------------------------
 
diff --git a/metadata/service/compute/single.yml b/metadata/service/compute/single.yml
index 3c14765..96f4268 100644
--- a/metadata/service/compute/single.yml
+++ b/metadata/service/compute/single.yml
@@ -26,6 +26,9 @@
       security_groups_enabled: true
       qos: false
       vlan_aware_vms: false
+      bgp_vpn:
+        enabled: false
+        driver: bagpipe
       metadata:
         host: ${_param:cluster_vip_address}
         password: ${_param:metadata_password}
diff --git a/metadata/service/control/cluster.yml b/metadata/service/control/cluster.yml
index 7f024c1..33ddaa2 100644
--- a/metadata/service/control/cluster.yml
+++ b/metadata/service/control/cluster.yml
@@ -13,6 +13,9 @@
       enabled: true
       dns_domain: novalocal
       vlan_aware_vms: false
+      bgp_vpn:
+        enabled: false
+        driver: bagpipe
       version: ${_param:neutron_version}
       controller_vip: ${_param:cluster_vip_address}
       bind:
diff --git a/metadata/service/control/single.yml b/metadata/service/control/single.yml
index d0ee1c5..939856c 100644
--- a/metadata/service/control/single.yml
+++ b/metadata/service/control/single.yml
@@ -17,6 +17,9 @@
       security_groups_enabled: true
       qos: false
       vlan_aware_vms: false
+      bgp_vpn:
+        enabled: false
+        driver: bagpipe
       version: ${_param:neutron_version}
       controller_vip: ${_param:single_address}
       bind:
diff --git a/neutron/compute.sls b/neutron/compute.sls
index 22cc29a..f003a57 100644
--- a/neutron/compute.sls
+++ b/neutron/compute.sls
@@ -6,6 +6,14 @@
   pkg.installed:
   - names: {{ compute.pkgs }}
 
+{% if compute.get('bgp_vpn', {}).get('enabled', False) %}
+{% if compute.bgp_vpn.driver == "bagpipe" %}
+bagpipe_packages:
+  pkg.installed:
+  - names: {{ compute.pkgs_bagpipe }}
+{% endif %}
+{% endif %}
+
 /etc/neutron/neutron.conf:
   file.managed:
   - source: salt://neutron/files/{{ compute.version }}/neutron-generic.conf.{{ grains.os_family }}
diff --git a/neutron/files/pike/neutron-server.conf.Debian b/neutron/files/pike/neutron-server.conf.Debian
index 99651bc..6164875 100644
--- a/neutron/files/pike/neutron-server.conf.Debian
+++ b/neutron/files/pike/neutron-server.conf.Debian
@@ -56,6 +56,7 @@
 {%- if server.get('qos', 'True') -%},neutron.services.qos.qos_plugin.QoSPlugin{%- endif -%}
 {%- if server.get('vlan_aware_vms', False) -%},trunk{%- endif -%}
 {%- if server.l2gw is defined and server.l2gw.get('enabled', False) -%},networking_l2gw.services.l2gateway.plugin.L2GatewayPlugin{%- endif -%}
+{%- if server.get('bgp_vpn', {}).get('enabled', False) -%},bgpvpn{%- endif -%}
 
 {% endif %}
 
@@ -2202,6 +2203,23 @@
 #ciphers = <None>
 [service_providers]
 
+{% if server.get('bgp_vpn', {}).get('enabled', False) -%}
+
+{%- if server.bgp_vpn.driver == "bagpipe" -%}
+
+service_provider = BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe.BaGPipeBGPVPNDriver:default
+
+{%- elif server.bgp_vpn.driver == "opencontrail" -%}
+
+service_provider = BGPVPN:OpenContrail:networking_bgpvpn.neutron.services.service_drivers.opencontrail.opencontrail.OpenContrailBGPVPNDriver:default
+
+{%- elif server.bgp_vpn.driver == "opendaylight" -%}
+
+service_provider = BGPVPN:OpenDaylight:networking_bgpvpn.neutron.services.service_drivers.opendaylight.odl.OpenDaylightBgpvpnDriver:default
+
+{%- endif -%}
+{%- endif -%}
+
 {% if server.lbaas is defined -%}
 
 {%- if server.lbaas.enabled -%}
diff --git a/neutron/map.jinja b/neutron/map.jinja
index 72f0171..19b19c2 100644
--- a/neutron/map.jinja
+++ b/neutron/map.jinja
@@ -10,6 +10,7 @@
     'Debian': {
         'pkgs': ['neutron-openvswitch-agent', 'openvswitch-switch', 'python-pycadf'],
         'pkgs_ovn': ['ovn-common', 'ovn-host'],
+        'pkgs_bagpipe': ['python-networking-bagpipe'],
         'services': ['neutron-openvswitch-agent'],
         'services_ovn': ['ovn-host'],
         'dpdk': false,
@@ -28,6 +29,7 @@
     'RedHat': {
         'pkgs': ['openstack-neutron-openvswitch', 'openvswitch', 'python-pycadf'],
         'pkgs_ovn': ['openvswitch-ovn'],
+        'pkgs_bagpipe': ['python-networking-bagpipe'],
         'services': ['neutron-openvswitch-agent'],
         'services_ovn': ['ovn-host'],
         'dpdk': false,
@@ -84,6 +86,8 @@
         'pkgs_ovn': ['python-networking-ovn', 'ovn-common', 'ovn-central'],
         'pkgs_ml2': ['neutron-plugin-ml2'],
         'pkgs_l2gw': ['python-networking-l2gw'],
+        'pkgs_bgpvpn': ['python-networking-bgpvpn'],
+        'pkgs_bagpipe': ['python-networking-bagpipe'],
         'services': ['neutron-server'],
         'services_ovn': ['ovn-central'],
         'notification': False,
@@ -106,6 +110,8 @@
         'pkgs': ['openstack-neutron'],
         'pkgs_ovn': ['openvswitch-ovn', 'python-networking-ovn'],
         'pkgs_l2gw': ['python2-networking-l2gw'],
+        'pkgs_bgpvpn': ['python-networking-bgpvpn'],
+        'pkgs_bagpipe': ['python-networking-bagpipe'],
         'services': ['neutron-server'],
         'services_ovn': ['ovn-central'],
         'notification': False,
diff --git a/neutron/server.sls b/neutron/server.sls
index 058d535..92aa61e 100644
--- a/neutron/server.sls
+++ b/neutron/server.sls
@@ -319,6 +319,29 @@
 {%- endif %}
 {%- endif %}
 
+{% if server.get('bgp_vpn', {}).get('enabled', False) %}
+
+bgpvpn_packages:
+  pkg.installed:
+  - names: {{ server.pkgs_bgpvpn }}
+
+bgpvpn_db_manage:
+  cmd.run:
+  - name: neutron-db-manage --config-file /etc/neutron/neutron.conf --subproject networking-bgpvpn upgrade head
+  - require:
+    - file: /etc/neutron/neutron.conf
+    - pkg: bgpvpn_packages
+
+{% if server.bgp_vpn.driver == "bagpipe" %}
+
+bagpipe_packages:
+  pkg.installed:
+  - names: {{ server.pkgs_bagpipe }}
+
+{% endif %}
+
+{% endif %}
+
 neutron_server_services:
   service.running:
   - names: {{ server.services }}
diff --git a/tests/pillar/compute_bgpvpn.sls b/tests/pillar/compute_bgpvpn.sls
new file mode 100644
index 0000000..b4aaaba
--- /dev/null
+++ b/tests/pillar/compute_bgpvpn.sls
@@ -0,0 +1,21 @@
+include:
+  - .compute_legacy
+
+neutron:
+  compute:
+    version: pike
+    bgp_vpn:
+      enabled: true
+      driver: bagpipe
+    backend:
+      extension:
+        bagpipe_bgpvpn:
+          enabled: True
+linux:
+  system:
+    enabled: true
+    repo:
+      mirantis_openstack_pike:
+        source: "deb http://mirror.fuel-infra.org/mcp-repos/pike/xenial pike main"
+        architectures: amd64
+        key_url: "http://mirror.fuel-infra.org/mcp-repos/pike/xenial/archive-mcppike.key"
\ No newline at end of file
diff --git a/tests/pillar/control_bgpvpn.sls b/tests/pillar/control_bgpvpn.sls
new file mode 100644
index 0000000..d7b4d16
--- /dev/null
+++ b/tests/pillar/control_bgpvpn.sls
@@ -0,0 +1,17 @@
+include:
+  - .control_nodvr
+
+neutron:
+  server:
+    version: pike
+    bgp_vpn:
+      enabled: true
+      driver: bagpipe
+linux:
+  system:
+    enabled: true
+    repo:
+      mirantis_openstack_pike:
+        source: "deb http://mirror.fuel-infra.org/mcp-repos/pike/xenial pike main"
+        architectures: amd64
+        key_url: "http://mirror.fuel-infra.org/mcp-repos/pike/xenial/archive-mcppike.key"
\ No newline at end of file