NSXv: Add metadata configuration to the availability zones

The next global configurations are now added also per AZ:
- mgt_net_moid
- mgt_net_proxy_ips
- mgt_net_proxy_netmask
- mgt_net_default_gateway
- external_network
- vdn_scope_id
- dvs_id

In case any of them is not defined in the AZ section, the global value will be used.

Change-Id: I5fca433fb86163cee84e3b9fc54182017a5f266b
This commit is contained in:
Adit Sarfaty 2017-02-01 10:38:47 +02:00
parent e8889cf17f
commit 2808ededb7
19 changed files with 690 additions and 295 deletions

View File

@ -686,6 +686,27 @@ nsxv_az_opts = [
help=_("(Optional) Defines edge pool's management range for "
"the availability zone. If not defined, the global one "
"will be used")),
cfg.StrOpt('mgt_net_moid',
help=_('(Optional) Portgroup MoRef ID for metadata proxy '
'management network')),
cfg.ListOpt('mgt_net_proxy_ips',
default=[],
help=_('(Optional) Comma separated list of management network '
'IP addresses for metadata proxy.')),
cfg.StrOpt('mgt_net_proxy_netmask',
help=_("(Optional) Management network netmask for metadata "
"proxy.")),
cfg.StrOpt('mgt_net_default_gateway',
help=_("(Optional) Management network default gateway for "
"metadata proxy.")),
cfg.StrOpt('external_network',
help=_('(Optional) Network ID for physical network '
'connectivity')),
cfg.StrOpt('vdn_scope_id',
help=_('(Optional) Network scope ID for VXLAN virtual wires')),
cfg.StrOpt('dvs_id',
help=_('(Optional) DVS MoRef ID for DVS connected to '
'Management / Edge cluster')),
]
# Register the configuration options

View File

@ -1 +1 @@
5c8f451290b7
14a89ddf96e2

View File

@ -0,0 +1,43 @@
# Copyright 2017 VMware, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""NSX Adds a 'availability_zone' attribute to internal-networks table
Revision ID: 14a89ddf96e2
Revises: 5c8f451290b7
Create Date: 2017-02-05 14:34:21.163418
"""
# revision identifiers, used by Alembic.
revision = '14a89ddf96e2'
down_revision = '5c8f451290b7'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.engine import reflection
def upgrade():
table_name = 'nsxv_internal_networks'
# Add the new column
op.add_column(table_name, sa.Column(
'availability_zone', sa.String(36), server_default='default'))
# replace the old primary key constraint with a new one for both
# purpose & az
inspector = reflection.Inspector.from_engine(op.get_bind())
pk_constraint = inspector.get_pk_constraint(table_name)
op.drop_constraint(pk_constraint.get('name'), table_name, type_='primary')
op.create_primary_key(None, table_name,
['network_purpose', 'availability_zone'])

View File

@ -131,6 +131,12 @@ def get_edge_availability_zone(session, edge_id):
return binding['availability_zone']
def get_router_availability_zone(session, router_id):
binding = get_nsxv_router_binding(session, router_id)
if binding:
return binding['availability_zone']
def clean_edge_router_binding(session, edge_id):
with session.begin(subtransactions=True):
(session.query(nsxv_models.NsxvRouterBinding).
@ -220,14 +226,16 @@ def allocate_edge_vnic(session, edge_id, network_id):
raise nsx_exc.NsxPluginException(err_msg=msg)
def allocate_edge_vnic_with_tunnel_index(session, edge_id, network_id):
def allocate_edge_vnic_with_tunnel_index(session, edge_id, network_id,
availability_zone):
"""Allocate an available edge vnic with tunnel index to network."""
# TODO(berlin): temporary solution to let metadata and dhcp use
# different vnics
net_list = get_nsxv_internal_network(
session, constants.InternalEdgePurposes.INTER_EDGE_PURPOSE)
metadata_net_id = net_list[0]['network_id'] if net_list else None
int_net = get_nsxv_internal_network(
session, constants.InternalEdgePurposes.INTER_EDGE_PURPOSE,
availability_zone)
metadata_net_id = int_net['network_id'] if int_net else None
with session.begin(subtransactions=True):
query = session.query(nsxv_models.NsxvEdgeVnicBinding)
@ -353,36 +361,44 @@ def clean_edge_dhcp_static_bindings_by_edge(session, edge_id):
edge_id=edge_id).delete()
def create_nsxv_internal_network(session, network_purpose, network_id):
def create_nsxv_internal_network(session, network_purpose,
availability_zone, network_id):
with session.begin(subtransactions=True):
try:
network = nsxv_models.NsxvInternalNetworks(
network_purpose=network_purpose,
network_id=network_id)
network_id=network_id,
availability_zone=availability_zone)
session.add(network)
except db_exc.DBDuplicateEntry:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Duplicate internal network for purpose %s"),
network_purpose)
LOG.exception(_LE("Duplicate internal network for purpose "
"%(p)s and availabiltiy zone %(az)s"),
{'p': network_purpose,
'az': availability_zone})
def get_nsxv_internal_network(session, network_purpose):
def get_nsxv_internal_network(session, network_purpose, availability_zone):
with session.begin(subtransactions=True):
net_list = (session.query(nsxv_models.NsxvInternalNetworks).
filter_by(network_purpose=network_purpose,
availability_zone=availability_zone).all())
if net_list:
# Should have only one results as purpose+az are the keys
return net_list[0]
def get_nsxv_internal_networks(session, network_purpose):
with session.begin(subtransactions=True):
return (session.query(nsxv_models.NsxvInternalNetworks).
filter_by(network_purpose=network_purpose).all())
def update_nsxv_internal_network(session, network_purpose, network_id):
with session.begin(subtransactions=True):
nets = get_nsxv_internal_network(session, network_purpose)
for net in nets:
net['network_id'] = network_id
def delete_nsxv_internal_network(session, network_purpose):
def delete_nsxv_internal_network(session, network_purpose, network_id):
with session.begin(subtransactions=True):
return (session.query(nsxv_models.NsxvInternalNetworks).
filter_by(network_purpose=network_purpose).delete())
filter_by(network_purpose=network_purpose,
network_id=network_id).delete())
def create_nsxv_internal_edge(session, ext_ip_address, purpose, router_id):

View File

@ -79,7 +79,6 @@ class NsxvEdgeDhcpStaticBinding(model_base.BASEV2, models.TimestampMixin):
class NsxvInternalNetworks(model_base.BASEV2, models.TimestampMixin):
"""Represents internal networks between NSXV plugin elements."""
__tablename__ = 'nsxv_internal_networks'
network_purpose = sa.Column(
@ -89,11 +88,12 @@ class NsxvInternalNetworks(model_base.BASEV2, models.TimestampMixin):
network_id = sa.Column(sa.String(36),
sa.ForeignKey("networks.id", ondelete="CASCADE"),
nullable=True)
availability_zone = sa.Column(sa.String(36),
primary_key=True)
class NsxvInternalEdges(model_base.BASEV2, models.TimestampMixin):
"""Represents internal Edge appliances for NSXV plugin operations."""
__tablename__ = 'nsxv_internal_edges'
ext_ip_address = sa.Column(sa.String(64), primary_key=True)

View File

@ -71,6 +71,17 @@ class ConfiguredAvailabilityZone(object):
# using the global ones instead.
self.ha_placement_random = cfg.CONF.nsxv.ha_placement_random
self.backup_edge_pool = cfg.CONF.nsxv.backup_edge_pool
self.external_network = cfg.CONF.nsxv.external_network
self.vdn_scope_id = cfg.CONF.nsxv.vdn_scope_id
self.dvs_id = cfg.CONF.nsxv.dvs_id
# No support for metadata per az
self.az_metadata_support = False
self.mgt_net_moid = None
self.mgt_net_proxy_ips = []
self.mgt_net_proxy_netmask = None
self.mgt_net_default_gateway = None
elif config_line:
# Newer configuration - the name of the availability zone can be
# used to get the rest of the configuration for this AZ
@ -113,6 +124,57 @@ class ConfiguredAvailabilityZone(object):
if not self.backup_edge_pool:
self.backup_edge_pool = cfg.CONF.nsxv.backup_edge_pool
self.external_network = az_info.get('external_network')
if not self.external_network:
self.external_network = cfg.CONF.nsxv.external_network
self.vdn_scope_id = az_info.get('vdn_scope_id')
if not self.vdn_scope_id:
self.vdn_scope_id = cfg.CONF.nsxv.vdn_scope_id
self.dvs_id = az_info.get('dvs_id')
if not self.dvs_id:
self.dvs_id = cfg.CONF.nsxv.dvs_id
# Support for metadata per az only if configured, and different
# from the global one
self.mgt_net_proxy_ips = az_info.get('mgt_net_proxy_ips')
if self.mgt_net_proxy_ips:
# make sure there are no over lapping ips with the
# global configuration
if (set(self.mgt_net_proxy_ips) &
set(cfg.CONF.nsxv.mgt_net_proxy_ips)):
raise nsx_exc.NsxInvalidConfiguration(
opt_name="mgt_net_proxy_ips",
opt_value='None',
reason=(_("mgt_net_proxy_ips for availability zone "
"%s must be different from global one") %
self.name))
self.az_metadata_support = True
self.mgt_net_moid = az_info.get('mgt_net_moid')
if not self.mgt_net_moid:
self.mgt_net_moid = cfg.CONF.nsxv.mgt_net_moid
self.mgt_net_proxy_netmask = az_info.get(
'mgt_net_proxy_netmask')
if not self.mgt_net_proxy_netmask:
self.mgt_net_proxy_netmask = (
cfg.CONF.nsxv.mgt_net_proxy_netmask)
self.mgt_net_default_gateway = az_info.get(
'mgt_net_default_gateway')
if not self.mgt_net_default_gateway:
self.mgt_net_default_gateway = (
cfg.CONF.nsxv.mgt_net_default_gateway)
else:
self.az_metadata_support = False
self.mgt_net_moid = None
self.mgt_net_proxy_ips = []
self.mgt_net_proxy_netmask = None
self.mgt_net_default_gateway = None
else:
# use the default configuration
self.name = DEFAULT_NAME
@ -122,6 +184,23 @@ class ConfiguredAvailabilityZone(object):
self.ha_datastore_id = cfg.CONF.nsxv.ha_datastore_id
self.ha_placement_random = cfg.CONF.nsxv.ha_placement_random
self.backup_edge_pool = cfg.CONF.nsxv.backup_edge_pool
self.az_metadata_support = True
self.mgt_net_moid = cfg.CONF.nsxv.mgt_net_moid
self.mgt_net_proxy_ips = cfg.CONF.nsxv.mgt_net_proxy_ips
self.mgt_net_proxy_netmask = cfg.CONF.nsxv.mgt_net_proxy_netmask
self.mgt_net_default_gateway = (
cfg.CONF.nsxv.mgt_net_default_gateway)
self.external_network = cfg.CONF.nsxv.external_network
self.vdn_scope_id = cfg.CONF.nsxv.vdn_scope_id
self.dvs_id = cfg.CONF.nsxv.dvs_id
def is_default(self):
return self.name == DEFAULT_NAME
def supports_metadata(self):
# Return True if this az has it's own metadata configuration
# If False - it uses the global metadata (if defined)
return self.az_metadata_support
class ConfiguredAvailabilityZones(object):
@ -147,6 +226,14 @@ class ConfiguredAvailabilityZones(object):
resources.append(az.datastore_id)
if az.ha_datastore_id:
resources.append(az.ha_datastore_id)
if az.mgt_net_moid:
resources.append(az.mgt_net_moid)
if az.external_network:
resources.append(az.external_network)
if az.vdn_scope_id:
resources.append(az.vdn_scope_id)
if az.mgt_net_moid:
resources.append(az.mgt_net_moid)
return resources
def get_availability_zone(self, name):

View File

@ -197,7 +197,7 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver):
# Update external vnic if addr or mask is changed
if orgaddr != newaddr or orgmask != newmask:
edge_utils.update_external_interface(
self.edge_manager.update_external_interface(
self.nsx_v, context, plr_id,
new_ext_net_id, newaddr, newmask)

View File

@ -41,8 +41,9 @@ class RouterExclusiveDriver(router_driver.RouterBaseDriver):
context, lrouter, dist=False, appliance_size=appliance_size,
availability_zone=availability_zone)
if allow_metadata:
self.plugin.metadata_proxy_handler.configure_router_edge(
context, lrouter['id'])
self.plugin.get_metadata_proxy_handler(
availability_zone.name).configure_router_edge(
context, lrouter['id'])
def update_router(self, context, router_id, router):
r = router['router']
@ -78,8 +79,10 @@ class RouterExclusiveDriver(router_driver.RouterBaseDriver):
def detach_router(self, context, router_id, router):
LOG.debug("Detach exclusive router id %s", router_id)
self.edge_manager.unbind_router_on_edge(context, router_id)
metadata_proxy_handler = self.plugin.metadata_proxy_handler
if metadata_proxy_handler:
if self.plugin.metadata_proxy_handler:
az = self.get_router_az_by_id(context, router_id)
metadata_proxy_handler = self.plugin.get_metadata_proxy_handler(
az.name)
metadata_proxy_handler.cleanup_router_edge(context, router_id)
def _build_router_data_from_db(self, router_db, router):
@ -130,8 +133,9 @@ class RouterExclusiveDriver(router_driver.RouterBaseDriver):
def delete_router(self, context, router_id):
if self.plugin.metadata_proxy_handler:
self.plugin.metadata_proxy_handler.cleanup_router_edge(
context, router_id)
az = self.get_router_az_by_id(context, router_id)
md_proxy = self.plugin.get_metadata_proxy_handler(az.name)
md_proxy.cleanup_router_edge(context, router_id)
self.edge_manager.delete_lrouter(context, router_id, dist=False)
def update_routes(self, context, router_id, nexthop):
@ -168,7 +172,7 @@ class RouterExclusiveDriver(router_driver.RouterBaseDriver):
# Update external vnic if addr or mask is changed
if orgaddr != newaddr or orgmask != newmask or force_update:
edge_utils.update_external_interface(
self.edge_manager.update_external_interface(
self.nsx_v, context, router_id,
new_ext_net_id, newaddr, newmask)

View File

@ -274,7 +274,7 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
'primaryAddress: %s, netmask: %s, nexthop: %s, secondary: '
'%s.', ext_net_id, gateway_primary_addr, gateway_mask,
gateway_nexthop, secondary)
edge_utils.update_external_interface(
self.edge_manager.update_external_interface(
self.nsx_v, context, target_router_id, ext_net_id,
gateway_primary_addr, gateway_mask, secondary)
@ -552,7 +552,7 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
ports_qry = context.session.query(models_v2.Port)
all_gw_ports = ports_qry.filter_by(
device_owner=l3_db.DEVICE_OWNER_ROUTER_GW).all()
metadata_nets = nsxv_db.get_nsxv_internal_network(
metadata_nets = nsxv_db.get_nsxv_internal_networks(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)
metadata_net_ids = [metadata_net['network_id']
@ -592,10 +592,10 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
conflict_router_ids, conflict_network_ids,
intf_num, az)
# configure metadata service on the router.
metadata_proxy_handler = self.plugin.metadata_proxy_handler
if metadata_proxy_handler and new:
metadata_proxy_handler.configure_router_edge(context,
router_id)
if self.plugin.metadata_proxy_handler and new:
md_proxy_handler = self.plugin.get_metadata_proxy_handler(
az.name)
md_proxy_handler.configure_router_edge(context, router_id)
edge_id = edge_utils.get_router_edge_id(context, router_id)
with locking.LockManager.get_lock(str(edge_id)):
# add all internal interfaces of the router on edge
@ -618,11 +618,13 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
flavor_id, edge_id)
def _unbind_router_on_edge(self, context, router_id):
az = self.get_router_az_by_id(context, router_id)
self.edge_manager.reconfigure_shared_edge_metadata_port(
context, router_id)
self.edge_manager.unbind_router_on_edge(context, router_id)
metadata_proxy_handler = self.plugin.metadata_proxy_handler
if metadata_proxy_handler:
if self.plugin.metadata_proxy_handler:
metadata_proxy_handler = self.plugin.get_metadata_proxy_handler(
az.name)
metadata_proxy_handler.cleanup_router_edge(context, router_id)
def _add_router_services_on_available_edge(self, context, router_id):

View File

@ -92,22 +92,26 @@ def get_router_fw_rules():
return fw_rules
def get_db_internal_edge_ips(context):
def get_db_internal_edge_ips(context, az_name):
ip_list = []
edge_list = nsxv_db.get_nsxv_internal_edges_by_purpose(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)
if edge_list:
ip_list = [edge['ext_ip_address'] for edge in edge_list]
# Take only the edges on this availability zone
ip_list = [edge['ext_ip_address'] for edge in edge_list
if nsxv_db.get_router_availability_zone(
context.session, edge['router_id']) == az_name]
return ip_list
class NsxVMetadataProxyHandler(object):
def __init__(self, nsxv_plugin):
"""A metadata proxy handler for a specific availability zone"""
def __init__(self, nsxv_plugin, availability_zone):
self.nsxv_plugin = nsxv_plugin
context = neutron_context.get_admin_context()
self.az = availability_zone
# Init cannot run concurrently on multiple nodes
with locking.LockManager.get_lock('nsx-metadata-init'):
@ -119,11 +123,14 @@ class NsxVMetadataProxyHandler(object):
def _create_metadata_internal_network(self, context, cidr):
# Neutron requires a network to have some tenant_id
tenant_id = nsxv_constants.INTERNAL_TENANT_ID
net_data = {'network': {'name': 'inter-edge-net',
net_name = 'inter-edge-net'
if not self.az.is_default():
net_name = '%s-%s' % (net_name, self.az.name)
net_data = {'network': {'name': net_name,
'admin_state_up': True,
'port_security_enabled': False,
'shared': False,
'availability_zone_hints': [self.az.name],
'tenant_id': tenant_id}}
net = self.nsxv_plugin.create_network(context, net_data)
@ -145,17 +152,21 @@ class NsxVMetadataProxyHandler(object):
return net['id'], subnet['id']
def _get_internal_net_by_az(self, context):
# Get the internal network for the current az
int_net = nsxv_db.get_nsxv_internal_network(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE,
self.az.name)
if int_net:
return int_net['network_id']
def _get_internal_network_and_subnet(self, context):
internal_net = None
internal_subnet = None
# Try to find internal net, internal subnet. If not found, create new
net_list = nsxv_db.get_nsxv_internal_network(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)
if net_list:
internal_net = net_list[0]['network_id']
internal_net = self._get_internal_net_by_az(context)
internal_subnet = None
if internal_net:
internal_subnet = self.nsxv_plugin.get_subnets(
@ -173,7 +184,8 @@ class NsxVMetadataProxyHandler(object):
except Exception as e:
nsxv_db.delete_nsxv_internal_network(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE,
internal_net)
# if network is created, clean up
if internal_net:
@ -188,6 +200,7 @@ class NsxVMetadataProxyHandler(object):
nsxv_db.create_nsxv_internal_network(
context.session,
nsxv_constants.INTER_EDGE_PURPOSE,
self.az.name,
internal_net)
else:
error = _('Metadata initialization is incomplete on '
@ -223,29 +236,30 @@ class NsxVMetadataProxyHandler(object):
def _get_proxy_edges(self, context):
proxy_edge_ips = []
db_edge_ips = get_db_internal_edge_ips(context)
if len(db_edge_ips) > len(cfg.CONF.nsxv.mgt_net_proxy_ips):
error = _('Number of configured metadata proxy IPs is smaller '
'than number of Edges which are already provisioned')
db_edge_ips = get_db_internal_edge_ips(context, self.az.name)
if len(db_edge_ips) > len(self.az.mgt_net_proxy_ips):
error = (_('Number of configured metadata proxy IPs is smaller '
'than number of Edges which are already provisioned '
'for availability zone %s'), self.az.name)
raise nsxv_exc.NsxPluginException(err_msg=error)
pool = eventlet.GreenPool(min(MAX_INIT_THREADS,
len(cfg.CONF.nsxv.mgt_net_proxy_ips)))
len(self.az.mgt_net_proxy_ips)))
# Edge IPs that exist in both lists have to be validated that their
# Edge appliance settings are valid
for edge_inner_ip in pool.imap(
self._setup_proxy_edge_route_and_connectivity,
list(set(db_edge_ips) & set(cfg.CONF.nsxv.mgt_net_proxy_ips))):
list(set(db_edge_ips) & set(self.az.mgt_net_proxy_ips))):
proxy_edge_ips.append(edge_inner_ip)
# Edges that exist only in the CFG list, should be paired with Edges
# that exist only in the DB list. The existing Edge from the list will
# be reconfigured to match the new config
edge_to_convert_ips = (
list(set(db_edge_ips) - set(cfg.CONF.nsxv.mgt_net_proxy_ips)))
list(set(db_edge_ips) - set(self.az.mgt_net_proxy_ips)))
edge_ip_to_set = (
list(set(cfg.CONF.nsxv.mgt_net_proxy_ips) - set(db_edge_ips)))
list(set(self.az.mgt_net_proxy_ips) - set(db_edge_ips)))
if edge_to_convert_ips:
if cfg.CONF.nsxv.metadata_initializer:
@ -283,6 +297,12 @@ class NsxVMetadataProxyHandler(object):
rtr_id = self._get_edge_rtr_id_by_ext_ip(context, rtr_ext_ip)
if not edge_id:
edge_id = self._get_edge_id_by_rtr_id(context, rtr_id)
if not rtr_id or not edge_id:
# log this error and return without the ip, but don't fail
LOG.error(_LE("Failed find edge for router %(rtr_id)s with ip "
"%(rtr_ext_ip)s"),
{'rtr_id': rtr_id, 'rtr_ext_ip': rtr_ext_ip})
return
# Read and validate DGW. If different, replace with new value
try:
@ -297,11 +317,11 @@ class NsxVMetadataProxyHandler(object):
dgw = routes.get('defaultRoute', {}).get('gatewayAddress')
if dgw != cfg.CONF.nsxv.mgt_net_default_gateway:
if dgw != self.az.mgt_net_default_gateway:
if cfg.CONF.nsxv.metadata_initializer:
self.nsxv_plugin._update_routes(
context, rtr_id,
cfg.CONF.nsxv.mgt_net_default_gateway)
self.az.mgt_net_default_gateway)
else:
error = _('Metadata initialization is incomplete on '
'initializer node')
@ -314,16 +334,16 @@ class NsxVMetadataProxyHandler(object):
).get('addressGroups', {}
)[0].get('primaryAddress')
cur_pgroup = if_data['portgroupId']
if (if_data and cur_pgroup != cfg.CONF.nsxv.mgt_net_moid
if (if_data and cur_pgroup != self.az.mgt_net_moid
or cur_ip != rtr_ext_ip):
if cfg.CONF.nsxv.metadata_initializer:
self.nsxv_plugin.nsx_v.update_interface(
rtr_id,
edge_id,
vcns_const.EXTERNAL_VNIC_INDEX,
cfg.CONF.nsxv.mgt_net_moid,
self.az.mgt_net_moid,
address=rtr_ext_ip,
netmask=cfg.CONF.nsxv.mgt_net_proxy_netmask,
netmask=self.az.mgt_net_proxy_netmask,
secondary=[])
else:
error = _('Metadata initialization is incomplete on '
@ -397,12 +417,17 @@ class NsxVMetadataProxyHandler(object):
context = neutron_context.get_admin_context()
rtr_id = None
try:
rtr_name = 'metadata_proxy_router'
if not self.az.is_default():
rtr_name = '%s-%s' % (rtr_name, self.az.name)
router_data = {
'router': {
'name': 'metadata_proxy_router',
'name': rtr_name,
'admin_state_up': True,
'router_type': 'exclusive',
'availability_zone_hints': [self.az.name],
'tenant_id': nsxv_constants.INTERNAL_TENANT_ID}}
rtr = self.nsxv_plugin.create_router(
@ -417,9 +442,9 @@ class NsxVMetadataProxyHandler(object):
rtr['id'],
edge_id,
vcns_const.EXTERNAL_VNIC_INDEX,
cfg.CONF.nsxv.mgt_net_moid,
self.az.mgt_net_moid,
address=rtr_ext_ip,
netmask=cfg.CONF.nsxv.mgt_net_proxy_netmask,
netmask=self.az.mgt_net_proxy_netmask,
secondary=[])
port_data = {
@ -465,10 +490,10 @@ class NsxVMetadataProxyHandler(object):
{'firewall_rule_list': firewall_rules},
allow_external=False)
if cfg.CONF.nsxv.mgt_net_default_gateway:
if self.az.mgt_net_default_gateway:
self.nsxv_plugin._update_routes(
context, rtr_id,
cfg.CONF.nsxv.mgt_net_default_gateway)
self.az.mgt_net_default_gateway)
nsxv_db.create_nsxv_internal_edge(
context.session, rtr_ext_ip,

View File

@ -292,11 +292,27 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
and cfg.CONF.nsxv.mgt_net_proxy_ips
and cfg.CONF.nsxv.mgt_net_proxy_netmask)
if has_metadata_cfg:
self.metadata_proxy_handler = (
nsx_v_md_proxy.NsxVMetadataProxyHandler(self))
# Init md_proxy handler per availability zone
self.metadata_proxy_handler = {}
az_list = self._availability_zones_data.list_availability_zones()
for name in az_list:
az = self._availability_zones_data.get_availability_zone(name)
# create metadata handler only if the az supports it.
# if not, the global one will be used
if az.supports_metadata():
self.metadata_proxy_handler[name] = (
nsx_v_md_proxy.NsxVMetadataProxyHandler(self, az))
self.init_is_complete = True
def get_metadata_proxy_handler(self, az_name):
if not self.metadata_proxy_handler:
return None
if az_name in self.metadata_proxy_handler:
return self.metadata_proxy_handler[az_name]
# fallback to the global handler
return self.metadata_proxy_handler[nsx_az.DEFAULT_NAME]
def add_vms_to_service_insertion(self, sg_id):
def _add_vms_to_service_insertion(*args, **kwargs):
@ -545,13 +561,27 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
if err_msg:
raise n_exc.InvalidInput(error_message=err_msg)
def _validate_physical_network(self, physical_network):
dvs_ids = self._get_dvs_ids(physical_network)
def _validate_physical_network(self, physical_network, default_dvs):
dvs_ids = self._get_dvs_ids(physical_network, default_dvs)
for dvs_id in dvs_ids:
if not self.nsx_v.vcns.validate_dvs(dvs_id):
raise nsx_exc.NsxResourceNotFound(res_name='dvs_id',
res_id=dvs_id)
def _get_network_az_from_net_data(self, net_data):
if az_ext.AZ_HINTS in net_data and net_data[az_ext.AZ_HINTS]:
return self._availability_zones_data.get_availability_zone(
net_data[az_ext.AZ_HINTS][0])
return self.get_default_az()
def _get_network_az_dvs_id(self, net_data):
az = self._get_network_az_from_net_data(net_data)
return az.dvs_id
def _get_network_vdn_scope_id(self, net_data):
az = self._get_network_az_from_net_data(net_data)
return az.vdn_scope_id
def _validate_provider_create(self, context, network):
if not validators.is_attr_set(network.get(mpnet.SEGMENTS)):
return
@ -563,6 +593,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
network_type_set = validators.is_attr_set(network_type)
segmentation_id_set = validators.is_attr_set(segmentation_id)
physical_network_set = validators.is_attr_set(physical_network)
az_dvs = self._get_network_az_dvs_id(network)
err_msg = None
if not network_type_set:
@ -572,7 +603,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
err_msg = _("Segmentation ID cannot be specified with "
"flat network type")
if physical_network_set:
self._validate_physical_network(physical_network)
self._validate_physical_network(physical_network, az_dvs)
elif network_type == c_utils.NsxVNetworkTypes.VLAN:
if not segmentation_id_set:
err_msg = _("Segmentation ID must be specified with "
@ -589,8 +620,11 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
bindings = nsxv_db.get_network_bindings_by_vlanid(
context.session, segmentation_id)
if bindings:
phy_uuid = (physical_network if physical_network_set
else self.dvs_id)
if physical_network_set:
phy_uuid = physical_network
else:
# use the fvs_id of the availability zone
phy_uuid = az_dvs
for binding in bindings:
if binding['phy_uuid'] == phy_uuid:
raise n_exc.VlanIdInUse(
@ -598,7 +632,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
physical_network=phy_uuid)
# Verify whether the DVSes exist in the backend.
if physical_network_set:
self._validate_physical_network(physical_network)
self._validate_physical_network(physical_network, az_dvs)
elif network_type == c_utils.NsxVNetworkTypes.VXLAN:
# Currently unable to set the segmentation id
@ -810,7 +844,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
self._update_network_teaming(dvs_id, net_data['id'], c)
return c
def _get_dvs_ids(self, physical_network):
def _get_dvs_ids(self, physical_network, default_dvs):
"""Extract DVS-IDs provided in the physical network field.
If physical network attribute is not set, return the pre configured
@ -818,7 +852,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
to a list of unique DVS-IDs.
"""
if not validators.is_attr_set(physical_network):
return [self.dvs_id]
return [default_dvs]
# Return unique DVS-IDs only and ignore duplicates
return list(set(
dvs.strip() for dvs in physical_network.split(',') if dvs))
@ -946,7 +980,11 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
return self.get_default_az()
def get_network_az(self, context, network_id):
network = self.get_network(context, network_id)
try:
network = self.get_network(context, network_id)
except Exception:
return self.get_default_az()
return self.get_network_or_router_az(network)
def get_router_az(self, router):
@ -995,7 +1033,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
virtual_wire = {"name": net_data['id'],
"tenantId": "virtual wire tenant"}
config_spec = {"virtualWireCreateSpec": virtual_wire}
vdn_scope_id = self.vdn_scope_id
vdn_scope_id = self._get_network_vdn_scope_id(net_data)
if provider_type is not None:
segment = net_data[mpnet.SEGMENTS][0]
if validators.is_attr_set(
@ -1020,7 +1058,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# Retrieve the list of dvs-ids from physical network.
# If physical_network attr is not set, retrieve a list
# consisting of a single dvs-id pre-configured in nsx.ini
dvs_ids = self._get_dvs_ids(physical_network)
az_dvs = self._get_network_az_dvs_id(net_data)
dvs_ids = self._get_dvs_ids(physical_network, az_dvs)
dvs_net_ids = []
# Save the list of netmorefs from the backend
net_morefs = []
@ -1062,10 +1101,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# update the network with the availability zone hints
if az_ext.AZ_HINTS in net_data:
self.validate_availability_zones(context, 'network',
net_data[az_ext.AZ_HINTS])
az_hints = az_ext.convert_az_list_to_string(
net_data[az_ext.AZ_HINTS])
net_data[az_ext.AZ_HINTS])
super(NsxVPluginV2, self).update_network(context,
new_net['id'],
{'network': {az_ext.AZ_HINTS: az_hints}})
@ -1089,7 +1126,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
physical_net_set = validators.is_attr_set(
physical_network)
if not physical_net_set:
physical_network = self.dvs_id
# Use the dvs_id of the availability zone
physical_network = self._get_network_az_dvs_id(
net_data)
net_bindings.append(nsxv_db.add_network_binding(
context.session, new_net['id'],
network_type,
@ -1190,8 +1229,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
context.session, dhcp_edge['edge_id'])
if rtr_binding:
rtr_id = rtr_binding['router_id']
self.metadata_proxy_handler.cleanup_router_edge(
context, rtr_id)
az_name = rtr_binding['availability_zone']
md_proxy = self.get_metadata_proxy_handler(az_name)
md_proxy.cleanup_router_edge(context, rtr_id)
else:
self.edge_manager.reconfigure_shared_edge_metadata_port(
context, (vcns_const.DHCP_EDGE_PREFIX + net_id)[:36])
@ -1307,7 +1347,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
[db_utils.resource_fields(network,
fields) for network in networks])
def _raise_if_updates_provider_attributes(self, original_network, attrs):
def _raise_if_updates_provider_attributes(self, original_network, attrs,
az_dvs):
"""Raise exception if provider attributes are present.
For the NSX-V we want to allow changing the physical network of
@ -1322,11 +1363,12 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
and not validators.is_attr_set(
attrs.get(providernet.SEGMENTATION_ID))):
self._validate_physical_network(
attrs[providernet.PHYSICAL_NETWORK])
attrs[providernet.PHYSICAL_NETWORK], az_dvs)
return
providernet._raise_if_updates_provider_attributes(attrs)
def _update_vlan_network_dvs_ids(self, network, new_physical_network):
def _update_vlan_network_dvs_ids(self, network, new_physical_network,
az_dvs):
"""Update the dvs ids of a vlan provider network
The new values will be added to the current ones.
@ -1345,9 +1387,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
dvs_pg_mappings = {}
current_dvs_ids = set(self._get_dvs_ids(
network[providernet.PHYSICAL_NETWORK]))
network[providernet.PHYSICAL_NETWORK], az_dvs))
new_dvs_ids = set(self._get_dvs_ids(
new_physical_network))
new_physical_network, az_dvs))
additinal_dvs_ids = new_dvs_ids - current_dvs_ids
if not additinal_dvs_ids:
@ -1374,8 +1416,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
def update_network(self, context, id, network):
net_attrs = network['network']
orig_net = self.get_network(context, id)
az_dvs = self._get_network_az_dvs_id(orig_net)
self._raise_if_updates_provider_attributes(
orig_net, net_attrs)
orig_net, net_attrs, az_dvs)
if net_attrs.get("admin_state_up") is False:
raise NotImplementedError(_("admin_state_up=False networks "
"are not supported."))
@ -1402,7 +1445,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
(updated_morefs,
new_dvs_pg_mappings) = self._update_vlan_network_dvs_ids(
orig_net,
net_attrs[providernet.PHYSICAL_NETWORK])
net_attrs[providernet.PHYSICAL_NETWORK],
az_dvs)
if updated_morefs:
new_dvs = list(new_dvs_pg_mappings.values())
net_morefs.extend(new_dvs)
@ -2436,15 +2480,24 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
if binding:
return binding['edge_id']
def _get_edge_id_and_az_by_rtr_id(self, context, rtr_id):
binding = nsxv_db.get_nsxv_router_binding(
context.session,
rtr_id)
if binding:
return binding['edge_id'], binding['availability_zone']
def _update_dhcp_service_new_edge(self, context, resource_id):
edge_id = self._get_edge_id_by_rtr_id(context, resource_id)
edge_id, az_name = self._get_edge_id_and_az_by_rtr_id(
context, resource_id)
if edge_id:
with locking.LockManager.get_lock(str(edge_id)):
if self.metadata_proxy_handler:
LOG.debug('Update metadata for resource %s',
resource_id)
self.metadata_proxy_handler.configure_router_edge(
context, resource_id)
LOG.debug('Update metadata for resource %s az=%s',
resource_id, az_name)
md_proxy = self.get_metadata_proxy_handler(az_name)
md_proxy.configure_router_edge(context, resource_id)
self.setup_dhcp_edge_fw_rules(context, self,
resource_id)
@ -2839,23 +2892,29 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
return self._get_network_availability_zones(context, net_db)
def _get_network_availability_zones(self, context, net_db):
"""Return availability zones which a network belongs to."""
"""Return availability zones which a network belongs to.
Return only the actual az the dhcp edge is deployed on.
If there is no edge - the availability zones list is empty.
"""
resource_id = (vcns_const.DHCP_EDGE_PREFIX + net_db["id"])[:36]
dhcp_edge_binding = nsxv_db.get_nsxv_router_binding(
context.session, resource_id)
if dhcp_edge_binding:
edge_id = dhcp_edge_binding['edge_id']
return [self._get_availability_zone_name_by_edge(
context, edge_id)]
return [dhcp_edge_binding['availability_zone']]
return []
def get_router_availability_zones(self, router):
"""Return availability zones which a router belongs to."""
"""Return availability zones which a router belongs to.
Return only the actual az the router edge is deployed on.
If there is no edge - the availability zones list is empty.
"""
context = n_context.get_admin_context()
edge_id = self._get_edge_id_by_rtr_id(context, router["id"])
if edge_id:
return [self._get_availability_zone_name_by_edge(
context, edge_id)]
binding = nsxv_db.get_nsxv_router_binding(
context.session, router['id'])
if binding:
return [binding['availability_zone']]
return []
def _process_router_flavor_create(self, context, router_db, r):
@ -3192,7 +3251,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
secondary = self._get_floatingips_by_router(context, router['id'])
if not router_id:
router_id = router['id']
edge_utils.update_external_interface(
self.edge_manager.update_external_interface(
self.nsx_v, context, router_id, ext_net_id,
addr, mask, secondary)

View File

@ -397,11 +397,11 @@ class EdgeApplianceDriver(object):
if not dist:
vnic_external = self._assemble_edge_vnic(
constants.EXTERNAL_VNIC_NAME, constants.EXTERNAL_VNIC_INDEX,
self.external_network, type="uplink")
availability_zone.external_network, type="uplink")
edge['vnics']['vnics'].append(vnic_external)
else:
edge['mgmtInterface'] = {
'connectedToId': self.external_network,
'connectedToId': availability_zone.external_network,
'name': "mgmtInterface"}
if internal_network:
vnic_inside = self._assemble_edge_vnic(
@ -470,11 +470,11 @@ class EdgeApplianceDriver(object):
if not dist:
vnic_external = self._assemble_edge_vnic(
constants.EXTERNAL_VNIC_NAME, constants.EXTERNAL_VNIC_INDEX,
self.external_network, type="uplink")
availability_zone.external_network, type="uplink")
edge['vnics']['vnics'].append(vnic_external)
else:
edge['mgmtInterface'] = {
'connectedToId': self.external_network,
'connectedToId': availability_zone.external_network,
'name': "mgmtInterface"}
if internal_network:

View File

@ -184,7 +184,6 @@ class EdgeManager(object):
self._worker_pool_pid = None
self._worker_pool = None
self.nsxv_manager = nsxv_manager
self.dvs_id = cfg.CONF.nsxv.dvs_id
self._availability_zones = nsx_az.ConfiguredAvailabilityZones()
self.edge_pool_dicts = self._parse_backup_edge_pool_opt()
self.nsxv_plugin = nsxv_manager.callbacks.plugin
@ -444,10 +443,11 @@ class EdgeManager(object):
return router_binding
backup_router_bindings.remove(router_binding)
def _get_physical_provider_network(self, context, network_id):
def _get_physical_provider_network(self, context, network_id, az_dvs):
bindings = nsxv_db.get_network_bindings(context.session, network_id)
# Set the return value as global DVS-ID of the mgmt/edge cluster
phys_net = self.dvs_id
# Set the return value as the availability zone DVS-ID of the
# mgmt/edge cluster
phys_net = az_dvs
network_type = None
if bindings:
binding = bindings[0]
@ -471,7 +471,9 @@ class EdgeManager(object):
def _create_sub_interface(self, context, network_id, network_name,
tunnel_index, address_groups,
port_group_id=None):
vcns_network_id = _retrieve_nsx_switch_id(context, network_id)
az = self.plugin.get_network_az(context, network_id)
vcns_network_id = _retrieve_nsx_switch_id(context, network_id,
az.name)
if port_group_id is None:
portgroup = {'vlanId': 0,
'networkName': network_name,
@ -479,7 +481,7 @@ class EdgeManager(object):
'networkType': 'Isolation'}
config_spec = {'networkSpec': portgroup}
dvs_id, network_type = self._get_physical_provider_network(
context, network_id)
context, network_id, az.dvs_id)
pg, port_group_id = self.nsxv_manager.vcns.create_port_group(
dvs_id, config_spec)
# Ensure that the portgroup has the correct teaming
@ -522,10 +524,11 @@ class EdgeManager(object):
header, _ = self.nsxv_manager.vcns.delete_interface(edge_id,
vnic_index)
if port_group_id:
az = self.plugin.get_network_az(context, network_id)
dvs_id, net_type = self._get_physical_provider_network(
context, network_id)
context, network_id, az.dvs_id)
self.nsxv_manager.delete_port_group(dvs_id,
port_group_id)
port_group_id)
else:
self.nsxv_manager.vcns.update_interface(edge_id, vnic_config)
except nsxapi_exc.VcnsApiException:
@ -546,17 +549,20 @@ class EdgeManager(object):
"""Delete the router binding or clean the edge appliance."""
resource_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
bindings = nsxv_db.get_nsxv_router_bindings(context.session)
all_dhcp_edges = {binding['router_id']: binding['edge_id'] for
binding in bindings if binding['router_id'].
startswith(vcns_const.DHCP_EDGE_PREFIX)}
for router_id in all_dhcp_edges:
if (router_id != resource_id and
all_dhcp_edges[router_id] == edge_id):
bindings = nsxv_db.get_nsxv_router_bindings_by_edge(
context.session, edge_id)
all_edge_dhcp_entries = [binding['router_id'] for
binding in bindings if binding['router_id'].
startswith(vcns_const.DHCP_EDGE_PREFIX)]
for router_id in all_edge_dhcp_entries:
if (router_id != resource_id):
# There are additional networks on this DHCP edge.
# just delete the binding one and not the edge itself
nsxv_db.delete_nsxv_router_binding(context.session,
resource_id)
return
self._free_dhcp_edge_appliance(context, network_id)
az_name = bindings[0]['availability_zone'] if bindings else ''
self._free_dhcp_edge_appliance(context, network_id, az_name)
def _addr_groups_convert_to_ipset(self, address_groups):
cidr_list = []
@ -823,12 +829,13 @@ class EdgeManager(object):
appliance_size=appliance_size,
availability_zone=availability_zone)
def _free_dhcp_edge_appliance(self, context, network_id):
def _free_dhcp_edge_appliance(self, context, network_id, az_name):
router_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
# if there are still metadata ports on this edge - delete them now
metadata_proxy_handler = self.plugin.metadata_proxy_handler
if metadata_proxy_handler:
if self.plugin.metadata_proxy_handler:
metadata_proxy_handler = self.plugin.get_metadata_proxy_handler(
az_name)
metadata_proxy_handler.cleanup_router_edge(context, router_id,
warn=True)
@ -1183,23 +1190,31 @@ class EdgeManager(object):
appliance_size=app_size,
availability_zone=availability_zone.name)
nsxv_db.allocate_edge_vnic_with_tunnel_index(
context.session, edge_id, network_id)
context.session, edge_id, network_id,
availability_zone.name)
def reconfigure_shared_edge_metadata_port(self, context, org_router_id):
if not self.plugin.metadata_proxy_handler:
return
net_list = nsxv_db.get_nsxv_internal_network(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)
if not net_list:
org_binding = nsxv_db.get_nsxv_router_binding(context.session,
org_router_id)
if not org_binding:
return
internal_net = net_list[0]['network_id']
az_name = org_binding['availability_zone']
int_net = nsxv_db.get_nsxv_internal_network(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE,
az_name)
if not int_net:
return
# Query the ports of this internal network
internal_nets = [int_net['network_id']]
ports = self.nsxv_plugin.get_ports(
context, filters={'device_id': [org_router_id],
'network_id': [internal_net]})
'network_id': internal_nets})
if not ports:
LOG.debug('No metadata ports found for %s', org_router_id)
@ -1208,20 +1223,16 @@ class EdgeManager(object):
LOG.debug('Expecting one metadata port for %s. Found %d ports',
org_router_id, len(ports))
org_binding = nsxv_db.get_nsxv_router_binding(context.session,
org_router_id)
if org_binding:
edge_id = org_binding['edge_id']
bindings = nsxv_db.get_nsxv_router_bindings(
context.session, filters={'edge_id': [edge_id]})
for binding in bindings:
if binding['router_id'] != org_router_id:
for port in ports:
self.plugin.update_port(
context, port['id'],
{'port': {'device_id': binding['router_id']}})
return
edge_id = org_binding['edge_id']
bindings = nsxv_db.get_nsxv_router_bindings(
context.session, filters={'edge_id': [edge_id]})
for binding in bindings:
if binding['router_id'] != org_router_id:
for port in ports:
self.plugin.update_port(
context, port['id'],
{'port': {'device_id': binding['router_id']}})
return
def allocate_new_dhcp_edge(self, context, network_id, resource_id,
availability_zone):
@ -1231,7 +1242,8 @@ class EdgeManager(object):
new_edge = nsxv_db.get_nsxv_router_binding(context.session,
resource_id)
nsxv_db.allocate_edge_vnic_with_tunnel_index(
context.session, new_edge['edge_id'], network_id)
context.session, new_edge['edge_id'], network_id,
availability_zone.name)
return new_edge['edge_id']
def create_dhcp_edge_service(self, context, network_id,
@ -1421,9 +1433,9 @@ class EdgeManager(object):
# Attach to DHCP Edge
dhcp_edge_id = self.allocate_new_dhcp_edge(
context, network_id, resource_id, availability_zone)
self.plugin.metadata_proxy_handler.configure_router_edge(
context, resource_id)
md_proxy = self.plugin.get_metadata_proxy_handler(
availability_zone.name)
md_proxy.configure_router_edge(context, resource_id)
with locking.LockManager.get_lock(str(dhcp_edge_id)):
self.plugin.setup_dhcp_edge_fw_rules(
context, self.plugin, resource_id)
@ -1659,7 +1671,7 @@ class EdgeManager(object):
virtual_wire = {"name": lswitch_name,
"tenantId": "virtual wire tenant"}
config_spec = {"virtualWireCreateSpec": virtual_wire}
vdn_scope_id = cfg.CONF.nsxv.vdn_scope_id
vdn_scope_id = availability_zone.vdn_scope_id
h, lswitch_id = self.nsxv_manager.vcns.create_virtual_wire(
vdn_scope_id, config_spec)
@ -1997,6 +2009,83 @@ class EdgeManager(object):
metainfo = self.plugin.get_flavor_metainfo(context, flavor_id)
return metainfo.get('syslog')
def update_external_interface(
self, nsxv_manager, context, router_id, ext_net_id,
ipaddr, netmask, secondary=None):
with locking.LockManager.get_lock(str(router_id)):
self._update_external_interface(nsxv_manager, context, router_id,
ext_net_id, ipaddr, netmask,
secondary=secondary)
def _update_external_interface(
self, nsxv_manager, context, router_id, ext_net_id,
ipaddr, netmask, secondary=None):
secondary = secondary or []
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
# If no binding was found, no interface to update - exit
if not binding:
LOG.error(_LE('Edge binding not found for router %s'), router_id)
return
net_bindings = nsxv_db.get_network_bindings(
context.session, ext_net_id)
if not net_bindings:
az_name = binding.availability_zone
az = self._availability_zones.get_availability_zone(az_name)
vcns_network_id = az.external_network
else:
vcns_network_id = net_bindings[0].phy_uuid
# reorganize external vnic's address groups
if netmask:
address_groups = []
addr_list = []
for str_cidr in netmask:
ip_net = netaddr.IPNetwork(str_cidr)
address_group = {'primaryAddress': None,
'subnetPrefixLength': str(ip_net.prefixlen)}
if (ipaddr not in addr_list and
_check_ipnet_ip(ip_net, ipaddr)):
address_group['primaryAddress'] = ipaddr
addr_list.append(ipaddr)
for sec_ip in secondary:
if (sec_ip not in addr_list and
_check_ipnet_ip(ip_net, sec_ip)):
if not address_group['primaryAddress']:
address_group['primaryAddress'] = sec_ip
else:
if not address_group.get('secondaryAddresses'):
address_group['secondaryAddresses'] = {
'ipAddress': [sec_ip],
'type': 'secondary_addresses'}
else:
address_group['secondaryAddresses'][
'ipAddress'].append(sec_ip)
addr_list.append(sec_ip)
if address_group['primaryAddress']:
address_groups.append(address_group)
if ipaddr not in addr_list:
LOG.error(_LE("primary address %s of ext vnic is not "
"configured"), ipaddr)
if secondary:
missed_ip_sec = set(secondary) - set(addr_list)
if missed_ip_sec:
LOG.error(_LE("secondary address %s of ext vnic are not "
"configured"), str(missed_ip_sec))
nsxv_manager.update_interface(router_id, binding['edge_id'],
vcns_const.EXTERNAL_VNIC_INDEX,
vcns_network_id,
address_groups=address_groups)
else:
nsxv_manager.update_interface(router_id, binding['edge_id'],
vcns_const.EXTERNAL_VNIC_INDEX,
vcns_network_id,
address=ipaddr,
netmask=netmask,
secondary=secondary)
def create_lrouter(nsxv_manager, context, lrouter, lswitch=None, dist=False,
availability_zone=None):
@ -2040,7 +2129,7 @@ def remove_irrelevant_keys_from_edge_request(edge_request):
edge_request.pop(key, None)
def _retrieve_nsx_switch_id(context, network_id):
def _retrieve_nsx_switch_id(context, network_id, az_name):
"""Helper method to retrieve backend switch ID."""
bindings = nsxv_db.get_network_bindings(context.session, network_id)
if bindings:
@ -2053,8 +2142,10 @@ def _retrieve_nsx_switch_id(context, network_id):
else:
# If network is of type VLAN and multiple dvs associated with
# one neutron network, retrieve the logical network id for the
# edge/mgmt cluster's DVS.
dvs_id = cfg.CONF.nsxv.dvs_id
# edge/mgmt cluster's DVS from the networks availability zone.
azs = nsx_az.ConfiguredAvailabilityZones()
az = azs.get_availability_zone(az_name)
dvs_id = az.dvs_id
return nsx_db.get_nsx_switch_id_for_dvs(
context.session, network_id, dvs_id)
# Get the physical port group /wire id of the network id
@ -2215,15 +2306,6 @@ def clear_gateway(nsxv_manager, context, router_id):
return update_gateway(nsxv_manager, context, router_id, None)
def update_external_interface(
nsxv_manager, context, router_id, ext_net_id,
ipaddr, netmask, secondary=None):
with locking.LockManager.get_lock(str(router_id)):
_update_external_interface(nsxv_manager, context, router_id,
ext_net_id, ipaddr, netmask,
secondary=secondary)
def _check_ipnet_ip(ipnet, ip_address):
"""Check one ip is valid ip from ipnet."""
ip = netaddr.IPAddress(ip_address)
@ -2234,73 +2316,6 @@ def _check_ipnet_ip(ipnet, ip_address):
return False
def _update_external_interface(
nsxv_manager, context, router_id, ext_net_id,
ipaddr, netmask, secondary=None):
secondary = secondary or []
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
# If no binding was found, no interface to update - exit
if not binding:
LOG.error(_LE('Edge binding not found for router %s'), router_id)
return
net_bindings = nsxv_db.get_network_bindings(context.session, ext_net_id)
if not net_bindings:
vcns_network_id = nsxv_manager.external_network
else:
vcns_network_id = net_bindings[0].phy_uuid
# reorganize external vnic's address groups
if netmask:
address_groups = []
addr_list = []
for str_cidr in netmask:
ip_net = netaddr.IPNetwork(str_cidr)
address_group = {'primaryAddress': None,
'subnetPrefixLength': str(ip_net.prefixlen)}
if (ipaddr not in addr_list and
_check_ipnet_ip(ip_net, ipaddr)):
address_group['primaryAddress'] = ipaddr
addr_list.append(ipaddr)
for sec_ip in secondary:
if (sec_ip not in addr_list and
_check_ipnet_ip(ip_net, sec_ip)):
if not address_group['primaryAddress']:
address_group['primaryAddress'] = sec_ip
else:
if not address_group.get('secondaryAddresses'):
address_group['secondaryAddresses'] = {
'ipAddress': [sec_ip],
'type': 'secondary_addresses'}
else:
address_group['secondaryAddresses'][
'ipAddress'].append(sec_ip)
addr_list.append(sec_ip)
if address_group['primaryAddress']:
address_groups.append(address_group)
if ipaddr not in addr_list:
LOG.error(_LE("primary address %s of ext vnic is not "
"configured"), ipaddr)
if secondary:
missed_ip_sec = set(secondary) - set(addr_list)
if missed_ip_sec:
LOG.error(_LE("secondary address %s of ext vnic are not "
"configured"), str(missed_ip_sec))
nsxv_manager.update_interface(router_id, binding['edge_id'],
vcns_const.EXTERNAL_VNIC_INDEX,
vcns_network_id,
address_groups=address_groups)
else:
nsxv_manager.update_interface(router_id, binding['edge_id'],
vcns_const.EXTERNAL_VNIC_INDEX,
vcns_network_id,
address=ipaddr,
netmask=netmask,
secondary=secondary)
def update_internal_interface(nsxv_manager, context, router_id, int_net_id,
address_groups, is_connected=True):
with locking.LockManager.get_lock(str(router_id)):
@ -2311,15 +2326,18 @@ def update_internal_interface(nsxv_manager, context, router_id, int_net_id,
def _update_internal_interface(nsxv_manager, context, router_id, int_net_id,
address_groups, is_connected=True):
# Get the pg/wire id of the network id
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': int_net_id,
'net_moref': vcns_network_id})
# Get edge id
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
edge_id = binding['edge_id']
# Get the pg/wire id of the network id
az_name = binding['availability_zone']
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id, az_name)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': int_net_id,
'net_moref': vcns_network_id})
edge_vnic_binding = nsxv_db.get_edge_vnic_binding(
context.session, edge_id, int_net_id)
# if edge_vnic_binding is None, then first select one available
@ -2345,14 +2363,17 @@ def add_vdr_internal_interface(nsxv_manager, context, router_id,
def _add_vdr_internal_interface(nsxv_manager, context, router_id,
int_net_id, address_groups, is_connected=True):
# Get the pg/wire id of the network id
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': int_net_id,
'net_moref': vcns_network_id})
# Get edge id
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
edge_id = binding['edge_id']
# Get the pg/wire id of the network id
az_name = binding['availability_zone']
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id, az_name)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': int_net_id,
'net_moref': vcns_network_id})
edge_vnic_binding = nsxv_db.get_edge_vnic_binding(
context.session, edge_id, int_net_id)
if not edge_vnic_binding:
@ -2378,15 +2399,17 @@ def update_vdr_internal_interface(nsxv_manager, context, router_id, int_net_id,
def _update_vdr_internal_interface(nsxv_manager, context, router_id,
int_net_id, address_groups,
is_connected=True):
# Get edge id
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
edge_id = binding['edge_id']
# Get the pg/wire id of the network id
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id)
az_name = binding['availability_zone']
vcns_network_id = _retrieve_nsx_switch_id(context, int_net_id, az_name)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': int_net_id,
'net_moref': vcns_network_id})
# Get edge id
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
edge_id = binding['edge_id']
edge_vnic_binding = nsxv_db.get_edge_vnic_binding(
context.session, edge_id, int_net_id)
nsxv_manager.update_vdr_internal_interface(
@ -2402,12 +2425,6 @@ def delete_interface(nsxv_manager, context, router_id, network_id, dist=False):
def _delete_interface(nsxv_manager, context, router_id, network_id,
dist=False):
# Get the pg/wire id of the network id
vcns_network_id = _retrieve_nsx_switch_id(context, network_id)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': network_id,
'net_moref': vcns_network_id})
# Get edge id
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
if not binding:
@ -2416,6 +2433,14 @@ def _delete_interface(nsxv_manager, context, router_id, network_id,
return
edge_id = binding['edge_id']
# Get the pg/wire id of the network id
az_name = binding['availability_zone']
vcns_network_id = _retrieve_nsx_switch_id(context, network_id, az_name)
LOG.debug("Network id %(network_id)s corresponding ref is : "
"%(net_moref)s", {'network_id': network_id,
'net_moref': vcns_network_id})
edge_vnic_binding = nsxv_db.get_edge_vnic_binding(
context.session, edge_id, network_id)
if not edge_vnic_binding:

View File

@ -42,7 +42,6 @@ class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver,
self.insecure = cfg.CONF.nsxv.insecure
self.datacenter_moid = cfg.CONF.nsxv.datacenter_moid
self.deployment_container_id = cfg.CONF.nsxv.deployment_container_id
self.external_network = cfg.CONF.nsxv.external_network
self._pid = None
self._task_manager = None
self.vcns = vcns.Vcns(self.vcns_uri, self.vcns_user, self.vcns_passwd,

View File

@ -22,9 +22,11 @@ from neutron.db import models_v2
from oslo_config import cfg
from vmware_nsx._i18n import _LE, _LI
from vmware_nsx.common import config
from vmware_nsx.common import locking
from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import nsxv_db
from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az
from vmware_nsx.plugins.nsx_v import md_proxy
from vmware_nsx.plugins.nsx_v.vshield.common import constants as vcns_constants
from vmware_nsx.plugins.nsx_v.vshield import nsxv_loadbalancer as nsxv_lb
@ -42,26 +44,48 @@ nsxv = utils.get_nsxv_client()
@admin_utils.output_header
def nsx_redo_metadata_cfg(resource, event, trigger, **kwargs):
edgeapi = utils.NeutronDbClient()
net_list = nsxv_db.get_nsxv_internal_network(
config.register_nsxv_azs(cfg.CONF, cfg.CONF.nsxv.availability_zones)
conf_az = nsx_az.ConfiguredAvailabilityZones()
az_list = conf_az.list_availability_zones()
for name in az_list:
az = conf_az.get_availability_zone(name)
if az.supports_metadata():
nsx_redo_metadata_cfg_for_az(az, edgeapi)
else:
LOG.info(_LI("Skipping availability zone: %s - no metadata "
"configuration"), az.name)
def nsx_redo_metadata_cfg_for_az(az, edgeapi):
LOG.info(_LI("Updating MetaData for availability zone: %s"), az.name)
# Get the list of internal networks for this AZ
db_net = nsxv_db.get_nsxv_internal_network(
edgeapi.context.session,
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE)
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE,
az.name)
internal_net = None
internal_subnet = None
if net_list:
internal_net = net_list[0]['network_id']
if db_net:
internal_net = db_net['network_id']
internal_subnet = edgeapi.context.session.query(
models_v2.Subnet).filter_by(
network_id=internal_net).first().get('id')
# Get the list of internal edges for this AZ
edge_list = nsxv_db.get_nsxv_internal_edges_by_purpose(
edgeapi.context.session,
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE)
edge_az_list = [edge for edge in edge_list if
nsxv_db.get_router_availability_zone(
edgeapi.context.session, edge['router_id']) == az.name]
md_rtr_ids = [edge['router_id'] for edge in edge_list]
md_rtr_ids = [edge['router_id'] for edge in edge_az_list]
edge_internal_ips = []
for edge in edge_list:
for edge in edge_az_list:
edge_internal_port = edgeapi.context.session.query(
models_v2.Port).filter_by(network_id=internal_net,
device_id=edge['router_id']).first()
@ -79,7 +103,8 @@ def nsx_redo_metadata_cfg(resource, event, trigger, **kwargs):
router_bindings = nsxv_db.get_nsxv_router_bindings(
edgeapi.context.session,
filters={'edge_type': [nsxv_constants.SERVICE_EDGE]})
filters={'edge_type': [nsxv_constants.SERVICE_EDGE],
'availability_zones': az.name})
edge_ids = list(set([binding['edge_id'] for binding in router_bindings
if (binding['router_id'] not in set(md_rtr_ids)
and not binding['router_id'].startswith(

View File

@ -110,10 +110,11 @@ def nsx_recreate_router_edge(resource, event, trigger, **kwargs):
# Go over all the relevant routers
for router in routers:
router_id = router['id']
az_name = router['availability_zone']
# clean up other objects related to this router
if plugin.metadata_proxy_handler:
plugin.metadata_proxy_handler.cleanup_router_edge(
context, router_id)
md_proxy = plugin.get_metadata_proxy_handler(az_name)
md_proxy.cleanup_router_edge(context, router_id)
# attach the router to a new edge
appliance_size = router.get(routersize.ROUTER_SIZE)

View File

@ -34,11 +34,23 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
self.group_name = 'az:%s' % self.az_name
config.register_nsxv_azs(cfg.CONF, [self.az_name])
cfg.CONF.set_override("ha_placement_random", True, group="nsxv")
cfg.CONF.set_override("mgt_net_proxy_ips", ["2.2.2.2"], group="nsxv")
cfg.CONF.set_override("dvs_id", "dvs-1", group="nsxv")
def _config_az(self, resource_pool_id="respool", datastore_id="datastore",
edge_ha=True, ha_datastore_id="hastore",
def _config_az(self,
resource_pool_id="respool",
datastore_id="datastore",
edge_ha=True,
ha_datastore_id="hastore",
backup_edge_pool=DEF_AZ_POOL,
ha_placement_random=False,
backup_edge_pool=DEF_AZ_POOL):
mgt_net_moid="portgroup-407",
mgt_net_proxy_ips=["1.1.1.1"],
mgt_net_proxy_netmask="255.255.255.0",
mgt_net_default_gateway="2.2.2.2",
external_network="network-17",
vdn_scope_id="vdnscope-1",
dvs_id="dvs-2"):
cfg.CONF.set_override("resource_pool_id", resource_pool_id,
group=self.group_name)
cfg.CONF.set_override("datastore_id", datastore_id,
@ -55,6 +67,29 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
if backup_edge_pool is not None:
cfg.CONF.set_override("backup_edge_pool", backup_edge_pool,
group=self.group_name)
if mgt_net_moid is not None:
cfg.CONF.set_override("mgt_net_moid", mgt_net_moid,
group=self.group_name)
if mgt_net_proxy_ips is not None:
cfg.CONF.set_override("mgt_net_proxy_ips", mgt_net_proxy_ips,
group=self.group_name)
if mgt_net_proxy_netmask is not None:
cfg.CONF.set_override("mgt_net_proxy_netmask",
mgt_net_proxy_netmask,
group=self.group_name)
if mgt_net_default_gateway is not None:
cfg.CONF.set_override("mgt_net_default_gateway",
mgt_net_default_gateway,
group=self.group_name)
if external_network is not None:
cfg.CONF.set_override("external_network", external_network,
group=self.group_name)
if vdn_scope_id is not None:
cfg.CONF.set_override("vdn_scope_id", vdn_scope_id,
group=self.group_name)
if dvs_id is not None:
cfg.CONF.set_override("dvs_id", dvs_id,
group=self.group_name)
def test_simple_availability_zone(self):
self._config_az()
@ -62,10 +97,18 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertTrue(az.edge_ha)
self.assertEqual("hastore", az.ha_datastore_id)
self.assertEqual(False, az.ha_placement_random)
self.assertFalse(az.ha_placement_random)
self.assertEqual(DEF_AZ_POOL, az.backup_edge_pool)
self.assertEqual("portgroup-407", az.mgt_net_moid)
self.assertEqual(["1.1.1.1"], az.mgt_net_proxy_ips)
self.assertEqual("255.255.255.0", az.mgt_net_proxy_netmask)
self.assertEqual("2.2.2.2", az.mgt_net_default_gateway)
self.assertEqual("network-17", az.external_network)
self.assertEqual("vdnscope-1", az.vdn_scope_id)
self.assertEqual("dvs-2", az.dvs_id)
self.assertTrue(az.az_metadata_support)
def test_availability_zone_no_edge_ha(self):
self._config_az(edge_ha=False)
@ -73,9 +116,9 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(False, az.edge_ha)
self.assertEqual(None, az.ha_datastore_id)
self.assertEqual(False, az.ha_placement_random)
self.assertFalse(az.edge_ha)
self.assertIsNone(az.ha_datastore_id)
self.assertFalse(az.ha_placement_random)
def test_availability_zone_no_ha_datastore(self):
self._config_az(ha_datastore_id=None)
@ -83,9 +126,9 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertEqual(None, az.ha_datastore_id)
self.assertEqual(False, az.ha_placement_random)
self.assertTrue(az.edge_ha)
self.assertIsNone(az.ha_datastore_id)
self.assertFalse(az.ha_placement_random)
def test_missing_group_section(self):
self.assertRaises(
@ -113,9 +156,9 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(False, az.edge_ha)
self.assertEqual(None, az.ha_datastore_id)
self.assertEqual(False, az.ha_placement_random)
self.assertFalse(az.edge_ha)
self.assertIsNone(az.ha_datastore_id)
self.assertFalse(az.ha_placement_random)
def test_availability_zone_missing_edge_placement(self):
self._config_az(ha_placement_random=None)
@ -123,10 +166,10 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertTrue(az.edge_ha)
self.assertEqual("hastore", az.ha_datastore_id)
# ha_placement_random should have the global value
self.assertEqual(True, az.ha_placement_random)
self.assertTrue(az.ha_placement_random)
def test_availability_zone_missing_backup_pool(self):
self._config_az(backup_edge_pool=None)
@ -135,6 +178,28 @@ class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
# Should use the global configuration instead
self.assertEqual(DEF_GLOBAL_POOL, az.backup_edge_pool)
def test_availability_zone_missing_metadata(self):
self._config_az(mgt_net_proxy_ips=None)
az = nsx_az.ConfiguredAvailabilityZone(self.az_name)
self.assertIsNone(az.mgt_net_moid)
self.assertEqual([], az.mgt_net_proxy_ips)
self.assertIsNone(az.mgt_net_proxy_netmask)
self.assertIsNone(az.mgt_net_default_gateway)
self.assertFalse(az.az_metadata_support)
def test_availability_zone_same_metadata(self):
self._config_az(mgt_net_proxy_ips=["2.2.2.2"])
self.assertRaises(
nsx_exc.NsxInvalidConfiguration,
nsx_az.ConfiguredAvailabilityZone,
self.az_name)
self._config_az(mgt_net_proxy_ips=["2.2.2.2", "3.3.3.3"])
self.assertRaises(
nsx_exc.NsxInvalidConfiguration,
nsx_az.ConfiguredAvailabilityZone,
self.az_name)
class NsxvAvailabilityZonesOldTestCase(base.BaseTestCase):
"""Test old way of configuring the availability zones
@ -142,16 +207,31 @@ class NsxvAvailabilityZonesOldTestCase(base.BaseTestCase):
using a one-line configuration instead of different dynamic sections
"""
def setUp(self):
super(NsxvAvailabilityZonesOldTestCase, self).setUp()
cfg.CONF.set_override("mgt_net_proxy_ips", ["2.2.2.2"], group="nsxv")
cfg.CONF.set_override("dvs_id", "dvs-1", group="nsxv")
def test_simple_availability_zone(self):
az = nsx_az.ConfiguredAvailabilityZone(
"name:respool:datastore:true:hastore")
self.assertEqual("name", az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertTrue(az.edge_ha)
self.assertEqual("hastore", az.ha_datastore_id)
self.assertEqual(False, az.ha_placement_random)
self.assertFalse(az.ha_placement_random)
self.assertEqual(DEF_GLOBAL_POOL, az.backup_edge_pool)
# should get the global configuration (which is empty now)
self.assertIsNone(az.external_network)
self.assertIsNone(az.vdn_scope_id)
self.assertEqual("dvs-1", az.dvs_id)
# no metadata per az support
self.assertFalse(az.az_metadata_support)
self.assertIsNone(az.mgt_net_moid)
self.assertEqual([], az.mgt_net_proxy_ips)
self.assertIsNone(az.mgt_net_proxy_netmask)
self.assertIsNone(az.mgt_net_default_gateway)
def test_availability_zone_without_ha_datastore(self):
az = nsx_az.ConfiguredAvailabilityZone(
@ -159,7 +239,7 @@ class NsxvAvailabilityZonesOldTestCase(base.BaseTestCase):
self.assertEqual("name", az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertTrue(az.edge_ha)
self.assertIsNone(az.ha_datastore_id)
def test_availability_zone_without_edge_ha(self):
@ -168,7 +248,7 @@ class NsxvAvailabilityZonesOldTestCase(base.BaseTestCase):
self.assertEqual("name", az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(False, az.edge_ha)
self.assertFalse(az.edge_ha)
self.assertIsNone(az.ha_datastore_id)
def test_availability_fail_long_name(self):

View File

@ -176,6 +176,9 @@ class NsxVPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
plugin_instance.real_get_edge = plugin_instance._get_edge_id_by_rtr_id
plugin_instance._get_edge_id_by_rtr_id = mock.Mock()
plugin_instance._get_edge_id_by_rtr_id.return_value = False
plugin_instance._get_edge_id_and_az_by_rtr_id = mock.Mock()
plugin_instance._get_edge_id_and_az_by_rtr_id.return_value = (
False, False)
plugin_instance.edge_manager.is_dhcp_opt_enabled = True
# call init_complete manually. The event is not called in unit tests
plugin_instance.init_complete(None, None, {})
@ -505,26 +508,28 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
def test_get_dvs_ids_for_multiple_dvs_vlan_network(self):
p = directory.get_plugin()
default_dvs = 'fake_dvs_id'
# If no DVS-ID is provided as part of physical network, return
# global DVS-ID configured in nsx.ini
physical_network = constants.ATTR_NOT_SPECIFIED
self.assertEqual(['fake_dvs_id'], p._get_dvs_ids(physical_network))
self.assertEqual(['fake_dvs_id'], p._get_dvs_ids(
physical_network, default_dvs))
# If DVS-IDs are provided as part of physical network as a comma
# separated string, return them as a list of DVS-IDs.
physical_network = 'dvs-1,dvs-2, dvs-3'
expected_dvs_ids = ['dvs-1', 'dvs-2', 'dvs-3']
self.assertEqual(expected_dvs_ids,
sorted(p._get_dvs_ids(physical_network)))
sorted(p._get_dvs_ids(physical_network, default_dvs)))
# Ignore extra commas ',' in the physical_network attribute.
physical_network = ',,,dvs-1,dvs-2,, dvs-3,'
expected_dvs_ids = ['dvs-1', 'dvs-2', 'dvs-3']
self.assertEqual(expected_dvs_ids,
sorted(p._get_dvs_ids(physical_network)))
sorted(p._get_dvs_ids(physical_network, default_dvs)))
# Ignore duplicate DVS-IDs in the physical_network attribute.
physical_network = ',,,dvs-1,dvs-2,, dvs-2,'
expected_dvs_ids = ['dvs-1', 'dvs-2']
self.assertEqual(expected_dvs_ids,
sorted(p._get_dvs_ids(physical_network)))
sorted(p._get_dvs_ids(physical_network, default_dvs)))
def test_create_vxlan_with_tz_provider_network(self):
name = 'provider_net_vxlan'
@ -3311,6 +3316,9 @@ class NsxVTestSecurityGroup(ext_sg.TestSecurityGroups,
plugin_instance = directory.get_plugin()
plugin_instance._get_edge_id_by_rtr_id = mock.Mock()
plugin_instance._get_edge_id_by_rtr_id.return_value = False
plugin_instance._get_edge_id_and_az_by_rtr_id = mock.Mock()
plugin_instance._get_edge_id_and_az_by_rtr_id.return_value = (
False, False)
def test_list_ports_security_group(self):
with self.network() as n:

View File

@ -249,7 +249,7 @@ class FakeVcns(object):
response = {
'label': 'vNic_1',
'name': 'internal1',
'address_groups': {'address_groups': []},
'addressGroups': {'addressGroups': []},
'mtu': 1500,
'type': 'trunk',
'subInterfaces': {'subInterfaces': []},