Last active
November 9, 2023 15:40
-
-
Save ekohl/e487422d4aaad8ab176c19ec713b700a to your computer and use it in GitHub Desktop.
Libvirt with domain and resolvectl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# https://www.libvirt.org/hooks.html#network | |
# Place this as /etc/libvirt/hooks/network | |
import logging | |
import sys | |
from argparse import ArgumentParser | |
from subprocess import CalledProcessError, check_output | |
from xml.etree.ElementTree import ElementTree, fromstring, parse, dump | |
from xml.etree import ElementTree | |
logger = logging.getLogger('network-hook') | |
def read_xml(path: str) -> ElementTree.Element: | |
if path == '-': | |
root = ElementTree.fromstring(sys.stdin.read()) | |
return root.find('network') | |
else: | |
with open(path) as f: | |
return ElementTree.parse(f) | |
def handle_xml(xml: ElementTree) -> None: | |
domain = xml.find('domain') | |
if domain is None: | |
logger.debug('No domain found') | |
return | |
domain_name = domain.attrib['name'] | |
if domain_name is None: | |
logger.debug('No domain name found') | |
return | |
bridge = xml.find('bridge') | |
if bridge is None: | |
logger.debug('No bridge found') | |
return | |
interface = bridge.attrib['name'] | |
if interface is None: | |
logger.debug('No interface found') | |
return | |
ip = xml.find('ip') | |
if ip is None: | |
logger.debug('No ip found') | |
return | |
ip_address = ip.attrib['address'] | |
if ip_address is None: | |
logger.debug('No address found') | |
return | |
set_resolver(interface, ip_address, domain_name) | |
def set_resolver(interface: str, ip: str, domain: str) -> None: | |
logger.info('Setting resolver on %s to %s with %s', interface, ip, domain) | |
try: | |
check_output(['resolvectl', 'dns', interface, ip]) | |
except CalledProcessError: | |
logger.exception('Failed to set DNS resolver on interface %s to %s', interface, ip) | |
try: | |
check_output(['resolvectl', 'domain', interface, domain]) | |
except CalledProcessError: | |
logger.exception('Failed to set DNS domain on interface %s to %s', interface, domain) | |
def main(): | |
logging.basicConfig(level=logging.DEBUG) | |
parser = ArgumentParser() | |
parser.add_argument('network_name') | |
parser.add_argument('action') | |
parser.add_argument('phase') | |
parser.add_argument('xml') | |
args = parser.parse_args() | |
if args.action == 'started': | |
try: | |
xml = read_xml(args.xml) | |
except: | |
logger.exception('Failed to read XML from %s', args.xml) | |
raise | |
handle_xml(xml) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<network xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0'> | |
<bridge name='virbr0' stp='on' delay='0'/> | |
<!-- change your domain name here --> | |
<domain name="sub.example.com" localOnly="yes"/> | |
<ip address='192.168.122.1' netmask='255.255.255.0'> | |
<dhcp> | |
<range start='192.168.122.2' end='192.168.122.254'/> | |
</dhcp> | |
</ip> | |
</network> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment