Skip to content

Commit 96f025a

Browse files
committed
Network L3 Router Commands
SDK implementation of L3 Agent commands which would allow for list, add, remove of routers to L3 Agents. Partially Implements: blueprint network-l3-commands Change-Id: Iab11cfae17153a64f09590b6577c3c800dec0266
1 parent 991b9eb commit 96f025a

File tree

7 files changed

+242
-0
lines changed

7 files changed

+242
-0
lines changed

openstack/network/v2/_proxy.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,62 @@ def remove_gateway_from_router(self, router, **body):
22552255
"""
22562256
return router.remove_gateway(self.session, **body)
22572257

2258+
def routers_hosting_l3_agents(self, router, **query):
2259+
"""Return a generator of L3 agent hosting a router
2260+
2261+
:param router: Either the router id or an instance of
2262+
:class:`~openstack.network.v2.router.Router`
2263+
:param kwargs \*\*query: Optional query parameters to be sent to limit
2264+
the resources returned
2265+
2266+
:returns: A generator of Router L3 Agents
2267+
:rtype: :class:`~openstack.network.v2.router.RouterL3Agents`
2268+
"""
2269+
router = self._get_resource(_router.Router, router)
2270+
return self._list(_agent.RouterL3Agent, paginated=False,
2271+
router_id=router.id, **query)
2272+
2273+
def agent_hosted_routers(self, agent, **query):
2274+
"""Return a generator of routers hosted by a L3 agent
2275+
2276+
:param agent: Either the agent id of an instance of
2277+
:class:`~openstack.network.v2.network_agent.Agent`
2278+
:param kwargs \*\*query: Optional query parameters to be sent to limit
2279+
the resources returned
2280+
2281+
:returns: A generator of routers
2282+
:rtype: :class:`~openstack.network.v2.agent.L3AgentRouters`
2283+
"""
2284+
agent = self._get_resource(_agent.Agent, agent)
2285+
return self._list(_router.L3AgentRouter, paginated=False,
2286+
agent_id=agent.id, **query)
2287+
2288+
def add_router_to_agent(self, agent, router):
2289+
"""Add router to L3 agent
2290+
2291+
:param agent: Either the id of an agent
2292+
:class:`~openstack.network.v2.agent.Agent` instance
2293+
:param router: A router instance
2294+
:returns: Agent with attached router
2295+
:rtype: :class:`~openstack.network.v2.agent.Agent`
2296+
"""
2297+
agent = self._get_resource(_agent.Agent, agent)
2298+
router = self._get_resource(_router.Router, router)
2299+
return agent.add_router_to_agent(self.session, router.id)
2300+
2301+
def remove_router_from_agent(self, agent, router):
2302+
"""Remove router from L3 agent
2303+
2304+
:param agent: Either the id of an agent or an
2305+
:class:`~openstack.network.v2.agent.Agent` instance
2306+
:param router: A router instance
2307+
:returns: Agent with removed router
2308+
:rtype: :class:`~openstack.network.v2.agent.Agent`
2309+
"""
2310+
agent = self._get_resource(_agent.Agent, agent)
2311+
router = self._get_resource(_router.Router, router)
2312+
return agent.remove_router_from_agent(self.session, router.id)
2313+
22582314
def create_security_group(self, **attrs):
22592315
"""Create a new security group from attributes
22602316

openstack/network/v2/agent.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ def remove_agent_from_network(self, session, **body):
7575
network_id)
7676
session.delete(url, endpoint_filter=self.service, json=body)
7777

78+
def add_router_to_agent(self, session, router):
79+
body = {'router_id': router}
80+
url = utils.urljoin(self.base_path, self.id, 'l3-routers')
81+
resp = session.post(url, endpoint_filter=self.service, json=body)
82+
return resp.json()
83+
84+
def remove_router_from_agent(self, session, router):
85+
body = {'router_id': router}
86+
url = utils.urljoin(self.base_path, self.id, 'l3-routers', router)
87+
session.delete(url, endpoint_filter=self.service, json=body)
88+
7889

7990
class NetworkHostingDHCPAgent(Agent):
8091
resource_key = 'agent'
@@ -91,3 +102,20 @@ class NetworkHostingDHCPAgent(Agent):
91102
allow_list = True
92103

93104
# NOTE: Doesn't support query yet.
105+
106+
107+
class RouterL3Agent(Agent):
108+
resource_key = 'agent'
109+
resources_key = 'agents'
110+
base_path = '/routers/%(router_id)s/l3-agents'
111+
resource_name = 'l3-agent'
112+
service = network_service.NetworkService()
113+
114+
# capabilities
115+
allow_create = False
116+
allow_retrieve = True
117+
allow_update = False
118+
allow_delete = False
119+
allow_list = True
120+
121+
# NOTE: No query parameter is supported

openstack/network/v2/router.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,20 @@ def remove_gateway(self, session, **body):
128128
'remove_gateway_router')
129129
resp = session.put(url, endpoint_filter=self.service, json=body)
130130
return resp.json()
131+
132+
133+
class L3AgentRouter(Router):
134+
resource_key = 'router'
135+
resources_key = 'routers'
136+
base_path = '/agents/%(agent_id)s/l3-routers'
137+
resource_name = 'l3-router'
138+
service = network_service.NetworkService()
139+
140+
# capabilities
141+
allow_create = False
142+
allow_retrieve = True
143+
allow_update = False
144+
allow_delete = False
145+
allow_list = True
146+
147+
# NOTE: No query parameter is supported
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import uuid
14+
15+
from openstack.network.v2 import router
16+
from openstack.tests.functional import base
17+
18+
19+
class TestAgentRouters(base.BaseFunctionalTest):
20+
21+
ROUTER_NAME = 'router-name-' + uuid.uuid4().hex
22+
ROUTER_ID = None
23+
AGENT = None
24+
AGENT_ID = None
25+
26+
@classmethod
27+
def setUpClass(cls):
28+
super(TestAgentRouters, cls).setUpClass()
29+
30+
rot = cls.conn.network.create_router(name=cls.ROUTER_NAME)
31+
assert isinstance(rot, router.Router)
32+
cls.ROUTER_ID = rot.id
33+
agent_list = list(cls.conn.network.agents())
34+
agents = [agent for agent in agent_list
35+
if agent.agent_type == 'L3 agent']
36+
cls.AGENT = agents[0]
37+
cls.AGENT_ID = cls.AGENT.id
38+
39+
@classmethod
40+
def tearDownClass(cls):
41+
rot = cls.conn.network.delete_router(cls.ROUTER_ID,
42+
ignore_missing=False)
43+
cls.assertIs(None, rot)
44+
45+
def test_add_router_to_agent(self):
46+
sot = self.AGENT.add_router_to_agent(self.conn.session,
47+
router_id=self.ROUTER_ID)
48+
self._verify_add(sot)
49+
50+
def test_remove_router_from_agent(self):
51+
sot = self.AGENT.remove_router_from_agent(self.conn.session,
52+
router_id=self.ROUTER_ID)
53+
self._verify_remove(sot)
54+
55+
def _verify_add(self, sot):
56+
rots = self.conn.network.agent_hosted_routers(self.AGENT_ID)
57+
routers = [router.id for router in rots]
58+
self.assertIn(self.ROUTER_ID, routers)
59+
60+
def _verify_remove(self, sot):
61+
rots = self.conn.network.agent_hosted_routers(self.AGENT_ID)
62+
routers = [router.id for router in rots]
63+
self.assertNotIn(self.ROUTER_ID, routers)

openstack/tests/unit/network/v2/test_agent.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,33 @@ def test_remove_agent_from_network(self):
8989
sess.delete.assert_called_with('agents/IDENTIFIER/dhcp-networks/',
9090
endpoint_filter=net.service, json=body)
9191

92+
def test_add_router_to_agent(self):
93+
# Add router to agent
94+
sot = agent.Agent(**EXAMPLE)
95+
response = mock.Mock()
96+
response.body = {'router_id': '1'}
97+
response.json = mock.Mock(return_value=response.body)
98+
sess = mock.Mock()
99+
sess.post = mock.Mock(return_value=response)
100+
router_id = '1'
101+
self.assertEqual(response.body,
102+
sot.add_router_to_agent(sess, router_id))
103+
body = {'router_id': router_id}
104+
url = 'agents/IDENTIFIER/l3-routers'
105+
sess.post.assert_called_with(url, endpoint_filter=sot.service,
106+
json=body)
107+
108+
def test_remove_router_from_agent(self):
109+
# Remove router from agent
110+
sot = agent.Agent(**EXAMPLE)
111+
sess = mock.Mock()
112+
router_id = {}
113+
self.assertIsNone(sot.remove_router_from_agent(sess, router_id))
114+
body = {'router_id': {}}
115+
116+
sess.delete.assert_called_with('agents/IDENTIFIER/l3-routers/',
117+
endpoint_filter=sot.service, json=body)
118+
92119

93120
class TestNetworkHostingDHCPAgent(testtools.TestCase):
94121

@@ -104,3 +131,19 @@ def test_basic(self):
104131
self.assertFalse(net.allow_update)
105132
self.assertFalse(net.allow_delete)
106133
self.assertTrue(net.allow_list)
134+
135+
136+
class TestRouterL3Agent(testtools.TestCase):
137+
138+
def test_basic(self):
139+
sot = agent.RouterL3Agent()
140+
self.assertEqual('agent', sot.resource_key)
141+
self.assertEqual('agents', sot.resources_key)
142+
self.assertEqual('/routers/%(router_id)s/l3-agents', sot.base_path)
143+
self.assertEqual('l3-agent', sot.resource_name)
144+
self.assertEqual('network', sot.service.service_type)
145+
self.assertFalse(sot.allow_create)
146+
self.assertTrue(sot.allow_retrieve)
147+
self.assertFalse(sot.allow_update)
148+
self.assertFalse(sot.allow_delete)
149+
self.assertTrue(sot.allow_list)

openstack/tests/unit/network/v2/test_proxy.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
QOS_RULE_ID = 'qos-rule-id-' + uuid.uuid4().hex
5656
NETWORK_ID = 'network-id-' + uuid.uuid4().hex
5757
AGENT_ID = 'agent-id-' + uuid.uuid4().hex
58+
ROUTER_ID = 'router-id-' + uuid.uuid4().hex
5859

5960

6061
class TestNetworkProxy(test_proxy_base2.TestProxyBase):
@@ -739,6 +740,24 @@ def test_routers(self):
739740
def test_router_update(self):
740741
self.verify_update(self.proxy.update_router, router.Router)
741742

743+
def test_router_hosting_l3_agents_list(self):
744+
self.verify_list(
745+
self.proxy.routers_hosting_l3_agents,
746+
agent.RouterL3Agent,
747+
paginated=False,
748+
method_kwargs={'router': ROUTER_ID},
749+
expected_kwargs={'router_id': ROUTER_ID},
750+
)
751+
752+
def test_agent_hosted_routers_list(self):
753+
self.verify_list(
754+
self.proxy.agent_hosted_routers,
755+
router.L3AgentRouter,
756+
paginated=False,
757+
method_kwargs={'agent': AGENT_ID},
758+
expected_kwargs={'agent_id': AGENT_ID},
759+
)
760+
742761
def test_security_group_create_attrs(self):
743762
self.verify_create(self.proxy.create_security_group,
744763
security_group.SecurityGroup)

openstack/tests/unit/network/v2/test_router.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,19 @@ def test_remove_router_gateway(self):
203203
url = 'routers/IDENTIFIER/remove_gateway_router'
204204
sess.put.assert_called_with(url, endpoint_filter=sot.service,
205205
json=body)
206+
207+
208+
class TestL3AgentRouters(testtools.TestCase):
209+
210+
def test_basic(self):
211+
sot = router.L3AgentRouter()
212+
self.assertEqual('router', sot.resource_key)
213+
self.assertEqual('routers', sot.resources_key)
214+
self.assertEqual('/agents/%(agent_id)s/l3-routers', sot.base_path)
215+
self.assertEqual('l3-router', sot.resource_name)
216+
self.assertEqual('network', sot.service.service_type)
217+
self.assertFalse(sot.allow_create)
218+
self.assertTrue(sot.allow_retrieve)
219+
self.assertFalse(sot.allow_update)
220+
self.assertFalse(sot.allow_delete)
221+
self.assertTrue(sot.allow_list)

0 commit comments

Comments
 (0)