#!/usr/bin/python from snack import * import sys, getopt, string, socket, os, stat, tempfile def Usage(): print "tftptool 1.1 (C) 1999, 2000 Red Hat, Inc." print "Usage:" print " %s [ -e MACADDR ] [ -h HOSTNAME ] [ -t TYPE ] [ -i IMAGENAME ]" % sys.argv[0] print "where:" print "MACADDR is ethernet MAC address of the client in format" print " XX:XX:XX:XX:XX:XX where X is a hex digit. MAC" print " usually starts with 08:00:20: for Sun computers" print "HOSTNAME is either IP number of hostname of the client" print "TYPE is one of SUN4, SUN4C, SUN4D, SUN4M, SUN4U" print "IMAGENAME is a filename (without path) of the image which" print " should be served to the client. By default this" print " is either tftp32.img or tftp64.img" sys.exit(1) def CheckMac(mac): if len(mac) != 17: return 0 for i in [ 0, 3, 6, 9, 12 ]: if mac[i] in string.hexdigits and mac[i+1] in string.hexdigits and mac[i+2] == ':': continue return 0 if not mac[i] in string.hexdigits or not mac[i+1] in string.hexdigits: return 0 if mac[:9] == '08:00:20:': return 2 return 1 (options, args) = getopt.getopt(sys.argv[1:], "e:h:t:i:", ["eth=", "host=", "type=", "image="]) if args: Usage() mac = None host = None type = None imgname = None for (option, value) in options: if option == '-e' or option == '--eth': if not CheckMac(value): Usage() mac = value elif option == '-h' or option == '--host': host = value elif option == '-i' or option == '--image': imgname = value elif option == '-t' or option == '--type': type = string.lower(value) if type[:4] != 'sun4': Usage() type = type[4:] if len(type) > 1 or len(type) and not (type[0] in 'cdmu'): Usage() screen = SnackScreen() def checkCancel(ret): if ret == 'cancel': screen.finish() sys.exit(0) screen.drawRootText (0, 0, "Red Hat TFTP tool for Sparc network boots (C) 1999 Red Hat, Inc.") screen.pushHelpLine (" / between elements | selects | next screen") done = 0 if host and host != "": try: ip = socket.gethostbyname(host) except: pass else: if mac and CheckMac(mac): done = 1 while not done: if not host: host = "" if not mac: mac = "08:00:20:" hoste = Entry(30, host) mace = Entry(30, mac) x = EntryWindow(screen, "Client machine", "Please enter the hostname and Ethernet MAC address " "of the SPARC client machine to be booted from this server.\n" "Enter either a hostname or IP number.\n" "Ethernet MAC address should be 6 pairs of hexadecimal digits " "separated by `:'. Sun MAC addresses usually start with " "08:00:20:", [ ("Hostname", hoste), ("MAC address", mace) ]) checkCancel(x[0]) host = x[1][0] mac = x[1][1] try: ip = socket.gethostbyname(host) except: x = ButtonChoiceWindow(screen, "Could not resolve hostname", "Hostname `%s' could not be resolved.\n" "Either enter IP number if the host is not in DNS," "or check if the name is correct.\n" "Would you like to try again?" % host) checkCancel(x) continue if not CheckMac(mac): x = ButtonChoiceWindow(screen, "Invalid MAC", "MAC address `%s' is invalid.\n" "Would you like to try again?" % mac) checkCancel(x) continue done = 1 if not type: x = ListboxChoiceWindow(screen, "Type of client machine", "Please select the model or architecture " "of the client machine", [ ( "sun4 architecture", "sun4" ), ( "sun4c architecture", "sun4c" ), ( "sun4m architecture", "sun4m" ), ( "sun4d architecture", "sun4d" ), ( "sun4u architecture", "sun4u" ), ( "4/260", "sun4" ), ( "4/110", "sun4" ), ( "4/280", "sun4" ), ( "4/150", "sun4" ), ( "SPARCstation 1", "sun4c" ), ( "SPARCserver 1", "sun4c" ), ( "SPARCstation 330", "sun4" ), ( "SPARCserver 330", "sun4" ), ( "4/310", "sun4" ), ( "4/350", "sun4" ), ( "4/360", "sun4" ), ( "SPARCstation 370", "sun4" ), ( "SPARCserver 370", "sun4" ), ( "4/380", "sun4c" ), ( "SPARCserver 390", "sun4" ), ( "SPARCstation 470", "sun4" ), ( "SPARCserver 470", "sun4" ), ( "SPARCserver 490", "sun4" ), ( "SPARCstation SLC", "sun4c" ), ( "SPARCstation IPC", "sun4c" ), ( "SPARCstation 1+", "sun4c" ), ( "SPARCserver 1+", "sun4c" ), ( "SPARCstation SLC", "sun4c" ), ( "SPARCstation 2", "sun4c" ), ( "SPARCserver 2", "sun4c" ), ( "SPARCstation ELC", "sun4c" ), ( "SPARCstation IPX", "sun4c" ), ( "SPARCengine 1", "sun4c" ), ( "SPARCserver 630MP", "sun4m" ), ( "SPARCserver 670MP", "sun4m" ), ( "SPARCserver 690MP", "sun4m" ), ( "SPARCclassic", "sun4m" ), ( "SPARCclassic Server", "sun4m" ), ( "SPARCstation LC", "sun4m" ), ( "SPARCclassic X", "sun4m" ), ( "SPARCstation LX/ZX", "sun4m" ), ( "SPARCstation Voyager", "sun4m" ), ( "SPARCstation 4", "sun4m" ), ( "SPARCstation 5", "sun4m" ), ( "SPARCstation 10", "sun4m" ), ( "SPARCserver 10", "sun4m" ), ( "SPARCcenter 2000", "sun4d" ), ( "SPARCserver 1000", "sun4d" ), ( "SPARCserver 20", "sun4m" ), ( "SPARCserver 1000e", "sun4d" ), ( "Ultra 1", "sun4u" ), ( "Ultra 2", "sun4u" ), ( "Ultra 5", "sun4u" ), ( "Ultra 10", "sun4u" ), ( "Ultra 30", "sun4u" ), ( "Ultra 60", "sun4u" ), ( "Ultra 80", "sun4u" ), ( "Ultra AX", "sun4u" ), ( "Ultra AXi", "sun4u" ), ( "Sun Enterprise 2", "sun4u" ), ( "Sun Enterprise Ultra 5S", "sun4u" ), ( "Sun Enterprise Ultra 10S", "sun4u" ), ( "Sun Enterprise 250", "sun4u" ), ( "Sun Enterprise 450", "sun4u" ), ( "Sun Enterprise 3000", "sun4u" ), ( "Sun Enterprise 4000", "sun4u" ), ( "Sun Enterprise 5000", "sun4u" ), ( "Sun Enterprise 6000", "sun4u" ), ( "Sun Enterprise 3500", "sun4u" ), ( "Sun Enterprise 4500", "sun4u" ), ( "Sun Enterprise 5500", "sun4u" ), ( "Sun Enterprise 6500", "sun4u" ), ( "Sun Enterprise 10000", "sun4u" )], scroll = 1, height = screen.height - 18) checkCancel(x[0]) type = x[1] ips = string.split(ip, '.') iphex = "%02X%02X%02X%02X" % (string.atoi(ips[0]), string.atoi(ips[1]), string.atoi(ips[2]), string.atoi(ips[3])) if type != 'sun4u': iphex = iphex + "." + string.upper(type) maketftpboot = 0 copyfile = 0 enabletftp = 0 if type == 'sun4u': archsize = 64 else: archsize = 32 if not imgname: imgname = "tftp%d.img" % archsize try: st = os.stat("/tftpboot") except os.error: maketftpboot = 1 else: if not stat.S_ISDIR(st[stat.ST_MODE]): maketftpboot = 1 if maketftpboot: copyfile = 1 else: try: st = os.stat("/tftpboot/%s" % imgname) except: copyfile = 1 f = open ("/etc/inetd.conf", "r") lines = f.readlines() f.close() for line in lines: words = string.split(line) if words[0] == "#tftp": enabletftp = 1 break elif words[0] == "tftp": break image = None if copyfile: # First check if we're run from a known tree # where we can look for the image without # user intervention. try: cddir = os.path.dirname(sys.argv[0]) st = os.stat(cddir + "/../RedHat") f = open(cddir + "/../images/%s" % imgname, "r") image = f.read() f.close() except: image = None while not image: x = ButtonChoiceWindow(screen, "%s required" % imgname, "The %s image is needed to boot the client machine.\n" "You can install it from your Red Hat Linux/SPARC CD-ROM, " "from another location on the filesytem, or cancel." % imgname, buttons = [ "CD", "Filesystem", "Cancel" ]) checkCancel(x) if x == 'cd': ButtonChoiceWindow(screen, "Insert CD-ROM", "Please insert your Red Hat Linux/SPARC CD-ROM.", [ "Ok" ]) for i in range(10): dir = tempfile.mktemp("tftp-cdmnt") try: os.mkdir (dir, 0755) except: dir = None continue else: break if dir: childpid = os.fork() if not childpid: fd = os.open("/dev/null", os.O_RDWR) os.dup2(fd, 1) os.dup2(fd, 2) os.close(fd) os.execv("/bin/mount", [ "mount", "-t", "iso9660", "/dev/cdrom", dir ]) (pid, status) = os.waitpid(childpid, 0) if status: try: os.rmdir (dir) except: pass dir = None if not dir: ButtonChoiceWindow(screen, "Error", "Could not mount the CD-ROM", [ "Ok" ]) else: try: f = open(dir + "/images/%s" % imgname, "r") image = f.read() f.close() except: ButtonChoiceWindow(screen, "Error", "Could not find /images/%s on the CD-ROM. " "Make sure you inserted a correct media.", [ "Ok" ]) os.system("/bin/umount %s" % dir) os.rmdir(dir) else: x = EntryWindow(screen, "Enter path to %s" % imgname, "Please enter the path where %s can be found." % imgname, [ "Path" ], buttons = [ "Ok" ], entryWidth = 35) dir = x[1][0] try: f = open(dir + "/%s" % imgname, "r") image = f.read() f.close() except: ButtonChoiceWindow(screen, "Error", "Could not find or read %s/%s." % (dir, imgname), [ "Ok" ]) maketftpboota = "" if maketftpboot: maketftpboota = "Create /tftpboot directory\n" copyfilea = "" if copyfile: copyfilea = "Create /tftpboot/%s image\n" % imgname enabletftpa = "" if enabletftp: enabletftpa = "Enable tftp service in /etc/inetd.conf and restart inetd\n" x = ButtonChoiceWindow(screen, "About to setup tftp booting", "Would you like to:\n" "%s%s%sCreate symlink /tftpboot/%s -> %s\n" "Update rarp and permanent arp tables for the client." % (maketftpboota, copyfilea, enabletftpa, iphex, imgname)) checkCancel(x) if maketftpboot: try: os.mkdir("/tftpboot") except: ButtonChoiceWindow(screen, "Error", "Could not create /tftpboot directory", [ "Ok" ]) screen.finish() sys.exit(1) if copyfile: try: f = open("/tftpboot/%s" % imgname, "w") f.write(image) f.close() except: ButtonChoiceWindow(screen, "Error", "Could not create or write /tftpboot/%s file" % imgname, [ "Ok" ]) screen.finish() sys.exit(1) if enabletftp: try: f = open("/etc/inetd.conf", "r") g = open("/etc/inetd.conf-", "w") lines = f.readlines() f.close() for line in lines: words = line.split() if words[0] == "#tftp" and words[6] == "in.tftpd": ind = string.find(line, "#tftp") + 1 line = line[ind:] g.write(line) g.close() except: ButtonChoiceWindow(screen, "Error", "Could not update /etc/inetd.conf", [ "Ok" ]) screen.finish() sys.exit(1) else: os.system("/usr/bin/killall -1 inetd") try: os.remove("/tftpboot/" + iphex) except: pass try: os.symlink(imgname, "/tftpboot/" + iphex) except: ButtonChoiceWindow(screen, "Error", "Could not create symlink /tftpboot/%s -> %s" % (iphex, imgname), [ "Ok" ]) screen.finish() sys.exit(1) if os.system("/sbin/rarp -s %s %s" % (ip, mac)) or os.system("/sbin/arp -s %s %s" % (ip, mac)): ButtonChoiceWindow(screen, "Error", "Could not update rarp and arp tables for %s %s" % (ip, mac), [ "Ok" ]) screen.finish() sys.exit(1) ButtonChoiceWindow(screen, "Success", "You can now boot your client SPARC machine from this server.\n" "Type either `boot net' or `b le()' on the PROM command line " "depending on your PROM version.", [ "Ok" ]) screen.finish() sys.exit(0)