# @author: Rossella Sblendido, Midokura Japan KK
# @author: Duarte Nunes, Midokura Japan KK
+import functools
+
from midonetclient import api
+from midonetclient import exc
+from midonetclient.neutron import client as n_client
from oslo.config import cfg
from sqlalchemy.orm import exc as sa_exc
+from webob import exc as w_exc
from neutron.api.v2 import attributes
from neutron.common import constants
SNAT_RULE = 'SNAT'
+def handle_api_error(fn):
+ """Wrapper for methods that throws custom exceptions."""
+ @functools.wraps(fn)
+ def wrapped(*args, **kwargs):
+ try:
+ return fn(*args, **kwargs)
+ except (w_exc.HTTPException, exc.MidoApiConnectionError) as ex:
+ raise MidonetApiException(msg=ex)
+ return wrapped
+
+
+class MidonetApiException(n_exc.NeutronException):
+ message = _("MidoNet API error: %(msg)s")
+
+
def _get_nat_ips(type, fip):
"""Get NAT IP address information.
self.provider_router_id = midonet_conf.provider_router_id
self.provider_router = None
+ self.api_cli = n_client.MidonetClient(midonet_conf.midonet_uri,
+ midonet_conf.username,
+ midonet_conf.password,
+ project_id=midonet_conf.project_id)
self.mido_api = api.MidonetApi(midonet_uri, admin_user,
admin_pass,
project_id=admin_project_id)
LOG.debug(_("MidonetPluginV2.delete_subnet exiting"))
+ @handle_api_error
def create_network(self, context, network):
"""Create Neutron network.
Create a new Neutron network and its corresponding MidoNet bridge.
"""
- LOG.debug(_('MidonetPluginV2.create_network called: network=%r'),
+ LOG.debug('MidonetPluginV2.create_network called: network=%r',
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(**net_data)
- net_data['id'] = bridge.get_id()
-
- session = context.session
- with session.begin(subtransactions=True):
+ with context.session.begin(subtransactions=True):
net = super(MidonetPluginV2, self).create_network(context, network)
self._process_l3_create(context, net, net_data)
+ self.api_cli.create_network(net)
- LOG.debug(_("MidonetPluginV2.create_network exiting: net=%r"), net)
+ LOG.debug("MidonetPluginV2.create_network exiting: net=%r", net)
return net
+ @handle_api_error
def update_network(self, context, id, network):
"""Update Neutron network.
Update an existing Neutron network and its corresponding MidoNet
bridge.
"""
- LOG.debug(_("MidonetPluginV2.update_network called: id=%(id)r, "
- "network=%(network)r"), {'id': id, 'network': network})
- session = context.session
- with session.begin(subtransactions=True):
+ LOG.debug("MidonetPluginV2.update_network called: id=%(id)r, "
+ "network=%(network)r", {'id': id, 'network': network})
+
+ with context.session.begin(subtransactions=True):
net = super(MidonetPluginV2, self).update_network(
context, id, network)
self._process_l3_update(context, net, network['network'])
- self.client.update_bridge(id, **network['network'])
+ self.api_cli.update_network(id, net)
- LOG.debug(_("MidonetPluginV2.update_network exiting: net=%r"), net)
+ LOG.debug("MidonetPluginV2.update_network exiting: net=%r", net)
return net
- def get_network(self, context, id, fields=None):
- """Get Neutron network.
-
- Retrieves a Neutron network and its corresponding MidoNet bridge.
- """
- LOG.debug(_("MidonetPluginV2.get_network called: id=%(id)r, "
- "fields=%(fields)r"), {'id': id, 'fields': fields})
- qnet = super(MidonetPluginV2, self).get_network(context, id, fields)
- self.client.get_bridge(id)
-
- LOG.debug(_("MidonetPluginV2.get_network exiting: qnet=%r"), qnet)
- return qnet
-
+ @handle_api_error
def delete_network(self, context, id):
"""Delete a network and its corresponding MidoNet bridge."""
- LOG.debug(_("MidonetPluginV2.delete_network called: id=%r"), id)
- self.client.delete_bridge(id)
- try:
- with context.session.begin(subtransactions=True):
- self._process_l3_delete(context, id)
- super(MidonetPluginV2, self).delete_network(context, id)
- except Exception:
- with excutils.save_and_reraise_exception():
- LOG.error(_('Failed to delete neutron db, while Midonet '
- 'bridge=%r had been deleted'), id)
+ LOG.debug("MidonetPluginV2.delete_network called: id=%r", id)
+
+ with context.session.begin(subtransactions=True):
+ self._process_l3_delete(context, id)
+ super(MidonetPluginV2, self).delete_network(context, id)
+ self.api_cli.delete_network(id)
+
+ LOG.debug("MidonetPluginV2.delete_network exiting: id=%r", id)
def create_port(self, context, port):
"""Create a L2 port in Neutron/MidoNet."""
self.instance = self.mock_api.start()
mock_cfg = mock_lib.MidonetLibMockConfig(self.instance.return_value)
mock_cfg.setup()
- super(MidonetPluginV2TestCase, self).setUp(plugin=plugin,
- ext_mgr=ext_mgr)
- def tearDown(self):
- super(MidonetPluginV2TestCase, self).tearDown()
- self.mock_api.stop()
+ self.midoclient_mock = mock.MagicMock()
+ self.midoclient_mock.midonetclient.neutron.client.return_value = True
+ modules = {
+ 'midonetclient': self.midoclient_mock,
+ 'midonetclient.neutron': self.midoclient_mock.neutron,
+ 'midonetclient.neutron.client': self.midoclient_mock.client,
+ }
+
+ self.module_patcher = mock.patch.dict('sys.modules', modules)
+ self.module_patcher.start()
+ self.addCleanup(self.module_patcher.stop)
+
+ # import midonetclient here because it needs proper mock objects to be
+ # assigned to this module first. 'midoclient_mock' object is the
+ # mock object used for this module.
+ from midonetclient.neutron.client import MidonetClient
+ client_class = MidonetClient
+ self.mock_class = client_class()
+
+ super(MidonetPluginV2TestCase, self).setUp(plugin=plugin)
class TestMidonetNetworksV2(test_plugin.TestNetworksV2,
None)
self.assertTrue(self.instance.return_value.add_static_nat.called)
+ def test_delete_ext_net_with_disassociated_floating_ips(self):
+ pass
+
class TestMidonetSecurityGroupsTestCase(sg.SecurityGroupDBTestCase):
p.start()
# dict patches must be explicitly stopped
self.addCleanup(p.stop)
+ self.midoclient_mock = mock.MagicMock()
+ self.midoclient_mock.midonetclient.neutron.client.return_value = True
+ modules = {
+ 'midonetclient': self.midoclient_mock,
+ 'midonetclient.neutron': self.midoclient_mock.neutron,
+ 'midonetclient.neutron.client': self.midoclient_mock.client,
+ }
+
+ self.module_patcher = mock.patch.dict('sys.modules', modules)
+ self.module_patcher.start()
+ self.addCleanup(self.module_patcher.stop)
+
+ # import midonetclient here because it needs proper mock objects to be
+ # assigned to this module first. 'midoclient_mock' object is the
+ # mock object used for this module.
+ from midonetclient.neutron.client import MidonetClient
+ client_class = MidonetClient
+ self.mock_class = client_class()
+
super(TestMidonetSecurityGroupsTestCase, self).setUp(self._plugin_name)