def list_missing_routers(resource, event, trigger, **kwargs): """List neutron routers that are missing the NSX backend router """ plugin = RoutersPlugin() admin_cxt = neutron_context.get_admin_context() neutron_routers = plugin.get_routers(admin_cxt) routers = [] for router in neutron_routers: neutron_id = router['id'] # get the router nsx id from the mapping table nsx_id = nsx_db.get_nsx_router_id(admin_cxt.session, neutron_id) if not nsx_id: routers.append({ 'name': router['name'], 'neutron_id': neutron_id, 'nsx_id': None }) else: try: nsxlib.logical_router.get(nsx_id) except nsx_exc.ResourceNotFound: routers.append({ 'name': router['name'], 'neutron_id': neutron_id, 'nsx_id': nsx_id }) if len(routers) > 0: title = ("Found %d routers missing from the NSX " "manager:") % len(routers) LOG.info( formatters.output_formatter(title, routers, ['name', 'neutron_id', 'nsx_id'])) else: LOG.info("All routers exist on the NSX manager")
def _check_lb_service_on_router(self, resource, event, trigger, payload=None): """Prevent removing a router GW or deleting a router used by LB""" router_id = payload.resource_id context = payload.context nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) if not nsx_router_id: # Skip non-v3 routers (could be a V router in case of TVD plugin) return nsxlib = self.loadbalancer.core_plugin.nsxlib service_client = nsxlib.load_balancer.service # Check if there is any lb service on nsx router lb_service = service_client.get_router_lb_service(nsx_router_id) if lb_service: msg = _('Cannot delete a %s as it still has lb service ' 'attachment') % resource raise n_exc.BadRequest(resource='lbaas-lb', msg=msg) # Also check if there are any loadbalancers attached to this router # subnets router_subnets = self.loadbalancer.core_plugin._find_router_subnets( context.elevated(), router_id) subnet_ids = [subnet['id'] for subnet in router_subnets] if subnet_ids and self._get_lb_ports(context.elevated(), subnet_ids): msg = (_('Cannot delete a %s as it used by a loadbalancer') % resource) raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)
def get_nsx_router_id(session, cluster, neutron_router_id): """Return the NSX router uuid for a given neutron router. First, look up the Neutron database. If not found, execute a query on NSX platform as the mapping might be missing. """ if not neutron_router_id: return nsx_router_id = nsx_db.get_nsx_router_id( session, neutron_router_id) if not nsx_router_id: # Find logical router from backend. # This is a rather expensive query, but it won't be executed # more than once for each router in Neutron's lifetime nsx_routers = routerlib.query_lrouters( cluster, '*', filters={'tag': neutron_router_id, 'tag_scope': 'q_router_id'}) # Only one result expected # NOTE(salv-orlando): Not handling the case where more than one # port is found with the same neutron port tag if not nsx_routers: LOG.warning("Unable to find NSX router for Neutron router %s", neutron_router_id) return nsx_router = nsx_routers[0] nsx_router_id = nsx_router['uuid'] with session.begin(subtransactions=True): # Create DB mapping nsx_db.add_neutron_nsx_router_mapping( session, neutron_router_id, nsx_router_id) return nsx_router_id
def update_enable_standby_relocation(resource, event, trigger, **kwargs): """Enable standby relocation on all routers """ # This feature is supported only since nsx version 2.4 nsxlib = utils.get_connected_nsxlib() version = nsxlib.get_version() if not nsx_utils.is_nsx_version_2_4_0(version): LOG.info("Standby relocation update is only supported from 2.4 " "onwards") LOG.info("Version is %s", version) return # Go over all neutron routers plugin = RoutersPlugin() admin_cxt = neutron_context.get_admin_context() filters = utils.get_plugin_filters(admin_cxt) neutron_routers = plugin.get_routers(admin_cxt, filters=filters) for router in neutron_routers: neutron_id = router['id'] # get the router nsx id from the mapping table nsx_id = nsx_db.get_nsx_router_id(admin_cxt.session, neutron_id) try: nsxlib.logical_router.update(lrouter_id=nsx_id, enable_standby_relocation=True) except Exception as e: # This may fail if the service router is not created LOG.warning("Router %s cannot enable standby relocation: %s", neutron_id, e) else: LOG.info("Router %s was enabled with standby relocation", neutron_id) LOG.info("Done")
def get_nsx_router_id(session, cluster, neutron_router_id): """Return the NSX router uuid for a given neutron router. First, look up the Neutron database. If not found, execute a query on NSX platform as the mapping might be missing. """ if not neutron_router_id: return nsx_router_id = nsx_db.get_nsx_router_id(session, neutron_router_id) if not nsx_router_id: # Find logical router from backend. # This is a rather expensive query, but it won't be executed # more than once for each router in Neutron's lifetime nsx_routers = routerlib.query_lrouters(cluster, '*', filters={ 'tag': neutron_router_id, 'tag_scope': 'q_router_id' }) # Only one result expected # NOTE(salv-orlando): Not handling the case where more than one # port is found with the same neutron port tag if not nsx_routers: LOG.warning("Unable to find NSX router for Neutron router %s", neutron_router_id) return nsx_router = nsx_routers[0] nsx_router_id = nsx_router['uuid'] with session.begin(subtransactions=True): # Create DB mapping nsx_db.add_neutron_nsx_router_mapping(session, neutron_router_id, nsx_router_id) return nsx_router_id
def _get_backend_router_and_fw_section(self, context, router_id): # find the backend router id in the DB nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) if nsx_router_id is None: LOG.error("Didn't find nsx router for router %s", router_id) raise exceptions.FirewallInternalDriverError( driver=FWAAS_DRIVER_NAME) # get the FW section id of the backend router try: section_id = self.nsx_router.get_firewall_section_id(nsx_router_id) except Exception as e: LOG.error( "Failed to find router firewall section for router " "%(id)s: %(e)s", { 'id': router_id, 'e': e }) raise exceptions.FirewallInternalDriverError( driver=FWAAS_DRIVER_NAME) if section_id is None: LOG.error( "Failed to find router firewall section for router " "%(id)s.", {'id': router_id}) raise exceptions.FirewallInternalDriverError( driver=FWAAS_DRIVER_NAME) return nsx_router_id, section_id
def update_nat_rules(resource, event, trigger, **kwargs): """Update all routers NAT rules to not bypass the firewall""" # This feature is supported only since nsx version 2 nsxlib = utils.get_connected_nsxlib() version = nsxlib.get_version() if not nsx_utils.is_nsx_version_2_0_0(version): LOG.info("NAT rules update only supported from 2.0 onwards") LOG.info("Version is %s", version) return # Go over all neutron routers plugin = RoutersPlugin() admin_cxt = neutron_context.get_admin_context() neutron_routers = plugin.get_routers(admin_cxt) num_of_updates = 0 for router in neutron_routers: neutron_id = router['id'] # get the router nsx id from the mapping table nsx_id = nsx_db.get_nsx_router_id(admin_cxt.session, neutron_id) if nsx_id: # get all NAT rules: rules = nsxlib.logical_router.list_nat_rules(nsx_id)['results'] for rule in rules: if 'nat_pass' not in rule or rule['nat_pass']: nsxlib.logical_router.update_nat_rule(nsx_id, rule['id'], nat_pass=False) num_of_updates = num_of_updates + 1 if num_of_updates: LOG.info("Done updating %s NAT rules", num_of_updates) else: LOG.info("Did not find any NAT rule to update")
def _check_lb_service_on_router(self, resource, event, trigger, **kwargs): """Prevent removing a router GW or deleting a router used by LB""" router_id = kwargs.get('router_id') context = kwargs['context'] nsx_router_id = nsx_db.get_nsx_router_id(kwargs['context'].session, router_id) if not nsx_router_id: # Skip non-v3 routers (could be a V router in case of TVD plugin) return nsxlib = self.loadbalancer.core_plugin.nsxlib service_client = nsxlib.load_balancer.service # Check if there is any lb service on nsx router lb_service = service_client.get_router_lb_service(nsx_router_id) if lb_service: msg = _('Cannot delete a %s as it still has lb service ' 'attachment') % resource raise n_exc.BadRequest(resource='lbaas-lb', msg=msg) # Also check if there are any loadbalancers attached to this router # subnets router_subnets = self.loadbalancer.core_plugin._find_router_subnets( context.elevated(), router_id) subnet_ids = [subnet['id'] for subnet in router_subnets] if subnet_ids and self._get_lb_ports(context.elevated(), subnet_ids): msg = (_('Cannot delete a %s as it used by a loadbalancer') % resource) raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)
def _check_lb_service_on_router(self, resource, event, trigger, **kwargs): """Check if there is any lb service on nsx router""" nsx_router_id = nsx_db.get_nsx_router_id(kwargs['context'].session, kwargs['router_id']) nsxlib = self.loadbalancer.core_plugin.nsxlib service_client = nsxlib.load_balancer.service lb_service = service_client.get_router_lb_service(nsx_router_id) if lb_service: msg = _('Cannot delete router as it still has lb service ' 'attachment') raise nc_exc.CallbackFailure(msg)
def create(self, context, lb, completor): if not lb_utils.validate_lb_subnet(context, self.core_plugin, lb['vip_subnet_id']): completor(success=False) msg = (_('Cannot create lb on subnet %(sub)s for ' 'loadbalancer %(lb)s. The subnet needs to connect a ' 'router which is already set gateway.') % { 'sub': lb['vip_subnet_id'], 'lb': lb['id'] }) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) service_client = self.core_plugin.nsxlib.load_balancer.service nsx_router_id = None lb_service = None nsx_router_id = lb_utils.NO_ROUTER_ID router_id = lb_utils.get_router_from_network(context, self.core_plugin, lb['vip_subnet_id']) if router_id: nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) lb_service = service_client.get_router_lb_service(nsx_router_id) if not lb_service: lb_size = lb_utils.get_lb_flavor_size(self.flavor_plugin, context, lb.get('flavor_id')) if router_id: # Make sure the NSX service router exists if not self.core_plugin.service_router_has_services( context, router_id): self.core_plugin.create_service_router(context, router_id) lb_service = self._create_lb_service(context, service_client, lb['tenant_id'], router_id, nsx_router_id, lb['id'], lb_size) else: lb_service = self._create_lb_service_without_router( context, service_client, lb['tenant_id'], lb, lb_size) if not lb_service: completor(success=False) msg = (_('Failed to create lb service for loadbalancer ' '%s') % lb['id']) raise nsx_exc.NsxPluginException(err_msg=msg) nsx_db.add_nsx_lbaas_loadbalancer_binding(context.session, lb['id'], lb_service['id'], nsx_router_id, lb['vip_address']) completor(success=True)
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 create(self, context, lb, completor): if not lb_utils.validate_lb_subnet(context, self.core_plugin, lb['vip_subnet_id']): completor(success=False) msg = (_('Cannot create lb on subnet %(sub)s for ' 'loadbalancer %(lb)s. The subnet needs to connect a ' 'router which is already set gateway.') % {'sub': lb['vip_subnet_id'], 'lb': lb['id']}) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) service_client = self.core_plugin.nsxlib.load_balancer.service nsx_router_id = None lb_service = None nsx_router_id = lb_utils.NO_ROUTER_ID router_id = lb_utils.get_router_from_network( context, self.core_plugin, lb['vip_subnet_id']) if router_id: nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) lb_service = service_client.get_router_lb_service(nsx_router_id) if not lb_service: lb_size = lb_utils.get_lb_flavor_size( self.flavor_plugin, context, lb.get('flavor_id')) if router_id: # Make sure the NSX service router exists if not self.core_plugin.service_router_has_services( context, router_id): self.core_plugin.create_service_router(context, router_id) lb_service = self._create_lb_service( context, service_client, lb['tenant_id'], router_id, nsx_router_id, lb['id'], lb_size) else: lb_service = self._create_lb_service_without_router( context, service_client, lb['tenant_id'], lb, lb_size) if not lb_service: completor(success=False) msg = (_('Failed to create lb service for loadbalancer ' '%s') % lb['id']) raise nsx_exc.NsxPluginException(err_msg=msg) nsx_db.add_nsx_lbaas_loadbalancer_binding( context.session, lb['id'], lb_service['id'], nsx_router_id, lb['vip_address']) completor(success=True)
def _check_lb_service_on_router_interface(self, *args, **kwargs): # Prevent removing the interface of an LB subnet from a router router_id = kwargs.get('router_id') subnet_id = kwargs.get('subnet_id') if not router_id or not subnet_id: return nsx_router_id = nsx_db.get_nsx_router_id(kwargs['context'].session, kwargs['router_id']) if not nsx_router_id: # Skip non-v3 routers (could be a V router in case of TVD plugin) return # get LB ports and check if any loadbalancer is using this subnet if self._get_lb_ports(kwargs['context'].elevated(), [subnet_id]): msg = _('Cannot delete a router interface as it used by a ' 'loadbalancer') raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)
def _check_lb_service_on_router_interface( self, resource, event, trigger, payload=None): # Prevent removing the interface of an LB subnet from a router router_id = payload.resource_id subnet_id = payload.metadata.get('subnet_id') if not router_id or not subnet_id: return nsx_router_id = nsx_db.get_nsx_router_id(payload.context.session, router_id) if not nsx_router_id: # Skip non-v3 routers (could be a V router in case of TVD plugin) return # get LB ports and check if any loadbalancer is using this subnet if self._get_lb_ports(payload.context.elevated(), [subnet_id]): msg = _('Cannot delete a router interface as it used by a ' 'loadbalancer') raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)
def _update_router_advertisement(self, context, vpnservice): LOG.debug("Updating router advertisement rules for router %s", vpnservice['router_id']) router_id = vpnservice['router_id'] # skip no-snat router as it is already advertised, # and router with no gw rtr = self.l3_plugin.get_router(context, router_id) if (not rtr.get('external_gateway_info') or not rtr['external_gateway_info'].get('enable_snat', True)): return rules = [] # get all the active services of this router filters = {'router_id': [router_id], 'status': [constants.ACTIVE]} services = self.vpn_plugin.get_vpnservices(context.elevated(), filters=filters) for srv in services: # use only services with active connections filters = { 'vpnservice_id': [srv['id']], 'status': [constants.ACTIVE] } connections = self.vpn_plugin.get_ipsec_site_connections( context.elevated(), filters=filters) if not connections: continue subnet = self.l3_plugin.get_subnet(context.elevated(), srv['subnet_id']) rules.append({ 'display_name': 'VPN advertisement service ' + srv['id'], 'action': consts.FW_ACTION_ALLOW, 'networks': [subnet['cidr']] }) logical_router_id = db.get_nsx_router_id(context.session, router_id) self._nsxlib.logical_router.update_advertisement_rules( logical_router_id, rules)
def _check_lb_service_on_router_interface(self, resource, event, trigger, payload=None): # Prevent removing the interface of an LB subnet from a router router_id = payload.resource_id subnet_id = payload.metadata.get('subnet_id') if not router_id or not subnet_id: return nsx_router_id = nsx_db.get_nsx_router_id(payload.context.session, router_id) if not nsx_router_id: # Skip non-v3 routers (could be a V router in case of TVD plugin) return # get LB ports and check if any loadbalancer is using this subnet if self._get_lb_ports(payload.context.elevated(), [subnet_id]): msg = _('Cannot delete a router interface as it used by a ' 'loadbalancer') raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)
def _update_router_advertisement(self, context, vpnservice): LOG.debug("Updating router advertisement rules for router %s", vpnservice['router_id']) router_id = vpnservice['router_id'] # skip no-snat router as it is already advertised, # and router with no gw rtr = self.l3_plugin.get_router(context, router_id) if (not rtr.get('external_gateway_info') or not rtr['external_gateway_info'].get('enable_snat', True)): return rules = [] # get all the active services of this router filters = {'router_id': [router_id], 'status': [constants.ACTIVE]} services = self.vpn_plugin.get_vpnservices( context.elevated(), filters=filters) rule_name_pref = 'VPN advertisement service' for srv in services: # use only services with active connections filters = {'vpnservice_id': [srv['id']], 'status': [constants.ACTIVE]} connections = self.vpn_plugin.get_ipsec_site_connections( context.elevated(), filters=filters) if not connections: continue subnet = self.l3_plugin.get_subnet( context.elevated(), srv['subnet_id']) rules.append({ 'display_name': "%s %s" % (rule_name_pref, srv['id']), 'action': consts.FW_ACTION_ALLOW, 'networks': [subnet['cidr']]}) if rules: logical_router_id = db.get_nsx_router_id(context.session, router_id) self._nsxlib.logical_router.update_advertisement_rules( logical_router_id, rules, name_prefix=rule_name_pref)
def _member_create(self, context, member, completor): lb_id = member['pool']['loadbalancer_id'] pool_id = member['pool']['id'] loadbalancer = member['pool']['loadbalancer'] if not lb_utils.validate_lb_member_subnet(context, self.core_plugin, member['subnet_id'], loadbalancer): completor(success=False) msg = (_('Cannot add member %(member)s to pool as member subnet ' '%(subnet)s is neither public nor connected to the LB ' 'router') % {'member': member['id'], 'subnet': member['subnet_id']}) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) pool_client = self.core_plugin.nsxlib.load_balancer.pool service_client = self.core_plugin.nsxlib.load_balancer.service network = lb_utils.get_network_from_subnet( context, self.core_plugin, member['subnet_id']) if network.get('router:external'): fixed_ip, router_id = self._get_info_from_fip( context, member['address']) if not router_id: completor(success=False) msg = (_('Floating ip %(fip)s has no router') % { 'fip': member['address']}) raise n_exc.BadRequest(resource='lbaas-vip', msg=msg) else: router_id = lb_utils.get_router_from_network( context, self.core_plugin, member['subnet_id']) fixed_ip = member['address'] binding = nsx_db.get_nsx_lbaas_pool_binding(context.session, lb_id, pool_id) if binding: lb_pool_id = binding.get('lb_pool_id') lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) if not lb_binding: completor(success=False) msg = (_('Failed to get LB binding for member %s') % member['id']) raise nsx_exc.NsxPluginException(err_msg=msg) if lb_binding.lb_router_id == lb_utils.NO_ROUTER_ID: # Need to attach the LB service to the router now # This will happen here in case of external vip nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) try: tags = lb_utils.get_tags(self.core_plugin, router_id, lb_const.LR_ROUTER_TYPE, member['tenant_id'], context.project_name) service_client.update_service_with_attachment( lb_binding.lb_service_id, nsx_router_id, tags=tags) # TODO(asarfaty): Also update the tags except nsxlib_exc.ManagerError as e: # This will happen if there is another service already # attached to this router. # This is currently a limitation. completor(success=False) msg = (_('Failed to attach router %(rtr)s to LB service ' '%(srv)s: %(e)s') % {'rtr': router_id, 'srv': lb_binding.lb_service_id, 'e': e}) raise nsx_exc.NsxPluginException(err_msg=msg) # Update the nsx router in the DB binding nsx_db.update_nsx_lbaas_loadbalancer_binding( context.session, lb_id, nsx_router_id) # Add rule to advertise external vips router = self.core_plugin.get_router(context, router_id) lb_utils.update_router_lb_vip_advertisement( context, self.core_plugin, router, nsx_router_id) with locking.LockManager.get_lock('pool-member-%s' % lb_pool_id): lb_pool = pool_client.get(lb_pool_id) old_m = lb_pool.get('members', None) new_m = [{ 'display_name': member['name'][:219] + '_' + member['id'], 'ip_address': fixed_ip, 'port': member['protocol_port'], 'weight': member['weight']}] members = (old_m + new_m) if old_m else new_m pool_client.update_pool_with_members(lb_pool_id, members) else: completor(success=False) msg = (_('Failed to get pool binding to add member %s') % member['id']) raise nsx_exc.NsxPluginException(err_msg=msg) completor(success=True)
def create(self, context, member): lb_id = member.pool.loadbalancer_id pool_id = member.pool.id loadbalancer = member.pool.loadbalancer if not lb_utils.validate_lb_subnet(context, self.core_plugin, member.subnet_id): msg = (_('Cannot add member %(member)s to pool as member subnet ' '%(subnet)s is neither public nor connected to router') % { 'member': member.id, 'subnet': member.subnet_id }) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) pool_client = self.core_plugin.nsxlib.load_balancer.pool service_client = self.core_plugin.nsxlib.load_balancer.service pool_members = self.lbv2_driver.plugin.get_pool_members( context, pool_id) network = lb_utils.get_network_from_subnet(context, self.core_plugin, member.subnet_id) if network.get('router:external'): router_id, fixed_ip = self._get_info_from_fip( context, member.address) else: router_id = lb_utils.get_router_from_network( context, self.core_plugin, member.subnet_id) fixed_ip = member.address binding = nsx_db.get_nsx_lbaas_pool_binding(context.session, lb_id, pool_id) if binding: vs_id = binding.get('lb_vs_id') lb_pool_id = binding.get('lb_pool_id') lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) if not lb_binding and len(pool_members) == 1: nsx_router_id = nsx_db.get_nsx_router_id( context.session, router_id) lb_service = service_client.get_router_lb_service( nsx_router_id) if not lb_service: lb_size = lb_utils.get_lb_flavor_size( self.flavor_plugin, context, loadbalancer.flavor_id) lb_service = self._create_lb_service( context, service_client, member.tenant_id, router_id, nsx_router_id, loadbalancer.id, lb_size) if lb_service: lb_service_id = lb_service['id'] self._add_loadbalancer_binding(context, loadbalancer.id, lb_service_id, nsx_router_id, loadbalancer.vip_address) if vs_id: try: service_client.add_virtual_server( lb_service_id, vs_id) except nsxlib_exc.ManagerError: self.lbv2_driver.member.failed_completion( context, member) msg = (_('Failed to attach virtual server %(vs)s ' 'to lb service %(service)s') % { 'vs': vs_id, 'service': lb_service_id }) raise n_exc.BadRequest(resource='lbaas-member', msg=msg) else: msg = (_('Failed to get lb service to attach virtual ' 'server %(vs)s for member %(member)s') % { 'vs': vs_id, 'member': member['id'] }) raise nsx_exc.NsxPluginException(err_msg=msg) lb_pool = pool_client.get(lb_pool_id) old_m = lb_pool.get('members', None) new_m = [{ 'display_name': member.name[:219] + '_' + member.id, 'ip_address': fixed_ip, 'port': member.protocol_port, 'weight': member.weight }] members = (old_m + new_m) if old_m else new_m pool_client.update_pool_with_members(lb_pool_id, members) else: msg = (_('Failed to get pool binding to add member %s') % member['id']) raise nsx_exc.NsxPluginException(err_msg=msg) self.lbv2_driver.member.successful_completion(context, member)
def _member_create(self, context, member, completor): lb_id = member['pool']['loadbalancer_id'] pool_id = member['pool']['id'] loadbalancer = member['pool']['loadbalancer'] if not lb_utils.validate_lb_member_subnet( context, self.core_plugin, member['subnet_id'], loadbalancer): completor(success=False) msg = (_('Cannot add member %(member)s to pool as member subnet ' '%(subnet)s is neither public nor connected to the LB ' 'router') % { 'member': member['id'], 'subnet': member['subnet_id'] }) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) pool_client = self.core_plugin.nsxlib.load_balancer.pool service_client = self.core_plugin.nsxlib.load_balancer.service network = lb_utils.get_network_from_subnet(context, self.core_plugin, member['subnet_id']) if network.get('router:external'): fixed_ip, router_id = self._get_info_from_fip( context, member['address']) if not router_id: completor(success=False) msg = (_('Floating ip %(fip)s has no router') % { 'fip': member['address'] }) raise n_exc.BadRequest(resource='lbaas-vip', msg=msg) else: router_id = lb_utils.get_router_from_network( context, self.core_plugin, member['subnet_id']) fixed_ip = member['address'] binding = nsx_db.get_nsx_lbaas_pool_binding(context.session, lb_id, pool_id) if binding: vs_id = binding.get('lb_vs_id') lb_pool_id = binding.get('lb_pool_id') lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) lb_service = None if not lb_binding: nsx_router_id = nsx_db.get_nsx_router_id( context.session, router_id) lb_service = service_client.get_router_lb_service( nsx_router_id) virtual_server_ids = ( lb_service and lb_service.get('virtual_server_ids', []) or []) if not lb_service: lb_size = lb_utils.get_lb_flavor_size( self.flavor_plugin, context, loadbalancer.get('flavor_id')) if not self.core_plugin.service_router_has_services( context, router_id): self.core_plugin.create_service_router( context, router_id) lb_service = self._create_lb_service( context, service_client, member['tenant_id'], router_id, nsx_router_id, loadbalancer['id'], lb_size) if lb_service: lb_service_id = lb_service['id'] self._add_loadbalancer_binding(context, loadbalancer['id'], lb_service_id, nsx_router_id, loadbalancer['vip_address']) else: completor(success=False) msg = (_('Failed to get lb service to attach virtual ' 'server %(vs)s for member %(member)s') % { 'vs': vs_id, 'member': member['id'] }) raise nsx_exc.NsxPluginException(err_msg=msg) with locking.LockManager.get_lock('pool-member-%s' % lb_pool_id): lb_pool = pool_client.get(lb_pool_id) old_m = lb_pool.get('members', None) new_m = [{ 'display_name': member['name'][:219] + '_' + member['id'], 'ip_address': fixed_ip, 'port': member['protocol_port'], 'weight': member['weight'] }] members = (old_m + new_m) if old_m else new_m pool_client.update_pool_with_members(lb_pool_id, members) # Check whether the virtual server should be added to the load # balancing server. It is safe to perform this operation after the # member has been added to the pool. This allows us to skip this # check if there is already a member in the pool if vs_id and not old_m: # load the LB service if not already loaded if not lb_service: nsx_router_id = nsx_db.get_nsx_router_id( context.session, router_id) lb_service = service_client.get_router_lb_service( nsx_router_id) lb_service_id = lb_service['id'] virtual_server_ids = lb_service.get( 'virtual_server_ids', []) if vs_id not in virtual_server_ids: try: service_client.add_virtual_server(lb_service_id, vs_id) except nsxlib_exc.ManagerError: completor(success=False) msg = (_('Failed to attach virtual server %(vs)s ' 'to lb service %(service)s') % { 'vs': vs_id, 'service': lb_service_id }) raise n_exc.BadRequest(resource='lbaas-member', msg=msg) else: completor(success=False) msg = (_('Failed to get pool binding to add member %s') % member['id']) raise nsx_exc.NsxPluginException(err_msg=msg) completor(success=True)