From c0f3149c404f39873f4c354cecfdb468b5241df8 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Thu, 28 Jun 2018 08:12:44 +0300 Subject: [PATCH] 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 --- doc/source/admin_util.rst | 29 +- vmware_nsx/plugins/nsx_v3/plugin.py | 20 +- vmware_nsx/plugins/nsx_v3/utils.py | 308 ++++++++++++++++++ .../shell/admin/plugins/common/constants.py | 1 + .../plugins/nsxv3/resources/dhcp_binding.py | 6 +- .../plugins/nsxv3/resources/dhcp_servers.py | 83 +---- .../plugins/nsxv3/resources/metadata_proxy.py | 2 +- .../admin/plugins/nsxv3/resources/networks.py | 17 +- .../admin/plugins/nsxv3/resources/ports.py | 124 +------ .../admin/plugins/nsxv3/resources/routers.py | 25 +- .../plugins/nsxv3/resources/securitygroups.py | 69 ++-- .../admin/plugins/nsxv3/resources/utils.py | 21 +- vmware_nsx/shell/resources.py | 4 + 13 files changed, 434 insertions(+), 275 deletions(-) diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index e46aac1ea5..d09da32033 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -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 ~~~~~~~~~~~~~~ diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 1873b3120b..43aefa8eeb 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -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() diff --git a/vmware_nsx/plugins/nsx_v3/utils.py b/vmware_nsx/plugins/nsx_v3/utils.py index 0ab6c1e6d5..593897726d 100644 --- a/vmware_nsx/plugins/nsx_v3/utils.py +++ b/vmware_nsx/plugins/nsx_v3/utils.py @@ -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 diff --git a/vmware_nsx/shell/admin/plugins/common/constants.py b/vmware_nsx/shell/admin/plugins/common/constants.py index 7092915c49..f8f224cb0f 100644 --- a/vmware_nsx/shell/admin/plugins/common/constants.py +++ b/vmware_nsx/shell/admin/plugins/common/constants.py @@ -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' diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py index b30527df66..62df1f7f0b 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_binding.py @@ -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, diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_servers.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_servers.py index 8d6127fcec..42af01bf67 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_servers.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/dhcp_servers.py @@ -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, diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py index 53062cac4b..3be3cb8e52 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/metadata_proxy.py @@ -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 diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/networks.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/networks.py index 0d40e25c40..00deedda48 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/networks.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/networks.py @@ -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'])) diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/ports.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/ports.py index a0ce42d174..d232b49ca0 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/ports.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/ports.py @@ -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'] diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/routers.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/routers.py index 4f78be8417..378180e837 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/routers.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/routers.py @@ -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 diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py index 7c11a0da47..e11f74a735 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/securitygroups.py @@ -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) diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py index f42893e4e4..59057890ee 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py @@ -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 diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index 4ced2c917c..e9bcc65776 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -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,