#!/usr/bin/python """ Xspice Xspice is a standard X server that is also a Spice server. It is implemented as a module with video, mouse and keyboard drivers. The video driver is mostly the same code as the qxl guest driver, hence Xspice is kept in the same repository. It can also be used to debug the qxl driver. Xspice (this executable) will set a bunch of environment variables that are used by spiceqxl_drv.so, and then exec Xorg, giving it the default config file, which can be overridden as well. """ import argparse import os import sys def which(x): for p in os.environ['PATH'].split(':'): candidate = os.path.join(p, x) if os.path.exists(candidate): return candidate return None if 'XSPICE_ENABLE_GDB' in os.environ: cgdb = which('cgdb') if not cgdb: cgdb = which('gdb') else: cgdb = None def add_boolean(flag, *args, **kw): parser.add_argument(flag, action='store_const', const='1', default='0', *args, **kw) wan_compression_options = ['auto', 'never', 'always'] parser = argparse.ArgumentParser("Xspice", description="X and Spice server. example usage: Xspice --port 5900 --disable-ticketing :1.0", usage="Xspice [Xspice and Xorg options intermixed]", epilog="Any options not parsed by Xspice get passed to Xorg as is.") parser.add_argument('--xorg', default=which('Xorg')) parser.add_argument('--config', default='spiceqxl.xorg.conf') # Don't use any options that are already used by Xorg (unless we must) # specifically, don't use -p and -s. parser.add_argument('--port', type=int, help='standard spice port') parser.add_argument('--tls-port', type=int, help='spice tls port', default=0) add_boolean('--disable-ticketing', help="do not require a client password") add_boolean('--sasl', help="enable sasl") parser.add_argument('--x509-dir', help="x509 directory for tls", default='.') parser.add_argument('--cacert-file', help="ca certificate file for tls") parser.add_argument('--x509-cert-file', help="server certificate file for tls") parser.add_argument('--x509-key-file', help="server key file for tls") parser.add_argument('--x509-key-password', help="key file password for tls") parser.add_argument('--tls-ciphers') parser.add_argument('--dh-file') parser.add_argument('--password', help="set password required to connect to server") parser.add_argument('--image-compression', choices = ['off', 'auto_glz', 'auto_lz', 'quic', 'glz', 'lz'], default='auto_glz', help='auto_glz by default') parser.add_argument('--jpeg-wan-compression', choices=wan_compression_options, default='auto', help='auto by default') parser.add_argument('--zlib-glz-wan-compression', choices=wan_compression_options, default='auto', help='auto by default') # TODO - sound support #parser.add_argument('--playback-compression', choices=['0', '1'], default='1', help='enabled by default') parser.add_argument('--streaming-video', choices=['off', 'all', 'filter'], default='filter', help='filter by default') add_boolean('--ipv4-only') add_boolean('--ipv6-only') if cgdb: parser.add_argument('--cgdb', action='store_true', default=False) # TODO: #add_boolean(parser, '--agent-mouse') args, xorg_args = parser.parse_known_args(sys.argv[1:]) def tls_files(args): if args.tls_port == 0: return {} files = {} for k, var in [('ca-cert', 'cacert_file'), ('server-key', 'x509_key_file'), ('server-cert', 'x509_cert_file')]: files[k] = os.path.join(args.x509_dir, k + '.pem') if getattr(args, var): files[k] = getattr(args, var) return files # XXX spice-server aborts if it can't find the certificates - avoid by checking # ourselves. This isn't exhaustive - if the server key requires a password # and it isn't supplied spice will still abort, and Xorg with it. for key, filename in tls_files(args).items(): if not os.path.exists(filename): print "missing %s - %s does not exist" % (key, filename) sys.exit(1) def error(msg, exit_code=1): print "Xspice: %s" % msg sys.exit(exit_code) if not args.xorg: error("Xorg missing") var_args = ['port', 'tls_port', 'disable_ticketing', 'x509_dir', 'sasl', 'cacert_file', 'x509_cert_file', 'x509_key_file', 'x509_key_password', 'tls_ciphers', 'dh_file', 'password', 'image_compression', 'jpeg_wan_compression', 'zlib_glz_wan_compression', 'streaming_video'] for arg in var_args: if getattr(args, arg): os.environ['XSPICE_' + arg.upper()] = str(getattr(args, arg)) exec_args = [args.xorg, '-config', args.config] if cgdb and args.cgdb: exec_args = [cgdb, '--args'] + exec_args args.xorg = cgdb os.execv(args.xorg, exec_args + xorg_args)