nsxlib refactor: config + neutron deps

1. new config class was added to allow all the classes to use the same object
2. removing dependencies of the neutron project in nsxlib code & tests

Change-Id: I15ace2ab60c1e4307d7076426c48ecc7a242e792
This commit is contained in:
Adit Sarfaty 2016-09-20 15:21:09 +03:00
parent 701de5c48f
commit 34f3ee275e
21 changed files with 439 additions and 325 deletions

View File

@ -19,6 +19,7 @@ from vmware_nsx._i18n import _, _LW
from vmware_nsx.nsxlib.v3 import client from vmware_nsx.nsxlib.v3 import client
from vmware_nsx.nsxlib.v3 import cluster from vmware_nsx.nsxlib.v3 import cluster
from vmware_nsx.nsxlib.v3 import exceptions from vmware_nsx.nsxlib.v3 import exceptions
from vmware_nsx.nsxlib.v3 import native_dhcp
from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import security from vmware_nsx.nsxlib.v3 import security
from vmware_nsx.nsxlib.v3 import utils from vmware_nsx.nsxlib.v3 import utils
@ -28,60 +29,43 @@ LOG = log.getLogger(__name__)
class NsxLib(object): class NsxLib(object):
def __init__(self, def __init__(self, nsxlib_config):
username=None,
password=None,
retries=None,
insecure=None,
ca_file=None,
concurrent_connections=None,
http_timeout=None,
http_read_timeout=None,
conn_idle_timeout=None,
http_provider=None,
max_attempts=0,
nsx_api_managers=None):
self.max_attempts = max_attempts self.nsxlib_config = nsxlib_config
# create the Cluster # create the Cluster
self.cluster = cluster.NSXClusteredAPI( self.cluster = cluster.NSXClusteredAPI(nsxlib_config)
username=username, password=password,
retries=retries, insecure=insecure,
ca_file=ca_file,
concurrent_connections=concurrent_connections,
http_timeout=http_timeout,
http_read_timeout=http_read_timeout,
conn_idle_timeout=conn_idle_timeout,
http_provider=http_provider,
nsx_api_managers=nsx_api_managers)
# create the Client # create the Client
self.client = client.NSX3Client( self.client = client.NSX3Client(
self.cluster, self.cluster,
max_attempts=max_attempts) max_attempts=nsxlib_config.max_attempts)
# init the api object # init the api object
self.general_apis = utils.NsxLibApiBase(
self.client, nsxlib_config)
self.port_mirror = NsxLibPortMirror( self.port_mirror = NsxLibPortMirror(
self.client, self.max_attempts) self.client, nsxlib_config)
self.bridge_endpoint = NsxLibBridgeEndpoint( self.bridge_endpoint = NsxLibBridgeEndpoint(
self.client, self.max_attempts) self.client, nsxlib_config)
self.logical_switch = NsxLibLogicalSwitch( self.logical_switch = NsxLibLogicalSwitch(
self.client, self.max_attempts) self.client, nsxlib_config)
self.logical_router = NsxLibLogicalRouter( self.logical_router = NsxLibLogicalRouter(
self.client, self.max_attempts) self.client, nsxlib_config)
self.qos_switching_profile = NsxLibQosSwitchingProfile( self.qos_switching_profile = NsxLibQosSwitchingProfile(
self.client, self.max_attempts) self.client, nsxlib_config)
self.edge_cluster = NsxLibEdgeCluster( self.edge_cluster = NsxLibEdgeCluster(
self.client, self.max_attempts) self.client, nsxlib_config)
self.bridge_cluster = NsxLibBridgeCluster( self.bridge_cluster = NsxLibBridgeCluster(
self.client, self.max_attempts) self.client, nsxlib_config)
self.transport_zone = NsxLibTransportZone( self.transport_zone = NsxLibTransportZone(
self.client, self.max_attempts) self.client, nsxlib_config)
self.firewall_section = security.NsxLibFirewallSection( self.firewall_section = security.NsxLibFirewallSection(
self.client, self.max_attempts) self.client, nsxlib_config)
self.ns_group = security.NsxLibNsGroup( self.ns_group = security.NsxLibNsGroup(
self.client, self.max_attempts, self.firewall_section) self.client, nsxlib_config, self.firewall_section)
self.native_dhcp = native_dhcp.NsxLibNativeDhcp(
self.client, nsxlib_config)
super(NsxLib, self).__init__() super(NsxLib, self).__init__()
@ -90,6 +74,19 @@ class NsxLib(object):
version = node.get('node_version') version = node.get('node_version')
return version return version
def build_v3_api_version_tag(self):
return self.general_apis.build_v3_api_version_tag()
def is_internal_resource(self, nsx_resource):
return self.general_apis.is_internal_resource(nsx_resource)
def build_v3_tags_payload(self, resource, resource_type, project_name):
return self.general_apis.build_v3_tags_payload(
resource, resource_type, project_name)
def reinitialize_cluster(self, resource, event, trigger, **kwargs):
self.cluster.reinit_cluster()
class NsxLibPortMirror(utils.NsxLibApiBase): class NsxLibPortMirror(utils.NsxLibApiBase):
@ -182,8 +179,9 @@ class NsxLibLogicalSwitch(utils.NsxLibApiBase):
def delete(self, lswitch_id): def delete(self, lswitch_id):
#Using internal method so we can access max_attempts in the decorator #Using internal method so we can access max_attempts in the decorator
@utils.retry_upon_exception(exceptions.StaleRevision, @utils.retry_upon_exception(
max_attempts=self.max_attempts) exceptions.StaleRevision,
max_attempts=self.nsxlib_config.max_attempts)
def _do_delete(): def _do_delete():
resource = ('logical-switches/%s?detach=true&cascade=true' % resource = ('logical-switches/%s?detach=true&cascade=true' %
lswitch_id) lswitch_id)
@ -197,8 +195,9 @@ class NsxLibLogicalSwitch(utils.NsxLibApiBase):
def update(self, lswitch_id, name=None, admin_state=None, tags=None): def update(self, lswitch_id, name=None, admin_state=None, tags=None):
#Using internal method so we can access max_attempts in the decorator #Using internal method so we can access max_attempts in the decorator
@utils.retry_upon_exception(exceptions.StaleRevision, @utils.retry_upon_exception(
max_attempts=self.max_attempts) exceptions.StaleRevision,
max_attempts=self.nsxlib_config.max_attempts)
def _do_update(): def _do_update():
resource = "logical-switches/%s" % lswitch_id resource = "logical-switches/%s" % lswitch_id
lswitch = self.get(lswitch_id) lswitch = self.get(lswitch_id)
@ -234,7 +233,7 @@ class NsxLibQosSwitchingProfile(utils.NsxLibApiBase):
def _enable_shaping_in_args(self, body, burst_size=None, def _enable_shaping_in_args(self, body, burst_size=None,
peak_bandwidth=None, average_bandwidth=None): peak_bandwidth=None, average_bandwidth=None):
for shaper in body["shaper_configuration"]: for shaper in body["shaper_configuration"]:
# Neutron currently supports only shaping of Egress traffic # We currently supports only shaping of Egress traffic
if shaper["resource_type"] == "EgressRateShaper": if shaper["resource_type"] == "EgressRateShaper":
shaper["enabled"] = True shaper["enabled"] = True
if burst_size: if burst_size:
@ -249,7 +248,7 @@ class NsxLibQosSwitchingProfile(utils.NsxLibApiBase):
def _disable_shaping_in_args(self, body): def _disable_shaping_in_args(self, body):
for shaper in body["shaper_configuration"]: for shaper in body["shaper_configuration"]:
# Neutron currently supports only shaping of Egress traffic # We currently supports only shaping of Egress traffic
if shaper["resource_type"] == "EgressRateShaper": if shaper["resource_type"] == "EgressRateShaper":
shaper["enabled"] = False shaper["enabled"] = False
shaper["burst_size_bytes"] = 0 shaper["burst_size_bytes"] = 0

View File

@ -26,9 +26,6 @@ import six.moves.urllib.parse as urlparse
from eventlet import greenpool from eventlet import greenpool
from eventlet import pools from eventlet import pools
from neutron.callbacks import events
from neutron.callbacks import registry
from neutron.callbacks import resources
from oslo_log import log from oslo_log import log
from oslo_service import loopingcall from oslo_service import loopingcall
from requests import adapters from requests import adapters
@ -121,13 +118,14 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
manager=endpoint.provider.url, operation=msg) manager=endpoint.provider.url, operation=msg)
def new_connection(self, cluster_api, provider): def new_connection(self, cluster_api, provider):
session = TimeoutSession(cluster_api.http_timeout, config = cluster_api.nsxlib_config
cluster_api.http_read_timeout) session = TimeoutSession(config.http_timeout,
config.http_read_timeout)
session.auth = (provider.username, provider.password) session.auth = (provider.username, provider.password)
# NSX v3 doesn't use redirects # NSX v3 doesn't use redirects
session.max_redirects = 0 session.max_redirects = 0
session.verify = not cluster_api.insecure session.verify = not config.insecure
if session.verify and provider.ca_file: if session.verify and provider.ca_file:
# verify using the said ca bundle path # verify using the said ca bundle path
session.verify = provider.ca_file session.verify = provider.ca_file
@ -135,7 +133,7 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
# we are pooling with eventlet in the cluster class # we are pooling with eventlet in the cluster class
adapter = adapters.HTTPAdapter( adapter = adapters.HTTPAdapter(
pool_connections=1, pool_maxsize=1, pool_connections=1, pool_maxsize=1,
max_retries=cluster_api.retries, max_retries=config.retries,
pool_block=False) pool_block=False)
session.mount('http://', adapter) session.mount('http://', adapter)
session.mount('https://', adapter) session.mount('https://', adapter)
@ -258,10 +256,10 @@ class ClusteredAPI(object):
_init_cluster() _init_cluster()
# reinitialize upon fork for api workers to ensure each # keep this internal method for reinitialize upon fork
# process has its own keepalive loops + state # for api workers to ensure each process has its own keepalive
registry.subscribe( # loops + state
_init_cluster, resources.PROCESS, events.AFTER_INIT) self._reinit_cluster = _init_cluster
def _init_endpoints(self, providers, def _init_endpoints(self, providers,
min_conns_per_pool, max_conns_per_pool): min_conns_per_pool, max_conns_per_pool):
@ -450,40 +448,17 @@ class NSXClusteredAPI(ClusteredAPI):
NSX v3 cluster. NSX v3 cluster.
""" """
def __init__(self, def __init__(self, nsxlib_config):
username=None, self.nsxlib_config = nsxlib_config
password=None,
retries=None,
insecure=None,
ca_file=None,
concurrent_connections=None,
http_timeout=None,
http_read_timeout=None,
conn_idle_timeout=None,
http_provider=None,
nsx_api_managers=None):
# username, password & ca_file may be lists, in order to support self._http_provider = (nsxlib_config.http_provider or
# different credentials per nsx manager NSXRequestsHTTPProvider())
self._username = username
self._password = password
self._ca_file = ca_file
self.retries = retries
self.insecure = insecure
self.conns_per_pool = concurrent_connections
self.http_timeout = http_timeout
self.http_read_timeout = http_read_timeout
self.conn_idle_timeout = conn_idle_timeout
self.nsx_api_managers = nsx_api_managers
self._http_provider = http_provider or NSXRequestsHTTPProvider()
super(NSXClusteredAPI, self).__init__( super(NSXClusteredAPI, self).__init__(
self._build_conf_providers(), self._build_conf_providers(),
self._http_provider, self._http_provider,
max_conns_per_pool=self.conns_per_pool, max_conns_per_pool=self.nsxlib_config.concurrent_connections,
keepalive_interval=self.conn_idle_timeout) keepalive_interval=self.nsxlib_config.conn_idle_timeout)
LOG.debug("Created NSX clustered API with '%s' " LOG.debug("Created NSX clustered API with '%s' "
"provider", self._http_provider.provider_id) "provider", self._http_provider.provider_id)
@ -496,7 +471,7 @@ class NSXClusteredAPI(ClusteredAPI):
uri if uri.startswith('http') else uri if uri.startswith('http') else
"%s://%s" % (self._http_provider.default_scheme, uri)) "%s://%s" % (self._http_provider.default_scheme, uri))
conf_urls = self.nsx_api_managers[:] conf_urls = self.nsxlib_config.nsx_api_managers[:]
urls = [] urls = []
providers = [] providers = []
provider_index = -1 provider_index = -1
@ -512,27 +487,7 @@ class NSXClusteredAPI(ClusteredAPI):
Provider( Provider(
conf_url.netloc, conf_url.netloc,
urlparse.urlunparse(conf_url), urlparse.urlunparse(conf_url),
self.username(provider_index), self.nsxlib_config.username(provider_index),
self.password(provider_index), self.nsxlib_config.password(provider_index),
self.ca_file(provider_index))) self.nsxlib_config.ca_file(provider_index)))
return providers return providers
def _attribute_by_index(self, scalar_or_list, index):
if isinstance(scalar_or_list, list):
if not len(scalar_or_list):
return None
if len(scalar_or_list) > index:
return scalar_or_list[index]
# if not long enough - use the first one as default
return scalar_or_list[0]
# this is a scalar
return scalar_or_list
def username(self, index):
return self._attribute_by_index(self._username, index)
def password(self, index):
return self._attribute_by_index(self._password, index)
def ca_file(self, index):
return self._attribute_by_index(self._ca_file, index)

View File

@ -0,0 +1,123 @@
# 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.
class NsxLibConfig(object):
"""Class holding all the configuration parameters used by the nsxlib code.
:param nsx_api_managers: List of IP addresses of the NSX managers.
Each IP address should be of the form:
[<scheme>://]<ip_adress>[:<port>]
If scheme is not provided https is used.
If port is not provided port 80 is used for http
and port 443 for https.
:param username: User name for the NSX manager
:param password: Password for the NSX manager
:param insecure: If true, the NSX Manager server certificate is not
verified. If false the CA bundle specified via "ca_file"
will be used or if unsest the default system root CAs
will be used.
:param ca_file: Specify a CA bundle file to use in verifying the NSX
Manager server certificate. This option is ignored if
"insecure" is set to True. If "insecure" is set to
False and ca_file is unset, the system root CAs will
be used to verify the server certificate.
:param concurrent_connections: Maximum concurrent connections to each NSX
manager.
:param retries: Maximum number of times to retry a HTTP connection.
:param http_timeout: The time in seconds before aborting a HTTP connection
to a NSX manager.
:param http_read_timeout: The time in seconds before aborting a HTTP read
response from a NSX manager.
:param conn_idle_timeout: The amount of time in seconds to wait before
ensuring connectivity to the NSX manager if no
manager connection has been used.
:param http_provider: HTTPProvider object, or None.
:param max_attempts: Maximum number of times to retry API requests upon
stale revision errors.
:param plugin_scope: The default scope for the v3 api-version tag
:param plugin_tag: The value for the v3 api-version tag
:param plugin_ver: The version of the plugin used as the 'os-api-version'
tag value in the v3 api-version tag
:param dns_nameservers: List of nameservers to configure for the DHCP
binding entries. These will be used if there are
no nameservers defined on the subnet.
:param dns_domain: Domain to use for building the hostnames.
:param dhcp_profile_uuid: The UUID of the NSX DHCP Profile that will be
used to enable native DHCP service.
"""
def __init__(self,
nsx_api_managers=None,
username=None,
password=None,
insecure=True,
ca_file=None,
concurrent_connections=10,
retries=3,
http_timeout=10,
http_read_timeout=180,
conn_idle_timeout=10,
http_provider=None,
max_attempts=10,
plugin_scope=None,
plugin_tag=None,
plugin_ver=None,
dns_nameservers=None,
dns_domain='openstacklocal',
dhcp_profile_uuid=None):
self.nsx_api_managers = nsx_api_managers
self._username = username
self._password = password
self._ca_file = ca_file
self.insecure = insecure
self.concurrent_connections = concurrent_connections
self.retries = retries
self.http_timeout = http_timeout
self.http_read_timeout = http_read_timeout
self.conn_idle_timeout = conn_idle_timeout
self.http_provider = http_provider
self.max_attempts = max_attempts
self.plugin_scope = plugin_scope
self.plugin_tag = plugin_tag
self.plugin_ver = plugin_ver
self.dns_nameservers = dns_nameservers or []
self.dns_domain = dns_domain
self.dhcp_profile_uuid = dhcp_profile_uuid
def _attribute_by_index(self, scalar_or_list, index):
if isinstance(scalar_or_list, list):
if not len(scalar_or_list):
return None
if len(scalar_or_list) > index:
return scalar_or_list[index]
# if not long enough - use the first one as default
return scalar_or_list[0]
# this is a scalar
return scalar_or_list
def username(self, index):
return self._attribute_by_index(self._username, index)
def password(self, index):
return self._attribute_by_index(self._password, index)
def ca_file(self, index):
return self._attribute_by_index(self._ca_file, index)

View File

@ -20,46 +20,45 @@ from neutron_lib import constants
from vmware_nsx.nsxlib.v3 import utils from vmware_nsx.nsxlib.v3 import utils
def build_dhcp_server_config(network, subnet, port, project_name, class NsxLibNativeDhcp(utils.NsxLibApiBase):
nameservers, dhcp_profile_uuid, dns_domain):
# Prepare the configuration for a new logical DHCP server.
server_ip = "%s/%u" % (port['fixed_ips'][0]['ip_address'],
netaddr.IPNetwork(subnet['cidr']).prefixlen)
dns_nameservers = subnet['dns_nameservers']
if not dns_nameservers or not validators.is_attr_set(dns_nameservers):
dns_nameservers = nameservers
gateway_ip = subnet['gateway_ip']
if not validators.is_attr_set(gateway_ip):
gateway_ip = None
# The following code is based on _generate_opts_per_subnet() in def build_server_config(self, network, subnet, port, tags):
# neutron/agent/linux/dhcp.py. It prepares DHCP options for a subnet. # Prepare the configuration for a new logical DHCP server.
server_ip = "%s/%u" % (port['fixed_ips'][0]['ip_address'],
netaddr.IPNetwork(subnet['cidr']).prefixlen)
dns_nameservers = subnet['dns_nameservers']
if not dns_nameservers or not validators.is_attr_set(dns_nameservers):
dns_nameservers = self.nsxlib_config.dns_nameservers
gateway_ip = subnet['gateway_ip']
if not validators.is_attr_set(gateway_ip):
gateway_ip = None
# Add route for directly connected network. # The following code is based on _generate_opts_per_subnet() in
host_routes = [{'network': subnet['cidr'], 'next_hop': '0.0.0.0'}] # neutron/agent/linux/dhcp.py. It prepares DHCP options for a subnet.
# Copy routes from subnet host_routes attribute.
for hr in subnet['host_routes']:
if hr['destination'] == constants.IPv4_ANY:
if not gateway_ip:
gateway_ip = hr['nexthop']
else:
host_routes.append({'network': hr['destination'],
'next_hop': hr['nexthop']})
# If gateway_ip is defined, add default route via this gateway.
if gateway_ip:
host_routes.append({'network': constants.IPv4_ANY,
'next_hop': gateway_ip})
options = {'option121': {'static_routes': host_routes}} # Add route for directly connected network.
name = utils.get_name_and_uuid(network['name'] or 'dhcpserver', host_routes = [{'network': subnet['cidr'], 'next_hop': '0.0.0.0'}]
network['id']) # Copy routes from subnet host_routes attribute.
tags = utils.build_v3_tags_payload( for hr in subnet['host_routes']:
network, resource_type='os-neutron-net-id', project_name=project_name) if hr['destination'] == constants.IPv4_ANY:
return {'name': name, if not gateway_ip:
'dhcp_profile_id': dhcp_profile_uuid, gateway_ip = hr['nexthop']
'server_ip': server_ip, else:
'dns_nameservers': dns_nameservers, host_routes.append({'network': hr['destination'],
'domain_name': dns_domain, 'next_hop': hr['nexthop']})
'gateway_ip': gateway_ip, # If gateway_ip is defined, add default route via this gateway.
'options': options, if gateway_ip:
'tags': tags} host_routes.append({'network': constants.IPv4_ANY,
'next_hop': gateway_ip})
options = {'option121': {'static_routes': host_routes}}
name = utils.get_name_and_uuid(network['name'] or 'dhcpserver',
network['id'])
return {'name': name,
'dhcp_profile_id': self.nsxlib_config.dhcp_profile_uuid,
'server_ip': server_ip,
'dns_nameservers': dns_nameservers,
'domain_name': self.nsxlib_config.dns_domain,
'gateway_ip': gateway_ip,
'options': options,
'tags': tags}

View File

@ -22,7 +22,6 @@ from oslo_log import log
from vmware_nsx._i18n import _, _LW from vmware_nsx._i18n import _, _LW
from vmware_nsx.nsxlib.v3 import exceptions from vmware_nsx.nsxlib.v3 import exceptions
from vmware_nsx.nsxlib.v3 import nsx_constants as consts from vmware_nsx.nsxlib.v3 import nsx_constants as consts
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -69,7 +68,7 @@ class NSGroupManager(object):
nested_groups = { nested_groups = {
self._get_nested_group_index_from_name(nsgroup): nsgroup['id'] self._get_nested_group_index_from_name(nsgroup): nsgroup['id']
for nsgroup in self.nsxlib_nsgroup.list() for nsgroup in self.nsxlib_nsgroup.list()
if nsxlib_utils.is_internal_resource(nsgroup)} if self.nsxlib_nsgroup.is_internal_resource(nsgroup)}
if nested_groups: if nested_groups:
size = max(requested_size, max(nested_groups) + 1) size = max(requested_size, max(nested_groups) + 1)
@ -100,7 +99,7 @@ class NSGroupManager(object):
name_prefix = NSGroupManager.NESTED_GROUP_NAME name_prefix = NSGroupManager.NESTED_GROUP_NAME
name = '%s %s' % (name_prefix, index + 1) name = '%s %s' % (name_prefix, index + 1)
description = NSGroupManager.NESTED_GROUP_DESCRIPTION description = NSGroupManager.NESTED_GROUP_DESCRIPTION
tags = nsxlib_utils.build_v3_api_version_tag() tags = self.nsxlib_nsgroup.build_v3_api_version_tag()
return self.nsxlib_nsgroup.create(name, description, tags) return self.nsxlib_nsgroup.create(name, description, tags)
def _hash_uuid(self, internal_id): def _hash_uuid(self, internal_id):

View File

@ -30,7 +30,6 @@ from vmware_nsx.nsxlib.v3 import utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups'
PORT_SG_SCOPE = 'os-security-group' PORT_SG_SCOPE = 'os-security-group'
MAX_NSGROUPS_CRITERIA_TAGS = 10 MAX_NSGROUPS_CRITERIA_TAGS = 10
@ -168,7 +167,7 @@ class NsxLibNsGroup(utils.NsxLibApiBase):
#Using internal method so we can access max_attempts in the decorator #Using internal method so we can access max_attempts in the decorator
@utils.retry_upon_exception( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=self.max_attempts) max_attempts=self.nsxlib_config.max_attempts)
def _do_update(): def _do_update():
nsgroup = self.read(nsgroup_id) nsgroup = self.read(nsgroup_id)
if display_name is not None: if display_name is not None:
@ -196,7 +195,7 @@ class NsxLibNsGroup(utils.NsxLibApiBase):
#Using internal method so we can access max_attempts in the decorator #Using internal method so we can access max_attempts in the decorator
@utils.retry_upon_exception( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=self.max_attempts) max_attempts=self.nsxlib_config.max_attempts)
def _do_update(): def _do_update():
members_update = 'ns-groups/%s?action=%s' % (nsgroup_id, action) members_update = 'ns-groups/%s?action=%s' % (nsgroup_id, action)
return self.client.create(members_update, members) return self.client.create(members_update, members)
@ -342,7 +341,7 @@ class NsxLibFirewallSection(utils.NsxLibApiBase):
#Using internal method so we can access max_attempts in the decorator #Using internal method so we can access max_attempts in the decorator
@utils.retry_upon_exception( @utils.retry_upon_exception(
exceptions.StaleRevision, exceptions.StaleRevision,
max_attempts=self.max_attempts) max_attempts=self.nsxlib_config.max_attempts)
def _do_update(): def _do_update():
resource = 'firewall/sections/%s' % section_id resource = 'firewall/sections/%s' % section_id
section = self.read(section_id) section = self.read(section_id)
@ -494,7 +493,7 @@ class NsxLibFirewallSection(utils.NsxLibApiBase):
if section['display_name'] == name: if section['display_name'] == name:
break break
else: else:
tags = utils.build_v3_api_version_tag() tags = self.build_v3_api_version_tag()
section = self.create_empty( section = self.create_empty(
name, description, nested_groups, tags) name, description, nested_groups, tags)

View File

@ -15,7 +15,6 @@
import retrying import retrying
from neutron import version as n_version
from neutron_lib import exceptions from neutron_lib import exceptions
from oslo_log import log from oslo_log import log
@ -26,33 +25,9 @@ LOG = log.getLogger(__name__)
MAX_RESOURCE_TYPE_LEN = 20 MAX_RESOURCE_TYPE_LEN = 20
MAX_TAG_LEN = 40 MAX_TAG_LEN = 40
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
DEFAULT_MAX_ATTEMPTS = 10 DEFAULT_MAX_ATTEMPTS = 10
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): def _validate_resource_type_length(resource_type):
# Add in a validation to ensure that we catch this at build time # Add in a validation to ensure that we catch this at build time
if len(resource_type) > MAX_RESOURCE_TYPE_LEN: if len(resource_type) > MAX_RESOURCE_TYPE_LEN:
@ -63,31 +38,6 @@ def _validate_resource_type_length(resource_type):
'resource_type': resource_type})) '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): def add_v3_tag(tags, resource_type, tag):
_validate_resource_type_length(resource_type) _validate_resource_type_length(resource_type)
tags.append({'scope': resource_type, 'tag': tag[:MAX_TAG_LEN]}) tags.append({'scope': resource_type, 'tag': tag[:MAX_TAG_LEN]})
@ -174,15 +124,15 @@ def get_name_and_uuid(name, uuid, tag=None, maxlen=80):
class NsxLibApiBase(object): class NsxLibApiBase(object):
"""Base class for nsxlib api """ """Base class for nsxlib api """
def __init__(self, client, max_attempts): def __init__(self, client, nsxlib_config):
self.client = client self.client = client
self.max_attempts = max_attempts self.nsxlib_config = nsxlib_config
super(NsxLibApiBase, self).__init__() super(NsxLibApiBase, self).__init__()
def _update_resource_with_retry(self, resource, payload): def _update_resource_with_retry(self, resource, payload):
#Using internal method so we can access max_attempts in the decorator #Using internal method so we can access max_attempts in the decorator
@retry_upon_exception(nsxlib_exceptions.StaleRevision, @retry_upon_exception(nsxlib_exceptions.StaleRevision,
max_attempts=self.max_attempts) max_attempts=self.nsxlib_config.max_attempts)
def do_update(): def do_update():
revised_payload = self.client.get(resource) revised_payload = self.client.get(resource)
for key_name in payload.keys(): for key_name in payload.keys():
@ -215,3 +165,47 @@ class NsxLibApiBase(object):
raise exceptions.ManagerError(details=err_msg) raise exceptions.ManagerError(details=err_msg)
return matched_results[0].get('id') return matched_results[0].get('id')
def build_v3_api_version_tag(self,):
"""
Some resources are created on the manager that do not have a
corresponding plugin resource.
"""
return [{'scope': self.nsxlib_config.plugin_scope,
'tag': self.nsxlib_config.plugin_tag},
{'scope': "os-api-version",
'tag': self.nsxlib_config.plugin_ver}]
def is_internal_resource(self, 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'] == self.nsxlib_config.plugin_scope:
return tag['tag'] == self.nsxlib_config.plugin_tag
return False
def build_v3_tags_payload(self, resource, resource_type, project_name):
"""
Construct the tags payload that will be pushed to NSX-v3
Add <resource_type>:<resource-id>, os-project-id:<project-id>,
os-project-name:<project_name> os-api-version:<plugin-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 = self.nsxlib_config.plugin_tag
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': self.nsxlib_config.plugin_ver}]

View File

@ -84,7 +84,6 @@ from vmware_nsx.extensions import maclearning as mac_ext
from vmware_nsx.extensions import providersecuritygroup as provider_sg from vmware_nsx.extensions import providersecuritygroup as provider_sg
from vmware_nsx.extensions import securitygrouplogging as sg_logging from vmware_nsx.extensions import securitygrouplogging as sg_logging
from vmware_nsx.nsxlib.v3 import exceptions as nsx_lib_exc from vmware_nsx.nsxlib.v3 import exceptions as nsx_lib_exc
from vmware_nsx.nsxlib.v3 import native_dhcp
from vmware_nsx.nsxlib.v3 import ns_group_manager from vmware_nsx.nsxlib.v3 import ns_group_manager
from vmware_nsx.nsxlib.v3 import nsx_constants as nsxlib_consts from vmware_nsx.nsxlib.v3 import nsx_constants as nsxlib_consts
from vmware_nsx.nsxlib.v3 import resources as nsx_resources from vmware_nsx.nsxlib.v3 import resources as nsx_resources
@ -102,6 +101,7 @@ NSX_V3_PSEC_PROFILE_NAME = 'neutron_port_spoof_guard_profile'
NSX_V3_NO_PSEC_PROFILE_NAME = 'nsx-default-spoof-guard-vif-profile' NSX_V3_NO_PSEC_PROFILE_NAME = 'nsx-default-spoof-guard-vif-profile'
NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile' NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile'
NSX_V3_MAC_LEARNING_PROFILE_NAME = 'neutron_port_mac_learning_profile' NSX_V3_MAC_LEARNING_PROFILE_NAME = 'neutron_port_mac_learning_profile'
NSX_V3_FW_DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups'
# NOTE(asarfaty): the order of inheritance here is important. in order for the # NOTE(asarfaty): the order of inheritance here is important. in order for the
@ -166,6 +166,11 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
LOG.info(_LI("Starting NsxV3Plugin")) LOG.info(_LI("Starting NsxV3Plugin"))
self.nsxlib = v3_utils.get_nsxlib_wrapper() self.nsxlib = v3_utils.get_nsxlib_wrapper()
# reinitialize the cluster upon fork for api workers to ensure each
# process has its own keepalive loops + state
registry.subscribe(
self.nsxlib.reinitialize_cluster,
resources.PROCESS, events.AFTER_INIT)
self._nsx_version = self.nsxlib.get_version() self._nsx_version = self.nsxlib.get_version()
LOG.info(_LI("NSX Version: %s"), self._nsx_version) LOG.info(_LI("NSX Version: %s"), self._nsx_version)
@ -318,7 +323,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if not profile: if not profile:
self._switching_profiles.create_dhcp_profile( self._switching_profiles.create_dhcp_profile(
NSX_V3_DHCP_PROFILE_NAME, 'Neutron DHCP Security Profile', NSX_V3_DHCP_PROFILE_NAME, 'Neutron DHCP Security Profile',
tags=nsxlib_utils.build_v3_api_version_tag()) tags=self.nsxlib.build_v3_api_version_tag())
return self._get_dhcp_security_profile() return self._get_dhcp_security_profile()
def _get_dhcp_security_profile(self): def _get_dhcp_security_profile(self):
@ -338,7 +343,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._switching_profiles.create_mac_learning_profile( self._switching_profiles.create_mac_learning_profile(
NSX_V3_MAC_LEARNING_PROFILE_NAME, NSX_V3_MAC_LEARNING_PROFILE_NAME,
'Neutron MAC Learning Profile', 'Neutron MAC Learning Profile',
tags=nsxlib_utils.build_v3_api_version_tag()) tags=self.nsxlib.build_v3_api_version_tag())
return self._get_mac_learning_profile() return self._get_mac_learning_profile()
def _get_mac_learning_profile(self): def _get_mac_learning_profile(self):
@ -378,7 +383,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._switching_profiles.create_spoofguard_profile( self._switching_profiles.create_spoofguard_profile(
NSX_V3_PSEC_PROFILE_NAME, 'Neutron Port Security Profile', NSX_V3_PSEC_PROFILE_NAME, 'Neutron Port Security Profile',
whitelist_ports=True, whitelist_switches=False, whitelist_ports=True, whitelist_switches=False,
tags=nsxlib_utils.build_v3_api_version_tag()) tags=self.nsxlib.build_v3_api_version_tag())
return self._get_port_security_profile() return self._get_port_security_profile()
def _process_security_group_logging(self): def _process_security_group_logging(self):
@ -409,7 +414,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
section_description = ("This section is handled by OpenStack to " section_description = ("This section is handled by OpenStack to "
"contain default rules on security-groups.") "contain default rules on security-groups.")
section_id = self.nsxlib.firewall_section.init_default( section_id = self.nsxlib.firewall_section.init_default(
security.DEFAULT_SECTION, section_description, NSX_V3_FW_DEFAULT_SECTION, section_description,
nsgroup_manager.nested_groups.values(), nsgroup_manager.nested_groups.values(),
cfg.CONF.nsx_v3.log_security_groups_blocked_traffic) cfg.CONF.nsx_v3.log_security_groups_blocked_traffic)
return nsgroup_manager, section_id return nsgroup_manager, section_id
@ -596,7 +601,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
# update the network name to indicate the neutron id too. # update the network name to indicate the neutron id too.
net_name = utils.get_name_and_uuid(net_data['name'] or 'network', net_name = utils.get_name_and_uuid(net_data['name'] or 'network',
neutron_net_id) neutron_net_id)
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
net_data, resource_type='os-neutron-net-id', net_data, resource_type='os-neutron-net-id',
project_name=context.tenant_name) project_name=context.tenant_name)
@ -708,7 +713,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if is_backend_network and cfg.CONF.nsx_v3.native_dhcp_metadata: if is_backend_network and cfg.CONF.nsx_v3.native_dhcp_metadata:
# Enable native metadata proxy for this network. # Enable native metadata proxy for this network.
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
net_data, resource_type='os-neutron-net-id', net_data, resource_type='os-neutron-net-id',
project_name=context.tenant_name) project_name=context.tenant_name)
name = utils.get_name_and_uuid('%s-%s' % ( name = utils.get_name_and_uuid('%s-%s' % (
@ -915,13 +920,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
} }
neutron_port = super(NsxV3Plugin, self).create_port( neutron_port = super(NsxV3Plugin, self).create_port(
context, {'port': port_data}) context, {'port': port_data})
server_data = native_dhcp.build_dhcp_server_config( net_tags = self.nsxlib.build_v3_tags_payload(
network, subnet, neutron_port, context.tenant_name, network, resource_type='os-neutron-net-id',
cfg.CONF.nsx_v3.nameservers, project_name=context.tenant_name)
cfg.CONF.nsx_v3.dhcp_profile_uuid, server_data = self.nsxlib.native_dhcp.build_server_config(
cfg.CONF.nsx_v3.dns_domain) network, subnet, neutron_port, net_tags)
nsx_net_id = self._get_network_nsx_id(context, network['id']) nsx_net_id = self._get_network_nsx_id(context, network['id'])
tags = nsxlib_utils.build_v3_tags_payload( port_tags = self.nsxlib.build_v3_tags_payload(
neutron_port, resource_type='os-neutron-dport-id', neutron_port, resource_type='os-neutron-dport-id',
project_name=context.tenant_name) project_name=context.tenant_name)
dhcp_server = None dhcp_server = None
@ -932,7 +937,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
{'server': dhcp_server['id'], 'network': network['id']}) {'server': dhcp_server['id'], 'network': network['id']})
name = self._get_port_name(context, port_data) name = self._get_port_name(context, port_data)
nsx_port = self._port_client.create( nsx_port = self._port_client.create(
nsx_net_id, dhcp_server['id'], tags=tags, name=name, nsx_net_id, dhcp_server['id'], tags=port_tags, name=name,
attachment_type=nsxlib_consts.ATTACHMENT_DHCP) attachment_type=nsxlib_consts.ATTACHMENT_DHCP)
LOG.debug("Created DHCP logical port %(port)s for " LOG.debug("Created DHCP logical port %(port)s for "
"network %(network)s", "network %(network)s",
@ -1254,7 +1259,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
resource_type = 'os-neutron-rport-id' resource_type = 'os-neutron-rport-id'
else: else:
resource_type = 'os-neutron-port-id' resource_type = 'os-neutron-port-id'
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
port_data, resource_type=resource_type, port_data, resource_type=resource_type,
project_name=context.tenant_name) project_name=context.tenant_name)
resource_type = self._get_resource_type_for_device_id( resource_type = self._get_resource_type_for_device_id(
@ -2244,7 +2249,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
edge_cluster_uuid = self._get_edge_cluster(new_tier0_uuid) edge_cluster_uuid = self._get_edge_cluster(new_tier0_uuid)
self._routerlib.update_router_edge_cluster( self._routerlib.update_router_edge_cluster(
nsx_router_id, edge_cluster_uuid) nsx_router_id, edge_cluster_uuid)
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
router, resource_type='os-neutron-rport', router, resource_type='os-neutron-rport',
project_name=context.tenant_name) project_name=context.tenant_name)
self._routerlib.add_router_link_port(nsx_router_id, new_tier0_uuid, self._routerlib.add_router_link_port(nsx_router_id, new_tier0_uuid,
@ -2264,7 +2269,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
gw_info = self._extract_external_gw(context, router, is_extract=True) gw_info = self._extract_external_gw(context, router, is_extract=True)
router['router']['id'] = (router['router'].get('id') or router['router']['id'] = (router['router'].get('id') or
uuidutils.generate_uuid()) uuidutils.generate_uuid())
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
router['router'], resource_type='os-neutron-router-id', router['router'], resource_type='os-neutron-router-id',
project_name=context.tenant_name) project_name=context.tenant_name)
result = self._router_client.create( result = self._router_client.create(
@ -2530,7 +2535,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
context, router_id, network_id) context, router_id, network_id)
display_name = utils.get_name_and_uuid( display_name = utils.get_name_and_uuid(
subnet['name'] or 'subnet', subnet['id']) subnet['name'] or 'subnet', subnet['id'])
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
port, resource_type='os-neutron-rport-id', port, resource_type='os-neutron-rport-id',
project_name=context.tenant_name) project_name=context.tenant_name)
tags.append({'scope': 'os-subnet-id', 'tag': subnet['id']}) tags.append({'scope': 'os-subnet-id', 'tag': subnet['id']})
@ -2799,7 +2804,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
return firewall_section return firewall_section
def _create_security_group_backend_resources(self, secgroup): def _create_security_group_backend_resources(self, secgroup):
tags = nsxlib_utils.build_v3_tags_payload( tags = self.nsxlib.build_v3_tags_payload(
secgroup, resource_type='os-neutron-secgr-id', secgroup, resource_type='os-neutron-secgr-id',
project_name=secgroup['tenant_id']) project_name=secgroup['tenant_id'])
name = self.nsxlib.ns_group.get_name(secgroup) name = self.nsxlib.ns_group.get_name(secgroup)

View File

@ -14,11 +14,18 @@
# under the License. # under the License.
from oslo_config import cfg from oslo_config import cfg
from neutron import version as n_version
from vmware_nsx.nsxlib import v3 from vmware_nsx.nsxlib import v3
from vmware_nsx.nsxlib.v3 import config
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
def get_nsxlib_wrapper(): def get_nsxlib_wrapper():
return v3.NsxLib( nsxlib_config = config.NsxLibConfig(
username=cfg.CONF.nsx_v3.nsx_api_user, username=cfg.CONF.nsx_v3.nsx_api_user,
password=cfg.CONF.nsx_v3.nsx_api_password, password=cfg.CONF.nsx_v3.nsx_api_password,
retries=cfg.CONF.nsx_v3.http_retries, retries=cfg.CONF.nsx_v3.http_retries,
@ -30,4 +37,11 @@ def get_nsxlib_wrapper():
conn_idle_timeout=cfg.CONF.nsx_v3.conn_idle_timeout, conn_idle_timeout=cfg.CONF.nsx_v3.conn_idle_timeout,
http_provider=None, http_provider=None,
max_attempts=cfg.CONF.nsx_v3.retries, max_attempts=cfg.CONF.nsx_v3.retries,
nsx_api_managers=cfg.CONF.nsx_v3.nsx_api_managers) nsx_api_managers=cfg.CONF.nsx_v3.nsx_api_managers,
plugin_scope=OS_NEUTRON_ID_SCOPE,
plugin_tag=NSX_NEUTRON_PLUGIN,
plugin_ver=n_version.version_info.release_string(),
dns_nameservers=cfg.CONF.nsx_v3.nameservers,
dns_domain=cfg.CONF.nsx_v3.dns_domain,
dhcp_profile_uuid=cfg.CONF.nsx_v3.dhcp_profile_uuid)
return v3.NsxLib(nsxlib_config)

View File

@ -38,7 +38,6 @@ from vmware_nsx.common import utils as nsx_utils
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -220,7 +219,7 @@ class NsxV3Driver(l2gateway_db.L2GatewayMixin):
tenant_id = context.tenant_id tenant_id = context.tenant_id
gw_connection['tenant_id'] = tenant_id gw_connection['tenant_id'] = tenant_id
try: try:
tags = nsxlib_utils.build_v3_tags_payload( tags = self._core_plugin.nsxlib.build_v3_tags_payload(
gw_connection, resource_type='os-neutron-l2gw-id', gw_connection, resource_type='os-neutron-l2gw-id',
project_name=context.tenant_name) project_name=context.tenant_name)
bridge_endpoint = self._core_plugin.nsxlib.bridge_endpoint.create( bridge_endpoint = self._core_plugin.nsxlib.bridge_endpoint.create(

View File

@ -31,7 +31,6 @@ from vmware_nsx.db import db as nsx_db
from vmware_nsx.nsxlib import v3 as nsxlib from vmware_nsx.nsxlib import v3 as nsxlib
from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsx.nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsx.nsxlib.v3 import resources as nsx_resources from vmware_nsx.nsxlib.v3 import resources as nsx_resources
from vmware_nsx.nsxlib.v3 import utils as nsxlib_utils
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -178,7 +177,8 @@ class NsxV3Driver(base_driver.TaasBaseDriver,
tf.get('tap_service_id')) tf.get('tap_service_id'))
src_port_id = tf.get('source_port') src_port_id = tf.get('source_port')
dest_port_id = ts.get('port_id') dest_port_id = ts.get('port_id')
tags = nsxlib_utils.build_v3_tags_payload( nsxlib = v3_utils.get_nsxlib_wrapper()
tags = nsxlib.build_v3_tags_payload(
tf, resource_type='os-neutron-mirror-id', tf, resource_type='os-neutron-mirror-id',
project_name=context._plugin_context.tenant_name) project_name=context._plugin_context.tenant_name)
nsx_direction = self._convert_to_backend_direction( nsx_direction = self._convert_to_backend_direction(

View File

@ -26,7 +26,6 @@ from oslo_log import log as logging
from vmware_nsx._i18n import _, _LW from vmware_nsx._i18n import _, _LW
from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.nsxlib.v3 import utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
MAX_KBPS_MIN_VALUE = 1024 MAX_KBPS_MIN_VALUE = 1024
@ -90,7 +89,7 @@ class QosNotificationsHandler(object):
def _get_tags(self, context, policy): def _get_tags(self, context, policy):
policy_dict = {'id': policy.id, 'tenant_id': policy.tenant_id} policy_dict = {'id': policy.id, 'tenant_id': policy.tenant_id}
return utils.build_v3_tags_payload( return self._nsxlib_qos.build_v3_tags_payload(
policy_dict, resource_type='os-neutron-qos-id', policy_dict, resource_type='os-neutron-qos-id',
project_name=context.tenant_name) project_name=context.tenant_name)

View File

@ -21,7 +21,6 @@ from oslo_config import cfg
from vmware_nsx._i18n import _LE, _LI from vmware_nsx._i18n import _LE, _LI
from vmware_nsx.common import utils as nsx_utils from vmware_nsx.common import utils as nsx_utils
from vmware_nsx.nsxlib.v3 import native_dhcp
from vmware_nsx.nsxlib.v3 import nsx_constants from vmware_nsx.nsxlib.v3 import nsx_constants
from vmware_nsx.nsxlib.v3 import resources from vmware_nsx.nsxlib.v3 import resources
from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import constants
@ -48,7 +47,8 @@ def list_dhcp_bindings(resource, event, trigger, **kwargs):
def nsx_update_dhcp_bindings(resource, event, trigger, **kwargs): def nsx_update_dhcp_bindings(resource, event, trigger, **kwargs):
"""Resync DHCP bindings for NSXv3 CrossHairs.""" """Resync DHCP bindings for NSXv3 CrossHairs."""
nsx_version = utils.get_connected_nsxlib().get_version() nsxlib = utils.get_connected_nsxlib()
nsx_version = nsxlib.get_version()
if not nsx_utils.is_nsx_version_1_1_0(nsx_version): if not nsx_utils.is_nsx_version_1_1_0(nsx_version):
LOG.info(_LI("This utility is not available for NSX version %s"), LOG.info(_LI("This utility is not available for NSX version %s"),
nsx_version) nsx_version)
@ -88,11 +88,11 @@ def nsx_update_dhcp_bindings(resource, event, trigger, **kwargs):
# and update the attachment type to DHCP on the corresponding # and update the attachment type to DHCP on the corresponding
# logical port of the Neutron DHCP port. # logical port of the Neutron DHCP port.
network = neutron_client.get_network(port['network_id']) network = neutron_client.get_network(port['network_id'])
server_data = native_dhcp.build_dhcp_server_config( net_tags = nsxlib.build_v3_tags_payload(
network, subnet, port, 'admin', network, resource_type='os-neutron-net-id',
cfg.CONF.nsx_v3.nameservers, project_name='admin')
cfg.CONF.nsx_v3.dhcp_profile_uuid, server_data = nsxlib.native_dhcp.build_server_config(
cfg.CONF.nsx_v3.dns_domain) network, subnet, port, net_tags)
dhcp_server = dhcp_server_resource.create(**server_data) dhcp_server = dhcp_server_resource.create(**server_data)
LOG.info(_LI("Created logical DHCP server %(server)s for " LOG.info(_LI("Created logical DHCP server %(server)s for "
"network %(network)s"), "network %(network)s"),

View File

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

View File

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

View File

@ -20,9 +20,10 @@ import unittest
from oslo_utils import uuidutils from oslo_utils import uuidutils
from requests import exceptions as requests_exceptions from requests import exceptions as requests_exceptions
from vmware_nsx.nsxlib import v3
from vmware_nsx.nsxlib.v3 import client as nsx_client from vmware_nsx.nsxlib.v3 import client as nsx_client
from vmware_nsx.nsxlib.v3 import cluster as nsx_cluster from vmware_nsx.nsxlib.v3 import cluster as nsx_cluster
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils from vmware_nsx.nsxlib.v3 import config
NSX_USER = 'admin' NSX_USER = 'admin'
NSX_PASSWORD = 'default' NSX_PASSWORD = 'default'
@ -35,6 +36,10 @@ NSX_HTTP_READ_TIMEOUT = 180
NSX_CONCURENT_CONN = 10 NSX_CONCURENT_CONN = 10
NSX_CONN_IDLE_TIME = 10 NSX_CONN_IDLE_TIME = 10
PLUGIN_SCOPE = "plugin scope"
PLUGIN_TAG = "plugin tag"
PLUGIN_VER = "plugin ver"
def _mock_nsxlib(): def _mock_nsxlib():
def _return_id_key(*args, **kwargs): def _return_id_key(*args, **kwargs):
@ -84,13 +89,32 @@ def _mock_nsxlib():
return_value='1.1.0').start() return_value='1.1.0').start()
def get_default_nsxlib_config():
return config.NsxLibConfig(
username=NSX_USER,
password=NSX_PASSWORD,
retries=NSX_HTTP_RETRIES,
insecure=NSX_INSECURE,
ca_file=NSX_CERT,
concurrent_connections=NSX_CONCURENT_CONN,
http_timeout=NSX_HTTP_TIMEOUT,
http_read_timeout=NSX_HTTP_READ_TIMEOUT,
conn_idle_timeout=NSX_CONN_IDLE_TIME,
http_provider=None,
nsx_api_managers=[],
plugin_scope=PLUGIN_SCOPE,
plugin_tag=PLUGIN_TAG,
plugin_ver=PLUGIN_VER)
class NsxLibTestCase(unittest.TestCase): class NsxLibTestCase(unittest.TestCase):
def setUp(self, *args, **kwargs): def setUp(self, *args, **kwargs):
super(NsxLibTestCase, self).setUp() super(NsxLibTestCase, self).setUp()
_mock_nsxlib() _mock_nsxlib()
self.nsxlib = v3_utils.get_nsxlib_wrapper() nsxlib_config = get_default_nsxlib_config()
self.nsxlib = v3.NsxLib(nsxlib_config)
# print diffs when assert comparisons fail # print diffs when assert comparisons fail
self.maxDiff = None self.maxDiff = None
@ -135,7 +159,8 @@ class NsxClientTestCase(NsxLibTestCase):
http_read_timeout=None, http_read_timeout=None,
conn_idle_timeout=None, conn_idle_timeout=None,
nsx_api_managers=None): nsx_api_managers=None):
super(NsxClientTestCase.MockNSXClusteredAPI, self).__init__(
nsxlib_config = config.NsxLibConfig(
username=username or NSX_USER, username=username or NSX_USER,
password=password or NSX_PASSWORD, password=password or NSX_PASSWORD,
retries=retries or NSX_HTTP_RETRIES, retries=retries or NSX_HTTP_RETRIES,
@ -148,7 +173,13 @@ class NsxClientTestCase(NsxLibTestCase):
conn_idle_timeout=conn_idle_timeout or NSX_CONN_IDLE_TIME, conn_idle_timeout=conn_idle_timeout or NSX_CONN_IDLE_TIME,
http_provider=NsxClientTestCase.MockHTTPProvider( http_provider=NsxClientTestCase.MockHTTPProvider(
session_response=session_response), session_response=session_response),
nsx_api_managers=nsx_api_managers or [NSX_MANAGER]) nsx_api_managers=nsx_api_managers or [NSX_MANAGER],
plugin_scope=PLUGIN_SCOPE,
plugin_tag=PLUGIN_TAG,
plugin_ver=PLUGIN_VER)
super(NsxClientTestCase.MockNSXClusteredAPI, self).__init__(
nsxlib_config)
self._record = mock.Mock() self._record = mock.Mock()
def record_call(self, request, **kwargs): def record_call(self, request, **kwargs):
@ -279,16 +310,10 @@ class NsxClientTestCase(NsxLibTestCase):
mock_provider.default_scheme = 'https' mock_provider.default_scheme = 'https'
mock_provider.validate_connection = validate_conn_func mock_provider.validate_connection = validate_conn_func
return nsx_cluster.NSXClusteredAPI( nsxlib_config = get_default_nsxlib_config()
username=NSX_USER, if concurrent_connections:
password=NSX_PASSWORD, nsxlib_config.concurrent_connections = concurrent_connections
retries=NSX_HTTP_RETRIES, nsxlib_config.http_provider = mock_provider
insecure=NSX_INSECURE, nsxlib_config.nsx_api_managers = conf_managers
ca_file=NSX_CERT,
concurrent_connections=(concurrent_connections or return nsx_cluster.NSXClusteredAPI(nsxlib_config)
NSX_CONCURENT_CONN),
http_timeout=NSX_HTTP_TIMEOUT,
http_read_timeout=NSX_HTTP_READ_TIMEOUT,
conn_idle_timeout=NSX_CONN_IDLE_TIME,
http_provider=mock_provider,
nsx_api_managers=conf_managers)

View File

@ -38,13 +38,14 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
def test_new_connection(self): def test_new_connection(self):
mock_api = mock.Mock() mock_api = mock.Mock()
mock_api._username = 'nsxuser' mock_api.nsxlib_config = mock.Mock()
mock_api._password = 'nsxpassword' mock_api.nsxlib_config.username = 'nsxuser'
mock_api.retries = 100 mock_api.nsxlib_config.password = 'nsxpassword'
mock_api.insecure = True mock_api.nsxlib_config.retries = 100
mock_api._ca_file = None mock_api.nsxlib_config.insecure = True
mock_api.http_timeout = 99 mock_api.nsxlib_config.ca_file = None
mock_api.conn_idle_timeout = 39 mock_api.nsxlib_config.http_timeout = 99
mock_api.nsxlib_config.conn_idle_timeout = 39
provider = cluster.NSXRequestsHTTPProvider() provider = cluster.NSXRequestsHTTPProvider()
session = provider.new_connection( session = provider.new_connection(
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6', mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
@ -196,3 +197,8 @@ class ClusteredAPITestCase(nsxlib_testcase.NsxClientTestCase):
eps[0]._state = cluster.EndpointState.UP eps[0]._state = cluster.EndpointState.UP
self.assertEqual(_get_schedule(4), [eps[0], eps[2], eps[0], eps[2]]) self.assertEqual(_get_schedule(4), [eps[0], eps[2], eps[0], eps[2]])
def test_reinitialize_cluster(self):
api = self.mock_nsx_clustered_api()
# just make sure this api is defined, and does not crash
api._reinit_cluster()

View File

@ -52,7 +52,7 @@ class NsxLibQosTestCase(nsxlib_testcase.NsxClientTestCase):
body["description"] = description body["description"] = description
for shaper in body["shaper_configuration"]: for shaper in body["shaper_configuration"]:
# Neutron currently support only shaping of Egress traffic # We currently support only shaping of Egress traffic
if shaper["resource_type"] == "EgressRateShaper": if shaper["resource_type"] == "EgressRateShaper":
shaper["enabled"] = shaping_enabled shaper["enabled"] = shaping_enabled
if burst_size: if burst_size:

View File

@ -93,7 +93,7 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
mocked_resource = self._mocked_switching_profile() mocked_resource = self._mocked_switching_profile()
mocked_resource.create_spoofguard_profile( mocked_resource.create_spoofguard_profile(
'neutron-spoof', 'spoofguard-for-neutron', 'plugin-spoof', 'spoofguard-for-plugin',
whitelist_ports=True, tags=tags) whitelist_ports=True, tags=tags)
test_client.assert_json_call( test_client.assert_json_call(
@ -101,8 +101,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'https://1.2.3.4/api/v1/switching-profiles', 'https://1.2.3.4/api/v1/switching-profiles',
data=jsonutils.dumps({ data=jsonutils.dumps({
'resource_type': profile_types.SPOOF_GUARD, 'resource_type': profile_types.SPOOF_GUARD,
'display_name': 'neutron-spoof', 'display_name': 'plugin-spoof',
'description': 'spoofguard-for-neutron', 'description': 'spoofguard-for-plugin',
'white_list_providers': ['LPORT_BINDINGS'], 'white_list_providers': ['LPORT_BINDINGS'],
'tags': tags 'tags': tags
}, sort_keys=True)) }, sort_keys=True))
@ -123,7 +123,7 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
mocked_resource = self._mocked_switching_profile() mocked_resource = self._mocked_switching_profile()
mocked_resource.create_dhcp_profile( mocked_resource.create_dhcp_profile(
'neutron-dhcp', 'dhcp-for-neutron', 'plugin-dhcp', 'dhcp-for-plugin',
tags=tags) tags=tags)
test_client.assert_json_call( test_client.assert_json_call(
@ -135,8 +135,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'white_list': [] 'white_list': []
}, },
'resource_type': profile_types.SWITCH_SECURITY, 'resource_type': profile_types.SWITCH_SECURITY,
'display_name': 'neutron-dhcp', 'display_name': 'plugin-dhcp',
'description': 'dhcp-for-neutron', 'description': 'dhcp-for-plugin',
'tags': tags, 'tags': tags,
'dhcp_filter': { 'dhcp_filter': {
'client_block_enabled': True, 'client_block_enabled': True,
@ -168,7 +168,7 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
mocked_resource = self._mocked_switching_profile() mocked_resource = self._mocked_switching_profile()
mocked_resource.create_mac_learning_profile( mocked_resource.create_mac_learning_profile(
'neutron-mac-learning', 'mac-learning-for-neutron', 'plugin-mac-learning', 'mac-learning-for-plugin',
tags=tags) tags=tags)
test_client.assert_json_call( test_client.assert_json_call(
@ -179,8 +179,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'enabled': True, 'enabled': True,
}, },
'resource_type': profile_types.MAC_LEARNING, 'resource_type': profile_types.MAC_LEARNING,
'display_name': 'neutron-mac-learning', 'display_name': 'plugin-mac-learning',
'description': 'mac-learning-for-neutron', 'description': 'mac-learning-for-plugin',
'tags': tags, 'tags': tags,
'source_mac_change_allowed': True, 'source_mac_change_allowed': True,
}, sort_keys=True)) }, sort_keys=True))

View File

@ -13,71 +13,69 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
from neutron import version
from neutron_lib import exceptions as n_exc from neutron_lib import exceptions as n_exc
from vmware_nsx.nsxlib.v3 import utils from vmware_nsx.nsxlib.v3 import utils
from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase from vmware_nsx.tests.unit.nsxlib.v3 import nsxlib_testcase
class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase, class TestNsxV3Utils(nsxlib_testcase.NsxClientTestCase):
nsxlib_testcase.NsxClientTestCase):
def test_build_v3_tags_payload(self): def test_build_v3_tags_payload(self):
result = utils.build_v3_tags_payload( result = self.nsxlib.build_v3_tags_payload(
{'id': 'fake_id', {'id': 'fake_id',
'tenant_id': 'fake_tenant_id'}, 'tenant_id': 'fake_tenant_id'},
resource_type='os-neutron-net-id', resource_type='os-net-id',
project_name='fake_tenant_name') project_name='fake_tenant_name')
expected = [{'scope': 'os-neutron-net-id', 'tag': 'fake_id'}, expected = [{'scope': 'os-net-id', 'tag': 'fake_id'},
{'scope': 'os-project-id', 'tag': 'fake_tenant_id'}, {'scope': 'os-project-id', 'tag': 'fake_tenant_id'},
{'scope': 'os-project-name', 'tag': 'fake_tenant_name'}, {'scope': 'os-project-name', 'tag': 'fake_tenant_name'},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
self.assertEqual(expected, result) self.assertEqual(expected, result)
def test_build_v3_tags_payload_internal(self): def test_build_v3_tags_payload_internal(self):
result = utils.build_v3_tags_payload( result = self.nsxlib.build_v3_tags_payload(
{'id': 'fake_id', {'id': 'fake_id',
'tenant_id': 'fake_tenant_id'}, 'tenant_id': 'fake_tenant_id'},
resource_type='os-neutron-net-id', resource_type='os-net-id',
project_name=None) project_name=None)
expected = [{'scope': 'os-neutron-net-id', 'tag': 'fake_id'}, expected = [{'scope': 'os-net-id', 'tag': 'fake_id'},
{'scope': 'os-project-id', 'tag': 'fake_tenant_id'}, {'scope': 'os-project-id', 'tag': 'fake_tenant_id'},
{'scope': 'os-project-name', 'tag': 'NSX Neutron plugin'}, {'scope': 'os-project-name',
'tag': nsxlib_testcase.PLUGIN_TAG},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
self.assertEqual(expected, result) self.assertEqual(expected, result)
def test_build_v3_tags_payload_invalid_length(self): def test_build_v3_tags_payload_invalid_length(self):
self.assertRaises(n_exc.InvalidInput, self.assertRaises(n_exc.InvalidInput,
utils.build_v3_tags_payload, self.nsxlib.build_v3_tags_payload,
{'id': 'fake_id', {'id': 'fake_id',
'tenant_id': 'fake_tenant_id'}, 'tenant_id': 'fake_tenant_id'},
resource_type='os-neutron-maldini-rocks-id', resource_type='os-longer-maldini-rocks-id',
project_name='fake') project_name='fake')
def test_build_v3_api_version_tag(self): def test_build_v3_api_version_tag(self):
result = utils.build_v3_api_version_tag() result = self.nsxlib.build_v3_api_version_tag()
expected = [{'scope': 'os-neutron-id', expected = [{'scope': nsxlib_testcase.PLUGIN_SCOPE,
'tag': 'NSX Neutron plugin'}, 'tag': nsxlib_testcase.PLUGIN_TAG},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
self.assertEqual(expected, result) self.assertEqual(expected, result)
def test_is_internal_resource(self): def test_is_internal_resource(self):
project_tag = utils.build_v3_tags_payload( project_tag = self.nsxlib.build_v3_tags_payload(
{'id': 'fake_id', {'id': 'fake_id',
'tenant_id': 'fake_tenant_id'}, 'tenant_id': 'fake_tenant_id'},
resource_type='os-neutron-net-id', resource_type='os-net-id',
project_name=None) project_name=None)
internal_tag = utils.build_v3_api_version_tag() internal_tag = self.nsxlib.build_v3_api_version_tag()
expect_false = utils.is_internal_resource({'tags': project_tag}) expect_false = self.nsxlib.is_internal_resource({'tags': project_tag})
self.assertFalse(expect_false) self.assertFalse(expect_false)
expect_true = utils.is_internal_resource({'tags': internal_tag}) expect_true = self.nsxlib.is_internal_resource({'tags': internal_tag})
self.assertTrue(expect_true) self.assertTrue(expect_true)
def test_get_name_and_uuid(self): def test_get_name_and_uuid(self):
@ -93,16 +91,16 @@ class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase,
self.assertEqual(expected, short_name) self.assertEqual(expected, short_name)
def test_build_v3_tags_max_length_payload(self): def test_build_v3_tags_max_length_payload(self):
result = utils.build_v3_tags_payload( result = self.nsxlib.build_v3_tags_payload(
{'id': 'X' * 255, {'id': 'X' * 255,
'tenant_id': 'X' * 255}, 'tenant_id': 'X' * 255},
resource_type='os-neutron-net-id', resource_type='os-net-id',
project_name='X' * 255) project_name='X' * 255)
expected = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, expected = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'X' * 40}, {'scope': 'os-project-id', 'tag': 'X' * 40},
{'scope': 'os-project-name', 'tag': 'X' * 40}, {'scope': 'os-project-name', 'tag': 'X' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
self.assertEqual(expected, result) self.assertEqual(expected, result)
def test_add_v3_tag(self): def test_add_v3_tag(self):
@ -123,59 +121,59 @@ class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase,
'fake-tag') 'fake-tag')
def test_update_v3_tags_addition(self): def test_update_v3_tags_addition(self):
tags = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, tags = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
resources = [{'scope': 'os-instance-uuid', resources = [{'scope': 'os-instance-uuid',
'tag': 'A' * 40}] 'tag': 'A' * 40}]
tags = utils.update_v3_tags(tags, resources) tags = utils.update_v3_tags(tags, resources)
expected = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, expected = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}, 'tag': nsxlib_testcase.PLUGIN_VER},
{'scope': 'os-instance-uuid', {'scope': 'os-instance-uuid',
'tag': 'A' * 40}] 'tag': 'A' * 40}]
self.assertEqual(sorted(expected, key=lambda x: x.get('tag')), self.assertEqual(sorted(expected, key=lambda x: x.get('tag')),
sorted(tags, key=lambda x: x.get('tag'))) sorted(tags, key=lambda x: x.get('tag')))
def test_update_v3_tags_removal(self): def test_update_v3_tags_removal(self):
tags = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, tags = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
resources = [{'scope': 'os-neutron-net-id', resources = [{'scope': 'os-net-id',
'tag': ''}] 'tag': ''}]
tags = utils.update_v3_tags(tags, resources) tags = utils.update_v3_tags(tags, resources)
expected = [{'scope': 'os-project-id', 'tag': 'Y' * 40}, expected = [{'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
self.assertEqual(sorted(expected, key=lambda x: x.get('tag')), self.assertEqual(sorted(expected, key=lambda x: x.get('tag')),
sorted(tags, key=lambda x: x.get('tag'))) sorted(tags, key=lambda x: x.get('tag')))
def test_update_v3_tags_update(self): def test_update_v3_tags_update(self):
tags = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, tags = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
resources = [{'scope': 'os-project-id', resources = [{'scope': 'os-project-id',
'tag': 'A' * 40}] 'tag': 'A' * 40}]
tags = utils.update_v3_tags(tags, resources) tags = utils.update_v3_tags(tags, resources)
expected = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, expected = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'A' * 40}, {'scope': 'os-project-id', 'tag': 'A' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-api-version', {'scope': 'os-api-version',
'tag': version.version_info.release_string()}] 'tag': nsxlib_testcase.PLUGIN_VER}]
self.assertEqual(sorted(expected, key=lambda x: x.get('tag')), self.assertEqual(sorted(expected, key=lambda x: x.get('tag')),
sorted(tags, key=lambda x: x.get('tag'))) sorted(tags, key=lambda x: x.get('tag')))
def test_update_v3_tags_repetitive_scopes(self): def test_update_v3_tags_repetitive_scopes(self):
tags = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, tags = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-security-group', 'tag': 'SG1'}, {'scope': 'os-security-group', 'tag': 'SG1'},
@ -183,7 +181,7 @@ class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase,
tags_update = [{'scope': 'os-security-group', 'tag': 'SG3'}, tags_update = [{'scope': 'os-security-group', 'tag': 'SG3'},
{'scope': 'os-security-group', 'tag': 'SG4'}] {'scope': 'os-security-group', 'tag': 'SG4'}]
tags = utils.update_v3_tags(tags, tags_update) tags = utils.update_v3_tags(tags, tags_update)
expected = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, expected = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-security-group', 'tag': 'SG3'}, {'scope': 'os-security-group', 'tag': 'SG3'},
@ -192,14 +190,14 @@ class TestNsxV3Utils(test_plugin.NeutronDbPluginV2TestCase,
sorted(tags, key=lambda x: x.get('tag'))) sorted(tags, key=lambda x: x.get('tag')))
def test_update_v3_tags_repetitive_scopes_remove(self): def test_update_v3_tags_repetitive_scopes_remove(self):
tags = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, tags = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}, {'scope': 'os-project-name', 'tag': 'Z' * 40},
{'scope': 'os-security-group', 'tag': 'SG1'}, {'scope': 'os-security-group', 'tag': 'SG1'},
{'scope': 'os-security-group', 'tag': 'SG2'}] {'scope': 'os-security-group', 'tag': 'SG2'}]
tags_update = [{'scope': 'os-security-group', 'tag': None}] tags_update = [{'scope': 'os-security-group', 'tag': None}]
tags = utils.update_v3_tags(tags, tags_update) tags = utils.update_v3_tags(tags, tags_update)
expected = [{'scope': 'os-neutron-net-id', 'tag': 'X' * 40}, expected = [{'scope': 'os-net-id', 'tag': 'X' * 40},
{'scope': 'os-project-id', 'tag': 'Y' * 40}, {'scope': 'os-project-id', 'tag': 'Y' * 40},
{'scope': 'os-project-name', 'tag': 'Z' * 40}] {'scope': 'os-project-name', 'tag': 'Z' * 40}]
self.assertEqual(sorted(expected, key=lambda x: x.get('tag')), self.assertEqual(sorted(expected, key=lambda x: x.get('tag')),

View File

@ -25,7 +25,7 @@ from neutron.services.qos import qos_plugin
from neutron.tests.unit.services.qos import base from neutron.tests.unit.services.qos import base
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.nsxlib.v3 import utils from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin from vmware_nsx.tests.unit.nsx_v3 import test_plugin
@ -85,6 +85,8 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
self.peak_bw_multiplier = cfg.CONF.NSX.qos_peak_bw_multiplier self.peak_bw_multiplier = cfg.CONF.NSX.qos_peak_bw_multiplier
self.nsxlib = v3_utils.get_nsxlib_wrapper()
@mock.patch( @mock.patch(
'neutron.objects.rbac_db.RbacNeutronDbObjectMixin' 'neutron.objects.rbac_db.RbacNeutronDbObjectMixin'
'.create_rbac_policy') '.create_rbac_policy')
@ -100,7 +102,7 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
with mock.patch('neutron.objects.qos.policy.QosPolicy.create'): with mock.patch('neutron.objects.qos.policy.QosPolicy.create'):
policy = self.qos_plugin.create_policy(self.ctxt, policy = self.qos_plugin.create_policy(self.ctxt,
self.policy_data) self.policy_data)
expected_tags = utils.build_v3_tags_payload( expected_tags = self.nsxlib.build_v3_tags_payload(
policy, policy,
resource_type='os-neutron-qos-id', resource_type='os-neutron-qos-id',
project_name=self.ctxt.tenant_name) project_name=self.ctxt.tenant_name)
@ -129,7 +131,7 @@ class TestQosNsxV3Notification(base.BaseQosTestCase,
self.ctxt, self.policy.id, {'policy': fields}) self.ctxt, self.policy.id, {'policy': fields})
# verify that the profile was updated with the correct data # verify that the profile was updated with the correct data
self.policy_data["policy"]["id"] = self.policy.id self.policy_data["policy"]["id"] = self.policy.id
expected_tags = utils.build_v3_tags_payload( expected_tags = self.nsxlib.build_v3_tags_payload(
self.policy_data["policy"], self.policy_data["policy"],
resource_type='os-neutron-qos-id', resource_type='os-neutron-qos-id',
project_name=self.ctxt.tenant_name) project_name=self.ctxt.tenant_name)