Merge ~cjwatson/launchpad-layers:turnip-storage-literal-ipv6-address into launchpad-layers:main

Proposed by Colin Watson
Status: Needs review
Proposed branch: ~cjwatson/launchpad-layers:turnip-storage-literal-ipv6-address
Merge into: launchpad-layers:main
Diff against target: 57 lines (+19/-2)
2 files modified
turnip-storage/lib/charms/turnip/storage.py (+18/-1)
turnip-storage/templates/data.mount.j2 (+1/-1)
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+450692@code.launchpad.net

Commit message

Handle literal IPv6 addresses in turnip-storage

Description of the change

My local turnip deployment sometimes gets itself into a state where the individual units still have IPv6 addresses but no IPv4 addresses (until I run `systemctl restart systemd-networkd.service` on each of them manually). This has the very annoying consequence of getting the turnip charm hooks badly wedged, because they try to mount the NFS storage volume using its IPv6 address without using the correct literal address syntax.

While the units losing their IPv4 addresses is probably a bug somewhere else, it makes sense to handle mounting over IPv6 anyway, and it makes it much less difficult to recover from this situation.

To post a comment you must log in.

Unmerged commits

18c4c3f... by Colin Watson

Handle literal IPv6 addresses in turnip-storage

My local turnip deployment sometimes gets itself into a state where the
individual units still have IPv6 addresses but no IPv4 addresses (until
I run `systemctl restart systemd-networkd.service` on each of them
manually). This has the very annoying consequence of getting the turnip
charm hooks badly wedged, because they try to mount the NFS storage
volume using its IPv6 address without using the correct literal address
syntax.

While the units losing their IPv4 addresses is probably a bug somewhere
else, it makes sense to handle mounting over IPv6 anyway, and it makes
it much less difficult to recover from this situation.

Succeeded
[SUCCEEDED] lint:0 (build)
11 of 1 result

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/turnip-storage/lib/charms/turnip/storage.py b/turnip-storage/lib/charms/turnip/storage.py
2index 6b3505d..6922525 100644
3--- a/turnip-storage/lib/charms/turnip/storage.py
4+++ b/turnip-storage/lib/charms/turnip/storage.py
5@@ -1,7 +1,7 @@
6 # Copyright 2018 Canonical Ltd. This software is licensed under the
7 # GNU Affero General Public License version 3 (see the file LICENSE).
8
9-
10+import ipaddress
11 import os
12 import subprocess
13
14@@ -26,6 +26,20 @@ def ensure_mounted():
15 subprocess.check_call(["mountpoint", "-q", data_dir()])
16
17
18+def make_mount_path(hostname, mountpoint):
19+ """Turn a hostname (or IP address) and mount point into a mount path."""
20+ literal_ipv6_address = False
21+ try:
22+ if ipaddress.ip_address(hostname).version == 6:
23+ literal_ipv6_address = True
24+ except ValueError:
25+ pass
26+ if literal_ipv6_address:
27+ return f"[{hostname}]:{mountpoint}"
28+ else:
29+ return f"{hostname}:{mountpoint}"
30+
31+
32 def mount_data(mount_info):
33 # We use a systemd.mount(5) unit rather than a line in /etc/fstab partly
34 # because it's easier to deal with a file we can completely overwrite,
35@@ -35,6 +49,9 @@ def mount_data(mount_info):
36 data_mount_conf = f"/lib/systemd/system/{data_mount}"
37 context = dict(mount_info)
38 context["data_dir"] = data_dir()
39+ context["mount_path"] = make_mount_path(
40+ mount_info["hostname"], mount_info["mountpoint"]
41+ )
42 templating.render("data.mount.j2", data_mount_conf, context, perms=0o644)
43 host.service("unmask", data_mount)
44 reload_systemd()
45diff --git a/turnip-storage/templates/data.mount.j2 b/turnip-storage/templates/data.mount.j2
46index b115460..77ad6eb 100644
47--- a/turnip-storage/templates/data.mount.j2
48+++ b/turnip-storage/templates/data.mount.j2
49@@ -2,7 +2,7 @@
50 Description=Turnip data file system
51
52 [Mount]
53-What={{ hostname }}:{{ mountpoint }}
54+What={{ mount_path }}
55 Where={{ data_dir }}
56 Type={{ fstype }}
57 Options={{ options }}

Subscribers

People subscribed via source and target branches