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
This commit is contained in:
Adit Sarfaty 2016-09-14 08:13:55 +03:00
parent a3b17e2441
commit a7b5bfafcc
39 changed files with 977 additions and 877 deletions

View File

@ -13,52 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # 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 # L2 agent vif type
VIF_TYPE_DVS = 'dvs' VIF_TYPE_DVS = 'dvs'
# NSXv3 L2 Gateway constants
BRIDGE_ENDPOINT = "BRIDGEENDPOINT"
# NSX service type
SERVICE_DHCP = "dhcp"
# NSXv3 CORE PLUGIN PATH # NSXv3 CORE PLUGIN PATH
VMWARE_NSX_V3_PLUGIN_NAME = 'vmware_nsx.plugin.NsxV3Plugin' VMWARE_NSX_V3_PLUGIN_NAME = 'vmware_nsx.plugin.NsxV3Plugin'

View File

@ -18,25 +18,20 @@ import functools
import hashlib import hashlib
import eventlet import eventlet
import six
from neutron import version as n_version from neutron import version as n_version
from neutron_lib.api import validators from neutron_lib.api import validators
from neutron_lib import constants 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_context import context as common_context
from oslo_log import log 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__) LOG = log.getLogger(__name__)
MAX_DISPLAY_NAME_LEN = 40 MAX_DISPLAY_NAME_LEN = 40
MAX_RESOURCE_TYPE_LEN = 20
MAX_TAG_LEN = 40
NEUTRON_VERSION = n_version.version_info.release_string() NEUTRON_VERSION = n_version.version_info.release_string()
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
OS_NEUTRON_ID_SCOPE = 'os-neutron-id' OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
NSXV3_VERSION_1_1_0 = '1.1.0' NSXV3_VERSION_1_1_0 = '1.1.0'
@ -111,137 +106,6 @@ def check_and_truncate(display_name):
return display_name or '' 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 <resource_type>:<resource-id>, os-project-id:<tenant-id>,
os-project-name:<project_name> os-api-version:<neutron-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): def read_file(path):
try: try:
with open(path) as file: with open(path) as file:

View File

@ -14,10 +14,12 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import six
from sqlalchemy.orm import exc
from oslo_db import exception as db_exc from oslo_db import exception as db_exc
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
from sqlalchemy.orm import exc
import neutron.db.api as db import neutron.db.api as db
@ -27,6 +29,20 @@ from vmware_nsx.db import nsx_models
LOG = logging.getLogger(__name__) 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): def get_network_bindings(session, network_id):
session = session or db.get_session() session = session or db.get_session()
return (session.query(nsx_models.TzNetworkBinding). return (session.query(nsx_models.TzNetworkBinding).
@ -247,6 +263,19 @@ def get_nsx_security_group_id(session, neutron_id):
return None 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): def _delete_by_neutron_id(session, model, neutron_id):
return session.query(model).filter_by(neutron_id=neutron_id).delete() 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)) 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): def get_sg_rule_mapping(session, rule_id):
rule_mapping = session.query( rule_mapping = session.query(
nsx_models.NeutronNsxRuleMapping).filter_by( nsx_models.NeutronNsxRuleMapping).filter_by(
neutron_id=rule_id).one() neutron_id=rule_id).one()
return rule_mapping.nsx_id 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)

View File

@ -27,7 +27,7 @@ down_revision = 'c288bb6a7252'
from alembic import op from alembic import op
import sqlalchemy as sa 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( nsx_service_type_enum = sa.Enum(

View File

@ -27,7 +27,7 @@ from sqlalchemy import sql
from neutron.db import models_v2 from neutron.db import models_v2
from oslo_db.sqlalchemy import models 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): class TzNetworkBinding(model_base.BASEV2, models.TimestampMixin):

View File

@ -29,6 +29,7 @@ from sqlalchemy.sql import expression as expr
from vmware_nsx._i18n import _, _LE, _LW from vmware_nsx._i18n import _, _LE, _LW
from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.common import nsxv_constants 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.db import nsxv_models
from vmware_nsx.extensions import dhcp_mtu as ext_dhcp_mtu from vmware_nsx.extensions import dhcp_mtu as ext_dhcp_mtu
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain 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__) 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, def add_nsxv_router_binding(session, router_id, vse_id, lswitch_id, status,
appliance_size=nsxv_constants.LARGE, appliance_size=nsxv_constants.LARGE,
edge_type=nsxv_constants.SERVICE_EDGE, edge_type=nsxv_constants.SERVICE_EDGE,
@ -117,7 +104,7 @@ def get_nsxv_router_bindings(session, filters=None,
like_filters=None): like_filters=None):
session = db.get_session() session = db.get_session()
query = session.query(nsxv_models.NsxvRouterBinding) query = session.query(nsxv_models.NsxvRouterBinding)
return _apply_filters_to_query(query, nsxv_models.NsxvRouterBinding, return nsx_db._apply_filters_to_query(query, nsxv_models.NsxvRouterBinding,
filters, like_filters).all() filters, like_filters).all()
@ -586,7 +573,7 @@ def get_nsxv_spoofguard_policy_network_mappings(session, filters=None,
like_filters=None): like_filters=None):
session = db.get_session() session = db.get_session()
query = session.query(nsxv_models.NsxvSpoofGuardPolicyNetworkMapping) query = session.query(nsxv_models.NsxvSpoofGuardPolicyNetworkMapping)
return _apply_filters_to_query( return nsx_db._apply_filters_to_query(
query, nsxv_models.NsxvSpoofGuardPolicyNetworkMapping, query, nsxv_models.NsxvSpoofGuardPolicyNetworkMapping,
filters, like_filters).all() filters, like_filters).all()

View File

@ -16,23 +16,17 @@
from oslo_log import log from oslo_log import log
from vmware_nsx._i18n import _, _LW 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 client
from vmware_nsx.nsxlib.v3 import cluster 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 exceptions
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import security from vmware_nsx.nsxlib.v3 import security
from vmware_nsx.nsxlib.v3 import utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
# Max amount of time to try a request
DEFAULT_MAX_ATTEMPTS = 3
class NsxLib(security.Security):
class NsxLib(dfw_api.DfwApi, security.Security):
MAX_ATTEMPTS = DEFAULT_MAX_ATTEMPTS
def __init__(self, def __init__(self,
username=None, username=None,
@ -45,9 +39,11 @@ class NsxLib(dfw_api.DfwApi, security.Security):
http_read_timeout=None, http_read_timeout=None,
conn_idle_timeout=None, conn_idle_timeout=None,
http_provider=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( self.cluster = cluster.NSXClusteredAPI(
username=username, password=password, username=username, password=password,
retries=retries, insecure=insecure, retries=retries, insecure=insecure,
@ -58,7 +54,9 @@ class NsxLib(dfw_api.DfwApi, security.Security):
conn_idle_timeout=conn_idle_timeout, conn_idle_timeout=conn_idle_timeout,
http_provider=http_provider) http_provider=http_provider)
# create the Client
self.client = client.NSX3Client(self.cluster) self.client = client.NSX3Client(self.cluster)
super(NsxLib, self).__init__() super(NsxLib, self).__init__()
def get_version(self): def get_version(self):
@ -70,7 +68,7 @@ class NsxLib(dfw_api.DfwApi, security.Security):
resource = "edge-clusters/%s" % edge_cluster_uuid resource = "edge-clusters/%s" % edge_cluster_uuid
return self.client.get(resource) 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): def update_resource_with_retry(self, resource, payload):
revised_payload = self.client.get(resource) revised_payload = self.client.get(resource)
for key_name in payload.keys(): for key_name in payload.keys():
@ -128,8 +126,7 @@ class NsxLib(dfw_api.DfwApi, security.Security):
return self.client.create(resource, body) return self.client.create(resource, body)
@utils.retry_upon_exception_nsxv3(exceptions.StaleRevision, @utils.retry_upon_exception(exceptions.StaleRevision)
max_attempts=MAX_ATTEMPTS)
def delete_logical_switch(self, lswitch_id): def delete_logical_switch(self, lswitch_id):
resource = 'logical-switches/%s?detach=true&cascade=true' % lswitch_id resource = 'logical-switches/%s?detach=true&cascade=true' % lswitch_id
self.client.delete(resource) self.client.delete(resource)
@ -138,8 +135,7 @@ class NsxLib(dfw_api.DfwApi, security.Security):
resource = "logical-switches/%s" % logical_switch_id resource = "logical-switches/%s" % logical_switch_id
return self.client.get(resource) return self.client.get(resource)
@utils.retry_upon_exception_nsxv3(exceptions.StaleRevision, @utils.retry_upon_exception(exceptions.StaleRevision)
max_attempts=MAX_ATTEMPTS)
def update_logical_switch(self, lswitch_id, name=None, admin_state=None, def update_logical_switch(self, lswitch_id, name=None, admin_state=None,
tags=None): tags=None):
resource = "logical-switches/%s" % lswitch_id resource = "logical-switches/%s" % lswitch_id
@ -346,12 +342,12 @@ class NsxLib(dfw_api.DfwApi, security.Security):
if len(matched_results) == 0: if len(matched_results) == 0:
err_msg = (_("Could not find %(resource)s %(name)s") % err_msg = (_("Could not find %(resource)s %(name)s") %
{'name': name_or_id, 'resource': resource}) {'name': name_or_id, 'resource': resource})
# XXX improve exception handling... # TODO(asarfaty): improve exception handling...
raise exceptions.ManagerError(details=err_msg) raise exceptions.ManagerError(details=err_msg)
elif len(matched_results) > 1: elif len(matched_results) > 1:
err_msg = (_("Found multiple %(resource)s named %(name)s") % err_msg = (_("Found multiple %(resource)s named %(name)s") %
{'name': name_or_id, 'resource': resource}) {'name': name_or_id, 'resource': resource})
# XXX improve exception handling... # TODO(asarfaty): improve exception handling...
raise exceptions.ManagerError(details=err_msg) raise exceptions.ManagerError(details=err_msg)
return matched_results[0].get('id') return matched_results[0].get('id')

View File

@ -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)

View File

@ -18,7 +18,7 @@ from neutron_lib.api import validators
from neutron_lib import constants from neutron_lib import constants
from oslo_config import cfg 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): def build_dhcp_server_config(network, subnet, port, project_name):

View File

@ -21,10 +21,10 @@ from oslo_config import cfg
from oslo_log import log from oslo_log import log
from vmware_nsx._i18n import _, _LW from vmware_nsx._i18n import _, _LW
from vmware_nsx.common import utils
from vmware_nsx.nsxlib import v3 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 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__) LOG = log.getLogger(__name__)
@ -40,7 +40,7 @@ class NSGroupManager(object):
are also of type NSGroups) to group the other NSGroups and associate it are also of type NSGroups) to group the other NSGroups and associate it
with these rules. with these rules.
In practice, one NSGroup (nested) can't contain all the other NSGroups, as 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 create several nested groups instead of just one, and we evenly distribute
NSGroups (security-groups) between them. NSGroups (security-groups) between them.
By using an hashing function on the NSGroup uuid we determine in which 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.') NESTED_GROUP_DESCRIPTION = ('OpenStack NSGroup. Do not delete.')
def __init__(self, size): def __init__(self, size):
# XXX intergrate this in a better way.. # TODO(asarfaty): integrate this in a better way..
self.nsx = v3.NsxLib( self.nsx = v3.NsxLib(
username=cfg.CONF.nsx_v3.nsx_api_user, username=cfg.CONF.nsx_v3.nsx_api_user,
password=cfg.CONF.nsx_v3.nsx_api_password, password=cfg.CONF.nsx_v3.nsx_api_password,
@ -84,7 +84,7 @@ class NSGroupManager(object):
nested_groups = { nested_groups = {
self._get_nested_group_index_from_name(nsgroup): nsgroup['id'] self._get_nested_group_index_from_name(nsgroup): nsgroup['id']
for nsgroup in self.nsx.list_nsgroups() for nsgroup in self.nsx.list_nsgroups()
if utils.is_internal_resource(nsgroup)} if nsxlib_utils.is_internal_resource(nsgroup)}
if nested_groups: if nested_groups:
size = max(requested_size, max(nested_groups) + 1) size = max(requested_size, max(nested_groups) + 1)
@ -115,7 +115,7 @@ class NSGroupManager(object):
name_prefix = NSGroupManager.NESTED_GROUP_NAME name_prefix = NSGroupManager.NESTED_GROUP_NAME
name = '%s %s' % (name_prefix, index + 1) name = '%s %s' % (name_prefix, index + 1)
description = NSGroupManager.NESTED_GROUP_DESCRIPTION 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) return self.nsx.create_nsgroup(name, description, tags)
def _hash_uuid(self, internal_id): def _hash_uuid(self, internal_id):
@ -138,7 +138,7 @@ class NSGroupManager(object):
LOG.debug("Adding NSGroup %s to nested group %s", LOG.debug("Adding NSGroup %s to nested group %s",
nsgroup_id, group) nsgroup_id, group)
self.nsx.add_nsgroup_members(group, self.nsx.add_nsgroup_members(group,
firewall.NSGROUP, consts.NSGROUP,
[nsgroup_id]) [nsgroup_id])
break break
except exceptions.NSGroupIsFull: except exceptions.NSGroupIsFull:
@ -153,7 +153,8 @@ class NSGroupManager(object):
for group in self._suggest_nested_group(nsgroup_id): for group in self._suggest_nested_group(nsgroup_id):
try: try:
self.nsx.remove_nsgroup_member( self.nsx.remove_nsgroup_member(
group, firewall.NSGROUP, nsgroup_id, verify=True) group, consts.NSGROUP,
nsgroup_id, verify=True)
break break
except exceptions.NSGroupMemberNotFound: except exceptions.NSGroupMemberNotFound:
LOG.warning(_LW("NSGroup %(nsgroup)s was expected to be found " LOG.warning(_LW("NSGroup %(nsgroup)s was expected to be found "

View File

@ -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'

View File

@ -20,10 +20,10 @@ import six
from oslo_config import cfg from oslo_config import cfg
from vmware_nsx._i18n import _ 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 client
from vmware_nsx.nsxlib.v3 import exceptions 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( SwitchingProfileTypeId = collections.namedtuple(
@ -285,13 +285,13 @@ class LogicalPort(AbstractRESTResource):
attachment=attachment)) attachment=attachment))
return self._client.create(body=body) return self._client.create(body=body)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def delete(self, lport_id): def delete(self, lport_id):
return self._client.url_delete('%s?detach=true' % lport_id) return self._client.url_delete('%s?detach=true' % lport_id)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def update(self, lport_id, vif_uuid, def update(self, lport_id, vif_uuid,
@ -342,7 +342,7 @@ class LogicalRouter(AbstractRESTResource):
def delete(self, lrouter_id): def delete(self, lrouter_id):
return self._client.url_delete(lrouter_id) return self._client.url_delete(lrouter_id)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def update(self, lrouter_id, *args, **kwargs): def update(self, lrouter_id, *args, **kwargs):
@ -389,7 +389,7 @@ class LogicalRouterPort(AbstractRESTResource):
return self._client.create(body=body) return self._client.create(body=body)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def update(self, logical_port_id, **kwargs): def update(self, logical_port_id, **kwargs):
@ -402,7 +402,7 @@ class LogicalRouterPort(AbstractRESTResource):
# new revision_id # new revision_id
return self._client.update(logical_port_id, body=logical_router_port) return self._client.update(logical_port_id, body=logical_router_port)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def delete(self, logical_port_id): def delete(self, logical_port_id):
@ -511,7 +511,7 @@ class LogicalDhcpServer(AbstractRESTResource):
options, tags) options, tags)
return self._client.create(body=body) return self._client.create(body=body)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def update(self, uuid, dhcp_profile_id=None, server_ip=None, name=None, 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) url = "%s/static-bindings/%s" % (server_uuid, binding_uuid)
return self._client.url_get(url) return self._client.url_get(url)
@utils.retry_upon_exception_nsxv3( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries) max_attempts=cfg.CONF.nsx_v3.retries)
def update_binding(self, server_uuid, binding_uuid, **kwargs): def update_binding(self, server_uuid, binding_uuid, **kwargs):

View File

@ -22,9 +22,9 @@ from neutron_lib import exceptions as n_exc
from oslo_log import log from oslo_log import log
from vmware_nsx._i18n import _, _LW 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 exceptions
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -15,34 +15,27 @@
# under the License. # under the License.
""" """
NSX-V3 Plugin security integration module NSX-V3 Plugin security integration & Distributed Firewall module
""" """
from neutron_lib import constants from neutron_lib import constants
from oslo_config import cfg
from oslo_log import log from oslo_log import log
from oslo_utils import excutils from oslo_utils import excutils
from vmware_nsx._i18n import _LE from vmware_nsx._i18n import _LE, _LW
from vmware_nsx.common import utils from vmware_nsx.nsxlib.v3 import client as nsxclient
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.nsxlib.v3 import exceptions 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__) LOG = log.getLogger(__name__)
DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups' DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups'
DEFAULT_SECTION_TAG_NAME = 'neutron_default_dfw_section'
PORT_SG_SCOPE = 'os-security-group' PORT_SG_SCOPE = 'os-security-group'
MAX_NSGROUPS_CRITERIA_TAGS = 10 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): class Security(object):
def _get_l4_protocol_name(self, protocol_number): def _get_l4_protocol_name(self, protocol_number):
@ -52,24 +45,26 @@ class Security(object):
protocol_number) protocol_number)
protocol_number = int(protocol_number) protocol_number = int(protocol_number)
if protocol_number == 6: if protocol_number == 6:
return firewall.TCP return consts.TCP
elif protocol_number == 17: elif protocol_number == 17:
return firewall.UDP return consts.UDP
elif protocol_number == 1: elif protocol_number == 1:
return firewall.ICMPV4 return consts.ICMPV4
else: else:
return protocol_number return protocol_number
def _get_direction(self, sg_rule): def _get_direction(self, sg_rule):
return ( 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): def _decide_service(self, sg_rule):
l4_protocol = self._get_l4_protocol_name(sg_rule['protocol']) l4_protocol = self._get_l4_protocol_name(sg_rule['protocol'])
direction = self._get_direction(sg_rule) 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 # If port_range_min is not specified then we assume all ports are
# matched, relying on neutron to perform validation. # matched, relying on neutron to perform validation.
source_ports = [] source_ports = []
@ -82,20 +77,23 @@ class Security(object):
else: else:
destination_ports = ['%(port_range_min)s' % sg_rule] destination_ports = ['%(port_range_min)s' % sg_rule]
if direction == firewall.OUT: if direction == consts.OUT:
source_ports, destination_ports = destination_ports, [] source_ports, destination_ports = destination_ports, []
return self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE, return self.get_nsservice(
consts.L4_PORT_SET_NSSERVICE,
l4_protocol=l4_protocol, l4_protocol=l4_protocol,
source_ports=source_ports, source_ports=source_ports,
destination_ports=destination_ports) destination_ports=destination_ports)
elif l4_protocol == firewall.ICMPV4: elif l4_protocol == consts.ICMPV4:
return self.get_nsservice(firewall.ICMP_TYPE_NSSERVICE, return self.get_nsservice(
consts.ICMP_TYPE_NSSERVICE,
protocol=l4_protocol, protocol=l4_protocol,
icmp_type=sg_rule['port_range_min'], icmp_type=sg_rule['port_range_min'],
icmp_code=sg_rule['port_range_max']) icmp_code=sg_rule['port_range_max'])
elif l4_protocol is not None: elif l4_protocol is not None:
return self.get_nsservice(firewall.IP_PROTOCOL_NSSERVICE, return self.get_nsservice(
consts.IP_PROTOCOL_NSSERVICE,
protocol_number=l4_protocol) protocol_number=l4_protocol)
def _get_fw_rule_from_sg_rule(self, sg_rule, nsgroup_id, rmt_nsgroup_id, def _get_fw_rule_from_sg_rule(self, sg_rule, nsgroup_id, rmt_nsgroup_id,
@ -104,9 +102,9 @@ class Security(object):
ip_protocol = sg_rule['ethertype'].upper() ip_protocol = sg_rule['ethertype'].upper()
direction = self._get_direction(sg_rule) 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( 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) ip_protocol)
else: else:
local_ip_prefix = None local_ip_prefix = None
@ -121,7 +119,7 @@ class Security(object):
if rmt_nsgroup_id: if rmt_nsgroup_id:
source = self.get_nsgroup_reference(rmt_nsgroup_id) source = self.get_nsgroup_reference(rmt_nsgroup_id)
destination = local_ip_prefix or local_group destination = local_ip_prefix or local_group
if direction == firewall.OUT: if direction == consts.OUT:
source, destination = destination, source source, destination = destination, source
service = self._decide_service(sg_rule) service = self._decide_service(sg_rule)
@ -133,17 +131,15 @@ class Security(object):
action, logged) action, logged)
def create_firewall_rules(self, context, section_id, nsgroup_id, 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 # 1. translate rules
# 2. insert in section # 2. insert in section
# 3. save mappings # 3. return the rules
firewall_rules = [] firewall_rules = []
for sg_rule in security_group_rules: for sg_rule in security_group_rules:
remote_nsgroup_id = self._get_remote_nsg_mapping( remote_nsgroup_id = ruleid_2_remote_nsgroup_map[sg_rule['id']]
context, sg_rule, nsgroup_id)
fw_rule = self._get_fw_rule_from_sg_rule( fw_rule = self._get_fw_rule_from_sg_rule(
sg_rule, nsgroup_id, remote_nsgroup_id, sg_rule, nsgroup_id, remote_nsgroup_id,
logging_enabled, action) logging_enabled, action)
@ -167,13 +163,13 @@ class Security(object):
section_id, logging) section_id, logging)
self.update_section(section_id, rules=rules) self.update_section(section_id, rules=rules)
def update_security_group_on_backend(self, context, security_group): def update_security_group_on_backend(self, context, security_group,
nsgroup_id, section_id = self.get_sg_mappings(context.session, nsgroup_id, section_id,
security_group['id']) log_sg_allowed_traffic):
name = self.get_nsgroup_name(security_group) name = self.get_nsgroup_name(security_group)
description = security_group['description'] description = security_group['description']
logging = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic or logging = (log_sg_allowed_traffic or
security_group[sg_logging.LOGGING]) security_group[consts.LOGGING])
rules = self._process_firewall_section_rules_logging_for_update( rules = self._process_firewall_section_rules_logging_for_update(
section_id, logging) section_id, logging)
self.update_nsgroup(nsgroup_id, name, description) self.update_nsgroup(nsgroup_id, name, description)
@ -184,38 +180,6 @@ class Security(object):
# for usability purposes. # for usability purposes.
return '%(name)s - %(id)s' % security_group 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): def get_lport_tags_for_security_groups(self, secgroups):
if len(secgroups) > MAX_NSGROUPS_CRITERIA_TAGS: if len(secgroups) > MAX_NSGROUPS_CRITERIA_TAGS:
raise exceptions.NumberOfNsgroupCriteriaTagsReached( raise exceptions.NumberOfNsgroupCriteriaTagsReached(
@ -232,30 +196,29 @@ class Security(object):
original, updated): original, updated):
added = set(updated) - set(original) added = set(updated) - set(original)
removed = set(original) - set(updated) removed = set(original) - set(updated)
for sg_id in added: for nsgroup_id in added:
nsgroup_id, s = self.get_sg_mappings(context.session, sg_id)
try: try:
self.add_nsgroup_members( self.add_nsgroup_members(
nsgroup_id, firewall.LOGICAL_PORT, [lport_id]) nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT,
[lport_id])
except exceptions.NSGroupIsFull: except exceptions.NSGroupIsFull:
for sg_id in added: for nsgroup_id in added:
nsgroup_id, s = self.get_sg_mappings(
context.session, sg_id)
# NOTE(roeyc): If the port was not added to the nsgroup # NOTE(roeyc): If the port was not added to the nsgroup
# yet, then this request will silently fail. # yet, then this request will silently fail.
self.remove_nsgroup_member( self.remove_nsgroup_member(
nsgroup_id, firewall.LOGICAL_PORT, lport_id) nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT,
lport_id)
raise exceptions.SecurityGroupMaximumCapacityReached( raise exceptions.SecurityGroupMaximumCapacityReached(
sg_id=sg_id) sg_id=nsgroup_id)
except exceptions.ResourceNotFound: except exceptions.ResourceNotFound:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
LOG.error(_LE("NSGroup %s doesn't exists"), nsgroup_id) LOG.error(_LE("NSGroup %s doesn't exists"), nsgroup_id)
for sg_id in removed: for nsgroup_id in removed:
nsgroup_id, s = self.get_sg_mappings(context.session, sg_id)
self.remove_nsgroup_member( 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() fw_sections = self.list_sections()
for section in fw_sections: for section in fw_sections:
if section['display_name'] == name: if section['display_name'] == name:
@ -266,23 +229,28 @@ class Security(object):
name, description, nested_groups, tags) name, description, nested_groups, tags)
block_rule = self.get_firewall_rule_dict( block_rule = self.get_firewall_rule_dict(
'Block All', action=firewall.DROP, 'Block All', action=consts.FW_ACTION_DROP,
logged=cfg.CONF.nsx_v3.log_security_groups_blocked_traffic) logged=log_sg_blocked_traffic)
# TODO(roeyc): Add additional rules to allow IPV6 NDP. # TODO(roeyc): Add additional rules to allow IPV6 NDP.
dhcp_client = self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE, dhcp_client = self.get_nsservice(
l4_protocol=firewall.UDP, consts.L4_PORT_SET_NSSERVICE,
l4_protocol=consts.UDP,
source_ports=[67], source_ports=[67],
destination_ports=[68]) destination_ports=[68])
dhcp_client_rule_in = self.get_firewall_rule_dict( 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 = ( dhcp_server = (
self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE, self.get_nsservice(consts.L4_PORT_SET_NSSERVICE,
l4_protocol=firewall.UDP, l4_protocol=consts.UDP,
source_ports=[68], source_ports=[68],
destination_ports=[67])) destination_ports=[67]))
dhcp_client_rule_out = self.get_firewall_rule_dict( 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'], self.update_section(section['id'],
name, section['description'], name, section['description'],
@ -291,3 +259,205 @@ class Security(object):
dhcp_client_rule_in, dhcp_client_rule_in,
block_rule]) block_rule])
return section['id'] 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)

View File

@ -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 <resource_type>:<resource-id>, os-project-id:<tenant-id>,
os-project-name:<project_name> os-api-version:<neutron-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

View File

@ -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 config # noqa
from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.common import locking from vmware_nsx.common import locking
from vmware_nsx.common import nsx_constants
from vmware_nsx.common import utils from vmware_nsx.common import utils
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.db import extended_security_group 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 providersecuritygroup as provider_sg
from vmware_nsx.extensions import securitygrouplogging as sg_logging from vmware_nsx.extensions import securitygrouplogging as sg_logging
from vmware_nsx.nsxlib import v3 as nsxlib 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 exceptions as nsx_lib_exc
from vmware_nsx.nsxlib.v3 import native_dhcp from vmware_nsx.nsxlib.v3 import native_dhcp
from vmware_nsx.nsxlib.v3 import ns_group_manager 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 resources as nsx_resources
from vmware_nsx.nsxlib.v3 import router from vmware_nsx.nsxlib.v3 import router
from vmware_nsx.nsxlib.v3 import security 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.common import utils as qos_com_utils
from vmware_nsx.services.qos.nsx_v3 import utils as qos_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 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): def _init_nsx_profiles(self):
LOG.debug("Initializing NSX v3 port spoofguard switching profile") 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 = None
self._psec_profile = self._init_port_security_profile() self._psec_profile = self._init_port_security_profile()
if not self._psec_profile: if not self._psec_profile:
@ -236,7 +237,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
LOG.debug("Initializing NSX v3 DHCP switching profile") LOG.debug("Initializing NSX v3 DHCP switching profile")
try: 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 = None
self._dhcp_profile = self._init_dhcp_switching_profile() self._dhcp_profile = self._init_dhcp_switching_profile()
except Exception: except Exception:
@ -247,7 +249,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if utils.is_nsx_version_1_1_0(self._nsx_version): if utils.is_nsx_version_1_1_0(self._nsx_version):
LOG.debug("Initializing NSX v3 Mac Learning switching profile") LOG.debug("Initializing NSX v3 Mac Learning switching profile")
try: 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 = None
self._mac_learning_profile = self._init_mac_learning_profile() self._mac_learning_profile = self._init_mac_learning_profile()
# Only expose the extension if it is supported # Only expose the extension if it is supported
@ -318,14 +321,15 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
"must be disabled") % dhcp_profile_uuid "must be disabled") % dhcp_profile_uuid
raise n_exc.InvalidInput(error_message=msg) 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): def _init_dhcp_switching_profile(self):
with locking.LockManager.get_lock('nsxv3_dhcp_profile_init'): with locking.LockManager.get_lock('nsxv3_dhcp_profile_init'):
profile = self._get_dhcp_security_profile() profile = self._get_dhcp_security_profile()
if not profile: if not profile:
self._switching_profiles.create_dhcp_profile( self._switching_profiles.create_dhcp_profile(
NSX_V3_DHCP_PROFILE_NAME, 'Neutron DHCP Security 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() return self._get_dhcp_security_profile()
def _get_dhcp_security_profile(self): def _get_dhcp_security_profile(self):
@ -345,7 +349,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._switching_profiles.create_mac_learning_profile( self._switching_profiles.create_mac_learning_profile(
NSX_V3_MAC_LEARNING_PROFILE_NAME, NSX_V3_MAC_LEARNING_PROFILE_NAME,
'Neutron MAC Learning Profile', '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() return self._get_mac_learning_profile()
def _get_mac_learning_profile(self): def _get_mac_learning_profile(self):
@ -369,7 +373,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
NSX_V3_PSEC_PROFILE_NAME) NSX_V3_PSEC_PROFILE_NAME)
return profile[0] if profile else None 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): def _init_port_security_profile(self):
profile = self._get_port_security_profile() profile = self._get_port_security_profile()
if profile: if profile:
@ -384,7 +389,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._switching_profiles.create_spoofguard_profile( self._switching_profiles.create_spoofguard_profile(
NSX_V3_PSEC_PROFILE_NAME, 'Neutron Port Security Profile', NSX_V3_PSEC_PROFILE_NAME, 'Neutron Port Security Profile',
whitelist_ports=True, whitelist_switches=False, 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() return self._get_port_security_profile()
def _process_security_group_logging(self): def _process_security_group_logging(self):
@ -396,8 +401,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
sg_logging.LOGGING]) sg_logging.LOGGING])
for sg in [sg for sg in secgroups for sg in [sg for sg in secgroups
if sg[sg_logging.LOGGING] is False]: if sg[sg_logging.LOGGING] is False]:
_, section_id = self.nsxlib.get_sg_mappings(context.session, nsgroup_id, section_id = nsx_db.get_sg_mappings(
sg['id']) context.session, sg['id'])
try: try:
self.nsxlib.set_firewall_rule_logging_for_section( self.nsxlib.set_firewall_rule_logging_for_section(
section_id, logging=log_all_rules) section_id, logging=log_all_rules)
@ -414,9 +419,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
cfg.CONF.nsx_v3.number_of_nested_groups) cfg.CONF.nsx_v3.number_of_nested_groups)
section_description = ("This section is handled by OpenStack to " section_description = ("This section is handled by OpenStack to "
"contain default rules on security-groups.") "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, 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 return nsgroup_manager, section_id
def _init_dhcp_metadata(self): def _init_dhcp_metadata(self):
@ -601,7 +607,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
# update the network name to indicate the neutron id too. # update the network name to indicate the neutron id too.
net_name = utils.get_name_and_uuid(net_data['name'] or 'network', net_name = utils.get_name_and_uuid(net_data['name'] or 'network',
neutron_net_id) neutron_net_id)
tags = utils.build_v3_tags_payload( tags = nsxlib_utils.build_v3_tags_payload(
net_data, resource_type='os-neutron-net-id', net_data, resource_type='os-neutron-net-id',
project_name=context.tenant_name) 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: if is_backend_network and cfg.CONF.nsx_v3.native_dhcp_metadata:
# Enable native metadata proxy for this network. # 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', net_data, resource_type='os-neutron-net-id',
project_name=context.tenant_name) project_name=context.tenant_name)
name = utils.get_name_and_uuid('%s-%s' % ( name = utils.get_name_and_uuid('%s-%s' % (
@ -722,7 +728,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
md_port = self._port_client.create( md_port = self._port_client.create(
nsx_net_id, cfg.CONF.nsx_v3.metadata_proxy_uuid, nsx_net_id, cfg.CONF.nsx_v3.metadata_proxy_uuid,
tags=tags, name=name, 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 " LOG.debug("Created MD-Proxy logical port %(port)s "
"for network %(network)s", "for network %(network)s",
{'port': md_port['id'], {'port': md_port['id'],
@ -923,7 +929,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
server_data = native_dhcp.build_dhcp_server_config( server_data = native_dhcp.build_dhcp_server_config(
network, subnet, neutron_port, context.tenant_name) network, subnet, neutron_port, context.tenant_name)
nsx_net_id = self._get_network_nsx_id(context, network['id']) 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', neutron_port, resource_type='os-neutron-dport-id',
project_name=context.tenant_name) project_name=context.tenant_name)
dhcp_server = None dhcp_server = None
@ -935,7 +941,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
name = self._get_port_name(context, port_data) name = self._get_port_name(context, port_data)
nsx_port = self._port_client.create( nsx_port = self._port_client.create(
nsx_net_id, dhcp_server['id'], tags=tags, name=name, 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 " LOG.debug("Created DHCP logical port %(port)s for "
"network %(network)s", "network %(network)s",
{'port': nsx_port['id'], 'network': network['id']}) {'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. # Add neutron_net_id -> dhcp_service_id mapping to the DB.
nsx_db.add_neutron_nsx_service_binding( nsx_db.add_neutron_nsx_service_binding(
context.session, network['id'], neutron_port['id'], 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: except db_exc.DBError:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
LOG.error(_LE("Failed to create mapping for DHCP port %s," 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 # First delete the DHCP port in this network. Then delete the
# corresponding LogicalDhcpServer for this network. # corresponding LogicalDhcpServer for this network.
dhcp_service = nsx_db.get_nsx_service_binding( 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: if not dhcp_service:
return return
@ -1002,7 +1008,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
try: try:
# Delete neutron_id -> dhcp_service_id mapping from the DB. # Delete neutron_id -> dhcp_service_id mapping from the DB.
nsx_db.delete_neutron_nsx_service_binding( 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: except db_exc.DBError:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
LOG.error(_LE("Unable to delete DHCP server mapping for " LOG.error(_LE("Unable to delete DHCP server mapping for "
@ -1105,7 +1111,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if kwargs: if kwargs:
dhcp_service = nsx_db.get_nsx_service_binding( dhcp_service = nsx_db.get_nsx_service_binding(
context.session, orig_subnet['network_id'], context.session, orig_subnet['network_id'],
nsx_constants.SERVICE_DHCP) nsxlib_consts.SERVICE_DHCP)
if dhcp_service: if dhcp_service:
try: try:
self._dhcp_server.update( self._dhcp_server.update(
@ -1256,13 +1262,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
resource_type = 'os-neutron-rport-id' resource_type = 'os-neutron-rport-id'
else: else:
resource_type = 'os-neutron-port-id' 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, port_data, resource_type=resource_type,
project_name=context.tenant_name) project_name=context.tenant_name)
resource_type = self._get_resource_type_for_device_id( resource_type = self._get_resource_type_for_device_id(
device_owner, device_id) device_owner, device_id)
if resource_type: 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 utils.is_nsx_version_1_1_0(self._nsx_version):
# If port has no security-groups then we don't need to add any # 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 vif_uuid = False
else: else:
# default attachment # default attachment
attachment_type = nsx_constants.ATTACHMENT_VIF attachment_type = nsxlib_consts.ATTACHMENT_VIF
vif_uuid = port_data['id'] vif_uuid = port_data['id']
profiles = [] profiles = []
@ -1423,7 +1429,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if not utils.is_port_dhcp_configurable(port): if not utils.is_port_dhcp_configurable(port):
return return
dhcp_service = nsx_db.get_nsx_service_binding( 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: if not dhcp_service:
return return
for fixed_ip in self._filter_ipv4_dhcp_fixed_ips( 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. # Locate the backend DHCP server for this DHCP port.
dhcp_service = nsx_db.get_nsx_service_binding( dhcp_service = nsx_db.get_nsx_service_binding(
context.session, old_port['network_id'], context.session, old_port['network_id'],
nsx_constants.SERVICE_DHCP) nsxlib_consts.SERVICE_DHCP)
if dhcp_service: if dhcp_service:
new_ip = ips_to_add[0][1] new_ip = ips_to_add[0][1]
try: try:
@ -1586,7 +1592,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if ips_to_add: if ips_to_add:
dhcp_service = nsx_db.get_nsx_service_binding( dhcp_service = nsx_db.get_nsx_service_binding(
context.session, new_port['network_id'], context.session, new_port['network_id'],
nsx_constants.SERVICE_DHCP) nsxlib_consts.SERVICE_DHCP)
if dhcp_service: if dhcp_service:
for (subnet_id, ip) in ips_to_add: for (subnet_id, ip) in ips_to_add:
self._add_dhcp_binding_on_server( self._add_dhcp_binding_on_server(
@ -1622,6 +1628,16 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
{'mac': mac, 'ip': ip, 'port': binding['port_id'], {'mac': mac, 'ip': ip, 'port': binding['port_id'],
'server': binding['nsx_service_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): def create_port(self, context, port, l2gw_port_check=False):
port_data = port['port'] port_data = port['port']
dhcp_opts = port_data.get(ext_edo.EXTRADHCPOPTS, []) 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): if not utils.is_nsx_version_1_1_0(self._nsx_version):
try: try:
self.nsxlib.update_lport_with_security_groups( self._update_lport_with_security_groups(
context, lport['id'], [], sgids or []) context, lport['id'], [], sgids or [])
except Exception as e: except Exception as e:
with excutils.save_and_reraise_exception(reraise=False): with excutils.save_and_reraise_exception(reraise=False):
@ -1762,7 +1778,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
context.session, port_id) context.session, port_id)
self._port_client.delete(nsx_port_id) self._port_client.delete(nsx_port_id)
if not utils.is_nsx_version_1_1_0(self._nsx_version): 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, context, nsx_port_id,
port.get(ext_sg.SECURITYGROUPS, []), []) port.get(ext_sg.SECURITYGROUPS, []), [])
self.disassociate_floatingips(context, port_id) self.disassociate_floatingips(context, port_id)
@ -1866,21 +1882,21 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
resource_type = self._get_resource_type_for_device_id( resource_type = self._get_resource_type_for_device_id(
original_device_owner, updated_device_id) original_device_owner, updated_device_id)
if resource_type: if resource_type:
tags_update = utils.add_v3_tag(tags_update, resource_type, tags_update = nsxlib_utils.add_v3_tag(
updated_device_id) tags_update, resource_type, updated_device_id)
parent_vif_id, tag = self._get_data_from_binding_profile( parent_vif_id, tag = self._get_data_from_binding_profile(
context, updated_port) context, updated_port)
if updated_device_owner in (original_device_owner, if updated_device_owner in (original_device_owner,
l3_db.DEVICE_OWNER_ROUTER_INTF, l3_db.DEVICE_OWNER_ROUTER_INTF,
nsx_constants.BRIDGE_ENDPOINT): nsxlib_consts.BRIDGE_ENDPOINT):
# no attachment change # no attachment change
attachment_type = False attachment_type = False
vif_uuid = False vif_uuid = False
elif updated_device_owner: elif updated_device_owner:
# default attachment # default attachment
attachment_type = nsx_constants.ATTACHMENT_VIF attachment_type = nsxlib_consts.ATTACHMENT_VIF
vif_uuid = updated_port['id'] vif_uuid = updated_port['id']
else: else:
# no attachment # no attachment
@ -1894,7 +1910,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
updated_port.get(ext_sg.SECURITYGROUPS, []) + updated_port.get(ext_sg.SECURITYGROUPS, []) +
updated_port.get(provider_sg.PROVIDER_SECURITYGROUPS, [])) updated_port.get(provider_sg.PROVIDER_SECURITYGROUPS, []))
else: else:
self.nsxlib.update_lport_with_security_groups( self._update_lport_with_security_groups(
context, lport_id, context, lport_id,
original_port.get(ext_sg.SECURITYGROUPS, []) + original_port.get(ext_sg.SECURITYGROUPS, []) +
original_port.get(provider_sg.PROVIDER_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) edge_cluster_uuid = self._get_edge_cluster(new_tier0_uuid)
self._routerlib.update_router_edge_cluster( self._routerlib.update_router_edge_cluster(
nsx_router_id, edge_cluster_uuid) 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', router, resource_type='os-neutron-rport',
project_name=context.tenant_name) project_name=context.tenant_name)
self._routerlib.add_router_link_port(nsx_router_id, new_tier0_uuid, 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) gw_info = self._extract_external_gw(context, router, is_extract=True)
router['router']['id'] = (router['router'].get('id') or router['router']['id'] = (router['router'].get('id') or
uuidutils.generate_uuid()) uuidutils.generate_uuid())
tags = utils.build_v3_tags_payload( tags = nsxlib_utils.build_v3_tags_payload(
router['router'], resource_type='os-neutron-router-id', router['router'], resource_type='os-neutron-router-id',
project_name=context.tenant_name) project_name=context.tenant_name)
result = self._router_client.create( result = self._router_client.create(
@ -2522,7 +2538,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
context, router_id, network_id) context, router_id, network_id)
display_name = utils.get_name_and_uuid( display_name = utils.get_name_and_uuid(
subnet['name'] or 'subnet', subnet['id']) 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', port, resource_type='os-neutron-rport-id',
project_name=context.tenant_name) project_name=context.tenant_name)
tags.append({'scope': 'os-subnet-id', 'tag': subnet['id']}) 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): def _create_fw_section_for_secgroup(self, nsgroup, is_provider):
# NOTE(arosen): if a security group is provider we want to # NOTE(arosen): if a security group is provider we want to
# insert our rules at the top. # insert our rules at the top.
operation = (firewall.INSERT_TOP operation = (nsxlib_consts.FW_INSERT_TOP
if is_provider if is_provider
else firewall.INSERT_BEFORE) else nsxlib_consts.FW_INSERT_BEFORE)
# security-group rules are located in a dedicated firewall section. # security-group rules are located in a dedicated firewall section.
firewall_section = ( firewall_section = (
@ -2791,7 +2807,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
return firewall_section return firewall_section
def _create_security_group_backend_resources(self, secgroup): 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', secgroup, resource_type='os-neutron-secgr-id',
project_name=secgroup['tenant_id']) project_name=secgroup['tenant_id'])
name = self.nsxlib.get_nsgroup_name(secgroup) name = self.nsxlib.get_nsgroup_name(secgroup)
@ -2810,6 +2826,27 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
ns_group, secgroup.get(provider_sg.PROVIDER)) ns_group, secgroup.get(provider_sg.PROVIDER))
return ns_group, firewall_section 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): def create_security_group(self, context, security_group, default_sg=False):
secgroup = security_group['security_group'] secgroup = security_group['security_group']
secgroup['id'] = secgroup.get('id') or uuidutils.generate_uuid() secgroup['id'] = secgroup.get('id') or uuidutils.generate_uuid()
@ -2871,14 +2908,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
# translate and creates firewall rules. # translate and creates firewall rules.
logging = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic logging = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic
or secgroup.get(sg_logging.LOGGING, False)) or secgroup.get(sg_logging.LOGGING, False))
action = (firewall.DROP action = (nsxlib_consts.FW_ACTION_DROP
if secgroup.get(provider_sg.PROVIDER) if secgroup.get(provider_sg.PROVIDER)
else firewall.ALLOW) else nsxlib_consts.FW_ACTION_ALLOW)
rules = self.nsxlib.create_firewall_rules( rules = self._create_firewall_rules(
context, firewall_section['id'], ns_group['id'], context, firewall_section['id'], ns_group['id'],
logging, action, sg_rules) logging, action, sg_rules)
self.nsxlib.save_sg_rule_mappings(context.session, self.save_security_group_rule_mappings(context, rules['rules'])
rules['rules'])
self.nsgroup_manager.add_nsgroup(ns_group['id']) self.nsgroup_manager.add_nsgroup(ns_group['id'])
except nsx_lib_exc.ManagerError: except nsx_lib_exc.ManagerError:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
@ -2905,7 +2941,11 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._process_security_group_properties_update( self._process_security_group_properties_update(
context, secgroup_res, security_group['security_group']) context, secgroup_res, security_group['security_group'])
try: 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: except nsx_lib_exc.ManagerError:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
LOG.exception(_LE("Failed to update security-group %(name)s " 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): def delete_security_group(self, context, id):
self._prevent_non_admin_delete_provider_sg(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) context.session, id)
super(NsxV3Plugin, self).delete_security_group(context, id) super(NsxV3Plugin, self).delete_security_group(context, id)
self.nsxlib.delete_section(section_id) self.nsxlib.delete_section(section_id)
@ -2957,18 +2997,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
security_group = self.get_security_group( security_group = self.get_security_group(
context, sg_id) context, sg_id)
action = firewall.ALLOW action = nsxlib_consts.FW_ACTION_ALLOW
if security_group.get(provider_sg.PROVIDER) is True: if security_group.get(provider_sg.PROVIDER) is True:
# provider security groups are drop rules. # provider security groups are drop rules.
action = firewall.DROP action = nsxlib_consts.FW_ACTION_DROP
sg_id = rules_db[0]['security_group_id'] sg_id = rules_db[0]['security_group_id']
nsgroup_id, section_id = self.nsxlib.get_sg_mappings(context.session, nsgroup_id, section_id = nsx_db.get_sg_mappings(context.session,
sg_id) sg_id)
logging_enabled = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic logging_enabled = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic
or self._is_security_group_logged(context, sg_id)) or self._is_security_group_logged(context, sg_id))
try: try:
rules = self.nsxlib.create_firewall_rules( rules = self._create_firewall_rules(
context, section_id, nsgroup_id, context, section_id, nsgroup_id,
logging_enabled, action, rules_db) logging_enabled, action, rules_db)
except nsx_lib_exc.ManagerError: except nsx_lib_exc.ManagerError:
@ -2976,14 +3016,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
for rule in rules_db: for rule in rules_db:
super(NsxV3Plugin, self).delete_security_group_rule( super(NsxV3Plugin, self).delete_security_group_rule(
context, rule['id']) 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 return rules_db
def delete_security_group_rule(self, context, id): def delete_security_group_rule(self, context, id):
rule_db = self._get_security_group_rule(context, id) rule_db = self._get_security_group_rule(context, id)
sg_id = rule_db['security_group_id'] sg_id = rule_db['security_group_id']
self._prevent_non_admin_delete_provider_sg(context, sg_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) fw_rule_id = nsx_db.get_sg_rule_mapping(context.session, id)
self.nsxlib.delete_rule(section_id, fw_rule_id) self.nsxlib.delete_rule(section_id, fw_rule_id)
super(NsxV3Plugin, self).delete_security_group_rule(context, 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)

View File

@ -34,10 +34,11 @@ from neutron_lib import constants
from neutron_lib import exceptions as n_exc from neutron_lib import exceptions as n_exc
from vmware_nsx._i18n import _, _LE, _LI 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.common import utils as nsx_utils
from vmware_nsx.db import db as nsx_db 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 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__) LOG = logging.getLogger(__name__)
@ -219,7 +220,7 @@ class NsxV3Driver(l2gateway_db.L2GatewayMixin):
tenant_id = context.tenant_id tenant_id = context.tenant_id
gw_connection['tenant_id'] = tenant_id gw_connection['tenant_id'] = tenant_id
try: try:
tags = nsx_utils.build_v3_tags_payload( tags = nsxlib_utils.build_v3_tags_payload(
gw_connection, resource_type='os-neutron-l2gw-id', gw_connection, resource_type='os-neutron-l2gw-id',
project_name=context.tenant_name) project_name=context.tenant_name)
bridge_endpoint = self._core_plugin.nsxlib.create_bridge_endpoint( bridge_endpoint = self._core_plugin.nsxlib.create_bridge_endpoint(

View File

@ -27,11 +27,11 @@ from oslo_utils import excutils
from vmware_nsx._i18n import _, _LE, _LW from vmware_nsx._i18n import _, _LE, _LW
from vmware_nsx.common import exceptions as nsx_exc 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.db import db as nsx_db
from vmware_nsx.nsxlib import v3 as nsxlib from vmware_nsx.nsxlib import v3 as nsxlib
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc 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 resources as nsx_resources
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -177,7 +177,7 @@ class NsxV3Driver(base_driver.TaasBaseDriver,
tf.get('tap_service_id')) tf.get('tap_service_id'))
src_port_id = tf.get('source_port') src_port_id = tf.get('source_port')
dest_port_id = ts.get('port_id') 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', tf, resource_type='os-neutron-mirror-id',
project_name=context._plugin_context.tenant_name) project_name=context._plugin_context.tenant_name)
nsx_direction = self._convert_to_backend_direction( nsx_direction = self._convert_to_backend_direction(

View File

@ -25,8 +25,8 @@ from oslo_log import log as logging
from vmware_nsx._i18n import _, _LW from vmware_nsx._i18n import _, _LW
from vmware_nsx.common import exceptions as nsx_exc 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.db import db as nsx_db
from vmware_nsx.nsxlib.v3 import utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
MAX_KBPS_MIN_VALUE = 1024 MAX_KBPS_MIN_VALUE = 1024

View File

@ -20,9 +20,9 @@ from neutron_lib import constants as const
from oslo_config import cfg from oslo_config import cfg
from vmware_nsx._i18n import _LE, _LI 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.common import utils as nsx_utils
from vmware_nsx.nsxlib.v3 import native_dhcp 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.nsxlib.v3 import resources
from vmware_nsx.shell.admin.plugins.common import constants 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 formatters

View File

@ -19,10 +19,11 @@ from neutron_lib import constants as const
from oslo_config import cfg from oslo_config import cfg
from vmware_nsx._i18n import _LE, _LI 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.common import utils as nsx_utils
from vmware_nsx.dhcp_meta import rpc as nsx_rpc 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 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 constants
from vmware_nsx.shell.admin.plugins.common import formatters from vmware_nsx.shell.admin.plugins.common import formatters
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils 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']) lswitch_id = neutron_client.net_id_to_lswitch_id(network['id'])
if not lswitch_id: if not lswitch_id:
continue continue
tags = nsx_utils.build_v3_tags_payload( tags = nsxlib_utils.build_v3_tags_payload(
network, resource_type='os-neutron-net-id', network, resource_type='os-neutron-net-id',
project_name='admin') project_name='admin')
name = nsx_utils.get_name_and_uuid('%s-%s' % ( name = nsx_utils.get_name_and_uuid('%s-%s' % (

View File

@ -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.admin.plugins.nsxv3.resources import utils as v3_utils
from vmware_nsx.shell import resources as shell from vmware_nsx.shell import resources as shell
from vmware_nsx._i18n import _LE, _LW 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 security
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
LOG = logging.getLogger(__name__) 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) lport_id = neutron_db.get_logical_port_id(port_id)
members.append(lport_id) members.append(lport_id)
nsxlib.add_nsgroup_members( 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']: for rule in secgroup['security_group_rules']:
rule_mapping = (context_.session.query( rule_mapping = (context_.session.query(
@ -229,14 +230,14 @@ def fix_security_groups(resource, event, trigger, **kwargs):
neutron_id=rule['id']).one()) neutron_id=rule['id']).one())
with context_.session.begin(subtransactions=True): with context_.session.begin(subtransactions=True):
context_.session.delete(rule_mapping) context_.session.delete(rule_mapping)
action = (firewall.DROP action = (consts.FW_ACTION_DROP
if secgroup.get(provider_sg.PROVIDER) if secgroup.get(provider_sg.PROVIDER)
else firewall.ALLOW) else consts.FW_ACTION_ALLOW)
rules = nsxlib.create_firewall_rules( rules = plugin._create_firewall_rules(
context_, fw_section['id'], nsgroup['id'], context_, fw_section['id'], nsgroup['id'],
secgroup.get(sg_logging.LOGGING, False), action, secgroup.get(sg_logging.LOGGING, False), action,
secgroup['security_group_rules']) 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 # Add nsgroup to a nested group
plugin.nsgroup_manager.add_nsgroup(nsgroup['id']) 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_id = neutron_db.get_lswitch_and_lport_id(port['id'])
lport = port_client.get(lport_id) lport = port_client.get(lport_id)
criteria_tags = nsxlib.get_lport_tags_for_security_groups(secgroups) 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) lport.get('tags', []), criteria_tags)
port_client._client.update(lport_id, body=lport) port_client._client.update(lport_id, body=lport)

View File

@ -17,9 +17,9 @@ from neutron import context
from neutron.db import db_base_plugin_v2 from neutron.db import db_base_plugin_v2
from oslo_config import cfg from oslo_config import cfg
from vmware_nsx.common import nsx_constants
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.nsxlib import v3 from vmware_nsx.nsxlib import v3
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.plugins.nsx_v3 import plugin from vmware_nsx.plugins.nsx_v3 import plugin

View File

@ -150,4 +150,5 @@ class TestNSXv3ExtendedSGRule(test_nsxv3_plugin.NsxV3PluginTestCaseMixin,
mock.ANY, # ns_group_id mock.ANY, # ns_group_id
False, # logging False, # logging
'ALLOW', # action 'ALLOW', # action
sg_rules) # sg_rules sg_rules, # sg_rules
mock.ANY) # ruleid_2_remote_nsgroup_map

View File

@ -17,9 +17,9 @@ import mock
from neutron.extensions import securitygroup as ext_sg from neutron.extensions import securitygroup as ext_sg
from neutron.tests.unit.extensions import test_securitygroup as test_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 exceptions as nsxlib_exc
from vmware_nsx.nsxlib.v3 import ns_group_manager 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.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.nsx_v3 import test_plugin as test_nsxv3
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase 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 # The first nsgroup is associated with the default secgroup, which is
# not added to this port. # not added to this port.
calls = [mock.call(NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY), calls = [mock.call(NSG_IDS[1],
mock.call(NSG_IDS[2], firewall.LOGICAL_PORT, mock.ANY)] 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) add_member_mock.assert_has_calls(calls, any_order=True)
@_mock_create_and_list_nsgroups @_mock_create_and_list_nsgroups
@ -97,13 +99,16 @@ class TestSecurityGroupsNoDynamicCriteria(test_nsxv3.NsxV3PluginTestCaseMixin,
super(TestSecurityGroupsNoDynamicCriteria, super(TestSecurityGroupsNoDynamicCriteria,
self).test_update_port_with_multiple_security_groups() self).test_update_port_with_multiple_security_groups()
calls = [mock.call(NSG_IDS[0], firewall.LOGICAL_PORT, mock.ANY), calls = [mock.call(NSG_IDS[0],
mock.call(NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY), consts.TARGET_TYPE_LOGICAL_PORT, mock.ANY),
mock.call(NSG_IDS[2], firewall.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) add_member_mock.assert_has_calls(calls, any_order=True)
remove_member_mock.assert_called_with( 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_create_and_list_nsgroups
@mock.patch('vmware_nsx.nsxlib.v3.NsxLib.remove_nsgroup_member') @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() self).test_update_port_remove_security_group_empty_list()
add_member_mock.assert_called_with( 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( 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_create_and_list_nsgroups
@mock.patch('vmware_nsx.nsxlib.v3.NsxLib.add_nsgroup_members') @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 # 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 # revert any changes in the NSGroups - It is required to remove the
# lport from any NSGroups which it was added to during that call. # lport from any NSGroups which it was added to during that call.
calls = [mock.call(NSG_IDS[1], firewall.LOGICAL_PORT, mock.ANY), calls = [mock.call(NSG_IDS[1],
mock.call(NSG_IDS[2], firewall.LOGICAL_PORT, mock.ANY)] 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) remove_member_mock.assert_has_calls(calls, any_order=True)
def test_create_security_group_rule_icmpv6_legacy_protocol_name(self): 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 # There are 5 nested groups, the hash function will return 7, therefore
# we expect that the nsgroup will be placed in the 3rd group. # we expect that the nsgroup will be placed in the 3rd group.
add_member_mock.assert_called_once_with( 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( 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_create_and_list_nsgroups
@mock.patch('vmware_nsx.nsxlib.v3.NsxLib.remove_nsgroup_member') @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 # Trying to add nsgroup to the nested group at index 2 will raise
# NSGroupIsFull exception, we expect that the nsgroup will be added to # NSGroupIsFull exception, we expect that the nsgroup will be added to
# the nested group at index 3. # the nested group at index 3.
calls = [mock.call(NSG_IDS[2], firewall.NSGROUP, [nsgroup_id]), calls = [mock.call(NSG_IDS[2],
mock.call(NSG_IDS[3], firewall.NSGROUP, [nsgroup_id])] consts.NSGROUP, [nsgroup_id]),
mock.call(NSG_IDS[3],
consts.NSGROUP, [nsgroup_id])]
add_member_mock.assert_has_calls(calls) add_member_mock.assert_has_calls(calls)
# Since the nsgroup was added to the nested group at index 3, it will # 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. # remove it from the group at index 3.
calls = [ calls = [
mock.call( mock.call(
NSG_IDS[2], firewall.NSGROUP, nsgroup_id, verify=True), NSG_IDS[2], consts.NSGROUP,
nsgroup_id, verify=True),
mock.call( 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) remove_member_mock.assert_has_calls(calls)
@_mock_create_and_list_nsgroups @_mock_create_and_list_nsgroups
@ -282,9 +294,10 @@ class TestNSGroupManager(nsxlib_testcase.NsxLibTestCase):
size = 3 size = 3
cont_manager = ns_group_manager.NSGroupManager(size) cont_manager = ns_group_manager.NSGroupManager(size)
# list_nsgroups will return nested group 1 and 3, but not group 2. # list_nsgroups will return nested group 1 and 3, but not group 2.
with mock.patch.object(firewall, # FIXME: Not sure what this mock does. no one calls this method now.
'list_nsgroups_mock') as list_nsgroups_mock: #with mock.patch.object(vmware_nsx.nsxlib.v3.NsxLib.list_nsgroups,
list_nsgroups_mock = lambda: list_nsgroups_mock()[::2] # 'list_nsgroups_mock') as list_nsgroups_mock:
# list_nsgroups_mock = lambda: list_nsgroups_mock()[::2]
# invoking the initialization process again, it should process # invoking the initialization process again, it should process
# groups 1 and 3 and create group 2. # groups 1 and 3 and create group 2.
cont_manager = ns_group_manager.NSGroupManager(size) cont_manager = ns_group_manager.NSGroupManager(size)

View File

@ -14,149 +14,4 @@
# limitations under the License. # limitations under the License.
from oslo_utils import uuidutils
PLUGIN_NAME = 'vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin' 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
}

View File

@ -25,11 +25,12 @@ from oslo_config import cfg
from oslo_utils import uuidutils from oslo_utils import uuidutils
from vmware_nsx.common import exceptions as nsx_exc 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.common import utils
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.extensions import advancedserviceproviders as as_providers 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 resources as nsx_resources
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin from vmware_nsx.tests.unit.nsx_v3 import test_plugin
@ -456,7 +457,7 @@ class NsxNativeMetadataTestCase(test_plugin.NsxV3PluginTestCaseMixin):
with self.network() as network: with self.network() as network:
nsx_net_id = self.plugin._get_network_nsx_id( nsx_net_id = self.plugin._get_network_nsx_id(
context.get_admin_context(), network['network']['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', network['network'], resource_type='os-neutron-net-id',
project_name=None) project_name=None)
name = utils.get_name_and_uuid('%s-%s' % ( name = utils.get_name_and_uuid('%s-%s' % (

View File

@ -47,7 +47,7 @@ from vmware_nsx.common import utils
from vmware_nsx.plugins.nsx_v3 import plugin as nsx_plugin from vmware_nsx.plugins.nsx_v3 import plugin as nsx_plugin
from vmware_nsx.tests import unit as vmware from vmware_nsx.tests import unit as vmware
from vmware_nsx.tests.unit.extensions import test_metadata 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 from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

View File

@ -17,7 +17,7 @@ import six.moves.urllib.parse as urlparse
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
from vmware_nsx.common import nsx_constants from vmware_nsx.nsxlib.v3 import nsx_constants
FAKE_NAME = "fake_name" FAKE_NAME = "fake_name"
@ -135,7 +135,7 @@ class MockRequestSessionApi(object):
def _build_response(self, url, content=None, def _build_response(self, url, content=None,
status=requests.codes.ok, **kwargs): status=requests.codes.ok, **kwargs):
if type(content) is list: if isinstance(content, list):
content = { content = {
'result_count': len(content), 'result_count': len(content),
'results': content 'results': content

View File

@ -45,14 +45,14 @@ def _mock_nsxlib():
def _return_id_key(*args, **kwargs): def _return_id_key(*args, **kwargs):
return {'id': uuidutils.generate_uuid()} return {'id': uuidutils.generate_uuid()}
# FIXME(arosen): this is duplicated in test_plugin def _mock_add_rules_in_section(*args):
def _mock_create_firewall_rules(*args):
# NOTE(arosen): the code in the neutron plugin expects the # NOTE(arosen): the code in the neutron plugin expects the
# neutron rule id as the display_name. # neutron rule id as the display_name.
rules = args[5] rules = args[0]
return { return {
'rules': [ 'rules': [
{'display_name': rule['id'], 'id': uuidutils.generate_uuid()} {'display_name': rule['display_name'],
'id': uuidutils.generate_uuid()}
for rule in rules for rule in rules
]} ]}
@ -70,15 +70,15 @@ def _mock_nsxlib():
side_effect=_return_id_key).start() side_effect=_return_id_key).start()
mock.patch( mock.patch(
"vmware_nsx.nsxlib.v3.NsxLib._init_default_section", "vmware_nsx.nsxlib.v3.NsxLib.init_default_section",
side_effect=_return_id_key).start() side_effect=_return_id_key).start()
mock.patch( mock.patch(
"vmware_nsx.nsxlib.v3.NsxLib.list_nsgroups").start() "vmware_nsx.nsxlib.v3.NsxLib.list_nsgroups").start()
mock.patch( mock.patch(
"vmware_nsx.nsxlib.v3.NsxLib.create_firewall_rules", "vmware_nsx.nsxlib.v3.NsxLib.add_rules_in_section",
side_effect=_mock_create_firewall_rules).start() side_effect=_mock_add_rules_in_section).start()
mock.patch( mock.patch(
"vmware_nsx.nsxlib.v3.NsxLib.get_transport_zone_id_by_name_or_id", "vmware_nsx.nsxlib.v3.NsxLib.get_transport_zone_id_by_name_or_id",

View File

@ -20,7 +20,7 @@ from oslo_serialization import jsonutils
from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import client
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc 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 from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

View File

@ -23,7 +23,7 @@ from requests import exceptions as requests_exceptions
from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import client
from vmware_nsx.nsxlib.v3 import cluster from vmware_nsx.nsxlib.v3 import cluster
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc 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 from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

View File

@ -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
}

View File

@ -17,8 +17,8 @@ import mock
from oslo_log import log 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 nsxlib_testcase
from vmware_nsx.tests.unit.nsxlib.v3 import test_constants as test_constants_v3
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -20,10 +20,10 @@ import mock
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from vmware_nsx.nsxlib.v3 import resources from vmware_nsx.nsxlib.v3 import resources
from vmware_nsx.tests.unit.nsx_v3 import mocks from vmware_nsx.tests.unit.nsxlib.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 nsxlib_testcase 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_client
from vmware_nsx.tests.unit.nsxlib.v3 import test_constants as test_constants_v3
CLIENT_PKG = test_client.CLIENT_PKG CLIENT_PKG = test_client.CLIENT_PKG

View File

@ -17,8 +17,8 @@
import mock import mock
from oslo_log import log from oslo_log import log
from vmware_nsx.common import nsx_constants from vmware_nsx.nsxlib.v3 import nsx_constants
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 from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

View File

@ -13,14 +13,16 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
from neutron import version from neutron import version
from neutron_lib import exceptions as n_exc from neutron_lib import exceptions as n_exc
from vmware_nsx.common import utils from vmware_nsx.nsxlib.v3 import utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin 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): def test_build_v3_tags_payload(self):
result = utils.build_v3_tags_payload( result = utils.build_v3_tags_payload(

View File

@ -31,10 +31,10 @@ from neutron import context
from neutron.tests import base from neutron.tests import base
from neutron_lib import exceptions as n_exc 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.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.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') NSX_V3_PLUGIN_CLASS = ('vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin')

View File

@ -24,8 +24,8 @@ from neutron.objects.qos import rule as rule_object
from neutron.services.qos import qos_plugin from neutron.services.qos import qos_plugin
from neutron.tests.unit.services.qos import base 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.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.services.qos.nsx_v3 import utils as qos_utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin from vmware_nsx.tests.unit.nsx_v3 import test_plugin