diff -Nru landscape-client-23.02/debian/changelog landscape-client-23.02/debian/changelog --- landscape-client-23.02/debian/changelog 2023-08-14 19:50:19.000000000 +0000 +++ landscape-client-23.02/debian/changelog 2024-02-14 23:34:10.000000000 +0000 @@ -1,3 +1,12 @@ +landscape-client (23.02-0ubuntu1~22.04.2) jammy; urgency=medium + + * d/p/0001-start-service-during-config.patch: fix landscape-config does not + start landscape-client service (LP: #2040189) + * d/landscape-sysinfo.wrapper: fix handle using cache when permissions allow + (LP: #2040924) + + -- Mitch Burton Wed, 14 Feb 2024 15:34:10 -0800 + landscape-client (23.02-0ubuntu1~22.04.1) jammy; urgency=medium * Backporting release 23.02 for SRU (LP: #2006402): diff -Nru landscape-client-23.02/debian/landscape-sysinfo.wrapper landscape-client-23.02/debian/landscape-sysinfo.wrapper --- landscape-client-23.02/debian/landscape-sysinfo.wrapper 2022-03-30 10:32:38.000000000 +0000 +++ landscape-client-23.02/debian/landscape-sysinfo.wrapper 2024-02-14 23:34:10.000000000 +0000 @@ -2,28 +2,46 @@ # don't try refresh this more than once per minute # Due to cpu consumption and login delays (LP: #1893716) -stamp="/var/lib/landscape/landscape-sysinfo.cache" -NEED_UPDATE="FALSE" -[ -z "$(find "$stamp" -newermt 'now-1 minutes' 2> /dev/null)" ] && NEED_UPDATE="TRUE" +CACHE="/var/lib/landscape/landscape-sysinfo.cache" +HAS_CACHE="FALSE" +CACHE_NEEDS_UPDATE="FALSE" + +[ -r "$CACHE" ] && HAS_CACHE="TRUE" +[ -z "$(find "$CACHE" -newermt 'now-1 minutes' 2> /dev/null)" ] && CACHE_NEEDS_UPDATE="TRUE" + +if [ "$HAS_CACHE" = "TRUE" ] && [ "$CACHE_NEEDS_UPDATE" = "FALSE" ]; then + cat "$CACHE" +else + SYSINFO="" -if [ "$NEED_UPDATE" = "TRUE" ]; then # pam_motd does not carry the environment [ -f /etc/default/locale ] && . /etc/default/locale export LANG - cores=$(grep -c ^processor /proc/cpuinfo 2>/dev/null) - [ "$cores" -eq "0" ] && cores=1 - threshold="${cores:-1}.0" - if [ $(echo "`cut -f1 -d ' ' /proc/loadavg` < $threshold" | bc) -eq 1 ]; then - printf "\n System information as of %s\n\n%s\n" \ + CORES=$(grep -c ^processor /proc/cpuinfo 2>/dev/null) + [ "$CORES" -eq "0" ] && CORES=1 + THRESHOLD="${cores:-1}.0" + + if [ $(echo "`cut -f1 -d ' ' /proc/loadavg` < $THRESHOLD" | bc) -eq 1 ]; then + SYSINFO=$(printf "\n System information as of %s\n\n%s\n" \ "$(/bin/date)" \ - "$(/usr/bin/landscape-sysinfo)" \ - > "$stamp" + "$(/usr/bin/landscape-sysinfo)") + echo "$SYSINFO" 2>/dev/null >"$CACHE" || true + chmod 0644 "$CACHE" 2>/dev/null || true else - # do not replace a formerly good result due to load - if ! grep -q "System information as of" $stamp 2> /dev/null; then - printf "\n System information disabled due to load higher than %s\n" "$threshold" > "$stamp" + SYSINFO=$(printf "\n System information disabled due to load higher than %s\n" "$THRESHOLD") + + if [ "$HAS_CACHE" = "TRUE" ]; then + if ! grep -q "System information as of" $CACHE 2>/dev/null; then + # do not replace a formerly good result due to load + echo "$SYSINFO" 2>/dev/null >"$CACHE" || true + chmod 0644 "$CACHE" 2>/dev/null || true + else + SYSINFO=$(cat "$CACHE") + fi fi fi + + printf "%s\n" "$SYSINFO" fi -[ ! -r "$stamp" ] || cat "$stamp" +exit 0 diff -Nru landscape-client-23.02/debian/patches/0001-start-service-during-config.patch landscape-client-23.02/debian/patches/0001-start-service-during-config.patch --- landscape-client-23.02/debian/patches/0001-start-service-during-config.patch 1970-01-01 00:00:00.000000000 +0000 +++ landscape-client-23.02/debian/patches/0001-start-service-during-config.patch 2024-02-14 23:34:10.000000000 +0000 @@ -0,0 +1,271 @@ +Description: Allow landscape-config to start landscape-client systemd service +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/landscape-client/+bug/2040189 +Author: Mitch Burton +Origin: backport, https://github.com/canonical/landscape-client/commit/0da6b4b64c7ca50c109279bd42633c537458fcf4 +Reviewed-by: Kevin Nasto +Applied-Upstream: 23.10 +Last-Update: 2023-11-07 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/landscape/client/configuration.py ++++ b/landscape/client/configuration.py +@@ -562,8 +562,10 @@ + decode_base64_ssl_public_certificate(config) + config.write() + # Restart the client to ensure that it's using the new configuration. ++ + if not config.no_start: + try: ++ set_secure_id(config, "registering") + sysvconfig.restart_landscape() + except ProcessError: + print_text("Couldn't restart the Landscape client.", error=True) +@@ -710,13 +712,14 @@ + # Results will be things like "success" or "ssl-error". + result = results[0] + +- if isinstance(result, SystemExit): +- raise result +- + # If there was an error and the caller requested that errors be reported + # to the on_error callable, then do so. + if result != "success" and on_error is not None: + on_error(1) ++ ++ if isinstance(result, SystemExit): ++ raise result ++ + return result + + +@@ -788,6 +791,21 @@ + return text + + ++def set_secure_id(config, new_id): ++ """Persists a secure id in the identity data file. This is used to indicate ++ whether we are currently in the process of registering. ++ """ ++ persist = Persist( ++ filename=os.path.join( ++ config.data_path, ++ f"{BrokerService.service_name}.bpickle", ++ ), ++ ) ++ identity = Identity(config, persist) ++ identity.secure_id = new_id ++ persist.save() ++ ++ + def main(args, print=print): + """Interact with the user and the server to set up client configuration.""" + +@@ -834,7 +852,11 @@ + # Attempt to register the client. + reactor = LandscapeReactor() + if config.silent: +- result = register(config, reactor) ++ result = register( ++ config, ++ reactor, ++ on_error=lambda _: set_secure_id(config, None), ++ ) + report_registration_outcome(result, print=print) + sys.exit(determine_exit_code(result)) + else: +@@ -843,6 +865,10 @@ + "\nRequest a new registration for this computer now?", + default=default_answer) + if answer: +- result = register(config, reactor) ++ result = register( ++ config, ++ reactor, ++ on_error=lambda _: set_secure_id(config, None), ++ ) + report_registration_outcome(result, print=print) + sys.exit(determine_exit_code(result)) +--- a/landscape/client/tests/test_configuration.py ++++ b/landscape/client/tests/test_configuration.py +@@ -23,7 +23,7 @@ + bootstrap_tree, got_connection, success, failure, exchange_failure, + handle_registration_errors, done, got_error, report_registration_outcome, + determine_exit_code, is_registered, registration_info_text, +- EXIT_NOT_REGISTERED) ++ EXIT_NOT_REGISTERED, set_secure_id) + from landscape.lib.amp import MethodCallError + from landscape.lib.fetch import HTTPCodeError, PyCurlError + from landscape.lib.fs import read_binary_file +@@ -823,12 +823,18 @@ + getuid_patcher = mock.patch("os.getuid", return_value=0) + bootstrap_tree_patcher = mock.patch( + "landscape.client.configuration.bootstrap_tree") ++ set_secure_id_patch = mock.patch( ++ "landscape.client.configuration.set_secure_id", ++ ) + self.mock_getuid = getuid_patcher.start() + self.mock_bootstrap_tree = bootstrap_tree_patcher.start() ++ set_secure_id_patch.start() + + def cleanup(): + getuid_patcher.stop() + bootstrap_tree_patcher.stop() ++ set_secure_id_patch.stop() ++ + self.addCleanup(cleanup) + + def get_content(self, config): +@@ -1163,7 +1169,11 @@ + print=noop_print) + self.assertEqual(0, exception.code) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + + @mock.patch("landscape.client.configuration.input", return_value="y") + @mock.patch("landscape.client.configuration.register", +@@ -1182,7 +1192,11 @@ + print=faux_print) + self.assertEqual(0, exception.code) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_called_once_with( + "\nRequest a new registration for this computer now? [Y/n]: ") + self.assertEqual( +@@ -1207,7 +1221,11 @@ + print=faux_print) + self.assertEqual(2, exception.code) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_called_once_with( + "\nRequest a new registration for this computer now? [Y/n]: ") + +@@ -1235,7 +1253,11 @@ + print=faux_print) + self.assertEqual(0, exception.code) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_not_called() + + self.assertEqual( +@@ -1262,7 +1284,11 @@ + print=faux_print) + self.assertEqual(2, exception.code) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_not_called() + # Note that the error is output via sys.stderr. + self.assertEqual( +@@ -1296,7 +1322,11 @@ + mock_sysvconfig().set_start_on_boot.assert_called_once_with(True) + mock_sysvconfig().restart_landscape.assert_called_once_with() + mock_setup_script().run.assert_called_once_with() +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_any_call( + "\nThe Landscape client must be started " + "on boot to operate correctly.\n\n" +@@ -1356,7 +1386,11 @@ + self.assertRaises(SystemExit, main, ["-c", self.make_working_config()], + print=noop_print) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_called_once_with( + "\nRequest a new registration for this computer now? [Y/n]: ") + +@@ -1387,7 +1421,11 @@ + SystemExit, main, ["--silent", "-c", self.make_working_config()], + print=noop_print) + mock_setup.assert_called_once_with(mock.ANY) +- mock_register.assert_called_once_with(mock.ANY, mock.ANY) ++ mock_register.assert_called_once_with( ++ mock.ANY, ++ mock.ANY, ++ on_error=mock.ANY, ++ ) + mock_input.assert_not_called() + + @mock.patch("landscape.client.configuration.input") +@@ -1964,6 +2002,27 @@ + # We ask for retries because networks aren't reliable. + self.assertEqual(99, connector.max_retries) + ++ def test_register_got_error(self): ++ """If there is an error from the connection, raises `SystemExit`.""" ++ reactor = mock.Mock() ++ connector_factory = mock.Mock() ++ results = [] ++ ++ def add_error(): ++ results.append(SystemExit()) ++ ++ reactor.run.side_effect = add_error ++ ++ self.assertRaises( ++ SystemExit, ++ register, ++ self.config, ++ reactor, ++ connector_factory, ++ max_retries=2, ++ results=results, ++ ) ++ + @mock.patch("landscape.client.configuration.LandscapeReactor") + def test_register_without_reactor(self, mock_reactor): + """If no reactor is passed, a LandscapeReactor will be instantiated. +@@ -2304,3 +2363,21 @@ + SystemExit, main, ["--is-registered", "--silent"], + print=noop_print) + self.assertEqual(EXIT_NOT_REGISTERED, exception.code) ++ ++ ++class SetSecureIdTest(LandscapeTest): ++ """Tests for the `set_secure_id` function.""" ++ ++ @mock.patch("landscape.client.configuration.Persist") ++ @mock.patch("landscape.client.configuration.Identity") ++ def test_function(self, Identity, Persist): ++ config = mock.Mock(data_path="/tmp/landscape") ++ ++ set_secure_id(config, "fancysecureid") ++ ++ Persist.assert_called_once_with( ++ filename="/tmp/landscape/broker.bpickle", ++ ) ++ Persist().save.assert_called_once_with() ++ Identity.assert_called_once_with(config, Persist()) ++ self.assertEqual(Identity().secure_id, "fancysecureid") diff -Nru landscape-client-23.02/debian/patches/series landscape-client-23.02/debian/patches/series --- landscape-client-23.02/debian/patches/series 2023-08-14 19:50:19.000000000 +0000 +++ landscape-client-23.02/debian/patches/series 2024-02-14 23:34:10.000000000 +0000 @@ -0,0 +1 @@ +0001-start-service-during-config.patch