def create(self, context, lb, completor): lb_id = lb['id'] network = lb_utils.get_network_from_subnet(context, self.core_plugin, lb['vip_subnet_id']) router_id = self._validate_lb_network(context, lb) if not router_id and not network.get('router:external'): completor(success=False) msg = (_('Cannot create a loadbalancer %(lb_id)s on subnet. ' '%(subnet)s is neither public nor connected to the LB ' 'router') % { 'lb_id': lb_id, 'subnet': lb['vip_subnet_id'] }) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) if router_id and not self.core_plugin.service_router_has_services( context, router_id): self.core_plugin.create_service_router(context, router_id) lb_name = utils.get_name_and_uuid(lb['name'] or 'lb', lb_id) tags = lb_utils.get_tags(self.core_plugin, router_id if router_id else '', lb_const.LR_ROUTER_TYPE, lb['tenant_id'], context.project_name) lb_size = lb_utils.get_lb_flavor_size(self.flavor_plugin, context, lb.get('flavor_id')) service_client = self.core_plugin.nsxpolicy.load_balancer.lb_service try: if network.get('router:external'): connectivity_path = None else: connectivity_path = self.core_plugin.nsxpolicy.tier1.get_path( router_id) service_client.create_or_overwrite( lb_name, lb_service_id=lb['id'], description=lb['description'], tags=tags, size=lb_size, connectivity_path=connectivity_path) # Add rule to advertise external vips if router_id: p_utils.update_router_lb_vip_advertisement( context, self.core_plugin, router_id) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error( 'Failed to create loadbalancer %(lb)s for lb with ' 'exception %(e)s', { 'lb': lb['id'], 'e': e }) completor(success=True)
def update(self, context, old_member, new_member, completor): network = lb_utils.get_network_from_subnet(context, self.core_plugin, new_member['subnet_id']) if network.get('router:external'): fixed_ip = self._get_info_from_fip(context, new_member['address']) else: fixed_ip = new_member['address'] pool_id = new_member['pool']['id'] pool_client = self.core_plugin.nsxpolicy.load_balancer.lb_pool try: pool_client.update_pool_member( pool_id, fixed_ip, port=new_member['protocol_port'], display_name=new_member['name'][:219] + '_' + new_member['id'], weight=new_member['weight']) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error( 'Failed to update member %(member)s on pool %(pool)s' ': %(err)s', { 'member': new_member['id'], 'pool': pool_id, 'err': e }) completor(success=True)
def create(self, context, member, completor): pool_client = self.core_plugin.nsxpolicy.load_balancer.lb_pool network = lb_utils.get_network_from_subnet( context, self.core_plugin, member['subnet_id']) self._validate_member_lb_connectivity(context, member, completor) if network.get('router:external'): fixed_ip = self._get_info_from_fip(context, member['address']) else: fixed_ip = member['address'] pool_id = member['pool']['id'] try: pool_client.create_pool_member_and_add_to_pool( pool_id, fixed_ip, port=member['protocol_port'], display_name=member['name'][:218] + '_' + member['id'], weight=member['weight']) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error('Failed to create member %(member)s on pool %(pool)s' ': %(err)s', {'member': member['id'], 'pool': pool_id, 'err': e}) completor(success=True)
def delete(self, context, member, completor): lb_id = member['pool']['loadbalancer_id'] pool_id = member['pool']['id'] pool_client = self.core_plugin.nsxlib.load_balancer.pool pool_binding = nsx_db.get_nsx_lbaas_pool_binding( context.session, lb_id, pool_id) if pool_binding: lb_pool_id = pool_binding.get('lb_pool_id') try: with locking.LockManager.get_lock('pool-member-%s' % lb_pool_id): lb_pool = pool_client.get(lb_pool_id) 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']) else: fixed_ip = member['address'] if 'members' in lb_pool: m_list = lb_pool['members'] members = [ m for m in m_list if m['ip_address'] != fixed_ip ] pool_client.update_pool_with_members( lb_pool_id, members) except nsxlib_exc.ResourceNotFound: pass except nsxlib_exc.ManagerError: completor(success=False) msg = _('Failed to remove member from pool on NSX backend') raise n_exc.BadRequest(resource='lbaas-member', msg=msg) completor(success=True)
def create(self, context, member, completor): pool_client = self.core_plugin.nsxpolicy.load_balancer.lb_pool network = lb_utils.get_network_from_subnet(context, self.core_plugin, member['subnet_id']) self._validate_member_lb_connectivity(context, member, completor) if network.get('router:external'): fixed_ip = self._get_info_from_fip(context, member['address']) else: fixed_ip = member['address'] pool_id = member['pool']['id'] try: pool_client.create_pool_member_and_add_to_pool( pool_id, fixed_ip, port=member['protocol_port'], display_name=member['name'][:218] + '_' + member['id'], weight=member['weight']) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error( 'Failed to create member %(member)s on pool %(pool)s' ': %(err)s', { 'member': member['id'], 'pool': pool_id, 'err': e }) completor(success=True)
def delete(self, context, member, completor): lb_id = member['pool']['loadbalancer_id'] pool_id = member['pool']['id'] pool_client = self.core_plugin.nsxlib.load_balancer.pool pool_binding = nsx_db.get_nsx_lbaas_pool_binding( context.session, lb_id, pool_id) if pool_binding: lb_pool_id = pool_binding.get('lb_pool_id') try: with locking.LockManager.get_lock('pool-member-%s' % lb_pool_id): lb_pool = pool_client.get(lb_pool_id) 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']) else: fixed_ip = member['address'] if 'members' in lb_pool: m_list = lb_pool['members'] members = [m for m in m_list if m['ip_address'] != fixed_ip] pool_client.update_pool_with_members(lb_pool_id, members) except nsxlib_exc.ResourceNotFound: pass except nsxlib_exc.ManagerError: completor(success=False) msg = _('Failed to remove member from pool on NSX backend') raise n_exc.BadRequest(resource='lbaas-member', msg=msg) completor(success=True)
def _get_updated_pool_members(self, context, lb_pool, member): 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']) else: fixed_ip = member['address'] for m in lb_pool['members']: if m['ip_address'] == fixed_ip: m['display_name'] = member['name'][:219] + '_' + member['id'] m['weight'] = member['weight'] return lb_pool['members']
def _get_updated_pool_members(self, context, lb_pool, member): 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']) else: fixed_ip = member['address'] for m in lb_pool['members']: if m['ip_address'] == fixed_ip: m['display_name'] = member['name'][:219] + '_' + member['id'] m['weight'] = member['weight'] return lb_pool['members']
def create(self, context, lb, completor): lb_id = lb['id'] network = lb_utils.get_network_from_subnet( context, self.core_plugin, lb['vip_subnet_id']) router_id = self._validate_lb_network(context, lb) if not router_id and not network.get('router:external'): completor(success=False) msg = (_('Cannot create a loadbalancer %(lb_id)s on subnet. ' '%(subnet)s is neither public nor connected to the LB ' 'router') % {'lb_id': lb_id, 'subnet': lb['vip_subnet_id']}) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) if router_id and not self.core_plugin.service_router_has_services( context, router_id): self.core_plugin.create_service_router(context, router_id) lb_name = utils.get_name_and_uuid(lb['name'] or 'lb', lb_id) tags = lb_utils.get_tags(self.core_plugin, router_id if router_id else '', lb_const.LR_ROUTER_TYPE, lb['tenant_id'], context.project_name) lb_size = lb_utils.get_lb_flavor_size(self.flavor_plugin, context, lb.get('flavor_id')) service_client = self.core_plugin.nsxpolicy.load_balancer.lb_service try: if network.get('router:external'): connectivity_path = None else: connectivity_path = self.core_plugin.nsxpolicy.tier1.get_path( router_id) service_client.create_or_overwrite( lb_name, lb_service_id=lb['id'], description=lb['description'], tags=tags, size=lb_size, connectivity_path=connectivity_path) # Add rule to advertise external vips if router_id: p_utils.update_router_lb_vip_advertisement( context, self.core_plugin, router_id) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error('Failed to create loadbalancer %(lb)s for lb with ' 'exception %(e)s', {'lb': lb['id'], 'e': e}) completor(success=True)
def _validate_member_lb_connectivity(self, context, member, completor): lb = member['pool'].get('loadbalancer') if not lb: msg = (_('Member %s loadbalancer object is missing') % member['id']) raise n_exc.BadRequest(resource='lbaas-vip', msg=msg) subnet_id = lb.get('vip_subnet_id') network = lb_utils.get_network_from_subnet(context, self.core_plugin, subnet_id) if not network.get('router:external'): return # If VIP is attached to an external network, loadbalancer_mgr might not # attach it to a router. If not, set the LB service connectivity path # to the member subnet's router. service_client = self.core_plugin.nsxpolicy.load_balancer.lb_service service = service_client.get(lb['id']) if not service.get('connectivity_path'): router_id = lb_utils.get_router_from_network( context, self.core_plugin, member['subnet_id']) if not self.core_plugin.service_router_has_services( context, router_id): self.core_plugin.create_service_router(context, router_id) connectivity_path = self.core_plugin.nsxpolicy.tier1.get_path( router_id) tags = lb_utils.get_tags(self.core_plugin, router_id, lb_const.LR_ROUTER_TYPE, lb['tenant_id'], context.project_name) try: service_client.update(lb['id'], tags=tags, connectivity_path=connectivity_path) p_utils.update_router_lb_vip_advertisement( context, self.core_plugin, router_id) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error( 'Failed to set connectivity for loadbalancer ' '%(lb)s on subnet %(sub)s with error %(err)s', { 'lb': lb['id'], 'sub': member['subnet_id'], 'err': e })
def _validate_member_lb_connectivity(self, context, member, completor): lb = member['pool'].get('loadbalancer') if not lb: msg = (_('Member %s loadbalancer object is missing') % member['id']) raise n_exc.BadRequest(resource='lbaas-vip', msg=msg) subnet_id = lb.get('vip_subnet_id') network = lb_utils.get_network_from_subnet( context, self.core_plugin, subnet_id) if not network.get('router:external'): return # If VIP is attached to an external network, loadbalancer_mgr might not # attach it to a router. If not, set the LB service connectivity path # to the member subnet's router. service_client = self.core_plugin.nsxpolicy.load_balancer.lb_service service = service_client.get(lb['id']) if not service.get('connectivity_path'): router_id = lb_utils.get_router_from_network( context, self.core_plugin, member['subnet_id']) if not self.core_plugin.service_router_has_services(context, router_id): self.core_plugin.create_service_router(context, router_id) connectivity_path = self.core_plugin.nsxpolicy.tier1.get_path( router_id) tags = lb_utils.get_tags(self.core_plugin, router_id, lb_const.LR_ROUTER_TYPE, lb['tenant_id'], context.project_name) try: service_client.update(lb['id'], tags=tags, connectivity_path=connectivity_path) p_utils.update_router_lb_vip_advertisement( context, self.core_plugin, router_id) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error('Failed to set connectivity for loadbalancer ' '%(lb)s on subnet %(sub)s with error %(err)s', {'lb': lb['id'], 'sub': member['subnet_id'], 'err': e})
def delete(self, context, member, completor): network = lb_utils.get_network_from_subnet( context, self.core_plugin, member['subnet_id']) if network.get('router:external'): fixed_ip = self._get_info_from_fip(context, member['address']) else: fixed_ip = member['address'] pool_id = member['pool']['id'] pool_client = self.core_plugin.nsxpolicy.load_balancer.lb_pool try: pool_client.remove_pool_member( pool_id, fixed_ip, port=member['protocol_port']) except Exception as e: with excutils.save_and_reraise_exception(): completor(success=False) LOG.error('Failed to create member %(member)s on pool %(pool)s' ': %(err)s', {'member': member['id'], 'pool': pool_id, 'err': e}) completor(success=True)
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_subnet(context, self.core_plugin, member['subnet_id']): completor(success=False) 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 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: 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.get('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: 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 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) 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 _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)
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)