From 00c816de0118090f4b6f889b91e9d3aa1c0306c6 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Fri, 5 Oct 2018 10:42:30 +0100 Subject: [PATCH] Use NetworkRBAC OVO in neutron/db/db_base_plugin_v2.py Migrate to use NetworkRBAC OVO in NeutronDBPluginV2. Partially-Implements: blueprint adopt-oslo-versioned-objects-for-db Change-Id: I202318b4a4b91d03177d5e9792565e9daa44f9fb --- neutron/db/db_base_plugin_v2.py | 61 +++++++++++----------- neutron/objects/network.py | 14 ++++- neutron/tests/unit/objects/test_objects.py | 2 +- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 0e8517cb426..bce3d4c1b63 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -37,7 +37,6 @@ from oslo_db import exception as os_db_exc from oslo_log import log as logging from oslo_utils import excutils from oslo_utils import uuidutils -from sqlalchemy import and_ from sqlalchemy import exc as sql_exc from sqlalchemy import not_ @@ -53,13 +52,13 @@ from neutron.db import db_base_plugin_common from neutron.db import ipam_pluggable_backend from neutron.db import models_v2 from neutron.db import rbac_db_mixin as rbac_mixin -from neutron.db import rbac_db_models as rbac_db from neutron.db import standardattrdescription_db as stattr_db from neutron import ipam from neutron.ipam import exceptions as ipam_exc from neutron.ipam import subnet_alloc from neutron import neutron_plugin_base_v2 from neutron.objects import base as base_obj +from neutron.objects import network as network_obj from neutron.objects import ports as port_obj from neutron.objects import subnet as subnet_obj from neutron.objects import subnetpool as subnetpool_obj @@ -222,30 +221,27 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, def ensure_no_tenant_ports_on_network(self, network_id, net_tenant_id, tenant_id): ctx_admin = ctx.get_admin_context() - rb_model = rbac_db.NetworkRBAC - other_rbac_entries = model_query.query_with_hooks( - ctx_admin, rb_model).filter( - and_(rb_model.object_id == network_id, - rb_model.action == 'access_as_shared')) ports = model_query.query_with_hooks(ctx_admin, models_v2.Port).filter( models_v2.Port.network_id == network_id) if tenant_id == '*': # for the wildcard we need to get all of the rbac entries to # see if any allow the remaining ports on the network. - other_rbac_entries = other_rbac_entries.filter( - rb_model.target_tenant != tenant_id) # any port with another RBAC entry covering it or one belonging to # the same tenant as the network owner is ok - allowed_tenants = [entry['target_tenant'] - for entry in other_rbac_entries] + other_rbac_objs = network_obj.NetworkRBAC.get_objects( + ctx_admin, object_id=network_id, action='access_as_shared') + allowed_tenants = [rbac['target_tenant'] for rbac + in other_rbac_objs + if rbac.target_tenant != tenant_id] allowed_tenants.append(net_tenant_id) ports = ports.filter( ~models_v2.Port.tenant_id.in_(allowed_tenants)) else: # if there is a wildcard rule, we can return early because it # allows any ports - query = other_rbac_entries.filter(rb_model.target_tenant == '*') - if query.count(): + if network_obj.NetworkRBAC.get_object( + ctx_admin, object_id=network_id, action='access_as_shared', + target_tenant='*'): return ports = ports.filter(models_v2.Port.tenant_id == tenant_id) if ports.count(): @@ -290,14 +286,10 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, def _validate_projects_have_access_to_network(self, network, project_ids): ctx_admin = ctx.get_admin_context() - rb_model = rbac_db.NetworkRBAC - other_rbac_entries = model_query.query_with_hooks( - ctx_admin, rb_model).filter( - and_(rb_model.object_id == network.id, - rb_model.action == 'access_as_shared', - rb_model.target_tenant != "*")) - allowed_projects = {entry['target_tenant'] - for entry in other_rbac_entries} + other_rbac_objs = network_obj.NetworkRBAC.get_objects( + ctx_admin, object_id=network.id, action='access_as_shared') + allowed_projects = {rbac['target_tenant'] for rbac in other_rbac_objs + if rbac.target_tenant != '*'} allowed_projects.add(network.project_id) if project_ids - allowed_projects: raise n_exc.InvalidSharedSetting(network=network.name) @@ -403,12 +395,14 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, 'status': n.get('status', constants.NET_STATUS_ACTIVE), 'description': n.get('description')} network = models_v2.Network(**args) - if n['shared']: - entry = rbac_db.NetworkRBAC( - network=network, action='access_as_shared', - target_tenant='*', tenant_id=network['tenant_id']) - context.session.add(entry) context.session.add(network) + if n['shared']: + np_rbac_args = {'project_id': network.project_id, + 'object_id': network.id, + 'action': 'access_as_shared', + 'target_tenant': '*'} + np_rbac_obj = network_obj.NetworkRBAC(context, **np_rbac_args) + np_rbac_obj.create() return network @lib_db_api.retry_if_session_inactive() @@ -428,12 +422,17 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, self._validate_shared_update(context, id, network, n) update_shared = n.pop('shared') if update_shared and not entry: - entry = rbac_db.NetworkRBAC( - network=network, action='access_as_shared', - target_tenant='*', tenant_id=network['tenant_id']) - context.session.add(entry) + np_rbac_args = {'project_id': network.project_id, + 'object_id': network.id, + 'action': 'access_as_shared', + 'target_tenant': '*'} + np_rbac_obj = network_obj.NetworkRBAC(context, + **np_rbac_args) + np_rbac_obj.create() elif not update_shared and entry: - network.rbac_entries.remove(entry) + network_obj.NetworkRBAC.delete_objects( + context, object_id=network.id, + action='access_as_shared', target_tenant='*') # TODO(ihrachys) Below can be removed when we make sqlalchemy # event listeners in neutron/db/api.py to refresh expired diff --git a/neutron/objects/network.py b/neutron/objects/network.py index e9eafbe5dca..69a19d5aac1 100644 --- a/neutron/objects/network.py +++ b/neutron/objects/network.py @@ -14,6 +14,7 @@ from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api.validators import availability_zone as az_validator +from oslo_utils import versionutils from oslo_versionedobjects import fields as obj_fields from neutron.db.models import dns as dns_models @@ -34,16 +35,27 @@ from neutron.objects import rbac_db @base.NeutronObjectRegistry.register class NetworkRBAC(base.NeutronDbObject): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Added 'id' and 'project_id' + + VERSION = '1.1' db_model = rbac_db_models.NetworkRBAC fields = { + 'id': common_types.UUIDField(), + 'project_id': obj_fields.StringField(), 'object_id': obj_fields.StringField(), 'target_tenant': obj_fields.StringField(), 'action': obj_fields.StringField(), } + def obj_make_compatible(self, primitive, target_version): + _target_version = versionutils.convert_version_to_tuple(target_version) + if _target_version < (1, 1): + standard_fields = ['id', 'project_id'] + for f in standard_fields: + primitive.pop(f, None) + @base.NeutronObjectRegistry.register class NetworkDhcpAgentBinding(base.NeutronDbObject): diff --git a/neutron/tests/unit/objects/test_objects.py b/neutron/tests/unit/objects/test_objects.py index 8777e3b40d7..2070a3a9e47 100644 --- a/neutron/tests/unit/objects/test_objects.py +++ b/neutron/tests/unit/objects/test_objects.py @@ -60,7 +60,7 @@ object_data = { 'NetworkDhcpAgentBinding': '1.0-6eeceb5fb4335cd65a305016deb41c68', 'NetworkDNSDomain': '1.0-420db7910294608534c1e2e30d6d8319', 'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3', - 'NetworkRBAC': '1.0-c8a67f39809c5a3c8c7f26f2f2c620b2', + 'NetworkRBAC': '1.1-7f8baaf9ea4257a26408454ad0065adb', 'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8', 'Port': '1.4-1b6183bccfc2cd210919a1a72faefce1', 'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578',