zone-vnc-console revision 4623
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews#!/usr/bin/python2.7
bec154197d3d640b0d5b416cd5218ea58dca5d3aTinderbox User
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews#
4a14ce5ba00ab7bc55c99ffdcf59c7a4ab902721Automatic Updater# Licensed under the Apache License, Version 2.0 (the "License"); you may
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# not use this file except in compliance with the License. You may obtain
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# a copy of the License at
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews#
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# http://www.apache.org/licenses/LICENSE-2.0
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews#
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# Unless required by applicable law or agreed to in writing, software
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# License for the specific language governing permissions and limitations
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# under the License.
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
ea94d370123a5892f6c47a97f21d1b28d44bb168Tinderbox Userimport errno
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsimport os
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsimport pwd
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsimport smf_include
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsimport subprocess
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrewsimport sys
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsimport time
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsfrom subprocess import CalledProcessError, check_call, Popen
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsfrom tempfile import mkstemp
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsGTF = "/usr/bin/gtf"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsSVCCFG = "/usr/sbin/svccfg"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsSVCPROP = "/usr/bin/svcprop"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsVNCSERVER = "/usr/bin/vncserver"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXRANDR = "/usr/bin/xrandr"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXSTARTUPHDR = "# WARNING: THIS FILE GENERATED BY SMF.\n" + \
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews "# DO NOT EDIT THIS FILE. EDITS WILL BE LOST.\n"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXRESOURCES = "[[ -f ~/.Xresources ]] && /usr/bin/xrdb -merge ~/.Xresources\n"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXTERM = "/usr/bin/xterm"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# Borderless, Monospsce font, point size 14, white foreground on black
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# background are reasonable defaults.
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXTERMOPTS = ' -b 0 -fa Monospace -fs 14 -fg white -bg black -title ' + \
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews '"Zone Console: $ZONENAME"'
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXWININFO = "/usr/bin/xwininfo"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews# Enclose command in comments to prevent xterm consuming zlogin opts
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsZLOGINOPTS = ' -e "/usr/bin/pfexec /usr/sbin/zlogin -C -E $ZONENAME"\n'
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark AndrewsXSTARTUP = XSTARTUPHDR + XRESOURCES + XTERM + XTERMOPTS + ZLOGINOPTS
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsdef start():
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews check_vncserver()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews homedir = os.environ.get('HOME')
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User if not homedir:
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User homedir = pwd.getpwuid(os.getuid()).pw_dir
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews os.putenv("HOME", homedir)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews set_xstartup(homedir)
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews try:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews fmri = os.environ['SMF_FMRI']
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews zonename = fmri.rsplit(':', 1)[1]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews os.putenv("ZONENAME", zonename)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews desktop_name = zonename + ' console'
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # NOTE: 'geometry' below is that which matches the size of standard
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # 80 character undecorated xterm window using font style specified in
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # XTERMOPTS. The geometry doesn't matter too much because the display
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # will be resized using xrandr once the xterm geometry is established.
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cmd = [VNCSERVER, "-name", desktop_name, "-SecurityTypes=None",
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews "-geometry", "964x580", "-localhost", "-autokill"]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews vnc = Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews env=None)
f6da30bb5447c23d880b09f601441e70c5313557Mark Andrews out, err = vnc.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews vncret = vnc.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if vncret != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error starting VNC server: " + err
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews except Exception as e:
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User print e
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews output = err.splitlines()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews for line in output:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if line.startswith("New '%s' desktop is" % desktop_name):
f7b41fd9291b8f4dba27e2b57e1d93f0913a4f1dMark Andrews display = line.rpartition(' ')[2]
f7b41fd9291b8f4dba27e2b57e1d93f0913a4f1dMark Andrews host, display_num = display.split(':', 1)
f7b41fd9291b8f4dba27e2b57e1d93f0913a4f1dMark Andrews # set host prop
f7b41fd9291b8f4dba27e2b57e1d93f0913a4f1dMark Andrews port = 5900 + int(display_num)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "VNC port: %d" % port
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # set port num prop
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cmd = [SVCCFG, '-s', fmri, 'setprop', 'vnc/port', '=', 'integer:',
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews str(port)]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews svccfg = subprocess.Popen(cmd, stdout=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stderr=subprocess.PIPE)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out, err = svccfg.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retcode = svccfg.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if retcode != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error updating 'vnc/port' property: " + err
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User return smf_include.SMF_EXIT_ERR_FATAL
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User resize_xserver(display, zonename)
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User return smf_include.SMF_EXIT_OK
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox Userdef stop():
d8620c7234281056fdfd2ee40cf16636b8281092Tinderbox User try:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # first kill the SMF contract
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews check_call(["/usr/bin/pkill", "-c", sys.argv[2]])
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews except CalledProcessError as cpe:
9fbbfb5757a1e3e86d7dea62c4e63ffc2303ca2bAutomatic Updater # 1 is returncode if no SMF contract processes were matched,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # meaning they have already terminated.
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if cpe.returncode != 1:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "failed to kill the SMF contract: %s" % cpe
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
d71e2e0c61df16ff37c9934c371a4a60c08974f7Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews try:
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews fmri = os.environ['SMF_FMRI']
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews # reset port num prop to initial zero value
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews cmd = [SVCCFG, '-s', fmri, 'setprop', 'vnc/port', '=', 'integer:',
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews '0']
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews svccfg = subprocess.Popen(cmd, stdout=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stderr=subprocess.PIPE,)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out, err = svccfg.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retcode = svccfg.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if retcode != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error resetting 'vnc/port' property: " + err
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews except Exception as e:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print e
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsdef check_vncserver():
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if not os.path.exists(VNCSERVER):
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print("VNC console service not available on this compute node. "
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews "%s is missing. Run 'pkg install x11/server/xvnc'"
d71e2e0c61df16ff37c9934c371a4a60c08974f7Mark Andrews % VNCSERVER)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if not os.path.exists(XTERM):
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print("VNC console service not available on this compute node. "
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews "%s is missing. Run 'pkg install terminal/xterm'"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews % XTERM)
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews return smf_include.SMF_EXIT_ERR_FATAL
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrewsdef set_xstartup(homedir):
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews vncdir = os.path.join(homedir, '.vnc')
a057e8e33baa5fa369be28a9680585200ce3ff73Mark Andrews xstartup_path = os.path.join(vncdir, 'xstartup')
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews try:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews os.mkdir(vncdir)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews except OSError as ose:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if ose.errno != errno.EEXIST:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews raise
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
dba3c818ae00b10388d31703e86a28415db398acTinderbox User # Always clobber xstartup
43b94483957d3168796a816ed86cf097518817dcTinderbox User # stemp tuple = [fd, path]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stemp = mkstemp(dir=vncdir)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews os.write(stemp[0], XSTARTUP)
72938578c985138165e7a4b0a38f16daacbad95eAutomatic Updater os.close(stemp[0])
72938578c985138165e7a4b0a38f16daacbad95eAutomatic Updater os.chmod(stemp[1], 0700)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews os.rename(stemp[1], xstartup_path)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsdef resize_xserver(display, zonename):
72938578c985138165e7a4b0a38f16daacbad95eAutomatic Updater """ Try to determine xterm window geometry and resize the Xvnc display
72938578c985138165e7a4b0a38f16daacbad95eAutomatic Updater to match using XRANDR. Treat failure as non-fatal since an
dba3c818ae00b10388d31703e86a28415db398acTinderbox User incorrectly sized console is arguably better than none.
dba3c818ae00b10388d31703e86a28415db398acTinderbox User """
43b94483957d3168796a816ed86cf097518817dcTinderbox User class UninitializedWindowError(Exception):
dba3c818ae00b10388d31703e86a28415db398acTinderbox User pass
dba3c818ae00b10388d31703e86a28415db398acTinderbox User
dba3c818ae00b10388d31703e86a28415db398acTinderbox User class UnmappedWindowError(Exception):
dba3c818ae00b10388d31703e86a28415db398acTinderbox User pass
dba3c818ae00b10388d31703e86a28415db398acTinderbox User
dba3c818ae00b10388d31703e86a28415db398acTinderbox User def _get_window_geometry(display, windowname):
72938578c985138165e7a4b0a38f16daacbad95eAutomatic Updater """ Find the xterm xwindow by name/title and extract its geometry
72938578c985138165e7a4b0a38f16daacbad95eAutomatic Updater Returns: tuple of window [width, height]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews Raises:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews UninitializedWindowError if window not yet initialized
bf056b7184b38281c1b0bf0cf21b5982fa1a4edaMark Andrews UnmappedWindowError if window is not viewable/mapped
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews """
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cmd = [XWININFO, '-d', display, '-name', windowname]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews xwininfo = subprocess.Popen(cmd, stdout=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stderr=subprocess.PIPE)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out, err = xwininfo.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retcode = xwininfo.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if retcode != 0:
97e74139b19368e385a3564746d42db70879195eAutomatic Updater print "Error finding console xwindow info: " + err
97e74139b19368e385a3564746d42db70879195eAutomatic Updater raise UninitializedWindowError
43b94483957d3168796a816ed86cf097518817dcTinderbox User
dba3c818ae00b10388d31703e86a28415db398acTinderbox User width = None
dba3c818ae00b10388d31703e86a28415db398acTinderbox User height = None
dba3c818ae00b10388d31703e86a28415db398acTinderbox User mapped = False
97e74139b19368e385a3564746d42db70879195eAutomatic Updater for line in out.splitlines():
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews line = line.strip()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if line.startswith("Map State:"):
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if line.split()[-1] != "IsViewable":
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # Window is not mapped yet.
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews raise UnmappedWindowError
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews else:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews mapped = True
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews if line.startswith("Width:"):
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews width = int(line.split()[1])
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews elif line.startswith("Height:"):
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews height = int(line.split()[1])
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews if width and height and mapped:
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews return [width, height]
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews else:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # What, no width and height???
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "No window geometry info returned by " + XWINFINFO
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews raise UnmappedWindowError
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retries = 10
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews sleep = 1
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews uninit_count = 0
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews unmap_count = 0
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews width = 0
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews height = 0
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews while uninit_count < retries and unmap_count < retries:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews try:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews width, height = _get_window_geometry(display,
f7b41fd9291b8f4dba27e2b57e1d93f0913a4f1dMark Andrews 'Zone Console: ' + zonename)
f7b41fd9291b8f4dba27e2b57e1d93f0913a4f1dMark Andrews print "Discovered xterm geometry: %d x %d" % (width, height)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews break
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews except UninitializedWindowError:
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater if uninit_count < retries:
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater print "xterm window not initialized yet. Retrying in %ds" \
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater % sleep
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater uninit_count += 1
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater time.sleep(sleep)
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater continue
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater else:
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater print "xterm window is taking too long to initialize"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews break
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews except UnmappedWindowError:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if unmap_count < retries:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Discovered xterm not mapped yet. Retrying in %ds" \
285254345ce5ab270848f8c11f7be146793f1e00Mark Andrews % sleep
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews unmap_count += 1
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews time.sleep(sleep)
285254345ce5ab270848f8c11f7be146793f1e00Mark Andrews continue
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews else:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Discovered xterm window is taking too long to map"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews break
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews else:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Too many failed attempts to discover xterm window geometry"
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews # Generate a mode line for width and height, with a refresh of 60.0Hz
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews cmd = [GTF, str(width), str(height), '60.0', '-x']
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews gtf = subprocess.Popen(cmd, stdout=subprocess.PIPE,
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews stderr=subprocess.PIPE)
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews out, err = gtf.communicate()
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews retcode = gtf.wait()
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews if retcode != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error creating new modeline for VNC display: " + err
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return
d71e2e0c61df16ff37c9934c371a4a60c08974f7Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews for line in out.splitlines():
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews line = line.strip()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if line.startswith('Modeline'):
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews modeline = line.split('Modeline')[1]
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User print "New optimal modeline for Xvnc server: " + modeline
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User mode = modeline.split()
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User break
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User # Create a new mode for the Xvnc server using the modeline generated by gtf
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User cmd = [XRANDR, '-d', display, '--newmode']
7be2f6d5df28b207e3e385c555eb4f740150528dTinderbox User cmd.extend(mode)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews newmode = subprocess.Popen(cmd, stdout=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stderr=subprocess.PIPE)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out, err = newmode.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retcode = newmode.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if retcode != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error creating new xrandr modeline for VNC display: " + err
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # Add the new mode to the default display output
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews modename = mode[0]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cmd = [XRANDR, '-d', display, '--addmode', 'default', modename]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews addmode = subprocess.Popen(cmd, stdout=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stderr=subprocess.PIPE)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out, err = addmode.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retcode = addmode.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if retcode != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error adding new xrandr modeline for VNC display: " + err
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews # Activate the new mode on the default display output
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cmd = [XRANDR, '-d', display, '--output', 'default', '--mode', modename]
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews addmode = subprocess.Popen(cmd, stdout=subprocess.PIPE,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews stderr=subprocess.PIPE)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out, err = addmode.communicate()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews retcode = addmode.wait()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if retcode != 0:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews print "Error setting new xrandr modeline for VNC display: " + err
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews return
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsif __name__ == "__main__":
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews os.putenv("LC_ALL", "C")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews smf_include.smf_main()
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews