diff --git a/journalist_gui/journalist_gui/SecureDropUpdater.py b/journalist_gui/journalist_gui/SecureDropUpdater.py index 3fbbedc57d..9a0b4a3679 100644 --- a/journalist_gui/journalist_gui/SecureDropUpdater.py +++ b/journalist_gui/journalist_gui/SecureDropUpdater.py @@ -128,12 +128,13 @@ def run(self): tailsconfig_command = ("/home/amnesia/Persistent/" "securedrop/securedrop-admin " "tailsconfig") + self.failure_reason = "" try: child = pexpect.spawn(tailsconfig_command) child.expect('SUDO password:') self.output += child.before.decode('utf-8') child.sendline(self.sudo_password) - child.expect(pexpect.EOF) + child.expect(pexpect.EOF, timeout=120) self.output += child.before.decode('utf-8') child.close() @@ -141,13 +142,15 @@ def run(self): # failures in the Ansible output. if child.exitstatus: self.update_success = False - self.failure_reason = strings.tailsconfig_failed_generic_reason # noqa + if "[sudo via ansible" in self.output: + self.failure_reason = strings.tailsconfig_failed_sudo_password + else: + self.failure_reason = strings.tailsconfig_failed_generic_reason else: self.update_success = True except pexpect.exceptions.TIMEOUT: self.update_success = False - self.failure_reason = strings.tailsconfig_failed_sudo_password - + self.failure_reason = strings.tailsconfig_failed_timeout except subprocess.CalledProcessError: self.update_success = False self.failure_reason = strings.tailsconfig_failed_generic_reason diff --git a/journalist_gui/journalist_gui/strings.py b/journalist_gui/journalist_gui/strings.py index 9792df1e07..9308c9398a 100644 --- a/journalist_gui/journalist_gui/strings.py +++ b/journalist_gui/journalist_gui/strings.py @@ -25,12 +25,15 @@ "Contact your SecureDrop administrator " "or securedrop@freedom.press immediately.") tailsconfig_failed_sudo_password = ('Administrator password incorrect. ' - 'Exiting upgrade - ' - 'click Update Now to try again.') + 'Click Update Now to try again.') tailsconfig_failed_generic_reason = ("Tails workstation configuration failed. " "Contact your administrator. " "If you are an administrator, contact " "securedrop@freedom.press.") +tailsconfig_failed_timeout = ("Tails workstation configuration took too long. " + "Contact your administrator. " + "If you are an administrator, contact " + "securedrop@freedom.press.") install_update_button = 'Update Now' install_later_button = 'Update Later' sudo_password_text = ("Enter the Tails Administrator password you " diff --git a/journalist_gui/test_gui.py b/journalist_gui/test_gui.py index f5fed71bcf..a496a1ba73 100644 --- a/journalist_gui/test_gui.py +++ b/journalist_gui/test_gui.py @@ -204,6 +204,18 @@ def test_tailsconfigThread_generic_failure(self, pt): @mock.patch('pexpect.spawn') def test_tailsconfigThread_sudo_password_is_wrong(self, pt): + child = pt() + before = MagicMock() + before.decode.return_value = "stuff[sudo via ansible, key=blahblahblah" + child.before = before + self.window.tails_thread.run() + self.assertNotIn("failed=0", self.window.output) + self.assertEqual(self.window.update_success, False) + self.assertEqual(self.window.failure_reason, + strings.tailsconfig_failed_sudo_password) + + @mock.patch('pexpect.spawn') + def test_tailsconfigThread_timeout(self, pt): child = pt() before = MagicMock() before.decode.side_effect = ["some data", @@ -213,7 +225,7 @@ def test_tailsconfigThread_sudo_password_is_wrong(self, pt): self.assertNotIn("failed=0", self.window.output) self.assertEqual(self.window.update_success, False) self.assertEqual(self.window.failure_reason, - strings.tailsconfig_failed_sudo_password) + strings.tailsconfig_failed_timeout) @mock.patch('pexpect.spawn') def test_tailsconfigThread_some_other_subprocess_error(self, pt):