[X2Go-Commits] [python-x2go] 07/09: Add X2Go KDrive graphical rendering backend support.

git-admin at x2go.org git-admin at x2go.org
Fri Jul 19 19:42:45 CEST 2019


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository python-x2go.

commit a330b42d210b80ac6ebea76860ad9d0780c19dcc
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date:   Fri Jul 19 17:32:03 2019 +0200

    Add X2Go KDrive graphical rendering backend support.
---
 debian/changelog                          |  1 +
 x2go/backends/info/plain.py               | 58 +++++++++++++++++-
 x2go/backends/proxy/base.py               |  2 +-
 x2go/backends/proxy/{nx3.py => kdrive.py} | 61 ++++++++++---------
 x2go/backends/proxy/nx3.py                |  4 +-
 x2go/backends/terminal/plain.py           | 99 ++++++++++++++++++++++++++-----
 x2go/client.py                            | 15 ++++-
 x2go/defaults.py                          | 20 +++++--
 x2go/session.py                           | 14 ++++-
 x2go/utils.py                             |  3 +-
 x2go/x2go_exceptions.py                   |  1 +
 11 files changed, 220 insertions(+), 58 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 88e7159..09e0eaf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,6 +10,7 @@ python-x2go (0.6.0.3-0x2go1) UNRELEASED; urgency=medium
     - X2GoTerminalSession: Fix __doc__ string of constructor.
     - X2GoTerminalSession: Fully delegate the session type handling
       and remembering to the session's X2GoSessionInfo object.
+    - Add X2Go KDrive graphical rendering backend support.
 
  -- X2Go Release Manager <git-admin at x2go.org>  Sat, 01 Dec 2018 02:16:45 +0100
 
diff --git a/x2go/backends/info/plain.py b/x2go/backends/info/plain.py
index c16b198..9d9e270 100644
--- a/x2go/backends/info/plain.py
+++ b/x2go/backends/info/plain.py
@@ -133,7 +133,7 @@ class X2GoServerSessionInfo(object):
 
     def get_session_type(self):
         """\
-        Get the session type (i.e. 'D', 'R', 'S' or 'P').
+        Get the session type (i.e. 'D', 'K', 'R', 'S' or 'P').
 
 
         :returns: session type
@@ -199,10 +199,64 @@ class X2GoServerSessionInfo(object):
 
         """
         if self.initialized:
-            return self.get_session_type() == 'D'
+            return self.get_session_type() in ('D', 'K')
         else:
             return None
 
+    def is_kdrive_session(self):
+        """\
+        Is this session a KDrive based desktop session?
+
+
+        :returns: ``True`` if this session is a KDrive based desktop session, ``False`` otherwise
+
+        :rtype: ``bool``
+
+        """
+        if self.initialized:
+            return self.get_session_type() == 'K'
+        else:
+           return None
+
+    def is_nx3_session(self):
+        """\
+        Is this session an NXv3 based desktop/rootless/shadow session?
+
+
+        :returns: ``True`` if this session is a NXv3 based desktop, rootless or shadow session, ``False`` otherwise
+
+        :rtype: ``bool``
+
+        """
+        if self.initialized:
+            return self.get_session_type() in ('D', 'S', 'R', 'P')
+        else:
+            return None
+
+    def is_kdrive_session(self):
+        """\
+        Is this session a KDrive based desktop session?
+
+
+        :returns: ``True`` if this session is a KDrive based desktop session, ``False`` otherwise
+
+        :rtype: ``bool``
+
+        """
+        return self.get_session_type() == 'K'
+
+    def is_nx3_session(self):
+        """\
+        Is this session an NXv3 based desktop/rootless session?
+
+
+        :returns: ``True`` if this session is a NXv3 based desktop/rootless session, ``False`` otherwise
+
+        :rtype: ``bool``
+
+        """
+        return self.get_session_type() in ('D','R','P')
+
     def _parse_x2gostartagent_output(self, x2go_output):
         """\
         Parse x2gostartagent output.
diff --git a/x2go/backends/proxy/base.py b/x2go/backends/proxy/base.py
index 79818bc..f92449c 100644
--- a/x2go/backends/proxy/base.py
+++ b/x2go/backends/proxy/base.py
@@ -18,7 +18,7 @@
 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
 """\
-X2GoProxy class - proxying your connection through NX3 and others.
+X2GoProxy class - proxying/rendering your graphical connection through NX3, KDRIVE and others.
 
 """
 __NAME__ = 'x2goproxy-pylib'
diff --git a/x2go/backends/proxy/nx3.py b/x2go/backends/proxy/kdrive.py
similarity index 65%
copy from x2go/backends/proxy/nx3.py
copy to x2go/backends/proxy/kdrive.py
index f1d62e0..820c622 100644
--- a/x2go/backends/proxy/nx3.py
+++ b/x2go/backends/proxy/kdrive.py
@@ -18,13 +18,13 @@
 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
 """\
-X2GoProxy classes - proxying your connection through NX3 and others.
+X2GoProxy classes - rendering your graphical connection through KDRIVE.
 
 """
-__NAME__ = 'x2goproxynx3-pylib'
+__NAME__ = 'x2goproxykdrive-pylib'
 
 __package__ = 'x2go.backends.proxy'
-__name__    = 'x2go.backends.proxy.nx3'
+__name__    = 'x2go.backends.proxy.kdrive'
 
 # modules
 import os
@@ -37,7 +37,7 @@ from x2go.defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS
 
 class X2GoProxy(base.X2GoProxy):
     """\
-    This :class:`x2go.backends.proxy.nx3.X2GoProxy` class is a NX version 3 based X2Go proxy connection class.
+    This :class:`x2go.backends.proxy.kdrive.X2GoProxy` class is a X2Go KDrive Client connection class.
 
     It basically fills :class:`x2go.backends.proxy.base.X2GoProxy` variables with sensible content. Its
     methods mostly wrap around the corresponding methods of the parent class.
@@ -50,26 +50,29 @@ class X2GoProxy(base.X2GoProxy):
 
         """
         base.X2GoProxy.__init__(self, *args, **kwargs)
-        self.subsystem = 'NX Proxy'
+        self.subsystem = 'X2Go KDrive Client'
 
         # setting some default environment variables, nxproxy paths etc.
         if _X2GOCLIENT_OS == "Windows":
-            _nxproxy_paths = [
-                os.path.join(os.environ["ProgramFiles"], os.path.normpath("PyHoca-GUI/nxproxy/nxproxy.exe")),
-                os.path.join(os.environ["ProgramFiles"], os.path.normpath("x2goclient/nxproxy.exe")),
-                os.path.join(os.environ["ProgramFiles"], os.path.normpath("NX Client for Windows/bin/nxproxy.exe")),
+            _x2gokdriveclient_paths = [
+                os.path.join(os.environ["ProgramFiles"], os.path.normpath("PyHoca-GUI/x2gokdrive/x2gokdriveclient.exe")),
+                os.path.join(os.environ["ProgramFiles"], os.path.normpath("x2goclient/x2gokdriveclient.exe")),
                 os.path.normpath("../pyhoca-contrib/mswin/nxproxy-mswin/nxproxy-3.5.0.27_cygwin-2015-10-18/nxproxy.exe"),
+                os.path.normpath("../pyhoca-contrib/mswin/x2gokrive-mswin/x2gokdriveclient-0.0.0.1_cygwin-NOT-BUILT-YET/x2gokdriveclient.exe"),
             ]
-            if 'NXPROXY_BINARY' in os.environ:
-                _nxproxy_paths.insert(0, os.environ['NXPROXY_BINARY'])
-            for _nxproxy_cmd in _nxproxy_paths:
-                if os.path.exists(_nxproxy_cmd):
+            if 'X2GOKDRIVECLIENT_BINARY' in os.environ:
+                _x2gokdriveclient_paths.insert(0, os.environ['X2GOKDRIVECLIENT_BINARY'])
+            for _x2gokdriveclient_cmd in _x2gokdriveclient_paths:
+                if os.path.exists(_x2gokdriveclient_cmd):
                     break
-            self.PROXY_CMD = _nxproxy_cmd
+            self.PROXY_CMD = _x2gokdriveclient_cmd
         else:
-            self.PROXY_CMD = "/usr/bin/nxproxy"
+            self.PROXY_CMD = "/usr/bin/x2gokdriveclient"
+
+        # from here, all options are similar to NX options, as X2GoKDrive is fully NX Proxy compatible
+        # (although, some options being no-op in X2Go KDrive)
+
         self.PROXY_ENV.update({
-            "NX_CLIENT": "/bin/true",
             "NX_ROOT": self.sessions_rootdir
         })
         self.PROXY_MODE = '-S'
@@ -117,14 +120,18 @@ class X2GoProxy(base.X2GoProxy):
 
 
         """
+        _options_filename = os.path.join(self.session_info.local_container, 'options')
+        options = open(_options_filename, 'w')
+        options.write(u'%s:%s' % (','.join(self.PROXY_OPTIONS), self.PROXY_DISPLAY))
+        options.close()
+
         if _X2GOCLIENT_OS == "Windows":
-            _options_filename = os.path.join(self.session_info.local_container, 'options')
-            options = open(_options_filename, 'w')
-            options.write(u'%s:%s' % (','.join(self.PROXY_OPTIONS), self.PROXY_DISPLAY))
-            options.close()
-            self.PROXY_OPTIONS= [ 'nx/nx', 'options=%s' % os.path.join("\\", "..", "S-%s" % self.session_info.name, 'options'), ]
+            self.PROXY_OPTIONS= [ 'nx/nx', 'options=%s' % os.path.join(".", "..", "S-%s" % self.session_info.name, 'options'), ]
+        else:
+            self.PROXY_OPTIONS= [ 'nx/nx', 'options=%s' % os.path.join(self.session_info.local_container, 'options'), ]
 
-        cmd_line = [ self.PROXY_CMD, ]
+        cmd_line = [ self.PROXY_CMD,
+        ]
         cmd_line.append(self.PROXY_MODE)
         _proxy_options = "%s:%s" % (",".join(self.PROXY_OPTIONS), self.PROXY_DISPLAY)
         cmd_line.append(_proxy_options)
@@ -143,15 +150,15 @@ class X2GoProxy(base.X2GoProxy):
         :rtype: ``obj``
 
         """
-        self.logger('starting local NX3 proxy...', loglevel=log.loglevel_INFO)
-        self.logger('NX3 Proxy mode is server, cookie=%s, host=127.0.0.1, port=%s.' % (self.session_info.cookie, self.session_info.graphics_port,), loglevel=log.loglevel_DEBUG)
-        self.logger('NX3 proxy writes session log to %s.' % os.path.join(self.session_info.local_container, 'session.log'), loglevel=log.loglevel_DEBUG)
+        self.logger('starting local X2Go KDrive Client...', loglevel=log.loglevel_INFO)
+        self.logger('X2Go KDrive Client mode is server, cookie=%s, host=127.0.0.1, port=%s.' % (self.session_info.cookie, self.session_info.graphics_port,), loglevel=log.loglevel_DEBUG)
+        self.logger('X2Go KDrive Client writes session log to %s.' % os.path.join(self.session_info.local_container, 'session.log'), loglevel=log.loglevel_DEBUG)
 
         p, p_ok = base.X2GoProxy.start_proxy(self)
 
         if self.ok():
-            self.logger('NX3 proxy is up and running.', loglevel=log.loglevel_INFO)
+            self.logger('X2Go KDrive Client is up and running.', loglevel=log.loglevel_INFO)
         else:
-            self.logger('Bringing up NX3 proxy failed.', loglevel=log.loglevel_ERROR)
+            self.logger('Bringing up X2Go KDrive Client failed.', loglevel=log.loglevel_ERROR)
 
         return p, self.ok()
diff --git a/x2go/backends/proxy/nx3.py b/x2go/backends/proxy/nx3.py
index f1d62e0..7dee2da 100644
--- a/x2go/backends/proxy/nx3.py
+++ b/x2go/backends/proxy/nx3.py
@@ -18,7 +18,7 @@
 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
 """\
-X2GoProxy classes - proxying your connection through NX3 and others.
+X2GoProxy class - proxying your graphical connection through NX3.
 
 """
 __NAME__ = 'x2goproxynx3-pylib'
@@ -122,7 +122,7 @@ class X2GoProxy(base.X2GoProxy):
             options = open(_options_filename, 'w')
             options.write(u'%s:%s' % (','.join(self.PROXY_OPTIONS), self.PROXY_DISPLAY))
             options.close()
-            self.PROXY_OPTIONS= [ 'nx/nx', 'options=%s' % os.path.join("\\", "..", "S-%s" % self.session_info.name, 'options'), ]
+            self.PROXY_OPTIONS= [ 'nx/nx', 'options=%s' % os.path.join(".", "..", "S-%s" % self.session_info.name, 'options'), ]
 
         cmd_line = [ self.PROXY_CMD, ]
         cmd_line.append(self.PROXY_MODE)
diff --git a/x2go/backends/terminal/plain.py b/x2go/backends/terminal/plain.py
index 697864b..5047287 100644
--- a/x2go/backends/terminal/plain.py
+++ b/x2go/backends/terminal/plain.py
@@ -58,7 +58,8 @@ from x2go.defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR
 from x2go.defaults import X2GO_SESSIONS_ROOTDIR as _X2GO_SESSIONS_ROOTDIR
 from x2go.defaults import X2GO_GENERIC_APPLICATIONS as _X2GO_GENERIC_APPLICATIONS
 from x2go.defaults import X2GO_DESKTOPSESSIONS as _X2GO_DESKTOPSESSIONS
-
+from x2go.defaults import X2GO_DESKTOPSESSIONS_NX3_PREFERRED as _X2GO_DESKTOPSESSIONS_NX3_PREFERRED
+from x2go.defaults import X2GO_DESKTOPSESSIONS_KDRIVE_PREFERRED as _X2GO_DESKTOPSESSIONS_KDRIVE_PREFERRED
 from x2go.defaults import BACKENDS as _BACKENDS
 
 _local_color_depth = utils.local_color_depth()
@@ -128,11 +129,12 @@ class X2GoSessionParams(object):
     def rewrite_session_type(self):
         """\
         Rewrite the X2Go session type, so that the X2Go server
-        can understand it (``desktop`` -> ``D``, etc.).
+        can understand it (``desktop`` -> ``D`` or ``K``, depending
+        on the proxy backend, etc.).
 
         Also if the object's ``command`` property is a known window
         manager, the session type will be set to 'D'
-        (i.e. desktop).
+        (i.e. desktop with NX3 backend).
 
         :returns: D' if session should probably a desktop session,
             'R' for rootless sessions, 'P' for sessions providing published
@@ -152,14 +154,16 @@ class X2GoSessionParams(object):
                 if self.geometry == 'fullscreen': self.session_type = 'D'
                 else: self.session_type = 'R'
             elif cmd == 'XDMCP':
-                self.session_type = 'D'
+                self.session_type = 'desktop'
             elif cmd in list(_X2GO_DESKTOPSESSIONS.keys()):
-                self.session_type = 'D'
+                self.session_type = 'desktop'
             elif os.path.basename(cmd) in list(_X2GO_DESKTOPSESSIONS.values()):
-                self.session_type = 'D'
+                self.session_type = 'desktop'
 
-        if self.session_type in ("D", "desktop"):
+        if self.session_type == "D" or ( self.session_type == "desktop" and self.kdrive == False ):
             self.session_type = 'D'
+        elif self.session_type == "K" or ( self.session_type == "desktop" and self.kdrive == True ):
+            self.session_type = 'K'
         elif self.session_type in ("S", "shared", "shadow"):
             self.session_type = 'S'
         elif self.session_type in ("R", "rootless", "application"):
@@ -213,6 +217,7 @@ class X2GoTerminalSession(object):
                  kbtype='null/null', kblayout='null', kbvariant='null',
                  clipboard='both',
                  xinerama=False,
+                 kdrive=False,
                  session_type="application", snd_system='pulse', snd_port=4713, cmd=None,
                  published_applications=False,
                  set_session_title=False, session_title="", applications=[],
@@ -380,13 +385,29 @@ class X2GoTerminalSession(object):
         self.params.server_encoding = str(server_encoding)
 
         self.params.rootdir = (type(rootdir) is bytes) and rootdir or self.sessions_rootdir
+
+        self.params.kdrive = False
+        # enforce X2GoKDrive usage?
+        if kdrive:
+            proxy_backend = "KDRIVE"
+            self.params.kdrive = True
+
         self.params.update()
 
         self.profile_name = profile_name
         self.set_session_title = set_session_title
         self.session_title = session_title
         self.session_window = None
-        self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
+
+        # auto-detect graphical proxy/kdrive backend?
+        if proxy_backend == 'auto-detect':
+            # we need to defer this at this point
+            # until we know the exact session command
+            # to be launched... (i.e. what desktop environment
+            # the user wants to launch via X2Go
+            self.proxy_backend = proxy_backend
+        else:
+            self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
 
         self.snd_port = snd_port
         self.print_action = print_action
@@ -432,15 +453,22 @@ class X2GoTerminalSession(object):
 
 
         """
-        if self._share_local_folder_lock.locked():
-            self._share_local_folder_lock.release()
+        try:
+            if self._share_local_folder_lock and self._share_local_folder_lock.locked():
+                self._share_local_folder_lock.release()
+        except AttributeError:
+            pass
+
         self.release_telekinesis()
         self.release_proxy()
         self.session_window = None
-        self.update_session_window_file()
 
         try:
+            self.update_session_window_file()
+        except AttributeError:
+            pass
 
+        try:
             if self.control_session.get_transport() is not None:
                 try:
                     for _tunnel in [ _tun[1] for _tun in list(self.reverse_tunnels[self.session_info.name].values()) ]:
@@ -458,7 +486,10 @@ class X2GoTerminalSession(object):
         except AttributeError:
             pass
 
-        self.session_info.clear()
+        try:
+            self.session_info.clear()
+        except AttributeError:
+            pass
 
     def _mk_sessions_rootdir(self, rootdir):
         """\
@@ -1552,6 +1583,23 @@ class X2GoTerminalSession(object):
 
         self.params.rewrite_session_type()
 
+        # auto-detect proxy backend, if requested
+        if self.proxy_backend == 'auto-detect':
+            if self.params.cmd in list(_X2GO_DESKTOPSESSIONS_KDRIVE_PREFERRED.keys()):
+                self.proxy_backend = utils._get_backend_class("KDRIVE", "X2GoProxy")
+                self.params.kdrive = True
+            elif os.path.basename(self.params.cmd) in list(_X2GO_DESKTOPSESSIONS_KDRIVE_PREFERRED.values()):
+                self.proxy_backend = utils._get_backend_class("KDRIVE", "X2GoProxy")
+                self.params.kdrive = True
+            elif self.params.cmd in list(_X2GO_DESKTOPSESSIONS_NX3_PREFERRED.keys()):
+                self.proxy_backend = utils._get_backend_class("NX3", "X2GoProxy")
+            elif os.path.basename(self.params.cmd) in list(_X2GO_DESKTOPSESSIONS_NX3_PREFERRED.values()):
+                self.proxy_backend = utils._get_backend_class("NX3", "X2GoProxy")
+            else:
+                self.proxy_backend = utils._get_backend_class("default", "X2GoProxy")
+
+        self.params.rewrite_session_type()
+
         if self.params.geometry == 'maximize':
             _geometry = utils.get_workarea_geometry()
             if _geometry is None or len(_geometry) != 2:
@@ -1620,7 +1668,7 @@ class X2GoTerminalSession(object):
                                                                 self.session_info.name,
                                                                )
 
-        # set up SSH tunnel for X11 graphical elements
+        # set up SSH tunnel for X11 graphical elements and launch client-side proxy/kdrive client
         self.proxy = self.proxy_backend(session_info=self.session_info,
                                         ssh_transport=self.control_session.get_transport(),
                                         sessions_rootdir=self.sessions_rootdir,
@@ -1632,7 +1680,7 @@ class X2GoTerminalSession(object):
         if proxy_ok:
             self.active_threads.append(self.proxy)
 
-            if self.get_session_type() in ('D', 'S'):
+            if self.get_session_type() in ('D', 'S', 'K'):
                 self.find_session_window()
                 self.auto_session_window_title()
                 self.raise_session_window()
@@ -1719,12 +1767,19 @@ class X2GoTerminalSession(object):
         self.session_info.remote_container = '%s/.x2go/C-%s' % (self.control_session._x2go_remote_home,
                                                                 self.session_info.name,
                                                                )
+
+        # make sure to use the correct proxy backend
+        if self.is_kdrive_session():
+            self.proxy_backend = utils._get_backend_class("KDRIVE", "X2GoProxy")
+        else:
+            self.proxy_backend = utils._get_backend_class("NX3", "X2GoProxy")
+
         self.proxy = self.proxy_backend(session_info=self.session_info,
                                         ssh_transport=self.control_session.get_transport(),
                                         sessions_rootdir=self.sessions_rootdir,
                                         session_instance=self.session_instance,
                                         proxy_options=self.proxy_options,
-                                        logger=self.logger
+                                        logger=self.logger,
                                        )
         self.proxy_subprocess, proxy_ok = self.proxy.start_proxy()
 
@@ -1832,6 +1887,20 @@ class X2GoTerminalSession(object):
 
             self._cleaned_up = True
 
+    def is_kdrive_session(self):
+        """\
+        Test if this terminal session is a KDrive based desktop session.
+
+
+        :returns: ``True`` if this session is of session type KDrive ('K').
+
+        :rtype: ``bool``
+
+        """
+        if not self.session_info.is_initialized():
+            self.params.rewrite_session_type()
+        return self.get_session_type() == 'K'
+
     def is_rootless_session(self):
         """\
         Test if this terminal session is a rootless session.
diff --git a/x2go/client.py b/x2go/client.py
index c8b26c2..0e2b588 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -277,7 +277,16 @@ class X2GoClient(object):
         self.terminal_backend = utils._get_backend_class(terminal_backend, "X2GoTerminalSession")
         self.info_backend = utils._get_backend_class(info_backend, "X2GoServerSessionInfo")
         self.list_backend = utils._get_backend_class(list_backend, "X2GoServerSessionList")
-        self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
+
+        if proxy_backend == 'auto-detect':
+            # we need to defer this at this point
+            # until we know the exact session command
+            # to be launched... (i.e. what desktop environment
+            # the user wants to launch via X2Go
+            self.proxy_backend = proxy_backend
+        else:
+            self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
+
         if broker_url is not None:
             if broker_url.lower().startswith('ssh'):
                 profiles_backend = 'sshbroker'
@@ -2680,7 +2689,7 @@ class X2GoClient(object):
         if with_command:
             _filtered_session_list = copy.deepcopy(_session_list)
             for _session in list(_session_list.keys()):
-                if not re.match('.*_st(D|R|P){cmd}_dp.*'.format(cmd=with_command), _session):
+                if not re.match('.*_st(D|K|R|P){cmd}_dp.*'.format(cmd=with_command), _session):
                     del _filtered_session_list[_session]
             _session_list = _filtered_session_list
 
@@ -2713,7 +2722,7 @@ class X2GoClient(object):
         :param refresh_cache: query the X2Go server directly and update the desktop list cache
             with the new information (Default value = False)
         :type refresh_cache: ``bool``
-        :param exclude_session_types: session types (e.g. "D", "R", "S" or "P") to be excluded from the
+        :param exclude_session_types: session types (e.g. "D", "K", "R", "S" or "P") to be excluded from the
             returned list of sharable desktops (this only works for sharing someone's own sessions, for
             sharing other users' sessions, the X2Go Desktop Sharing decides on what is sharable and what not). (Default value = [])
         :type exclude_session_types: ``list``
diff --git a/x2go/defaults.py b/x2go/defaults.py
index a434365..538a6a6 100644
--- a/x2go/defaults.py
+++ b/x2go/defaults.py
@@ -121,6 +121,7 @@ BACKENDS = {
     'X2GoProxy': {
         'default': 'NX3',
         'NX3': 'x2go.backends.proxy.nx3',
+        'KDRIVE': 'x2go.backends.proxy.kdrive',
     },
     'X2GoSessionProfiles': {
         'default': 'FILE',
@@ -305,6 +306,7 @@ X2GO_SESSIONPROFILE_DEFAULTS = {
     'rdpoptions': '-u X2GO_USER -p X2GO_PASSWORD', 'rdpserver': '',
     'print': False,
     'xdmcpserver': 'localhost',
+    'kdrive': False,
 }
 """:class:`x2go.backends.profiles.base.X2GoSessionProfiles` default values to fill a new session profile with."""
 ##
@@ -368,19 +370,29 @@ pack_methods_nx3.sort()
 ## X2Go session defaults
 ##
 
-X2GO_DESKTOPSESSIONS={
-    'CINNAMON': 'cinnamon',
+X2GO_DESKTOPSESSIONS_NX3_PREFERRED={
     'IceWM': 'icewm',
     'KDE': 'startkde',
-    'GNOME': 'gnome-session',
     'MATE': 'mate-session',
     'XFCE': 'xfce4-session',
     'LXDE': 'startlxde',
     'LXQt': 'startlxqt',
     'TRINITY': 'starttrinity',
+}
+"""A dictionary with meta-commands for X2Go's window manager sessions, usage of NXv3 preferred."""
+
+X2GO_DESKTOPSESSIONS_KDRIVE_PREFERRED={
+    'CINNAMON': 'cinnamon',
+    'GNOME': 'gnome-session',
     'UNITY': 'unity',
 }
-"""A dictionary with meta-commands for X2Go's window manager sessions."""
+"""A dictionary with meta-commands for X2Go's window manager sessions, usage of X2GoKDrive preferred."""
+
+X2GO_DESKTOPSESSIONS={}
+"""A dictionary with meta-commands for X2Go's window manager sessions. Will be populated by the concatenation of ``X2GO_DESKTOPSESSIONS_<BACKEND>_PREFERRED``."""
+
+X2GO_DESKTOPSESSIONS.update(X2GO_DESKTOPSESSIONS_NX3_PREFERRED)
+X2GO_DESKTOPSESSIONS.update(X2GO_DESKTOPSESSIONS_KDRIVE_PREFERRED)
 
 ##
 ## X2Go SFTP server defaults
diff --git a/x2go/session.py b/x2go/session.py
index 097f2f2..ec983a5 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -97,7 +97,7 @@ _X2GO_SESSION_PARAMS = ('use_sshproxy', 'sshproxy_reuse_authinfo',
 # options of the paramiko.SSHClient().connect() method, any option that is allowed for a terminal session instance
 _X2GO_TERMINAL_PARAMS = ('geometry', 'depth', 'link', 'pack', 'dpi',
                          'cache_type', 'kbtype', 'kblayout', 'kbvariant', 'clipboard', 'xinerama',
-                         'session_type', 'snd_system', 'snd_port',
+                         'session_type', 'kdrive', 'snd_system', 'snd_port',
                          'cmd', 'set_session_title', 'session_title',
                          'rdp_server', 'rdp_options', 'applications',
                          'xdmcp_server',
@@ -283,7 +283,15 @@ class X2GoSession(object):
         self.terminal_backend = utils._get_backend_class(terminal_backend, "X2GoTerminalSession")
         self.info_backend = utils._get_backend_class(info_backend, "X2GoServerSessionInfo")
         self.list_backend = utils._get_backend_class(list_backend, "X2GoServerSessionList")
-        self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
+
+        if proxy_backend == 'auto-detect':
+            # we need to defer this at this point
+            # until we know the exact session command
+            # to be launched... (i.e. what desktop environment
+            # the user wants to launch via X2Go
+            self.proxy_backend = proxy_backend
+        else:
+            self.proxy_backend = utils._get_backend_class(proxy_backend, "X2GoProxy")
         self.settings_backend = utils._get_backend_class(settings_backend, "X2GoClientSettings")
         self.printing_backend = utils._get_backend_class(printing_backend, "X2GoClientPrinting")
         self.client_rootdir = client_rootdir
@@ -2311,7 +2319,7 @@ class X2GoSession(object):
         Test if this X2Go session is a desktop session.
 
 
-        :returns: ``True`` if this session is of session type desktop ('D').
+        :returns: ``True`` if this session is of session type desktop ('D' or 'K').
 
         :rtype: ``bool``
 
diff --git a/x2go/utils.py b/x2go/utils.py
index 5a48ec4..76772e8 100644
--- a/x2go/utils.py
+++ b/x2go/utils.py
@@ -842,7 +842,8 @@ def _get_backend_class(backend, class_name):
     # silence pyflakes, the _this_class var will be assigned in an exec() statement below...
     _this_class = None
     if type(backend) not in (bytes, str): return backend
-    backend = backend.upper()
+    if backend != "default":
+        backend = backend.upper(    )
     available_backends = [ k for k in list(_BACKENDS[class_name].keys()) if k != 'default' ]
     # if for backend is given 'default' use the default backend module
     if backend == 'default': backend = _BACKENDS[class_name]['default']
diff --git a/x2go/x2go_exceptions.py b/x2go/x2go_exceptions.py
index 0485178..655fef4 100644
--- a/x2go/x2go_exceptions.py
+++ b/x2go/x2go_exceptions.py
@@ -72,6 +72,7 @@ class X2GoDesktopSharingDenied(_X2GoException): pass
 class X2GoTimeOutException(_X2GoException): pass
 class X2GoBrokerConnectionException(_X2GoException): pass
 class X2GoTelekinesisClientException(_X2GoException): pass
+class X2GoBackendException(_X2GoException): pass
 if _X2GOCLIENT_OS != 'Windows':
     # faking Windows errors on non-Windows systems...
     class WindowsError(_X2GoException): pass

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/python-x2go.git


More information about the x2go-commits mailing list