Salvatore Orlando 819c74ef30 Replace occurrences of registry.notify
This change replaces remaining occurences of the notify method with
calls to the publish method.
As NSX admin utilities heavily rely on callbacks, this change also
ensures that all callbacks are now accepting event payloads rather
thank kwargs.

Change-Id: I0450fff486898d6ab74086b7952dc27134cb77e2
2021-10-18 03:24:34 -07:00

296 lines
11 KiB
Python

# Copyright 2015 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.
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters
import vmware_nsx.shell.admin.plugins.common.utils as admin_utils
from vmware_nsx.shell.admin.plugins.nsxv.resources import utils
import vmware_nsx.shell.resources as shell
from neutron_lib.callbacks import registry
from neutron_lib import exceptions
from vmware_nsx.db import nsxv_db
from vmware_nsx.extensions import (
vnicindex as ext_vnic_idx)
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
nsxv = utils.get_nsxv_client()
def get_spoofguard_policies():
nsxv_c = utils.get_nsxv_client()
return nsxv_c.get_spoofguard_policies()[1].get("policies")
def get_spoofguard_policy_data(policy_id):
nsxv_c = utils.get_nsxv_client()
return nsxv_c.get_spoofguard_policy_data(policy_id)[1].get(
'spoofguardList', [])
@admin_utils.output_header
@admin_utils.unpack_payload
def nsx_list_spoofguard_policies(resource, event, trigger, **kwargs):
"""List spoofguard policies from NSXv backend"""
policies = get_spoofguard_policies()
LOG.info(formatters.output_formatter(constants.SPOOFGUARD_POLICY, policies,
['policyId', 'name']))
def get_spoofguard_policy_network_mappings():
spgapi = utils.NeutronDbClient()
return nsxv_db.get_nsxv_spoofguard_policy_network_mappings(
spgapi.context)
@admin_utils.output_header
@admin_utils.unpack_payload
def neutron_list_spoofguard_policy_mappings(resource, event, trigger,
**kwargs):
mappings = get_spoofguard_policy_network_mappings()
LOG.info(formatters.output_formatter(constants.SPOOFGUARD_POLICY, mappings,
['network_id', 'policy_id']))
def get_missing_spoofguard_policy_mappings(reverse=None):
nsxv_spoofguard_policies = set()
for spg in get_spoofguard_policies():
nsxv_spoofguard_policies.add(spg.get('policyId'))
neutron_spoofguard_policy_mappings = set()
for binding in get_spoofguard_policy_network_mappings():
neutron_spoofguard_policy_mappings.add(binding.policy_id)
if reverse:
return nsxv_spoofguard_policies - neutron_spoofguard_policy_mappings
return neutron_spoofguard_policy_mappings - nsxv_spoofguard_policies
@admin_utils.output_header
@admin_utils.unpack_payload
def nsx_list_missing_spoofguard_policies(resource, event, trigger,
**kwargs):
"""List missing spoofguard policies on NSXv.
Spoofguard policies that have a binding in Neutron Db but there is
no policy on NSXv backend to back it.
"""
props = kwargs.get('property')
reverse = bool(props and props[0] == 'reverse')
if reverse:
LOG.info("Spoofguard policies on NSXv but not present in "
"Neutron Db")
else:
LOG.info("Spoofguard policies in Neutron Db but not present "
"on NSXv")
missing_policies = get_missing_spoofguard_policy_mappings(reverse)
if not missing_policies:
LOG.info("\nNo missing spoofguard policies found."
"\nNeutron DB and NSXv backend are in sync\n")
else:
LOG.info(missing_policies)
missing_policies = [{'policy_id': pid} for pid in missing_policies]
LOG.info(formatters.output_formatter(
constants.SPOOFGUARD_POLICY, missing_policies, ['policy_id']))
def get_port_vnic_id(plugin, port):
vnic_idx = port.get(ext_vnic_idx.VNIC_INDEX)
device_id = port.get('device_id')
return plugin._get_port_vnic_id(vnic_idx, device_id)
def nsx_list_mismatch_addresses_for_net(context, plugin, network_id,
policy_id):
policy_data = get_spoofguard_policy_data(policy_id)
missing = []
# Get all neutron compute ports on this network
port_filters = {'network_id': [network_id]}
neutron_ports = plugin.get_ports(context, filters=port_filters)
comp_ports = [port for port in neutron_ports
if port.get('device_owner', '').startswith('compute:')]
for port in comp_ports:
if not port['port_security_enabled']:
# This port is not in spoofguard
continue
error_data = None
port_ips = []
for pair in port.get('allowed_address_pairs'):
port_ips.append(pair['ip_address'])
for fixed in port.get('fixed_ips'):
port_ips.append(fixed['ip_address'])
if not port_ips:
continue
port_ips.sort()
mac_addr = port['mac_address']
vnic_id = get_port_vnic_id(plugin, port)
# look for this port in the spoofguard data
found_port = False
for spd in policy_data:
if spd['id'] == vnic_id:
found_port = True
actual_ips = spd.get('publishedIpAddress',
{}).get('ipAddresses', [])
actual_ips.sort()
if actual_ips != port_ips:
error_data = ('Different IPs (%s/%s)' % (
len(actual_ips), len(port_ips)))
elif spd.get('publishedMacAddress') != mac_addr:
error_data = ('Different MAC address (%s/%s)' % (
spd.get('publishedMacAddress'), mac_addr))
continue
if not found_port:
error_data = 'Port missing from SG policy'
if error_data:
missing.append({'network': network_id,
'policy': policy_id,
'port': port['id'],
'data': error_data})
return missing
@admin_utils.output_header
@admin_utils.unpack_payload
def nsx_list_mismatch_addresses(resource, event, trigger, **kwargs):
"""List missing spoofguard policies approved addresses on NSXv.
Address pairs defined on neutron compute ports that are missing from the
NSX-V spoofguard policy of a specific/all networks.
"""
network_id = None
if kwargs.get('property'):
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
network_id = properties.get('network')
spgapi = utils.NeutronDbClient()
if network_id:
policy_id = nsxv_db.get_spoofguard_policy_id(
spgapi.context.session, network_id)
if not policy_id:
LOG.error("Could not find spoofguard policy for neutron network "
"%s", network_id)
return
with utils.NsxVPluginWrapper() as plugin:
missing_data = nsx_list_mismatch_addresses_for_net(
spgapi.context, plugin, network_id, policy_id)
else:
with utils.NsxVPluginWrapper() as plugin:
missing_data = []
# Go over all the networks with spoofguard policies
mappings = get_spoofguard_policy_network_mappings()
for entry in mappings:
missing_data.extend(nsx_list_mismatch_addresses_for_net(
spgapi.context, plugin, entry['network_id'],
entry['policy_id']))
if missing_data:
LOG.info(formatters.output_formatter(
constants.SPOOFGUARD_POLICY, missing_data,
['network', 'policy', 'port', 'data']))
else:
LOG.info("No mismatches found.")
@admin_utils.output_header
@admin_utils.unpack_payload
def nsx_fix_mismatch_addresses(resource, event, trigger, **kwargs):
"""Fix missing spoofguard policies approved addresses for a port."""
port_id = None
if kwargs.get('property'):
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
port_id = properties.get('port')
if not port_id:
usage_msg = ("Need to specify the id of the neutron port. "
"Add --property port=<port_id>")
LOG.error(usage_msg)
return
spgapi = utils.NeutronDbClient()
with utils.NsxVPluginWrapper() as plugin:
try:
port = plugin.get_port(spgapi.context, port_id)
except exceptions.PortNotFound:
LOG.error("Could not find neutron port %s", port_id)
return
vnic_id = get_port_vnic_id(plugin, port)
plugin._update_vnic_assigned_addresses(
spgapi.context.session, port, vnic_id)
LOG.info("Done.")
@admin_utils.unpack_payload
def nsx_clean_spoofguard_policy(resource, event, trigger, **kwargs):
"""Delete spoofguard policy"""
errmsg = ("Need to specify policy-id. Add --property "
"policy-id=<policy-id>")
if not kwargs.get('property'):
LOG.error("%s", errmsg)
return
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
policy_id = properties.get('policy-id')
if not policy_id:
LOG.error("%s", errmsg)
return
try:
h, c = nsxv.get_spoofguard_policy(policy_id)
except exceptions.NeutronException as e:
LOG.error("Unable to retrieve policy %(p)s: %(e)s",
{'p': policy_id, 'e': str(e)})
else:
if not c.get('spoofguardList'):
LOG.error("Policy %s does not exist", policy_id)
return
confirm = admin_utils.query_yes_no(
"Do you want to delete spoofguard-policy: %s" % policy_id,
default="no")
if not confirm:
LOG.info("spoofguard-policy deletion aborted by user")
return
try:
nsxv.delete_spoofguard_policy(policy_id)
except Exception as e:
LOG.error("%s", str(e))
LOG.info('spoofguard-policy successfully deleted.')
registry.subscribe(neutron_list_spoofguard_policy_mappings,
constants.SPOOFGUARD_POLICY,
shell.Operations.LIST.value)
registry.subscribe(nsx_list_spoofguard_policies,
constants.SPOOFGUARD_POLICY,
shell.Operations.LIST.value)
registry.subscribe(nsx_list_missing_spoofguard_policies,
constants.SPOOFGUARD_POLICY,
shell.Operations.LIST.value)
registry.subscribe(nsx_list_mismatch_addresses,
constants.SPOOFGUARD_POLICY,
shell.Operations.LIST_MISMATCHES.value)
registry.subscribe(nsx_fix_mismatch_addresses,
constants.SPOOFGUARD_POLICY,
shell.Operations.FIX_MISMATCH.value)
registry.subscribe(nsx_clean_spoofguard_policy,
constants.SPOOFGUARD_POLICY,
shell.Operations.CLEAN.value)