#!/usr/bin/python # -*- coding: UTF-8 -*- # TcosConfigurator version __VERSION__ # # Copyright (c) 2006-2011 Mario Izquierdo # # This package 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 package 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import sys import os import glob # for get_ip_address import socket import fcntl import struct import netifaces ##################### import pygtk pygtk.require('2.0') from gtk import * import gtk.glade import time import getopt from gettext import gettext as _ from gettext import bindtextdomain, textdomain from locale import setlocale, LC_ALL from subprocess import Popen, PIPE, STDOUT from threading import Thread import netifaces import pwd import gobject #import threading gtk.gdk.threads_init() gobject.threads_init() ######################################################## # # Extends python-configobj this class use '=' instead of ' = ' # ######################################################## from configobj import ConfigObj class MyConfigObj (ConfigObj): def _write_line(self, indent_string, entry, this_entry, comment): """Write an individual line, for the write method""" # NOTE: the calls to self._quote here handles non-StringType values. if not self.unrepr: val = self._decode_element(self._quote(this_entry)) else: val = repr(this_entry) return '%s%s%s%s%s' % ( indent_string, self._decode_element(self._quote(entry, multiline=False)), self._a_to_u('='), val, self._decode_element(comment)) ############################################################# debug=False SIMULATE=False PACKAGE="tcos-configurator" # if exec from svn or sources dir if os.path.isfile('./setup.py'): LOCALE_DIR = "./po/" UI_DIR = "./" IMG_DIR = "./images/" print "exec in sources dir" else: UI_DIR = "/usr/share/tcos-configurator/" IMG_DIR = "/usr/share/tcos-configurator/images/" LOCALE_DIR = "/usr/share/locale/" def print_debug(txt): if debug: print >> sys.stderr, "%s::%s" %("tcos-configurator", txt) return def usage(): print "tcos-configurator help:" print "" print " tcos-configurator -d [--debug] (write debug data to stdout)" print " tcos-configurator -s [--simulate] (dry-run)" print " tcos-configurator -h [--help] (this help)" try: opts, args = getopt.getopt(sys.argv[1:], ":hds", ["help", "debug", "simulate"]) except getopt.error, msg: print msg print "for command line options use tcosconfig --help" sys.exit(2) # process options for o, a in opts: if o in ("-d", "--debug"): print "DEBUG ACTIVE" debug = True if o in ("-s", "--simulate"): print "SIMULATE" SIMULATE = True if o in ("-h", "--help"): usage() sys.exit() ################################################################################ DHCP_CONF=[ ['# dhcpd.conf',"# generated by __PROGRAM__ on date __DATE__"] , ['ddns-update-style ad-hoc;', 'option subnet-mask __MASK__;', '#option domain-name "tcos-domain.org";', '# set authorative to be first providing DHCP lease', 'authorative;', 'option option-128 code 128 = string;', 'option option-129 code 129 = text;', 'get-lease-hostnames true;', ], ['shared-network TCOS {', "\t\tsubnet __NET__ netmask __MASK__ {", "\t\toption domain-name-servers __DNS__;", "\t\toption broadcast-address __BROADCAST__;", "\t\toption routers __ROUTERS__;", "\t\tnext-server __SERVERIP__;", "\t\trange dynamic-bootp __STARTIP__ __ENDIP__;", "\t\tfilename \"__BOOTMODE__\";", "\t}", "}" ], ] TFTPBOOT="/var/lib/tftpboot" if os.path.isdir("/var/lib/max-netboot"): TFTPBOOT="/var/lib/max-netboot" DNSMASQ_CONF=[ ['# dnsmasq.conf for TCOS', '# file generated by __PROGRAM__ on date __DATE__\n'], ['## put your ISP DNS server in this file', 'resolv-file=/etc/resolv.conf.real\n'], ['listen-address=__SERVERIP__,127.0.0.1\n', 'dhcp-range=__STARTIP__,__ENDIP__,12h\n', 'dhcp-option=option:router,__ROUTERS__', 'dhcp-option=option:tftp-server,__SERVERIP__', 'dhcp-boot=__BOOTMODE__,__SERVERIP__,__SERVERIP__\n\n', '# option 49 x-display-manager', 'dhcp-option-force=49,__SERVERIP__', '# option 48 font-servers', 'dhcp-option-force=48,__SERVERIP__', '# option 16 swap-server', 'dhcp-option-force=16,__SERVERIP__\n\n', ], ['enable-tftp', 'tftp-root=%s'%TFTPBOOT, ], ['dhcp-authoritative\n\n', '## uncomment this for DHCP debug', '#log-dhcp', '## uncomment this for DNS querys debug', '#log-queries\n\n', '## example reserved lease', '#dhcp-host=00:11:22:33:44:55,192.168.0.101'], ] # this settings could be more precise but work for # 15-20 thin clients without problems #Enable=true #MaxSessions=40 #MaxPending=60 #MaxPendingIndirect=30 #MaxWait=75 #MaxWaitIndirect=80 #PingIntervalSeconds=35 #DisplaysPerHost=4 GDM_CONFIG={ "xdmcp": {"Enable":"true", "MaxSessions":"30", "MaxSessions":"40", "MaxPending":"60", "MaxPendingIndirect":"30", "MaxWait":"75", "MaxWaitIndirect":"80", "PingIntervalSeconds":"35", "DisplaysPerHost":"4"}, "security": {"AllowRemoteAutoLogin":"true", "DisallowTCP":"false"}, "daemon": {"TimedLoginEnable":"__AUTOLOGIN__", "TimedLogin":"/usr/sbin/tcos-gdm-autologin|", "TimedLoginDelay":"__TIMEOUT__"}, } GDM_CONF_FILE="/etc/gdm/gdm.conf" # try to edit correct file (Ubuntu use -custom file) if os.path.isfile(GDM_CONF_FILE + "-custom"): GDM_CONF_FILE=GDM_CONF_FILE+"-custom" if os.path.isfile("/etc/gdm/gdm-cdd.conf"): GDM_CONF_FILE="/etc/gdm/gdm-cdd.conf" # in new Ubuntu create empty file and use it if os.path.isfile("/etc/gdm/gdm.schemas") and not os.path.isfile("/etc/gdm/custom.conf"): # create empty file f=open("/etc/gdm/custom.conf", 'w') f.write('\n') f.close() # new GDM in Ubuntu Karmic if os.path.isfile("/etc/gdm/custom.conf"): GDM_CONF_FILE="/etc/gdm/custom.conf" # in Debian unstable GDM is installed in /etc/gdm3 create empty file and use it if os.path.isdir("/etc/gdm3") and not os.path.isfile("/etc/gdm3/daemon.conf"): # create empty file f=open("/etc/gdm3/daemon.conf", 'w') f.write('\n') f.close() # new GDM in Debian unstable if os.path.isfile("/etc/gdm3/daemon.conf"): GDM_CONF_FILE="/etc/gdm3/daemon.conf" KDM_CONFIG={ "Xdmcp":[ {"Enable":"true"} ] } KDM_CONF_FILE="/etc/kde4/kdm/kdmrc" KDM_ACCESS_FILE="/etc/kde4/kdm/Xaccess" KDM_ACCESS_LINE="#any host can get a login window" HIDDEN_INTERFACES=['lo', 'pan0', 'sit0'] DNSMASQ_FILE="/etc/dnsmasq.conf" NETWORK_INTERFACES="/etc/network/interfaces" RESOLV_CONF_REAL="/etc/resolv.conf.real" if SIMULATE: GDM_CONF_FILE="./" + os.path.basename(GDM_CONF_FILE) DNSMASQ_FILE="./dnsmasq.conf" NETWORK_INTERFACES="./interfaces" RESOLV_CONF_REAL="./resolv.conf.real" ################################################################################ class TcosStandalone: def __init__(self): print_debug("__init__()") # vars self.v={} self.begin_usernumber=1 gtk.glade.bindtextdomain(PACKAGE, LOCALE_DIR) gtk.glade.textdomain(PACKAGE) # gettext support setlocale( LC_ALL ) bindtextdomain( PACKAGE, LOCALE_DIR ) textdomain( PACKAGE ) if os.path.isdir('/usr/share/backharddi') or os.path.isdir('/usr/share/backharddi-ng'): self.BOOT_MODES=[ [_("TCOS and Backharddi"), "/pxelinux.0" ], [_("TCOS"), "/tcos/pxelinux.0" ], [_("Backharddi"), "/backharddi/pxelinux.0"], ] else: self.BOOT_MODES=[ [_("TCOS"), "/tcos/pxelinux.0" ] ] # Widgets self.ui = gtk.Builder() self.ui.set_translation_domain(PACKAGE) self.ui.add_from_file(UI_DIR + 'tcos-configurator.ui') self.mainwindow = self.ui.get_object('mainwindow') self.mainwindow.set_icon_from_file(IMG_DIR +'tcos-icon-32x32.png') # close windows signals self.mainwindow.connect('destroy', self.quitapp ) self.mainwindow.connect('delete_event', self.quitapp) self.button_quit=self.ui.get_object("btn_quit") self.button_quit.connect('clicked', self.quitapp) self.window_autologin_help=self.ui.get_object('window_autologin_help') self.window_autologin_help.set_icon_from_file(IMG_DIR +'tcos-icon-32x32.png') self.window_autologin_help.connect('destroy', self.hidehelp ) self.window_autologin_help.connect('delete_event', self.hidehelp) # widgets self.w={} for widget in ['img_logo', 'combo_interfaces', 'txt_serverip', 'txt_startip', 'txt_endip', 'btn_configure_dhcp', 'combo_boot_mode', 'hbox_dynamic', 'ck_static', 'btn_hostname_help', 'txt_hostname_prefix', 'lbl_dhcp', 'label_boot_mode']: self.w[widget]=self.ui.get_object(widget) self.w['lbl_dhcp'].set_text("") self.w['img_logo'].set_from_file(IMG_DIR + 'tcos-logo.png') self.w['combo_interfaces'].connect('changed', self.combo_interface_change ) self.w['btn_configure_dhcp'].connect('clicked', self.on_btn_configure_dhcp) self.w['txt_serverip'].connect('focus-out-event', self.on_serverip_blur ) self.w['btn_hostname_help'].connect('clicked', self.on_btn_autologin_help) self.populate_select(self.w['combo_boot_mode'], self.BOOT_MODES) self.set_active_in_select(self.w['combo_boot_mode'], self.BOOT_MODES[0][0]) if len(self.BOOT_MODES) < 2: self.w['combo_boot_mode'].hide() self.w['label_boot_mode'].hide() self.interfaces=self.getNetInterfaces() self.configured_interfaces=self.read_etc_network_interfaces() print_debug("self.configured_interfaces=%s len=%s"%(self.configured_interfaces, len(self.configured_interfaces))) self.populate_select(self.w['combo_interfaces'], self.interfaces ) if len(self.interfaces) == 1: self.set_active_in_select(self.w['combo_interfaces'], self.interfaces[0][0]) for widget in ['txt_serverip', 'txt_startip', 'txt_endip', 'combo_boot_mode']: self.w[widget].connect('changed', self.set_dhcp_modified) if len(self.configured_interfaces) < 2: self.w['hbox_dynamic'].show() self.dhcp_modified=False print_debug("configured_interfaces %s"%self.configured_interfaces) print_debug("detected_interfaces %s"%self.interfaces) # users for widget in ['scale_number_users', 'txt_prefix', 'txt_groups', 'lbl_users', 'btn_commit_users']: self.w[widget]=self.ui.get_object(widget) self.w['txt_prefix'].connect('changed', self.on_scale_number_users) self.w['scale_number_users'].connect('value_changed', self.on_scale_number_users) self.on_scale_number_users(self.w['scale_number_users']) self.w['btn_commit_users'].set_sensitive(False) self.w['btn_commit_users'].connect('clicked', self.on_btn_commit_users) # remote login for widget in ['ck_remotelogin', 'ck_autologin', 'scale_autologin', 'btn_commit_login', 'btn_autologin_help', 'lbl_login', 'btn_launch_tcosconfig']: self.w[widget]=self.ui.get_object(widget) # read GDM_CONF_FILE config=MyConfigObj( GDM_CONF_FILE ) try: if config['xdmcp']['Enable'] == 'true': self.w['ck_remotelogin'].set_active(True) except: pass try: if config['daemon']['TimedLogin'] == '/usr/sbin/tcos-gdm-autologin|': self.w['ck_autologin'].set_active(True) except: pass try: if config['daemon']['TimedLoginDelay'] != '10': self.w['scale_autologin'].set_value( int(config['daemon']['TimedLoginDelay']) ) except: pass self.w['ck_remotelogin'].connect('toggled', self.on_ck_remotelogin) self.w['ck_autologin'].connect('toggled', self.on_ck_remotelogin) self.w['scale_autologin'].connect('value_changed', self.on_ck_remotelogin) self.w['btn_commit_login'].connect('clicked', self.on_btn_commit_login) self.w['btn_autologin_help'].connect('clicked', self.on_btn_autologin_help) self.w['btn_launch_tcosconfig'].connect('clicked', self.on_btn_launch_tcosconfig) def read_mayor_generated_users(self, prefix): if prefix == '': return tmpusers=[] maxu=0 # read generated users for user in pwd.getpwall(): if user[0].startswith(prefix): u=user[0].replace(prefix,'') try: i=int(u) if i> maxu: maxu=i except: pass self.begin_usernumber=maxu+1 print_debug("read_mayor_generated_users() begin=%s"%self.begin_usernumber) return "%02d"%maxu def on_serverip_blur(self, widget, event): value=widget.get_text() if value == "": return self.w['txt_startip'].set_text(".".join(value.split('.')[0:3]) + ".101") self.w['txt_endip'].set_text( ".".join(value.split('.')[0:3]) + ".131") self.w['lbl_dhcp'].set_text("") def get_ip_from_iface(self, seliface): print_debug("get_ip_from_iface(%s) self.configured_interfaces=%s"%(seliface, self.configured_interfaces)) if not self.configured_interfaces.has_key(seliface): return None if not self.configured_interfaces[seliface].has_key('address'): return None return self.configured_interfaces[seliface]['address'] def combo_interface_change(self, widget): configured=False seliface=self.read_select_value(widget) for iface in self.interfaces: if iface[0] != seliface: #print_debug("combo_interface_change(%s) iface(%s) != seliface and iface != None"%(seliface, iface[0])) continue iface_ip=self.get_ip_from_iface(iface[0]) print_debug("combo_interface_change(%s) static iface=%s seliface=%s iface_ip=%s"%(seliface, iface, seliface, iface_ip)) print_debug("combo_interface_change(%s) self.interfaces=%s"%(seliface, self.interfaces)) print_debug("combo_interface_change() iface[1]=%s iface_ip=%s"%(iface[1], iface_ip)) if iface_ip: self.w['lbl_dhcp'].hide() self.w['hbox_dynamic'].hide() self.w['ck_static'].set_active(False) print_debug("combo_interface_change(%s) iface=%s HAVE IP"%(seliface, iface) ) else: self.w['hbox_dynamic'].show() self.w['ck_static'].set_active(True) self.w['lbl_dhcp'].set_markup( _("WARNING:\nNetwork interface don't have IP") ) self.w['lbl_dhcp'].show() self.w['txt_serverip'].set_text('') self.w['txt_startip'].set_text('') self.w['txt_endip'].set_text('') print_debug("combo_interface_change(%s) iface=%s DON'T HAVE IP" %(seliface, iface) ) if iface[1]: self.w['txt_startip'].set_text(".".join(iface[1].split('.')[0:3]) + ".101") self.w['txt_endip'].set_text( ".".join(iface[1].split('.')[0:3]) + ".131") self.w['txt_serverip'].set_text(iface[1]) self.set_dhcp_modified() def set_dhcp_modified(self, *args): self.dhcp_modified=True self.w['btn_configure_dhcp'].set_sensitive(True) def on_btn_configure_dhcp(self, *args): if os.path.isfile('/usr/sbin/dnsmasq'): if not self.ask_msg( _("Your %s file will be overwritten.\n\nContinue?") %"/etc/dnsmasq.conf" ): return th=Thread(target=self.configureDNSMASQ) th.start() else: if not self.ask_msg( _("Your %s file will be overwritten.\n\nContinue?") %"/etc/dhcp3/dhcpd.conf" ): return th=Thread(target=self.configureDHCP) th.start() def hidehelp(self, *args): self.window_autologin_help.hide() return True def on_btn_autologin_help(self, widget): self.window_autologin_help.show() ############## login ####################################################### def on_ck_remotelogin(self, widget): if self.w['ck_remotelogin'].get_active(): self.w['ck_autologin'].set_sensitive(True) self.w['scale_autologin'].set_sensitive(True) else: self.w['ck_autologin'].set_sensitive(False) self.w['scale_autologin'].set_sensitive(False) self.w['btn_commit_login'].set_sensitive(True) def on_btn_commit_login(self, widget): if self.w['ck_remotelogin'].get_active(): self.enable_remotelogin() else: self.disable_remotelogin() self.w['btn_commit_login'].set_sensitive(False) def enable_remotelogin(self): if os.path.isfile(GDM_CONF_FILE): self.SetVar("xdmcp", "Enable", "true") for gdmvar in GDM_CONFIG['xdmcp']: self.SetVar('xdmcp', gdmvar, GDM_CONFIG['xdmcp'][gdmvar]) if os.path.exists("/usr/lib/gdm/gdmgreeter"): self.SetVar("daemon", "RemoteGreeter", "/usr/lib/gdm/gdmgreeter") self.SetVar("daemon", "TimedLogin", "/usr/sbin/tcos-gdm-autologin|") if self.w['ck_autologin'].get_active(): self.SetVar("daemon", "TimedLoginEnable", "true") self.SetVar("security", "AllowRemoteAutoLogin", "true") else: self.SetVar("daemon", "TimedLoginEnable", "false") self.SetVar("security", "AllowRemoteAutoLogin", "false") self.SetVar("daemon", "TimedLoginDelay", str( int(self.w['scale_autologin'].get_value()) ) ) if os.path.isfile(KDM_CONF_FILE): self.SetVar("Xdmcp", "Enable", "true", CONF=KDM_CONF_FILE) # configure Xaccess f=open(KDM_ACCESS_FILE, 'r') data=f.readlines() f.close() for i in range(len(data)): line=data[i] if KDM_ACCESS_LINE in line: data[i]=line.replace('#*', '*') f=open(KDM_ACCESS_FILE, 'w') for line in data: print_debug("enable_remotelogin() KDM_ACCESS_FILE: %s"%line.replace('\n','') ) f.write(line) f.close() # show message to reboot required self.w['lbl_login'].set_markup( _("Reboot required (or restart gdm/kdm daemon) to enable new GDM/KDM settings") ) self.w['lbl_login'].show() return def disable_remotelogin(self): if os.path.isfile(KDM_CONF_FILE): self.SetVar("Xdmcp", "Enable", "false", CONF=KDM_CONF_FILE) self.SetVar("xdmcp","Enable","false") def SetVar(self, section, key, value, do=True, CONF=GDM_CONF_FILE): if not do: print_debug("NOACTION: SetVar() gdm.conf=%s section=%s key=%s value=%s" %(CONF, section,key,value) ) return config=MyConfigObj( os.path.realpath(CONF) ) print_debug("setting conf=%s section=[%s] key=%s value=%s" %(CONF, section, key, value) ) if not config.has_key(section): config[section]={} config[section][key] = value try: config.write() return True except: print_debug("Error, can't write in %s" %(CONF)) return False ############## users ########################################################## def on_scale_number_users(self, widget): num=int(self.w['scale_number_users'].get_value()) prefix=self.w['txt_prefix'].get_text() if prefix=='': self.w['btn_commit_users'].set_sensitive(False) return self.read_mayor_generated_users(prefix) init=self.begin_usernumber end=self.begin_usernumber+num self.w['lbl_users'].set_text(_("Creating from %(prefix)s%(init)02d to %(prefix)s%(end)02d") %{"prefix":prefix, "init":init, "end":end} ) self.w['lbl_users'].show() self.w['btn_commit_users'].set_sensitive(True) def on_btn_commit_users(self, widget): th=Thread(target=self.createUsers) th.start() def userExists(self, username): try: pwd.getpwnam(username) return True except: return False def createUsers(self): number=int(self.w['scale_number_users'].get_value()) user_prefix=self.w['txt_prefix'].get_text() groups=self.w['txt_groups'].get_text() gtk.gdk.threads_enter() self.w['btn_commit_users'].set_sensitive(False) self.w['lbl_users'].set_text("") gtk.gdk.threads_leave() for i in range(self.begin_usernumber, self.begin_usernumber+number): # range starts in 1 i="%02d"%(i) username="%s%s"%(user_prefix, i) if not self.userExists(username): print_debug("Creating username %s"%username) gtk.gdk.threads_enter() self.w['lbl_users'].set_text( _("Creating user: '%s'") %username ) gtk.gdk.threads_leave() self.exe_cmd("useradd -m %s -p%s -s /bin/bash -d /home/%s" %(username, username, username)) self.exe_cmd("echo %s:%s | chpasswd" %(username, username)) self.exe_cmd("adduser %s fuse" %(username) ) else: print_debug("User already exists: %s"%username) gtk.gdk.threads_enter() self.w['lbl_users'].set_text( _("User already exists: '%s'") %username ) gtk.gdk.threads_leave() time.sleep(1) self.read_mayor_generated_users(user_prefix) gtk.gdk.threads_enter() self.w['lbl_users'].set_markup( _("Done") ) gtk.gdk.threads_leave() ######################network ########################################## def get_ip_address(self, ifname): print_debug("get_ip_address() ifname=%s" %(ifname) ) if not ifname in netifaces.interfaces(): return None ip=netifaces.ifaddresses(ifname) if ip.has_key(netifaces.AF_INET): print_debug("get_ip_address(%s)=%s"%(ifname, ip[netifaces.AF_INET][0])) return ip[netifaces.AF_INET][0]['addr'] return None def getNetInterfaces(self): interfaces=[] for dev in netifaces.interfaces(): if not dev in HIDDEN_INTERFACES and not dev.startswith("vbox") and not dev.startswith("vmnet") and not dev.startswith("wmaster"): ip=self.get_ip_address(dev) print_debug("getNetInterfaces() iface=%s data=%s"%(dev,ip)) interfaces.append( [dev, ip] ) return interfaces def read_etc_network_interfaces(self): interfaces={} curiface=None try: f=open(NETWORK_INTERFACES,'r') except: print_debug("Error, can't read " + NETWORK_INTERFACES) return interfaces data=f.readlines() f.close() for line in data: line=line.strip() if len(line) == 0: continue if line.startswith('#'): continue if line.startswith("iface"): curiface=line.split()[1] interfaces[curiface]={} if curiface and line.startswith('address'): interfaces[curiface]['address']=line.split()[1] if curiface and line.startswith('netmask'): interfaces[curiface]['netmask']=line.split()[1] if curiface and line.startswith('gateway'): interfaces[curiface]['gateway']=line.split()[1] if curiface and line.startswith('network'): interfaces[curiface]['network']=line.split()[1] if curiface and line.startswith('broadcast'): interfaces[curiface]['broadcast']=line.split()[1] if curiface and line.startswith('dns-nameservers'): interfaces[curiface]['dns-nameservers']=line.split()[1:] print_debug("read_etc_network_interfaces() %s"%interfaces) return interfaces def configure_static(self, data): print_debug("configure_static() data=%s"%data) newdata=[] curiface=None added=False try: f=open(NETWORK_INTERFACES,'r') except: print_debug("Error, can't read "+NETWORK_INTERFACES) return False ifile=f.readlines() f.close() for line in ifile: sline=line.strip() if sline.startswith('iface'): curiface=sline.split()[1] if not added and curiface and curiface == data['iface']: newdata.append("# added by tcos-configurator") newdata.append("auto %s" %curiface) newdata.append("iface %s inet static" %curiface) for opt in data: if opt == 'iface': continue #if opt == 'gateway': continue newdata.append("\t%s %s" %(opt, data[opt]) ) newdata.append("\n\n") added=True if added and curiface == data['iface']: continue if (sline.startswith('auto') or sline.startswith('allow') ) and sline.split()[1] == data['iface']: continue newdata.append(line.replace('\n','') ) if not added: newdata.append("\n#added by tcos-configurator") newdata.append("auto %s"%data['iface']) newdata.append("iface %s inet static"%data['iface']) newdata.append("\taddress %s"%data['address']) newdata.append("\tnetmask %s"%data['netmask']) if data['gateway'] and ".".join(data['gateway'].split('.')[0:3]) == ".".join(data['address'].split('.')[0:3]): # only save gateway if is in the same network newdata.append("\tgateway %s"%data['gateway']) newdata.append("\n\n") print_debug(newdata) try: f=open(NETWORK_INTERFACES, 'w') except: return False for line in newdata: f.write(line + "\n") f.close() return True ################### combo stuff ############################## def populate_select(self, widget, values): valuelist = gtk.ListStore(str) for value in values: valuelist.append([value[0]]) widget.set_model(valuelist) #widget.set_text_column(0) if widget.get_text_column() != 0: widget.set_text_column(0) model=widget.get_model() return def set_active_in_select(self, widget, default): model=widget.get_model() for i in range(len(model)): if model[i][0] == default: print_debug ("set_active_in_select() default is '%s', index %d" %( model[i][0] , i ) ) widget.set_active(i) return def read_select_value(self, widget): selected=-1 try: selected=widget.get_active() except: print_debug ( "read_select() ERROR reading " ) model=widget.get_model() value=model[selected][0] print_debug ( "read_select() reading %s" %(value) ) return value ################################################################################ def parse_dhcp(self, line, options): for option in options: print_debug("line %s replace %s with %s"%(line, option, options[option])) line=line.replace(option, options[option]) print_debug(line) return line def write_into_etc_host(self, newline, noaction=False): ip=newline[0] hostname=newline[1] # check if exists f=open("/etc/hosts", "r") data=f.readlines() f.close() for line in data: line=line.replace('\n','') if ip + " " in line or ip + '\t' in line: print_debug ( "IP %s is in /etc/hosts" %(ip) ) return True try: print_debug ("Adding %s %s" %(ip, hostname) ) if noaction: print_debug("NOACTION: AddHost() hostname=%s, ip=%s" %(hostname,ip) ) else: f=open("/etc/hosts", "a") f.write("%s\t%s\n" %(ip, hostname) ) f.close() return True except Exception, err: print "Error '%s' editting /etc/hosts, are you root?"%err return False def configureDNSMASQ(self, *args): # get data gtk.gdk.threads_enter() self.w['btn_configure_dhcp'].set_sensitive(False) self.w['lbl_dhcp'].set_text( _("Configuring DNSMASQ service...") ) self.w['lbl_dhcp'].show() gtk.gdk.threads_leave() boot_mode=self.read_select_value(self.w['combo_boot_mode']) boot_filename="/pxelinux.0" for boot in self.BOOT_MODES: print_debug("boot[0]=%s boot_mode=%s"%(boot[0], boot_mode) ) if boot[0] == boot_mode: boot_filename=boot[1] print_debug("configureDNSMASQ() setting boot filename to %s"%boot_filename) # get server_ip false_gateway=False server_iface=self.read_select_value(self.w['combo_interfaces']) if self.configured_interfaces.has_key(server_iface) and len(self.configured_interfaces[server_iface]) > 1: server_ip=self.configured_interfaces[server_iface]['address'] try: gateway=self.configured_interfaces[server_iface]['gateway'] except: gateway=server_ip netmask=self.configured_interfaces[server_iface]['netmask'] if self.configured_interfaces[server_iface].has_key('network'): network=self.configured_interfaces[server_iface]['network'] else: network=".".join( server_ip.split('.')[0:-1]) + ".0" if self.configured_interfaces[server_iface].has_key('broadcast'): broadcast=self.configured_interfaces[server_iface]['broadcast'] else: broadcast=".".join( server_ip.split('.')[0:-1]) + ".255" else: print_debug("configureDNSMASQ() dynamic IP") server_ip=None for interface in self.interfaces: if interface[0] == server_iface: server_ip=interface[1] if self.w['txt_serverip'].get_text() != '': server_ip=self.w['txt_serverip'].get_text() # gateway #gateway=self.exe_cmd("ip route| grep %s| awk '/^default/ {print $3}'"%server_iface) gateway=self.exe_cmd("/sbin/route -n| awk '/^0.0.0.0(.*)%s/ {print $2}'| head -1" %server_iface) if gateway == [] or gateway == "": print_debug("gateway not found, using server_ip") gateway=server_ip false_gateway=True else: print_debug("FOUNG gateway =%s"%gateway) false_gateway=False broadcast=".".join( server_ip.split('.')[0:-1]) + ".255" netmask="255.255.255.0" network=".".join( server_ip.split('.')[0:-1]) + ".0" dns=[] entry="" if os.path.exists('/etc/resolv.conf'): # read dns f=open("/etc/resolv.conf", 'r') for line in f.readlines(): if line.startswith("nameserver") and len(dns) == 0: entry=line.split(' ')[1].strip() if entry != server_ip and entry != "127.0.0.1": dns.append(entry) f.close() if len(dns) == 0: # use server_ip as DNS dns.append(server_ip) # generate /etc/resolv.conf.real with real DNS # FIXME, use OpenDNS if entry is not found? if entry != "" and entry != server_ip: f=open(RESOLV_CONF_REAL, 'w') f.write("nameserver %s\n"%entry) f.close() options={ "__PROGRAM__":PACKAGE, "__DATE__":time.ctime(), "__MASK__":netmask, "__NET__":network, "__DNS__":dns[0], "__BROADCAST__":broadcast, "__ROUTERS__":gateway, "__SERVERIP__":server_ip, "__STARTIP__":self.w['txt_startip'].get_text(), "__ENDIP__":self.w['txt_endip'].get_text(), "__BOOTMODE__":boot_filename } # backup old conf file # generate /etc/dnsmasq.conf new_file=[] for block in DNSMASQ_CONF: for line in block: new_file.append(self.parse_dhcp(line, options)) try: f=open(DNSMASQ_FILE, 'w') for line in new_file: f.write(line + "\n") print_debug(DNSMASQ_FILE +":: %s"%line) f.close() except: # error writing gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_markup( _("Error writing /etc/dnsmasq.conf.\nAre you root?") ) gtk.gdk.threads_leave() time.sleep(4) # edit /etc/hosts ip_pref=".".join(self.w['txt_startip'].get_text().split('.')[0:3]) ip_start=int(self.w['txt_startip'].get_text().split('.')[-1]) ip_end=int(self.w['txt_endip'].get_text().split('.')[-1]) txt_prefix=self.w['txt_hostname_prefix'].get_text() for ip in range ( (ip_end - ip_start) + 1 ): ip=ip_start + ip ipname=ip if ip > 100: ipname=ip-100 if not SIMULATE: self.write_into_etc_host( ["%s.%d"%(ip_pref, ip), "%s%02d"%(txt_prefix, ipname) ] ) print_debug("write_into_etc_host() %s"%["%s.%d"%(ip_pref, ip), "%s%02d"%(txt_prefix, ipname) ] ) # read ck_static data={ "iface":server_iface, "address":server_ip, "gateway":gateway, "netmask":netmask, "network":network, "broadcast":broadcast, } if false_gateway: print_debug("configureDNSMASQ() remove false_gateway") data['gateway']=None if self.w['ck_static'].get_active(): if self.configure_static(data): time.sleep(1) gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_text( _("Configured static network") ) gtk.gdk.threads_leave() #self.exe_cmd("/etc/init.d/networking restart") self.exe_cmd("ifdown --all --exclude=lo") self.exe_cmd("ifdown --all --exclude=lo") self.exe_cmd("ifdown --all --exclude=lo") time.sleep(2) self.exe_cmd("ifup --all --exclude=lo") #self.exe_cmd("ifconfig %s"%server_iface) gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_markup( _("Done") ) gtk.gdk.threads_leave() time.sleep(2) else: gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_markup( _("ERROR:Error configuring static network.") ) gtk.gdk.threads_leave() time.sleep(4) gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_text( _("Restarting DNSMASQ service...") ) gtk.gdk.threads_leave() fail=False if not SIMULATE: result=self.exe_cmd("/etc/init.d/dnsmasq restart") for line in result: if "fail" in line: fail=True if "OK" in line: fail=False if "done" in line: fail=False gtk.gdk.threads_enter() if not fail: self.w['lbl_dhcp'].set_markup( _("Done") ) else: self.w['lbl_dhcp'].set_markup( _("Error restarting DNSMASQ server.") ) gtk.gdk.threads_leave() def configureDHCP(self, *args): # get data gtk.gdk.threads_enter() self.w['btn_configure_dhcp'].set_sensitive(False) self.w['lbl_dhcp'].set_text( _("Configuring DHCP service...") ) self.w['lbl_dhcp'].show() gtk.gdk.threads_leave() boot_mode=self.read_select_value(self.w['combo_boot_mode']) boot_filename="/pxelinux.0" for boot in self.BOOT_MODES: print_debug("boot[0]=%s boot_mode=%s"%(boot[0], boot_mode) ) if boot[0] == boot_mode: boot_filename=boot[1] print_debug("configureDHCP() setting boot filename to %s"%boot_filename) # get server_ip false_gateway=False server_iface=self.read_select_value(self.w['combo_interfaces']) if self.configured_interfaces.has_key(server_iface) and len(self.configured_interfaces[server_iface]) > 1: server_ip=self.configured_interfaces[server_iface]['address'] try: gateway=self.configured_interfaces[server_iface]['gateway'] except: gateway=server_ip netmask=self.configured_interfaces[server_iface]['netmask'] if self.configured_interfaces[server_iface].has_key('network'): network=self.configured_interfaces[server_iface]['network'] else: network=".".join( server_ip.split('.')[0:-1]) + ".0" if self.configured_interfaces[server_iface].has_key('broadcast'): broadcast=self.configured_interfaces[server_iface]['broadcast'] else: broadcast=".".join( server_ip.split('.')[0:-1]) + ".255" else: print_debug("configureDHCP() dynamic IP") server_ip=None for interface in self.interfaces: if interface[0] == server_iface: server_ip=interface[1] if self.w['txt_serverip'].get_text() != '': server_ip=self.w['txt_serverip'].get_text() # gateway #gateway=self.exe_cmd("ip route| grep %s| awk '/^default/ {print $3}'"%server_iface) gateway=self.exe_cmd("/sbin/route -n| awk '/^0.0.0.0(.*)%s/ {print $2}'" %server_iface) if gateway == [] or gateway == "": print_debug("gateway not found, using server_ip") gateway=server_ip false_gateway=True else: print_debug("FOUNG gateway =%s"%gateway) false_gateway=False broadcast=".".join( server_ip.split('.')[0:-1]) + ".255" netmask="255.255.255.0" network=".".join( server_ip.split('.')[0:-1]) + ".0" dns=[] if os.path.exists('/etc/resolv.conf'): # read dns f=open("/etc/resolv.conf", 'r') for line in f.readlines(): if line.startswith("nameserver") and len(dns) == 0: dns.append(line.split(' ')[1].strip()) f.close() else: # use server_ip as DNS dns.append(server_ip) options={ "__PROGRAM__":PACKAGE, "__DATE__":time.ctime(), "__MASK__":netmask, "__NET__":network, "__DNS__":dns[0], "__BROADCAST__":broadcast, "__ROUTERS__":gateway, "__SERVERIP__":server_ip, "__STARTIP__":self.w['txt_startip'].get_text(), "__ENDIP__":self.w['txt_endip'].get_text(), "__BOOTMODE__":boot_filename } # backup old conf file # generate /etc/dhcp3/dhcpd.confask_ new_file=[] for block in DHCP_CONF: for line in block: new_file.append(self.parse_dhcp(line, options)) try: f=open("/etc/dhcp3/dhcpd.conf", 'w') for line in new_file: f.write(line + "\n") f.close() except: # error writing gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_markup( _("Error writing /etc/dhcp3/dhcpd.conf.\nAre you root?") ) gtk.gdk.threads_leave() time.sleep(4) f=open("/etc/default/dhcp3-server", 'r') dhcpdata=[] for line in f.readlines(): if line.startswith("INTERFACES"): dhcpdata.append("INTERFACES=\"%s\"\n"%server_iface) else: dhcpdata.append(line) f.close() f=open("/etc/default/dhcp3-server", 'w') for line in dhcpdata: f.write(line) f.close() # edit /etc/hosts ip_pref=".".join(self.w['txt_startip'].get_text().split('.')[0:3]) ip_start=int(self.w['txt_startip'].get_text().split('.')[-1]) ip_end=int(self.w['txt_endip'].get_text().split('.')[-1]) txt_prefix=self.w['txt_hostname_prefix'].get_text() for ip in range ( (ip_end - ip_start) + 1 ): ip=ip_start + ip ipname=ip if ip > 100: ipname=ip-100 self.write_into_etc_host( ["%s.%d"%(ip_pref, ip), "%s%02d"%(txt_prefix, ipname) ] ) # read ck_static data={ "iface":server_iface, "address":server_ip, "gateway":gateway, "netmask":netmask, "network":network, "broadcast":broadcast, } if self.w['ck_static'].get_active(): if self.configure_static(data): time.sleep(1) gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_text( _("Configured static network") ) gtk.gdk.threads_leave() #self.exe_cmd("/etc/init.d/networking restart") self.exe_cmd("ifdown --all --exclude=lo") self.exe_cmd("ifdown --all --exclude=lo") self.exe_cmd("ifdown --all --exclude=lo") time.sleep(2) self.exe_cmd("ifup --all --exclude=lo") #self.exe_cmd("ifconfig %s"%server_iface) gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_markup( _("Done") ) gtk.gdk.threads_leave() time.sleep(2) else: gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_markup( _("ERROR:Error configuring static network.") ) gtk.gdk.threads_leave() time.sleep(4) gtk.gdk.threads_enter() self.w['lbl_dhcp'].set_text( _("Restarting DHCP service...") ) gtk.gdk.threads_leave() result=self.exe_cmd("/etc/init.d/dhcp3-server restart") fail=False for line in result: if "fail" in line: fail=True if "OK" in line: fail=False gtk.gdk.threads_enter() if not fail: self.w['lbl_dhcp'].set_markup( _("Done") ) else: self.w['lbl_dhcp'].set_markup( _("Error restarting DHCP server.") ) gtk.gdk.threads_leave() def on_btn_launch_tcosconfig(self, widget): th=Thread(target=self.exe_cmd, args=('gksu tcosconfig',) ) th.setDaemon(1) th.start() ################################################################################ def ask_msg(self, txt): response="yes" d = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, txt) if d.run() == gtk.RESPONSE_YES: response=True else: response=False d.destroy() return response def exe_cmd(self, cmd, verbose=1): self.p = Popen(cmd, shell=True, bufsize=0, stdout=PIPE, stderr=STDOUT, close_fds=True) output=[] stdout = self.p.stdout for line in stdout.readlines(): if line != '\n': line=line.replace('\n', '') output.append(line) if len(output) == 1: return output[0] elif len(output) > 1: if verbose==1: print_debug ( "exe_cmd(%s) %s" %(cmd, output) ) return output else: if verbose == 1: print_debug ( "exe_cmd(%s)=None" %(cmd) ) return [] def quitapp(self,*args): print_debug ( "Exiting" ) self.mainloop.quit() def run (self): self.mainloop = gobject.MainLoop() try: self.mainloop.run() except KeyboardInterrupt: # Press Ctrl+C self.quitapp() if __name__ == '__main__': app = TcosStandalone () # Run app app.run ()