def tag_default_ports(resource, event, trigger, **kwargs): nsxlib = v3_utils.get_connected_nsxlib() admin_cxt = neutron_context.get_admin_context() filters = v3_utils.get_plugin_filters(admin_cxt) # the plugin creation below will create the NS group and update the default # OS section to have the correct applied to group with v3_utils.NsxV3PluginWrapper() as _plugin: neutron_ports = _plugin.get_ports(admin_cxt, filters=filters) 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: continue device_owner = port['device_owner'] if (device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF or device_owner == const.DEVICE_OWNER_DHCP): continue ps = _plugin._get_port_security_binding(admin_cxt, neutron_id) if not ps: continue try: nsx_port = nsxlib.logical_port.get(nsx_id) except nsx_exc.ResourceNotFound: continue tags_update = nsx_port['tags'] tags_update += [{ 'scope': security.PORT_SG_SCOPE, 'tag': plugin.NSX_V3_DEFAULT_SECTION }] nsxlib.logical_port.update(nsx_id, None, tags_update=tags_update)
def update_security_groups_logging(resource, event, trigger, **kwargs): """Update allowed traffic logging for all neutron security group rules""" errmsg = ("Need to specify log-allowed-traffic property. Add --property " "log-allowed-traffic=true/false") if not kwargs.get('property'): LOG.error("%s", errmsg) return properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) log_allowed_str = properties.get('log-allowed-traffic') if not log_allowed_str or log_allowed_str.lower() not in ['true', 'false']: LOG.error("%s", errmsg) return log_allowed = log_allowed_str.lower() == 'true' context = neutron_context.get_admin_context() nsxlib = v3_utils.get_connected_nsxlib() with v3_utils.NsxV3PluginWrapper() as plugin: secgroups = plugin.get_security_groups( context, fields=['id', sg_logging.LOGGING]) LOG.info("Going to update logging of %s sections", len(secgroups)) for sg in [ sg for sg in secgroups if sg.get(sg_logging.LOGGING) is False ]: nsgroup_id, section_id = nsx_db.get_sg_mappings( context.session, sg['id']) if section_id: try: nsxlib.firewall_section.set_rule_logging( section_id, logging=log_allowed) except nsx_lib_exc.ManagerError: LOG.error( "Failed to update firewall rule logging " "for rule in section %s", section_id)
def _init_mock_plugin(self): test_v3_plugin._mock_nsx_backend_calls() # mock resources for cls in (nsx_v3_resources.LogicalPort, nsx_v3_resources.LogicalDhcpServer, core_resources.NsxLibLogicalRouter, core_resources.NsxLibSwitchingProfile): self._patch_object(cls, 'list', return_value={'results': []}) self._patch_object(cls, 'get', return_value={'id': uuidutils.generate_uuid()}) self._patch_object(cls, 'update') self._patch_object(core_resources.NsxLibSwitchingProfile, 'find_by_display_name', return_value=[{ 'id': uuidutils.generate_uuid() }]) super(TestNsxv3AdminUtils, self)._init_mock_plugin() self._plugin = nsxv3_utils.NsxV3PluginWrapper() mock_nm_get_plugin = mock.patch( "neutron_lib.plugins.directory.get_plugin") self.mock_nm_get_plugin = mock_nm_get_plugin.start() self.mock_nm_get_plugin.return_value = self._plugin
def nsx_update_metadata_proxy(resource, event, trigger, **kwargs): """Update Metadata proxy for NSXv3 CrossHairs.""" nsx_version = utils.get_connected_nsxlib().get_version() if not nsx_utils.is_nsx_version_1_1_0(nsx_version): LOG.info(_LI("This utility is not available for NSX version %s"), nsx_version) return metadata_proxy_uuid = None if kwargs.get('property'): properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) metadata_proxy_uuid = properties.get('metadata_proxy_uuid') if not metadata_proxy_uuid: LOG.error(_LE("metadata_proxy_uuid is not defined")) return cfg.CONF.set_override('dhcp_agent_notification', False) cfg.CONF.set_override('native_dhcp_metadata', True, 'nsx_v3') cfg.CONF.set_override('metadata_proxy_uuid', metadata_proxy_uuid, 'nsx_v3') plugin = utils.NsxV3PluginWrapper() nsx_client = utils.get_nsxv3_client() port_resource = resources.LogicalPort(nsx_client) # For each Neutron network, check if it is an internal metadata network. # If yes, delete the network and associated router interface. # Otherwise, create a logical switch port with MD-Proxy attachment. for network in neutron_client.get_networks(): if _is_metadata_network(network): # It is a metadata network, find the attached router, # remove the router interface and the network. filters = {'device_owner': const.ROUTER_INTERFACE_OWNERS, 'fixed_ips': { 'subnet_id': [network['subnets'][0]], 'ip_address': [nsx_rpc.METADATA_GATEWAY_IP]}} ports = neutron_client.get_ports(filters=filters) if not ports: continue router_id = ports[0]['device_id'] interface = {'subnet_id': network['subnets'][0]} plugin.remove_router_interface(router_id, interface) LOG.info(_LI("Removed metadata interface on router %s"), router_id) plugin.delete_network(network['id']) LOG.info(_LI("Removed metadata network %s"), network['id']) else: lswitch_id = neutron_client.net_id_to_lswitch_id(network['id']) if not lswitch_id: continue tags = nsx_utils.build_v3_tags_payload( network, resource_type='os-neutron-net-id', project_name='admin') name = nsx_utils.get_name_and_uuid('%s-%s' % ( 'mdproxy', network['name'] or 'network'), network['id']) port_resource.create( lswitch_id, metadata_proxy_uuid, tags=tags, name=name, attachment_type=nsx_constants.ATTACHMENT_MDPROXY) LOG.info(_LI("Enabled native metadata proxy for network %s"), network['id'])
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()) nsxlib = v3_utils.get_connected_nsxlib() with v3_utils.NsxV3PluginWrapper() as plugin: for sg_id, sg in inconsistent_secgroups.items(): secgroup = plugin.get_security_group(context_, sg_id) try: # FIXME(roeyc): try..except clause should be removed once the # api will return 404 response code instead 400 for trying to # delete a non-existing firewall section. nsxlib.firewall_section.delete(sg['section-id']) except Exception: pass nsxlib.ns_group.delete(sg['nsx-securitygroup-id']) neutron_sg.delete_security_group_section_mapping(sg_id) neutron_sg.delete_security_group_backend_mapping(sg_id) nsgroup, fw_section = ( plugin._create_security_group_backend_resources(secgroup)) nsx_db.save_sg_mappings(context_, sg_id, nsgroup['id'], fw_section['id']) # If version > 1.1 then we use dynamic criteria tags, and the port # should already have them. if not nsxlib.feature_supported(consts.FEATURE_DYNAMIC_CRITERIA): members = [] for port_id in neutron_sg.get_ports_in_security_group(sg_id): lport_id = neutron_sg.get_logical_port_id(port_id) members.append(lport_id) nsxlib.ns_group.add_members(nsgroup['id'], consts.TARGET_TYPE_LOGICAL_PORT, members) for rule in secgroup['security_group_rules']: rule_mapping = (context_.session.query( nsx_models.NeutronNsxRuleMapping).filter_by( neutron_id=rule['id']).one()) with context_.session.begin(subtransactions=True): context_.session.delete(rule_mapping) action = (consts.FW_ACTION_DROP if secgroup.get( provider_sg.PROVIDER) else consts.FW_ACTION_ALLOW) rules = plugin._create_firewall_rules( context_, fw_section['id'], nsgroup['id'], secgroup.get(sg_logging.LOGGING, False), action, secgroup['security_group_rules']) plugin.save_security_group_rule_mappings(context_, rules['rules'])
def update_dhcp_relay(resource, event, trigger, **kwargs): """Update all routers dhcp relay service by the current configuration""" nsxlib = utils.get_connected_nsxlib() if not nsxlib.feature_supported(nsx_constants.FEATURE_DHCP_RELAY): version = nsxlib.get_version() LOG.error("DHCP relay is not supported by NSX version %s", version) return admin_cxt = neutron_context.get_admin_context() filters = utils.get_plugin_filters(admin_cxt) with utils.NsxV3PluginWrapper() as plugin: # Make sure FWaaS was initialized plugin.init_fwaas_for_admin_utils() # get all neutron routers and interfaces ports routers = plugin.get_routers(admin_cxt, filters=filters) for router in routers: LOG.info("Updating router %s", router['id']) port_filters = { 'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF], 'device_id': [router['id']] } ports = plugin.get_ports(admin_cxt, filters=port_filters) for port in ports: # get the backend router port by the tag nsx_port_id = nsxlib.get_id_by_resource_and_tag( 'LogicalRouterDownLinkPort', 'os-neutron-rport-id', port['id']) if not nsx_port_id: LOG.warning( "Couldn't find nsx router port for interface " "%s", port['id']) continue # get the network of this port network_id = port['network_id'] # check the relay service on the az of the network az = plugin.get_network_az_by_net_id(admin_cxt, network_id) nsxlib.logical_router_port.update( nsx_port_id, relay_service_uuid=az.dhcp_relay_service) # if FWaaS is enables, also update the firewall rules try: plugin.update_router_firewall(admin_cxt, router['id']) except Exception as e: LOG.warning( "Updating router firewall was skipped because of " "an error %s", e) LOG.info("Done.")
def nsx_update_router_lb_advertisement(resource, event, trigger, **kwargs): """The implementation of the VIP advertisement changed. This utility will update existing LB/routers """ nsxlib = utils.get_connected_nsxlib() if not nsxlib.feature_supported(consts.FEATURE_LOAD_BALANCER): LOG.error("This utility is not available for NSX version %s", nsxlib.get_version()) return # Get the list of neutron routers used by LB lb_services = nsxlib.load_balancer.service.list()['results'] lb_routers = [] for lb_srv in lb_services: for tag in lb_srv.get('tags', []): if tag['scope'] == 'os-neutron-router-id': lb_routers.append(tag['tag']) lb_routers = set(lb_routers) LOG.info( "Going to update LB advertisement on %(num)s router(s): " "%(routers)s", { 'num': len(lb_routers), 'routers': lb_routers }) context = neutron_context.get_admin_context() with utils.NsxV3PluginWrapper() as plugin: for rtr_id in lb_routers: nsx_router_id = nsx_db.get_nsx_router_id(context.session, rtr_id) if not nsx_router_id: LOG.error("Router %s NSX Id was not found.", rtr_id) continue try: # disable the global vip advertisement flag plugin.nsxlib.logical_router.update_advertisement( nsx_router_id, advertise_lb_vip=False) # Add an advertisement rule for the external network router = plugin.get_router(context, rtr_id) lb_utils.update_router_lb_vip_advertisement( context, plugin, router, nsx_router_id) except Exception as e: LOG.error("Failed updating router %(id)s: %(e)s", { 'id': rtr_id, 'e': e }) LOG.info("Done.")
def nsx_recreate_dhcp_server(resource, event, trigger, **kwargs): """Recreate DHCP server & binding for a neutron network""" if not cfg.CONF.nsx_v3.native_dhcp_metadata: LOG.error("Native DHCP is disabled.") return errmsg = ("Need to specify net-id property. Add --property net-id=<id>") if not kwargs.get('property'): LOG.error("%s", errmsg) return properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) net_id = properties.get('net-id') if not net_id: LOG.error("%s", errmsg) return context = neutron_context.get_admin_context() with utils.NsxV3PluginWrapper() as plugin: # verify that this is an existing network with dhcp enabled try: network = plugin._get_network(context, net_id) except exceptions.NetworkNotFound: LOG.error("Network %s was not found", net_id) return if plugin._has_no_dhcp_enabled_subnet(context, network): LOG.error("Network %s has no DHCP enabled subnet", net_id) return dhcp_relay = plugin.get_network_az_by_net_id( context, net_id).dhcp_relay_service if dhcp_relay: LOG.error("Native DHCP should not be enabled with dhcp relay") return # find the dhcp subnet of this network subnet_id = None for subnet in network.subnets: if subnet.enable_dhcp: subnet_id = subnet.id break if not subnet_id: LOG.error("Network %s has no DHCP enabled subnet", net_id) return dhcp_subnet = plugin.get_subnet(context, subnet_id) # disable and re-enable the dhcp plugin._enable_native_dhcp(context, network, dhcp_subnet) LOG.info("Done.")
def list_missing_ports(resource, event, trigger, **kwargs): """List neutron ports that are missing the NSX backend port 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 v3_utils.NsxV3PluginWrapper() as plugin: problems = plugin_utils.get_mismatch_logical_ports( admin_cxt, nsxlib, plugin, filters) if len(problems) > 0: title = ("Found internal ports misconfiguration on the " "NSX manager:") LOG.info( formatters.output_formatter(title, problems, ['neutron_id', 'nsx_id', 'error'])) else: LOG.info("All internal ports verified on the NSX manager")
def fix_security_groups(resource, event, trigger, **kwargs): context_ = neutron_context.get_admin_context() plugin = v3_utils.NsxV3PluginWrapper() inconsistent_secgroups = _find_missing_sections() inconsistent_secgroups.update(_find_missing_security_groups()) for sg_id, sg in inconsistent_secgroups.items(): secgroup = plugin.get_security_group(context_, sg_id) nsxlib.delete_section(sg['section-id']) nsxlib.delete_nsgroup(sg['nsx-securitygroup-id']) neutron_sg.delete_security_group_section_mapping(sg_id) neutron_sg.delete_security_group_backend_mapping(sg_id) nsgroup, fw_section = ( plugin._create_security_group_backend_resources(secgroup)) nsx_db.save_sg_mappings(context_.session, sg_id, nsgroup['id'], fw_section['id']) # If version > 1.1 then we use dynamic criteria tags, and the port # should already have them. if not utils.is_nsx_version_1_1_0(plugin._nsx_version): members = [] for port_id in neutron_db.get_ports_in_security_group(sg_id): lport_id = neutron_db.get_logical_port_id(port_id) members.append(lport_id) nsxlib.add_nsgroup_members(nsgroup['id'], firewall.LOGICAL_PORT, members) for rule in secgroup['security_group_rules']: rule_mapping = (context_.session.query( nsx_models.NeutronNsxRuleMapping).filter_by( neutron_id=rule['id']).one()) with context_.session.begin(subtransactions=True): context_.session.delete(rule_mapping) action = (firewall.DROP if secgroup.get(provider_sg.PROVIDER) else firewall.ALLOW) rules = nsxlib.create_firewall_rules( context_, fw_section['id'], nsgroup['id'], secgroup.get(sg_logging.LOGGING, False), action, secgroup['security_group_rules']) nsxlib.save_sg_rule_mappings(context_.session, rules['rules']) # Add nsgroup to a nested group plugin.nsgroup_manager.add_nsgroup(nsgroup['id'])
def migrate_v_project_to_t(resource, event, trigger, **kwargs): """Migrate 1 project from v to t with all its resources""" # filter out the plugins INFO logging # TODO(asarfaty): Consider this for all admin utils LOG.logger.setLevel(logging.INFO) logging.getLogger(None).logger.setLevel(logging.WARN) # get the configuration: tenant + public network + from file flag usage = ("Usage: nsxadmin -r projects -o %s --property project-id=<> " "--property external-net=<NSX-T external network to be used> " "<--property from-file=True>" % shell.Operations.NSX_MIGRATE_V_V3.value) if not kwargs.get('property'): LOG.error("Missing parameters: %s", usage) return properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) project = properties.get('project-id') ext_net_id = properties.get('external-net') from_file = properties.get('from-file', 'false').lower() == "true" # TODO(asarfaty): get files path if not project: LOG.error("Missing project-id parameter: %s", usage) return if not ext_net_id: LOG.error("Missing external-net parameter: %s", usage) return # check if files exist in the current directory try: filename = get_resource_file_name(project, 'network') file = open(filename, 'r') if file.read(): if not from_file: from_file = admin_utils.query_yes_no( "Use existing resources files for this project?", default="yes") file.close() except Exception: sys.exc_clear() if from_file: LOG.error("Cannot run from file: files not found") return # validate tenant id and public network ctx = n_context.get_admin_context() mapping = db.get_project_plugin_mapping(ctx.session, project) current_plugin = mapping.plugin if not mapping: LOG.error("Project %s is unknown", project) return if not from_file and current_plugin != projectpluginmap.NsxPlugins.NSX_V: LOG.error("Project %s belongs to plugin %s.", project, mapping.plugin) return with v3_utils.NsxV3PluginWrapper() as plugin: try: plugin.get_network(ctx, ext_net_id) except exceptions.NetworkNotFound: LOG.error("Network %s was not found", ext_net_id) return if not plugin._network_is_external(ctx, ext_net_id): LOG.error("Network %s is not external", ext_net_id) return if from_file: # read resources from files objects = read_v_resources_from_files(project) else: # read all V resources and dump to a file objects = read_v_resources_to_files(ctx, project) # delete all the V resources (reading it from the files) if current_plugin == projectpluginmap.NsxPlugins.NSX_V: delete_v_resources(ctx, objects) # change the mapping of this tenant to T db.update_project_plugin_mapping(ctx.session, project, projectpluginmap.NsxPlugins.NSX_T) # use api replay flag to allow keeping the IDs cfg.CONF.set_override('api_replay_mode', True) # add resources 1 by one after adapting them to T (api-replay code) create_t_resources(ctx, objects, ext_net_id) # reset api replay flag to allow keeping the IDs cfg.CONF.set_override('api_replay_mode', False)
def create_t_resources(context, objects, ext_net): """Create a list of objects in the T plugin""" LOG.info(">>>>Creating all the objects of the project in NSX-T.") prepare = replay_utils.PrepareObjectForMigration() with v3_utils.NsxV3PluginWrapper() as plugin: # create the resource in the order opposite to the deletion # (but start with routers) ordered_resources = migrated_resources[::-1] ordered_resources.remove('router') ordered_resources = ['router'] + ordered_resources dhcp_subnets = [] for resource in ordered_resources: total_num = len(objects[resource]) LOG.info(">>>Creating %s %s%s.", total_num, resource, 's' if total_num > 1 else '') get_object = getattr(plugin, "get_%s" % resource) create_object = getattr(plugin, "create_%s" % resource) # go over the objects of this resource for count, obj in enumerate(objects[resource], 1): # check if this object already exists try: get_object(context, obj['id']) except exceptions.NotFound: # prevent logger from logging this exception sys.exc_clear() else: # already exists (this will happen if we rerun from files, # or if the deletion failed) LOG.info(">>Skipping %(resource)s %(name)s %(count)s/" "%(total)s as it was already created.", {'resource': resource, 'name': obj.get('name') or obj['id'], 'count': count, 'total': total_num}) continue # fix object before creation using the api replay code orig_id = obj['id'] prepare_object = getattr(prepare, "prepare_%s" % resource) obj_data = prepare_object(obj, direct_call=True) enable_dhcp = False # special cases for different objects before create: if resource == 'subnet': if obj_data['enable_dhcp']: enable_dhcp = True # disable dhcp for now, to avoid ip collisions obj_data['enable_dhcp'] = False elif resource == 'security_group': # security group rules should be added separately sg_rules = obj_data.pop('security_group_rules') elif resource == 'floatingip': # Create the floating IP on the T external network obj_data['floating_network_id'] = ext_net del obj_data['floating_ip_address'] elif resource == 'port': # remove the old subnet id field from ports fixed_ips dict # since the subnet ids are changed for fixed_ips in obj_data['fixed_ips']: del fixed_ips['subnet_id'] if obj_data['device_owner'] == 'network:dhcp': continue if obj_data['device_owner'] == 'network:floatingip': continue if obj_data['device_owner'] == 'network:router_gateway': # add a gateway on the new ext network for this router router_id = obj_data['device_id'] # keep the original enable-snat value router_data = get_router_by_id(objects, router_id) enable_snat = router_data['external_gateway_info'].get( 'enable_snat', True) rtr_body = { "external_gateway_info": {"network_id": ext_net, "enable_snat": enable_snat}} try: plugin.update_router( context, router_id, {'router': rtr_body}) LOG.info(">>Uplinked router %(rtr)s to new " "external network %(net)s", {'rtr': router_id, 'net': ext_net}) except Exception as e: LOG.error(">>Failed to add router %(rtr)s " "gateway: %(e)s", {'rtr': router_id, 'e': e}) continue if obj_data['device_owner'] == 'network:router_interface': try: # uplink router_interface ports by creating the # port, and attaching it to the router router_id = obj_data['device_id'] obj_data['device_owner'] = "" obj_data['device_id'] = "" created_port = plugin.create_port( context, {'port': obj_data}) LOG.info(">>Created interface port %(port)s, ip " "%(ip)s, mac %(mac)s)", {'port': created_port['id'], 'ip': created_port['fixed_ips'][0][ 'ip_address'], 'mac': created_port['mac_address']}) plugin.add_router_interface( context, router_id, {'port_id': created_port['id']}) LOG.info(">>Uplinked router %(rtr)s to network " "%(net)s", {'rtr': router_id, 'net': obj_data['network_id']}) except Exception as e: LOG.error(">>Failed to add router %(rtr)s " "interface port: %(e)s", {'rtr': router_id, 'e': e}) continue # create the object on the NSX-T plugin try: created_obj = create_object(context, {resource: obj_data}) LOG.info(">>Created %(resource)s %(name)s %(count)s/" "%(total)s", {'resource': resource, 'count': count, 'name': obj_data.get('name') or orig_id, 'total': total_num}) except Exception as e: # TODO(asarfaty): subnets ids are changed, so recreating a # subnet will fail on overlapping ips. LOG.error(">>Failed to create %(resource)s %(name)s: " "%(e)s", {'resource': resource, 'e': e, 'name': obj_data.get('name') or orig_id}) continue # special cases for different objects after create: if resource == 'security_group': sg_id = obj_data.get('name') or obj_data['id'] for rule in sg_rules: rule_data = prepare.prepare_security_group_rule(rule) try: plugin.create_security_group_rule( context, {'security_group_rule': rule_data}) except ext_sg.SecurityGroupRuleExists: # default rules were already created. # prevent logger from logging this exception sys.exc_clear() except Exception as e: LOG.error( ">>Failed to create security group %(name)s " "rules: %(e)s", {'name': sg_id, 'e': e}) elif resource == 'subnet': if enable_dhcp: dhcp_subnets.append(created_obj['id']) # Enable dhcp on all the relevant subnets (after creating all ports, # to maintain original IPs): if dhcp_subnets: for subnet_id in dhcp_subnets: try: plugin.update_subnet( context, subnet_id, {'subnet': {'enable_dhcp': True}}) except Exception as e: LOG.error("Failed to enable DHCP on subnet %(subnet)s:" " %(e)s", {'subnet': subnet_id, 'e': e}) # Add static routes (after all router interfaces and gateways are set) for obj_data in objects['router']: if 'routes' in obj_data: try: plugin.update_router( context, obj_data['id'], {'router': {'routes': obj_data['routes']}}) except Exception as e: LOG.error("Failed to add routes to router %(rtr)s: " "%(e)s", {'rtr': obj_data['id'], 'e': e}) LOG.info(">>>Done Creating all objects in NSX-T.")