asarfaty 50afa71853 Fix broken Victoria branch
1.Upgrade pylint to 2.4.4, add exclusions to the tests, and
  fix some lint errors in the code

2. Fix user creation with GRANT in MySQL 8.0(Ubuntu Focal)
In Ubuntu Bionic (18.04) mysql 5.7 version used to create
the user implicitly when using using the GRANT.
Ubuntu Focal (20.04) has mysql 8.0 and with mysql 8.0 there
is no implicit user creation with GRANT. We need to
create the user first before using GRANT command.
See also commit I97b0dcbb88c6ef7c22e3c55970211bed792bbd0d

3. Remove fwaas from the zuul.yaml
4. Remove DB migration test which is failing ue to FWaaS migration
with py38
5. Fix cover tests python version in .tox
6. fix requirememnts

Change-Id: I22654a5d5ccaad3185ae3365a90afba1ce870695
2020-09-21 15:31:18 +02:00

435 lines
17 KiB
Python

# Copyright 2016 VMware, Inc.
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import hashlib
import hmac
from neutron.db import models_v2
from neutron_lib.callbacks import registry
from oslo_config import cfg
from oslo_log import log as logging
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
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
from vmware_nsx.shell.admin.plugins.nsxv.resources import utils
from vmware_nsx.shell import resources as shell
INTERNAL_SUBNET = '169.254.128.0/17'
NSXV_MD_RULES = [
{
'name': 'VSERule',
'enabled': True,
'action': 'accept',
'source_vnic_groups': ['vse'],
'destination_vnic_groups': ['external']},
{
'name': 'MDServiceIP',
'destination': {'ipAddress': ['169.254.169.254']},
'enabled': True,
'application': {'service': [{'protocol': 'tcp',
'port': [80, 443, 8775]}]},
'action': 'accept',
'ruleTag': None},
{
'name': 'VSEMDInterEdgeNet',
'enabled': True,
'action': 'accept',
'source_vnic_groups': ['vse'],
'destination_ip_address': [INTERNAL_SUBNET]},
{
'name': 'MDInterEdgeNet',
'destination': {'ipAddress': ['169.254.128.0/17']},
'enabled': True,
'action': 'deny',
'ruleTag': None}]
LOG = logging.getLogger(__name__)
nsxv = utils.get_nsxv_client()
def _append_md_fw_rules(fw_rules):
fw_rules = NSXV_MD_RULES + fw_rules
# Set FW rules tags
for i in range(len(fw_rules)):
fw_rules[i]['ruleTag'] = i + 1
return fw_rules
def _handle_edge_firewall_rules(edge_id):
try:
h, fw_cfg = nsxv.get_firewall(edge_id)
except Exception as e:
fw_cfg = {}
LOG.error("Failed to retrieve firewall config for edge %(edge)s "
"with exception %(e)s", {'edge': edge_id, 'e': e})
fw_rules = fw_cfg.get('firewallRules', {}).get('firewallRules', [])
md_rule_names = ['MDInterEdgeNet',
'MDServiceIP',
'VSEMDInterEdgeNet',
'VSERule']
new_rules = []
for rule in fw_rules:
if rule['name'] in md_rule_names:
md_rule_names.remove(rule['name'])
else:
new_rules.append(rule)
if md_rule_names:
new_rules = _append_md_fw_rules(new_rules)
fw_cfg['firewallRules']['firewallRules'] = new_rules
try:
nsxv.update_firewall(edge_id, fw_cfg)
LOG.info('Added missing firewall rules for edge %s', edge_id)
except Exception as e:
LOG.warning("Failed to update firewall config for edge "
"%(edge)s with exception %(e)s",
{'edge': edge_id, 'e': e})
def _recreate_rtr_metadata_cfg(context, plugin, az_name, edge_id):
rtr_binding = nsxv_db.get_nsxv_router_binding_by_edge(
context.session, edge_id)
md_handler = plugin.metadata_proxy_handler[az_name]
if md_handler:
try:
md_handler.configure_router_edge(
context, rtr_binding['router_id'])
LOG.info('Added metadata components for edge %s',
edge_id)
except Exception as e:
LOG.error('Recreation of metadata components for edge '
'%(edge)s failed with error %(e)s',
{'edge': edge_id, 'e': e})
else:
LOG.error('Could not find a metadata handler for availability zone %s',
az_name)
def _update_md_lb_members(edge_id, edge_internal_ips, lb, pool):
LOG.info('Updating metadata members for edge %s', edge_id)
pool.members = {}
i = 0
s_port = cfg.CONF.nsxv.nova_metadata_port
for member_ip in edge_internal_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)
try:
lb.submit_to_backend(nsxv, edge_id)
LOG.info('Updated members for %s', edge_id)
except Exception as e:
LOG.error('Updating members for %(edge)s failed with '
'error %(e)s', {'edge': edge_id, 'e': e})
def _get_internal_edge_ips(context, az_name):
# Get the list of internal networks for this AZ
db_net = nsxv_db.get_nsxv_internal_network_for_az(
context.session,
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE,
az_name)
internal_net = None
internal_subnet = None
if db_net:
internal_net = db_net['network_id']
internal_subnet = 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(
context.session,
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE)
edge_az_list = [edge for edge in edge_list if
nsxv_db.get_router_availability_zone(
context.session, edge['router_id']) == az_name]
md_rtr_ids = [edge['router_id'] for edge in edge_az_list]
edge_internal_ips = []
for edge in edge_az_list:
edge_internal_port = context.session.query(
models_v2.Port).filter_by(network_id=internal_net,
device_id=edge['router_id']).first()
if edge_internal_port:
edge_internal_ip = context.session.query(
models_v2.IPAllocation).filter_by(
port_id=edge_internal_port['id']).first()
edge_internal_ips.append(edge_internal_ip['ip_address'])
if not internal_net or not internal_subnet or not edge_internal_ips:
return None, None
LOG.info('Metadata proxy internal IPs are %s', edge_internal_ips)
return edge_internal_ips, md_rtr_ids
def _handle_edge(context, plugin, az_name, edge_id, edge_internal_ips):
with locking.LockManager.get_lock(edge_id):
lb = nsxv_lb.NsxvLoadbalancer.get_loadbalancer(nsxv, edge_id)
virt = lb.virtual_servers.get(md_proxy.METADATA_VSE_NAME)
if virt:
pool = virt.default_pool
curr_member_ips = [member.payload['ipAddress'] for member in
pool.members.values()]
if set(curr_member_ips) != set(edge_internal_ips):
_update_md_lb_members(edge_id, edge_internal_ips, lb, pool)
else:
# Interface connectivity and LB definition are done at the same
# operation. if LB is missing then interface should be missing
# as well
LOG.info('Metadata LB components for edge %s are missing',
edge_id)
_recreate_rtr_metadata_cfg(context, plugin, az_name, edge_id)
_handle_edge_firewall_rules(edge_id)
@admin_utils.output_header
def nsx_redo_metadata_cfg(resource, event, trigger, **kwargs):
properties = admin_utils.parse_multi_keyval_opt(kwargs.get('property'))
edgeapi = utils.NeutronDbClient()
plugin = utils.NsxVPluginWrapper()
edge_id = properties.get('edge-id')
if properties:
if edge_id:
nsx_redo_metadata_cfg_for_edge(edgeapi.context, plugin, edge_id)
return
else:
# if the net-id property exist - recreate the edge for this network
az_name = properties.get('az-name')
if az_name:
nsx_redo_metadata_cfg_for_az(edgeapi.context, plugin, az_name)
return
LOG.error('Cannot parse properties %s', properties)
return
nsx_redo_metadata_cfg_all(edgeapi.context, plugin)
def nsx_redo_metadata_cfg_for_edge(context, plugin, edge_id):
binding = nsxv_db.get_nsxv_router_binding_by_edge(context.session, edge_id)
if binding:
az_name = binding['availability_zone']
conf_az = nsx_az.NsxVAvailabilityZones()
az = conf_az.availability_zones[az_name]
if not az.supports_metadata():
LOG.error('Edge %(edge)s belongs to az %(az)s which does not '
'support metadata',
{'az': az_name, 'edge': edge_id})
edge_internal_ips, md_rtr_ids = _get_internal_edge_ips(context,
az_name)
if not edge_internal_ips and not md_rtr_ids:
LOG.error("Metadata infrastructure is missing or broken. "
"It is recommended to restart neutron service before "
"proceeding with configuration restoration")
return
if binding['router_id'] in md_rtr_ids:
LOG.error('Edge %s is a metadata proxy', edge_id)
return
if (binding['router_id'].startswith(
vcns_constants.BACKUP_ROUTER_PREFIX) or
binding['router_id'].startswith(
vcns_constants.PLR_EDGE_PREFIX) or
binding['router_id'].startswith(
lb_common.RESOURCE_ID_PFX)):
LOG.error('Edge %s is not a metadata delivery appliance', edge_id)
return
_handle_edge(context, plugin, az_name, edge_id, edge_internal_ips)
else:
LOG.error('No edge binding found for edge %s', edge_id)
@admin_utils.output_header
def nsx_redo_metadata_cfg_all(context, plugin):
user_confirm = admin_utils.query_yes_no("Do you want to setup metadata "
"infrastructure for all the edges",
default="no")
if not user_confirm:
LOG.info("NSXv vnics deletion aborted by user")
return
config.register_nsxv_azs(cfg.CONF, cfg.CONF.nsxv.availability_zones)
conf_az = nsx_az.NsxVAvailabilityZones()
az_list = conf_az.list_availability_zones_objects()
for az in az_list:
if az.supports_metadata():
nsx_redo_metadata_cfg_for_az(context, plugin, az.name, False)
else:
LOG.info("Skipping availability zone: %s - no metadata "
"configuration", az.name)
def nsx_redo_metadata_cfg_for_az(context, plugin, az_name, check_az=True):
LOG.info("Updating MetaData for availability zone: %s", az_name)
if check_az:
conf_az = nsx_az.NsxVAvailabilityZones()
az = conf_az.availability_zones.get(az_name)
if not az:
LOG.error('Availability zone %s not found', az_name)
return
if not az.supports_metadata():
LOG.error('Availability zone %s is not configured with metadata',
az_name)
return
edge_internal_ips, md_rtr_ids = _get_internal_edge_ips(context,
az_name)
if not edge_internal_ips and not md_rtr_ids:
LOG.error("Metadata infrastructure is missing or broken. "
"It is recommended to restart neutron service before "
"proceeding with configuration restoration")
return
router_bindings = nsxv_db.get_nsxv_router_bindings(
context.session,
filters={'edge_type': [nsxv_constants.SERVICE_EDGE],
'availability_zone': [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(
vcns_constants.BACKUP_ROUTER_PREFIX) and
not binding['router_id'].startswith(
vcns_constants.PLR_EDGE_PREFIX) and
not binding['router_id'].startswith(
lb_common.RESOURCE_ID_PFX))]))
for edge_id in edge_ids:
_handle_edge(context, plugin, az_name, edge_id, edge_internal_ips)
@admin_utils.output_header
def update_shared_secret(resource, event, trigger, **kwargs):
edgeapi = utils.NeutronDbClient()
edge_list = nsxv_db.get_nsxv_internal_edges_by_purpose(
edgeapi.context.session,
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE)
md_rtr_ids = [edge['router_id'] for edge in edge_list]
router_bindings = nsxv_db.get_nsxv_router_bindings(
edgeapi.context.session,
filters={'edge_type': [nsxv_constants.SERVICE_EDGE]})
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(
vcns_constants.BACKUP_ROUTER_PREFIX) and
not binding['router_id'].startswith(
vcns_constants.PLR_EDGE_PREFIX))]))
for edge_id in edge_ids:
with locking.LockManager.get_lock(edge_id):
lb = nsxv_lb.NsxvLoadbalancer.get_loadbalancer(nsxv, edge_id)
virt = lb.virtual_servers.get(md_proxy.METADATA_VSE_NAME)
if not virt:
LOG.error("Virtual server not found for edge: %s", edge_id)
continue
virt.del_app_rule('insert-auth')
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 = 'reqadd X-Metadata-Provider-Signature:' + signature
sign_app_rule = nsxv_lb.NsxvLBAppRule('insert-auth', sign)
virt.add_app_rule(sign_app_rule)
lb.submit_to_backend(nsxv, edge_id)
def _md_member_status(title, edge_ids):
for edge_id in edge_ids:
lb_stats = nsxv.get_loadbalancer_statistics(
edge_id)
pools_stats = lb_stats[1].get('pool', [])
members = []
for pool_stats in pools_stats:
if pool_stats['name'] == md_proxy.METADATA_POOL_NAME:
for member in pool_stats.get('member', []):
members.append({'member_ip': member['ipAddress'],
'member_status': member['status']})
LOG.info(formatters.output_formatter(
title % edge_id,
members, ['member_ip', 'member_status']))
@admin_utils.output_header
def get_metadata_status(resource, event, trigger, **kwargs):
if kwargs.get('property'):
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
net_id = properties.get('network_id')
else:
net_id = None
edgeapi = utils.NeutronDbClient()
edge_list = nsxv_db.get_nsxv_internal_edges_by_purpose(
edgeapi.context.session,
vcns_constants.InternalEdgePurposes.INTER_EDGE_PURPOSE)
md_rtr_ids = [edge['router_id'] for edge in edge_list]
router_bindings = nsxv_db.get_nsxv_router_bindings(
edgeapi.context.session,
filters={'router_id': md_rtr_ids})
edge_ids = [b['edge_id'] for b in router_bindings]
_md_member_status('Metadata edge appliance: %s members', edge_ids)
if net_id:
as_provider_data = nsxv_db.get_edge_vnic_bindings_by_int_lswitch(
edgeapi.context.session, net_id)
providers = [asp['edge_id'] for asp in as_provider_data]
if providers:
LOG.info('Metadata providers for network %s', net_id)
_md_member_status('Edge %s', providers)
else:
LOG.info('No providers found for network %s', net_id)
registry.subscribe(nsx_redo_metadata_cfg,
constants.METADATA,
shell.Operations.NSX_UPDATE.value)
registry.subscribe(update_shared_secret,
constants.METADATA,
shell.Operations.NSX_UPDATE_SECRET.value)
registry.subscribe(get_metadata_status, constants.METADATA,
shell.Operations.STATUS.value)