[docs]classPopulateZones(AbstractPlugin):"""This plugin builds the zone graphs needed for DNS. The plugin first walks the entire graph, building a graph of the zone data for the system, and installs that on the master dns server (usually named DNS). It then walks the graph to find each in-experiment node marked as a dns server and uses a similar process to add zone data for it. In each case, it puts the zone graphs on each dns server node of the Firewheel graph. """
[docs]defrun(self):"""Function to invoke the ConfigureDNS plugin."""# Create zones for in-experiment dns serversforvertexinself.g.get_vertices():# Look for dns key {'dns':{"server" "dns.ssn.gov",# "hosts_tracked": ...}}ifvertex.is_decorated_by(DNSServer):name=vertex.namehosts_tracked=vertex.dns_data.get("hosts_tracked")ifnothosts_tracked:hosts_tracked="*"zones=self.populate_zones(name,hosts_tracked)self.log.debug("Zones for %s:",name)self.log.debug(zones)vertex.dns_data["zones"]=zones
[docs]defpopulate_zones(self,dns_server_name,hosts_tracked):""" Walk the graph building a dictionary which specifies the zones in the graph. The many level dictionary allows the generation function to easily figure out the contents of potential A records and glue records. Arguments: dns_server_name (str): The name of the DNS server hosts_tracked (list): The hosts that the DNS server is tracking Returns: dict: The DNS zone dictionary. """zones={}self.log.debug("PTRs requested for %s = %s",dns_server_name,str(hosts_tracked))vertices=self.g.get_vertices()forvertexinvertices:ifnotvertex.is_decorated_by(Switch):full_name=vertex.namename=full_name.split(".")name.reverse()try:interfaces=vertex.interfaces.interfacesexceptAttributeError:self.log.warning("Vertex with name=%s did not have an interface, ignoring",vertex.name,)continueaddress=None# pull addressifnotinterfaces:continueifvertex.is_decorated_by(DNSServer):# continuepassforifaceininterfaces:if"switch"iniface:address=iface["address"]breakifnotaddress:# This VM is not part of the experiment, but that's okaycontinue# Skip any machines this server doesn't care about.ifhosts_tracked=="*"orfull_nameinhosts_tracked:passelse:continue# populate the dictionarycurrent_location=zonesforname_index,componentinenumerate(name):ifcomponentnotincurrent_location:ifname_index==(len(name)-1):current_location[component]=[("A",address)]else:current_location[component]={}current_location=current_location[component]else:current_location=current_location[component]# Create the PTR recordptr_addr=f"arpa.in-addr.{address}"ptr_addr=ptr_addr.split(".")current_location=zonesforptr_addr_index,componentinenumerate(ptr_addr):ifcomponentnotincurrent_location:ifptr_addr_index==(len(ptr_addr)-1):current_location[component]=[("PTR",f"{full_name}.")]else:current_location[component]={}current_location=current_location[component]else:current_location=current_location[component]returnzones