Merge lp:~allenap/maas/systemd-status-unicode-error--bug-1491822--1.8 into lp:maas/1.8

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 4042
Proposed branch: lp:~allenap/maas/systemd-status-unicode-error--bug-1491822--1.8
Merge into: lp:maas/1.8
Diff against target: 84 lines (+29/-10)
2 files modified
src/provisioningserver/service_monitor.py (+5/-5)
src/provisioningserver/tests/test_service_monitor.py (+24/-5)
To merge this branch: bzr merge lp:~allenap/maas/systemd-status-unicode-error--bug-1491822--1.8
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+270147@code.launchpad.net

Commit message

Backport r4236 from trunk: In the system monitor, decode output from the init system as UTF-8.

Always invoke the init system using the C.UTF-8 locale. Previously LANG=en_US.UTF-8 and LC_CTYPE=C was used.

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

Simple backport.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/provisioningserver/service_monitor.py'
--- src/provisioningserver/service_monitor.py 2015-06-27 00:34:56 +0000
+++ src/provisioningserver/service_monitor.py 2015-09-04 08:31:44 +0000
@@ -186,17 +186,17 @@
186186
187 :return: tuple (exit code, output)187 :return: tuple (exit code, output)
188 """188 """
189 # Force systemd to output in UTF-8 instead of unicode. This doesn't189 # Force systemd to output in UTF-8 by selecting the C.UTF-8 locale.
190 # have any affect on upstart.190 # This doesn't have any effect on upstart.
191 env = os.environ.copy()191 env = os.environ.copy()
192 env["LANG"] = "en_US.UTF-8"192 env["LANG"] = "C.UTF-8"
193 env["LC_CTYPE"] = "C"193 env["LC_ALL"] = "C.UTF-8"
194 process = Popen(194 process = Popen(
195 ["sudo", "service", service_name, action],195 ["sudo", "service", service_name, action],
196 stdin=PIPE, stdout=PIPE,196 stdin=PIPE, stdout=PIPE,
197 stderr=STDOUT, close_fds=True, env=env)197 stderr=STDOUT, close_fds=True, env=env)
198 output, _ = process.communicate()198 output, _ = process.communicate()
199 return process.wait(), output.strip()199 return process.wait(), output.decode("utf-8").strip()
200200
201 def _service_action(self, service, action):201 def _service_action(self, service, action):
202 """Start or stop the service."""202 """Start or stop the service."""
203203
=== modified file 'src/provisioningserver/tests/test_service_monitor.py'
--- src/provisioningserver/tests/test_service_monitor.py 2015-06-27 00:34:56 +0000
+++ src/provisioningserver/tests/test_service_monitor.py 2015-09-04 08:31:44 +0000
@@ -44,6 +44,7 @@
44)44)
45from provisioningserver.utils.testing import RegistryFixture45from provisioningserver.utils.testing import RegistryFixture
46from testtools import ExpectedException46from testtools import ExpectedException
47from testtools.matchers import Equals
4748
4849
49class TestServiceMonitor(MAASTestCase):50class TestServiceMonitor(MAASTestCase):
@@ -294,22 +295,40 @@
294 service_name = factory.make_name("service")295 service_name = factory.make_name("service")
295 action = factory.make_name("action")296 action = factory.make_name("action")
296 mock_popen = self.patch(service_monitor_module, "Popen")297 mock_popen = self.patch(service_monitor_module, "Popen")
297 mock_popen.return_value.communicate.return_value = ("", "")298 mock_popen.return_value.communicate.return_value = (b"", b"")
298 service_monitor._exec_service_action(service_name, action)299 service_monitor._exec_service_action(service_name, action)
299 self.assertEquals(300 self.assertEquals(
300 ["sudo", "service", service_name, action],301 ["sudo", "service", service_name, action],
301 mock_popen.call_args[0][0])302 mock_popen.call_args[0][0])
302303
303 def test__exec_service_action_calls_service_with_LC_CTYPE_in_env(self):304 def test__exec_service_action_calls_service_with_LC_ALL_in_env(self):
304 service_monitor = ServiceMonitor()305 service_monitor = ServiceMonitor()
305 service_name = factory.make_name("service")306 service_name = factory.make_name("service")
306 action = factory.make_name("action")307 action = factory.make_name("action")
307 mock_popen = self.patch(service_monitor_module, "Popen")308 mock_popen = self.patch(service_monitor_module, "Popen")
308 mock_popen.return_value.communicate.return_value = ("", "")309 mock_popen.return_value.communicate.return_value = (b"", b"")
309 service_monitor._exec_service_action(service_name, action)310 service_monitor._exec_service_action(service_name, action)
310 self.assertEquals(311 self.assertEquals(
311 "C",312 "C.UTF-8",
312 mock_popen.call_args[1]['env']['LC_CTYPE'])313 mock_popen.call_args[1]['env']['LC_ALL'])
314
315 def test__exec_service_action_decodes_stdout(self):
316 # From https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt.
317 example_text = (
318 '\u16bb\u16d6 \u16b3\u16b9\u16ab\u16a6 \u16a6\u16ab\u16cf '
319 '\u16bb\u16d6 \u16d2\u16a2\u16de\u16d6 \u16a9\u16be \u16a6'
320 '\u16ab\u16d7 \u16da\u16aa\u16be\u16de\u16d6 \u16be\u16a9'
321 '\u16b1\u16a6\u16b9\u16d6\u16aa\u16b1\u16de\u16a2\u16d7 '
322 '\u16b9\u16c1\u16a6 \u16a6\u16aa \u16b9\u16d6\u16e5\u16ab'
323 )
324 service_monitor = ServiceMonitor()
325 service_name = factory.make_name("service")
326 action = factory.make_name("action")
327 mock_popen = self.patch(service_monitor_module, "Popen")
328 mock_popen.return_value.communicate.return_value = (
329 example_text.encode("utf-8"), b"")
330 _, output = service_monitor._exec_service_action(service_name, action)
331 self.assertThat(output, Equals(example_text))
313332
314 def test__service_action_calls__exec_service_action(self):333 def test__service_action_calls__exec_service_action(self):
315 service = self.make_service_driver(SERVICE_STATE.ON)334 service = self.make_service_driver(SERVICE_STATE.ON)

Subscribers

People subscribed via source and target branches

to all changes: