def add_auto_addrs_on_network_ports(self, context, subnet, ipam_subnet): """For an auto-address subnet, add addrs for ports on the net.""" # TODO(ataraday): switched for writer when flush_on_subtransaction # will be available for neutron with context.session.begin(subtransactions=True): network_id = subnet['network_id'] ports = port_obj.Port.get_objects( context, network_id=network_id, device_owner=obj_utils.NotIn( constants.ROUTER_INTERFACE_OWNERS_SNAT)) updated_ports = [] ipam_driver = driver.Pool.get_instance(None, context) factory = ipam_driver.get_address_request_factory() for port in ports: ip = { 'subnet_id': subnet['id'], 'subnet_cidr': subnet['cidr'], 'eui64_address': True, 'mac': port.mac_address } ip_request = factory.get_request(context, port, ip) try: ip_address = ipam_subnet.allocate(ip_request) allocated = port_obj.IPAllocation(context, network_id=network_id, port_id=port.id, ip_address=ip_address, subnet_id=subnet['id']) # Do the insertion of each IP allocation entry within # the context of a nested transaction, so that the entry # is rolled back independently of other entries whenever # the corresponding port has been deleted; since OVO # already opens a nested transaction, we don't need to do # it explicitly here. allocated.create() updated_ports.append(port.id) except db_exc.DBReferenceError: LOG.debug( "Port %s was deleted while updating it with an " "IPv6 auto-address. Ignoring.", port.id) LOG.debug("Reverting IP allocation for %s", ip_address) # Do not fail if reverting allocation was unsuccessful try: ipam_subnet.deallocate(ip_address) except Exception: LOG.debug("Reverting IP allocation failed for %s", ip_address) except ipam_exc.IpAddressAlreadyAllocated: LOG.debug( "Port %s got IPv6 auto-address in a concurrent " "create or update port request. Ignoring.", port.id) return updated_ports
def test_get_objects_with_filters_not_in(self): class FakeColumn(object): def __init__(self, column): self.column = column def in_(self, value): self.value = value return self def __invert__(self): return list(set(self.column) - set(self.value)) filter_obj = obj_utils.NotIn([1, 2, 3]) fake_column = FakeColumn([1, 2, 4, 5]) self.assertEqual([4, 5], sorted(filter_obj.filter(fake_column))) fake_column = FakeColumn([1, 2]) self.assertEqual([], filter_obj.filter(fake_column)) fake_column = FakeColumn([4, 5]) self.assertEqual([4, 5], sorted(filter_obj.filter(fake_column)))
def add_auto_addrs_on_network_ports(self, context, subnet, ipam_subnet): """For an auto-address subnet, add addrs for ports on the net.""" network_id = subnet['network_id'] with db_api.CONTEXT_READER.using(context): ports = port_obj.Port.get_objects( context, network_id=network_id, device_owner=obj_utils.NotIn( constants.ROUTER_INTERFACE_OWNERS_SNAT)) updated_ports = [] ipam_driver = driver.Pool.get_instance(None, context) factory = ipam_driver.get_address_request_factory() for port in ports: # Find candidate subnets based on host_id and existing # fixed_ips. This will filter subnets on other segments. Only # allocate if this subnet is a valid candidate. p = self._make_port_dict(port) fixed_configured = (p['fixed_ips'] is not constants.ATTR_NOT_SPECIFIED) with db_api.CONTEXT_READER.using(context): subnet_candidates = obj_subnet.Subnet.find_candidate_subnets( context, network_id, p.get(portbindings.HOST_ID), p.get('device_owner'), fixed_configured, p.get('fixed_ips'), distributed_service=self._is_distributed_service(p)) if subnet['id'] not in [s['id'] for s in subnet_candidates]: continue ip = {'subnet_id': subnet['id'], 'subnet_cidr': subnet['cidr'], 'eui64_address': True, 'mac': port.mac_address} ip_request = factory.get_request(context, port, ip) try: with db_api.CONTEXT_WRITER.using(context): ip_address = ipam_subnet.allocate(ip_request) allocated = port_obj.IPAllocation( context, network_id=network_id, port_id=port.id, ip_address=ip_address, subnet_id=subnet['id']) # Do the insertion of each IP allocation entry within # the context of a nested transaction, so that the entry # is rolled back independently of other entries whenever # the corresponding port has been deleted; since OVO # already opens a nested transaction, we don't need to do # it explicitly here. allocated.create() updated_ports.append(port.id) except db_exc.DBReferenceError: LOG.debug("Port %s was deleted while updating it with an " "IPv6 auto-address. Ignoring.", port.id) LOG.debug("Reverting IP allocation for %s", ip_address) # Do not fail if reverting allocation was unsuccessful with db_api.CONTEXT_WRITER.using(context): try: ipam_subnet.deallocate(ip_address) except Exception: LOG.debug("Reverting IP allocation failed for %s", ip_address) except ipam_exc.IpAddressAlreadyAllocated: LOG.debug("Port %s got IPv6 auto-address in a concurrent " "create or update port request. Ignoring.", port.id) return updated_ports