mirror of
https://abf.rosa.ru/djam/italc2.git
synced 2025-02-23 14:32:48 +00:00
274 lines
8.4 KiB
Python
274 lines
8.4 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
# coding=UTF-8
|
|
|
|
# iTalc master launcher using avahi
|
|
# Written by Stéphane Graber <stgraber@ubuntu.com>
|
|
|
|
from xml.dom import minidom
|
|
import subprocess, re, socket, os, sys
|
|
# The md5 module is deprecated in Python 2.5
|
|
try:
|
|
from hashlib import md5
|
|
except ImportError:
|
|
from md5 import md5
|
|
|
|
def getValueFromConfigFile(filename,key,default):
|
|
file=open(filename)
|
|
for line in file:
|
|
if line.startswith(key):
|
|
try:
|
|
param=line.split("=")[1]
|
|
param=param.strip()
|
|
if not param.isdigit():
|
|
param=param.strip('"')
|
|
except:
|
|
param=default
|
|
file.close()
|
|
return param
|
|
|
|
def getLocalIPs():
|
|
"Scan ifconfig output for local IPV4 addresses"
|
|
# Saving current LANG
|
|
SYSTEM_LANG=os.environ["LANG"]
|
|
# Apparently ifconfig has localizations according to the following line,
|
|
# but with LANG=es_ES.UTF-8 the output looks the same as LANG=C
|
|
os.environ["LANG"]="C" # Set environ LANG to C
|
|
ip=[]
|
|
output=subprocess.Popen("/sbin/ifconfig",stdout=subprocess.PIPE)
|
|
output.wait()
|
|
for line in output.stdout.readlines():
|
|
line=line.strip()
|
|
if line.startswith("inet addr"):
|
|
ip.append(line.split(" ")[1].split(":")[1])
|
|
# Restoring LANG
|
|
os.environ["LANG"]=SYSTEM_LANG
|
|
return ip
|
|
|
|
def getHostPort():
|
|
isdhost="127.0.0.1"
|
|
isdport=getValueFromConfigFile(configfile,"ICA_ISDPORT","5800")
|
|
if "LTSP_CLIENT" in os.environ:
|
|
xprop=subprocess.Popen(["/usr/bin/xprop","-root","ica_ltsp"],stdout=subprocess.PIPE)
|
|
xprop.wait()
|
|
if xprop.stdout.read().split(" ")[2].strip() == "1":
|
|
isdhost=os.environ["LTSP_CLIENT"]
|
|
else:
|
|
isdport=str(int(os.environ["LTSP_CLIENT"].split(".")[3])+11000)
|
|
return [isdhost,isdport]
|
|
|
|
def getSettings():
|
|
"Find settings file and read paths"
|
|
global section_keypathsprivate
|
|
global section_keypathspublic
|
|
global section_paths
|
|
global path_adminprivatekey
|
|
global path_adminpublickey
|
|
global path_globalconfig
|
|
global path_supporterprivatekey
|
|
global path_supporterpublickey
|
|
global path_teacherprivatekey
|
|
global path_teacherpublickey
|
|
global settingsfile
|
|
file=open(settingsfile)
|
|
mode=""
|
|
for line in file:
|
|
line = line.strip()
|
|
if line == section_keypathsprivate:
|
|
mode=section_keypathsprivate
|
|
elif line == section_keypathspublic:
|
|
mode=section_keypathspublic
|
|
elif line == section_paths:
|
|
mode=section_paths
|
|
else:
|
|
if mode==section_keypathsprivate:
|
|
if line.startswith("admin"):
|
|
try:
|
|
path_adminprivatekey=line.split("=")[1]
|
|
path_adminprivatekey=path_adminprivatekey.strip()
|
|
except:
|
|
path_adminprivatekey="/etc/italc/keys/private/admin/key"
|
|
elif line.startswith("teacher"):
|
|
try:
|
|
path_teacherprivatekey=line.split("=")[1]
|
|
path_teacherprivatekey=path_teacherprivatekey.strip()
|
|
except:
|
|
path_teacherprivatekey="/etc/italc/keys/private/teacher/key"
|
|
elif line.startswith("supporter"):
|
|
try:
|
|
path_supporterprivatekey=line.split("=")[1]
|
|
path_supporterprivatekey=path_supporterprivatekey.strip()
|
|
except:
|
|
path_supporterprivatekey="/etc/italc/keys/private/supporter/key"
|
|
elif mode==section_keypathspublic:
|
|
if line.startswith("admin"):
|
|
try:
|
|
path_adminpublickey=line.split("=")[1]
|
|
path_adminpublickey=path_adminpublickey.strip()
|
|
except:
|
|
path_adminpublickey="/etc/italc/keys/public/admin/key"
|
|
elif line.startswith("teacher"):
|
|
try:
|
|
path_teacherpublickey=line.split("=")[1]
|
|
path_teacherpublickey=path_teacherpublickey.strip()
|
|
except:
|
|
path_teacherpublickey="/etc/italc/keys/public/teacher/key"
|
|
elif line.startswith("supporter"):
|
|
try:
|
|
path_supporterpublickey=line.split("=")[1]
|
|
path_supporterpublickey=path_supporterpublickey.strip()
|
|
except:
|
|
path_supporterpublickey="/etc/italc/keys/public/supporter/key"
|
|
elif mode==section_paths:
|
|
if line.startswith("globalconfig"):
|
|
try:
|
|
path_globalconfig=line.split("=")[1]
|
|
path_globalconfig=path_globalconfig.strip()
|
|
except:
|
|
path_globalconfig="/etc/italc/globalconfig.xml"
|
|
file.close()
|
|
return
|
|
|
|
# openSUSE uses /etc/sysconfig/ica to define the ports
|
|
configfile="/etc/sysconfig/ica"
|
|
# Empty config file to use if it doesn't already exist
|
|
skeleton="""<?xml version="1.0"?>
|
|
<!DOCTYPE italc-config-file>
|
|
<globalclientconfig version="1.0.7" >
|
|
<body>
|
|
</body>
|
|
</globalclientconfig>"""
|
|
|
|
settingsfile="/etc/settings/iTALC Solutions/iTALC.conf"
|
|
section_keypathsprivate="[keypathsprivate]"
|
|
section_keypathspublic="[keypathspublic]"
|
|
section_paths="[paths]"
|
|
path_teacherpublickey="/etc/italc/keys/public/teacher/key"
|
|
path_adminpublickey="/etc/italc/keys/public/admin/key"
|
|
path_supporterpublickey="/etc/italc/keys/public/supporter/key"
|
|
path_teacherprivatekey="/etc/italc/keys/private/teacher/key"
|
|
path_adminprivatekey="/etc/italc/keys/private/admin/key"
|
|
path_supporterprivatekey="/etc/italc/keys/private/supporter/key"
|
|
path_globalconfig="/etc/italc/globalconfig.xml"
|
|
|
|
try:
|
|
getSettings()
|
|
except:
|
|
print "Settings not found in "+settingsfile+", using defaults."
|
|
|
|
try:
|
|
confdir=os.environ.get("HOME")+"/.italc/"
|
|
except:
|
|
sys.exit('Invalid or undefined env variable \"HOME\"')
|
|
|
|
try:
|
|
file=open(path_teacherpublickey,"r")
|
|
md5_1=md5(file.read()).hexdigest()
|
|
file.close()
|
|
|
|
file=open(path_adminpublickey,"r")
|
|
md5_2=md5(file.read()).hexdigest()
|
|
file.close()
|
|
|
|
file=open(path_supporterpublickey,"r")
|
|
md5_3=md5(file.read()).hexdigest()
|
|
file.close()
|
|
except:
|
|
sys.exit('iTalc keys not correctly installed ('+path_teacherpublickey+')('+path_adminpublickey+')('+path_supporterpublickey)
|
|
|
|
if not os.access(path_teacherprivatekey,os.R_OK):
|
|
md5_1="0"
|
|
if not os.access(path_adminprivatekey,os.R_OK):
|
|
md5_2="0"
|
|
if not os.access(path_supporterprivatekey,os.R_OK):
|
|
md5_3="0"
|
|
access="none"
|
|
else:
|
|
access="supporter"
|
|
else:
|
|
access="admin"
|
|
else:
|
|
access="teacher"
|
|
|
|
try:
|
|
xmldoc=minidom.parse(confdir+"globalconfig.xml")
|
|
body=xmldoc.getElementsByTagName("globalclientconfig")[0].getElementsByTagName("body")[0]
|
|
classrooms=body.getElementsByTagName("classroom")
|
|
except:
|
|
mkdir=subprocess.Popen(["/bin/mkdir","-p",confdir])
|
|
mkdir.wait()
|
|
try:
|
|
config=open(confdir+"globalconfig.xml","w+")
|
|
try:
|
|
file=open(path_globalconfig)
|
|
for line in file:
|
|
config.write(line)
|
|
except:
|
|
print("Globalconfig in "+path_globalconfig+" not found, using skeleton.")
|
|
config.write(skeleton)
|
|
config.close()
|
|
except:
|
|
sys.exit('Unable to write to config file')
|
|
xmldoc=minidom.parse(confdir+"globalconfig.xml")
|
|
body=xmldoc.getElementsByTagName("globalclientconfig")[0].getElementsByTagName("body")[0]
|
|
classrooms=body.getElementsByTagName("classroom")
|
|
|
|
# Scan for an existing classroom and delete it
|
|
for classroom in classrooms:
|
|
if classroom.getAttribute("name") == "Auto-detected computers":
|
|
body.removeChild(classroom)
|
|
|
|
# Create the Auto-detected computers classroom
|
|
avahi=xmldoc.createElement("classroom")
|
|
avahi.setAttribute("name","Auto-detected computers")
|
|
avahi.setAttribute("forcevisible","yes")
|
|
body.appendChild(avahi)
|
|
|
|
# Add computers to the classroom
|
|
client_list=subprocess.Popen(["/usr/bin/avahi-browse","-trp","_italc._tcp"],stdout=subprocess.PIPE)
|
|
client_list.wait()
|
|
count=0
|
|
|
|
local_addr=getLocalIPs()
|
|
isdhost,isdport=getHostPort()
|
|
if isdhost not in local_addr:
|
|
local_addr=[isdhost]
|
|
|
|
for line in client_list.stdout.readlines():
|
|
if line.startswith("="):
|
|
try:
|
|
param=line.split(";")
|
|
comment=re.findall('"(.*)" "(.*)" "(.*)" "(.*)"\n',param[9])[0]
|
|
if (comment[1] == md5_1 or comment[2] == md5_2 or comment[3] == md5_3) and (param[7] not in local_addr or str(int(isdport)+100) != param[8]):
|
|
# Make sure we have a running VNC server
|
|
connection=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
|
connection.connect((param[7],int(param[8])))
|
|
connection.close()
|
|
|
|
# Get MAC address
|
|
mac=subprocess.Popen(("/sbin/arp", param[7], "-n", "-a"),stdout=subprocess.PIPE)
|
|
mac.wait()
|
|
mac=mac.stdout.read().strip().split(" ")[3]
|
|
if not re.match("^..:..:..:..:..:..$",mac):
|
|
mac=""
|
|
|
|
# Generate the new node
|
|
client=xmldoc.createElement("client")
|
|
client.setAttribute("id",str(count))
|
|
client.setAttribute("localip",param[7]+":"+param[8])
|
|
client.setAttribute("mac",mac)
|
|
client.setAttribute("name",comment[0])
|
|
client.setAttribute("type","0")
|
|
avahi.appendChild(client)
|
|
count+=1
|
|
except:
|
|
print 'Ignoring a client, invalid data received'
|
|
|
|
try:
|
|
file=open(confdir+"globalconfig.xml","w")
|
|
xmldoc.writexml(file)
|
|
file.close()
|
|
except:
|
|
exit('Failed to save updated config')
|
|
#print "Starting italc as "+access+" ("+isdhost+":"+isdport+")"
|
|
subprocess.Popen(["/usr/bin/italc","-isdport",isdport,"-isdhost",isdhost,"-role",access])
|