NSX|V3+P: cleanup common code

1. Move common code to a dedicated file
2. Stop using deprecated nsxlib apis
3. Remove irrelevant admin utilities

Change-Id: If6308ff47dcd8f51e17cf1e4d367a664681ad2de
This commit is contained in:
asarfaty 2020-04-16 11:44:36 +02:00 committed by Adit Sarfaty
parent e567073dfb
commit b970d8cc58
16 changed files with 261 additions and 518 deletions

View File

@ -424,10 +424,6 @@ Security Groups & NSX Security Groups
nsxadmin -r security-groups -o fix-mismatch
- Update NSX security groups dynamic criteria for NSX-T CrossHairs::
nsxadmin -r nsx-security-groups -o migrate-to-dynamic-criteria
- Update logging flag of the security groups on the NSX DFW::
nsxadmin -r security-groups -o update-logging --property log-allowed-traffic=true
@ -465,10 +461,6 @@ Metadata Proxy
nsxadmin -r metadata-proxy -o list
- Resync metadata proxies for NSX-T version 1.1.0 and above (enable MD proxy, or update the uuid). This is only for migrating to native metadata support::
nsxadmin -r metadata-proxy -o nsx-update --property metadata_proxy_uuid=<metadata_proxy_uuid>
- update the ip of the Nova server in the metadata proxy server on the NSX::
nsxadmin -r metadata-proxy -o nsx-update-ip --property server-ip=<server-ip> --property availability-zone=<optional zone name>
@ -480,10 +472,6 @@ DHCP Bindings
nsxadmin -r dhcp-binding -o list
- Resync DHCP bindings for NSX-T version 1.1.0 and above. This is only for migrating to native DHCP support::
nsxadmin -r dhcp-binding -o nsx-update --property dhcp_profile_uuid=<dhcp_profile_uuid>
- Recreate dhcp server for a neutron network::
nsxadmin -r dhcp-binding -o nsx-recreate --property net-id=<neutron-net-id>
@ -672,30 +660,6 @@ Client Certificate
nsxadmin -r certificate -o nsx-list
Upgrade Steps (NSX-T Version 1.0.0 to Version 1.1.0)
----------------------------------------------------
1. Upgrade NSX backend from version 1.0.0 to version 1.1.0
2. Create a DHCP-Profile and a Metadata-Proxy in NSX backend
3. Stop Neutron
4. Install version 1.1.0 Neutron plugin
5. Run admin tools to migrate version 1.0.0 objects to version 1.1.0 objects
nsxadmin -r metadata-proxy -o nsx-update --property metadata_proxy_uuid=<UUID of Metadata-Proxy created in Step 2>
nsxadmin -r dhcp-binding -o nsx-update --property dhcp_profile_uuid=<UUID of DHCP-Profile created in Step 2>
6. Start Neutron
7. Make sure /etc/nova/nova.conf has
metadata_proxy_shared_secret = <Secret of Metadata-Proxy created in Step 2>
8. Restart VMs or ifdown/ifup their network interface to get new DHCP options
Steps to create a TVD admin user
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -41,7 +41,6 @@ LOG = log.getLogger(__name__)
MAX_DISPLAY_NAME_LEN = 40
NEUTRON_VERSION = n_version.version_info.release_string()
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
# Allowed network types for the NSX Plugin

View File

@ -25,7 +25,6 @@ from sqlalchemy import exc as sql_exc
import webob.exc
from six import moves
from six import string_types
from neutron.db import agents_db
from neutron.db import agentschedulers_db
@ -88,6 +87,7 @@ from vmware_nsx.extensions import advancedserviceproviders as as_providers
from vmware_nsx.extensions import maclearning as mac_ext
from vmware_nsx.extensions import providersecuritygroup as provider_sg
from vmware_nsx.plugins.common import plugin
from vmware_nsx.plugins.common_v3 import utils as common_utils
from vmware_nsx.services.qos.common import utils as qos_com_utils
from vmware_nsx.services.vpnaas.common_v3 import ipsec_utils
@ -1477,47 +1477,6 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
LOG.warning(err_msg)
raise n_exc.InvalidInput(error_message=err_msg)
def _get_network_dns_domain(self, az, network):
dns_domain = None
if network.get('dns_domain'):
net_dns = network['dns_domain']
if isinstance(net_dns, string_types):
dns_domain = net_dns
elif hasattr(net_dns, "dns_domain"):
dns_domain = net_dns.dns_domain
if not dns_domain or not validators.is_attr_set(dns_domain):
dns_domain = az.dns_domain
return dns_domain
def _build_dhcp_server_config(self, context, network, subnet, port, az):
name = self.nsxlib.native_dhcp.build_server_name(
network['name'], network['id'])
net_tags = self.nsxlib.build_v3_tags_payload(
network, resource_type='os-neutron-net-id',
project_name=context.tenant_name)
dns_domain = self._get_network_dns_domain(az, network)
dns_nameservers = subnet['dns_nameservers']
if not dns_nameservers or not validators.is_attr_set(dns_nameservers):
dns_nameservers = az.nameservers
# There must be exactly one fixed ip matching given subnet
fixed_ip_addr = [fip['ip_address'] for fip in port['fixed_ips']
if fip['subnet_id'] == subnet['id']]
return self.nsxlib.native_dhcp.build_server(
name,
ip_address=fixed_ip_addr[0],
cidr=subnet['cidr'],
gateway_ip=subnet['gateway_ip'],
host_routes=subnet['host_routes'],
dns_domain=dns_domain,
dns_nameservers=dns_nameservers,
dhcp_profile_id=az._native_dhcp_profile_uuid,
tags=net_tags)
def _enable_native_dhcp(self, context, network, subnet, az=None):
# Enable native DHCP service on the backend for this network.
# First create a Neutron DHCP port and use its assigned IP
@ -1569,8 +1528,9 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
self._process_portbindings_create_and_update(
context, port_data, neutron_port)
server_data = self._build_dhcp_server_config(
context, network, subnet, neutron_port, az)
server_data = common_utils.build_dhcp_server_config(
self.nsxlib, context.tenant_name, network, subnet,
neutron_port, az)
port_tags = self.nsxlib.build_v3_tags_payload(
neutron_port, resource_type='os-neutron-dport-id',
project_name=context.tenant_name)

View File

@ -0,0 +1,244 @@
# Copyright 2020 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 os
import random
import re
from six import string_types
from oslo_config import cfg
from oslo_context import context as context_utils
from oslo_log import log as logging
from oslo_utils import fileutils
from neutron import version as n_version
from neutron_lib.api import validators
from neutron_lib import context as q_context
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.plugins.nsx_v3 import cert_utils
from vmware_nsxlib import v3
from vmware_nsxlib.v3 import client_cert
from vmware_nsxlib.v3 import config
from vmware_nsxlib.v3 import policy
LOG = logging.getLogger(__name__)
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
class DbCertProvider(client_cert.ClientCertProvider):
"""Write cert data from DB to file and delete after use
New provider object with random filename is created for each request.
This is not most efficient, but the safest way to avoid race conditions,
since backend connections can occur both before and after neutron
fork, and several concurrent requests can occupy the same thread.
Note that new cert filename for each request does not result in new
connection for each request (at least for now..)
"""
EXPIRATION_ALERT_DAYS = 30 # days prior to expiration
def __init__(self):
super(DbCertProvider, self).__init__(None)
random.seed()
self._filename = '/tmp/.' + str(random.randint(1, 10000000))
def _check_expiration(self, expires_in_days):
if expires_in_days > self.EXPIRATION_ALERT_DAYS:
return
if expires_in_days < 0:
LOG.error("Client certificate has expired %d days ago.",
expires_in_days * -1)
else:
LOG.warning("Client certificate expires in %d days. "
"Once expired, service will become unavailable.",
expires_in_days)
def __enter__(self):
try:
context = q_context.get_admin_context()
db_storage_driver = cert_utils.DbCertificateStorageDriver(
context)
with client_cert.ClientCertificateManager(
cert_utils.NSX_OPENSTACK_IDENTITY,
None,
db_storage_driver) as cert_manager:
if not cert_manager.exists():
msg = _("Unable to load from nsx-db")
raise nsx_exc.ClientCertificateException(err_msg=msg)
filename = self._filename
if not os.path.exists(os.path.dirname(filename)):
if len(os.path.dirname(filename)) > 0:
fileutils.ensure_tree(os.path.dirname(filename))
cert_manager.export_pem(filename)
expires_in_days = cert_manager.expires_in_days()
self._check_expiration(expires_in_days)
except Exception as e:
self._on_exit()
raise e
return self
def _on_exit(self):
if os.path.isfile(self._filename):
os.remove(self._filename)
self._filename = None
def __exit__(self, type, value, traceback):
self._on_exit()
def filename(self):
return self._filename
def get_client_cert_provider(conf_path=cfg.CONF.nsx_v3):
if not conf_path.nsx_use_client_auth:
return None
if conf_path.nsx_client_cert_storage.lower() == 'none':
# Admin is responsible for providing cert file, the plugin
# should not touch it
return client_cert.ClientCertProvider(
conf_path.nsx_client_cert_file)
if conf_path.nsx_client_cert_storage.lower() == 'nsx-db':
# Cert data is stored in DB, and written to file system only
# when new connection is opened, and deleted immediately after.
return DbCertProvider
def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False,
plugin_conf=None, allow_overwrite_header=False):
client_cert_provider = None
if not basic_auth:
# if basic auth requested, dont use cert file even if provided
client_cert_provider = get_client_cert_provider()
if not plugin_conf:
plugin_conf = cfg.CONF.nsx_v3
nsxlib_config = config.NsxLibConfig(
username=nsx_username or plugin_conf.nsx_api_user,
password=nsx_password or plugin_conf.nsx_api_password,
client_cert_provider=client_cert_provider,
retries=plugin_conf.http_retries,
insecure=plugin_conf.insecure,
ca_file=plugin_conf.ca_file,
concurrent_connections=plugin_conf.concurrent_connections,
http_timeout=plugin_conf.http_timeout,
http_read_timeout=plugin_conf.http_read_timeout,
conn_idle_timeout=plugin_conf.conn_idle_timeout,
http_provider=None,
max_attempts=plugin_conf.retries,
nsx_api_managers=plugin_conf.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,
allow_overwrite_header=allow_overwrite_header)
return v3.NsxLib(nsxlib_config)
def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None,
basic_auth=False):
client_cert_provider = None
if not basic_auth:
# if basic auth requested, dont use cert file even if provided
client_cert_provider = get_client_cert_provider(
conf_path=cfg.CONF.nsx_p)
nsxlib_config = config.NsxLibConfig(
username=nsx_username or cfg.CONF.nsx_p.nsx_api_user,
password=nsx_password or cfg.CONF.nsx_p.nsx_api_password,
client_cert_provider=client_cert_provider,
retries=cfg.CONF.nsx_p.http_retries,
insecure=cfg.CONF.nsx_p.insecure,
ca_file=cfg.CONF.nsx_p.ca_file,
concurrent_connections=cfg.CONF.nsx_p.concurrent_connections,
http_timeout=cfg.CONF.nsx_p.http_timeout,
http_read_timeout=cfg.CONF.nsx_p.http_read_timeout,
conn_idle_timeout=cfg.CONF.nsx_p.conn_idle_timeout,
http_provider=None,
max_attempts=cfg.CONF.nsx_p.retries,
nsx_api_managers=cfg.CONF.nsx_p.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_p.nameservers,
dns_domain=cfg.CONF.nsx_p.dns_domain,
allow_passthrough=cfg.CONF.nsx_p.allow_passthrough,
realization_max_attempts=cfg.CONF.nsx_p.realization_max_attempts,
realization_wait_sec=cfg.CONF.nsx_p.realization_wait_sec)
return policy.NsxPolicyLib(nsxlib_config)
def inject_headers():
ctx = context_utils.get_current()
if ctx:
ctx_dict = ctx.to_dict()
# Remove unsupported characters from the user-id
user_id = ctx_dict.get('user_identity')
re.sub('[^A-Za-z0-9]+', '', user_id)
return {'X-NSX-EUSER': user_id,
'X-NSX-EREQID': ctx_dict.get('request_id')}
return {}
def get_network_dns_domain(az, network):
dns_domain = None
if network.get('dns_domain'):
net_dns = network['dns_domain']
if isinstance(net_dns, string_types):
dns_domain = net_dns
elif hasattr(net_dns, "dns_domain"):
dns_domain = net_dns.dns_domain
if not dns_domain or not validators.is_attr_set(dns_domain):
dns_domain = az.dns_domain
return dns_domain
def build_dhcp_server_config(nsxlib, project_name, network, subnet, port, az):
name = nsxlib.native_dhcp.build_server_name(
network['name'], network['id'])
net_tags = nsxlib.build_v3_tags_payload(
network, resource_type='os-neutron-net-id',
project_name=project_name)
dns_domain = get_network_dns_domain(az, network)
dns_nameservers = subnet['dns_nameservers']
if not dns_nameservers or not validators.is_attr_set(dns_nameservers):
dns_nameservers = az.nameservers
# There must be exactly one fixed ip matching given subnet
fixed_ip_addr = [fip['ip_address'] for fip in port['fixed_ips']
if fip['subnet_id'] == subnet['id']]
return nsxlib.native_dhcp.build_server(
name,
ip_address=fixed_ip_addr[0],
cidr=subnet['cidr'],
gateway_ip=subnet['gateway_ip'],
host_routes=subnet['host_routes'],
dns_domain=dns_domain,
dns_nameservers=dns_nameservers,
dhcp_profile_id=az._native_dhcp_profile_uuid,
tags=net_tags)

View File

@ -75,8 +75,8 @@ from vmware_nsx.extensions import providersecuritygroup as provider_sg
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as sg_prefix
from vmware_nsx.extensions import securitygrouplogging as sg_logging
from vmware_nsx.plugins.common_v3 import plugin as nsx_plugin_common
from vmware_nsx.plugins.common_v3 import utils as v3_utils
from vmware_nsx.plugins.nsx_p import availability_zones as nsxp_az
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.services.fwaas.common import utils as fwaas_utils
from vmware_nsx.services.fwaas.nsx_p import fwaas_callbacks_v2
from vmware_nsx.services.lbaas import lb_const
@ -1145,7 +1145,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
if is_ipv6:
network = self._get_network(context, net_id)
kwargs['domain_names'] = [
self._get_network_dns_domain(net_az, network)]
v3_utils.get_network_dns_domain(net_az, network)]
dhcp_config = policy_defs.SegmentDhcpConfigV6(**kwargs)
else:
dhcp_config = policy_defs.SegmentDhcpConfigV4(**kwargs)

View File

@ -87,6 +87,7 @@ from vmware_nsx.extensions import secgroup_rule_local_ip_prefix
from vmware_nsx.extensions import securitygrouplogging as sg_logging
from vmware_nsx.plugins.common.housekeeper import housekeeper
from vmware_nsx.plugins.common_v3 import plugin as nsx_plugin_common
from vmware_nsx.plugins.common_v3 import utils as common_utils
from vmware_nsx.plugins.nsx import utils as tvd_utils
from vmware_nsx.plugins.nsx_v3 import availability_zones as nsx_az
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
@ -195,8 +196,8 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
self.supported_extension_aliases.extend(
self._extension_manager.extension_aliases())
self.nsxlib = v3_utils.get_nsxlib_wrapper()
nsxlib_utils.set_inject_headers_callback(v3_utils.inject_headers)
self.nsxlib = common_utils.get_nsxlib_wrapper()
nsxlib_utils.set_inject_headers_callback(common_utils.inject_headers)
registry.subscribe(
self.on_subnetpool_address_scope_updated,
@ -1142,8 +1143,8 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
dhcp_name = self.nsxlib.native_dhcp.build_server_name(
network['name'], network['id'])
az = self.get_network_az_by_net_id(context, network['id'])
domain_name = self.nsxlib.native_dhcp.build_server_domain_name(
network.get('dns_domain'), az.dns_domain)
domain_name = common_utils.get_network_dns_domain(
az, network)
try:
# There should be only 1 dhcp server
# Update its name and domain

View File

@ -12,37 +12,20 @@
# 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 os
import random
import re
from oslo_config import cfg
from oslo_context import context as context_utils
from oslo_log import log as logging
from oslo_utils import fileutils
from sqlalchemy.orm import exc
from neutron.db.models import securitygroup
from neutron import version as n_version
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
from neutron_lib import constants as const
from neutron_lib import context as q_context
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.db import db as nsx_db
from vmware_nsx.db import nsx_models
from vmware_nsx.plugins.nsx_v3 import cert_utils
from vmware_nsx.services.qos.common import utils as qos_utils
from vmware_nsxlib import v3
from vmware_nsxlib.v3 import client_cert
from vmware_nsxlib.v3 import config
from vmware_nsxlib.v3 import core_resources
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsxlib.v3 import nsx_constants
from vmware_nsxlib.v3 import policy
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
NSX_V3_PSEC_PROFILE_NAME = 'neutron_port_spoof_guard_profile'
NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile'
@ -57,155 +40,6 @@ NSX_V3_OS_DFW_UUID = '00000000-def0-0000-0fed-000000000000'
LOG = logging.getLogger(__name__)
class DbCertProvider(client_cert.ClientCertProvider):
"""Write cert data from DB to file and delete after use
New provider object with random filename is created for each request.
This is not most efficient, but the safest way to avoid race conditions,
since backend connections can occur both before and after neutron
fork, and several concurrent requests can occupy the same thread.
Note that new cert filename for each request does not result in new
connection for each request (at least for now..)
"""
EXPIRATION_ALERT_DAYS = 30 # days prior to expiration
def __init__(self):
super(DbCertProvider, self).__init__(None)
random.seed()
self._filename = '/tmp/.' + str(random.randint(1, 10000000))
def _check_expiration(self, expires_in_days):
if expires_in_days > self.EXPIRATION_ALERT_DAYS:
return
if expires_in_days < 0:
LOG.error("Client certificate has expired %d days ago.",
expires_in_days * -1)
else:
LOG.warning("Client certificate expires in %d days. "
"Once expired, service will become unavailable.",
expires_in_days)
def __enter__(self):
try:
context = q_context.get_admin_context()
db_storage_driver = cert_utils.DbCertificateStorageDriver(
context)
with client_cert.ClientCertificateManager(
cert_utils.NSX_OPENSTACK_IDENTITY,
None,
db_storage_driver) as cert_manager:
if not cert_manager.exists():
msg = _("Unable to load from nsx-db")
raise nsx_exc.ClientCertificateException(err_msg=msg)
filename = self._filename
if not os.path.exists(os.path.dirname(filename)):
if len(os.path.dirname(filename)) > 0:
fileutils.ensure_tree(os.path.dirname(filename))
cert_manager.export_pem(filename)
expires_in_days = cert_manager.expires_in_days()
self._check_expiration(expires_in_days)
except Exception as e:
self._on_exit()
raise e
return self
def _on_exit(self):
if os.path.isfile(self._filename):
os.remove(self._filename)
self._filename = None
def __exit__(self, type, value, traceback):
self._on_exit()
def filename(self):
return self._filename
def get_client_cert_provider(conf_path=cfg.CONF.nsx_v3):
if not conf_path.nsx_use_client_auth:
return None
if conf_path.nsx_client_cert_storage.lower() == 'none':
# Admin is responsible for providing cert file, the plugin
# should not touch it
return client_cert.ClientCertProvider(
conf_path.nsx_client_cert_file)
if conf_path.nsx_client_cert_storage.lower() == 'nsx-db':
# Cert data is stored in DB, and written to file system only
# when new connection is opened, and deleted immediately after.
return DbCertProvider
def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False,
plugin_conf=None, allow_overwrite_header=False):
client_cert_provider = None
if not basic_auth:
# if basic auth requested, dont use cert file even if provided
client_cert_provider = get_client_cert_provider()
if not plugin_conf:
plugin_conf = cfg.CONF.nsx_v3
nsxlib_config = config.NsxLibConfig(
username=nsx_username or plugin_conf.nsx_api_user,
password=nsx_password or plugin_conf.nsx_api_password,
client_cert_provider=client_cert_provider,
retries=plugin_conf.http_retries,
insecure=plugin_conf.insecure,
ca_file=plugin_conf.ca_file,
concurrent_connections=plugin_conf.concurrent_connections,
http_timeout=plugin_conf.http_timeout,
http_read_timeout=plugin_conf.http_read_timeout,
conn_idle_timeout=plugin_conf.conn_idle_timeout,
http_provider=None,
max_attempts=plugin_conf.retries,
nsx_api_managers=plugin_conf.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,
allow_overwrite_header=allow_overwrite_header)
return v3.NsxLib(nsxlib_config)
def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None,
basic_auth=False):
#TODO(asarfaty) move to a different file? (under common_v3)
client_cert_provider = None
if not basic_auth:
# if basic auth requested, dont use cert file even if provided
client_cert_provider = get_client_cert_provider(
conf_path=cfg.CONF.nsx_p)
nsxlib_config = config.NsxLibConfig(
username=nsx_username or cfg.CONF.nsx_p.nsx_api_user,
password=nsx_password or cfg.CONF.nsx_p.nsx_api_password,
client_cert_provider=client_cert_provider,
retries=cfg.CONF.nsx_p.http_retries,
insecure=cfg.CONF.nsx_p.insecure,
ca_file=cfg.CONF.nsx_p.ca_file,
concurrent_connections=cfg.CONF.nsx_p.concurrent_connections,
http_timeout=cfg.CONF.nsx_p.http_timeout,
http_read_timeout=cfg.CONF.nsx_p.http_read_timeout,
conn_idle_timeout=cfg.CONF.nsx_p.conn_idle_timeout,
http_provider=None,
max_attempts=cfg.CONF.nsx_p.retries,
nsx_api_managers=cfg.CONF.nsx_p.nsx_api_managers,
plugin_scope=OS_NEUTRON_ID_SCOPE,
plugin_tag=NSX_NEUTRON_PLUGIN,
plugin_ver=n_version.version_info.release_string(),
allow_passthrough=cfg.CONF.nsx_p.allow_passthrough,
realization_max_attempts=cfg.CONF.nsx_p.realization_max_attempts,
realization_wait_sec=cfg.CONF.nsx_p.realization_wait_sec)
return policy.NsxPolicyLib(nsxlib_config)
def get_orphaned_dhcp_servers(context, plugin, nsxlib, dhcp_profile_uuid=None):
# An orphaned DHCP server means the associated neutron network
# does not exist or has no DHCP-enabled subnet.
@ -532,15 +366,3 @@ def get_mismatch_logical_ports(context, nsxlib, plugin, get_filters=None):
'error': 'Different MAC address bindings',
'error_type': PORT_ERROR_TYPE_BINDINGS})
return problems
def inject_headers():
ctx = context_utils.get_current()
if ctx:
ctx_dict = ctx.to_dict()
# Remove unsupported characters from the user-id
user_id = ctx_dict.get('user_identity')
re.sub('[^A-Za-z0-9]+', '', user_id)
return {'X-NSX-EUSER': user_id,
'X-NSX-EREQID': ctx_dict.get('request_id')}
return {}

View File

@ -21,8 +21,8 @@ from neutron_lib.plugins import directory
from oslo_log import log as logging
from vmware_nsx.common import config
from vmware_nsx.plugins.common_v3 import utils as v3_utils
from vmware_nsx.plugins.nsx_p import plugin
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.shell.admin.plugins.common import formatters
LOG = logging.getLogger(__name__)

View File

@ -11,11 +11,7 @@
# 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 netaddr
from neutron_lib.callbacks import registry
from neutron_lib import constants as const
from neutron_lib import context as neutron_context
from neutron_lib import exceptions
from oslo_config import cfg
@ -27,7 +23,6 @@ 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.nsxv3.resources import utils
import vmware_nsx.shell.resources as shell
from vmware_nsxlib.v3 import nsx_constants
LOG = logging.getLogger(__name__)
neutron_client = utils.NeutronDbClient()
@ -43,108 +38,6 @@ def list_dhcp_bindings(resource, event, trigger, **kwargs):
['id', 'mac_address', 'fixed_ips']))
@admin_utils.output_header
def nsx_update_dhcp_bindings(resource, event, trigger, **kwargs):
"""Resync DHCP bindings for NSXv3 CrossHairs."""
nsxlib = utils.get_connected_nsxlib()
nsx_version = nsxlib.get_version()
if not nsx_utils.is_nsx_version_1_1_0(nsx_version):
LOG.error("This utility is not available for NSX version %s",
nsx_version)
return
dhcp_profile_uuid = None
# TODO(asarfaty) Add availability zones support here
if kwargs.get('property'):
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
dhcp_profile_uuid = properties.get('dhcp_profile_uuid')
if not dhcp_profile_uuid:
LOG.error("dhcp_profile_uuid is not defined")
return
cfg.CONF.set_override('dhcp_agent_notification', False)
cfg.CONF.set_override('native_dhcp_metadata', True, 'nsx_v3')
cfg.CONF.set_override('dhcp_profile', dhcp_profile_uuid, 'nsx_v3')
port_bindings = {} # lswitch_id: [(port_id, mac, ip), ...]
server_bindings = {} # lswitch_id: dhcp_server_id
ports = neutron_client.get_ports()
for port in ports:
device_owner = port['device_owner']
if (device_owner != const.DEVICE_OWNER_DHCP and
not nsx_utils.is_port_dhcp_configurable(port)):
continue
for fixed_ip in port['fixed_ips']:
if netaddr.IPNetwork(fixed_ip['ip_address']).version == 6:
continue
network_id = port['network_id']
subnet = neutron_client.get_subnet(None, fixed_ip['subnet_id'])
if device_owner == const.DEVICE_OWNER_DHCP:
# For each DHCP-enabled network, create a logical DHCP server
# and update the attachment type to DHCP on the corresponding
# logical port of the Neutron DHCP port.
network = neutron_client.get_network(None, port['network_id'])
net_tags = nsxlib.build_v3_tags_payload(
network, resource_type='os-neutron-net-id',
project_name='admin')
# TODO(asarfaty): add default_dns_nameservers & dns_domain
# from availability zone
server_data = nsxlib.native_dhcp.build_server_config(
network, subnet, port, net_tags)
server_data['dhcp_profile_id'] = dhcp_profile_uuid
dhcp_server = nsxlib.dhcp_server.create(**server_data)
LOG.info("Created logical DHCP server %(server)s for "
"network %(network)s",
{'server': dhcp_server['id'],
'network': port['network_id']})
# Add DHCP service binding in neutron DB.
neutron_client.add_dhcp_service_binding(
network['id'], port['id'], dhcp_server['id'])
# Update logical port for DHCP purpose.
lswitch_id, lport_id = (
neutron_client.get_lswitch_and_lport_id(port['id']))
nsxlib.logical_port.update(
lport_id, dhcp_server['id'],
attachment_type=nsx_constants.ATTACHMENT_DHCP)
server_bindings[lswitch_id] = dhcp_server['id']
LOG.info("Updated DHCP logical port %(port)s for "
"network %(network)s",
{'port': lport_id, 'network': port['network_id']})
elif subnet['enable_dhcp']:
# Store (mac, ip) binding of each compute port in a
# DHCP-enabled subnet.
lswitch_id = neutron_client.net_id_to_lswitch_id(network_id)
bindings = port_bindings.get(lswitch_id, [])
bindings.append((port['id'], port['mac_address'],
fixed_ip['ip_address'],
fixed_ip['subnet_id']))
port_bindings[lswitch_id] = bindings
break # process only the first IPv4 address
# Populate mac/IP bindings in each logical DHCP server.
for lswitch_id, bindings in port_bindings.items():
dhcp_server_id = server_bindings.get(lswitch_id)
if not dhcp_server_id:
continue
for (port_id, mac, ip, subnet_id) in bindings:
hostname = 'host-%s' % ip.replace('.', '-')
options = {'option121': {'static_routes': [
{'network': '%s' % cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip}]}}
subnet = neutron_client.get_subnet(None, subnet_id)
binding = nsxlib.dhcp_server.create_binding(
dhcp_server_id, mac, ip, hostname,
cfg.CONF.nsx_v3.dhcp_lease_time, options,
subnet.get('gateway_ip'))
# Add DHCP static binding in neutron DB.
neutron_client.add_dhcp_static_binding(
port_id, subnet_id, ip, dhcp_server_id, binding['id'])
LOG.info("Added DHCP binding (mac: %(mac)s, ip: %(ip)s) "
"for neutron port %(port)s",
{'mac': mac, 'ip': ip, 'port': port_id})
@admin_utils.output_header
def nsx_recreate_dhcp_server(resource, event, trigger, **kwargs):
"""Recreate DHCP server & binding for a neutron network"""
@ -197,9 +90,6 @@ def nsx_recreate_dhcp_server(resource, event, trigger, **kwargs):
registry.subscribe(list_dhcp_bindings,
constants.DHCP_BINDING,
shell.Operations.LIST.value)
registry.subscribe(nsx_update_dhcp_bindings,
constants.DHCP_BINDING,
shell.Operations.NSX_UPDATE.value)
registry.subscribe(nsx_recreate_dhcp_server,
constants.DHCP_BINDING,
shell.Operations.NSX_RECREATE.value)

View File

@ -17,7 +17,6 @@ import re
import netaddr
from neutron_lib.callbacks import registry
from neutron_lib import constants as const
from oslo_config import cfg
from oslo_log import log as logging
@ -31,7 +30,6 @@ from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils
import vmware_nsx.shell.resources as shell
from vmware_nsxlib.v3 import exceptions as nsx_exc
from vmware_nsxlib.v3 import nsx_constants
LOG = logging.getLogger(__name__)
neutron_client = utils.NeutronDbClient()
@ -77,81 +75,6 @@ def list_metadata_networks(resource, event, trigger, **kwargs):
status.get('proxy_status', 'Unknown'))
@admin_utils.output_header
def nsx_update_metadata_proxy(resource, event, trigger, **kwargs):
"""Update Metadata proxy for NSXv3 CrossHairs."""
nsxlib = utils.get_connected_nsxlib()
nsx_version = nsxlib.get_version()
if not nsx_utils.is_nsx_version_1_1_0(nsx_version):
LOG.error("This utility is not available for NSX version %s",
nsx_version)
return
metadata_proxy_uuid = None
if kwargs.get('property'):
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
metadata_proxy_uuid = properties.get('metadata_proxy_uuid')
if not metadata_proxy_uuid:
LOG.error("metadata_proxy_uuid is not defined")
return
cfg.CONF.set_override('dhcp_agent_notification', False)
cfg.CONF.set_override('native_dhcp_metadata', True, 'nsx_v3')
cfg.CONF.set_override('metadata_proxy', metadata_proxy_uuid, 'nsx_v3')
with utils.NsxV3PluginWrapper() as plugin:
# For each Neutron network, check if it is an internal metadata
# network.
# If yes, delete the network and associated router interface.
# Otherwise, create a logical switch port with MD-Proxy attachment.
for network in neutron_client.get_networks():
if _is_metadata_network(network):
# It is a metadata network, find the attached router,
# remove the router interface and the network.
filters = {'device_owner': const.ROUTER_INTERFACE_OWNERS,
'fixed_ips': {
'subnet_id': [network['subnets'][0]],
'ip_address': [nsx_rpc.METADATA_GATEWAY_IP]}}
ports = neutron_client.get_ports(filters=filters)
if not ports:
continue
router_id = ports[0]['device_id']
interface = {'subnet_id': network['subnets'][0]}
plugin.remove_router_interface(None, router_id, interface)
LOG.info("Removed metadata interface on router %s", router_id)
plugin.delete_network(None, network['id'])
LOG.info("Removed metadata network %s", network['id'])
else:
lswitch_id = neutron_client.net_id_to_lswitch_id(
network['id'])
if not lswitch_id:
continue
tags = nsxlib.build_v3_tags_payload(
network, resource_type='os-neutron-net-id',
project_name='admin')
name = plugin._get_mdproxy_port_name(network['name'],
network['id'])
# check if this logical port already exists
existing_ports = nsxlib.logical_port.find_by_display_name(
name)
if not existing_ports:
# create a new port with the md-proxy
nsxlib.logical_port.create(
lswitch_id, metadata_proxy_uuid, tags=tags, name=name,
attachment_type=nsx_constants.ATTACHMENT_MDPROXY)
LOG.info("Enabled native metadata proxy for network %s",
network['id'])
else:
# update the MDproxy of this port
port = existing_ports[0]
nsxlib.logical_port.update(
port['id'], metadata_proxy_uuid,
attachment_type=nsx_constants.ATTACHMENT_MDPROXY)
LOG.info("Updated native metadata proxy for network %s",
network['id'])
@admin_utils.output_header
def nsx_update_metadata_proxy_server_ip(resource, event, trigger, **kwargs):
"""Update Metadata proxy server ip on the nsx."""
@ -207,9 +130,6 @@ def nsx_update_metadata_proxy_server_ip(resource, event, trigger, **kwargs):
registry.subscribe(list_metadata_networks,
constants.METADATA_PROXY,
shell.Operations.LIST.value)
registry.subscribe(nsx_update_metadata_proxy,
constants.METADATA_PROXY,
shell.Operations.NSX_UPDATE.value)
registry.subscribe(nsx_update_metadata_proxy_server_ip,
constants.METADATA_PROXY,
shell.Operations.NSX_UPDATE_IP.value)

View File

@ -33,7 +33,6 @@ from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils as v3_utils
from vmware_nsx.shell import resources as shell
from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
from vmware_nsxlib.v3 import nsx_constants as consts
from vmware_nsxlib.v3 import security
LOG = logging.getLogger(__name__)
@ -253,54 +252,6 @@ def fix_security_groups(resource, event, trigger, **kwargs):
plugin.save_security_group_rule_mappings(context_, rules['rules'])
def _update_ports_dynamic_criteria_tags():
nsxlib = v3_utils.get_connected_nsxlib()
for port in neutron_db.get_ports():
secgroups = neutron_sg.get_port_security_groups(port['id'])
# Nothing to do with ports that are not associated with any sec-group.
if not secgroups:
continue
_, lport_id = neutron_db.get_lswitch_and_lport_id(port['id'])
criteria_tags = nsxlib.ns_group.get_lport_tags(secgroups)
nsxlib.logical_port.update(
lport_id, False, tags_update=criteria_tags)
def _update_security_group_dynamic_criteria():
nsxlib = v3_utils.get_connected_nsxlib()
secgroups = neutron_sg.get_security_groups()
for sg in secgroups:
nsgroup_id = neutron_sg.get_nsgroup_id(sg['id'])
membership_criteria = nsxlib.ns_group.get_port_tag_expression(
security.PORT_SG_SCOPE, sg['id'])
try:
# We want to add the dynamic criteria and remove all direct members
# they will be added by the manager using the new criteria.
nsxlib.ns_group.update(nsgroup_id,
membership_criteria=membership_criteria,
members=[])
except Exception as e:
LOG.warning("Failed to update membership criteria for nsgroup "
"%(nsgroup_id)s, request to backend returned "
"with error: %(error)s",
{'nsgroup_id': nsgroup_id, 'error': str(e)})
@admin_utils.output_header
def migrate_nsgroups_to_dynamic_criteria(resource, event, trigger, **kwargs):
"""Update NSX security groups dynamic criteria for NSXv3 CrossHairs"""
nsxlib = v3_utils.get_connected_nsxlib()
if not nsxlib.feature_supported(consts.FEATURE_DYNAMIC_CRITERIA):
LOG.error("Dynamic criteria grouping feature isn't supported by "
"this NSX version.")
return
# First, we add the criteria tags for all ports.
_update_ports_dynamic_criteria_tags()
# Update security-groups with dynamic criteria and remove direct members.
_update_security_group_dynamic_criteria()
def list_orphaned_sections(resource, event, trigger, **kwargs):
"""List orphaned firewall sections"""
nsxlib = v3_utils.get_connected_nsxlib()
@ -473,10 +424,6 @@ registry.subscribe(update_security_groups_logging,
constants.SECURITY_GROUPS,
shell.Operations.UPDATE_LOGGING.value)
registry.subscribe(migrate_nsgroups_to_dynamic_criteria,
constants.FIREWALL_NSX_GROUPS,
shell.Operations.MIGRATE_TO_DYNAMIC_CRITERIA.value)
registry.subscribe(fix_security_groups,
constants.FIREWALL_SECTIONS,
shell.Operations.NSX_UPDATE.value)

View File

@ -25,8 +25,8 @@ from neutron_lib.plugins import directory
from vmware_nsx.common import config
from vmware_nsx.db import db as nsx_db
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.plugins.common_v3 import utils as v3_utils
from vmware_nsx.plugins.nsx_v3 import plugin
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.services.fwaas.nsx_v3 import fwaas_callbacks_v2
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
from vmware_nsxlib.v3 import nsx_constants

View File

@ -59,7 +59,6 @@ class Operations(enum.Enum):
NSX_REDISTRIBURE = 'nsx-redistribute'
NSX_REORDER = 'nsx-reorder'
NSX_TAG_DEFAULT = 'nsx-tag-default'
MIGRATE_TO_DYNAMIC_CRITERIA = 'migrate-to-dynamic-criteria'
NSX_MIGRATE_V_V3 = 'nsx-migrate-v-v3'
MIGRATE_TO_POLICY = 'migrate-to-policy'
LIST_POLICIES = 'list-policies'
@ -98,8 +97,7 @@ nsxv3_resources = {
constants.FIREWALL_NSX_GROUPS: Resource(
constants.FIREWALL_NSX_GROUPS, [
Operations.LIST.value,
Operations.LIST_MISMATCHES.value,
Operations.MIGRATE_TO_DYNAMIC_CRITERIA.value]),
Operations.LIST_MISMATCHES.value]),
constants.ORPHANED_FIREWALL_SECTIONS: Resource(
constants.ORPHANED_FIREWALL_SECTIONS, [
Operations.NSX_LIST.value,
@ -120,11 +118,9 @@ nsxv3_resources = {
Operations.UPDATE_TIER0.value]),
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
[Operations.LIST.value,
Operations.NSX_UPDATE.value,
Operations.NSX_RECREATE.value]),
constants.METADATA_PROXY: Resource(constants.METADATA_PROXY,
[Operations.LIST.value,
Operations.NSX_UPDATE.value,
Operations.NSX_UPDATE_IP.value]),
constants.ORPHANED_DHCP_SERVERS: Resource(constants.ORPHANED_DHCP_SERVERS,
[Operations.NSX_LIST.value,

View File

@ -21,8 +21,8 @@ from oslo_config import cfg
from neutron.tests.unit import testlib_api
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.plugins.common_v3 import utils
from vmware_nsx.plugins.nsx_v3 import cert_utils
from vmware_nsx.plugins.nsx_v3 import utils
class NsxV3ClientCertProviderTestCase(testlib_api.SqlTestCase):

View File

@ -24,7 +24,7 @@ from neutron.services.qos import qos_plugin
from neutron.tests.unit.services.qos import base
from vmware_nsx.common import utils
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.plugins.common_v3 import utils as v3_utils
from vmware_nsx.services.qos.nsx_v3 import driver as qos_driver
from vmware_nsx.services.qos.nsx_v3 import pol_utils as qos_utils
from vmware_nsx.tests.unit.nsx_p import test_plugin

View File

@ -25,7 +25,7 @@ from neutron.services.qos import qos_plugin
from neutron.tests.unit.services.qos import base
from vmware_nsx.db import db as nsx_db
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.plugins.common_v3 import utils as v3_utils
from vmware_nsx.services.qos.nsx_v3 import driver as qos_driver
from vmware_nsx.services.qos.nsx_v3 import utils as qos_utils
from vmware_nsx.tests.unit.nsx_v3 import test_plugin