From 0161097e1e00f79873197300320dd9fcdab9d293 Mon Sep 17 00:00:00 2001 From: totaam Date: Fri, 10 Dec 2021 22:08:59 +0700 Subject: [PATCH] #3217 store mode so we can upgrade automatically use 'upgrade-seamless' to force seamless mode, 'upgrade-desktop' to force desktop mode, 'upgrade' reloads the config to find what mode was used before and defaults to 'seamless' --- xpra/scripts/main.py | 32 ++++++++++++----- xpra/scripts/parsing.py | 14 +++++--- xpra/scripts/server.py | 78 +++++++++++++++++++++++------------------ 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/xpra/scripts/main.py b/xpra/scripts/main.py index c35730ee0d..298d2606da 100755 --- a/xpra/scripts/main.py +++ b/xpra/scripts/main.py @@ -212,7 +212,7 @@ def configure_logging(options, mode): ) setloghandler(SIGPIPEStreamHandler(to)) if mode in ( - "start", "start-desktop", "upgrade", "upgrade-desktop", "recover", + "start", "start-desktop", "upgrade", "upgrade-seamless", "upgrade-desktop", "recover", "attach", "listen", "shadow", "proxy", "_sound_record", "_sound_play", "stop", "print", "showconfig", @@ -365,7 +365,11 @@ def run_mode(script_file, cmdline, error_cb, options, args, mode, defaults): warn("\nWarning: running as root") display_is_remote = isdisplaytype(args, "ssh", "tcp", "ssl", "vsock") - if mode in ("start", "start-desktop", "upgrade", "upgrade-desktop", "shadow") and not display_is_remote: + if mode in ( + "start", "start-desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", + "shadow", + ) and not display_is_remote: if use_systemd_run(options.systemd_run): #make sure we run via the same interpreter, #inject it into the command line if we have to: @@ -399,14 +403,19 @@ def run_mode(script_file, cmdline, error_cb, options, args, mode, defaults): #sound commands don't want to set the name #(they do it later to prevent glib import conflicts) #"attach" does it when it received the session name from the server - if mode not in ("attach", "listen", "start", "start-desktop", "upgrade", "upgrade-desktop", "proxy", "shadow"): + if mode not in ( + "attach", "listen", + "start", "start-desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", + "proxy", "shadow", + ): from xpra.platform import set_name set_name("Xpra", "Xpra %s" % mode.strip("_")) if mode in ( "start", "start-desktop", "shadow", "attach", "listen", - "upgrade", "upgrade-desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", "recover", "request-start", "request-start-desktop", "request-shadow", ): @@ -441,7 +450,11 @@ def do_run_mode(script_file, cmdline, error_cb, options, args, mode, defaults): noerr(sys.stdout.write, "existing live display found, attaching") return do_run_mode(script_file, cmdline, error_cb, options, args, "attach", defaults) - if mode in ("start", "start-desktop", "upgrade", "upgrade-desktop", "shadow", "proxy"): + if mode in ( + "start", "start-desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", + "shadow", "proxy", + ): return run_server(script_file, cmdline, error_cb, options, args, mode, defaults) elif mode in ( "attach", "listen", "detach", @@ -1706,17 +1719,20 @@ def run_server(script_file, cmdline, error_cb, options, args, mode, defaults): if scaling==(1, 1): options.resize_display = "%ix%i" % (root_w, root_h) - if mode in ("start", "start-desktop", "upgrade", "upgrade-desktop") and (OSX or WIN32): + if mode in ( + "start", "start-desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", + ) and (OSX or WIN32): raise InitException("%s is not supported on this platform" % mode) if ( - mode in ("start", "start-desktop", "upgrade", "upgrade-desktop") and not supports_server + mode in ("start", "start-desktop", "upgrade", "upgrade-seamless", "upgrade-desktop") and not supports_server ) or ( mode=="shadow" and not supports_shadow ) or ( mode=="proxy" and not supports_proxy ) or ( - mode not in ("start", "start-desktop", "upgrade", "upgrade-desktop", "shadow", "proxy") + mode not in ("start", "start-desktop", "upgrade", "upgrade-seamless", "upgrade-desktop", "shadow", "proxy") ): raise InitException("%s is not supported by this local installation" % mode) diff --git a/xpra/scripts/parsing.py b/xpra/scripts/parsing.py index a6b80f240f..0a3dd91bf6 100755 --- a/xpra/scripts/parsing.py +++ b/xpra/scripts/parsing.py @@ -1837,10 +1837,16 @@ def dcsv(v): args[1] = address break - NEED_ENCODING_MODES = ("attach", "start", "start-desktop", "shadow", "proxy", - "upgrade", "upgrade-desktop", "recover", - "listen", "launcher", - "bug-report", "encoding", "gui-info") + NEED_ENCODING_MODES = ( + "attach", + "start", "seamless", + "start-desktop", "desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", + "recover", + "shadow", "proxy", + "listen", "launcher", + "bug-report", "encoding", "gui-info", + ) fixup_options(options, defaults, skip_encodings=len(args)==0 or MODE_ALIAS.get(args[0], args[0]) not in NEED_ENCODING_MODES) diff --git a/xpra/scripts/server.py b/xpra/scripts/server.py index 17801726ff..b1aa0fcbc0 100644 --- a/xpra/scripts/server.py +++ b/xpra/scripts/server.py @@ -33,7 +33,7 @@ fixup_options, make_defaults_struct, read_config, dict_to_validated_config, ) from xpra.common import CLOBBER_USE_DISPLAY, CLOBBER_UPGRADE -from xpra.exit_codes import EXIT_VFB_ERROR, EXIT_OK, EXIT_FAILURE +from xpra.exit_codes import EXIT_VFB_ERROR, EXIT_OK, EXIT_FAILURE, EXIT_UPGRADE from xpra.os_util import ( SIGNAMES, POSIX, WIN32, OSX, FDChangeCaptureContext, @@ -467,12 +467,16 @@ def clean_session_files(*filenames): "start-child-on-last-client-exit", ) -def get_options_file_contents(opts): +def get_options_file_contents(opts, mode="seamless"): from xpra.scripts.parsing import fixup_defaults defaults = make_defaults_struct() fixup_defaults(defaults) fixup_options(defaults) - diff_contents = ["# xpra server %s" % __version__] + diff_contents = [ + "# xpra server %s" % __version__, + "", + "mode=%s" % mode, + ] for attr, dtype in OPTION_TYPES.items(): if attr in CLIENT_ONLY_OPTIONS: continue @@ -497,11 +501,14 @@ def load_options(): config_file = session_file_path("config") return read_config(config_file) -def apply_config(opts): +def apply_config(opts, mode): #if we had saved the start / start-desktop config, reload it: options = load_options() if not options: - return + return mode + if mode=="upgrade": + #unspecified upgrade, try to find the original mode used: + mode = options.pop("mode", mode) upgrade_config = dict_to_validated_config(options) #apply the previous session options: for k in options.keys(): @@ -521,6 +528,7 @@ def apply_config(opts): continue value = getattr(upgrade_config, fn) setattr(opts, fn, value) + return mode def reload_dbus_attributes(display_name): @@ -591,8 +599,9 @@ def is_splash_enabled(mode, daemon, splash, display): MODE_TO_NAME = { "start" : "Seamless", "start-desktop" : "Desktop", - "upgrade" : "Seamless", - "upgrade-desktop" : "Desktop", + "upgrade" : "Upgrade", + "upgrade-seamless" : "Seamless Upgrade", + "upgrade-desktop" : "Desktop Upgrade", "shadow" : "Shadow", "proxy" : "Proxy", } @@ -613,12 +622,12 @@ def request_exit(uri): noerr(sys.stderr.write, "Error: failed to 'exit' the server to upgrade\n") noerr(sys.stderr.write, " %s\n" % e) return False - return p.poll()==0 + return p.poll() in (EXIT_OK, EXIT_UPGRADE) def do_run_server(script_file, cmdline, error_cb, opts, extra_args, mode, display_name, defaults): assert mode in ( "start", "start-desktop", - "upgrade", "upgrade-desktop", + "upgrade", "upgrade-seamless", "upgrade-desktop", "shadow", "proxy", ) validate_encryption(opts) @@ -682,8 +691,7 @@ def _do_run_server(script_file, cmdline, use_display = parse_bool("use-display", opts.use_display) starting = mode == "start" starting_desktop = mode == "start-desktop" - upgrading = mode == "upgrade" - upgrading_desktop = mode == "upgrade-desktop" + upgrading = mode.startswith("upgrade") shadowing = mode == "shadow" proxying = mode == "proxy" @@ -698,7 +706,7 @@ def _do_run_server(script_file, cmdline, opts.start_child_after_connect or opts.start_child_on_last_client_exit ) - if proxying or upgrading or upgrading_desktop: + if proxying or upgrading: #when proxying or upgrading, don't exec any plain start commands: opts.start = [] opts.start_child = [] @@ -711,7 +719,7 @@ def _do_run_server(script_file, cmdline, warn(" but 'exit-with-children' is not enabled,") warn(" you should just use 'start' instead") - if (upgrading or upgrading_desktop or shadowing) and opts.pulseaudio is None: + if (upgrading or shadowing) and opts.pulseaudio is None: #there should already be one running #so change None ('auto') to False opts.pulseaudio = False @@ -726,7 +734,7 @@ def _do_run_server(script_file, cmdline, from xpra.scripts.main import guess_X11_display dotxpra = DotXpra(opts.socket_dir, opts.socket_dirs) display_name = guess_X11_display(dotxpra, desktop_display) - elif (upgrading or upgrading_desktop) and not extra_args: + elif upgrading and not extra_args: display_name = guess_xpra_display(opts.socket_dir, opts.socket_dirs) else: if len(extra_args) > 1: @@ -762,7 +770,7 @@ def _do_run_server(script_file, cmdline, # Use the temporary magic value 'S' as marker: display_name = 'S' + str(os.getpid()) - if upgrading or upgrading_desktop: + if upgrading: assert display_name, "no display found to upgrade" if POSIX and not OSX and get_saved_env_var("DISPLAY", "")==display_name: warn("Warning: upgrading from an environment connected to the same display") @@ -771,26 +779,22 @@ def _do_run_server(script_file, cmdline, sessions = get_xpra_sessions(dotxpra, ignore_state=(DotXpra.UNKNOWN, DotXpra.DEAD), matching_display=display_name, query=True) session = sessions.get(display_name) + print("session(%s)=%s" % (display_name, session)) if session: socket_path = session.get("socket-path") uri = ("socket://%s" % socket_path) if socket_path else display_name if request_exit(uri): #the server has terminated as we had requested use_display = True - if upgrading: - starting = True - upgrading = False - else: - starting_desktop = True - upgrading_desktop = False #but it may need a second to disconnect the clients #and then close the sockets cleanly #(so we can re-create them safely) import time time.sleep(1) + else: + warn("server for %s is not exiting" % display_name) - if not (shadowing or proxying or upgrading or upgrading_desktop) and \ - opts.exit_with_children and not has_child_arg: + if not (shadowing or proxying or upgrading) and opts.exit_with_children and not has_child_arg: error_cb("--exit-with-children specified without any children to spawn; exiting immediately") # Generate the script text now, because os.getcwd() will @@ -862,7 +866,7 @@ def write_session_file(filename, contents): stderr.write(" %s\n" % e) del e - clobber = int(upgrading or upgrading_desktop)*CLOBBER_UPGRADE | int(use_display or 0)*CLOBBER_USE_DISPLAY + clobber = int(upgrading)*CLOBBER_UPGRADE | int(use_display or 0)*CLOBBER_USE_DISPLAY start_vfb = not (shadowing or proxying or clobber) xauth_data = None if start_vfb: @@ -958,10 +962,14 @@ def write_session_file(filename, contents): if env_script: write_session_file("server.env", env_script) write_session_file("cmdline", "\n".join(cmdline)+"\n") - if mode in ("upgrade", "upgrade-desktop"): + upgrading_seamless = upgrading_desktop = False + if upgrading: #if we had saved the start / start-desktop config, reload it: - apply_config(opts) - write_session_file("config", get_options_file_contents(opts)) + mode = apply_config(opts, mode) + upgrading_desktop = mode=="desktop" + upgrading_seamless = not upgrading_desktop + + write_session_file("config", get_options_file_contents(opts, mode)) extra_expand = {"TIMESTAMP" : datetime.datetime.now().strftime("%Y%m%d-%H%M%S")} log_to_file = opts.daemon or os.environ.get("XPRA_LOG_TO_FILE", "")=="1" @@ -1019,7 +1027,7 @@ def write_session_file(filename, contents): progress(30, "creating sockets") from xpra.net.socket_util import get_network_logger, setup_local_sockets, create_sockets - retry = 10*int(mode in ("upgrade", "upgrade-desktop")) + retry = 10*int(mode.startswith("upgrade")) sockets = create_sockets(opts, error_cb, retry=retry) from xpra.log import Logger @@ -1039,7 +1047,7 @@ def write_session_file(filename, contents): commands += list(getattr(opts, start_prop.replace("-", "_"))) if not commands: opts.start.append("xpra desktop-greeter") - if POSIX and configure_imsettings_env(opts.input_method)=="ibus" and not (upgrading or upgrading_desktop or shadowing or proxying): + if POSIX and configure_imsettings_env(opts.input_method)=="ibus" and not (upgrading or shadowing or proxying): #start ibus-daemon unless already specified in 'start': if IBUS_DAEMON_COMMAND and not ( any(x.find("ibus-daemon")>=0 for x in opts.start) or any(x.find("ibus-daemon")>=0 for x in opts.start_late) @@ -1080,10 +1088,10 @@ def write_session_file(filename, contents): log("found existing XAUTHORITY file '%s'", xauthority) write_session_file("xauthority", xauthority) #resolve use-display='auto': - if use_display is None or upgrading or upgrading_desktop: + if use_display is None or upgrading: #figure out if we have to start the vfb or not: if not display_name: - if upgrading or upgrading_desktop: + if upgrading: error_cb("no displays found to upgrade") use_display = False else: @@ -1092,7 +1100,7 @@ def write_session_file(filename, contents): stat = stat_X11_display(display_no) log("stat_X11_display(%i)=%s", display_no, stat) if not stat: - if upgrading or upgrading_desktop: + if upgrading: error_cb("cannot access display '%s'" % (display_name,)) #no X11 socket to connect to, so we have to start one: start_vfb = True @@ -1290,7 +1298,7 @@ def init_local_sockets(): username, uid, gid) netlog("setting up local sockets: %s", local_sockets) sockets.update(local_sockets) - if POSIX and (starting or upgrading or starting_desktop or upgrading_desktop): + if POSIX and (starting or upgrading or starting_desktop): #all unix domain sockets: ud_paths = [sockpath for stype, _, sockpath, _ in local_sockets if stype=="unix-domain"] if ud_paths: @@ -1336,7 +1344,7 @@ def _get_int(prop): elif proxying: app = make_proxy_server() else: - if starting or upgrading: + if starting or upgrading_seamless: app = make_server(clobber) else: assert starting_desktop or upgrading_desktop @@ -1348,7 +1356,7 @@ def server_not_started(msg="server not started"): #check the initial 'mode' value instead of "upgrading" or "upgrading_desktop" #as we may have switched to "starting=True" #if the existing server has exited as we requested) - if mode.find("upgrade")>=0 or use_display: + if mode.startswith("upgrade") or use_display: #something abnormal occurred, #don't kill the vfb on exit: from xpra.server import EXITING_CODE