Proyecto

General

Perfil

« Anterior | Siguiente » 

Revisión 99

Añadido por jredrejo hace alrededor de 14 años

creada rama de web2py y movido desarrollo a trunk

Ver diferencias:

controlies/Server.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: Server.py
# Purpose: ControlIES web server
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
#
# ControlIES 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 3 of the License, or
# (at your option) any later version.
# ControlIES 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 ControlIES. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from Utils.avahiClient import avahiClient
from Utils import Configs
from twisted.web import static, server
from twisted.web.server import Session
from twisted.python.components import registerAdapter
import logging,logging.handlers
import MainLoop
from zope.interface import Interface, Attribute, implements
from Plugins.LdapConnection import LdapConnection, ILdapConnection
import os.path
# Logging
log_handler = logging.handlers.RotatingFileHandler(Configs.LOG_FILENAME, maxBytes=100000, backupCount=5)
log_formatter = logging.Formatter(fmt='%(asctime)s %(levelname)-8s %(message)s',datefmt='%a, %d %b %Y %H:%M:%S')
log_handler.setFormatter(log_formatter)
root_logger=logging.getLogger()
root_logger.addHandler(log_handler)
root_logger.level=logging.DEBUG
registerAdapter(LdapConnection, Session, ILdapConnection)
# Start up the web service.
Root = MainLoop.ControlIESProtocol() #Resource object
Root.PageDir='/home/manu/proyectos/controlies/www/'
#Root.PageDir='/home/chisco/Proyectos/controlies/www'
site = server.Site(Root)
fileNameServers = '/tmp/controlIES.ltpsSevers'
if os.path.isfile(fileNameServers):
os.remove(fileNameServers)
f = open(fileNameServers, 'w')
fileNameTeachers = '/tmp/controlIES.ltpsTeachers'
if os.path.isfile(fileNameTeachers):
os.remove(fileNameTeachers)
f = open(fileNameTeachers, 'w')
def _add_locationServers(self, name, address, port):
print name
computerToAdd = name.split(" ")
f = open(fileNameServers, 'a')
f.write(computerToAdd[0]+" ")
f.close()
def _remove_locationServers(self, name, address, port):
computerToDelete = name.split(" ")
f = open(fileNameServers, 'r')
computersList = f.read()
f.close()
computersList = computersList.replace(computerToDelete[0]+" ","")
f = open(fileNameServers, 'w')
f.write(computersList)
f.close()
def _add_locationTeachers(self, name, address, port):
print name
teacherToAdd = name.split(" ")
f = open(fileNameTeachers, 'a')
f.write(teacherToAdd[0]+" ")
f.close()
def _remove_locationTeachers(self, name, address, port):
teacherToDelete = name.split(" ")
f = open(fileNameTeachers, 'r')
teachersList = f.read()
f.close()
teachersList = teachersList.replace(teacherToDelete[0]+" ","")
f = open(fileNameTeachers, 'w')
f.write(teachersList)
f.close()
try:
_monitor = avahiClient('_workstation._tcp')
_monitor.add_callback('new-service', _add_locationServers)
_monitor.add_callback('remove-service', _remove_locationServers)
_monitor.start()
except Exception, ex:
logging.getLogger().debug("Couldn't initialize Avahi monitor: workstations")
try:
_monitor = avahiClient('_controlaula._tcp')
_monitor.add_callback('new-service', _add_locationTeachers)
_monitor.add_callback('remove-service', _remove_locationTeachers)
_monitor.start()
except Exception, ex:
logging.getLogger().debug("Couldn't initialize Avahi monitor: controlaula")
from twisted.internet import reactor
reactor.listenTCP(7778,site)
reactor.run()
controlies/Plugins/NetworkUtils.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: Controlaula
# Module: NetworkUtils.py
# Purpose: Several network utilities to be used in Python
# Language: Python 2.5
# Date: 17-Jan-2010.
# Ver: 17-Jan-2010.
# Author: José L. Redrejo Rodríguez
# Copyright: 2009 - José L. Redrejo Rodríguez <jredrejo @nospam@ debian.org>
#
# ControlAula 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 3 of the License, or
# (at your option) any later version.
# ControlAula 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 ControlAula. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import array,fcntl,socket,struct,os,re
import logging,subprocess
gateway='0'
ltspGateway='0'
essid=''
bssid=''
IFNAMSIZE = 16
IW_ESSID_MAX_SIZE = 16
SIOCGIWESSID = 0x8B1B
SIOCGIWAP = 0x8B15
def get_ip_address(ifname):
"""Returns the ip address of the interface ifname"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
ip= socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15]) )[20:24]
)
except:
ip=''
return ip
def get_ip_inet_address(connection_ip='198.41.0.4'):
"""Returns the ip address of the interface used to connect to the given ip
198.41.0.4 is a DNS ROOT Server, so it's the default value to connect to Internet
"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect((connection_ip, 0))
inet_address= s.getsockname()[0]
except:
inet_address=''
s.close()
logging.getLogger().debug("Inet Address:" + inet_address)
return inet_address
def get_inet_HwAddr(connection_ip='192.168.0.254'):
"""Returns the mac address of the interface used to connect to the given ip"""
interfaces=all_interfaces()
rightIP=get_ip_inet_address(connection_ip)
mac=''
ifname=''
for i in interfaces:
if rightIP== get_ip_address(i[0]):
ifname=i[0]
break
if ifname !='':
mac=get_HwAddr(ifname)
return mac
def get_HwAddr(ifname):
"""Returns the mac of the ifname network card"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
try:
mac= ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
except:
mac=''
return mac
def getWirelessNICnames():
""" return list of wireless device names """
device = re.compile('[a-z]{3,4}[0-9]')
ifnames = []
f = open('/proc/net/wireless', 'r')
data = f.readlines()
for line in data:
try:
ifnames.append(device.search(line).group())
except AttributeError:
pass
return ifnames
def all_interfaces():
"""Returns all the available network interfaces in a linux machine"""
max_possible = 128 # arbitrary. raise if needed.
bytes = max_possible * 32
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
names = array.array('B', '\0' * bytes)
outbytes = struct.unpack('iL', fcntl.ioctl( s.fileno(), 0x8912, struct.pack('iL', bytes, names.buffer_info()[0]) ))[0]
namestr = names.tostring()
#return [namestr[i:i+32].split('\0', 1)[0] for i in range(0, outbytes, 32)]
lst = []
arch64=(os.uname()[4]=='x86_64')
if arch64:
totalStruct=40
else:
totalStruct=32
for i in range(0, outbytes, totalStruct):
if arch64:
name = namestr[i:i+16].split('\0', 1)[0]
else:
name = namestr[i:i+32].split('\0', 1)[0]
ip = namestr[i+20:i+24]
lst.append((name, socket.inet_ntoa(ip)))
return lst
def getESSID( ifname):
sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
essid = ""
buff = array.array('c', '\0'*32)
caddr_t, length = buff.buffer_info()
s = struct.pack('Pi', caddr_t, length)
buff2 = IFNAMSIZE-len(ifname)
ifreq = ifname + '\0'*buff2
ifreq = ifreq + s
try:
result = fcntl.ioctl(sockfd.fileno(), SIOCGIWESSID, ifreq)
i=0
result=result[16:]
except IOError, (i, e):
i=i
result=e
if i > 0:
return (i, result)
str = buff.tostring()
return (0,str.strip('\x00'))
def getHostName():
return socket.gethostname()
def getFreeTCPPort():
"""Returns a random free port provided by the Operative System"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('localhost', 0))
newPort= sock.getsockname()[1]
sock.close()
return newPort
def getWirelessData():
global essid
global bssid
wifiNICs=getWirelessNICnames()
if len(wifiNICs)>0:
for i in wifiNICs:
value,nessid=getESSID(i)
if value==0:
essid=nessid
value2,nbssid=getAPaddr(i)
if value2==0:
bssid=nbssid
def getAPaddr(ifname):
sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
buff = array.array('c', '\0'*32)
caddr_t, length = buff.buffer_info()
s = struct.pack('Pi', caddr_t, length)
buff2 = IFNAMSIZE-len(ifname)
ifreq = ifname + '\0'*buff2
ifreq = ifreq + s
try:
result = fcntl.ioctl(sockfd.fileno(), SIOCGIWAP, ifreq)
i=0
result=result[16:]
except IOError, (i, e):
i=i
result=e
if i > 0:
return (i, result)
else:
mac_addr = struct.unpack('xxBBBBBB',result[:8])
return (0,"%02X:%02X:%02X:%02X:%02X:%02X" % mac_addr)
def scan_server(address, port):
"""Returns true if a port is open at address, or false otherwise"""
s = socket.socket()
#print "Attempting to connect to %s on port %s." %(address, port)
try:
s.connect((address, port))
#print "Connected to server %s on port %s." %(address, port)
s.close()
return True
except socket.error, e:
logging.getLogger().debug("Connecting to %s on port %s failed with the following error: %s" %(address, port, e))
return False
def getUsableTCPPort(address,port):
"""Returns the first free port between port and port +10"""
freeport=port
for x in range(port,port+10):
check = scan_server(address, x)
if check==False :
freeport=x
break
return freeport
def startup(address):
addr_byte = address.split(':')
hw_addr = struct.pack('BBBBBB', int(addr_byte[0], 16),
int(addr_byte[1], 16),
int(addr_byte[2], 16),
int(addr_byte[3], 16),
int(addr_byte[4], 16),
int(addr_byte[5], 16))
msg = '\xff' * 6 + hw_addr * 16
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
try:
s.sendto(msg, ('<broadcast>', 9))
s.sendto(msg, ('<broadcast>', 7))
s.sendto(msg, ('192.168.0.255', 9))
s.sendto(msg, ('192.168.0.255', 7))
except:
s.sendto(msg, ('<broadcast>', 2000))
s.sendto(msg, ('192.168.0.255', 2000))
s.close()
def defaultGW():
global gateway
if gateway=='0':
try:
s=subprocess.Popen('/sbin/route -n|grep "0.0.0.0"|grep UG',shell=True,stdout=subprocess.PIPE).communicate()[0]
gateway=s.splitlines()[0].split()[1]
except:
gateway='0'
return gateway
def ltspGW():
global ltspGateway
if ltspGateway=='0':
try:
externalIP=get_ip_inet_address()
internalIP=get_ip_inet_address('192.168.0.2')
if externalIP==internalIP or externalIP=='':
ltspGateway=defaultGW()
else:
ltspGateway=internalIP
except:
ltspGateway='0'
return ltspGateway
def cleanRoutes():
s=subprocess.Popen(['route','-n'],stdout=subprocess.PIPE).communicate()[0]
l=s.splitlines()
for route in l:
target=route.split()[0]
if target[:4]=='239.':
subprocess.Popen(['route','del','-net',target + '/24'])
def addRoute(net,gw=''):
if gw=='':
newgw=defaultGW()
else:
newgw=gw
subprocess.Popen(['route','add','-net',net+ '/24','gw',newgw])
controlies/Plugins/DHCP.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: DHCP.py
# Purpose: DHCP class
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Francisco Mendez Palma
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
# 2011 - Francisco Mendez Palma <fmendezpalma @no-spam@ gmail.com>
#
# ControlIES 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 3 of the License, or
# (at your option) any later version.
# ControlIES 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 ControlAula. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ldap
import logging
from math import ceil
class DHCP(object):
def __init__(self):
pass
def __init__(self,ldap,subnet_mask,broadcast_address,routers,domain_name_servers,domain_name,ntp_servers,log_servers,netbios_name_servers,netbios_node_type):
self.ldap = ldap
self.subnet_mask = subnet_mask
self.broadcast_address = broadcast_address
self.routers = routers
self.domain_name_servers = domain_name_servers
self.domain_name = domain_name
self.ntp_servers = ntp_servers
self.log_servers = log_servers
self.netbios_name_servers = netbios_name_servers
self.netbios_node_type = netbios_node_type
def validation(self):
if self.subnet_mask == "":
return "subnet_mask"
if self.broadcast_address == "broadcast_address":
return "broadcast_address"
if self.routers == "routers":
return "routers"
if self.domain-name == "domain-name":
return "domain-name"
if self.domain_name_servers == "domain_name_servers":
return "domain_name_servers"
if self.ntp_servers == "ntp_servers":
return "ntp_servers"
if self.log_servers == "log_servers":
return "log_servers"
if self.netbios_name_servers == "netbios_name_servers":
return "netbios_name_servers"
if self.netbios_node_type == "netbios_node_type":
return "netbios_node_type"
return "OK"
def process(self,action):
if action == "add":
val = self.validation()
if val != "OK":
return val
else:
response = self.add()
return response
if action == "modify":
val = self.validation()
if val != "OK":
return val
else:
response = self.modify()
return response
if action == "delete":
response = self.delete()
return response
if action == "list":
response = self.list();
return response
def list(self,args):
#busqueda dhcp
search = self.ldap.search("cn=INTERNAL,cn=DHCP Config,dc=instituto,dc=extremadura,dc=es","dhcpOption=*",["dhcpOption"])
limit = int(args['rows'][0])
page = int(args['page'][0])
start = limit * page - limit
finish = start + limit;
if len(search) > 0:
totalPages = ceil( len(search) / int(limit) )
else:
totalPages = 0
if page > totalPages:
page = totalPages
# print search[0][0][1]["uidNumber"][0]
rows = []
for i in search[start:finish]:
row = { "cn":i[0][0], "cell":[i[0][1]["cn"][0], i[0][1]["ipHostNumber"][0],i[0][1]["macAddress"]]}
rows.append(row)
return { "page":page, "total":totalPages, "records":len(search), "rows":rows }
def add(self):
record = [
('objectclass', ['person','organizationalperson','inetorgperson']),
('uid', ['francis']),
('cn', [self.name] ),
('sn', ['Bacon'] ),
('userpassword', [self.password]),
('ou', ['users'])
]
try:
self.ldap.add("cn=hosts", record)
except ldap.ALREADY_EXISTS:
return "fail"
return "OK"
def modify(self):
mod_attrs = [
(ldap.MOD_ADD, 'description', 'Author of New Organon'),
(ldap.MOD_ADD, 'description', 'British empiricist')
]
self.ldap.modify_s('uid='+ uid +',cn=hosts', mod_attrs)
def delete(self,uid):
self.ldap.delete('uid='+ uid +',cn=hosts')
def wakeup(self):
from twisted.internet.task import LoopingCall
from twisted.internet import defer
from Plugins import NetworkUtils
NetworkUtils.startup(self.mac)
# def wakeup(self):
# from twisted.internet.task import LoopingCall
# from twisted.internet import defer
# from Plugins import NetworkUtils
# NetworkUtils.startup(self.mac)
# Encender el equipo
#def wakeup(self):
# macs=[]
# for i in self.targets:
# mac=Configs.MonitorConfigs.GetMAC(i)
# if mac !='':
# macs.append(mac)
# Actions.sendWOLBurst(macs, 2)
#Apagar el equipo
# def sleep(self):
# self.usersCommand(Desktop.sleep)
#def sendWOLBurst(macs,throttle):
# from twisted.internet.task import LoopingCall
# from twisted.internet import defer
# if not macs:
# return defer.succeed(None)
# d = defer.Deferred()
# work = list(macs)
# def sendNext():
# if not work:
# loop.stop()
# d.callback(None)
# return defer.succeed(None)
# next = work.pop(0)
#
# #subprocess.Popen(['wakeonlan',next ])
# #subprocess.Popen(['wakeonlan','-i','192.168.0.255',next ])
# NetworkUtils.startup(next)
#
# return None
# loop = LoopingCall(sendNext)
# loop.start(throttle)
# return d
controlies/Plugins/Groups.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: Groups.py
# Purpose: Groups class
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Francisco Mendez Palma
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
# 2011 - Francisco Mendez Palma <fmendezpalma @no-spam@ gmail.com>
#
# ControlIES 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 3 of the License, or
# (at your option) any later version.
# ControlIES 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 ControlIES. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ldap
import logging
from math import ceil
from operator import itemgetter
from Utils import Utils, LdapUtils
class Groups(object):
def __init__(self):
pass
def __init__(self,ldap,type,name,users):
self.ldap = ldap
self.type = type
self.name = Utils.parseToLdap(name)
self.users = users
def validation(self,action):
if self.type == "none":
return "type"
if self.name == "":
return "name"
if self.users == "":
return "users"
return "OK"
def process(self,action):
if action == "add":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.add()
return response
if action == "modify":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.modify()
return response
def list(self,args):
filter = self.buildFilter(args)
search = self.ldap.search("ou=Group",filter,["cn","gidNumber","groupType","memberUid"])
# grid parameters
limit = int(args['rows'][0])
page = int(args['page'][0])
start = limit * page - limit
finish = start + limit;
# sort by field
sortBy = args['sidx'][0]
if sortBy == "cn":
sortBy = "id"
# reverse Sort
reverseSort = False
if args['sord'][0] == "asc":
reverseSort = True
# type of group (Classroom/Department)
try:
searchType = args['type'][0]
except LookupError:
searchType = "none"
rows = []
for i in search:
typeRow="Aula"
if i[0][1]["groupType"][0]=="school_department":
typeRow="Departamento"
if searchType == typeRow or searchType=="none":
try:
usersNumber = len(i[0][1]["memberUid"])
except:
usersNumber = 0
row = {
"id":i[0][1]["cn"][0],
"cell":[typeRow, i[0][1]["cn"][0], i[0][1]["gidNumber"][0], usersNumber],
"type": typeRow,
"cn": i[0][1]["cn"][0],
"gidNumber": i[0][1]["gidNumber"][0],
"usersNumber": usersNumber
}
rows.append(row)
if len(search) > 0:
totalPages = ceil( len(search) / int(limit) )
else:
totalPages = 0
if page > totalPages:
page = totalPages
# sort rows
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(search), "rows":result[start:finish] }
def buildFilter(self, args):
filter = "(&(cn=*)(|(groupType=school_class)(groupType=school_department))"
try:
filter = filter + "(cn=*" + args['cn'][0] + "*)"
except LookupError:
pass
try:
filter = filter + "(gidNumber=" + args['gidNumber'][0] + ")"
except LookupError:
pass
filter = filter + ")"
return filter
def add(self):
maxID = str(LdapUtils.getMaxID(self.ldap))
members = []
for m in self.users.split(','):
members.append("uid=" + m + ",ou=People,dc=instituto,dc=extremadura,dc=es")
attr = [
('objectclass', ['top','posixGroup','lisGroup','lisAclGroup']),
('grouptype', [self.type] ),
('gidnumber', [maxID] ),
('cn', [self.name] ),
('description', [self.name+' department group']),
('memberuid', self.users.split(',')),
('member', members)
]
self.ldap.add("cn="+self.name+",ou=Group", attr)
return "OK"
def modify(self):
members = []
for m in self.users.split(','):
members.append("uid=" + m + ",ou=People,dc=instituto,dc=extremadura,dc=es")
mod_attrs = [
(ldap.MOD_REPLACE, 'memberuid', self.users.split(',')),
(ldap.MOD_REPLACE, 'member', members)
]
self.ldap.modify('cn='+ self.name +',ou=Group', mod_attrs)
return "OK"
def delete(self):
self.ldap.delete('cn='+ self.name +',ou=Group')
return "OK"
def getGroupData(self):
result = self.ldap.search("ou=Group","cn="+self.name,["cn","grouptype","memberuid"])
members = result[0][0][1]["memberUid"]
members.sort()
dataGroup = {
"name":result[0][0][1]["cn"][0],
"type":result[0][0][1]["groupType"][0],
"memberuid":members
}
return dataGroup
def getGroupUsers(self):
result = self.ldap.search("ou=Group","cn="+self.name,["cn","memberUid"])
members = []
for m in result:
members.append(m[0][1]["memberUid"][0])
members.sort()
return members
controlies/Plugins/LdapConnection.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: LdapConnection.py
# Purpose: Connection with ldap server
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
#
# ControlIES 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 3 of the License, or
# (at your option) any later version.
# ControlIES 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 ControlAula. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ldap
import logging
from zope.interface import Interface, Attribute, implements
class ILdapConnection(Interface):
connection=Attribute("a ldap connection")
class LdapConnection(object):
implements(ILdapConnection)
def __init__(self,session):
self.host = ""
self.user = ""
self.passwd = ""
pass
def setCredentials(self,host,user,passwd):
self.host = host
self.user = user
self.passwd = passwd
def validation(self):
if self.host == "":
return "host"
if self.user == "":
return "user"
if self.passwd == "":
return "password"
return "OK"
def process(self):
val = self.validation()
if val != "OK":
return val
auth = self.connect()
return auth
def connect(self):
self.connection=ldap.open(self.host)
try:
self.connection.simple_bind_s("cn="+self.user+",ou=People,dc=instituto,dc=extremadura,dc=es",self.passwd)
except ldap.INVALID_CREDENTIALS:
logging.getLogger().debug('LDAP user or password incorrect')
return False
except ldap.LDAPError:
logging.getLogger().debug('LDAP error connect')
return False
return True
def getConnect(self):
return self.connection
def search(self,baseDN,filter,retrieveAttributes):
try:
ldap_result_id = self.connection.search(baseDN+",dc=instituto,dc=extremadura,dc=es", ldap.SCOPE_SUBTREE, filter, retrieveAttributes)
result_set = []
while 1:
result_type, result_data = self.connection.result(ldap_result_id, 0)
if (result_data == []):
break
else:
if result_type == ldap.RES_SEARCH_ENTRY:
result_set.append(result_data)
return result_set
except ldap.LDAPError, e:
logging.getLogger().debug('LDAP error search')
"""result = con.search_s( base_dn, ldap.SCOPE_SUBTREE, filter, attrs )
return result"""
def add(self,baseDN,attr):
try:
self.connection.add_s(baseDN+",dc=instituto,dc=extremadura,dc=es", attr)
except ldap.ALREADY_EXISTS:
logging.getLogger().debug("LDAP already exists %s" % (baseDN))
except ldap.OPERATIONS_ERROR:
logging.getLogger().debug("LDAP operation error %s" % (baseDN))
except ldap.NO_SUCH_OBJECT:
logging.getLogger().debug("LDAP no such object %s" % (baseDN))
return True
def modify(self,baseDN,attr):
try:
self.connection.modify_s(baseDN+",dc=instituto,dc=extremadura,dc=es", attr)
except ldap.OPERATIONS_ERROR:
print "error"
except ldap.NO_SUCH_OBJECT:
print "no_such_object"
return True
def delete(self,baseDN):
try:
self.connection.delete_s(baseDN+",dc=instituto,dc=extremadura,dc=es")
except ldap.OPERATIONS_ERROR:
print "error"
except ldap.NO_SUCH_OBJECT:
print "no_such_object"
return True
"""def searchClassroomComputers(self,classroom):
''' How many groups? '''
base_dn = 'cn=THINCLIENTS,cn=DHCP Config,dc=instituto,dc=extremadura,dc=es'
filter = '(cn=group*)'
attrs = ['cn']
groups = self.search(self,base_dn,filter,attrs)
numberDesktops=0;
for i in range(0,len(groups)):
''' search computers of different groups '''
base_dn = 'cn='+groups[i][0]['cn'][0]+',cn=THINCLIENTS,cn=DHCP Config,dc=instituto,dc=extremadura,dc=es'
filter = '(cn='+classroom+'-o*)'
attrs = ['cn','dhcpHWAddress']
computers = self.search(self,base_dn,filter,attrs)
for j in range(0,len(computers)):
self.Desktops[numberDesktops] = {'desktop':computers[j][1]['cn'][0] , 'mac':computers[j][1]['dhcpHWAddress'][0]}
numberDesktops = numberDesktops + 1"""
controlies/Plugins/Hosts.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: Hosts.py
# Purpose: Hosts class
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Francisco Mendez Palma
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
# 2011 - Francisco Mendez Palma <fmendezpalma @no-spam@ gmail.com>
#
# ControlIES 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 3 of the License, or
# (at your option) any later version.
# ControlIES 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 ControlIES. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ldap
import logging
import time
from math import ceil
from operator import itemgetter
class Hosts(object):
def __init__(self):
pass
def __init__(self,ldap,name,ip,mac,group,type):
self.ldap = ldap
self.name = name
self.ip = ip
self.mac = mac
self.group = group
self.type = type
def getName (self):
return self.mac
def validation(self,action):
if action == "add":
if self.type == "none":
return "type"
if self.name == "":
return "name"
if self.type <> 'thinclient':
if self.ip == "":
return "ip"
if self.mac == "":
return "mac"
if self.type =="thinclient":
if self.group == "":
return "group"
if self.type == "":
return "type"
if action == "add":
if self.existsHostname():
return "hostAlreadyExists"
# thinclients no requieren ip, la cogen dinamicamente en el aula
if self.type <> "thinclient":
if self.existsIP():
return "ipAlreadyExists"
#controlar overflow en nodos
if self.groupOverflow(300):
return "groupOverflow"
if self.existsMAC():
return "macAlreadyExists"
elif action == "modify":
return "OK"
return "OK"
def process(self,action):
import pdb
if action == "add":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.add()
return response
if action == "modify":
val = self.validation()
if val != "OK":
return val
else:
response = self.modify()
return response
if action == "delete":
response = self.delete()
return response
if action == "list":
response = self.list();
return response
def list(self,args):
#from Plugins.LdapConnection import LdapConnection
#l = LdapConnection("172.23.36.5",'cn=admin,ou=People,dc=instituto,dc=extremadura,dc=es',"Sta1987teleco")
#l.connect()
# grid parameters
limit = int(args['rows'][0])
page = int(args['page'][0])
start = limit * page - limit
finish = start + limit;
# sort by field
sortBy = args['sidx'][0]
#if sortBy == "uid":
#sortBy = "id"
# reverse Sort
reverseSort = False
if args['sord'][0] == "asc":
reverseSort = True
#Distinguimos entre hosts ltsp, workstations y portatiles
type = args['type'][0]
if type == "ltsp":
# Obtengo todos los elementos del nodo hosts
#search = l.search("ou=hosts","cn=*",["cn","ipHostNumber","macAddress"])
#filter = self.buildFilter(args)
search = self.ldap.search("ou=hosts","cn=*",["cn","ipHostNumber","macAddress"])
# triplets que contiene los nombres de los ltsp-servers
hostnames = self.getLTSPServers()
# Ahora tengo que quedarme con los elementos de search que estan en hostnames: los que son ltsp
resultado=list()
for element in search:
if element[0][1]["cn"][0] in hostnames:
resultado.append(element)
search = resultado
rows = []
for i in search:
row = {
"id":i[0][1]["cn"][0],
"cell":[i[0][1]["cn"][0], i[0][1]["ipHostNumber"][0],i[0][1]["macAddress"]],
"cn":i[0][1]["cn"][0],
"ipHostNumber":i[0][1]["ipHostNumber"][0],
"macAddress":i[0][1]["macAddress"][0]
}
#row = { "cn":i[0][0], "cell":[i[0][1]["cn"][0], i[0][1]["ipHostNumber"][0],i[0][1]["macAddress"]]}
rows.append(row)
if len(rows) > 0:
totalPages = ceil( len(rows) / int(limit) )
else:
totalPages = 0
if page > totalPages:
page = totalPages
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(rows), "rows":result[start:finish] }
elif type == "thinclient":
search = self.ldap.search("cn=THINCLIENTS,cn=DHCP Config","cn=*",["cn","dhcpHWAddress"])
rows = []
# esto hay que cambiarlo: tenemos 4 groups en thinclientes
for i in search[6:len(search)]:
row = {
"id":i[0][1]["cn"][0],
"cell":[i[0][1]["cn"][0], i[0][1]["dhcpHWAddress"]],
"cn":i[0][1]["cn"][0],
"dhcpHWAddress":i[0][1]["dhcpHWAddress"][0]
}
#row = { "cn":i[0][0], "cell":[i[0][1]["cn"][0], i[0][1]["dhcpHWAddress"][0]]}
rows.append(row)
if len(rows) > 0:
totalPages = ceil( len(rows) / int(limit) )
else:
totalPages = 0
if page > totalPages:
page = totalPages
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(rows), "rows":result[start:finish] }
elif type == "workstation":
# Obtengo todos los elementos del nodo hosts
#search = l.search("ou=hosts","cn=*",["cn","ipHostNumber","macAddress"])
search = self.ldap.search("ou=hosts","cn=*",["cn","ipHostNumber","macAddress"])
# triplets que contiene los nombres de las workstations
#triplets = l.search("ou=Netgroup","cn=workstation-hosts",["nisNetgroupTriple"])
triplets = self.ldap.search("ou=Netgroup","cn=workstation-hosts",["nisNetgroupTriple"])
triplets = triplets [0][0][1]["nisNetgroupTriple"]
hostnames=list()
# obtengo lista de nombres de los hosts workstation
for node in triplets:
name = node.replace(",-,-)","").replace("(","")
hostnames.append(name)
# Ahora tengo que quedarme con los elementos de search que estan en hostnames
resultado=list()
for element in search:
if element[0][1]["cn"][0] in hostnames:
resultado.append(element)
search = resultado
rows = []
for i in search:
row = {
"id":i[0][1]["cn"][0],
"cell":[i[0][1]["cn"][0], i[0][1]["ipHostNumber"][0],i[0][1]["macAddress"]],
"cn":i[0][1]["cn"][0],
"ipHostNumber":i[0][1]["ipHostNumber"][0],
"macAddress":i[0][1]["macAddress"][0]
}
#row = { "cn":i[0][0], "cell":[i[0][1]["cn"][0], i[0][1]["ipHostNumber"][0],i[0][1]["macAddress"]]}
rows.append(row)
if len(rows) > 0:
totalPages = ceil( len(rows) / int(limit) )
else:
totalPages = 0
if page > totalPages:
page = totalPages
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(rows), "rows":result[start:finish] }
def add(self):
if self.type=="thinclient":
attr = [
('objectclass', ['top','dhcpHost']),
('cn', [self.name] ),
('dhcpStatements', ['filename "/var/lib/tftpboot/ltsp/i386/pxelinux.0"'] ),
('dhcpHWAddress', ['ethernet ' + self.mac] )
]
self.ldap.add("cn="+self.name +",cn=group2,cn=THINCLIENTS,cn=DHCP Config", attr)
return "OK"
def modify(self):
mod_attrs = [
(ldap.MOD_ADD, 'description', 'Author of New Organon'),
(ldap.MOD_ADD, 'description', 'British empiricist')
]
self.ldap.modify_s('uid='+ uid +',cn=hosts', mod_attrs)
def delete(self,uid):
self.ldap.delete('uid='+ uid +',cn=hosts')
def wakeup(self):
from Plugins import NetworkUtils
NetworkUtils.startup(self.mac)
def groupOverflow(self,overflow):
import pdb
if self.type == 'thinclient':
search = self.ldap.search("cn=" + self.group +",cn=THINCLIENTS,cn=DHCP Config","cn=*",["cn"])
if len(search)-2 >= overflow:
return True
return False
def existsHostname(self):
if self.type == 'thinclient':
result = self.ldap.search("cn=THINCLIENTS,cn=DHCP Config","cn="+self.name,["cn"])
else:
result = self.ldap.search("ou=hosts","cn="+self.name,["cn"])
if len(result) > 0:
return True
return False
def existsMAC(self):
# Compruebo con las macs de la rama hosts
if self.type == 'thinclient':
#search = self.ldap.search("cn=THINCLIENTS,cn=DHCP Config","cn=a*",["dhcpHWAddress"])
result = self.ldap.search("cn=THINCLIENTS,cn=DHCP Config","dhcpHWAddress=*",["dhcpHWAddress"])
for i in range (0, len(result) - 1):
if result [i][0][1]['dhcpHWAddress'][0].replace ("ethernet ", "") == self.mac:
return True
else:
result = self.ldap.search("ou=hosts","macAddress="+self.mac,["macAddress"])
if len(result) > 0:
return True
return False
def existsIP (self):
# Cojo las ips de la rama hosts -> arpa -> in-addr
result = self.ldap.search ("dc=23,dc=172,dc=in-addr,dc=arpa,ou=hosts", "dc=*",["associatedDomain"])
myIP = self.ip.split (".")
for i in range (0, len (result) -1):
reverseIP = result [i][0][1]['associatedDomain'][0].replace (".in-addr.arpa","").split(".")
reverseIP.reverse()
if myIP == reverseIP:
return True
return False
def getThinclientGroups (self):
import pdb
groups = []
search = self.ldap.search("cn=THINCLIENTS,cn=DHCP Config","cn=group*",["cn"])
for g in search:
groups.append (g[0][1]["cn"][0])
return { "groups":groups }
def getLTSPServers (self):
triplets = self.ldap.search("ou=Netgroup","cn=ltsp-server-hosts",["nisNetgroupTriple"])
triplets = triplets [0][0][1]["nisNetgroupTriple"]
hostnames=list()
for node in triplets:
name = node.replace(",-,-)","").replace("(","")
hostnames.append(name)
hostnames.sort()
return hostnames
def getLTSPStatus (self):
from Utils.avahiClient import avahiClient
import threading
a = avahiClient()
a.start()
time.sleep(1000)
a.cancel()
names = a.getList()
print names
"""a = avahiClient()
time.sleep(1000)
names = a.getList()
print names
a.kill()"""
return names
# def wakeup(self):
# from twisted.internet.task import LoopingCall
# from twisted.internet import defer
# from Plugins import NetworkUtils
# NetworkUtils.startup(self.mac)
# Encender el equipo
#def wakeup(self):
# macs=[]
# for i in self.targets:
# mac=Configs.MonitorConfigs.GetMAC(i)
# if mac !='':
# macs.append(mac)
# Actions.sendWOLBurst(macs, 2)
#Apagar el equipo
# def sleep(self):
# self.usersCommand(Desktop.sleep)
#def sendWOLBurst(macs,throttle):
# from twisted.internet.task import LoopingCall
# from twisted.internet import defer
# if not macs:
# return defer.succeed(None)
# d = defer.Deferred()
# work = list(macs)
# def sendNext():
# if not work:
# loop.stop()
# d.callback(None)
# return defer.succeed(None)
# next = work.pop(0)
#
# #subprocess.Popen(['wakeonlan',next ])
# #subprocess.Popen(['wakeonlan','-i','192.168.0.255',next ])
# NetworkUtils.startup(next)
#
# return None
# loop = LoopingCall(sendNext)
# loop.start(throttle)
# return d
... Diferencia truncada por exceder el máximo tamaño visualizable.

Exportar a: Unified diff