Merge "MidoNet: Added support for the admin_state_up flag"
This commit is contained in:
commit
c655156b98
@ -19,7 +19,7 @@
|
||||
# @author: Tomoe Sugihara, Midokura Japan KK
|
||||
# @author: Ryu Ishimoto, Midokura Japan KK
|
||||
# @author: Rossella Sblendido, Midokura Japan KK
|
||||
|
||||
# @author: Duarte Nunes, Midokura Japan KK
|
||||
|
||||
from midonetclient import exc
|
||||
from webob import exc as w_exc
|
||||
@ -55,19 +55,35 @@ class MidoClient:
|
||||
def __init__(self, mido_api):
|
||||
self.mido_api = mido_api
|
||||
|
||||
@classmethod
|
||||
def _fill_dto(cls, dto, fields):
|
||||
for field_name, field_value in fields.iteritems():
|
||||
# We assume the setters are named the
|
||||
# same way as the attributes themselves.
|
||||
try:
|
||||
getattr(dto, field_name)(field_value)
|
||||
except AttributeError:
|
||||
pass
|
||||
return dto
|
||||
|
||||
@classmethod
|
||||
def _create_dto(cls, dto, fields):
|
||||
return cls._fill_dto(dto, fields).create()
|
||||
|
||||
@classmethod
|
||||
def _update_dto(cls, dto, fields):
|
||||
return cls._fill_dto(dto, fields).update()
|
||||
|
||||
@handle_api_error
|
||||
def create_bridge(self, tenant_id, name):
|
||||
def create_bridge(self, **kwargs):
|
||||
"""Create a new bridge
|
||||
|
||||
:param tenant_id: id of tenant creating the bridge
|
||||
:param name: name of the bridge
|
||||
:param \**kwargs: configuration of the new bridge
|
||||
:returns: newly created bridge
|
||||
"""
|
||||
LOG.debug(_("MidoClient.create_bridge called: "
|
||||
"tenant_id=%(tenant_id)s, name=%(name)s"),
|
||||
{'tenant_id': tenant_id, 'name': name})
|
||||
return self.mido_api.add_bridge().name(name).tenant_id(
|
||||
tenant_id).create()
|
||||
"kwargs=%(kwargs)s"), {'kwargs': kwargs})
|
||||
return self._create_dto(self.mido_api.add_bridge(), kwargs)
|
||||
|
||||
@handle_api_error
|
||||
def delete_bridge(self, id):
|
||||
@ -92,17 +108,18 @@ class MidoClient:
|
||||
raise MidonetResourceNotFound(resource_type='Bridge', id=id)
|
||||
|
||||
@handle_api_error
|
||||
def update_bridge(self, id, name):
|
||||
"""Update a bridge of the given id with the new name
|
||||
def update_bridge(self, id, **kwargs):
|
||||
"""Update a bridge of the given id with the new fields
|
||||
|
||||
:param id: id of the bridge
|
||||
:param name: name of the bridge to set to
|
||||
:param \**kwargs: the fields to update and their values
|
||||
:returns: bridge object
|
||||
"""
|
||||
LOG.debug(_("MidoClient.update_bridge called: "
|
||||
"id=%(id)s, name=%(name)s"), {'id': id, 'name': name})
|
||||
"id=%(id)s, kwargs=%(kwargs)s"),
|
||||
{'id': id, 'kwargs': kwargs})
|
||||
try:
|
||||
return self.mido_api.get_bridge(id).name(name).update()
|
||||
return self._update_dto(self.mido_api.get_bridge(id), kwargs)
|
||||
except w_exc.HTTPNotFound:
|
||||
raise MidonetResourceNotFound(resource_type='Bridge', id=id)
|
||||
|
||||
@ -234,38 +251,53 @@ class MidoClient:
|
||||
raise MidonetResourceNotFound(resource_type='Port', id=id)
|
||||
|
||||
@handle_api_error
|
||||
def add_bridge_port(self, bridge):
|
||||
def add_bridge_port(self, bridge, **kwargs):
|
||||
"""Add a port on a bridge
|
||||
|
||||
:param bridge: Bridge to add a new port to
|
||||
:param bridge: bridge to add a new port to
|
||||
:param \**kwargs: configuration of the new port
|
||||
:returns: newly created port
|
||||
"""
|
||||
LOG.debug(_("MidoClient.add_bridge_port called: "
|
||||
"bridge=%(bridge)s"), {'bridge': bridge})
|
||||
return self.mido_api.add_bridge_port(bridge)
|
||||
"bridge=%(bridge)s, kwargs=%(kwargs)s"),
|
||||
{'bridge': bridge, 'kwargs': kwargs})
|
||||
return self._create_dto(self.mido_api.add_bridge_port(bridge), kwargs)
|
||||
|
||||
@handle_api_error
|
||||
def add_router_port(self, router, port_address=None,
|
||||
network_address=None, network_length=None):
|
||||
"""Add a new port to an existing router."""
|
||||
return self.mido_api.add_router_port(router,
|
||||
port_address=port_address,
|
||||
network_address=network_address,
|
||||
network_length=network_length)
|
||||
def update_port(self, id, **kwargs):
|
||||
"""Update a port of the given id with the new fields
|
||||
|
||||
:param id: id of the port
|
||||
:param \**kwargs: the fields to update and their values
|
||||
"""
|
||||
LOG.debug(_("MidoClient.update_port called: "
|
||||
"id=%(id)s, kwargs=%(kwargs)s"),
|
||||
{'id': id, 'kwargs': kwargs})
|
||||
try:
|
||||
return self._update_dto(self.mido_api.get_port(id), kwargs)
|
||||
except w_exc.HTTPNotFound:
|
||||
raise MidonetResourceNotFound(resource_type='Port', id=id)
|
||||
|
||||
@handle_api_error
|
||||
def create_router(self, tenant_id, name):
|
||||
def add_router_port(self, router, **kwargs):
|
||||
"""Add a new port to an existing router.
|
||||
|
||||
:param router: router to add a new port to
|
||||
:param \**kwargs: configuration of the new port
|
||||
:returns: newly created port
|
||||
"""
|
||||
return self._create_dto(self.mido_api.add_router_port(router), kwargs)
|
||||
|
||||
@handle_api_error
|
||||
def create_router(self, **kwargs):
|
||||
"""Create a new router
|
||||
|
||||
:param tenant_id: id of tenant creating the router
|
||||
:param name: name of the router
|
||||
:param \**kwargs: configuration of the new router
|
||||
:returns: newly created router
|
||||
"""
|
||||
LOG.debug(_("MidoClient.create_router called: "
|
||||
"tenant_id=%(tenant_id)s, name=%(name)s"),
|
||||
{'tenant_id': tenant_id, 'name': name})
|
||||
return self.mido_api.add_router().name(name).tenant_id(
|
||||
tenant_id).create()
|
||||
"kwargs=%(kwargs)s"), {'kwargs': kwargs})
|
||||
return self._create_dto(self.mido_api.add_router(), kwargs)
|
||||
|
||||
@handle_api_error
|
||||
def delete_router(self, id):
|
||||
@ -290,17 +322,18 @@ class MidoClient:
|
||||
raise MidonetResourceNotFound(resource_type='Router', id=id)
|
||||
|
||||
@handle_api_error
|
||||
def update_router(self, id, name):
|
||||
def update_router(self, id, **kwargs):
|
||||
"""Update a router of the given id with the new name
|
||||
|
||||
:param id: id of the router
|
||||
:param name: name of the router to set to
|
||||
:param \**kwargs: the fields to update and their values
|
||||
:returns: router object
|
||||
"""
|
||||
LOG.debug(_("MidoClient.update_router called: "
|
||||
"id=%(id)s, name=%(name)s"), {'id': id, 'name': name})
|
||||
"id=%(id)s, kwargs=%(kwargs)s"),
|
||||
{'id': id, 'kwargs': kwargs})
|
||||
try:
|
||||
return self.mido_api.get_router(id).name(name).update()
|
||||
return self._update_dto(self.mido_api.get_router(id), kwargs)
|
||||
except w_exc.HTTPNotFound:
|
||||
raise MidonetResourceNotFound(resource_type='Router', id=id)
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
# @author: Tomoe Sugihara, Midokura Japan KK
|
||||
# @author: Ryu Ishimoto, Midokura Japan KK
|
||||
# @author: Rossella Sblendido, Midokura Japan KK
|
||||
# @author: Duarte Nunes, Midokura Japan KK
|
||||
|
||||
from midonetclient import api
|
||||
from oslo.config import cfg
|
||||
@ -458,17 +459,18 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
"""
|
||||
LOG.debug(_('MidonetPluginV2.create_network called: network=%r'),
|
||||
network)
|
||||
tenant_id = self._get_tenant_id_for_create(context, network['network'])
|
||||
net_data = network['network']
|
||||
tenant_id = self._get_tenant_id_for_create(context, net_data)
|
||||
net_data['tenant_id'] = tenant_id
|
||||
self._ensure_default_security_group(context, tenant_id)
|
||||
|
||||
bridge = self.client.create_bridge(tenant_id,
|
||||
network['network']['name'])
|
||||
network['network']['id'] = bridge.get_id()
|
||||
bridge = self.client.create_bridge(**net_data)
|
||||
net_data['id'] = bridge.get_id()
|
||||
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
net = super(MidonetPluginV2, self).create_network(context, network)
|
||||
self._process_l3_create(context, net, network['network'])
|
||||
self._process_l3_create(context, net, net_data)
|
||||
|
||||
LOG.debug(_("MidonetPluginV2.create_network exiting: net=%r"), net)
|
||||
return net
|
||||
@ -486,7 +488,7 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
net = super(MidonetPluginV2, self).update_network(
|
||||
context, id, network)
|
||||
self._process_l3_update(context, net, network['network'])
|
||||
self.client.update_bridge(id, net['name'])
|
||||
self.client.update_bridge(id, **network['network'])
|
||||
|
||||
LOG.debug(_("MidonetPluginV2.update_network exiting: net=%r"), net)
|
||||
return net
|
||||
@ -524,8 +526,11 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
# port ID in Neutron.
|
||||
bridge = self.client.get_bridge(port_data["network_id"])
|
||||
tenant_id = bridge.get_tenant_id()
|
||||
bridge_port = self.client.add_bridge_port(bridge)
|
||||
asu = port_data.get("admin_state_up", True)
|
||||
bridge_port = self.client.add_bridge_port(bridge,
|
||||
admin_state_up=asu)
|
||||
port_data["id"] = bridge_port.get_id()
|
||||
|
||||
try:
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
@ -661,6 +666,17 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
# update the port DB
|
||||
p = super(MidonetPluginV2, self).update_port(context, id, port)
|
||||
|
||||
if "admin_state_up" in port["port"]:
|
||||
asu = port["port"]["admin_state_up"]
|
||||
mido_port = self.client.update_port(id, admin_state_up=asu)
|
||||
|
||||
# If we're changing the admin_state_up flag and the port is
|
||||
# associated with a router, then we also need to update the
|
||||
# peer port.
|
||||
if _is_router_interface_port(p):
|
||||
self.client.update_port(mido_port.get_peer_id(),
|
||||
admin_state_up=asu)
|
||||
|
||||
new_ips = p["fixed_ips"]
|
||||
if new_ips:
|
||||
bridge = self.client.get_bridge(net_id)
|
||||
@ -698,7 +714,7 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
|
||||
When a new Neutron router is created, its corresponding MidoNet router
|
||||
is also created. In MidoNet, this router is initialized with chains
|
||||
for inbuond and outbound traffic, which will be used to hold other
|
||||
for inbound and outbound traffic, which will be used to hold other
|
||||
chains that include various rules, such as NAT.
|
||||
|
||||
:param router: Router information provided to create a new router.
|
||||
@ -710,19 +726,17 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
# 3rd parties to specify IDs as we do with l2 plugin
|
||||
LOG.debug(_("MidonetPluginV2.create_router called: router=%(router)s"),
|
||||
{"router": router})
|
||||
tenant_id = self._get_tenant_id_for_create(context, router['router'])
|
||||
mido_router = self.client.create_router(tenant_id,
|
||||
router['router']['name'])
|
||||
r = router['router']
|
||||
tenant_id = self._get_tenant_id_for_create(context, r)
|
||||
r['tenant_id'] = tenant_id
|
||||
mido_router = self.client.create_router(**r)
|
||||
mido_router_id = mido_router.get_id()
|
||||
|
||||
try:
|
||||
r = router['router']
|
||||
has_gw_info = False
|
||||
if EXTERNAL_GW_INFO in r:
|
||||
has_gw_info = True
|
||||
gw_info = r[EXTERNAL_GW_INFO]
|
||||
del r[EXTERNAL_GW_INFO]
|
||||
tenant_id = self._get_tenant_id_for_create(context, r)
|
||||
gw_info = r.pop(EXTERNAL_GW_INFO)
|
||||
with context.session.begin(subtransactions=True):
|
||||
# pre-generate id so it will be available when
|
||||
# configuring external gw port
|
||||
@ -868,10 +882,7 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
chain_names['post-routing'],
|
||||
gw_ip, gw_port["id"], **props)
|
||||
|
||||
# Update the name if changed
|
||||
changed_name = router_data.get('name')
|
||||
if changed_name:
|
||||
self.client.update_router(id, changed_name)
|
||||
self.client.update_router(id, **router_data)
|
||||
|
||||
LOG.debug(_("MidonetPluginV2.update_router exiting: router=%r"), r)
|
||||
return r
|
||||
@ -945,12 +956,12 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
for port in bridge_ports_to_delete:
|
||||
self.client.delete_port(port.get_id())
|
||||
|
||||
def _link_bridge_to_router(self, router, bridge_port_id, net_addr, net_len,
|
||||
def _link_bridge_to_router(self, router, bridge_port, net_addr, net_len,
|
||||
gw_ip, metadata_gw_ip):
|
||||
router_port = self.client.add_router_port(
|
||||
router, port_address=gw_ip, network_address=net_addr,
|
||||
network_length=net_len)
|
||||
self.client.link(router_port, bridge_port_id)
|
||||
router, network_length=net_len, network_address=net_addr,
|
||||
port_address=gw_ip, admin_state_up=bridge_port['admin_state_up'])
|
||||
self.client.link(router_port, bridge_port['id'])
|
||||
self.client.add_router_route(router, type='Normal',
|
||||
src_network_addr='0.0.0.0',
|
||||
src_network_length=0,
|
||||
@ -999,7 +1010,7 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
net_addr, net_len = net_util.net_addr(cidr)
|
||||
router = self.client.get_router(router_id)
|
||||
|
||||
# Get the metadatat GW IP
|
||||
# Get the metadata GW IP
|
||||
metadata_gw_ip = None
|
||||
rport_qry = context.session.query(models_v2.Port)
|
||||
dhcp_ports = rport_qry.filter_by(
|
||||
@ -1011,7 +1022,9 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
LOG.warn(_("DHCP agent is not working correctly. No port "
|
||||
"to reach the Metadata server on this network"))
|
||||
# Link the router and the bridge
|
||||
self._link_bridge_to_router(router, info["port_id"], net_addr,
|
||||
port = super(MidonetPluginV2, self).get_port(context,
|
||||
info["port_id"])
|
||||
self._link_bridge_to_router(router, port, net_addr,
|
||||
net_len, subnet["gateway_ip"],
|
||||
metadata_gw_ip)
|
||||
except Exception:
|
||||
|
@ -21,21 +21,21 @@ import mock
|
||||
import uuid
|
||||
|
||||
|
||||
def get_bridge_mock(id=None, tenant_id='test-tenant', name='net'):
|
||||
def get_bridge_mock(id=None, **kwargs):
|
||||
if id is None:
|
||||
id = str(uuid.uuid4())
|
||||
|
||||
bridge = mock.Mock()
|
||||
bridge.get_id.return_value = id
|
||||
bridge.get_tenant_id.return_value = tenant_id
|
||||
bridge.get_name.return_value = name
|
||||
bridge.get_tenant_id.return_value = kwargs.get("tenant_id", "test-tenant")
|
||||
bridge.get_name.return_value = kwargs.get("name", "net")
|
||||
bridge.get_ports.return_value = []
|
||||
bridge.get_peer_ports.return_value = []
|
||||
bridge.get_admin_state_up.return_value = kwargs.get("admin_state_up", True)
|
||||
return bridge
|
||||
|
||||
|
||||
def get_bridge_port_mock(id=None, bridge_id=None,
|
||||
type='ExteriorBridge'):
|
||||
def get_bridge_port_mock(id=None, bridge_id=None, **kwargs):
|
||||
if id is None:
|
||||
id = str(uuid.uuid4())
|
||||
if bridge_id is None:
|
||||
@ -43,8 +43,10 @@ def get_bridge_port_mock(id=None, bridge_id=None,
|
||||
|
||||
port = mock.Mock()
|
||||
port.get_id.return_value = id
|
||||
port.get_brige_id.return_value = bridge_id
|
||||
port.get_type.return_value = type
|
||||
port.get_bridge_id.return_value = bridge_id
|
||||
port.get_admin_state_up.return_value = kwargs.get("admin_state_up", True)
|
||||
port.get_type.return_value = "Bridge"
|
||||
port.create.return_value = port
|
||||
return port
|
||||
|
||||
|
||||
@ -75,17 +77,18 @@ def get_port_group_mock(id=None, tenant_id='test-tenant', name='pg'):
|
||||
return port_group
|
||||
|
||||
|
||||
def get_router_mock(id=None, tenant_id='test-tenant', name='router'):
|
||||
def get_router_mock(id=None, **kwargs):
|
||||
if id is None:
|
||||
id = str(uuid.uuid4())
|
||||
|
||||
router = mock.Mock()
|
||||
router.get_id.return_value = id
|
||||
router.get_tenant_id.return_value = tenant_id
|
||||
router.get_name.return_value = name
|
||||
router.get_tenant_id.return_value = kwargs.get("tenant_id", "test-tenant")
|
||||
router.get_name.return_value = kwargs.get("name", "router")
|
||||
router.get_ports.return_value = []
|
||||
router.get_peer_ports.return_value = []
|
||||
router.get_routes.return_value = []
|
||||
router.get_admin_state_up.return_value = kwargs.get("admin_state_up", True)
|
||||
return router
|
||||
|
||||
|
||||
@ -125,19 +128,19 @@ class MidonetLibMockConfig():
|
||||
def __init__(self, inst):
|
||||
self.inst = inst
|
||||
|
||||
def _create_bridge(self, tenant_id, name):
|
||||
return get_bridge_mock(tenant_id=tenant_id, name=name)
|
||||
def _create_bridge(self, **kwargs):
|
||||
return get_bridge_mock(**kwargs)
|
||||
|
||||
def _create_router(self, tenant_id, name):
|
||||
return get_router_mock(tenant_id=tenant_id, name=name)
|
||||
def _create_router(self, **kwargs):
|
||||
return get_router_mock(**kwargs)
|
||||
|
||||
def _create_subnet(self, bridge, gateway_ip, subnet_prefix, subnet_len):
|
||||
return get_subnet_mock(bridge.get_id(), gateway_ip=gateway_ip,
|
||||
subnet_prefix=subnet_prefix,
|
||||
subnet_len=subnet_len)
|
||||
|
||||
def _add_bridge_port(self, bridge):
|
||||
return get_bridge_port_mock(bridge_id=bridge.get_id())
|
||||
def _add_bridge_port(self, bridge, **kwargs):
|
||||
return get_bridge_port_mock(bridge_id=bridge.get_id(), **kwargs)
|
||||
|
||||
def _get_bridge(self, id):
|
||||
return get_bridge_mock(id=id)
|
||||
@ -148,8 +151,8 @@ class MidonetLibMockConfig():
|
||||
def _get_router(self, id):
|
||||
return get_router_mock(id=id)
|
||||
|
||||
def _update_bridge(self, id, name):
|
||||
return get_bridge_mock(id=id, name=name)
|
||||
def _update_bridge(self, id, **kwargs):
|
||||
return get_bridge_mock(id=id, **kwargs)
|
||||
|
||||
def setup(self):
|
||||
# Bridge methods side effects
|
||||
@ -250,9 +253,13 @@ class MidoClientMockConfig():
|
||||
def _get_router(self, id):
|
||||
return get_router_mock(id=id)
|
||||
|
||||
def _add_bridge_port(self, bridge):
|
||||
return get_bridge_port_mock(bridge_id=bridge.get_id())
|
||||
|
||||
def setup(self):
|
||||
self.inst.get_bridge.side_effect = self._get_bridge
|
||||
self.inst.get_chains.side_effect = self._get_chains
|
||||
self.inst.get_chain.side_effect = self._get_chain
|
||||
self.inst.get_port_groups.side_effect = self._get_port_groups
|
||||
self.inst.get_router.side_effect = self._get_router
|
||||
self.inst.add_bridge_port.side_effect = self._add_bridge_port
|
||||
|
@ -166,3 +166,25 @@ class MidoClientTestCase(testtools.TestCase):
|
||||
|
||||
self.assertIsNotNone(bridge)
|
||||
self.assertEqual(bridge.get_id(), bridge_id)
|
||||
self.assertTrue(bridge.get_admin_state_up())
|
||||
|
||||
def test_add_bridge_port(self):
|
||||
bridge_id = uuidutils.generate_uuid()
|
||||
|
||||
bridge = self.client.get_bridge(bridge_id)
|
||||
|
||||
self.assertIsNotNone(bridge)
|
||||
|
||||
port = self.client.add_bridge_port(bridge)
|
||||
|
||||
self.assertEqual(bridge.get_id(), port.get_bridge_id())
|
||||
self.assertTrue(port.get_admin_state_up())
|
||||
|
||||
def test_get_router(self):
|
||||
router_id = uuidutils.generate_uuid()
|
||||
|
||||
router = self.client.get_router(router_id)
|
||||
|
||||
self.assertIsNotNone(router)
|
||||
self.assertEqual(router.get_id(), router_id)
|
||||
self.assertTrue(router.get_admin_state_up())
|
||||
|
Loading…
Reference in New Issue
Block a user