vmware-nsx/vmware_nsx/plugins/nsx_v/md_proxy.py
Kobi Samoray 7a39f6f524 NSXv: Resolve FWaaS-LBaaS conflict
While using nsxv_use_routers_as_lbaas_platform option, FWaaS rules do
not apply to LBaaS VIPs because of metadata's VSERule.

Change-Id: If09a3f2cc445cb6867c6dd0f389f9105471a3cde
2019-04-28 13:53:03 +00:00

786 lines
31 KiB
Python

# Copyright 2014 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 hashlib
import hmac
import eventlet
import netaddr
from neutron_lib import constants
from neutron_lib import context as neutron_context
from neutron_lib.plugins import directory
from oslo_config import cfg
from oslo_log import log as logging
from vmware_nsx._i18n import _
from vmware_nsx.common import exceptions as nsxv_exc
from vmware_nsx.common import locking
from vmware_nsx.common import nsxv_constants
from vmware_nsx.common import utils
from vmware_nsx.db import nsxv_db
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.plugins.nsx_v.vshield import (
nsxv_loadbalancer as nsxv_lb)
from vmware_nsx.plugins.nsx_v.vshield.common import (
constants as vcns_const)
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
from vmware_nsx.services.lbaas.nsx_v import lbaas_common
METADATA_POOL_NAME = 'MDSrvPool'
METADATA_VSE_NAME = 'MdSrv'
METADATA_IP_ADDR = '169.254.169.254'
METADATA_TCP_PORT = 80
METADATA_HTTPS_PORT = 443
METADATA_HTTPS_VIP_PORT = 8775
INTERNAL_SUBNET = '169.254.128.0/17'
MAX_INIT_THREADS = 3
NET_WAIT_INTERVAL = 240
NET_CHECK_INTERVAL = 10
EDGE_WAIT_INTERVAL = 900
EDGE_CHECK_INTERVAL = 10
LOG = logging.getLogger(__name__)
DEFAULT_EDGE_FIREWALL_RULE = {
'name': 'VSERule',
'enabled': True,
'action': 'allow',
'source_vnic_groups': ['vse'],
'destination_vnic_groups': ['external']}
def get_router_fw_rules():
# build the allowed destination ports list
int_ports = [METADATA_TCP_PORT,
METADATA_HTTPS_PORT,
METADATA_HTTPS_VIP_PORT]
str_ports = [str(p) for p in int_ports]
# the list of ports can be extended by configuration
if cfg.CONF.nsxv.metadata_service_allowed_ports:
str_metadata_ports = [str(p) for p in
cfg.CONF.nsxv.metadata_service_allowed_ports]
str_ports = str_ports + str_metadata_ports
separator = ','
dest_ports = separator.join(str_ports)
fw_rules = [
DEFAULT_EDGE_FIREWALL_RULE,
{
'name': 'MDServiceIP',
'enabled': True,
'action': 'allow',
'destination_ip_address': [METADATA_IP_ADDR],
'protocol': 'tcp',
'destination_port': dest_ports
},
{
'name': 'VSEMDInterEdgeNet',
'enabled': True,
'action': 'allow',
'source_vnic_groups': ['vse'],
'destination_ip_address': [INTERNAL_SUBNET]
},
{
'name': 'MDInterEdgeNet',
'enabled': True,
'action': 'deny',
'destination_ip_address': [INTERNAL_SUBNET]
}]
return fw_rules
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:
# 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):
"""A metadata proxy handler for a specific availability zone"""
def __init__(self, nsxv_plugin, availability_zone):
LOG.debug('Initializing metadata for availability zone %s',
availability_zone.name)
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'):
# if the core plugin is the TVD - we need to add project
# plugin mapping for the internal project
core_plugin = directory.get_plugin()
if core_plugin.is_tvd_plugin():
try:
core_plugin.create_project_plugin_map(
context,
{'project_plugin_map':
{'plugin': projectpluginmap.NsxPlugins.NSX_V,
'project': nsxv_constants.INTERNAL_TENANT_ID}},
internal=True)
except projectpluginmap.ProjectPluginAlreadyExists:
pass
self.internal_net, self.internal_subnet = (
self._get_internal_network_and_subnet(context))
LOG.debug('Metadata internal net for AZ %(az)s is %(net)s, '
'subnet is %(sub)s',
{'az': availability_zone.name,
'net': self.internal_net,
'sub': self.internal_subnet})
self.proxy_edge_ips = self._get_proxy_edges(context)
LOG.debug('Metadata proxy internal IPs for AZ %(az)s is '
'%(addresses)s', {'az': availability_zone.name,
'addresses': self.proxy_edge_ips})
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_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)
subnet_data = {'subnet':
{'cidr': cidr,
'name': 'inter-edge-subnet',
'gateway_ip': constants.ATTR_NOT_SPECIFIED,
'allocation_pools': constants.ATTR_NOT_SPECIFIED,
'ip_version': 4,
'dns_nameservers': constants.ATTR_NOT_SPECIFIED,
'host_routes': constants.ATTR_NOT_SPECIFIED,
'enable_dhcp': False,
'network_id': net['id'],
'tenant_id': tenant_id}}
subnet = self.nsxv_plugin.create_subnet(
context,
subnet_data)
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_for_az(
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):
# Try to find internal net, internal subnet. If not found, create new
internal_net = self._get_internal_net_by_az(context)
internal_subnet = None
if internal_net:
internal_subnet = self.nsxv_plugin.get_subnets(
context,
fields=['id'],
filters={'network_id': [internal_net]})[0]['id']
if internal_net is None or internal_subnet is None:
if cfg.CONF.nsxv.metadata_initializer:
# Couldn't find net, subnet - create new
try:
internal_net, internal_subnet = (
self._create_metadata_internal_network(
context, INTERNAL_SUBNET))
except Exception as e:
nsxv_db.delete_nsxv_internal_network(
context.session,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE,
internal_net)
# if network is created, clean up
if internal_net:
self.nsxv_plugin.delete_network(context,
internal_net)
error = (_("Exception %s while creating internal "
"network for metadata service") % e)
LOG.exception(error)
raise nsxv_exc.NsxPluginException(err_msg=error)
# Update the new network_id in DB
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 '
'initializer node')
raise nsxv_exc.NsxPluginException(err_msg=error)
return internal_net, internal_subnet
def _get_edge_internal_ip(self, context, rtr_id):
filters = {
'network_id': [self.internal_net],
'device_id': [rtr_id]}
ports = self.nsxv_plugin.get_ports(context, filters=filters)
if ports:
return ports[0]['fixed_ips'][0]['ip_address']
else:
LOG.error("No port found for metadata for %s", rtr_id)
def _get_edge_rtr_id_by_ext_ip(self, context, edge_ip):
rtr_list = nsxv_db.get_nsxv_internal_edge(
context.session, edge_ip)
if rtr_list:
return rtr_list[0]['router_id']
def _get_edge_id_by_rtr_id(self, context, rtr_id):
binding = nsxv_db.get_nsxv_router_binding(
context.session,
rtr_id)
if binding:
return binding['edge_id']
def _get_proxy_edges(self, context):
proxy_edge_ips = []
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(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(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(self.az.mgt_net_proxy_ips)))
edge_ip_to_set = (
list(set(self.az.mgt_net_proxy_ips) - set(db_edge_ips)))
if edge_to_convert_ips:
if cfg.CONF.nsxv.metadata_initializer:
for edge_inner_ip in pool.imap(
self._setup_proxy_edge_external_interface_ip,
zip(edge_to_convert_ips, edge_ip_to_set)):
proxy_edge_ips.append(edge_inner_ip)
else:
error = _('Metadata initialization is incomplete on '
'initializer node')
raise nsxv_exc.NsxPluginException(err_msg=error)
# Edges that exist in the CFG list but do not have a matching DB
# element will be created.
remaining_cfg_ips = edge_ip_to_set[len(edge_to_convert_ips):]
if remaining_cfg_ips:
if cfg.CONF.nsxv.metadata_initializer:
for edge_inner_ip in pool.imap(
self._setup_new_proxy_edge, remaining_cfg_ips):
proxy_edge_ips.append(edge_inner_ip)
pool.waitall()
else:
error = _('Metadata initialization is incomplete on '
'initializer node')
raise nsxv_exc.NsxPluginException(err_msg=error)
return proxy_edge_ips
def _setup_proxy_edge_route_and_connectivity(self, rtr_ext_ip,
rtr_id=None, edge_id=None):
# Use separate context per each as we use this in tread context
context = neutron_context.get_admin_context()
if not rtr_id:
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("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:
# This may fail if the edge was deleted on backend
h, routes = self.nsxv_plugin.nsx_v.vcns.get_routes(edge_id)
except exceptions.ResourceNotFound as e:
# log this error and return without the ip, but don't fail
LOG.error("Failed to get routes for metadata proxy edge "
"%(edge)s: %(err)s",
{'edge': edge_id, 'err': e})
return
dgw = routes.get('defaultRoute', {}).get('gatewayAddress')
if dgw != self.az.mgt_net_default_gateway:
if cfg.CONF.nsxv.metadata_initializer:
self.nsxv_plugin._update_routes(
context, rtr_id,
self.az.mgt_net_default_gateway)
else:
error = _('Metadata initialization is incomplete on '
'initializer node')
raise nsxv_exc.NsxPluginException(err_msg=error)
# Read and validate connectivity
h, if_data = self.nsxv_plugin.nsx_v.get_interface(
edge_id, vcns_const.EXTERNAL_VNIC_INDEX)
a_groups = if_data.get('addressGroups', {}).get('addressGroups')
if a_groups:
cur_ip = a_groups[0].get('primaryAddress')
else:
cur_ip = None
cur_pgroup = if_data['portgroupId']
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,
self.az.mgt_net_moid,
address=rtr_ext_ip,
netmask=self.az.mgt_net_proxy_netmask,
secondary=[])
else:
error = _('Metadata initialization is incomplete on '
'initializer node')
raise nsxv_exc.NsxPluginException(err_msg=error)
# Read and validate LB pool member configuration
# When the Nova IP address is changed in the ini file, we should apply
# this change to the LB pool
lb_obj = nsxv_lb.NsxvLoadbalancer.get_loadbalancer(
self.nsxv_plugin.nsx_v.vcns, edge_id)
vs = lb_obj.virtual_servers.get(METADATA_VSE_NAME)
update_md_proxy = False
if vs:
md_members = {member.payload['ipAddress']: member.payload['name']
for member in vs.default_pool.members.values()}
if len(cfg.CONF.nsxv.nova_metadata_ips) == len(md_members):
m_ips = md_members.keys()
m_to_convert = (list(set(m_ips) -
set(cfg.CONF.nsxv.nova_metadata_ips)))
m_ip_to_set = (list(set(cfg.CONF.nsxv.nova_metadata_ips) -
set(m_ips)))
if m_to_convert or m_ip_to_set:
update_md_proxy = True
for m_ip in m_to_convert:
m_name = md_members[m_ip]
vs.default_pool.members[m_name].payload['ipAddress'] = (
m_ip_to_set.pop())
else:
LOG.error('Number of metadata members should not change')
try:
# This may fail if the edge is powered off right now
if update_md_proxy:
lb_obj.submit_to_backend(self.nsxv_plugin.nsx_v.vcns,
edge_id)
except exceptions.RequestBad as e:
# log the error and continue
LOG.error("Failed to update load balancer on metadata "
"proxy edge %(edge)s: %(err)s",
{'edge': edge_id, 'err': e})
edge_ip = self._get_edge_internal_ip(context, rtr_id)
if edge_ip:
return edge_ip
def _setup_proxy_edge_external_interface_ip(self, rtr_ext_ips):
# Use separate context per each as we use this in tread context
context = neutron_context.get_admin_context()
rtr_old_ext_ip, rtr_new_ext_ip = rtr_ext_ips
rtr_id = self._get_edge_rtr_id_by_ext_ip(context, rtr_old_ext_ip)
edge_id = self._get_edge_id_by_rtr_id(context, rtr_id)
# Replace DB entry as we cannot update the table PK
nsxv_db.delete_nsxv_internal_edge(context.session, rtr_old_ext_ip)
edge_ip = self._setup_proxy_edge_route_and_connectivity(
rtr_new_ext_ip, rtr_id, edge_id)
nsxv_db.create_nsxv_internal_edge(
context.session, rtr_new_ext_ip,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE, rtr_id)
if edge_ip:
return edge_ip
def _setup_new_proxy_edge(self, rtr_ext_ip):
# Use separate context per each as we use this in tread context
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': 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(
context,
router_data,
allow_metadata=False)
rtr_id = rtr['id']
edge_id = self._get_edge_id_by_rtr_id(context, rtr_id)
if not edge_id:
LOG.error('No edge create for router - %s', rtr_id)
if rtr_id:
self.nsxv_plugin.delete_router(context, rtr_id)
return
self.nsxv_plugin.nsx_v.update_interface(
rtr['id'],
edge_id,
vcns_const.EXTERNAL_VNIC_INDEX,
self.az.mgt_net_moid,
address=rtr_ext_ip,
netmask=self.az.mgt_net_proxy_netmask,
secondary=[])
port_data = {
'port': {
'network_id': self.internal_net,
'name': None,
'admin_state_up': True,
'device_id': rtr_id,
'device_owner': (constants.DEVICE_OWNER_NETWORK_PREFIX +
'md_interface'),
'fixed_ips': constants.ATTR_NOT_SPECIFIED,
'mac_address': constants.ATTR_NOT_SPECIFIED,
'port_security_enabled': False,
'tenant_id': nsxv_constants.INTERNAL_TENANT_ID}}
port = self.nsxv_plugin.base_create_port(context, port_data)
address_groups = self._get_address_groups(
context, self.internal_net, rtr_id, is_proxy=True)
edge_ip = port['fixed_ips'][0]['ip_address']
with locking.LockManager.get_lock(edge_id):
edge_utils.update_internal_interface(
self.nsxv_plugin.nsx_v, context, rtr_id,
self.internal_net, address_groups)
self._setup_metadata_lb(rtr_id,
port['fixed_ips'][0]['ip_address'],
cfg.CONF.nsxv.nova_metadata_port,
cfg.CONF.nsxv.nova_metadata_port,
cfg.CONF.nsxv.nova_metadata_ips,
proxy_lb=True)
firewall_rules = [
DEFAULT_EDGE_FIREWALL_RULE,
{
'action': 'allow',
'enabled': True,
'source_ip_address': [INTERNAL_SUBNET]}]
edge_utils.update_firewall(
self.nsxv_plugin.nsx_v,
context,
rtr_id,
{'firewall_rule_list': firewall_rules},
allow_external=False)
if self.az.mgt_net_default_gateway:
self.nsxv_plugin._update_routes(
context, rtr_id,
self.az.mgt_net_default_gateway)
nsxv_db.create_nsxv_internal_edge(
context.session, rtr_ext_ip,
vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE, rtr_id)
return edge_ip
except Exception as e:
LOG.exception("Exception %s while creating internal edge "
"for metadata service", e)
ports = self.nsxv_plugin.get_ports(
context, filters={'device_id': [rtr_id]})
for port in ports:
self.nsxv_plugin.delete_port(context, port['id'],
l3_port_check=True,
nw_gw_port_check=True,
allow_delete_internal=True)
nsxv_db.delete_nsxv_internal_edge(
context.session,
rtr_ext_ip)
if rtr_id:
self.nsxv_plugin.delete_router(context, rtr_id)
def _get_address_groups(self, context, network_id, device_id, is_proxy):
filters = {'network_id': [network_id],
'device_id': [device_id]}
ports = self.nsxv_plugin.get_ports(context, filters=filters)
subnets = self.nsxv_plugin.get_subnets(context, filters=filters)
address_groups = []
for subnet in subnets:
address_group = {}
net = netaddr.IPNetwork(subnet['cidr'])
address_group['subnetMask'] = str(net.netmask)
address_group['subnetPrefixLength'] = str(net.prefixlen)
for port in ports:
fixed_ips = port['fixed_ips']
for fip in fixed_ips:
s_id = fip['subnet_id']
ip_addr = fip['ip_address']
if s_id == subnet['id'] and netaddr.valid_ipv4(ip_addr):
address_group['primaryAddress'] = ip_addr
break
# For Edge appliances which aren't the metadata proxy Edge
# we add the metadata IP address
if not is_proxy and network_id == self.internal_net:
address_group['secondaryAddresses'] = {
'type': 'secondary_addresses',
'ipAddress': [METADATA_IP_ADDR]}
address_groups.append(address_group)
return address_groups
def _create_ssl_cert(self, edge_id=None):
# Create a self signed certificate in the backend if both Cert details
# and private key are not supplied in nsx.ini
if (not cfg.CONF.nsxv.metadata_nova_client_cert and
not cfg.CONF.nsxv.metadata_nova_client_priv_key):
h = self.nsxv_plugin.nsx_v.vcns.create_csr(edge_id)[0]
# Extract the CSR ID from header
csr_id = lbaas_common.extract_resource_id(h['location'])
# Create a self signed certificate
cert = self.nsxv_plugin.nsx_v.vcns.create_csr_cert(csr_id)[1]
cert_id = cert['objectId']
else:
# Raise an error if either the Cert path or the private key is not
# configured
error = None
if not cfg.CONF.nsxv.metadata_nova_client_cert:
error = _('Metadata certificate path not configured')
elif not cfg.CONF.nsxv.metadata_nova_client_priv_key:
error = _('Metadata client private key not configured')
if error:
raise nsxv_exc.NsxPluginException(err_msg=error)
pem_encoding = utils.read_file(
cfg.CONF.nsxv.metadata_nova_client_cert)
priv_key = utils.read_file(
cfg.CONF.nsxv.metadata_nova_client_priv_key)
request = {
'pemEncoding': pem_encoding,
'privateKey': priv_key}
cert = self.nsxv_plugin.nsx_v.vcns.upload_edge_certificate(
edge_id, request)[1]
cert_id = cert.get('certificates')[0]['objectId']
return cert_id
def _setup_metadata_lb(self, rtr_id, vip, v_port, s_port, member_ips,
proxy_lb=False, context=None):
if context is None:
context = neutron_context.get_admin_context()
edge_id = self._get_edge_id_by_rtr_id(context, rtr_id)
LOG.debug('Setting up Edge device %s', edge_id)
lb_obj = nsxv_lb.NsxvLoadbalancer()
protocol = 'HTTP'
ssl_pass_through = False
cert_id = None
# Set protocol to HTTPS with default port of 443 if metadata_insecure
# is set to False.
if not cfg.CONF.nsxv.metadata_insecure:
protocol = 'HTTPS'
if proxy_lb:
v_port = METADATA_HTTPS_VIP_PORT
else:
v_port = METADATA_HTTPS_PORT
# Create the certificate on the backend
cert_id = self._create_ssl_cert(edge_id)
ssl_pass_through = proxy_lb
mon_type = protocol if proxy_lb else 'tcp'
# Create virtual server
virt_srvr = nsxv_lb.NsxvLBVirtualServer(
name=METADATA_VSE_NAME,
ip_address=vip,
protocol=protocol,
port=v_port)
# For router Edge, we add X-LB-Proxy-ID header
if not proxy_lb:
md_app_rule = nsxv_lb.NsxvLBAppRule(
'insert-mdp',
'reqadd X-Metadata-Provider:' + edge_id)
virt_srvr.add_app_rule(md_app_rule)
# When shared proxy is configured, insert authentication string
if cfg.CONF.nsxv.metadata_shared_secret:
signature = hmac.new(
bytearray(cfg.CONF.nsxv.metadata_shared_secret, 'ascii'),
bytearray(edge_id, 'ascii'),
hashlib.sha256).hexdigest()
sign_app_rule = nsxv_lb.NsxvLBAppRule(
'insert-auth',
'reqadd X-Metadata-Provider-Signature:' + signature)
virt_srvr.add_app_rule(sign_app_rule)
# Create app profile
# XFF is inserted in router LBs
app_profile = nsxv_lb.NsxvLBAppProfile(
name='MDSrvProxy',
template=protocol,
server_ssl_enabled=not cfg.CONF.nsxv.metadata_insecure,
ssl_pass_through=ssl_pass_through,
insert_xff=not proxy_lb,
client_ssl_cert=cert_id)
virt_srvr.set_app_profile(app_profile)
# Create pool, members and monitor
pool = nsxv_lb.NsxvLBPool(
name=METADATA_POOL_NAME)
monitor = nsxv_lb.NsxvLBMonitor(name='MDSrvMon',
mon_type=mon_type.lower())
pool.add_monitor(monitor)
i = 0
for member_ip in member_ips:
i += 1
member = nsxv_lb.NsxvLBPoolMember(
name='Member-%d' % i,
ip_address=member_ip,
port=s_port,
monitor_port=s_port)
pool.add_member(member)
virt_srvr.set_default_pool(pool)
lb_obj.add_virtual_server(virt_srvr)
lb_obj.submit_to_backend(self.nsxv_plugin.nsx_v.vcns, edge_id)
def configure_router_edge(self, context, rtr_id):
LOG.debug('Configuring metadata infrastructure for %s', rtr_id)
ctx = neutron_context.get_admin_context()
# Connect router interface to inter-edge network
port_data = {
'port': {
'network_id': self.internal_net,
'name': None,
'admin_state_up': True,
'device_id': rtr_id,
'device_owner': constants.DEVICE_OWNER_ROUTER_GW,
'fixed_ips': constants.ATTR_NOT_SPECIFIED,
'mac_address': constants.ATTR_NOT_SPECIFIED,
'port_security_enabled': False,
'tenant_id': nsxv_constants.INTERNAL_TENANT_ID}}
self.nsxv_plugin.base_create_port(ctx, port_data)
address_groups = self._get_address_groups(
ctx,
self.internal_net,
rtr_id,
is_proxy=False)
edge_utils.update_internal_interface(
self.nsxv_plugin.nsx_v,
context,
rtr_id,
self.internal_net,
address_groups=address_groups)
self._setup_metadata_lb(rtr_id,
METADATA_IP_ADDR,
METADATA_TCP_PORT,
cfg.CONF.nsxv.nova_metadata_port,
self.proxy_edge_ips,
proxy_lb=False,
context=context)
def cleanup_router_edge(self, context, rtr_id, warn=False):
filters = {
'network_id': [self.internal_net],
'device_id': [rtr_id]}
ctx = context.elevated()
ports = self.nsxv_plugin.get_ports(ctx, filters=filters)
if ports:
if warn:
LOG.warning("cleanup_router_edge found port %(port)s for "
"router %(router)s - deleting it now.",
{'port': ports[0]['id'], 'router': rtr_id})
try:
self.nsxv_plugin.delete_port(
ctx, ports[0]['id'],
l3_port_check=False,
allow_delete_internal=True)
except Exception as e:
LOG.error("Failed to delete md_proxy port %(port)s: "
"%(e)s", {'port': ports[0]['id'], 'e': e})
def is_md_subnet(self, subnet_id):
return self.internal_subnet == subnet_id