zone-vnc-console revision 3652
8d483882aa3390058094b043f3d62187b5d1de03mlf#!/usr/bin/python2.6
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlfimport errno
8d483882aa3390058094b043f3d62187b5d1de03mlfimport os
8d483882aa3390058094b043f3d62187b5d1de03mlfimport pwd
8d483882aa3390058094b043f3d62187b5d1de03mlfimport smf_include
8d483882aa3390058094b043f3d62187b5d1de03mlfimport subprocess
8d483882aa3390058094b043f3d62187b5d1de03mlfimport sys
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlffrom subprocess import CalledProcessError, check_call, Popen
8d483882aa3390058094b043f3d62187b5d1de03mlffrom tempfile import mkstemp
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlfSVCCFG = "/usr/sbin/svccfg"
8d483882aa3390058094b043f3d62187b5d1de03mlfSVCPROP = "/usr/bin/svcprop"
8d483882aa3390058094b043f3d62187b5d1de03mlfVNCSERVER = "/usr/bin/vncserver"
8d483882aa3390058094b043f3d62187b5d1de03mlfXSTARTUPHDR = "# WARNING: THIS FILE GENERATED BY SMF.\n" + \
8d483882aa3390058094b043f3d62187b5d1de03mlf "# DO NOT EDIT THIS FILE. EDITS WILL BE LOST.\n"
8d483882aa3390058094b043f3d62187b5d1de03mlfXTERM = "/usr/bin/xterm"
8d483882aa3390058094b043f3d62187b5d1de03mlf# Monospsce font, point size 15, white foreground on black background"
8d483882aa3390058094b043f3d62187b5d1de03mlfXTERMOPTS = ' -fa Monospace -fs 15 -fg white -bg black'
8d483882aa3390058094b043f3d62187b5d1de03mlf# Enclose command in comments to prevent xterm consuming zlogin opts
8d483882aa3390058094b043f3d62187b5d1de03mlfZLOGINOPTS = ' -e "/usr/bin/pfexec /usr/sbin/zlogin -C -E $ZONENAME"\n'
8d483882aa3390058094b043f3d62187b5d1de03mlfXSTARTUP = XSTARTUPHDR + XTERM + XTERMOPTS + ZLOGINOPTS
8d483882aa3390058094b043f3d62187b5d1de03mlf
7014882c6a3672fd0e5d60200af8643ae53c5928Richard Lowe
8d483882aa3390058094b043f3d62187b5d1de03mlfdef start():
8d483882aa3390058094b043f3d62187b5d1de03mlf check_vncserver()
8d483882aa3390058094b043f3d62187b5d1de03mlf homedir = os.environ.get('HOME')
8d483882aa3390058094b043f3d62187b5d1de03mlf if not homedir:
8d483882aa3390058094b043f3d62187b5d1de03mlf homedir = pwd.getpwuid(os.getuid()).pw_dir
8d483882aa3390058094b043f3d62187b5d1de03mlf os.putenv("HOME", homedir)
8d483882aa3390058094b043f3d62187b5d1de03mlf set_xstartup(homedir)
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf try:
8d483882aa3390058094b043f3d62187b5d1de03mlf fmri = os.environ['SMF_FMRI']
8d483882aa3390058094b043f3d62187b5d1de03mlf zonename = fmri.rsplit(':', 1)[1]
8d483882aa3390058094b043f3d62187b5d1de03mlf os.putenv("ZONENAME", zonename)
8d483882aa3390058094b043f3d62187b5d1de03mlf desktop_name = zonename + ' console'
8d483882aa3390058094b043f3d62187b5d1de03mlf # NOTE: 'geometry' below is that which matches the size of standard
8d483882aa3390058094b043f3d62187b5d1de03mlf # 80 character undecorated xterm window using font style specified in
8d483882aa3390058094b043f3d62187b5d1de03mlf # XTERMOPTS. Update this geometry whenever XTERMOPTS are changed.
8d483882aa3390058094b043f3d62187b5d1de03mlf # Avoids exposing X root window within noVNC canvas widget.
8d483882aa3390058094b043f3d62187b5d1de03mlf cmd = [VNCSERVER, "-name", desktop_name, "-SecurityTypes=None",
8d483882aa3390058094b043f3d62187b5d1de03mlf "-geometry", "964x580", "-localhost", "-autokill"]
8d483882aa3390058094b043f3d62187b5d1de03mlf vnc = Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
8d483882aa3390058094b043f3d62187b5d1de03mlf env=None)
8d483882aa3390058094b043f3d62187b5d1de03mlf out, err = vnc.communicate()
8d483882aa3390058094b043f3d62187b5d1de03mlf vncret = vnc.wait()
8d483882aa3390058094b043f3d62187b5d1de03mlf if vncret != 0:
8d483882aa3390058094b043f3d62187b5d1de03mlf print "Error starting VNC server: " + err
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf except Exception as e:
8d483882aa3390058094b043f3d62187b5d1de03mlf print e
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf output = err.splitlines()
8d483882aa3390058094b043f3d62187b5d1de03mlf for line in output:
8d483882aa3390058094b043f3d62187b5d1de03mlf if line.startswith("New '%s' desktop is" % desktop_name):
8d483882aa3390058094b043f3d62187b5d1de03mlf display = line.rpartition(' ')[2]
8d483882aa3390058094b043f3d62187b5d1de03mlf host, display_num = display.split(':', 1)
8d483882aa3390058094b043f3d62187b5d1de03mlf # set host prop
8d483882aa3390058094b043f3d62187b5d1de03mlf port = 5900 + int(display_num)
8d483882aa3390058094b043f3d62187b5d1de03mlf print "VNC port: %d" % port
8d483882aa3390058094b043f3d62187b5d1de03mlf # set port num prop
8d483882aa3390058094b043f3d62187b5d1de03mlf cmd = [SVCCFG, '-s', fmri, 'setprop', 'vnc/port', '=', 'integer:',
8d483882aa3390058094b043f3d62187b5d1de03mlf str(port)]
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf svccfg = subprocess.Popen(cmd, stdout=subprocess.PIPE,
8d483882aa3390058094b043f3d62187b5d1de03mlf stderr=subprocess.PIPE)
8d483882aa3390058094b043f3d62187b5d1de03mlf out, err = svccfg.communicate()
8d483882aa3390058094b043f3d62187b5d1de03mlf retcode = svccfg.wait()
8d483882aa3390058094b043f3d62187b5d1de03mlf if retcode != 0:
8d483882aa3390058094b043f3d62187b5d1de03mlf print "Error updating 'vnc/port' property: " + err
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_OK
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlfdef stop():
8d483882aa3390058094b043f3d62187b5d1de03mlf try:
8d483882aa3390058094b043f3d62187b5d1de03mlf # first kill the SMF contract
8d483882aa3390058094b043f3d62187b5d1de03mlf check_call(["/usr/bin/pkill", "-c", sys.argv[2]])
8d483882aa3390058094b043f3d62187b5d1de03mlf except CalledProcessError as cpe:
8d483882aa3390058094b043f3d62187b5d1de03mlf # 1 is returncode if no SMF contract processes were matched,
8d483882aa3390058094b043f3d62187b5d1de03mlf # meaning they have already terminated.
8d483882aa3390058094b043f3d62187b5d1de03mlf if cpe.returncode != 1:
8d483882aa3390058094b043f3d62187b5d1de03mlf print "failed to kill the SMF contract: %s" % cpe
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf try:
7014882c6a3672fd0e5d60200af8643ae53c5928Richard Lowe fmri = os.environ['SMF_FMRI']
7014882c6a3672fd0e5d60200af8643ae53c5928Richard Lowe # reset port num prop to initial zero value
8d483882aa3390058094b043f3d62187b5d1de03mlf cmd = [SVCCFG, '-s', fmri, 'setprop', 'vnc/port', '=', 'integer:',
8d483882aa3390058094b043f3d62187b5d1de03mlf '0']
8d483882aa3390058094b043f3d62187b5d1de03mlf svccfg = subprocess.Popen(cmd, stdout=subprocess.PIPE,
8d483882aa3390058094b043f3d62187b5d1de03mlf stderr=subprocess.PIPE,)
8d483882aa3390058094b043f3d62187b5d1de03mlf out, err = svccfg.communicate()
8d483882aa3390058094b043f3d62187b5d1de03mlf retcode = svccfg.wait()
8d483882aa3390058094b043f3d62187b5d1de03mlf if retcode != 0:
8d483882aa3390058094b043f3d62187b5d1de03mlf print "Error resetting 'vnc/port' property: " + err
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf except Exception as e:
8d483882aa3390058094b043f3d62187b5d1de03mlf print e
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlfdef check_vncserver():
8d483882aa3390058094b043f3d62187b5d1de03mlf if not os.path.exists(VNCSERVER):
8d483882aa3390058094b043f3d62187b5d1de03mlf print("VNC console service not available on this compute node. "
8d483882aa3390058094b043f3d62187b5d1de03mlf "%s is missing. Run 'pkg install x11/server/xvnc'"
8d483882aa3390058094b043f3d62187b5d1de03mlf % VNCSERVER)
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf if not os.path.exists(XTERM):
8d483882aa3390058094b043f3d62187b5d1de03mlf print("VNC console service not available on this compute node. "
8d483882aa3390058094b043f3d62187b5d1de03mlf "%s is missing. Run 'pkg install terminal/xterm'"
8d483882aa3390058094b043f3d62187b5d1de03mlf % XTERM)
8d483882aa3390058094b043f3d62187b5d1de03mlf return smf_include.SMF_EXIT_ERR_FATAL
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlfdef set_xstartup(homedir):
8d483882aa3390058094b043f3d62187b5d1de03mlf vncdir = os.path.join(homedir, '.vnc')
8d483882aa3390058094b043f3d62187b5d1de03mlf xstartup_path = os.path.join(vncdir, 'xstartup')
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf try:
8d483882aa3390058094b043f3d62187b5d1de03mlf os.mkdir(vncdir)
8d483882aa3390058094b043f3d62187b5d1de03mlf except OSError as ose:
8d483882aa3390058094b043f3d62187b5d1de03mlf if ose.errno != errno.EEXIST:
8d483882aa3390058094b043f3d62187b5d1de03mlf raise
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf # Always clobber xstartup
8d483882aa3390058094b043f3d62187b5d1de03mlf # stemp tuple = [fd, path]
8d483882aa3390058094b043f3d62187b5d1de03mlf stemp = mkstemp(dir=vncdir)
8d483882aa3390058094b043f3d62187b5d1de03mlf os.write(stemp[0], XSTARTUP)
8d483882aa3390058094b043f3d62187b5d1de03mlf os.close(stemp[0])
8d483882aa3390058094b043f3d62187b5d1de03mlf os.chmod(stemp[1], 0700)
8d483882aa3390058094b043f3d62187b5d1de03mlf os.rename(stemp[1], xstartup_path)
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlf
8d483882aa3390058094b043f3d62187b5d1de03mlfif __name__ == "__main__":
8d483882aa3390058094b043f3d62187b5d1de03mlf os.putenv("LC_ALL", "C")
8d483882aa3390058094b043f3d62187b5d1de03mlf smf_include.smf_main()