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
This commit is contained in:
Ankur Gupta 2016-10-12 22:38:39 -05:00
parent 991b9ebb20
commit 96f025afce
7 changed files with 242 additions and 0 deletions

View File

@ -2255,6 +2255,62 @@ class Proxy(proxy2.BaseProxy):
"""
return router.remove_gateway(self.session, **body)
def routers_hosting_l3_agents(self, router, **query):
"""Return a generator of L3 agent hosting a router
:param router: Either the router id or an instance of
:class:`~openstack.network.v2.router.Router`
:param kwargs \*\*query: Optional query parameters to be sent to limit
the resources returned
:returns: A generator of Router L3 Agents
:rtype: :class:`~openstack.network.v2.router.RouterL3Agents`
"""
router = self._get_resource(_router.Router, router)
return self._list(_agent.RouterL3Agent, paginated=False,
router_id=router.id, **query)
def agent_hosted_routers(self, agent, **query):
"""Return a generator of routers hosted by a L3 agent
:param agent: Either the agent id of an instance of
:class:`~openstack.network.v2.network_agent.Agent`
:param kwargs \*\*query: Optional query parameters to be sent to limit
the resources returned
:returns: A generator of routers
:rtype: :class:`~openstack.network.v2.agent.L3AgentRouters`
"""
agent = self._get_resource(_agent.Agent, agent)
return self._list(_router.L3AgentRouter, paginated=False,
agent_id=agent.id, **query)
def add_router_to_agent(self, agent, router):
"""Add router to L3 agent
:param agent: Either the id of an agent
:class:`~openstack.network.v2.agent.Agent` instance
:param router: A router instance
:returns: Agent with attached router
:rtype: :class:`~openstack.network.v2.agent.Agent`
"""
agent = self._get_resource(_agent.Agent, agent)
router = self._get_resource(_router.Router, router)
return agent.add_router_to_agent(self.session, router.id)
def remove_router_from_agent(self, agent, router):
"""Remove router from L3 agent
:param agent: Either the id of an agent or an
:class:`~openstack.network.v2.agent.Agent` instance
:param router: A router instance
:returns: Agent with removed router
:rtype: :class:`~openstack.network.v2.agent.Agent`
"""
agent = self._get_resource(_agent.Agent, agent)
router = self._get_resource(_router.Router, router)
return agent.remove_router_from_agent(self.session, router.id)
def create_security_group(self, **attrs):
"""Create a new security group from attributes

View File

@ -75,6 +75,17 @@ class Agent(resource.Resource):
network_id)
session.delete(url, endpoint_filter=self.service, json=body)
def add_router_to_agent(self, session, router):
body = {'router_id': router}
url = utils.urljoin(self.base_path, self.id, 'l3-routers')
resp = session.post(url, endpoint_filter=self.service, json=body)
return resp.json()
def remove_router_from_agent(self, session, router):
body = {'router_id': router}
url = utils.urljoin(self.base_path, self.id, 'l3-routers', router)
session.delete(url, endpoint_filter=self.service, json=body)
class NetworkHostingDHCPAgent(Agent):
resource_key = 'agent'
@ -91,3 +102,20 @@ class NetworkHostingDHCPAgent(Agent):
allow_list = True
# NOTE: Doesn't support query yet.
class RouterL3Agent(Agent):
resource_key = 'agent'
resources_key = 'agents'
base_path = '/routers/%(router_id)s/l3-agents'
resource_name = 'l3-agent'
service = network_service.NetworkService()
# capabilities
allow_create = False
allow_retrieve = True
allow_update = False
allow_delete = False
allow_list = True
# NOTE: No query parameter is supported

View File

@ -128,3 +128,20 @@ class Router(resource.Resource):
'remove_gateway_router')
resp = session.put(url, endpoint_filter=self.service, json=body)
return resp.json()
class L3AgentRouter(Router):
resource_key = 'router'
resources_key = 'routers'
base_path = '/agents/%(agent_id)s/l3-routers'
resource_name = 'l3-router'
service = network_service.NetworkService()
# capabilities
allow_create = False
allow_retrieve = True
allow_update = False
allow_delete = False
allow_list = True
# NOTE: No query parameter is supported

View File

@ -0,0 +1,63 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from openstack.network.v2 import router
from openstack.tests.functional import base
class TestAgentRouters(base.BaseFunctionalTest):
ROUTER_NAME = 'router-name-' + uuid.uuid4().hex
ROUTER_ID = None
AGENT = None
AGENT_ID = None
@classmethod
def setUpClass(cls):
super(TestAgentRouters, cls).setUpClass()
rot = cls.conn.network.create_router(name=cls.ROUTER_NAME)
assert isinstance(rot, router.Router)
cls.ROUTER_ID = rot.id
agent_list = list(cls.conn.network.agents())
agents = [agent for agent in agent_list
if agent.agent_type == 'L3 agent']
cls.AGENT = agents[0]
cls.AGENT_ID = cls.AGENT.id
@classmethod
def tearDownClass(cls):
rot = cls.conn.network.delete_router(cls.ROUTER_ID,
ignore_missing=False)
cls.assertIs(None, rot)
def test_add_router_to_agent(self):
sot = self.AGENT.add_router_to_agent(self.conn.session,
router_id=self.ROUTER_ID)
self._verify_add(sot)
def test_remove_router_from_agent(self):
sot = self.AGENT.remove_router_from_agent(self.conn.session,
router_id=self.ROUTER_ID)
self._verify_remove(sot)
def _verify_add(self, sot):
rots = self.conn.network.agent_hosted_routers(self.AGENT_ID)
routers = [router.id for router in rots]
self.assertIn(self.ROUTER_ID, routers)
def _verify_remove(self, sot):
rots = self.conn.network.agent_hosted_routers(self.AGENT_ID)
routers = [router.id for router in rots]
self.assertNotIn(self.ROUTER_ID, routers)

View File

@ -89,6 +89,33 @@ class TestAgent(testtools.TestCase):
sess.delete.assert_called_with('agents/IDENTIFIER/dhcp-networks/',
endpoint_filter=net.service, json=body)
def test_add_router_to_agent(self):
# Add router to agent
sot = agent.Agent(**EXAMPLE)
response = mock.Mock()
response.body = {'router_id': '1'}
response.json = mock.Mock(return_value=response.body)
sess = mock.Mock()
sess.post = mock.Mock(return_value=response)
router_id = '1'
self.assertEqual(response.body,
sot.add_router_to_agent(sess, router_id))
body = {'router_id': router_id}
url = 'agents/IDENTIFIER/l3-routers'
sess.post.assert_called_with(url, endpoint_filter=sot.service,
json=body)
def test_remove_router_from_agent(self):
# Remove router from agent
sot = agent.Agent(**EXAMPLE)
sess = mock.Mock()
router_id = {}
self.assertIsNone(sot.remove_router_from_agent(sess, router_id))
body = {'router_id': {}}
sess.delete.assert_called_with('agents/IDENTIFIER/l3-routers/',
endpoint_filter=sot.service, json=body)
class TestNetworkHostingDHCPAgent(testtools.TestCase):
@ -104,3 +131,19 @@ class TestNetworkHostingDHCPAgent(testtools.TestCase):
self.assertFalse(net.allow_update)
self.assertFalse(net.allow_delete)
self.assertTrue(net.allow_list)
class TestRouterL3Agent(testtools.TestCase):
def test_basic(self):
sot = agent.RouterL3Agent()
self.assertEqual('agent', sot.resource_key)
self.assertEqual('agents', sot.resources_key)
self.assertEqual('/routers/%(router_id)s/l3-agents', sot.base_path)
self.assertEqual('l3-agent', sot.resource_name)
self.assertEqual('network', sot.service.service_type)
self.assertFalse(sot.allow_create)
self.assertTrue(sot.allow_retrieve)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)

View File

@ -55,6 +55,7 @@ QOS_POLICY_ID = 'qos-policy-id-' + uuid.uuid4().hex
QOS_RULE_ID = 'qos-rule-id-' + uuid.uuid4().hex
NETWORK_ID = 'network-id-' + uuid.uuid4().hex
AGENT_ID = 'agent-id-' + uuid.uuid4().hex
ROUTER_ID = 'router-id-' + uuid.uuid4().hex
class TestNetworkProxy(test_proxy_base2.TestProxyBase):
@ -739,6 +740,24 @@ class TestNetworkProxy(test_proxy_base2.TestProxyBase):
def test_router_update(self):
self.verify_update(self.proxy.update_router, router.Router)
def test_router_hosting_l3_agents_list(self):
self.verify_list(
self.proxy.routers_hosting_l3_agents,
agent.RouterL3Agent,
paginated=False,
method_kwargs={'router': ROUTER_ID},
expected_kwargs={'router_id': ROUTER_ID},
)
def test_agent_hosted_routers_list(self):
self.verify_list(
self.proxy.agent_hosted_routers,
router.L3AgentRouter,
paginated=False,
method_kwargs={'agent': AGENT_ID},
expected_kwargs={'agent_id': AGENT_ID},
)
def test_security_group_create_attrs(self):
self.verify_create(self.proxy.create_security_group,
security_group.SecurityGroup)

View File

@ -203,3 +203,19 @@ class TestRouter(testtools.TestCase):
url = 'routers/IDENTIFIER/remove_gateway_router'
sess.put.assert_called_with(url, endpoint_filter=sot.service,
json=body)
class TestL3AgentRouters(testtools.TestCase):
def test_basic(self):
sot = router.L3AgentRouter()
self.assertEqual('router', sot.resource_key)
self.assertEqual('routers', sot.resources_key)
self.assertEqual('/agents/%(agent_id)s/l3-routers', sot.base_path)
self.assertEqual('l3-router', sot.resource_name)
self.assertEqual('network', sot.service.service_type)
self.assertFalse(sot.allow_create)
self.assertTrue(sot.allow_retrieve)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)