Skip to content

Commit

Permalink
Fix: Operators had to specify DNS resolution
Browse files Browse the repository at this point in the history
The DNS resolver defaulted to `resolv.conf`, which is not the default on all supported systems.

This adds an option to detect if systemd-resolved is available, and else defaults to `/etc/resolv.conf`.
  • Loading branch information
hoh committed Sep 19, 2023
1 parent d35b544 commit 5072746
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 27 deletions.
1 change: 0 additions & 1 deletion .github/workflows/test-on-droplet-ubuntu-22.04.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ jobs:
scp packaging/target/aleph-vm.ubuntu-22.04.deb root@${DROPLET_IPV4}:/opt
ssh root@${DROPLET_IPV4} DEBIAN_FRONTEND=noninteractive "apt install -y /opt/aleph-vm.ubuntu-22.04.deb"
ssh root@${DROPLET_IPV4} "echo ALEPH_VM_SUPERVISOR_HOST=0.0.0.0 >> /etc/aleph-vm/supervisor.env"
ssh root@${DROPLET_IPV4} "echo ALEPH_VM_DNS_RESOLUTION=resolvectl >> /etc/aleph-vm/supervisor.env"
ssh root@${DROPLET_IPV4} "echo ALEPH_VM_ALLOCATION_TOKEN_HASH=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 >> /etc/aleph-vm/supervisor.env"
ssh root@${DROPLET_IPV4} "systemctl restart aleph-vm-supervisor"
Expand Down
12 changes: 6 additions & 6 deletions doc/INSTALL-Debian-12.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,19 @@ ALEPH_VM_DOMAIN_NAME=vm.example.org

#### Network configuration

The network configuration is detected automatically.

The default network interface is detected automatically from the IP routes.
On some systems, this is not the desired configuration and you will want to configure the default interface
by adding:
You can configure the default interface manually instead by adding:
```
ALEPH_VM_NETWORK_INTERFACE=enp0s1
```
(don't forget to replace `enp0s1` with the name of your default network interface).

Debian 12 by default uses `/etc/resolv.conf` for DNS resolution. The VM Supervisor uses this by default.
If your system uses [systemd-resolved](https://manpages.debian.org/bullseye/systemd/systemd-resolved.8.en.html)
instead, uncomment and add the following setting:
You can configure the DNS resolver manually by using one of the following options:
```
#ALEPH_VM_DNS_RESOLUTION=resolvctl
ALEPH_VM_DNS_RESOLUTION=resolvectl
ALEPH_VM_DNS_RESOLUTION=resolv.conf
```

> 💡 You can instead specify the DNS resolvers used by the VMs using `ALEPH_VM_DNS_NAMESERVERS=["1.2.3.4", "5.6.7.8"]`.
Expand Down
20 changes: 11 additions & 9 deletions doc/INSTALL-Ubuntu-22.04.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,24 @@ ALEPH_VM_DOMAIN_NAME=vm.example.org

#### Network configuration

Ubuntu 22.04 by default uses [systemd-resolved](https://manpages.ubuntu.com/manpages/jammy/man8/systemd-resolved.service.8.html)
for DNS resolution. The following setting configures the VM Supervisor to use it instead of reading the default `/etc/resolv.conf`.
```
ALEPH_VM_DNS_RESOLUTION=resolvectl
```

> 💡 You can instead specify the DNS resolvers used by the VMs using `ALEPH_VM_DNS_NAMESERVERS=["1.2.3.4", "5.6.7.8"]`.
The network configuration is detected automatically.

The default network interface is detected automatically from the IP routes.
On some systems, this is not the desired configuration and you will want to configure the default interface
by adding:
You can configure the default interface manually instead by adding:
```
ALEPH_VM_NETWORK_INTERFACE=enp0s1
```
(don't forget to replace `enp0s1` with the name of your default network interface).

You can configure the DNS resolver manually by using one of the following options:
```
ALEPH_VM_DNS_RESOLUTION=resolvectl
ALEPH_VM_DNS_RESOLUTION=resolv.conf
```

> 💡 You can instead specify the DNS resolvers used by the VMs using `ALEPH_VM_DNS_NAMESERVERS=["1.2.3.4", "5.6.7.8"]`.

#### Volumes and partitions

Two directories are used to store data from the network:
Expand Down
42 changes: 31 additions & 11 deletions vm_supervisor/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from enum import Enum
from os.path import abspath, exists, isdir, isfile, join
from pathlib import Path
from subprocess import check_output
from subprocess import CalledProcessError, check_output
from typing import Any, Dict, Iterable, List, Literal, NewType, Optional, Union

from pydantic import BaseSettings, Field
Expand All @@ -19,6 +19,7 @@


class DnsResolver(str, Enum):
detect = "detect" # Detect the resolver used by the system
resolv_conf = "resolv.conf" # Simply copy from /etc/resolv.conf
resolvectl = "resolvectl" # Systemd-resolved, common on Ubuntu

Expand Down Expand Up @@ -79,6 +80,30 @@ def get_default_interface() -> Optional[str]:
return None


def obtain_dns_ips(dns_resolver: DnsResolver, network_interface: str) -> List[str]:
# The match syntax is not yet available as of Python 3.9
# match dns_resolver:
if dns_resolver == DnsResolver.detect:
# Use a try-except approach since resolvectl can be present but disabled and raise the following
# "Failed to get global data: Unit dbus-org.freedesktop.resolve1.service not found."
try:
return list(resolvectl_dns_servers_ipv4(interface=network_interface))
except (FileNotFoundError, CalledProcessError):
if Path("/etc/resolv.conf").exists():
return list(etc_resolv_conf_dns_servers())
else:
raise FileNotFoundError("No DNS resolver found")

elif dns_resolver == DnsResolver.resolv_conf:
return list(etc_resolv_conf_dns_servers())

elif dns_resolver == DnsResolver.resolvectl:
return list(resolvectl_dns_servers_ipv4(interface=network_interface))

else:
assert "No DNS resolve defined, this should never happen."


class Settings(BaseSettings):
SUPERVISOR_HOST = "127.0.0.1"
SUPERVISOR_PORT: int = 4020
Expand Down Expand Up @@ -134,7 +159,7 @@ class Settings(BaseSettings):
description="Use the Neighbor Discovery Protocol Proxy to respond to Router Solicitation for instances on IPv6",
)

DNS_RESOLUTION: Optional[DnsResolver] = DnsResolver.resolv_conf
DNS_RESOLUTION: Optional[DnsResolver] = DnsResolver.detect
DNS_NAMESERVERS: Optional[List[str]] = None

FIRECRACKER_PATH = Path("/opt/firecracker/firecracker")
Expand Down Expand Up @@ -286,15 +311,10 @@ def setup(self):
self.NETWORK_INTERFACE = get_default_interface()

if self.DNS_NAMESERVERS is None and self.DNS_RESOLUTION:
if self.DNS_RESOLUTION == DnsResolver.resolv_conf:
self.DNS_NAMESERVERS = list(etc_resolv_conf_dns_servers())

elif self.DNS_RESOLUTION == DnsResolver.resolvectl:
self.DNS_NAMESERVERS = list(
resolvectl_dns_servers_ipv4(interface=self.NETWORK_INTERFACE)
)
else:
assert "This should never happen"
self.DNS_NAMESERVERS = obtain_dns_ips(
dns_resolver=self.DNS_RESOLUTION,
network_interface=self.NETWORK_INTERFACE,
)

def display(self) -> str:
attributes: Dict[str, Any] = {}
Expand Down

0 comments on commit 5072746

Please sign in to comment.