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
# under the License.
# Admin statuses
ADMIN_STATE_UP = "UP"
ADMIN_STATE_DOWN = "DOWN"
ADMIN_STATUSES = [ADMIN_STATE_UP, ADMIN_STATE_DOWN]
# Port attachment types
ATTACHMENT_VIF = "VIF"
ATTACHMENT_LR = "LOGICALROUTER"
ATTACHMENT_DHCP = "DHCP_SERVICE"
ATTACHMENT_MDPROXY = "METADATA_PROXY"
ATTACHMENT_CIF = "CIF"
CIF_RESOURCE_TYPE = "CifAttachmentContext"
ATTACHMENT_TYPES = [ATTACHMENT_VIF, ATTACHMENT_LR]
# Replication modes
MTEP = "MTEP"
SOURCE = "SOURCE"
REPLICATION_MODES = [MTEP, SOURCE]
# Router type
ROUTER_TYPE_TIER0 = "TIER0"
ROUTER_TYPE_TIER1 = "TIER1"
ROUTER_TYPES = [ROUTER_TYPE_TIER0, ROUTER_TYPE_TIER1]
LROUTERPORT_UPLINK = "LogicalRouterUplinkPort"
LROUTERPORT_DOWNLINK = "LogicalRouterDownLinkPort"
LROUTERPORT_LINKONTIER0 = "LogicalRouterLinkPortOnTIER0"
LROUTERPORT_LINKONTIER1 = "LogicalRouterLinkPortOnTIER1"
LROUTER_TYPES = [LROUTERPORT_UPLINK,
LROUTERPORT_DOWNLINK,
LROUTERPORT_LINKONTIER0,
LROUTERPORT_LINKONTIER1]
# L2 agent vif type
VIF_TYPE_DVS = 'dvs'
# NSXv3 L2 Gateway constants
BRIDGE_ENDPOINT = "BRIDGEENDPOINT"
# NSX service type
SERVICE_DHCP = "dhcp"
# NSXv3 CORE PLUGIN PATH
VMWARE_NSX_V3_PLUGIN_NAME = 'vmware_nsx.plugin.NsxV3Plugin'

View File

@ -18,25 +18,20 @@ import functools
import hashlib
import eventlet
import six
from neutron import version as n_version
from neutron_lib.api import validators
from neutron_lib import constants
from neutron_lib import exceptions
from oslo_config import cfg
from oslo_context import context as common_context
from oslo_log import log
import retrying
import six
from vmware_nsx._i18n import _, _LE
from vmware_nsx._i18n import _LE
LOG = log.getLogger(__name__)
MAX_DISPLAY_NAME_LEN = 40
MAX_RESOURCE_TYPE_LEN = 20
MAX_TAG_LEN = 40
NEUTRON_VERSION = n_version.version_info.release_string()
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
NSXV3_VERSION_1_1_0 = '1.1.0'
@ -111,137 +106,6 @@ def check_and_truncate(display_name):
return display_name or ''
def is_internal_resource(nsx_resource):
"""
Indicates whether the passed nsx-resource is owned by the plugin for
internal use.
"""
for tag in nsx_resource.get('tags', []):
if tag['scope'] == OS_NEUTRON_ID_SCOPE:
return tag['tag'] == NSX_NEUTRON_PLUGIN
return False
def build_v3_api_version_tag():
"""
Some resources are created on the manager that do not have a corresponding
Neutron resource.
"""
return [{'scope': OS_NEUTRON_ID_SCOPE,
'tag': NSX_NEUTRON_PLUGIN},
{'scope': "os-api-version",
'tag': n_version.version_info.release_string()}]
def _validate_resource_type_length(resource_type):
# Add in a validation to ensure that we catch this at build time
if len(resource_type) > MAX_RESOURCE_TYPE_LEN:
raise exceptions.InvalidInput(
error_message=(_('Resource type cannot exceed %(max_len)s '
'characters: %(resource_type)s') %
{'max_len': MAX_RESOURCE_TYPE_LEN,
'resource_type': resource_type}))
def build_v3_tags_payload(resource, resource_type, project_name):
"""
Construct the tags payload that will be pushed to NSX-v3
Add <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):
try:
with open(path) as file:

View File

@ -14,10 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
from sqlalchemy.orm import exc
from oslo_db import exception as db_exc
from oslo_log import log as logging
from oslo_utils import excutils
from sqlalchemy.orm import exc
import neutron.db.api as db
@ -27,6 +29,20 @@ from vmware_nsx.db import nsx_models
LOG = logging.getLogger(__name__)
def _apply_filters_to_query(query, model, filters, like_filters=None):
if filters:
for key, value in six.iteritems(filters):
column = getattr(model, key, None)
if column:
query = query.filter(column.in_(value))
if like_filters:
for key, search_term in six.iteritems(like_filters):
column = getattr(model, key, None)
if column:
query = query.filter(column.like(search_term))
return query
def get_network_bindings(session, network_id):
session = session or db.get_session()
return (session.query(nsx_models.TzNetworkBinding).
@ -247,6 +263,19 @@ def get_nsx_security_group_id(session, neutron_id):
return None
def get_nsx_security_group_ids(session, neutron_ids):
"""Return list of ids of a security groups in the NSX backend.
"""
filters = {'neutron_id': neutron_ids}
like_filters = None
query = session.query(nsx_models.NeutronNsxSecurityGroupMapping)
mappings = _apply_filters_to_query(
query, nsx_models.NeutronNsxSecurityGroupMapping,
filters, like_filters).all()
return [mapping['nsx_id'] for mapping in mappings
if mapping['nsx_id'] is not None]
def _delete_by_neutron_id(session, model, neutron_id):
return session.query(model).filter_by(neutron_id=neutron_id).delete()
@ -361,8 +390,26 @@ def save_sg_mappings(session, sg_id, nsgroup_id, section_id):
nsx_id=nsgroup_id))
def get_sg_mappings(session, sg_id):
nsgroup_mapping = session.query(
nsx_models.NeutronNsxSecurityGroupMapping
).filter_by(neutron_id=sg_id).one()
section_mapping = session.query(
nsx_models.NeutronNsxFirewallSectionMapping
).filter_by(neutron_id=sg_id).one()
return nsgroup_mapping.nsx_id, section_mapping.nsx_id
def get_sg_rule_mapping(session, rule_id):
rule_mapping = session.query(
nsx_models.NeutronNsxRuleMapping).filter_by(
neutron_id=rule_id).one()
return rule_mapping.nsx_id
def save_sg_rule_mappings(session, rules):
with session.begin(subtransactions=True):
for neutron_id, nsx_id in rules:
mapping = nsx_models.NeutronNsxRuleMapping(
neutron_id=neutron_id, nsx_id=nsx_id)
session.add(mapping)

View File

@ -27,7 +27,7 @@ down_revision = 'c288bb6a7252'
from alembic import op
import sqlalchemy as sa
from vmware_nsx.common import nsx_constants
from vmware_nsx.nsxlib.v3 import nsx_constants
nsx_service_type_enum = sa.Enum(

View File

@ -27,7 +27,7 @@ from sqlalchemy import sql
from neutron.db import models_v2
from oslo_db.sqlalchemy import models
from vmware_nsx.common import nsx_constants
from vmware_nsx.nsxlib.v3 import nsx_constants
class TzNetworkBinding(model_base.BASEV2, models.TimestampMixin):

View File

@ -29,6 +29,7 @@ from sqlalchemy.sql import expression as expr
from vmware_nsx._i18n import _, _LE, _LW
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import db as nsx_db
from vmware_nsx.db import nsxv_models
from vmware_nsx.extensions import dhcp_mtu as ext_dhcp_mtu
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
@ -38,20 +39,6 @@ NsxvEdgeDhcpStaticBinding = nsxv_models.NsxvEdgeDhcpStaticBinding
LOG = logging.getLogger(__name__)
def _apply_filters_to_query(query, model, filters, like_filters=None):
if filters:
for key, value in six.iteritems(filters):
column = getattr(model, key, None)
if column:
query = query.filter(column.in_(value))
if like_filters:
for key, search_term in six.iteritems(like_filters):
column = getattr(model, key, None)
if column:
query = query.filter(column.like(search_term))
return query
def add_nsxv_router_binding(session, router_id, vse_id, lswitch_id, status,
appliance_size=nsxv_constants.LARGE,
edge_type=nsxv_constants.SERVICE_EDGE,
@ -117,8 +104,8 @@ def get_nsxv_router_bindings(session, filters=None,
like_filters=None):
session = db.get_session()
query = session.query(nsxv_models.NsxvRouterBinding)
return _apply_filters_to_query(query, nsxv_models.NsxvRouterBinding,
filters, like_filters).all()
return nsx_db._apply_filters_to_query(query, nsxv_models.NsxvRouterBinding,
filters, like_filters).all()
def update_nsxv_router_binding(session, router_id, **kwargs):
@ -586,7 +573,7 @@ def get_nsxv_spoofguard_policy_network_mappings(session, filters=None,
like_filters=None):
session = db.get_session()
query = session.query(nsxv_models.NsxvSpoofGuardPolicyNetworkMapping)
return _apply_filters_to_query(
return nsx_db._apply_filters_to_query(
query, nsxv_models.NsxvSpoofGuardPolicyNetworkMapping,
filters, like_filters).all()

View File

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

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

View File

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

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

View File

@ -22,9 +22,9 @@ from neutron_lib import exceptions as n_exc
from oslo_log import log
from vmware_nsx._i18n import _, _LW
from vmware_nsx.common import nsx_constants
from vmware_nsx.common import utils
from vmware_nsx.nsxlib.v3 import exceptions
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import utils
LOG = log.getLogger(__name__)

View File

@ -15,34 +15,27 @@
# under the License.
"""
NSX-V3 Plugin security integration module
NSX-V3 Plugin security integration & Distributed Firewall module
"""
from neutron_lib import constants
from oslo_config import cfg
from oslo_log import log
from oslo_utils import excutils
from vmware_nsx._i18n import _LE
from vmware_nsx.common import utils
from vmware_nsx.db import nsx_models
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix
from vmware_nsx.extensions import securitygrouplogging as sg_logging
from vmware_nsx.nsxlib.v3 import dfw_api as firewall
from vmware_nsx._i18n import _LE, _LW
from vmware_nsx.nsxlib.v3 import client as nsxclient
from vmware_nsx.nsxlib.v3 import exceptions
from vmware_nsx.nsxlib.v3 import nsx_constants as consts
from vmware_nsx.nsxlib.v3 import utils
LOG = log.getLogger(__name__)
DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups'
DEFAULT_SECTION_TAG_NAME = 'neutron_default_dfw_section'
PORT_SG_SCOPE = 'os-security-group'
MAX_NSGROUPS_CRITERIA_TAGS = 10
# XXX this method should be refactored to pull the common stuff out to
# a security_group utils file.
class Security(object):
def _get_l4_protocol_name(self, protocol_number):
@ -52,24 +45,26 @@ class Security(object):
protocol_number)
protocol_number = int(protocol_number)
if protocol_number == 6:
return firewall.TCP
return consts.TCP
elif protocol_number == 17:
return firewall.UDP
return consts.UDP
elif protocol_number == 1:
return firewall.ICMPV4
return consts.ICMPV4
else:
return protocol_number
def _get_direction(self, sg_rule):
return (
firewall.IN if sg_rule['direction'] == 'ingress' else firewall.OUT
consts.IN if sg_rule['direction'] == 'ingress'
else consts.OUT
)
def _decide_service(self, sg_rule):
l4_protocol = self._get_l4_protocol_name(sg_rule['protocol'])
direction = self._get_direction(sg_rule)
if l4_protocol in [firewall.TCP, firewall.UDP]:
if l4_protocol in [consts.TCP,
consts.UDP]:
# If port_range_min is not specified then we assume all ports are
# matched, relying on neutron to perform validation.
source_ports = []
@ -82,21 +77,24 @@ class Security(object):
else:
destination_ports = ['%(port_range_min)s' % sg_rule]
if direction == firewall.OUT:
if direction == consts.OUT:
source_ports, destination_ports = destination_ports, []
return self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE,
l4_protocol=l4_protocol,
source_ports=source_ports,
destination_ports=destination_ports)
elif l4_protocol == firewall.ICMPV4:
return self.get_nsservice(firewall.ICMP_TYPE_NSSERVICE,
protocol=l4_protocol,
icmp_type=sg_rule['port_range_min'],
icmp_code=sg_rule['port_range_max'])
return self.get_nsservice(
consts.L4_PORT_SET_NSSERVICE,
l4_protocol=l4_protocol,
source_ports=source_ports,
destination_ports=destination_ports)
elif l4_protocol == consts.ICMPV4:
return self.get_nsservice(
consts.ICMP_TYPE_NSSERVICE,
protocol=l4_protocol,
icmp_type=sg_rule['port_range_min'],
icmp_code=sg_rule['port_range_max'])
elif l4_protocol is not None:
return self.get_nsservice(firewall.IP_PROTOCOL_NSSERVICE,
protocol_number=l4_protocol)
return self.get_nsservice(
consts.IP_PROTOCOL_NSSERVICE,
protocol_number=l4_protocol)
def _get_fw_rule_from_sg_rule(self, sg_rule, nsgroup_id, rmt_nsgroup_id,
logged, action):
@ -104,9 +102,9 @@ class Security(object):
ip_protocol = sg_rule['ethertype'].upper()
direction = self._get_direction(sg_rule)
if sg_rule.get(secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX):
if sg_rule.get(consts.LOCAL_IP_PREFIX):
local_ip_prefix = self.get_ip_cidr_reference(
sg_rule[secgroup_rule_local_ip_prefix.LOCAL_IP_PREFIX],
sg_rule[consts.LOCAL_IP_PREFIX],
ip_protocol)
else:
local_ip_prefix = None
@ -121,7 +119,7 @@ class Security(object):
if rmt_nsgroup_id:
source = self.get_nsgroup_reference(rmt_nsgroup_id)
destination = local_ip_prefix or local_group
if direction == firewall.OUT:
if direction == consts.OUT:
source, destination = destination, source
service = self._decide_service(sg_rule)
@ -133,17 +131,15 @@ class Security(object):
action, logged)
def create_firewall_rules(self, context, section_id, nsgroup_id,
logging_enabled, action, security_group_rules):
logging_enabled, action, security_group_rules,
ruleid_2_remote_nsgroup_map):
# 1. translate rules
# 2. insert in section
# 3. save mappings
# 3. return the rules
firewall_rules = []
for sg_rule in security_group_rules:
remote_nsgroup_id = self._get_remote_nsg_mapping(
context, sg_rule, nsgroup_id)
remote_nsgroup_id = ruleid_2_remote_nsgroup_map[sg_rule['id']]
fw_rule = self._get_fw_rule_from_sg_rule(
sg_rule, nsgroup_id, remote_nsgroup_id,
logging_enabled, action)
@ -167,13 +163,13 @@ class Security(object):
section_id, logging)
self.update_section(section_id, rules=rules)
def update_security_group_on_backend(self, context, security_group):
nsgroup_id, section_id = self.get_sg_mappings(context.session,
security_group['id'])
def update_security_group_on_backend(self, context, security_group,
nsgroup_id, section_id,
log_sg_allowed_traffic):
name = self.get_nsgroup_name(security_group)
description = security_group['description']
logging = (cfg.CONF.nsx_v3.log_security_groups_allowed_traffic or
security_group[sg_logging.LOGGING])
logging = (log_sg_allowed_traffic or
security_group[consts.LOGGING])
rules = self._process_firewall_section_rules_logging_for_update(
section_id, logging)
self.update_nsgroup(nsgroup_id, name, description)
@ -184,38 +180,6 @@ class Security(object):
# for usability purposes.
return '%(name)s - %(id)s' % security_group
# XXX remove db calls from nsxlib
def save_sg_rule_mappings(self, session, firewall_rules):
# REVISIT(roeyc): This method should take care db access only.
rules = [(rule['display_name'], rule['id']) for rule in firewall_rules]
with session.begin(subtransactions=True):
for neutron_id, nsx_id in rules:
mapping = nsx_models.NeutronNsxRuleMapping(
neutron_id=neutron_id, nsx_id=nsx_id)
session.add(mapping)
return mapping
# XXX db calls should not be here...
def get_sg_mappings(self, session, sg_id):
nsgroup_mapping = session.query(
nsx_models.NeutronNsxSecurityGroupMapping
).filter_by(neutron_id=sg_id).one()
section_mapping = session.query(
nsx_models.NeutronNsxFirewallSectionMapping
).filter_by(neutron_id=sg_id).one()
return nsgroup_mapping.nsx_id, section_mapping.nsx_id
def _get_remote_nsg_mapping(self, context, sg_rule, nsgroup_id):
remote_nsgroup_id = None
remote_group_id = sg_rule.get('remote_group_id')
# skip unnecessary db access when possible
if remote_group_id == sg_rule['security_group_id']:
remote_nsgroup_id = nsgroup_id
elif remote_group_id:
remote_nsgroup_id, s = self.get_sg_mappings(context.session,
remote_group_id)
return remote_nsgroup_id
def get_lport_tags_for_security_groups(self, secgroups):
if len(secgroups) > MAX_NSGROUPS_CRITERIA_TAGS:
raise exceptions.NumberOfNsgroupCriteriaTagsReached(
@ -232,30 +196,29 @@ class Security(object):
original, updated):
added = set(updated) - set(original)
removed = set(original) - set(updated)
for sg_id in added:
nsgroup_id, s = self.get_sg_mappings(context.session, sg_id)
for nsgroup_id in added:
try:
self.add_nsgroup_members(
nsgroup_id, firewall.LOGICAL_PORT, [lport_id])
nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT,
[lport_id])
except exceptions.NSGroupIsFull:
for sg_id in added:
nsgroup_id, s = self.get_sg_mappings(
context.session, sg_id)
for nsgroup_id in added:
# NOTE(roeyc): If the port was not added to the nsgroup
# yet, then this request will silently fail.
self.remove_nsgroup_member(
nsgroup_id, firewall.LOGICAL_PORT, lport_id)
nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT,
lport_id)
raise exceptions.SecurityGroupMaximumCapacityReached(
sg_id=sg_id)
sg_id=nsgroup_id)
except exceptions.ResourceNotFound:
with excutils.save_and_reraise_exception():
LOG.error(_LE("NSGroup %s doesn't exists"), nsgroup_id)
for sg_id in removed:
nsgroup_id, s = self.get_sg_mappings(context.session, sg_id)
for nsgroup_id in removed:
self.remove_nsgroup_member(
nsgroup_id, firewall.LOGICAL_PORT, lport_id)
nsgroup_id, consts.TARGET_TYPE_LOGICAL_PORT, lport_id)
def _init_default_section(self, name, description, nested_groups):
def init_default_section(self, name, description, nested_groups,
log_sg_blocked_traffic):
fw_sections = self.list_sections()
for section in fw_sections:
if section['display_name'] == name:
@ -266,23 +229,28 @@ class Security(object):
name, description, nested_groups, tags)
block_rule = self.get_firewall_rule_dict(
'Block All', action=firewall.DROP,
logged=cfg.CONF.nsx_v3.log_security_groups_blocked_traffic)
'Block All', action=consts.FW_ACTION_DROP,
logged=log_sg_blocked_traffic)
# TODO(roeyc): Add additional rules to allow IPV6 NDP.
dhcp_client = self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE,
l4_protocol=firewall.UDP,
source_ports=[67],
destination_ports=[68])
dhcp_client = self.get_nsservice(
consts.L4_PORT_SET_NSSERVICE,
l4_protocol=consts.UDP,
source_ports=[67],
destination_ports=[68])
dhcp_client_rule_in = self.get_firewall_rule_dict(
'DHCP Reply', direction=firewall.IN, service=dhcp_client)
'DHCP Reply',
direction=consts.IN,
service=dhcp_client)
dhcp_server = (
self.get_nsservice(firewall.L4_PORT_SET_NSSERVICE,
l4_protocol=firewall.UDP,
self.get_nsservice(consts.L4_PORT_SET_NSSERVICE,
l4_protocol=consts.UDP,
source_ports=[68],
destination_ports=[67]))
dhcp_client_rule_out = self.get_firewall_rule_dict(
'DHCP Request', direction=firewall.OUT, service=dhcp_server)
'DHCP Request',
direction=consts.OUT,
service=dhcp_server)
self.update_section(section['id'],
name, section['description'],
@ -291,3 +259,205 @@ class Security(object):
dhcp_client_rule_in,
block_rule])
return section['id']
def get_nsservice(self, resource_type, **properties):
service = {'resource_type': resource_type}
service.update(properties)
return {'service': service}
def get_nsgroup_port_tag_expression(self, scope, tag):
return {
'resource_type': consts.NSGROUP_TAG_EXP,
'target_type': consts.TARGET_TYPE_LOGICAL_PORT,
'scope': scope,
'tag': tag}
def create_nsgroup(self, display_name, description, tags,
membership_criteria=None):
body = {'display_name': display_name,
'description': description,
'tags': tags,
'members': []}
if membership_criteria:
body.update({'membership_criteria': [membership_criteria]})
return self.client.create('ns-groups', body)
def list_nsgroups(self):
return self.client.get(
'ns-groups?populate_references=false').get('results', [])
@utils.retry_upon_exception(exceptions.StaleRevision)
def update_nsgroup(self, nsgroup_id, display_name=None, description=None,
membership_criteria=None, members=None):
nsgroup = self.read_nsgroup(nsgroup_id)
if display_name is not None:
nsgroup['display_name'] = display_name
if description is not None:
nsgroup['description'] = description
if members is not None:
nsgroup['members'] = members
if membership_criteria is not None:
nsgroup['membership_criteria'] = [membership_criteria]
return self.client.update(
'ns-groups/%s' % nsgroup_id, nsgroup)
def get_nsgroup_member_expression(self, target_type, target_id):
return {
'resource_type': consts.NSGROUP_SIMPLE_EXP,
'target_property': 'id',
'target_type': target_type,
'op': consts.EQUALS,
'value': target_id}
@utils.retry_upon_exception(exceptions.ManagerError)
def _update_nsgroup_with_members(self, nsgroup_id, members, action):
members_update = 'ns-groups/%s?action=%s' % (nsgroup_id, action)
return self.client.create(members_update, members)
def add_nsgroup_members(self, nsgroup_id, target_type, target_ids):
members = []
for target_id in target_ids:
member_expr = self.get_nsgroup_member_expression(
target_type, target_id)
members.append(member_expr)
members = {'members': members}
try:
return self._update_nsgroup_with_members(
nsgroup_id, members, consts.NSGROUP_ADD_MEMBERS)
except (exceptions.StaleRevision, exceptions.ResourceNotFound):
raise
except exceptions.ManagerError:
# REVISIT(roeyc): A ManagerError might have been raised for a
# different reason, e.g - NSGroup does not exists.
LOG.warning(_LW("Failed to add %(target_type)s resources "
"(%(target_ids))s to NSGroup %(nsgroup_id)s"),
{'target_type': target_type,
'target_ids': target_ids,
'nsgroup_id': nsgroup_id})
raise exceptions.NSGroupIsFull(nsgroup_id=nsgroup_id)
def remove_nsgroup_member(self, nsgroup_id, target_type,
target_id, verify=False):
member_expr = self.get_nsgroup_member_expression(
target_type, target_id)
members = {'members': [member_expr]}
try:
return self._update_nsgroup_with_members(
nsgroup_id, members, consts.NSGROUP_REMOVE_MEMBERS)
except exceptions.ManagerError:
if verify:
raise exceptions.NSGroupMemberNotFound(member_id=target_id,
nsgroup_id=nsgroup_id)
def read_nsgroup(self, nsgroup_id):
return self.client.get(
'ns-groups/%s?populate_references=true' % nsgroup_id)
def delete_nsgroup(self, nsgroup_id):
try:
return self.client.delete(
'ns-groups/%s?force=true' % nsgroup_id)
# FIXME(roeyc): Should only except NotFound error.
except Exception:
LOG.debug("NSGroup %s does not exists for delete request.",
nsgroup_id)
def _build_section(self, display_name, description, applied_tos, tags):
return {'display_name': display_name,
'description': description,
'stateful': True,
'section_type': consts.FW_SECTION_LAYER3,
'applied_tos': [self.get_nsgroup_reference(t_id)
for t_id in applied_tos],
'tags': tags}
def create_empty_section(self, display_name, description,
applied_tos, tags,
operation=consts.FW_INSERT_BOTTOM,
other_section=None):
resource = 'firewall/sections?operation=%s' % operation
body = self._build_section(display_name, description,
applied_tos, tags)
if other_section:
resource += '&id=%s' % other_section
return self.client.create(resource, body)
@utils.retry_upon_exception(exceptions.StaleRevision)
def update_section(self, section_id, display_name=None, description=None,
applied_tos=None, rules=None):
resource = 'firewall/sections/%s' % section_id
section = self.read_section(section_id)
if rules is not None:
resource += '?action=update_with_rules'
section.update({'rules': rules})
if display_name is not None:
section['display_name'] = display_name
if description is not None:
section['description'] = description
if applied_tos is not None:
section['applied_tos'] = [self.get_nsgroup_reference(nsg_id)
for nsg_id in applied_tos]
if rules is not None:
return nsxclient.create_resource(resource, section)
elif any(p is not None for p in (display_name, description,
applied_tos)):
return self.client.update(resource, section)
def read_section(self, section_id):
resource = 'firewall/sections/%s' % section_id
return self.client.get(resource)
def list_sections(self):
resource = 'firewall/sections'
return self.client.get(resource).get('results', [])
def delete_section(self, section_id):
resource = 'firewall/sections/%s?cascade=true' % section_id
return self.client.delete(resource)
def get_nsgroup_reference(self, nsgroup_id):
return {'target_id': nsgroup_id,
'target_type': consts.NSGROUP}
def get_ip_cidr_reference(self, ip_cidr_block, ip_protocol):
target_type = (consts.TARGET_TYPE_IPV4ADDRESS
if ip_protocol == consts.IPV4
else consts.TARGET_TYPE_IPV6ADDRESS)
return {'target_id': ip_cidr_block,
'target_type': target_type}
def get_firewall_rule_dict(
self, display_name, source=None,
destination=None,
direction=consts.IN_OUT,
ip_protocol=consts.IPV4_IPV6,
service=None, action=consts.FW_ACTION_ALLOW,
logged=False):
return {'display_name': display_name,
'sources': [source] if source else [],
'destinations': [destination] if destination else [],
'direction': direction,
'ip_protocol': ip_protocol,
'services': [service] if service else [],
'action': action,
'logged': logged}
def add_rule_in_section(self, rule, section_id):
resource = 'firewall/sections/%s/rules' % section_id
params = '?operation=insert_bottom'
return self.client.create(resource + params, rule)
def add_rules_in_section(self, rules, section_id):
resource = 'firewall/sections/%s/rules' % section_id
params = '?action=create_multiple&operation=insert_bottom'
return self.client.create(resource + params, {'rules': rules})
def delete_rule(self, section_id, rule_id):
resource = 'firewall/sections/%s/rules/%s' % (section_id, rule_id)
return self.client.delete(resource)
def get_section_rules(self, section_id):
resource = 'firewall/sections/%s/rules' % section_id
return self.client.get(resource)

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

View File

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

View File

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

View File

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

View File

@ -20,9 +20,9 @@ from neutron_lib import constants as const
from oslo_config import cfg
from vmware_nsx._i18n import _LE, _LI
from vmware_nsx.common import nsx_constants
from vmware_nsx.common import utils as nsx_utils
from vmware_nsx.nsxlib.v3 import native_dhcp
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import resources
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters

View File

@ -19,10 +19,11 @@ from neutron_lib import constants as const
from oslo_config import cfg
from vmware_nsx._i18n import _LE, _LI
from vmware_nsx.common import nsx_constants
from vmware_nsx.common import utils as nsx_utils
from vmware_nsx.dhcp_meta import rpc as nsx_rpc
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import resources
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
@ -104,7 +105,7 @@ def nsx_update_metadata_proxy(resource, event, trigger, **kwargs):
lswitch_id = neutron_client.net_id_to_lswitch_id(network['id'])
if not lswitch_id:
continue
tags = nsx_utils.build_v3_tags_payload(
tags = nsxlib_utils.build_v3_tags_payload(
network, resource_type='os-neutron-net-id',
project_name='admin')
name = nsx_utils.get_name_and_uuid('%s-%s' % (

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

View File

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

View File

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

View File

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

View File

@ -14,149 +14,4 @@
# limitations under the License.
from oslo_utils import uuidutils
PLUGIN_NAME = 'vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin'
FAKE_NAME = "fake_name"
FAKE_SWITCH_UUID = uuidutils.generate_uuid()
FAKE_PORT_UUID = uuidutils.generate_uuid()
FAKE_PORT = {
"id": FAKE_PORT_UUID,
"display_name": FAKE_NAME,
"resource_type": "LogicalPort",
"address_bindings": [],
"logical_switch_id": FAKE_SWITCH_UUID,
"admin_state": "UP",
"attachment": {
"id": "9ca8d413-f7bf-4276-b4c9-62f42516bdb2",
"attachment_type": "VIF"
},
"switching_profile_ids": [
{
"value": "64814784-7896-3901-9741-badeff705639",
"key": "IpDiscoverySwitchingProfile"
},
{
"value": "fad98876-d7ff-11e4-b9d6-1681e6b88ec1",
"key": "SpoofGuardSwitchingProfile"
},
{
"value": "93b4b7e8-f116-415d-a50c-3364611b5d09",
"key": "PortMirroringSwitchingProfile"
},
{
"value": "fbc4fb17-83d9-4b53-a286-ccdf04301888",
"key": "SwitchSecuritySwitchingProfile"
},
{
"value": "f313290b-eba8-4262-bd93-fab5026e9495",
"key": "QosSwitchingProfile"
}
]
}
FAKE_CONTAINER_PORT = {
"id": FAKE_PORT_UUID,
"display_name": FAKE_NAME,
"resource_type": "LogicalPort",
"address_bindings": [
{
"ip_address": "192.168.1.110",
"mac_address": "aa:bb:cc:dd:ee:ff"
}
],
"logical_switch_id": FAKE_SWITCH_UUID,
"admin_state": "UP",
"attachment": {
"id": "9ca8d413-f7bf-4276-b4c9-62f42516bdb2",
"attachment_type": "CIF",
"context": {
"vlan_tag": 122,
"container_host_vif_id": "c6f817a0-4e36-421e-98a6-8a2faed880bc",
"key_values": [],
"resource_type": "CifAttachmentContext",
}
},
"switching_profile_ids": [
{
"value": "64814784-7896-3901-9741-badeff705639",
"key": "IpDiscoverySwitchingProfile"
},
{
"value": "fad98876-d7ff-11e4-b9d6-1681e6b88ec1",
"key": "SpoofGuardSwitchingProfile"
},
{
"value": "93b4b7e8-f116-415d-a50c-3364611b5d09",
"key": "PortMirroringSwitchingProfile"
},
{
"value": "fbc4fb17-83d9-4b53-a286-ccdf04301888",
"key": "SwitchSecuritySwitchingProfile"
},
{
"value": "f313290b-eba8-4262-bd93-fab5026e9495",
"key": "QosSwitchingProfile"
}
]
}
FAKE_QOS_PROFILE = {
"resource_type": "QosSwitchingProfile",
"id": uuidutils.generate_uuid(),
"display_name": FAKE_NAME,
"system_defined": False,
"dscp": {
"priority": 25,
"mode": "UNTRUSTED"
},
"tags": [],
"description": FAKE_NAME,
"class_of_service": 0,
"shaper_configuration": [
{
"resource_type": "IngressRateShaper",
"enabled": False,
"peak_bandwidth_mbps": 0,
"burst_size_bytes": 0,
"average_bandwidth_mbps": 0
},
{
"resource_type": "IngressBroadcastRateShaper",
"enabled": False,
"peak_bandwidth_kbps": 0,
"average_bandwidth_kbps": 0,
"burst_size_bytes": 0
},
{
"resource_type": "EgressRateShaper",
"enabled": False,
"peak_bandwidth_mbps": 0,
"burst_size_bytes": 0,
"average_bandwidth_mbps": 0
}
],
"_last_modified_user": "admin",
"_last_modified_time": 1438383180608,
"_create_time": 1438383180608,
"_create_user": "admin",
"_revision": 0
}
FAKE_ROUTER_UUID = uuidutils.generate_uuid()
FAKE_ROUTER = {
"resource_type": "LogicalRouter",
"revision": 0,
"id": FAKE_ROUTER_UUID,
"display_name": FAKE_NAME
}
FAKE_ROUTER_PORT_UUID = uuidutils.generate_uuid()
FAKE_ROUTER_PORT = {
"resource_type": "LogicalRouterLinkPort",
"revision": 0,
"id": FAKE_ROUTER_PORT_UUID,
"display_name": FAKE_NAME,
"logical_router_id": FAKE_ROUTER_UUID
}

View File

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

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.tests import unit as vmware
from vmware_nsx.tests.unit.extensions import test_metadata
from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks
from vmware_nsx.tests.unit.nsxlib.v3 import mocks as nsx_v3_mocks
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

View File

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

View File

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

View File

@ -20,7 +20,7 @@ from oslo_serialization import jsonutils
from vmware_nsx.nsxlib.v3 import client
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsx.tests.unit.nsx_v3 import mocks
from vmware_nsx.tests.unit.nsxlib.v3 import mocks
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

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 cluster
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsx.tests.unit.nsx_v3 import mocks
from vmware_nsx.tests.unit.nsxlib.v3 import mocks
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

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 vmware_nsx.tests.unit.nsx_v3 import test_constants as test_constants_v3
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase
from vmware_nsx.tests.unit.nsxlib.v3 import test_constants as test_constants_v3
LOG = log.getLogger(__name__)

View File

@ -20,10 +20,10 @@ import mock
from oslo_serialization import jsonutils
from vmware_nsx.nsxlib.v3 import resources
from vmware_nsx.tests.unit.nsx_v3 import mocks
from vmware_nsx.tests.unit.nsx_v3 import test_constants as test_constants_v3
from vmware_nsx.tests.unit.nsxlib.v3 import mocks
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase
from vmware_nsx.tests.unit.nsxlib.v3 import test_client
from vmware_nsx.tests.unit.nsxlib.v3 import test_constants as test_constants_v3
CLIENT_PKG = test_client.CLIENT_PKG

View File

@ -17,8 +17,8 @@
import mock
from oslo_log import log
from vmware_nsx.common import nsx_constants
from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.tests.unit.nsxlib.v3 import mocks as nsx_v3_mocks
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase

View File

@ -13,14 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
from neutron import version
from neutron_lib import exceptions as n_exc
from vmware_nsx.common import utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin
from vmware_nsx.nsxlib.v3 import utils
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase
class TestNsxV3Utils(test_plugin.NsxV3PluginTestCaseMixin):
class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase,
nsxlib_testcase.NsxClientTestCase):
def test_build_v3_tags_payload(self):
result = utils.build_v3_tags_payload(

View File

@ -31,10 +31,10 @@ from neutron import context
from neutron.tests import base
from neutron_lib import exceptions as n_exc
from vmware_nsx.common import nsx_constants
from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.services.l2gateway.nsx_v3 import driver as nsx_v3_driver
from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsx_v3_plugin
from vmware_nsx.tests.unit.nsxlib.v3 import mocks as nsx_v3_mocks
NSX_V3_PLUGIN_CLASS = ('vmware_nsx.plugins.nsx_v3.plugin.NsxV3Plugin')

View File

@ -24,8 +24,8 @@ from neutron.objects.qos import rule as rule_object
from neutron.services.qos import qos_plugin
from neutron.tests.unit.services.qos import base
from vmware_nsx.common import utils
from vmware_nsx.db import db as nsx_db
from vmware_nsx.nsxlib.v3 import utils
from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin