
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
296 lines
11 KiB
Python
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)
|