From a7b5bfafcccdf424f5458a216c8e920388734a06 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Wed, 14 Sep 2016 08:13:55 +0300 Subject: [PATCH] nsxlib refactor continue - separate nsxlib/v3 constants and utils from the common ones - separate the nsxlib/v3 tests - update the nsxlib tests to cover create_firewall_rules - remove all of the DB calls from the nsxlib/v3 - merge security & dfw_api classes To be done in future patches: - Avoid using the nsx configuration values directly - Improve nsxlib interface (as Aaron suggested in If2fe1e014b78703ff0a9cdff1e4e8d45f3a4a16d) Change-Id: I43257f557ce1e98b4f64b8157d723cc84ea58c2b --- vmware_nsx/common/nsx_constants.py | 44 --- vmware_nsx/common/utils.py | 142 +------ vmware_nsx/db/db.py | 49 ++- ...2c585_nsxv3_add_nsx_dhcp_service_tables.py | 2 +- vmware_nsx/db/nsx_models.py | 2 +- vmware_nsx/db/nsxv_db.py | 21 +- vmware_nsx/nsxlib/v3/__init__.py | 32 +- vmware_nsx/nsxlib/v3/dfw_api.py | 269 ------------- vmware_nsx/nsxlib/v3/native_dhcp.py | 2 +- vmware_nsx/nsxlib/v3/ns_group_manager.py | 17 +- vmware_nsx/nsxlib/v3/nsx_constants.py | 96 +++++ vmware_nsx/nsxlib/v3/resources.py | 18 +- vmware_nsx/nsxlib/v3/router.py | 4 +- vmware_nsx/nsxlib/v3/security.py | 364 +++++++++++++----- vmware_nsx/nsxlib/v3/utils.py | 171 ++++++++ vmware_nsx/plugins/nsx_v3/plugin.py | 156 +++++--- .../services/l2gateway/nsx_v3/driver.py | 5 +- .../services/neutron_taas/nsx_v3/driver.py | 4 +- vmware_nsx/services/qos/nsx_v3/utils.py | 2 +- .../plugins/nsxv3/resources/dhcp_binding.py | 2 +- .../plugins/nsxv3/resources/metadata_proxy.py | 5 +- .../plugins/nsxv3/resources/securitygroups.py | 15 +- .../admin/plugins/nsxv3/resources/utils.py | 2 +- .../test_secgroup_rule_local_ip_prefix.py | 3 +- .../unit/extensions/test_securitygroup.py | 67 ++-- .../tests/unit/nsx_v3/test_constants.py | 145 ------- .../tests/unit/nsx_v3/test_dhcp_metadata.py | 5 +- vmware_nsx/tests/unit/nsx_v3/test_plugin.py | 2 +- .../tests/unit/{nsx_v3 => nsxlib/v3}/mocks.py | 4 +- .../tests/unit/nsxlib/v3/nsxlib_testcase.py | 14 +- .../tests/unit/nsxlib/v3/test_client.py | 2 +- .../tests/unit/nsxlib/v3/test_cluster.py | 2 +- .../tests/unit/nsxlib/v3/test_constants.py | 162 ++++++++ .../nsxlib/v3/test_qos_switching_profile.py | 2 +- .../tests/unit/nsxlib/v3/test_resources.py | 4 +- .../tests/unit/nsxlib/v3/test_switch.py | 4 +- .../unit/{nsx_v3 => nsxlib/v3}/test_utils.py | 8 +- .../services/l2gateway/test_nsxv3_driver.py | 4 +- .../services/qos/test_nsxv3_notification.py | 2 +- 39 files changed, 977 insertions(+), 877 deletions(-) delete mode 100644 vmware_nsx/nsxlib/v3/dfw_api.py create mode 100644 vmware_nsx/nsxlib/v3/nsx_constants.py create mode 100644 vmware_nsx/nsxlib/v3/utils.py rename vmware_nsx/tests/unit/{nsx_v3 => nsxlib/v3}/mocks.py (98%) create mode 100644 vmware_nsx/tests/unit/nsxlib/v3/test_constants.py rename vmware_nsx/tests/unit/{nsx_v3 => nsxlib/v3}/test_utils.py (97%) diff --git a/vmware_nsx/common/nsx_constants.py b/vmware_nsx/common/nsx_constants.py index b5b91624de..f9c54d0405 100644 --- a/vmware_nsx/common/nsx_constants.py +++ b/vmware_nsx/common/nsx_constants.py @@ -13,52 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -# Admin statuses -ADMIN_STATE_UP = "UP" -ADMIN_STATE_DOWN = "DOWN" - -ADMIN_STATUSES = [ADMIN_STATE_UP, ADMIN_STATE_DOWN] - -# Port attachment types -ATTACHMENT_VIF = "VIF" -ATTACHMENT_LR = "LOGICALROUTER" -ATTACHMENT_DHCP = "DHCP_SERVICE" -ATTACHMENT_MDPROXY = "METADATA_PROXY" -ATTACHMENT_CIF = "CIF" -CIF_RESOURCE_TYPE = "CifAttachmentContext" - -ATTACHMENT_TYPES = [ATTACHMENT_VIF, ATTACHMENT_LR] - -# Replication modes -MTEP = "MTEP" -SOURCE = "SOURCE" - -REPLICATION_MODES = [MTEP, SOURCE] - -# Router type -ROUTER_TYPE_TIER0 = "TIER0" -ROUTER_TYPE_TIER1 = "TIER1" - -ROUTER_TYPES = [ROUTER_TYPE_TIER0, ROUTER_TYPE_TIER1] - -LROUTERPORT_UPLINK = "LogicalRouterUplinkPort" -LROUTERPORT_DOWNLINK = "LogicalRouterDownLinkPort" -LROUTERPORT_LINKONTIER0 = "LogicalRouterLinkPortOnTIER0" -LROUTERPORT_LINKONTIER1 = "LogicalRouterLinkPortOnTIER1" - -LROUTER_TYPES = [LROUTERPORT_UPLINK, - LROUTERPORT_DOWNLINK, - LROUTERPORT_LINKONTIER0, - LROUTERPORT_LINKONTIER1] - # L2 agent vif type VIF_TYPE_DVS = 'dvs' -# NSXv3 L2 Gateway constants -BRIDGE_ENDPOINT = "BRIDGEENDPOINT" - -# NSX service type -SERVICE_DHCP = "dhcp" - # NSXv3 CORE PLUGIN PATH VMWARE_NSX_V3_PLUGIN_NAME = 'vmware_nsx.plugin.NsxV3Plugin' diff --git a/vmware_nsx/common/utils.py b/vmware_nsx/common/utils.py index 0a62feed47..b7d795ef9f 100644 --- a/vmware_nsx/common/utils.py +++ b/vmware_nsx/common/utils.py @@ -18,25 +18,20 @@ import functools import hashlib import eventlet +import six + from neutron import version as n_version from neutron_lib.api import validators from neutron_lib import constants -from neutron_lib import exceptions -from oslo_config import cfg from oslo_context import context as common_context from oslo_log import log -import retrying -import six -from vmware_nsx._i18n import _, _LE +from vmware_nsx._i18n import _LE LOG = log.getLogger(__name__) MAX_DISPLAY_NAME_LEN = 40 -MAX_RESOURCE_TYPE_LEN = 20 -MAX_TAG_LEN = 40 NEUTRON_VERSION = n_version.version_info.release_string() -NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin' OS_NEUTRON_ID_SCOPE = 'os-neutron-id' NSXV3_VERSION_1_1_0 = '1.1.0' @@ -111,137 +106,6 @@ def check_and_truncate(display_name): return display_name or '' -def is_internal_resource(nsx_resource): - """ - Indicates whether the passed nsx-resource is owned by the plugin for - internal use. - """ - for tag in nsx_resource.get('tags', []): - if tag['scope'] == OS_NEUTRON_ID_SCOPE: - return tag['tag'] == NSX_NEUTRON_PLUGIN - return False - - -def build_v3_api_version_tag(): - """ - Some resources are created on the manager that do not have a corresponding - Neutron resource. - """ - return [{'scope': OS_NEUTRON_ID_SCOPE, - 'tag': NSX_NEUTRON_PLUGIN}, - {'scope': "os-api-version", - 'tag': n_version.version_info.release_string()}] - - -def _validate_resource_type_length(resource_type): - # Add in a validation to ensure that we catch this at build time - if len(resource_type) > MAX_RESOURCE_TYPE_LEN: - raise exceptions.InvalidInput( - error_message=(_('Resource type cannot exceed %(max_len)s ' - 'characters: %(resource_type)s') % - {'max_len': MAX_RESOURCE_TYPE_LEN, - 'resource_type': resource_type})) - - -def build_v3_tags_payload(resource, resource_type, project_name): - """ - Construct the tags payload that will be pushed to NSX-v3 - Add :, os-project-id:, - os-project-name: os-api-version: - """ - _validate_resource_type_length(resource_type) - # There may be cases when the plugin creates the port, for example DHCP - if not project_name: - project_name = 'NSX Neutron plugin' - tenant_id = resource.get('tenant_id', '') - # If tenant_id is present in resource and set to None, explicitly set - # the tenant_id in tags as ''. - if tenant_id is None: - tenant_id = '' - return [{'scope': resource_type, - 'tag': resource.get('id', '')[:MAX_TAG_LEN]}, - {'scope': 'os-project-id', - 'tag': tenant_id[:MAX_TAG_LEN]}, - {'scope': 'os-project-name', - 'tag': project_name[:MAX_TAG_LEN]}, - {'scope': 'os-api-version', - 'tag': n_version.version_info.release_string()[:MAX_TAG_LEN]}] - - -def add_v3_tag(tags, resource_type, tag): - _validate_resource_type_length(resource_type) - tags.append({'scope': resource_type, 'tag': tag[:MAX_TAG_LEN]}) - return tags - - -def update_v3_tags(current_tags, tags_update): - current_scopes = set([tag['scope'] for tag in current_tags]) - updated_scopes = set([tag['scope'] for tag in tags_update]) - - tags = [{'scope': tag['scope'], 'tag': tag['tag']} - for tag in (current_tags + tags_update) - if tag['scope'] in (current_scopes ^ updated_scopes)] - - modified_scopes = current_scopes & updated_scopes - for tag in tags_update: - if tag['scope'] in modified_scopes: - # If the tag value is empty or None, then remove the tag completely - if tag['tag']: - tag['tag'] = tag['tag'][:MAX_TAG_LEN] - tags.append(tag) - - return tags - - -def retry_upon_exception_nsxv3(exc, delay=500, max_delay=2000, - max_attempts=cfg.CONF.nsx_v3.retries): - return retrying.retry(retry_on_exception=lambda e: isinstance(e, exc), - wait_exponential_multiplier=delay, - wait_exponential_max=max_delay, - stop_max_attempt_number=max_attempts) - - -def list_match(list1, list2): - # Check if list1 and list2 have identical elements, but relaxed on - # dict elements where list1's dict element can be a subset of list2's - # corresponding element. - if (not isinstance(list1, list) or - not isinstance(list2, list) or - len(list1) != len(list2)): - return False - list1 = sorted(list1) - list2 = sorted(list2) - for (v1, v2) in zip(list1, list2): - if isinstance(v1, dict): - if not dict_match(v1, v2): - return False - elif isinstance(v1, list): - if not list_match(v1, v2): - return False - elif v1 != v2: - return False - return True - - -def dict_match(dict1, dict2): - # Check if dict1 is a subset of dict2. - if not isinstance(dict1, dict) or not isinstance(dict2, dict): - return False - for k1, v1 in dict1.items(): - if k1 not in dict2: - return False - v2 = dict2[k1] - if isinstance(v1, dict): - if not dict_match(v1, v2): - return False - elif isinstance(v1, list): - if not list_match(v1, v2): - return False - elif v1 != v2: - return False - return True - - def read_file(path): try: with open(path) as file: diff --git a/vmware_nsx/db/db.py b/vmware_nsx/db/db.py index 3ac9b53009..091a8745cb 100644 --- a/vmware_nsx/db/db.py +++ b/vmware_nsx/db/db.py @@ -14,10 +14,12 @@ # License for the specific language governing permissions and limitations # under the License. +import six +from sqlalchemy.orm import exc + from oslo_db import exception as db_exc from oslo_log import log as logging from oslo_utils import excutils -from sqlalchemy.orm import exc import neutron.db.api as db @@ -27,6 +29,20 @@ from vmware_nsx.db import nsx_models LOG = logging.getLogger(__name__) +def _apply_filters_to_query(query, model, filters, like_filters=None): + if filters: + for key, value in six.iteritems(filters): + column = getattr(model, key, None) + if column: + query = query.filter(column.in_(value)) + if like_filters: + for key, search_term in six.iteritems(like_filters): + column = getattr(model, key, None) + if column: + query = query.filter(column.like(search_term)) + return query + + def get_network_bindings(session, network_id): session = session or db.get_session() return (session.query(nsx_models.TzNetworkBinding). @@ -247,6 +263,19 @@ def get_nsx_security_group_id(session, neutron_id): return None +def get_nsx_security_group_ids(session, neutron_ids): + """Return list of ids of a security groups in the NSX backend. + """ + filters = {'neutron_id': neutron_ids} + like_filters = None + query = session.query(nsx_models.NeutronNsxSecurityGroupMapping) + mappings = _apply_filters_to_query( + query, nsx_models.NeutronNsxSecurityGroupMapping, + filters, like_filters).all() + return [mapping['nsx_id'] for mapping in mappings + if mapping['nsx_id'] is not None] + + def _delete_by_neutron_id(session, model, neutron_id): return session.query(model).filter_by(neutron_id=neutron_id).delete() @@ -361,8 +390,26 @@ def save_sg_mappings(session, sg_id, nsgroup_id, section_id): nsx_id=nsgroup_id)) +def get_sg_mappings(session, sg_id): + nsgroup_mapping = session.query( + nsx_models.NeutronNsxSecurityGroupMapping + ).filter_by(neutron_id=sg_id).one() + section_mapping = session.query( + nsx_models.NeutronNsxFirewallSectionMapping + ).filter_by(neutron_id=sg_id).one() + return nsgroup_mapping.nsx_id, section_mapping.nsx_id + + def get_sg_rule_mapping(session, rule_id): rule_mapping = session.query( nsx_models.NeutronNsxRuleMapping).filter_by( neutron_id=rule_id).one() return rule_mapping.nsx_id + + +def save_sg_rule_mappings(session, rules): + with session.begin(subtransactions=True): + for neutron_id, nsx_id in rules: + mapping = nsx_models.NeutronNsxRuleMapping( + neutron_id=neutron_id, nsx_id=nsx_id) + session.add(mapping) diff --git a/vmware_nsx/db/migration/alembic_migrations/versions/newton/expand/c644ec62c585_nsxv3_add_nsx_dhcp_service_tables.py b/vmware_nsx/db/migration/alembic_migrations/versions/newton/expand/c644ec62c585_nsxv3_add_nsx_dhcp_service_tables.py index b8884c6f9e..42a49a4860 100644 --- a/vmware_nsx/db/migration/alembic_migrations/versions/newton/expand/c644ec62c585_nsxv3_add_nsx_dhcp_service_tables.py +++ b/vmware_nsx/db/migration/alembic_migrations/versions/newton/expand/c644ec62c585_nsxv3_add_nsx_dhcp_service_tables.py @@ -27,7 +27,7 @@ down_revision = 'c288bb6a7252' from alembic import op import sqlalchemy as sa -from vmware_nsx.common import nsx_constants +from vmware_nsx.nsxlib.v3 import nsx_constants nsx_service_type_enum = sa.Enum( diff --git a/vmware_nsx/db/nsx_models.py b/vmware_nsx/db/nsx_models.py index a409e4a532..1ee9edc086 100644 --- a/vmware_nsx/db/nsx_models.py +++ b/vmware_nsx/db/nsx_models.py @@ -27,7 +27,7 @@ from sqlalchemy import sql from neutron.db import models_v2 from oslo_db.sqlalchemy import models -from vmware_nsx.common import nsx_constants +from vmware_nsx.nsxlib.v3 import nsx_constants class TzNetworkBinding(model_base.BASEV2, models.TimestampMixin): diff --git a/vmware_nsx/db/nsxv_db.py b/vmware_nsx/db/nsxv_db.py index af135a7f40..23c4b41633 100644 --- a/vmware_nsx/db/nsxv_db.py +++ b/vmware_nsx/db/nsxv_db.py @@ -29,6 +29,7 @@ from sqlalchemy.sql import expression as expr from vmware_nsx._i18n import _, _LE, _LW from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import nsxv_constants +from vmware_nsx.db import db as nsx_db from vmware_nsx.db import nsxv_models from vmware_nsx.extensions import dhcp_mtu as ext_dhcp_mtu from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain @@ -38,20 +39,6 @@ NsxvEdgeDhcpStaticBinding = nsxv_models.NsxvEdgeDhcpStaticBinding LOG = logging.getLogger(__name__) -def _apply_filters_to_query(query, model, filters, like_filters=None): - if filters: - for key, value in six.iteritems(filters): - column = getattr(model, key, None) - if column: - query = query.filter(column.in_(value)) - if like_filters: - for key, search_term in six.iteritems(like_filters): - column = getattr(model, key, None) - if column: - query = query.filter(column.like(search_term)) - return query - - def add_nsxv_router_binding(session, router_id, vse_id, lswitch_id, status, appliance_size=nsxv_constants.LARGE, edge_type=nsxv_constants.SERVICE_EDGE, @@ -117,8 +104,8 @@ def get_nsxv_router_bindings(session, filters=None, like_filters=None): session = db.get_session() query = session.query(nsxv_models.NsxvRouterBinding) - return _apply_filters_to_query(query, nsxv_models.NsxvRouterBinding, - filters, like_filters).all() + return nsx_db._apply_filters_to_query(query, nsxv_models.NsxvRouterBinding, + filters, like_filters).all() def update_nsxv_router_binding(session, router_id, **kwargs): @@ -586,7 +573,7 @@ def get_nsxv_spoofguard_policy_network_mappings(session, filters=None, like_filters=None): session = db.get_session() query = session.query(nsxv_models.NsxvSpoofGuardPolicyNetworkMapping) - return _apply_filters_to_query( + return nsx_db._apply_filters_to_query( query, nsxv_models.NsxvSpoofGuardPolicyNetworkMapping, filters, like_filters).all() diff --git a/vmware_nsx/nsxlib/v3/__init__.py b/vmware_nsx/nsxlib/v3/__init__.py index 173eb14f79..c31b800eca 100644 --- a/vmware_nsx/nsxlib/v3/__init__.py +++ b/vmware_nsx/nsxlib/v3/__init__.py @@ -16,23 +16,17 @@ from oslo_log import log from vmware_nsx._i18n import _, _LW -from vmware_nsx.common import nsx_constants -from vmware_nsx.common import utils from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import cluster -from vmware_nsx.nsxlib.v3 import dfw_api from vmware_nsx.nsxlib.v3 import exceptions +from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import security +from vmware_nsx.nsxlib.v3 import utils LOG = log.getLogger(__name__) -# Max amount of time to try a request -DEFAULT_MAX_ATTEMPTS = 3 - -class NsxLib(dfw_api.DfwApi, security.Security): - - MAX_ATTEMPTS = DEFAULT_MAX_ATTEMPTS +class NsxLib(security.Security): def __init__(self, username=None, @@ -45,9 +39,11 @@ class NsxLib(dfw_api.DfwApi, security.Security): http_read_timeout=None, conn_idle_timeout=None, http_provider=None, - max_attempts=DEFAULT_MAX_ATTEMPTS): + max_attempts=0): - self.max_attempts = max_attempts + # TODO(asarfaty): use max_attempts instead of cfg value + + # create the Cluster self.cluster = cluster.NSXClusteredAPI( username=username, password=password, retries=retries, insecure=insecure, @@ -58,7 +54,9 @@ class NsxLib(dfw_api.DfwApi, security.Security): conn_idle_timeout=conn_idle_timeout, http_provider=http_provider) + # create the Client self.client = client.NSX3Client(self.cluster) + super(NsxLib, self).__init__() def get_version(self): @@ -70,7 +68,7 @@ class NsxLib(dfw_api.DfwApi, security.Security): resource = "edge-clusters/%s" % edge_cluster_uuid return self.client.get(resource) - @utils.retry_upon_exception_nsxv3(exceptions.StaleRevision) + @utils.retry_upon_exception(exceptions.StaleRevision) def update_resource_with_retry(self, resource, payload): revised_payload = self.client.get(resource) for key_name in payload.keys(): @@ -128,8 +126,7 @@ class NsxLib(dfw_api.DfwApi, security.Security): return self.client.create(resource, body) - @utils.retry_upon_exception_nsxv3(exceptions.StaleRevision, - max_attempts=MAX_ATTEMPTS) + @utils.retry_upon_exception(exceptions.StaleRevision) def delete_logical_switch(self, lswitch_id): resource = 'logical-switches/%s?detach=true&cascade=true' % lswitch_id self.client.delete(resource) @@ -138,8 +135,7 @@ class NsxLib(dfw_api.DfwApi, security.Security): resource = "logical-switches/%s" % logical_switch_id return self.client.get(resource) - @utils.retry_upon_exception_nsxv3(exceptions.StaleRevision, - max_attempts=MAX_ATTEMPTS) + @utils.retry_upon_exception(exceptions.StaleRevision) def update_logical_switch(self, lswitch_id, name=None, admin_state=None, tags=None): resource = "logical-switches/%s" % lswitch_id @@ -346,12 +342,12 @@ class NsxLib(dfw_api.DfwApi, security.Security): if len(matched_results) == 0: err_msg = (_("Could not find %(resource)s %(name)s") % {'name': name_or_id, 'resource': resource}) - # XXX improve exception handling... + # TODO(asarfaty): improve exception handling... raise exceptions.ManagerError(details=err_msg) elif len(matched_results) > 1: err_msg = (_("Found multiple %(resource)s named %(name)s") % {'name': name_or_id, 'resource': resource}) - # XXX improve exception handling... + # TODO(asarfaty): improve exception handling... raise exceptions.ManagerError(details=err_msg) return matched_results[0].get('id') diff --git a/vmware_nsx/nsxlib/v3/dfw_api.py b/vmware_nsx/nsxlib/v3/dfw_api.py deleted file mode 100644 index bbcf20de70..0000000000 --- a/vmware_nsx/nsxlib/v3/dfw_api.py +++ /dev/null @@ -1,269 +0,0 @@ -# Copyright 2015 OpenStack Foundation -# 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. - - -""" -NSX-V3 Distributed Firewall -""" -from oslo_log import log - -from vmware_nsx._i18n import _LW -from vmware_nsx.common import utils -from vmware_nsx.nsxlib.v3 import client as nsxclient -from vmware_nsx.nsxlib.v3 import exceptions - -LOG = log.getLogger(__name__) - -# firewall section types -LAYER3 = 'LAYER3' - -INSERT_BEFORE = 'insert_before' -INSERT_BOTTOM = 'insert_bottom' -INSERT_TOP = 'insert_top' - -# firewall rule actions -ALLOW = 'ALLOW' -DROP = 'DROP' -REJECT = 'REJECT' - -# filtering operators and expressions -EQUALS = 'EQUALS' -NSGROUP_SIMPLE_EXPRESSION = 'NSGroupSimpleExpression' -NSGROUP_TAG_EXPRESSION = 'NSGroupTagExpression' - -# nsgroup members update actions -ADD_MEMBERS = 'ADD_MEMBERS' -REMOVE_MEMBERS = 'REMOVE_MEMBERS' - -NSGROUP = 'NSGroup' -LOGICAL_SWITCH = 'LogicalSwitch' -LOGICAL_PORT = 'LogicalPort' -IPV4ADDRESS = 'IPv4Address' -IPV6ADDRESS = 'IPv6Address' - -IN = 'IN' -OUT = 'OUT' -IN_OUT = 'IN_OUT' - -# NSServices resource types -L4_PORT_SET_NSSERVICE = 'L4PortSetNSService' -ICMP_TYPE_NSSERVICE = 'ICMPTypeNSService' -IP_PROTOCOL_NSSERVICE = 'IPProtocolNSService' - -TCP = 'TCP' -UDP = 'UDP' -ICMPV4 = 'ICMPv4' -ICMPV6 = 'ICMPv6' - -IPV4 = 'IPV4' -IPV6 = 'IPV6' -IPV4_IPV6 = 'IPV4_IPV6' - - -class DfwApi(object): - - def get_nsservice(self, resource_type, **properties): - service = {'resource_type': resource_type} - service.update(properties) - return {'service': service} - - def get_nsgroup_port_tag_expression(self, scope, tag): - return {'resource_type': NSGROUP_TAG_EXPRESSION, - 'target_type': LOGICAL_PORT, - 'scope': scope, - 'tag': tag} - - def create_nsgroup(self, display_name, description, tags, - membership_criteria=None): - body = {'display_name': display_name, - 'description': description, - 'tags': tags, - 'members': []} - if membership_criteria: - body.update({'membership_criteria': [membership_criteria]}) - return self.client.create('ns-groups', body) - - def list_nsgroups(self): - return self.client.get( - 'ns-groups?populate_references=false').get('results', []) - - @utils.retry_upon_exception_nsxv3(exceptions.StaleRevision) - def update_nsgroup(self, nsgroup_id, display_name=None, description=None, - membership_criteria=None, members=None): - nsgroup = self.read_nsgroup(nsgroup_id) - if display_name is not None: - nsgroup['display_name'] = display_name - if description is not None: - nsgroup['description'] = description - if members is not None: - nsgroup['members'] = members - if membership_criteria is not None: - nsgroup['membership_criteria'] = [membership_criteria] - return self.client.update( - 'ns-groups/%s' % nsgroup_id, nsgroup) - - def get_nsgroup_member_expression(self, target_type, target_id): - return {'resource_type': NSGROUP_SIMPLE_EXPRESSION, - 'target_property': 'id', - 'target_type': target_type, - 'op': EQUALS, - 'value': target_id} - - @utils.retry_upon_exception_nsxv3(exceptions.ManagerError) - def _update_nsgroup_with_members(self, nsgroup_id, members, action): - members_update = 'ns-groups/%s?action=%s' % (nsgroup_id, action) - return self.client.create(members_update, members) - - def add_nsgroup_members(self, nsgroup_id, target_type, target_ids): - members = [] - for target_id in target_ids: - member_expr = self.get_nsgroup_member_expression( - target_type, target_id) - members.append(member_expr) - members = {'members': members} - try: - return self._update_nsgroup_with_members( - nsgroup_id, members, ADD_MEMBERS) - except (exceptions.StaleRevision, exceptions.ResourceNotFound): - raise - except exceptions.ManagerError: - # REVISIT(roeyc): A ManagerError might have been raised for a - # different reason, e.g - NSGroup does not exists. - LOG.warning(_LW("Failed to add %(target_type)s resources " - "(%(target_ids))s to NSGroup %(nsgroup_id)s"), - {'target_type': target_type, - 'target_ids': target_ids, - 'nsgroup_id': nsgroup_id}) - - raise exceptions.NSGroupIsFull(nsgroup_id=nsgroup_id) - - def remove_nsgroup_member(self, nsgroup_id, target_type, - target_id, verify=False): - member_expr = self.get_nsgroup_member_expression( - target_type, target_id) - members = {'members': [member_expr]} - try: - return self._update_nsgroup_with_members( - nsgroup_id, members, REMOVE_MEMBERS) - except exceptions.ManagerError: - if verify: - raise exceptions.NSGroupMemberNotFound(member_id=target_id, - nsgroup_id=nsgroup_id) - - def read_nsgroup(self, nsgroup_id): - return self.client.get( - 'ns-groups/%s?populate_references=true' % nsgroup_id) - - def delete_nsgroup(self, nsgroup_id): - try: - return self.client.delete( - 'ns-groups/%s?force=true' % nsgroup_id) - # FIXME(roeyc): Should only except NotFound error. - except Exception: - LOG.debug("NSGroup %s does not exists for delete request.", - nsgroup_id) - - def _build_section(self, display_name, description, applied_tos, tags): - return {'display_name': display_name, - 'description': description, - 'stateful': True, - 'section_type': LAYER3, - 'applied_tos': [self.get_nsgroup_reference(t_id) - for t_id in applied_tos], - 'tags': tags} - - def create_empty_section(self, display_name, description, applied_tos, - tags, operation=INSERT_BOTTOM, - other_section=None): - resource = 'firewall/sections?operation=%s' % operation - body = self._build_section(display_name, description, - applied_tos, tags) - if other_section: - resource += '&id=%s' % other_section - return self.client.create(resource, body) - - @utils.retry_upon_exception_nsxv3(exceptions.StaleRevision) - def update_section(self, section_id, display_name=None, description=None, - applied_tos=None, rules=None): - resource = 'firewall/sections/%s' % section_id - section = self.read_section(section_id) - - if rules is not None: - resource += '?action=update_with_rules' - section.update({'rules': rules}) - if display_name is not None: - section['display_name'] = display_name - if description is not None: - section['description'] = description - if applied_tos is not None: - section['applied_tos'] = [self.get_nsgroup_reference(nsg_id) - for nsg_id in applied_tos] - if rules is not None: - return nsxclient.create_resource(resource, section) - elif any(p is not None for p in (display_name, description, - applied_tos)): - return self.client.update(resource, section) - - def read_section(self, section_id): - resource = 'firewall/sections/%s' % section_id - return self.client.get(resource) - - def list_sections(self): - resource = 'firewall/sections' - return self.client.get(resource).get('results', []) - - def delete_section(self, section_id): - resource = 'firewall/sections/%s?cascade=true' % section_id - return self.client.delete(resource) - - def get_nsgroup_reference(self, nsgroup_id): - return {'target_id': nsgroup_id, - 'target_type': NSGROUP} - - def get_ip_cidr_reference(self, ip_cidr_block, ip_protocol): - target_type = IPV4ADDRESS if ip_protocol == IPV4 else IPV6ADDRESS - return {'target_id': ip_cidr_block, - 'target_type': target_type} - - def get_firewall_rule_dict(self, display_name, source=None, - destination=None, - direction=IN_OUT, ip_protocol=IPV4_IPV6, - service=None, action=ALLOW, logged=False): - return {'display_name': display_name, - 'sources': [source] if source else [], - 'destinations': [destination] if destination else [], - 'direction': direction, - 'ip_protocol': ip_protocol, - 'services': [service] if service else [], - 'action': action, - 'logged': logged} - - def add_rule_in_section(self, rule, section_id): - resource = 'firewall/sections/%s/rules' % section_id - params = '?operation=insert_bottom' - return self.client.create(resource + params, rule) - - def add_rules_in_section(self, rules, section_id): - resource = 'firewall/sections/%s/rules' % section_id - params = '?action=create_multiple&operation=insert_bottom' - return self.client.create(resource + params, {'rules': rules}) - - def delete_rule(self, section_id, rule_id): - resource = 'firewall/sections/%s/rules/%s' % (section_id, rule_id) - return self.client.delete(resource) - - def get_section_rules(self, section_id): - resource = 'firewall/sections/%s/rules' % section_id - return self.client.get(resource) diff --git a/vmware_nsx/nsxlib/v3/native_dhcp.py b/vmware_nsx/nsxlib/v3/native_dhcp.py index 2f6951edc0..1f1d363cd7 100644 --- a/vmware_nsx/nsxlib/v3/native_dhcp.py +++ b/vmware_nsx/nsxlib/v3/native_dhcp.py @@ -18,7 +18,7 @@ from neutron_lib.api import validators from neutron_lib import constants from oslo_config import cfg -from vmware_nsx.common import utils +from vmware_nsx.nsxlib.v3 import utils def build_dhcp_server_config(network, subnet, port, project_name): diff --git a/vmware_nsx/nsxlib/v3/ns_group_manager.py b/vmware_nsx/nsxlib/v3/ns_group_manager.py index a9c11c0d0b..ff07375f38 100644 --- a/vmware_nsx/nsxlib/v3/ns_group_manager.py +++ b/vmware_nsx/nsxlib/v3/ns_group_manager.py @@ -21,10 +21,10 @@ from oslo_config import cfg from oslo_log import log from vmware_nsx._i18n import _, _LW -from vmware_nsx.common import utils from vmware_nsx.nsxlib import v3 -from vmware_nsx.nsxlib.v3 import dfw_api as firewall from vmware_nsx.nsxlib.v3 import exceptions +from vmware_nsx.nsxlib.v3 import nsx_constants as consts +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils LOG = log.getLogger(__name__) @@ -40,7 +40,7 @@ class NSGroupManager(object): are also of type NSGroups) to group the other NSGroups and associate it with these rules. In practice, one NSGroup (nested) can't contain all the other NSGroups, as - it has strict size limit. To overcome the limited space challange, we + it has strict size limit. To overcome the limited space challenge, we create several nested groups instead of just one, and we evenly distribute NSGroups (security-groups) between them. By using an hashing function on the NSGroup uuid we determine in which @@ -52,7 +52,7 @@ class NSGroupManager(object): NESTED_GROUP_DESCRIPTION = ('OpenStack NSGroup. Do not delete.') def __init__(self, size): - # XXX intergrate this in a better way.. + # TODO(asarfaty): integrate this in a better way.. self.nsx = v3.NsxLib( username=cfg.CONF.nsx_v3.nsx_api_user, password=cfg.CONF.nsx_v3.nsx_api_password, @@ -84,7 +84,7 @@ class NSGroupManager(object): nested_groups = { self._get_nested_group_index_from_name(nsgroup): nsgroup['id'] for nsgroup in self.nsx.list_nsgroups() - if utils.is_internal_resource(nsgroup)} + if nsxlib_utils.is_internal_resource(nsgroup)} if nested_groups: size = max(requested_size, max(nested_groups) + 1) @@ -115,7 +115,7 @@ class NSGroupManager(object): name_prefix = NSGroupManager.NESTED_GROUP_NAME name = '%s %s' % (name_prefix, index + 1) description = NSGroupManager.NESTED_GROUP_DESCRIPTION - tags = utils.build_v3_api_version_tag() + tags = nsxlib_utils.build_v3_api_version_tag() return self.nsx.create_nsgroup(name, description, tags) def _hash_uuid(self, internal_id): @@ -138,7 +138,7 @@ class NSGroupManager(object): LOG.debug("Adding NSGroup %s to nested group %s", nsgroup_id, group) self.nsx.add_nsgroup_members(group, - firewall.NSGROUP, + consts.NSGROUP, [nsgroup_id]) break except exceptions.NSGroupIsFull: @@ -153,7 +153,8 @@ class NSGroupManager(object): for group in self._suggest_nested_group(nsgroup_id): try: self.nsx.remove_nsgroup_member( - group, firewall.NSGROUP, nsgroup_id, verify=True) + group, consts.NSGROUP, + nsgroup_id, verify=True) break except exceptions.NSGroupMemberNotFound: LOG.warning(_LW("NSGroup %(nsgroup)s was expected to be found " diff --git a/vmware_nsx/nsxlib/v3/nsx_constants.py b/vmware_nsx/nsxlib/v3/nsx_constants.py new file mode 100644 index 0000000000..2a655c60b8 --- /dev/null +++ b/vmware_nsx/nsxlib/v3/nsx_constants.py @@ -0,0 +1,96 @@ +# Copyright 2016 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. + +# Admin statuses +ADMIN_STATE_UP = "UP" +ADMIN_STATE_DOWN = "DOWN" + +# Replication modes +MTEP = "MTEP" + +# Port attachment types +ATTACHMENT_VIF = "VIF" +ATTACHMENT_CIF = "CIF" +ATTACHMENT_LR = "LOGICALROUTER" +ATTACHMENT_DHCP = "DHCP_SERVICE" +ATTACHMENT_MDPROXY = "METADATA_PROXY" + +CIF_RESOURCE_TYPE = "CifAttachmentContext" + +# NSXv3 L2 Gateway constants +BRIDGE_ENDPOINT = "BRIDGEENDPOINT" + +# Router type +ROUTER_TYPE_TIER0 = "TIER0" +ROUTER_TYPE_TIER1 = "TIER1" + +LROUTERPORT_UPLINK = "LogicalRouterUplinkPort" +LROUTERPORT_DOWNLINK = "LogicalRouterDownLinkPort" +LROUTERPORT_LINKONTIER0 = "LogicalRouterLinkPortOnTIER0" +LROUTERPORT_LINKONTIER1 = "LogicalRouterLinkPortOnTIER1" + +# NSX service type +SERVICE_DHCP = "dhcp" + +# NSX-V3 Distributed Firewall constants +NSGROUP = 'NSGroup' +NSGROUP_SIMPLE_EXP = 'NSGroupSimpleExpression' +NSGROUP_TAG_EXP = 'NSGroupTagExpression' + +# Firewall rule position +FW_INSERT_BEFORE = 'insert_before' +FW_INSERT_BOTTOM = 'insert_bottom' +FW_INSERT_TOP = 'insert_top' + +# firewall rule actions +FW_ACTION_ALLOW = 'ALLOW' +FW_ACTION_DROP = 'DROP' +FW_ACTION_REJECT = 'REJECT' + +# nsgroup members update actions +NSGROUP_ADD_MEMBERS = 'ADD_MEMBERS' +NSGROUP_REMOVE_MEMBERS = 'REMOVE_MEMBERS' + +# NSServices resource types +L4_PORT_SET_NSSERVICE = 'L4PortSetNSService' +ICMP_TYPE_NSSERVICE = 'ICMPTypeNSService' +IP_PROTOCOL_NSSERVICE = 'IPProtocolNSService' + +# firewall section types +FW_SECTION_LAYER3 = 'LAYER3' + +TARGET_TYPE_LOGICAL_SWITCH = 'LogicalSwitch' +TARGET_TYPE_LOGICAL_PORT = 'LogicalPort' +TARGET_TYPE_IPV4ADDRESS = 'IPv4Address' +TARGET_TYPE_IPV6ADDRESS = 'IPv6Address' + +# filtering operators and expressions +EQUALS = 'EQUALS' + +IN = 'IN' +OUT = 'OUT' +IN_OUT = 'IN_OUT' + +TCP = 'TCP' +UDP = 'UDP' +ICMPV4 = 'ICMPv4' +ICMPV6 = 'ICMPv6' +IPV4 = 'IPV4' +IPV6 = 'IPV6' +IPV4_IPV6 = 'IPV4_IPV6' + +LOCAL_IP_PREFIX = 'local_ip_prefix' + +LOGGING = 'logging' diff --git a/vmware_nsx/nsxlib/v3/resources.py b/vmware_nsx/nsxlib/v3/resources.py index fd24c8925f..96c8c3f959 100644 --- a/vmware_nsx/nsxlib/v3/resources.py +++ b/vmware_nsx/nsxlib/v3/resources.py @@ -20,10 +20,10 @@ import six from oslo_config import cfg from vmware_nsx._i18n import _ -from vmware_nsx.common import nsx_constants -from vmware_nsx.common import utils from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import exceptions +from vmware_nsx.nsxlib.v3 import nsx_constants +from vmware_nsx.nsxlib.v3 import utils SwitchingProfileTypeId = collections.namedtuple( @@ -285,13 +285,13 @@ class LogicalPort(AbstractRESTResource): attachment=attachment)) return self._client.create(body=body) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def delete(self, lport_id): return self._client.url_delete('%s?detach=true' % lport_id) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def update(self, lport_id, vif_uuid, @@ -342,7 +342,7 @@ class LogicalRouter(AbstractRESTResource): def delete(self, lrouter_id): return self._client.url_delete(lrouter_id) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def update(self, lrouter_id, *args, **kwargs): @@ -389,7 +389,7 @@ class LogicalRouterPort(AbstractRESTResource): return self._client.create(body=body) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def update(self, logical_port_id, **kwargs): @@ -402,7 +402,7 @@ class LogicalRouterPort(AbstractRESTResource): # new revision_id return self._client.update(logical_port_id, body=logical_router_port) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def delete(self, logical_port_id): @@ -511,7 +511,7 @@ class LogicalDhcpServer(AbstractRESTResource): options, tags) return self._client.create(body=body) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def update(self, uuid, dhcp_profile_id=None, server_ip=None, name=None, @@ -539,7 +539,7 @@ class LogicalDhcpServer(AbstractRESTResource): url = "%s/static-bindings/%s" % (server_uuid, binding_uuid) return self._client.url_get(url) - @utils.retry_upon_exception_nsxv3( + @utils.retry_upon_exception( exceptions.StaleRevision, max_attempts=cfg.CONF.nsx_v3.retries) def update_binding(self, server_uuid, binding_uuid, **kwargs): diff --git a/vmware_nsx/nsxlib/v3/router.py b/vmware_nsx/nsxlib/v3/router.py index e1d75486c1..d77ee021b8 100644 --- a/vmware_nsx/nsxlib/v3/router.py +++ b/vmware_nsx/nsxlib/v3/router.py @@ -22,9 +22,9 @@ from neutron_lib import exceptions as n_exc from oslo_log import log from vmware_nsx._i18n import _, _LW -from vmware_nsx.common import nsx_constants -from vmware_nsx.common import utils from vmware_nsx.nsxlib.v3 import exceptions +from vmware_nsx.nsxlib.v3 import nsx_constants +from vmware_nsx.nsxlib.v3 import utils LOG = log.getLogger(__name__) diff --git a/vmware_nsx/nsxlib/v3/security.py b/vmware_nsx/nsxlib/v3/security.py index 3f38db3b58..fbde00d2e5 100644 --- a/vmware_nsx/nsxlib/v3/security.py +++ b/vmware_nsx/nsxlib/v3/security.py @@ -15,34 +15,27 @@ # under the License. """ -NSX-V3 Plugin security integration module +NSX-V3 Plugin security integration & Distributed Firewall module """ from neutron_lib import constants -from oslo_config import cfg from oslo_log import log from oslo_utils import excutils -from vmware_nsx._i18n import _LE -from vmware_nsx.common import utils -from vmware_nsx.db import nsx_models -from vmware_nsx.extensions import secgroup_rule_local_ip_prefix -from vmware_nsx.extensions import securitygrouplogging as sg_logging -from vmware_nsx.nsxlib.v3 import dfw_api as firewall +from vmware_nsx._i18n import _LE, _LW +from vmware_nsx.nsxlib.v3 import client as nsxclient from vmware_nsx.nsxlib.v3 import exceptions +from vmware_nsx.nsxlib.v3 import nsx_constants as consts +from vmware_nsx.nsxlib.v3 import utils LOG = log.getLogger(__name__) DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups' -DEFAULT_SECTION_TAG_NAME = 'neutron_default_dfw_section' PORT_SG_SCOPE = 'os-security-group' - MAX_NSGROUPS_CRITERIA_TAGS = 10 -# XXX this method should be refactored to pull the common stuff out to -# a security_group utils file. class Security(object): def _get_l4_protocol_name(self, protocol_number): @@ -52,24 +45,26 @@ class Security(object): protocol_number) protocol_number = int(protocol_number) if protocol_number == 6: - return firewall.TCP + return consts.TCP elif protocol_number == 17: - return firewall.UDP + return consts.UDP elif protocol_number == 1: - return firewall.ICMPV4 + return consts.ICMPV4 else: return protocol_number def _get_direction(self, sg_rule): return ( - firewall.IN if sg_rule['direction'] == 'ingress' else firewall.OUT + consts.IN if sg_rule['direction'] == 'ingress' + else consts.OUT ) def _decide_service(self, sg_rule): l4_protocol = self._get_l4_protocol_name(sg_rule['protocol']) direction = self._get_direction(sg_rule) - if l4_protocol in [firewall.TCP, firewall.UDP]: + if l4_protocol in [consts.TCP, + consts.UDP]: # If port_range_min is not specified then we assume all ports are # matched, relying on neutron to perform validation. source_ports = [] @@ -82,21 +77,24 @@ class Security(object): else: destination_ports = ['%(port_range_min)s' % sg_rule] - if direction == firewall.OUT: + if direction == consts.OUT: source_ports, destination_ports = destination_ports, [] - return self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE, - l4_protocol=l4_protocol, - source_ports=source_ports, - destination_ports=destination_ports) - elif l4_protocol == firewall.ICMPV4: - return self.get_nsservice(firewall.ICMP_TYPE_NSSERVICE, - protocol=l4_protocol, - icmp_type=sg_rule['port_range_min'], - icmp_code=sg_rule['port_range_max']) + return self.get_nsservice( + consts.L4_PORT_SET_NSSERVICE, + l4_protocol=l4_protocol, + source_ports=source_ports, + destination_ports=destination_ports) + elif l4_protocol == consts.ICMPV4: + return self.get_nsservice( + consts.ICMP_TYPE_NSSERVICE, + protocol=l4_protocol, + icmp_type=sg_rule['port_range_min'], + icmp_code=sg_rule['port_range_max']) elif l4_protocol is not None: - return self.get_nsservice(firewall.IP_PROTOCOL_NSSERVICE, - protocol_number=l4_protocol) + return self.get_nsservice( + consts.IP_PROTOCOL_NSSERVICE, + protocol_number=l4_protocol) def _get_fw_rule_from_sg_rule(self, sg_rule, nsgroup_id, rmt_nsgroup_id, logged, action): @@ -104,9 +102,9 @@ class Security(object): ip_protocol = sg_rule['ethertype'].upper() direction = self._get_direction(sg_rule) - if sg_rule.get(secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX): + if sg_rule.get(consts.LOCAL_IP_PREFIX): local_ip_prefix = self.get_ip_cidr_reference( - sg_rule[secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX], + sg_rule[consts.LOCAL_IP_PREFIX], ip_protocol) else: local_ip_prefix = None @@ -121,7 +119,7 @@ class Security(object): if rmt_nsgroup_id: source = self.get_nsgroup_reference(rmt_nsgroup_id) destination = local_ip_prefix or local_group - if direction == firewall.OUT: + if direction == consts.OUT: source, destination = destination, source service = self._decide_service(sg_rule) @@ -133,17 +131,15 @@ class Security(object): action, logged) def create_firewall_rules(self, context, section_id, nsgroup_id, - logging_enabled, action, security_group_rules): + logging_enabled, action, security_group_rules, + ruleid_2_remote_nsgroup_map): # 1. translate rules # 2. insert in section - # 3. save mappings - + # 3. return the rules firewall_rules = [] for sg_rule in security_group_rules: - remote_nsgroup_id = self._get_remote_nsg_mapping( - context, sg_rule, nsgroup_id) - + remote_nsgroup_id = ruleid_2_remote_nsgroup_map[sg_rule['id']] fw_rule = self._get_fw_rule_from_sg_rule( sg_rule, nsgroup_id, remote_nsgroup_id, logging_enabled, action) @@ -167,13 +163,13 @@ class Security(object): section_id, logging) self.update_section(section_id, rules=rules) - def update_security_group_on_backend(self, context, security_group): - nsgroup_id, section_id = self.get_sg_mappings(context.session, - security_group['id']) + def update_security_group_on_backend(self, context, security_group, + nsgroup_id, section_id, + log_sg_allowed_traffic): name = self.get_nsgroup_name(security_group) description = security_group['description'] - logging = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic or - security_group[sg_logging.LOGGING]) + logging = (log_sg_allowed_traffic or + security_group[consts.LOGGING]) rules = self._process_firewall_section_rules_logging_for_update( section_id, logging) self.update_nsgroup(nsgroup_id, name, description) @@ -184,38 +180,6 @@ class Security(object): # for usability purposes. return '%(name)s - %(id)s' % security_group - # XXX remove db calls from nsxlib - def save_sg_rule_mappings(self, session, firewall_rules): - # REVISIT(roeyc): This method should take care db access only. - rules = [(rule['display_name'], rule['id']) for rule in firewall_rules] - with session.begin(subtransactions=True): - for neutron_id, nsx_id in rules: - mapping = nsx_models.NeutronNsxRuleMapping( - neutron_id=neutron_id, nsx_id=nsx_id) - session.add(mapping) - return mapping - - # XXX db calls should not be here... - def get_sg_mappings(self, session, sg_id): - nsgroup_mapping = session.query( - nsx_models.NeutronNsxSecurityGroupMapping - ).filter_by(neutron_id=sg_id).one() - section_mapping = session.query( - nsx_models.NeutronNsxFirewallSectionMapping - ).filter_by(neutron_id=sg_id).one() - return nsgroup_mapping.nsx_id, section_mapping.nsx_id - - def _get_remote_nsg_mapping(self, context, sg_rule, nsgroup_id): - remote_nsgroup_id = None - remote_group_id = sg_rule.get('remote_group_id') - # skip unnecessary db access when possible - if remote_group_id == sg_rule['security_group_id']: - remote_nsgroup_id = nsgroup_id - elif remote_group_id: - remote_nsgroup_id, s = self.get_sg_mappings(context.session, - remote_group_id) - return remote_nsgroup_id - def get_lport_tags_for_security_groups(self, secgroups): if len(secgroups) > MAX_NSGROUPS_CRITERIA_TAGS: raise exceptions.NumberOfNsgroupCriteriaTagsReached( @@ -232,30 +196,29 @@ class Security(object): original, updated): added = set(updated) - set(original) removed = set(original) - set(updated) - for sg_id in added: - nsgroup_id, s = self.get_sg_mappings(context.session, sg_id) + for nsgroup_id in added: try: self.add_nsgroup_members( - nsgroup_id, firewall.LOGICAL_PORT, [lport_id]) + nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT, + [lport_id]) except exceptions.NSGroupIsFull: - for sg_id in added: - nsgroup_id, s = self.get_sg_mappings( - context.session, sg_id) + for nsgroup_id in added: # NOTE(roeyc): If the port was not added to the nsgroup # yet, then this request will silently fail. self.remove_nsgroup_member( - nsgroup_id, firewall.LOGICAL_PORT, lport_id) + nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT, + lport_id) raise exceptions.SecurityGroupMaximumCapacityReached( - sg_id=sg_id) + sg_id=nsgroup_id) except exceptions.ResourceNotFound: with excutils.save_and_reraise_exception(): LOG.error(_LE("NSGroup %s doesn't exists"), nsgroup_id) - for sg_id in removed: - nsgroup_id, s = self.get_sg_mappings(context.session, sg_id) + for nsgroup_id in removed: self.remove_nsgroup_member( - nsgroup_id, firewall.LOGICAL_PORT, lport_id) + nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT, lport_id) - def _init_default_section(self, name, description, nested_groups): + def init_default_section(self, name, description, nested_groups, + log_sg_blocked_traffic): fw_sections = self.list_sections() for section in fw_sections: if section['display_name'] == name: @@ -266,23 +229,28 @@ class Security(object): name, description, nested_groups, tags) block_rule = self.get_firewall_rule_dict( - 'Block All', action=firewall.DROP, - logged=cfg.CONF.nsx_v3.log_security_groups_blocked_traffic) + 'Block All', action=consts.FW_ACTION_DROP, + logged=log_sg_blocked_traffic) # TODO(roeyc): Add additional rules to allow IPV6 NDP. - dhcp_client = self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE, - l4_protocol=firewall.UDP, - source_ports=[67], - destination_ports=[68]) + dhcp_client = self.get_nsservice( + consts.L4_PORT_SET_NSSERVICE, + l4_protocol=consts.UDP, + source_ports=[67], + destination_ports=[68]) dhcp_client_rule_in = self.get_firewall_rule_dict( - 'DHCP Reply', direction=firewall.IN, service=dhcp_client) + 'DHCP Reply', + direction=consts.IN, + service=dhcp_client) dhcp_server = ( - self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE, - l4_protocol=firewall.UDP, + self.get_nsservice(consts.L4_PORT_SET_NSSERVICE, + l4_protocol=consts.UDP, source_ports=[68], destination_ports=[67])) dhcp_client_rule_out = self.get_firewall_rule_dict( - 'DHCP Request', direction=firewall.OUT, service=dhcp_server) + 'DHCP Request', + direction=consts.OUT, + service=dhcp_server) self.update_section(section['id'], name, section['description'], @@ -291,3 +259,205 @@ class Security(object): dhcp_client_rule_in, block_rule]) return section['id'] + + def get_nsservice(self, resource_type, **properties): + service = {'resource_type': resource_type} + service.update(properties) + return {'service': service} + + def get_nsgroup_port_tag_expression(self, scope, tag): + return { + 'resource_type': consts.NSGROUP_TAG_EXP, + 'target_type': consts.TARGET_TYPE_LOGICAL_PORT, + 'scope': scope, + 'tag': tag} + + def create_nsgroup(self, display_name, description, tags, + membership_criteria=None): + body = {'display_name': display_name, + 'description': description, + 'tags': tags, + 'members': []} + if membership_criteria: + body.update({'membership_criteria': [membership_criteria]}) + return self.client.create('ns-groups', body) + + def list_nsgroups(self): + return self.client.get( + 'ns-groups?populate_references=false').get('results', []) + + @utils.retry_upon_exception(exceptions.StaleRevision) + def update_nsgroup(self, nsgroup_id, display_name=None, description=None, + membership_criteria=None, members=None): + nsgroup = self.read_nsgroup(nsgroup_id) + if display_name is not None: + nsgroup['display_name'] = display_name + if description is not None: + nsgroup['description'] = description + if members is not None: + nsgroup['members'] = members + if membership_criteria is not None: + nsgroup['membership_criteria'] = [membership_criteria] + return self.client.update( + 'ns-groups/%s' % nsgroup_id, nsgroup) + + def get_nsgroup_member_expression(self, target_type, target_id): + return { + 'resource_type': consts.NSGROUP_SIMPLE_EXP, + 'target_property': 'id', + 'target_type': target_type, + 'op': consts.EQUALS, + 'value': target_id} + + @utils.retry_upon_exception(exceptions.ManagerError) + def _update_nsgroup_with_members(self, nsgroup_id, members, action): + members_update = 'ns-groups/%s?action=%s' % (nsgroup_id, action) + return self.client.create(members_update, members) + + def add_nsgroup_members(self, nsgroup_id, target_type, target_ids): + members = [] + for target_id in target_ids: + member_expr = self.get_nsgroup_member_expression( + target_type, target_id) + members.append(member_expr) + members = {'members': members} + try: + return self._update_nsgroup_with_members( + nsgroup_id, members, consts.NSGROUP_ADD_MEMBERS) + except (exceptions.StaleRevision, exceptions.ResourceNotFound): + raise + except exceptions.ManagerError: + # REVISIT(roeyc): A ManagerError might have been raised for a + # different reason, e.g - NSGroup does not exists. + LOG.warning(_LW("Failed to add %(target_type)s resources " + "(%(target_ids))s to NSGroup %(nsgroup_id)s"), + {'target_type': target_type, + 'target_ids': target_ids, + 'nsgroup_id': nsgroup_id}) + + raise exceptions.NSGroupIsFull(nsgroup_id=nsgroup_id) + + def remove_nsgroup_member(self, nsgroup_id, target_type, + target_id, verify=False): + member_expr = self.get_nsgroup_member_expression( + target_type, target_id) + members = {'members': [member_expr]} + try: + return self._update_nsgroup_with_members( + nsgroup_id, members, consts.NSGROUP_REMOVE_MEMBERS) + except exceptions.ManagerError: + if verify: + raise exceptions.NSGroupMemberNotFound(member_id=target_id, + nsgroup_id=nsgroup_id) + + def read_nsgroup(self, nsgroup_id): + return self.client.get( + 'ns-groups/%s?populate_references=true' % nsgroup_id) + + def delete_nsgroup(self, nsgroup_id): + try: + return self.client.delete( + 'ns-groups/%s?force=true' % nsgroup_id) + # FIXME(roeyc): Should only except NotFound error. + except Exception: + LOG.debug("NSGroup %s does not exists for delete request.", + nsgroup_id) + + def _build_section(self, display_name, description, applied_tos, tags): + return {'display_name': display_name, + 'description': description, + 'stateful': True, + 'section_type': consts.FW_SECTION_LAYER3, + 'applied_tos': [self.get_nsgroup_reference(t_id) + for t_id in applied_tos], + 'tags': tags} + + def create_empty_section(self, display_name, description, + applied_tos, tags, + operation=consts.FW_INSERT_BOTTOM, + other_section=None): + resource = 'firewall/sections?operation=%s' % operation + body = self._build_section(display_name, description, + applied_tos, tags) + if other_section: + resource += '&id=%s' % other_section + return self.client.create(resource, body) + + @utils.retry_upon_exception(exceptions.StaleRevision) + def update_section(self, section_id, display_name=None, description=None, + applied_tos=None, rules=None): + resource = 'firewall/sections/%s' % section_id + section = self.read_section(section_id) + + if rules is not None: + resource += '?action=update_with_rules' + section.update({'rules': rules}) + if display_name is not None: + section['display_name'] = display_name + if description is not None: + section['description'] = description + if applied_tos is not None: + section['applied_tos'] = [self.get_nsgroup_reference(nsg_id) + for nsg_id in applied_tos] + if rules is not None: + return nsxclient.create_resource(resource, section) + elif any(p is not None for p in (display_name, description, + applied_tos)): + return self.client.update(resource, section) + + def read_section(self, section_id): + resource = 'firewall/sections/%s' % section_id + return self.client.get(resource) + + def list_sections(self): + resource = 'firewall/sections' + return self.client.get(resource).get('results', []) + + def delete_section(self, section_id): + resource = 'firewall/sections/%s?cascade=true' % section_id + return self.client.delete(resource) + + def get_nsgroup_reference(self, nsgroup_id): + return {'target_id': nsgroup_id, + 'target_type': consts.NSGROUP} + + def get_ip_cidr_reference(self, ip_cidr_block, ip_protocol): + target_type = (consts.TARGET_TYPE_IPV4ADDRESS + if ip_protocol == consts.IPV4 + else consts.TARGET_TYPE_IPV6ADDRESS) + return {'target_id': ip_cidr_block, + 'target_type': target_type} + + def get_firewall_rule_dict( + self, display_name, source=None, + destination=None, + direction=consts.IN_OUT, + ip_protocol=consts.IPV4_IPV6, + service=None, action=consts.FW_ACTION_ALLOW, + logged=False): + return {'display_name': display_name, + 'sources': [source] if source else [], + 'destinations': [destination] if destination else [], + 'direction': direction, + 'ip_protocol': ip_protocol, + 'services': [service] if service else [], + 'action': action, + 'logged': logged} + + def add_rule_in_section(self, rule, section_id): + resource = 'firewall/sections/%s/rules' % section_id + params = '?operation=insert_bottom' + return self.client.create(resource + params, rule) + + def add_rules_in_section(self, rules, section_id): + resource = 'firewall/sections/%s/rules' % section_id + params = '?action=create_multiple&operation=insert_bottom' + return self.client.create(resource + params, {'rules': rules}) + + def delete_rule(self, section_id, rule_id): + resource = 'firewall/sections/%s/rules/%s' % (section_id, rule_id) + return self.client.delete(resource) + + def get_section_rules(self, section_id): + resource = 'firewall/sections/%s/rules' % section_id + return self.client.get(resource) diff --git a/vmware_nsx/nsxlib/v3/utils.py b/vmware_nsx/nsxlib/v3/utils.py new file mode 100644 index 0000000000..c284129736 --- /dev/null +++ b/vmware_nsx/nsxlib/v3/utils.py @@ -0,0 +1,171 @@ +# Copyright 2016 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. + +import retrying + +from neutron import version as n_version +from neutron_lib import exceptions +from oslo_log import log + +from vmware_nsx._i18n import _ + +LOG = log.getLogger(__name__) + +MAX_RESOURCE_TYPE_LEN = 20 +MAX_TAG_LEN = 40 +NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin' +OS_NEUTRON_ID_SCOPE = 'os-neutron-id' + + +def is_internal_resource(nsx_resource): + """ + Indicates whether the passed nsx-resource is owned by the plugin for + internal use. + """ + for tag in nsx_resource.get('tags', []): + if tag['scope'] == OS_NEUTRON_ID_SCOPE: + return tag['tag'] == NSX_NEUTRON_PLUGIN + return False + + +def build_v3_api_version_tag(): + """ + Some resources are created on the manager that do not have a corresponding + Neutron resource. + """ + return [{'scope': OS_NEUTRON_ID_SCOPE, + 'tag': NSX_NEUTRON_PLUGIN}, + {'scope': "os-api-version", + 'tag': n_version.version_info.release_string()}] + + +def _validate_resource_type_length(resource_type): + # Add in a validation to ensure that we catch this at build time + if len(resource_type) > MAX_RESOURCE_TYPE_LEN: + raise exceptions.InvalidInput( + error_message=(_('Resource type cannot exceed %(max_len)s ' + 'characters: %(resource_type)s') % + {'max_len': MAX_RESOURCE_TYPE_LEN, + 'resource_type': resource_type})) + + +def build_v3_tags_payload(resource, resource_type, project_name): + """ + Construct the tags payload that will be pushed to NSX-v3 + Add :, os-project-id:, + os-project-name: os-api-version: + """ + _validate_resource_type_length(resource_type) + # There may be cases when the plugin creates the port, for example DHCP + if not project_name: + project_name = NSX_NEUTRON_PLUGIN + tenant_id = resource.get('tenant_id', '') + # If tenant_id is present in resource and set to None, explicitly set + # the tenant_id in tags as ''. + if tenant_id is None: + tenant_id = '' + return [{'scope': resource_type, + 'tag': resource.get('id', '')[:MAX_TAG_LEN]}, + {'scope': 'os-project-id', + 'tag': tenant_id[:MAX_TAG_LEN]}, + {'scope': 'os-project-name', + 'tag': project_name[:MAX_TAG_LEN]}, + {'scope': 'os-api-version', + 'tag': n_version.version_info.release_string()[:MAX_TAG_LEN]}] + + +def add_v3_tag(tags, resource_type, tag): + _validate_resource_type_length(resource_type) + tags.append({'scope': resource_type, 'tag': tag[:MAX_TAG_LEN]}) + return tags + + +def update_v3_tags(current_tags, tags_update): + current_scopes = set([tag['scope'] for tag in current_tags]) + updated_scopes = set([tag['scope'] for tag in tags_update]) + + tags = [{'scope': tag['scope'], 'tag': tag['tag']} + for tag in (current_tags + tags_update) + if tag['scope'] in (current_scopes ^ updated_scopes)] + + modified_scopes = current_scopes & updated_scopes + for tag in tags_update: + if tag['scope'] in modified_scopes: + # If the tag value is empty or None, then remove the tag completely + if tag['tag']: + tag['tag'] = tag['tag'][:MAX_TAG_LEN] + tags.append(tag) + + return tags + + +#Todo(asarfaty): figure out a way to use an NsxLib class variable in the +#retry decorator instead of the configuration/constant one +def retry_upon_exception(exc, delay=500, max_delay=2000, max_attempts=10): + return retrying.retry(retry_on_exception=lambda e: isinstance(e, exc), + wait_exponential_multiplier=delay, + wait_exponential_max=max_delay, + stop_max_attempt_number=max_attempts) + + +def list_match(list1, list2): + # Check if list1 and list2 have identical elements, but relaxed on + # dict elements where list1's dict element can be a subset of list2's + # corresponding element. + if (not isinstance(list1, list) or + not isinstance(list2, list) or + len(list1) != len(list2)): + return False + list1 = sorted(list1) + list2 = sorted(list2) + for (v1, v2) in zip(list1, list2): + if isinstance(v1, dict): + if not dict_match(v1, v2): + return False + elif isinstance(v1, list): + if not list_match(v1, v2): + return False + elif v1 != v2: + return False + return True + + +def dict_match(dict1, dict2): + # Check if dict1 is a subset of dict2. + if not isinstance(dict1, dict) or not isinstance(dict2, dict): + return False + for k1, v1 in dict1.items(): + if k1 not in dict2: + return False + v2 = dict2[k1] + if isinstance(v1, dict): + if not dict_match(v1, v2): + return False + elif isinstance(v1, list): + if not list_match(v1, v2): + return False + elif v1 != v2: + return False + return True + + +def get_name_and_uuid(name, uuid, tag=None, maxlen=80): + short_uuid = '_' + uuid[:5] + '...' + uuid[-5:] + maxlen = maxlen - len(short_uuid) + if tag: + maxlen = maxlen - len(tag) - 1 + return name[:maxlen] + '_' + tag + short_uuid + else: + return name[:maxlen] + short_uuid diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index ee4577da7f..a179ed3bc2 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -73,7 +73,6 @@ from vmware_nsx.api_replay import utils as api_replay_utils from vmware_nsx.common import config # noqa from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import locking -from vmware_nsx.common import nsx_constants from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db from vmware_nsx.db import extended_security_group @@ -85,13 +84,14 @@ from vmware_nsx.extensions import maclearning as mac_ext from vmware_nsx.extensions import providersecuritygroup as provider_sg from vmware_nsx.extensions import securitygrouplogging as sg_logging from vmware_nsx.nsxlib import v3 as nsxlib -from vmware_nsx.nsxlib.v3 import dfw_api as firewall from vmware_nsx.nsxlib.v3 import exceptions as nsx_lib_exc from vmware_nsx.nsxlib.v3 import native_dhcp from vmware_nsx.nsxlib.v3 import ns_group_manager +from vmware_nsx.nsxlib.v3 import nsx_constants as nsxlib_consts from vmware_nsx.nsxlib.v3 import resources as nsx_resources from vmware_nsx.nsxlib.v3 import router from vmware_nsx.nsxlib.v3 import security +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils from vmware_nsx.services.qos.common import utils as qos_com_utils from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils from vmware_nsx.services.trunk.nsx_v3 import driver as trunk_driver @@ -221,7 +221,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, def _init_nsx_profiles(self): LOG.debug("Initializing NSX v3 port spoofguard switching profile") - # XXX improve logic to avoid requiring setting this to none. + # TODO(asarfaty): improve logic to avoid requiring setting + # this to none. self._psec_profile = None self._psec_profile = self._init_port_security_profile() if not self._psec_profile: @@ -236,7 +237,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, LOG.debug("Initializing NSX v3 DHCP switching profile") try: - # XXX improve logic to avoid requiring setting this to none. + # TODO(asarfaty): improve logic to avoid requiring setting + # this to none. self._dhcp_profile = None self._dhcp_profile = self._init_dhcp_switching_profile() except Exception: @@ -247,7 +249,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if utils.is_nsx_version_1_1_0(self._nsx_version): LOG.debug("Initializing NSX v3 Mac Learning switching profile") try: - # XXX improve logic to avoid requiring setting this to none. + # TODO(asarfaty): improve logic to avoid requiring setting + # this to none. self._mac_learning_profile = None self._mac_learning_profile = self._init_mac_learning_profile() # Only expose the extension if it is supported @@ -318,14 +321,15 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, "must be disabled") % dhcp_profile_uuid raise n_exc.InvalidInput(error_message=msg) - @utils.retry_upon_exception_nsxv3(Exception) + @nsxlib_utils.retry_upon_exception( + Exception, max_attempts=cfg.CONF.nsx_v3.retries) def _init_dhcp_switching_profile(self): with locking.LockManager.get_lock('nsxv3_dhcp_profile_init'): profile = self._get_dhcp_security_profile() if not profile: self._switching_profiles.create_dhcp_profile( NSX_V3_DHCP_PROFILE_NAME, 'Neutron DHCP Security Profile', - tags=utils.build_v3_api_version_tag()) + tags=nsxlib_utils.build_v3_api_version_tag()) return self._get_dhcp_security_profile() def _get_dhcp_security_profile(self): @@ -345,7 +349,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, self._switching_profiles.create_mac_learning_profile( NSX_V3_MAC_LEARNING_PROFILE_NAME, 'Neutron MAC Learning Profile', - tags=utils.build_v3_api_version_tag()) + tags=nsxlib_utils.build_v3_api_version_tag()) return self._get_mac_learning_profile() def _get_mac_learning_profile(self): @@ -369,7 +373,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, NSX_V3_PSEC_PROFILE_NAME) return profile[0] if profile else None - @utils.retry_upon_exception_nsxv3(Exception) + @nsxlib_utils.retry_upon_exception( + Exception, max_attempts=cfg.CONF.nsx_v3.retries) def _init_port_security_profile(self): profile = self._get_port_security_profile() if profile: @@ -384,7 +389,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, self._switching_profiles.create_spoofguard_profile( NSX_V3_PSEC_PROFILE_NAME, 'Neutron Port Security Profile', whitelist_ports=True, whitelist_switches=False, - tags=utils.build_v3_api_version_tag()) + tags=nsxlib_utils.build_v3_api_version_tag()) return self._get_port_security_profile() def _process_security_group_logging(self): @@ -396,8 +401,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, sg_logging.LOGGING]) for sg in [sg for sg in secgroups if sg[sg_logging.LOGGING] is False]: - _, section_id = self.nsxlib.get_sg_mappings(context.session, - sg['id']) + nsgroup_id, section_id = nsx_db.get_sg_mappings( + context.session, sg['id']) try: self.nsxlib.set_firewall_rule_logging_for_section( section_id, logging=log_all_rules) @@ -414,9 +419,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, cfg.CONF.nsx_v3.number_of_nested_groups) section_description = ("This section is handled by OpenStack to " "contain default rules on security-groups.") - section_id = self.nsxlib._init_default_section( + section_id = self.nsxlib.init_default_section( security.DEFAULT_SECTION, section_description, - nsgroup_manager.nested_groups.values()) + nsgroup_manager.nested_groups.values(), + cfg.CONF.nsx_v3.log_security_groups_blocked_traffic) return nsgroup_manager, section_id def _init_dhcp_metadata(self): @@ -601,7 +607,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, # update the network name to indicate the neutron id too. net_name = utils.get_name_and_uuid(net_data['name'] or 'network', neutron_net_id) - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( net_data, resource_type='os-neutron-net-id', project_name=context.tenant_name) @@ -713,7 +719,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if is_backend_network and cfg.CONF.nsx_v3.native_dhcp_metadata: # Enable native metadata proxy for this network. - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( net_data, resource_type='os-neutron-net-id', project_name=context.tenant_name) name = utils.get_name_and_uuid('%s-%s' % ( @@ -722,7 +728,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, md_port = self._port_client.create( nsx_net_id, cfg.CONF.nsx_v3.metadata_proxy_uuid, tags=tags, name=name, - attachment_type=nsx_constants.ATTACHMENT_MDPROXY) + attachment_type=nsxlib_consts.ATTACHMENT_MDPROXY) LOG.debug("Created MD-Proxy logical port %(port)s " "for network %(network)s", {'port': md_port['id'], @@ -923,7 +929,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, server_data = native_dhcp.build_dhcp_server_config( network, subnet, neutron_port, context.tenant_name) nsx_net_id = self._get_network_nsx_id(context, network['id']) - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( neutron_port, resource_type='os-neutron-dport-id', project_name=context.tenant_name) dhcp_server = None @@ -935,7 +941,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, name = self._get_port_name(context, port_data) nsx_port = self._port_client.create( nsx_net_id, dhcp_server['id'], tags=tags, name=name, - attachment_type=nsx_constants.ATTACHMENT_DHCP) + attachment_type=nsxlib_consts.ATTACHMENT_DHCP) LOG.debug("Created DHCP logical port %(port)s for " "network %(network)s", {'port': nsx_port['id'], 'network': network['id']}) @@ -956,7 +962,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, # Add neutron_net_id -> dhcp_service_id mapping to the DB. nsx_db.add_neutron_nsx_service_binding( context.session, network['id'], neutron_port['id'], - nsx_constants.SERVICE_DHCP, dhcp_server['id']) + nsxlib_consts.SERVICE_DHCP, dhcp_server['id']) except db_exc.DBError: with excutils.save_and_reraise_exception(): LOG.error(_LE("Failed to create mapping for DHCP port %s," @@ -970,7 +976,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, # First delete the DHCP port in this network. Then delete the # corresponding LogicalDhcpServer for this network. dhcp_service = nsx_db.get_nsx_service_binding( - context.session, network_id, nsx_constants.SERVICE_DHCP) + context.session, network_id, nsxlib_consts.SERVICE_DHCP) if not dhcp_service: return @@ -1002,7 +1008,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, try: # Delete neutron_id -> dhcp_service_id mapping from the DB. nsx_db.delete_neutron_nsx_service_binding( - context.session, network_id, nsx_constants.SERVICE_DHCP) + context.session, network_id, nsxlib_consts.SERVICE_DHCP) except db_exc.DBError: with excutils.save_and_reraise_exception(): LOG.error(_LE("Unable to delete DHCP server mapping for " @@ -1105,7 +1111,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if kwargs: dhcp_service = nsx_db.get_nsx_service_binding( context.session, orig_subnet['network_id'], - nsx_constants.SERVICE_DHCP) + nsxlib_consts.SERVICE_DHCP) if dhcp_service: try: self._dhcp_server.update( @@ -1256,13 +1262,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, resource_type = 'os-neutron-rport-id' else: resource_type = 'os-neutron-port-id' - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( port_data, resource_type=resource_type, project_name=context.tenant_name) resource_type = self._get_resource_type_for_device_id( device_owner, device_id) if resource_type: - tags = utils.add_v3_tag(tags, resource_type, device_id) + tags = nsxlib_utils.add_v3_tag(tags, resource_type, device_id) if utils.is_nsx_version_1_1_0(self._nsx_version): # If port has no security-groups then we don't need to add any @@ -1293,7 +1299,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, vif_uuid = False else: # default attachment - attachment_type = nsx_constants.ATTACHMENT_VIF + attachment_type = nsxlib_consts.ATTACHMENT_VIF vif_uuid = port_data['id'] profiles = [] @@ -1423,7 +1429,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if not utils.is_port_dhcp_configurable(port): return dhcp_service = nsx_db.get_nsx_service_binding( - context.session, port['network_id'], nsx_constants.SERVICE_DHCP) + context.session, port['network_id'], nsxlib_consts.SERVICE_DHCP) if not dhcp_service: return for fixed_ip in self._filter_ipv4_dhcp_fixed_ips( @@ -1542,7 +1548,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, # Locate the backend DHCP server for this DHCP port. dhcp_service = nsx_db.get_nsx_service_binding( context.session, old_port['network_id'], - nsx_constants.SERVICE_DHCP) + nsxlib_consts.SERVICE_DHCP) if dhcp_service: new_ip = ips_to_add[0][1] try: @@ -1586,7 +1592,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if ips_to_add: dhcp_service = nsx_db.get_nsx_service_binding( context.session, new_port['network_id'], - nsx_constants.SERVICE_DHCP) + nsxlib_consts.SERVICE_DHCP) if dhcp_service: for (subnet_id, ip) in ips_to_add: self._add_dhcp_binding_on_server( @@ -1622,6 +1628,16 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, {'mac': mac, 'ip': ip, 'port': binding['port_id'], 'server': binding['nsx_service_id']}) + def _update_lport_with_security_groups(self, context, lport_id, + original, updated): + # translate the neutron sg ids to nsx ids, and call nsxlib + nsx_origial = nsx_db.get_nsx_security_group_ids(context.session, + original) + nsx_updated = nsx_db.get_nsx_security_group_ids(context.session, + updated) + self.nsxlib.update_lport_with_security_groups( + context, lport_id, nsx_origial, nsx_updated) + def create_port(self, context, port, l2gw_port_check=False): port_data = port['port'] dhcp_opts = port_data.get(ext_edo.EXTRADHCPOPTS, []) @@ -1686,7 +1702,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, if not utils.is_nsx_version_1_1_0(self._nsx_version): try: - self.nsxlib.update_lport_with_security_groups( + self._update_lport_with_security_groups( context, lport['id'], [], sgids or []) except Exception as e: with excutils.save_and_reraise_exception(reraise=False): @@ -1762,7 +1778,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, context.session, port_id) self._port_client.delete(nsx_port_id) if not utils.is_nsx_version_1_1_0(self._nsx_version): - self.nsxlib.update_lport_with_security_groups( + self._update_lport_with_security_groups( context, nsx_port_id, port.get(ext_sg.SECURITYGROUPS, []), []) self.disassociate_floatingips(context, port_id) @@ -1866,21 +1882,21 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, resource_type = self._get_resource_type_for_device_id( original_device_owner, updated_device_id) if resource_type: - tags_update = utils.add_v3_tag(tags_update, resource_type, - updated_device_id) + tags_update = nsxlib_utils.add_v3_tag( + tags_update, resource_type, updated_device_id) parent_vif_id, tag = self._get_data_from_binding_profile( context, updated_port) if updated_device_owner in (original_device_owner, l3_db.DEVICE_OWNER_ROUTER_INTF, - nsx_constants.BRIDGE_ENDPOINT): + nsxlib_consts.BRIDGE_ENDPOINT): # no attachment change attachment_type = False vif_uuid = False elif updated_device_owner: # default attachment - attachment_type = nsx_constants.ATTACHMENT_VIF + attachment_type = nsxlib_consts.ATTACHMENT_VIF vif_uuid = updated_port['id'] else: # no attachment @@ -1894,7 +1910,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, updated_port.get(ext_sg.SECURITYGROUPS, []) + updated_port.get(provider_sg.PROVIDER_SECURITYGROUPS, [])) else: - self.nsxlib.update_lport_with_security_groups( + self._update_lport_with_security_groups( context, lport_id, original_port.get(ext_sg.SECURITYGROUPS, []) + original_port.get(provider_sg.PROVIDER_SECURITYGROUPS, []), @@ -2236,7 +2252,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, edge_cluster_uuid = self._get_edge_cluster(new_tier0_uuid) self._routerlib.update_router_edge_cluster( nsx_router_id, edge_cluster_uuid) - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( router, resource_type='os-neutron-rport', project_name=context.tenant_name) self._routerlib.add_router_link_port(nsx_router_id, new_tier0_uuid, @@ -2256,7 +2272,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, gw_info = self._extract_external_gw(context, router, is_extract=True) router['router']['id'] = (router['router'].get('id') or uuidutils.generate_uuid()) - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( router['router'], resource_type='os-neutron-router-id', project_name=context.tenant_name) result = self._router_client.create( @@ -2522,7 +2538,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, context, router_id, network_id) display_name = utils.get_name_and_uuid( subnet['name'] or 'subnet', subnet['id']) - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( port, resource_type='os-neutron-rport-id', project_name=context.tenant_name) tags.append({'scope': 'os-subnet-id', 'tag': subnet['id']}) @@ -2777,9 +2793,9 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, def _create_fw_section_for_secgroup(self, nsgroup, is_provider): # NOTE(arosen): if a security group is provider we want to # insert our rules at the top. - operation = (firewall.INSERT_TOP + operation = (nsxlib_consts.FW_INSERT_TOP if is_provider - else firewall.INSERT_BEFORE) + else nsxlib_consts.FW_INSERT_BEFORE) # security-group rules are located in a dedicated firewall section. firewall_section = ( @@ -2791,7 +2807,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, return firewall_section def _create_security_group_backend_resources(self, secgroup): - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( secgroup, resource_type='os-neutron-secgr-id', project_name=secgroup['tenant_id']) name = self.nsxlib.get_nsgroup_name(secgroup) @@ -2810,6 +2826,27 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, ns_group, secgroup.get(provider_sg.PROVIDER)) return ns_group, firewall_section + def _create_firewall_rules(self, context, section_id, nsgroup_id, + logging_enabled, action, sg_rules): + # since the nsxlib does not have access to the nsx db, + # we need to provide a mapping for the remote nsgroup ids. + ruleid_2_remote_nsgroup_map = {} + for sg_rule in sg_rules: + remote_nsgroup_id = None + remote_group_id = sg_rule.get('remote_group_id') + # skip unnecessary db access when possible + if remote_group_id == sg_rule['security_group_id']: + remote_nsgroup_id = nsgroup_id + elif remote_group_id: + remote_nsgroup_id = nsx_db.get_nsx_security_group_id( + context.session, remote_group_id) + ruleid_2_remote_nsgroup_map[sg_rule['id']] = remote_nsgroup_id + + return self.nsxlib.create_firewall_rules( + context, section_id, nsgroup_id, + logging_enabled, action, sg_rules, + ruleid_2_remote_nsgroup_map) + def create_security_group(self, context, security_group, default_sg=False): secgroup = security_group['security_group'] secgroup['id'] = secgroup.get('id') or uuidutils.generate_uuid() @@ -2871,14 +2908,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, # translate and creates firewall rules. logging = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic or secgroup.get(sg_logging.LOGGING, False)) - action = (firewall.DROP + action = (nsxlib_consts.FW_ACTION_DROP if secgroup.get(provider_sg.PROVIDER) - else firewall.ALLOW) - rules = self.nsxlib.create_firewall_rules( + else nsxlib_consts.FW_ACTION_ALLOW) + rules = self._create_firewall_rules( context, firewall_section['id'], ns_group['id'], logging, action, sg_rules) - self.nsxlib.save_sg_rule_mappings(context.session, - rules['rules']) + self.save_security_group_rule_mappings(context, rules['rules']) self.nsgroup_manager.add_nsgroup(ns_group['id']) except nsx_lib_exc.ManagerError: with excutils.save_and_reraise_exception(): @@ -2905,7 +2941,11 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, self._process_security_group_properties_update( context, secgroup_res, security_group['security_group']) try: - self.nsxlib.update_security_group_on_backend(context, secgroup_res) + nsgroup_id, section_id = nsx_db.get_sg_mappings( + context.session, id) + self.nsxlib.update_security_group_on_backend( + context, secgroup_res, nsgroup_id, section_id, + cfg.CONF.nsx_v3.log_security_groups_allowed_traffic) except nsx_lib_exc.ManagerError: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Failed to update security-group %(name)s " @@ -2918,7 +2958,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, def delete_security_group(self, context, id): self._prevent_non_admin_delete_provider_sg(context, id) - nsgroup_id, section_id = self.nsxlib.get_sg_mappings( + nsgroup_id, section_id = nsx_db.get_sg_mappings( context.session, id) super(NsxV3Plugin, self).delete_security_group(context, id) self.nsxlib.delete_section(section_id) @@ -2957,18 +2997,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, security_group = self.get_security_group( context, sg_id) - action = firewall.ALLOW + action = nsxlib_consts.FW_ACTION_ALLOW if security_group.get(provider_sg.PROVIDER) is True: # provider security groups are drop rules. - action = firewall.DROP + action = nsxlib_consts.FW_ACTION_DROP sg_id = rules_db[0]['security_group_id'] - nsgroup_id, section_id = self.nsxlib.get_sg_mappings(context.session, - sg_id) + nsgroup_id, section_id = nsx_db.get_sg_mappings(context.session, + sg_id) logging_enabled = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic or self._is_security_group_logged(context, sg_id)) try: - rules = self.nsxlib.create_firewall_rules( + rules = self._create_firewall_rules( context, section_id, nsgroup_id, logging_enabled, action, rules_db) except nsx_lib_exc.ManagerError: @@ -2976,14 +3016,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, for rule in rules_db: super(NsxV3Plugin, self).delete_security_group_rule( context, rule['id']) - self.nsxlib.save_sg_rule_mappings(context.session, rules['rules']) + self.save_security_group_rule_mappings(context, rules['rules']) return rules_db def delete_security_group_rule(self, context, id): rule_db = self._get_security_group_rule(context, id) sg_id = rule_db['security_group_id'] self._prevent_non_admin_delete_provider_sg(context, sg_id) - _, section_id = self.nsxlib.get_sg_mappings(context.session, sg_id) + nsgroup_id, section_id = nsx_db.get_sg_mappings(context.session, sg_id) fw_rule_id = nsx_db.get_sg_rule_mapping(context.session, id) self.nsxlib.delete_rule(section_id, fw_rule_id) super(NsxV3Plugin, self).delete_security_group_rule(context, id) + + def save_security_group_rule_mappings(self, context, firewall_rules): + rules = [(rule['display_name'], rule['id']) for rule in firewall_rules] + nsx_db.save_sg_rule_mappings(context.session, rules) diff --git a/vmware_nsx/services/l2gateway/nsx_v3/driver.py b/vmware_nsx/services/l2gateway/nsx_v3/driver.py index e8c6bac9f4..a67cd9673c 100644 --- a/vmware_nsx/services/l2gateway/nsx_v3/driver.py +++ b/vmware_nsx/services/l2gateway/nsx_v3/driver.py @@ -34,10 +34,11 @@ from neutron_lib import constants from neutron_lib import exceptions as n_exc from vmware_nsx._i18n import _, _LE, _LI -from vmware_nsx.common import nsx_constants from vmware_nsx.common import utils as nsx_utils from vmware_nsx.db import db as nsx_db from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc +from vmware_nsx.nsxlib.v3 import nsx_constants +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils LOG = logging.getLogger(__name__) @@ -219,7 +220,7 @@ class NsxV3Driver(l2gateway_db.L2GatewayMixin): tenant_id = context.tenant_id gw_connection['tenant_id'] = tenant_id try: - tags = nsx_utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( gw_connection, resource_type='os-neutron-l2gw-id', project_name=context.tenant_name) bridge_endpoint = self._core_plugin.nsxlib.create_bridge_endpoint( diff --git a/vmware_nsx/services/neutron_taas/nsx_v3/driver.py b/vmware_nsx/services/neutron_taas/nsx_v3/driver.py index 3b9a2dac5b..9389e103bc 100644 --- a/vmware_nsx/services/neutron_taas/nsx_v3/driver.py +++ b/vmware_nsx/services/neutron_taas/nsx_v3/driver.py @@ -27,11 +27,11 @@ from oslo_utils import excutils from vmware_nsx._i18n import _, _LE, _LW from vmware_nsx.common import exceptions as nsx_exc -from vmware_nsx.common import utils as nsx_utils from vmware_nsx.db import db as nsx_db from vmware_nsx.nsxlib import v3 as nsxlib from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsx.nsxlib.v3 import resources as nsx_resources +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils LOG = logging.getLogger(__name__) @@ -177,7 +177,7 @@ class NsxV3Driver(base_driver.TaasBaseDriver, tf.get('tap_service_id')) src_port_id = tf.get('source_port') dest_port_id = ts.get('port_id') - tags = nsx_utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( tf, resource_type='os-neutron-mirror-id', project_name=context._plugin_context.tenant_name) nsx_direction = self._convert_to_backend_direction( diff --git a/vmware_nsx/services/qos/nsx_v3/utils.py b/vmware_nsx/services/qos/nsx_v3/utils.py index c8c5df5023..238cfb3414 100644 --- a/vmware_nsx/services/qos/nsx_v3/utils.py +++ b/vmware_nsx/services/qos/nsx_v3/utils.py @@ -25,8 +25,8 @@ from oslo_log import log as logging from vmware_nsx._i18n import _, _LW from vmware_nsx.common import exceptions as nsx_exc -from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db +from vmware_nsx.nsxlib.v3 import utils LOG = logging.getLogger(__name__) MAX_KBPS_MIN_VALUE = 1024 diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py index 6771fb4156..fec61b5c68 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py @@ -20,9 +20,9 @@ from neutron_lib import constants as const from oslo_config import cfg from vmware_nsx._i18n import _LE, _LI -from vmware_nsx.common import nsx_constants from vmware_nsx.common import utils as nsx_utils from vmware_nsx.nsxlib.v3 import native_dhcp +from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import resources from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import formatters diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py index aa5e779aa0..7fc0286352 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py @@ -19,10 +19,11 @@ from neutron_lib import constants as const from oslo_config import cfg from vmware_nsx._i18n import _LE, _LI -from vmware_nsx.common import nsx_constants from vmware_nsx.common import utils as nsx_utils from vmware_nsx.dhcp_meta import rpc as nsx_rpc +from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import resources +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import formatters from vmware_nsx.shell.admin.plugins.common import utils as admin_utils @@ -104,7 +105,7 @@ def nsx_update_metadata_proxy(resource, event, trigger, **kwargs): lswitch_id = neutron_client.net_id_to_lswitch_id(network['id']) if not lswitch_id: continue - tags = nsx_utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( network, resource_type='os-neutron-net-id', project_name='admin') name = nsx_utils.get_name_and_uuid('%s-%s' % ( diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py index cb913e762d..6ea990e221 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py @@ -32,8 +32,9 @@ from vmware_nsx.shell.admin.plugins.nsxv3.resources import ports from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils as v3_utils from vmware_nsx.shell import resources as shell from vmware_nsx._i18n import _LE, _LW -from vmware_nsx.nsxlib.v3 import dfw_api as firewall +from vmware_nsx.nsxlib.v3 import nsx_constants as consts from vmware_nsx.nsxlib.v3 import security +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils LOG = logging.getLogger(__name__) @@ -221,7 +222,7 @@ def fix_security_groups(resource, event, trigger, **kwargs): lport_id = neutron_db.get_logical_port_id(port_id) members.append(lport_id) nsxlib.add_nsgroup_members( - nsgroup['id'], firewall.LOGICAL_PORT, members) + nsgroup['id'], consts.TARGET_TYPE_LOGICAL_PORT, members) for rule in secgroup['security_group_rules']: rule_mapping = (context_.session.query( @@ -229,14 +230,14 @@ def fix_security_groups(resource, event, trigger, **kwargs): neutron_id=rule['id']).one()) with context_.session.begin(subtransactions=True): context_.session.delete(rule_mapping) - action = (firewall.DROP + action = (consts.FW_ACTION_DROP if secgroup.get(provider_sg.PROVIDER) - else firewall.ALLOW) - rules = nsxlib.create_firewall_rules( + else consts.FW_ACTION_ALLOW) + rules = plugin._create_firewall_rules( context_, fw_section['id'], nsgroup['id'], secgroup.get(sg_logging.LOGGING, False), action, secgroup['security_group_rules']) - nsxlib.save_sg_rule_mappings(context_.session, rules['rules']) + plugin.save_security_group_rule_mappings(context_, rules['rules']) # Add nsgroup to a nested group plugin.nsgroup_manager.add_nsgroup(nsgroup['id']) @@ -252,7 +253,7 @@ def _update_ports_dynamic_criteria_tags(): _, lport_id = neutron_db.get_lswitch_and_lport_id(port['id']) lport = port_client.get(lport_id) criteria_tags = nsxlib.get_lport_tags_for_security_groups(secgroups) - lport['tags'] = utils.update_v3_tags( + lport['tags'] = nsxlib_utils.update_v3_tags( lport.get('tags', []), criteria_tags) port_client._client.update(lport_id, body=lport) diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py index ab0d7e542d..c3a10c6ec6 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py @@ -17,9 +17,9 @@ from neutron import context from neutron.db import db_base_plugin_v2 from oslo_config import cfg -from vmware_nsx.common import nsx_constants from vmware_nsx.db import db as nsx_db from vmware_nsx.nsxlib import v3 +from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.plugins.nsx_v3 import plugin diff --git a/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py b/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py index 7749b7f5b4..f3ee8c17c1 100644 --- a/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py +++ b/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py @@ -150,4 +150,5 @@ class TestNSXv3ExtendedSGRule(test_nsxv3_plugin.NsxV3PluginTestCaseMixin, mock.ANY, # ns_group_id False, # logging 'ALLOW', # action - sg_rules) # sg_rules + sg_rules, # sg_rules + mock.ANY) # ruleid_2_remote_nsgroup_map diff --git a/vmware_nsx/tests/unit/extensions/test_securitygroup.py b/vmware_nsx/tests/unit/extensions/test_securitygroup.py index b455c21782..1427062d1e 100644 --- a/vmware_nsx/tests/unit/extensions/test_securitygroup.py +++ b/vmware_nsx/tests/unit/extensions/test_securitygroup.py @@ -17,9 +17,9 @@ import mock from neutron.extensions import securitygroup as ext_sg from neutron.tests.unit.extensions import test_securitygroup as test_ext_sg -from vmware_nsx.nsxlib.v3 import dfw_api as firewall from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsx.nsxlib.v3 import ns_group_manager +from vmware_nsx.nsxlib.v3 import nsx_constants as consts from vmware_nsx.plugins.nsx_v3 import plugin as nsx_plugin from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsxv3 from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase @@ -84,8 +84,10 @@ class TestSecurityGroupsNoDynamicCriteria(test_nsxv3.NsxV3PluginTestCaseMixin, # The first nsgroup is associated with the default secgroup, which is # not added to this port. - calls = [mock.call(NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY), - mock.call(NSG_IDS[2], firewall.LOGICAL_PORT, mock.ANY)] + calls = [mock.call(NSG_IDS[1], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY), + mock.call(NSG_IDS[2], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY)] add_member_mock.assert_has_calls(calls, any_order=True) @_mock_create_and_list_nsgroups @@ -97,13 +99,16 @@ class TestSecurityGroupsNoDynamicCriteria(test_nsxv3.NsxV3PluginTestCaseMixin, super(TestSecurityGroupsNoDynamicCriteria, self).test_update_port_with_multiple_security_groups() - calls = [mock.call(NSG_IDS[0], firewall.LOGICAL_PORT, mock.ANY), - mock.call(NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY), - mock.call(NSG_IDS[2], firewall.LOGICAL_PORT, mock.ANY)] + calls = [mock.call(NSG_IDS[0], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY), + mock.call(NSG_IDS[1], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY), + mock.call(NSG_IDS[2], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY)] add_member_mock.assert_has_calls(calls, any_order=True) remove_member_mock.assert_called_with( - NSG_IDS[0], firewall.LOGICAL_PORT, mock.ANY) + NSG_IDS[0], consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY) @_mock_create_and_list_nsgroups @mock.patch('vmware_nsx.nsxlib.v3.NsxLib.remove_nsgroup_member') @@ -115,9 +120,9 @@ class TestSecurityGroupsNoDynamicCriteria(test_nsxv3.NsxV3PluginTestCaseMixin, self).test_update_port_remove_security_group_empty_list() add_member_mock.assert_called_with( - NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY) + NSG_IDS[1], consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY) remove_member_mock.assert_called_with( - NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY) + NSG_IDS[1], consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY) @_mock_create_and_list_nsgroups @mock.patch('vmware_nsx.nsxlib.v3.NsxLib.add_nsgroup_members') @@ -166,8 +171,10 @@ class TestSecurityGroupsNoDynamicCriteria(test_nsxv3.NsxV3PluginTestCaseMixin, # Because the update has failed we excpect that the plugin will try to # revert any changes in the NSGroups - It is required to remove the # lport from any NSGroups which it was added to during that call. - calls = [mock.call(NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY), - mock.call(NSG_IDS[2], firewall.LOGICAL_PORT, mock.ANY)] + calls = [mock.call(NSG_IDS[1], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY), + mock.call(NSG_IDS[2], + consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY)] remove_member_mock.assert_has_calls(calls, any_order=True) def test_create_security_group_rule_icmpv6_legacy_protocol_name(self): @@ -225,9 +232,10 @@ class TestNSGroupManager(nsxlib_testcase.NsxLibTestCase): # There are 5 nested groups, the hash function will return 7, therefore # we expect that the nsgroup will be placed in the 3rd group. add_member_mock.assert_called_once_with( - NSG_IDS[2], firewall.NSGROUP, [nsgroup_id]) + NSG_IDS[2], consts.NSGROUP, [nsgroup_id]) remove_member_mock.assert_called_once_with( - NSG_IDS[2], firewall.NSGROUP, nsgroup_id, verify=True) + NSG_IDS[2], consts.NSGROUP, nsgroup_id, + verify=True) @_mock_create_and_list_nsgroups @mock.patch('vmware_nsx.nsxlib.v3.NsxLib.remove_nsgroup_member') @@ -259,8 +267,10 @@ class TestNSGroupManager(nsxlib_testcase.NsxLibTestCase): # Trying to add nsgroup to the nested group at index 2 will raise # NSGroupIsFull exception, we expect that the nsgroup will be added to # the nested group at index 3. - calls = [mock.call(NSG_IDS[2], firewall.NSGROUP, [nsgroup_id]), - mock.call(NSG_IDS[3], firewall.NSGROUP, [nsgroup_id])] + calls = [mock.call(NSG_IDS[2], + consts.NSGROUP, [nsgroup_id]), + mock.call(NSG_IDS[3], + consts.NSGROUP, [nsgroup_id])] add_member_mock.assert_has_calls(calls) # Since the nsgroup was added to the nested group at index 3, it will @@ -268,9 +278,11 @@ class TestNSGroupManager(nsxlib_testcase.NsxLibTestCase): # remove it from the group at index 3. calls = [ mock.call( - NSG_IDS[2], firewall.NSGROUP, nsgroup_id, verify=True), + NSG_IDS[2], consts.NSGROUP, + nsgroup_id, verify=True), mock.call( - NSG_IDS[3], firewall.NSGROUP, nsgroup_id, verify=True)] + NSG_IDS[3], consts.NSGROUP, + nsgroup_id, verify=True)] remove_member_mock.assert_has_calls(calls) @_mock_create_and_list_nsgroups @@ -282,16 +294,17 @@ class TestNSGroupManager(nsxlib_testcase.NsxLibTestCase): size = 3 cont_manager = ns_group_manager.NSGroupManager(size) # list_nsgroups will return nested group 1 and 3, but not group 2. - with mock.patch.object(firewall, - 'list_nsgroups_mock') as list_nsgroups_mock: - list_nsgroups_mock = lambda: list_nsgroups_mock()[::2] - # invoking the initialization process again, it should process - # groups 1 and 3 and create group 2. - cont_manager = ns_group_manager.NSGroupManager(size) - self.assertEqual({1: NSG_IDS[0], - 2: NSG_IDS[3], - 3: NSG_IDS[2]}, - cont_manager.nested_groups) + # FIXME: Not sure what this mock does. no one calls this method now. + #with mock.patch.object(vmware_nsx.nsxlib.v3.NsxLib.list_nsgroups, + # 'list_nsgroups_mock') as list_nsgroups_mock: + # list_nsgroups_mock = lambda: list_nsgroups_mock()[::2] + # invoking the initialization process again, it should process + # groups 1 and 3 and create group 2. + cont_manager = ns_group_manager.NSGroupManager(size) + self.assertEqual({1: NSG_IDS[0], + 2: NSG_IDS[3], + 3: NSG_IDS[2]}, + cont_manager.nested_groups) @_mock_create_and_list_nsgroups def test_suggest_nested_group(self): diff --git a/vmware_nsx/tests/unit/nsx_v3/test_constants.py b/vmware_nsx/tests/unit/nsx_v3/test_constants.py index 5befdc36ca..d6a39fa7f9 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_constants.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_constants.py @@ -14,149 +14,4 @@ # limitations under the License. -from oslo_utils import uuidutils - PLUGIN_NAME = 'vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin' -FAKE_NAME = "fake_name" -FAKE_SWITCH_UUID = uuidutils.generate_uuid() - -FAKE_PORT_UUID = uuidutils.generate_uuid() -FAKE_PORT = { - "id": FAKE_PORT_UUID, - "display_name": FAKE_NAME, - "resource_type": "LogicalPort", - "address_bindings": [], - "logical_switch_id": FAKE_SWITCH_UUID, - "admin_state": "UP", - "attachment": { - "id": "9ca8d413-f7bf-4276-b4c9-62f42516bdb2", - "attachment_type": "VIF" - }, - "switching_profile_ids": [ - { - "value": "64814784-7896-3901-9741-badeff705639", - "key": "IpDiscoverySwitchingProfile" - }, - { - "value": "fad98876-d7ff-11e4-b9d6-1681e6b88ec1", - "key": "SpoofGuardSwitchingProfile" - }, - { - "value": "93b4b7e8-f116-415d-a50c-3364611b5d09", - "key": "PortMirroringSwitchingProfile" - }, - { - "value": "fbc4fb17-83d9-4b53-a286-ccdf04301888", - "key": "SwitchSecuritySwitchingProfile" - }, - { - "value": "f313290b-eba8-4262-bd93-fab5026e9495", - "key": "QosSwitchingProfile" - } - ] -} - -FAKE_CONTAINER_PORT = { - "id": FAKE_PORT_UUID, - "display_name": FAKE_NAME, - "resource_type": "LogicalPort", - "address_bindings": [ - { - "ip_address": "192.168.1.110", - "mac_address": "aa:bb:cc:dd:ee:ff" - } - ], - "logical_switch_id": FAKE_SWITCH_UUID, - "admin_state": "UP", - "attachment": { - "id": "9ca8d413-f7bf-4276-b4c9-62f42516bdb2", - "attachment_type": "CIF", - "context": { - "vlan_tag": 122, - "container_host_vif_id": "c6f817a0-4e36-421e-98a6-8a2faed880bc", - "key_values": [], - "resource_type": "CifAttachmentContext", - } - }, - "switching_profile_ids": [ - { - "value": "64814784-7896-3901-9741-badeff705639", - "key": "IpDiscoverySwitchingProfile" - }, - { - "value": "fad98876-d7ff-11e4-b9d6-1681e6b88ec1", - "key": "SpoofGuardSwitchingProfile" - }, - { - "value": "93b4b7e8-f116-415d-a50c-3364611b5d09", - "key": "PortMirroringSwitchingProfile" - }, - { - "value": "fbc4fb17-83d9-4b53-a286-ccdf04301888", - "key": "SwitchSecuritySwitchingProfile" - }, - { - "value": "f313290b-eba8-4262-bd93-fab5026e9495", - "key": "QosSwitchingProfile" - } - ] -} - -FAKE_QOS_PROFILE = { - "resource_type": "QosSwitchingProfile", - "id": uuidutils.generate_uuid(), - "display_name": FAKE_NAME, - "system_defined": False, - "dscp": { - "priority": 25, - "mode": "UNTRUSTED" - }, - "tags": [], - "description": FAKE_NAME, - "class_of_service": 0, - "shaper_configuration": [ - { - "resource_type": "IngressRateShaper", - "enabled": False, - "peak_bandwidth_mbps": 0, - "burst_size_bytes": 0, - "average_bandwidth_mbps": 0 - }, - { - "resource_type": "IngressBroadcastRateShaper", - "enabled": False, - "peak_bandwidth_kbps": 0, - "average_bandwidth_kbps": 0, - "burst_size_bytes": 0 - }, - { - "resource_type": "EgressRateShaper", - "enabled": False, - "peak_bandwidth_mbps": 0, - "burst_size_bytes": 0, - "average_bandwidth_mbps": 0 - } - ], - "_last_modified_user": "admin", - "_last_modified_time": 1438383180608, - "_create_time": 1438383180608, - "_create_user": "admin", - "_revision": 0 -} - -FAKE_ROUTER_UUID = uuidutils.generate_uuid() -FAKE_ROUTER = { - "resource_type": "LogicalRouter", - "revision": 0, - "id": FAKE_ROUTER_UUID, - "display_name": FAKE_NAME -} - -FAKE_ROUTER_PORT_UUID = uuidutils.generate_uuid() -FAKE_ROUTER_PORT = { - "resource_type": "LogicalRouterLinkPort", - "revision": 0, - "id": FAKE_ROUTER_PORT_UUID, - "display_name": FAKE_NAME, - "logical_router_id": FAKE_ROUTER_UUID -} diff --git a/vmware_nsx/tests/unit/nsx_v3/test_dhcp_metadata.py b/vmware_nsx/tests/unit/nsx_v3/test_dhcp_metadata.py index 8bcd8acb6d..ae3aa4498d 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_dhcp_metadata.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_dhcp_metadata.py @@ -25,11 +25,12 @@ from oslo_config import cfg from oslo_utils import uuidutils from vmware_nsx.common import exceptions as nsx_exc -from vmware_nsx.common import nsx_constants from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db from vmware_nsx.extensions import advancedserviceproviders as as_providers +from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import resources as nsx_resources +from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils from vmware_nsx.tests.unit.nsx_v3 import test_plugin @@ -456,7 +457,7 @@ class NsxNativeMetadataTestCase(test_plugin.NsxV3PluginTestCaseMixin): with self.network() as network: nsx_net_id = self.plugin._get_network_nsx_id( context.get_admin_context(), network['network']['id']) - tags = utils.build_v3_tags_payload( + tags = nsxlib_utils.build_v3_tags_payload( network['network'], resource_type='os-neutron-net-id', project_name=None) name = utils.get_name_and_uuid('%s-%s' % ( diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index d37fa2f25b..95da7abeb9 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -47,7 +47,7 @@ from vmware_nsx.common import utils from vmware_nsx.plugins.nsx_v3 import plugin as nsx_plugin from vmware_nsx.tests import unit as vmware from vmware_nsx.tests.unit.extensions import test_metadata -from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks +from vmware_nsx.tests.unit.nsxlib.v3 import mocks as nsx_v3_mocks from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase diff --git a/vmware_nsx/tests/unit/nsx_v3/mocks.py b/vmware_nsx/tests/unit/nsxlib/v3/mocks.py similarity index 98% rename from vmware_nsx/tests/unit/nsx_v3/mocks.py rename to vmware_nsx/tests/unit/nsxlib/v3/mocks.py index 261ab8f469..1c7682d377 100644 --- a/vmware_nsx/tests/unit/nsx_v3/mocks.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/mocks.py @@ -17,7 +17,7 @@ import six.moves.urllib.parse as urlparse from oslo_serialization import jsonutils from oslo_utils import uuidutils -from vmware_nsx.common import nsx_constants +from vmware_nsx.nsxlib.v3 import nsx_constants FAKE_NAME = "fake_name" @@ -135,7 +135,7 @@ class MockRequestSessionApi(object): def _build_response(self, url, content=None, status=requests.codes.ok, **kwargs): - if type(content) is list: + if isinstance(content, list): content = { 'result_count': len(content), 'results': content diff --git a/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py b/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py index e6dc158462..e015bc6aa9 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/nsxlib_testcase.py @@ -45,14 +45,14 @@ def _mock_nsxlib(): def _return_id_key(*args, **kwargs): return {'id': uuidutils.generate_uuid()} - # FIXME(arosen): this is duplicated in test_plugin - def _mock_create_firewall_rules(*args): + def _mock_add_rules_in_section(*args): # NOTE(arosen): the code in the neutron plugin expects the # neutron rule id as the display_name. - rules = args[5] + rules = args[0] return { 'rules': [ - {'display_name': rule['id'], 'id': uuidutils.generate_uuid()} + {'display_name': rule['display_name'], + 'id': uuidutils.generate_uuid()} for rule in rules ]} @@ -70,15 +70,15 @@ def _mock_nsxlib(): side_effect=_return_id_key).start() mock.patch( - "vmware_nsx.nsxlib.v3.NsxLib._init_default_section", + "vmware_nsx.nsxlib.v3.NsxLib.init_default_section", side_effect=_return_id_key).start() mock.patch( "vmware_nsx.nsxlib.v3.NsxLib.list_nsgroups").start() mock.patch( - "vmware_nsx.nsxlib.v3.NsxLib.create_firewall_rules", - side_effect=_mock_create_firewall_rules).start() + "vmware_nsx.nsxlib.v3.NsxLib.add_rules_in_section", + side_effect=_mock_add_rules_in_section).start() mock.patch( "vmware_nsx.nsxlib.v3.NsxLib.get_transport_zone_id_by_name_or_id", diff --git a/vmware_nsx/tests/unit/nsxlib/v3/test_client.py b/vmware_nsx/tests/unit/nsxlib/v3/test_client.py index 7caae76a7e..fd9fd17378 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/test_client.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_client.py @@ -20,7 +20,7 @@ from oslo_serialization import jsonutils from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc -from vmware_nsx.tests.unit.nsx_v3 import mocks +from vmware_nsx.tests.unit.nsxlib.v3 import mocks from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase diff --git a/vmware_nsx/tests/unit/nsxlib/v3/test_cluster.py b/vmware_nsx/tests/unit/nsxlib/v3/test_cluster.py index 466c609adb..401b72de7e 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/test_cluster.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_cluster.py @@ -23,7 +23,7 @@ from requests import exceptions as requests_exceptions from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import cluster from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc -from vmware_nsx.tests.unit.nsx_v3 import mocks +from vmware_nsx.tests.unit.nsxlib.v3 import mocks from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase diff --git a/vmware_nsx/tests/unit/nsxlib/v3/test_constants.py b/vmware_nsx/tests/unit/nsxlib/v3/test_constants.py new file mode 100644 index 0000000000..b51c8dfdcc --- /dev/null +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_constants.py @@ -0,0 +1,162 @@ +# Copyright (c) 2016 VMware, Inc. +# +# 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_utils import uuidutils + +FAKE_NAME = "fake_name" +FAKE_SWITCH_UUID = uuidutils.generate_uuid() + +FAKE_PORT_UUID = uuidutils.generate_uuid() +FAKE_PORT = { + "id": FAKE_PORT_UUID, + "display_name": FAKE_NAME, + "resource_type": "LogicalPort", + "address_bindings": [], + "logical_switch_id": FAKE_SWITCH_UUID, + "admin_state": "UP", + "attachment": { + "id": "9ca8d413-f7bf-4276-b4c9-62f42516bdb2", + "attachment_type": "VIF" + }, + "switching_profile_ids": [ + { + "value": "64814784-7896-3901-9741-badeff705639", + "key": "IpDiscoverySwitchingProfile" + }, + { + "value": "fad98876-d7ff-11e4-b9d6-1681e6b88ec1", + "key": "SpoofGuardSwitchingProfile" + }, + { + "value": "93b4b7e8-f116-415d-a50c-3364611b5d09", + "key": "PortMirroringSwitchingProfile" + }, + { + "value": "fbc4fb17-83d9-4b53-a286-ccdf04301888", + "key": "SwitchSecuritySwitchingProfile" + }, + { + "value": "f313290b-eba8-4262-bd93-fab5026e9495", + "key": "QosSwitchingProfile" + } + ] +} + +FAKE_CONTAINER_PORT = { + "id": FAKE_PORT_UUID, + "display_name": FAKE_NAME, + "resource_type": "LogicalPort", + "address_bindings": [ + { + "ip_address": "192.168.1.110", + "mac_address": "aa:bb:cc:dd:ee:ff" + } + ], + "logical_switch_id": FAKE_SWITCH_UUID, + "admin_state": "UP", + "attachment": { + "id": "9ca8d413-f7bf-4276-b4c9-62f42516bdb2", + "attachment_type": "CIF", + "context": { + "vlan_tag": 122, + "container_host_vif_id": "c6f817a0-4e36-421e-98a6-8a2faed880bc", + "key_values": [], + "resource_type": "CifAttachmentContext", + } + }, + "switching_profile_ids": [ + { + "value": "64814784-7896-3901-9741-badeff705639", + "key": "IpDiscoverySwitchingProfile" + }, + { + "value": "fad98876-d7ff-11e4-b9d6-1681e6b88ec1", + "key": "SpoofGuardSwitchingProfile" + }, + { + "value": "93b4b7e8-f116-415d-a50c-3364611b5d09", + "key": "PortMirroringSwitchingProfile" + }, + { + "value": "fbc4fb17-83d9-4b53-a286-ccdf04301888", + "key": "SwitchSecuritySwitchingProfile" + }, + { + "value": "f313290b-eba8-4262-bd93-fab5026e9495", + "key": "QosSwitchingProfile" + } + ] +} + + +FAKE_ROUTER_UUID = uuidutils.generate_uuid() +FAKE_ROUTER = { + "resource_type": "LogicalRouter", + "revision": 0, + "id": FAKE_ROUTER_UUID, + "display_name": FAKE_NAME +} + +FAKE_ROUTER_PORT_UUID = uuidutils.generate_uuid() +FAKE_ROUTER_PORT = { + "resource_type": "LogicalRouterLinkPort", + "revision": 0, + "id": FAKE_ROUTER_PORT_UUID, + "display_name": FAKE_NAME, + "logical_router_id": FAKE_ROUTER_UUID +} + +FAKE_QOS_PROFILE = { + "resource_type": "QosSwitchingProfile", + "id": uuidutils.generate_uuid(), + "display_name": FAKE_NAME, + "system_defined": False, + "dscp": { + "priority": 25, + "mode": "UNTRUSTED" + }, + "tags": [], + "description": FAKE_NAME, + "class_of_service": 0, + "shaper_configuration": [ + { + "resource_type": "IngressRateShaper", + "enabled": False, + "peak_bandwidth_mbps": 0, + "burst_size_bytes": 0, + "average_bandwidth_mbps": 0 + }, + { + "resource_type": "IngressBroadcastRateShaper", + "enabled": False, + "peak_bandwidth_kbps": 0, + "average_bandwidth_kbps": 0, + "burst_size_bytes": 0 + }, + { + "resource_type": "EgressRateShaper", + "enabled": False, + "peak_bandwidth_mbps": 0, + "burst_size_bytes": 0, + "average_bandwidth_mbps": 0 + } + ], + "_last_modified_user": "admin", + "_last_modified_time": 1438383180608, + "_create_time": 1438383180608, + "_create_user": "admin", + "_revision": 0 +} diff --git a/vmware_nsx/tests/unit/nsxlib/v3/test_qos_switching_profile.py b/vmware_nsx/tests/unit/nsxlib/v3/test_qos_switching_profile.py index 5fc8d47971..b5e56f1e2f 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/test_qos_switching_profile.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_qos_switching_profile.py @@ -17,8 +17,8 @@ import mock from oslo_log import log -from vmware_nsx.tests.unit.nsx_v3 import test_constants as test_constants_v3 from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase +from vmware_nsx.tests.unit.nsxlib.v3 import test_constants as test_constants_v3 LOG = log.getLogger(__name__) diff --git a/vmware_nsx/tests/unit/nsxlib/v3/test_resources.py b/vmware_nsx/tests/unit/nsxlib/v3/test_resources.py index 67bc5f1416..4736cec007 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/test_resources.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_resources.py @@ -20,10 +20,10 @@ import mock from oslo_serialization import jsonutils from vmware_nsx.nsxlib.v3 import resources -from vmware_nsx.tests.unit.nsx_v3 import mocks -from vmware_nsx.tests.unit.nsx_v3 import test_constants as test_constants_v3 +from vmware_nsx.tests.unit.nsxlib.v3 import mocks from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase from vmware_nsx.tests.unit.nsxlib.v3 import test_client +from vmware_nsx.tests.unit.nsxlib.v3 import test_constants as test_constants_v3 CLIENT_PKG = test_client.CLIENT_PKG diff --git a/vmware_nsx/tests/unit/nsxlib/v3/test_switch.py b/vmware_nsx/tests/unit/nsxlib/v3/test_switch.py index 6039acf6bd..4e6cfebc00 100644 --- a/vmware_nsx/tests/unit/nsxlib/v3/test_switch.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_switch.py @@ -17,8 +17,8 @@ import mock from oslo_log import log -from vmware_nsx.common import nsx_constants -from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks +from vmware_nsx.nsxlib.v3 import nsx_constants +from vmware_nsx.tests.unit.nsxlib.v3 import mocks as nsx_v3_mocks from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase diff --git a/vmware_nsx/tests/unit/nsx_v3/test_utils.py b/vmware_nsx/tests/unit/nsxlib/v3/test_utils.py similarity index 97% rename from vmware_nsx/tests/unit/nsx_v3/test_utils.py rename to vmware_nsx/tests/unit/nsxlib/v3/test_utils.py index 285b5bf843..3d9a7dd034 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_utils.py +++ b/vmware_nsx/tests/unit/nsxlib/v3/test_utils.py @@ -13,14 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin from neutron import version from neutron_lib import exceptions as n_exc -from vmware_nsx.common import utils -from vmware_nsx.tests.unit.nsx_v3 import test_plugin +from vmware_nsx.nsxlib.v3 import utils +from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase -class TestNsxV3Utils(test_plugin.NsxV3PluginTestCaseMixin): +class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase, + nsxlib_testcase.NsxClientTestCase): def test_build_v3_tags_payload(self): result = utils.build_v3_tags_payload( diff --git a/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py b/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py index afa6dbaa8b..ddd5a97814 100644 --- a/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py +++ b/vmware_nsx/tests/unit/services/l2gateway/test_nsxv3_driver.py @@ -31,10 +31,10 @@ from neutron import context from neutron.tests import base from neutron_lib import exceptions as n_exc -from vmware_nsx.common import nsx_constants +from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.services.l2gateway.nsx_v3 import driver as nsx_v3_driver -from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsx_v3_plugin +from vmware_nsx.tests.unit.nsxlib.v3 import mocks as nsx_v3_mocks NSX_V3_PLUGIN_CLASS = ('vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin') diff --git a/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py b/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py index a41bdff72b..a4b65ec2f7 100644 --- a/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py +++ b/vmware_nsx/tests/unit/services/qos/test_nsxv3_notification.py @@ -24,8 +24,8 @@ from neutron.objects.qos import rule as rule_object from neutron.services.qos import qos_plugin from neutron.tests.unit.services.qos import base -from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db +from vmware_nsx.nsxlib.v3 import utils from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils from vmware_nsx.tests.unit.nsx_v3 import test_plugin