summaryrefslogtreecommitdiffstats
path: root/pyanaconda/vnc.py
diff options
context:
space:
mode:
authorMartin Sivak <msivak@redhat.com>2010-05-11 17:31:06 +0200
committerMartin Sivak <msivak@redhat.com>2010-05-31 14:21:49 +0200
commit78421d4ed23ad58b021c4d9d1bae690b99c167fe (patch)
tree909c1b650afe9afea03ecf1a03b2d39d39cf72b7 /pyanaconda/vnc.py
parent40b979f28cfd73078d5dd58b8f7e97e76198a222 (diff)
downloadanaconda-78421d4ed23ad58b021c4d9d1bae690b99c167fe.tar.gz
anaconda-78421d4ed23ad58b021c4d9d1bae690b99c167fe.tar.xz
anaconda-78421d4ed23ad58b021c4d9d1bae690b99c167fe.zip
Structure the repo layout so it matches final structure better and make isys a real Python package.
Also updates the build and autotools stuff to work with the new structure
Diffstat (limited to 'pyanaconda/vnc.py')
-rw-r--r--pyanaconda/vnc.py437
1 files changed, 437 insertions, 0 deletions
diff --git a/pyanaconda/vnc.py b/pyanaconda/vnc.py
new file mode 100644
index 000000000..0a6a04933
--- /dev/null
+++ b/pyanaconda/vnc.py
@@ -0,0 +1,437 @@
+#
+# vnc.py: VNC related installer functionality
+#
+# Copyright (C) 2004, 2007 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Jeremy Katz <katzj@redhat.com>
+#
+
+import os, sys, string
+import time
+from snack import *
+from constants import *
+from constants_text import *
+import network
+import isys
+import product
+import socket
+import subprocess
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+P_ = lambda x, y, z: gettext.ldngettext("anaconda", x, y, z)
+
+import logging
+log = logging.getLogger("anaconda")
+stdoutLog = logging.getLogger("anaconda.stdout")
+
+class VncServer:
+
+ def __init__(self, display="1", root="/", ip=None, name=None,
+ desktop="Desktop", password="", vncconnecthost="",
+ vncconnectport="", log_file="/tmp/vncserver.log",
+ pw_file="/tmp/vncpassword", pw_init_file="/tmp/vncpassword.dat"):
+ self.display = display
+ self.root = root
+ self.ip = ip
+ self.name = name
+ self.desktop = desktop
+ self.password = password
+ self.vncconnecthost = vncconnecthost
+ self.vncconnectport = vncconnectport
+ self.log_file = log_file
+ self.pw_file = pw_file
+ self.pw_init_file = pw_init_file
+ self.connxinfo = None
+ self.anaconda = None
+ self.log = logging.getLogger("anaconda.stdout")
+
+ def recoverVNCPassword(self):
+ """Rescue the vncpassword from where loader left it
+
+ We are not to check for validity yet, if there is a file
+ pass it to the variable, if there is not, set the var
+ to ''. We will check valididty later.
+ """
+ # see if there is a vnc password file
+ try:
+ pfile = open(self.pw_init_file, "r")
+ self.password=pfile.readline().strip()
+ pfile.close()
+ os.unlink(self.pw_init_file)
+ except:
+ self.password=""
+
+ def setVNCPassword(self):
+ """Change the vnc server password. Output to file. """
+
+ if len(self.password) == 0:
+ self.setVNCParam("SecurityTypes", "None")
+ self.setVNCParam("rfbauth","0")
+ return
+
+ # If there is a password the SecurityTypes = VncAuth for all connections.
+ self.setVNCParam("SecurityTypes", "VncAuth")
+ self.setVNCParam("rfbauth",self.pw_file)
+
+ # password input combination.
+ pwinput = "%s\n%s\n" % (self.password, self.password)
+ vnccommand = [self.root+"/usr/bin/vncpasswd", self.pw_file]
+ vncpswdo = subprocess.Popen(vnccommand, stdin=subprocess.PIPE, stdout=subprocess.PIPE)# We pipe the output
+ # so the user does not see it.
+ (out, err) = vncpswdo.communicate(input=pwinput)
+ return vncpswdo.returncode
+
+ def initialize(self):
+ """Here is were all the relative vars get initialized. """
+
+ # see if we can sniff out network info
+ netinfo = network.Network()
+
+ devices = netinfo.netdevices
+ active_devs = network.getActiveNetDevs()
+
+ if active_devs != []:
+ dev = devices[active_devs[0]]
+
+ try:
+ self.ip = isys.getIPAddress(dev.get("DEVICE"))
+ log.info("ip of %s is %s" % (dev.get("DEVICE"), self.ip))
+
+ if self.ip == "127.0.0.1" or self.ip == "::1":
+ self.ip = None
+ except Exception, e:
+ log.warning("Got an exception trying to get the self.ip addr "
+ "of %s: %s" % (dev.get("DEVICE"), e))
+ else:
+ self.ip = None
+
+ self.name = network.getDefaultHostname(self.anaconda)
+ ipstr = self.ip
+
+ if self.ip.find(':') != -1:
+ ipstr = "[%s]" % (self.ip,)
+
+ if (self.name is not None) and (not self.name.startswith('localhost')) and (ipstr is not None):
+ self.connxinfo = "%s:%s (%s)" % (socket.getfqdn(name=self.name), self.display, ipstr,)
+ elif ipstr is not None:
+ self.connxinfo = "%s:%s" % (ipstr, self.display,)
+ else:
+ self.connxinfo = None
+
+ # figure out product info
+ if self.name is not None:
+ self.desktop = _("%(productName)s %(productVersion)s installation "
+ "on host %(name)s") \
+ % {'productName': product.productName,
+ 'productVersion': product.productVersion,
+ 'name': self.name}
+ else:
+ self.desktop = _("%(productName)s %(productVersion)s installation")\
+ % {'productName': product.productName,
+ 'productVersion': product.productVersion}
+
+ def setVNCParam(self, param, value):
+ """Set a parameter in the Xvnc server.
+
+ Possible values for param and value. param=(values)
+ SecurityTypes=(VncAuth,None)
+ """
+ vncconfigcommand = [self.root+"/usr/bin/vncconfig", "-display", ":%s"%self.display , "-set" , "%s=%s" %(param, value)]
+ vncconfo = subprocess.Popen(vncconfigcommand)# we dont want output
+ return vncconfo.returncode
+
+ def openlogfile(self):
+ try:
+ err = os.open(self.log_file, os.O_RDWR | os.O_CREAT)
+ if err < 0:
+ sys.stderr.write("error opening %s\n", log)
+ return None
+ else:
+ return err
+ except:
+ return None
+
+ def connectToView(self):
+ """Attempt to connect to self.vncconnecthost"""
+
+ maxTries = 10
+ self.log.info(_("Attempting to connect to vnc client on host %s...") % (self.vncconnecthost,))
+
+ if self.vncconnectport != "":
+ hostarg = self.vncconnecthost + ":" + self.vncconnectport
+ else:
+ hostarg = self.vncconnecthost
+
+ vncconfigcommand = [self.root+"/usr/bin/vncconfig", "-display", ":%s"%self.display, "-connect", hostarg]
+
+ for i in range(maxTries):
+ vncconfp = subprocess.Popen(vncconfigcommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # vncconfig process
+ (out, err) = vncconfp.communicate()
+
+ if err == '':
+ self.log.info(_("Connected!"))
+ return True
+ elif err.startswith("connecting") and err.endswith("failed\n"):
+ self.log.info(_("Will try to connect again in 15 seconds..."))
+ time.sleep(15)
+ continue
+ else:
+ log.critical(err)
+ sys.exit(1)
+ self.log.error(P_("Giving up attempting to connect after %d try!\n",
+ "Giving up attempting to connect after %d tries!\n",
+ maxTries) % (maxTries,))
+ return False
+
+ def VNCListen(self):
+ """Put the server in listening mode.
+
+ We dont really have to do anything for the server to listen :)
+ """
+ if self.connxinfo != None:
+ self.log.info(_("Please manually connect your vnc client to %s to begin the install.") % (self.connxinfo,))
+ else:
+ self.log.info(_("Please manually connect your vnc client to begin the install."))
+
+ def startServer(self):
+ self.log.info(_("Starting VNC..."))
+
+ # Lets call it from here for now.
+ self.initialize()
+
+ # Lets start the xvnc regardless of vncconnecthost and password.
+ # We can change the configuration on the fly later.
+ xvnccommand = [ self.root + "/usr/bin/Xvnc", ":%s" % self.display, "-nevershared",
+ "-depth", "16", "-geometry", "800x600", "-br",
+ "IdleTimeout=0", "-auth", "/dev/null", "-once",
+ "DisconnectClients=false", "desktop=%s" % (self.desktop,),
+ "SecurityTypes=None"]
+ try:
+ xvncp = subprocess.Popen(xvnccommand, stdout=self.openlogfile(), stderr=subprocess.STDOUT)
+ except:
+ stdoutLog.critical("Could not start the VNC server. Aborting.")
+ sys.exit(1)
+
+ # Lets give the xvnc time to initialize
+ time.sleep(1)
+
+ # Make sure it hasn't blown up
+ if xvncp.poll() != None:
+ sys.exit(1)
+ else:
+ self.log.info(_("The VNC server is now running."))
+
+ # Lets look at the password stuff
+ if self.password == "":
+ pass
+ elif len(self.password) < 6:
+ self.changeVNCPasswdWindow()
+
+ # Create the password file.
+ self.setVNCPassword()
+
+ # Lets tell the user what we are going to do.
+ if self.vncconnecthost != "":
+ self.log.warning(_("\n\nYou chose to connect to a listening vncviewer. \n"
+ "This does not require a password to be set. If you \n"
+ "set a password, it will be used in case the connection \n"
+ "to the vncviewer is unsuccessful\n\n"))
+ elif self.password == "":
+ self.log.warning(_("\n\nWARNING!!! VNC server running with NO PASSWORD!\n"
+ "You can use the vncpassword=<password> boot option\n"
+ "if you would like to secure the server.\n\n"))
+ elif self.password != "":
+ self.log.warning(_("\n\nYou chose to execute vnc with a password. \n\n"))
+ else:
+ self.log.warning(_("\n\nUnknown Error. Aborting. \n\n"))
+ sys.exit(1)
+
+ # Lets try to configure the vnc server to whatever the user specified
+ if self.vncconnecthost != "":
+ connected = self.connectToView()
+ if not connected:
+ self.VNCListen()
+ else:
+ self.VNCListen()
+
+ os.environ["DISPLAY"]=":%s" % self.display
+
+ def changeVNCPasswdWindow(self):
+ """ Change the password to a sane parameter.
+
+ We ask user to input a password that len(password) > 6
+ or password == ''. Have to find a way to put askVncWindow
+ and this method together.
+ """
+
+ screen = SnackScreen()
+ grid = GridFormHelp(screen, _("VNC Configuration"),"vnc", 1, 10)
+
+ bb = ButtonBar(screen, (TEXT_OK_BUTTON,
+ (_("No password"), "nopass")))
+
+ text = _("A password will prevent unauthorized listeners "
+ "connecting and monitoring your installation progress. "
+ "Please enter a password to be used for the installation")
+ grid.add(TextboxReflowed(40, text), 0, 0, (0, 0, 0, 1))
+
+ entry1 = Entry (16, password = 1)
+ entry2 = Entry (16, password = 1)
+ passgrid = Grid (2, 2)
+ passgrid.setField (Label (_("Password:")), 0, 0, (0, 0, 1, 0), anchorLeft = 1)
+ passgrid.setField (Label (_("Password (confirm):")), 0, 1, (0, 0, 1, 0), anchorLeft = 1)
+ passgrid.setField (entry1, 1, 0)
+ passgrid.setField (entry2, 1, 1)
+ grid.add (passgrid, 0, 1, (0, 0, 0, 1))
+
+ grid.add(bb, 0, 8, (0, 1, 1, 0), growx = 1)
+
+ while 1:
+ res = grid.run()
+ rc = bb.buttonPressed(res)
+
+ if rc == "nopass":
+ screen.finish()
+ return ""
+ else:
+ pw = entry1.value()
+ cf = entry2.value()
+ if pw != cf:
+ ButtonChoiceWindow(screen, _("Password Mismatch"),
+ _("The passwords you entered were "
+ "different. Please try again."),
+ buttons = [ TEXT_OK_BUTTON ],
+ width = 50)
+ elif len(pw) < 6:
+ ButtonChoiceWindow(screen, _("Password Length"),
+ _("The password must be at least "
+ "six characters long."),
+ buttons = [ TEXT_OK_BUTTON ],
+ width = 50)
+ else:
+ screen.finish()
+ self.password = pw
+ return
+
+ entry1.set("")
+ entry2.set("")
+ continue
+ continue
+
+def askVncWindow(title = None, message = None):
+ if not os.access('/usr/bin/Xvnc', os.X_OK):
+ return -1
+
+ if not network.hasActiveNetDev():
+ return -1
+
+ if not title:
+ title = _("Unable to Start X")
+ if not message:
+ message = _("X was unable to start on your "
+ "machine. Would you like to "
+ "start VNC to connect to "
+ "this computer from another "
+ "computer and perform a "
+ "graphical install or continue "
+ "with a text mode install?")
+
+ screen = SnackScreen()
+ vncpass = None
+ vncconnect = 0
+
+ STEP_MESSAGE = 0
+ STEP_PASS = 1
+ STEP_DONE = 3
+ step = 0
+ while step < STEP_DONE:
+ if step == STEP_MESSAGE:
+ button = ButtonChoiceWindow(screen, title, message,
+ buttons = [ _("Start VNC"),
+ _("Use text mode") ])
+
+ if button == string.lower (_("Use text mode")):
+ screen.finish()
+ return -1
+ else:
+ step = STEP_PASS
+ continue
+
+ if step == STEP_PASS:
+ grid = GridFormHelp(screen, _("VNC Configuration"),
+ "vnc", 1, 10)
+
+ bb = ButtonBar(screen, (TEXT_OK_BUTTON,
+ (_("No password"), "nopass"),
+ TEXT_BACK_BUTTON))
+
+ text = _("A password will prevent unauthorized listeners "
+ "connecting and monitoring your installation progress. "
+ "Please enter a password to be used for the installation")
+ grid.add(TextboxReflowed(40, text), 0, 0, (0, 0, 0, 1))
+
+ entry1 = Entry (16, password = 1)
+ entry2 = Entry (16, password = 1)
+ passgrid = Grid (2, 2)
+ passgrid.setField (Label (_("Password:")), 0, 0, (0, 0, 1, 0), anchorLeft = 1)
+ passgrid.setField (Label (_("Password (confirm):")), 0, 1, (0, 0, 1, 0), anchorLeft = 1)
+ passgrid.setField (entry1, 1, 0)
+ passgrid.setField (entry2, 1, 1)
+ grid.add (passgrid, 0, 1, (0, 0, 0, 1))
+
+ grid.add(bb, 0, 8, (0, 1, 1, 0), growx = 1)
+
+ while 1:
+ res = grid.run()
+ rc = bb.buttonPressed(res)
+
+ if rc == TEXT_BACK_CHECK:
+ screen.popWindow()
+ step = STEP_MESSAGE
+ break
+ elif rc == "nopass":
+ screen.finish()
+ return None
+ else:
+ pw = entry1.value()
+ cf = entry2.value()
+ if pw != cf:
+ ButtonChoiceWindow(screen, _("Password Mismatch"),
+ _("The passwords you entered were "
+ "different. Please try again."),
+ buttons = [ TEXT_OK_BUTTON ],
+ width = 50)
+ elif len(pw) < 6:
+ ButtonChoiceWindow(screen, _("Password Length"),
+ _("The password must be at least "
+ "six characters long."),
+ buttons = [ TEXT_OK_BUTTON ],
+ width = 50)
+ else:
+ screen.finish()
+ return pw
+
+ entry1.set("")
+ entry2.set("")
+ continue
+ continue
+
+ screen.finish()
+ return -1
+
+if __name__ == "__main__":
+ askVncWindow()