Merge lp:~tcuthbert/ubuntu-repository-cache/squid-mem-qos into lp:ubuntu-repository-cache

Proposed by Thomas Cuthbert
Status: Rejected
Rejected by: Haw Loeung
Proposed branch: lp:~tcuthbert/ubuntu-repository-cache/squid-mem-qos
Merge into: lp:ubuntu-repository-cache
Diff against target: 227 lines (+148/-1)
5 files modified
config.yaml (+18/-0)
lib/ubuntu_repository_cache/service.py (+1/-0)
lib/ubuntu_repository_cache/squid.py (+69/-1)
lib/ubuntu_repository_cache/util.py (+52/-0)
templates/squid-deb-proxy.service.d/squid-deb-proxy.conf (+8/-0)
To merge this branch: bzr merge lp:~tcuthbert/ubuntu-repository-cache/squid-mem-qos
Reviewer Review Type Date Requested Status
Ubuntu Repository Cache Charmers, Canonical Pending
Review via email: mp+429532@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Haw Loeung (hloeung) wrote :

Comments inline. I tested and confirmed memory limits are applied - https://pastebin.canonical.com/p/3Jh3mSBJfV/

Revision history for this message
Haw Loeung (hloeung) wrote :
Revision history for this message
Haw Loeung (hloeung) wrote :

Unmerged revisions

374. By Thomas Cuthbert

WIP: squid systemd memory qos

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2022-08-22 02:45:49 +0000
3+++ config.yaml 2022-09-06 23:31:29 +0000
4@@ -76,6 +76,24 @@
5 effect running units, only newly added units. An example would be
6 '/dev/xvdb,/dev/xvdc' to specify two ephemeral disks for cache
7 storage.
8+ squid-memory-high:
9+ default: 90%
10+ type: string
11+ description: |
12+ Configurable systemd.resource-control for high squid memory. Takes a
13+ memory size in either bytes with an optional suffix or a percentage
14+ relative to physical system memory. The series must be xenial or
15+ higher for this to take effect.
16+ See man systemd.resource-control for details.
17+ squid-memory-max:
18+ default: 95%
19+ type: string
20+ description: |
21+ Configurable systemd.resource-control for maximum squid memory. Takes a
22+ memory size in either bytes with an optional suffix or a percentage
23+ relative to physical system memory. The series must be xenial or
24+ higher for this to take effect.
25+ See man systemd.resource-control for details.
26 cache-memory-size:
27 default: 0
28 type: int
29
30=== modified file 'lib/ubuntu_repository_cache/service.py'
31--- lib/ubuntu_repository_cache/service.py 2022-08-24 04:03:17 +0000
32+++ lib/ubuntu_repository_cache/service.py 2022-09-06 23:31:29 +0000
33@@ -190,6 +190,7 @@
34 """
35
36 return {
37+ ('/etc/systemd/system/squid-deb-proxy.service.d/', 'squid-deb-proxy.conf'): ['squid-deb-proxy'],
38 '/etc/squid-deb-proxy/squid-deb-proxy.conf': ['squid-deb-proxy'],
39 '/etc/squid-deb-proxy/allowed-networks-src.acl': ['squid-deb-proxy'],
40 ('/etc/squid-deb-proxy/mirror-dstdomain.acl.d/' '99-ubuntu-repository-cache'): ['squid-deb-proxy'],
41
42=== modified file 'lib/ubuntu_repository_cache/squid.py'
43--- lib/ubuntu_repository_cache/squid.py 2022-08-22 02:49:47 +0000
44+++ lib/ubuntu_repository_cache/squid.py 2022-09-06 23:31:29 +0000
45@@ -1,8 +1,11 @@
46 '''Functions related to squid-deb-proxy use within this charm'''
47
48+import filecmp
49 import os
50+import re
51+import shutil
52 import subprocess
53-import re
54+import tempfile
55
56 from charmhelpers import fetch
57
58@@ -80,6 +83,68 @@
59 )
60
61
62+@util.run_as_user('root')
63+def configure_systemd_override():
64+ """Configure squid-deb-proxy with systemd-resource controls.
65+
66+ 1. shallow[^1] compare config changes from tempdir
67+ 2. safely[^2] move configs into /etc/systemd/system
68+ - cleanup any leftover files from /etc/systemd on error
69+ 3. call `systemctl daemon-reload`, handling OS related errors where possible
70+
71+ [^1]: https://docs.python.org/3/library/filecmp.html#the-dircmp-class
72+ [^2]: https://docs.python.org/3/library/shutil.html#shutil.move
73+ """
74+ context = {}
75+ config = hookenv.config()
76+
77+ LOG("Installing squid-deb-proxy systemd service override configuration", hookenv.INFO)
78+ context["squid_memory_high"] = config.get("squid-memory-max", "90%")
79+ context["squid_memory_max"] = config.get("squid-memory-max", "95%")
80+
81+ dirname = "/etc/systemd/system/squid-deb-proxy.service.d"
82+ configdir_exists = os.path.exists(dirname)
83+ cleanup_files = []
84+
85+ with tempfile.TemporaryDirectory() as tmpdirname:
86+ charm_squid_path = os.path.join(os.getcwd(), "templates/squid-deb-proxy.service.d")
87+ temp_squid_path = os.path.join(tmpdirname, "templates/squid-deb-proxy.service.d")
88+
89+ shutil.copytree(charm_squid_path, temp_squid_path)
90+ templating.render(
91+ "squid-deb-proxy.service.d/" + "squid-deb-proxy.conf",
92+ os.path.join(temp_squid_path, "squid-deb-proxy.conf"),
93+ context,
94+ )
95+
96+ config_files = [os.path.join(dirname, f) for f in os.listdir(temp_squid_path)]
97+ if configdir_exists:
98+ config_files = [os.path.join(dirname, f) for f in filecmp.dircmp(temp_squid_path, dirname).diff_files]
99+
100+ try:
101+ shutil.move(temp_squid_path, "/etc/systemd/system/")
102+ verified = util.systemd_verify("squid-deb-proxy.service")
103+
104+ except Exception as e:
105+ cleanup_files.extend(config_files)
106+ err_msg = "Installing squid-deb-proxy.service.d files failed: {0}, {err}".format(dirname, err=e)
107+ LOG(err_msg, hookenv.ERROR)
108+ raise e from None
109+
110+ else:
111+ LOG("Reloading systemd daemons", hookenv.INFO)
112+ with util.systemctl_daemon_reload() as (reloaded, stderr):
113+ if reloaded and verified:
114+ LOG("squid-deb-proxy.service.d overrides reconfigured, restarting squid", hookenv.INFO)
115+ host.service_restart('squid-deb-proxy')
116+ else:
117+ LOG("squid-deb-proxy.service.d in an unexpected state: {}".format(stderr), hookenv.ERROR)
118+
119+ finally:
120+ for f in (f for f in cleanup_files):
121+ os.remove(f)
122+
123+
124 def install():
125 '''Perform the install/config and disable avahi'''
126
127@@ -107,6 +172,7 @@
128 stop()
129
130 render_configs()
131+ configure_systemd_override()
132 init_caches()
133
134
135@@ -246,6 +312,8 @@
136 dstdomain_context,
137 )
138
139+ configure_systemd_override()
140+
141
142 def update_checks(nrpe_config):
143 '''Update Nagios checks for squid serving archive pool content'''
144
145=== modified file 'lib/ubuntu_repository_cache/util.py'
146--- lib/ubuntu_repository_cache/util.py 2022-08-29 02:29:43 +0000
147+++ lib/ubuntu_repository_cache/util.py 2022-09-06 23:31:29 +0000
148@@ -7,6 +7,8 @@
149 import socket
150 import subprocess
151
152+from contextlib import contextmanager
153+
154 from charmhelpers.contrib.hahelpers import cluster
155 from charmhelpers.core import (
156 hookenv,
157@@ -167,6 +169,56 @@
158 return int(output[1].split()[1])
159
160
161+def has_systemd():
162+ release = host.lsb_release()['DISTRIB_RELEASE']
163+ rv = True
164+ if release < '16.04': # before xenial
165+ rv = False
166+ return rv
167+
168+
169+def systemd_verify(unit_file, timeout=5):
170+ args = ["systemd-analyze", "verify", "--system", "--generators", unit_file]
171+ ok = 0
172+ try:
173+ return subprocess.check_call(args, timeout=timeout) == ok
174+ except subprocess.CalledProcessError as cpe:
175+ LOG("failed to verify systemd override configuration: {}".format(cpe), hookenv.ERROR)
176+ raise cpe from None
177+ except subprocess.TimeoutExpired as te:
178+ LOG("timed out verifying systemd override files: {}".format(te), hookenv.ERROR)
179+ raise te from None
180+
181+
182+@contextmanager
183+def systemctl_daemon_reload(timeout=5):
184+ """
185+ contextmanager around the systemctl daemon-reload command.
186+
187+ Defaults with a 5s timeout that will send SIGTERM on expiry.
188+ Yields true and stderr if the process returned 0.
189+ Attempts to cleanup the process with SIGKILL[^1] if it's wedged.
190+
191+ [^1]: https://docs.python.org/3/library/subprocess.html#subprocess.Popen.returncode
192+ """
193+ cmd = ["/bin/systemctl", "daemon-reload"]
194+ proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
195+ stderr = None
196+ ok = 0
197+ try:
198+ _, stderr = proc.communicate(timeout=timeout)
199+ yield proc.returncode == ok, stderr
200+ except subprocess.TimeoutExpired:
201+ LOG("Timeout reloading squid-deb-proxy systemd override config", hookenv.ERROR)
202+ finally:
203+ proc.terminate()
204+ try:
205+ proc.wait(timeout=2)
206+ except subprocess.TimeoutExpired:
207+ LOG("systemctl daemon-reload did not terminate, attempting SIGKILL", hookenv.ERROR)
208+ proc.kill()
209+
210+
211 def change_aptsources_url(url='http://archive.ubuntu.com/ubuntu'):
212 """Change the URL for the current apt sources
213
214
215=== added directory 'templates/squid-deb-proxy.service.d'
216=== added file 'templates/squid-deb-proxy.service.d/squid-deb-proxy.conf'
217--- templates/squid-deb-proxy.service.d/squid-deb-proxy.conf 1970-01-01 00:00:00 +0000
218+++ templates/squid-deb-proxy.service.d/squid-deb-proxy.conf 2022-09-06 23:31:29 +0000
219@@ -0,0 +1,8 @@
220+[Unit]
221+StartLimitIntervalSec=3m
222+StartLimitBurst=3
223+
224+[Service]
225+MemoryHigh={{ squid_memory_high }}
226+MemoryMax={{ squid_memory_max }}
227+Restart=on-failure

Subscribers

People subscribed via source and target branches