
Refactor plugin.py and midonet_lib.py to improve unit testing of the MidoNet plugin. Make all the tests pass in the plugin except those that test features that are not currently supported by the plugin, which are IPv6 and multiple subnets per network. Consolidate the mocking code in mock_lib.py to be shared by plugin.py and midonet_lib.py. Change-Id: Idcdfc3d90d5ec9e0be29bb6833d336af596fe363 Fixes: bug #1133215 Signed-off-by: Ryu Ishimoto <ryu@midokura.com> Signed-off-by: Tomoe Sugihara <tomoe@midokura.com>
675 lines
29 KiB
Python
675 lines
29 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright (C) 2012 Midokura Japan K.K.
|
|
# Copyright (C) 2013 Midokura PTE LTD
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
#
|
|
# @author: Takaaki Suzuki, Midokura Japan KK
|
|
# @author: Tomoe Sugihara, Midokura Japan KK
|
|
# @author: Ryu Ishimoto, Midokura Japan KK
|
|
|
|
from midonetclient import api
|
|
from oslo.config import cfg
|
|
|
|
from quantum.common import exceptions as q_exc
|
|
from quantum.db import api as db
|
|
from quantum.db import db_base_plugin_v2
|
|
from quantum.db import l3_db
|
|
from quantum.db import models_v2
|
|
from quantum.db import securitygroups_db
|
|
from quantum.extensions import securitygroup as ext_sg
|
|
from quantum.openstack.common import log as logging
|
|
from quantum.plugins.midonet import config # noqa
|
|
from quantum.plugins.midonet import midonet_lib
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class MidonetPluginException(q_exc.QuantumException):
|
|
message = _("%(msg)s")
|
|
|
|
|
|
class MidonetPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
|
l3_db.L3_NAT_db_mixin,
|
|
securitygroups_db.SecurityGroupDbMixin):
|
|
|
|
supported_extension_aliases = ['router', 'security-group']
|
|
__native_bulk_support = False
|
|
|
|
def __init__(self):
|
|
|
|
# Read config values
|
|
midonet_conf = cfg.CONF.MIDONET
|
|
midonet_uri = midonet_conf.midonet_uri
|
|
admin_user = midonet_conf.username
|
|
admin_pass = midonet_conf.password
|
|
admin_project_id = midonet_conf.project_id
|
|
provider_router_id = midonet_conf.provider_router_id
|
|
metadata_router_id = midonet_conf.metadata_router_id
|
|
mode = midonet_conf.mode
|
|
|
|
self.mido_api = api.MidonetApi(midonet_uri, admin_user,
|
|
admin_pass,
|
|
project_id=admin_project_id)
|
|
self.client = midonet_lib.MidoClient(self.mido_api)
|
|
|
|
if provider_router_id and metadata_router_id:
|
|
# get MidoNet provider router and metadata router
|
|
self.provider_router = self.client.get_router(provider_router_id)
|
|
self.metadata_router = self.client.get_router(metadata_router_id)
|
|
|
|
elif not provider_router_id or not metadata_router_id:
|
|
if mode == 'dev':
|
|
msg = _('No provider router and metadata device ids found. '
|
|
'But skipping because running in dev env.')
|
|
LOG.debug(msg)
|
|
else:
|
|
msg = _('provider_router_id and metadata_router_id '
|
|
'should be configured in the plugin config file')
|
|
LOG.exception(msg)
|
|
raise MidonetPluginException(msg=msg)
|
|
|
|
db.configure_db()
|
|
|
|
def create_subnet(self, context, subnet):
|
|
"""Create Quantum subnet.
|
|
|
|
Creates a Quantum subnet and a DHCP entry in MidoNet bridge.
|
|
"""
|
|
LOG.debug(_("MidonetPluginV2.create_subnet called: subnet=%r"), subnet)
|
|
|
|
if subnet['subnet']['ip_version'] == 6:
|
|
raise q_exc.NotImplementedError(
|
|
_("MidoNet doesn't support IPv6."))
|
|
|
|
net = super(MidonetPluginV2, self).get_network(
|
|
context, subnet['subnet']['network_id'], fields=None)
|
|
if net['subnets']:
|
|
raise q_exc.NotImplementedError(
|
|
_("MidoNet doesn't support multiple subnets "
|
|
"on the same network."))
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
sn_entry = super(MidonetPluginV2, self).create_subnet(context,
|
|
subnet)
|
|
bridge = self.client.get_bridge(sn_entry['network_id'])
|
|
|
|
gateway_ip = subnet['subnet']['gateway_ip']
|
|
network_address, prefix = subnet['subnet']['cidr'].split('/')
|
|
self.client.create_dhcp(bridge, gateway_ip, network_address,
|
|
prefix)
|
|
|
|
# For external network, link the bridge to the provider router.
|
|
self._extend_network_dict_l3(context, net)
|
|
if net['router:external']:
|
|
gateway_ip = sn_entry['gateway_ip']
|
|
network_address, length = sn_entry['cidr'].split('/')
|
|
|
|
self.client.link_bridge_to_provider_router(
|
|
bridge, self.provider_router, gateway_ip, network_address,
|
|
length)
|
|
|
|
LOG.debug(_("MidonetPluginV2.create_subnet exiting: sn_entry=%r"),
|
|
sn_entry)
|
|
return sn_entry
|
|
|
|
def delete_subnet(self, context, id):
|
|
"""Delete Quantum subnet.
|
|
|
|
Delete quantum network and its corresponding MidoNet bridge.
|
|
"""
|
|
LOG.debug(_("MidonetPluginV2.delete_subnet called: id=%s"), id)
|
|
subnet = super(MidonetPluginV2, self).get_subnet(context, id,
|
|
fields=None)
|
|
net = super(MidonetPluginV2, self).get_network(context,
|
|
subnet['network_id'],
|
|
fields=None)
|
|
bridge = self.client.get_bridge(subnet['network_id'])
|
|
self.client.delete_dhcp(bridge)
|
|
|
|
# If the network is external, clean up routes, links, ports.
|
|
self._extend_network_dict_l3(context, net)
|
|
if net['router:external']:
|
|
self.client.unlink_bridge_from_provider_router(
|
|
bridge, self.provider_router)
|
|
|
|
super(MidonetPluginV2, self).delete_subnet(context, id)
|
|
LOG.debug(_("MidonetPluginV2.delete_subnet exiting"))
|
|
|
|
def create_network(self, context, network):
|
|
"""Create Quantum network.
|
|
|
|
Create a new Quantum network and its corresponding MidoNet bridge.
|
|
"""
|
|
LOG.debug(_('MidonetPluginV2.create_network called: network=%r'),
|
|
network)
|
|
|
|
if network['network']['admin_state_up'] is False:
|
|
LOG.warning(_('Ignoring admin_state_up=False for network=%r '
|
|
'because it is not yet supported'), network)
|
|
|
|
tenant_id = self._get_tenant_id_for_create(context, network['network'])
|
|
|
|
self._ensure_default_security_group(context, tenant_id)
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
bridge = self.client.create_bridge(tenant_id,
|
|
network['network']['name'])
|
|
|
|
# Set MidoNet bridge ID to the quantum DB entry
|
|
network['network']['id'] = bridge.get_id()
|
|
net = super(MidonetPluginV2, self).create_network(context, network)
|
|
|
|
# to handle l3 related data in DB
|
|
self._process_l3_create(context, network['network'], net['id'])
|
|
self._extend_network_dict_l3(context, net)
|
|
LOG.debug(_("MidonetPluginV2.create_network exiting: net=%r"), net)
|
|
return net
|
|
|
|
def update_network(self, context, id, network):
|
|
"""Update Quantum network.
|
|
|
|
Update an existing Quantum network and its corresponding MidoNet
|
|
bridge.
|
|
"""
|
|
LOG.debug(_("MidonetPluginV2.update_network called: id=%(id)r, "
|
|
"network=%(network)r"), {'id': id, 'network': network})
|
|
|
|
# Reject admin_state_up=False
|
|
if network['network'].get('admin_state_up') and network['network'][
|
|
'admin_state_up'] is False:
|
|
raise q_exc.NotImplementedError(_('admin_state_up=False '
|
|
'networks are not '
|
|
'supported.'))
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
net = super(MidonetPluginV2, self).update_network(
|
|
context, id, network)
|
|
self.client.update_bridge(id, net['name'])
|
|
|
|
self._extend_network_dict_l3(context, net)
|
|
LOG.debug(_("MidonetPluginV2.update_network exiting: net=%r"), net)
|
|
return net
|
|
|
|
def get_network(self, context, id, fields=None):
|
|
"""Get Quantum network.
|
|
|
|
Retrieves a Quantum network and its corresponding MidoNet bridge.
|
|
"""
|
|
LOG.debug(_("MidonetPluginV2.get_network called: id=%(id)r, "
|
|
"fields=%(fields)r"), {'id': id, 'fields': fields})
|
|
|
|
# NOTE: Get network data with all fields (fields=None) for
|
|
# _extend_network_dict_l3() method, which needs 'id' field
|
|
qnet = super(MidonetPluginV2, self).get_network(context, id, None)
|
|
self.client.get_bridge(id)
|
|
|
|
self._extend_network_dict_l3(context, qnet)
|
|
LOG.debug(_("MidonetPluginV2.get_network exiting: qnet=%r"), qnet)
|
|
return self._fields(qnet, fields)
|
|
|
|
def get_networks(self, context, filters=None, fields=None):
|
|
"""List quantum networks and verify that all exist in MidoNet."""
|
|
LOG.debug(_("MidonetPluginV2.get_networks called: "
|
|
"filters=%(filters)r, fields=%(fields)r"),
|
|
{'filters': filters, 'fields': fields})
|
|
|
|
# NOTE: Get network data with all fields (fields=None) for
|
|
# _extend_network_dict_l3() method, which needs 'id' field
|
|
qnets = super(MidonetPluginV2, self).get_networks(context, filters,
|
|
None)
|
|
for n in qnets:
|
|
self._extend_network_dict_l3(context, n)
|
|
|
|
return [self._fields(net, fields) for net in qnets]
|
|
|
|
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:
|
|
super(MidonetPluginV2, self).delete_network(context, id)
|
|
except Exception:
|
|
LOG.error(_('Failed to delete quantum db, while Midonet bridge=%r'
|
|
'had been deleted'), id)
|
|
raise
|
|
|
|
def create_port(self, context, port):
|
|
"""Create a L2 port in Quantum/MidoNet."""
|
|
LOG.debug(_("MidonetPluginV2.create_port called: port=%r"), port)
|
|
|
|
is_compute_interface = False
|
|
port_data = port['port']
|
|
# get the bridge and create a port on it.
|
|
bridge = self.client.get_bridge(port_data['network_id'])
|
|
|
|
device_owner = port_data['device_owner']
|
|
|
|
if device_owner.startswith('compute:') or device_owner is '':
|
|
is_compute_interface = True
|
|
bridge_port = self.client.create_exterior_bridge_port(bridge)
|
|
elif device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF:
|
|
bridge_port = self.client.create_interior_bridge_port(bridge)
|
|
elif (device_owner == l3_db.DEVICE_OWNER_ROUTER_GW or
|
|
device_owner == l3_db.DEVICE_OWNER_FLOATINGIP):
|
|
|
|
# This is a dummy port to make l3_db happy.
|
|
# This will not be used in MidoNet
|
|
bridge_port = self.client.create_interior_bridge_port(bridge)
|
|
|
|
if bridge_port:
|
|
# set midonet port id to quantum port id and create a DB record.
|
|
port_data['id'] = bridge_port.get_id()
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
port_db_entry = super(MidonetPluginV2,
|
|
self).create_port(context, port)
|
|
# Caveat: port_db_entry is not a db model instance
|
|
sg_ids = self._get_security_groups_on_port(context, port)
|
|
self._process_port_create_security_group(context, port, sg_ids)
|
|
if is_compute_interface:
|
|
# Create a DHCP entry if needed.
|
|
if 'ip_address' in (port_db_entry['fixed_ips'] or [{}])[0]:
|
|
# get ip and mac from DB record, assuming one IP address
|
|
# at most since we only support one subnet per network now.
|
|
fixed_ip = port_db_entry['fixed_ips'][0]['ip_address']
|
|
mac = port_db_entry['mac_address']
|
|
# create dhcp host entry under the bridge.
|
|
self.client.create_dhcp_hosts(bridge, fixed_ip, mac)
|
|
LOG.debug(_("MidonetPluginV2.create_port exiting: port_db_entry=%r"),
|
|
port_db_entry)
|
|
return port_db_entry
|
|
|
|
def get_port(self, context, id, fields=None):
|
|
"""Retrieve port."""
|
|
LOG.debug(_("MidonetPluginV2.get_port called: id=%(id)s "
|
|
"fields=%(fields)r"), {'id': id, 'fields': fields})
|
|
|
|
# get the quantum port from DB.
|
|
port_db_entry = super(MidonetPluginV2, self).get_port(context,
|
|
id, fields)
|
|
# verify that corresponding port exists in MidoNet.
|
|
self.client.get_port(id)
|
|
|
|
LOG.debug(_("MidonetPluginV2.get_port exiting: port_db_entry=%r"),
|
|
port_db_entry)
|
|
return port_db_entry
|
|
|
|
def get_ports(self, context, filters=None, fields=None):
|
|
"""List quantum ports and verify that they exist in MidoNet."""
|
|
LOG.debug(_("MidonetPluginV2.get_ports called: filters=%(filters)s "
|
|
"fields=%(fields)r"),
|
|
{'filters': filters, 'fields': fields})
|
|
ports_db_entry = super(MidonetPluginV2, self).get_ports(context,
|
|
filters,
|
|
fields)
|
|
if ports_db_entry:
|
|
for port in ports_db_entry:
|
|
if 'security_gorups' in port:
|
|
self._extend_port_dict_security_group(context, port)
|
|
return ports_db_entry
|
|
|
|
def delete_port(self, context, id, l3_port_check=True):
|
|
"""Delete a quantum port and corresponding MidoNet bridge port."""
|
|
LOG.debug(_("MidonetPluginV2.delete_port called: id=%(id)s "
|
|
"l3_port_check=%(l3_port_check)r"),
|
|
{'id': id, 'l3_port_check': l3_port_check})
|
|
# if needed, check to see if this is a port owned by
|
|
# and l3-router. If so, we should prevent deletion.
|
|
if l3_port_check:
|
|
self.prevent_l3_port_deletion(context, id)
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
port_db_entry = super(MidonetPluginV2, self).get_port(context,
|
|
id, None)
|
|
# Clean up dhcp host entry if needed.
|
|
if 'ip_address' in (port_db_entry['fixed_ips'] or [{}])[0]:
|
|
# get ip and mac from DB record.
|
|
ip = port_db_entry['fixed_ips'][0]['ip_address']
|
|
mac = port_db_entry['mac_address']
|
|
|
|
# create dhcp host entry under the bridge.
|
|
self.client.delete_dhcp_hosts(port_db_entry['network_id'], ip,
|
|
mac)
|
|
|
|
self.client.delete_port(id)
|
|
return super(MidonetPluginV2, self).delete_port(context, id)
|
|
|
|
#
|
|
# L3 APIs.
|
|
#
|
|
|
|
def create_router(self, context, router):
|
|
LOG.debug(_("MidonetPluginV2.create_router called: router=%r"), router)
|
|
|
|
if router['router']['admin_state_up'] is False:
|
|
LOG.warning(_('Ignoring admin_state_up=False for router=%r. '
|
|
'Overriding with True'), router)
|
|
router['router']['admin_state_up'] = True
|
|
|
|
tenant_id = self._get_tenant_id_for_create(context, router['router'])
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
mrouter = self.client.create_tenant_router(
|
|
tenant_id, router['router']['name'], self.metadata_router)
|
|
|
|
qrouter = super(MidonetPluginV2, self).create_router(context,
|
|
router)
|
|
|
|
# get entry from the DB and update 'id' with MidoNet router id.
|
|
qrouter_entry = self._get_router(context, qrouter['id'])
|
|
qrouter['id'] = mrouter.get_id()
|
|
qrouter_entry.update(qrouter)
|
|
|
|
LOG.debug(_("MidonetPluginV2.create_router exiting: qrouter=%r"),
|
|
qrouter)
|
|
return qrouter
|
|
|
|
def update_router(self, context, id, router):
|
|
LOG.debug(_("MidonetPluginV2.update_router called: id=%(id)s "
|
|
"router=%(router)r"), router)
|
|
|
|
if router['router'].get('admin_state_up') is False:
|
|
raise q_exc.NotImplementedError(_('admin_state_up=False '
|
|
'routers are not '
|
|
'supported.'))
|
|
|
|
op_gateway_set = False
|
|
op_gateway_clear = False
|
|
|
|
# figure out which operation it is in
|
|
if ('external_gateway_info' in router['router'] and
|
|
'network_id' in router['router']['external_gateway_info']):
|
|
op_gateway_set = True
|
|
elif ('external_gateway_info' in router['router'] and
|
|
router['router']['external_gateway_info'] == {}):
|
|
op_gateway_clear = True
|
|
|
|
qports = super(MidonetPluginV2, self).get_ports(
|
|
context, {'device_id': [id],
|
|
'device_owner': ['network:router_gateway']})
|
|
|
|
assert len(qports) == 1
|
|
qport = qports[0]
|
|
snat_ip = qport['fixed_ips'][0]['ip_address']
|
|
qport['network_id']
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
|
|
qrouter = super(MidonetPluginV2, self).update_router(context, id,
|
|
router)
|
|
|
|
changed_name = router['router'].get('name')
|
|
if changed_name:
|
|
self.client.update_router(id, changed_name)
|
|
|
|
if op_gateway_set:
|
|
# find a qport with the network_id for the router
|
|
qports = super(MidonetPluginV2, self).get_ports(
|
|
context, {'device_id': [id],
|
|
'device_owner': ['network:router_gateway']})
|
|
assert len(qports) == 1
|
|
qport = qports[0]
|
|
snat_ip = qport['fixed_ips'][0]['ip_address']
|
|
|
|
self.client.set_router_external_gateway(id,
|
|
self.provider_router,
|
|
snat_ip)
|
|
|
|
if op_gateway_clear:
|
|
self.client.clear_router_external_gateway(id)
|
|
|
|
LOG.debug(_("MidonetPluginV2.update_router exiting: qrouter=%r"),
|
|
qrouter)
|
|
return qrouter
|
|
|
|
def delete_router(self, context, id):
|
|
LOG.debug(_("MidonetPluginV2.delete_router called: id=%s"), id)
|
|
|
|
self.client.delete_tenant_router(id)
|
|
|
|
result = super(MidonetPluginV2, self).delete_router(context, id)
|
|
LOG.debug(_("MidonetPluginV2.delete_router exiting: result=%s"),
|
|
result)
|
|
return result
|
|
|
|
def add_router_interface(self, context, router_id, interface_info):
|
|
LOG.debug(_("MidonetPluginV2.add_router_interface called: "
|
|
"router_id=%(router_id)s "
|
|
"interface_info=%(interface_info)r"),
|
|
{'router_id': router_id, 'interface_info': interface_info})
|
|
|
|
qport = super(MidonetPluginV2, self).add_router_interface(
|
|
context, router_id, interface_info)
|
|
|
|
# TODO(tomoe): handle a case with 'port' in interface_info
|
|
if 'subnet_id' in interface_info:
|
|
subnet_id = interface_info['subnet_id']
|
|
subnet = self._get_subnet(context, subnet_id)
|
|
|
|
gateway_ip = subnet['gateway_ip']
|
|
network_address, length = subnet['cidr'].split('/')
|
|
|
|
# Link the router and the bridge port.
|
|
self.client.link_bridge_port_to_router(qport['port_id'], router_id,
|
|
gateway_ip, network_address,
|
|
length,
|
|
self.metadata_router)
|
|
|
|
LOG.debug(_("MidonetPluginV2.add_router_interface exiting: "
|
|
"qport=%r"), qport)
|
|
return qport
|
|
|
|
def remove_router_interface(self, context, router_id, interface_info):
|
|
"""Remove interior router ports."""
|
|
LOG.debug(_("MidonetPluginV2.remove_router_interface called: "
|
|
"router_id=%(router_id)s "
|
|
"interface_info=%(interface_info)r"),
|
|
{'router_id': router_id, 'interface_info': interface_info})
|
|
port_id = None
|
|
if 'port_id' in interface_info:
|
|
|
|
port_id = interface_info['port_id']
|
|
subnet_id = self.get_port(context,
|
|
interface_info['port_id']
|
|
)['fixed_ips'][0]['subnet_id']
|
|
|
|
subnet = self._get_subnet(context, subnet_id)
|
|
|
|
if 'subnet_id' in interface_info:
|
|
|
|
subnet_id = interface_info['subnet_id']
|
|
subnet = self._get_subnet(context, subnet_id)
|
|
network_id = subnet['network_id']
|
|
|
|
# find a quantum port for the network
|
|
rport_qry = context.session.query(models_v2.Port)
|
|
ports = rport_qry.filter_by(
|
|
device_id=router_id,
|
|
device_owner=l3_db.DEVICE_OWNER_ROUTER_INTF,
|
|
network_id=network_id)
|
|
network_port = None
|
|
for p in ports:
|
|
if p['fixed_ips'][0]['subnet_id'] == subnet_id:
|
|
network_port = p
|
|
break
|
|
assert network_port
|
|
port_id = network_port['id']
|
|
|
|
assert port_id
|
|
|
|
# get network information from subnet data
|
|
network_addr, network_length = subnet['cidr'].split('/')
|
|
network_length = int(network_length)
|
|
|
|
# Unlink the router and the bridge.
|
|
self.client.unlink_bridge_port_from_router(port_id, network_addr,
|
|
network_length,
|
|
self.metadata_router)
|
|
|
|
info = super(MidonetPluginV2, self).remove_router_interface(
|
|
context, router_id, interface_info)
|
|
LOG.debug(_("MidonetPluginV2.remove_router_interface exiting"))
|
|
return info
|
|
|
|
def update_floatingip(self, context, id, floatingip):
|
|
LOG.debug(_("MidonetPluginV2.update_floatingip called: id=%(id)s "
|
|
"floatingip=%(floatingip)s "),
|
|
{'id': id, 'floatingip': floatingip})
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
if floatingip['floatingip']['port_id']:
|
|
fip = super(MidonetPluginV2, self).update_floatingip(
|
|
context, id, floatingip)
|
|
|
|
self.client.setup_floating_ip(fip['router_id'],
|
|
self.provider_router,
|
|
fip['floating_ip_address'],
|
|
fip['fixed_ip_address'], id)
|
|
# disassociate floating IP
|
|
elif floatingip['floatingip']['port_id'] is None:
|
|
|
|
fip = super(MidonetPluginV2, self).get_floatingip(context, id)
|
|
self.client.clear_floating_ip(fip['router_id'],
|
|
self.provider_router,
|
|
fip['floating_ip_address'], id)
|
|
super(MidonetPluginV2, self).update_floatingip(context, id,
|
|
floatingip)
|
|
|
|
LOG.debug(_("MidonetPluginV2.update_floating_ip exiting: fip=%s"), fip)
|
|
return fip
|
|
|
|
#
|
|
# Security groups supporting methods
|
|
#
|
|
|
|
def create_security_group(self, context, security_group, default_sg=False):
|
|
"""Create chains for Quantum security group."""
|
|
LOG.debug(_("MidonetPluginV2.create_security_group called: "
|
|
"security_group=%(security_group)s "
|
|
"default_sg=%(default_sg)s "),
|
|
{'security_group': security_group, 'default_sg': default_sg})
|
|
|
|
sg = security_group.get('security_group')
|
|
tenant_id = self._get_tenant_id_for_create(context, sg)
|
|
|
|
with context.session.begin(subtransactions=True):
|
|
sg_db_entry = super(MidonetPluginV2, self).create_security_group(
|
|
context, security_group, default_sg)
|
|
|
|
# Create MidoNet chains and portgroup for the SG
|
|
self.client.create_for_sg(tenant_id, sg_db_entry['id'],
|
|
sg_db_entry['name'])
|
|
|
|
LOG.debug(_("MidonetPluginV2.create_security_group exiting: "
|
|
"sg_db_entry=%r"), sg_db_entry)
|
|
return sg_db_entry
|
|
|
|
def delete_security_group(self, context, id):
|
|
"""Delete chains for Quantum security group."""
|
|
LOG.debug(_("MidonetPluginV2.delete_security_group called: id=%s"), id)
|
|
|
|
with context.session.begin(subtransactions=True):
|
|
sg_db_entry = super(MidonetPluginV2, self).get_security_group(
|
|
context, id)
|
|
|
|
if not sg_db_entry:
|
|
raise ext_sg.SecurityGroupNotFound(id=id)
|
|
|
|
sg_name = sg_db_entry['name']
|
|
sg_id = sg_db_entry['id']
|
|
tenant_id = sg_db_entry['tenant_id']
|
|
|
|
if sg_name == 'default' and not context.is_admin:
|
|
raise ext_sg.SecurityGroupCannotRemoveDefault()
|
|
|
|
filters = {'security_group_id': [sg_id]}
|
|
if super(MidonetPluginV2, self)._get_port_security_group_bindings(
|
|
context, filters):
|
|
raise ext_sg.SecurityGroupInUse(id=sg_id)
|
|
|
|
# Delete MidoNet Chains and portgroup for the SG
|
|
self.client.delete_for_sg(tenant_id, sg_id, sg_name)
|
|
|
|
return super(MidonetPluginV2, self).delete_security_group(
|
|
context, id)
|
|
|
|
def get_security_groups(self, context, filters=None, fields=None,
|
|
default_sg=False):
|
|
LOG.debug(_("MidonetPluginV2.get_security_groups called: "
|
|
"filters=%(filters)r fields=%(fields)r"),
|
|
{'filters': filters, 'fields': fields})
|
|
return super(MidonetPluginV2, self).get_security_groups(
|
|
context, filters, fields, default_sg=default_sg)
|
|
|
|
def get_security_group(self, context, id, fields=None, tenant_id=None):
|
|
LOG.debug(_("MidonetPluginV2.get_security_group called: id=%(id)s "
|
|
"fields=%(fields)r tenant_id=%(tenant_id)s"),
|
|
{'id': id, 'fields': fields, 'tenant_id': tenant_id})
|
|
return super(MidonetPluginV2, self).get_security_group(context, id,
|
|
fields)
|
|
|
|
def create_security_group_rule(self, context, security_group_rule):
|
|
LOG.debug(_("MidonetPluginV2.create_security_group_rule called: "
|
|
"security_group_rule=%(security_group_rule)r"),
|
|
{'security_group_rule': security_group_rule})
|
|
|
|
with context.session.begin(subtransactions=True):
|
|
rule_db_entry = super(
|
|
MidonetPluginV2, self).create_security_group_rule(
|
|
context, security_group_rule)
|
|
|
|
self.client.create_for_sg_rule(rule_db_entry)
|
|
LOG.debug(_("MidonetPluginV2.create_security_group_rule exiting: "
|
|
"rule_db_entry=%r"), rule_db_entry)
|
|
return rule_db_entry
|
|
|
|
def delete_security_group_rule(self, context, sgrid):
|
|
LOG.debug(_("MidonetPluginV2.delete_security_group_rule called: "
|
|
"sgrid=%s"), sgrid)
|
|
|
|
with context.session.begin(subtransactions=True):
|
|
rule_db_entry = super(MidonetPluginV2,
|
|
self).get_security_group_rule(context, sgrid)
|
|
|
|
if not rule_db_entry:
|
|
raise ext_sg.SecurityGroupRuleNotFound(id=sgrid)
|
|
|
|
self.client.delete_for_sg_rule(rule_db_entry)
|
|
return super(MidonetPluginV2,
|
|
self).delete_security_group_rule(context, sgrid)
|
|
|
|
def get_security_group_rules(self, context, filters=None, fields=None):
|
|
LOG.debug(_("MidonetPluginV2.get_security_group_rules called: "
|
|
"filters=%(filters)r fields=%(fields)r"),
|
|
{'filters': filters, 'fields': fields})
|
|
return super(MidonetPluginV2, self).get_security_group_rules(
|
|
context, filters, fields)
|
|
|
|
def get_security_group_rule(self, context, id, fields=None):
|
|
LOG.debug(_("MidonetPluginV2.get_security_group_rule called: "
|
|
"id=%(id)s fields=%(fields)r"),
|
|
{'id': id, 'fields': fields})
|
|
return super(MidonetPluginV2, self).get_security_group_rule(
|
|
context, id, fields)
|