Add BGP Dynamic Routing DB Model and Basic CRUD

This patch enables basic CRUD on BGP dynamic routing
entities bgp_speaker and bgp_peer, as well as
bgp_speaker-bgp_peer and bgp_speaker-network
bindings.

An admin user can create BgpSpeakers and configure
peering entities (BgpPeers) for BgpSpeakers. BgpSpeaker
to BgpPeer association is n-to-n. An admin user can
also associate networks with BgpSpeakers. Relationship
between BgpSpeaker and Network is 1-to-n.

This patch provides BGP-related functionality only to
the admin users.

Partially-Implements: blueprint bgp-dynamic-routing
Co-Authored-By: Ryan Tidwell <ryan.tidwell@hpe.com>
Co-Authored-By: Jaume Devesa <devvesa@gmail.com>
Co-Authored-By: vikram.choudhary <vikram.choudhary@huawei.com>
Change-Id: I2412c1689683da9d7ec884a4cea506d4eed99453
diff --git a/neutron/tests/tempest/services/network/json/network_client.py b/neutron/tests/tempest/services/network/json/network_client.py
index d7c1656..61bd85f 100644
--- a/neutron/tests/tempest/services/network/json/network_client.py
+++ b/neutron/tests/tempest/services/network/json/network_client.py
@@ -48,6 +48,8 @@
         # the following map is used to construct proper URI
         # for the given neutron resource
         service_resource_prefix_map = {
+            'bgp-peers': '',
+            'bgp-speakers': '',
             'networks': '',
             'subnets': '',
             'subnetpools': '',
@@ -220,6 +222,109 @@
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, body)
 
+    # BGP speaker methods
+    def create_bgp_speaker(self, post_data):
+        body = self.serialize_list(post_data, "bgp-speakers", "bgp-speaker")
+        uri = self.get_uri("bgp-speakers")
+        resp, body = self.post(uri, body)
+        body = {'bgp-speaker': self.deserialize_list(body)}
+        self.expected_success(201, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def get_bgp_speaker(self, id):
+        uri = self.get_uri("bgp-speakers")
+        bgp_speaker_uri = '%s/%s' % (uri, id)
+        resp, body = self.get(bgp_speaker_uri)
+        body = {'bgp-speaker': self.deserialize_list(body)}
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def get_bgp_speakers(self):
+        uri = self.get_uri("bgp-speakers")
+        resp, body = self.get(uri)
+        body = {'bgp-speakers': self.deserialize_list(body)}
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def update_bgp_speaker(self, id, put_data):
+        body = self.serialize_list(put_data, "bgp-speakers", "bgp-speaker")
+        uri = self.get_uri("bgp-speakers")
+        bgp_speaker_uri = '%s/%s' % (uri, id)
+        resp, body = self.put(bgp_speaker_uri, body)
+        body = {'bgp-speaker': self.deserialize_list(body)}
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_bgp_speaker(self, id):
+        uri = self.get_uri("bgp-speakers")
+        bgp_speaker_uri = '%s/%s' % (uri, id)
+        resp, body = self.delete(bgp_speaker_uri)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def create_bgp_peer(self, post_data):
+        body = self.serialize_list(post_data, "bgp-peers", "bgp-peer")
+        uri = self.get_uri("bgp-peers")
+        resp, body = self.post(uri, body)
+        body = {'bgp-peer': self.deserialize_list(body)}
+        self.expected_success(201, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def get_bgp_peer(self, id):
+        uri = self.get_uri("bgp-peers")
+        bgp_speaker_uri = '%s/%s' % (uri, id)
+        resp, body = self.get(bgp_speaker_uri)
+        body = {'bgp-peer': self.deserialize_list(body)}
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_bgp_peer(self, id):
+        uri = self.get_uri("bgp-peers")
+        bgp_speaker_uri = '%s/%s' % (uri, id)
+        resp, body = self.delete(bgp_speaker_uri)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def add_bgp_peer_with_id(self, bgp_speaker_id, bgp_peer_id):
+        uri = '%s/bgp-speakers/%s/add_bgp_peer' % (self.uri_prefix,
+                                                   bgp_speaker_id)
+        update_body = {"bgp_peer_id": bgp_peer_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def remove_bgp_peer_with_id(self, bgp_speaker_id, bgp_peer_id):
+        uri = '%s/bgp-speakers/%s/remove_bgp_peer' % (self.uri_prefix,
+                                                      bgp_speaker_id)
+        update_body = {"bgp_peer_id": bgp_peer_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def add_bgp_gateway_network(self, bgp_speaker_id, network_id):
+        uri = '%s/bgp-speakers/%s/add_gateway_network' % (self.uri_prefix,
+                                                        bgp_speaker_id)
+        update_body = {"network_id": network_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def remove_bgp_gateway_network(self, bgp_speaker_id, network_id):
+        uri = '%s/bgp-speakers/%s/remove_gateway_network'
+        uri = uri % (self.uri_prefix, bgp_speaker_id)
+        update_body = {"network_id": network_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
     # Common methods that are hard to automate
     def create_bulk_network(self, names, shared=False):
         network_list = [{'name': name, 'shared': shared} for name in names]