def populate_tags(tag): """Evaluate `tag` for all nodes. This returns a `Deferred` that will fire when all tags have been evaluated. The return value is intended FOR TESTING ONLY because: - You must not use the `Deferred` in the calling thread; it must only be manipulated in the reactor thread. Pretending it's not there is safer than chaining code onto it because it's easy to get wrong. - The call may not finish for 10 minutes or more. It is therefore not a good thing to be waiting for in a web request. """ # This function cannot be called inside a transaction. The function manages # its own transaction. if in_transaction(): raise TransactionManagementError( '`populate_tags` cannot be called inside an existing transaction.') logger.debug('Evaluating the "%s" tag for all nodes.', tag.name) clients = getAllClients() if len(clients) == 0: # We have no clients so we need to do the work locally. @transactional def _populate_tag(): return populate_tag_for_multiple_nodes(tag, Node.objects.all()) return _populate_tag() else: # Split the work between the connected rack controllers. @transactional def _generate_work(): node_ids = Node.objects.all().values_list("system_id", flat=True) node_ids = [{"system_id": node_id} for node_id in node_ids] chunked_node_ids = list(chunk_list(node_ids, len(clients))) connected_racks = [] for idx, client in enumerate(clients): rack = RackController.objects.get(system_id=client.ident) token = _get_or_create_auth_token(rack.owner) creds = convert_tuple_to_string(get_creds_tuple(token)) if len(chunked_node_ids) > idx: connected_racks.append({ "system_id": rack.system_id, "hostname": rack.hostname, "client": client, "tag_name": tag.name, "tag_definition": tag.definition, "tag_nsmap": [ {"prefix": prefix, "uri": uri} for prefix, uri in tag_nsmap.items() ], "credentials": creds, "nodes": list(chunked_node_ids[idx]), }) return connected_racks return _do_populate_tags(_generate_work())
def populate_tags(tag): """Send worker for all nodegroups an update_node_tags request. """ items = { 'tag_name': tag.name, 'tag_definition': tag.definition, 'tag_nsmap': tag_nsmap, } # Rather than using NodeGroup.objects.refresh_workers() we call # refresh_worker immediately before we pass the requet. This is mostly for # the test suite, where we need the single real worker to switch to the # worker for a given nodegroup, before we have that worker process the # request. logger.debug('Refreshing tag definition for %s' % (items, )) for nodegroup in NodeGroup.objects.all(): refresh_worker(nodegroup) update_node_tags.apply_async(queue=nodegroup.work_queue, kwargs=items)
def _gen_reverse_zones(subnets, serial, ns_host_name, mappings, default_ttl): """Generator of reverse zones, sorted by network.""" subnets = set(subnets) # Generate the list of parent networks for rfc2317 glue. Note that we # need to handle the case where we are controlling both the small net # and a bigger network containing the /24, not just a /24 network. rfc2317_glue = {} for subnet in subnets: network = IPNetwork(subnet.cidr) if subnet.rdns_mode == RDNS_MODE.RFC2317: # If this is a small subnet and we are doing RFC2317 glue for # it, then we need to combine that with any other such subnets # We need to know this before we start creating reverse DNS # zones. if network.version == 4 and network.prefixlen > 24: # Turn 192.168.99.32/29 into 192.168.99.0/24 basenet = IPNetwork( "%s/24" % IPNetwork("%s/24" % network.network).network) rfc2317_glue.setdefault(basenet, set()).add(network) elif network.version == 6 and network.prefixlen > 124: basenet = IPNetwork( "%s/124" % IPNetwork("%s/124" % network.network).network) rfc2317_glue.setdefault(basenet, set()).add(network) # Since get_hostname_ip_mapping(Subnet) ignores Subnet.id, so we can # just do it once and be happy. LP#1600259 if len(subnets): mappings['reverse'] = mappings[Subnet.objects.first()] # For each of the zones that we are generating (one or more per # subnet), compile the zone from: # 1. Dynamic ranges on this subnet. # 2. Node: ip mapping(subnet), including DNSResource records for # StaticIPAddresses in this subnet. # All of this needs to be done smallest to largest so that we can # correctly gather the rfc2317 glue that we need. Failure to sort # means that we wind up grabbing (and deleting) the rfc2317 glue info # while processing the wrong network. for subnet in sorted( subnets, key=lambda subnet: IPNetwork(subnet.cidr).prefixlen, reverse=True): network = IPNetwork(subnet.cidr) if subnet.rdns_mode == RDNS_MODE.DISABLED: # If we are not doing reverse dns for this subnet, then just # skip to the next subnet. logger.debug("%s disabled subnet in DNS config list" % subnet.cidr) continue # 1. Figure out the dynamic ranges. dynamic_ranges = [ ip_range.netaddr_iprange for ip_range in subnet.get_dynamic_ranges() ] # 2. Start with the map of all of the nodes, including all # DNSResource-associated addresses. We will prune this to just # entries for the subnet when we actually generate the zonefile. # If we get here, then we have subnets, so we noticed that above # and created mappings['reverse']. LP#1600259 mapping = mappings['reverse'] # Use the default_domain as the name for the NS host in the reverse # zones. If this network is actually a parent rfc2317 glue # network, then we need to generate the glue records. # We need to detect the need for glue in our networks that are # big. if ((network.version == 6 and network.prefixlen < 124) or network.prefixlen < 24): glue = set() # This is the reason for needing the subnets sorted in # increasing order of size. for net in rfc2317_glue.copy().keys(): if net in network: glue.update(rfc2317_glue[net]) del (rfc2317_glue[net]) elif network in rfc2317_glue: glue = rfc2317_glue[network] del (rfc2317_glue[network]) else: glue = set() yield DNSReverseZoneConfig( ns_host_name, serial=serial, default_ttl=default_ttl, ns_host_name=ns_host_name, mapping=mapping, network=IPNetwork(subnet.cidr), dynamic_ranges=dynamic_ranges, rfc2317_ranges=glue, ) # Now provide any remaining rfc2317 glue networks. for network, ranges in rfc2317_glue.items(): yield DNSReverseZoneConfig( ns_host_name, serial=serial, default_ttl=default_ttl, network=network, ns_host_name=ns_host_name, rfc2317_ranges=ranges, )