def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): subnet_db = self._get_subnet(context, internal_subnet_id) if not subnet_db['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip') % internal_subnet_id) raise q_exc.BadRequest(resource='floatingip', msg=msg) # find router interface ports on this network router_intf_qry = context.session.query(models_v2.Port) router_intf_ports = router_intf_qry.filter_by( network_id=internal_port['network_id'], device_owner=DEVICE_OWNER_ROUTER_INTF) for intf_p in router_intf_ports: if intf_p['fixed_ips'][0]['subnet_id'] == internal_subnet_id: router_id = intf_p['device_id'] router_gw_qry = context.session.query(models_v2.Port) has_gw_port = router_gw_qry.filter_by( network_id=external_network_id, device_id=router_id, device_owner=DEVICE_OWNER_ROUTER_GW).count() if has_gw_port: return router_id raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, external_network_id=external_network_id, port_id=internal_port['id'])
def _get_router_for_internal_subnet(self, context, internal_port, internal_subnet_id): subnet_db = self._get_subnet(context, internal_subnet_id) if not subnet_db['gateway_ip']: msg = ('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip' % internal_subnet_id) raise q_exc.BadRequest(resource='floatingip', msg=msg) #FIXME(danwent): can do join, but cannot use standard F-K syntax? # just do it inefficiently for now port_qry = context.session.query(models_v2.Port) ports = port_qry.filter_by(network_id=internal_port['network_id']) for p in ports: ips = [ip['ip_address'] for ip in p['fixed_ips']] if len(ips) != 1: continue fixed = p['fixed_ips'][0] if (fixed['ip_address'] == subnet_db['gateway_ip'] and fixed['subnet_id'] == internal_subnet_id): router_qry = context.session.query(Router) try: router = router_qry.filter_by(id=p['device_id']).one() return router['id'] except exc.NoResultFound: pass raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, port_id=internal_port['id'])
def get_assoc_data(self, context, fip, floating_network_id): """When a floating IP is associated with an internal port, we need to extract/determine some data associated with the internal port, including the internal_ip_address, and router_id. We also need to confirm that this internal port is owned by the tenant who owns the floating IP. """ internal_port = self._get_port(context, fip['port_id']) if not internal_port['tenant_id'] == fip['tenant_id']: port_id = fip['port_id'] if 'id' in fip: floatingip_id = fip['id'] msg = _('Port %(port_id)s is associated with a different ' 'tenant than Floating IP %(floatingip_id)s and ' 'therefore cannot be bound.') else: msg = _('Cannnot create floating IP and bind it to ' 'Port %(port_id)s, since that port is owned by a ' 'different tenant.') raise q_exc.BadRequest(resource='floatingip', msg=msg % locals()) internal_subnet_id = None if 'fixed_ip_address' in fip and fip['fixed_ip_address']: internal_ip_address = fip['fixed_ip_address'] for ip in internal_port['fixed_ips']: if ip['ip_address'] == internal_ip_address: internal_subnet_id = ip['subnet_id'] if not internal_subnet_id: msg = ('Port %s does not have fixed ip %s' % (internal_port['id'], internal_ip_address)) raise q_exc.BadRequest(resource='floatingip', msg=msg) else: ips = [ip['ip_address'] for ip in internal_port['fixed_ips']] if len(ips) == 0: msg = ('Cannot add floating IP to port %s that has' 'no fixed IP addresses' % internal_port['id']) raise q_exc.BadRequest(resource='floatingip', msg=msg) if len(ips) > 1: msg = ('Port %s has multiple fixed IPs. Must provide' ' a specific IP when assigning a floating IP' % internal_port['id']) raise q_exc.BadRequest(resource='floatingip', msg=msg) internal_ip_address = internal_port['fixed_ips'][0]['ip_address'] internal_subnet_id = internal_port['fixed_ips'][0]['subnet_id'] router_id = self._get_router_for_internal_subnet( context, internal_port, internal_subnet_id) # confirm that this router has a floating # ip enabled gateway with support for this floating IP network try: port_qry = context.elevated().session.query(models_v2.Port) ports = port_qry.filter_by( network_id=floating_network_id, device_id=router_id, device_owner=DEVICE_OWNER_ROUTER_GW).one() except exc.NoResultFound: raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, port_id=internal_port['id']) return (fip['port_id'], internal_ip_address, router_id)
def get_assoc_data(self, context, fip, floating_network_id): """Determine/extract data associated with the internal port. When a floating IP is associated with an internal port, we need to extract/determine some data associated with the internal port, including the internal_ip_address, and router_id. We also need to confirm that this internal port is owned by the tenant who owns the floating IP. """ (internal_port, internal_subnet_id, internal_ip_address) = self._internal_fip_assoc_data(context, fip) router_id = self._get_router_for_floatingip(context, internal_port, internal_subnet_id, floating_network_id) # confirm that this router has a floating # ip enabled gateway with support for this floating IP network try: port_qry = context.elevated().session.query(models_v2.Port) port_qry.filter_by(network_id=floating_network_id, device_id=router_id, device_owner=DEVICE_OWNER_ROUTER_GW).one() except exc.NoResultFound: raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, port_id=internal_port['id']) return (fip['port_id'], internal_ip_address, router_id)