Integration with new neutron code

1. Use new enginefacade + l3_db breakage
Use reader and writer for db operations.
Partially-Implements blueprint: enginefacade-switch

2. Fix the callback pass for _prevent_l3_port_delete_callback
which was changed in commit Ia8ac4f510c003667cac95f76dea0e9ae55159878

3. QoS driver integration
Commit I5f747635be3fd66b70326d9f94c85a6736286bd2 removes the qos
notification driver.
Fixing the nsx-v and nsx-v3 to work only with the regular driver

4. _get_extra_routes_dict_by_router_id was removed by
Ia815d6c597730bd5cb49455e7409ca747a4cc22c

5. Floating IP association without subnet gateway IP
not supported by our plugins.
Added in commit If212c36d918ed57400a53f4b5fa1925b3d1fa6fd

Co-Authored-by: Adit Sarfaty <asarfaty@vmware.com>
Change-Id: I277ec5c38c5895337011019f71d586b254bfafde
changes/17/452517/21
Gary Kotton 6 years ago committed by Adit Sarfaty
parent bf3bbb5c4c
commit 01d33ffa65
  1. 3
      doc/source/devstack.rst
  2. 13
      vmware_nsx/common/sync.py
  3. 16
      vmware_nsx/db/db.py
  4. 6
      vmware_nsx/db/extended_security_group.py
  5. 3
      vmware_nsx/db/extended_security_group_rule.py
  6. 15
      vmware_nsx/db/lsn_db.py
  7. 3
      vmware_nsx/db/maclearning.py
  8. 29
      vmware_nsx/db/networkgw_db.py
  9. 15
      vmware_nsx/db/qos_db.py
  10. 3
      vmware_nsx/db/routertype.py
  11. 6
      vmware_nsx/plugins/dvs/plugin.py
  12. 117
      vmware_nsx/plugins/nsx_mh/plugin.py
  13. 2
      vmware_nsx/plugins/nsx_v/drivers/distributed_router_driver.py
  14. 50
      vmware_nsx/plugins/nsx_v/plugin.py
  15. 35
      vmware_nsx/plugins/nsx_v3/plugin.py
  16. 71
      vmware_nsx/services/qos/nsx_v/driver.py
  17. 27
      vmware_nsx/services/qos/nsx_v/utils.py
  18. 54
      vmware_nsx/services/qos/nsx_v3/utils.py
  19. 29
      vmware_nsx/shell/admin/plugins/nsxv/resources/securitygroups.py
  20. 23
      vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py
  21. 3
      vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py
  22. 7
      vmware_nsx/tests/unit/extensions/test_provider_security_groups.py
  23. 3
      vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py
  24. 5
      vmware_nsx/tests/unit/extensions/test_vnic_index.py
  25. 6
      vmware_nsx/tests/unit/nsx_mh/test_plugin.py
  26. 15
      vmware_nsx/tests/unit/nsx_mh/test_sync.py
  27. 84
      vmware_nsx/tests/unit/nsx_v/test_plugin.py
  28. 3
      vmware_nsx/tests/unit/nsx_v3/test_plugin.py
  29. 39
      vmware_nsx/tests/unit/services/qos/fake_nsxv_notifier.py
  30. 2
      vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py
  31. 192
      vmware_nsx/tests/unit/services/qos/test_nsxv_notification.py

@ -135,9 +135,6 @@ Enable the qos in ``local.conf``::
[DEFAULT]
service_plugins = neutron.services.qos.qos_plugin.QoSPlugin
[qos]
notification_drivers =
Optional: Update the nsx qos_peak_bw_multiplier in nsx.ini (default value is 2.0)::
[NSX]

@ -17,7 +17,7 @@ import copy
import random
from neutron_lib import constants
from neutron_lib import context
from neutron_lib import context as n_context
from neutron_lib import exceptions
from oslo_log import log
from oslo_serialization import jsonutils
@ -25,6 +25,7 @@ from oslo_service import loopingcall
from oslo_utils import timeutils
import six
from neutron.db import api as db_api
from neutron.db.models import external_net as external_net_db
from neutron.db.models import l3 as l3_db
from neutron.db import models_v2
@ -300,7 +301,7 @@ class NsxSynchronizer(object):
# do nothing
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
try:
network = self._plugin._get_network(context,
neutron_network_data['id'])
@ -382,7 +383,7 @@ class NsxSynchronizer(object):
# do nothing
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
try:
router = self._plugin._get_router(context,
neutron_router_data['id'])
@ -434,7 +435,7 @@ class NsxSynchronizer(object):
(models_v2.Network.id ==
external_net_db.ExternalNetwork.network_id))]
if neutron_port_data['network_id'] in ext_networks:
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
neutron_port_data['status'] = constants.PORT_STATUS_ACTIVE
return
@ -477,7 +478,7 @@ class NsxSynchronizer(object):
# do nothing
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
try:
port = self._plugin._get_port(context,
neutron_port_data['id'])
@ -660,7 +661,7 @@ class NsxSynchronizer(object):
LOG.debug("Time elapsed hashing data: %s",
timeutils.utcnow() - start)
# Get an admin context
ctx = context.get_admin_context()
ctx = n_context.get_admin_context()
# Synchronize with database
self._synchronize_lswitches(ctx, ls_uuids,
scan_missing=scan_missing)

@ -402,14 +402,14 @@ def delete_port_mirror_session_mapping(session, tf_id):
filter_by(tap_flow_id=tf_id).delete())
def save_sg_mappings(session, sg_id, nsgroup_id, section_id):
with session.begin(subtransactions=True):
session.add(
nsx_models.NeutronNsxFirewallSectionMapping(neutron_id=sg_id,
nsx_id=section_id))
session.add(
nsx_models.NeutronNsxSecurityGroupMapping(neutron_id=sg_id,
nsx_id=nsgroup_id))
@db.context_manager.writer
def save_sg_mappings(context, sg_id, nsgroup_id, section_id):
context.session.add(
nsx_models.NeutronNsxFirewallSectionMapping(neutron_id=sg_id,
nsx_id=section_id))
context.session.add(
nsx_models.NeutronNsxSecurityGroupMapping(neutron_id=sg_id,
nsx_id=nsgroup_id))
def get_sg_mappings(session, sg_id):

@ -120,7 +120,7 @@ class ExtendedSecurityGroupPropertiesMixin(object):
default_sg=False):
self._validate_security_group_properties_create(
context, sg_req, default_sg)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
properties = NsxExtendedSecurityGroupProperties(
security_group_id=sg_res['id'],
logging=sg_req.get(sg_logging.LOGGING, False),
@ -132,7 +132,7 @@ class ExtendedSecurityGroupPropertiesMixin(object):
sg_res[sg_policy.POLICY] = sg_req.get(sg_policy.POLICY)
def _get_security_group_properties(self, context, security_group_id):
with context.session.begin(subtransactions=True):
with db_api.context_manager.reader.using(context):
try:
prop = context.session.query(
NsxExtendedSecurityGroupProperties).filter_by(
@ -150,7 +150,7 @@ class ExtendedSecurityGroupPropertiesMixin(object):
and (sg_req[sg_policy.POLICY] !=
sg_res.get(sg_policy.POLICY)))):
prop = self._get_security_group_properties(context, sg_res['id'])
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
prop.update({
sg_logging.LOGGING: sg_req.get(sg_logging.LOGGING, False),
sg_policy.POLICY: sg_req.get(sg_policy.POLICY)})

@ -17,6 +17,7 @@ from neutron_lib.db import model_base
import sqlalchemy as sa
from sqlalchemy import orm
from neutron.db import api as db_api
from neutron.db import db_base_plugin_v2
from neutron.db.models import securitygroup
from neutron.extensions import securitygroup as ext_sg
@ -72,7 +73,7 @@ class ExtendedSecurityGroupRuleMixin(object):
rule_req.get(ext_local_ip.LOCAL_IP_PREFIX)):
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
properties = NsxExtendedSecurityGroupRuleProperties(
rule_id=rule_res['id'],
local_ip_prefix=rule_req[ext_local_ip.LOCAL_IP_PREFIX])

@ -23,26 +23,27 @@ from vmware_nsx._i18n import _
from vmware_nsx.common import exceptions as p_exc
from vmware_nsx.db import nsx_models
from neutron.db import api as db_api
LOG = logging.getLogger(__name__)
def lsn_add(context, network_id, lsn_id):
"""Add Logical Service Node information to persistent datastore."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
lsn = nsx_models.Lsn(network_id, lsn_id)
context.session.add(lsn)
def lsn_remove(context, lsn_id):
"""Remove Logical Service Node information from datastore given its id."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
context.session.query(nsx_models.Lsn).filter_by(lsn_id=lsn_id).delete()
def lsn_remove_for_network(context, network_id):
"""Remove information about the Logical Service Node given its network."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
context.session.query(nsx_models.Lsn).filter_by(
net_id=network_id).delete()
@ -64,14 +65,14 @@ def lsn_get_for_network(context, network_id, raise_on_err=True):
def lsn_port_add_for_lsn(context, lsn_port_id, subnet_id, mac, lsn_id):
"""Add Logical Service Node Port information to persistent datastore."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
lsn_port = nsx_models.LsnPort(lsn_port_id, subnet_id, mac, lsn_id)
context.session.add(lsn_port)
def lsn_port_get_for_subnet(context, subnet_id, raise_on_err=True):
"""Return Logical Service Node Port information given its subnet id."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.reader.using(context):
try:
return (context.session.query(nsx_models.LsnPort).
filter_by(sub_id=subnet_id).one())
@ -84,7 +85,7 @@ def lsn_port_get_for_subnet(context, subnet_id, raise_on_err=True):
def lsn_port_get_for_mac(context, mac_address, raise_on_err=True):
"""Return Logical Service Node Port information given its mac address."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.reader.using(context):
try:
return (context.session.query(nsx_models.LsnPort).
filter_by(mac_addr=mac_address).one())
@ -97,6 +98,6 @@ def lsn_port_get_for_mac(context, mac_address, raise_on_err=True):
def lsn_port_remove(context, lsn_port_id):
"""Remove Logical Service Node port from the given Logical Service Node."""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
(context.session.query(nsx_models.LsnPort).
filter_by(lsn_port_id=lsn_port_id).delete())

@ -17,6 +17,7 @@ from sqlalchemy.orm import exc
from neutron.api.v2 import attributes
from neutron.db import _utils as db_utils
from neutron.db import api as db_api
from neutron.db import db_base_plugin_v2
from oslo_log import log as logging
@ -56,7 +57,7 @@ class MacLearningDbMixin(object):
mac.MAC_LEARNING: enabled})
def _create_mac_learning_state(self, context, port):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
enabled = port[mac.MAC_LEARNING]
state = nsx_models.MacLearningState(
port_id=port['id'],

@ -15,6 +15,7 @@
from sqlalchemy.orm import exc as sa_orm_exc
from neutron.db import _utils as db_utils
from neutron.db import api as db_api
from neutron.plugins.common import utils
from neutron_lib import constants
from neutron_lib import exceptions
@ -177,12 +178,12 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
return query.one() if only_one else query.all()
def _unset_default_network_gateways(self, context):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
context.session.query(nsx_models.NetworkGateway).update(
{nsx_models.NetworkGateway.default: False})
def _set_default_network_gateway(self, context, gw_id):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
gw = (context.session.query(nsx_models.NetworkGateway).
filter_by(id=gw_id).one())
gw['default'] = True
@ -217,7 +218,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
validate_device_list=True):
gw_data = network_gateway[self.gateway_resource]
tenant_id = gw_data['tenant_id']
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
gw_db = nsx_models.NetworkGateway(
id=gw_data.get('id', uuidutils.generate_uuid()),
tenant_id=tenant_id,
@ -230,27 +231,27 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
[nsx_models.NetworkGatewayDeviceReference(**device)
for device in gw_data['devices']])
context.session.add(gw_db)
LOG.debug("Created network gateway with id:%s", gw_db['id'])
return self._make_network_gateway_dict(gw_db)
LOG.debug("Created network gateway with id:%s", gw_db['id'])
return self._make_network_gateway_dict(gw_db)
def update_network_gateway(self, context, id, network_gateway):
gw_data = network_gateway[self.gateway_resource]
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
gw_db = self._get_network_gateway(context, id)
if gw_db.default:
raise NetworkGatewayUnchangeable(gateway_id=id)
# Ensure there is something to update before doing it
if any([gw_db[k] != gw_data[k] for k in gw_data]):
gw_db.update(gw_data)
LOG.debug("Updated network gateway with id:%s", id)
return self._make_network_gateway_dict(gw_db)
LOG.debug("Updated network gateway with id:%s", id)
return self._make_network_gateway_dict(gw_db)
def get_network_gateway(self, context, id, fields=None):
gw_db = self._get_network_gateway(context, id)
return self._make_network_gateway_dict(gw_db, fields)
def delete_network_gateway(self, context, id):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
gw_db = self._get_network_gateway(context, id)
if gw_db.network_connections:
raise GatewayInUse(gateway_id=id)
@ -278,7 +279,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
"'%(network_gateway_id)s'",
{'network_id': network_id,
'network_gateway_id': network_gateway_id})
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
gw_db = self._get_network_gateway(context, network_gateway_id)
tenant_id = gw_db['tenant_id']
if context.is_admin and not tenant_id:
@ -355,7 +356,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
"'%(network_gateway_id)s'",
{'network_id': network_id,
'network_gateway_id': network_gateway_id})
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# Uniquely identify connection, otherwise raise
try:
net_connection = self._retrieve_gateway_connections(
@ -439,7 +440,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
initial_status=STATUS_UNKNOWN):
device_data = gateway_device[self.device_resource]
tenant_id = device_data['tenant_id']
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
device_db = nsx_models.NetworkGatewayDevice(
id=device_data.get('id', uuidutils.generate_uuid()),
tenant_id=tenant_id,
@ -454,7 +455,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
def update_gateway_device(self, context, gateway_device_id,
gateway_device, include_nsx_id=False):
device_data = gateway_device[self.device_resource]
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
device_db = self._get_gateway_device(context, gateway_device_id)
# Ensure there is something to update before doing it
if any([device_db[k] != device_data[k] for k in device_data]):
@ -465,7 +466,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase):
device_db, include_nsx_id=include_nsx_id)
def delete_gateway_device(self, context, device_id):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# A gateway device should not be deleted
# if it is used in any network gateway service
if self._is_device_in_use(context, device_id):

@ -17,6 +17,7 @@ from sqlalchemy.orm import exc
from neutron.api.v2 import attributes as attr
from neutron.db import _utils as db_utils
from neutron.db import api as db_api
from neutron.db import db_base_plugin_v2
from neutron.db import models_v2
@ -34,7 +35,7 @@ class QoSDbMixin(qos.QueuePluginBase):
def create_qos_queue(self, context, qos_queue):
q = qos_queue['qos_queue']
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
qos_queue = nsx_models.QoSQueue(
id=q.get('id', uuidutils.generate_uuid()),
name=q.get('name'),
@ -68,15 +69,15 @@ class QoSDbMixin(qos.QueuePluginBase):
page_reverse=page_reverse)
def delete_qos_queue(self, context, queue_id):
qos_queue = self._get_qos_queue(context, queue_id)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
qos_queue = self._get_qos_queue(context, queue_id)
context.session.delete(qos_queue)
def _process_port_queue_mapping(self, context, port_data, queue_id):
port_data[qos.QUEUE] = queue_id
if not queue_id:
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
context.session.add(nsx_models.PortQueueMapping(
port_id=port_data['id'],
queue_id=queue_id))
@ -96,14 +97,14 @@ class QoSDbMixin(qos.QueuePluginBase):
# did not already have a queue on it. There is no need to check
# if there is one before deleting if we return here.
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
context.session.delete(binding)
def _process_network_queue_mapping(self, context, net_data, queue_id):
net_data[qos.QUEUE] = queue_id
if not queue_id:
return
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
context.session.add(
nsx_models.NetworkQueueMapping(network_id=net_data['id'],
queue_id=queue_id))
@ -115,7 +116,7 @@ class QoSDbMixin(qos.QueuePluginBase):
def _delete_network_queue_mapping(self, context, network_id):
query = self._model_query(context, nsx_models.NetworkQueueMapping)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
binding = query.filter_by(network_id=network_id).first()
if binding:
context.session.delete(binding)

@ -14,6 +14,7 @@
# under the License.
#
from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import (
distributedrouter as dist_rtr)
from vmware_nsx.extensions import routertype as rt_rtr
@ -25,5 +26,5 @@ class RouterType_mixin(dist_rtr.DistributedRouter_mixin):
nsx_attributes = (
dist_rtr.DistributedRouter_mixin.nsx_attributes + [{
'name': rt_rtr.ROUTER_TYPE,
'default': False
'default': nsxv_constants.SHARED
}])

@ -346,7 +346,7 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
# shared network that is not owned by the tenant.
port_data = port['port']
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# First we allocate port in neutron database
neutron_db = super(NsxDvsV2, self).create_port(context, port)
port_security = self._get_network_security_binding(
@ -407,7 +407,7 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
port)
has_addr_pairs = self._check_update_has_allowed_address_pairs(port)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
ret_port = super(NsxDvsV2, self).update_port(
context, id, port)
# Save current mac learning state to check whether it's
@ -463,7 +463,7 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
"""
neutron_db_port = self.get_port(context, id)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# metadata_dhcp_host_route
self.handle_port_metadata_access(
context, neutron_db_port, is_delete=True)

@ -1032,7 +1032,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
LOG.debug("Delete network complete for network: %s", id)
def get_network(self, context, id, fields=None):
with db_api.context_manager.reader.using(context):
with db_api.context_manager.writer.using(context):
# goto to the plugin DB and fetch the network
network = self._get_network(context, id)
if (self.nsx_sync_opts.always_read_status or
@ -1112,7 +1112,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
dhcp_opts = port_data.get(edo_ext.EXTRADHCPOPTS, [])
# Set port status as 'DOWN'. This will be updated by backend sync.
port_data['status'] = constants.PORT_STATUS_DOWN
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# First we allocate port in neutron database
neutron_db = super(NsxPluginV2, self).create_port(context, port)
neutron_port_id = neutron_db['id']
@ -1182,7 +1182,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
LOG.warning("Logical switch for network %s was not "
"found in NSX.", port_data['network_id'])
# Put port in error on neutron DB
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
port = self._get_port(context, neutron_port_id)
port_data['status'] = constants.PORT_STATUS_ERROR
port['status'] = port_data['status']
@ -1192,7 +1192,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
with excutils.save_and_reraise_exception():
LOG.error("Unable to create port or set port "
"attachment in NSX.")
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
self.ipam.delete_port(context, neutron_port_id)
# this extra lookup is necessary to get the
# latest db model for the extension functions
@ -1209,7 +1209,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
port)
has_addr_pairs = self._check_update_has_allowed_address_pairs(port)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
ret_port = super(NsxPluginV2, self).update_port(
context, id, port)
@ -1357,7 +1357,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
port_delete_func(context, neutron_db_port)
self.disassociate_floatingips(context, id)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
queue = self._get_port_queue_bindings(context, {'port_id': [id]})
# metadata_dhcp_host_route
self.handle_port_metadata_access(
@ -1370,7 +1370,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
context, neutron_db_port, action='delete_port')
def get_port(self, context, id, fields=None):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
if (self.nsx_sync_opts.always_read_status or
fields and 'status' in fields):
# Perform explicit state synchronization
@ -1382,15 +1382,16 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
return super(NsxPluginV2, self).get_port(context, id, fields)
def get_router(self, context, id, fields=None):
if (self.nsx_sync_opts.always_read_status or
fields and 'status' in fields):
db_router = self._get_router(context, id)
# Perform explicit state synchronization
self._synchronizer.synchronize_router(
context, db_router)
return self._make_router_dict(db_router, fields)
else:
return super(NsxPluginV2, self).get_router(context, id, fields)
with db_api.context_manager.writer.using(context):
if (self.nsx_sync_opts.always_read_status or
fields and 'status' in fields):
db_router = self._get_router(context, id)
# Perform explicit state synchronization
self._synchronizer.synchronize_router(
context, db_router)
return self._make_router_dict(db_router, fields)
else:
return super(NsxPluginV2, self).get_router(context, id, fields)
def _create_lrouter(self, context, router, nexthop):
tenant_id = router['tenant_id']
@ -1482,10 +1483,10 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
lrouter = self._create_lrouter(context, r, nexthop)
# TODO(salv-orlando): Deal with backend object removal in case
# of db failures
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# Transaction nesting is needed to avoid foreign key violations
# when processing the distributed router binding
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
router_db = l3_db_models.Router(
id=neutron_router_id,
tenant_id=tenant_id,
@ -1500,27 +1501,28 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
nsx_db.add_neutron_nsx_router_mapping(
context.session, router_db['id'], lrouter['uuid'])
if has_gw_info:
# NOTE(salv-orlando): This operation has been moved out of the
# database transaction since it performs several NSX queries,
# ithis ncreasing the risk of deadlocks between eventlet and
# sqlalchemy operations.
# Set external gateway and remove router in case of failure
try:
self._update_router_gw_info(context, router_db['id'], gw_info)
except (n_exc.NeutronException, api_exc.NsxApiException):
with excutils.save_and_reraise_exception():
# As setting gateway failed, the router must be deleted
# in order to ensure atomicity
router_id = router_db['id']
LOG.warning("Failed to set gateway info for router "
"being created:%s - removing router",
router_id)
self.delete_router(context, router_id)
LOG.info("Create router failed while setting external "
"gateway. Router:%s has been removed from "
"DB and backend",
router_id)
if has_gw_info:
# NOTE(salv-orlando): This operation has been moved out of the
# database transaction since it performs several NSX queries,
# ithis ncreasing the risk of deadlocks between eventlet and
# sqlalchemy operations.
# Set external gateway and remove router in case of failure
try:
self._update_router_gw_info(context, router_db['id'],
gw_info)
except (n_exc.NeutronException, api_exc.NsxApiException):
with excutils.save_and_reraise_exception():
# As setting gateway failed, the router must be deleted
# in order to ensure atomicity
router_id = router_db['id']
LOG.warning("Failed to set gateway info for router "
"being created:%s - removing router",
router_id)
self.delete_router(context, router_id)
LOG.info("Create router failed while setting external "
"gateway. Router:%s has been removed from "
"DB and backend",
router_id)
return self._make_router_dict(router_db)
def _update_lrouter(self, context, router_id, name, nexthop, routes=None):
@ -1571,7 +1573,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# object is not found in the underlying backend
except n_exc.NotFound:
# Put the router in ERROR status
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
router_db = self._get_router(context, router_id)
router_db['status'] = constants.NET_STATUS_ERROR
raise nsx_exc.NsxPluginException(
@ -1603,7 +1605,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
routerlib.delete_lrouter(self.cluster, nsx_router_id)
def delete_router(self, context, router_id):
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# NOTE(salv-orlando): These checks will be repeated anyway when
# calling the superclass. This is wasteful, but is the simplest
# way of ensuring a consistent removal of the router both in
@ -1969,12 +1971,21 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
msg = _("Failed to update NAT rules for floatingip update")
raise nsx_exc.NsxPluginException(err_msg=msg)
# Update also floating ip status (no need to call base class method)
new_status = self._floatingip_status(floatingip_db, router_id)
floatingip_db.update(
{'fixed_ip_address': internal_ip,
'fixed_port_id': port_id,
'router_id': router_id,
'status': self._floatingip_status(floatingip_db, router_id)})
return floatingip_db
'status': new_status})
return {'fixed_ip_address': internal_ip,
'fixed_port_id': port_id,
'router_id': router_id,
'last_known_router_id': None,
'floating_ip_address': floatingip_db.floating_ip_address,
'floating_network_id': floatingip_db.floating_network_id,
'floating_ip_id': floatingip_db.id,
'context': context}
@lockutils.synchronized('vmware', 'neutron-')
def create_floatingip(self, context, floatingip):
@ -2077,7 +2088,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
"""
# Ensure the default gateway in the config file is in sync with the db
self._ensure_default_network_gateway()
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
try:
super(NsxPluginV2, self).delete_network_gateway(
context, gateway_id)
@ -2143,7 +2154,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
new_status=None, is_create=False):
LOG.error("Rolling back database changes for gateway device %s "
"because of an error in the NSX backend", device_id)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
query = self._model_query(
context, nsx_models.NetworkGatewayDevice).filter(
nsx_models.NetworkGatewayDevice.id == device_id)
@ -2179,7 +2190,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
nsx_res['uuid'])
# set NSX GW device in neutron database and update status
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
query = self._model_query(
context, nsx_models.NetworkGatewayDevice).filter(
nsx_models.NetworkGatewayDevice.id == neutron_id)
@ -2218,7 +2229,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
device_status = nsx_utils.get_nsx_device_status(self.cluster,
nsx_id)
# update status
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
query = self._model_query(
context, nsx_models.NetworkGatewayDevice).filter(
nsx_models.NetworkGatewayDevice.id == neutron_id)
@ -2253,7 +2264,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
device_status = nsx_utils.get_nsx_device_status(self.cluster, nsx_id)
# TODO(salv-orlando): Asynchronous sync for gateway device status
# Update status in database
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
query = self._model_query(
context, nsx_models.NetworkGatewayDevice).filter(
nsx_models.NetworkGatewayDevice.id == device_id)
@ -2274,7 +2285,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
nsx_statuses = nsx_utils.get_nsx_device_statuses(self.cluster,
tenant_id)
# Update statuses in database
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
for device in devices:
new_status = nsx_statuses.get(device['nsx_id'])
if new_status:
@ -2349,7 +2360,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
neutron_id = str(uuid.uuid4())
nsx_secgroup = secgrouplib.create_security_profile(
self.cluster, tenant_id, neutron_id, s)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
s['id'] = neutron_id
sec_group = super(NsxPluginV2, self).create_security_group(
context, security_group, default_sg)
@ -2386,7 +2397,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
:param security_group_id: security group rule to remove.
"""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
security_group = super(NsxPluginV2, self).get_security_group(
context, security_group_id)
if not security_group:
@ -2458,7 +2469,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# TODO(arosen) is there anyway we could avoid having the update of
# the security group rules in nsx outside of this transaction?
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
security_group_id = self._validate_security_group_rules(
context, security_group_rules)
# Check to make sure security group exists
@ -2488,7 +2499,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
"""Delete a security group rule
:param sgrid: security group id to remove.
"""
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
# determine security profile id
security_group_rule = (
super(NsxPluginV2, self).get_security_group_rule(

@ -395,7 +395,7 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver):
for port in vdr_ports:
subnet_id = port['fixed_ips'][0]['subnet_id']
port_subnet = self.plugin.get_subnet(
context, subnet_id)
context.elevated(), subnet_id)
if (port_subnet['id'] != subnet['id']
and port_subnet['enable_dhcp']):
# We already have a subnet which is connected to

@ -33,9 +33,6 @@ from oslo_utils import uuidutils
from sqlalchemy.orm import exc as sa_exc
from neutron.api import extensions as neutron_extensions
from neutron.api.rpc.callbacks.consumer import registry as callbacks_registry
from neutron.api.rpc.callbacks import resources as callbacks_resources
from neutron.api.rpc.handlers import resources_rpc
from neutron.api.v2 import attributes as attr
from neutron.callbacks import events
from neutron.callbacks import registry
@ -85,6 +82,7 @@ from neutron.services.qos import qos_consts
from neutron_lib.api.definitions import portbindings as pbin
from vmware_nsx.dvs import dvs
from vmware_nsx.services.qos.common import utils as qos_com_utils
from vmware_nsx.services.qos.nsx_v import driver as qos_driver
from vmware_nsx.services.qos.nsx_v import utils as qos_utils
import vmware_nsx
@ -272,10 +270,6 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# Only expose the extension if it is supported
self.supported_extension_aliases.append("dhcp-mtu")
# Bind QoS notifications
callbacks_registry.register(self._handle_qos_notification,
callbacks_resources.QOS_POLICY)
# Make sure starting rpc listeners (for QoS and other agents)
# will happen only once
self.start_rpc_listeners_called = False
@ -292,6 +286,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
if c_utils.is_nsxv_version_6_2(self.nsx_v.vcns.get_version()):
self.supported_extension_aliases.append("provider-security-group")
# Bind QoS notifications
qos_driver.register(self)
# Register extend dict methods for network and port resources.
# Each extension driver that supports extend attribute for the resources
# can add those attribute to the result.
@ -374,17 +371,6 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
self.conn = n_rpc.create_connection()
self.conn.create_consumer(self.topic, self.endpoints, fanout=False)
# Add QoS
qos_plugin = directory.get_plugin(plugin_const.QOS)
if (qos_plugin and qos_plugin.driver_manager and
qos_plugin.driver_manager.rpc_notifications_required):
# TODO(asarfaty) this option should be deprecated on Pike
qos_topic = resources_rpc.resource_type_versioned_topic(
callbacks_resources.QOS_POLICY)
self.conn.create_consumer(
qos_topic, [resources_rpc.ResourcesPushRpcCallback()],
fanout=False)
self.start_rpc_listeners_called = True
return self.conn.consume_in_threads()
@ -2808,7 +2794,6 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# Will raise FlavorNotFound if doesn't exist
fl_db = flavors_plugin.FlavorsPlugin.get_flavor(
flv_plugin, context, flavor_id)
if fl_db['service_type'] != constants.L3:
raise flavors.InvalidFlavorServiceType(
service_type=fl_db['service_type'])
@ -2914,14 +2899,15 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
gw_info = self._extract_external_gw(context, router)
lrouter = super(NsxVPluginV2, self).create_router(context, router)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
router_db = self._get_router(context, lrouter['id'])
self._process_extra_attr_router_create(context, router_db, r)
self._process_nsx_router_create(context, router_db, r)
self._process_router_flavor_create(context, router_db, r)
lrouter = super(NsxVPluginV2, self).get_router(context,
lrouter['id'])
with db_api.context_manager.reader.using(context):
lrouter = super(NsxVPluginV2, self).get_router(context,
lrouter['id'])
try:
router_driver = self._get_router_driver(context, router_db)
if router_driver.get_type() == nsxv_constants.EXCLUSIVE:
@ -2941,7 +2927,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
except Exception:
with excutils.save_and_reraise_exception():
self.delete_router(context, lrouter['id'])
return self.get_router(context, lrouter['id'])
# re-read the router with the updated data, and return it
with db_api.context_manager.reader.using(context):
return self.get_router(context, lrouter['id'])
def _validate_router_migration(self, context, router_id,
new_router_type, router):
@ -2988,7 +2977,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
old_router_driver.detach_router(context, router_id, router)
# update the router-type
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
router_db = self._get_router(context, router_id)
self._process_nsx_router_create(
context, router_db, router['router'])
@ -3011,7 +3000,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
return router_driver.update_router(context, router_id, router)
def _check_router_in_use(self, context, router_id):
with context.session.begin(subtransactions=True):
with db_api.context_manager.reader.using(context):
# Ensure that the router is not used
router_filter = {'router_id': [router_id]}
fips = self.get_floatingips_count(context.elevated(),
@ -3734,7 +3723,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
sg_id = sg_data["id"] = str(uuid.uuid4())
self._validate_security_group(context, sg_data, default_sg)
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
is_provider = True if sg_data.get(provider_sg.PROVIDER) else False
is_policy = True if sg_data.get(sg_policy.POLICY) else False
if is_provider or is_policy:
@ -4001,7 +3990,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
try:
# Save new rules in Database, including mappings between Nsx rules
# and Neutron security-groups rules
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
new_rule_list = super(
NsxVPluginV2, self).create_security_group_rule_bulk_native(
context, security_group_rules)
@ -4042,7 +4031,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
"nsx-rule %(nsx_rule_id)s doesn't exist.",
{'id': id, 'nsx_rule_id': nsx_rule_id})
with context.session.begin(subtransactions=True):
with db_api.context_manager.writer.using(context):
rule_db = self._get_security_group_rule(context, id)
context.session.delete(rule_db)
def _remove_vnic_from_spoofguard_policy(self, session, net_id, vnic_id):
@ -4193,10 +4183,6 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
if cfg.CONF.nsxv.vdr_transit_network:
edge_utils.validate_vdr_transit_network()
def _handle_qos_notification(self, context, resource_type,
qos_policys, event_type):
qos_utils.handle_qos_notification(qos_policys, event_type, self)
def _nsx_policy_is_hidden(self, policy):
for attrib in policy.get('extendedAttributes', []):
if (attrib['name'].lower() == 'ishidden' and

@ -17,7 +17,6 @@ import netaddr
import six
from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api
from neutron.api.rpc.callbacks.consumer import registry as callbacks_registry
from neutron.api.rpc.callbacks import resources as callbacks_resources
from neutron.api.rpc.handlers import dhcp_rpc
from neutron.api.rpc.handlers import metadata_rpc
@ -67,7 +66,6 @@ from neutron_lib.api import validators
from neutron_lib import constants as const
from neutron_lib import context as q_context
from neutron_lib import exceptions as n_exc
from neutron_lib.plugins import directory
from neutron_lib.utils import helpers
from oslo_config import cfg
from oslo_db import exception as db_exc
@ -99,7 +97,6 @@ from vmware_nsx.plugins.nsx_v3 import availability_zones as nsx_az
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.services.qos.common import utils as qos_com_utils
from vmware_nsx.services.qos.nsx_v3 import driver as qos_driver
from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils
from vmware_nsx.services.trunk.nsx_v3 import driver as trunk_driver
from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
@ -236,7 +233,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
) % NSX_V3_EXCLUDED_PORT_NSGROUP_NAME
raise nsx_exc.NsxPluginException(err_msg=msg)
self._init_qos_callbacks()
qos_driver.register()
self.start_rpc_listeners_called = False
@ -368,9 +365,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
# callback is unsubscribed here since l3 APIs are handled by
# core_plugin instead of an advanced service, in case of NSXv3 plugin,
# and the prevention logic is handled by NSXv3 plugin itself.
registry.unsubscribe(l3_db._prevent_l3_port_delete_callback,
resources.PORT,
events.BEFORE_DELETE)
registry.unsubscribe(
l3_db.L3_NAT_dbonly_mixin._prevent_l3_port_delete_callback,
resources.PORT,
events.BEFORE_DELETE)
def _validate_dhcp_profile(self, dhcp_profile_uuid):
dhcp_profile = self._switching_profiles.get(dhcp_profile_uuid)
@ -491,20 +489,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
cfg.CONF.nsx_v3.log_security_groups_blocked_traffic)
return section_id
def _init_qos_callbacks(self):
# Bind QoS notifications. the RPC option will be deprecated soon,
# but for now we need to support both options
qos_plugin = directory.get_plugin(plugin_const.QOS)
if (qos_plugin and qos_plugin.driver_manager and
qos_plugin.driver_manager.rpc_notifications_required):
# TODO(asarfaty) this option should be deprecated on Pike
self.qos_use_rpc = True
callbacks_registry.register(qos_utils.handle_qos_notification,
callbacks_resources.QOS_POLICY)
else:
self.qos_use_rpc = False
qos_driver.register()
def _init_dhcp_metadata(self):
if cfg.CONF.nsx_v3.native_dhcp_metadata:
if cfg.CONF.dhcp_agent_notification:
@ -2705,7 +2689,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
r, resource_type='os-neutron-router-id',
project_name=context.tenant_name)
router = super(NsxV3Plugin, self).create_router(context, router)
with context.session.begin():
with db_api.context_manager.writer.using(context):
router_db = self._get_router(context, r['id'])
self._process_extra_attr_router_create(context, router_db, r)
# Create backend entries here in case neutron DB exception
@ -2829,9 +2813,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._validate_ext_routes(context, router_id, gw_info,
new_routes)
self._validate_routes(context, router_id, new_routes)
old_routes, routes_dict = (
self._get_extra_routes_dict_by_router_id(
context, router_id))
old_routes = self._get_extra_routes_by_router_id(
context, router_id)
routes_added, routes_removed = helpers.diff_list_of_dict(
old_routes, new_routes)
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
@ -3343,7 +3326,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
super(NsxV3Plugin, self).create_security_group(
context, security_group, default_sg))
nsx_db.save_sg_mappings(context.session,
nsx_db.save_sg_mappings(context,
secgroup_db['id'],
ns_group['id'],
firewall_section['id'])

@ -0,0 +1,71 @@
# Copyright 2017 VMware, Inc.
#
# 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.
from oslo_log import log as logging
from neutron.services.qos.drivers import base
from neutron.services.qos import qos_consts
LOG = logging.getLogger(__name__)
DRIVER = None
SUPPORTED_RULES = [qos_consts.RULE_TYPE_BANDWIDTH_LIMIT,
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH]
class NSXvQosDriver(base.DriverBase):
@staticmethod
def create(core_plugin):
return NSXvQosDriver(
core_plugin,
name='NSXvQosDriver',
vif_types=None,
vnic_types=None,
supported_rules=SUPPORTED_RULES,
requires_rpc_notifications=False)
def __init__(self, core_plugin, **kwargs):
super(NSXvQosDriver, self).__init__(**kwargs)
self.core_plugin = core_plugin
self.requires_rpc_notifications = False
def is_vif_type_compatible(self, vif_type):
return True
def is_vnic_compatible(self, vnic_type):
return True
def create_policy(self, context, policy):
pass
def update_policy(self, context, policy):
# get all the bound networks of this policy
networks = policy.get_bound_networks()
for net_id in networks:
# update the new bw limitations for this network
self.core_plugin._update_qos_on_backend_network(
context, net_id, policy.id)
def delete_policy(self, context, policy):
pass
def register(core_plugin):
"""Register the NSX-V QoS driver."""
global DRIVER
if not DRIVER:
DRIVER = NSXvQosDriver.create(core_plugin)
LOG.debug('NSXvQosDriver QoS driver registered')

@ -14,11 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron.api.rpc.callbacks import events as callbacks_events
from neutron.objects.qos import policy as qos_policy
from neutron.plugins.common import constants
from neutron.services.qos import qos_consts
from neutron_lib import context as n_context
from neutron_lib.plugins import directory
from oslo_config import cfg
@ -85,27 +82,3 @@ class NsxVQosRule(object):
self.dscpMarkValue = rule_obj['dscp_mark']