From 6fa499d2e2df13c26d950b5fba48fe387a23f2f7 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Tue, 26 Dec 2017 11:19:08 +0200 Subject: [PATCH] TVD: fix plugin apis to allow CI job to succeed Change-Id: I46e312f4577d34f406c138ce9d7e9f7dc0d55265 --- vmware_nsx/plugins/dvs/plugin.py | 14 +++- vmware_nsx/plugins/nsx/plugin.py | 116 ++++++++++++++++++++++++--- vmware_nsx/plugins/nsx_v/md_proxy.py | 2 +- 3 files changed, 118 insertions(+), 14 deletions(-) diff --git a/vmware_nsx/plugins/dvs/plugin.py b/vmware_nsx/plugins/dvs/plugin.py index 00f54ecd27..fed23b18bc 100644 --- a/vmware_nsx/plugins/dvs/plugin.py +++ b/vmware_nsx/plugins/dvs/plugin.py @@ -16,7 +16,6 @@ import uuid from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef -from neutron_lib.api.definitions import port as port_def from neutron_lib.api.definitions import port_security as psec from neutron_lib.exceptions import allowedaddresspairs as addr_exc from neutron_lib.exceptions import port_security as psec_exc @@ -133,8 +132,8 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin, return False @staticmethod - @resource_extend.extends([port_def.COLLECTION_NAME]) def _extend_port_dict_binding(result, portdb): + LOG.error("DEBUG ADIT DVS _extend_port_dict_binding") result[pbin.VIF_TYPE] = nsx_constants.VIF_TYPE_DVS port_attr = portdb.get('nsx_port_attributes') if port_attr: @@ -432,6 +431,7 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin, # latest db model for the extension functions port_model = self._get_port(context, port_data['id']) resource_extend.apply_funcs('ports', port_data, port_model) + self._extend_port_dict_binding(port_data, port_model) self.handle_port_dhcp_access(context, port_data, action='create_port') return port_data @@ -507,6 +507,16 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin, self.handle_port_dhcp_access( context, neutron_db_port, action='delete_port') + def get_port(self, context, id, fields=None): + port = super(NsxDvsV2, self).get_port(context, id, fields=None) + if 'id' in port: + port_model = self._get_port(context, port['id']) + resource_extend.apply_funcs('ports', port, port_model) + self._extend_port_dict_binding(port, port_model) + self._extend_get_port_dict_qos_and_binding(context, port) + self._remove_provider_security_groups_from_list(port) + return db_utils.resource_fields(port, fields) + def create_router(self, context, router): # DVS backend cannot support logical router msg = (_("Unable to create router %s with DVS") % diff --git a/vmware_nsx/plugins/nsx/plugin.py b/vmware_nsx/plugins/nsx/plugin.py index ca16c31e8e..2767d7b7ff 100644 --- a/vmware_nsx/plugins/nsx/plugin.py +++ b/vmware_nsx/plugins/nsx/plugin.py @@ -16,20 +16,27 @@ from neutron_lib.api.definitions import network as net_def from neutron_lib.api.definitions import port as port_def from neutron_lib.api.definitions import subnet as subnet_def +from neutron_lib.callbacks import events +from neutron_lib.callbacks import registry +from neutron_lib.callbacks import resources from neutron_lib import context as n_context +from neutron_lib.plugins import constants as plugin_constants from neutron_lib.plugins import directory from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from neutron.db import _resource_extend as resource_extend from neutron.db import _utils as db_utils from neutron.db import agents_db +from neutron.db import agentschedulers_db from neutron.db import allowedaddresspairs_db as addr_pair_db from neutron.db import api as db_api from neutron.db.availability_zone import router as router_az_db from neutron.db import external_net_db from neutron.db import extradhcpopt_db from neutron.db import extraroute_db +from neutron.db import l3_db from neutron.db import l3_gwmode_db from neutron.db.models import l3 as l3_db_models from neutron.db.models import securitygroup as securitygroup_model # noqa @@ -61,7 +68,8 @@ TVD_PLUGIN_TYPE = "Nsx-TVD" @resource_extend.has_resource_extenders -class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, +class NsxTVDPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, + addr_pair_db.AllowedAddressPairsMixin, agents_db.AgentDbMixin, nsx_plugin_common.NsxPluginBase, rt_rtr.RouterType_mixin, @@ -78,7 +86,7 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, supported_extension_aliases = ['project-plugin-map'] - __native_bulk_support = False + __native_bulk_support = True __native_pagination_support = True __native_sorting_support = True @@ -106,6 +114,8 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, self.init_extensions() self.lbv2_driver = lb_driver_v2.EdgeLoadbalancerDriverV2() + self._unsubscribe_callback_events() + @staticmethod def plugin_type(): return TVD_PLUGIN_TYPE @@ -183,6 +193,36 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, self._unsupported_fields[plugin_type]['port'] = [ 'mac_learning_enabled', 'provider_security_groups'] + def _unsubscribe_callback_events(self): + # unsubscribe the callback that should be called on all plugins + # other that NSX-T. + registry.unsubscribe_all( + l3_db.L3_NAT_dbonly_mixin._prevent_l3_port_delete_callback) + + # Instead we will subscribe our internal callback. + registry.subscribe(self._prevent_l3_port_delete_callback, + resources.PORT, events.BEFORE_DELETE) + + @staticmethod + def _prevent_l3_port_delete_callback(resource, event, trigger, **kwargs): + """Register a callback to replace the default one + + This callback will prevent port deleting only if the port plugin + is not NSX-T (in NSX-T plugin it was already handled) + """ + context = kwargs['context'] + port_id = kwargs['port_id'] + port_check = kwargs['port_check'] + l3plugin = directory.get_plugin(plugin_constants.L3) + if l3plugin and port_check: + # if not nsx-t - call super code + core_plugin = directory.get_plugin() + db_port = core_plugin._get_port(context, port_id) + p = core_plugin._get_plugin_from_net_id( + context, db_port['network_id']) + if p.plugin_type() != projectpluginmap.NsxPlugins.NSX_T: + l3plugin.prevent_l3_port_deletion(context, port_id) + def _validate_obj_extensions(self, data, plugin_type, obj_type): """prevent configuration of unsupported extensions""" for field in self._unsupported_fields[plugin_type][obj_type]: @@ -228,6 +268,46 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, p = self._get_plugin_from_project(context, tenant_id) return p.create_network(context, network) + def _create_bulk(self, resource, context, request_items): + objects = [] + collection = "%ss" % resource + items = request_items[collection] + try: + with db_api.context_manager.writer.using(context): + for item in items: + obj_creator = getattr(self, 'create_%s' % resource) + objects.append(obj_creator(context, item)) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("An exception occurred while creating " + "the %(resource)s:%(item)s", + {'resource': resource, 'item': item}) + return objects + + @db_api.retry_if_session_inactive() + def create_network_bulk(self, context, networks): + #Implement create bulk so that the plugin calculation will be done once + objects = [] + items = networks['networks'] + + # look at the first network to find out the project & plugin + net_data = items[0]['network'] + tenant_id = net_data['tenant_id'] + self._ensure_default_security_group(context, tenant_id) + p = self._get_plugin_from_project(context, tenant_id) + + # create all networks one by one + try: + with db_api.context_manager.writer.using(context): + for item in items: + objects.append(p.create_network(context, item)) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("An exception occurred while creating " + "the networks:%(item)s", + {'item': item}) + return objects + def delete_network(self, context, id): p = self._get_plugin_from_net_id(context, id) p.delete_network(context, id) @@ -454,11 +534,11 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, p = self._get_plugin_from_net_id(context, net_id) return p.delete_floatingip(context, id) - def get_floatingip(self, context, id): + def get_floatingip(self, context, id, fields=None): fip = self._get_floatingip(context, id) net_id = fip['floating_network_id'] p = self._get_plugin_from_net_id(context, net_id) - return p.get_floatingip(context, id) + return p.get_floatingip(context, id, fields=fields) def disassociate_floatingips(self, context, port_id): db_port = self._get_port(context, port_id) @@ -490,9 +570,9 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, p = self._get_plugin_from_sg_id(context, id) return p.update_security_group(context, id, security_group) - def get_security_group(self, context, id): + def get_security_group(self, context, id, fields=None): p = self._get_plugin_from_sg_id(context, id) - return p.get_security_group(context, id) + return p.get_security_group(context, id, fields=fields) def create_security_group_rule_bulk(self, context, security_group_rules): p = self._get_plugin_from_project(context, context.project_id) @@ -504,7 +584,9 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, return p.create_security_group_rule(context, security_group_rule) def delete_security_group_rule(self, context, id): - p = self._get_plugin_from_sg_id(context, id) + rule_db = self._get_security_group_rule(context, id) + sg_id = rule_db['security_group_id'] + p = self._get_plugin_from_sg_id(context, sg_id) p.delete_security_group_rule(context, id) @staticmethod @@ -582,14 +664,26 @@ class NsxTVDPlugin(addr_pair_db.AllowedAddressPairsMixin, If not there - add an entry with the default plugin """ plugin_type = self.default_plugin + if not project_id: + # if the project_id is empty - return the default one and do not + # add to db (used by admin context to get actions) + return plugin_type + mapping = nsx_db.get_project_plugin_mapping( context.session, project_id) if mapping: plugin_type = mapping['plugin'] - elif project_id: - self.create_project_plugin_map(context, - {'project_plugin_map': {'plugin': plugin_type, - 'project': project_id}}) + else: + # add a new entry with the default plugin + try: + # TODO(asarfaty) we get timeout here when called under + # _ext_extend_network_dict of the first create_network + self.create_project_plugin_map(context, + {'project_plugin_map': {'plugin': plugin_type, + 'project': project_id}}) + except projectpluginmap.ProjectPluginAlreadyExists: + # Maybe added by another thread + pass if not self.plugins.get(plugin_type): msg = (_("Cannot use unsupported plugin %(plugin)s for project " "%(project)s") % {'plugin': plugin_type, diff --git a/vmware_nsx/plugins/nsx_v/md_proxy.py b/vmware_nsx/plugins/nsx_v/md_proxy.py index d57a950762..843e1a7a96 100644 --- a/vmware_nsx/plugins/nsx_v/md_proxy.py +++ b/vmware_nsx/plugins/nsx_v/md_proxy.py @@ -127,7 +127,7 @@ class NsxVMetadataProxyHandler(object): core_plugin.create_project_plugin_map( context, {'project_plugin_map': - {'plugin': projectpluginmap.NsxPlugins.NSX_T, + {'plugin': projectpluginmap.NsxPlugins.NSX_V, 'project': nsxv_constants.INTERNAL_TENANT_ID}}) except projectpluginmap.ProjectPluginAlreadyExists: pass