NSX|v3 Admin utils refactor + additions
- Refactor nsx-v3 admin utilities by moving some of the code to a different file which will later be consumed by the housekeeper code as well - Adding orphaned firewall sections list/clean utilities - Adding a capability to detect problems in logical port address bindings - Update the documentation Change-Id: If6aba167c2dd1234d1bb10a8a115fcdfe13cf2f0
This commit is contained in:
parent
f570c651bf
commit
c0f3149c40
@ -351,7 +351,7 @@ Orphaned Routers
|
||||
Ports
|
||||
~~~~~
|
||||
|
||||
- List missing ports, and ports that exist on backend but without the expected switch profiles::
|
||||
- List missing ports, and ports that exist on backend but without the expected switch profiles or address bindings::
|
||||
|
||||
nsxadmin -r ports -o list-mismatches
|
||||
|
||||
@ -370,7 +370,7 @@ Ports
|
||||
Security Groups & NSX Security Groups
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- List backed security groups::
|
||||
- List NSX backend security groups::
|
||||
|
||||
nsxadmin -r nsx-security-groups -o list
|
||||
|
||||
@ -378,14 +378,14 @@ Security Groups & NSX Security Groups
|
||||
|
||||
nsxadmin -r security-groups -o list
|
||||
|
||||
- Fix mismatch sections in security group::
|
||||
|
||||
nsxadmin -r security-groups -o fix-mismatch
|
||||
|
||||
- List nsx security groups with mismatch sections::
|
||||
- List security groups with sections missing on the NSX backend::
|
||||
|
||||
nsxadmin -r nsx-security-groups -o list-mismatches
|
||||
|
||||
- Fix mismatch security groups by recreating missing sections & NS groups on the NSX backend::
|
||||
|
||||
nsxadmin -r security-groups -o fix-mismatch
|
||||
|
||||
- Update NSX security groups dynamic criteria for NSXv3 CrossHairs::
|
||||
|
||||
nsxadmin -r nsx-security-groups -o migrate-to-dynamic-criteria
|
||||
@ -393,14 +393,25 @@ Security Groups & NSX Security Groups
|
||||
Firewall Sections
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
- List backed firewall sections::
|
||||
- List NSX backend firewall sections::
|
||||
|
||||
nsxadmin -r firewall-sections -o list
|
||||
|
||||
- List security groups with missing sections::
|
||||
- List security groups with missing sections on the NSX backend::
|
||||
|
||||
nsxadmin -r firewall-sections -o list-mismatches
|
||||
|
||||
Orphaned Firewall Sections
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- List orphaned firewall sections (exist on NSXv3 backend but don't have a corresponding binding in Neutron DB)::
|
||||
|
||||
nsxadmin -r orphaned-firewall-sections -o nsx-list
|
||||
|
||||
- Delete orphaned firewall sections (exist on NSXv3 backend but don't have a corresponding binding in Neutron DB)::
|
||||
|
||||
nsxadmin -r orphaned-firewall-sections -o nsx-clean
|
||||
|
||||
Metadata Proxy
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -129,9 +129,7 @@ from vmware_nsxlib.v3 import utils as nsxlib_utils
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
NSX_V3_PSEC_PROFILE_NAME = 'neutron_port_spoof_guard_profile'
|
||||
NSX_V3_NO_PSEC_PROFILE_NAME = 'nsx-default-spoof-guard-vif-profile'
|
||||
NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile'
|
||||
NSX_V3_MAC_LEARNING_PROFILE_NAME = 'neutron_port_mac_learning_profile'
|
||||
NSX_V3_FW_DEFAULT_SECTION = 'OS Default Section for Neutron Security-Groups'
|
||||
NSX_V3_FW_DEFAULT_NS_GROUP = 'os_default_section_ns_group'
|
||||
@ -507,12 +505,12 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
def _init_nsx_profiles(self):
|
||||
LOG.debug("Initializing NSX v3 port spoofguard switching profile")
|
||||
if not self._init_port_security_profile():
|
||||
msg = _("Unable to initialize NSX v3 port spoofguard "
|
||||
"switching profile: %s") % NSX_V3_PSEC_PROFILE_NAME
|
||||
msg = _("Unable to initialize NSX v3 port spoofguard switching "
|
||||
"profile: %s") % v3_utils.NSX_V3_PSEC_PROFILE_NAME
|
||||
raise nsx_exc.NsxPluginException(err_msg=msg)
|
||||
profile_client = self.nsxlib.switching_profile
|
||||
no_psec_prof = profile_client.find_by_display_name(
|
||||
NSX_V3_NO_PSEC_PROFILE_NAME)[0]
|
||||
NSX_V3_NO_PSEC_PROFILE_NAME)[0]
|
||||
self._no_psec_profile_id = profile_client.build_switch_profile_ids(
|
||||
profile_client, no_psec_prof)[0]
|
||||
|
||||
@ -522,7 +520,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
except Exception as e:
|
||||
msg = (_("Unable to initialize NSX v3 DHCP switching profile: "
|
||||
"%(id)s. Reason: %(reason)s") % {
|
||||
'id': NSX_V3_DHCP_PROFILE_NAME,
|
||||
'id': v3_utils.NSX_V3_DHCP_PROFILE_NAME,
|
||||
'reason': str(e)})
|
||||
raise nsx_exc.NsxPluginException(err_msg=msg)
|
||||
|
||||
@ -672,7 +670,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
with locking.LockManager.get_lock('nsxv3_dhcp_profile_init'):
|
||||
if not self._get_dhcp_security_profile():
|
||||
self.nsxlib.switching_profile.create_dhcp_profile(
|
||||
NSX_V3_DHCP_PROFILE_NAME, 'Neutron DHCP Security Profile',
|
||||
v3_utils.NSX_V3_DHCP_PROFILE_NAME,
|
||||
'Neutron DHCP Security Profile',
|
||||
tags=self.nsxlib.build_v3_api_version_tag())
|
||||
return self._get_dhcp_security_profile()
|
||||
|
||||
@ -680,7 +679,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
if hasattr(self, '_dhcp_profile') and self._dhcp_profile:
|
||||
return self._dhcp_profile
|
||||
profile = self.nsxlib.switching_profile.find_by_display_name(
|
||||
NSX_V3_DHCP_PROFILE_NAME)
|
||||
v3_utils.NSX_V3_DHCP_PROFILE_NAME)
|
||||
self._dhcp_profile = nsx_resources.SwitchingProfileTypeId(
|
||||
profile_type=(nsx_resources.SwitchingProfileTypes.
|
||||
SWITCH_SECURITY),
|
||||
@ -745,7 +744,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
if hasattr(self, '_psec_profile') and self._psec_profile:
|
||||
return self._psec_profile
|
||||
profile = self.nsxlib.switching_profile.find_by_display_name(
|
||||
NSX_V3_PSEC_PROFILE_NAME)
|
||||
v3_utils.NSX_V3_PSEC_PROFILE_NAME)
|
||||
self._psec_profile = profile[0] if profile else None
|
||||
return self._psec_profile
|
||||
|
||||
@ -763,7 +762,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
return profile
|
||||
|
||||
self.nsxlib.switching_profile.create_spoofguard_profile(
|
||||
NSX_V3_PSEC_PROFILE_NAME, 'Neutron Port Security Profile',
|
||||
v3_utils.NSX_V3_PSEC_PROFILE_NAME,
|
||||
'Neutron Port Security Profile',
|
||||
whitelist_ports=True, whitelist_switches=False,
|
||||
tags=self.nsxlib.build_v3_api_version_tag())
|
||||
return self._get_port_security_profile()
|
||||
|
@ -18,19 +18,36 @@ import random
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import fileutils
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron.db.models import securitygroup
|
||||
from neutron import version as n_version
|
||||
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
||||
from neutron_lib import constants as const
|
||||
from neutron_lib import context as q_context
|
||||
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.db import nsx_models
|
||||
from vmware_nsx.plugins.nsx_v3 import cert_utils
|
||||
from vmware_nsx.services.qos.common import utils as qos_utils
|
||||
from vmware_nsxlib import v3
|
||||
from vmware_nsxlib.v3 import client_cert
|
||||
from vmware_nsxlib.v3 import config
|
||||
from vmware_nsxlib.v3 import core_resources
|
||||
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
|
||||
NSX_NEUTRON_PLUGIN = 'NSX Neutron plugin'
|
||||
OS_NEUTRON_ID_SCOPE = 'os-neutron-id'
|
||||
|
||||
NSX_V3_PSEC_PROFILE_NAME = 'neutron_port_spoof_guard_profile'
|
||||
NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile'
|
||||
|
||||
PORT_ERROR_TYPE_MISSING = "Missing port"
|
||||
PORT_ERROR_TYPE_PROFILE = "Wrong switching profiles"
|
||||
PORT_ERROR_TYPE_BINDINGS = "Wrong address binding"
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -145,3 +162,294 @@ def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False):
|
||||
dns_nameservers=cfg.CONF.nsx_v3.nameservers,
|
||||
dns_domain=cfg.CONF.nsx_v3.dns_domain)
|
||||
return v3.NsxLib(nsxlib_config)
|
||||
|
||||
|
||||
def get_orphaned_dhcp_servers(context, plugin, nsxlib, dhcp_profile_uuid=None):
|
||||
# An orphaned DHCP server means the associated neutron network
|
||||
# does not exist or has no DHCP-enabled subnet.
|
||||
|
||||
orphaned_servers = []
|
||||
server_net_pairs = []
|
||||
|
||||
# Find matching DHCP servers (for a given dhcp_profile_uuid).
|
||||
response = nsxlib.dhcp_server.list()
|
||||
for dhcp_server in response['results']:
|
||||
if (dhcp_profile_uuid and
|
||||
dhcp_server['dhcp_profile_id'] != dhcp_profile_uuid):
|
||||
continue
|
||||
found = False
|
||||
neutron_obj = False
|
||||
for tag in dhcp_server.get('tags', []):
|
||||
if tag['scope'] == 'os-neutron-net-id':
|
||||
dhcp_server['neutron_net_id'] = tag['tag']
|
||||
server_net_pairs.append((dhcp_server, tag['tag']))
|
||||
found = True
|
||||
if tag['scope'] == 'os-api-version':
|
||||
neutron_obj = True
|
||||
if not found and neutron_obj:
|
||||
# The associated neutron network is not defined.
|
||||
dhcp_server['neutron_net_id'] = None
|
||||
orphaned_servers.append(dhcp_server)
|
||||
|
||||
# Check if there is DHCP-enabled subnet in each network.
|
||||
for dhcp_server, net_id in server_net_pairs:
|
||||
try:
|
||||
network = plugin.get_network(context, net_id)
|
||||
except Exception:
|
||||
# The associated neutron network is not found in DB.
|
||||
orphaned_servers.append(dhcp_server)
|
||||
continue
|
||||
dhcp_enabled = False
|
||||
for subnet_id in network['subnets']:
|
||||
subnet = plugin.get_subnet(context, subnet_id)
|
||||
if subnet['enable_dhcp']:
|
||||
dhcp_enabled = True
|
||||
break
|
||||
if not dhcp_enabled:
|
||||
orphaned_servers.append(dhcp_server)
|
||||
|
||||
return orphaned_servers
|
||||
|
||||
|
||||
def delete_orphaned_dhcp_server(context, nsxlib, server):
|
||||
# Delete an orphaned DHCP server:
|
||||
# (1) delete the attached logical DHCP port,
|
||||
# (2) delete the logical DHCP server,
|
||||
# (3) clean corresponding neutron DB entry.
|
||||
# Return True if it was deleted, or false + error if not
|
||||
try:
|
||||
response = nsxlib.logical_port.get_by_attachment('DHCP_SERVICE',
|
||||
server['id'])
|
||||
if response and response['result_count'] > 0:
|
||||
nsxlib.logical_port.delete(response['results'][0]['id'])
|
||||
nsxlib.dhcp_server.delete(server['id'])
|
||||
net_id = server.get('neutron_net_id')
|
||||
if net_id:
|
||||
# Delete neutron_net_id -> dhcp_service_id mapping from the DB.
|
||||
nsx_db.delete_neutron_nsx_service_binding(
|
||||
context.session, net_id,
|
||||
nsx_constants.SERVICE_DHCP)
|
||||
return True, None
|
||||
except Exception as e:
|
||||
return False, e
|
||||
|
||||
|
||||
def get_orphaned_networks(context, nsxlib):
|
||||
nsx_switches = nsxlib.logical_switch.list()['results']
|
||||
missing_networks = []
|
||||
for nsx_switch in nsx_switches:
|
||||
# check if it exists in the neutron DB
|
||||
net_ids = nsx_db.get_net_ids(context.session, nsx_switch['id'])
|
||||
if not net_ids:
|
||||
# Skip non-neutron networks, by tags
|
||||
neutron_net = False
|
||||
for tag in nsx_switch.get('tags', []):
|
||||
if tag.get('scope') == 'os-neutron-net-id':
|
||||
neutron_net = True
|
||||
nsx_switch['neutron_net_id'] = tag['tag']
|
||||
break
|
||||
if neutron_net:
|
||||
missing_networks.append(nsx_switch)
|
||||
return missing_networks
|
||||
|
||||
|
||||
def get_orphaned_routers(context, nsxlib):
|
||||
nsx_routers = nsxlib.logical_router.list()['results']
|
||||
missing_routers = []
|
||||
for nsx_router in nsx_routers:
|
||||
# check if it exists in the neutron DB
|
||||
neutron_id = nsx_db.get_neutron_from_nsx_router_id(context.session,
|
||||
nsx_router['id'])
|
||||
if not neutron_id:
|
||||
# Skip non-neutron routers, by tags
|
||||
for tag in nsx_router.get('tags', []):
|
||||
if tag.get('scope') == 'os-neutron-router-id':
|
||||
nsx_router['neutron_router_id'] = tag['tag']
|
||||
missing_routers.append(nsx_router)
|
||||
break
|
||||
return missing_routers
|
||||
|
||||
|
||||
def delete_orphaned_router(nsxlib, nsx_id):
|
||||
# Delete an orphaned logical router from the NSX:
|
||||
# (1) delete the attached ports,
|
||||
# (2) delete the logical router
|
||||
# Return True if it was deleted, or false + error if not
|
||||
try:
|
||||
# first delete its ports
|
||||
ports = nsxlib.logical_router_port.get_by_router_id(nsx_id)
|
||||
for port in ports:
|
||||
nsxlib.logical_router_port.delete(port['id'])
|
||||
nsxlib.logical_router.delete(nsx_id)
|
||||
except Exception as e:
|
||||
return False, e
|
||||
else:
|
||||
return True, None
|
||||
|
||||
|
||||
def get_security_groups_mappings(context):
|
||||
q = context.session.query(
|
||||
securitygroup.SecurityGroup.name,
|
||||
securitygroup.SecurityGroup.id,
|
||||
nsx_models.NeutronNsxFirewallSectionMapping.nsx_id,
|
||||
nsx_models.NeutronNsxSecurityGroupMapping.nsx_id).join(
|
||||
nsx_models.NeutronNsxFirewallSectionMapping,
|
||||
nsx_models.NeutronNsxSecurityGroupMapping).all()
|
||||
sg_mappings = [{'name': mapp[0],
|
||||
'id': mapp[1],
|
||||
'section-id': mapp[2],
|
||||
'nsx-securitygroup-id': mapp[3]}
|
||||
for mapp in q]
|
||||
return sg_mappings
|
||||
|
||||
|
||||
def get_orphaned_firewall_sections(context, nsxlib):
|
||||
fw_sections = nsxlib.firewall_section.list()
|
||||
sg_mappings = get_security_groups_mappings(context)
|
||||
orphaned_sections = []
|
||||
for fw_section in fw_sections:
|
||||
for sg_db in sg_mappings:
|
||||
if fw_section['id'] == sg_db['section-id']:
|
||||
break
|
||||
else:
|
||||
# Skip non-neutron sections, by tags
|
||||
neutron_obj = False
|
||||
for tag in fw_section.get('tags', []):
|
||||
if tag['scope'] == 'os-api-version':
|
||||
neutron_obj = True
|
||||
if tag.get('scope') == 'os-neutron-secgr-id':
|
||||
fw_section['neutron_sg_id'] = tag['tag']
|
||||
if neutron_obj:
|
||||
orphaned_sections.append(fw_section)
|
||||
return orphaned_sections
|
||||
|
||||
|
||||
def get_dhcp_profile_id(nsxlib):
|
||||
profiles = nsxlib.switching_profile.find_by_display_name(
|
||||
NSX_V3_DHCP_PROFILE_NAME)
|
||||
if profiles and len(profiles) == 1:
|
||||
return profiles[0]['id']
|
||||
LOG.warning("Could not find DHCP profile on backend")
|
||||
|
||||
|
||||
def get_spoofguard_profile_id(nsxlib):
|
||||
profiles = nsxlib.switching_profile.find_by_display_name(
|
||||
NSX_V3_PSEC_PROFILE_NAME)
|
||||
if profiles and len(profiles) == 1:
|
||||
return profiles[0]['id']
|
||||
LOG.warning("Could not find Spoof Guard profile on backend")
|
||||
|
||||
|
||||
def add_profile_mismatch(problems, neutron_id, nsx_id, prf_id, title):
|
||||
msg = ('Wrong %(title)s profile %(prf_id)s') % {'title': title,
|
||||
'prf_id': prf_id}
|
||||
problems.append({'neutron_id': neutron_id,
|
||||
'nsx_id': nsx_id,
|
||||
'error': msg,
|
||||
'error_type': PORT_ERROR_TYPE_PROFILE})
|
||||
|
||||
|
||||
def get_port_nsx_id(session, neutron_id):
|
||||
# get the nsx port id from the DB mapping
|
||||
try:
|
||||
mapping = (session.query(nsx_models.NeutronNsxPortMapping).
|
||||
filter_by(neutron_id=neutron_id).
|
||||
one())
|
||||
return mapping['nsx_port_id']
|
||||
except exc.NoResultFound:
|
||||
pass
|
||||
|
||||
|
||||
def get_mismatch_logical_ports(context, nsxlib, plugin, get_filters=None):
|
||||
neutron_ports = plugin.get_ports(context, filters=get_filters)
|
||||
|
||||
# get pre-defined profile ids
|
||||
dhcp_profile_id = get_dhcp_profile_id(nsxlib)
|
||||
dhcp_profile_key = (
|
||||
core_resources.SwitchingProfileTypes.SWITCH_SECURITY)
|
||||
spoofguard_profile_id = get_spoofguard_profile_id(nsxlib)
|
||||
spoofguard_profile_key = (
|
||||
core_resources.SwitchingProfileTypes.SPOOF_GUARD)
|
||||
qos_profile_key = core_resources.SwitchingProfileTypes.QOS
|
||||
|
||||
problems = []
|
||||
for port in neutron_ports:
|
||||
neutron_id = port['id']
|
||||
# get the network nsx id from the mapping table
|
||||
nsx_id = get_port_nsx_id(context.session, neutron_id)
|
||||
if not nsx_id:
|
||||
# skip external ports
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
nsx_port = nsxlib.logical_port.get(nsx_id)
|
||||
except nsxlib_exc.ResourceNotFound:
|
||||
problems.append({'neutron_id': neutron_id,
|
||||
'nsx_id': nsx_id,
|
||||
'error': 'Missing from backend',
|
||||
'error_type': PORT_ERROR_TYPE_MISSING})
|
||||
continue
|
||||
|
||||
# Port found on backend!
|
||||
# Check that it has all the expected switch profiles.
|
||||
# create a dictionary of the current profiles:
|
||||
profiles_dict = {}
|
||||
for prf in nsx_port['switching_profile_ids']:
|
||||
profiles_dict[prf['key']] = prf['value']
|
||||
|
||||
# DHCP port: neutron dhcp profile should be attached
|
||||
# to logical ports created for neutron DHCP but not
|
||||
# for native DHCP.
|
||||
if (port.get('device_owner') == const.DEVICE_OWNER_DHCP and
|
||||
not cfg.CONF.nsx_v3.native_dhcp_metadata):
|
||||
prf_id = profiles_dict[dhcp_profile_key]
|
||||
if prf_id != dhcp_profile_id:
|
||||
add_profile_mismatch(problems, neutron_id, nsx_id,
|
||||
prf_id, "DHCP security")
|
||||
|
||||
# Port with QoS policy: a matching profile should be attached
|
||||
qos_policy_id = qos_utils.get_port_policy_id(context,
|
||||
neutron_id)
|
||||
if qos_policy_id:
|
||||
qos_profile_id = nsx_db.get_switch_profile_by_qos_policy(
|
||||
context.session, qos_policy_id)
|
||||
prf_id = profiles_dict[qos_profile_key]
|
||||
if prf_id != qos_profile_id:
|
||||
add_profile_mismatch(problems, neutron_id, nsx_id,
|
||||
prf_id, "QoS")
|
||||
|
||||
# Port with security & fixed ips/address pairs:
|
||||
# neutron spoofguard profile should be attached
|
||||
port_sec, has_ip = plugin._determine_port_security_and_has_ip(
|
||||
context, port)
|
||||
addr_pair = port.get(addr_apidef.ADDRESS_PAIRS)
|
||||
if port_sec and (has_ip or addr_pair):
|
||||
prf_id = profiles_dict[spoofguard_profile_key]
|
||||
if prf_id != spoofguard_profile_id:
|
||||
add_profile_mismatch(problems, neutron_id, nsx_id,
|
||||
prf_id, "Spoof Guard")
|
||||
|
||||
# Check the address bindings
|
||||
if port_sec:
|
||||
nsx_address_bindings = nsx_port.get('address_bindings', [])
|
||||
nsx_ips = [x['ip_address'] for x in nsx_address_bindings]
|
||||
nsx_macs = [x['mac_address'] for x in nsx_address_bindings]
|
||||
neutron_ips = [x['ip_address']
|
||||
for x in port.get('fixed_ips', [])]
|
||||
neutron_mac = port['mac_address']
|
||||
different_macs = [mac for mac in nsx_macs
|
||||
if mac != neutron_mac]
|
||||
if (len(nsx_ips) != len(neutron_ips) or
|
||||
set(nsx_ips) != set(neutron_ips)):
|
||||
problems.append({'neutron_id': neutron_id,
|
||||
'nsx_id': nsx_id,
|
||||
'port': port,
|
||||
'error': 'Different IP address bindings',
|
||||
'error_type': PORT_ERROR_TYPE_BINDINGS})
|
||||
elif different_macs:
|
||||
problems.append({'neutron_id': neutron_id,
|
||||
'nsx_id': nsx_id,
|
||||
'port': port,
|
||||
'error': 'Different MAC address bindings',
|
||||
'error_type': PORT_ERROR_TYPE_BINDINGS})
|
||||
return problems
|
||||
|
@ -45,6 +45,7 @@ LB_VIRTUAL_SERVERS = 'lb-virtual-servers'
|
||||
LB_POOLS = 'lb-pools'
|
||||
LB_MONITORS = 'lb-monitors'
|
||||
RATE_LIMIT = 'rate-limit'
|
||||
ORPHANED_FIREWALL_SECTIONS = 'orphaned-firewall-sections'
|
||||
|
||||
# NSXV only Resource Constants
|
||||
EDGES = 'edges'
|
||||
|
@ -79,12 +79,12 @@ def nsx_update_dhcp_bindings(resource, event, trigger, **kwargs):
|
||||
if netaddr.IPNetwork(fixed_ip['ip_address']).version == 6:
|
||||
continue
|
||||
network_id = port['network_id']
|
||||
subnet = neutron_client.get_subnet(fixed_ip['subnet_id'])
|
||||
subnet = neutron_client.get_subnet(None, fixed_ip['subnet_id'])
|
||||
if device_owner == const.DEVICE_OWNER_DHCP:
|
||||
# For each DHCP-enabled network, create a logical DHCP server
|
||||
# and update the attachment type to DHCP on the corresponding
|
||||
# logical port of the Neutron DHCP port.
|
||||
network = neutron_client.get_network(port['network_id'])
|
||||
network = neutron_client.get_network(None, port['network_id'])
|
||||
net_tags = nsxlib.build_v3_tags_payload(
|
||||
network, resource_type='os-neutron-net-id',
|
||||
project_name='admin')
|
||||
@ -132,7 +132,7 @@ def nsx_update_dhcp_bindings(resource, event, trigger, **kwargs):
|
||||
options = {'option121': {'static_routes': [
|
||||
{'network': '%s' % cfg.CONF.nsx_v3.native_metadata_route,
|
||||
'next_hop': ip}]}}
|
||||
subnet = neutron_client.get_subnet(subnet_id)
|
||||
subnet = neutron_client.get_subnet(None, subnet_id)
|
||||
binding = nsxlib.dhcp_server.create_binding(
|
||||
dhcp_server_id, mac, ip, hostname,
|
||||
cfg.CONF.nsx_v3.dhcp_lease_time, options,
|
||||
|
@ -18,13 +18,12 @@ from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from vmware_nsx.common import utils as nsx_utils
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
|
||||
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.nsxv3.resources import utils
|
||||
import vmware_nsx.shell.resources as shell
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
neutron_client = utils.NeutronDbClient()
|
||||
@ -43,52 +42,6 @@ def _get_dhcp_profile_uuid(**kwargs):
|
||||
cfg.CONF.nsx_v3.dhcp_profile)
|
||||
|
||||
|
||||
def _get_orphaned_dhcp_servers(dhcp_profile_uuid):
|
||||
# An orphaned DHCP server means the associated neutron network
|
||||
# does not exist or has no DHCP-enabled subnet.
|
||||
|
||||
orphaned_servers = []
|
||||
server_net_pairs = []
|
||||
|
||||
# Find matching DHCP servers for a given dhcp_profile_uuid.
|
||||
nsxlib = utils.get_connected_nsxlib()
|
||||
response = nsxlib.dhcp_server.list()
|
||||
for dhcp_server in response['results']:
|
||||
if dhcp_server['dhcp_profile_id'] != dhcp_profile_uuid:
|
||||
continue
|
||||
found = False
|
||||
for tag in dhcp_server.get('tags', []):
|
||||
if tag['scope'] == 'os-neutron-net-id':
|
||||
server_net_pairs.append((dhcp_server, tag['tag']))
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
# The associated neutron network is not defined.
|
||||
dhcp_server['neutron_net_id'] = None
|
||||
orphaned_servers.append(dhcp_server)
|
||||
|
||||
# Check if there is DHCP-enabled subnet in each network.
|
||||
for dhcp_server, net_id in server_net_pairs:
|
||||
try:
|
||||
network = neutron_client.get_network(net_id)
|
||||
except Exception:
|
||||
# The associated neutron network is not found in DB.
|
||||
dhcp_server['neutron_net_id'] = None
|
||||
orphaned_servers.append(dhcp_server)
|
||||
continue
|
||||
dhcp_enabled = False
|
||||
for subnet_id in network['subnets']:
|
||||
subnet = neutron_client.get_subnet(subnet_id)
|
||||
if subnet['enable_dhcp']:
|
||||
dhcp_enabled = True
|
||||
break
|
||||
if not dhcp_enabled:
|
||||
dhcp_server['neutron_net_id'] = net_id
|
||||
orphaned_servers.append(dhcp_server)
|
||||
|
||||
return orphaned_servers
|
||||
|
||||
|
||||
@admin_utils.output_header
|
||||
def nsx_list_orphaned_dhcp_servers(resource, event, trigger, **kwargs):
|
||||
"""List logical DHCP servers without associated DHCP-enabled subnet."""
|
||||
@ -105,10 +58,13 @@ def nsx_list_orphaned_dhcp_servers(resource, event, trigger, **kwargs):
|
||||
LOG.error("dhcp_profile_uuid is not defined")
|
||||
return
|
||||
|
||||
orphaned_servers = _get_orphaned_dhcp_servers(dhcp_profile_uuid)
|
||||
LOG.info(formatters.output_formatter(constants.ORPHANED_DHCP_SERVERS,
|
||||
orphaned_servers,
|
||||
['id', 'neutron_net_id']))
|
||||
orphaned_servers = v3_utils.get_orphaned_dhcp_servers(
|
||||
context.get_admin_context(),
|
||||
neutron_client, nsxlib, dhcp_profile_uuid)
|
||||
LOG.info(formatters.output_formatter(
|
||||
constants.ORPHANED_DHCP_SERVERS,
|
||||
orphaned_servers,
|
||||
['id', 'neutron_net_id', 'display_name']))
|
||||
|
||||
|
||||
@admin_utils.output_header
|
||||
@ -136,25 +92,18 @@ def nsx_clean_orphaned_dhcp_servers(resource, event, trigger, **kwargs):
|
||||
cfg.CONF.set_override('native_dhcp_metadata', True, 'nsx_v3')
|
||||
cfg.CONF.set_override('dhcp_profile', dhcp_profile_uuid, 'nsx_v3')
|
||||
|
||||
orphaned_servers = _get_orphaned_dhcp_servers(dhcp_profile_uuid)
|
||||
orphaned_servers = v3_utils.get_orphaned_dhcp_servers(
|
||||
context.get_admin_context(),
|
||||
neutron_client, nsxlib, dhcp_profile_uuid)
|
||||
|
||||
for server in orphaned_servers:
|
||||
try:
|
||||
response = nsxlib.logical_port.get_by_attachment('DHCP_SERVICE',
|
||||
server['id'])
|
||||
if response and response['result_count'] > 0:
|
||||
nsxlib.logical_port.delete(response['results'][0]['id'])
|
||||
nsxlib.dhcp_server.delete(server['id'])
|
||||
net_id = server.get('neutron_net_id')
|
||||
if net_id:
|
||||
# Delete neutron_net_id -> dhcp_service_id mapping from the DB.
|
||||
nsx_db.delete_neutron_nsx_service_binding(
|
||||
context.get_admin_context().session, net_id,
|
||||
nsx_constants.SERVICE_DHCP)
|
||||
success, error = v3_utils.delete_orphaned_dhcp_server(
|
||||
context.get_admin_context(), nsxlib, server)
|
||||
if success:
|
||||
LOG.info("Removed orphaned DHCP server %s", server['id'])
|
||||
except Exception as e:
|
||||
else:
|
||||
LOG.error("Failed to clean orphaned DHCP server %(id)s. "
|
||||
"Exception: %(e)s", {'id': server['id'], 'e': e})
|
||||
"Exception: %(e)s", {'id': server['id'], 'e': error})
|
||||
|
||||
|
||||
registry.subscribe(nsx_list_orphaned_dhcp_servers,
|
||||
|
@ -41,7 +41,7 @@ def _is_metadata_network(network):
|
||||
# If a Neutron network has only one subnet with 169.254.169.252/30 CIDR,
|
||||
# then it is an internal metadata network.
|
||||
if len(network['subnets']) == 1:
|
||||
subnet = neutron_client.get_subnet(network['subnets'][0])
|
||||
subnet = neutron_client.get_subnet(None, network['subnets'][0])
|
||||
if subnet['cidr'] == nsx_rpc.METADATA_SUBNET_CIDR:
|
||||
return True
|
||||
return False
|
||||
|
@ -15,6 +15,7 @@
|
||||
import sys
|
||||
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
|
||||
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
|
||||
@ -75,20 +76,8 @@ def list_missing_networks(resource, event, trigger, **kwargs):
|
||||
@admin_utils.output_header
|
||||
def list_orphaned_networks(resource, event, trigger, **kwargs):
|
||||
nsxlib = utils.get_connected_nsxlib()
|
||||
nsx_switches = nsxlib.logical_switch.list()['results']
|
||||
missing_networks = []
|
||||
for nsx_switch in nsx_switches:
|
||||
# check if it exists in the neutron DB
|
||||
if not neutron_client.lswitch_id_to_net_id(nsx_switch['id']):
|
||||
# Skip non-neutron networks, by tags
|
||||
neutron_net = False
|
||||
for tag in nsx_switch.get('tags', []):
|
||||
if tag.get('scope') == 'os-neutron-net-id':
|
||||
neutron_net = True
|
||||
break
|
||||
if neutron_net:
|
||||
missing_networks.append(nsx_switch)
|
||||
|
||||
admin_cxt = neutron_context.get_admin_context()
|
||||
missing_networks = v3_utils.get_orphaned_networks(admin_cxt, nsxlib)
|
||||
LOG.info(formatters.output_formatter(constants.ORPHANED_NETWORKS,
|
||||
missing_networks,
|
||||
['id', 'display_name']))
|
||||
|
@ -12,23 +12,18 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from vmware_nsx.common import utils as nsx_utils
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.db import nsx_models
|
||||
from vmware_nsx.dvs import dvs
|
||||
from vmware_nsx.plugins.nsx_v3 import plugin
|
||||
from vmware_nsx.services.qos.common import utils as qos_utils
|
||||
from vmware_nsx.plugins.nsx_v3 import utils as plugin_utils
|
||||
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.nsxv3.resources import utils as v3_utils
|
||||
from vmware_nsx.shell import resources as shell
|
||||
from vmware_nsxlib.v3 import core_resources
|
||||
from vmware_nsxlib.v3 import exceptions as nsx_exc
|
||||
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
||||
from vmware_nsxlib.v3 import resources
|
||||
@ -38,7 +33,6 @@ from neutron.db import allowedaddresspairs_db as addr_pair_db
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import l3_db
|
||||
from neutron.db import portsecurity_db
|
||||
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
||||
from neutron_lib.callbacks import registry
|
||||
from neutron_lib import constants as const
|
||||
from neutron_lib import context as neutron_context
|
||||
@ -59,17 +53,6 @@ class PortsPlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
directory.add_plugin(plugin_constants.CORE, None)
|
||||
|
||||
|
||||
def get_port_nsx_id(session, neutron_id):
|
||||
# get the nsx port id from the DB mapping
|
||||
try:
|
||||
mapping = (session.query(nsx_models.NeutronNsxPortMapping).
|
||||
filter_by(neutron_id=neutron_id).
|
||||
one())
|
||||
return mapping['nsx_port_id']
|
||||
except exc.NoResultFound:
|
||||
pass
|
||||
|
||||
|
||||
def get_network_nsx_id(session, neutron_id):
|
||||
# get the nsx switch id from the DB mapping
|
||||
mappings = nsx_db.get_nsx_switch_ids(session, neutron_id)
|
||||
@ -84,111 +67,17 @@ def get_network_nsx_id(session, neutron_id):
|
||||
return mappings[0]
|
||||
|
||||
|
||||
def get_port_and_profile_clients():
|
||||
_nsx_client = v3_utils.get_nsxv3_client()
|
||||
return (resources.LogicalPort(_nsx_client),
|
||||
core_resources.NsxLibSwitchingProfile(_nsx_client))
|
||||
|
||||
|
||||
def get_dhcp_profile_id(profile_client):
|
||||
profiles = profile_client.find_by_display_name(
|
||||
plugin.NSX_V3_DHCP_PROFILE_NAME)
|
||||
if profiles and len(profiles) == 1:
|
||||
return profiles[0]['id']
|
||||
LOG.warning("Could not find DHCP profile on backend")
|
||||
|
||||
|
||||
def get_spoofguard_profile_id(profile_client):
|
||||
profiles = profile_client.find_by_display_name(
|
||||
plugin.NSX_V3_PSEC_PROFILE_NAME)
|
||||
if profiles and len(profiles) == 1:
|
||||
return profiles[0]['id']
|
||||
LOG.warning("Could not find Spoof Guard profile on backend")
|
||||
|
||||
|
||||
def add_profile_mismatch(problems, neutron_id, nsx_id, prf_id, title):
|
||||
msg = ('Wrong %(title)s profile %(prf_id)s') % {'title': title,
|
||||
'prf_id': prf_id}
|
||||
problems.append({'neutron_id': neutron_id,
|
||||
'nsx_id': nsx_id,
|
||||
'error': msg})
|
||||
|
||||
|
||||
@admin_utils.output_header
|
||||
def list_missing_ports(resource, event, trigger, **kwargs):
|
||||
"""List neutron ports that are missing the NSX backend port
|
||||
And ports with wrong switch profiles
|
||||
And ports with wrong switch profiles or bindings
|
||||
"""
|
||||
admin_cxt = neutron_context.get_admin_context()
|
||||
filters = v3_utils.get_plugin_filters(admin_cxt)
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
with PortsPlugin() as plugin:
|
||||
neutron_ports = plugin.get_ports(admin_cxt, filters=filters)
|
||||
port_client, profile_client = get_port_and_profile_clients()
|
||||
|
||||
# get pre-defined profile ids
|
||||
dhcp_profile_id = get_dhcp_profile_id(profile_client)
|
||||
dhcp_profile_key = (
|
||||
core_resources.SwitchingProfileTypes.SWITCH_SECURITY)
|
||||
spoofguard_profile_id = get_spoofguard_profile_id(profile_client)
|
||||
spoofguard_profile_key = (
|
||||
core_resources.SwitchingProfileTypes.SPOOF_GUARD)
|
||||
qos_profile_key = core_resources.SwitchingProfileTypes.QOS
|
||||
|
||||
problems = []
|
||||
for port in neutron_ports:
|
||||
neutron_id = port['id']
|
||||
# get the network nsx id from the mapping table
|
||||
nsx_id = get_port_nsx_id(admin_cxt.session, neutron_id)
|
||||
if not nsx_id:
|
||||
# skip external ports
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
nsx_port = port_client.get(nsx_id)
|
||||
except nsx_exc.ResourceNotFound:
|
||||
problems.append({'neutron_id': neutron_id,
|
||||
'nsx_id': nsx_id,
|
||||
'error': 'Missing from backend'})
|
||||
continue
|
||||
|
||||
# Port found on backend!
|
||||
# Check that it has all the expected switch profiles.
|
||||
# create a dictionary of the current profiles:
|
||||
profiles_dict = {}
|
||||
for prf in nsx_port['switching_profile_ids']:
|
||||
profiles_dict[prf['key']] = prf['value']
|
||||
|
||||
# DHCP port: neutron dhcp profile should be attached
|
||||
# to logical ports created for neutron DHCP but not
|
||||
# for native DHCP.
|
||||
if (port.get('device_owner') == const.DEVICE_OWNER_DHCP and
|
||||
not cfg.CONF.nsx_v3.native_dhcp_metadata):
|
||||
prf_id = profiles_dict[dhcp_profile_key]
|
||||
if prf_id != dhcp_profile_id:
|
||||
add_profile_mismatch(problems, neutron_id, nsx_id,
|
||||
prf_id, "DHCP security")
|
||||
|
||||
# Port with QoS policy: a matching profile should be attached
|
||||
qos_policy_id = qos_utils.get_port_policy_id(admin_cxt,
|
||||
neutron_id)
|
||||
if qos_policy_id:
|
||||
qos_profile_id = nsx_db.get_switch_profile_by_qos_policy(
|
||||
admin_cxt.session, qos_policy_id)
|
||||
prf_id = profiles_dict[qos_profile_key]
|
||||
if prf_id != qos_profile_id:
|
||||
add_profile_mismatch(problems, neutron_id, nsx_id,
|
||||
prf_id, "QoS")
|
||||
|
||||
# Port with security & fixed ips/address pairs:
|
||||
# neutron spoofguard profile should be attached
|
||||
port_sec, has_ip = plugin._determine_port_security_and_has_ip(
|
||||
admin_cxt, port)
|
||||
addr_pair = port.get(addr_apidef.ADDRESS_PAIRS)
|
||||
if port_sec and (has_ip or addr_pair):
|
||||
prf_id = profiles_dict[spoofguard_profile_key]
|
||||
if prf_id != spoofguard_profile_id:
|
||||
add_profile_mismatch(problems, neutron_id, nsx_id,
|
||||
prf_id, "Spoof Guard")
|
||||
problems = plugin_utils.get_mismatch_logical_ports(
|
||||
admin_cxt, nsxlib, plugin, filters)
|
||||
|
||||
if len(problems) > 0:
|
||||
title = ("Found internal ports misconfiguration on the "
|
||||
@ -365,7 +254,8 @@ def tag_default_ports(resource, event, trigger, **kwargs):
|
||||
for port in neutron_ports:
|
||||
neutron_id = port['id']
|
||||
# get the network nsx id from the mapping table
|
||||
nsx_id = get_port_nsx_id(admin_cxt.session, neutron_id)
|
||||
nsx_id = plugin_utils.get_port_nsx_id(admin_cxt.session,
|
||||
neutron_id)
|
||||
if not nsx_id:
|
||||
continue
|
||||
device_owner = port['device_owner']
|
||||
|
@ -16,6 +16,7 @@ import sys
|
||||
|
||||
from vmware_nsx.common import utils as nsx_utils
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
|
||||
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
|
||||
@ -115,17 +116,8 @@ def update_nat_rules(resource, event, trigger, **kwargs):
|
||||
@admin_utils.output_header
|
||||
def list_orphaned_routers(resource, event, trigger, **kwargs):
|
||||
nsxlib = utils.get_connected_nsxlib()
|
||||
nsx_routers = nsxlib.logical_router.list()['results']
|
||||
missing_routers = []
|
||||
for nsx_router in nsx_routers:
|
||||
# check if it exists in the neutron DB
|
||||
if not neutron_client.lrouter_id_to_router_id(nsx_router['id']):
|
||||
# Skip non-neutron routers, by tags
|
||||
for tag in nsx_router.get('tags', []):
|
||||
if tag.get('scope') == 'os-neutron-router-id':
|
||||
missing_routers.append(nsx_router)
|
||||
break
|
||||
|
||||
admin_cxt = neutron_context.get_admin_context()
|
||||
missing_routers = v3_utils.get_orphaned_routers(admin_cxt, nsxlib)
|
||||
LOG.info(formatters.output_formatter(constants.ORPHANED_ROUTERS,
|
||||
missing_routers,
|
||||
['id', 'display_name']))
|
||||
@ -154,15 +146,10 @@ def delete_backend_router(resource, event, trigger, **kwargs):
|
||||
return
|
||||
|
||||
# try to delete it
|
||||
try:
|
||||
# first delete its ports
|
||||
ports = nsxlib.logical_router_port.get_by_router_id(nsx_id)
|
||||
for port in ports:
|
||||
nsxlib.logical_router_port.delete(port['id'])
|
||||
nsxlib.logical_router.delete(nsx_id)
|
||||
except Exception as e:
|
||||
success, error = v3_utils.delete_orphaned_router(nsxlib, nsx_id)
|
||||
if not success:
|
||||
LOG.error("Failed to delete backend router %(id)s : %(e)s.", {
|
||||
'id': nsx_id, 'e': e})
|
||||
'id': nsx_id, 'e': error})
|
||||
return
|
||||
|
||||
# Verify that the router was deleted since the backend does not always
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
from neutron.db import api as db_api
|
||||
from neutron.db import common_db_mixin as common_db
|
||||
from neutron.db.models import securitygroup
|
||||
from neutron.db import securitygroups_db
|
||||
from neutron_lib.callbacks import registry
|
||||
from neutron_lib import context as neutron_context
|
||||
@ -24,10 +23,10 @@ from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.db import nsx_models
|
||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||
from vmware_nsx.extensions import securitygrouplogging as sg_logging
|
||||
from vmware_nsx.plugins.nsx_v3 import utils as plugin_utils
|
||||
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.nsxv3.resources import ports
|
||||
from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils as v3_utils
|
||||
from vmware_nsx.shell import resources as shell
|
||||
from vmware_nsxlib.v3 import nsx_constants as consts
|
||||
@ -82,21 +81,6 @@ class NeutronSecurityGroupApi(securitygroups_db.SecurityGroupDbMixin,
|
||||
if sg_mapping:
|
||||
self.context.session.delete(sg_mapping)
|
||||
|
||||
def get_security_groups_mappings(self):
|
||||
q = self.context.session.query(
|
||||
securitygroup.SecurityGroup.name,
|
||||
securitygroup.SecurityGroup.id,
|
||||
nsx_models.NeutronNsxFirewallSectionMapping.nsx_id,
|
||||
nsx_models.NeutronNsxSecurityGroupMapping.nsx_id).join(
|
||||
nsx_models.NeutronNsxFirewallSectionMapping,
|
||||
nsx_models.NeutronNsxSecurityGroupMapping).all()
|
||||
sg_mappings = [{'name': mapp[0],
|
||||
'id': mapp[1],
|
||||
'section-id': mapp[2],
|
||||
'nsx-securitygroup-id': mapp[3]}
|
||||
for mapp in q]
|
||||
return sg_mappings
|
||||
|
||||
def get_logical_port_id(self, port_id):
|
||||
mapping = self.context.session.query(
|
||||
nsx_models.NeutronNsxPortMapping).filter_by(
|
||||
@ -116,7 +100,8 @@ def _log_info(resource, data, attrs=['display_name', 'id']):
|
||||
@admin_utils.list_handler(constants.SECURITY_GROUPS)
|
||||
@admin_utils.output_header
|
||||
def list_security_groups_mappings(resource, event, trigger, **kwargs):
|
||||
sg_mappings = neutron_sg.get_security_groups_mappings()
|
||||
"""List neutron security groups"""
|
||||
sg_mappings = plugin_utils.get_security_groups_mappings(neutron_sg.context)
|
||||
_log_info(constants.SECURITY_GROUPS,
|
||||
sg_mappings,
|
||||
attrs=['name', 'id', 'section-id', 'nsx-securitygroup-id'])
|
||||
@ -126,6 +111,7 @@ def list_security_groups_mappings(resource, event, trigger, **kwargs):
|
||||
@admin_utils.list_handler(constants.FIREWALL_SECTIONS)
|
||||
@admin_utils.output_header
|
||||
def nsx_list_dfw_sections(resource, event, trigger, **kwargs):
|
||||
"""List NSX backend firewall sections"""
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
fw_sections = nsxlib.firewall_section.list()
|
||||
_log_info(constants.FIREWALL_SECTIONS, fw_sections)
|
||||
@ -135,6 +121,7 @@ def nsx_list_dfw_sections(resource, event, trigger, **kwargs):
|
||||
@admin_utils.list_handler(constants.FIREWALL_NSX_GROUPS)
|
||||
@admin_utils.output_header
|
||||
def nsx_list_security_groups(resource, event, trigger, **kwargs):
|
||||
"""List NSX backend security groups"""
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
nsx_secgroups = nsxlib.ns_group.list()
|
||||
_log_info(constants.FIREWALL_NSX_GROUPS, nsx_secgroups)
|
||||
@ -144,7 +131,7 @@ def nsx_list_security_groups(resource, event, trigger, **kwargs):
|
||||
def _find_missing_security_groups():
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
nsx_secgroups = nsxlib.ns_group.list()
|
||||
sg_mappings = neutron_sg.get_security_groups_mappings()
|
||||
sg_mappings = plugin_utils.get_security_groups_mappings(neutron_sg.context)
|
||||
missing_secgroups = {}
|
||||
for sg_db in sg_mappings:
|
||||
for nsx_sg in nsx_secgroups:
|
||||
@ -158,6 +145,7 @@ def _find_missing_security_groups():
|
||||
@admin_utils.list_mismatches_handler(constants.FIREWALL_NSX_GROUPS)
|
||||
@admin_utils.output_header
|
||||
def list_missing_security_groups(resource, event, trigger, **kwargs):
|
||||
"""List security groups with sections missing on the NSX backend"""
|
||||
sgs_with_missing_nsx_group = _find_missing_security_groups()
|
||||
missing_securitgroups_info = [
|
||||
{'securitygroup-name': sg['name'],
|
||||
@ -174,7 +162,7 @@ def list_missing_security_groups(resource, event, trigger, **kwargs):
|
||||
def _find_missing_sections():
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
fw_sections = nsxlib.firewall_section.list()
|
||||
sg_mappings = neutron_sg.get_security_groups_mappings()
|
||||
sg_mappings = plugin_utils.get_security_groups_mappings(neutron_sg.context)
|
||||
missing_sections = {}
|
||||
for sg_db in sg_mappings:
|
||||
for fw_section in fw_sections:
|
||||
@ -188,6 +176,7 @@ def _find_missing_sections():
|
||||
@admin_utils.list_mismatches_handler(constants.FIREWALL_SECTIONS)
|
||||
@admin_utils.output_header
|
||||
def list_missing_firewall_sections(resource, event, trigger, **kwargs):
|
||||
"""List security groups with missing sections on the NSX backend"""
|
||||
sgs_with_missing_section = _find_missing_sections()
|
||||
missing_sections_info = [{'securitygroup-name': sg['name'],
|
||||
'securitygroup-id': sg['id'],
|
||||
@ -201,6 +190,9 @@ def list_missing_firewall_sections(resource, event, trigger, **kwargs):
|
||||
@admin_utils.fix_mismatches_handler(constants.SECURITY_GROUPS)
|
||||
@admin_utils.output_header
|
||||
def fix_security_groups(resource, event, trigger, **kwargs):
|
||||
"""Fix mismatch security groups by recreating missing sections & NS groups
|
||||
on the NSX backend
|
||||
"""
|
||||
context_ = neutron_context.get_admin_context()
|
||||
inconsistent_secgroups = _find_missing_sections()
|
||||
inconsistent_secgroups.update(_find_missing_security_groups())
|
||||
@ -252,7 +244,6 @@ def fix_security_groups(resource, event, trigger, **kwargs):
|
||||
|
||||
def _update_ports_dynamic_criteria_tags():
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
port_client, _ = ports.get_port_and_profile_clients()
|
||||
for port in neutron_db.get_ports():
|
||||
secgroups = neutron_sg.get_port_security_groups(port['id'])
|
||||
# Nothing to do with ports that are not associated with any sec-group.
|
||||
@ -261,7 +252,8 @@ def _update_ports_dynamic_criteria_tags():
|
||||
|
||||
_, lport_id = neutron_db.get_lswitch_and_lport_id(port['id'])
|
||||
criteria_tags = nsxlib.ns_group.get_lport_tags(secgroups)
|
||||
port_client.update(lport_id, False, tags_update=criteria_tags)
|
||||
nsxlib.logical_port.update(
|
||||
lport_id, False, tags_update=criteria_tags)
|
||||
|
||||
|
||||
def _update_security_group_dynamic_criteria():
|
||||
@ -286,6 +278,7 @@ def _update_security_group_dynamic_criteria():
|
||||
|
||||
@admin_utils.output_header
|
||||
def migrate_nsgroups_to_dynamic_criteria(resource, event, trigger, **kwargs):
|
||||
"""Update NSX security groups dynamic criteria for NSXv3 CrossHairs"""
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
if not nsxlib.feature_supported(consts.FEATURE_DYNAMIC_CRITERIA):
|
||||
LOG.error("Dynamic criteria grouping feature isn't supported by "
|
||||
@ -297,6 +290,30 @@ def migrate_nsgroups_to_dynamic_criteria(resource, event, trigger, **kwargs):
|
||||
_update_security_group_dynamic_criteria()
|
||||
|
||||
|
||||
def list_orphaned_sections(resource, event, trigger, **kwargs):
|
||||
"""List orphaned firewall sections"""
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
orphaned_sections = plugin_utils.get_orphaned_firewall_sections(
|
||||
neutron_sg.context, nsxlib)
|
||||
_log_info(constants.ORPHANED_FIREWALL_SECTIONS, orphaned_sections,
|
||||
attrs=['id', 'display_name'])
|
||||
|
||||
|
||||
def clean_orphaned_sections(resource, event, trigger, **kwargs):
|
||||
"""Delete orphaned firewall sections from the NSX backend"""
|
||||
nsxlib = v3_utils.get_connected_nsxlib()
|
||||
orphaned_sections = plugin_utils.get_orphaned_firewall_sections(
|
||||
neutron_sg.context, nsxlib)
|
||||
for sec in orphaned_sections:
|
||||
try:
|
||||
nsxlib.firewall_section.delete(sec['id'])
|
||||
except Exception as e:
|
||||
LOG.error("Failed to delete backend firewall section %(id)s : "
|
||||
"%(e)s.", {'id': sec['id'], 'e': e})
|
||||
else:
|
||||
LOG.info("Backend firewall section %s was deleted.", sec['id'])
|
||||
|
||||
|
||||
registry.subscribe(migrate_nsgroups_to_dynamic_criteria,
|
||||
constants.FIREWALL_NSX_GROUPS,
|
||||
shell.Operations.MIGRATE_TO_DYNAMIC_CRITERIA.value)
|
||||
@ -304,3 +321,11 @@ registry.subscribe(migrate_nsgroups_to_dynamic_criteria,
|
||||
registry.subscribe(fix_security_groups,
|
||||
constants.FIREWALL_SECTIONS,
|
||||
shell.Operations.NSX_UPDATE.value)
|
||||
|
||||
registry.subscribe(list_orphaned_sections,
|
||||
constants.ORPHANED_FIREWALL_SECTIONS,
|
||||
shell.Operations.NSX_LIST.value)
|
||||
|
||||
registry.subscribe(clean_orphaned_sections,
|
||||
constants.ORPHANED_FIREWALL_SECTIONS,
|
||||
shell.Operations.NSX_CLEAN.value)
|
||||
|
@ -92,24 +92,19 @@ class NeutronDbClient(db_base_plugin_v2.NeutronDbPluginV2):
|
||||
return super(NeutronDbClient, self).get_networks(
|
||||
self.context, filters=filters, fields=fields)
|
||||
|
||||
def get_network(self, network_id):
|
||||
return super(NeutronDbClient, self).get_network(
|
||||
self.context, network_id)
|
||||
def get_network(self, context, network_id):
|
||||
if not context:
|
||||
context = self.context
|
||||
return super(NeutronDbClient, self).get_network(context, network_id)
|
||||
|
||||
def get_subnet(self, subnet_id):
|
||||
return super(NeutronDbClient, self).get_subnet(self.context, subnet_id)
|
||||
def get_subnet(self, context, subnet_id):
|
||||
if not context:
|
||||
context = self.context
|
||||
return super(NeutronDbClient, self).get_subnet(context, subnet_id)
|
||||
|
||||
def get_lswitch_and_lport_id(self, port_id):
|
||||
return nsx_db.get_nsx_switch_and_port_id(self.context.session, port_id)
|
||||
|
||||
def lswitch_id_to_net_id(self, lswitch_id):
|
||||
net_ids = nsx_db.get_net_ids(self.context.session, lswitch_id)
|
||||
return net_ids[0] if net_ids else None
|
||||
|
||||
def lrouter_id_to_router_id(self, lrouter_id):
|
||||
return nsx_db.get_neutron_from_nsx_router_id(self.context.session,
|
||||
lrouter_id)
|
||||
|
||||
def net_id_to_lswitch_id(self, net_id):
|
||||
lswitch_ids = nsx_db.get_nsx_switch_ids(self.context.session, net_id)
|
||||
return lswitch_ids[0] if lswitch_ids else None
|
||||
|
@ -89,6 +89,10 @@ nsxv3_resources = {
|
||||
Operations.LIST.value,
|
||||
Operations.LIST_MISMATCHES.value,
|
||||
Operations.MIGRATE_TO_DYNAMIC_CRITERIA.value]),
|
||||
constants.ORPHANED_FIREWALL_SECTIONS: Resource(
|
||||
constants.ORPHANED_FIREWALL_SECTIONS, [
|
||||
Operations.NSX_LIST.value,
|
||||
Operations.NSX_CLEAN.value]),
|
||||
constants.NETWORKS: Resource(constants.NETWORKS,
|
||||
[Operations.LIST_MISMATCHES.value]),
|
||||
constants.PORTS: Resource(constants.PORTS,
|
||||
|
Loading…
Reference in New Issue
Block a user